Explorar o código

HarfBuzz: Update to version 3.0.0

bruvzg %!s(int64=4) %!d(string=hai) anos
pai
achega
3061e3859d
Modificáronse 100 ficheiros con 7343 adicións e 5606 borrados
  1. 1 1
      COPYRIGHT.txt
  2. 1 0
      modules/text_server_adv/SCsub
  3. 2 2
      thirdparty/README.md
  4. 2 2
      thirdparty/harfbuzz/COPYING
  5. 0 2457
      thirdparty/harfbuzz/NEWS
  6. 4 4
      thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh
  7. 8 3
      thirdparty/harfbuzz/src/hb-aat-layout-common.hh
  8. 1 1
      thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
  9. 8 8
      thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
  10. 7 7
      thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
  11. 19 2
      thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
  12. 4 4
      thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
  13. 4 4
      thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh
  14. 10 3
      thirdparty/harfbuzz/src/hb-aat-layout.cc
  15. 2 2
      thirdparty/harfbuzz/src/hb-aat-ltag-table.hh
  16. 37 5
      thirdparty/harfbuzz/src/hb-algs.hh
  17. 35 16
      thirdparty/harfbuzz/src/hb-array.hh
  18. 5 0
      thirdparty/harfbuzz/src/hb-bimap.hh
  19. 203 0
      thirdparty/harfbuzz/src/hb-bit-page.hh
  20. 354 0
      thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
  21. 808 0
      thirdparty/harfbuzz/src/hb-bit-set.hh
  22. 91 32
      thirdparty/harfbuzz/src/hb-blob.cc
  23. 10 0
      thirdparty/harfbuzz/src/hb-blob.h
  24. 1 1
      thirdparty/harfbuzz/src/hb-blob.hh
  25. 657 532
      thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
  26. 763 674
      thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
  27. 58 41
      thirdparty/harfbuzz/src/hb-buffer.cc
  28. 11 6
      thirdparty/harfbuzz/src/hb-buffer.hh
  29. 1 1
      thirdparty/harfbuzz/src/hb-cache.hh
  30. 1 1
      thirdparty/harfbuzz/src/hb-cff-interp-common.hh
  31. 2 2
      thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
  32. 15 18
      thirdparty/harfbuzz/src/hb-common.cc
  33. 14 0
      thirdparty/harfbuzz/src/hb-common.h
  34. 4 5
      thirdparty/harfbuzz/src/hb-config.hh
  35. 44 6
      thirdparty/harfbuzz/src/hb-coretext.cc
  36. 5 1
      thirdparty/harfbuzz/src/hb-debug.hh
  37. 0 3
      thirdparty/harfbuzz/src/hb-deprecated.h
  38. 65 199
      thirdparty/harfbuzz/src/hb-directwrite.cc
  39. 1 1
      thirdparty/harfbuzz/src/hb-draw.cc
  40. 57 45
      thirdparty/harfbuzz/src/hb-face.cc
  41. 40 39
      thirdparty/harfbuzz/src/hb-font.cc
  42. 18 30
      thirdparty/harfbuzz/src/hb-ft.cc
  43. 3 3
      thirdparty/harfbuzz/src/hb-gdi.cc
  44. 3 9
      thirdparty/harfbuzz/src/hb-glib.cc
  45. 2 2
      thirdparty/harfbuzz/src/hb-gobject-structs.cc
  46. 7 6
      thirdparty/harfbuzz/src/hb-graphite2.cc
  47. 3 9
      thirdparty/harfbuzz/src/hb-icu.cc
  48. 1 1
      thirdparty/harfbuzz/src/hb-iter.hh
  49. 3 3
      thirdparty/harfbuzz/src/hb-machinery.hh
  50. 3 4
      thirdparty/harfbuzz/src/hb-map.cc
  51. 15 11
      thirdparty/harfbuzz/src/hb-map.hh
  52. 16 15
      thirdparty/harfbuzz/src/hb-meta.hh
  53. 177 0
      thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc
  54. 96 0
      thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh
  55. 1 7
      thirdparty/harfbuzz/src/hb-mutex.hh
  56. 16 4
      thirdparty/harfbuzz/src/hb-null.hh
  57. 10 15
      thirdparty/harfbuzz/src/hb-object.hh
  58. 42 26
      thirdparty/harfbuzz/src/hb-open-file.hh
  59. 83 63
      thirdparty/harfbuzz/src/hb-open-type.hh
  60. 3 3
      thirdparty/harfbuzz/src/hb-ot-cff-common.hh
  61. 4 3
      thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
  62. 176 80
      thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
  63. 7 7
      thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh
  64. 878 12
      thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
  65. 101 0
      thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh
  66. 122 5
      thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
  67. 5 5
      thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
  68. 2 2
      thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh
  69. 1 1
      thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
  70. 3 9
      thirdparty/harfbuzz/src/hb-ot-font.cc
  71. 1 1
      thirdparty/harfbuzz/src/hb-ot-gasp-table.hh
  72. 105 35
      thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
  73. 2 2
      thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh
  74. 1 1
      thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
  75. 18 18
      thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
  76. 396 107
      thirdparty/harfbuzz/src/hb-ot-layout-common.hh
  77. 20 22
      thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
  78. 348 181
      thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
  79. 228 94
      thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
  80. 336 104
      thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
  81. 16 16
      thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh
  82. 117 67
      thirdparty/harfbuzz/src/hb-ot-layout.cc
  83. 1 2
      thirdparty/harfbuzz/src/hb-ot-layout.hh
  84. 25 11
      thirdparty/harfbuzz/src/hb-ot-map.cc
  85. 22 22
      thirdparty/harfbuzz/src/hb-ot-math-table.hh
  86. 1 1
      thirdparty/harfbuzz/src/hb-ot-maxp-table.hh
  87. 2 2
      thirdparty/harfbuzz/src/hb-ot-meta-table.hh
  88. 11 6
      thirdparty/harfbuzz/src/hb-ot-name-table.hh
  89. 6 3
      thirdparty/harfbuzz/src/hb-ot-name.cc
  90. 4 21
      thirdparty/harfbuzz/src/hb-ot-os2-table.hh
  91. 130 0
      thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
  92. 27 9
      thirdparty/harfbuzz/src/hb-ot-post-table.hh
  93. 6 6
      thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
  94. 5 4
      thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh
  95. 23 15
      thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
  96. 2 2
      thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
  97. 2 2
      thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
  98. 21 21
      thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
  99. 8 6
      thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
  100. 303 362
      thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh

+ 1 - 1
COPYRIGHT.txt

@@ -1379,7 +1379,7 @@ License: HarfBuzz
  Copyright (C) 2009  Keith Stribley
  Copyright (C) 2009  Keith Stribley
  Copyright (C) 2009  Martin Hosken and SIL International
  Copyright (C) 2009  Martin Hosken and SIL International
  Copyright (C) 2007  Chris Wilson
  Copyright (C) 2007  Chris Wilson
- Copyright (C) 2006  Behdad Esfahbod
+ Copyright (C) 2005,2006,2020,2021  Behdad Esfahbod
  Copyright (C) 2005  David Turner
  Copyright (C) 2005  David Turner
  Copyright (C) 2004,2007,2008,2009,2010  Red Hat, Inc.
  Copyright (C) 2004,2007,2008,2009,2010  Red Hat, Inc.
  Copyright (C) 1998-2004  David Turner and Werner Lemberg
  Copyright (C) 1998-2004  David Turner and Werner Lemberg

+ 1 - 0
modules/text_server_adv/SCsub

@@ -64,6 +64,7 @@ if env["builtin_harfbuzz"]:
         #'src/hb-gobject-structs.cc',
         #'src/hb-gobject-structs.cc',
         "src/hb-icu.cc",
         "src/hb-icu.cc",
         "src/hb-map.cc",
         "src/hb-map.cc",
+        "src/hb-ms-feature-ranges.cc",
         "src/hb-number.cc",
         "src/hb-number.cc",
         "src/hb-ot-cff1-table.cc",
         "src/hb-ot-cff1-table.cc",
         "src/hb-ot-cff2-table.cc",
         "src/hb-ot-cff2-table.cc",

+ 2 - 2
thirdparty/README.md

@@ -192,13 +192,13 @@ Files extracted from upstream source:
 ## harfbuzz
 ## harfbuzz
 
 
 - Upstream: https://github.com/harfbuzz/harfbuzz
 - Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 2.8.0 (03538e872a0610a65fad692b33d3646f387cf578, 2021)
+- Version: 3.0.0 (9c387e20d65a7a366ac270d789f6ad266014c9e0, 2021)
 - License: MIT
 - License: MIT
 
 
 Files extracted from upstream source:
 Files extracted from upstream source:
 
 
 - the `src` folder
 - the `src` folder
-- `AUTHORS`, `COPYING`, `NEWS`, `THANKS`
+- `AUTHORS`, `COPYING`, `THANKS`
 
 
 
 
 ## icu4c
 ## icu4c

+ 2 - 2
thirdparty/harfbuzz/COPYING

@@ -4,14 +4,14 @@ files names COPYING in subdirectories where applicable.
 
 
 Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020  Google, Inc.
 Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020  Google, Inc.
 Copyright © 2018,2019,2020  Ebrahim Byagowi
 Copyright © 2018,2019,2020  Ebrahim Byagowi
-Copyright © 2019,2020  Facebook, Inc. 
+Copyright © 2019,2020  Facebook, Inc.
 Copyright © 2012  Mozilla Foundation
 Copyright © 2012  Mozilla Foundation
 Copyright © 2011  Codethink Limited
 Copyright © 2011  Codethink Limited
 Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
 Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
 Copyright © 2009  Keith Stribley
 Copyright © 2009  Keith Stribley
 Copyright © 2009  Martin Hosken and SIL International
 Copyright © 2009  Martin Hosken and SIL International
 Copyright © 2007  Chris Wilson
 Copyright © 2007  Chris Wilson
-Copyright © 2006  Behdad Esfahbod
+Copyright © 2005,2006,2020,2021  Behdad Esfahbod
 Copyright © 2005  David Turner
 Copyright © 2005  David Turner
 Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
 Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
 Copyright © 1998-2004  David Turner and Werner Lemberg
 Copyright © 1998-2004  David Turner and Werner Lemberg

+ 0 - 2457
thirdparty/harfbuzz/NEWS

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

+ 4 - 4
thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh

@@ -54,7 +54,7 @@ struct Anchor
   DEFINE_SIZE_STATIC (4);
   DEFINE_SIZE_STATIC (4);
 };
 };
 
 
-typedef LArrayOf<Anchor> GlyphAnchors;
+typedef Array32Of<Anchor> GlyphAnchors;
 
 
 struct ankr
 struct ankr
 {
 {
@@ -64,7 +64,7 @@ struct ankr
 			    unsigned int i,
 			    unsigned int i,
 			    unsigned int num_glyphs) const
 			    unsigned int num_glyphs) const
   {
   {
-    const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
+    const NNOffset16To<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
     if (!offset)
     if (!offset)
       return Null (Anchor);
       return Null (Anchor);
     const GlyphAnchors &anchors = &(this+anchorData) + *offset;
     const GlyphAnchors &anchors = &(this+anchorData) + *offset;
@@ -83,9 +83,9 @@ struct ankr
   protected:
   protected:
   HBUINT16	version;	/* Version number (set to zero) */
   HBUINT16	version;	/* Version number (set to zero) */
   HBUINT16	flags;		/* Flags (currently unused; set to zero) */
   HBUINT16	flags;		/* Flags (currently unused; set to zero) */
-  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
+  Offset32To<Lookup<NNOffset16To<GlyphAnchors>>>
 		lookupTable;	/* Offset to the table's lookup table */
 		lookupTable;	/* Offset to the table's lookup table */
-  LNNOffsetTo<HBUINT8>
+  NNOffset32To<HBUINT8>
 		anchorData;	/* Offset to the glyph data table */
 		anchorData;	/* Offset to the glyph data table */
 
 
   public:
   public:

+ 8 - 3
thirdparty/harfbuzz/src/hb-aat-layout-common.hh

@@ -30,6 +30,9 @@
 #include "hb-aat-layout.hh"
 #include "hb-aat-layout.hh"
 #include "hb-open-type.hh"
 #include "hb-open-type.hh"
 
 
+namespace OT {
+struct GDEF;
+};
 
 
 namespace AAT {
 namespace AAT {
 
 
@@ -164,7 +167,7 @@ struct LookupSegmentArray
 
 
   HBGlyphID	last;		/* Last GlyphID in this segment */
   HBGlyphID	last;		/* Last GlyphID in this segment */
   HBGlyphID	first;		/* First GlyphID in this segment */
   HBGlyphID	first;		/* First GlyphID in this segment */
-  NNOffsetTo<UnsizedArrayOf<T>>
+  NNOffset16To<UnsizedArrayOf<T>>
 		valuesZ;	/* A 16-bit offset from the start of
 		valuesZ;	/* A 16-bit offset from the start of
 				 * the table to the data. */
 				 * the table to the data. */
   public:
   public:
@@ -659,7 +662,7 @@ struct ClassTable
   }
   }
   protected:
   protected:
   HBGlyphID		firstGlyph;	/* First glyph index included in the trimmed array. */
   HBGlyphID		firstGlyph;	/* First glyph index included in the trimmed array. */
-  ArrayOf<HBUCHAR>	classArray;	/* The class codes (indexed by glyph index minus
+  Array16Of<HBUCHAR>	classArray;	/* The class codes (indexed by glyph index minus
 					 * firstGlyph). */
 					 * firstGlyph). */
   public:
   public:
   DEFINE_SIZE_ARRAY (4, classArray);
   DEFINE_SIZE_ARRAY (4, classArray);
@@ -678,7 +681,8 @@ struct ObsoleteTypes
 				     const void *base,
 				     const void *base,
 				     const T *array)
 				     const T *array)
   {
   {
-    return (offset - ((const char *) array - (const char *) base)) / T::static_size;
+    /* https://github.com/harfbuzz/harfbuzz/issues/2816 */
+    return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
   }
   }
   template <typename T>
   template <typename T>
   static unsigned int byteOffsetToIndex (unsigned int offset,
   static unsigned int byteOffsetToIndex (unsigned int offset,
@@ -862,6 +866,7 @@ struct hb_aat_apply_context_t :
   hb_buffer_t *buffer;
   hb_buffer_t *buffer;
   hb_sanitize_context_t sanitizer;
   hb_sanitize_context_t sanitizer;
   const ankr *ankr_table;
   const ankr *ankr_table;
+  const OT::GDEF *gdef_table;
 
 
   /* Unused. For debug tracing only. */
   /* Unused. For debug tracing only. */
   unsigned int lookup_index;
   unsigned int lookup_index;

+ 1 - 1
thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh

@@ -144,7 +144,7 @@ struct FeatureName
   protected:
   protected:
   HBUINT16	feature;	/* Feature type. */
   HBUINT16	feature;	/* Feature type. */
   HBUINT16	nSettings;	/* The number of records in the setting name array. */
   HBUINT16	nSettings;	/* The number of records in the setting name array. */
-  LNNOffsetTo<UnsizedArrayOf<SettingName>>
+  NNOffset32To<UnsizedArrayOf<SettingName>>
 		settingTableZ;	/* Offset in bytes from the beginning of this table to
 		settingTableZ;	/* Offset in bytes from the beginning of this table to
 				 * this feature's setting name array. The actual type of
 				 * this feature's setting name array. The actual type of
 				 * record this offset refers to will depend on the
 				 * record this offset refers to will depend on the

+ 8 - 8
thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh

@@ -79,7 +79,7 @@ struct DecompositionAction
 				 * to decompose before more frequent ones. The ligatures
 				 * to decompose before more frequent ones. The ligatures
 				 * on the line of text will decompose in increasing
 				 * on the line of text will decompose in increasing
 				 * value of this field. */
 				 * value of this field. */
-  ArrayOf<HBUINT16>
+  Array16Of<HBUINT16>
 		decomposedglyphs;
 		decomposedglyphs;
 				/* Number of 16-bit glyph indexes that follow;
 				/* Number of 16-bit glyph indexes that follow;
 				 * the ligature will be decomposed into these glyphs.
 				 * the ligature will be decomposed into these glyphs.
@@ -310,7 +310,7 @@ struct WidthDeltaPair
   DEFINE_SIZE_STATIC (24);
   DEFINE_SIZE_STATIC (24);
 };
 };
 
 
-typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
+typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
 
 
 struct JustificationCategory
 struct JustificationCategory
 {
 {
@@ -358,20 +358,20 @@ struct JustificationHeader
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<JustificationCategory>
+  Offset16To<JustificationCategory>
 		justClassTable;	/* Offset to the justification category state table. */
 		justClassTable;	/* Offset to the justification category state table. */
-  OffsetTo<WidthDeltaCluster>
+  Offset16To<WidthDeltaCluster>
 		wdcTable;	/* Offset from start of justification table to start
 		wdcTable;	/* Offset from start of justification table to start
 				 * of the subtable containing the width delta factors
 				 * of the subtable containing the width delta factors
 				 * for the glyphs in your font.
 				 * for the glyphs in your font.
 				 *
 				 *
 				 * The width delta clusters table. */
 				 * The width delta clusters table. */
-  OffsetTo<PostcompensationActionChain>
+  Offset16To<PostcompensationActionChain>
 		pcTable;	/* Offset from start of justification table to start
 		pcTable;	/* Offset from start of justification table to start
 				 * of postcompensation subtable (set to zero if none).
 				 * of postcompensation subtable (set to zero if none).
 				 *
 				 *
 				 * The postcompensation subtable, if present in the font. */
 				 * The postcompensation subtable, if present in the font. */
-  Lookup<OffsetTo<WidthDeltaCluster>>
+  Lookup<Offset16To<WidthDeltaCluster>>
 		lookupTable;	/* Lookup table associating glyphs with width delta
 		lookupTable;	/* Lookup table associating glyphs with width delta
 				 * clusters. See the description of Width Delta Clusters
 				 * clusters. See the description of Width Delta Clusters
 				 * table for details on how to interpret the lookup values. */
 				 * table for details on how to interpret the lookup values. */
@@ -398,13 +398,13 @@ struct just
   FixedVersion<>version;	/* Version of the justification table
   FixedVersion<>version;	/* Version of the justification table
 				 * (0x00010000u for version 1.0). */
 				 * (0x00010000u for version 1.0). */
   HBUINT16	format;		/* Format of the justification table (set to 0). */
   HBUINT16	format;		/* Format of the justification table (set to 0). */
-  OffsetTo<JustificationHeader>
+  Offset16To<JustificationHeader>
 		horizData;	/* Byte offset from the start of the justification table
 		horizData;	/* Byte offset from the start of the justification table
 				 * to the header for tables that contain justification
 				 * to the header for tables that contain justification
 				 * information for horizontal text.
 				 * information for horizontal text.
 				 * If you are not including this information,
 				 * If you are not including this information,
 				 * store 0. */
 				 * store 0. */
-  OffsetTo<JustificationHeader>
+  Offset16To<JustificationHeader>
 		vertData;	/* ditto, vertical */
 		vertData;	/* ditto, vertical */
 
 
   public:
   public:

+ 7 - 7
thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh

@@ -710,18 +710,18 @@ struct KerxSubTableFormat6
   {
   {
     struct Long
     struct Long
     {
     {
-      LNNOffsetTo<Lookup<HBUINT32>>		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT32>>		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD32>>	array;
+      NNOffset32To<Lookup<HBUINT32>>		rowIndexTable;
+      NNOffset32To<Lookup<HBUINT32>>		columnIndexTable;
+      NNOffset32To<UnsizedArrayOf<FWORD32>>	array;
     } l;
     } l;
     struct Short
     struct Short
     {
     {
-      LNNOffsetTo<Lookup<HBUINT16>>		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT16>>		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD>>	array;
+      NNOffset32To<Lookup<HBUINT16>>		rowIndexTable;
+      NNOffset32To<Lookup<HBUINT16>>		columnIndexTable;
+      NNOffset32To<UnsizedArrayOf<FWORD>>	array;
     } s;
     } s;
   } u;
   } u;
-  LNNOffsetTo<UnsizedArrayOf<FWORD>>	vector;
+  NNOffset32To<UnsizedArrayOf<FWORD>>	vector;
   public:
   public:
   DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
   DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
 };
 };

+ 19 - 2
thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh

@@ -30,6 +30,7 @@
 #include "hb-open-type.hh"
 #include "hb-open-type.hh"
 #include "hb-aat-layout-common.hh"
 #include "hb-aat-layout-common.hh"
 #include "hb-ot-layout-common.hh"
 #include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
 #include "hb-aat-map.hh"
 #include "hb-aat-map.hh"
 
 
 /*
 /*
@@ -215,7 +216,9 @@ struct ContextualSubtable
 			     hb_aat_apply_context_t *c_) :
 			     hb_aat_apply_context_t *c_) :
 	ret (false),
 	ret (false),
 	c (c_),
 	c (c_),
+	gdef (*c->gdef_table),
 	mark_set (false),
 	mark_set (false),
+	has_glyph_classes (gdef.has_glyph_classes ()),
 	mark (0),
 	mark (0),
 	table (table_),
 	table (table_),
 	subs (table+table->substitutionTables) {}
 	subs (table+table->substitutionTables) {}
@@ -263,6 +266,9 @@ struct ContextualSubtable
       {
       {
 	buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
 	buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
 	buffer->info[mark].codepoint = *replacement;
 	buffer->info[mark].codepoint = *replacement;
+	if (has_glyph_classes)
+	  _hb_glyph_info_set_glyph_props (&buffer->info[mark],
+					  gdef.get_glyph_props (*replacement));
 	ret = true;
 	ret = true;
       }
       }
 
 
@@ -287,6 +293,9 @@ struct ContextualSubtable
       if (replacement)
       if (replacement)
       {
       {
 	buffer->info[idx].codepoint = *replacement;
 	buffer->info[idx].codepoint = *replacement;
+	if (has_glyph_classes)
+	  _hb_glyph_info_set_glyph_props (&buffer->info[idx],
+					  gdef.get_glyph_props (*replacement));
 	ret = true;
 	ret = true;
       }
       }
 
 
@@ -301,10 +310,12 @@ struct ContextualSubtable
     bool ret;
     bool ret;
     private:
     private:
     hb_aat_apply_context_t *c;
     hb_aat_apply_context_t *c;
+    const OT::GDEF &gdef;
     bool mark_set;
     bool mark_set;
+    bool has_glyph_classes;
     unsigned int mark;
     unsigned int mark;
     const ContextualSubtable *table;
     const ContextualSubtable *table;
-    const UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false> &subs;
+    const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs;
   };
   };
 
 
   bool apply (hb_aat_apply_context_t *c) const
   bool apply (hb_aat_apply_context_t *c) const
@@ -348,7 +359,7 @@ struct ContextualSubtable
   protected:
   protected:
   StateTable<Types, EntryData>
   StateTable<Types, EntryData>
 		machine;
 		machine;
-  NNOffsetTo<UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
+  NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
 		substitutionTables;
 		substitutionTables;
   public:
   public:
   DEFINE_SIZE_STATIC (20);
   DEFINE_SIZE_STATIC (20);
@@ -599,6 +610,9 @@ struct NoncontextualSubtable
   {
   {
     TRACE_APPLY (this);
     TRACE_APPLY (this);
 
 
+    const OT::GDEF &gdef (*c->gdef_table);
+    bool has_glyph_classes = gdef.has_glyph_classes ();
+
     bool ret = false;
     bool ret = false;
     unsigned int num_glyphs = c->face->get_num_glyphs ();
     unsigned int num_glyphs = c->face->get_num_glyphs ();
 
 
@@ -610,6 +624,9 @@ struct NoncontextualSubtable
       if (replacement)
       if (replacement)
       {
       {
 	info[i].codepoint = *replacement;
 	info[i].codepoint = *replacement;
+	if (has_glyph_classes)
+	  _hb_glyph_info_set_glyph_props (&info[i],
+					  gdef.get_glyph_props (*replacement));
 	ret = true;
 	ret = true;
       }
       }
     }
     }

+ 4 - 4
thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh

@@ -58,7 +58,7 @@ struct opbdFormat0
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
 		   hb_glyph_extents_t *extents, const void *base) const
 		   hb_glyph_extents_t *extents, const void *base) const
   {
   {
-    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
     if (!bounds_offset) return false;
     if (!bounds_offset) return false;
     const OpticalBounds &bounds = base+*bounds_offset;
     const OpticalBounds &bounds = base+*bounds_offset;
 
 
@@ -79,7 +79,7 @@ struct opbdFormat0
   }
   }
 
 
   protected:
   protected:
-  Lookup<OffsetTo<OpticalBounds>>
+  Lookup<Offset16To<OpticalBounds>>
 		lookupTable;	/* Lookup table associating glyphs with the four
 		lookupTable;	/* Lookup table associating glyphs with the four
 				 * int16 values for the left-side, top-side,
 				 * int16 values for the left-side, top-side,
 				 * right-side, and bottom-side optical bounds. */
 				 * right-side, and bottom-side optical bounds. */
@@ -92,7 +92,7 @@ struct opbdFormat1
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
 		   hb_glyph_extents_t *extents, const void *base) const
 		   hb_glyph_extents_t *extents, const void *base) const
   {
   {
-    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
     if (!bounds_offset) return false;
     if (!bounds_offset) return false;
     const OpticalBounds &bounds = base+*bounds_offset;
     const OpticalBounds &bounds = base+*bounds_offset;
 
 
@@ -116,7 +116,7 @@ struct opbdFormat1
   }
   }
 
 
   protected:
   protected:
-  Lookup<OffsetTo<OpticalBounds>>
+  Lookup<Offset16To<OpticalBounds>>
 		lookupTable;	/* Lookup table associating glyphs with the four
 		lookupTable;	/* Lookup table associating glyphs with the four
 				 * int16 values for the left-side, top-side,
 				 * int16 values for the left-side, top-side,
 				 * right-side, and bottom-side optical bounds. */
 				 * right-side, and bottom-side optical bounds. */

+ 4 - 4
thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh

@@ -66,7 +66,7 @@ struct TrackTableEntry
   NameID	trackNameID;	/* The 'name' table index for this track.
   NameID	trackNameID;	/* The 'name' table index for this track.
 				 * (a short word or phrase like "loose"
 				 * (a short word or phrase like "loose"
 				 * or "very tight") */
 				 * or "very tight") */
-  NNOffsetTo<UnsizedArrayOf<FWORD>>
+  NNOffset16To<UnsizedArrayOf<FWORD>>
 		valuesZ;	/* Offset from start of tracking table to
 		valuesZ;	/* Offset from start of tracking table to
 				 * per-size tracking values for this track. */
 				 * per-size tracking values for this track. */
 
 
@@ -141,7 +141,7 @@ struct TrackData
   protected:
   protected:
   HBUINT16	nTracks;	/* Number of separate tracks included in this table. */
   HBUINT16	nTracks;	/* Number of separate tracks included in this table. */
   HBUINT16	nSizes;		/* Number of point sizes included in this table. */
   HBUINT16	nSizes;		/* Number of point sizes included in this table. */
-  LNNOffsetTo<UnsizedArrayOf<HBFixed>>
+  NNOffset32To<UnsizedArrayOf<HBFixed>>
 		sizeTable;	/* Offset from start of the tracking table to
 		sizeTable;	/* Offset from start of the tracking table to
 				 * Array[nSizes] of size values.. */
 				 * Array[nSizes] of size values.. */
   UnsizedArrayOf<TrackTableEntry>
   UnsizedArrayOf<TrackTableEntry>
@@ -212,10 +212,10 @@ struct trak
   FixedVersion<>version;	/* Version of the tracking table
   FixedVersion<>version;	/* Version of the tracking table
 				 * (0x00010000u for version 1.0). */
 				 * (0x00010000u for version 1.0). */
   HBUINT16	format;		/* Format of the tracking table (set to 0). */
   HBUINT16	format;		/* Format of the tracking table (set to 0). */
-  OffsetTo<TrackData>
+  Offset16To<TrackData>
 		horizData;	/* Offset from start of tracking table to TrackData
 		horizData;	/* Offset from start of tracking table to TrackData
 				 * for horizontal text (or 0 if none). */
 				 * for horizontal text (or 0 if none). */
-  OffsetTo<TrackData>
+  Offset16To<TrackData>
 		vertData;	/* Offset from start of tracking table to TrackData
 		vertData;	/* Offset from start of tracking table to TrackData
 				 * for vertical text (or 0 if none). */
 				 * for vertical text (or 0 if none). */
   HBUINT16	reserved;	/* Reserved. Set to 0. */
   HBUINT16	reserved;	/* Reserved. Set to 0. */

+ 10 - 3
thirdparty/harfbuzz/src/hb-aat-layout.cc

@@ -55,6 +55,7 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
 						       buffer (buffer_),
 						       buffer (buffer_),
 						       sanitizer (),
 						       sanitizer (),
 						       ankr_table (&Null (AAT::ankr)),
 						       ankr_table (&Null (AAT::ankr)),
+						       gdef_table (face->table.GDEF->table),
 						       lookup_index (0)
 						       lookup_index (0)
 {
 {
   sanitizer.init (blob);
   sanitizer.init (blob);
@@ -79,7 +80,7 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
  * @short_description: Apple Advanced Typography Layout
  * @short_description: Apple Advanced Typography Layout
  * @include: hb-aat.h
  * @include: hb-aat.h
  *
  *
- * Functions for querying AAT Layout features in the font face. 
+ * Functions for querying AAT Layout features in the font face.
  *
  *
  * HarfBuzz supports all of the AAT tables used to implement shaping. Other
  * HarfBuzz supports all of the AAT tables used to implement shaping. Other
  * AAT tables and their associated features are not supported.
  * AAT tables and their associated features are not supported.
@@ -172,13 +173,13 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
   {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},
   {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},
 };
 };
 
 
-/** 
+/**
  * hb_aat_layout_find_feature_mapping:
  * hb_aat_layout_find_feature_mapping:
  * @tag: The requested #hb_tag_t feature tag
  * @tag: The requested #hb_tag_t feature tag
  *
  *
  * Fetches the AAT feature-and-selector combination that corresponds
  * Fetches the AAT feature-and-selector combination that corresponds
  * to a given OpenType feature tag.
  * to a given OpenType feature tag.
- *  
+ *
  * Return value: the AAT features and selectors corresponding to the
  * Return value: the AAT features and selectors corresponding to the
  * OpenType feature tag queried
  * OpenType feature tag queried
  *
  *
@@ -248,7 +249,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
   if (morx.has_data ())
   if (morx.has_data ())
   {
   {
     AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
     AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
+    if (!buffer->message (font, "start table morx")) return;
     morx.apply (&c);
     morx.apply (&c);
+    (void) buffer->message (font, "end table morx");
     return;
     return;
   }
   }
 
 
@@ -257,7 +260,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
   if (mort.has_data ())
   if (mort.has_data ())
   {
   {
     AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
     AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
+    if (!buffer->message (font, "start table mort")) return;
     mort.apply (&c);
     mort.apply (&c);
+    (void) buffer->message (font, "end table mort");
     return;
     return;
   }
   }
 }
 }
@@ -313,8 +318,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
 
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
   AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
+  if (!buffer->message (font, "start table kerx")) return;
   c.set_ankr_table (font->face->table.ankr.get ());
   c.set_ankr_table (font->face->table.ankr.get ());
   kerx.apply (&c);
   kerx.apply (&c);
+  (void) buffer->message (font, "end table kerx");
 }
 }
 
 
 
 

+ 2 - 2
thirdparty/harfbuzz/src/hb-aat-ltag-table.hh

@@ -50,7 +50,7 @@ struct FTStringRange
   }
   }
 
 
   protected:
   protected:
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		tag;		/* Offset from the start of the table to
 		tag;		/* Offset from the start of the table to
 				 * the beginning of the string */
 				 * the beginning of the string */
   HBUINT16	length;		/* String length (in bytes) */
   HBUINT16	length;		/* String length (in bytes) */
@@ -80,7 +80,7 @@ struct ltag
   protected:
   protected:
   HBUINT32	version;	/* Table version; currently 1 */
   HBUINT32	version;	/* Table version; currently 1 */
   HBUINT32	flags;		/* Table flags; currently none defined */
   HBUINT32	flags;		/* Table flags; currently none defined */
-  LArrayOf<FTStringRange>
+  Array32Of<FTStringRange>
 		tagRanges;	/* Range for each tag's string */
 		tagRanges;	/* Range for each tag's string */
   public:
   public:
   DEFINE_SIZE_ARRAY (12, tagRanges);
   DEFINE_SIZE_ARRAY (12, tagRanges);

+ 37 - 5
thirdparty/harfbuzz/src/hb-algs.hh

@@ -760,6 +760,14 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
 
 
 
 
+static inline void *
+hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
+{
+  /* It's illegal to pass 0 as size to memcpy. */
+  if (unlikely (!len)) return dst;
+  return memcpy (dst, src, len);
+}
+
 static inline int
 static inline int
 hb_memcmp (const void *a, const void *b, unsigned int len)
 hb_memcmp (const void *a, const void *b, unsigned int len)
 {
 {
@@ -1151,30 +1159,48 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
 
 
 /* Operators. */
 /* Operators. */
 
 
-struct hb_bitwise_and
+struct
 { HB_PARTIALIZE(2);
 { HB_PARTIALIZE(2);
   template <typename T> constexpr auto
   template <typename T> constexpr auto
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
 }
 }
 HB_FUNCOBJ (hb_bitwise_and);
 HB_FUNCOBJ (hb_bitwise_and);
-struct hb_bitwise_or
+struct
 { HB_PARTIALIZE(2);
 { HB_PARTIALIZE(2);
   template <typename T> constexpr auto
   template <typename T> constexpr auto
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
 }
 }
 HB_FUNCOBJ (hb_bitwise_or);
 HB_FUNCOBJ (hb_bitwise_or);
-struct hb_bitwise_xor
+struct
 { HB_PARTIALIZE(2);
 { HB_PARTIALIZE(2);
   template <typename T> constexpr auto
   template <typename T> constexpr auto
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
 }
 }
 HB_FUNCOBJ (hb_bitwise_xor);
 HB_FUNCOBJ (hb_bitwise_xor);
-struct hb_bitwise_sub
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T> constexpr auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
+}
+HB_FUNCOBJ (hb_bitwise_lt);
+struct
 { HB_PARTIALIZE(2);
 { HB_PARTIALIZE(2);
   template <typename T> constexpr auto
   template <typename T> constexpr auto
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
 }
 }
-HB_FUNCOBJ (hb_bitwise_sub);
+HB_FUNCOBJ (hb_bitwise_gt); // aka sub
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T> constexpr auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
+}
+HB_FUNCOBJ (hb_bitwise_le);
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T> constexpr auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
+}
+HB_FUNCOBJ (hb_bitwise_ge);
 struct
 struct
 {
 {
   template <typename T> constexpr auto
   template <typename T> constexpr auto
@@ -1195,6 +1221,12 @@ struct
 }
 }
 HB_FUNCOBJ (hb_sub);
 HB_FUNCOBJ (hb_sub);
 struct
 struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> constexpr auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
+}
+HB_FUNCOBJ (hb_rsub);
+struct
 { HB_PARTIALIZE(2);
 { HB_PARTIALIZE(2);
   template <typename T, typename T2> constexpr auto
   template <typename T, typename T2> constexpr auto
   operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
   operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)

+ 35 - 16
thirdparty/harfbuzz/src/hb-array.hh

@@ -36,6 +36,14 @@
 template <typename Type>
 template <typename Type>
 struct hb_sorted_array_t;
 struct hb_sorted_array_t;
 
 
+enum hb_not_found_t
+{
+  HB_NOT_FOUND_DONT_STORE,
+  HB_NOT_FOUND_STORE,
+  HB_NOT_FOUND_STORE_CLOSEST,
+};
+
+
 template <typename Type>
 template <typename Type>
 struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 {
 {
@@ -139,7 +147,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
     return lfind (x, &i) ? &this->arrayZ[i] : not_found;
     return lfind (x, &i) ? &this->arrayZ[i] : not_found;
   }
   }
   template <typename T>
   template <typename T>
-  bool lfind (const T &x, unsigned *pos = nullptr) const
+  bool lfind (const T &x, unsigned *pos = nullptr,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
+	      unsigned int to_store = (unsigned int) -1) const
   {
   {
     for (unsigned i = 0; i < length; ++i)
     for (unsigned i = 0; i < length; ++i)
       if (hb_equal (x, this->arrayZ[i]))
       if (hb_equal (x, this->arrayZ[i]))
@@ -149,6 +159,22 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 	return true;
 	return true;
       }
       }
 
 
+    if (pos)
+    {
+      switch (not_found)
+      {
+	case HB_NOT_FOUND_DONT_STORE:
+	  break;
+
+	case HB_NOT_FOUND_STORE:
+	  *pos = to_store;
+	  break;
+
+	case HB_NOT_FOUND_STORE_CLOSEST:
+	  *pos = length;
+	  break;
+      }
+    }
     return false;
     return false;
   }
   }
 
 
@@ -219,7 +245,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 	    unsigned P = sizeof (Type),
 	    unsigned P = sizeof (Type),
 	    hb_enable_if (P == 1)>
 	    hb_enable_if (P == 1)>
   const T *as () const
   const T *as () const
-  { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
+  { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
 
 
   template <typename T,
   template <typename T,
 	    unsigned P = sizeof (Type),
 	    unsigned P = sizeof (Type),
@@ -231,9 +257,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 	&& (unsigned int) (arrayZ + length - (const char *) p) >= size;
 	&& (unsigned int) (arrayZ + length - (const char *) p) >= size;
   }
   }
 
 
-  /* Only call if you allocated the underlying array using malloc() or similar. */
-  void free ()
-  { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
+  /* Only call if you allocated the underlying array using hb_malloc() or similar. */
+  void fini ()
+  { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
 
 
   template <typename hb_serialize_context_t>
   template <typename hb_serialize_context_t>
   hb_array_t copy (hb_serialize_context_t *c) const
   hb_array_t copy (hb_serialize_context_t *c) const
@@ -266,13 +292,6 @@ template <typename T, unsigned int length_> inline hb_array_t<T>
 hb_array (T (&array_)[length_])
 hb_array (T (&array_)[length_])
 { return hb_array_t<T> (array_); }
 { 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>
 template <typename Type>
 struct hb_sorted_array_t :
 struct hb_sorted_array_t :
 	hb_iter_t<hb_sorted_array_t<Type>, Type&>,
 	hb_iter_t<hb_sorted_array_t<Type>, Type&>,
@@ -323,7 +342,7 @@ struct hb_sorted_array_t :
   }
   }
   template <typename T>
   template <typename T>
   bool bfind (const T &x, unsigned int *i = nullptr,
   bool bfind (const T &x, unsigned int *i = nullptr,
-	      hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
 	      unsigned int to_store = (unsigned int) -1) const
 	      unsigned int to_store = (unsigned int) -1) const
   {
   {
     unsigned pos;
     unsigned pos;
@@ -339,14 +358,14 @@ struct hb_sorted_array_t :
     {
     {
       switch (not_found)
       switch (not_found)
       {
       {
-	case HB_BFIND_NOT_FOUND_DONT_STORE:
+	case HB_NOT_FOUND_DONT_STORE:
 	  break;
 	  break;
 
 
-	case HB_BFIND_NOT_FOUND_STORE:
+	case HB_NOT_FOUND_STORE:
 	  *i = to_store;
 	  *i = to_store;
 	  break;
 	  break;
 
 
-	case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+	case HB_NOT_FOUND_STORE_CLOSEST:
 	  *i = pos;
 	  *i = pos;
 	  break;
 	  break;
       }
       }

+ 5 - 0
thirdparty/harfbuzz/src/hb-bimap.hh

@@ -58,10 +58,15 @@ struct hb_bimap_t
 
 
   void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
   void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
   {
   {
+    if (in_error ()) return;
     if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
     if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
     if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
     if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
+
     forw_map.set (lhs, rhs);
     forw_map.set (lhs, rhs);
+    if (in_error ()) return;
+
     back_map.set (rhs, lhs);
     back_map.set (rhs, lhs);
+    if (in_error ()) forw_map.del (lhs);
   }
   }
 
 
   hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
   hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }

+ 203 - 0
thirdparty/harfbuzz/src/hb-bit-page.hh

@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2012,2017  Google, Inc.
+ * Copyright © 2021 Behdad Esfahbod
+ *
+ *  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_BIT_PAGE_HH
+#define HB_BIT_PAGE_HH
+
+#include "hb.hh"
+
+struct hb_bit_page_t
+{
+  void init0 () { v.clear (); }
+  void init1 () { v.clear (0xFF); }
+
+  constexpr unsigned 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); }
+  void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
+  bool get (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);
+    }
+  }
+  void del_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, 0, (char *) lb - (char *) la);
+
+      *lb &= ~((mask (b) << 1) - 1);
+    }
+  }
+  void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
+  { if (v) add_range (a, b); else del_range (a, b); }
+
+  bool is_equal (const hb_bit_page_t &other) const
+  {
+    return 0 == hb_memcmp (&v, &other.v, sizeof (v));
+  }
+  bool is_subset (const hb_bit_page_t &larger_page) const
+  {
+    for (unsigned i = 0; i < len (); i++)
+      if (~larger_page.v[i] & v[i])
+	return false;
+    return true;
+  }
+
+  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;
+
+    /* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */
+    const elt_t mask = j < 8 * sizeof (elt_t) - 1 ?
+		       ((elt_t (1) << (j + 1)) - 1) :
+		       (elt_t) -1;
+    const elt_t vv = v[i] & mask;
+    const elt_t *p = &vv;
+    while (true)
+    {
+      if (*p)
+      {
+	*codepoint = i * ELT_BITS + elt_get_max (*p);
+	return true;
+      }
+      if ((int) i <= 0) break;
+      p = &v[--i];
+    }
+
+    *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;
+  }
+
+  static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
+
+  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]; }
+  const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
+  static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
+
+  vector_t v;
+};
+static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, "");
+
+
+#endif /* HB_BIT_PAGE_HH */

+ 354 - 0
thirdparty/harfbuzz/src/hb-bit-set-invertible.hh

@@ -0,0 +1,354 @@
+/*
+ * Copyright © 2012,2017  Google, Inc.
+ * Copyright © 2021 Behdad Esfahbod
+ *
+ *  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_BIT_SET_INVERTIBLE_HH
+#define HB_BIT_SET_INVERTIBLE_HH
+
+#include "hb.hh"
+#include "hb-bit-set.hh"
+
+
+struct hb_bit_set_invertible_t
+{
+  hb_bit_set_t s;
+  bool inverted;
+
+  hb_bit_set_invertible_t () { init (); }
+  ~hb_bit_set_invertible_t () { fini (); }
+
+  void init () { s.init (); inverted = false; }
+  void fini () { s.fini (); }
+  void err () { s.err (); }
+  bool in_error () const { return s.in_error (); }
+  explicit operator bool () const { return !is_empty (); }
+
+  void reset ()
+  {
+    s.reset ();
+    inverted = false;
+  }
+  void clear ()
+  {
+    s.clear ();
+    if (likely (s.successful))
+      inverted = false;
+  }
+  void invert ()
+  {
+    if (likely (s.successful))
+      inverted = !inverted;
+  }
+
+  bool is_empty () const
+  {
+    hb_codepoint_t v = INVALID;
+    next (&v);
+    return v == INVALID;
+  }
+  hb_codepoint_t get_min () const
+  {
+    hb_codepoint_t v = INVALID;
+    next (&v);
+    return v;
+  }
+  hb_codepoint_t get_max () const
+  {
+    hb_codepoint_t v = INVALID;
+    previous (&v);
+    return v;
+  }
+  unsigned int get_population () const
+  { return inverted ? INVALID - s.get_population () : s.get_population (); }
+
+
+  void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); }
+  template <typename T>
+  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
+
+  /* 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))
+  { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); }
+  template <typename T>
+  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+
+  void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
+  void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
+
+  bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
+
+  /* Has interface. */
+  static constexpr bool SENTINEL = false;
+  typedef bool value_t;
+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  /* Predicate. */
+  bool operator () (hb_codepoint_t k) const { return has (k); }
+
+  /* Sink interface. */
+  hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
+  { add (v); return *this; }
+  hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  { add_range (range.first, range.second); return *this; }
+
+  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_bit_set_invertible_t &other)
+  {
+    s.set (other.s);
+    if (likely (s.successful))
+      inverted = other.inverted;
+  }
+
+  bool is_equal (const hb_bit_set_invertible_t &other) const
+  {
+    if (likely (inverted == other.inverted))
+      return s.is_equal (other.s);
+    else
+    {
+      /* TODO Add iter_ranges() and use here. */
+      auto it1 = iter ();
+      auto it2 = other.iter ();
+      return hb_all (+ hb_zip (it1, it2)
+		     | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
+    }
+  }
+
+  bool is_subset (const hb_bit_set_invertible_t &larger_set) const
+  {
+    if (unlikely (inverted != larger_set.inverted))
+      return hb_all (hb_iter (s) | hb_map (larger_set.s));
+    else
+      return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
+  }
+
+  protected:
+  template <typename Op>
+  void process (const Op& op, const hb_bit_set_invertible_t &other)
+  { s.process (op, other.s); }
+  public:
+  void union_ (const hb_bit_set_invertible_t &other)
+  {
+    if (likely (inverted == other.inverted))
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_and, other);
+      else
+	process (hb_bitwise_or, other); /* Main branch. */
+    }
+    else
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_gt, other);
+      else
+	process (hb_bitwise_lt, other);
+    }
+    if (likely (s.successful))
+      inverted = inverted || other.inverted;
+  }
+  void intersect (const hb_bit_set_invertible_t &other)
+  {
+    if (likely (inverted == other.inverted))
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_or, other);
+      else
+	process (hb_bitwise_and, other); /* Main branch. */
+    }
+    else
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_lt, other);
+      else
+	process (hb_bitwise_gt, other);
+    }
+    if (likely (s.successful))
+      inverted = inverted && other.inverted;
+  }
+  void subtract (const hb_bit_set_invertible_t &other)
+  {
+    if (likely (inverted == other.inverted))
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_lt, other);
+      else
+	process (hb_bitwise_gt, other); /* Main branch. */
+    }
+    else
+    {
+      if (unlikely (inverted))
+	process (hb_bitwise_or, other);
+      else
+	process (hb_bitwise_and, other);
+    }
+    if (likely (s.successful))
+      inverted = inverted && !other.inverted;
+  }
+  void symmetric_difference (const hb_bit_set_invertible_t &other)
+  {
+    process (hb_bitwise_xor, other);
+    if (likely (s.successful))
+      inverted = inverted ^ other.inverted;
+  }
+
+  bool next (hb_codepoint_t *codepoint) const
+  {
+    if (likely (!inverted))
+      return s.next (codepoint);
+
+    auto old = *codepoint;
+    if (unlikely (old + 1 == INVALID))
+    {
+      *codepoint = INVALID;
+      return false;
+    }
+
+    auto v = old;
+    s.next (&v);
+    if (old + 1 < v)
+    {
+      *codepoint = old + 1;
+      return true;
+    }
+
+    v = old;
+    s.next_range (&old, &v);
+
+    *codepoint = v + 1;
+    return *codepoint != INVALID;
+  }
+  bool previous (hb_codepoint_t *codepoint) const
+  {
+    if (likely (!inverted))
+      return s.previous (codepoint);
+
+    auto old = *codepoint;
+    if (unlikely (old - 1 == INVALID))
+    {
+      *codepoint = INVALID;
+      return false;
+    }
+
+    auto v = old;
+    s.previous (&v);
+
+    if (old - 1 > v || v == INVALID)
+    {
+      *codepoint = old - 1;
+      return true;
+    }
+
+    v = old;
+    s.previous_range (&v, &old);
+
+    *codepoint = v - 1;
+    return *codepoint != INVALID;
+  }
+  bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    if (likely (!inverted))
+      return s.next_range (first, last);
+
+    if (!next (last))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    *first = *last;
+    s.next (last);
+    --*last;
+    return true;
+  }
+  bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    if (likely (!inverted))
+      return s.previous_range (first, last);
+
+    if (!previous (first))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    *last = *first;
+    s.previous (first);
+    ++*first;
+    return true;
+  }
+
+  static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
+
+  /*
+   * Iterator implementation.
+   */
+  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+  {
+    static constexpr bool is_sorted_iterator = true;
+    iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
+	    bool init = true) : s (&s_), v (INVALID), l(0)
+    {
+      if (init)
+      {
+	l = s->get_population () + 1;
+	__next__ ();
+      }
+    }
+
+    typedef hb_codepoint_t __item_t__;
+    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__ () const { return l; }
+    iter_t end () const { return iter_t (*s, false); }
+    bool operator != (const iter_t& o) const
+    { return s != o.s || v != o.v; }
+
+    protected:
+    const hb_bit_set_invertible_t *s;
+    hb_codepoint_t v;
+    unsigned l;
+  };
+  iter_t iter () const { return iter_t (*this); }
+  operator iter_t () const { return iter (); }
+};
+
+
+#endif /* HB_BIT_SET_INVERTIBLE_HH */

+ 808 - 0
thirdparty/harfbuzz/src/hb-bit-set.hh

@@ -0,0 +1,808 @@
+/*
+ * Copyright © 2012,2017  Google, Inc.
+ * Copyright © 2021 Behdad Esfahbod
+ *
+ *  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_BIT_SET_HH
+#define HB_BIT_SET_HH
+
+#include "hb.hh"
+#include "hb-bit-page.hh"
+#include "hb-machinery.hh"
+
+
+struct hb_bit_set_t
+{
+  hb_bit_set_t () { init (); }
+  ~hb_bit_set_t () { fini (); }
+
+  hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); }
+  void operator= (const hb_bit_set_t& other) { set (other); }
+  // TODO Add move construtor/assign
+  // TODO Add constructor for Iterator; with specialization for (sorted) vector / array?
+
+  void init ()
+  {
+    successful = true;
+    population = 0;
+    last_page_lookup = 0;
+    page_map.init ();
+    pages.init ();
+  }
+  void fini ()
+  {
+    page_map.fini ();
+    pages.fini ();
+  }
+
+  using page_t = hb_bit_page_t;
+  struct page_map_t
+  {
+    int cmp (const page_map_t &o) const { return cmp (o.major); }
+    int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
+
+    uint32_t major;
+    uint32_t index;
+  };
+
+  bool successful; /* Allocations successful */
+  mutable unsigned int population;
+  mutable unsigned int last_page_lookup;
+  hb_sorted_vector_t<page_map_t> page_map;
+  hb_vector_t<page_t> pages;
+
+  void err () { if (successful) successful = false; } /* TODO Remove */
+  bool in_error () const { return !successful; }
+
+  bool resize (unsigned int count)
+  {
+    if (unlikely (!successful)) return false;
+    if (unlikely (!pages.resize (count) || !page_map.resize (count)))
+    {
+      pages.resize (page_map.length);
+      successful = false;
+      return false;
+    }
+    return true;
+  }
+
+  void reset ()
+  {
+    successful = true;
+    clear ();
+  }
+
+  void clear ()
+  {
+    resize (0);
+    if (likely (successful))
+      population = 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;
+  }
+  explicit operator bool () const { return !is_empty (); }
+
+  private:
+  void dirty () { population = UINT_MAX; }
+  public:
+
+  void add (hb_codepoint_t g)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (g == INVALID)) return;
+    dirty ();
+    page_t *page = page_for (g, true); 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 (a, true); if (unlikely (!page)) return false;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for (a, true); 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 (major_start (m), true); if (unlikely (!page)) return false;
+	page->init1 ();
+      }
+
+      page = page_for (b, true); if (unlikely (!page)) return false;
+      page->add_range (major_start (mb), b);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void set_array (bool v, 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 (g, v); if (unlikely (v && !page)) return;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        if (v || page) /* The v check is to optimize out the page check if v is true. */
+	  page->set (g, v);
+
+	array = &StructAtOffsetUnaligned<T> (array, stride);
+	count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
+    }
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  { set_array (true, array, count, stride); }
+  template <typename T>
+  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
+
+  template <typename T>
+  void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  { set_array (false, array, count, stride); }
+  template <typename T>
+  void del_array (const hb_array_t<const T>& arr) { del_array (&arr, arr.len ()); }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename T>
+  bool set_sorted_array (bool v, 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 (g, v); if (unlikely (v && !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;
+
+        if (v || page) /* The v check is to optimize out the page check if v is true. */
+	  page->add (g);
+
+	array = (const T *) ((const char *) array + stride);
+	count--;
+      }
+      while (count && (g = *array, g < end));
+    }
+    return true;
+  }
+
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  { return set_sorted_array (true, array, count, stride); }
+  template <typename T>
+  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+
+  template <typename T>
+  bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  { return set_sorted_array (false, array, count, stride); }
+  template <typename T>
+  bool del_sorted_array (const hb_sorted_array_t<const T>& arr) { return del_sorted_array (&arr, arr.len ()); }
+
+  void del (hb_codepoint_t g)
+  {
+    if (unlikely (!successful)) return;
+    page_t *page = page_for (g);
+    if (!page)
+      return;
+    dirty ();
+    page->del (g);
+  }
+
+  private:
+  void del_pages (int ds, int de)
+  {
+    if (ds <= de)
+    {
+      // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
+      // before attempting to rewrite the page map.
+      hb_vector_t<unsigned> compact_workspace;
+      if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
+
+      unsigned int write_index = 0;
+      for (unsigned int i = 0; i < page_map.length; i++)
+      {
+	int m = (int) page_map[i].major;
+	if (m < ds || de < m)
+	  page_map[write_index++] = page_map[i];
+      }
+      compact (compact_workspace, write_index);
+      resize (write_index);
+    }
+  }
+
+
+  public:
+  void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (a > b || a == INVALID)) return;
+    dirty ();
+    unsigned int ma = get_major (a);
+    unsigned int mb = get_major (b);
+    /* Delete pages from ds through de if ds <= de. */
+    int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
+    int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
+    if (ds > de || (int) ma < ds)
+    {
+      page_t *page = page_for (a);
+      if (page)
+      {
+	if (ma == mb)
+	  page->del_range (a, b);
+	else
+	  page->del_range (a, major_start (ma + 1) - 1);
+      }
+    }
+    if (de < (int) mb && ma != mb)
+    {
+      page_t *page = page_for (b);
+      if (page)
+	page->del_range (major_start (mb), b);
+    }
+    del_pages (ds, de);
+  }
+
+  bool get (hb_codepoint_t g) const
+  {
+    const page_t *page = page_for (g);
+    if (!page)
+      return false;
+    return page->get (g);
+  }
+
+  /* Has interface. */
+  static constexpr bool SENTINEL = false;
+  typedef bool value_t;
+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  /* Predicate. */
+  bool operator () (hb_codepoint_t k) const { return has (k); }
+
+  /* Sink interface. */
+  hb_bit_set_t& operator << (hb_codepoint_t v)
+  { add (v); return *this; }
+  hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  { add_range (range.first, range.second); return *this; }
+
+  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_bit_set_t &other)
+  {
+    if (unlikely (!successful)) return;
+    unsigned int count = other.pages.length;
+    if (unlikely (!resize (count)))
+      return;
+    population = other.population;
+
+    /* TODO switch to vector operator =. */
+    hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
+    hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
+  }
+
+  bool is_equal (const hb_bit_set_t &other) const
+  {
+    if (has_population () && other.has_population () &&
+	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_bit_set_t &larger_set) const
+  {
+    if (has_population () && larger_set.has_population () &&
+	get_population () != larger_set.get_population ())
+      return false;
+
+    uint32_t spi = 0;
+    for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
+    {
+      uint32_t spm = page_map[spi].major;
+      uint32_t lpm = larger_set.page_map[lpi].major;
+      auto sp = page_at (spi);
+      auto lp = larger_set.page_at (lpi);
+
+      if (spm < lpm && !sp.is_empty ())
+        return false;
+
+      if (lpm < spm)
+        continue;
+
+      if (!sp.is_subset (lp))
+        return false;
+
+      spi++;
+    }
+
+    while (spi < page_map.length)
+      if (!page_at (spi++).is_empty ())
+        return false;
+
+    return true;
+  }
+
+  private:
+  bool allocate_compact_workspace (hb_vector_t<unsigned>& workspace)
+  {
+    if (unlikely (!workspace.resize (pages.length)))
+    {
+      successful = false;
+      return false;
+    }
+
+    return true;
+  }
+
+  /*
+   * workspace should be a pre-sized vector allocated to hold at exactly pages.length
+   * elements.
+   */
+  void compact (hb_vector_t<unsigned>& workspace,
+                unsigned int length)
+  {
+    assert(workspace.length == pages.length);
+    hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
+
+    hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
+    for (unsigned i = 0; i < length; i++)
+      old_index_to_page_map_index[page_map[i].index] =  i;
+
+    compact_pages (old_index_to_page_map_index);
+  }
+  void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
+  {
+    unsigned int write_index = 0;
+    for (unsigned int i = 0; i < pages.length; i++)
+    {
+      if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
+
+      if (write_index < i)
+	pages[write_index] = pages[i];
+
+      page_map[old_index_to_page_map_index[i]].index = write_index;
+      write_index++;
+    }
+  }
+  public:
+
+  template <typename Op>
+  void process (const Op& op, const hb_bit_set_t &other)
+  {
+    const bool passthru_left = op (1, 0);
+    const bool passthru_right = op (0, 1);
+
+    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;
+    unsigned int write_index = 0;
+
+    // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
+    // before attempting to rewrite the page map.
+    hb_vector_t<unsigned> compact_workspace;
+    if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
+
+    for (; a < na && b < nb; )
+    {
+      if (page_map[a].major == other.page_map[b].major)
+      {
+	if (!passthru_left)
+	{
+	  // Move page_map entries that we're keeping from the left side set
+	  // to the front of the page_map vector. This isn't necessary if
+	  // passthru_left is set since no left side pages will be removed
+	  // in that case.
+	  if (write_index < a)
+	    page_map[write_index] = page_map[a];
+	  write_index++;
+	}
+
+	count++;
+	a++;
+	b++;
+      }
+      else if (page_map[a].major < other.page_map[b].major)
+      {
+	if (passthru_left)
+	  count++;
+	a++;
+      }
+      else
+      {
+	if (passthru_right)
+	  count++;
+	b++;
+      }
+    }
+    if (passthru_left)
+      count += na - a;
+    if (passthru_right)
+      count += nb - b;
+
+    if (!passthru_left)
+    {
+      na  = write_index;
+      next_page = write_index;
+      compact (compact_workspace, write_index);
+    }
+
+    if (unlikely (!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];
+	page_at (count).v = op (page_at (a).v, other.page_at (b).v);
+      }
+      else if (page_map[a - 1].major > other.page_map[b - 1].major)
+      {
+	a--;
+	if (passthru_left)
+	{
+	  count--;
+	  page_map[count] = page_map[a];
+	}
+      }
+      else
+      {
+	b--;
+	if (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 (passthru_left)
+      while (a)
+      {
+	a--;
+	count--;
+	page_map[count] = page_map [a];
+      }
+    if (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);
+    resize (newCount);
+  }
+
+  void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
+  void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
+  void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); }
+  void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); }
+
+  bool next (hb_codepoint_t *codepoint) const
+  {
+    // TODO: this should be merged with prev() as both implementations
+    //       are very similar.
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_min ();
+      return *codepoint != INVALID;
+    }
+
+    const auto* page_map_array = page_map.arrayZ;
+    unsigned int major = get_major (*codepoint);
+    unsigned int i = last_page_lookup;
+
+    if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+    {
+      page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+      if (i >= page_map.length) {
+        *codepoint = INVALID;
+        return false;
+      }
+    }
+
+    const auto* pages_array = pages.arrayZ;
+    const page_map_t &current = page_map_array[i];
+    if (likely (current.major == major))
+    {
+      if (pages_array[current.index].next (codepoint))
+      {
+        *codepoint += current.major * page_t::PAGE_BITS;
+        last_page_lookup = i;
+        return true;
+      }
+      i++;
+    }
+
+    for (; i < page_map.length; i++)
+    {
+      const page_map_t &current = page_map.arrayZ[i];
+      hb_codepoint_t m = pages_array[current.index].get_min ();
+      if (m != INVALID)
+      {
+	*codepoint = current.major * page_t::PAGE_BITS + m;
+        last_page_lookup = i;
+	return true;
+      }
+    }
+    last_page_lookup = 0;
+    *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_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;
+  }
+
+  bool has_population () const { return population != UINT_MAX; }
+  unsigned int get_population () const
+  {
+    if (has_population ())
+      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 count = pages.length;
+    for (unsigned i = 0; i < count; i++)
+    {
+      const auto& map = page_map[i];
+      const auto& page = pages[map.index];
+
+      if (!page.is_empty ())
+	return map.major * page_t::PAGE_BITS + page.get_min ();
+    }
+    return INVALID;
+  }
+  hb_codepoint_t get_max () const
+  {
+    unsigned count = pages.length;
+    for (signed i = count - 1; i >= 0; i--)
+    {
+      const auto& map = page_map[(unsigned) i];
+      const auto& page = pages[map.index];
+
+      if (!page.is_empty ())
+	return map.major * page_t::PAGE_BITS + page.get_max ();
+    }
+    return INVALID;
+  }
+
+  static constexpr hb_codepoint_t INVALID = page_t::INVALID;
+
+  /*
+   * Iterator implementation.
+   */
+  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+  {
+    static constexpr bool is_sorted_iterator = true;
+    iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
+	    bool init = true) : s (&s_), v (INVALID), l(0)
+    {
+      if (init)
+      {
+	l = s->get_population () + 1;
+	__next__ ();
+      }
+    }
+
+    typedef hb_codepoint_t __item_t__;
+    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__ () const { return l; }
+    iter_t end () const { return iter_t (*s, false); }
+    bool operator != (const iter_t& o) const
+    { return s != o.s || v != o.v; }
+
+    protected:
+    const hb_bit_set_t *s;
+    hb_codepoint_t v;
+    unsigned l;
+  };
+  iter_t iter () const { return iter_t (*this); }
+  operator iter_t () const { return iter (); }
+
+  protected:
+
+  page_t *page_for (hb_codepoint_t g, bool insert = false)
+  {
+    page_map_t map = {get_major (g), pages.length};
+    unsigned int i;
+    if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
+    {
+      if (!insert)
+        return nullptr;
+
+      if (unlikely (!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];
+  }
+  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_BIT_SET_HH */

+ 91 - 32
thirdparty/harfbuzz/src/hb-blob.cc

@@ -71,15 +71,53 @@ hb_blob_create (const char        *data,
 		hb_memory_mode_t   mode,
 		hb_memory_mode_t   mode,
 		void              *user_data,
 		void              *user_data,
 		hb_destroy_func_t  destroy)
 		hb_destroy_func_t  destroy)
+{
+  if (!length)
+  {
+    if (destroy)
+      destroy (user_data);
+    return hb_blob_get_empty ();
+  }
+
+  hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode,
+					    user_data, destroy);
+  return likely (blob) ? blob : hb_blob_get_empty ();
+}
+
+/**
+ * hb_blob_create_or_fail: (skip)
+ * @data: Pointer to blob data.
+ * @length: Length of @data in bytes.
+ * @mode: Memory mode for @data.
+ * @user_data: Data parameter to pass to @destroy.
+ * @destroy: (nullable): Callback to call when @data is not needed anymore.
+ *
+ * Creates a new "blob" object wrapping @data.  The @mode parameter is used
+ * to negotiate ownership and lifecycle of @data.
+ *
+ * Note that this function returns a freshly-allocated empty blob even if @length
+ * is zero. This is in contrast to hb_blob_create(), which returns the singleton
+ * empty blob (as returned by hb_blob_get_empty()) if @length is zero.
+ *
+ * Return value: New blob, or %NULL if failed.  Destroy with hb_blob_destroy().
+ *
+ * Since: 2.8.2
+ **/
+hb_blob_t *
+hb_blob_create_or_fail (const char        *data,
+			unsigned int       length,
+			hb_memory_mode_t   mode,
+			void              *user_data,
+			hb_destroy_func_t  destroy)
 {
 {
   hb_blob_t *blob;
   hb_blob_t *blob;
 
 
-  if (!length ||
-      length >= 1u << 31 ||
-      !(blob = hb_object_create<hb_blob_t> ())) {
+  if (length >= 1u << 31 ||
+      !(blob = hb_object_create<hb_blob_t> ()))
+  {
     if (destroy)
     if (destroy)
       destroy (user_data);
       destroy (user_data);
-    return hb_blob_get_empty ();
+    return nullptr;
   }
   }
 
 
   blob->data = data;
   blob->data = data;
@@ -91,9 +129,10 @@ hb_blob_create (const char        *data,
 
 
   if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
   if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
     blob->mode = HB_MEMORY_MODE_READONLY;
     blob->mode = HB_MEMORY_MODE_READONLY;
-    if (!blob->try_make_writable ()) {
+    if (!blob->try_make_writable ())
+    {
       hb_blob_destroy (blob);
       hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
+      return nullptr;
     }
     }
   }
   }
 
 
@@ -226,7 +265,7 @@ hb_blob_destroy (hb_blob_t *blob)
 
 
   blob->fini_shallow ();
   blob->fini_shallow ();
 
 
-  free (blob);
+  hb_free (blob);
 }
 }
 
 
 /**
 /**
@@ -452,7 +491,7 @@ hb_blob_t::try_make_writable ()
 
 
   char *new_data;
   char *new_data;
 
 
-  new_data = (char *) malloc (this->length);
+  new_data = (char *) hb_malloc (this->length);
   if (unlikely (!new_data))
   if (unlikely (!new_data))
     return false;
     return false;
 
 
@@ -463,7 +502,7 @@ hb_blob_t::try_make_writable ()
   this->mode = HB_MEMORY_MODE_WRITABLE;
   this->mode = HB_MEMORY_MODE_WRITABLE;
   this->data = new_data;
   this->data = new_data;
   this->user_data = new_data;
   this->user_data = new_data;
-  this->destroy = free;
+  this->destroy = hb_free;
 
 
   return true;
   return true;
 }
 }
@@ -517,7 +556,7 @@ _hb_mapped_file_destroy (void *file_)
   assert (0); // If we don't have mmap we shouldn't reach here
   assert (0); // If we don't have mmap we shouldn't reach here
 #endif
 #endif
 
 
-  free (file);
+  hb_free (file);
 }
 }
 #endif
 #endif
 
 
@@ -528,7 +567,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
   size_t name_len = strlen (file_name);
   size_t name_len = strlen (file_name);
   size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC);
   size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC);
 
 
-  char *rsrc_name = (char *) malloc (len);
+  char *rsrc_name = (char *) hb_malloc (len);
   if (unlikely (!rsrc_name)) return -1;
   if (unlikely (!rsrc_name)) return -1;
 
 
   strncpy (rsrc_name, file_name, name_len);
   strncpy (rsrc_name, file_name, name_len);
@@ -536,7 +575,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
 	   sizeof (_PATH_RSRCFORKSPEC) - 1);
 	   sizeof (_PATH_RSRCFORKSPEC) - 1);
 
 
   int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
   int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
-  free (rsrc_name);
+  hb_free (rsrc_name);
 
 
   if (fd != -1)
   if (fd != -1)
   {
   {
@@ -561,17 +600,37 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
  * Creates a new blob containing the data from the
  * Creates a new blob containing the data from the
  * specified binary font file.
  * specified binary font file.
  *
  *
- * Returns: An #hb_blob_t pointer with the content of the file
+ * Returns: An #hb_blob_t pointer with the content of the file,
+ * or hb_blob_get_empty() if failed.
  *
  *
  * Since: 1.7.7
  * Since: 1.7.7
  **/
  **/
 hb_blob_t *
 hb_blob_t *
 hb_blob_create_from_file (const char *file_name)
 hb_blob_create_from_file (const char *file_name)
+{
+  hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name);
+  return likely (blob) ? blob : hb_blob_get_empty ();
+}
+
+/**
+ * hb_blob_create_from_file_or_fail:
+ * @file_name: A font filename
+ *
+ * Creates a new blob containing the data from the
+ * specified binary font file.
+ *
+ * Returns: An #hb_blob_t pointer with the content of the file,
+ * or %NULL if failed.
+ *
+ * Since: 2.8.2
+ **/
+hb_blob_t *
+hb_blob_create_from_file_or_fail (const char *file_name)
 {
 {
   /* Adopted from glib's gmappedfile.c with Matthias Clasen and
   /* Adopted from glib's gmappedfile.c with Matthias Clasen and
      Allison Lortie permission but changed a lot to suit our need. */
      Allison Lortie permission but changed a lot to suit our need. */
 #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
 #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
-  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
+  hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
   if (unlikely (!file)) return hb_blob_get_empty ();
 
 
   int fd = open (file_name, O_RDONLY | O_BINARY, 0);
   int fd = open (file_name, O_RDONLY | O_BINARY, 0);
@@ -601,22 +660,22 @@ hb_blob_create_from_file (const char *file_name)
 
 
   close (fd);
   close (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);
+  return hb_blob_create_or_fail (file->contents, file->length,
+				 HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
+				 (hb_destroy_func_t) _hb_mapped_file_destroy);
 
 
 fail:
 fail:
   close (fd);
   close (fd);
 fail_without_close:
 fail_without_close:
-  free (file);
+  hb_free (file);
 
 
 #elif defined(_WIN32) && !defined(HB_NO_MMAP)
 #elif defined(_WIN32) && !defined(HB_NO_MMAP)
-  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
+  hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
   if (unlikely (!file)) return hb_blob_get_empty ();
 
 
   HANDLE fd;
   HANDLE fd;
   unsigned int size = strlen (file_name) + 1;
   unsigned int size = strlen (file_name) + 1;
-  wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
+  wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size);
   if (unlikely (!wchar_file_name)) goto fail_without_close;
   if (unlikely (!wchar_file_name)) goto fail_without_close;
   mbstowcs (wchar_file_name, file_name, size);
   mbstowcs (wchar_file_name, file_name, size);
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
@@ -636,7 +695,7 @@ fail_without_close:
 		    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
 		    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
 		    nullptr);
 		    nullptr);
 #endif
 #endif
-  free (wchar_file_name);
+  hb_free (wchar_file_name);
 
 
   if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
   if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
 
 
@@ -661,22 +720,22 @@ fail_without_close:
   if (unlikely (!file->contents)) goto fail;
   if (unlikely (!file->contents)) goto fail;
 
 
   CloseHandle (fd);
   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);
+  return hb_blob_create_or_fail (file->contents, file->length,
+				 HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
+				 (hb_destroy_func_t) _hb_mapped_file_destroy);
 
 
 fail:
 fail:
   CloseHandle (fd);
   CloseHandle (fd);
 fail_without_close:
 fail_without_close:
-  free (file);
+  hb_free (file);
 
 
 #endif
 #endif
 
 
   /* The following tries to read a file without knowing its size beforehand
   /* 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 */
      It's used as a fallback for systems without mmap or to read from pipes */
   unsigned long len = 0, allocated = BUFSIZ * 16;
   unsigned long len = 0, allocated = BUFSIZ * 16;
-  char *data = (char *) malloc (allocated);
-  if (unlikely (!data)) return hb_blob_get_empty ();
+  char *data = (char *) hb_malloc (allocated);
+  if (unlikely (!data)) return nullptr;
 
 
   FILE *fp = fopen (file_name, "rb");
   FILE *fp = fopen (file_name, "rb");
   if (unlikely (!fp)) goto fread_fail_without_close;
   if (unlikely (!fp)) goto fread_fail_without_close;
@@ -689,7 +748,7 @@ fail_without_close:
       /* Don't allocate and go more than ~536MB, our mmap reader still
       /* Don't allocate and go more than ~536MB, our mmap reader still
 	 can cover files like that but lets limit our fallback reader */
 	 can cover files like that but lets limit our fallback reader */
       if (unlikely (allocated > (2 << 28))) goto fread_fail;
       if (unlikely (allocated > (2 << 28))) goto fread_fail;
-      char *new_data = (char *) realloc (data, allocated);
+      char *new_data = (char *) hb_realloc (data, allocated);
       if (unlikely (!new_data)) goto fread_fail;
       if (unlikely (!new_data)) goto fread_fail;
       data = new_data;
       data = new_data;
     }
     }
@@ -706,13 +765,13 @@ fail_without_close:
   }
   }
 	fclose (fp);
 	fclose (fp);
 
 
-  return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
-			 (hb_destroy_func_t) free);
+  return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data,
+				 (hb_destroy_func_t) hb_free);
 
 
 fread_fail:
 fread_fail:
   fclose (fp);
   fclose (fp);
 fread_fail_without_close:
 fread_fail_without_close:
-  free (data);
-  return hb_blob_get_empty ();
+  hb_free (data);
+  return nullptr;
 }
 }
 #endif /* !HB_NO_OPEN */
 #endif /* !HB_NO_OPEN */

+ 10 - 0
thirdparty/harfbuzz/src/hb-blob.h

@@ -90,9 +90,19 @@ hb_blob_create (const char        *data,
 		void              *user_data,
 		void              *user_data,
 		hb_destroy_func_t  destroy);
 		hb_destroy_func_t  destroy);
 
 
+HB_EXTERN hb_blob_t *
+hb_blob_create_or_fail (const char        *data,
+			unsigned int       length,
+			hb_memory_mode_t   mode,
+			void              *user_data,
+			hb_destroy_func_t  destroy);
+
 HB_EXTERN hb_blob_t *
 HB_EXTERN hb_blob_t *
 hb_blob_create_from_file (const char *file_name);
 hb_blob_create_from_file (const char *file_name);
 
 
+HB_EXTERN hb_blob_t *
+hb_blob_create_from_file_or_fail (const char *file_name);
+
 /* Always creates with MEMORY_MODE_READONLY.
 /* Always creates with MEMORY_MODE_READONLY.
  * Even if the parent blob is writable, we don't
  * Even if the parent blob is writable, we don't
  * want the user of the sub-blob to be able to
  * want the user of the sub-blob to be able to

+ 1 - 1
thirdparty/harfbuzz/src/hb-blob.hh

@@ -88,7 +88,7 @@ struct hb_blob_ptr_t
   const T * get () const { return b->as<T> (); }
   const T * get () const { return b->as<T> (); }
   hb_blob_t * get_blob () const { return b.get_raw (); }
   hb_blob_t * get_blob () const { return b.get_raw (); }
   unsigned int get_length () const { return b.get ()->length; }
   unsigned int get_length () const { return b.get ()->length; }
-  void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
+  void destroy () { hb_blob_destroy (b.get_raw ()); b = nullptr; }
 
 
   private:
   private:
   hb_nonnull_ptr_t<hb_blob_t> b;
   hb_nonnull_ptr_t<hb_blob_t> b;

+ 657 - 532
thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh

@@ -1,29 +1,30 @@
+
 #line 1 "hb-buffer-deserialize-json.rl"
 #line 1 "hb-buffer-deserialize-json.rl"
 /*
 /*
-* Copyright © 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.
-*
-* Google Author(s): Behdad Esfahbod
-*/
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
 
 
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
@@ -31,158 +32,446 @@
 #include "hb.hh"
 #include "hb.hh"
 
 
 
 
-#line 35 "hb-buffer-deserialize-json.hh"
+#line 36 "hb-buffer-deserialize-json.hh"
 static const unsigned char _deserialize_json_trans_keys[] = {
 static const unsigned char _deserialize_json_trans_keys[] = {
-	1u, 0u, 0u, 18u, 0u, 2u, 10u, 15u,
-	16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u,
-	5u, 6u, 0u, 19u, 0u, 19u, 0u, 19u,
-	2u, 2u, 0u, 7u, 0u, 6u, 5u, 6u,
-	0u, 19u, 0u, 19u, 14u, 14u, 2u, 2u,
-	0u, 7u, 0u, 6u, 0u, 19u, 0u, 19u,
-	16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u,
-	5u, 6u, 0u, 19u, 0u, 19u, 2u, 2u,
-	0u, 7u, 0u, 6u, 5u, 6u, 0u, 19u,
-	0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u,
-	2u, 8u, 0u, 19u, 2u, 8u, 0u, 19u,
-	0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u,
-	0u, 19u, 0u, 9u, 0u, 18u, 1u, 0u,
-	0u
+	0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 
+	48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 
+	9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 
+	120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 
+	9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 
+	34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 
+	9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
 };
 };
 
 
-static const signed char _deserialize_json_char_class[] = {
-	0, 0, 0, 0, 0, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 0,
-	1, 2, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 3, 4, 1, 1, 5,
-	6, 6, 6, 6, 6, 6, 6, 6,
-	6, 7, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 8, 9, 1, 1, 1,
-	10, 1, 11, 12, 1, 1, 13, 1,
-	1, 1, 1, 14, 1, 1, 1, 1,
-	1, 1, 1, 1, 15, 1, 1, 16,
-	17, 1, 18, 1, 19, 0
+static const char _deserialize_json_key_spans[] = {
+	0, 115, 26, 21, 2, 1, 50, 49, 
+	10, 117, 117, 117, 1, 50, 49, 10, 
+	117, 117, 1, 1, 50, 49, 117, 117, 
+	2, 1, 50, 49, 10, 117, 117, 1, 
+	50, 49, 10, 117, 117, 1, 50, 49, 
+	59, 117, 59, 117, 117, 1, 50, 49, 
+	117, 85, 115, 0
 };
 };
 
 
 static const short _deserialize_json_index_offsets[] = {
 static const short _deserialize_json_index_offsets[] = {
-	0, 0, 19, 22, 28, 30, 31, 39,
-	46, 48, 68, 88, 108, 109, 117, 124,
-	126, 146, 166, 167, 168, 176, 183, 203,
-	223, 225, 226, 234, 241, 243, 263, 283,
-	284, 292, 299, 301, 321, 341, 342, 350,
-	357, 364, 384, 391, 411, 431, 432, 440,
-	447, 467, 477, 496, 0
+	0, 0, 116, 143, 165, 168, 170, 221, 
+	271, 282, 400, 518, 636, 638, 689, 739, 
+	750, 868, 986, 988, 990, 1041, 1091, 1209, 
+	1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680, 
+	1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083, 
+	2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660, 
+	2710, 2828, 2914, 3030
 };
 };
 
 
-static const signed char _deserialize_json_indicies[] = {
-	1, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 2, 3, 0, 4, 5, 6,
-	7, 8, 0, 9, 10, 11, 12, 12,
-	0, 0, 0, 0, 0, 0, 13, 13,
-	0, 0, 0, 14, 15, 16, 18, 19,
-	20, 0, 0, 21, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 22, 23, 0, 0, 3,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 24,
-	20, 0, 0, 21, 0, 19, 19, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 22, 25, 25, 0, 0,
-	0, 0, 0, 0, 26, 26, 0, 0,
-	0, 27, 28, 29, 31, 32, 33, 0,
-	0, 34, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 35, 33, 0, 0, 34, 0, 32,
-	32, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 35, 36, 37,
-	37, 0, 0, 0, 0, 0, 0, 38,
-	38, 0, 0, 0, 0, 39, 40, 42,
-	0, 0, 43, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 44, 42, 0, 0, 43, 0,
-	45, 45, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 44, 46,
-	47, 48, 48, 0, 0, 0, 0, 0,
-	0, 49, 49, 0, 0, 0, 50, 51,
-	52, 54, 55, 56, 0, 0, 57, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 58, 56,
-	0, 0, 57, 0, 55, 55, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 58, 59, 59, 0, 0, 0,
-	0, 0, 0, 60, 60, 0, 0, 0,
-	61, 62, 63, 65, 66, 67, 0, 0,
-	68, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	69, 67, 0, 0, 68, 0, 66, 66,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 69, 70, 70, 0,
-	0, 0, 0, 0, 0, 71, 71, 0,
-	72, 0, 0, 73, 74, 76, 75, 75,
-	75, 75, 75, 77, 79, 0, 0, 80,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 81,
-	75, 0, 0, 0, 0, 0, 75, 83,
-	0, 0, 84, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 85, 83, 0, 0, 84, 0,
-	87, 87, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 85, 88,
-	88, 0, 0, 0, 0, 0, 0, 89,
-	89, 0, 0, 0, 0, 90, 91, 83,
-	0, 0, 84, 0, 93, 93, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 85, 94, 0, 0, 95, 0,
-	0, 0, 0, 0, 96, 1, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 2,
+static const char _deserialize_json_indicies[] = {
+	0, 0, 0, 0, 0, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	0, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 2, 1, 3, 3, 3, 
+	3, 3, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 3, 1, 4, 1, 
+	5, 1, 6, 7, 1, 1, 8, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 9, 1, 10, 11, 
+	1, 12, 1, 12, 12, 12, 12, 12, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 12, 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, 13, 1, 13, 13, 
+	13, 13, 13, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 13, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 14, 1, 1, 15, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 1, 
+	17, 18, 18, 18, 18, 18, 18, 18, 
+	18, 18, 1, 19, 19, 19, 19, 19, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 19, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 20, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 21, 
+	1, 22, 22, 22, 22, 22, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	22, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 3, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 23, 1, 19, 
+	19, 19, 19, 19, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 19, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 20, 1, 1, 1, 18, 18, 
+	18, 18, 18, 18, 18, 18, 18, 18, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 21, 1, 24, 1, 24, 
+	24, 24, 24, 24, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 24, 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, 
+	25, 1, 25, 25, 25, 25, 25, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 25, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 26, 1, 
+	1, 27, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 1, 29, 30, 30, 30, 
+	30, 30, 30, 30, 30, 30, 1, 31, 
+	31, 31, 31, 31, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 31, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 32, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 33, 1, 31, 31, 31, 
+	31, 31, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 31, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	32, 1, 1, 1, 30, 30, 30, 30, 
+	30, 30, 30, 30, 30, 30, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 33, 1, 34, 1, 35, 1, 35, 
+	35, 35, 35, 35, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 35, 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, 
+	36, 1, 36, 36, 36, 36, 36, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 36, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 37, 38, 38, 38, 38, 38, 38, 
+	38, 38, 38, 1, 39, 39, 39, 39, 
+	39, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 39, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 40, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	41, 1, 39, 39, 39, 39, 39, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 39, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 40, 1, 1, 
+	1, 42, 42, 42, 42, 42, 42, 42, 
+	42, 42, 42, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 41, 1, 
+	43, 44, 1, 45, 1, 45, 45, 45, 
+	45, 45, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 45, 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, 46, 1, 
+	46, 46, 46, 46, 46, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 46, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 47, 1, 1, 48, 
+	49, 49, 49, 49, 49, 49, 49, 49, 
+	49, 1, 50, 51, 51, 51, 51, 51, 
+	51, 51, 51, 51, 1, 52, 52, 52, 
+	52, 52, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 52, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	53, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 54, 1, 52, 52, 52, 52, 52, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 52, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 53, 1, 
+	1, 1, 51, 51, 51, 51, 51, 51, 
+	51, 51, 51, 51, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 54, 
+	1, 55, 1, 55, 55, 55, 55, 55, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 55, 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, 56, 1, 56, 56, 
+	56, 56, 56, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 56, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 57, 1, 1, 58, 59, 59, 
+	59, 59, 59, 59, 59, 59, 59, 1, 
+	60, 61, 61, 61, 61, 61, 61, 61, 
+	61, 61, 1, 62, 62, 62, 62, 62, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 62, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 63, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 64, 
+	1, 62, 62, 62, 62, 62, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	62, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 63, 1, 1, 1, 
+	61, 61, 61, 61, 61, 61, 61, 61, 
+	61, 61, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 64, 1, 65, 
+	1, 65, 65, 65, 65, 65, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	65, 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, 66, 1, 66, 66, 66, 66, 
+	66, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 66, 1, 67, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 68, 69, 69, 69, 69, 
+	69, 69, 69, 69, 69, 1, 71, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	70, 70, 70, 70, 70, 70, 70, 70, 
+	72, 70, 73, 73, 73, 73, 73, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 73, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 74, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 75, 1, 
+	70, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 70, 1, 76, 76, 76, 76, 
+	76, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 76, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 77, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	78, 1, 76, 76, 76, 76, 76, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 76, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 77, 1, 1, 
+	1, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 78, 1, 
+	80, 1, 80, 80, 80, 80, 80, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 80, 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, 81, 1, 81, 81, 81, 
+	81, 81, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 81, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 82, 83, 83, 83, 
+	83, 83, 83, 83, 83, 83, 1, 76, 
+	76, 76, 76, 76, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 76, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 77, 1, 1, 1, 84, 84, 
+	84, 84, 84, 84, 84, 84, 84, 84, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 78, 1, 85, 85, 85, 
+	85, 85, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 85, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	86, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 87, 1, 0, 0, 0, 0, 0, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 0, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 2, 1, 1, 
 	0
 	0
 };
 };
 
 
-static const signed char _deserialize_json_index_defaults[] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	75, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0
-};
-
-static const signed char _deserialize_json_cond_targs[] = {
-	0, 1, 2, 2, 3, 4, 18, 24,
-	37, 45, 5, 12, 6, 7, 8, 9,
-	11, 8, 9, 11, 10, 2, 49, 10,
-	49, 13, 14, 15, 16, 17, 15, 16,
-	17, 10, 2, 49, 19, 20, 21, 22,
-	23, 22, 10, 2, 49, 23, 25, 31,
-	26, 27, 28, 29, 30, 28, 29, 30,
-	10, 2, 49, 32, 33, 34, 35, 36,
-	34, 35, 36, 10, 2, 49, 38, 39,
-	40, 43, 44, 40, 41, 42, 41, 10,
-	2, 49, 43, 10, 2, 49, 44, 44,
-	46, 47, 43, 48, 48, 48, 49, 50,
-	51, 0
+static const char _deserialize_json_trans_targs[] = {
+	1, 0, 2, 2, 3, 4, 18, 24, 
+	37, 45, 5, 12, 6, 7, 8, 9, 
+	11, 9, 11, 10, 2, 49, 10, 49, 
+	13, 14, 15, 16, 17, 16, 17, 10, 
+	2, 49, 19, 20, 21, 22, 23, 10, 
+	2, 49, 23, 25, 31, 26, 27, 28, 
+	29, 30, 29, 30, 10, 2, 49, 32, 
+	33, 34, 35, 36, 35, 36, 10, 2, 
+	49, 38, 39, 40, 43, 44, 40, 41, 
+	42, 10, 2, 49, 10, 2, 49, 44, 
+	46, 47, 43, 48, 48, 49, 50, 51
 };
 };
 
 
-static const signed char _deserialize_json_cond_actions[] = {
-	0, 0, 1, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 2, 2,
-	2, 0, 0, 0, 3, 3, 4, 0,
-	5, 0, 0, 2, 2, 2, 0, 0,
-	0, 6, 6, 7, 0, 0, 0, 2,
-	2, 0, 8, 8, 9, 0, 0, 0,
-	0, 0, 2, 2, 2, 0, 0, 0,
-	10, 10, 11, 0, 0, 2, 2, 2,
-	0, 0, 0, 12, 12, 13, 0, 0,
-	2, 14, 14, 0, 15, 0, 0, 16,
-	16, 17, 0, 18, 18, 19, 0, 15,
-	0, 0, 20, 20, 0, 21, 0, 0,
-	0, 0
+static const char _deserialize_json_trans_actions[] = {
+	0, 0, 1, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 2, 2, 
+	2, 0, 0, 3, 3, 4, 0, 5, 
+	0, 0, 2, 2, 2, 0, 0, 6, 
+	6, 7, 0, 0, 0, 2, 2, 8, 
+	8, 9, 0, 0, 0, 0, 0, 2, 
+	2, 2, 0, 0, 10, 10, 11, 0, 
+	0, 2, 2, 2, 0, 0, 12, 12, 
+	13, 0, 0, 2, 14, 14, 0, 15, 
+	0, 16, 16, 17, 18, 18, 19, 15, 
+	0, 0, 20, 20, 21, 0, 0, 0
 };
 };
 
 
 static const int deserialize_json_start = 1;
 static const int deserialize_json_start = 1;
@@ -197,411 +486,247 @@ static const int deserialize_json_en_main = 1;
 
 
 static hb_bool_t
 static hb_bool_t
 _hb_buffer_deserialize_json (hb_buffer_t *buffer,
 _hb_buffer_deserialize_json (hb_buffer_t *buffer,
-const char *buf,
-unsigned int buf_len,
-const char **end_ptr,
-hb_font_t *font)
+				    const char *buf,
+				    unsigned int buf_len,
+				    const char **end_ptr,
+				    hb_font_t *font)
 {
 {
-	const char *p = buf, *pe = buf + buf_len;
-	
-	/* Ensure we have positions. */
-	(void) hb_buffer_get_glyph_positions (buffer, nullptr);
-	
-	while (p < pe && ISSPACE (*p))
-	p++;
-	if (p < pe && *p == (buffer->len ? ',' : '['))
-		{
-		*end_ptr = ++p;
-	}
-	
-	const char *tok = nullptr;
-	int cs;
-	hb_glyph_info_t info = {0};
-	hb_glyph_position_t pos = {0};
-	
-#line 223 "hb-buffer-deserialize-json.hh"
+  const char *p = buf, *pe = buf + buf_len;
+
+  /* Ensure we have positions. */
+  (void) hb_buffer_get_glyph_positions (buffer, nullptr);
+
+  while (p < pe && ISSPACE (*p))
+    p++;
+  if (p < pe && *p == (buffer->len ? ',' : '['))
+  {
+    *end_ptr = ++p;
+  }
+
+  const char *tok = nullptr;
+  int cs;
+  hb_glyph_info_t info = {0};
+  hb_glyph_position_t pos = {0};
+  
+#line 512 "hb-buffer-deserialize-json.hh"
 	{
 	{
-		cs = (int)deserialize_json_start;
+	cs = deserialize_json_start;
 	}
 	}
-	
-#line 228 "hb-buffer-deserialize-json.hh"
+
+#line 517 "hb-buffer-deserialize-json.hh"
 	{
 	{
-		unsigned int _trans = 0;
-		const unsigned char * _keys;
-		const signed char * _inds;
-		int _ic;
-		_resume: {}
-		if ( p == pe )
-			goto _out;
-		_keys = ( _deserialize_json_trans_keys + ((cs<<1)));
-		_inds = ( _deserialize_json_indicies + (_deserialize_json_index_offsets[cs]));
-		
-		if ( ( (*( p))) <= 125 && ( (*( p))) >= 9 ) {
-			_ic = (int)_deserialize_json_char_class[(int)( (*( p))) - 9];
-			if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
-				_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); 
-			else
-				_trans = (unsigned int)_deserialize_json_index_defaults[cs];
-		}
-		else {
-			_trans = (unsigned int)_deserialize_json_index_defaults[cs];
-		}
-		
-		cs = (int)_deserialize_json_cond_targs[_trans];
-		
-		if ( _deserialize_json_cond_actions[_trans] != 0 ) {
-			
-			switch ( _deserialize_json_cond_actions[_trans] ) {
-				case 1:  {
-					{
+	int _slen;
+	int _trans;
+	const unsigned char *_keys;
+	const char *_inds;
+	if ( p == pe )
+		goto _test_eof;
+	if ( cs == 0 )
+		goto _out;
+_resume:
+	_keys = _deserialize_json_trans_keys + (cs<<1);
+	_inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs];
+
+	_slen = _deserialize_json_key_spans[cs];
+	_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
+		(*p) <= _keys[1] ?
+		(*p) - _keys[0] : _slen ];
+
+	cs = _deserialize_json_trans_targs[_trans];
+
+	if ( _deserialize_json_trans_actions[_trans] == 0 )
+		goto _again;
+
+	switch ( _deserialize_json_trans_actions[_trans] ) {
+	case 1:
 #line 38 "hb-buffer-deserialize-json.rl"
 #line 38 "hb-buffer-deserialize-json.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 264 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 5:  {
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
+	break;
+	case 5:
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 280 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 2:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 2:
 #line 51 "hb-buffer-deserialize-json.rl"
 #line 51 "hb-buffer-deserialize-json.rl"
-						
-						tok = p;
-					}
-					
-#line 292 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 15:  {
-					{
+	{
+	tok = p;
+}
+	break;
+	case 15:
 #line 55 "hb-buffer-deserialize-json.rl"
 #line 55 "hb-buffer-deserialize-json.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 302 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 21:  {
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
+	break;
+	case 21:
 #line 56 "hb-buffer-deserialize-json.rl"
 #line 56 "hb-buffer-deserialize-json.rl"
-						if (unlikely (!buffer->ensure_unicode ())) return false; }
-					
-#line 312 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 16:  {
-					{
+	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
+	break;
+	case 16:
 #line 58 "hb-buffer-deserialize-json.rl"
 #line 58 "hb-buffer-deserialize-json.rl"
-						
-						/* TODO Unescape \" and \\ if found. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 328 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 18:  {
-					{
+	{
+	/* TODO Unescape \" and \\ if found. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
+	break;
+	case 18:
 #line 66 "hb-buffer-deserialize-json.rl"
 #line 66 "hb-buffer-deserialize-json.rl"
-						if (!parse_uint (tok, p, &info.codepoint)) return false; }
-					
-#line 338 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 8:  {
-					{
+	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
+	break;
+	case 8:
 #line 67 "hb-buffer-deserialize-json.rl"
 #line 67 "hb-buffer-deserialize-json.rl"
-						if (!parse_uint (tok, p, &info.cluster )) return false; }
-					
-#line 348 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 10:  {
-					{
+	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
+	break;
+	case 10:
 #line 68 "hb-buffer-deserialize-json.rl"
 #line 68 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-					
-#line 358 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 12:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
+	break;
+	case 12:
 #line 69 "hb-buffer-deserialize-json.rl"
 #line 69 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-					
-#line 368 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 3:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
+	break;
+	case 3:
 #line 70 "hb-buffer-deserialize-json.rl"
 #line 70 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-					
-#line 378 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 6:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
+	break;
+	case 6:
 #line 71 "hb-buffer-deserialize-json.rl"
 #line 71 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-					
-#line 388 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 14:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
+	break;
+	case 14:
 #line 51 "hb-buffer-deserialize-json.rl"
 #line 51 "hb-buffer-deserialize-json.rl"
-						
-						tok = p;
-					}
-					
-#line 400 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 55 "hb-buffer-deserialize-json.rl"
 #line 55 "hb-buffer-deserialize-json.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 406 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 20:  {
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
+	break;
+	case 20:
 #line 51 "hb-buffer-deserialize-json.rl"
 #line 51 "hb-buffer-deserialize-json.rl"
-						
-						tok = p;
-					}
-					
-#line 418 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 56 "hb-buffer-deserialize-json.rl"
 #line 56 "hb-buffer-deserialize-json.rl"
-						if (unlikely (!buffer->ensure_unicode ())) return false; }
-					
-#line 424 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 17:  {
-					{
+	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
+	break;
+	case 17:
 #line 58 "hb-buffer-deserialize-json.rl"
 #line 58 "hb-buffer-deserialize-json.rl"
-						
-						/* TODO Unescape \" and \\ if found. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 440 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{
+	/* TODO Unescape \" and \\ if found. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 452 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 19:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 19:
 #line 66 "hb-buffer-deserialize-json.rl"
 #line 66 "hb-buffer-deserialize-json.rl"
-						if (!parse_uint (tok, p, &info.codepoint)) return false; }
-					
-#line 462 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 474 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 9:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 9:
 #line 67 "hb-buffer-deserialize-json.rl"
 #line 67 "hb-buffer-deserialize-json.rl"
-						if (!parse_uint (tok, p, &info.cluster )) return false; }
-					
-#line 484 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 496 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 11:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 11:
 #line 68 "hb-buffer-deserialize-json.rl"
 #line 68 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-					
-#line 506 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 518 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 13:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 13:
 #line 69 "hb-buffer-deserialize-json.rl"
 #line 69 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-					
-#line 528 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 540 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 4:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 4:
 #line 70 "hb-buffer-deserialize-json.rl"
 #line 70 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-					
-#line 550 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 562 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-				case 7:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 7:
 #line 71 "hb-buffer-deserialize-json.rl"
 #line 71 "hb-buffer-deserialize-json.rl"
-						if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-					
-#line 572 "hb-buffer-deserialize-json.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 #line 43 "hb-buffer-deserialize-json.rl"
 #line 43 "hb-buffer-deserialize-json.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 584 "hb-buffer-deserialize-json.hh"
-					
-					
-					break; 
-				}
-			}
-			
-		}
-		
-		if ( cs != 0 ) {
-			p += 1;
-			goto _resume;
-		}
-		_out: {}
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+#line 713 "hb-buffer-deserialize-json.hh"
 	}
 	}
-	
+
+_again:
+	if ( cs == 0 )
+		goto _out;
+	if ( ++p != pe )
+		goto _resume;
+	_test_eof: {}
+	_out: {}
+	}
+
 #line 136 "hb-buffer-deserialize-json.rl"
 #line 136 "hb-buffer-deserialize-json.rl"
-	
-	
-	*end_ptr = p;
-	
-	return p == pe && *(p-1) != ']';
+
+
+  *end_ptr = p;
+
+  return p == pe && *(p-1) != ']';
 }
 }
 
 
 #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
 #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */

+ 763 - 674
thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh

@@ -1,29 +1,30 @@
+
 #line 1 "hb-buffer-deserialize-text.rl"
 #line 1 "hb-buffer-deserialize-text.rl"
 /*
 /*
-* Copyright © 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.
-*
-* Google Author(s): Behdad Esfahbod
-*/
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
 
 
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
@@ -31,143 +32,366 @@
 #include "hb.hh"
 #include "hb.hh"
 
 
 
 
-#line 35 "hb-buffer-deserialize-text.hh"
+#line 36 "hb-buffer-deserialize-text.hh"
 static const unsigned char _deserialize_text_trans_keys[] = {
 static const unsigned char _deserialize_text_trans_keys[] = {
-	1u, 0u, 0u, 13u, 12u, 12u, 2u, 2u,
-	5u, 11u, 0u, 12u, 5u, 6u, 4u, 6u,
-	5u, 6u, 5u, 6u, 4u, 6u, 5u, 6u,
-	3u, 3u, 4u, 6u, 5u, 6u, 3u, 6u,
-	2u, 16u, 4u, 6u, 5u, 6u, 0u, 16u,
-	0u, 16u, 1u, 0u, 0u, 12u, 0u, 16u,
-	0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u,
-	0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u,
-	0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u,
-	0u, 16u, 0u
+	0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, 
+	48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 
+	43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, 
+	9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 
+	9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0
 };
 };
 
 
-static const signed char _deserialize_text_char_class[] = {
-	0, 0, 0, 0, 0, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 0,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 2, 3, 4, 1, 1, 5,
-	6, 6, 6, 6, 6, 6, 6, 6,
-	6, 1, 1, 7, 8, 9, 1, 10,
-	11, 11, 11, 11, 11, 11, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 12, 1, 1, 1,
-	1, 1, 13, 14, 15, 1, 1, 1,
-	11, 11, 11, 11, 11, 11, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 16, 0
+static const char _deserialize_text_key_spans[] = {
+	0, 83, 1, 1, 55, 77, 10, 13, 
+	10, 10, 13, 10, 1, 13, 10, 14, 
+	82, 13, 10, 116, 116, 0, 77, 116, 
+	116, 116, 116, 116, 116, 116, 116, 116, 
+	116, 116, 116, 116, 116
 };
 };
 
 
 static const short _deserialize_text_index_offsets[] = {
 static const short _deserialize_text_index_offsets[] = {
-	0, 0, 14, 15, 16, 23, 36, 38,
-	41, 43, 45, 48, 50, 51, 54, 56,
-	60, 75, 78, 80, 97, 114, 114, 127,
-	144, 161, 178, 195, 212, 229, 246, 263,
-	280, 297, 314, 331, 348, 0
-};
-
-static const signed char _deserialize_text_indicies[] = {
-	1, 0, 0, 0, 0, 0, 0, 2,
-	0, 0, 0, 0, 0, 3, 4, 6,
-	7, 7, 0, 0, 0, 0, 7, 8,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 4, 10, 11, 13, 14,
-	15, 17, 18, 20, 21, 23, 24, 25,
-	27, 28, 29, 31, 32, 33, 35, 36,
-	29, 0, 28, 28, 38, 38, 0, 0,
-	0, 0, 38, 0, 38, 0, 0, 0,
-	38, 38, 38, 40, 41, 42, 44, 45,
-	47, 0, 0, 0, 0, 48, 48, 0,
-	49, 50, 0, 48, 0, 0, 0, 0,
-	51, 52, 0, 0, 0, 0, 0, 0,
-	0, 0, 53, 0, 0, 0, 0, 0,
-	0, 54, 8, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 4, 56,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	57, 0, 0, 0, 0, 0, 0, 58,
-	56, 0, 0, 0, 0, 60, 60, 0,
-	0, 57, 0, 0, 0, 0, 0, 0,
-	58, 63, 62, 64, 0, 62, 62, 62,
-	62, 65, 62, 66, 62, 62, 62, 67,
-	68, 69, 71, 38, 72, 0, 38, 38,
-	38, 38, 73, 38, 74, 38, 38, 38,
-	37, 75, 76, 78, 0, 0, 79, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 80, 81, 82, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 53, 83, 84, 62, 64,
-	0, 62, 62, 62, 62, 65, 62, 66,
-	62, 62, 62, 67, 68, 69, 86, 0,
-	87, 0, 0, 0, 0, 0, 0, 0,
-	88, 0, 0, 0, 0, 57, 89, 91,
-	0, 92, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 93, 94,
-	91, 0, 92, 0, 0, 36, 36, 0,
-	0, 0, 0, 0, 0, 0, 0, 93,
-	94, 86, 0, 87, 0, 0, 97, 97,
-	0, 0, 0, 88, 0, 0, 0, 0,
-	57, 89, 99, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 100, 101, 99, 0, 0, 0, 0,
-	45, 45, 0, 0, 0, 0, 0, 0,
-	0, 0, 100, 101, 78, 0, 0, 79,
-	0, 18, 18, 0, 0, 0, 0, 0,
-	0, 0, 0, 80, 81, 0
+	0, 0, 84, 86, 88, 144, 222, 233, 
+	247, 258, 269, 283, 294, 296, 310, 321, 
+	336, 419, 433, 444, 561, 678, 679, 757, 
+	874, 991, 1108, 1225, 1342, 1459, 1576, 1693, 
+	1810, 1927, 2044, 2161, 2278
 };
 };
 
 
-static const signed char _deserialize_text_index_defaults[] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 62, 38, 0, 0, 62, 0, 0,
-	0, 0, 0, 0, 0, 0
+static const char _deserialize_text_indicies[] = {
+	0, 0, 0, 0, 0, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	0, 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, 2, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 3, 1, 4, 1, 5, 
+	1, 6, 6, 6, 6, 6, 6, 6, 
+	6, 6, 6, 1, 1, 1, 1, 1, 
+	1, 1, 6, 6, 6, 6, 6, 6, 
+	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, 6, 6, 6, 6, 6, 6, 
+	1, 7, 7, 7, 7, 7, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	7, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 4, 1, 8, 
+	9, 9, 9, 9, 9, 9, 9, 9, 
+	9, 1, 10, 1, 1, 11, 12, 12, 
+	12, 12, 12, 12, 12, 12, 12, 1, 
+	13, 14, 14, 14, 14, 14, 14, 14, 
+	14, 14, 1, 15, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 1, 17, 1, 
+	1, 18, 19, 19, 19, 19, 19, 19, 
+	19, 19, 19, 1, 20, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 1, 22, 
+	1, 23, 1, 1, 24, 25, 25, 25, 
+	25, 25, 25, 25, 25, 25, 1, 26, 
+	27, 27, 27, 27, 27, 27, 27, 27, 
+	27, 1, 22, 1, 1, 1, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	1, 28, 28, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 28, 1, 1, 28, 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, 28, 28, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 28, 1, 29, 1, 1, 30, 
+	31, 31, 31, 31, 31, 31, 31, 31, 
+	31, 1, 32, 33, 33, 33, 33, 33, 
+	33, 33, 33, 33, 1, 34, 34, 34, 
+	34, 34, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 34, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 1, 1, 
+	1, 36, 37, 1, 1, 35, 35, 35, 
+	35, 35, 35, 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, 35, 35, 35, 
+	35, 35, 35, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	38, 1, 39, 39, 39, 39, 39, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 39, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 40, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 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, 41, 1, 1, 
+	7, 7, 7, 7, 7, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 7, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 4, 1, 42, 42, 
+	42, 42, 42, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 42, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 43, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 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, 44, 1, 42, 42, 42, 42, 42, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 42, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 1, 1, 1, 1, 
+	43, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 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, 44, 1, 
+	47, 47, 47, 47, 47, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 47, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 48, 1, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 49, 46, 46, 50, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 51, 52, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 53, 46, 54, 54, 54, 
+	54, 54, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 54, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 55, 
+	1, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 56, 28, 28, 57, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	58, 59, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 28, 28, 28, 28, 
+	60, 28, 61, 61, 61, 61, 61, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 61, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 62, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 63, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 64, 1, 65, 
+	65, 65, 65, 65, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 65, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 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, 40, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 66, 1, 67, 67, 67, 67, 
+	67, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 67, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 48, 1, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	49, 46, 46, 50, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 51, 
+	52, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 53, 
+	46, 68, 68, 68, 68, 68, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	68, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 69, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	70, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 43, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 71, 1, 72, 72, 
+	72, 72, 72, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 72, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	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, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 74, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 75, 1, 72, 72, 72, 72, 72, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 72, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 73, 1, 1, 
+	1, 1, 27, 27, 27, 27, 27, 27, 
+	27, 27, 27, 27, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 74, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 75, 1, 
+	68, 68, 68, 68, 68, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 68, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 69, 1, 1, 1, 1, 76, 
+	76, 76, 76, 76, 76, 76, 76, 76, 
+	76, 1, 1, 1, 1, 1, 1, 70, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 43, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 71, 1, 77, 77, 77, 
+	77, 77, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 77, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 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, 78, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	79, 1, 77, 77, 77, 77, 77, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 77, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 33, 33, 33, 33, 33, 33, 33, 
+	33, 33, 33, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 78, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 79, 1, 61, 
+	61, 61, 61, 61, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 61, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 62, 1, 1, 1, 14, 14, 
+	14, 14, 14, 14, 14, 14, 14, 14, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 63, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 64, 1, 0
 };
 };
 
 
-static const signed char _deserialize_text_cond_targs[] = {
-	0, 1, 2, 25, 3, 3, 4, 19,
-	5, 6, 23, 24, 7, 8, 27, 36,
-	8, 27, 36, 9, 30, 33, 10, 11,
-	12, 15, 11, 12, 15, 13, 13, 14,
-	31, 32, 14, 31, 32, 16, 26, 17,
-	18, 34, 35, 18, 34, 35, 19, 20,
-	19, 6, 21, 22, 20, 21, 22, 23,
-	20, 21, 22, 24, 24, 25, 26, 26,
-	7, 9, 10, 16, 21, 29, 26, 26,
-	7, 9, 10, 21, 29, 27, 28, 17,
-	21, 29, 28, 29, 29, 30, 28, 7,
-	10, 29, 31, 28, 7, 21, 29, 32,
-	33, 33, 34, 28, 21, 29, 35, 36,
-	0
+static const char _deserialize_text_trans_targs[] = {
+	1, 0, 2, 25, 3, 4, 19, 5, 
+	23, 24, 8, 27, 36, 27, 36, 30, 
+	33, 11, 12, 15, 12, 15, 13, 14, 
+	31, 32, 31, 32, 26, 18, 34, 35, 
+	34, 35, 20, 19, 6, 21, 22, 20, 
+	21, 22, 20, 21, 22, 24, 26, 26, 
+	7, 9, 10, 16, 21, 29, 26, 7, 
+	9, 10, 16, 21, 29, 28, 17, 21, 
+	29, 28, 29, 29, 28, 7, 10, 29, 
+	28, 7, 21, 29, 33, 28, 21, 29
 };
 };
 
 
-static const signed char _deserialize_text_cond_actions[] = {
-	0, 0, 0, 0, 1, 0, 0, 2,
-	0, 0, 2, 2, 0, 3, 4, 4,
-	0, 5, 5, 0, 4, 4, 0, 3,
-	3, 3, 0, 0, 0, 6, 0, 3,
-	4, 4, 0, 5, 5, 0, 5, 0,
-	3, 4, 4, 0, 5, 5, 7, 7,
-	8, 9, 7, 7, 0, 0, 0, 10,
-	10, 10, 10, 10, 8, 11, 12, 13,
-	14, 14, 14, 15, 11, 11, 16, 17,
-	18, 18, 18, 16, 16, 19, 19, 20,
-	19, 19, 0, 0, 13, 10, 10, 21,
-	21, 10, 22, 22, 23, 22, 22, 22,
-	10, 5, 24, 24, 24, 24, 24, 19,
-	0
+static const char _deserialize_text_trans_actions[] = {
+	0, 0, 0, 0, 1, 0, 2, 0, 
+	2, 2, 3, 4, 4, 5, 5, 4, 
+	4, 3, 3, 3, 0, 0, 6, 3, 
+	4, 4, 5, 5, 5, 3, 4, 4, 
+	5, 5, 7, 8, 9, 7, 7, 0, 
+	0, 0, 10, 10, 10, 8, 12, 13, 
+	14, 14, 14, 15, 11, 11, 17, 18, 
+	18, 18, 0, 16, 16, 19, 20, 19, 
+	19, 0, 0, 13, 10, 21, 21, 10, 
+	22, 23, 22, 22, 5, 24, 24, 24
 };
 };
 
 
-static const signed char _deserialize_text_eof_trans[] = {
-	1, 2, 3, 6, 7, 9, 10, 13,
-	17, 20, 23, 27, 28, 31, 35, 29,
-	38, 40, 44, 47, 53, 54, 55, 56,
-	60, 62, 71, 78, 83, 70, 86, 91,
-	96, 97, 99, 103, 104, 0
+static const char _deserialize_text_eof_actions[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 7, 0, 0, 0, 10, 
+	10, 11, 16, 19, 0, 11, 10, 22, 
+	22, 10, 24, 24, 19
 };
 };
 
 
 static const int deserialize_text_start = 1;
 static const int deserialize_text_start = 1;
@@ -182,583 +406,448 @@ static const int deserialize_text_en_main = 1;
 
 
 static hb_bool_t
 static hb_bool_t
 _hb_buffer_deserialize_text (hb_buffer_t *buffer,
 _hb_buffer_deserialize_text (hb_buffer_t *buffer,
-const char *buf,
-unsigned int buf_len,
-const char **end_ptr,
-hb_font_t *font)
+				    const char *buf,
+				    unsigned int buf_len,
+				    const char **end_ptr,
+				    hb_font_t *font)
 {
 {
-	const char *p = buf, *pe = buf + buf_len;
-	
-	/* Ensure we have positions. */
-	(void) hb_buffer_get_glyph_positions (buffer, nullptr);
-	
-	while (p < pe && ISSPACE (*p))
-	p++;
-	
-	const char *eof = pe, *tok = nullptr;
-	int cs;
-	hb_glyph_info_t info = {0};
-	hb_glyph_position_t pos = {0};
-	
-#line 204 "hb-buffer-deserialize-text.hh"
-	{
-		cs = (int)deserialize_text_start;
+  const char *p = buf, *pe = buf + buf_len;
+
+  /* Ensure we have positions. */
+  (void) hb_buffer_get_glyph_positions (buffer, nullptr);
+
+  while (p < pe && ISSPACE (*p))
+    p++;
+
+  const char *eof = pe, *tok = nullptr;
+  int cs;
+  hb_glyph_info_t info = {0};
+  hb_glyph_position_t pos = {0};
+  
+#line 428 "hb-buffer-deserialize-text.hh"
+	{
+	cs = deserialize_text_start;
 	}
 	}
-	
-#line 209 "hb-buffer-deserialize-text.hh"
-	{
-		unsigned int _trans = 0;
-		const unsigned char * _keys;
-		const signed char * _inds;
-		int _ic;
-		_resume: {}
-		if ( p == pe && p != eof )
-			goto _out;
-		if ( p == eof ) {
-			if ( _deserialize_text_eof_trans[cs] > 0 ) {
-				_trans = (unsigned int)_deserialize_text_eof_trans[cs] - 1;
-			}
-		}
-		else {
-			_keys = ( _deserialize_text_trans_keys + ((cs<<1)));
-			_inds = ( _deserialize_text_indicies + (_deserialize_text_index_offsets[cs]));
-			
-			if ( ( (*( p))) <= 124 && ( (*( p))) >= 9 ) {
-				_ic = (int)_deserialize_text_char_class[(int)( (*( p))) - 9];
-				if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
-					_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); 
-				else
-					_trans = (unsigned int)_deserialize_text_index_defaults[cs];
-			}
-			else {
-				_trans = (unsigned int)_deserialize_text_index_defaults[cs];
-			}
-			
-		}
-		cs = (int)_deserialize_text_cond_targs[_trans];
-		
-		if ( _deserialize_text_cond_actions[_trans] != 0 ) {
-			
-			switch ( _deserialize_text_cond_actions[_trans] ) {
-				case 1:  {
-					{
+
+#line 433 "hb-buffer-deserialize-text.hh"
+	{
+	int _slen;
+	int _trans;
+	const unsigned char *_keys;
+	const char *_inds;
+	if ( p == pe )
+		goto _test_eof;
+	if ( cs == 0 )
+		goto _out;
+_resume:
+	_keys = _deserialize_text_trans_keys + (cs<<1);
+	_inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs];
+
+	_slen = _deserialize_text_key_spans[cs];
+	_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
+		(*p) <= _keys[1] ?
+		(*p) - _keys[0] : _slen ];
+
+	cs = _deserialize_text_trans_targs[_trans];
+
+	if ( _deserialize_text_trans_actions[_trans] == 0 )
+		goto _again;
+
+	switch ( _deserialize_text_trans_actions[_trans] ) {
+	case 1:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 252 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 3:  {
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
+	break;
+	case 3:
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 264 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 5:  {
-					{
+	{
+	tok = p;
+}
+	break;
+	case 5:
 #line 55 "hb-buffer-deserialize-text.rl"
 #line 55 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 274 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 8:  {
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
+	break;
+	case 8:
 #line 56 "hb-buffer-deserialize-text.rl"
 #line 56 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_unicode ())) return false; }
-					
-#line 284 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 18:  {
-					{
+	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
+	break;
+	case 18:
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 300 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 9:  {
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
+	break;
+	case 9:
 #line 66 "hb-buffer-deserialize-text.rl"
 #line 66 "hb-buffer-deserialize-text.rl"
-						if (!parse_hex (tok, p, &info.codepoint )) return false; }
-					
-#line 310 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 21:  {
-					{
+	{if (!parse_hex (tok, p, &info.codepoint )) return false; }
+	break;
+	case 21:
 #line 68 "hb-buffer-deserialize-text.rl"
 #line 68 "hb-buffer-deserialize-text.rl"
-						if (!parse_uint (tok, p, &info.cluster )) return false; }
-					
-#line 320 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 6:  {
-					{
+	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
+	break;
+	case 6:
 #line 69 "hb-buffer-deserialize-text.rl"
 #line 69 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-					
-#line 330 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 23:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
+	break;
+	case 23:
 #line 70 "hb-buffer-deserialize-text.rl"
 #line 70 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-					
-#line 340 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 20:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
+	break;
+	case 20:
 #line 71 "hb-buffer-deserialize-text.rl"
 #line 71 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-					
-#line 350 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 15:  {
-					{
+	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
+	break;
+	case 15:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 363 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 371 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 4:  {
-					{
+	{
+	tok = p;
+}
+	break;
+	case 4:
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 383 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 55 "hb-buffer-deserialize-text.rl"
 #line 55 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 389 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 2:  {
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
+	break;
+	case 2:
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 401 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 56 "hb-buffer-deserialize-text.rl"
 #line 56 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_unicode ())) return false; }
-					
-#line 407 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 16:  {
-					{
+	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
+	break;
+	case 16:
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 423 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 435 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 7:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 7:
 #line 66 "hb-buffer-deserialize-text.rl"
 #line 66 "hb-buffer-deserialize-text.rl"
-						if (!parse_hex (tok, p, &info.codepoint )) return false; }
-					
-#line 445 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{if (!parse_hex (tok, p, &info.codepoint )) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 457 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 10:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 10:
 #line 68 "hb-buffer-deserialize-text.rl"
 #line 68 "hb-buffer-deserialize-text.rl"
-						if (!parse_uint (tok, p, &info.cluster )) return false; }
-					
-#line 467 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 479 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 22:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 22:
 #line 70 "hb-buffer-deserialize-text.rl"
 #line 70 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-					
-#line 489 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 501 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 19:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 19:
 #line 71 "hb-buffer-deserialize-text.rl"
 #line 71 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-					
-#line 511 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 523 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 24:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 24:
 #line 72 "hb-buffer-deserialize-text.rl"
 #line 72 "hb-buffer-deserialize-text.rl"
-						if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-					
-#line 533 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 545 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 12:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 12:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 558 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 566 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 55 "hb-buffer-deserialize-text.rl"
 #line 55 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 572 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 14:  {
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
+	break;
+	case 14:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 585 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 593 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 605 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 17:  {
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
+	break;
+	case 17:
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 621 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
 #line 55 "hb-buffer-deserialize-text.rl"
 #line 55 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 627 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 639 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 11:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 11:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 652 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 660 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 672 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 684 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-				case 13:  {
-					{
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 13:
 #line 38 "hb-buffer-deserialize-text.rl"
 #line 38 "hb-buffer-deserialize-text.rl"
-						
-						memset (&info, 0, sizeof (info));
-						memset (&pos , 0, sizeof (pos ));
-					}
-					
-#line 697 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
 #line 51 "hb-buffer-deserialize-text.rl"
 #line 51 "hb-buffer-deserialize-text.rl"
-						
-						tok = p;
-					}
-					
-#line 705 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	tok = p;
+}
 #line 58 "hb-buffer-deserialize-text.rl"
 #line 58 "hb-buffer-deserialize-text.rl"
-						
-						/* TODO Unescape delimeters. */
-						if (!hb_font_glyph_from_string (font,
-						tok, p - tok,
-						&info.codepoint))
-						return false;
-					}
-					
-#line 717 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
 #line 55 "hb-buffer-deserialize-text.rl"
 #line 55 "hb-buffer-deserialize-text.rl"
-						if (unlikely (!buffer->ensure_glyphs ())) return false; }
-					
-#line 723 "hb-buffer-deserialize-text.hh"
-					
-					{
+	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
 #line 43 "hb-buffer-deserialize-text.rl"
-						
-						buffer->add_info (info);
-						if (unlikely (!buffer->successful))
-						return false;
-						buffer->pos[buffer->len - 1] = pos;
-						*end_ptr = p;
-					}
-					
-#line 735 "hb-buffer-deserialize-text.hh"
-					
-					
-					break; 
-				}
-			}
-			
-		}
-		
-		if ( p == eof ) {
-			if ( cs >= 19 )
-				goto _out;
-		}
-		else {
-			if ( cs != 0 ) {
-				p += 1;
-				goto _resume;
-			}
-		}
-		_out: {}
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+#line 722 "hb-buffer-deserialize-text.hh"
 	}
 	}
-	
-#line 138 "hb-buffer-deserialize-text.rl"
-	
-	
+
+_again:
+	if ( cs == 0 )
+		goto _out;
+	if ( ++p != pe )
+		goto _resume;
+	_test_eof: {}
+	if ( p == eof )
+	{
+	switch ( _deserialize_text_eof_actions[cs] ) {
+	case 16:
+#line 58 "hb-buffer-deserialize-text.rl"
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 7:
+#line 66 "hb-buffer-deserialize-text.rl"
+	{if (!parse_hex (tok, p, &info.codepoint )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 10:
+#line 68 "hb-buffer-deserialize-text.rl"
+	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 22:
+#line 70 "hb-buffer-deserialize-text.rl"
+	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 19:
+#line 71 "hb-buffer-deserialize-text.rl"
+	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 24:
+#line 72 "hb-buffer-deserialize-text.rl"
+	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
+	*end_ptr = p;
+}
+	break;
+	case 11:
+#line 38 "hb-buffer-deserialize-text.rl"
+	{
+	memset (&info, 0, sizeof (info));
+	memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text.rl"
+	{
+	tok = p;
+}
+#line 58 "hb-buffer-deserialize-text.rl"
+	{
+	/* TODO Unescape delimeters. */
+	if (!hb_font_glyph_from_string (font,
+					tok, p - tok,
+					&info.codepoint))
+	  return false;
+}
+#line 43 "hb-buffer-deserialize-text.rl"
+	{
+	buffer->add_info (info);
+	if (unlikely (!buffer->successful))
+	  return false;
+	buffer->pos[buffer->len - 1] = pos;
 	*end_ptr = p;
 	*end_ptr = p;
-	
-	return p == pe && *(p-1) != ']';
+}
+	break;
+#line 839 "hb-buffer-deserialize-text.hh"
+	}
+	}
+
+	_out: {}
+	}
+
+#line 138 "hb-buffer-deserialize-text.rl"
+
+
+  *end_ptr = p;
+
+  return p == pe && *(p-1) != ']';
 }
 }
 
 
 #endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */
 #endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */

+ 58 - 41
thirdparty/harfbuzz/src/hb-buffer.cc

@@ -96,14 +96,15 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
  * As an optimization, both info and out_info may point to the
  * As an optimization, both info and out_info may point to the
  * same piece of memory, which is owned by info.  This remains the
  * same piece of memory, which is owned by info.  This remains the
  * case as long as out_len doesn't exceed i at any time.
  * case as long as out_len doesn't exceed i at any time.
- * In that case, swap_buffers() is no-op and the glyph operations operate
- * mostly in-place.
+ * In that case, swap_buffers() is mostly no-op and the glyph operations
+ * operate mostly in-place.
  *
  *
  * As soon as out_info gets longer than info, out_info is moved over
  * As soon as out_info gets longer than info, out_info is moved over
- * to an alternate buffer (which we reuse the pos buffer for!), and its
+ * to an alternate buffer (which we reuse the pos buffer for), and its
  * current contents (out_len entries) are copied to the new place.
  * current contents (out_len entries) are copied to the new place.
+ *
  * This should all remain transparent to the user.  swap_buffers() then
  * This should all remain transparent to the user.  swap_buffers() then
- * switches info and out_info.
+ * switches info over to out_info and does housekeeping.
  */
  */
 
 
 
 
@@ -136,8 +137,8 @@ hb_buffer_t::enlarge (unsigned int size)
   if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
   if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
     goto done;
     goto done;
 
 
-  new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
-  new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
+  new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
+  new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
 
 
 done:
 done:
   if (unlikely (!new_pos || !new_info))
   if (unlikely (!new_pos || !new_info))
@@ -281,22 +282,13 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
 }
 }
 
 
 
 
-void
-hb_buffer_t::remove_output ()
-{
-  have_output = false;
-  have_positions = false;
-
-  out_len = 0;
-  out_info = info;
-}
-
 void
 void
 hb_buffer_t::clear_output ()
 hb_buffer_t::clear_output ()
 {
 {
   have_output = true;
   have_output = true;
   have_positions = false;
   have_positions = false;
 
 
+  idx = 0;
   out_len = 0;
   out_len = 0;
   out_info = info;
   out_info = info;
 }
 }
@@ -316,29 +308,23 @@ hb_buffer_t::clear_positions ()
 void
 void
 hb_buffer_t::swap_buffers ()
 hb_buffer_t::swap_buffers ()
 {
 {
-  if (unlikely (!successful)) return;
+  assert (have_output);
 
 
   assert (idx <= len);
   assert (idx <= len);
-  if (unlikely (!next_glyphs (len - idx))) return;
 
 
-  assert (have_output);
-  have_output = false;
+  if (unlikely (!successful || !next_glyphs (len - idx)))
+    goto reset;
 
 
   if (out_info != info)
   if (out_info != info)
   {
   {
-    hb_glyph_info_t *tmp;
-    tmp = info;
+    pos = (hb_glyph_position_t *) info;
     info = out_info;
     info = out_info;
-    out_info = tmp;
-
-    pos = (hb_glyph_position_t *) out_info;
   }
   }
-
-  unsigned int tmp;
-  tmp = len;
   len = out_len;
   len = out_len;
-  out_len = tmp;
 
 
+reset:
+  have_output = false;
+  out_len = 0;
   idx = 0;
   idx = 0;
 }
 }
 
 
@@ -373,12 +359,11 @@ hb_buffer_t::move_to (unsigned int i)
     /* This will blow in our face if memory allocation fails later
     /* This will blow in our face if memory allocation fails later
      * in this same lookup...
      * in this same lookup...
      *
      *
-     * We used to shift with extra 32 items, instead of the 0 below.
+     * We used to shift with extra 32 items.
      * But that would leave empty slots in the buffer in case of allocation
      * 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;
+     * failures.  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 - idx))) return false;
 
 
     assert (idx >= count);
     assert (idx >= count);
 
 
@@ -630,7 +615,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
   HB_BUFFER_CONTENT_TYPE_INVALID,
   HB_BUFFER_CONTENT_TYPE_INVALID,
   HB_SEGMENT_PROPERTIES_DEFAULT,
   HB_SEGMENT_PROPERTIES_DEFAULT,
   false, /* successful */
   false, /* successful */
-  true, /* have_output */
+  false, /* have_output */
   true  /* have_positions */
   true  /* have_positions */
 
 
   /* Zero is good enough for everything else. */
   /* Zero is good enough for everything else. */
@@ -717,14 +702,14 @@ hb_buffer_destroy (hb_buffer_t *buffer)
 
 
   hb_unicode_funcs_destroy (buffer->unicode);
   hb_unicode_funcs_destroy (buffer->unicode);
 
 
-  free (buffer->info);
-  free (buffer->pos);
+  hb_free (buffer->info);
+  hb_free (buffer->pos);
 #ifndef HB_NO_BUFFER_MESSAGE
 #ifndef HB_NO_BUFFER_MESSAGE
   if (buffer->message_destroy)
   if (buffer->message_destroy)
     buffer->message_destroy (buffer->message_data);
     buffer->message_destroy (buffer->message_data);
 #endif
 #endif
 
 
-  free (buffer);
+  hb_free (buffer);
 }
 }
 
 
 /**
 /**
@@ -1363,6 +1348,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
  * Returns @buffer glyph position array.  Returned pointer
  * Returns @buffer glyph position array.  Returned pointer
  * is valid as long as @buffer contents are not modified.
  * is valid as long as @buffer contents are not modified.
  *
  *
+ * If buffer did not have positions before, the positions will be
+ * initialized to zeros, unless this function is called from
+ * within a buffer message callback (see hb_buffer_set_message_func()),
+ * in which case %NULL is returned.
+ *
  * Return value: (transfer none) (array length=length):
  * Return value: (transfer none) (array length=length):
  * The @buffer glyph position array.
  * The @buffer glyph position array.
  * The value valid as long as buffer has not been modified.
  * The value valid as long as buffer has not been modified.
@@ -1373,12 +1363,17 @@ hb_glyph_position_t *
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
 			       unsigned int *length)
 			       unsigned int *length)
 {
 {
-  if (!buffer->have_positions)
-    buffer->clear_positions ();
-
   if (length)
   if (length)
     *length = buffer->len;
     *length = buffer->len;
 
 
+  if (!buffer->have_positions)
+  {
+    if (unlikely (buffer->message_depth))
+      return nullptr;
+
+    buffer->clear_positions ();
+  }
+
   return (hb_glyph_position_t *) buffer->pos;
   return (hb_glyph_position_t *) buffer->pos;
 }
 }
 
 
@@ -1760,6 +1755,28 @@ hb_buffer_append (hb_buffer_t *buffer,
   memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
   memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
   if (buffer->have_positions)
   if (buffer->have_positions)
     memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
     memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
+
+  if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
+  {
+    /* See similar logic in add_utf. */
+
+    /* pre-context */
+    if (!orig_len && start + source->context_len[0] > 0)
+    {
+      buffer->clear_context (0);
+      while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
+	buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint;
+      for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++)
+	buffer->context[0][buffer->context_len[0]++] = source->context[0][i];
+    }
+
+    /* post-context */
+    buffer->clear_context (1);
+    while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
+      buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint;
+    for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++)
+      buffer->context[1][buffer->context_len[1]++] = source->context[1][i];
+  }
 }
 }
 
 
 
 

+ 11 - 6
thirdparty/harfbuzz/src/hb-buffer.hh

@@ -107,7 +107,7 @@ struct hb_buffer_t
 
 
   unsigned int idx; /* Cursor into ->info and ->pos arrays */
   unsigned int idx; /* Cursor into ->info and ->pos arrays */
   unsigned int len; /* Length of ->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 out_len; /* Length of ->out_info array if have_output */
 
 
   unsigned int allocated; /* Length of allocated arrays */
   unsigned int allocated; /* Length of allocated arrays */
   hb_glyph_info_t     *info;
   hb_glyph_info_t     *info;
@@ -128,6 +128,9 @@ struct hb_buffer_t
   hb_buffer_message_func_t message_func;
   hb_buffer_message_func_t message_func;
   void *message_data;
   void *message_data;
   hb_destroy_func_t message_destroy;
   hb_destroy_func_t message_destroy;
+  unsigned message_depth; /* How deeply are we inside a message callback? */
+#else
+  static constexpr unsigned message_depth = 0u;
 #endif
 #endif
 
 
   /* Internal debugging. */
   /* Internal debugging. */
@@ -186,13 +189,10 @@ struct hb_buffer_t
   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
   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]; }
   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
 
 
-  HB_NODISCARD bool has_separate_output () const { return info != out_info; }
-
-
   HB_INTERNAL void reset ();
   HB_INTERNAL void reset ();
   HB_INTERNAL void clear ();
   HB_INTERNAL void clear ();
 
 
-  unsigned int backtrack_len () const { return have_output? out_len : idx; }
+  unsigned int backtrack_len () const { return have_output ? out_len : idx; }
   unsigned int lookahead_len () const { return len - idx; }
   unsigned int lookahead_len () const { return len - idx; }
   unsigned int next_serial () { return serial++; }
   unsigned int next_serial () { return serial++; }
 
 
@@ -206,7 +206,6 @@ struct hb_buffer_t
   HB_INTERNAL void guess_segment_properties ();
   HB_INTERNAL void guess_segment_properties ();
 
 
   HB_INTERNAL void swap_buffers ();
   HB_INTERNAL void swap_buffers ();
-  HB_INTERNAL void remove_output ();
   HB_INTERNAL void clear_output ();
   HB_INTERNAL void clear_output ();
   HB_INTERNAL void clear_positions ();
   HB_INTERNAL void clear_positions ();
 
 
@@ -400,10 +399,16 @@ struct hb_buffer_t
 #else
 #else
     if (!messaging ())
     if (!messaging ())
       return true;
       return true;
+
+    message_depth++;
+
     va_list ap;
     va_list ap;
     va_start (ap, fmt);
     va_start (ap, fmt);
     bool ret = message_impl (font, fmt, ap);
     bool ret = message_impl (font, fmt, ap);
     va_end (ap);
     va_end (ap);
+
+    message_depth--;
+
     return ret;
     return ret;
 #endif
 #endif
   }
   }

+ 1 - 1
thirdparty/harfbuzz/src/hb-cache.hh

@@ -30,7 +30,7 @@
 #include "hb.hh"
 #include "hb.hh"
 
 
 
 
-/* Implements a lock-free cache for int->int functions. */
+/* Implements a lockfree cache for int->int functions. */
 
 
 template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
 template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
 struct hb_cache_t
 struct hb_cache_t

+ 1 - 1
thirdparty/harfbuzz/src/hb-cff-interp-common.hh

@@ -263,7 +263,7 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
 
 
     T *ip = c->allocate_size<T> (T::static_size);
     T *ip = c->allocate_size<T> (T::static_size);
     if (unlikely (!ip)) return_trace (false);
     if (unlikely (!ip)) return_trace (false);
-    return_trace (c->check_assign (*ip, value));
+    return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
   }
 
 
   template <typename V>
   template <typename V>

+ 2 - 2
thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh

@@ -136,8 +136,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
 	if (unlikely (!scalars.resize (region_count)))
 	if (unlikely (!scalars.resize (region_count)))
 	  set_error ();
 	  set_error ();
 	else
 	else
-	  varStore->varStore.get_scalars (get_ivs (), coords, num_coords,
-					  &scalars[0], region_count);
+	  varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
+						 &scalars[0], region_count);
       }
       }
       seen_blend = true;
       seen_blend = true;
     }
     }

+ 15 - 18
thirdparty/harfbuzz/src/hb-common.cc

@@ -257,13 +257,11 @@ struct hb_language_item_t {
   bool operator == (const char *s) const
   bool operator == (const char *s) const
   { return lang_equal (lang, s); }
   { return lang_equal (lang, 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.
-    */
+  hb_language_item_t & operator = (const char *s)
+  {
+    /* We can't call strdup(), because we allow custom allocators. */
     size_t len = strlen(s) + 1;
     size_t len = strlen(s) + 1;
-    lang = (hb_language_t) malloc(len);
+    lang = (hb_language_t) hb_malloc(len);
     if (likely (lang))
     if (likely (lang))
     {
     {
       memcpy((unsigned char *) lang, s, len);
       memcpy((unsigned char *) lang, s, len);
@@ -274,16 +272,15 @@ struct hb_language_item_t {
     return *this;
     return *this;
   }
   }
 
 
-  void fini () { free ((void *) lang); }
+  void fini () { hb_free ((void *) lang); }
 };
 };
 
 
 
 
-/* Thread-safe lock-free language list */
+/* Thread-safe lockfree language list */
 
 
 static hb_atomic_ptr_t <hb_language_item_t> langs;
 static hb_atomic_ptr_t <hb_language_item_t> langs;
 
 
-#if HB_USE_ATEXIT
-static void
+static inline void
 free_langs ()
 free_langs ()
 {
 {
 retry:
 retry:
@@ -294,11 +291,10 @@ retry:
   while (first_lang) {
   while (first_lang) {
     hb_language_item_t *next = first_lang->next;
     hb_language_item_t *next = first_lang->next;
     first_lang->fini ();
     first_lang->fini ();
-    free (first_lang);
+    hb_free (first_lang);
     first_lang = next;
     first_lang = next;
   }
   }
 }
 }
-#endif
 
 
 static hb_language_item_t *
 static hb_language_item_t *
 lang_find_or_insert (const char *key)
 lang_find_or_insert (const char *key)
@@ -311,28 +307,26 @@ retry:
       return lang;
       return lang;
 
 
   /* Not found; allocate one. */
   /* Not found; allocate one. */
-  hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
+  hb_language_item_t *lang = (hb_language_item_t *) hb_calloc (1, sizeof (hb_language_item_t));
   if (unlikely (!lang))
   if (unlikely (!lang))
     return nullptr;
     return nullptr;
   lang->next = first_lang;
   lang->next = first_lang;
   *lang = key;
   *lang = key;
   if (unlikely (!lang->lang))
   if (unlikely (!lang->lang))
   {
   {
-    free (lang);
+    hb_free (lang);
     return nullptr;
     return nullptr;
   }
   }
 
 
   if (unlikely (!langs.cmpexch (first_lang, lang)))
   if (unlikely (!langs.cmpexch (first_lang, lang)))
   {
   {
     lang->fini ();
     lang->fini ();
-    free (lang);
+    hb_free (lang);
     goto retry;
     goto retry;
   }
   }
 
 
-#if HB_USE_ATEXIT
   if (!first_lang)
   if (!first_lang)
-    atexit (free_langs); /* First person registers atexit() callback. */
-#endif
+    hb_atexit (free_langs); /* First person registers atexit() callback. */
 
 
   return lang;
   return lang;
 }
 }
@@ -601,6 +595,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
     case HB_SCRIPT_CHORASMIAN:
     case HB_SCRIPT_CHORASMIAN:
     case HB_SCRIPT_YEZIDI:
     case HB_SCRIPT_YEZIDI:
 
 
+    /* Unicode-14.0 additions */
+    case HB_SCRIPT_OLD_UYGHUR:
+
       return HB_DIRECTION_RTL;
       return HB_DIRECTION_RTL;
 
 
 
 

+ 14 - 0
thirdparty/harfbuzz/src/hb-common.h

@@ -476,6 +476,11 @@ hb_language_get_default (void);
  * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
  * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
  * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
  * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
  * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
  * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
+ * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
+ * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
+ * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
+ * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
+ * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
  * @HB_SCRIPT_INVALID: No script set
  * @HB_SCRIPT_INVALID: No script set
  *
  *
  * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
  * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
@@ -683,6 +688,15 @@ typedef enum
   HB_SCRIPT_KHITAN_SMALL_SCRIPT		= HB_TAG ('K','i','t','s'), /*13.0*/
   HB_SCRIPT_KHITAN_SMALL_SCRIPT		= HB_TAG ('K','i','t','s'), /*13.0*/
   HB_SCRIPT_YEZIDI			= HB_TAG ('Y','e','z','i'), /*13.0*/
   HB_SCRIPT_YEZIDI			= HB_TAG ('Y','e','z','i'), /*13.0*/
 
 
+  /*
+   * Since 3.0.0
+   */
+  HB_SCRIPT_CYPRO_MINOAN		= HB_TAG ('C','p','m','n'), /*14.0*/
+  HB_SCRIPT_OLD_UYGHUR			= HB_TAG ('O','u','g','r'), /*14.0*/
+  HB_SCRIPT_TANGSA			= HB_TAG ('T','n','s','a'), /*14.0*/
+  HB_SCRIPT_TOTO			= HB_TAG ('T','o','t','o'), /*14.0*/
+  HB_SCRIPT_VITHKUQI			= HB_TAG ('V','i','t','h'), /*14.0*/
+
   /* No script set. */
   /* No script set. */
   HB_SCRIPT_INVALID			= HB_TAG_NONE,
   HB_SCRIPT_INVALID			= HB_TAG_NONE,
 
 

+ 4 - 5
thirdparty/harfbuzz/src/hb-config.hh

@@ -86,6 +86,9 @@
 #define HB_NO_LEGACY
 #define HB_NO_LEGACY
 #endif
 #endif
 
 
+#ifdef HAVE_CONFIG_OVERRIDE_H
+#include "config-override.h"
+#endif
 
 
 /* Closure of options. */
 /* Closure of options. */
 
 
@@ -117,7 +120,7 @@
 #define HB_NO_CMAP_LEGACY_SUBTABLES
 #define HB_NO_CMAP_LEGACY_SUBTABLES
 #define HB_NO_FALLBACK_SHAPE
 #define HB_NO_FALLBACK_SHAPE
 #define HB_NO_OT_KERN
 #define HB_NO_OT_KERN
-#define HB_NO_OT_LAYOUT_BLACKLIST
+#define HB_NO_OT_LAYOUT_BLOCKLIST
 #define HB_NO_OT_SHAPE_FALLBACK
 #define HB_NO_OT_SHAPE_FALLBACK
 #endif
 #endif
 
 
@@ -155,9 +158,5 @@
 #endif
 #endif
 #endif
 #endif
 
 
-#ifdef HAVE_CONFIG_OVERRIDE_H
-#include "config-override.h"
-#endif
-
 
 
 #endif /* HB_CONFIG_HH */
 #endif /* HB_CONFIG_HH */

+ 44 - 6
thirdparty/harfbuzz/src/hb-coretext.cc

@@ -332,6 +332,44 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
     return nullptr;
     return nullptr;
   }
   }
 
 
+  if (font->coords)
+  {
+    CFMutableDictionaryRef variations =
+      CFDictionaryCreateMutable (kCFAllocatorDefault,
+				 font->num_coords,
+				 &kCFTypeDictionaryKeyCallBacks,
+				 &kCFTypeDictionaryValueCallBacks);
+
+    for (unsigned i = 0; i < font->num_coords; i++)
+    {
+      if (font->coords[i] == 0.) continue;
+
+      hb_ot_var_axis_info_t info;
+      unsigned int c = 1;
+      hb_ot_var_get_axis_infos (font->face, i, &c, &info);
+      CFDictionarySetValue (variations,
+	CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
+	CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
+      );
+    }
+
+    CFDictionaryRef attributes =
+      CFDictionaryCreate (kCFAllocatorDefault,
+			  (const void **) &kCTFontVariationAttribute,
+			  (const void **) &variations,
+			  1,
+			  &kCFTypeDictionaryKeyCallBacks,
+			  &kCFTypeDictionaryValueCallBacks);
+
+    CTFontDescriptorRef varDesc = CTFontDescriptorCreateWithAttributes (attributes);
+    CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0, nullptr, varDesc);
+
+    CFRelease (ct_font);
+    CFRelease (attributes);
+    CFRelease (variations);
+    ct_font = new_ct_font;
+  }
+
   return (hb_coretext_font_data_t *) ct_font;
   return (hb_coretext_font_data_t *) ct_font;
 }
 }
 
 
@@ -1061,7 +1099,7 @@ resize_and_retry:
 	hb_glyph_info_t *info = run_info;
 	hb_glyph_info_t *info = run_info;
 	if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
 	if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
 	{
 	{
-	  hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
+	  hb_position_t x_offset = round ((positions[0].x - advances_so_far) * x_mult);
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  {
 	  {
 	    CGFloat advance;
 	    CGFloat advance;
@@ -1069,15 +1107,15 @@ resize_and_retry:
 	      advance = positions[j + 1].x - positions[j].x;
 	      advance = positions[j + 1].x - positions[j].x;
 	    else /* last glyph */
 	    else /* last glyph */
 	      advance = run_advance - (positions[j].x - positions[0].x);
 	      advance = run_advance - (positions[j].x - positions[0].x);
-	    info->mask = advance * x_mult;
+	    info->mask = round (advance * x_mult);
 	    info->var1.i32 = x_offset;
 	    info->var1.i32 = x_offset;
-	    info->var2.i32 = positions[j].y * y_mult;
+	    info->var2.i32 = round (positions[j].y * y_mult);
 	    info++;
 	    info++;
 	  }
 	  }
 	}
 	}
 	else
 	else
 	{
 	{
-	  hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
+	  hb_position_t y_offset = round ((positions[0].y - advances_so_far) * y_mult);
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  for (unsigned int j = 0; j < num_glyphs; j++)
 	  {
 	  {
 	    CGFloat advance;
 	    CGFloat advance;
@@ -1085,8 +1123,8 @@ resize_and_retry:
 	      advance = positions[j + 1].y - positions[j].y;
 	      advance = positions[j + 1].y - positions[j].y;
 	    else /* last glyph */
 	    else /* last glyph */
 	      advance = run_advance - (positions[j].y - positions[0].y);
 	      advance = run_advance - (positions[j].y - positions[0].y);
-	    info->mask = advance * y_mult;
-	    info->var1.i32 = positions[j].x * x_mult;
+	    info->mask = round (advance * y_mult);
+	    info->var1.i32 = round (positions[j].x * x_mult);
 	    info->var2.i32 = y_offset;
 	    info->var2.i32 = y_offset;
 	    info++;
 	    info++;
 	  }
 	  }

+ 5 - 1
thirdparty/harfbuzz/src/hb-debug.hh

@@ -307,7 +307,7 @@ struct hb_auto_trace_t
 
 
     _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
     _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
 			      "return %s (line %d)",
 			      "return %s (line %d)",
-			      hb_printer_t<decltype (v)>().print (v), line);
+			      hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
     if (plevel) --*plevel;
     if (plevel) --*plevel;
     plevel = nullptr;
     plevel = nullptr;
     returned = true;
     returned = true;
@@ -438,6 +438,10 @@ struct hb_no_trace_t {
 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
 #endif
 #endif
 
 
+#ifndef HB_DEBUG_SUBSET_REPACK
+#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
+#endif
+
 #ifndef HB_DEBUG_DISPATCH
 #ifndef HB_DEBUG_DISPATCH
 #define HB_DEBUG_DISPATCH ( \
 #define HB_DEBUG_DISPATCH ( \
 	HB_DEBUG_APPLY + \
 	HB_DEBUG_APPLY + \

+ 0 - 3
thirdparty/harfbuzz/src/hb-deprecated.h

@@ -107,9 +107,6 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
 			      hb_font_get_glyph_func_t func,
 			      hb_font_get_glyph_func_t func,
 			      void *user_data, hb_destroy_func_t destroy);
 			      void *user_data, hb_destroy_func_t destroy);
 
 
-HB_EXTERN HB_DEPRECATED void
-hb_set_invert (hb_set_t *set);
-
 /**
 /**
  * hb_unicode_eastasian_width_func_t:
  * hb_unicode_eastasian_width_func_t:
  * @ufuncs: A Unicode-functions structure
  * @ufuncs: A Unicode-functions structure

+ 65 - 199
thirdparty/harfbuzz/src/hb-directwrite.cc

@@ -32,6 +32,7 @@
 
 
 #include "hb-directwrite.h"
 #include "hb-directwrite.h"
 
 
+#include "hb-ms-feature-ranges.hh"
 
 
 /**
 /**
  * SECTION:hb-directwrite
  * SECTION:hb-directwrite
@@ -42,24 +43,6 @@
  * Functions for using HarfBuzz with DirectWrite fonts.
  * Functions for using HarfBuzz with DirectWrite fonts.
  **/
  **/
 
 
-/* Declare object creator for dynamic support of DWRITE */
-typedef HRESULT (* WINAPI t_DWriteCreateFactory)(
-  DWRITE_FACTORY_TYPE factoryType,
-  REFIID              iid,
-  IUnknown            **factory
-);
-
-/*
- * 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 delete [] (void* pointer) { free (pointer); }
-
-
 /*
 /*
  * DirectWrite font stream helpers
  * DirectWrite font stream helpers
  */
  */
@@ -154,7 +137,6 @@ public:
 
 
 struct hb_directwrite_face_data_t
 struct hb_directwrite_face_data_t
 {
 {
-  HMODULE dwrite_dll;
   IDWriteFactory *dwriteFactory;
   IDWriteFactory *dwriteFactory;
   IDWriteFontFile *fontFile;
   IDWriteFontFile *fontFile;
   DWriteFontFileStream *fontFileStream;
   DWriteFontFileStream *fontFileStream;
@@ -176,33 +158,12 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
     return nullptr; \
     return nullptr; \
   } HB_STMT_END
   } HB_STMT_END
 
 
-  data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
-  if (unlikely (!data->dwrite_dll))
-    FAIL ("Cannot find DWrite.DLL");
-
-  t_DWriteCreateFactory p_DWriteCreateFactory;
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-function-type"
-#endif
-
-  p_DWriteCreateFactory = (t_DWriteCreateFactory)
-			  GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-  if (unlikely (!p_DWriteCreateFactory))
-    FAIL ("Cannot find DWriteCreateFactory().");
-
   HRESULT hr;
   HRESULT hr;
 
 
   // TODO: factory and fontFileLoader should be cached separately
   // TODO: factory and fontFileLoader should be cached separately
   IDWriteFactory* dwriteFactory;
   IDWriteFactory* dwriteFactory;
-  hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
-			      (IUnknown**) &dwriteFactory);
+  hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+			    (IUnknown**) &dwriteFactory);
 
 
   if (unlikely (hr != S_OK))
   if (unlikely (hr != S_OK))
     FAIL ("Failed to run DWriteCreateFactory().");
     FAIL ("Failed to run DWriteCreateFactory().");
@@ -266,8 +227,6 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
     delete data->fontFileStream;
     delete data->fontFileStream;
   if (data->faceBlob)
   if (data->faceBlob)
     hb_blob_destroy (data->faceBlob);
     hb_blob_destroy (data->faceBlob);
-  if (data->dwrite_dll)
-    FreeLibrary (data->dwrite_dll);
   if (data)
   if (data)
     delete data;
     delete data;
 }
 }
@@ -552,13 +511,12 @@ protected:
  * shaper
  * shaper
  */
  */
 
 
-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_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_face_t *face = font->face;
   hb_face_t *face = font->face;
   const hb_directwrite_face_data_t *face_data = face->data.directwrite;
   const hb_directwrite_face_data_t *face_data = face->data.directwrite;
@@ -611,8 +569,6 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
       log_clusters[chars_len++] = cluster; /* Surrogates. */
       log_clusters[chars_len++] = cluster; /* Surrogates. */
   }
   }
 
 
-  // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
-
   DWRITE_READING_DIRECTION readingDirection;
   DWRITE_READING_DIRECTION readingDirection;
   readingDirection = buffer->props.direction ?
   readingDirection = buffer->props.direction ?
 		     DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
 		     DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
@@ -623,7 +579,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
   * but we never attempt to shape a word longer than 64K characters
   * but we never attempt to shape a word longer than 64K characters
   * in a single gfxShapedWord, so we cannot exceed that limit.
   * in a single gfxShapedWord, so we cannot exceed that limit.
   */
   */
-  uint32_t textLength = buffer->len;
+  uint32_t textLength = chars_len;
 
 
   TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
   TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
   TextAnalysis::Run *runHead;
   TextAnalysis::Run *runHead;
@@ -648,38 +604,54 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
     mbstowcs ((wchar_t*) localeName,
     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;
-  typographic_features.featureCount = num_features;
+  /*
+   * Set up features.
+   */
+  static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
+  static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
+  hb_vector_t<hb_ms_features_t *> range_features;
+  hb_vector_t<uint32_t> range_char_counts;
   if (num_features)
   if (num_features)
   {
   {
-    typographic_features.features = new DWRITE_FONT_FEATURE[num_features];
-    for (unsigned int i = 0; i < num_features; ++i)
-    {
-      typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
-						 hb_uint32_swap (features[i].tag);
-      typographic_features.features[i].parameter = features[i].value;
-    }
+    hb_vector_t<hb_ms_feature_t> feature_records;
+    hb_vector_t<hb_ms_range_record_t> range_records;
+    if (hb_ms_setup_features (features, num_features, feature_records, range_records))
+      hb_ms_make_feature_ranges (feature_records,
+				 range_records,
+				 0,
+				 chars_len,
+				 log_clusters,
+				 range_features,
+				 range_char_counts);
   }
   }
-  const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures;
-  dwFeatures = (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features;
-  const uint32_t featureRangeLengths[] = { textLength };
-  //
 
 
   uint16_t* clusterMap;
   uint16_t* clusterMap;
   clusterMap = new uint16_t[textLength];
   clusterMap = new uint16_t[textLength];
   DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
   DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
   textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
   textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
+
 retry_getglyphs:
 retry_getglyphs:
   uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
   uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
   DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
   DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
   glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
   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);
+  hr = analyzer->GetGlyphs (textString,
+			    chars_len,
+			    fontFace,
+			    false,
+			    isRightToLeft,
+			    &runHead->mScript,
+			    localeName,
+			    nullptr,
+			    (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
+			    range_char_counts.arrayZ,
+			    range_features.length,
+			    maxGlyphCount,
+			    clusterMap,
+			    textProperties,
+			    glyphIndices,
+			    glyphProperties,
+			    &glyphCount);
 
 
   if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
   if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
   {
   {
@@ -715,101 +687,28 @@ retry_getglyphs:
   double x_mult = (double) font->x_scale / fontEmSize;
   double x_mult = (double) font->x_scale / fontEmSize;
   double y_mult = (double) font->y_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,
+				     chars_len,
+				     glyphIndices,
+				     glyphProperties,
+				     glyphCount,
+				     fontFace,
+				     fontEmSize,
+				     false,
+				     isRightToLeft,
+				     &runHead->mScript,
+				     localeName,
+				     (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
+				     range_char_counts.arrayZ,
+				     range_features.length,
+				     glyphAdvances,
+				     glyphOffsets);
 
 
   if (FAILED (hr))
   if (FAILED (hr))
     FAIL ("Analyzer failed to get glyph placements.");
     FAIL ("Analyzer failed to get glyph placements.");
 
 
-  IDWriteTextAnalyzer1* analyzer1;
-  analyzer->QueryInterface (&analyzer1);
-
-  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);
-
-    if (FAILED (hr))
-      FAIL ("Analyzer failed to get justification opportunities.");
-
-    float* justifiedGlyphAdvances = new float[maxGlyphCount];
-    DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount];
-    hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
-					  glyphAdvances, glyphOffsets, justifiedGlyphAdvances,
-					  justifiedGlyphOffsets);
-
-    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.");
-    uint32_t justificationCharacter = scriptProperties.justificationCharacter;
-
-    // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
-    if (justificationCharacter != 32)
-    {
-      uint16_t* modifiedClusterMap = new uint16_t[textLength];
-    retry_getjustifiedglyphs:
-      uint16_t* modifiedGlyphIndices = new uint16_t[maxGlyphCount];
-      float* modifiedGlyphAdvances = new float[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);
-
-      if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
-      {
-	maxGlyphCount = actualGlyphsCount;
-	delete [] modifiedGlyphIndices;
-	delete [] modifiedGlyphAdvances;
-	delete [] modifiedGlyphOffsets;
-
-	maxGlyphCount = actualGlyphsCount;
-
-	goto retry_getjustifiedglyphs;
-      }
-      if (FAILED (hr))
-	FAIL ("Analyzer failed to get justified glyphs.");
-
-      delete [] clusterMap;
-      delete [] glyphIndices;
-      delete [] glyphAdvances;
-      delete [] glyphOffsets;
-
-      glyphCount = actualGlyphsCount;
-      clusterMap = modifiedClusterMap;
-      glyphIndices = modifiedGlyphIndices;
-      glyphAdvances = modifiedGlyphAdvances;
-      glyphOffsets = modifiedGlyphOffsets;
-
-      delete [] justifiedGlyphAdvances;
-      delete [] justifiedGlyphOffsets;
-    }
-    else
-    {
-      delete [] glyphAdvances;
-      delete [] glyphOffsets;
-
-      glyphAdvances = justifiedGlyphAdvances;
-      glyphOffsets = justifiedGlyphOffsets;
-    }
-
-    delete [] justificationOpportunities;
-  }
-
   /* Ok, we've got everything we need, now compose output buffer,
   /* Ok, we've got everything we need, now compose output buffer,
    * very, *very*, carefully! */
    * very, *very*, carefully! */
 
 
@@ -870,43 +769,10 @@ retry_getglyphs:
   delete [] glyphAdvances;
   delete [] glyphAdvances;
   delete [] glyphOffsets;
   delete [] glyphOffsets;
 
 
-  if (num_features)
-    delete [] typographic_features.features;
-
   /* Wow, done! */
   /* Wow, done! */
   return true;
   return true;
 }
 }
 
 
-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)
-{
-  return _hb_directwrite_shape_full (shape_plan, font, buffer,
-				     features, num_features, 0);
-}
-
-HB_UNUSED static bool
-_hb_directwrite_shape_experimental_width (hb_font_t          *font,
-					  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;
-  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);
-
-  buffer->unsafe_to_break_all ();
-
-  return res;
-}
-
 struct _hb_directwrite_font_table_context {
 struct _hb_directwrite_font_table_context {
   IDWriteFontFace *face;
   IDWriteFontFace *face;
   void *table_context;
   void *table_context;
@@ -917,7 +783,7 @@ _hb_directwrite_table_data_release (void *data)
 {
 {
   _hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) data;
   _hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) data;
   context->face->ReleaseFontTable (context->table_context);
   context->face->ReleaseFontTable (context->table_context);
-  delete context;
+  hb_free (context);
 }
 }
 
 
 static hb_blob_t *
 static hb_blob_t *
@@ -938,7 +804,7 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *
     return nullptr;
     return nullptr;
   }
   }
 
 
-  _hb_directwrite_font_table_context *context = new _hb_directwrite_font_table_context;
+  _hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) hb_malloc (sizeof (_hb_directwrite_font_table_context));
   context->face = dw_face;
   context->face = dw_face;
   context->table_context = table_context;
   context->table_context = table_context;
 
 

+ 1 - 1
thirdparty/harfbuzz/src/hb-draw.cc

@@ -191,7 +191,7 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
 {
 {
   if (!hb_object_destroy (funcs)) return;
   if (!hb_object_destroy (funcs)) return;
 
 
-  free (funcs);
+  hb_free (funcs);
 }
 }
 
 
 /**
 /**

+ 57 - 45
thirdparty/harfbuzz/src/hb-face.cc

@@ -33,6 +33,7 @@
 #include "hb-open-file.hh"
 #include "hb-open-file.hh"
 #include "hb-ot-face.hh"
 #include "hb-ot-face.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-cmap-table.hh"
+#include "hb-map.hh"
 
 
 
 
 /**
 /**
@@ -106,9 +107,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
  * convenient to provide data for individual tables instead of the whole font
  * convenient to provide data for individual tables instead of the whole font
  * data. With the caveat that hb_face_get_table_tags() does not currently work
  * data. With the caveat that hb_face_get_table_tags() does not currently work
  * with faces created this way.
  * with faces created this way.
- * 
+ *
  * Creates a new face object from the specified @user_data and @reference_table_func,
  * Creates a new face object from the specified @user_data and @reference_table_func,
- * with the @destroy callback. 
+ * with the @destroy callback.
  *
  *
  * Return value: (transfer full): The new face object
  * Return value: (transfer full): The new face object
  *
  *
@@ -150,7 +151,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
 {
 {
   hb_face_for_data_closure_t *closure;
   hb_face_for_data_closure_t *closure;
 
 
-  closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
+  closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t));
   if (unlikely (!closure))
   if (unlikely (!closure))
     return nullptr;
     return nullptr;
 
 
@@ -166,7 +167,7 @@ _hb_face_for_data_closure_destroy (void *data)
   hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
   hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
 
 
   hb_blob_destroy (closure->blob);
   hb_blob_destroy (closure->blob);
-  free (closure);
+  hb_free (closure);
 }
 }
 
 
 static hb_blob_t *
 static hb_blob_t *
@@ -265,7 +266,7 @@ hb_face_reference (hb_face_t *face)
 /**
 /**
  * hb_face_destroy: (skip)
  * hb_face_destroy: (skip)
  * @face: A face object
  * @face: A face object
- * 
+ *
  * Decreases the reference count on a face object. When the
  * Decreases the reference count on a face object. When the
  * reference count reaches zero, the face is destroyed,
  * reference count reaches zero, the face is destroyed,
  * freeing all memory.
  * freeing all memory.
@@ -281,7 +282,7 @@ hb_face_destroy (hb_face_t *face)
   {
   {
     hb_face_t::plan_node_t *next = node->next;
     hb_face_t::plan_node_t *next = node->next;
     hb_shape_plan_destroy (node->shape_plan);
     hb_shape_plan_destroy (node->shape_plan);
-    free (node);
+    hb_free (node);
     node = next;
     node = next;
   }
   }
 
 
@@ -291,7 +292,7 @@ hb_face_destroy (hb_face_t *face)
   if (face->destroy)
   if (face->destroy)
     face->destroy (face->user_data);
     face->destroy (face->user_data);
 
 
-  free (face);
+  hb_free (face);
 }
 }
 
 
 /**
 /**
@@ -302,7 +303,7 @@ hb_face_destroy (hb_face_t *face)
  * @destroy: (nullable): A callback to call when @data is not needed anymore
  * @destroy: (nullable): A callback to call when @data is not needed anymore
  * @replace: Whether to replace an existing data with the same key
  * @replace: Whether to replace an existing data with the same key
  *
  *
- * Attaches a user-data key/data pair to the given face object. 
+ * Attaches a user-data key/data pair to the given face object.
  *
  *
  * Return value: %true if success, %false otherwise
  * Return value: %true if success, %false otherwise
  *
  *
@@ -441,7 +442,7 @@ hb_face_set_index (hb_face_t    *face,
  *
  *
  * <note>Note: face indices within a collection are zero-based.</note>
  * <note>Note: face indices within a collection are zero-based.</note>
  *
  *
- * Return value: The index of @face. 
+ * Return value: The index of @face.
  *
  *
  * Since: 0.9.2
  * Since: 0.9.2
  **/
  **/
@@ -623,26 +624,26 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
 
 
 struct hb_face_builder_data_t
 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;
+  hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
 };
 };
 
 
+static int compare_entries (const void* pa, const void* pb)
+{
+  const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
+  const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
+
+  /* Order by blob size first (smallest to largest) and then table tag */
+
+  if (a.second->length != b.second->length)
+    return a.second->length < b.second->length ? -1 : +1;
+
+  return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
+}
+
 static hb_face_builder_data_t *
 static hb_face_builder_data_t *
 _hb_face_builder_data_create ()
 _hb_face_builder_data_create ()
 {
 {
-  hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t));
   if (unlikely (!data))
   if (unlikely (!data))
     return nullptr;
     return nullptr;
 
 
@@ -656,25 +657,25 @@ _hb_face_builder_data_destroy (void *user_data)
 {
 {
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) 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);
+  for (hb_blob_t* b : data->tables.values())
+    hb_blob_destroy (b);
 
 
   data->tables.fini ();
   data->tables.fini ();
 
 
-  free (data);
+  hb_free (data);
 }
 }
 
 
 static hb_blob_t *
 static hb_blob_t *
 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
 _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
 {
 {
 
 
-  unsigned int table_count = data->tables.length;
+  unsigned int table_count = data->tables.get_population ();
   unsigned int face_length = table_count * 16 + 12;
   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));
+  for (hb_blob_t* b : data->tables.values())
+    face_length += hb_ceil_to_4 (hb_blob_get_length (b));
 
 
-  char *buf = (char *) malloc (face_length);
+  char *buf = (char *) hb_malloc (face_length);
   if (unlikely (!buf))
   if (unlikely (!buf))
     return nullptr;
     return nullptr;
 
 
@@ -682,20 +683,31 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
   c.propagate_error (data->tables);
   c.propagate_error (data->tables);
   OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
   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'));
+  bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
+                 || data->tables.has (HB_TAG ('C','F','F','2')));
   hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
   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 ());
+  // Sort the tags so that produced face is deterministic.
+  hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
+  data->tables.iter () | hb_sink (sorted_entries);
+  if (unlikely (sorted_entries.in_error ()))
+  {
+    hb_free (buf);
+    return nullptr;
+  }
+
+  sorted_entries.qsort (compare_entries);
+  bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
 
 
   c.end_serialize ();
   c.end_serialize ();
 
 
   if (unlikely (!ret))
   if (unlikely (!ret))
   {
   {
-    free (buf);
+    hb_free (buf);
     return nullptr;
     return nullptr;
   }
   }
 
 
-  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free);
 }
 }
 
 
 static hb_blob_t *
 static hb_blob_t *
@@ -706,11 +718,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
   if (!tag)
   if (!tag)
     return _hb_face_builder_data_reference_blob (data);
     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;
+  return hb_blob_reference (data->tables[tag]);
 }
 }
 
 
 
 
@@ -750,17 +758,21 @@ hb_face_builder_create ()
 hb_bool_t
 hb_bool_t
 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 {
 {
+  if (tag == HB_MAP_VALUE_INVALID)
+    return false;
+
   if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
   if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
     return false;
     return false;
 
 
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
   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 ();
-  if (unlikely (data->tables.in_error()))
+  hb_blob_t* previous = data->tables.get (tag);
+  if (!data->tables.set (tag, hb_blob_reference (blob)))
+  {
+    hb_blob_destroy (blob);
     return false;
     return false;
+  }
 
 
-  entry->tag = tag;
-  entry->blob = hb_blob_reference (blob);
-
+  hb_blob_destroy (previous);
   return true;
   return true;
 }
 }

+ 40 - 39
thirdparty/harfbuzz/src/hb-font.cc

@@ -620,7 +620,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
 #undef HB_FONT_FUNC_IMPLEMENT
 
 
-  free (ffuncs);
+  hb_free (ffuncs);
 }
 }
 
 
 /**
 /**
@@ -1544,8 +1544,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
 			   float *design_coords,
 			   float *design_coords,
 			   unsigned int coords_length)
 			   unsigned int coords_length)
 {
 {
-  free (font->coords);
-  free (font->design_coords);
+  hb_free (font->coords);
+  hb_free (font->design_coords);
 
 
   font->coords = coords;
   font->coords = coords;
   font->design_coords = design_coords;
   font->design_coords = design_coords;
@@ -1586,8 +1586,8 @@ hb_font_create_sub_font (hb_font_t *parent)
   unsigned int num_coords = parent->num_coords;
   unsigned int num_coords = parent->num_coords;
   if (num_coords)
   if (num_coords)
   {
   {
-    int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0]));
-    float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0]));
+    int *coords = (int *) hb_calloc (num_coords, sizeof (parent->coords[0]));
+    float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0]));
     if (likely (coords && design_coords))
     if (likely (coords && design_coords))
     {
     {
       memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
       memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
@@ -1596,8 +1596,8 @@ hb_font_create_sub_font (hb_font_t *parent)
     }
     }
     else
     else
     {
     {
-      free (coords);
-      free (design_coords);
+      hb_free (coords);
+      hb_free (design_coords);
     }
     }
   }
   }
 
 
@@ -1659,10 +1659,10 @@ hb_font_destroy (hb_font_t *font)
   hb_face_destroy (font->face);
   hb_face_destroy (font->face);
   hb_font_funcs_destroy (font->klass);
   hb_font_funcs_destroy (font->klass);
 
 
-  free (font->coords);
-  free (font->design_coords);
+  hb_free (font->coords);
+  hb_free (font->design_coords);
 
 
-  free (font);
+  hb_free (font);
 }
 }
 
 
 /**
 /**
@@ -2052,29 +2052,30 @@ hb_font_set_variations (hb_font_t            *font,
     return;
     return;
   }
   }
 
 
-  unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
+  const OT::fvar &fvar = *font->face->table.fvar;
+  auto axes = fvar.get_axes ();
+  const unsigned coords_length = axes.length;
 
 
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
-  float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
+  int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
+  float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
 
 
   if (unlikely (coords_length && !(normalized && design_coords)))
   if (unlikely (coords_length && !(normalized && design_coords)))
   {
   {
-    free (normalized);
-    free (design_coords);
+    hb_free (normalized);
+    hb_free (design_coords);
     return;
     return;
   }
   }
 
 
-  const OT::fvar &fvar = *font->face->table.fvar;
   for (unsigned int i = 0; i < variations_length; i++)
   for (unsigned int i = 0; i < variations_length; i++)
   {
   {
-    hb_ot_var_axis_info_t info;
-    if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) &&
-	info.axis_index < coords_length)
-    {
-      float v = variations[i].value;
-      design_coords[info.axis_index] = v;
-      normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v);
-    }
+    const auto tag = variations[i].tag;
+    const auto v = variations[i].value;
+    for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
+      if (axes[axis_index].axisTag == tag)
+      {
+	design_coords[axis_index] = v;
+	normalized[axis_index] = fvar.normalize_axis_value (axis_index, v);
+      }
   }
   }
   font->face->table.avar->map_coords (normalized, coords_length);
   font->face->table.avar->map_coords (normalized, coords_length);
 
 
@@ -2100,13 +2101,13 @@ hb_font_set_var_coords_design (hb_font_t    *font,
   if (hb_object_is_immutable (font))
   if (hb_object_is_immutable (font))
     return;
     return;
 
 
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
-  float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
+  int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
+  float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
 
 
   if (unlikely (coords_length && !(normalized && design_coords)))
   if (unlikely (coords_length && !(normalized && design_coords)))
   {
   {
-    free (normalized);
-    free (design_coords);
+    hb_free (normalized);
+    hb_free (design_coords);
     return;
     return;
   }
   }
 
 
@@ -2135,13 +2136,13 @@ hb_font_set_var_named_instance (hb_font_t *font,
 
 
   unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
   unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
 
 
-  float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
+  float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
   if (unlikely (coords_length && !coords))
   if (unlikely (coords_length && !coords))
     return;
     return;
 
 
   hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
   hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
   hb_font_set_var_coords_design (font, coords, coords_length);
   hb_font_set_var_coords_design (font, coords, coords_length);
-  free (coords);
+  hb_free (coords);
 }
 }
 
 
 /**
 /**
@@ -2165,15 +2166,15 @@ hb_font_set_var_coords_normalized (hb_font_t    *font,
   if (hb_object_is_immutable (font))
   if (hb_object_is_immutable (font))
     return;
     return;
 
 
-  int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
-  int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
-  float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr;
+  int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
+  int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
+  float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
 
 
   if (unlikely (coords_length && !(copy && unmapped && design_coords)))
   if (unlikely (coords_length && !(copy && unmapped && design_coords)))
   {
   {
-    free (copy);
-    free (unmapped);
-    free (design_coords);
+    hb_free (copy);
+    hb_free (unmapped);
+    hb_free (design_coords);
     return;
     return;
   }
   }
 
 
@@ -2187,7 +2188,7 @@ hb_font_set_var_coords_normalized (hb_font_t    *font,
   font->face->table.avar->unmap_coords (unmapped, coords_length);
   font->face->table.avar->unmap_coords (unmapped, coords_length);
   for (unsigned int i = 0; i < coords_length; ++i)
   for (unsigned int i = 0; i < coords_length; ++i)
     design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
     design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
-  free (unmapped);
+  hb_free (unmapped);
 
 
   _hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
   _hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
 }
 }
@@ -2267,7 +2268,7 @@ trampoline_create (FuncType           func,
 {
 {
   typedef hb_trampoline_t<FuncType> trampoline_t;
   typedef hb_trampoline_t<FuncType> trampoline_t;
 
 
-  trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
+  trampoline_t *trampoline = (trampoline_t *) hb_calloc (1, sizeof (trampoline_t));
 
 
   if (unlikely (!trampoline))
   if (unlikely (!trampoline))
     return nullptr;
     return nullptr;
@@ -2296,7 +2297,7 @@ trampoline_destroy (void *user_data)
 
 
   if (closure->destroy)
   if (closure->destroy)
     closure->destroy (closure->user_data);
     closure->destroy (closure->user_data);
-  free (closure);
+  hb_free (closure);
 }
 }
 
 
 typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
 typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;

+ 18 - 30
thirdparty/harfbuzz/src/hb-ft.cc

@@ -91,7 +91,7 @@ struct hb_ft_font_t
 static hb_ft_font_t *
 static hb_ft_font_t *
 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
 {
 {
-  hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
+  hb_ft_font_t *ft_font = (hb_ft_font_t *) hb_calloc (1, sizeof (hb_ft_font_t));
   if (unlikely (!ft_font)) return nullptr;
   if (unlikely (!ft_font)) return nullptr;
 
 
   ft_font->lock.init ();
   ft_font->lock.init ();
@@ -125,7 +125,7 @@ _hb_ft_font_destroy (void *data)
 
 
   ft_font->lock.fini ();
   ft_font->lock.fini ();
 
 
-  free (ft_font);
+  hb_free (ft_font);
 }
 }
 
 
 /**
 /**
@@ -561,9 +561,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
   return true;
   return true;
 }
 }
 
 
-#if HB_USE_ATEXIT
-static void free_static_ft_funcs ();
-#endif
+static inline void free_static_ft_funcs ();
 
 
 static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
 static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
 {
 {
@@ -591,21 +589,17 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
 
 
     hb_font_funcs_make_immutable (funcs);
     hb_font_funcs_make_immutable (funcs);
 
 
-#if HB_USE_ATEXIT
-    atexit (free_static_ft_funcs);
-#endif
+    hb_atexit (free_static_ft_funcs);
 
 
     return funcs;
     return funcs;
   }
   }
 } static_ft_funcs;
 } static_ft_funcs;
 
 
-#if HB_USE_ATEXIT
-static
+static inline
 void free_static_ft_funcs ()
 void free_static_ft_funcs ()
 {
 {
   static_ft_funcs.free_instance ();
   static_ft_funcs.free_instance ();
 }
 }
-#endif
 
 
 static hb_font_funcs_t *
 static hb_font_funcs_t *
 _hb_ft_get_font_funcs ()
 _hb_ft_get_font_funcs ()
@@ -642,20 +636,20 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
   if (error)
   if (error)
     return nullptr;
     return nullptr;
 
 
-  buffer = (FT_Byte *) malloc (length);
+  buffer = (FT_Byte *) hb_malloc (length);
   if (!buffer)
   if (!buffer)
     return nullptr;
     return nullptr;
 
 
   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
   if (error)
   if (error)
   {
   {
-    free (buffer);
+    hb_free (buffer);
     return nullptr;
     return nullptr;
   }
   }
 
 
   return hb_blob_create ((const char *) buffer, length,
   return hb_blob_create ((const char *) buffer, length,
 			 HB_MEMORY_MODE_WRITABLE,
 			 HB_MEMORY_MODE_WRITABLE,
-			 buffer, free);
+			 buffer, hb_free);
 }
 }
 
 
 /**
 /**
@@ -846,8 +840,8 @@ hb_ft_font_changed (hb_font_t *font)
   FT_MM_Var *mm_var = nullptr;
   FT_MM_Var *mm_var = nullptr;
   if (!FT_Get_MM_Var (ft_face, &mm_var))
   if (!FT_Get_MM_Var (ft_face, &mm_var))
   {
   {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
-    int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
+    FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (mm_var->num_axis, sizeof (FT_Fixed));
+    int *coords = (int *) hb_calloc (mm_var->num_axis, sizeof (int));
     if (coords && ft_coords)
     if (coords && ft_coords)
     {
     {
       if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
       if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
@@ -866,12 +860,12 @@ hb_ft_font_changed (hb_font_t *font)
 	  hb_font_set_var_coords_normalized (font, nullptr, 0);
 	  hb_font_set_var_coords_normalized (font, nullptr, 0);
       }
       }
     }
     }
-    free (coords);
-    free (ft_coords);
+    hb_free (coords);
+    hb_free (ft_coords);
 #ifdef HAVE_FT_DONE_MM_VAR
 #ifdef HAVE_FT_DONE_MM_VAR
     FT_Done_MM_Var (ft_face->glyph->library, mm_var);
     FT_Done_MM_Var (ft_face->glyph->library, mm_var);
 #else
 #else
-    free (mm_var);
+    hb_free (mm_var);
 #endif
 #endif
   }
   }
 #endif
 #endif
@@ -905,9 +899,7 @@ hb_ft_font_create_referenced (FT_Face ft_face)
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 }
 
 
-#if HB_USE_ATEXIT
-static void free_static_ft_library ();
-#endif
+static inline void free_static_ft_library ();
 
 
 static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<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>
 							     hb_ft_library_lazy_loader_t>
@@ -918,9 +910,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
     if (FT_Init_FreeType (&l))
     if (FT_Init_FreeType (&l))
       return nullptr;
       return nullptr;
 
 
-#if HB_USE_ATEXIT
-    atexit (free_static_ft_library);
-#endif
+    hb_atexit (free_static_ft_library);
 
 
     return l;
     return l;
   }
   }
@@ -934,13 +924,11 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
   }
   }
 } static_ft_library;
 } static_ft_library;
 
 
-#if HB_USE_ATEXIT
-static
+static inline
 void free_static_ft_library ()
 void free_static_ft_library ()
 {
 {
   static_ft_library.free_instance ();
   static_ft_library.free_instance ();
 }
 }
-#endif
 
 
 static FT_Library
 static FT_Library
 get_ft_library ()
 get_ft_library ()
@@ -1020,13 +1008,13 @@ hb_ft_font_set_funcs (hb_font_t *font)
   const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
   const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
   if (num_coords)
   if (num_coords)
   {
   {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
+    FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
     if (ft_coords)
     if (ft_coords)
     {
     {
       for (unsigned int i = 0; i < num_coords; i++)
       for (unsigned int i = 0; i < num_coords; i++)
 	ft_coords[i] = coords[i] * 4;
 	ft_coords[i] = coords[i] * 4;
       FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
       FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
-      free (ft_coords);
+      hb_free (ft_coords);
     }
     }
   }
   }
 #endif
 #endif

+ 3 - 3
thirdparty/harfbuzz/src/hb-gdi.cc

@@ -50,16 +50,16 @@ _hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_dat
   length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
   length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
   if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
   if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
 
 
-  buffer = (char *) malloc (length);
+  buffer = (char *) hb_malloc (length);
   if (unlikely (!buffer)) goto fail_with_releasedc;
   if (unlikely (!buffer)) goto fail_with_releasedc;
   length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
   length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
   if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
   if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
   ReleaseDC (nullptr, hdc);
   ReleaseDC (nullptr, hdc);
 
 
-  return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
+  return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, hb_free);
 
 
 fail_with_releasedc_and_free:
 fail_with_releasedc_and_free:
-  free (buffer);
+  hb_free (buffer);
 fail_with_releasedc:
 fail_with_releasedc:
   ReleaseDC (nullptr, hdc);
   ReleaseDC (nullptr, hdc);
 fail:
 fail:

+ 3 - 9
thirdparty/harfbuzz/src/hb-glib.cc

@@ -218,9 +218,7 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 }
 }
 
 
 
 
-#if HB_USE_ATEXIT
-static void free_static_glib_funcs ();
-#endif
+static inline void free_static_glib_funcs ();
 
 
 static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
 static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
 {
 {
@@ -237,21 +235,17 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
 
 
     hb_unicode_funcs_make_immutable (funcs);
     hb_unicode_funcs_make_immutable (funcs);
 
 
-#if HB_USE_ATEXIT
-    atexit (free_static_glib_funcs);
-#endif
+    hb_atexit (free_static_glib_funcs);
 
 
     return funcs;
     return funcs;
   }
   }
 } static_glib_funcs;
 } static_glib_funcs;
 
 
-#if HB_USE_ATEXIT
-static
+static inline
 void free_static_glib_funcs ()
 void free_static_glib_funcs ()
 {
 {
   static_glib_funcs.free_instance ();
   static_glib_funcs.free_instance ();
 }
 }
-#endif
 
 
 /**
 /**
  * hb_glib_get_unicode_funcs:
  * hb_glib_get_unicode_funcs:

+ 2 - 2
thirdparty/harfbuzz/src/hb-gobject-structs.cc

@@ -80,12 +80,12 @@ hb_gobject_##name##_get_type () \
 #define HB_DEFINE_VALUE_TYPE(name) \
 #define HB_DEFINE_VALUE_TYPE(name) \
 	static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
 	static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
 	{ \
 	{ \
-	  hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
+	  hb_##name##_t *c = (hb_##name##_t *) hb_calloc (1, sizeof (hb_##name##_t)); \
 	  if (unlikely (!c)) return nullptr; \
 	  if (unlikely (!c)) return nullptr; \
 	  *c = *l; \
 	  *c = *l; \
 	  return c; \
 	  return c; \
 	} \
 	} \
-	static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \
+	static void _hb_##name##_destroy (hb_##name##_t *l) { hb_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 (buffer)

+ 7 - 6
thirdparty/harfbuzz/src/hb-graphite2.cc

@@ -88,7 +88,7 @@ static const void *hb_graphite2_get_table (const void *data, unsigned int tag, s
   {
   {
     blob = face_data->face->reference_table (tag);
     blob = face_data->face->reference_table (tag);
 
 
-    hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
+    hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) hb_calloc (1, sizeof (hb_graphite2_tablelist_t));
     if (unlikely (!p)) {
     if (unlikely (!p)) {
       hb_blob_destroy (blob);
       hb_blob_destroy (blob);
       return nullptr;
       return nullptr;
@@ -123,15 +123,16 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
   }
   }
   hb_blob_destroy (silf_blob);
   hb_blob_destroy (silf_blob);
 
 
-  hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
+  hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) hb_calloc (1, sizeof (hb_graphite2_face_data_t));
   if (unlikely (!data))
   if (unlikely (!data))
     return nullptr;
     return nullptr;
 
 
   data->face = face;
   data->face = face;
-  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
+  const gr_face_ops ops = {sizeof(gr_face_ops), &hb_graphite2_get_table, NULL};
+  data->grface = gr_make_face_with_ops (data, &ops, gr_face_preloadAll);
 
 
   if (unlikely (!data->grface)) {
   if (unlikely (!data->grface)) {
-    free (data);
+    hb_free (data);
     return nullptr;
     return nullptr;
   }
   }
 
 
@@ -148,12 +149,12 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
     hb_graphite2_tablelist_t *old = tlist;
     hb_graphite2_tablelist_t *old = tlist;
     hb_blob_destroy (tlist->blob);
     hb_blob_destroy (tlist->blob);
     tlist = tlist->next;
     tlist = tlist->next;
-    free (old);
+    hb_free (old);
   }
   }
 
 
   gr_face_destroy (data->grface);
   gr_face_destroy (data->grface);
 
 
-  free (data);
+  hb_free (data);
 }
 }
 
 
 /**
 /**

+ 3 - 9
thirdparty/harfbuzz/src/hb-icu.cc

@@ -233,9 +233,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 }
 }
 
 
 
 
-#if HB_USE_ATEXIT
-static void free_static_icu_funcs ();
-#endif
+static inline void free_static_icu_funcs ();
 
 
 static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
 static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
 {
 {
@@ -257,21 +255,17 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
 
 
     hb_unicode_funcs_make_immutable (funcs);
     hb_unicode_funcs_make_immutable (funcs);
 
 
-#if HB_USE_ATEXIT
-    atexit (free_static_icu_funcs);
-#endif
+    hb_atexit (free_static_icu_funcs);
 
 
     return funcs;
     return funcs;
   }
   }
 } static_icu_funcs;
 } static_icu_funcs;
 
 
-#if HB_USE_ATEXIT
-static
+static inline
 void free_static_icu_funcs ()
 void free_static_icu_funcs ()
 {
 {
   static_icu_funcs.free_instance ();
   static_icu_funcs.free_instance ();
 }
 }
-#endif
 
 
 /**
 /**
  * hb_icu_get_unicode_funcs:
  * hb_icu_get_unicode_funcs:

+ 1 - 1
thirdparty/harfbuzz/src/hb-iter.hh

@@ -46,7 +46,7 @@
  * TODO Document more.
  * TODO Document more.
  *
  *
  * If iterator implementation implements operator!=, then can be
  * If iterator implementation implements operator!=, then can be
- * used in range-based for loop.  That comes free if the iterator
+ * used in range-based for loop.  That already happens if the iterator
  * is random-access.  Otherwise, the range-based for loop incurs
  * is random-access.  Otherwise, the range-based for loop incurs
  * one traversal to find end(), which can be avoided if written
  * one traversal to find end(), which can be avoided if written
  * as a while-style for loop, or if iterator implements a faster
  * as a while-style for loop, or if iterator implements a faster

+ 3 - 3
thirdparty/harfbuzz/src/hb-machinery.hh

@@ -242,14 +242,14 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
   static const Stored* get_null () { return &Null (Stored); }
   static const Stored* get_null () { return &Null (Stored); }
   static Stored *create (Data *data)
   static Stored *create (Data *data)
   {
   {
-    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
     if (likely (p))
     if (likely (p))
       p->init (data);
       p->init (data);
     return p;
     return p;
   }
   }
   static Stored *create ()
   static Stored *create ()
   {
   {
-    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
     if (likely (p))
     if (likely (p))
       p->init ();
       p->init ();
     return p;
     return p;
@@ -257,7 +257,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
   static void destroy (Stored *p)
   static void destroy (Stored *p)
   {
   {
     p->fini ();
     p->fini ();
-    free (p);
+    hb_free (p);
   }
   }
 
 
 //  private:
 //  private:

+ 3 - 4
thirdparty/harfbuzz/src/hb-map.cc

@@ -109,7 +109,7 @@ hb_map_destroy (hb_map_t *map)
 
 
   map->fini_shallow ();
   map->fini_shallow ();
 
 
-  free (map);
+  hb_free (map);
 }
 }
 
 
 /**
 /**
@@ -188,6 +188,7 @@ hb_map_set (hb_map_t       *map,
 	    hb_codepoint_t  key,
 	    hb_codepoint_t  key,
 	    hb_codepoint_t  value)
 	    hb_codepoint_t  value)
 {
 {
+  /* Immutable-safe. */
   map->set (key, value);
   map->set (key, value);
 }
 }
 
 
@@ -220,6 +221,7 @@ void
 hb_map_del (hb_map_t       *map,
 hb_map_del (hb_map_t       *map,
 	    hb_codepoint_t  key)
 	    hb_codepoint_t  key)
 {
 {
+  /* Immutable-safe. */
   map->del (key);
   map->del (key);
 }
 }
 
 
@@ -253,9 +255,6 @@ hb_map_has (const hb_map_t *map,
 void
 void
 hb_map_clear (hb_map_t *map)
 hb_map_clear (hb_map_t *map)
 {
 {
-  if (unlikely (hb_object_is_immutable (map)))
-    return;
-
   return map->clear ();
   return map->clear ();
 }
 }
 
 

+ 15 - 11
thirdparty/harfbuzz/src/hb-map.hh

@@ -85,7 +85,7 @@ struct hb_hashmap_t
   }
   }
   void fini_shallow ()
   void fini_shallow ()
   {
   {
-    free (items);
+    hb_free (items);
     items = nullptr;
     items = nullptr;
     population = occupancy = 0;
     population = occupancy = 0;
   }
   }
@@ -109,7 +109,7 @@ struct hb_hashmap_t
 
 
     unsigned int power = hb_bit_storage (population * 2 + 8);
     unsigned int power = hb_bit_storage (population * 2 + 8);
     unsigned int new_size = 1u << power;
     unsigned int new_size = 1u << power;
-    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
+    item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
     if (unlikely (!new_items))
     if (unlikely (!new_items))
     {
     {
       successful = false;
       successful = false;
@@ -135,14 +135,14 @@ struct hb_hashmap_t
 			 old_items[i].hash,
 			 old_items[i].hash,
 			 old_items[i].value);
 			 old_items[i].value);
 
 
-    free (old_items);
+    hb_free (old_items);
 
 
     return true;
     return true;
   }
   }
 
 
-  void set (K key, V value)
+  bool set (K key, V value)
   {
   {
-    set_with_hash (key, hb_hash (key), value);
+    return set_with_hash (key, hb_hash (key), value);
   }
   }
 
 
   V get (K key) const
   V get (K key) const
@@ -169,6 +169,8 @@ struct hb_hashmap_t
 
 
   void clear ()
   void clear ()
   {
   {
+    if (unlikely (!successful)) return;
+
     if (items)
     if (items)
       for (auto &_ : hb_iter (items, mask + 1))
       for (auto &_ : hb_iter (items, mask + 1))
 	_.clear ();
 	_.clear ();
@@ -211,20 +213,20 @@ struct hb_hashmap_t
 
 
   protected:
   protected:
 
 
-  void set_with_hash (K key, uint32_t hash, V value)
+  bool set_with_hash (K key, uint32_t hash, V value)
   {
   {
-    if (unlikely (!successful)) return;
-    if (unlikely (key == kINVALID)) return;
-    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
+    if (unlikely (!successful)) return false;
+    if (unlikely (key == kINVALID)) return true;
+    if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
     unsigned int i = bucket_for_hash (key, hash);
     unsigned int i = bucket_for_hash (key, hash);
 
 
     if (value == vINVALID && items[i].key != key)
     if (value == vINVALID && items[i].key != key)
-      return; /* Trying to delete non-existent key. */
+      return true; /* Trying to delete non-existent key. */
 
 
     if (!items[i].is_unused ())
     if (!items[i].is_unused ())
     {
     {
       occupancy--;
       occupancy--;
-      if (items[i].is_tombstone ())
+      if (!items[i].is_tombstone ())
 	population--;
 	population--;
     }
     }
 
 
@@ -235,6 +237,8 @@ struct hb_hashmap_t
     occupancy++;
     occupancy++;
     if (!items[i].is_tombstone ())
     if (!items[i].is_tombstone ())
       population++;
       population++;
+
+    return true;
   }
   }
 
 
   unsigned int bucket_for (K key) const
   unsigned int bucket_for (K key) const

+ 16 - 15
thirdparty/harfbuzz/src/hb-meta.hh

@@ -101,14 +101,14 @@ HB_FUNCOBJ (hb_addressof);
 template <typename T> static inline T hb_declval ();
 template <typename T> static inline T hb_declval ();
 #define hb_declval(T) (hb_declval<T> ())
 #define hb_declval(T) (hb_declval<T> ())
 
 
-template <typename T> struct hb_match_const		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-template <typename T> struct hb_match_const<const T>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
+template <typename T> struct hb_match_const		: hb_type_identity_t<T>, hb_false_type	{};
+template <typename T> struct hb_match_const<const T>	: hb_type_identity_t<T>, hb_true_type	{};
 template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
 template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
 template <typename T> using hb_add_const = const T;
 template <typename T> using hb_add_const = const T;
 #define hb_is_const(T) hb_match_const<T>::value
 #define hb_is_const(T) hb_match_const<T>::value
-template <typename T> struct hb_match_reference		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-template <typename T> struct hb_match_reference<T &>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
-template <typename T> struct hb_match_reference<T &&>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
+template <typename T> struct hb_match_reference		: hb_type_identity_t<T>, hb_false_type	{};
+template <typename T> struct hb_match_reference<T &>	: hb_type_identity_t<T>, hb_true_type	{};
+template <typename T> struct hb_match_reference<T &&>	: hb_type_identity_t<T>, hb_true_type	{};
 template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
 template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
 template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
 template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
 template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
 template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
@@ -117,8 +117,8 @@ template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_t
 template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
 template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
 template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
 template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
 #define hb_is_reference(T) hb_match_reference<T>::value
 #define hb_is_reference(T) hb_match_reference<T>::value
-template <typename T> struct hb_match_pointer		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-template <typename T> struct hb_match_pointer<T *>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
+template <typename T> struct hb_match_pointer		: hb_type_identity_t<T>, hb_false_type	{};
+template <typename T> struct hb_match_pointer<T *>	: hb_type_identity_t<T>, hb_true_type	{};
 template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
 template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
 template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
 template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
 template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
 template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
@@ -259,15 +259,15 @@ using hb_is_arithmetic = hb_bool_constant<
 #define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
 #define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
 
 
 
 
-template <typename T>
-using hb_is_signed = hb_conditional<hb_is_arithmetic (T),
-				    hb_bool_constant<(T) -1 < (T) 0>,
-				    hb_false_type>;
+template <typename T, bool is_arithmetic> struct hb_is_signed_;
+template <typename T> struct hb_is_signed_<T, false>	: hb_false_type {};
+template <typename T> struct hb_is_signed_<T, true>	: hb_bool_constant<(T) -1 < (T) 0> {};
+template <typename T> struct hb_is_signed : hb_is_signed_<T, hb_is_arithmetic (T)> {};
 #define hb_is_signed(T) hb_is_signed<T>::value
 #define hb_is_signed(T) hb_is_signed<T>::value
-template <typename T>
-using hb_is_unsigned = hb_conditional<hb_is_arithmetic (T),
-				      hb_bool_constant<(T) 0 < (T) -1>,
-				      hb_false_type>;
+template <typename T, bool is_arithmetic> struct hb_is_unsigned_;
+template <typename T> struct hb_is_unsigned_<T, false>	: hb_false_type {};
+template <typename T> struct hb_is_unsigned_<T, true>	: hb_bool_constant<(T) 0 < (T) -1> {};
+template <typename T> struct hb_is_unsigned : hb_is_unsigned_<T, hb_is_arithmetic (T)> {};
 #define hb_is_unsigned(T) hb_is_unsigned<T>::value
 #define hb_is_unsigned(T) hb_is_unsigned<T>::value
 
 
 template <typename T> struct hb_int_min;
 template <typename T> struct hb_int_min;
@@ -282,6 +282,7 @@ template <> struct hb_int_min<signed long>		: hb_integral_constant<signed long,
 template <> struct hb_int_min<unsigned long>		: hb_integral_constant<unsigned long,		0>		{};
 template <> struct hb_int_min<unsigned long>		: hb_integral_constant<unsigned long,		0>		{};
 template <> struct hb_int_min<signed long long>		: hb_integral_constant<signed long long,	LLONG_MIN>	{};
 template <> struct hb_int_min<signed long long>		: hb_integral_constant<signed long long,	LLONG_MIN>	{};
 template <> struct hb_int_min<unsigned long long>	: hb_integral_constant<unsigned long long,	0>		{};
 template <> struct hb_int_min<unsigned long long>	: hb_integral_constant<unsigned long long,	0>		{};
+template <typename T> struct hb_int_min<T *>		: hb_integral_constant<T *,			nullptr>	{};
 #define hb_int_min(T) hb_int_min<T>::value
 #define hb_int_min(T) hb_int_min<T>::value
 template <typename T> struct hb_int_max;
 template <typename T> struct hb_int_max;
 template <> struct hb_int_max<char>			: hb_integral_constant<char,			CHAR_MAX>	{};
 template <> struct hb_int_max<char>			: hb_integral_constant<char,			CHAR_MAX>	{};

+ 177 - 0
thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc

@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2011,2012,2013  Google, Inc.
+ * Copyright © 2021  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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ms-feature-ranges.hh"
+
+bool
+hb_ms_setup_features (const hb_feature_t                *features,
+		      unsigned int                       num_features,
+		      hb_vector_t<hb_ms_feature_t>      &feature_records, /* OUT */
+		      hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
+{
+  feature_records.shrink(0);
+  range_records.shrink(0);
+
+  /* Sort features by start/end events. */
+  hb_vector_t<hb_ms_feature_event_t> feature_events;
+  for (unsigned int i = 0; i < num_features; i++)
+  {
+    hb_ms_active_feature_t feature;
+    feature.fea.tag_le = hb_uint32_swap (features[i].tag);
+    feature.fea.value = features[i].value;
+    feature.order = i;
+
+    hb_ms_feature_event_t *event;
+
+    event = feature_events.push ();
+    event->index = features[i].start;
+    event->start = true;
+    event->feature = feature;
+
+    event = feature_events.push ();
+    event->index = features[i].end;
+    event->start = false;
+    event->feature = feature;
+  }
+  feature_events.qsort ();
+  /* Add a strategic final event. */
+  {
+    hb_ms_active_feature_t feature;
+    feature.fea.tag_le = 0;
+    feature.fea.value = 0;
+    feature.order = num_features + 1;
+
+    auto *event = feature_events.push ();
+    event->index = 0; /* This value does magic. */
+    event->start = false;
+    event->feature = feature;
+  }
+
+  /* Scan events and save features for each range. */
+  hb_vector_t<hb_ms_active_feature_t> active_features;
+  unsigned int last_index = 0;
+  for (unsigned int i = 0; i < feature_events.length; i++)
+  {
+    auto *event = &feature_events[i];
+
+    if (event->index != last_index)
+    {
+      /* Save a snapshot of active features and the range. */
+      auto *range = range_records.push ();
+      auto offset = feature_records.length;
+
+      active_features.qsort ();
+      for (unsigned int j = 0; j < active_features.length; j++)
+      {
+        if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
+        {
+          feature_records.push (active_features[j].fea);
+        }
+        else
+        {
+          /* Overrides value for existing feature. */
+          feature_records[feature_records.length - 1].value = active_features[j].fea.value;
+        }
+      }
+
+      /* Will convert to pointer after all is ready, since feature_records.array
+       * may move as we grow it. */
+      range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
+      range->features.num_features = feature_records.length - offset;
+      range->index_first = last_index;
+      range->index_last  = event->index - 1;
+
+      last_index = event->index;
+    }
+
+    if (event->start)
+    {
+      active_features.push (event->feature);
+    }
+    else
+    {
+      auto *feature = active_features.find (&event->feature);
+      if (feature)
+        active_features.remove (feature - active_features.arrayZ);
+    }
+  }
+
+  if (!range_records.length) /* No active feature found. */
+    num_features = 0;
+
+  /* Fixup the pointers. */
+  for (unsigned int i = 0; i < range_records.length; i++)
+  {
+    auto *range = &range_records[i];
+    range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
+  }
+
+  return !!num_features;
+}
+
+void
+hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t>      &feature_records,
+			   hb_vector_t<hb_ms_range_record_t> &range_records,
+			   unsigned int                       chars_offset,
+			   unsigned int                       chars_len,
+			   uint16_t                          *log_clusters,
+			   hb_vector_t<hb_ms_features_t*>    &range_features, /* OUT */
+			   hb_vector_t<uint32_t>             &range_counts /* OUT */)
+{
+  range_features.shrink (0);
+  range_counts.shrink (0);
+
+  auto *last_range = &range_records[0];
+  for (unsigned int i = chars_offset; i < chars_len; i++)
+  {
+    auto *range = last_range;
+    while (log_clusters[i] < range->index_first)
+      range--;
+    while (log_clusters[i] > range->index_last)
+      range++;
+    if (!range_features.length ||
+        &range->features != range_features[range_features.length - 1])
+    {
+      auto **features = range_features.push ();
+      auto *c = range_counts.push ();
+      if (unlikely (!features || !c))
+      {
+        range_features.shrink (0);
+        range_counts.shrink (0);
+        break;
+      }
+      *features = &range->features;
+      *c = 1;
+    }
+    else
+    {
+      range_counts[range_counts.length - 1]++;
+    }
+
+    last_range = range;
+  }
+}

+ 96 - 0
thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh

@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2011,2012,2013  Google, Inc.
+ * Copyright © 2021  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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MS_FEATURE_RANGES_HH
+#define HB_MS_FEATURE_RANGES_HH
+
+#include "hb.hh"
+
+typedef struct hb_ms_feature_t {
+  uint32_t tag_le;
+  uint32_t value;
+} hb_ms_feature_t;
+
+typedef struct hb_ms_features_t {
+  hb_ms_feature_t *features;
+  uint32_t         num_features;
+} hb_ms_features_t;
+
+struct hb_ms_active_feature_t {
+  hb_ms_feature_t fea;
+  unsigned int order;
+
+  HB_INTERNAL static int cmp (const void *pa, const void *pb) {
+    const auto *a = (const hb_ms_active_feature_t *) pa;
+    const auto *b = (const hb_ms_active_feature_t *) pb;
+    return a->fea.tag_le < b->fea.tag_le ? -1 : a->fea.tag_le > b->fea.tag_le ? 1 :
+	   a->order < b->order ? -1 : a->order > b->order ? 1 :
+	   a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 :
+	   0;
+  }
+  bool operator== (const hb_ms_active_feature_t *f)
+  { return cmp (this, f) == 0; }
+};
+
+struct hb_ms_feature_event_t {
+  unsigned int index;
+  bool start;
+  hb_ms_active_feature_t feature;
+
+  HB_INTERNAL static int cmp (const void *pa, const void *pb)
+  {
+    const auto *a = (const hb_ms_feature_event_t *) pa;
+    const auto *b = (const hb_ms_feature_event_t *) pb;
+    return a->index < b->index ? -1 : a->index > b->index ? 1 :
+	   a->start < b->start ? -1 : a->start > b->start ? 1 :
+	   hb_ms_active_feature_t::cmp (&a->feature, &b->feature);
+  }
+};
+
+struct hb_ms_range_record_t {
+  hb_ms_features_t features;
+  unsigned int index_first; /* == start */
+  unsigned int index_last;  /* == end - 1 */
+};
+
+HB_INTERNAL bool
+hb_ms_setup_features (const hb_feature_t                *features,
+		      unsigned int                       num_features,
+		      hb_vector_t<hb_ms_feature_t>      &feature_records, /* OUT */
+		      hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */);
+
+
+HB_INTERNAL void
+hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t>      &feature_records,
+			   hb_vector_t<hb_ms_range_record_t> &range_records,
+			   unsigned int                       chars_offset,
+			   unsigned int                       chars_len,
+			   uint16_t                          *log_clusters,
+			   hb_vector_t<hb_ms_features_t*>    &range_features, /* OUT */
+			   hb_vector_t<uint32_t>             &range_counts /* OUT */);
+
+#endif /* HB_MS_FEATURE_RANGES_HH */

+ 1 - 7
thirdparty/harfbuzz/src/hb-mutex.hh

@@ -39,8 +39,7 @@
 
 
 /* We need external help for these */
 /* We need external help for these */
 
 
-#if defined(HB_MUTEX_IMPL_INIT) \
- && defined(hb_mutex_impl_init) \
+#if defined(hb_mutex_impl_init) \
  && defined(hb_mutex_impl_lock) \
  && defined(hb_mutex_impl_lock) \
  && defined(hb_mutex_impl_unlock) \
  && defined(hb_mutex_impl_unlock) \
  && defined(hb_mutex_impl_finish)
  && defined(hb_mutex_impl_finish)
@@ -52,7 +51,6 @@
 
 
 #include <pthread.h>
 #include <pthread.h>
 typedef pthread_mutex_t hb_mutex_impl_t;
 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_init(M)	pthread_mutex_init (M, nullptr)
 #define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
 #define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
 #define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
 #define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
@@ -62,7 +60,6 @@ typedef pthread_mutex_t hb_mutex_impl_t;
 #elif !defined(HB_NO_MT) && defined(_WIN32)
 #elif !defined(HB_NO_MT) && defined(_WIN32)
 
 
 typedef CRITICAL_SECTION hb_mutex_impl_t;
 typedef CRITICAL_SECTION hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	{0}
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 #define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
 #define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
 #else
 #else
@@ -76,7 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
 #elif defined(HB_NO_MT)
 #elif defined(HB_NO_MT)
 
 
 typedef int hb_mutex_impl_t;
 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_init(M)	HB_STMT_START {} HB_STMT_END
 #define hb_mutex_impl_lock(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_unlock(M)	HB_STMT_START {} HB_STMT_END
@@ -91,8 +87,6 @@ typedef int hb_mutex_impl_t;
 #endif
 #endif
 
 
 
 
-#define HB_MUTEX_INIT		{HB_MUTEX_IMPL_INIT}
-
 struct hb_mutex_t
 struct hb_mutex_t
 {
 {
   hb_mutex_impl_t m;
   hb_mutex_impl_t m;

+ 16 - 4
thirdparty/harfbuzz/src/hb-null.hh

@@ -39,8 +39,11 @@
 
 
 #define HB_NULL_POOL_SIZE 384
 #define HB_NULL_POOL_SIZE 384
 
 
-/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
- * otherwise return sizeof(T). */
+/* Use SFINAE to sniff whether T has min_size; in which case return the larger
+ * of sizeof(T) and T::null_size, otherwise return sizeof(T).
+ *
+ * The main purpose of this is to let structs communicate that they are not nullable,
+ * by defining min_size but *not* null_size. */
 
 
 /* The hard way...
 /* The hard way...
  * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
  * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
@@ -49,8 +52,9 @@
 template <typename T, typename>
 template <typename T, typename>
 struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
 struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
 template <typename T>
 template <typename T>
-struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
-
+struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>>
+	: hb_integral_constant<unsigned,
+			       (sizeof (T) > T::null_size ? sizeof (T) : T::null_size)> {};
 template <typename T>
 template <typename T>
 using hb_null_size = _hb_null_size<T, void>;
 using hb_null_size = _hb_null_size<T, void>;
 #define hb_null_size(T) hb_null_size<T>::value
 #define hb_null_size(T) hb_null_size<T>::value
@@ -68,6 +72,14 @@ template <typename T>
 using hb_static_size = _hb_static_size<T, void>;
 using hb_static_size = _hb_static_size<T, void>;
 #define hb_static_size(T) hb_static_size<T>::value
 #define hb_static_size(T) hb_static_size<T>::value
 
 
+template <typename T, typename>
+struct _hb_min_size : hb_integral_constant<unsigned, sizeof (T)> {};
+template <typename T>
+struct _hb_min_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::min_size> {};
+template <typename T>
+using hb_min_size = _hb_min_size<T, void>;
+#define hb_min_size(T) hb_min_size<T>::value
+
 
 
 /*
 /*
  * Null()
  * Null()

+ 10 - 15
thirdparty/harfbuzz/src/hb-object.hh

@@ -140,8 +140,6 @@ struct hb_lockable_set_t
  * Reference-count.
  * Reference-count.
  */
  */
 
 
-#define HB_REFERENCE_COUNT_INIT {0}
-
 struct hb_reference_count_t
 struct hb_reference_count_t
 {
 {
   mutable hb_atomic_int_t ref_count;
   mutable hb_atomic_int_t ref_count;
@@ -197,6 +195,8 @@ struct hb_object_header_t
   hb_reference_count_t ref_count;
   hb_reference_count_t ref_count;
   mutable hb_atomic_int_t writable = 0;
   mutable hb_atomic_int_t writable = 0;
   hb_atomic_ptr_t<hb_user_data_array_t> user_data;
   hb_atomic_ptr_t<hb_user_data_array_t> user_data;
+
+  bool is_inert () const { return !ref_count.get_relaxed (); }
 };
 };
 #define HB_OBJECT_HEADER_STATIC {}
 #define HB_OBJECT_HEADER_STATIC {}
 
 
@@ -217,7 +217,7 @@ static inline void hb_object_trace (const Type *obj, const char *function)
 template <typename Type>
 template <typename Type>
 static inline Type *hb_object_create ()
 static inline Type *hb_object_create ()
 {
 {
-  Type *obj = (Type *) calloc (1, sizeof (Type));
+  Type *obj = (Type *) hb_calloc (1, sizeof (Type));
 
 
   if (unlikely (!obj))
   if (unlikely (!obj))
     return obj;
     return obj;
@@ -234,11 +234,6 @@ static inline void hb_object_init (Type *obj)
   obj->header.user_data.init ();
   obj->header.user_data.init ();
 }
 }
 template <typename Type>
 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)
 static inline bool hb_object_is_valid (const Type *obj)
 {
 {
   return likely (obj->header.ref_count.is_valid ());
   return likely (obj->header.ref_count.is_valid ());
@@ -257,7 +252,7 @@ template <typename Type>
 static inline Type *hb_object_reference (Type *obj)
 static inline Type *hb_object_reference (Type *obj)
 {
 {
   hb_object_trace (obj, HB_FUNC);
   hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
+  if (unlikely (!obj || obj->header.is_inert ()))
     return obj;
     return obj;
   assert (hb_object_is_valid (obj));
   assert (hb_object_is_valid (obj));
   obj->header.ref_count.inc ();
   obj->header.ref_count.inc ();
@@ -267,7 +262,7 @@ template <typename Type>
 static inline bool hb_object_destroy (Type *obj)
 static inline bool hb_object_destroy (Type *obj)
 {
 {
   hb_object_trace (obj, HB_FUNC);
   hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
+  if (unlikely (!obj || obj->header.is_inert ()))
     return false;
     return false;
   assert (hb_object_is_valid (obj));
   assert (hb_object_is_valid (obj));
   if (obj->header.ref_count.dec () != 1)
   if (obj->header.ref_count.dec () != 1)
@@ -284,7 +279,7 @@ static inline void hb_object_fini (Type *obj)
   if (user_data)
   if (user_data)
   {
   {
     user_data->fini ();
     user_data->fini ();
-    free (user_data);
+    hb_free (user_data);
     user_data = nullptr;
     user_data = nullptr;
   }
   }
 }
 }
@@ -295,7 +290,7 @@ static inline bool hb_object_set_user_data (Type               *obj,
 					    hb_destroy_func_t   destroy,
 					    hb_destroy_func_t   destroy,
 					    hb_bool_t           replace)
 					    hb_bool_t           replace)
 {
 {
-  if (unlikely (!obj || hb_object_is_inert (obj)))
+  if (unlikely (!obj || obj->header.is_inert ()))
     return false;
     return false;
   assert (hb_object_is_valid (obj));
   assert (hb_object_is_valid (obj));
 
 
@@ -303,14 +298,14 @@ retry:
   hb_user_data_array_t *user_data = obj->header.user_data.get ();
   hb_user_data_array_t *user_data = obj->header.user_data.get ();
   if (unlikely (!user_data))
   if (unlikely (!user_data))
   {
   {
-    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
+    user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1);
     if (unlikely (!user_data))
     if (unlikely (!user_data))
       return false;
       return false;
     user_data->init ();
     user_data->init ();
     if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
     if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
     {
     {
       user_data->fini ();
       user_data->fini ();
-      free (user_data);
+      hb_free (user_data);
       goto retry;
       goto retry;
     }
     }
   }
   }
@@ -322,7 +317,7 @@ template <typename Type>
 static inline void *hb_object_get_user_data (Type               *obj,
 static inline void *hb_object_get_user_data (Type               *obj,
 					     hb_user_data_key_t *key)
 					     hb_user_data_key_t *key)
 {
 {
-  if (unlikely (!obj || hb_object_is_inert (obj)))
+  if (unlikely (!obj || obj->header.is_inert ()))
     return nullptr;
     return nullptr;
   assert (hb_object_is_valid (obj));
   assert (hb_object_is_valid (obj));
   hb_user_data_array_t *user_data = obj->header.user_data.get ();
   hb_user_data_array_t *user_data = obj->header.user_data.get ();

+ 42 - 26
thirdparty/harfbuzz/src/hb-open-file.hh

@@ -35,7 +35,6 @@
 
 
 namespace OT {
 namespace OT {
 
 
-
 /*
 /*
  *
  *
  * The OpenType Font File
  * The OpenType Font File
@@ -102,7 +101,13 @@ typedef struct OpenTypeOffsetTable
   {
   {
     Tag t;
     Tag t;
     t = tag;
     t = tag;
-    return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+    /* Use lfind for small fonts; there are fonts that have unsorted table entries;
+     * those tend to work in other tools, so tolerate them.
+     * https://github.com/harfbuzz/harfbuzz/issues/3065 */
+    if (tables.len < 16)
+      return tables.lfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+    else
+      return tables.bfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
   }
   }
   const TableRecord& get_table_by_tag (hb_tag_t tag) const
   const TableRecord& get_table_by_tag (hb_tag_t tag) const
   {
   {
@@ -113,44 +118,53 @@ typedef struct OpenTypeOffsetTable
 
 
   public:
   public:
 
 
-  template <typename item_t>
+  template <typename Iterator,
+	    hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
   bool serialize (hb_serialize_context_t *c,
   bool serialize (hb_serialize_context_t *c,
 		  hb_tag_t sfnt_tag,
 		  hb_tag_t sfnt_tag,
-		  hb_array_t<item_t> items)
+		  Iterator it)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     /* Alloc 12 for the OTHeader. */
     /* Alloc 12 for the OTHeader. */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     /* Write sfntVersion (bytes 0..3). */
     /* Write sfntVersion (bytes 0..3). */
     sfnt_version = sfnt_tag;
     sfnt_version = sfnt_tag;
     /* Take space for numTables, searchRange, entrySelector, RangeShift
     /* Take space for numTables, searchRange, entrySelector, RangeShift
      * and the TableRecords themselves.  */
      * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
+    unsigned num_items = it.len ();
+    if (unlikely (!tables.serialize (c, num_items))) return_trace (false);
 
 
     const char *dir_end = (const char *) c->head;
     const char *dir_end = (const char *) c->head;
     HBUINT32 *checksum_adjustment = nullptr;
     HBUINT32 *checksum_adjustment = nullptr;
 
 
     /* Write OffsetTables, alloc for and write actual table blobs. */
     /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < tables.len; i++)
+    unsigned i = 0;
+    for (hb_pair_t<hb_tag_t, hb_blob_t*> entry : it)
     {
     {
-      TableRecord &rec = tables.arrayZ[i];
-      hb_blob_t *blob = items[i].blob;
-      rec.tag = items[i].tag;
-      rec.length = blob->length;
-      rec.offset.serialize (c, this);
+      hb_blob_t *blob = entry.second;
+      unsigned len = blob->length;
 
 
       /* Allocate room for the table and copy it. */
       /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (rec.length);
+      char *start = (char *) c->allocate_size<void> (len);
       if (unlikely (!start)) return false;
       if (unlikely (!start)) return false;
 
 
-      if (likely (rec.length))
-	memcpy (start, blob->data, rec.length);
+      TableRecord &rec = tables.arrayZ[i];
+      rec.tag = entry.first;
+      rec.length = len;
+      rec.offset = 0;
+      if (unlikely (!c->check_assign (rec.offset,
+				      (unsigned) ((char *) start - (char *) this),
+				      HB_SERIALIZE_ERROR_OFFSET_OVERFLOW)))
+        return_trace (false);
+
+      if (likely (len))
+	memcpy (start, blob->data, len);
 
 
       /* 4-byte alignment. */
       /* 4-byte alignment. */
       c->align (4);
       c->align (4);
       const char *end = (const char *) c->head;
       const char *end = (const char *) c->head;
 
 
-      if (items[i].tag == HB_OT_TAG_head &&
+      if (entry.first == HB_OT_TAG_head &&
 	  (unsigned) (end - start) >= head::static_size)
 	  (unsigned) (end - start) >= head::static_size)
       {
       {
 	head *h = (head *) start;
 	head *h = (head *) start;
@@ -159,6 +173,7 @@ typedef struct OpenTypeOffsetTable
       }
       }
 
 
       rec.checkSum.set_for_data (start, end - start);
       rec.checkSum.set_for_data (start, end - start);
+      i++;
     }
     }
 
 
     tables.qsort ();
     tables.qsort ();
@@ -170,7 +185,7 @@ typedef struct OpenTypeOffsetTable
       /* The following line is a slower version of the following block. */
       /* 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, (const char *) c->head - (const char *) this);
       checksum.set_for_data (this, dir_end - (const char *) this);
       checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < items.length; i++)
+      for (unsigned int i = 0; i < num_items; i++)
       {
       {
 	TableRecord &rec = tables.arrayZ[i];
 	TableRecord &rec = tables.arrayZ[i];
 	checksum = checksum + rec.checkSum;
 	checksum = checksum + rec.checkSum;
@@ -218,7 +233,7 @@ struct TTCHeaderVersion1
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
 				 * 0x00010000u */
-  LArrayOf<LOffsetTo<OpenTypeOffsetTable>>
+  Array32Of<Offset32To<OpenTypeOffsetTable>>
 		table;		/* Array of offsets to the OffsetTable for each font
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
 				 * from the beginning of the file */
   public:
   public:
@@ -295,7 +310,7 @@ struct ResourceRecord
   HBINT16	nameOffset;	/* Offset from beginning of resource name list
   HBINT16	nameOffset;	/* Offset from beginning of resource name list
 				 * to resource name, -1 means there is none. */
 				 * to resource name, -1 means there is none. */
   HBUINT8	attrs;		/* Resource attributes */
   HBUINT8	attrs;		/* Resource attributes */
-  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
+  NNOffset24To<Array32Of<HBUINT8>>
 		offset;		/* Offset from beginning of data block to
 		offset;		/* Offset from beginning of data block to
 				 * data for this resource */
 				 * data for this resource */
   HBUINT32	reserved;	/* Reserved for handle to resource */
   HBUINT32	reserved;	/* Reserved for handle to resource */
@@ -330,7 +345,7 @@ struct ResourceTypeRecord
   protected:
   protected:
   Tag		tag;		/* Resource type. */
   Tag		tag;		/* Resource type. */
   HBUINT16	resCountM1;	/* Number of resources minus 1. */
   HBUINT16	resCountM1;	/* Number of resources minus 1. */
-  NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
+  NNOffset16To<UnsizedArrayOf<ResourceRecord>>
 		resourcesZ;	/* Offset from beginning of resource type list
 		resourcesZ;	/* Offset from beginning of resource type list
 				 * to reference item list for this type. */
 				 * to reference item list for this type. */
   public:
   public:
@@ -386,7 +401,7 @@ struct ResourceMap
   HBUINT32	reserved1;	/* Reserved for handle to next resource map */
   HBUINT32	reserved1;	/* Reserved for handle to next resource map */
   HBUINT16	resreved2;	/* Reserved for file reference number */
   HBUINT16	resreved2;	/* Reserved for file reference number */
   HBUINT16	attrs;		/* Resource fork attribute */
   HBUINT16	attrs;		/* Resource fork attribute */
-  NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
+  NNOffset16To<ArrayOfM1<ResourceTypeRecord>>
 		typeList;	/* Offset from beginning of map to
 		typeList;	/* Offset from beginning of map to
 				 * resource type list */
 				 * resource type list */
   Offset16	nameList;	/* Offset from beginning of map to
   Offset16	nameList;	/* Offset from beginning of map to
@@ -418,10 +433,10 @@ struct ResourceForkHeader
   }
   }
 
 
   protected:
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		data;		/* Offset from beginning of resource fork
 		data;		/* Offset from beginning of resource fork
 				 * to resource data */
 				 * to resource data */
-  LNNOffsetTo<ResourceMap >
+  NNOffset32To<ResourceMap >
 		map;		/* Offset from beginning of resource fork
 		map;		/* Offset from beginning of resource fork
 				 * to resource map */
 				 * to resource map */
   HBUINT32	dataLen;	/* Length of resource data */
   HBUINT32	dataLen;	/* Length of resource data */
@@ -477,14 +492,15 @@ struct OpenTypeFontFile
     }
     }
   }
   }
 
 
-  template <typename item_t>
+  template <typename Iterator,
+	    hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
   bool serialize_single (hb_serialize_context_t *c,
   bool serialize_single (hb_serialize_context_t *c,
 			 hb_tag_t sfnt_tag,
 			 hb_tag_t sfnt_tag,
-			 hb_array_t<item_t> items)
+			 Iterator items)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     assert (sfnt_tag != TTCTag);
     assert (sfnt_tag != TTCTag);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     return_trace (u.fontFace.serialize (c, sfnt_tag, items));
     return_trace (u.fontFace.serialize (c, sfnt_tag, items));
   }
   }
 
 

+ 83 - 63
thirdparty/harfbuzz/src/hb-open-type.hh

@@ -196,6 +196,12 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
 
 
 typedef Index NameID;
 typedef Index NameID;
 
 
+struct VarIdx : HBUINT32 {
+  static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+  VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
+
 /* Offset, Null offset = 0 */
 /* Offset, Null offset = 0 */
 template <typename Type, bool has_null=true>
 template <typename Type, bool has_null=true>
 struct Offset : Type
 struct Offset : Type
@@ -206,18 +212,12 @@ struct Offset : Type
 
 
   bool is_null () const { return has_null && 0 == *this; }
   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> ();
-    c->check_assign (*this, (unsigned) ((char *) t - (char *) base));
-    return t;
-  }
-
   public:
   public:
   DEFINE_SIZE_STATIC (sizeof (Type));
   DEFINE_SIZE_STATIC (sizeof (Type));
 };
 };
 
 
 typedef Offset<HBUINT16> Offset16;
 typedef Offset<HBUINT16> Offset16;
+typedef Offset<HBUINT24> Offset24;
 typedef Offset<HBUINT32> Offset32;
 typedef Offset<HBUINT32> Offset32;
 
 
 
 
@@ -287,7 +287,7 @@ struct _hb_has_null<Type, true>
   static       Type *get_crap () { return &Crap (Type); }
   static       Type *get_crap () { return &Crap (Type); }
 };
 };
 
 
-template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+template <typename Type, typename OffsetType, bool has_null=true>
 struct OffsetTo : Offset<OffsetType, has_null>
 struct OffsetTo : Offset<OffsetType, has_null>
 {
 {
   HB_DELETE_COPY_ASSIGN (OffsetTo);
   HB_DELETE_COPY_ASSIGN (OffsetTo);
@@ -319,10 +319,6 @@ struct OffsetTo : Offset<OffsetType, has_null>
 	    hb_enable_if (hb_is_convertible (Base, void *))>
 	    hb_enable_if (hb_is_convertible (Base, void *))>
   friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
   friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
 
 
-  Type& serialize (hb_serialize_context_t *c, const void *base)
-  {
-    return * (Type *) Offset<OffsetType>::serialize (c, base);
-  }
 
 
   template <typename ...Ts>
   template <typename ...Ts>
   bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
   bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
@@ -346,6 +342,23 @@ struct OffsetTo : Offset<OffsetType, has_null>
     return ret;
     return ret;
   }
   }
 
 
+
+  template <typename ...Ts>
+  bool serialize_serialize (hb_serialize_context_t *c, Ts&&... ds)
+  {
+    *this = 0;
+
+    Type* obj = c->push<Type> ();
+    bool ret = obj->serialize (c, hb_forward<Ts> (ds)...);
+
+    if (ret)
+      c->add_link (*this, c->pop_pack ());
+    else
+      c->pop_discard ();
+
+    return ret;
+  }
+
   /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
   /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
   /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
   /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
    * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
    * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
@@ -378,7 +391,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
     if (unlikely (!c->check_struct (this))) return_trace (false);
     if (unlikely (this->is_null ())) return_trace (true);
     if (unlikely (this->is_null ())) return_trace (true);
-    if (unlikely (!c->check_range (base, *this))) return_trace (false);
+    if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
     return_trace (true);
     return_trace (true);
   }
   }
 
 
@@ -401,12 +414,14 @@ struct OffsetTo : Offset<OffsetType, has_null>
   DEFINE_SIZE_STATIC (sizeof (OffsetType));
   DEFINE_SIZE_STATIC (sizeof (OffsetType));
 };
 };
 /* Partial specializations. */
 /* Partial specializations. */
-template <typename Type, bool has_null=true>
-using LOffsetTo = OffsetTo<Type, HBUINT32, has_null>;
-template <typename Type, typename OffsetType=HBUINT16>
-using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
-template <typename Type>
-using LNNOffsetTo = LOffsetTo<Type, false>;
+template <typename Type, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, has_null>;
+template <typename Type, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, has_null>;
+template <typename Type, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, has_null>;
+
+template <typename Type, typename OffsetType> using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
+template <typename Type> using NNOffset16To = Offset16To<Type, false>;
+template <typename Type> using NNOffset24To = Offset24To<Type, false>;
+template <typename Type> using NNOffset32To = Offset32To<Type, false>;
 
 
 
 
 /*
 /*
@@ -453,8 +468,10 @@ struct UnsizedArrayOf
   const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
   const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
   { return *as_array (len).lsearch (x, &not_found); }
   { return *as_array (len).lsearch (x, &not_found); }
   template <typename T>
   template <typename T>
-  bool lfind (unsigned int len, const T &x, unsigned *pos = nullptr) const
-  { return as_array (len).lfind (x, pos); }
+  bool lfind (unsigned int len, const T &x, unsigned int *i = nullptr,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
+	      unsigned int to_store = (unsigned int) -1) const
+  { return as_array (len).lfind (x, i, not_found, to_store); }
 
 
   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
   { as_array (len).qsort (start, end); }
   { as_array (len).qsort (start, end); }
@@ -462,7 +479,7 @@ struct UnsizedArrayOf
   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend (*this, items_len))) return_trace (false);
+    if (unlikely (!c->extend (this, items_len))) return_trace (false);
     return_trace (true);
     return_trace (true);
   }
   }
   template <typename Iterator,
   template <typename Iterator,
@@ -513,11 +530,11 @@ struct UnsizedArrayOf
 
 
 /* Unsized array of offset's */
 /* Unsized array of offset's */
 template <typename Type, typename OffsetType, bool has_null=true>
 template <typename Type, typename OffsetType, bool has_null=true>
-using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
+using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
 
 
 /* Unsized array of offsets relative to the beginning of the array itself. */
 /* Unsized array of offsets relative to the beginning of the array itself. */
 template <typename Type, typename OffsetType, bool has_null=true>
 template <typename Type, typename OffsetType, bool has_null=true>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
 {
 {
   const Type& operator [] (int i_) const
   const Type& operator [] (int i_) const
   {
   {
@@ -538,7 +555,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
   bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+    return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
 		   ::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
 		   ::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
   }
   }
 };
 };
@@ -562,14 +579,14 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
   { return *as_array (len).bsearch (x, &not_found); }
   { return *as_array (len).bsearch (x, &not_found); }
   template <typename T>
   template <typename T>
   bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
   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,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
 	      unsigned int to_store = (unsigned int) -1) const
 	      unsigned int to_store = (unsigned int) -1) const
   { return as_array (len).bfind (x, i, not_found, to_store); }
   { return as_array (len).bfind (x, i, not_found, to_store); }
 };
 };
 
 
 
 
 /* An array with a number of elements. */
 /* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
 struct ArrayOf
 struct ArrayOf
 {
 {
   typedef Type item_t;
   typedef Type item_t;
@@ -617,17 +634,32 @@ struct ArrayOf
   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
   { return as_array ().sub_array (start_offset, count); }
   { return as_array ().sub_array (start_offset, count); }
 
 
-  hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len)
+  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); }
+  template <typename T>
+  bool lfind (const T &x, unsigned int *i = nullptr,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
+	      unsigned int to_store = (unsigned int) -1) const
+  { return as_array ().lfind (x, i, not_found, to_store); }
+
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    c->check_assign (len, items_len);
-    if (unlikely (!c->extend (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+    c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
+    if (unlikely (!c->extend (this))) return_trace (false);
     return_trace (true);
     return_trace (true);
   }
   }
   template <typename Iterator,
   template <typename Iterator,
 	    hb_requires (hb_is_source_of (Iterator, Type))>
 	    hb_requires (hb_is_source_of (Iterator, Type))>
-  hb_success_t serialize (hb_serialize_context_t *c, Iterator items)
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     unsigned count = items.len ();
     unsigned count = items.len ();
@@ -643,7 +675,7 @@ struct ArrayOf
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     len++;
     len++;
-    if (unlikely (!len || !c->extend (*this)))
+    if (unlikely (!len || !c->extend (this)))
     {
     {
       len--;
       len--;
       return_trace (nullptr);
       return_trace (nullptr);
@@ -656,7 +688,7 @@ struct ArrayOf
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
     auto *out = c->start_embed (this);
     if (unlikely (!c->extend_min (out))) return_trace (nullptr);
     if (unlikely (!c->extend_min (out))) return_trace (nullptr);
-    c->check_assign (out->len, len);
+    c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
     if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
     if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
     return_trace (out);
     return_trace (out);
   }
   }
@@ -674,19 +706,6 @@ struct ArrayOf
     return_trace (true);
     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); }
-  template <typename T>
-  bool lfind (const T &x, unsigned *pos = nullptr) const
-  { return as_array ().lfind (x, pos); }
-
-  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
   bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
@@ -699,21 +718,18 @@ struct ArrayOf
   public:
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
 };
 };
-template <typename Type>
-using LArrayOf = ArrayOf<Type, HBUINT32>;
+template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
+template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
 using PString = ArrayOf<HBUINT8, HBUINT8>;
 using PString = ArrayOf<HBUINT8, HBUINT8>;
 
 
 /* Array of Offset's */
 /* Array of Offset's */
-template <typename Type>
-using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>;
-template <typename Type>
-using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>;
-template <typename Type>
-using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
+template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>;
+template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>;
+template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
 
 
 /* Array of offsets relative to the beginning of the array itself. */
 /* Array of offsets relative to the beginning of the array itself. */
 template <typename Type>
 template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
+struct List16OfOffset16To : Array16OfOffset16To<Type>
 {
 {
   const Type& operator [] (int i_) const
   const Type& operator [] (int i_) const
   {
   {
@@ -731,7 +747,7 @@ struct OffsetListOf : OffsetArrayOf<Type>
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
   {
   {
     TRACE_SUBSET (this);
     TRACE_SUBSET (this);
-    struct OffsetListOf<Type> *out = c->serializer->embed (*this);
+    struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!out)) return_trace (false);
     unsigned int count = this->len;
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
     for (unsigned int i = 0; i < count; i++)
@@ -743,7 +759,7 @@ struct OffsetListOf : OffsetArrayOf<Type>
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
+    return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
   }
   }
 };
 };
 
 
@@ -786,9 +802,9 @@ struct HeadlessArrayOf
   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    c->check_assign (lenP1, items_len + 1);
-    if (unlikely (!c->extend (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+    c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
+    if (unlikely (!c->extend (this))) return_trace (false);
     return_trace (true);
     return_trace (true);
   }
   }
   template <typename Iterator,
   template <typename Iterator,
@@ -859,6 +875,7 @@ struct ArrayOfM1
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
     unsigned int count = lenM1 + 1;
     unsigned int count = lenM1 + 1;
     for (unsigned int i = 0; i < count; i++)
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
       if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
@@ -882,7 +899,7 @@ struct ArrayOfM1
 };
 };
 
 
 /* An array with sorted elements.  Supports binary searching. */
 /* An array with sorted elements.  Supports binary searching. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
 struct SortedArrayOf : ArrayOf<Type, LenType>
 struct SortedArrayOf : ArrayOf<Type, LenType>
 {
 {
   hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->len); }
   hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->len); }
@@ -928,11 +945,14 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
   { return *as_array ().bsearch (x, &not_found); }
   { return *as_array ().bsearch (x, &not_found); }
   template <typename T>
   template <typename T>
   bool bfind (const T &x, unsigned int *i = nullptr,
   bool bfind (const T &x, unsigned int *i = nullptr,
-	      hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
 	      unsigned int to_store = (unsigned int) -1) const
 	      unsigned int to_store = (unsigned int) -1) const
   { return as_array ().bfind (x, i, not_found, to_store); }
   { return as_array ().bfind (x, i, not_found, to_store); }
 };
 };
 
 
+template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
+template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
+
 /*
 /*
  * Binary-search arrays
  * Binary-search arrays
  */
  */

+ 3 - 3
thirdparty/harfbuzz/src/hb-ot-cff-common.hh

@@ -126,7 +126,7 @@ struct CFFIndex
     else
     else
     {
     {
       /* serialize CFFIndex header */
       /* serialize CFFIndex header */
-      if (unlikely (!c->extend_min (*this))) return_trace (false);
+      if (unlikely (!c->extend_min (this))) return_trace (false);
       this->count = byteArray.length;
       this->count = byteArray.length;
       this->offSize = offSize_;
       this->offSize = offSize_;
       if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
       if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
@@ -214,7 +214,7 @@ struct CFFIndex
     unsigned off_size = calcOffSize (total);
     unsigned off_size = calcOffSize (total);
 
 
     /* serialize CFFIndex header */
     /* serialize CFFIndex header */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     this->count = it.len ();
     this->count = it.len ();
     this->offSize = off_size;
     this->offSize = off_size;
     if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
     if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
@@ -335,7 +335,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     /* serialize CFFIndex header */
     /* serialize CFFIndex header */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     this->count = dataArrayLen;
     this->count = dataArrayLen;
     this->offSize = offSize_;
     this->offSize = offSize_;
     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))

+ 4 - 3
thirdparty/harfbuzz/src/hb-ot-cff1-table.hh

@@ -187,7 +187,7 @@ struct Encoding
 		  const hb_vector_t<code_pair_t>& supp_codes)
 		  const hb_vector_t<code_pair_t>& supp_codes)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    Encoding *dest = c->extend_min (*this);
+    Encoding *dest = c->extend_min (this);
     if (unlikely (!dest)) return_trace (false);
     if (unlikely (!dest)) return_trace (false);
     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
     dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
     switch (format) {
     switch (format) {
@@ -457,7 +457,7 @@ struct Charset
 		  const hb_vector_t<code_pair_t>& sid_ranges)
 		  const hb_vector_t<code_pair_t>& sid_ranges)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    Charset *dest = c->extend_min (*this);
+    Charset *dest = c->extend_min (this);
     if (unlikely (!dest)) return_trace (false);
     if (unlikely (!dest)) return_trace (false);
     dest->format = format;
     dest->format = format;
     switch (format)
     switch (format)
@@ -713,6 +713,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
       case OpCode_Notice:
       case OpCode_Notice:
       case OpCode_Copyright:
       case OpCode_Copyright:
       case OpCode_FullName:
       case OpCode_FullName:
+      case OpCode_FontName:
       case OpCode_FamilyName:
       case OpCode_FamilyName:
       case OpCode_Weight:
       case OpCode_Weight:
       case OpCode_PostScript:
       case OpCode_PostScript:
@@ -1390,7 +1391,7 @@ struct cff1
 
 
   public:
   public:
   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
-  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
+  NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
   HBUINT8	       offSize;	  /* offset size (unused?) */
   HBUINT8	       offSize;	  /* offset size (unused?) */
 
 
   public:
   public:

+ 176 - 80
thirdparty/harfbuzz/src/hb-ot-cmap-table.hh

@@ -49,6 +49,12 @@ struct CmapSubtableFormat0
     *glyph = gid;
     *glyph = gid;
     return true;
     return true;
   }
   }
+
+  unsigned get_language () const
+  {
+    return language;
+  }
+
   void collect_unicodes (hb_set_t *out) const
   void collect_unicodes (hb_set_t *out) const
   {
   {
     for (unsigned int i = 0; i < 256; i++)
     for (unsigned int i = 0; i < 256; i++)
@@ -212,29 +218,24 @@ struct CmapSubtableFormat4
 					 HBINT16 *idDelta,
 					 HBINT16 *idDelta,
 					 unsigned segcount)
 					 unsigned segcount)
   {
   {
+    hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
+    + it | hb_sink (cp_to_gid);
+
     HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
     HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
     if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
     if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
     if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
     if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
 
 
-    + hb_range (segcount)
-    | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
-    | hb_apply ([&] (const unsigned i)
-		{
-		  idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
-
-		  + it
-		  | hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
-		  | hb_apply ([&] (const hb_item_type<Iterator> _)
-			      {
-				HBUINT16 glyID;
-				glyID = _.second;
-				c->copy<HBUINT16> (glyID);
-			      })
-		  ;
-
-
-		})
-    ;
+    for (unsigned i : + hb_range (segcount)
+             | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
+    {
+      idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
+      for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
+      {
+        HBUINT16 gid;
+        gid = cp_to_gid[cp];
+        c->copy<HBUINT16> (gid);
+      }
+    }
 
 
     return idRangeOffset;
     return idRangeOffset;
   }
   }
@@ -253,7 +254,7 @@ struct CmapSubtableFormat4
     if (format4_iter.len () == 0) return;
     if (format4_iter.len () == 0) return;
 
 
     unsigned table_initpos = c->length ();
     unsigned table_initpos = c->length ();
-    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->extend_min (this))) return;
     this->format = 4;
     this->format = 4;
 
 
     //serialize endCode[]
     //serialize endCode[]
@@ -276,7 +277,17 @@ struct CmapSubtableFormat4
     HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
     HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
     if (unlikely (!c->check_success (idRangeOffset))) return;
     if (unlikely (!c->check_success (idRangeOffset))) return;
 
 
-    if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
+    this->length = c->length () - table_initpos;
+    if ((long long) this->length != (long long) c->length () - table_initpos)
+    {
+      // Length overflowed. Discard the current object before setting the error condition, otherwise
+      // discard is a noop which prevents the higher level code from reverting the serializer to the
+      // pre-error state in cmap4 overflow handling code.
+      c->pop_discard ();
+      c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW);
+      return;
+    }
+
     this->segCountX2 = segcount * 2;
     this->segCountX2 = segcount * 2;
     this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
     this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
     this->searchRange = 2 * (1u << this->entrySelector);
     this->searchRange = 2 * (1u << this->entrySelector);
@@ -285,6 +296,11 @@ struct CmapSubtableFormat4
 		       : 0;
 		       : 0;
   }
   }
 
 
+  unsigned get_language () const
+  {
+    return language;
+  }
+
   struct accelerator_t
   struct accelerator_t
   {
   {
     accelerator_t () {}
     accelerator_t () {}
@@ -547,6 +563,12 @@ struct CmapSubtableTrimmed
     *glyph = gid;
     *glyph = gid;
     return true;
     return true;
   }
   }
+
+  unsigned get_language () const
+  {
+    return language;
+  }
+
   void collect_unicodes (hb_set_t *out) const
   void collect_unicodes (hb_set_t *out) const
   {
   {
     hb_codepoint_t start = startCharCode;
     hb_codepoint_t start = startCharCode;
@@ -606,6 +628,11 @@ struct CmapSubtableLongSegmented
     return true;
     return true;
   }
   }
 
 
+  unsigned get_language () const
+  {
+    return language;
+  }
+
   void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
   void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
   {
   {
     for (unsigned int i = 0; i < this->groups.len; i++)
     for (unsigned int i = 0; i < this->groups.len; i++)
@@ -670,7 +697,7 @@ struct CmapSubtableLongSegmented
   HBUINT16	reserved;	/* Reserved; set to 0. */
   HBUINT16	reserved;	/* Reserved; set to 0. */
   HBUINT32	length;		/* Byte length of this subtable. */
   HBUINT32	length;		/* Byte length of this subtable. */
   HBUINT32	language;	/* Ignore. */
   HBUINT32	language;	/* Ignore. */
-  SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
+  SortedArray32Of<CmapSubtableLongGroup>
 		groups;		/* Groupings. */
 		groups;		/* Groupings. */
   public:
   public:
   DEFINE_SIZE_ARRAY (16, groups);
   DEFINE_SIZE_ARRAY (16, groups);
@@ -691,7 +718,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
   {
   {
     if (it.len () == 0) return;
     if (it.len () == 0) return;
     unsigned table_initpos = c->length ();
     unsigned table_initpos = c->length ();
-    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->extend_min (this))) return;
 
 
     hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
     hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
     hb_codepoint_t glyphID = 0;
     hb_codepoint_t glyphID = 0;
@@ -784,7 +811,7 @@ struct UnicodeValueRange
   DEFINE_SIZE_STATIC (4);
   DEFINE_SIZE_STATIC (4);
 };
 };
 
 
-struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
+struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
 {
 {
   void collect_unicodes (hb_set_t *out) const
   void collect_unicodes (hb_set_t *out) const
   {
   {
@@ -850,7 +877,9 @@ struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
     }
     }
     else
     else
     {
     {
-      if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr;
+      if (unlikely (!c->check_assign (out->len,
+                                      (c->length () - init_len) / UnicodeValueRange::static_size,
+                                      HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr;
       return out;
       return out;
     }
     }
   }
   }
@@ -876,23 +905,21 @@ struct UVSMapping
   DEFINE_SIZE_STATIC (5);
   DEFINE_SIZE_STATIC (5);
 };
 };
 
 
-struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
+struct NonDefaultUVS : SortedArray32Of<UVSMapping>
 {
 {
   void collect_unicodes (hb_set_t *out) const
   void collect_unicodes (hb_set_t *out) const
   {
   {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      out->add (arrayZ[i].unicodeValue);
+    for (const auto& a : as_array ())
+      out->add (a.unicodeValue);
   }
   }
 
 
   void collect_mapping (hb_set_t *unicodes, /* OUT */
   void collect_mapping (hb_set_t *unicodes, /* OUT */
 			hb_map_t *mapping /* OUT */) const
 			hb_map_t *mapping /* OUT */) const
   {
   {
-    unsigned count = len;
-    for (unsigned i = 0; i < count; i++)
+    for (const auto& a : as_array ())
     {
     {
-      hb_codepoint_t unicode = arrayZ[i].unicodeValue;
-      hb_codepoint_t glyphid = arrayZ[i].glyphID;
+      hb_codepoint_t unicode = a.unicodeValue;
+      hb_codepoint_t glyphid = a.glyphID;
       unicodes->add (unicode);
       unicodes->add (unicode);
       mapping->set (unicode, glyphid);
       mapping->set (unicode, glyphid);
     }
     }
@@ -1041,9 +1068,9 @@ struct VariationSelectorRecord
   }
   }
 
 
   HBUINT24	varSelector;	/* Variation selector. */
   HBUINT24	varSelector;	/* Variation selector. */
-  LOffsetTo<DefaultUVS>
+  Offset32To<DefaultUVS>
 		defaultUVS;	/* Offset to Default UVS Table.  May be 0. */
 		defaultUVS;	/* Offset to Default UVS Table.  May be 0. */
-  LOffsetTo<NonDefaultUVS>
+  Offset32To<NonDefaultUVS>
 		nonDefaultUVS;	/* Offset to Non-Default UVS Table.  May be 0. */
 		nonDefaultUVS;	/* Offset to Non-Default UVS Table.  May be 0. */
   public:
   public:
   DEFINE_SIZE_STATIC (11);
   DEFINE_SIZE_STATIC (11);
@@ -1058,9 +1085,8 @@ struct CmapSubtableFormat14
 
 
   void collect_variation_selectors (hb_set_t *out) 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);
+    for (const auto& a : record.as_array ())
+      out->add (a.varSelector);
   }
   }
   void collect_variation_unicodes (hb_codepoint_t variation_selector,
   void collect_variation_unicodes (hb_codepoint_t variation_selector,
 				   hb_set_t *out) const
 				   hb_set_t *out) const
@@ -1076,7 +1102,7 @@ struct CmapSubtableFormat14
     unsigned table_initpos = c->length ();
     unsigned table_initpos = c->length ();
     const char* init_tail = c->tail;
     const char* init_tail = c->tail;
 
 
-    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->extend_min (this))) return;
     this->format = 14;
     this->format = 14;
 
 
     auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
     auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
@@ -1112,10 +1138,12 @@ struct CmapSubtableFormat14
       return;
       return;
 
 
     int tail_len = init_tail - c->tail;
     int tail_len = init_tail - c->tail;
-    c->check_assign (this->length, c->length () - table_initpos + tail_len);
+    c->check_assign (this->length, c->length () - table_initpos + tail_len,
+                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
     c->check_assign (this->record.len,
     c->check_assign (this->record.len,
 		     (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
 		     (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
-		     VariationSelectorRecord::static_size);
+		     VariationSelectorRecord::static_size,
+                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
 
 
     /* Correct the incorrect write order by reversing the order of the variation
     /* Correct the incorrect write order by reversing the order of the variation
        records array. */
        records array. */
@@ -1180,7 +1208,7 @@ struct CmapSubtableFormat14
   protected:
   protected:
   HBUINT16	format;		/* Format number is set to 14. */
   HBUINT16	format;		/* Format number is set to 14. */
   HBUINT32	length;		/* Byte length of this subtable. */
   HBUINT32	length;		/* Byte length of this subtable. */
-  SortedArrayOf<VariationSelectorRecord, HBUINT32>
+  SortedArray32Of<VariationSelectorRecord>
 		record;		/* Variation selector records; sorted
 		record;		/* Variation selector records; sorted
 				 * in increasing order of `varSelector'. */
 				 * in increasing order of `varSelector'. */
   public:
   public:
@@ -1235,6 +1263,20 @@ struct CmapSubtable
     }
     }
   }
   }
 
 
+  unsigned get_language () const
+  {
+    switch (u.format) {
+    case  0: return u.format0 .get_language ();
+    case  4: return u.format4 .get_language ();
+    case  6: return u.format6 .get_language ();
+    case 10: return u.format10.get_language ();
+    case 12: return u.format12.get_language ();
+    case 13: return u.format13.get_language ();
+    case 14:
+    default: return 0;
+    }
+  }
+
   template<typename Iterator,
   template<typename Iterator,
 	   hb_requires (hb_is_iterator (Iterator))>
 	   hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
   void serialize (hb_serialize_context_t *c,
@@ -1338,7 +1380,7 @@ struct EncodingRecord
 
 
   HBUINT16	platformID;	/* Platform ID. */
   HBUINT16	platformID;	/* Platform ID. */
   HBUINT16	encodingID;	/* Platform-specific encoding ID. */
   HBUINT16	encodingID;	/* Platform-specific encoding ID. */
-  LOffsetTo<CmapSubtable>
+  Offset32To<CmapSubtable>
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
   public:
   public:
   DEFINE_SIZE_STATIC (8);
   DEFINE_SIZE_STATIC (8);
@@ -1350,58 +1392,112 @@ struct cmap
 
 
   template<typename Iterator, typename EncodingRecIter,
   template<typename Iterator, typename EncodingRecIter,
 	   hb_requires (hb_is_iterator (EncodingRecIter))>
 	   hb_requires (hb_is_iterator (EncodingRecIter))>
-  void serialize (hb_serialize_context_t *c,
+  bool serialize (hb_serialize_context_t *c,
 		  Iterator it,
 		  Iterator it,
 		  EncodingRecIter encodingrec_iter,
 		  EncodingRecIter encodingrec_iter,
 		  const void *base,
 		  const void *base,
-		  const hb_subset_plan_t *plan)
+		  const hb_subset_plan_t *plan,
+                  bool drop_format_4 = false)
   {
   {
-    if (unlikely (!c->extend_min ((*this))))  return;
+    if (unlikely (!c->extend_min ((*this))))  return false;
     this->version = 0;
     this->version = 0;
 
 
     unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
     unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
+    auto snap = c->snapshot ();
 
 
     for (const EncodingRecord& _ : encodingrec_iter)
     for (const EncodingRecord& _ : encodingrec_iter)
     {
     {
+      if (c->in_error ())
+        return false;
+
       unsigned format = (base+_.subtable).u.format;
       unsigned format = (base+_.subtable).u.format;
-      if (!plan->glyphs_requested->is_empty ())
+      if (format != 4 && format != 12 && format != 14) continue;
+
+      hb_set_t unicodes_set;
+      (base+_.subtable).collect_unicodes (&unicodes_set);
+
+      if (!drop_format_4 && format == 4)
       {
       {
-	hb_set_t unicodes_set;
-	hb_map_t cp_glyphid_map;
-	(base+_.subtable).collect_mapping (&unicodes_set, &cp_glyphid_map);
-
-	auto table_iter =
-	+ hb_zip (unicodes_set.iter(), unicodes_set.iter() | hb_map(cp_glyphid_map))
-	| hb_filter (plan->_glyphset, hb_second)
-	| hb_filter ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p)
-		     {
-		       return plan->unicodes->has (p.first) ||
-			      plan->glyphs_requested->has (p.second);
-		     })
-	| hb_map ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p_org)
-		  {
-		    return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (p_org.first, plan->glyph_map->get(p_org.second));
-		  })
-	;
-
-	if (format == 4) c->copy (_, table_iter, 4u, base, plan, &format4objidx);
-	else if (format == 12) c->copy (_, table_iter, 12u, base, plan, &format12objidx);
-	else if (format == 14) c->copy (_, table_iter, 14u, base, plan, &format14objidx);
+        c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+        if (c->in_error () && c->only_overflow ())
+        {
+          // cmap4 overflowed, reset and retry serialization without format 4 subtables.
+          c->revert (snap);
+          return serialize (c, it,
+                            encodingrec_iter,
+                            base,
+                            plan,
+                            true);
+        }
       }
       }
-      /* when --gids option is not used, we iterate input unicodes instead of
-       * all codepoints in each subtable, which is more efficient */
-      else
+
+      else if (format == 12)
       {
       {
-	hb_set_t unicodes_set;
-	(base+_.subtable).collect_unicodes (&unicodes_set);
+        if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
+        c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+      }
+      else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
+    }
+    c->check_assign(this->encodingRecord.len,
+                    (c->length () - cmap::min_size)/EncodingRecord::static_size,
+                    HB_SERIALIZE_ERROR_INT_OVERFLOW);
 
 
-	if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
-	else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
-	else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
+    // Fail if format 4 was dropped and there is no cmap12.
+    return !drop_format_4 || format12objidx;
+  }
+
+  template<typename Iterator, typename EncodingRecordIterator,
+      hb_requires (hb_is_iterator (Iterator)),
+      hb_requires (hb_is_iterator (EncodingRecordIterator))>
+  bool _can_drop (const EncodingRecord& cmap12,
+                  const hb_set_t& cmap12_unicodes,
+                  const void* base,
+                  Iterator subset_unicodes,
+                  EncodingRecordIterator encoding_records)
+  {
+    for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes))
+    {
+      if (cp >= 0x10000) return false;
+    }
+
+    unsigned target_platform;
+    unsigned target_encoding;
+    unsigned target_language = (base+cmap12.subtable).get_language ();
+
+    if (cmap12.platformID == 0 && cmap12.encodingID == 4)
+    {
+      target_platform = 0;
+      target_encoding = 3;
+    } else if (cmap12.platformID == 3 && cmap12.encodingID == 10) {
+      target_platform = 3;
+      target_encoding = 1;
+    } else {
+      return false;
+    }
+
+    for (const auto& _ : encoding_records)
+    {
+      if (_.platformID != target_platform
+          || _.encodingID != target_encoding
+          || (base+_.subtable).get_language() != target_language)
+        continue;
+
+      hb_set_t sibling_unicodes;
+      (base+_.subtable).collect_unicodes (&sibling_unicodes);
+
+      auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
+      auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
+      for (; cmap12 && sibling; cmap12++, sibling++)
+      {
+        unsigned a = *cmap12;
+        unsigned b = *sibling;
+        if (a != b) return false;
       }
       }
+
+      return !cmap12 && !sibling;
     }
     }
 
 
-    c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
+    return false;
   }
   }
 
 
   void closure_glyphs (const hb_set_t      *unicodes,
   void closure_glyphs (const hb_set_t      *unicodes,
@@ -1468,8 +1564,8 @@ struct cmap
     | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
     | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
 		 { return (_.second != HB_MAP_VALUE_INVALID); })
 		 { return (_.second != HB_MAP_VALUE_INVALID); })
     ;
     ;
-    cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan);
-    return_trace (true);
+
+    return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
   }
   }
 
 
   const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
   const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
@@ -1697,7 +1793,7 @@ struct cmap
 
 
   protected:
   protected:
   HBUINT16	version;	/* Table version number (0). */
   HBUINT16	version;	/* Table version number (0). */
-  SortedArrayOf<EncodingRecord>
+  SortedArray16Of<EncodingRecord>
 		encodingRecord;	/* Encoding tables. */
 		encodingRecord;	/* Encoding tables. */
   public:
   public:
   DEFINE_SIZE_ARRAY (4, encodingRecord);
   DEFINE_SIZE_ARRAY (4, encodingRecord);

+ 7 - 7
thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh

@@ -510,7 +510,7 @@ struct IndexSubtableRecord
 
 
   HBGlyphID			firstGlyphIndex;
   HBGlyphID			firstGlyphIndex;
   HBGlyphID			lastGlyphIndex;
   HBGlyphID			lastGlyphIndex;
-  LOffsetTo<IndexSubtable>	offsetToSubtable;
+  Offset32To<IndexSubtable>	offsetToSubtable;
   public:
   public:
   DEFINE_SIZE_STATIC (8);
   DEFINE_SIZE_STATIC (8);
 };
 };
@@ -672,7 +672,7 @@ struct BitmapSizeTable
   }
   }
 
 
   protected:
   protected:
-  LNNOffsetTo<IndexSubtableArray>
+  NNOffset32To<IndexSubtableArray>
 			indexSubtableArrayOffset;
 			indexSubtableArrayOffset;
   HBUINT32		indexTablesSize;
   HBUINT32		indexTablesSize;
   HBUINT32		numberOfIndexSubtables;
   HBUINT32		numberOfIndexSubtables;
@@ -697,7 +697,7 @@ struct BitmapSizeTable
 struct GlyphBitmapDataFormat17
 struct GlyphBitmapDataFormat17
 {
 {
   SmallGlyphMetrics	glyphMetrics;
   SmallGlyphMetrics	glyphMetrics;
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   public:
   DEFINE_SIZE_ARRAY (9, data);
   DEFINE_SIZE_ARRAY (9, data);
 };
 };
@@ -705,14 +705,14 @@ struct GlyphBitmapDataFormat17
 struct GlyphBitmapDataFormat18
 struct GlyphBitmapDataFormat18
 {
 {
   BigGlyphMetrics	glyphMetrics;
   BigGlyphMetrics	glyphMetrics;
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   public:
   DEFINE_SIZE_ARRAY (12, data);
   DEFINE_SIZE_ARRAY (12, data);
 };
 };
 
 
 struct GlyphBitmapDataFormat19
 struct GlyphBitmapDataFormat19
 {
 {
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   public:
   DEFINE_SIZE_ARRAY (4, data);
   DEFINE_SIZE_ARRAY (4, data);
 };
 };
@@ -738,7 +738,7 @@ struct CBLC
 						 cbdt_prime->length,
 						 cbdt_prime->length,
 						 HB_MEMORY_MODE_WRITABLE,
 						 HB_MEMORY_MODE_WRITABLE,
 						 cbdt_prime->arrayZ,
 						 cbdt_prime->arrayZ,
-						 free);
+						 hb_free);
     cbdt_prime->init ();  // Leak arrayZ to the blob.
     cbdt_prime->init ();  // Leak arrayZ to the blob.
     bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
     bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
     hb_blob_destroy (cbdt_prime_blob);
     hb_blob_destroy (cbdt_prime_blob);
@@ -798,7 +798,7 @@ struct CBLC
 
 
   protected:
   protected:
   FixedVersion<>		version;
   FixedVersion<>		version;
-  LArrayOf<BitmapSizeTable>	sizeTables;
+  Array32Of<BitmapSizeTable>	sizeTables;
   public:
   public:
   DEFINE_SIZE_ARRAY (8, sizeTables);
   DEFINE_SIZE_ARRAY (8, sizeTables);
 };
 };

+ 878 - 12
thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh

@@ -29,6 +29,7 @@
 #define HB_OT_COLOR_COLR_TABLE_HH
 #define HB_OT_COLOR_COLR_TABLE_HH
 
 
 #include "hb-open-type.hh"
 #include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
 
 
 /*
 /*
  * COLR -- Color
  * COLR -- Color
@@ -36,9 +37,78 @@
  */
  */
 #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
 #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
 
 
+#ifndef COLRV1_MAX_NESTING_LEVEL
+#define COLRV1_MAX_NESTING_LEVEL	100
+#endif
+
+#ifndef COLRV1_ENABLE_SUBSETTING
+#define COLRV1_ENABLE_SUBSETTING 0
+#endif
 
 
 namespace OT {
 namespace OT {
 
 
+struct COLR;
+struct hb_colrv1_closure_context_t :
+       hb_dispatch_context_t<hb_colrv1_closure_context_t>
+{
+  template <typename T>
+  return_t dispatch (const T &obj)
+  {
+    if (unlikely (nesting_level_left == 0))
+      return hb_empty_t ();
+
+    if (paint_visited (&obj))
+      return hb_empty_t ();
+
+    nesting_level_left--;
+    obj.closurev1 (this);
+    nesting_level_left++;
+    return hb_empty_t ();
+  }
+  static return_t default_return_value () { return hb_empty_t (); }
+
+  bool paint_visited (const void *paint)
+  {
+    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base);
+     if (visited_paint.has (delta))
+      return true;
+
+    visited_paint.add (delta);
+    return false;
+  }
+
+  const COLR* get_colr_table () const
+  { return reinterpret_cast<const COLR *> (base); }
+
+  void add_glyph (unsigned glyph_id)
+  { glyphs->add (glyph_id); }
+
+  void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers)
+  { layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); }
+
+  void add_palette_index (unsigned palette_index)
+  { palette_indices->add (palette_index); }
+
+  public:
+  const void *base;
+  hb_set_t visited_paint;
+  hb_set_t *glyphs;
+  hb_set_t *layer_indices;
+  hb_set_t *palette_indices;
+  unsigned nesting_level_left;
+
+  hb_colrv1_closure_context_t (const void *base_,
+                               hb_set_t *glyphs_,
+                               hb_set_t *layer_indices_,
+                               hb_set_t *palette_indices_,
+                               unsigned nesting_level_left_ = COLRV1_MAX_NESTING_LEVEL) :
+                          base (base_),
+                          glyphs (glyphs_),
+                          layer_indices (layer_indices_),
+                          palette_indices (palette_indices_),
+                          nesting_level_left (nesting_level_left_)
+  {}
+};
 
 
 struct LayerRecord
 struct LayerRecord
 {
 {
@@ -90,6 +160,707 @@ struct BaseGlyphRecord
   DEFINE_SIZE_STATIC (6);
   DEFINE_SIZE_STATIC (6);
 };
 };
 
 
+template <typename T>
+struct Variable
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  T      value;
+  VarIdx varIdx;
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <typename T>
+struct NoVariable
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  T      value;
+  public:
+  DEFINE_SIZE_STATIC (T::static_size);
+};
+
+// Color structures
+
+template <template<typename> class Var>
+struct ColorIndex
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16	paletteIndex;
+  Var<F2DOT14>	alpha;
+  public:
+  DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size);
+};
+
+template <template<typename> class Var>
+struct ColorStop
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false);
+    return_trace (color.subset (c));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Var<F2DOT14>		stopOffset;
+  ColorIndex<Var>		color;
+  public:
+  DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size);
+};
+
+struct Extend : HBUINT8
+{
+  enum {
+    EXTEND_PAD     = 0,
+    EXTEND_REPEAT  = 1,
+    EXTEND_REFLECT = 2,
+  };
+  public:
+  DEFINE_SIZE_STATIC (1);
+};
+
+template <template<typename> class Var>
+struct ColorLine
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!out)) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+    if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false);
+
+    for (const auto& stop : stops.iter ())
+    {
+      if (!stop.subset (c)) return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  stops.sanitize (c));
+  }
+
+  Extend			extend;
+  Array16Of<ColorStop<Var>>	stops;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (3, stops);
+};
+
+// Composition modes
+
+// Compositing modes are taken from https://www.w3.org/TR/compositing-1/
+// NOTE: a brief audit of major implementations suggests most support most
+// or all of the specified modes.
+struct CompositeMode : HBUINT8
+{
+  enum {
+    // Porter-Duff modes
+    // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators
+    COMPOSITE_CLEAR          =  0,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear
+    COMPOSITE_SRC            =  1,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src
+    COMPOSITE_DEST           =  2,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst
+    COMPOSITE_SRC_OVER       =  3,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover
+    COMPOSITE_DEST_OVER      =  4,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover
+    COMPOSITE_SRC_IN         =  5,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin
+    COMPOSITE_DEST_IN        =  6,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin
+    COMPOSITE_SRC_OUT        =  7,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout
+    COMPOSITE_DEST_OUT       =  8,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout
+    COMPOSITE_SRC_ATOP       =  9,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop
+    COMPOSITE_DEST_ATOP      = 10,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop
+    COMPOSITE_XOR            = 11,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor
+    COMPOSITE_PLUS           = 12,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus
+
+    // Blend modes
+    // https://www.w3.org/TR/compositing-1/#blending
+    COMPOSITE_SCREEN         = 13,  // https://www.w3.org/TR/compositing-1/#blendingscreen
+    COMPOSITE_OVERLAY        = 14,  // https://www.w3.org/TR/compositing-1/#blendingoverlay
+    COMPOSITE_DARKEN         = 15,  // https://www.w3.org/TR/compositing-1/#blendingdarken
+    COMPOSITE_LIGHTEN        = 16,  // https://www.w3.org/TR/compositing-1/#blendinglighten
+    COMPOSITE_COLOR_DODGE    = 17,  // https://www.w3.org/TR/compositing-1/#blendingcolordodge
+    COMPOSITE_COLOR_BURN     = 18,  // https://www.w3.org/TR/compositing-1/#blendingcolorburn
+    COMPOSITE_HARD_LIGHT     = 19,  // https://www.w3.org/TR/compositing-1/#blendinghardlight
+    COMPOSITE_SOFT_LIGHT     = 20,  // https://www.w3.org/TR/compositing-1/#blendingsoftlight
+    COMPOSITE_DIFFERENCE     = 21,  // https://www.w3.org/TR/compositing-1/#blendingdifference
+    COMPOSITE_EXCLUSION      = 22,  // https://www.w3.org/TR/compositing-1/#blendingexclusion
+    COMPOSITE_MULTIPLY       = 23,  // https://www.w3.org/TR/compositing-1/#blendingmultiply
+
+    // Modes that, uniquely, do not operate on components
+    // https://www.w3.org/TR/compositing-1/#blendingnonseparable
+    COMPOSITE_HSL_HUE        = 24,  // https://www.w3.org/TR/compositing-1/#blendinghue
+    COMPOSITE_HSL_SATURATION = 25,  // https://www.w3.org/TR/compositing-1/#blendingsaturation
+    COMPOSITE_HSL_COLOR      = 26,  // https://www.w3.org/TR/compositing-1/#blendingcolor
+    COMPOSITE_HSL_LUMINOSITY = 27,  // https://www.w3.org/TR/compositing-1/#blendingluminosity
+  };
+  public:
+  DEFINE_SIZE_STATIC (1);
+};
+
+template <template<typename> class Var>
+struct Affine2x3
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Var<HBFixed> xx;
+  Var<HBFixed> yx;
+  Var<HBFixed> xy;
+  Var<HBFixed> yy;
+  Var<HBFixed> dx;
+  Var<HBFixed> dy;
+  public:
+  DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size);
+};
+
+struct PaintColrLayers
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+    return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8	format; /* format = 1 */
+  HBUINT8	numLayers;
+  HBUINT32	firstLayerIndex;  /* index into COLRv1::layersV1 */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <template<typename> class Var>
+struct PaintSolid
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { c->add_palette_index (color.paletteIndex); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    if (unlikely (!c->serializer->embed (format))) return_trace (false);
+    return_trace (color.subset (c));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8		format; /* format = 2(noVar) or 3(Var)*/
+  ColorIndex<Var>	color;
+  public:
+  DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintLinearGradient
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  {
+    for (const auto &stop : (this+colorLine).stops.iter ())
+      c->add_palette_index (stop.color.paletteIndex);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 4(noVar) or 5 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintLinearGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			x0;
+  Var<FWORD>			y0;
+  Var<FWORD>			x1;
+  Var<FWORD>			y1;
+  Var<FWORD>			x2;
+  Var<FWORD>			y2;
+  public:
+  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintRadialGradient
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
+  }
+
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  {
+    for (const auto &stop : (this+colorLine).stops.iter ())
+      c->add_palette_index (stop.color.paletteIndex);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 6(noVar) or 7 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintRadialGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			x0;
+  Var<FWORD>			y0;
+  Var<UFWORD>			radius0;
+  Var<FWORD>			x1;
+  Var<FWORD>			y1;
+  Var<UFWORD>			radius1;
+  public:
+  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintSweepGradient
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
+  }
+
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  {
+    for (const auto &stop : (this+colorLine).stops.iter ())
+      c->add_palette_index (stop.color.paletteIndex);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 8(noVar) or 9 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintSweepGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			centerX;
+  Var<FWORD>			centerY;
+  Var<HBFixed>			startAngle;
+  Var<HBFixed>			endAngle;
+  public:
+  DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size);
+};
+
+struct Paint;
+// Paint a non-COLR glyph, filled as indicated by paint.
+struct PaintGlyph
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
+                                       HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    return_trace (out->paint.serialize_subset (c, paint, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && paint.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 10 */
+  Offset24To<Paint>	paint;  /* Offset (from beginning of PaintGlyph table) to Paint subtable. */
+  HBUINT16		gid;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct PaintColrGlyph
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8	format; /* format = 11 */
+  HBUINT16	gid;
+  public:
+  DEFINE_SIZE_STATIC (3);
+};
+
+template <template<typename> class Var>
+struct PaintTransform
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 12(noVar) or 13 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
+  Affine2x3<Var>	transform;
+  public:
+  DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintTranslate
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 14(noVar) or 15 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
+  Var<HBFixed>		dx;
+  Var<HBFixed>		dy;
+  public:
+  DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintRotate
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 16 (noVar) or 17(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
+  Var<HBFixed>		angle;
+  Var<HBFixed>		centerX;
+  Var<HBFixed>		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintSkew
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 18(noVar) or 19 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
+  Var<HBFixed>		xSkewAngle;
+  Var<HBFixed>		ySkewAngle;
+  Var<HBFixed>		centerX;
+  Var<HBFixed>		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size);
+};
+
+struct PaintComposite
+{
+  void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    if (!out->src.serialize_subset (c, src, this)) return_trace (false);
+    return_trace (out->backdrop.serialize_subset (c, backdrop, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  src.sanitize (c, this) &&
+                  backdrop.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 20 */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
+  CompositeMode		mode;   /* If mode is unrecognized use COMPOSITE_CLEAR */
+  Offset24To<Paint>	backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct Paint
+{
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...));
+    case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...));
+    case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...));
+    case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...));
+    case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...));
+    case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...));
+    case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...));
+    case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...));
+    case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...));
+    case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...));
+    case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...));
+    case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...));
+    case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...));
+    case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...));
+    case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...));
+    case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...));
+    case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...));
+    case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...));
+    case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT8				format;
+  PaintColrLayers			paintformat1;
+  PaintSolid<NoVariable>		paintformat2;
+  PaintSolid<Variable>			paintformat3;
+  PaintLinearGradient<NoVariable>	paintformat4;
+  PaintLinearGradient<Variable>		paintformat5;
+  PaintRadialGradient<NoVariable>	paintformat6;
+  PaintRadialGradient<Variable>		paintformat7;
+  PaintSweepGradient<NoVariable>	paintformat8;
+  PaintSweepGradient<Variable>		paintformat9;
+  PaintGlyph				paintformat10;
+  PaintColrGlyph			paintformat11;
+  PaintTransform<NoVariable>		paintformat12;
+  PaintTransform<Variable>		paintformat13;
+  PaintTranslate<NoVariable>		paintformat14;
+  PaintTranslate<Variable>		paintformat15;
+  PaintRotate<NoVariable>		paintformat16;
+  PaintRotate<Variable>			paintformat17;
+  PaintSkew<NoVariable>			paintformat18;
+  PaintSkew<Variable>			paintformat19;
+  PaintComposite			paintformat20;
+  } u;
+};
+
+struct BaseGlyphV1Record
+{
+  int cmp (hb_codepoint_t g) const
+  { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
+
+  bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
+                  const void* src_base, hb_subset_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = s->embed (this);
+    if (unlikely (!out)) return_trace (false);
+    if (!s->check_assign (out->glyphId, glyph_map->get (glyphId),
+                          HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    return_trace (out->paint.serialize_subset (c, paint, src_base));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && paint.sanitize (c, base)));
+  }
+
+  public:
+  HBGlyphID		glyphId;    /* Glyph ID of reference glyph */
+  Offset32To<Paint>	paint;      /* Offset (from beginning of BaseGlyphV1Record array) to Paint,
+                                     * Typically PaintColrLayers */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
+{
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
+    const hb_set_t* glyphset = c->plan->_glyphset;
+
+    for (const auto& _ : as_array ())
+    {
+      unsigned gid = _.glyphId;
+      if (!glyphset->has (gid)) continue;
+
+      if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
+      else return_trace (false);
+    }
+
+    return_trace (out->len != 0);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (SortedArray32Of<BaseGlyphV1Record>::sanitize (c, this));
+  }
+};
+
+struct LayerV1List : Array32OfOffset32To<Paint>
+{
+  const Paint& get_paint (unsigned i) const
+  { return this+(*this)[i]; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
+
+    for (const auto& _ : + hb_enumerate (*this)
+                         | hb_filter (c->plan->colrv1_layers, hb_first))
+
+    {
+      auto *o = out->serialize_append (c->serializer);
+      if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (Array32OfOffset32To<Paint>::sanitize (c, this));
+  }
+};
+
 struct COLR
 struct COLR
 {
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
   static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
@@ -131,6 +902,15 @@ struct COLR
 			 hb_set_t *related_ids /* OUT */) const
 			 hb_set_t *related_ids /* OUT */) const
     { colr->closure_glyphs (glyph, related_ids); }
     { colr->closure_glyphs (glyph, related_ids); }
 
 
+    void closure_V0palette_indices (const hb_set_t *glyphs,
+				    hb_set_t *palettes /* OUT */) const
+    { colr->closure_V0palette_indices (glyphs, palettes); }
+
+    void closure_forV1 (hb_set_t *glyphset,
+                        hb_set_t *layer_indices,
+                        hb_set_t *palette_indices) const
+    { colr->closure_forV1 (glyphset, layer_indices, palette_indices); }
+
     private:
     private:
     hb_blob_ptr_t<COLR> colr;
     hb_blob_ptr_t<COLR> colr;
   };
   };
@@ -147,21 +927,70 @@ struct COLR
     related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
     related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
   }
   }
 
 
+  void closure_V0palette_indices (const hb_set_t *glyphs,
+				  hb_set_t *palettes /* OUT */) const
+  {
+    if (!numBaseGlyphs || !numLayers) return;
+    hb_array_t<const BaseGlyphRecord> baseGlyphs = (this+baseGlyphsZ).as_array (numBaseGlyphs);
+    hb_array_t<const LayerRecord> all_layers = (this+layersZ).as_array (numLayers);
+
+    for (const BaseGlyphRecord record : baseGlyphs)
+    {
+      if (!glyphs->has (record.glyphId)) continue;
+      hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
+                                                                   record.numLayers);
+      for (const LayerRecord layer : glyph_layers)
+        palettes->add (layer.colorIdx);
+    }
+  }
+
+  void closure_forV1 (hb_set_t *glyphset,
+                      hb_set_t *layer_indices,
+                      hb_set_t *palette_indices) const
+  {
+    if (version != 1) return;
+    hb_set_t visited_glyphs;
+
+    hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
+    const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List;
+
+    for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ())
+    {
+      unsigned gid = baseglyphV1record.glyphId;
+      if (!glyphset->has (gid)) continue;
+
+      const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint;
+      paint.dispatch (&c);
+    }
+    hb_set_union (glyphset, &visited_glyphs);
+  }
+
+  const LayerV1List& get_layerV1List () const
+  { return (this+layersV1); }
+
+  const BaseGlyphV1List& get_baseglyphV1List () const
+  { return (this+baseGlyphsV1List); }
+
   bool sanitize (hb_sanitize_context_t *c) const
   bool sanitize (hb_sanitize_context_t *c) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
-			  (this+layersZ).sanitize (c, numLayers)));
+    return_trace (c->check_struct (this) &&
+                  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+                  (this+layersZ).sanitize (c, numLayers) &&
+                  (version == 0 ||
+		   (COLRV1_ENABLE_SUBSETTING && version == 1 &&
+		    baseGlyphsV1List.sanitize (c, this) &&
+		    layersV1.sanitize (c, this) &&
+		    varStore.sanitize (c, this))));
   }
   }
 
 
   template<typename BaseIterator, typename LayerIterator,
   template<typename BaseIterator, typename LayerIterator,
 	   hb_requires (hb_is_iterator (BaseIterator)),
 	   hb_requires (hb_is_iterator (BaseIterator)),
 	   hb_requires (hb_is_iterator (LayerIterator))>
 	   hb_requires (hb_is_iterator (LayerIterator))>
-  bool serialize (hb_serialize_context_t *c,
-		  unsigned version,
-		  BaseIterator base_it,
-		  LayerIterator layer_it)
+  bool serialize_V0 (hb_serialize_context_t *c,
+		     unsigned version,
+		     BaseIterator base_it,
+		     LayerIterator layer_it)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     if (unlikely (base_it.len () != layer_it.len ()))
     if (unlikely (base_it.len () != layer_it.len ()))
@@ -171,6 +1000,12 @@ struct COLR
     this->version = version;
     this->version = version;
     numLayers = 0;
     numLayers = 0;
     numBaseGlyphs = base_it.len ();
     numBaseGlyphs = base_it.len ();
+    if (base_it.len () == 0)
+    {
+      baseGlyphsZ = 0;
+      layersZ = 0;
+      return_trace (true);
+    }
     baseGlyphsZ = COLR::min_size;
     baseGlyphsZ = COLR::min_size;
     layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
     layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
 
 
@@ -198,6 +1033,14 @@ struct COLR
     return record;
     return record;
   }
   }
 
 
+  const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const
+  {
+    const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid);
+    if ((record && (hb_codepoint_t) record->glyphId != gid))
+      record = nullptr;
+    return record;
+  }
+
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
   {
   {
     TRACE_SUBSET (this);
     TRACE_SUBSET (this);
@@ -245,6 +1088,7 @@ struct COLR
 				  if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
 				  if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
 				    return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
 				    return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
 				  out_layers[i].glyphId = new_gid;
 				  out_layers[i].glyphId = new_gid;
+				  out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx);
 				}
 				}
 
 
 				return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
 				return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
@@ -253,23 +1097,45 @@ struct COLR
     | hb_map_retains_sorting (hb_second)
     | hb_map_retains_sorting (hb_second)
     ;
     ;
 
 
-    if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ()))
+    if (version == 0 && (!base_it || !layer_it))
       return_trace (false);
       return_trace (false);
 
 
     COLR *colr_prime = c->serializer->start_embed<COLR> ();
     COLR *colr_prime = c->serializer->start_embed<COLR> ();
-    return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it));
+    bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it);
+
+    if (version == 0) return_trace (ret);
+    auto snap = c->serializer->snapshot ();
+    if (!c->serializer->allocate_size<void> (3 * HBUINT32::static_size)) return_trace (false);
+    if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this))
+    {
+      if (c->serializer->in_error ()) return_trace (false);
+      //no more COLRv1 glyphs: downgrade to version 0
+      c->serializer->revert (snap);
+      colr_prime->version = 0;
+      return_trace (true);
+    }
+
+    if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false);
+
+    colr_prime->varStore = 0;
+    //TODO: subset varStore once it's implemented in fonttools
+    return_trace (true);
   }
   }
 
 
   protected:
   protected:
   HBUINT16	version;	/* Table version number (starts at 0). */
   HBUINT16	version;	/* Table version number (starts at 0). */
   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
-  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>>
+  NNOffset32To<SortedUnsizedArrayOf<BaseGlyphRecord>>
 		baseGlyphsZ;	/* Offset to Base Glyph records. */
 		baseGlyphsZ;	/* Offset to Base Glyph records. */
-  LNNOffsetTo<UnsizedArrayOf<LayerRecord>>
+  NNOffset32To<UnsizedArrayOf<LayerRecord>>
 		layersZ;	/* Offset to Layer Records. */
 		layersZ;	/* Offset to Layer Records. */
   HBUINT16	numLayers;	/* Number of Layer Records. */
   HBUINT16	numLayers;	/* Number of Layer Records. */
+  // Version-1 additions
+  Offset32To<BaseGlyphV1List>		baseGlyphsV1List;
+  Offset32To<LayerV1List>		layersV1;
+  Offset32To<VariationStore>		varStore;
   public:
   public:
-  DEFINE_SIZE_STATIC (14);
+  DEFINE_SIZE_MIN (14);
 };
 };
 
 
 } /* namespace OT */
 } /* namespace OT */

+ 101 - 0
thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh

@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2020  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.
+ *
+ */
+
+#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH
+#define HB_OT_COLR_COLRV1_CLOSURE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-color-colr-table.hh"
+
+/*
+ * COLR -- Color
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
+ */
+namespace OT {
+
+HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  c->add_layer_indices (firstLayerIndex, numLayers);
+  const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List ();
+  for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
+  {
+    const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
+    paint.dispatch (c);
+  }
+}
+
+HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  c->add_glyph (gid);
+  (this+paint).dispatch (c);
+}
+
+HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  const COLR *colr_table = c->get_colr_table ();
+  const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid);
+  if (!baseglyphV1_record) return;
+  c->add_glyph (gid);
+
+  const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List ();
+  (&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c);
+}
+
+template <template<typename> class Var>
+HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  (this+src).dispatch (c);
+}
+
+template <template<typename> class Var>
+HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  (this+src).dispatch (c);
+}
+
+template <template<typename> class Var>
+HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  (this+src).dispatch (c);
+}
+
+template <template<typename> class Var>
+HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  (this+src).dispatch (c);
+}
+
+HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
+{
+  (this+src).dispatch (c);
+  (this+backdrop).dispatch (c);
+}
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */

+ 122 - 5
thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh

@@ -39,7 +39,6 @@
  */
  */
 #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
 #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
 
 
-
 namespace OT {
 namespace OT {
 
 
 
 
@@ -74,6 +73,44 @@ struct CPALV1Tail
   }
   }
 
 
   public:
   public:
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned palette_count,
+                  unsigned color_count,
+                  const void *base,
+                  const hb_map_t *color_index_map) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->allocate_size<CPALV1Tail> (static_size);
+    if (unlikely (!out)) return_trace (false);
+
+    out->paletteFlagsZ = 0;
+    if (paletteFlagsZ)
+      out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
+
+    out->paletteLabelsZ = 0;
+    if (paletteLabelsZ)
+      out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
+
+    const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
+    if (colorLabelsZ)
+    {
+      c->push ();
+      for (const auto _ : colorLabels)
+      {
+        if (!color_index_map->has (_)) continue;
+        NameID new_color_idx;
+        new_color_idx = color_index_map->get (_);
+        if (!c->copy<NameID> (new_color_idx))
+        {
+          c->pop_discard ();
+          return_trace (false);
+        }
+      }
+      c->add_link (out->colorLabelsZ, c->pop_pack ());
+    }
+    return_trace (true);
+  }
+
   bool sanitize (hb_sanitize_context_t *c,
   bool sanitize (hb_sanitize_context_t *c,
 		 const void *base,
 		 const void *base,
 		 unsigned int palette_count,
 		 unsigned int palette_count,
@@ -87,15 +124,17 @@ struct CPALV1Tail
   }
   }
 
 
   protected:
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT32>>
+  // TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
+  //                     here. Currently they are needed since UnsizedArrayOf doesn't define null_size
+  NNOffset32To<UnsizedArrayOf<HBUINT32>>
 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to
 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to
 					 * the Palette Type Array. Set to 0 if no array
 					 * the Palette Type Array. Set to 0 if no array
 					 * is provided. */
 					 * is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID>>
+  NNOffset32To<UnsizedArrayOf<NameID>>
 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to
 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the palette labels array. Set to 0 if no
 					 * the palette labels array. Set to 0 if no
 					 * array is provided. */
 					 * array is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID>>
+  NNOffset32To<UnsizedArrayOf<NameID>>
 		colorLabelsZ;		/* Offset from the beginning of CPAL table to
 		colorLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the color labels array. Set to 0
 					 * the color labels array. Set to 0
 					 * if no array is provided. */
 					 * if no array is provided. */
@@ -157,6 +196,84 @@ struct CPAL
   }
   }
 
 
   public:
   public:
+  bool serialize (hb_serialize_context_t *c,
+                  const hb_array_t<const BGRAColor> &color_records,
+                  const hb_array_t<const HBUINT16> &color_record_indices,
+                  const hb_map_t &color_record_index_map,
+                  const hb_set_t &retained_color_record_indices) const
+  {
+    TRACE_SERIALIZE (this);
+
+    for (const auto idx : color_record_indices)
+    {
+      HBUINT16 new_idx;
+      if (idx == 0) new_idx = 0;
+      else new_idx = color_record_index_map.get (idx);
+      if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
+    }
+
+    c->push ();
+    for (const auto _ : retained_color_record_indices.iter ())
+    {
+      if (!c->copy<BGRAColor> (color_records[_]))
+      {
+        c->pop_discard ();
+        return_trace (false);
+      }
+    }
+    c->add_link (colorRecordsZ, c->pop_pack ());
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_map_t *color_index_map = c->plan->colr_palettes;
+    if (color_index_map->is_empty ()) return_trace (false);
+
+    hb_set_t retained_color_indices;
+    for (const auto _ : color_index_map->keys ())
+    {
+      if (_ == 0xFFFF) continue;
+      retained_color_indices.add (_);
+    }
+    if (retained_color_indices.is_empty ()) return_trace (false);
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    out->version = version;
+    out->numColors = retained_color_indices.get_population ();
+    out->numPalettes = numPalettes;
+
+    const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
+    hb_map_t color_record_index_map;
+    hb_set_t retained_color_record_indices;
+
+    unsigned record_count = 0;
+    for (const auto first_color_record_idx : colorRecordIndices)
+    {
+      for (unsigned retained_color_idx : retained_color_indices.iter ())
+      {
+        unsigned color_record_idx = first_color_record_idx + retained_color_idx;
+        if (color_record_index_map.has (color_record_idx)) continue;
+        color_record_index_map.set (color_record_idx, record_count);
+        retained_color_record_indices.add (color_record_idx);
+        record_count++;
+      }
+    }
+
+    out->numColorRecords = record_count;
+    const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
+    if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices))
+      return_trace (false);
+
+    if (version == 1)
+      return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
+
+    return_trace (true);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   bool sanitize (hb_sanitize_context_t *c) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
@@ -173,7 +290,7 @@ struct CPAL
   HBUINT16	numPalettes;		/* Number of palettes in the table. */
   HBUINT16	numPalettes;		/* Number of palettes in the table. */
   HBUINT16	numColorRecords;	/* Total number of color records, combined for
   HBUINT16	numColorRecords;	/* Total number of color records, combined for
 					 * all palettes. */
 					 * all palettes. */
-  LNNOffsetTo<UnsizedArrayOf<BGRAColor>>
+  NNOffset32To<UnsizedArrayOf<BGRAColor>>
 		colorRecordsZ;		/* Offset from the beginning of CPAL table to
 		colorRecordsZ;		/* Offset from the beginning of CPAL table to
 					 * the first ColorRecord. */
 					 * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>
   UnsizedArrayOf<HBUINT16>

+ 5 - 5
thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh

@@ -145,7 +145,7 @@ struct SBIXStrike
     auto* out = c->serializer->start_embed<SBIXStrike> ();
     auto* out = c->serializer->start_embed<SBIXStrike> ();
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!out)) return_trace (false);
     auto snap = c->serializer->snapshot ();
     auto snap = c->serializer->snapshot ();
-    if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
+    if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
     out->ppem = ppem;
     out->ppem = ppem;
     out->resolution = resolution;
     out->resolution = resolution;
     HBUINT32 head;
     HBUINT32 head;
@@ -185,7 +185,7 @@ struct SBIXStrike
   HBUINT16	resolution;	/* The device pixel density (in PPI) for which this
   HBUINT16	resolution;	/* The device pixel density (in PPI) for which this
 				 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
 				 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
   protected:
   protected:
-  UnsizedArrayOf<LOffsetTo<SBIXGlyph>>
+  UnsizedArrayOf<Offset32To<SBIXGlyph>>
 		imageOffsetsZ;	/* Offset from the beginning of the strike data header
 		imageOffsetsZ;	/* Offset from the beginning of the strike data header
 				 * to bitmap data for an individual glyph ID. */
 				 * to bitmap data for an individual glyph ID. */
   public:
   public:
@@ -352,11 +352,11 @@ struct sbix
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
 
 
-    auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
+    auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
 
-    hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
+    hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
     hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
     hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
     for (int i = strikes.len - 1; i >= 0; --i)
     for (int i = strikes.len - 1; i >= 0; --i)
     {
     {
@@ -400,7 +400,7 @@ struct sbix
   HBUINT16	version;	/* Table version number — set to 1 */
   HBUINT16	version;	/* Table version number — set to 1 */
   HBUINT16	flags;		/* Bit 0: Set to 1. Bit 1: Draw outlines.
   HBUINT16	flags;		/* Bit 0: Set to 1. Bit 1: Draw outlines.
 				 * Bits 2 to 15: reserved (set to 0). */
 				 * Bits 2 to 15: reserved (set to 0). */
-  LOffsetLArrayOf<SBIXStrike>
+  Array32OfOffset32To<SBIXStrike>
 		strikes;	/* Offsets from the beginning of the 'sbix'
 		strikes;	/* Offsets from the beginning of the 'sbix'
 				 * table to data for each individual bitmap strike. */
 				 * table to data for each individual bitmap strike. */
   public:
   public:

+ 2 - 2
thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh

@@ -62,7 +62,7 @@ struct SVGDocumentIndexEntry
 				 * this index entry. */
 				 * this index entry. */
   HBUINT16	endGlyphID;	/* The last glyph ID in the range described by
   HBUINT16	endGlyphID;	/* The last glyph ID in the range described by
 				 * this index entry. Must be >= startGlyphID. */
 				 * this index entry. Must be >= startGlyphID. */
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		svgDoc;		/* Offset from the beginning of the SVG Document Index
 		svgDoc;		/* Offset from the beginning of the SVG Document Index
 				 * to an SVG document. Must be non-zero. */
 				 * to an SVG document. Must be non-zero. */
   HBUINT32	svgDocLength;	/* Length of the SVG document.
   HBUINT32	svgDocLength;	/* Length of the SVG document.
@@ -107,7 +107,7 @@ struct SVG
 
 
   protected:
   protected:
   HBUINT16	version;	/* Table version (starting at 0). */
   HBUINT16	version;	/* Table version (starting at 0). */
-  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>>
+  Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
 		svgDocEntries;	/* Offset (relative to the start of the SVG table) to the
 		svgDocEntries;	/* Offset (relative to the start of the SVG table) to the
 				 * SVG Documents Index. Must be non-zero. */
 				 * SVG Documents Index. Must be non-zero. */
 				/* Array of SVG Document Index Entries. */
 				/* Array of SVG Document Index Entries. */

+ 1 - 1
thirdparty/harfbuzz/src/hb-ot-face-table-list.hh

@@ -40,7 +40,7 @@
 
 
 /* This lists font tables that the hb_face_t will contain and lazily
 /* This lists font tables that the hb_face_t will contain and lazily
  * load.  Don't add a table unless it's used though.  This is not
  * load.  Don't add a table unless it's used though.  This is not
- * exactly free. */
+ * exactly zero-cost. */
 
 
 /* v--- Add new tables in the right place here. */
 /* v--- Add new tables in the right place here. */
 
 

+ 3 - 9
thirdparty/harfbuzz/src/hb-ot-font.cc

@@ -253,9 +253,7 @@ hb_ot_get_font_v_extents (hb_font_t *font,
 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
 	 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
 }
 }
 
 
-#if HB_USE_ATEXIT
-static void free_static_ot_funcs ();
-#endif
+static inline void free_static_ot_funcs ();
 
 
 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
 {
 {
@@ -281,21 +279,17 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
 
 
     hb_font_funcs_make_immutable (funcs);
     hb_font_funcs_make_immutable (funcs);
 
 
-#if HB_USE_ATEXIT
-    atexit (free_static_ot_funcs);
-#endif
+    hb_atexit (free_static_ot_funcs);
 
 
     return funcs;
     return funcs;
   }
   }
 } static_ot_funcs;
 } static_ot_funcs;
 
 
-#if HB_USE_ATEXIT
-static
+static inline
 void free_static_ot_funcs ()
 void free_static_ot_funcs ()
 {
 {
   static_ot_funcs.free_instance ();
   static_ot_funcs.free_instance ();
 }
 }
-#endif
 
 
 static hb_font_funcs_t *
 static hb_font_funcs_t *
 _hb_ot_get_font_funcs ()
 _hb_ot_get_font_funcs ()

+ 1 - 1
thirdparty/harfbuzz/src/hb-ot-gasp-table.hh

@@ -71,7 +71,7 @@ struct gasp
 
 
   protected:
   protected:
   HBUINT16	version;	/* Version number (set to 1) */
   HBUINT16	version;	/* Version number (set to 1) */
-  ArrayOf<GaspRange>
+  Array16Of<GaspRange>
 		gaspRanges;	/* Number of records to follow
 		gaspRanges;	/* Number of records to follow
 				 * Sorted by ppem */
 				 * Sorted by ppem */
   public:
   public:

+ 105 - 35
thirdparty/harfbuzz/src/hb-ot-glyf-table.hh

@@ -45,6 +45,10 @@ namespace OT {
  */
  */
 #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
 #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
 
 
+#ifndef HB_MAX_COMPOSITE_OPERATIONS
+#define HB_MAX_COMPOSITE_OPERATIONS 100000
+#endif
+
 
 
 struct loca
 struct loca
 {
 {
@@ -98,7 +102,7 @@ struct glyf
     unsigned num_offsets = padded_offsets.len () + 1;
     unsigned num_offsets = padded_offsets.len () + 1;
     bool use_short_loca = max_offset < 0x1FFFF;
     bool use_short_loca = max_offset < 0x1FFFF;
     unsigned entry_size = use_short_loca ? 2 : 4;
     unsigned entry_size = use_short_loca ? 2 : 4;
-    char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
+    char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
 
 
     if (unlikely (!loca_prime_data)) return false;
     if (unlikely (!loca_prime_data)) return false;
 
 
@@ -115,7 +119,7 @@ struct glyf
 					   entry_size * num_offsets,
 					   entry_size * num_offsets,
 					   HB_MEMORY_MODE_WRITABLE,
 					   HB_MEMORY_MODE_WRITABLE,
 					   loca_prime_data,
 					   loca_prime_data,
-					   free);
+					   hb_free);
 
 
     bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
     bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
 	       && _add_head_and_set_loca_version (plan, use_short_loca);
 	       && _add_head_and_set_loca_version (plan, use_short_loca);
@@ -209,10 +213,15 @@ struct glyf
 		if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
 		if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
 		  return subset_glyph;
 		  return subset_glyph;
 
 
-		subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
-		if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
-		else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
-
+		if (new_gid == 0 &&
+                    !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+		  subset_glyph.source_glyph = Glyph ();
+		else
+		  subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+		if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+                  subset_glyph.drop_hints_bytes ();
+		else
+                  subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
 		return subset_glyph;
 		return subset_glyph;
 	      })
 	      })
     | hb_sink (glyphs)
     | hb_sink (glyphs)
@@ -281,6 +290,11 @@ struct glyf
     hb_codepoint_t get_glyph_index ()       const { return glyphIndex; }
     hb_codepoint_t get_glyph_index ()       const { return glyphIndex; }
 
 
     void drop_instructions_flag ()  { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
     void drop_instructions_flag ()  { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
+    void set_overlaps_flag ()
+    {
+      flags = (uint16_t) flags | OVERLAP_COMPOUND;
+    }
+
     bool has_instructions ()  const { return   flags & WE_HAVE_INSTRUCTIONS; }
     bool has_instructions ()  const { return   flags & WE_HAVE_INSTRUCTIONS; }
 
 
     bool has_more ()          const { return   flags & MORE_COMPONENTS; }
     bool has_more ()          const { return   flags & MORE_COMPONENTS; }
@@ -383,9 +397,12 @@ struct glyf
   {
   {
     typedef const CompositeGlyphChain *__item_t__;
     typedef const CompositeGlyphChain *__item_t__;
     composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
     composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
-      glyph (glyph_), current (current_)
-    { if (!check_range (current)) current = nullptr; }
-    composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
+        glyph (glyph_), current (nullptr), current_size (0)
+    {
+      set_next (current_);
+    }
+
+    composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
 
 
     const CompositeGlyphChain &__item__ () const { return *current; }
     const CompositeGlyphChain &__item__ () const { return *current; }
     bool __more__ () const { return current; }
     bool __more__ () const { return current; }
@@ -393,23 +410,36 @@ struct glyf
     {
     {
       if (!current->has_more ()) { current = nullptr; return; }
       if (!current->has_more ()) { current = nullptr; return; }
 
 
-      const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
-							 CompositeGlyphChain> (*current);
-      if (!check_range (possible)) { current = nullptr; return; }
-      current = possible;
+      set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
     }
     }
     bool operator != (const composite_iter_t& o) const
     bool operator != (const composite_iter_t& o) const
     { return glyph != o.glyph || current != o.current; }
     { return glyph != o.glyph || current != o.current; }
 
 
-    bool check_range (const CompositeGlyphChain *composite) const
+
+    void set_next (const CompositeGlyphChain *composite)
     {
     {
-      return glyph.check_range (composite, CompositeGlyphChain::min_size)
-	  && glyph.check_range (composite, composite->get_size ());
+      if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
+      {
+        current = nullptr;
+        current_size = 0;
+        return;
+      }
+      unsigned size = composite->get_size ();
+      if (!glyph.check_range (composite, size))
+      {
+        current = nullptr;
+        current_size = 0;
+        return;
+      }
+
+      current = composite;
+      current_size = size;
     }
     }
 
 
     private:
     private:
     hb_bytes_t glyph;
     hb_bytes_t glyph;
     __item_t__ current;
     __item_t__ current;
+    unsigned current_size;
   };
   };
 
 
   enum phantom_point_index_t
   enum phantom_point_index_t
@@ -427,14 +457,14 @@ struct glyf
   {
   {
     enum simple_glyph_flag_t
     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_RESERVED1 = 0x40,
-      FLAG_RESERVED2 = 0x80
+      FLAG_ON_CURVE       = 0x01,
+      FLAG_X_SHORT        = 0x02,
+      FLAG_Y_SHORT        = 0x04,
+      FLAG_REPEAT         = 0x08,
+      FLAG_X_SAME         = 0x10,
+      FLAG_Y_SAME         = 0x20,
+      FLAG_OVERLAP_SIMPLE = 0x40,
+      FLAG_RESERVED2      = 0x80
     };
     };
 
 
     private:
     private:
@@ -495,8 +525,8 @@ struct glyf
       const Glyph trim_padding () const
       const Glyph trim_padding () const
       {
       {
 	/* based on FontTools _g_l_y_f.py::trim */
 	/* based on FontTools _g_l_y_f.py::trim */
-	const char *glyph = bytes.arrayZ;
-	const char *glyph_end = glyph + bytes.length;
+	const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
+	const uint8_t *glyph_end = glyph + bytes.length;
 	/* simple glyph w/contours, possibly trimmable */
 	/* simple glyph w/contours, possibly trimmable */
 	glyph += instruction_len_offset ();
 	glyph += instruction_len_offset ();
 
 
@@ -553,6 +583,17 @@ struct glyf
 	dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
 	dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
       }
       }
 
 
+      void set_overlaps_flag ()
+      {
+        if (unlikely (!header.numberOfContours)) return;
+
+        unsigned flags_offset = length (instructions_length ());
+        if (unlikely (length (flags_offset + 1) > bytes.length)) return;
+
+	HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
+        first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
+      }
+
       static bool read_points (const HBUINT8 *&p /* IN/OUT */,
       static bool read_points (const HBUINT8 *&p /* IN/OUT */,
 			       contour_point_vector_t &points_ /* IN/OUT */,
 			       contour_point_vector_t &points_ /* IN/OUT */,
 			       const hb_bytes_t &bytes,
 			       const hb_bytes_t &bytes,
@@ -666,6 +707,12 @@ struct glyf
       /* Chop instructions off the end */
       /* Chop instructions off the end */
       void drop_hints_bytes (hb_bytes_t &dest_start) const
       void drop_hints_bytes (hb_bytes_t &dest_start) const
       { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
       { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+      void set_overlaps_flag ()
+      {
+        const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
+                .set_overlaps_flag ();
+      }
     };
     };
 
 
     enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
     enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
@@ -695,6 +742,15 @@ struct glyf
       }
       }
     }
     }
 
 
+    void set_overlaps_flag ()
+    {
+      switch (type) {
+      case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+      case SIMPLE:    SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+      default:        return;
+      }
+    }
+
     void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
     void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
     {
     {
       switch (type) {
       switch (type) {
@@ -886,7 +942,7 @@ struct glyf
     {
     {
       if (gid >= num_glyphs) return false;
       if (gid >= num_glyphs) return false;
 
 
-      /* Making this alloc free is not that easy
+      /* Making this allocfree is not that easy
 	 https://github.com/harfbuzz/harfbuzz/issues/2095
 	 https://github.com/harfbuzz/harfbuzz/issues/2095
 	 mostly because of gvar handling in VF fonts,
 	 mostly because of gvar handling in VF fonts,
 	 perhaps a separate path for non-VF fonts can be considered */
 	 perhaps a separate path for non-VF fonts can be considered */
@@ -1045,18 +1101,28 @@ struct glyf
       return needs_padding_removal ? glyph.trim_padding () : glyph;
       return needs_padding_removal ? glyph.trim_padding () : glyph;
     }
     }
 
 
-    void
-    add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain,
-			  unsigned int depth = 0) const
+    unsigned
+    add_gid_and_children (hb_codepoint_t gid,
+			  hb_set_t *gids_to_retain,
+			  unsigned depth = 0,
+			  unsigned operation_count = 0) const
     {
     {
-      if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
+      if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
+      if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
       /* Check if is already visited */
       /* Check if is already visited */
-      if (gids_to_retain->has (gid)) return;
+      if (gids_to_retain->has (gid)) return operation_count;
 
 
       gids_to_retain->add (gid);
       gids_to_retain->add (gid);
 
 
-      for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
-	add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth);
+      auto it = glyph_for_gid (gid).get_composite_iterator ();
+      while (it)
+      {
+        auto item = *(it++);
+        operation_count +=
+            add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
+      }
+
+      return operation_count;
     }
     }
 
 
 #ifdef HB_EXPERIMENTAL_API
 #ifdef HB_EXPERIMENTAL_API
@@ -1230,7 +1296,11 @@ struct glyf
 	  const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
 	  const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
       }
       }
 
 
-      if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
+      if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+        Glyph (dest_glyph).drop_hints ();
+
+      if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
+        Glyph (dest_glyph).set_overlaps_flag ();
 
 
       return_trace (true);
       return_trace (true);
     }
     }

+ 2 - 2
thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh

@@ -52,7 +52,7 @@ struct DeviceRecord
 
 
     unsigned length = it.len ();
     unsigned length = it.len ();
 
 
-    if (unlikely (!c->extend (*this, length)))  return_trace (false);
+    if (unlikely (!c->extend (this, length)))  return_trace (false);
 
 
     this->pixelSize = pixelSize;
     this->pixelSize = pixelSize;
     this->maxWidth =
     this->maxWidth =
@@ -110,7 +110,7 @@ struct hdmx
     for (const hb_item_type<Iterator>& _ : +it)
     for (const hb_item_type<Iterator>& _ : +it)
       c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
       c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
 
 
-    return_trace (c->successful);
+    return_trace (c->successful ());
   }
   }
 
 
 
 

+ 1 - 1
thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh

@@ -146,7 +146,7 @@ struct hmtxvmtx
 
 
     _mtx.fini ();
     _mtx.fini ();
 
 
-    if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
+    if (unlikely (c->serializer->in_error ()))
       return_trace (false);
       return_trace (false);
 
 
     // Amend header num hmetrics
     // Amend header num hmetrics

+ 18 - 18
thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh

@@ -103,7 +103,7 @@ struct BaseCoordFormat3
   protected:
   protected:
   HBUINT16	format;		/* Format identifier--format = 3 */
   HBUINT16	format;		/* Format identifier--format = 3 */
   FWORD		coordinate;	/* X or Y value, in design units */
   FWORD		coordinate;	/* X or Y value, in design units */
-  OffsetTo<Device>
+  Offset16To<Device>
 		deviceTable;	/* Offset to Device table for X or
 		deviceTable;	/* Offset to Device table for X or
 				 * Y value, from beginning of
 				 * Y value, from beginning of
 				 * BaseCoord table (may be NULL). */
 				 * BaseCoord table (may be NULL). */
@@ -173,11 +173,11 @@ struct FeatMinMaxRecord
   protected:
   protected:
   Tag		tag;		/* 4-byte feature identification tag--must
   Tag		tag;		/* 4-byte feature identification tag--must
 				 * match feature tag in FeatureList */
 				 * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		minCoord;	/* Offset to BaseCoord table that defines
 		minCoord;	/* Offset to BaseCoord table that defines
 				 * the minimum extent value, from beginning
 				 * the minimum extent value, from beginning
 				 * of MinMax table (may be NULL) */
 				 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		maxCoord;	/* Offset to BaseCoord table that defines
 		maxCoord;	/* Offset to BaseCoord table that defines
 				 * the maximum extent value, from beginning
 				 * the maximum extent value, from beginning
 				 * of MinMax table (may be NULL) */
 				 * of MinMax table (may be NULL) */
@@ -212,15 +212,15 @@ struct MinMax
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		minCoord;	/* Offset to BaseCoord table that defines
 		minCoord;	/* Offset to BaseCoord table that defines
 				 * minimum extent value, from the beginning
 				 * minimum extent value, from the beginning
 				 * of MinMax table (may be NULL) */
 				 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		maxCoord;	/* Offset to BaseCoord table that defines
 		maxCoord;	/* Offset to BaseCoord table that defines
 				 * maximum extent value, from the beginning
 				 * maximum extent value, from the beginning
 				 * of MinMax table (may be NULL) */
 				 * of MinMax table (may be NULL) */
-  SortedArrayOf<FeatMinMaxRecord>
+  SortedArray16Of<FeatMinMaxRecord>
 		featMinMaxRecords;
 		featMinMaxRecords;
 				/* Array of FeatMinMaxRecords, in alphabetical
 				/* Array of FeatMinMaxRecords, in alphabetical
 				 * order by featureTableTag */
 				 * order by featureTableTag */
@@ -247,7 +247,7 @@ struct BaseValues
   Index		defaultIndex;	/* Index number of default baseline for this
   Index		defaultIndex;	/* Index number of default baseline for this
 				 * script — equals index position of baseline tag
 				 * script — equals index position of baseline tag
 				 * in baselineTags array of the BaseTagList */
 				 * in baselineTags array of the BaseTagList */
-  OffsetArrayOf<BaseCoord>
+  Array16OfOffset16To<BaseCoord>
 		baseCoords;	/* Number of BaseCoord tables defined — should equal
 		baseCoords;	/* Number of BaseCoord tables defined — should equal
 				 * baseTagCount in the BaseTagList
 				 * baseTagCount in the BaseTagList
 				 *
 				 *
@@ -275,7 +275,7 @@ struct BaseLangSysRecord
 
 
   protected:
   protected:
   Tag		baseLangSysTag;	/* 4-byte language system identification tag */
   Tag		baseLangSysTag;	/* 4-byte language system identification tag */
-  OffsetTo<MinMax>
+  Offset16To<MinMax>
 		minMax;		/* Offset to MinMax table, from beginning
 		minMax;		/* Offset to MinMax table, from beginning
 				 * of BaseScript table */
 				 * of BaseScript table */
   public:
   public:
@@ -305,13 +305,13 @@ struct BaseScript
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<BaseValues>
+  Offset16To<BaseValues>
 		baseValues;	/* Offset to BaseValues table, from beginning
 		baseValues;	/* Offset to BaseValues table, from beginning
 				 * of BaseScript table (may be NULL) */
 				 * of BaseScript table (may be NULL) */
-  OffsetTo<MinMax>
+  Offset16To<MinMax>
 		defaultMinMax;	/* Offset to MinMax table, from beginning of
 		defaultMinMax;	/* Offset to MinMax table, from beginning of
 				 * BaseScript table (may be NULL) */
 				 * BaseScript table (may be NULL) */
-  SortedArrayOf<BaseLangSysRecord>
+  SortedArray16Of<BaseLangSysRecord>
 		baseLangSysRecords;
 		baseLangSysRecords;
 				/* Number of BaseLangSysRecords
 				/* Number of BaseLangSysRecords
 				 * defined — may be zero (0) */
 				 * defined — may be zero (0) */
@@ -339,7 +339,7 @@ struct BaseScriptRecord
 
 
   protected:
   protected:
   Tag		baseScriptTag;	/* 4-byte script identification tag */
   Tag		baseScriptTag;	/* 4-byte script identification tag */
-  OffsetTo<BaseScript>
+  Offset16To<BaseScript>
 		baseScript;	/* Offset to BaseScript table, from beginning
 		baseScript;	/* Offset to BaseScript table, from beginning
 				 * of BaseScriptList */
 				 * of BaseScriptList */
 
 
@@ -364,7 +364,7 @@ struct BaseScriptList
   }
   }
 
 
   protected:
   protected:
-  SortedArrayOf<BaseScriptRecord>
+  SortedArray16Of<BaseScriptRecord>
 			baseScriptRecords;
 			baseScriptRecords;
 
 
   public:
   public:
@@ -426,12 +426,12 @@ struct Axis
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<SortedArrayOf<Tag>>
+  Offset16To<SortedArray16Of<Tag>>
 		baseTagList;	/* Offset to BaseTagList table, from beginning
 		baseTagList;	/* Offset to BaseTagList table, from beginning
 				 * of Axis table (may be NULL)
 				 * of Axis table (may be NULL)
 				 * Array of 4-byte baseline identification tags — must
 				 * Array of 4-byte baseline identification tags — must
 				 * be in alphabetical order */
 				 * be in alphabetical order */
-  OffsetTo<BaseScriptList>
+  Offset16To<BaseScriptList>
 		baseScriptList;	/* Offset to BaseScriptList table, from beginning
 		baseScriptList;	/* Offset to BaseScriptList table, from beginning
 				 * of Axis table
 				 * of Axis table
 				 * Array of BaseScriptRecords, in alphabetical order
 				 * Array of BaseScriptRecords, in alphabetical order
@@ -501,11 +501,11 @@ struct BASE
 
 
   protected:
   protected:
   FixedVersion<>version;	/* Version of the BASE table */
   FixedVersion<>version;	/* Version of the BASE table */
-  OffsetTo<Axis>hAxis;		/* Offset to horizontal Axis table, from beginning
+  Offset16To<Axis>hAxis;		/* Offset to horizontal Axis table, from beginning
 				 * of BASE table (may be NULL) */
 				 * of BASE table (may be NULL) */
-  OffsetTo<Axis>vAxis;		/* Offset to vertical Axis table, from beginning
+  Offset16To<Axis>vAxis;		/* Offset to vertical Axis table, from beginning
 				 * of BASE table (may be NULL) */
 				 * of BASE table (may be NULL) */
-  LOffsetTo<VariationStore>
+  Offset32To<VariationStore>
 		varStore;	/* Offset to the table of Item Variation
 		varStore;	/* Offset to the table of Item Variation
 				 * Store--from beginning of BASE
 				 * Store--from beginning of BASE
 				 * header (may be NULL).  Introduced
 				 * header (may be NULL).  Introduced

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 396 - 107
thirdparty/harfbuzz/src/hb-ot-layout-common.hh


+ 20 - 22
thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh

@@ -42,7 +42,7 @@ namespace OT {
  */
  */
 
 
 /* Array of contour point indices--in increasing numerical order */
 /* Array of contour point indices--in increasing numerical order */
-struct AttachPoint : ArrayOf<HBUINT16>
+struct AttachPoint : Array16Of<HBUINT16>
 {
 {
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
   {
   {
@@ -98,8 +98,7 @@ struct AttachList
     | hb_map (glyph_map)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
     | hb_sink (new_coverage)
     ;
     ;
-    out->coverage.serialize (c->serializer, out)
-		 .serialize (c->serializer, new_coverage.iter ());
+    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
     return_trace (bool (new_coverage));
     return_trace (bool (new_coverage));
   }
   }
 
 
@@ -110,10 +109,10 @@ struct AttachList
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table -- from
 		coverage;		/* Offset to Coverage table -- from
 					 * beginning of AttachList table */
 					 * beginning of AttachList table */
-  OffsetArrayOf<AttachPoint>
+  Array16OfOffset16To<AttachPoint>
 		attachPoint;		/* Array of AttachPoint tables
 		attachPoint;		/* Array of AttachPoint tables
 					 * in Coverage Index order */
 					 * in Coverage Index order */
   public:
   public:
@@ -220,7 +219,7 @@ struct CaretValueFormat3
   protected:
   protected:
   HBUINT16	caretValueFormat;	/* Format identifier--format = 3 */
   HBUINT16	caretValueFormat;	/* Format identifier--format = 3 */
   FWORD		coordinate;		/* X or Y value, in design units */
   FWORD		coordinate;		/* X or Y value, in design units */
-  OffsetTo<Device>
+  Offset16To<Device>
 		deviceTable;		/* Offset to Device table for X or Y
 		deviceTable;		/* Offset to Device table for X or Y
 					 * value--from beginning of CaretValue
 					 * value--from beginning of CaretValue
 					 * table */
 					 * table */
@@ -329,7 +328,7 @@ struct LigGlyph
 
 
   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
   {
   {
-    for (const OffsetTo<CaretValue>& offset : carets.iter ())
+    for (const Offset16To<CaretValue>& offset : carets.iter ())
       (this+offset).collect_variation_indices (c->layout_variation_indices);
       (this+offset).collect_variation_indices (c->layout_variation_indices);
   }
   }
 
 
@@ -340,7 +339,7 @@ struct LigGlyph
   }
   }
 
 
   protected:
   protected:
-  OffsetArrayOf<CaretValue>
+  Array16OfOffset16To<CaretValue>
 		carets;			/* Offset array of CaretValue tables
 		carets;			/* Offset array of CaretValue tables
 					 * --from beginning of LigGlyph table
 					 * --from beginning of LigGlyph table
 					 * --in increasing coordinate order */
 					 * --in increasing coordinate order */
@@ -386,8 +385,7 @@ struct LigCaretList
     | hb_map (glyph_map)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
     | hb_sink (new_coverage)
     ;
     ;
-    out->coverage.serialize (c->serializer, out)
-		 .serialize (c->serializer, new_coverage.iter ());
+    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
     return_trace (bool (new_coverage));
     return_trace (bool (new_coverage));
   }
   }
 
 
@@ -408,10 +406,10 @@ struct LigCaretList
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of LigCaretList table */
 					 * beginning of LigCaretList table */
-  OffsetArrayOf<LigGlyph>
+  Array16OfOffset16To<LigGlyph>
 		ligGlyph;		/* Array of LigGlyph tables
 		ligGlyph;		/* Array of LigGlyph tables
 					 * in Coverage Index order */
 					 * in Coverage Index order */
   public:
   public:
@@ -432,7 +430,7 @@ struct MarkGlyphSetsFormat1
     out->format = format;
     out->format = format;
 
 
     bool ret = true;
     bool ret = true;
-    for (const LOffsetTo<Coverage>& offset : coverage.iter ())
+    for (const Offset32To<Coverage>& offset : coverage.iter ())
     {
     {
       auto *o = out->coverage.serialize_append (c->serializer);
       auto *o = out->coverage.serialize_append (c->serializer);
       if (unlikely (!o))
       if (unlikely (!o))
@@ -460,7 +458,7 @@ struct MarkGlyphSetsFormat1
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  ArrayOf<LOffsetTo<Coverage>>
+  Array16Of<Offset32To<Coverage>>
 		coverage;		/* Array of long offsets to mark set
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
 					 * coverage tables */
   public:
   public:
@@ -643,10 +641,10 @@ struct GDEF
     auto *out = c->serializer->embed (*this);
     auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!out)) return_trace (false);
 
 
-    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this);
+    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
     bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
     bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
     bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
     bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
-    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this);
+    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
 
 
     bool subset_markglyphsetsdef = true;
     bool subset_markglyphsetsdef = true;
     if (version.to_int () >= 0x00010002u)
     if (version.to_int () >= 0x00010002u)
@@ -687,28 +685,28 @@ struct GDEF
   protected:
   protected:
   FixedVersion<>version;		/* Version of the GDEF table--currently
   FixedVersion<>version;		/* Version of the GDEF table--currently
 					 * 0x00010003u */
 					 * 0x00010003u */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		glyphClassDef;		/* Offset to class definition table
 		glyphClassDef;		/* Offset to class definition table
 					 * for glyph type--from beginning of
 					 * for glyph type--from beginning of
 					 * GDEF header (may be Null) */
 					 * GDEF header (may be Null) */
-  OffsetTo<AttachList>
+  Offset16To<AttachList>
 		attachList;		/* Offset to list of glyphs with
 		attachList;		/* Offset to list of glyphs with
 					 * attachment points--from beginning
 					 * attachment points--from beginning
 					 * of GDEF header (may be Null) */
 					 * of GDEF header (may be Null) */
-  OffsetTo<LigCaretList>
+  Offset16To<LigCaretList>
 		ligCaretList;		/* Offset to list of positioning points
 		ligCaretList;		/* Offset to list of positioning points
 					 * for ligature carets--from beginning
 					 * for ligature carets--from beginning
 					 * of GDEF header (may be Null) */
 					 * of GDEF header (may be Null) */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		markAttachClassDef;	/* Offset to class definition table for
 		markAttachClassDef;	/* Offset to class definition table for
 					 * mark attachment type--from beginning
 					 * mark attachment type--from beginning
 					 * of GDEF header (may be Null) */
 					 * of GDEF header (may be Null) */
-  OffsetTo<MarkGlyphSets>
+  Offset16To<MarkGlyphSets>
 		markGlyphSetsDef;	/* Offset to the table of mark set
 		markGlyphSetsDef;	/* Offset to the table of mark set
 					 * definitions--from beginning of GDEF
 					 * definitions--from beginning of GDEF
 					 * header (may be NULL).  Introduced
 					 * header (may be NULL).  Introduced
 					 * in version 0x00010002. */
 					 * in version 0x00010002. */
-  LOffsetTo<VariationStore>
+  Offset32To<VariationStore>
 		varStore;		/* Offset to the table of Item Variation
 		varStore;		/* Offset to the table of Item Variation
 					 * Store--from beginning of GDEF
 					 * Store--from beginning of GDEF
 					 * header (may be NULL).  Introduced
 					 * header (may be NULL).  Introduced

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 348 - 181
thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh


+ 228 - 94
thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh

@@ -46,14 +46,19 @@ struct SingleSubstFormat1
   bool intersects (const hb_set_t *glyphs) const
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
   { return (this+coverage).intersects (glyphs); }
 
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     unsigned d = deltaGlyphID;
     unsigned d = deltaGlyphID;
+
     + hb_iter (this+coverage)
     + hb_iter (this+coverage)
-    | hb_filter (*c->glyphs)
+    | hb_filter (c->parent_active_glyphs ())
     | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
     | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
     | hb_sink (c->output)
     | hb_sink (c->output)
     ;
     ;
+
   }
   }
 
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -95,9 +100,9 @@ struct SingleSubstFormat1
 		  unsigned delta)
 		  unsigned delta)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
-    c->check_assign (deltaGlyphID, delta);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+    if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+    c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
     return_trace (true);
     return_trace (true);
   }
   }
 
 
@@ -133,7 +138,7 @@ struct SingleSubstFormat1
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
 					 * beginning of Substitution table */
   HBUINT16	deltaGlyphID;		/* Add to original GlyphID to get
   HBUINT16	deltaGlyphID;		/* Add to original GlyphID to get
@@ -147,13 +152,17 @@ struct SingleSubstFormat2
   bool intersects (const hb_set_t *glyphs) const
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
   { return (this+coverage).intersects (glyphs); }
 
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     + hb_zip (this+coverage, substitute)
     + hb_zip (this+coverage, substitute)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
     | hb_sink (c->output)
     | hb_sink (c->output)
     ;
     ;
+
   }
   }
 
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -200,9 +209,9 @@ struct SingleSubstFormat2
       + it
       + it
       | hb_map_retains_sorting (hb_first)
       | hb_map_retains_sorting (hb_first)
       ;
       ;
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
     if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
+    if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
     return_trace (true);
     return_trace (true);
   }
   }
 
 
@@ -233,10 +242,10 @@ struct SingleSubstFormat2
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
 					 * beginning of Substitution table */
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substitute;		/* Array of substitute
 		substitute;		/* Array of substitute
 					 * GlyphIDs--ordered by Coverage Index */
 					 * GlyphIDs--ordered by Coverage Index */
   public:
   public:
@@ -334,9 +343,14 @@ struct Sequence
 
 
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
 			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
 			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+    unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
 
 
-    for (unsigned int i = 0; i < count; i++) {
-      _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+    for (unsigned int i = 0; i < count; i++)
+    {
+      /* If is attached to a ligature, don't disturb that.
+       * https://github.com/harfbuzz/harfbuzz/issues/3069 */
+      if (!lig_id)
+	_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
       c->output_glyph_for_component (substitute.arrayZ[i], klass);
       c->output_glyph_for_component (substitute.arrayZ[i], klass);
     }
     }
     c->buffer->skip_glyph ();
     c->buffer->skip_glyph ();
@@ -377,7 +391,7 @@ struct Sequence
   }
   }
 
 
   protected:
   protected:
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substitute;		/* String of GlyphIDs to substitute */
 		substitute;		/* String of GlyphIDs to substitute */
   public:
   public:
   DEFINE_SIZE_ARRAY (2, substitute);
   DEFINE_SIZE_ARRAY (2, substitute);
@@ -388,10 +402,13 @@ struct MultipleSubstFormat1
   bool intersects (const hb_set_t *glyphs) const
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
   { return (this+coverage).intersects (glyphs); }
 
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     + hb_zip (this+coverage, sequence)
     + hb_zip (this+coverage, sequence)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_map (hb_add (this))
     | hb_apply ([c] (const Sequence &_) { _.closure (c); })
     | hb_apply ([c] (const Sequence &_) { _.closure (c); })
@@ -431,17 +448,17 @@ struct MultipleSubstFormat1
 		  hb_array_t<const HBGlyphID> substitute_glyphs_list)
 		  hb_array_t<const HBGlyphID> substitute_glyphs_list)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
     if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
     for (unsigned int i = 0; i < glyphs.length; i++)
     for (unsigned int i = 0; i < glyphs.length; i++)
     {
     {
       unsigned int substitute_len = substitute_len_list[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))))
+      if (unlikely (!sequence[i]
+                        .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
 	return_trace (false);
 	return_trace (false);
       substitute_glyphs_list += substitute_len;
       substitute_glyphs_list += substitute_len;
     }
     }
-    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
+    return_trace (coverage.serialize_serialize (c, glyphs));
   }
   }
 
 
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
@@ -462,8 +479,7 @@ struct MultipleSubstFormat1
     | hb_map (glyph_map)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
     | hb_sink (new_coverage)
     ;
     ;
-    out->coverage.serialize (c->serializer, out)
-		 .serialize (c->serializer, new_coverage.iter ());
+    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
     return_trace (bool (new_coverage));
     return_trace (bool (new_coverage));
   }
   }
 
 
@@ -475,10 +491,10 @@ struct MultipleSubstFormat1
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
 					 * beginning of Substitution table */
-  OffsetArrayOf<Sequence>
+  Array16OfOffset16To<Sequence>
 		sequence;		/* Array of Sequence tables
 		sequence;		/* Array of Sequence tables
 					 * ordered by Coverage Index */
 					 * ordered by Coverage Index */
   public:
   public:
@@ -547,7 +563,12 @@ struct AlternateSet
 
 
     /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
     /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
     if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
     if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+    {
+      /* Maybe we can do better than unsafe-to-break all; but since we are
+       * changing random state, it would be hard to track that.  Good 'nough. */
+      c->buffer->unsafe_to_break_all ();
       alt_index = c->random_number () % count + 1;
       alt_index = c->random_number () % count + 1;
+    }
 
 
     if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
     if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
 
 
@@ -603,7 +624,7 @@ struct AlternateSet
   }
   }
 
 
   protected:
   protected:
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		alternates;		/* Array of alternate GlyphIDs--in
 		alternates;		/* Array of alternate GlyphIDs--in
 					 * arbitrary order */
 					 * arbitrary order */
   public:
   public:
@@ -615,14 +636,18 @@ struct AlternateSubstFormat1
   bool intersects (const hb_set_t *glyphs) const
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
   { return (this+coverage).intersects (glyphs); }
 
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     + hb_zip (this+coverage, alternateSet)
     + hb_zip (this+coverage, alternateSet)
-    | hb_filter (c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_map (hb_add (this))
     | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
     | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
     ;
     ;
+
   }
   }
 
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -666,17 +691,17 @@ struct AlternateSubstFormat1
 		  hb_array_t<const HBGlyphID> alternate_glyphs_list)
 		  hb_array_t<const HBGlyphID> alternate_glyphs_list)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
     if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
     for (unsigned int i = 0; i < glyphs.length; i++)
     for (unsigned int i = 0; i < glyphs.length; i++)
     {
     {
       unsigned int alternate_len = alternate_len_list[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))))
+      if (unlikely (!alternateSet[i]
+                        .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
 	return_trace (false);
 	return_trace (false);
       alternate_glyphs_list += alternate_len;
       alternate_glyphs_list += alternate_len;
     }
     }
-    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
+    return_trace (coverage.serialize_serialize (c, glyphs));
   }
   }
 
 
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
@@ -697,8 +722,7 @@ struct AlternateSubstFormat1
     | hb_map (glyph_map)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
     | hb_sink (new_coverage)
     ;
     ;
-    out->coverage.serialize (c->serializer, out)
-		 .serialize (c->serializer, new_coverage.iter ());
+    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
     return_trace (bool (new_coverage));
     return_trace (bool (new_coverage));
   }
   }
 
 
@@ -710,10 +734,10 @@ struct AlternateSubstFormat1
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
 					 * beginning of Substitution table */
-  OffsetArrayOf<AlternateSet>
+  Array16OfOffset16To<AlternateSet>
 		alternateSet;		/* Array of AlternateSet tables
 		alternateSet;		/* Array of AlternateSet tables
 					 * ordered by Coverage Index */
 					 * ordered by Coverage Index */
   public:
   public:
@@ -831,7 +855,7 @@ struct Ligature
 		  Iterator components /* Starting from second */)
 		  Iterator components /* Starting from second */)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     ligGlyph = ligature;
     ligGlyph = ligature;
     if (unlikely (!component.serialize (c, components))) return_trace (false);
     if (unlikely (!component.serialize (c, components))) return_trace (false);
     return_trace (true);
     return_trace (true);
@@ -930,15 +954,14 @@ struct LigatureSet
 		  hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */)
 		  hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
     if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
     for (unsigned int i = 0; i < ligatures.length; i++)
     for (unsigned int i = 0; i < ligatures.length; i++)
     {
     {
       unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
       unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
-      if (unlikely (!ligature[i].serialize (c, this)
-				.serialize (c,
-					    ligatures[i],
-					    component_list.sub_array (0, component_count))))
+      if (unlikely (!ligature[i].serialize_serialize (c,
+                                                      ligatures[i],
+                                                      component_list.sub_array (0, component_count))))
 	return_trace (false);
 	return_trace (false);
       component_list += component_count;
       component_list += component_count;
     }
     }
@@ -965,7 +988,7 @@ struct LigatureSet
   }
   }
 
 
   protected:
   protected:
-  OffsetArrayOf<Ligature>
+  Array16OfOffset16To<Ligature>
 		ligature;		/* Array LigatureSet tables
 		ligature;		/* Array LigatureSet tables
 					 * ordered by preference */
 					 * ordered by preference */
   public:
   public:
@@ -980,20 +1003,24 @@ struct LigatureSubstFormat1
     + hb_zip (this+coverage, ligatureSet)
     + hb_zip (this+coverage, ligatureSet)
     | hb_filter (*glyphs, hb_first)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
-    | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_)
+    | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
 	      { return (this+_).intersects (glyphs); })
 	      { return (this+_).intersects (glyphs); })
     | hb_any
     | hb_any
     ;
     ;
   }
   }
 
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     + hb_zip (this+coverage, ligatureSet)
     + hb_zip (this+coverage, ligatureSet)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_map (hb_add (this))
     | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
     | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
     ;
     ;
+
   }
   }
 
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -1039,20 +1066,20 @@ struct LigatureSubstFormat1
 		  hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
 		  hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
     if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
     if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
     for (unsigned int i = 0; i < first_glyphs.length; i++)
     for (unsigned int i = 0; i < first_glyphs.length; i++)
     {
     {
       unsigned int ligature_count = ligature_per_first_glyph_count_list[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);
+      if (unlikely (!ligatureSet[i]
+                        .serialize_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;
       ligatures_list += ligature_count;
       component_count_list += ligature_count;
       component_count_list += ligature_count;
     }
     }
-    return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
+    return_trace (coverage.serialize_serialize (c, first_glyphs));
   }
   }
 
 
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
@@ -1073,8 +1100,7 @@ struct LigatureSubstFormat1
     | hb_map (glyph_map)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
     | hb_sink (new_coverage)
     ;
     ;
-    out->coverage.serialize (c->serializer, out)
-		 .serialize (c->serializer, new_coverage.iter ());
+    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
     return_trace (bool (new_coverage));
     return_trace (bool (new_coverage));
   }
   }
 
 
@@ -1086,10 +1112,10 @@ struct LigatureSubstFormat1
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
 					 * beginning of Substitution table */
-  OffsetArrayOf<LigatureSet>
+  Array16OfOffset16To<LigatureSet>
 		ligatureSet;		/* Array LigatureSet tables
 		ligatureSet;		/* Array LigatureSet tables
 					 * ordered by Coverage Index */
 					 * ordered by Coverage Index */
   public:
   public:
@@ -1157,7 +1183,7 @@ struct ReverseChainSingleSubstFormat1
     if (!(this+coverage).intersects (glyphs))
     if (!(this+coverage).intersects (glyphs))
       return false;
       return false;
 
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
 
     unsigned int count;
     unsigned int count;
 
 
@@ -1174,15 +1200,18 @@ struct ReverseChainSingleSubstFormat1
     return true;
     return true;
   }
   }
 
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   void closure (hb_closure_context_t *c) const
   {
   {
     if (!intersects (c->glyphs)) return;
     if (!intersects (c->glyphs)) return;
 
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
 
 
     + hb_zip (this+coverage, substitute)
     + hb_zip (this+coverage, substitute)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_second)
     | hb_sink (c->output)
     | hb_sink (c->output)
     ;
     ;
@@ -1200,12 +1229,12 @@ struct ReverseChainSingleSubstFormat1
     for (unsigned int i = 0; i < count; i++)
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
       if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
 
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     count = lookahead.len;
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
       if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
 
 
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
     count = substitute.len;
     count = substitute.len;
     c->output->add_array (substitute.arrayZ, substitute.len);
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
   }
@@ -1224,8 +1253,8 @@ struct ReverseChainSingleSubstFormat1
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
 
 
     if (unlikely (index >= substitute.len)) return_trace (false);
     if (unlikely (index >= substitute.len)) return_trace (false);
 
 
@@ -1250,11 +1279,80 @@ struct ReverseChainSingleSubstFormat1
     return_trace (false);
     return_trace (false);
   }
   }
 
 
+  template<typename Iterator,
+           hb_requires (hb_is_iterator (Iterator))>
+  bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
+
+    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+      return_trace (false);
+
+    for (auto& offset : it) {
+      auto *o = out->serialize_append (c->serializer);
+      if (unlikely (!o) || !o->serialize_subset (c, offset, this))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
+           hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
+           hb_requires (hb_is_iterator (BacktrackIterator)),
+           hb_requires (hb_is_iterator (LookaheadIterator))>
+  bool serialize (hb_subset_context_t *c,
+                  Iterator coverage_subst_iter,
+                  BacktrackIterator backtrack_iter,
+                  LookaheadIterator lookahead_iter) const
+  {
+    TRACE_SERIALIZE (this);
+
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->check_success (out))) return_trace (false);
+    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+    if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
+
+    if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
+    if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
+
+    auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> ();
+    auto substitutes =
+    + coverage_subst_iter
+    | hb_map (hb_second)
+    ;
+
+    auto glyphs =
+    + coverage_subst_iter
+    | hb_map_retains_sorting (hb_first)
+    ;
+    if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
+        return_trace (false);
+
+    if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
+      return_trace (false);
+    return_trace (true);
+  }
+
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
   {
   {
     TRACE_SUBSET (this);
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
+
+    auto it =
+    + hb_zip (this+coverage, substitute)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter (glyphset, hb_second)
+    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
+                              { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+    ;
+
+    return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
   }
   }
 
 
   bool sanitize (hb_sanitize_context_t *c) const
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1262,27 +1360,27 @@ struct ReverseChainSingleSubstFormat1
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
       return_trace (false);
       return_trace (false);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     if (!lookahead.sanitize (c, this))
     if (!lookahead.sanitize (c, this))
       return_trace (false);
       return_trace (false);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
     return_trace (substitute.sanitize (c));
     return_trace (substitute.sanitize (c));
   }
   }
 
 
   protected:
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
 					 * beginning of table */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		backtrack;		/* Array of coverage tables
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in glyph
 					 * in backtracking sequence, in glyph
 					 * sequence order */
 					 * sequence order */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		lookaheadX;		/* Array of coverage tables
 		lookaheadX;		/* Array of coverage tables
 					 * in lookahead sequence, in glyph
 					 * in lookahead sequence, in glyph
 					 * sequence order */
 					 * sequence order */
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substituteX;		/* Array of substitute
 		substituteX;		/* Array of substitute
 					 * GlyphIDs--ordered by Coverage Index */
 					 * GlyphIDs--ordered by Coverage Index */
   public:
   public:
@@ -1388,6 +1486,12 @@ struct SubstLookup : Lookup
     return lookup_type_is_reverse (type);
     return lookup_type_is_reverse (type);
   }
   }
 
 
+  bool may_have_non_1to1 () const
+  {
+    hb_have_non_1to1_context_t c;
+    return dispatch (&c);
+  }
+
   bool apply (hb_ot_apply_context_t *c) const
   bool apply (hb_ot_apply_context_t *c) const
   {
   {
     TRACE_APPLY (this);
     TRACE_APPLY (this);
@@ -1455,10 +1559,6 @@ struct SubstLookup : Lookup
 
 
   static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
   static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
 
-  SubTable& serialize_subtable (hb_serialize_context_t *c,
-				unsigned int i)
-  { return get_subtables<SubTable> ()[i].serialize (c, this); }
-
   bool serialize_single (hb_serialize_context_t *c,
   bool serialize_single (hb_serialize_context_t *c,
 			 uint32_t lookup_props,
 			 uint32_t lookup_props,
 			 hb_sorted_array_t<const HBGlyphID> glyphs,
 			 hb_sorted_array_t<const HBGlyphID> glyphs,
@@ -1466,8 +1566,13 @@ struct SubstLookup : Lookup
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
     if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.
-		  serialize (c, hb_zip (glyphs, substitutes)));
+    if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
+    {
+      c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+      return_trace (true);
+    }
+    c->pop_discard ();
+    return_trace (false);
   }
   }
 
 
   bool serialize_multiple (hb_serialize_context_t *c,
   bool serialize_multiple (hb_serialize_context_t *c,
@@ -1478,11 +1583,17 @@ struct SubstLookup : Lookup
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::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,
-			     substitute_glyphs_list));
+    if (c->push<SubTable> ()->u.multiple.
+        serialize (c,
+                   glyphs,
+                   substitute_len_list,
+                   substitute_glyphs_list))
+    {
+      c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+      return_trace (true);
+    }
+    c->pop_discard ();
+    return_trace (false);
   }
   }
 
 
   bool serialize_alternate (hb_serialize_context_t *c,
   bool serialize_alternate (hb_serialize_context_t *c,
@@ -1493,11 +1604,18 @@ struct SubstLookup : Lookup
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::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,
-			     alternate_glyphs_list));
+
+    if (c->push<SubTable> ()->u.alternate.
+        serialize (c,
+                   glyphs,
+                   alternate_len_list,
+                   alternate_glyphs_list))
+    {
+      c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+      return_trace (true);
+    }
+    c->pop_discard ();
+    return_trace (false);
   }
   }
 
 
   bool serialize_ligature (hb_serialize_context_t *c,
   bool serialize_ligature (hb_serialize_context_t *c,
@@ -1510,24 +1628,32 @@ struct SubstLookup : Lookup
   {
   {
     TRACE_SERIALIZE (this);
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::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,
-			     ligatures_list,
-			     component_count_list,
-			     component_list));
+    if (c->push<SubTable> ()->u.ligature.
+        serialize (c,
+                   first_glyphs,
+                   ligature_per_first_glyph_count_list,
+                   ligatures_list,
+                   component_count_list,
+                   component_list))
+    {
+      c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+      return_trace (true);
+    }
+    c->pop_discard ();
+    return_trace (false);
   }
   }
 
 
   template <typename context_t>
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
   static inline 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 inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
+
+  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
   {
   {
     if (!c->should_visit_lookup (lookup_index))
     if (!c->should_visit_lookup (lookup_index))
       return hb_empty_t ();
       return hb_empty_t ();
 
 
-    hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+    hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
 
 
     /* While in theory we should flush here, it will cause timeouts because a recursive
     /* 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
      * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
@@ -1564,7 +1690,7 @@ struct GSUB : GSUBGPOS
 
 
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
   {
   {
-    hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_features);
+    hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
     return GSUBGPOS::subset<SubstLookup> (&l);
     return GSUBGPOS::subset<SubstLookup> (&l);
   }
   }
 
 
@@ -1600,6 +1726,14 @@ template <typename context_t>
   return l.dispatch (c);
   return l.dispatch (c);
 }
 }
 
 
+/*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
+{
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
+  if (l.may_have_non_1to1 ())
+      hb_set_add_range (covered_seq_indices, seq_index, end_index);
+  return l.dispatch (c);
+}
+
 /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
 /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
 {
 {
   const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
   const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 336 - 104
thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh


+ 16 - 16
thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh

@@ -45,7 +45,7 @@ typedef IndexArray JstfModList;
  * JstfMax -- Justification Maximum Table
  * JstfMax -- Justification Maximum Table
  */
  */
 
 
-typedef OffsetListOf<PosLookup> JstfMax;
+typedef List16OfOffset16To<PosLookup> JstfMax;
 
 
 
 
 /*
 /*
@@ -71,43 +71,43 @@ struct JstfPriority
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageEnableGSUB;	/* Offset to Shrinkage Enable GSUB
 		shrinkageEnableGSUB;	/* Offset to Shrinkage Enable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageDisableGSUB;	/* Offset to Shrinkage Disable GSUB
 		shrinkageDisableGSUB;	/* Offset to Shrinkage Disable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageEnableGPOS;	/* Offset to Shrinkage Enable GPOS
 		shrinkageEnableGPOS;	/* Offset to Shrinkage Enable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageDisableGPOS;	/* Offset to Shrinkage Disable GPOS
 		shrinkageDisableGPOS;	/* Offset to Shrinkage Disable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
+  Offset16To<JstfMax>
 		shrinkageJstfMax;	/* Offset to Shrinkage JstfMax table--
 		shrinkageJstfMax;	/* Offset to Shrinkage JstfMax table--
 					 * from beginning of JstfPriority table
 					 * from beginning of JstfPriority table
 					 * --may be NULL */
 					 * --may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionEnableGSUB;	/* Offset to Extension Enable GSUB
 		extensionEnableGSUB;	/* Offset to Extension Enable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionDisableGSUB;	/* Offset to Extension Disable GSUB
 		extensionDisableGSUB;	/* Offset to Extension Disable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionEnableGPOS;	/* Offset to Extension Enable GPOS
 		extensionEnableGPOS;	/* Offset to Extension Enable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionDisableGPOS;	/* Offset to Extension Disable GPOS
 		extensionDisableGPOS;	/* Offset to Extension Disable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
+  Offset16To<JstfMax>
 		extensionJstfMax;	/* Offset to Extension JstfMax table--
 		extensionJstfMax;	/* Offset to Extension JstfMax table--
 					 * from beginning of JstfPriority table
 					 * from beginning of JstfPriority table
 					 * --may be NULL */
 					 * --may be NULL */
@@ -121,13 +121,13 @@ struct JstfPriority
  * JstfLangSys -- Justification Language System Table
  * JstfLangSys -- Justification Language System Table
  */
  */
 
 
-struct JstfLangSys : OffsetListOf<JstfPriority>
+struct JstfLangSys : List16OfOffset16To<JstfPriority>
 {
 {
   bool sanitize (hb_sanitize_context_t *c,
   bool sanitize (hb_sanitize_context_t *c,
 		 const Record_sanitize_closure_t * = nullptr) const
 		 const Record_sanitize_closure_t * = nullptr) const
   {
   {
     TRACE_SANITIZE (this);
     TRACE_SANITIZE (this);
-    return_trace (OffsetListOf<JstfPriority>::sanitize (c));
+    return_trace (List16OfOffset16To<JstfPriority>::sanitize (c));
   }
   }
 };
 };
 
 
@@ -136,7 +136,7 @@ struct JstfLangSys : OffsetListOf<JstfPriority>
  * ExtenderGlyphs -- Extender Glyph Table
  * ExtenderGlyphs -- Extender Glyph Table
  */
  */
 
 
-typedef SortedArrayOf<HBGlyphID> ExtenderGlyphs;
+typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs;
 
 
 
 
 /*
 /*
@@ -174,10 +174,10 @@ struct JstfScript
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<ExtenderGlyphs>
+  Offset16To<ExtenderGlyphs>
 		extenderGlyphs;	/* Offset to ExtenderGlyph table--from beginning
 		extenderGlyphs;	/* Offset to ExtenderGlyph table--from beginning
 				 * of JstfScript table-may be NULL */
 				 * of JstfScript table-may be NULL */
-  OffsetTo<JstfLangSys>
+  Offset16To<JstfLangSys>
 		defaultLangSys;	/* Offset to DefaultJstfLangSys table--from
 		defaultLangSys;	/* Offset to DefaultJstfLangSys table--from
 				 * beginning of JstfScript table--may be Null */
 				 * beginning of JstfScript table--may be Null */
   RecordArrayOf<JstfLangSys>
   RecordArrayOf<JstfLangSys>

+ 117 - 67
thirdparty/harfbuzz/src/hb-ot-layout.cc

@@ -131,7 +131,9 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
 
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
 
+  if (!buffer->message (font, "start table kern")) return;
   kern.apply (&c);
   kern.apply (&c);
+  (void) buffer->message (font, "end table kern");
 }
 }
 #endif
 #endif
 
 
@@ -144,7 +146,7 @@ bool
 OT::GDEF::is_blocklisted (hb_blob_t *blob,
 OT::GDEF::is_blocklisted (hb_blob_t *blob,
 			  hb_face_t *face) const
 			  hb_face_t *face) const
 {
 {
-#ifdef HB_NO_OT_LAYOUT_BLACKLIST
+#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
   return false;
   return false;
 #endif
 #endif
   /* The ugly business of blocklisting individual fonts' tables happen here!
   /* The ugly business of blocklisting individual fonts' tables happen here!
@@ -331,6 +333,8 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
  *
  *
  * Useful if the client program wishes to cache the list.
  * Useful if the client program wishes to cache the list.
  *
  *
+ * Return value: Total number of attachment points for @glyph.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
 hb_ot_layout_get_attach_points (hb_face_t      *face,
@@ -357,6 +361,8 @@ hb_ot_layout_get_attach_points (hb_face_t      *face,
  * Fetches a list of the caret positions defined for a ligature glyph in the GDEF
  * Fetches a list of the caret positions defined for a ligature glyph in the GDEF
  * table of the font. The list returned will begin at the offset provided.
  * table of the font. The list returned will begin at the offset provided.
  *
  *
+ * Return value: Total number of ligature caret positions for @glyph.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_get_ligature_carets (hb_font_t      *font,
 hb_ot_layout_get_ligature_carets (hb_font_t      *font,
@@ -379,7 +385,7 @@ bool
 OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
 OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face) const
 			  hb_face_t *face) const
 {
 {
-#ifdef HB_NO_OT_LAYOUT_BLACKLIST
+#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
   return false;
   return false;
 #endif
 #endif
   return false;
   return false;
@@ -389,7 +395,7 @@ bool
 OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
 OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face HB_UNUSED) const
 			  hb_face_t *face HB_UNUSED) const
 {
 {
-#ifdef HB_NO_OT_LAYOUT_BLACKLIST
+#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
   return false;
   return false;
 #endif
 #endif
   return false;
   return false;
@@ -419,6 +425,8 @@ get_gsubgpos_table (hb_face_t *face,
  * Fetches a list of all scripts enumerated in the specified face's GSUB table
  * Fetches a list of all scripts enumerated in the specified face's GSUB table
  * or GPOS table. The list returned will begin at the offset provided.
  * or GPOS table. The list returned will begin at the offset provided.
  *
  *
+ * Return value: Total number of script tags.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
@@ -585,6 +593,8 @@ hb_ot_layout_table_select_script (hb_face_t      *face,
  *
  *
  * Fetches a list of all feature tags in the given face's GSUB or GPOS table.
  * Fetches a list of all feature tags in the given face's GSUB or GPOS table.
  *
  *
+ * Return value: Total number of feature tags.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
@@ -647,6 +657,8 @@ hb_ot_layout_table_find_feature (hb_face_t    *face,
  * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath
  * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath
  * the specified script index. The list returned will begin at the offset provided.
  * the specified script index. The list returned will begin at the offset provided.
  *
  *
+ * Return value: Total number of language tags.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
@@ -818,6 +830,8 @@ hb_ot_layout_language_get_required_feature (hb_face_t    *face,
  * Fetches a list of all features in the specified face's GSUB table
  * Fetches a list of all features in the specified face's GSUB table
  * or GPOS table, underneath the specified script and language. The list
  * or GPOS table, underneath the specified script and language. The list
  * returned will begin at the offset provided.
  * returned will begin at the offset provided.
+ *
+ * Return value: Total number of features.
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
@@ -850,6 +864,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
  * or GPOS table, underneath the specified script and language. The list
  * or GPOS table, underneath the specified script and language. The list
  * returned will begin at the offset provided.
  * returned will begin at the offset provided.
  *
  *
+ * Return value: Total number of feature tags.
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
@@ -932,6 +947,8 @@ hb_ot_layout_language_find_feature (hb_face_t    *face,
  * the specified face's GSUB table or GPOS table. The list returned will
  * the specified face's GSUB table or GPOS table. The list returned will
  * begin at the offset provided.
  * begin at the offset provided.
  *
  *
+ * Return value: Total number of lookups.
+ *
  * Since: 0.9.7
  * Since: 0.9.7
  **/
  **/
 unsigned int
 unsigned int
@@ -960,6 +977,8 @@ hb_ot_layout_feature_get_lookups (hb_face_t    *face,
  * Fetches the total number of lookups enumerated in the specified
  * Fetches the total number of lookups enumerated in the specified
  * face's GSUB table or GPOS table.
  * face's GSUB table or GPOS table.
  *
  *
+ * Return value: Total number of lookups.
+ *
  * Since: 0.9.22
  * Since: 0.9.22
  **/
  **/
 unsigned int
 unsigned int
@@ -974,10 +993,46 @@ struct hb_collect_features_context_t
 {
 {
   hb_collect_features_context_t (hb_face_t *face,
   hb_collect_features_context_t (hb_face_t *face,
 				 hb_tag_t   table_tag,
 				 hb_tag_t   table_tag,
-				 hb_set_t  *feature_indexes_)
+				 hb_set_t  *feature_indices_,
+                                 const hb_tag_t *features)
+
     : g (get_gsubgpos_table (face, table_tag)),
     : g (get_gsubgpos_table (face, table_tag)),
-      feature_indexes (feature_indexes_),
-      script_count (0),langsys_count (0), feature_index_count (0) {}
+      feature_indices (feature_indices_),
+      has_feature_filter (false),
+      script_count (0),langsys_count (0), feature_index_count (0)
+  {
+    compute_feature_filter (features);
+  }
+
+  void compute_feature_filter (const hb_tag_t *features)
+  {
+    if (features == nullptr)
+    {
+      has_feature_filter = false;
+      return;
+    }
+
+    has_feature_filter = true;
+    for (; *features; features++)
+    {
+      hb_tag_t tag = *features;
+      unsigned index;
+      g.find_feature_index (tag, &index);
+      if (index == OT::Index::NOT_FOUND_INDEX) continue;
+
+      feature_indices_filter.add(index);
+      for (int i = (int) index - 1; i >= 0; i--)
+      {
+        if (g.get_feature_tag (i) != tag) break;
+        feature_indices_filter.add(i);
+      }
+      for (unsigned i = index + 1; i < g.get_feature_count (); i++)
+      {
+        if (g.get_feature_tag (i) != tag) break;
+        feature_indices_filter.add(i);
+      }
+    }
+  }
 
 
   bool visited (const OT::Script &s)
   bool visited (const OT::Script &s)
   {
   {
@@ -1026,7 +1081,9 @@ struct hb_collect_features_context_t
 
 
   public:
   public:
   const OT::GSUBGPOS &g;
   const OT::GSUBGPOS &g;
-  hb_set_t           *feature_indexes;
+  hb_set_t *feature_indices;
+  hb_set_t  feature_indices_filter;
+  bool has_feature_filter;
 
 
   private:
   private:
   hb_set_t visited_script;
   hb_set_t visited_script;
@@ -1038,37 +1095,31 @@ struct hb_collect_features_context_t
 
 
 static void
 static void
 langsys_collect_features (hb_collect_features_context_t *c,
 langsys_collect_features (hb_collect_features_context_t *c,
-			  const OT::LangSys  &l,
-			  const hb_tag_t     *features)
+			  const OT::LangSys  &l)
 {
 {
   if (c->visited (l)) return;
   if (c->visited (l)) return;
 
 
-  if (!features)
+  if (!c->has_feature_filter)
   {
   {
     /* All features. */
     /* All features. */
     if (l.has_required_feature () && !c->visited_feature_indices (1))
     if (l.has_required_feature () && !c->visited_feature_indices (1))
-      c->feature_indexes->add (l.get_required_feature_index ());
+      c->feature_indices->add (l.get_required_feature_index ());
 
 
+    // TODO(garretrieger): filter out indices >= feature count?
     if (!c->visited_feature_indices (l.featureIndex.len))
     if (!c->visited_feature_indices (l.featureIndex.len))
-      l.add_feature_indexes_to (c->feature_indexes);
+      l.add_feature_indexes_to (c->feature_indices);
   }
   }
   else
   else
   {
   {
-    /* Ugh. Any faster way? */
-    for (; *features; features++)
+    if (c->feature_indices_filter.is_empty()) return;
+    unsigned int num_features = l.get_feature_count ();
+    for (unsigned int i = 0; i < num_features; i++)
     {
     {
-      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);
+      unsigned int feature_index = l.get_feature_index (i);
+      if (!c->feature_indices_filter.has (feature_index)) continue;
 
 
-	if (feature_tag == c->g.get_feature_tag (feature_index))
-	{
-	  c->feature_indexes->add (feature_index);
-	  break;
-	}
-      }
+      c->feature_indices->add (feature_index);
+      c->feature_indices_filter.del (feature_index);
     }
     }
   }
   }
 }
 }
@@ -1076,8 +1127,7 @@ langsys_collect_features (hb_collect_features_context_t *c,
 static void
 static void
 script_collect_features (hb_collect_features_context_t *c,
 script_collect_features (hb_collect_features_context_t *c,
 			 const OT::Script   &s,
 			 const OT::Script   &s,
-			 const hb_tag_t *languages,
-			 const hb_tag_t *features)
+			 const hb_tag_t *languages)
 {
 {
   if (c->visited (s)) return;
   if (c->visited (s)) return;
 
 
@@ -1086,14 +1136,13 @@ script_collect_features (hb_collect_features_context_t *c,
     /* All languages. */
     /* All languages. */
     if (s.has_default_lang_sys ())
     if (s.has_default_lang_sys ())
       langsys_collect_features (c,
       langsys_collect_features (c,
-				s.get_default_lang_sys (),
-				features);
+				s.get_default_lang_sys ());
+
 
 
     unsigned int count = s.get_lang_sys_count ();
     unsigned int count = s.get_lang_sys_count ();
     for (unsigned int language_index = 0; language_index < count; language_index++)
     for (unsigned int language_index = 0; language_index < count; language_index++)
       langsys_collect_features (c,
       langsys_collect_features (c,
-				s.get_lang_sys (language_index),
-				features);
+				s.get_lang_sys (language_index));
   }
   }
   else
   else
   {
   {
@@ -1102,8 +1151,8 @@ script_collect_features (hb_collect_features_context_t *c,
       unsigned int language_index;
       unsigned int language_index;
       if (s.find_lang_sys_index (*languages, &language_index))
       if (s.find_lang_sys_index (*languages, &language_index))
 	langsys_collect_features (c,
 	langsys_collect_features (c,
-				  s.get_lang_sys (language_index),
-				  features);
+				  s.get_lang_sys (language_index));
+
     }
     }
   }
   }
 }
 }
@@ -1134,7 +1183,7 @@ hb_ot_layout_collect_features (hb_face_t      *face,
 			       const hb_tag_t *features,
 			       const hb_tag_t *features,
 			       hb_set_t       *feature_indexes /* OUT */)
 			       hb_set_t       *feature_indexes /* OUT */)
 {
 {
-  hb_collect_features_context_t c (face, table_tag, feature_indexes);
+  hb_collect_features_context_t c (face, table_tag, feature_indexes, features);
   if (!scripts)
   if (!scripts)
   {
   {
     /* All scripts. */
     /* All scripts. */
@@ -1142,8 +1191,7 @@ hb_ot_layout_collect_features (hb_face_t      *face,
     for (unsigned int script_index = 0; script_index < count; script_index++)
     for (unsigned int script_index = 0; script_index < count; script_index++)
       script_collect_features (&c,
       script_collect_features (&c,
 			       c.g.get_script (script_index),
 			       c.g.get_script (script_index),
-			       languages,
-			       features);
+			       languages);
   }
   }
   else
   else
   {
   {
@@ -1153,8 +1201,7 @@ hb_ot_layout_collect_features (hb_face_t      *face,
       if (c.g.find_script_index (*scripts, &script_index))
       if (c.g.find_script_index (*scripts, &script_index))
 	script_collect_features (&c,
 	script_collect_features (&c,
 				 c.g.get_script (script_index),
 				 c.g.get_script (script_index),
-				 languages,
-				 features);
+				 languages);
     }
     }
   }
   }
 }
 }
@@ -1262,6 +1309,8 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
  * Fetches a list of feature variations in the specified face's GSUB table
  * Fetches a list of feature variations in the specified face's GSUB table
  * or GPOS table, at the specified variation coordinates.
  * or GPOS table, at the specified variation coordinates.
  *
  *
+ * Return value: %true if feature variations were found, %false otherwise.
+ *
  **/
  **/
 hb_bool_t
 hb_bool_t
 hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
 hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
@@ -1291,6 +1340,8 @@ hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
  * the specified face's GSUB table or GPOS table, enabled at the specified
  * the specified face's GSUB table or GPOS table, enabled at the specified
  * variations index. The list returned will begin at the offset provided.
  * variations index. The list returned will begin at the offset provided.
  *
  *
+ * Return value: Total number of lookups.
+ *
  **/
  **/
 unsigned int
 unsigned int
 hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
 hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
@@ -1337,7 +1388,8 @@ hb_ot_layout_has_substitution (hb_face_t *face)
  * @lookup_index: The index of the lookup to query
  * @lookup_index: The index of the lookup to query
  * @glyphs: The sequence of glyphs to query for substitution
  * @glyphs: The sequence of glyphs to query for substitution
  * @glyphs_length: The length of the glyph sequence
  * @glyphs_length: The length of the glyph sequence
- * @zero_context: #hb_bool_t indicating whether substitutions should be context-free
+ * @zero_context: #hb_bool_t indicating whether pre-/post-context are disallowed
+ * in substitutions
  *
  *
  * Tests whether a specified lookup in the specified face would
  * Tests whether a specified lookup in the specified face would
  * trigger a substitution on the given glyph sequence.
  * trigger a substitution on the given glyph sequence.
@@ -1443,12 +1495,17 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
 					unsigned int  lookup_index,
 					unsigned int  lookup_index,
 					hb_set_t     *glyphs /* OUT */)
 					hb_set_t     *glyphs /* OUT */)
 {
 {
-  hb_map_t done_lookups;
-  OT::hb_closure_context_t c (face, glyphs, &done_lookups);
+  hb_set_t cur_intersected_glyphs;
+  hb_map_t done_lookups_glyph_count;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
+  OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
 
 
   const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
   const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
 
   l.closure (&c, lookup_index);
   l.closure (&c, lookup_index);
+
+  for (auto _ : done_lookups_glyph_set.iter ())
+    hb_set_destroy (_.second);
 }
 }
 
 
 /**
 /**
@@ -1467,8 +1524,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
 					 const hb_set_t *lookups,
 					 const hb_set_t *lookups,
 					 hb_set_t       *glyphs /* OUT */)
 					 hb_set_t       *glyphs /* OUT */)
 {
 {
-  hb_map_t done_lookups;
-  OT::hb_closure_context_t c (face, glyphs, &done_lookups);
+  hb_set_t cur_intersected_glyphs;
+  hb_map_t done_lookups_glyph_count;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
+  OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
   const OT::GSUB& gsub = *face->table.GSUB->table;
   const OT::GSUB& gsub = *face->table.GSUB->table;
 
 
   unsigned int iteration_count = 0;
   unsigned int iteration_count = 0;
@@ -1488,6 +1547,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
     }
     }
   } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
   } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
 	   glyphs_length != glyphs->get_population ());
 	   glyphs_length != glyphs->get_population ());
+
+  for (auto _ : done_lookups_glyph_set.iter ())
+    hb_set_destroy (_.second);
 }
 }
 
 
 /*
 /*
@@ -1824,27 +1886,20 @@ apply_string (OT::hb_ot_apply_context_t *c,
   if (likely (!lookup.is_reverse ()))
   if (likely (!lookup.is_reverse ()))
   {
   {
     /* in/out forward substitution/positioning */
     /* in/out forward substitution/positioning */
-    if (Proxy::table_index == 0u)
+    if (!Proxy::inplace)
       buffer->clear_output ();
       buffer->clear_output ();
+
     buffer->idx = 0;
     buffer->idx = 0;
+    apply_forward (c, accel);
 
 
-    bool ret;
-    ret = apply_forward (c, accel);
-    if (ret)
-    {
-      if (!Proxy::inplace)
-	buffer->swap_buffers ();
-      else
-	assert (!buffer->has_separate_output ());
-    }
+    if (!Proxy::inplace)
+      buffer->swap_buffers ();
   }
   }
   else
   else
   {
   {
     /* in-place backward substitution/positioning */
     /* in-place backward substitution/positioning */
-    if (Proxy::table_index == 0u)
-      buffer->remove_output ();
+    assert (!buffer->have_output);
     buffer->idx = buffer->len - 1;
     buffer->idx = buffer->len - 1;
-
     apply_backward (c, accel);
     apply_backward (c, accel);
   }
   }
 }
 }
@@ -1860,7 +1915,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
   OT::hb_ot_apply_context_t c (table_index, font, buffer);
   OT::hb_ot_apply_context_t c (table_index, font, buffer);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
 
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].length; 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];
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     for (; i < stage->last_lookup; i++)
     {
     {
@@ -1870,11 +1926,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
       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 ();
-      }
+      c.set_random (lookups[table_index][i].random);
+
       apply_string<Proxy> (&c,
       apply_string<Proxy> (&c,
 			   proxy.table.get_lookup (lookup_index),
 			   proxy.table.get_lookup (lookup_index),
 			   proxy.accels[lookup_index]);
 			   proxy.accels[lookup_index]);
@@ -1882,10 +1935,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
     }
     }
 
 
     if (stage->pause_func)
     if (stage->pause_func)
-    {
-      buffer->clear_output ();
       stage->pause_func (plan, font, buffer);
       stage->pause_func (plan, font, buffer);
-    }
   }
   }
 }
 }
 
 
@@ -1925,7 +1975,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
  *
  *
  * Fetches a baseline value from the face.
  * Fetches a baseline value from the face.
  *
  *
- * Return value: if found baseline value in the font.
+ * Return value: %true if found baseline value in the font.
  *
  *
  * Since: 2.6.0
  * Since: 2.6.0
  **/
  **/
@@ -1984,7 +2034,7 @@ struct hb_get_glyph_alternates_dispatch_t :
  *
  *
  * Fetches alternates of a glyph from a given GSUB lookup index.
  * Fetches alternates of a glyph from a given GSUB lookup index.
  *
  *
- * Return value: total number of alternates found in the specific lookup index for the given glyph id.
+ * Return value: Total number of alternates found in the specific lookup index for the given glyph id.
  *
  *
  * Since: 2.6.8
  * Since: 2.6.8
  **/
  **/

+ 1 - 2
thirdparty/harfbuzz/src/hb-ot-layout.hh

@@ -314,7 +314,6 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
 	 hb_unicode_funcs_t::NOT_SPACE;
 	 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_substituted (const hb_glyph_info_t *info);
 static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
 
 
 static inline bool
 static inline bool
@@ -328,7 +327,7 @@ _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))
   return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
 	  == UPROPS_MASK_IGNORABLE) &&
 	  == UPROPS_MASK_IGNORABLE) &&
-	 !_hb_glyph_info_ligated (info);
+	 !_hb_glyph_info_substituted (info);
 }
 }
 static inline void
 static inline void
 _hb_glyph_info_unhide (hb_glyph_info_t *info)
 _hb_glyph_info_unhide (hb_glyph_info_t *info)

+ 25 - 11
thirdparty/harfbuzz/src/hb-ot-map.cc

@@ -54,7 +54,6 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
   face = face_;
   face = face_;
   props = *props_;
   props = *props_;
 
 
-
   /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
   /* 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. */
    * features not available in either table and not waste precious bits for them. */
 
 
@@ -63,12 +62,28 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
   hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
   hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
   hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
   hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
 
 
-  hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
+  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++) {
+  for (unsigned int table_index = 0; table_index < 2; table_index++)
+  {
     hb_tag_t table_tag = table_tags[table_index];
     hb_tag_t table_tag = table_tags[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]);
+    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]);
   }
   }
 }
 }
 
 
@@ -150,9 +165,8 @@ void
 hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
 hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
 			      const hb_ot_shape_plan_key_t &key)
 			      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 = 8 * sizeof (hb_mask_t) - 1;
+  unsigned int global_bit_mask = 1u << global_bit_shift;
 
 
   m.global_mask = global_bit_mask;
   m.global_mask = global_bit_mask;
 
 
@@ -205,7 +219,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
 
 
 
 
   /* Allocate bits now */
   /* Allocate bits now */
-  unsigned int next_bit = global_bit_shift + 1;
+  static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
+  unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
 
 
   for (unsigned int i = 0; i < feature_infos.length; i++)
   for (unsigned int i = 0; i < feature_infos.length; i++)
   {
   {
@@ -220,7 +235,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
       /* Limit bits per feature. */
       /* Limit bits per feature. */
       bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
       bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
 
 
-    if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
+    if (!info->max_value || next_bit + bits_needed >= global_bit_shift)
       continue; /* Feature disabled, or not enough bits. */
       continue; /* Feature disabled, or not enough bits. */
 
 
 
 
@@ -274,7 +289,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
     }
     }
     map->_1_mask = (1u << map->shift) & map->mask;
     map->_1_mask = (1u << map->shift) & map->mask;
     map->needs_fallback = !found;
     map->needs_fallback = !found;
-
   }
   }
   feature_infos.shrink (0); /* Done with these */
   feature_infos.shrink (0); /* Done with these */
 
 

+ 22 - 22
thirdparty/harfbuzz/src/hb-ot-math-table.hh

@@ -49,7 +49,7 @@ struct MathValueRecord
 
 
   protected:
   protected:
   HBINT16		value;		/* The X or Y value in design units */
   HBINT16		value;		/* The X or Y value in design units */
-  OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
+  Offset16To<Device>	deviceTable;	/* Offset to the device table - from the
 					 * beginning of parent table.  May be NULL.
 					 * beginning of parent table.  May be NULL.
 					 * Suggested format for device table is 1. */
 					 * Suggested format for device table is 1. */
 
 
@@ -181,11 +181,11 @@ struct MathItalicsCorrectionInfo
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
+  Offset16To<Coverage>       coverage;		/* Offset to Coverage table -
 						 * from the beginning of
 						 * from the beginning of
 						 * MathItalicsCorrectionInfo
 						 * MathItalicsCorrectionInfo
 						 * table. */
 						 * table. */
-  ArrayOf<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
+  Array16Of<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
 						 * defining italics correction
 						 * defining italics correction
 						 * values for each
 						 * values for each
 						 * covered glyph. */
 						 * covered glyph. */
@@ -214,11 +214,11 @@ struct MathTopAccentAttachment
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+  Offset16To<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
 						 * from the beginning of
 						 * from the beginning of
 						 * MathTopAccentAttachment
 						 * MathTopAccentAttachment
 						 * table. */
 						 * table. */
-  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+  Array16Of<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
 						 * defining top accent
 						 * defining top accent
 						 * attachment points for each
 						 * attachment points for each
 						 * covered glyph. */
 						 * covered glyph. */
@@ -320,7 +320,7 @@ struct MathKernInfoRecord
   protected:
   protected:
   /* Offset to MathKern table for each corner -
   /* Offset to MathKern table for each corner -
    * from the beginning of MathKernInfo table.  May be NULL. */
    * from the beginning of MathKernInfo table.  May be NULL. */
-  OffsetTo<MathKern> mathKern[4];
+  Offset16To<MathKern> mathKern[4];
 
 
   public:
   public:
   DEFINE_SIZE_STATIC (8);
   DEFINE_SIZE_STATIC (8);
@@ -346,12 +346,12 @@ struct MathKernInfo
   }
   }
 
 
   protected:
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		mathKernCoverage;
 		mathKernCoverage;
 				/* Offset to Coverage table -
 				/* Offset to Coverage table -
 				 * from the beginning of the
 				 * from the beginning of the
 				 * MathKernInfo table. */
 				 * MathKernInfo table. */
-  ArrayOf<MathKernInfoRecord>
+  Array16Of<MathKernInfoRecord>
 		mathKernInfoRecords;
 		mathKernInfoRecords;
 				/* Array of MathKernInfoRecords,
 				/* Array of MathKernInfoRecords,
 				 * per-glyph information for
 				 * per-glyph information for
@@ -395,22 +395,22 @@ struct MathGlyphInfo
   protected:
   protected:
   /* Offset to MathItalicsCorrectionInfo table -
   /* Offset to MathItalicsCorrectionInfo table -
    * from the beginning of MathGlyphInfo table. */
    * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+  Offset16To<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
 
 
   /* Offset to MathTopAccentAttachment table -
   /* Offset to MathTopAccentAttachment table -
    * from the beginning of MathGlyphInfo table. */
    * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+  Offset16To<MathTopAccentAttachment> mathTopAccentAttachment;
 
 
   /* Offset to coverage table for Extended Shape glyphs -
   /* Offset to coverage table for Extended Shape glyphs -
    * from the beginning of MathGlyphInfo table. When the left or right glyph of
    * 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
    * 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
    * position defined by values in MathConstants table) should be used for
    * vertical positioning purposes.  May be NULL.. */
    * vertical positioning purposes.  May be NULL.. */
-  OffsetTo<Coverage> extendedShapeCoverage;
+  Offset16To<Coverage> extendedShapeCoverage;
 
 
    /* Offset to MathKernInfo table -
    /* Offset to MathKernInfo table -
     * from the beginning of MathGlyphInfo table. */
     * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathKernInfo> mathKernInfo;
+  Offset16To<MathKernInfo> mathKernInfo;
 
 
   public:
   public:
   DEFINE_SIZE_STATIC (8);
   DEFINE_SIZE_STATIC (8);
@@ -532,7 +532,7 @@ struct MathGlyphAssembly
 				/* Italics correction of this
 				/* Italics correction of this
 				 * MathGlyphAssembly. Should not
 				 * MathGlyphAssembly. Should not
 				 * depend on the assembly size. */
 				 * depend on the assembly size. */
-  ArrayOf<MathGlyphPartRecord>
+  Array16Of<MathGlyphPartRecord>
 		partRecords;	/* Array of part records, from
 		partRecords;	/* Array of part records, from
 				 * left to right and bottom to
 				 * left to right and bottom to
 				 * top. */
 				 * top. */
@@ -572,10 +572,10 @@ struct MathGlyphConstruction
   protected:
   protected:
   /* Offset to MathGlyphAssembly table for this shape - from the beginning of
   /* Offset to MathGlyphAssembly table for this shape - from the beginning of
      MathGlyphConstruction table.  May be NULL. */
      MathGlyphConstruction table.  May be NULL. */
-  OffsetTo<MathGlyphAssembly>	  glyphAssembly;
+  Offset16To<MathGlyphAssembly>	  glyphAssembly;
 
 
   /* MathGlyphVariantRecords for alternative variants of the glyphs. */
   /* MathGlyphVariantRecords for alternative variants of the glyphs. */
-  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+  Array16Of<MathGlyphVariantRecord> mathGlyphVariantRecord;
 
 
   public:
   public:
   DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
   DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
@@ -636,7 +636,7 @@ struct MathVariants
   {
   {
     bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
     unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
-    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+    const Offset16To<Coverage> &coverage = vertical ? vertGlyphCoverage
 						  : horizGlyphCoverage;
 						  : horizGlyphCoverage;
 
 
     unsigned int index = (this+coverage).get_coverage (glyph);
     unsigned int index = (this+coverage).get_coverage (glyph);
@@ -653,11 +653,11 @@ struct MathVariants
 				/* Minimum overlap of connecting
 				/* Minimum overlap of connecting
 				 * glyphs during glyph construction,
 				 * glyphs during glyph construction,
 				 * in design units. */
 				 * in design units. */
-  OffsetTo<Coverage> vertGlyphCoverage;
+  Offset16To<Coverage> vertGlyphCoverage;
 				/* Offset to Coverage table -
 				/* Offset to Coverage table -
 				 * from the beginning of MathVariants
 				 * from the beginning of MathVariants
 				 * table. */
 				 * table. */
-  OffsetTo<Coverage> horizGlyphCoverage;
+  Offset16To<Coverage> horizGlyphCoverage;
 				/* Offset to Coverage table -
 				/* Offset to Coverage table -
 				 * from the beginning of MathVariants
 				 * from the beginning of MathVariants
 				 * table. */
 				 * table. */
@@ -671,7 +671,7 @@ struct MathVariants
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
      direction. */
-  UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
+  UnsizedArrayOf<Offset16To<MathGlyphConstruction>>
 			glyphConstruction;
 			glyphConstruction;
 
 
   public:
   public:
@@ -711,11 +711,11 @@ struct MATH
   protected:
   protected:
   FixedVersion<>version;	/* Version of the MATH table
   FixedVersion<>version;	/* Version of the MATH table
 				 * initially set to 0x00010000u */
 				 * initially set to 0x00010000u */
-  OffsetTo<MathConstants>
+  Offset16To<MathConstants>
 		mathConstants;	/* MathConstants table */
 		mathConstants;	/* MathConstants table */
-  OffsetTo<MathGlyphInfo>
+  Offset16To<MathGlyphInfo>
 		mathGlyphInfo;	/* MathGlyphInfo table */
 		mathGlyphInfo;	/* MathGlyphInfo table */
-  OffsetTo<MathVariants>
+  Offset16To<MathVariants>
 		mathVariants;	/* MathVariants table */
 		mathVariants;	/* MathVariants table */
 
 
   public:
   public:

+ 1 - 1
thirdparty/harfbuzz/src/hb-ot-maxp-table.hh

@@ -107,7 +107,7 @@ struct maxp
       maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
       maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
       if (unlikely (!dest_v1)) return_trace (false);
       if (unlikely (!dest_v1)) return_trace (false);
 
 
-      if (c->plan->drop_hints)
+      if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
 	drop_hint_fields (dest_v1);
 	drop_hint_fields (dest_v1);
     }
     }
 
 

+ 2 - 2
thirdparty/harfbuzz/src/hb-ot-meta-table.hh

@@ -56,7 +56,7 @@ struct DataMap
 
 
   protected:
   protected:
   Tag		tag;		/* A tag indicating the type of metadata. */
   Tag		tag;		/* A tag indicating the type of metadata. */
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		dataZ;		/* Offset in bytes from the beginning of the
 		dataZ;		/* Offset in bytes from the beginning of the
 				 * metadata table to the data for this tag. */
 				 * metadata table to the data for this tag. */
   HBUINT32	dataLength;	/* Length of the data. The data is not required to
   HBUINT32	dataLength;	/* Length of the data. The data is not required to
@@ -113,7 +113,7 @@ struct meta
 				 * Offset from the beginning of the table to the data.
 				 * Offset from the beginning of the table to the data.
 				 * Per OT specification:
 				 * Per OT specification:
 				 * Reserved. Not used; should be set to 0. */
 				 * Reserved. Not used; should be set to 0. */
-  LArrayOf<DataMap>
+  Array32Of<DataMap>
 		dataMaps;/* Array of data map records. */
 		dataMaps;/* Array of data map records. */
   public:
   public:
   DEFINE_SIZE_ARRAY (16, dataMaps);
   DEFINE_SIZE_ARRAY (16, dataMaps);

+ 11 - 6
thirdparty/harfbuzz/src/hb-ot-name-table.hh

@@ -149,7 +149,7 @@ struct NameRecord
   HBUINT16	languageID;	/* Language ID. */
   HBUINT16	languageID;	/* Language ID. */
   HBUINT16	nameID;		/* Name ID. */
   HBUINT16	nameID;		/* Name ID. */
   HBUINT16	length;		/* String length (in bytes). */
   HBUINT16	length;		/* String length (in bytes). */
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		offset;		/* String offset from start of storage area (in bytes). */
 		offset;		/* String offset from start of storage area (in bytes). */
   public:
   public:
   DEFINE_SIZE_STATIC (12);
   DEFINE_SIZE_STATIC (12);
@@ -214,7 +214,7 @@ struct name
     this->format = 0;
     this->format = 0;
     this->count = it.len ();
     this->count = it.len ();
 
 
-    NameRecord *name_records = (NameRecord *) calloc (it.len (), NameRecord::static_size);
+    NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size);
     if (unlikely (!name_records)) return_trace (false);
     if (unlikely (!name_records)) return_trace (false);
 
 
     hb_array_t<NameRecord> records (name_records, it.len ());
     hb_array_t<NameRecord> records (name_records, it.len ());
@@ -228,9 +228,10 @@ struct name
     records.qsort ();
     records.qsort ();
 
 
     c->copy_all (records, src_string_pool);
     c->copy_all (records, src_string_pool);
-    free (records.arrayZ);
+    hb_free (records.arrayZ);
 
 
-    if (unlikely (c->ran_out_of_room)) return_trace (false);
+
+    if (unlikely (c->ran_out_of_room ())) return_trace (false);
 
 
     this->stringOffset = c->length ();
     this->stringOffset = c->length ();
 
 
@@ -248,7 +249,11 @@ struct name
     + nameRecordZ.as_array (count)
     + nameRecordZ.as_array (count)
     | hb_filter (c->plan->name_ids, &NameRecord::nameID)
     | hb_filter (c->plan->name_ids, &NameRecord::nameID)
     | hb_filter (c->plan->name_languages, &NameRecord::languageID)
     | hb_filter (c->plan->name_languages, &NameRecord::languageID)
-    | hb_filter ([&] (const NameRecord& namerecord) { return c->plan->name_legacy || namerecord.isUnicode (); })
+    | hb_filter ([&] (const NameRecord& namerecord) {
+      return
+          (c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
+          || namerecord.isUnicode ();
+    })
     ;
     ;
 
 
     name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
     name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
@@ -357,7 +362,7 @@ struct name
   /* We only implement format 0 for now. */
   /* We only implement format 0 for now. */
   HBUINT16	format;		/* Format selector (=0/1). */
   HBUINT16	format;		/* Format selector (=0/1). */
   HBUINT16	count;		/* Number of name records. */
   HBUINT16	count;		/* Number of name records. */
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		stringOffset;	/* Offset to start of string storage (from start of table). */
 		stringOffset;	/* Offset to start of string storage (from start of table). */
   UnsizedArrayOf<NameRecord>
   UnsizedArrayOf<NameRecord>
 		nameRecordZ;	/* The name records where count is the number of records. */
 		nameRecordZ;	/* The name records where count is the number of records. */

+ 6 - 3
thirdparty/harfbuzz/src/hb-ot-name.cc

@@ -156,7 +156,8 @@ hb_ot_name_get_utf (hb_face_t       *face,
  *
  *
  * Fetches a font name from the OpenType 'name' table.
  * Fetches a font name from the OpenType 'name' table.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
- * Returns string in UTF-8 encoding.
+ * Returns string in UTF-8 encoding. A NUL terminator is always written
+ * for convenience, and isn't included in the output @text_size.
  *
  *
  * Returns: full length of the requested string, or 0 if not found.
  * Returns: full length of the requested string, or 0 if not found.
  * Since: 2.1.0
  * Since: 2.1.0
@@ -183,7 +184,8 @@ hb_ot_name_get_utf8 (hb_face_t       *face,
  *
  *
  * Fetches a font name from the OpenType 'name' table.
  * Fetches a font name from the OpenType 'name' table.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
- * Returns string in UTF-16 encoding.
+ * Returns string in UTF-16 encoding. A NUL terminator is always written
+ * for convenience, and isn't included in the output @text_size.
  *
  *
  * Returns: full length of the requested string, or 0 if not found.
  * Returns: full length of the requested string, or 0 if not found.
  * Since: 2.1.0
  * Since: 2.1.0
@@ -209,7 +211,8 @@ hb_ot_name_get_utf16 (hb_face_t       *face,
  *
  *
  * Fetches a font name from the OpenType 'name' table.
  * Fetches a font name from the OpenType 'name' table.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
  * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
- * Returns string in UTF-32 encoding.
+ * Returns string in UTF-32 encoding. A NUL terminator is always written
+ * for convenience, and isn't included in the output @text_size.
  *
  *
  * Returns: full length of the requested string, or 0 if not found.
  * Returns: full length of the requested string, or 0 if not found.
  * Since: 2.1.0
  * Since: 2.1.0

+ 4 - 21
thirdparty/harfbuzz/src/hb-ot-os2-table.hh

@@ -30,7 +30,6 @@
 
 
 #include "hb-open-type.hh"
 #include "hb-open-type.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
-#include "hb-ot-cmap-table.hh"
 
 
 #include "hb-set.hh"
 #include "hb-set.hh"
 
 
@@ -172,33 +171,17 @@ struct OS2
     TRACE_SUBSET (this);
     TRACE_SUBSET (this);
     OS2 *os2_prime = c->serializer->embed (this);
     OS2 *os2_prime = c->serializer->embed (this);
     if (unlikely (!os2_prime)) return_trace (false);
     if (unlikely (!os2_prime)) return_trace (false);
+    if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
+      return_trace (true);
 
 
-    hb_set_t unicodes;
-    if (!c->plan->glyphs_requested->is_empty ())
-    {
-      hb_map_t unicode_glyphid_map;
-
-      OT::cmap::accelerator_t cmap;
-      cmap.init (c->plan->source);
-      cmap.collect_mapping (&unicodes, &unicode_glyphid_map);
-      cmap.fini ();
-
-      hb_set_set (&unicodes, c->plan->unicodes);
-
-      + unicode_glyphid_map.iter ()
-      | hb_filter (c->plan->glyphs_requested, hb_second)
-      | hb_map (hb_first)
-      | hb_sink (unicodes)
-      ;
-    }
     /* when --gids option is not used, no need to do collect_mapping that is
     /* when --gids option is not used, no need to do collect_mapping that is
        * iterating all codepoints in each subtable, which is not efficient */
        * iterating all codepoints in each subtable, which is not efficient */
     uint16_t min_cp, max_cp;
     uint16_t min_cp, max_cp;
-    find_min_and_max_codepoint (unicodes.is_empty () ? c->plan->unicodes : &unicodes, &min_cp, &max_cp);
+    find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
     os2_prime->usFirstCharIndex = min_cp;
     os2_prime->usFirstCharIndex = min_cp;
     os2_prime->usLastCharIndex = max_cp;
     os2_prime->usLastCharIndex = max_cp;
 
 
-    _update_unicode_ranges (unicodes.is_empty () ? c->plan->unicodes : &unicodes, os2_prime->ulUnicodeRange);
+    _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
 
 
     return_trace (true);
     return_trace (true);
   }
   }

+ 130 - 0
thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh

@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2021  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.
+ *
+ */
+
+#ifndef HB_OT_POST_TABLE_V2SUBSET_HH
+#define HB_OT_POST_TABLE_V2SUBSET_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-post-table.hh"
+
+/*
+ * post -- PostScript
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/post
+ */
+
+namespace OT {
+template<typename Iterator>
+HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
+                                        Iterator it,
+                                        const void* _post) const
+{
+  TRACE_SERIALIZE (this);
+  auto *out = c->start_embed (this);
+  if (unlikely (!c->check_success (out))) return_trace (false);
+  if (!out->glyphNameIndex.serialize (c, + it
+                                         | hb_map (hb_second)))
+      return_trace (false);
+
+  hb_set_t copied_indices;
+  for (const auto& _ : + it )
+  {
+    unsigned glyph_id = _.first;
+    unsigned new_index = _.second;
+    
+    if (new_index < 258) continue;
+    if (copied_indices.has (new_index)) continue;
+    copied_indices.add (new_index);
+    
+    hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
+    HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
+    if (unlikely (!o)) return_trace (false);
+    if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+    memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
+  }
+
+  return_trace (true);
+}
+
+HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
+{
+  TRACE_SUBSET (this);
+
+  const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
+  unsigned num_glyphs = c->plan->num_output_glyphs ();
+  hb_map_t old_new_index_map, old_gid_new_index_map;
+  unsigned i = 0;
+
+  post::accelerator_t _post;
+  _post.init (c->plan->source);
+
+  for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
+  {
+    hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
+    unsigned old_index = glyphNameIndex[old_gid];
+
+    unsigned new_index;
+    if (old_index <= 257) new_index = old_index;
+    else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
+    else
+    {
+      hb_bytes_t s = _post.find_glyph_name (old_gid);
+      int standard_glyph_index = -1;
+      for (unsigned i = 0; i < format1_names_length; i++)
+      {
+        if (s == format1_names (i))
+        {
+          standard_glyph_index = i;
+          break;
+        }
+      }
+      if (standard_glyph_index == -1)
+      {
+        new_index = 258 + i;
+        i++;
+      }
+      else
+      { new_index = standard_glyph_index; }
+      old_new_index_map.set (old_index, new_index);
+    }
+    old_gid_new_index_map.set (old_gid, new_index);
+  }
+
+  auto index_iter =
+  + hb_range (num_glyphs)
+  | hb_map (reverse_glyph_map)
+  | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
+                            {
+                              unsigned new_index = old_gid_new_index_map.get (old_gid);
+                              return hb_pair_t<unsigned, unsigned> (old_gid, new_index);
+                            })
+  ;
+
+  bool ret = serialize (c->serializer, index_iter, &_post);
+  _post.fini ();
+  return_trace (ret);
+}
+
+} /* namespace OT */
+#endif /* HB_OT_POST_TABLE_V2SUBSET_HH */

+ 27 - 9
thirdparty/harfbuzz/src/hb-ot-post-table.hh

@@ -55,8 +55,15 @@ struct postV2Tail
     return_trace (glyphNameIndex.sanitize (c));
     return_trace (glyphNameIndex.sanitize (c));
   }
   }
 
 
+  template<typename Iterator>
+  bool serialize (hb_serialize_context_t *c,
+                  Iterator it,
+                  const void* _post) const;
+
+  bool subset (hb_subset_context_t *c) const;
+
   protected:
   protected:
-  ArrayOf<HBUINT16>	glyphNameIndex;	/* This is not an offset, but is the
+  Array16Of<HBUINT16>	glyphNameIndex;	/* This is not an offset, but is the
 					 * ordinal number of the glyph in 'post'
 					 * ordinal number of the glyph in 'post'
 					 * string tables. */
 					 * string tables. */
 /*UnsizedArrayOf<HBUINT8>
 /*UnsizedArrayOf<HBUINT8>
@@ -71,13 +78,18 @@ struct post
 {
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
   static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
 
 
-  void serialize (hb_serialize_context_t *c) const
+  bool serialize (hb_serialize_context_t *c, bool glyph_names) const
   {
   {
+    TRACE_SERIALIZE (this);
     post *post_prime = c->allocate_min<post> ();
     post *post_prime = c->allocate_min<post> ();
-    if (unlikely (!post_prime))  return;
+    if (unlikely (!post_prime))  return_trace (false);
 
 
     memcpy (post_prime, this, post::min_size);
     memcpy (post_prime, this, post::min_size);
-    post_prime->version.major = 3; // Version 3 does not have any glyph names.
+    if (!glyph_names)
+      return_trace (c->check_assign (post_prime->version.major, 3,
+                                     HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
+
+    return_trace (true);
   }
   }
 
 
   bool subset (hb_subset_context_t *c) const
   bool subset (hb_subset_context_t *c) const
@@ -86,13 +98,19 @@ struct post
     post *post_prime = c->serializer->start_embed<post> ();
     post *post_prime = c->serializer->start_embed<post> ();
     if (unlikely (!post_prime)) return_trace (false);
     if (unlikely (!post_prime)) return_trace (false);
 
 
-    serialize (c->serializer);
+    bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
+    if (!serialize (c->serializer, glyph_names))
+      return_trace (false);
+
+    if (glyph_names && version.major == 2)
+      return_trace (v2X.subset (c));
 
 
     return_trace (true);
     return_trace (true);
   }
   }
 
 
   struct accelerator_t
   struct accelerator_t
   {
   {
+    friend struct postV2Tail;
     void init (hb_face_t *face)
     void init (hb_face_t *face)
     {
     {
       index_to_offset.init ();
       index_to_offset.init ();
@@ -117,7 +135,7 @@ struct post
     void fini ()
     void fini ()
     {
     {
       index_to_offset.fini ();
       index_to_offset.fini ();
-      free (gids_sorted_by_name.get ());
+      hb_free (gids_sorted_by_name.get ());
       table.destroy ();
       table.destroy ();
     }
     }
 
 
@@ -148,7 +166,7 @@ struct post
 
 
       if (unlikely (!gids))
       if (unlikely (!gids))
       {
       {
-	gids = (uint16_t *) malloc (count * sizeof (gids[0]));
+	gids = (uint16_t *) hb_malloc (count * sizeof (gids[0]));
 	if (unlikely (!gids))
 	if (unlikely (!gids))
 	  return false; /* Anything better?! */
 	  return false; /* Anything better?! */
 
 
@@ -158,7 +176,7 @@ struct post
 
 
 	if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
 	if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
 	{
 	{
-	  free (gids);
+	  hb_free (gids);
 	  goto retry;
 	  goto retry;
 	}
 	}
       }
       }
@@ -236,7 +254,7 @@ struct post
 
 
     private:
     private:
     uint32_t version;
     uint32_t version;
-    const ArrayOf<HBUINT16> *glyphNameIndex;
+    const Array16Of<HBUINT16> *glyphNameIndex;
     hb_vector_t<uint32_t> index_to_offset;
     hb_vector_t<uint32_t> index_to_offset;
     const uint8_t *pool;
     const uint8_t *pool;
     hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
     hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;

+ 6 - 6
thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh

@@ -208,11 +208,11 @@ struct ManifestLookup
 {
 {
   public:
   public:
   OT::Tag tag;
   OT::Tag tag;
-  OT::OffsetTo<OT::SubstLookup> lookupOffset;
+  OT::Offset16To<OT::SubstLookup> lookupOffset;
   public:
   public:
   DEFINE_SIZE_STATIC (6);
   DEFINE_SIZE_STATIC (6);
 };
 };
-typedef OT::ArrayOf<ManifestLookup> Manifest;
+typedef OT::Array16Of<ManifestLookup> Manifest;
 
 
 static bool
 static bool
 arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
 arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
@@ -290,7 +290,7 @@ static arabic_fallback_plan_t *
 arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 			     hb_font_t *font)
 			     hb_font_t *font)
 {
 {
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
+  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
   if (unlikely (!fallback_plan))
     return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
     return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
 
 
@@ -308,7 +308,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
     return fallback_plan;
     return fallback_plan;
 
 
   assert (fallback_plan->num_lookups == 0);
   assert (fallback_plan->num_lookups == 0);
-  free (fallback_plan);
+  hb_free (fallback_plan);
   return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
   return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
 }
 }
 
 
@@ -323,10 +323,10 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
     {
     {
       fallback_plan->accel_array[i].fini ();
       fallback_plan->accel_array[i].fini ();
       if (fallback_plan->free_lookups)
       if (fallback_plan->free_lookups)
-	free (fallback_plan->lookup_array[i]);
+	hb_free (fallback_plan->lookup_array[i]);
     }
     }
 
 
-  free (fallback_plan);
+  hb_free (fallback_plan);
 }
 }
 
 
 static void
 static void

+ 5 - 4
thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh

@@ -6,10 +6,10 @@
  *
  *
  * on files with these headers:
  * on files with these headers:
  *
  *
- * # ArabicShaping-13.0.0.txt
- * # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
- * # Scripts-13.0.0.txt
- * # Date: 2020-01-22, 00:07:43 GMT
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
  */
  */
 
 
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
@@ -29,6 +29,7 @@ has_arabic_joining (hb_script_t script)
     case HB_SCRIPT_MANICHAEAN:
     case HB_SCRIPT_MANICHAEAN:
     case HB_SCRIPT_MONGOLIAN:
     case HB_SCRIPT_MONGOLIAN:
     case HB_SCRIPT_NKO:
     case HB_SCRIPT_NKO:
+    case HB_SCRIPT_OLD_UYGHUR:
     case HB_SCRIPT_PHAGS_PA:
     case HB_SCRIPT_PHAGS_PA:
     case HB_SCRIPT_PSALTER_PAHLAVI:
     case HB_SCRIPT_PSALTER_PAHLAVI:
     case HB_SCRIPT_SOGDIAN:
     case HB_SCRIPT_SOGDIAN:

+ 23 - 15
thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh

@@ -6,10 +6,10 @@
  *
  *
  * on files with these headers:
  * on files with these headers:
  *
  *
- * # ArabicShaping-13.0.0.txt
- * # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
- * # Blocks-13.0.0.txt
- * # Date: 2019-07-10, 19:06:00 GMT [KW]
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
  * UnicodeData.txt does not have a header.
  * UnicodeData.txt does not have a header.
  */
  */
 
 
@@ -75,13 +75,17 @@ static const uint8_t joining_table[] =
 
 
   /* Syriac Supplement */
   /* Syriac Supplement */
 
 
-  /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,
+
+  /* Arabic Extended-B */
+
+  /* 0860 */                                 R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,
+  /* 0880 */ R,R,R,C,C,C,D,U,U,D,D,D,D,D,R,X,U,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
 
 
   /* Arabic Extended-A */
   /* Arabic Extended-A */
 
 
-  /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,D,D,
-  /* 08C0 */ D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,D,D,D,D,R,D,D,D,D,D,D,
+  /* 08C0 */ D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
   /* 08E0 */ X,X,U,
   /* 08E0 */ X,X,U,
 
 
 #define joining_offset_0x1806u 739
 #define joining_offset_0x1806u 739
@@ -137,23 +141,28 @@ static const uint8_t joining_table[] =
   /* Sogdian */
   /* Sogdian */
 
 
   /* 10F20 */                                 D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 10F20 */                                 D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,
+  /* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,X,X,X,X,X,X,X,X,X,X,X,
+  /* 10F60 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+  /* Old Uyghur */
 
 
-#define joining_offset_0x10fb0u 1219
+  /* 10F60 */                                 D,D,D,D,R,R,D,D,D,D,D,D,D,D,D,D,
+  /* 10F80 */ D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+  /* 10FA0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
 
 
   /* Chorasmian */
   /* Chorasmian */
 
 
   /* 10FA0 */                                 D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
   /* 10FA0 */                                 D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
   /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
   /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
 
 
-#define joining_offset_0x110bdu 1247
+#define joining_offset_0x110bdu 1338
 
 
   /* Kaithi */
   /* Kaithi */
 
 
   /* 110A0 */                                                           U,X,X,
   /* 110A0 */                                                           U,X,X,
   /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
   /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
 
 
-#define joining_offset_0x1e900u 1264
+#define joining_offset_0x1e900u 1355
 
 
   /* Adlam */
   /* Adlam */
 
 
@@ -161,7 +170,7 @@ static const uint8_t joining_table[] =
   /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
   /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
 
 
-}; /* Table items: 1340; occupancy: 57% */
+}; /* Table items: 1431; occupancy: 57% */
 
 
 
 
 static unsigned int
 static unsigned int
@@ -189,8 +198,7 @@ joining_type (hb_codepoint_t u)
       if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F54u)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x10FCBu)) return joining_table[u - 0x10FB0u + joining_offset_0x10fb0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
       break;
       break;
 
 
     case 0x11u:
     case 0x11u:

+ 2 - 2
thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc

@@ -259,7 +259,7 @@ struct arabic_shape_plan_t
 void *
 void *
 data_create_arabic (const hb_ot_shape_plan_t *plan)
 data_create_arabic (const hb_ot_shape_plan_t *plan)
 {
 {
-  arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
+  arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) hb_calloc (1, sizeof (arabic_shape_plan_t));
   if (unlikely (!arabic_plan))
   if (unlikely (!arabic_plan))
     return nullptr;
     return nullptr;
 
 
@@ -282,7 +282,7 @@ data_destroy_arabic (void *data)
 
 
   arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
   arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
 
 
-  free (data);
+  hb_free (data);
 }
 }
 
 
 static void
 static void

+ 2 - 2
thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc

@@ -80,7 +80,7 @@ struct hangul_shape_plan_t
 static void *
 static void *
 data_create_hangul (const hb_ot_shape_plan_t *plan)
 data_create_hangul (const hb_ot_shape_plan_t *plan)
 {
 {
-  hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t));
+  hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) hb_calloc (1, sizeof (hangul_shape_plan_t));
   if (unlikely (!hangul_plan))
   if (unlikely (!hangul_plan))
     return nullptr;
     return nullptr;
 
 
@@ -93,7 +93,7 @@ data_create_hangul (const hb_ot_shape_plan_t *plan)
 static void
 static void
 data_destroy_hangul (void *data)
 data_destroy_hangul (void *data)
 {
 {
-  free (data);
+  hb_free (data);
 }
 }
 
 
 /* Constants for algorithmic hangul syllable [de]composition. */
 /* Constants for algorithmic hangul syllable [de]composition. */

+ 21 - 21
thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc

@@ -6,12 +6,12 @@
  *
  *
  * on files with these headers:
  * on files with these headers:
  *
  *
- * # IndicSyllabicCategory-13.0.0.txt
- * # Date: 2019-07-22, 19:55:00 GMT [KW, RP]
- * # IndicPositionalCategory-13.0.0.txt
- * # Date: 2019-07-23, 00:01:00 GMT [KW, RP]
- * # Blocks-13.0.0.txt
- * # Date: 2019-07-10, 19:06:00 GMT [KW]
+ * # IndicSyllabicCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # IndicPositionalCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
  */
  */
 
 
 #include "hb.hh"
 #include "hb.hh"
@@ -27,9 +27,9 @@
 #define ISC_Bi   INDIC_SYLLABIC_CATEGORY_BINDU                       /*   91 chars; Bindu */
 #define ISC_Bi   INDIC_SYLLABIC_CATEGORY_BINDU                       /*   91 chars; Bindu */
 #define ISC_BJN  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER       /*   20 chars; Brahmi_Joining_Number */
 #define ISC_BJN  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER       /*   20 chars; Brahmi_Joining_Number */
 #define ISC_Ca   INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK           /*   59 chars; Cantillation_Mark */
 #define ISC_Ca   INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK           /*   59 chars; Cantillation_Mark */
-#define ISC_C    INDIC_SYLLABIC_CATEGORY_CONSONANT                   /* 2195 chars; Consonant */
-#define ISC_CD   INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD              /*   12 chars; Consonant_Dead */
-#define ISC_CF   INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL             /*   67 chars; Consonant_Final */
+#define ISC_C    INDIC_SYLLABIC_CATEGORY_CONSONANT                   /* 2206 chars; Consonant */
+#define ISC_CD   INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD              /*   14 chars; Consonant_Dead */
+#define ISC_CF   INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL             /*   70 chars; Consonant_Final */
 #define ISC_CHL  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER       /*    5 chars; Consonant_Head_Letter */
 #define ISC_CHL  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER       /*    5 chars; Consonant_Head_Letter */
 #define ISC_CIP  INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /*    1 chars; Consonant_Initial_Postfixed */
 #define ISC_CIP  INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /*    1 chars; Consonant_Initial_Postfixed */
 #define ISC_CK   INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER            /*    2 chars; Consonant_Killer */
 #define ISC_CK   INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER            /*    2 chars; Consonant_Killer */
@@ -38,18 +38,18 @@
 #define ISC_CPR  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA   /*    3 chars; Consonant_Preceding_Repha */
 #define ISC_CPR  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA   /*    3 chars; Consonant_Preceding_Repha */
 #define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED          /*   10 chars; Consonant_Prefixed */
 #define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED          /*   10 chars; Consonant_Prefixed */
 #define ISC_CS   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED         /*   94 chars; Consonant_Subjoined */
 #define ISC_CS   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED         /*   94 chars; Consonant_Subjoined */
-#define ISC_CSR  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA  /*    4 chars; Consonant_Succeeding_Repha */
+#define ISC_CSR  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA  /*    1 chars; Consonant_Succeeding_Repha */
 #define ISC_CWS  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER      /*    8 chars; Consonant_With_Stacker */
 #define ISC_CWS  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER      /*    8 chars; Consonant_With_Stacker */
 #define ISC_GM   INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK             /*    3 chars; Gemination_Mark */
 #define ISC_GM   INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK             /*    3 chars; Gemination_Mark */
 #define ISC_IS   INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER           /*   12 chars; Invisible_Stacker */
 #define ISC_IS   INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER           /*   12 chars; Invisible_Stacker */
 #define ISC_ZWJ  INDIC_SYLLABIC_CATEGORY_JOINER                      /*    1 chars; Joiner */
 #define ISC_ZWJ  INDIC_SYLLABIC_CATEGORY_JOINER                      /*    1 chars; Joiner */
 #define ISC_ML   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER            /*    1 chars; Modifying_Letter */
 #define ISC_ML   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER            /*    1 chars; Modifying_Letter */
 #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER                  /*    1 chars; Non_Joiner */
 #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER                  /*    1 chars; Non_Joiner */
-#define ISC_N    INDIC_SYLLABIC_CATEGORY_NUKTA                       /*   31 chars; Nukta */
+#define ISC_N    INDIC_SYLLABIC_CATEGORY_NUKTA                       /*   32 chars; Nukta */
 #define ISC_Nd   INDIC_SYLLABIC_CATEGORY_NUMBER                      /*  491 chars; Number */
 #define ISC_Nd   INDIC_SYLLABIC_CATEGORY_NUMBER                      /*  491 chars; Number */
 #define ISC_NJ   INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER               /*    1 chars; Number_Joiner */
 #define ISC_NJ   INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER               /*    1 chars; Number_Joiner */
 #define ISC_x    INDIC_SYLLABIC_CATEGORY_OTHER                       /*    1 chars; Other */
 #define ISC_x    INDIC_SYLLABIC_CATEGORY_OTHER                       /*    1 chars; Other */
-#define ISC_PK   INDIC_SYLLABIC_CATEGORY_PURE_KILLER                 /*   23 chars; Pure_Killer */
+#define ISC_PK   INDIC_SYLLABIC_CATEGORY_PURE_KILLER                 /*   25 chars; Pure_Killer */
 #define ISC_RS   INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER            /*    2 chars; Register_Shifter */
 #define ISC_RS   INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER            /*    2 chars; Register_Shifter */
 #define ISC_SM   INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER           /*   25 chars; Syllable_Modifier */
 #define ISC_SM   INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER           /*   25 chars; Syllable_Modifier */
 #define ISC_TL   INDIC_SYLLABIC_CATEGORY_TONE_LETTER                 /*    7 chars; Tone_Letter */
 #define ISC_TL   INDIC_SYLLABIC_CATEGORY_TONE_LETTER                 /*    7 chars; Tone_Letter */
@@ -57,18 +57,18 @@
 #define ISC_V    INDIC_SYLLABIC_CATEGORY_VIRAMA                      /*   27 chars; Virama */
 #define ISC_V    INDIC_SYLLABIC_CATEGORY_VIRAMA                      /*   27 chars; Virama */
 #define ISC_Vs   INDIC_SYLLABIC_CATEGORY_VISARGA                     /*   35 chars; Visarga */
 #define ISC_Vs   INDIC_SYLLABIC_CATEGORY_VISARGA                     /*   35 chars; Visarga */
 #define ISC_Vo   INDIC_SYLLABIC_CATEGORY_VOWEL                       /*   30 chars; Vowel */
 #define ISC_Vo   INDIC_SYLLABIC_CATEGORY_VOWEL                       /*   30 chars; Vowel */
-#define ISC_M    INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT             /*  683 chars; Vowel_Dependent */
-#define ISC_VI   INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT           /*  484 chars; Vowel_Independent */
+#define ISC_M    INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT             /*  686 chars; Vowel_Dependent */
+#define ISC_VI   INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT           /*  486 chars; Vowel_Independent */
 
 
-#define IMC_B    INDIC_MATRA_CATEGORY_BOTTOM                         /*  351 chars; Bottom */
+#define IMC_B    INDIC_MATRA_CATEGORY_BOTTOM                         /*  352 chars; Bottom */
 #define IMC_BL   INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT                /*    1 chars; Bottom_And_Left */
 #define IMC_BL   INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT                /*    1 chars; Bottom_And_Left */
 #define IMC_BR   INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT               /*    4 chars; Bottom_And_Right */
 #define IMC_BR   INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT               /*    4 chars; Bottom_And_Right */
 #define IMC_L    INDIC_MATRA_CATEGORY_LEFT                           /*   64 chars; Left */
 #define IMC_L    INDIC_MATRA_CATEGORY_LEFT                           /*   64 chars; Left */
 #define IMC_LR   INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                 /*   22 chars; Left_And_Right */
 #define IMC_LR   INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                 /*   22 chars; Left_And_Right */
 #define IMC_x    INDIC_MATRA_CATEGORY_NOT_APPLICABLE                 /*    1 chars; Not_Applicable */
 #define IMC_x    INDIC_MATRA_CATEGORY_NOT_APPLICABLE                 /*    1 chars; Not_Applicable */
 #define IMC_O    INDIC_MATRA_CATEGORY_OVERSTRUCK                     /*   10 chars; Overstruck */
 #define IMC_O    INDIC_MATRA_CATEGORY_OVERSTRUCK                     /*   10 chars; Overstruck */
-#define IMC_R    INDIC_MATRA_CATEGORY_RIGHT                          /*  288 chars; Right */
-#define IMC_T    INDIC_MATRA_CATEGORY_TOP                            /*  415 chars; Top */
+#define IMC_R    INDIC_MATRA_CATEGORY_RIGHT                          /*  290 chars; Right */
+#define IMC_T    INDIC_MATRA_CATEGORY_TOP                            /*  418 chars; Top */
 #define IMC_TB   INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                 /*   10 chars; Top_And_Bottom */
 #define IMC_TB   INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                 /*   10 chars; Top_And_Bottom */
 #define IMC_TBL  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT        /*    2 chars; Top_And_Bottom_And_Left */
 #define IMC_TBL  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT        /*    2 chars; Top_And_Bottom_And_Left */
 #define IMC_TBR  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT       /*    1 chars; Top_And_Bottom_And_Right */
 #define IMC_TBR  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT       /*    1 chars; Top_And_Bottom_And_Right */
@@ -231,11 +231,11 @@ static const uint16_t indic_table[] = {
   /* 0C20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0C30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(A,x),  _(M,T),  _(M,T),
+  /* 0C38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,T),  _(M,T),
   /* 0C40 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T),  _(M,T),
   /* 0C40 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T),  _(M,T),
   /* 0C48 */ _(M,TB),  _(x,x),  _(M,T),  _(M,T),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0C48 */ _(M,TB),  _(x,x),  _(M,T),  _(M,T),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0C50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),  _(M,B),  _(x,x),
   /* 0C50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),  _(M,B),  _(x,x),
-  /* 0C58 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0C58 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x), _(CD,x),  _(x,x),  _(x,x),
   /* 0C60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0C60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0C70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0C70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -254,7 +254,7 @@ static const uint16_t indic_table[] = {
   /* 0CC0 */ _(M,TR),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T), _(M,TR),
   /* 0CC0 */ _(M,TR),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T), _(M,TR),
   /* 0CC8 */ _(M,TR),  _(x,x), _(M,TR), _(M,TR),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0CC8 */ _(M,TR),  _(x,x), _(M,TR), _(M,TR),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
   /* 0CD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),
   /* 0CD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),
-  /* 0CD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(x,x),
+  /* 0CD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CD,x),  _(C,x),  _(x,x),
   /* 0CE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0CE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0CF0 */  _(x,x),_(CWS,x),_(CWS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0CF0 */  _(x,x),_(CWS,x),_(CWS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
@@ -402,7 +402,7 @@ static const uint16_t indic_table[] = {
   /* AA70 */  _(x,x),  _(C,x),  _(C,x),  _(C,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),
   /* AA70 */  _(x,x),  _(C,x),  _(C,x),  _(C,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),
   /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,R), _(TM,T), _(TM,R),  _(C,x),  _(C,x),
   /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,R), _(TM,T), _(TM,R),  _(C,x),  _(C,x),
 
 
-}; /* Table items: 1792; occupancy: 70% */
+}; /* Table items: 1792; occupancy: 71% */
 
 
 uint16_t
 uint16_t
 hb_indic_get_categories (hb_codepoint_t u)
 hb_indic_get_categories (hb_codepoint_t u)

+ 8 - 6
thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc

@@ -106,7 +106,8 @@ indic_features[] =
 {
 {
   /*
   /*
    * 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 initial_reordering,
+   * constrained to the syllable.
    */
    */
   {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
@@ -121,8 +122,8 @@ indic_features[] =
   {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
   {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
   /*
   /*
    * Other features.
    * Other features.
-   * These features are applied all at once, after final_reordering
-   * but before clearing syllables.
+   * These features are applied all at once, after final_reordering, constrained
+   * to the syllable.
    * Default Bengali font in Windows for example has intermixed
    * Default Bengali font in Windows for example has intermixed
    * lookups for init,pres,abvs,blws features.
    * lookups for init,pres,abvs,blws features.
    */
    */
@@ -257,7 +258,7 @@ struct indic_shape_plan_t
 static void *
 static void *
 data_create_indic (const hb_ot_shape_plan_t *plan)
 data_create_indic (const hb_ot_shape_plan_t *plan)
 {
 {
-  indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) calloc (1, sizeof (indic_shape_plan_t));
+  indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) hb_calloc (1, sizeof (indic_shape_plan_t));
   if (unlikely (!indic_plan))
   if (unlikely (!indic_plan))
     return nullptr;
     return nullptr;
 
 
@@ -300,7 +301,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
 static void
 static void
 data_destroy_indic (void *data)
 data_destroy_indic (void *data)
 {
 {
-  free (data);
+  hb_free (data);
 }
 }
 
 
 static indic_position_t
 static indic_position_t
@@ -960,7 +961,8 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan,
   hb_syllabic_insert_dotted_circles (font, buffer,
   hb_syllabic_insert_dotted_circles (font, buffer,
 				     indic_broken_cluster,
 				     indic_broken_cluster,
 				     OT_DOTTEDCIRCLE,
 				     OT_DOTTEDCIRCLE,
-				     OT_Repha);
+				     OT_Repha,
+				     POS_END);
 
 
   foreach_syllable (buffer, start, end)
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
     initial_reordering_syllable_indic (plan, font->face, buffer, start, end);

+ 303 - 362
thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh

@@ -1,29 +1,30 @@
+
 #line 1 "hb-ot-shape-complex-khmer-machine.rl"
 #line 1 "hb-ot-shape-complex-khmer-machine.rl"
 /*
 /*
-* 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.
-*
-* Google Author(s): Behdad Esfahbod
-*/
+ * 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
 
 
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
@@ -31,13 +32,13 @@
 #include "hb.hh"
 #include "hb.hh"
 
 
 enum khmer_syllable_type_t {
 enum khmer_syllable_type_t {
-	khmer_consonant_syllable,
-	khmer_broken_cluster,
-	khmer_non_khmer_cluster,
+  khmer_consonant_syllable,
+  khmer_broken_cluster,
+  khmer_non_khmer_cluster,
 };
 };
 
 
 
 
-#line 41 "hb-ot-shape-complex-khmer-machine.hh"
+#line 42 "hb-ot-shape-complex-khmer-machine.hh"
 #define khmer_syllable_machine_ex_C 1u
 #define khmer_syllable_machine_ex_C 1u
 #define khmer_syllable_machine_ex_Coeng 14u
 #define khmer_syllable_machine_ex_Coeng 14u
 #define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
 #define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
@@ -55,125 +56,180 @@ enum khmer_syllable_type_t {
 #define khmer_syllable_machine_ex_ZWNJ 5u
 #define khmer_syllable_machine_ex_ZWNJ 5u
 
 
 
 
-#line 59 "hb-ot-shape-complex-khmer-machine.hh"
+#line 60 "hb-ot-shape-complex-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
-	2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u,
-	0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u,
-	2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u,
-	2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u,
-	2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u,
-	0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u,
-	7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u,
-	2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u,
-	2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u,
-	2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u,
-	0u
+	5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 
+	5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 
+	5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u, 
+	22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u, 
+	5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u, 
+	0
 };
 };
 
 
-static const signed char _khmer_syllable_machine_char_class[] = {
-	0, 0, 1, 1, 2, 2, 1, 1,
-	1, 1, 3, 3, 1, 4, 1, 0,
-	1, 1, 1, 5, 6, 7, 1, 1,
-	1, 8, 9, 10, 11, 0
+static const char _khmer_syllable_machine_key_spans[] = {
+	22, 17, 22, 17, 16, 17, 22, 17, 
+	22, 17, 17, 22, 17, 16, 17, 22, 
+	17, 22, 17, 22, 29, 25, 25, 25, 
+	1, 18, 25, 25, 25, 16, 22, 25, 
+	25, 1, 18, 25, 25, 16, 25, 25
 };
 };
 
 
 static const short _khmer_syllable_machine_index_offsets[] = {
 static const short _khmer_syllable_machine_index_offsets[] = {
-	0, 7, 12, 19, 24, 25, 30, 37,
-	42, 49, 54, 59, 66, 71, 72, 77,
-	84, 89, 96, 101, 108, 120, 130, 140,
-	150, 151, 157, 167, 177, 187, 188, 195,
-	205, 215, 216, 222, 232, 242, 243, 253,
-	0
-};
-
-static const signed char _khmer_syllable_machine_indicies[] = {
-	1, 0, 0, 2, 3, 0, 4, 1,
-	0, 0, 0, 3, 1, 0, 0, 0,
-	3, 0, 4, 5, 0, 0, 0, 4,
-	6, 7, 0, 0, 0, 8, 9, 0,
-	0, 0, 10, 0, 4, 9, 0, 0,
-	0, 10, 11, 0, 0, 0, 12, 0,
-	4, 11, 0, 0, 0, 12, 14, 13,
-	13, 13, 15, 14, 16, 16, 16, 15,
-	16, 17, 18, 16, 16, 16, 17, 19,
-	20, 16, 16, 16, 21, 22, 16, 16,
-	16, 23, 16, 17, 22, 16, 16, 16,
-	23, 24, 16, 16, 16, 25, 16, 17,
-	24, 16, 16, 16, 25, 14, 16, 16,
-	26, 15, 16, 17, 29, 28, 30, 2,
-	31, 28, 15, 19, 17, 23, 25, 21,
-	33, 32, 34, 2, 3, 6, 4, 10,
-	12, 8, 35, 32, 36, 32, 3, 6,
-	4, 10, 12, 8, 5, 32, 36, 32,
-	4, 6, 32, 32, 32, 8, 6, 7,
-	32, 36, 32, 8, 6, 37, 32, 36,
-	32, 10, 6, 4, 32, 32, 8, 38,
-	32, 36, 32, 12, 6, 4, 10, 32,
-	8, 35, 32, 34, 32, 3, 6, 4,
-	10, 12, 8, 29, 14, 39, 39, 39,
-	15, 39, 17, 41, 40, 42, 40, 15,
-	19, 17, 23, 25, 21, 18, 40, 42,
-	40, 17, 19, 40, 40, 40, 21, 19,
-	20, 40, 42, 40, 21, 19, 43, 40,
-	42, 40, 23, 19, 17, 40, 40, 21,
-	44, 40, 42, 40, 25, 19, 17, 23,
-	40, 21, 45, 46, 40, 31, 26, 15,
-	19, 17, 23, 25, 21, 41, 40, 31,
-	40, 15, 19, 17, 23, 25, 21, 0
+	0, 23, 41, 64, 82, 99, 117, 140, 
+	158, 181, 199, 217, 240, 258, 275, 293, 
+	316, 334, 357, 375, 398, 428, 454, 480, 
+	506, 508, 527, 553, 579, 605, 622, 645, 
+	671, 697, 699, 718, 744, 770, 787, 813
 };
 };
 
 
-static const signed char _khmer_syllable_machine_index_defaults[] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 13, 16, 16, 16, 16, 16,
-	16, 16, 16, 16, 28, 32, 32, 32,
-	32, 32, 32, 32, 32, 32, 39, 40,
-	40, 40, 40, 40, 40, 40, 40, 40,
-	0
+static const char _khmer_syllable_machine_indicies[] = {
+	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, 3, 0, 0, 0, 0, 4, 0, 
+	5, 5, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	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, 14, 
+	14, 13, 13, 13, 13, 13, 13, 13, 
+	13, 13, 13, 13, 13, 13, 13, 15, 
+	13, 14, 14, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 15, 16, 16, 16, 16, 17, 16, 
+	18, 18, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	17, 16, 19, 19, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 19, 16, 20, 20, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 21, 16, 22, 22, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 23, 16, 16, 
+	16, 16, 17, 16, 22, 22, 16, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 23, 16, 24, 24, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 25, 16, 
+	16, 16, 16, 17, 16, 24, 24, 16, 
+	16, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 25, 16, 14, 
+	14, 16, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 16, 16, 26, 15, 
+	16, 16, 16, 16, 17, 16, 28, 28, 
+	27, 27, 29, 29, 27, 27, 27, 27, 
+	2, 2, 27, 30, 27, 28, 27, 27, 
+	27, 27, 15, 19, 27, 27, 27, 17, 
+	23, 25, 21, 27, 32, 32, 31, 31, 
+	31, 31, 31, 31, 31, 33, 31, 31, 
+	31, 31, 31, 2, 3, 6, 31, 31, 
+	31, 4, 10, 12, 8, 31, 34, 34, 
+	31, 31, 31, 31, 31, 31, 31, 35, 
+	31, 31, 31, 31, 31, 31, 3, 6, 
+	31, 31, 31, 4, 10, 12, 8, 31, 
+	5, 5, 31, 31, 31, 31, 31, 31, 
+	31, 35, 31, 31, 31, 31, 31, 31, 
+	4, 6, 31, 31, 31, 31, 31, 31, 
+	8, 31, 6, 31, 7, 7, 31, 31, 
+	31, 31, 31, 31, 31, 35, 31, 31, 
+	31, 31, 31, 31, 8, 6, 31, 36, 
+	36, 31, 31, 31, 31, 31, 31, 31, 
+	35, 31, 31, 31, 31, 31, 31, 10, 
+	6, 31, 31, 31, 4, 31, 31, 8, 
+	31, 37, 37, 31, 31, 31, 31, 31, 
+	31, 31, 35, 31, 31, 31, 31, 31, 
+	31, 12, 6, 31, 31, 31, 4, 10, 
+	31, 8, 31, 34, 34, 31, 31, 31, 
+	31, 31, 31, 31, 33, 31, 31, 31, 
+	31, 31, 31, 3, 6, 31, 31, 31, 
+	4, 10, 12, 8, 31, 28, 28, 31, 
+	31, 31, 31, 31, 31, 31, 31, 31, 
+	31, 31, 31, 31, 28, 31, 14, 14, 
+	38, 38, 38, 38, 38, 38, 38, 38, 
+	38, 38, 38, 38, 38, 38, 15, 38, 
+	38, 38, 38, 17, 38, 40, 40, 39, 
+	39, 39, 39, 39, 39, 39, 41, 39, 
+	39, 39, 39, 39, 39, 15, 19, 39, 
+	39, 39, 17, 23, 25, 21, 39, 18, 
+	18, 39, 39, 39, 39, 39, 39, 39, 
+	41, 39, 39, 39, 39, 39, 39, 17, 
+	19, 39, 39, 39, 39, 39, 39, 21, 
+	39, 19, 39, 20, 20, 39, 39, 39, 
+	39, 39, 39, 39, 41, 39, 39, 39, 
+	39, 39, 39, 21, 19, 39, 42, 42, 
+	39, 39, 39, 39, 39, 39, 39, 41, 
+	39, 39, 39, 39, 39, 39, 23, 19, 
+	39, 39, 39, 17, 39, 39, 21, 39, 
+	43, 43, 39, 39, 39, 39, 39, 39, 
+	39, 41, 39, 39, 39, 39, 39, 39, 
+	25, 19, 39, 39, 39, 17, 23, 39, 
+	21, 39, 44, 44, 39, 39, 39, 39, 
+	39, 39, 39, 39, 39, 39, 39, 39, 
+	39, 44, 39, 45, 45, 39, 39, 39, 
+	39, 39, 39, 39, 30, 39, 39, 39, 
+	39, 39, 26, 15, 19, 39, 39, 39, 
+	17, 23, 25, 21, 39, 40, 40, 39, 
+	39, 39, 39, 39, 39, 39, 30, 39, 
+	39, 39, 39, 39, 39, 15, 19, 39, 
+	39, 39, 17, 23, 25, 21, 39, 0
 };
 };
 
 
-static const signed char _khmer_syllable_machine_cond_targs[] = {
-	20, 1, 28, 22, 23, 3, 24, 5,
-	25, 7, 26, 9, 27, 20, 10, 31,
-	20, 32, 12, 33, 14, 34, 16, 35,
-	18, 36, 39, 20, 20, 21, 30, 37,
-	20, 0, 29, 2, 4, 6, 8, 20,
-	20, 11, 13, 15, 17, 38, 19, 0
+static const char _khmer_syllable_machine_trans_targs[] = {
+	20, 1, 28, 22, 23, 3, 24, 5, 
+	25, 7, 26, 9, 27, 20, 10, 31, 
+	20, 32, 12, 33, 14, 34, 16, 35, 
+	18, 36, 39, 20, 21, 30, 37, 20, 
+	0, 29, 2, 4, 6, 8, 20, 20, 
+	11, 13, 15, 17, 38, 19
 };
 };
 
 
-static const signed char _khmer_syllable_machine_cond_actions[] = {
-	1, 0, 2, 2, 2, 0, 0, 0,
-	2, 0, 2, 0, 2, 3, 0, 4,
-	5, 2, 0, 0, 0, 2, 0, 2,
-	0, 2, 4, 0, 8, 2, 9, 0,
-	10, 0, 0, 0, 0, 0, 0, 11,
-	12, 0, 0, 0, 0, 4, 0, 0
+static const char _khmer_syllable_machine_trans_actions[] = {
+	1, 0, 2, 2, 2, 0, 0, 0, 
+	2, 0, 2, 0, 2, 3, 0, 4, 
+	5, 2, 0, 0, 0, 2, 0, 2, 
+	0, 2, 4, 8, 2, 9, 0, 10, 
+	0, 0, 0, 0, 0, 0, 11, 12, 
+	0, 0, 0, 0, 4, 0
 };
 };
 
 
-static const signed char _khmer_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, 6, 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_to_state_actions[] = {
+	0, 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
 };
 };
 
 
-static const signed char _khmer_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, 7, 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, 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
 };
 };
 
 
-static const signed char _khmer_syllable_machine_eof_trans[] = {
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 14, 17, 17, 17, 17, 17,
-	17, 17, 17, 17, 28, 33, 33, 33,
-	33, 33, 33, 33, 33, 33, 40, 41,
-	41, 41, 41, 41, 41, 41, 41, 41,
-	0
+static const unsigned char _khmer_syllable_machine_eof_trans[] = {
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 14, 17, 17, 17, 17, 17, 
+	17, 17, 17, 17, 0, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 39, 40, 
+	40, 40, 40, 40, 40, 40, 40, 40
 };
 };
 
 
 static const int khmer_syllable_machine_start = 20;
 static const int khmer_syllable_machine_start = 20;
@@ -191,263 +247,148 @@ static const int khmer_syllable_machine_en_main = 20;
 
 
 
 
 #define found_syllable(syllable_type) \
 #define found_syllable(syllable_type) \
-HB_STMT_START { \
-	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; \
-	syllable_serial++; \
-	if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
-	} HB_STMT_END
+  HB_STMT_START { \
+    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; \
+    syllable_serial++; \
+    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+  } HB_STMT_END
 
 
 static void
 static void
 find_syllables_khmer (hb_buffer_t *buffer)
 find_syllables_khmer (hb_buffer_t *buffer)
 {
 {
-	unsigned int p, pe, eof, ts, te, act HB_UNUSED;
-	int cs;
-	hb_glyph_info_t *info = buffer->info;
-	
-#line 210 "hb-ot-shape-complex-khmer-machine.hh"
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+  int cs;
+  hb_glyph_info_t *info = buffer->info;
+  
+#line 266 "hb-ot-shape-complex-khmer-machine.hh"
 	{
 	{
-		cs = (int)khmer_syllable_machine_start;
-		ts = 0;
-		te = 0;
-		act = 0;
+	cs = khmer_syllable_machine_start;
+	ts = 0;
+	te = 0;
+	act = 0;
 	}
 	}
-	
+
 #line 106 "hb-ot-shape-complex-khmer-machine.rl"
 #line 106 "hb-ot-shape-complex-khmer-machine.rl"
-	
-	
-	p = 0;
-	pe = eof = buffer->len;
-	
-	unsigned int syllable_serial = 1;
-	
-#line 226 "hb-ot-shape-complex-khmer-machine.hh"
+
+
+  p = 0;
+  pe = eof = buffer->len;
+
+  unsigned int syllable_serial = 1;
+  
+#line 282 "hb-ot-shape-complex-khmer-machine.hh"
 	{
 	{
-		unsigned int _trans = 0;
-		const unsigned char * _keys;
-		const signed char * _inds;
-		int _ic;
-		_resume: {}
-		if ( p == pe && p != eof )
-			goto _out;
-		switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
-			case 7:  {
-				{
+	int _slen;
+	int _trans;
+	const unsigned char *_keys;
+	const char *_inds;
+	if ( p == pe )
+		goto _test_eof;
+_resume:
+	switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
+	case 7:
 #line 1 "NONE"
 #line 1 "NONE"
-					{ts = p;}}
-				
-#line 241 "hb-ot-shape-complex-khmer-machine.hh"
-				
-				
-				break; 
-			}
-		}
-		
-		if ( p == eof ) {
-			if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
-				_trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1;
-			}
-		}
-		else {
-			_keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1)));
-			_inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs]));
-			
-			if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) {
-				_ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1];
-				if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
-					_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); 
-				else
-					_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
-			}
-			else {
-				_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
-			}
-			
-		}
-		cs = (int)_khmer_syllable_machine_cond_targs[_trans];
-		
-		if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) {
-			
-			switch ( _khmer_syllable_machine_cond_actions[_trans] ) {
-				case 2:  {
-					{
+	{ts = p;}
+	break;
+#line 296 "hb-ot-shape-complex-khmer-machine.hh"
+	}
+
+	_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
+	_inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
+
+	_slen = _khmer_syllable_machine_key_spans[cs];
+	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
+		( info[p].khmer_category()) <= _keys[1] ?
+		( info[p].khmer_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+	cs = _khmer_syllable_machine_trans_targs[_trans];
+
+	if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
+		goto _again;
+
+	switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
+	case 2:
 #line 1 "NONE"
 #line 1 "NONE"
-						{te = p+1;}}
-					
-#line 279 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 8:  {
-					{
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
-						{te = p+1;{
+	{te = p+1;}
+	break;
+	case 8:
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_non_khmer_cluster); }
-						}}
-					
-#line 292 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 10:  {
-					{
+	{te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
+	break;
+	case 10:
 #line 80 "hb-ot-shape-complex-khmer-machine.rl"
 #line 80 "hb-ot-shape-complex-khmer-machine.rl"
-						{te = p;p = p - 1;{
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_consonant_syllable); }
-						}}
-					
-#line 305 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 12:  {
-					{
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
-						{te = p;p = p - 1;{
+	{te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
+	break;
+	case 12:
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_broken_cluster); }
-						}}
-					
-#line 318 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 11:  {
-					{
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
-						{te = p;p = p - 1;{
+	{te = p;p--;{ found_syllable (khmer_broken_cluster); }}
+	break;
+	case 11:
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_non_khmer_cluster); }
-						}}
-					
-#line 331 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 1:  {
-					{
+	{te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
+	break;
+	case 1:
 #line 80 "hb-ot-shape-complex-khmer-machine.rl"
 #line 80 "hb-ot-shape-complex-khmer-machine.rl"
-						{p = ((te))-1;
-							{
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_consonant_syllable); }
-						}}
-					
-#line 345 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 5:  {
-					{
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
-						{p = ((te))-1;
-							{
+	{{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
+	break;
+	case 5:
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
-								found_syllable (khmer_broken_cluster); }
-						}}
-					
-#line 359 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 3:  {
-					{
+	{{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
+	break;
+	case 3:
 #line 1 "NONE"
 #line 1 "NONE"
-						{switch( act ) {
-								case 2:  {
-									p = ((te))-1;
-									{
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
-										found_syllable (khmer_broken_cluster); }
-									break; 
-								}
-								case 3:  {
-									p = ((te))-1;
-									{
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
-										found_syllable (khmer_non_khmer_cluster); }
-									break; 
-								}
-							}}
-					}
-					
-#line 385 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 4:  {
-					{
+	{	switch( act ) {
+	case 2:
+	{{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
+	break;
+	case 3:
+	{{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
+	break;
+	}
+	}
+	break;
+	case 4:
 #line 1 "NONE"
 #line 1 "NONE"
-						{te = p+1;}}
-					
-#line 395 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					{
+	{te = p+1;}
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
 #line 81 "hb-ot-shape-complex-khmer-machine.rl"
-						{act = 2;}}
-					
-#line 401 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-				case 9:  {
-					{
+	{act = 2;}
+	break;
+	case 9:
 #line 1 "NONE"
 #line 1 "NONE"
-						{te = p+1;}}
-					
-#line 411 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					{
+	{te = p+1;}
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
 #line 82 "hb-ot-shape-complex-khmer-machine.rl"
-						{act = 3;}}
-					
-#line 417 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-			}
-			
-		}
-		
-		if ( p == eof ) {
-			if ( cs >= 20 )
-				goto _out;
-		}
-		else {
-			switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
-				case 6:  {
-					{
+	{act = 3;}
+	break;
+#line 366 "hb-ot-shape-complex-khmer-machine.hh"
+	}
+
+_again:
+	switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+	case 6:
 #line 1 "NONE"
 #line 1 "NONE"
-						{ts = 0;}}
-					
-#line 437 "hb-ot-shape-complex-khmer-machine.hh"
-					
-					
-					break; 
-				}
-			}
-			
-			p += 1;
-			goto _resume;
-		}
-		_out: {}
+	{ts = 0;}
+	break;
+#line 375 "hb-ot-shape-complex-khmer-machine.hh"
+	}
+
+	if ( ++p != pe )
+		goto _resume;
+	_test_eof: {}
+	if ( p == eof )
+	{
+	if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
+		_trans = _khmer_syllable_machine_eof_trans[cs] - 1;
+		goto _eof_trans;
+	}
 	}
 	}
-	
+
+	}
+
 #line 114 "hb-ot-shape-complex-khmer-machine.rl"
 #line 114 "hb-ot-shape-complex-khmer-machine.rl"
-	
+
 }
 }
 
 
 #undef found_syllable
 #undef found_syllable

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio