Merge "Update harfbuzz to 1.8.8"
diff --git a/NEWS b/NEWS
index 9031766..3ae857e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,57 @@
+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
====================================
diff --git a/OWNERS b/OWNERS
index dd9112b..9bc89fb 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,3 @@
-roozbeh@google.com
behdad@google.com
siyamed@google.com
nona@google.com
diff --git a/README.version b/README.version
index 6d052f6..457bf26 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: https://github.com/harfbuzz/harfbuzz/commit/2b76767bf572364d3d647cdd139f2044a7ad06b2
-Version: 1.8.3
+URL: https://github.com/harfbuzz/harfbuzz/commit/63be5dcdde61275822d931b2924425478bc1dac1
+Version: 1.8.8
BugComponent: 25699
diff --git a/RELEASING.md b/RELEASING.md
index 0aef610..d431871 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -25,11 +25,14 @@
6. Do "make distcheck", if it passes, you get a tarball.
Otherwise, fix things and commit them separately before making release,
+ Note: Check src/hb-version.h and make sure the new version number is
+ there. Sometimes, it does not get updated. If that's the case,
+ "touch configure.ac" and rebuild. TODO: debug.
7. "make release-files". Enter your GPG password. This creates a sha256 hash
and signs it.
-8. Now that you have release files built, commit NEWS and configure.ac changes,
+8. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
as well as any REPLACEME changes you made. The commit message is simply the
release number. Eg. "1.4.7"
diff --git a/appveyor.yml b/appveyor.yml
index 05a72d9..cc4acec 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -29,6 +29,7 @@
MSYS2_ARCH: i686
install:
+ - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman -Syu --noconfirm"'
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
build_script:
@@ -43,7 +44,8 @@
- 'if "%compiler%"=="msvc" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%'
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%'
- - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
+ - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syyu mingw-w64-$MSYS2_ARCH-gcc"'
+ - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"'
diff --git a/configure.ac b/configure.ac
index b6fcfc0..55cc12b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
- [1.8.3],
+ [1.8.8],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 5715d77..16b6627 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -208,10 +208,12 @@
hb_font_funcs_set_glyph_extents_func
hb_font_funcs_set_glyph_from_name_func
hb_font_funcs_set_glyph_h_advance_func
+hb_font_funcs_set_glyph_h_advances_func
hb_font_funcs_set_glyph_h_kerning_func
hb_font_funcs_set_glyph_h_origin_func
hb_font_funcs_set_glyph_name_func
hb_font_funcs_set_glyph_v_advance_func
+hb_font_funcs_set_glyph_v_advances_func
hb_font_funcs_set_glyph_v_kerning_func
hb_font_funcs_set_glyph_v_origin_func
hb_font_funcs_set_nominal_glyph_func
@@ -223,6 +225,7 @@
hb_font_get_glyph
hb_font_get_glyph_advance_for_direction
hb_font_get_glyph_advance_func_t
+hb_font_get_glyph_advances_for_direction
hb_font_get_glyph_contour_point
hb_font_get_glyph_contour_point_for_origin
hb_font_get_glyph_contour_point_func_t
@@ -233,6 +236,8 @@
hb_font_get_glyph_from_name_func_t
hb_font_get_glyph_h_advance
hb_font_get_glyph_h_advance_func_t
+hb_font_get_glyph_h_advances
+hb_font_get_glyph_h_advances_func_t
hb_font_get_glyph_h_kerning
hb_font_get_glyph_h_kerning_func_t
hb_font_get_glyph_h_origin
@@ -245,6 +250,8 @@
hb_font_get_glyph_origin_func_t
hb_font_get_glyph_v_advance
hb_font_get_glyph_v_advance_func_t
+hb_font_get_glyph_v_advances
+hb_font_get_glyph_v_advances_func_t
hb_font_get_glyph_v_kerning
hb_font_get_glyph_v_kerning_func_t
hb_font_get_glyph_v_origin
@@ -327,6 +334,7 @@
HB_GOBJECT_TYPE_FONT
HB_GOBJECT_TYPE_FONT_FUNCS
HB_GOBJECT_TYPE_GLYPH_FLAGS
+HB_GOBJECT_TYPE_MAP
HB_GOBJECT_TYPE_MEMORY_MODE
HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
HB_GOBJECT_TYPE_OT_MATH_CONSTANT
@@ -358,6 +366,7 @@
hb_gobject_font_funcs_get_type
hb_gobject_font_get_type
hb_gobject_glyph_flags_get_type
+hb_gobject_map_get_type
hb_gobject_memory_mode_get_type
hb_gobject_ot_layout_glyph_class_get_type
hb_gobject_ot_math_constant_get_type
@@ -447,6 +456,7 @@
HB_OT_TAG_GSUB
HB_OT_TAG_JSTF
hb_ot_layout_collect_lookups
+hb_ot_layout_collect_features
hb_ot_layout_feature_get_lookups
hb_ot_layout_feature_with_variations_get_lookups
hb_ot_layout_get_attach_points
diff --git a/src/Makefile.am b/src/Makefile.am
index 6dfec3b..9e7fd29 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,7 @@
# Convenience targets:
lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
+libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
lib_LTLIBRARIES = libharfbuzz.la
@@ -373,15 +374,11 @@
endif
check_PROGRAMS += \
- dump-fon \
dump-indic-data \
dump-khmer-data \
dump-myanmar-data \
dump-use-data \
$(NULL)
-dump_fon_SOURCES = dump-fon.cc
-dump_fon_CPPFLAGS = $(HBCFLAGS)
-dump_fon_LDADD = libharfbuzz.la $(HBLIBS)
dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
dump_indic_data_CPPFLAGS = $(HBCFLAGS)
dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0bc9e58..b981b0e 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -14,9 +14,12 @@
hb-face.cc \
hb-font-private.hh \
hb-font.cc \
+ hb-iter-private.hh \
hb-map-private.hh \
hb-map.cc \
+ hb-machinery-private.hh \
hb-mutex-private.hh \
+ hb-null.hh \
hb-object-private.hh \
hb-open-file-private.hh \
hb-open-type-private.hh \
@@ -50,6 +53,7 @@
hb-string-array.hh \
hb-unicode-private.hh \
hb-unicode.cc \
+ hb-vector-private.hh \
hb-utf-private.hh \
hb-warning.cc \
$(NULL)
@@ -93,8 +97,6 @@
hb-aat-layout-morx-table.hh \
hb-aat-layout-trak-table.hh \
hb-aat-layout-private.hh \
- hb-aat-fmtx-table.hh \
- hb-aat-gcid-table.hh \
hb-aat-ltag-table.hh \
hb-ot-font.cc \
hb-ot-layout.cc \
diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc
index 99e8ef9..6521469 100644
--- a/src/dump-emoji.cc
+++ b/src/dump-emoji.cc
@@ -233,12 +233,10 @@
svg.dump (svg_callback);
svg.fini ();
- OT::Sanitizer<OT::COLR> sanitizerCOLR;
- hb_blob_t* colr_blob = sanitizerCOLR.sanitize (face->reference_table (HB_OT_TAG_COLR));
+ hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face);
const OT::COLR *colr = colr_blob->as<OT::COLR> ();
- OT::Sanitizer<OT::CPAL> sanitizerCPAL;
- hb_blob_t* cpal_blob = sanitizerCPAL.sanitize (face->reference_table (HB_OT_TAG_CPAL));
+ hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face);
const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
cairo_font_face_t *cairo_face;
diff --git a/src/dump-fon.cc b/src/dump-fon.cc
deleted file mode 100644
index 4015409..0000000
--- a/src/dump-fon.cc
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright © 2018 Ebrahim Byagowi
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#include "hb-static.cc"
-#include <stdio.h>
-#include <stdlib.h>
-#include "hb-open-type-private.hh"
-
-template <typename Type, int Bytes> struct LEInt;
-
-template <typename Type>
-struct LEInt<Type, 1>
-{
- public:
- inline void set (Type V)
- {
- v = V;
- }
- inline operator Type (void) const
- {
- return v;
- }
- private: uint8_t v;
-};
-template <typename Type>
-struct LEInt<Type, 2>
-{
- public:
- inline void set (Type V)
- {
- v[1] = (V >> 8) & 0xFF;
- v[0] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[1] << 8)
- + (v[0] );
- }
- private: uint8_t v[2];
-};
-template <typename Type>
-struct LEInt<Type, 3>
-{
- public:
- inline void set (Type V)
- {
- v[2] = (V >> 16) & 0xFF;
- v[1] = (V >> 8) & 0xFF;
- v[0] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[2] << 16)
- + (v[1] << 8)
- + (v[0] );
- }
- private: uint8_t v[3];
-};
-template <typename Type>
-struct LEInt<Type, 4>
-{
- public:
- inline void set (Type V)
- {
- v[3] = (V >> 24) & 0xFF;
- v[2] = (V >> 16) & 0xFF;
- v[1] = (V >> 8) & 0xFF;
- v[0] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[3] << 24)
- + (v[2] << 16)
- + (v[1] << 8)
- + (v[0] );
- }
- private: uint8_t v[4];
-};
-
-template <typename Type, unsigned int Size>
-struct LEIntType
-{
- inline void set (Type i) { v.set (i); }
- inline operator Type(void) const { return v; }
- inline bool sanitize (OT::hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
- }
- protected:
- LEInt<Type, Size> v;
- public:
- DEFINE_SIZE_STATIC (Size);
-};
-
-typedef LEIntType<uint8_t, 1> LEUINT8; /* 8-bit unsigned integer. */
-typedef LEIntType<int8_t, 1> LEINT8; /* 8-bit signed integer. */
-typedef LEIntType<uint16_t, 2> LEUINT16; /* 16-bit unsigned integer. */
-typedef LEIntType<int16_t, 2> LEINT16; /* 16-bit signed integer. */
-typedef LEIntType<uint32_t, 4> LEUINT32; /* 32-bit unsigned integer. */
-typedef LEIntType<int32_t, 4> LEINT32; /* 32-bit signed integer. */
-typedef LEIntType<uint32_t, 3> LEUINT24; /* 24-bit unsigned integer. */
-
-
-struct LE_FONTINFO16
-{
- inline bool sanitize (OT::hb_sanitize_context_t *c, unsigned int length) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) && c->check_range (this, length)));
- }
-
- // https://msdn.microsoft.com/en-us/library/cc194829.aspx
- enum charset_t
- {
- // dfCharSet possible values and the codepage they are indicating to
- ANSI = 0x00, // 1252
- DEFAULT = 0x01, //
- SYMBOL = 0x02, //
- SHIFTJIS = 0x80, // 932
- HANGUL = 0x81, // 949
- GB2312 = 0x86, // 936
- CHINESEBIG5 = 0x88, // 950
- GREEK = 0xA1, // 1253
- TURKISH = 0xA2, // 1254
- HEBREW = 0xB1, // 1255
- ARABIC = 0xB2, // 1256
- BALTIC = 0xBA, // 1257
- RUSSIAN = 0xCC, // 1251
- THAI = 0xDE, // 874
- EE = 0xEE, // 1250
- OEM = 0xFF //
- };
-
- inline const char* get_charset() const
- {
- switch (dfCharSet) {
- case ANSI: return "ISO8859";
- case DEFAULT: return "WinDefault";
- case SYMBOL: return "Symbol";
- case SHIFTJIS: return "JISX0208.1983";
- case HANGUL: return "MSHangul";
- case GB2312: return "GB2312.1980";
- case CHINESEBIG5: return "Big5";
- case GREEK: return "CP1253";
- case TURKISH: return "CP1254";
- case HEBREW: return "CP1255";
- case ARABIC: return "CP1256";
- case BALTIC: return "CP1257";
- case RUSSIAN: return "CP1251";
- case THAI: return "CP874";
- case EE: return "CP1250";
- case OEM: return "OEM";
- default: return "Unknown";
- }
- }
-
- inline unsigned int get_version () const
- {
- return dfVersion;
- }
-
- inline unsigned int get_weight () const
- {
- return dfWeight;
- }
-
- enum weight_t {
- DONTCARE = 0,
- THIN = 100,
- EXTRALIGHT = 200,
- ULTRALIGHT = 200,
- LIGHT = 300,
- NORMAL = 400,
- REGULAR = 400,
- MEDIUM = 500,
- SEMIBOLD = 600,
- DEMIBOLD = 600,
- BOLD = 700,
- EXTRABOLD = 800,
- ULTRABOLD = 800,
- HEAVY = 900,
- BLACK = 900
- };
-
- inline void dump () const
- {
- // With https://github.com/juanitogan/mkwinfont/blob/master/python/dewinfont.py help
- // Should be implemented differently eventually, but for now
- unsigned int ctstart;
- unsigned int ctsize;
- if (dfVersion == 0x200)
- {
- ctstart = 0x76;
- ctsize = 4;
- }
- else
- {
- return; // must of ".fon"s are version 2 and even dewinfont V1 implmentation doesn't seem correct
- ctstart = 0x94;
- ctsize = 6;
- }
- // unsigned int maxwidth = 0;
- for (unsigned int i = dfFirstChar; i < dfLastChar; ++i)
- {
- unsigned int entry = ctstart + ctsize * (i-dfFirstChar);
- unsigned int w = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry);
-
- unsigned int off;
- if (ctsize == 4)
- off = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry+2);
- else
- off = (uint32_t) OT::StructAtOffset<LEUINT32> (this, entry+2);
-
- unsigned int widthbytes = (w + 7) / 8;
- for (unsigned int j = 0; j < dfPixHeight; ++j)
- {
- for (unsigned int k = 0; k < widthbytes; ++k)
- {
- unsigned int bytepos = off + k * dfPixHeight + j;
- const uint8_t b = (uint8_t) OT::StructAtOffset<LEINT8> (this, bytepos);
- for (unsigned int a = 128; a > 0; a >>= 1)
- printf (b & a ? "x" : ".");
- }
- printf ("\n");
- }
- printf ("\n\n");
- }
- }
-
- protected:
- LEUINT16 dfVersion;
- LEUINT32 dfSize;
- LEUINT8 dfCopyright[60];
- LEUINT16 dfType;
- LEUINT16 dfPoints;
- LEUINT16 dfVertRes;
- LEUINT16 dfHorizRes;
- LEUINT16 dfAscent;
- LEUINT16 dfInternalLeading;
- LEUINT16 dfExternalLeading;
- LEUINT8 dfItalic;
- LEUINT8 dfUnderline;
- LEUINT8 dfStrikeOut;
- LEUINT16 dfWeight; // see weight_t
- LEUINT8 dfCharSet; // see charset_t
- LEUINT16 dfPixWidth;
- LEUINT16 dfPixHeight;
- LEUINT8 dfPitchAndFamily;
- LEUINT16 dfAvgWidth;
- LEUINT16 dfMaxWidth;
- LEUINT8 dfFirstChar;
- LEUINT8 dfLastChar;
- LEUINT8 dfDefaultChar;
- LEUINT8 dfBreakChar;
- LEUINT16 dfWidthBytes;
- LEUINT32 dfDevice;
- LEUINT32 dfFace;
- LEUINT32 dfBitsPointer;
- LEUINT32 dfBitsOffset;
- LEUINT8 dfReserved;
-// LEUINT32 dfFlags;
-// LEUINT16 dfAspace;
-// LEUINT16 dfBspace;
-// LEUINT16 dfCspace;
-// LEUINT32 dfColorPointer;
-// LEUINT32 dfReserved1[4];
- OT::UnsizedArrayOf<LEUINT8>
- dataZ;
- public:
- DEFINE_SIZE_ARRAY (118, dataZ);
-};
-
-struct NE_NAMEINFO
-{
- friend struct NE_TYPEINFO;
-
- inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) &&
- get_font (base, shift).sanitize (c, length << shift)));
- }
-
- inline const LE_FONTINFO16& get_font (const void *base, int shift) const
- {
- return OT::StructAtOffset<LE_FONTINFO16> (base, offset << shift);
- }
-
- enum resource_type_flag_t {
- NONE = 0x0000,
- MOVEABLE = 0x0010,
- PURE = 0x0020,
- PRELOAD = 0x0040
- };
-
- protected:
- LEUINT16 offset; // Should be shifted with alignmentShiftCount before use
- LEUINT16 length; // Should be shifted with alignmentShiftCount before use
- LEUINT16 flags; // resource_type_flag_t
- LEUINT16 id;
- LEUINT16 handle;
- LEUINT16 usage;
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct NE_TYPEINFO
-{
- inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && resources.sanitize (c, count, base, shift));
- }
-
- inline unsigned int get_size (void) const
- { return 8 + count * NE_NAMEINFO::static_size; }
-
- inline const NE_TYPEINFO& next () const
- {
- const NE_TYPEINFO& next = OT::StructAfter<NE_TYPEINFO> (*this);
- if (type_id == 0)
- return Null(NE_TYPEINFO);
- return next;
- }
-
- inline const LE_FONTINFO16& get_font (unsigned int idx, const void *base, int shift) const
- {
- if (idx < count)
- return resources[idx].get_font (base, shift);
- return Null(LE_FONTINFO16);
- }
-
- inline unsigned int get_count () const
- {
- return count;
- }
-
- inline unsigned int get_type_id () const
- {
- return type_id;
- }
-
- enum type_id_t {
- CURSOR = 0x8001,
- BITMAP = 0x8002,
- ICON = 0x8003,
- MENU = 0x8004,
- DIALOG = 0x8005,
- STRING = 0x8006,
- FONT_DIRECTORY = 0x8007,
- FONT = 0x8008,
- ACCELERATOR_TABLE = 0x8009,
- RESOURCE_DATA = 0x800a,
- GROUP_CURSOR = 0x800c,
- GROUP_ICON = 0x800e,
- VERSION = 0x8010
- };
-
- protected:
- LEUINT16 type_id; // see type_id_t
- LEUINT16 count;
- LEUINT32 resloader;
- OT::UnsizedArrayOf<NE_NAMEINFO>
- resources;
- public:
- DEFINE_SIZE_ARRAY (8, resources);
-};
-
-struct NE_RESOURCE_TABLE
-{
- inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
-
- if (!c->check_struct (this))
- return_trace (false);
-
- const NE_TYPEINFO* n = &chain;
- while (n != &Null(NE_TYPEINFO) && c->check_struct (n) && n->get_type_id () != 0)
- {
- if (n->get_type_id () == NE_TYPEINFO::FONT)
- return_trace (n->sanitize (c, base, alignmentShiftCount));
- n = &n->next();
- }
- return_trace (false);
- }
-
- inline unsigned int get_shift_value () const
- {
- return alignmentShiftCount;
- }
-
- inline const NE_TYPEINFO& get_fonts_entry () const
- {
- const NE_TYPEINFO* n = &chain;
- while (n != &Null(NE_TYPEINFO) && n->get_type_id () != 0)
- {
- if (n->get_type_id () == NE_TYPEINFO::FONT)
- return *n;
- n = &n->next();
- }
- return Null(NE_TYPEINFO);
- }
-
- protected:
- LEUINT16 alignmentShiftCount;
- NE_TYPEINFO chain;
- // It is followed by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
- public:
- DEFINE_SIZE_MIN (2);
-};
-
-// https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L2467
-struct LE_IMAGE_OS2_HEADER
-{
- inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) && (this+rsrctab).sanitize (c, base)));
- }
-
- inline const NE_RESOURCE_TABLE& get_resource_table () const
- {
- if (magic != 0x454E) // Only NE containers are support for now, NE == 0x454E
- return Null(NE_RESOURCE_TABLE);
- return this+rsrctab;
- }
-
- protected:
- LEUINT16 magic; /* 00 NE signature 'NE' */
- LEUINT8 ver; /* 02 Linker version number */
- LEUINT8 rev; /* 03 Linker revision number */
- LEUINT16 enttab; /* 04 Offset to entry table relative to NE */
- LEUINT16 cbenttab; /* 06 Length of entry table in bytes */
- LEUINT32 crc; /* 08 Checksum */
- LEUINT16 flags; /* 0c Flags about segments in this file */
- LEUINT16 autodata; /* 0e Automatic data segment number */
- LEUINT16 heap; /* 10 Initial size of local heap */
- LEUINT16 stack; /* 12 Initial size of stack */
- LEUINT32 csip; /* 14 Initial CS:IP */
- LEUINT32 sssp; /* 18 Initial SS:SP */
- LEUINT16 cseg; /* 1c # of entries in segment table */
- LEUINT16 cmod; /* 1e # of entries in module reference tab. */
- LEUINT16 cbnrestab; /* 20 Length of nonresident-name table */
- LEUINT16 segtab; /* 22 Offset to segment table */
- OT::OffsetTo<NE_RESOURCE_TABLE, LEUINT16>
- rsrctab; /* 24 Offset to resource table */
- LEUINT16 restab; /* 26 Offset to resident-name table */
- LEUINT16 modtab; /* 28 Offset to module reference table */
- LEUINT16 imptab; /* 2a Offset to imported name table */
- LEUINT32 nrestab; /* 2c Offset to nonresident-name table */
- LEUINT16 cmovent; /* 30 # of movable entry points */
- LEUINT16 align; /* 32 Logical sector alignment shift count */
- LEUINT16 cres; /* 34 # of resource segments */
- LEUINT8 exetyp; /* 36 Flags indicating target OS */
- LEUINT8 flagsothers; /* 37 Additional information flags */
- LEUINT16 pretthunks; /* 38 Offset to return thunks */
- LEUINT16 psegrefbytes; /* 3a Offset to segment ref. bytes */
- LEUINT16 swaparea; /* 3c Reserved by Microsoft */
- LEUINT16 expver; /* 3e Expected Windows version number */
- public:
- DEFINE_SIZE_STATIC (64);
-};
-
-struct LE_IMAGE_DOS_HEADER {
- inline bool sanitize (OT::hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) &&
- get_os2_header ().sanitize (c, this)));
- }
-
- inline const LE_IMAGE_OS2_HEADER& get_os2_header () const
- {
- return this+e_lfanew;
- }
-
- protected:
- LEUINT16 e_magic; // Magic number
- LEUINT16 e_cblp; // Bytes on last page of file
- LEUINT16 e_cp; // Pages in file
- LEUINT16 e_crlc; // Relocations
- LEUINT16 e_cparhdr; // Size of header in paragraphs
- LEUINT16 e_minalloc; // Minimum extra paragraphs needed
- LEUINT16 e_maxalloc; // Maximum extra paragraphs needed
- LEUINT16 e_ss; // Initial (relative) SS value
- LEUINT16 e_sp; // Initial SP value
- LEUINT16 e_csum; // Checksum
- LEUINT16 e_ip; // Initial IP value
- LEUINT16 e_cs; // Initial (relative) CS value
- LEUINT16 e_lfarlc; // File address of relocation table
- LEUINT16 e_ovno; // Overlay number
- LEUINT16 e_res_0; // Reserved words
- LEUINT16 e_res_1; // Reserved words
- LEUINT16 e_res_2; // Reserved words
- LEUINT16 e_res_3; // Reserved words
- LEUINT16 e_oemid; // OEM identifier (for e_oeminfo)
- LEUINT16 e_oeminfo; // OEM information; e_oemid specific
- LEUINT16 e_res2_0; // Reserved words
- LEUINT16 e_res2_1; // Reserved words
- LEUINT16 e_res2_2; // Reserved words
- LEUINT16 e_res2_3; // Reserved words
- LEUINT16 e_res2_4; // Reserved words
- LEUINT16 e_res2_5; // Reserved words
- LEUINT16 e_res2_6; // Reserved words
- LEUINT16 e_res2_7; // Reserved words
- LEUINT16 e_res2_8; // Reserved words
- LEUINT16 e_res2_9; // Reserved words
- OT::OffsetTo<LE_IMAGE_OS2_HEADER, LEUINT32>
- e_lfanew; // File address of new exe header
- public:
- DEFINE_SIZE_STATIC (64);
-};
-
-int main (int argc, char** argv) {
- hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-
- OT::Sanitizer<LE_IMAGE_DOS_HEADER> sanitizer;
- hb_blob_t *font_blob = sanitizer.sanitize (blob);
- const LE_IMAGE_DOS_HEADER* dos_header = font_blob->as<LE_IMAGE_DOS_HEADER> ();
-
- const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
- int shift = rtable.get_shift_value ();
- const NE_TYPEINFO& entry = rtable.get_fonts_entry ();
- for (unsigned int i = 0; i < entry.get_count (); ++i)
- {
- const LE_FONTINFO16& font = entry.get_font (i, dos_header, shift);
- printf ("version: %x, weight: %d, charset: %s\n", font.get_version (),
- font.get_weight (), font.get_charset ());
- // font.dump ();
- }
- return 0;
-}
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index e7c621c..c742eba 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -328,6 +328,9 @@
# TODO: https://github.com/harfbuzz/harfbuzz/pull/626
if U == 0xA8B4: UISC = Consonant_Medial
+ # TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
+ if U == 0x11134: UISC = Gemination_Mark
+
values = [k for k,v in items if v(U,UISC,UGC)]
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
USE = values[0]
@@ -356,6 +359,13 @@
# https://github.com/roozbehp/unicode-data/issues/8
if U == 0x0A51: UIPC = Bottom
+ # TODO: https://github.com/harfbuzz/harfbuzz/pull/982
+ if UBlock == 'Chakma' and is_VOWEL (U, UISC, UGC):
+ if UIPC == Top:
+ UIPC = Bottom
+ elif UIPC == Bottom:
+ UIPC = Top
+
assert (UIPC in [Not_Applicable, Visual_Order_Left] or
USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC)
diff --git a/src/hb-aat-fmtx-table.hh b/src/hb-aat-fmtx-table.hh
deleted file mode 100644
index aa82c88..0000000
--- a/src/hb-aat-fmtx-table.hh
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2018 Ebrahim Byagowi
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#ifndef HB_AAT_FMTX_TABLE_HH
-#define HB_AAT_FMTX_TABLE_HH
-
-#include "hb-aat-layout-common-private.hh"
-
-/*
- * fmtx -- Font Metrics
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fmtx.html
- */
-#define HB_AAT_TAG_fmtx HB_TAG('f','m','t','x')
-
-
-namespace AAT {
-
-
-struct fmtx
-{
- static const hb_tag_t tableTag = HB_AAT_TAG_fmtx;
-
- inline bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
- }
-
- FixedVersion<>version; /* Version (set to 0x00020000). */
- HBUINT32 glyphIndex; /* The glyph whose points represent the metrics. */
- HBUINT8 horizontalBefore; /* Point number for the horizontal ascent. */
- HBUINT8 horizontalAfter; /* Point number for the horizontal descent. */
- HBUINT8 horizontalCaretHead; /* Point number for the horizontal caret head. */
- HBUINT8 horizontalCaretBase; /* Point number for the horizontal caret base. */
- HBUINT8 verticalBefore; /* Point number for the vertical ascent. */
- HBUINT8 verticalAfter; /* Point number for the vertical descent. */
- HBUINT8 verticalCaretHead; /* Point number for the vertical caret head. */
- HBUINT8 verticalCaretBase; /* Point number for the vertical caret base. */
- public:
- DEFINE_SIZE_STATIC (16);
-};
-
-} /* namespace AAT */
-
-
-#endif /* HB_AAT_FMTX_TABLE_HH */
diff --git a/src/hb-aat-gcid-table.hh b/src/hb-aat-gcid-table.hh
deleted file mode 100644
index b48a279..0000000
--- a/src/hb-aat-gcid-table.hh
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright © 2018 Ebrahim Byagowi
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#ifndef HB_AAT_GCID_TABLE_HH
-#define HB_AAT_GCID_TABLE_HH
-
-#include "hb-aat-layout-common-private.hh"
-
-/*
- * gcid -- Glyphs CIDs
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gcid.html
- */
-#define HB_AAT_TAG_gcid HB_TAG('g','c','i','d')
-
-
-namespace AAT {
-
-
-struct gcid
-{
- static const hb_tag_t tableTag = HB_AAT_TAG_gcid;
-
- inline bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) && CIDs.sanitize (c)));
- }
-
- protected:
- HBUINT16 version; /* Version number (set to 0) */
- HBUINT16 format; /* Data format (set to 0) */
- HBUINT32 size; /* Size of the table, including header */
- HBUINT16 registry; /* The registry ID */
- HBUINT8 registryName[64];
- /* The registry name in ASCII */
- HBUINT16 order; /* The order ID */
- HBUINT8 orderName[64]; /* The order name in ASCII */
- HBUINT16 supplementVersion;
- /* The supplement version */
- ArrayOf<HBUINT16>
- CIDs; /* The CIDs for the glyphs in the font,
- * starting with glyph 0. If a glyph does not correspond
- * to a CID in the identified collection, 0xFFFF is used.
- * This should not exceed the number of glyphs in the font. */
- public:
- DEFINE_SIZE_ARRAY (144, CIDs);
-};
-
-} /* namespace AAT */
-
-
-#endif /* HB_AAT_GCID_TABLE_HH */
diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index 2825b18..d7f3505 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -161,7 +161,7 @@
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (arrayZ.sanitize (c, c->num_glyphs));
+ return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
}
protected:
@@ -625,7 +625,7 @@
sanitizer (), lookup_index (0), debug_depth (0)
{
sanitizer.init (table);
- sanitizer.num_glyphs = face->get_num_glyphs ();
+ sanitizer.set_num_glyphs (face->get_num_glyphs ());
sanitizer.start_processing ();
}
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 7784fae..36d4037 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -36,48 +36,12 @@
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-trak-table.hh"
-#include "hb-aat-fmtx-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-aat-gcid-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise.
/*
- * morx/kerx/trak
+ * morx/kerx/trak/ankr
*/
-#if 0
-static inline const AAT::ankr&
-_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
-{
- if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
- {
- if (blob)
- *blob = hb_blob_get_empty ();
- return Null(AAT::ankr);
- }
- hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- const AAT::ankr& ankr = *(layout->ankr.get ());
- if (blob)
- *blob = layout->ankr.blob;
- return ankr;
-}
-
-static inline const AAT::kerx&
-_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
-{
- if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
- {
- if (blob)
- *blob = hb_blob_get_empty ();
- return Null(AAT::kerx);
- }
- hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- /* XXX this doesn't call set_num_glyphs on sanitizer. */
- const AAT::kerx& kerx = *(layout->kerx.get ());
- if (blob)
- *blob = layout->kerx.blob;
- return kerx;
-}
-
static inline const AAT::morx&
_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
{
@@ -88,36 +52,16 @@
return Null(AAT::morx);
}
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- /* XXX this doesn't call set_num_glyphs on sanitizer. */
- const AAT::morx& morx = *(layout->morx.get ());
+ const AAT::morx& morx = *(layout->table.morx.get ());
if (blob)
- *blob = layout->morx.blob;
+ *blob = layout->table.morx.get_blob ();
return morx;
}
-static inline const AAT::trak&
-_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
-{
- if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
- {
- if (blob)
- *blob = hb_blob_get_empty ();
- return Null(AAT::trak);
- }
- hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- const AAT::trak& trak = *(layout->trak.get ());
- if (blob)
- *blob = layout->trak.blob;
- return trak;
-}
-#endif
-
// static inline void
// _hb_aat_layout_create (hb_face_t *face)
// {
-// OT::Sanitizer<AAT::morx> sanitizer;
-// sanitizer.set_num_glyphs (face->get_num_glyphs ());
-// hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_morx));
+// hb_blob_t *morx_blob = hb_sanitize_context_t ().reference_table<AAT::morx> (face);
// morx_blob->as<AAT::morx> ();
// if (0)
@@ -129,13 +73,11 @@
void
hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
{
-#if 0
hb_blob_t *blob;
const AAT::morx& morx = _get_morx (font->face, &blob);
AAT::hb_aat_apply_context_t c (font, buffer, blob);
morx.apply (&c);
-#endif
}
void
diff --git a/src/hb-atomic-private.hh b/src/hb-atomic-private.hh
index 12caaca..297c646 100644
--- a/src/hb-atomic-private.hh
+++ b/src/hb-atomic-private.hh
@@ -35,7 +35,10 @@
#include "hb-private.hh"
-/* atomic_int */
+/*
+ * Atomic integers and pointers.
+ */
+
/* We need external help for these */
@@ -43,38 +46,77 @@
&& defined(hb_atomic_ptr_impl_get) \
&& defined(hb_atomic_ptr_impl_cmpexch)
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
+/* Defined externally, i.e. in config.h. */
+
+
+#elif !defined(HB_NO_MT) && defined(__ATOMIC_CONSUME)
+
+/* C++11-style GCC primitives. */
+
+#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
+#define hb_atomic_int_impl_set_relaxed(AI, V) __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_get_relaxed(AI) __atomic_load_n ((AI), __ATOMIC_RELAXED)
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V) __atomic_store_n ((P), (V), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get_relaxed(P) __atomic_load_n ((P), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get(P) __atomic_load_n ((P), __ATOMIC_CONSUME)
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+ const void *O = O_; // Need lvalue
+ return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
+
+/* C++11 atomics. */
+
+#include <atomic>
+
+#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_consume))
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+ const void *O = O_; // Need lvalue
+ return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
#include <windows.h>
-/* MinGW has a convoluted history of supporting MemoryBarrier
- * properly. As such, define a function to wrap the whole
- * thing. */
-static inline void _HBMemoryBarrier (void) {
+static inline void _hb_memory_barrier (void)
+{
#if !defined(MemoryBarrier)
+ /* MinGW has a convoluted history of supporting MemoryBarrier. */
long dummy = 0;
InterlockedExchange (&dummy, 1);
#else
MemoryBarrier ();
#endif
}
+#define _hb_memory_barrier() _hb_memory_barrier ()
-typedef LONG hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
+#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((unsigned *) (AI), (V))
-#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V))
+#define _hb_memory_barrier() __sync_synchronize ()
-#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P))
+#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
+
#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
@@ -83,11 +125,28 @@
#include <atomic.h>
#include <mbarrier.h>
-typedef unsigned int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
+#define _hb_memory_r_barrier() __machine_r_barrier ()
+#define _hb_memory_w_barrier() __machine_w_barrier ()
+#define _hb_memory_barrier() __machine_rw_barrier ()
-#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+ _hb_memory_w_barrier ();
+ int result = atomic_add_int_nv ((uint_t *) AI, V);
+ _hb_memory_r_barrier ();
+ return result;
+}
+static inline bool _hb_compare_and_swap_ptr (const void **P, const void *O, const void *N)
+{
+ _hb_memory_w_barrier ();
+ int result = atomic_cas_ptr ((void **) P, (void *) O, (void *) N) == (void *) O;
+ _hb_memory_r_barrier ();
+ return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && defined(__APPLE__)
@@ -99,11 +158,10 @@
#include <Availability.h>
#endif
+#define _hb_memory_barrier() OSMemoryBarrier ()
-typedef int32_t hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
+#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
-#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else
@@ -119,64 +177,105 @@
#include <builtins.h>
+#define _hb_memory_barrier() __lwsync ()
-static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
- __lwsync();
- int result = __fetch_and_add(AI, V);
- __isync();
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+ _hb_memory_barrier ();
+ int result = __fetch_and_add (AI, V);
+ _hb_memory_barrier ();
return result;
}
-static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
- __sync();
- int result = __compare_and_swaplp (P, &O, N);
- __sync();
+static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
+{
+ _hb_memory_barrier ();
+ bool result = __compare_and_swaplp (P, &O, N);
+ _hb_memory_barrier ();
return result;
}
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V))
+#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
-#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
+static_assert ((sizeof (long) == sizeof (void *)), "");
+
#elif !defined(HB_NO_MT)
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
+#define _hb_memory_barrier()
-#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
+#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#else /* HB_NO_MT */
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
+#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
-#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
+#define _hb_memory_barrier()
+
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#endif
-#define HB_ATOMIC_INT_INIT(V) {V}
+#ifndef _hb_memory_r_barrier
+#define _hb_memory_r_barrier() _hb_memory_barrier ()
+#endif
+#ifndef _hb_memory_w_barrier
+#define _hb_memory_w_barrier() _hb_memory_barrier ()
+#endif
+#ifndef hb_atomic_int_impl_set_relaxed
+#define hb_atomic_int_impl_set_relaxed(AI, V) (*(AI) = (V))
+#endif
+#ifndef hb_atomic_int_impl_get_relaxed
+#define hb_atomic_int_impl_get_relaxed(AI) (*(AI))
+#endif
+#ifndef hb_atomic_ptr_impl_set_relaxed
+#define hb_atomic_ptr_impl_set_relaxed(P, V) (*(P) = (V))
+#endif
+#ifndef hb_atomic_ptr_impl_get_relaxed
+#define hb_atomic_ptr_impl_get_relaxed(P) (*(P))
+#endif
+#ifndef hb_atomic_ptr_impl_get
+inline void *hb_atomic_ptr_impl_get (void **P) { void *v = *P; _hb_memory_r_barrier (); return v; }
+#endif
+
+
+#define HB_ATOMIC_INT_INIT(V) {V}
struct hb_atomic_int_t
{
- hb_atomic_int_impl_t v;
+ inline void set_relaxed (int v_) const { hb_atomic_int_impl_set_relaxed (&v, v_); }
+ inline int get_relaxed (void) const { return hb_atomic_int_impl_get_relaxed (&v); }
+ inline int inc (void) { return hb_atomic_int_impl_add (&v, 1); }
+ inline int dec (void) { return hb_atomic_int_impl_add (&v, -1); }
- inline void set_unsafe (int v_) { v = v_; }
- inline int get_unsafe (void) const { return v; }
- inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), 1); }
- inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
+ mutable int v;
};
-#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
-#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
+template <typename T> struct hb_remove_ptr_t { typedef T value; };
+template <typename T> struct hb_remove_ptr_t<T *> { typedef T value; };
+
+#define HB_ATOMIC_PTR_INIT(V) {V}
+template <typename P>
+struct hb_atomic_ptr_t
+{
+ typedef typename hb_remove_ptr_t<P>::value T;
+
+ inline void init (T* v_ = nullptr) { set_relaxed (v_); }
+ inline void set_relaxed (T* v_) const { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
+ inline T *get_relaxed (void) const { return hb_atomic_ptr_impl_get_relaxed (&v); }
+ inline T *get (void) const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+ inline bool cmpexch (const T *old, T *new_) const{ return hb_atomic_ptr_impl_cmpexch (&v, old, new_); }
+
+ mutable T *v;
+};
#endif /* HB_ATOMIC_PRIVATE_HH */
diff --git a/src/hb-blob-private.hh b/src/hb-blob-private.hh
index 56a7b66..49ad68e 100644
--- a/src/hb-blob-private.hh
+++ b/src/hb-blob-private.hh
@@ -57,11 +57,6 @@
HB_INTERNAL bool try_make_writable_inplace (void);
HB_INTERNAL bool try_make_writable_inplace_unix (void);
- inline void lock (void)
- {
- hb_blob_make_immutable (this);
- }
-
template <typename Type>
inline const Type* as (void) const
{
@@ -81,6 +76,7 @@
void *user_data;
hb_destroy_func_t destroy;
};
+DECLARE_NULL_INSTANCE (hb_blob_t);
#endif /* HB_BLOB_PRIVATE_HH */
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 5bab1ab..25c3e05 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -45,6 +45,20 @@
#include <stdlib.h>
+DEFINE_NULL_INSTANCE (hb_blob_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ true, /* immutable */
+
+ nullptr, /* data */
+ 0, /* length */
+ HB_MEMORY_MODE_READONLY, /* mode */
+
+ nullptr, /* user_data */
+ nullptr /* destroy */
+};
+
/**
* hb_blob_create: (skip)
* @data: Pointer to blob data.
@@ -182,20 +196,7 @@
hb_blob_t *
hb_blob_get_empty (void)
{
- static const hb_blob_t _hb_blob_nil = {
- HB_OBJECT_HEADER_STATIC,
-
- true, /* immutable */
-
- nullptr, /* data */
- 0, /* length */
- HB_MEMORY_MODE_READONLY, /* mode */
-
- nullptr, /* user_data */
- nullptr /* destroy */
- };
-
- return const_cast<hb_blob_t *> (&_hb_blob_nil);
+ return const_cast<hb_blob_t *> (&Null(hb_blob_t));
}
/**
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index f458140..a6c4b69 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -83,7 +83,8 @@
* hb_buffer_t
*/
-struct hb_buffer_t {
+struct hb_buffer_t
+{
hb_object_header_t header;
ASSERT_POD ();
@@ -352,6 +353,7 @@
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
};
+DECLARE_NULL_INSTANCE (hb_buffer_t);
/* Loop over clusters. Duplicated in foreach_syllable(). */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index d04e1e8..eb7b01c 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -216,7 +216,7 @@
return;
hb_unicode_funcs_destroy (unicode);
- unicode = hb_unicode_funcs_get_default ();
+ unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
flags = HB_BUFFER_FLAG_DEFAULT;
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
@@ -701,6 +701,28 @@
/* Public API */
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+ HB_BUFFER_FLAG_DEFAULT,
+ HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+ HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+ HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+ HB_BUFFER_MAX_LEN_DEFAULT,
+ HB_BUFFER_MAX_OPS_DEFAULT,
+
+ HB_BUFFER_CONTENT_TYPE_INVALID,
+ HB_SEGMENT_PROPERTIES_DEFAULT,
+ false, /* successful */
+ true, /* have_output */
+ true /* have_positions */
+
+ /* Zero is good enough for everything else. */
+};
+
+
/**
* hb_buffer_create: (Xconstructor)
*
@@ -743,27 +765,7 @@
hb_buffer_t *
hb_buffer_get_empty (void)
{
- static const hb_buffer_t _hb_buffer_nil = {
- HB_OBJECT_HEADER_STATIC,
-
- const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
- HB_BUFFER_FLAG_DEFAULT,
- HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
- HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
- HB_BUFFER_SCRATCH_FLAG_DEFAULT,
- HB_BUFFER_MAX_LEN_DEFAULT,
- HB_BUFFER_MAX_OPS_DEFAULT,
-
- HB_BUFFER_CONTENT_TYPE_INVALID,
- HB_SEGMENT_PROPERTIES_DEFAULT,
- false, /* successful */
- true, /* have_output */
- true /* have_positions */
-
- /* Zero is good enough for everything else. */
- };
-
- return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+ return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
}
/**
@@ -906,7 +908,6 @@
if (!unicode_funcs)
unicode_funcs = hb_unicode_funcs_get_default ();
-
hb_unicode_funcs_reference (unicode_funcs);
hb_unicode_funcs_destroy (buffer->unicode);
buffer->unicode = unicode_funcs;
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 243c216..22dd52f 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -28,6 +28,7 @@
#include "hb-private.hh"
+#include "hb-machinery-private.hh"
#include <locale.h>
#ifdef HAVE_XLOCALE_H
@@ -37,7 +38,7 @@
/* hb_options_t */
-hb_options_union_t _hb_options;
+hb_atomic_int_t _hb_options;
void
_hb_options_init (void)
@@ -50,7 +51,7 @@
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
/* This is idempotent and threadsafe. */
- _hb_options = u;
+ _hb_options.set_relaxed (u.i);
}
@@ -244,15 +245,15 @@
/* Thread-safe lock-free language list */
-static hb_language_item_t *langs;
+static hb_atomic_ptr_t <hb_language_item_t> langs;
#ifdef HB_USE_ATEXIT
static void
free_langs (void)
{
retry:
- hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
- if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr))
+ hb_language_item_t *first_lang = langs.get ();
+ if (unlikely (!langs.cmpexch (first_lang, nullptr)))
goto retry;
while (first_lang) {
@@ -268,7 +269,7 @@
lang_find_or_insert (const char *key)
{
retry:
- hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
+ hb_language_item_t *first_lang = langs.get ();
for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
if (*lang == key)
@@ -286,7 +287,8 @@
return nullptr;
}
- if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+ if (unlikely (!langs.cmpexch (first_lang, lang)))
+ {
lang->fini ();
free (lang);
goto retry;
@@ -368,15 +370,16 @@
hb_language_t
hb_language_get_default (void)
{
- static hb_language_t default_language = HB_LANGUAGE_INVALID;
+ static hb_atomic_ptr_t <hb_language_t> default_language;
- hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
- if (unlikely (language == HB_LANGUAGE_INVALID)) {
+ hb_language_t language = default_language.get ();
+ if (unlikely (language == HB_LANGUAGE_INVALID))
+ {
language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
- (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+ (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
}
- return default_language;
+ return language;
}
@@ -728,47 +731,46 @@
#ifdef USE_XLOCALE
-static HB_LOCALE_T C_locale;
+
+static void free_static_C_locale (void);
+
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_ptr_t<HB_LOCALE_T>::value,
+ hb_C_locale_lazy_loader_t>
+{
+ static inline HB_LOCALE_T create (void)
+ {
+ HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
#ifdef HB_USE_ATEXIT
-static void
-free_C_locale (void)
+ atexit (free_static_C_locale);
+#endif
+
+ return C_locale;
+ }
+ static inline void destroy (HB_LOCALE_T p)
+ {
+ HB_FREE_LOCALE (p);
+ }
+ static inline HB_LOCALE_T get_null (void)
+ {
+ return nullptr;
+ }
+} static_C_locale;
+
+#ifdef HB_USE_ATEXIT
+static
+void free_static_C_locale (void)
{
-retry:
- HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
- if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr))
- goto retry;
-
- if (locale)
- HB_FREE_LOCALE (locale);
+ static_C_locale.free_instance ();
}
#endif
static HB_LOCALE_T
get_C_locale (void)
{
-retry:
- HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
- if (unlikely (!C))
- {
- C = HB_CREATE_LOCALE ("C");
-
- if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
- {
- HB_FREE_LOCALE (C_locale);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_C_locale); /* First person registers atexit() callback. */
-#endif
- }
-
- return C;
+ return static_C_locale.get_unconst ();
}
-#endif
+#endif /* USE_XLOCALE */
static bool
parse_float (const char **pp, const char *end, float *pv)
@@ -845,7 +847,7 @@
}
const char *p = *pp;
- while (*pp < end && ISALNUM(**pp))
+ while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
(*pp)++;
if (p == *pp || *pp - p > 4)
@@ -1069,3 +1071,12 @@
memcpy (buf, s, len);
buf[len] = '\0';
}
+
+/* If there is no visibility control, then hb-static.cc will NOT
+ * define anything. Instead, we get it to define one set in here
+ * only, so only libharfbuzz.so defines them, not other libs. */
+#ifdef HB_NO_VISIBILITY
+#undef HB_NO_VISIBILITY
+#include "hb-static.cc"
+#define HB_NO_VISIBILITY 1
+#endif
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 3bdc3f7..1b916a5 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -269,7 +269,7 @@
return ct_font;
}
-hb_coretext_shaper_face_data_t *
+hb_coretext_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
CGFontRef cg_font = create_cg_font (face);
@@ -280,11 +280,11 @@
return nullptr;
}
- return (hb_coretext_shaper_face_data_t *) cg_font;
+ return (hb_coretext_face_data_t *) cg_font;
}
void
-_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
+_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
{
CFRelease ((CGFontRef) data);
}
@@ -306,7 +306,7 @@
}
-hb_coretext_shaper_font_data_t *
+hb_coretext_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
hb_face_t *face = font->face;
@@ -321,11 +321,11 @@
return nullptr;
}
- return (hb_coretext_shaper_font_data_t *) ct_font;
+ return (hb_coretext_font_data_t *) ct_font;
}
void
-_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
+_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
{
CFRelease ((CTFontRef) data);
}
@@ -348,7 +348,7 @@
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
/* Let there be dragons here... */
- HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
+ HB_SHAPER_DATA (HB_SHAPER, font).set_relaxed ((hb_coretext_font_data_t *) CFRetain (ct_font));
return font;
}
@@ -366,20 +366,20 @@
* shaper shape_plan data
*/
-struct hb_coretext_shaper_shape_plan_data_t {};
+struct hb_coretext_shape_plan_data_t {};
-hb_coretext_shaper_shape_plan_data_t *
+hb_coretext_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_coretext_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shape_plan_data_t *data HB_UNUSED)
{
}
@@ -1329,9 +1329,9 @@
* shaper face data
*/
-struct hb_coretext_aat_shaper_face_data_t {};
+struct hb_coretext_aat_face_data_t {};
-hb_coretext_aat_shaper_face_data_t *
+hb_coretext_aat_face_data_t *
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
{
static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
@@ -1342,7 +1342,7 @@
if (hb_blob_get_length (blob))
{
hb_blob_destroy (blob);
- return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
+ return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
hb_blob_destroy (blob);
}
@@ -1351,7 +1351,7 @@
}
void
-_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
{
}
@@ -1360,16 +1360,16 @@
* shaper font data
*/
-struct hb_coretext_aat_shaper_font_data_t {};
+struct hb_coretext_aat_font_data_t {};
-hb_coretext_aat_shaper_font_data_t *
+hb_coretext_aat_font_data_t *
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
{
- return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
+ return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
void
-_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
{
}
@@ -1378,20 +1378,20 @@
* shaper shape_plan data
*/
-struct hb_coretext_aat_shaper_shape_plan_data_t {};
+struct hb_coretext_aat_shape_plan_data_t {};
-hb_coretext_aat_shaper_shape_plan_data_t *
+hb_coretext_aat_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_coretext_aat_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shape_plan_data_t *data HB_UNUSED)
{
}
diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index ae0b677..9056ffc 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -28,6 +28,7 @@
#define HB_DEBUG_HH
#include "hb-private.hh"
+#include "hb-atomic-private.hh"
#include "hb-dsalgs.hh"
@@ -35,6 +36,47 @@
#define HB_DEBUG 0
#endif
+
+/*
+ * Global runtime options.
+ */
+
+struct hb_options_t
+{
+ unsigned int unused : 1; /* In-case sign bit is here. */
+ unsigned int initialized : 1;
+ unsigned int uniscribe_bug_compatible : 1;
+};
+
+union hb_options_union_t {
+ int i;
+ hb_options_t opts;
+};
+static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+
+HB_INTERNAL void
+_hb_options_init (void);
+
+extern HB_INTERNAL hb_atomic_int_t _hb_options;
+
+static inline hb_options_t
+hb_options (void)
+{
+ /* Make a local copy, so we can access bitfield threadsafely. */
+ hb_options_union_t u;
+ u.i = _hb_options.get_relaxed ();
+
+ if (unlikely (!u.i))
+ _hb_options_init ();
+
+ return u.opts;
+}
+
+
+/*
+ * Debug output (needs enabling at compile time.)
+ */
+
static inline bool
_hb_debug (unsigned int level,
unsigned int max_level)
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index 7c68849..baad818 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -133,7 +133,7 @@
* shaper face data
*/
-struct hb_directwrite_shaper_face_data_t
+struct hb_directwrite_face_data_t
{
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
@@ -143,10 +143,10 @@
hb_blob_t *faceBlob;
};
-hb_directwrite_shaper_face_data_t *
+hb_directwrite_face_data_t *
_hb_directwrite_shaper_face_data_create (hb_face_t *face)
{
- hb_directwrite_shaper_face_data_t *data = new hb_directwrite_shaper_face_data_t;
+ hb_directwrite_face_data_t *data = new hb_directwrite_face_data_t;
if (unlikely (!data))
return nullptr;
@@ -206,7 +206,7 @@
}
void
-_hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *data)
+_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
{
if (data->fontFace)
data->fontFace->Release ();
@@ -233,16 +233,16 @@
* shaper font data
*/
-struct hb_directwrite_shaper_font_data_t
+struct hb_directwrite_font_data_t
{
};
-hb_directwrite_shaper_font_data_t *
+hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return nullptr;
- hb_directwrite_shaper_font_data_t *data = new hb_directwrite_shaper_font_data_t;
+ hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
if (unlikely (!data))
return nullptr;
@@ -250,7 +250,7 @@
}
void
-_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
+_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
delete data;
}
@@ -260,20 +260,20 @@
* shaper shape_plan data
*/
-struct hb_directwrite_shaper_shape_plan_data_t {};
+struct hb_directwrite_shape_plan_data_t {};
-hb_directwrite_shaper_shape_plan_data_t *
+hb_directwrite_shape_plan_data_t *
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_directwrite_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shape_plan_data_t *data HB_UNUSED)
{
}
@@ -555,8 +555,8 @@
float lineWidth)
{
hb_face_t *face = font->face;
- hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
- hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+ hb_directwrite_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+ hb_directwrite_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
IDWriteFontFace *fontFace = face_data->fontFace;
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index 6a8ddaa..8cbe658 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -232,6 +232,18 @@
* Tiny stuff.
*/
+/* ASCII tag/character handling */
+static inline bool ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline bool ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline bool ISSPACE (unsigned char c)
+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
#undef MIN
template <typename Type>
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
@@ -262,6 +274,37 @@
return ((v - 1) | 3) + 1;
}
+template <typename T> class hb_assert_unsigned_t;
+template <> class hb_assert_unsigned_t<unsigned char> {};
+template <> class hb_assert_unsigned_t<unsigned short> {};
+template <> class hb_assert_unsigned_t<unsigned int> {};
+template <> class hb_assert_unsigned_t<unsigned long> {};
+
+template <typename T> static inline bool
+hb_in_range (T u, T lo, T hi)
+{
+ /* The sizeof() is here to force template instantiation.
+ * I'm sure there are better ways to do this but can't think of
+ * one right now. Declaring a variable won't work as HB_UNUSED
+ * is unusable on some platforms and unused types are less likely
+ * to generate a warning than unused variables. */
+ static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
+
+ /* The casts below are important as if T is smaller than int,
+ * the subtract results will become a signed int! */
+ return (T)(u - lo) <= (T)(hi - lo);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+{
+ return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+{
+ return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+}
+
/*
* Sort and search.
@@ -445,305 +488,6 @@
}
-#define HB_VECTOR_INIT {0, 0, false, nullptr}
-template <typename Type, unsigned int StaticSize=8>
-struct hb_vector_t
-{
- unsigned int len;
- unsigned int allocated;
- bool successful;
- Type *arrayZ;
- Type static_array[StaticSize];
-
- void init (void)
- {
- len = 0;
- allocated = ARRAY_LENGTH (static_array);
- successful = true;
- arrayZ = static_array;
- }
-
- inline Type& operator [] (unsigned int i)
- {
- if (unlikely (i >= len))
- return Crap (Type);
- return arrayZ[i];
- }
- inline const Type& operator [] (unsigned int i) const
- {
- if (unlikely (i >= len))
- return Null(Type);
- return arrayZ[i];
- }
-
- inline Type *push (void)
- {
- if (unlikely (!resize (len + 1)))
- return &Crap(Type);
- return &arrayZ[len - 1];
- }
- inline Type *push (const Type& v)
- {
- Type *p = push ();
- *p = v;
- return p;
- }
-
- /* Allocate for size but don't adjust len. */
- inline bool alloc (unsigned int size)
- {
- if (unlikely (!successful))
- return false;
-
- if (likely (size <= allocated))
- return true;
-
- /* Reallocate */
-
- unsigned int new_allocated = allocated;
- while (size >= new_allocated)
- new_allocated += (new_allocated >> 1) + 8;
-
- Type *new_array = nullptr;
-
- if (arrayZ == static_array)
- {
- new_array = (Type *) calloc (new_allocated, sizeof (Type));
- if (new_array)
- memcpy (new_array, arrayZ, len * sizeof (Type));
- }
- else
- {
- bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
- if (likely (!overflows))
- new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
- }
-
- if (unlikely (!new_array))
- {
- successful = false;
- return false;
- }
-
- arrayZ = new_array;
- allocated = new_allocated;
-
- return true;
- }
-
- inline bool resize (int size_)
- {
- unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
- if (!alloc (size))
- return false;
-
- if (size > len)
- memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
-
- len = size;
- return true;
- }
-
- inline void pop (void)
- {
- if (!len) return;
- len--;
- }
-
- inline void remove (unsigned int i)
- {
- if (unlikely (i >= len))
- return;
- memmove (static_cast<void *> (&arrayZ[i]),
- static_cast<void *> (&arrayZ[i + 1]),
- (len - i - 1) * sizeof (Type));
- len--;
- }
-
- inline void shrink (int size_)
- {
- unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
- if (size < len)
- len = size;
- }
-
- template <typename T>
- inline Type *find (T v) {
- for (unsigned int i = 0; i < len; i++)
- if (arrayZ[i] == v)
- return &arrayZ[i];
- return nullptr;
- }
- template <typename T>
- inline const Type *find (T v) const {
- for (unsigned int i = 0; i < len; i++)
- if (arrayZ[i] == v)
- return &arrayZ[i];
- return nullptr;
- }
-
- inline void qsort (int (*cmp)(const void*, const void*))
- {
- ::qsort (arrayZ, len, sizeof (Type), cmp);
- }
-
- inline void qsort (void)
- {
- ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
- }
-
- inline void qsort (unsigned int start, unsigned int end)
- {
- ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
- }
-
- template <typename T>
- inline Type *lsearch (const T &x)
- {
- for (unsigned int i = 0; i < len; i++)
- if (0 == this->arrayZ[i].cmp (&x))
- return &arrayZ[i];
- return nullptr;
- }
-
- template <typename T>
- inline Type *bsearch (const T &x)
- {
- unsigned int i;
- return bfind (x, &i) ? &arrayZ[i] : nullptr;
- }
- template <typename T>
- inline const Type *bsearch (const T &x) const
- {
- unsigned int i;
- return bfind (x, &i) ? &arrayZ[i] : nullptr;
- }
- template <typename T>
- inline bool bfind (const T &x, unsigned int *i) const
- {
- int min = 0, max = (int) this->len - 1;
- while (min <= max)
- {
- int mid = (min + max) / 2;
- int c = this->arrayZ[mid].cmp (&x);
- if (c < 0)
- max = mid - 1;
- else if (c > 0)
- min = mid + 1;
- else
- {
- *i = mid;
- return true;
- }
- }
- if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
- max++;
- *i = max;
- return false;
- }
-
- inline void fini (void)
- {
- if (arrayZ != static_array)
- free (arrayZ);
- arrayZ = nullptr;
- allocated = len = 0;
- }
-};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
- hb_vector_t <item_t, 1> items;
-
- inline void init (void) { items.init (); }
-
- template <typename T>
- inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
- {
- l.lock ();
- item_t *item = items.find (v);
- if (item) {
- if (replace) {
- item_t old = *item;
- *item = v;
- l.unlock ();
- old.fini ();
- }
- else {
- item = nullptr;
- l.unlock ();
- }
- } else {
- item = items.push (v);
- l.unlock ();
- }
- return item;
- }
-
- template <typename T>
- inline void remove (T v, lock_t &l)
- {
- l.lock ();
- item_t *item = items.find (v);
- if (item) {
- item_t old = *item;
- *item = items[items.len - 1];
- items.pop ();
- l.unlock ();
- old.fini ();
- } else {
- l.unlock ();
- }
- }
-
- template <typename T>
- inline bool find (T v, item_t *i, lock_t &l)
- {
- l.lock ();
- item_t *item = items.find (v);
- if (item)
- *i = *item;
- l.unlock ();
- return !!item;
- }
-
- template <typename T>
- inline item_t *find_or_insert (T v, lock_t &l)
- {
- l.lock ();
- item_t *item = items.find (v);
- if (!item) {
- item = items.push (v);
- }
- l.unlock ();
- return item;
- }
-
- inline void fini (lock_t &l)
- {
- if (!items.len) {
- /* No need for locking. */
- items.fini ();
- return;
- }
- l.lock ();
- while (items.len) {
- item_t old = items[items.len - 1];
- items.pop ();
- l.unlock ();
- old.fini ();
- l.lock ();
- }
- items.fini ();
- l.unlock ();
- }
-
-};
-
-
template <typename Type>
struct hb_auto_t : Type
{
@@ -854,8 +598,7 @@
union {
elt_t v[byte_size / sizeof (elt_t)];
#if HB_VECTOR_SIZE
- typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
- vec_t vec[byte_size / sizeof (vec_t)];
+ hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
#endif
} u;
};
diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh
index fe3b8b2..086ce6e 100644
--- a/src/hb-face-private.hh
+++ b/src/hb-face-private.hh
@@ -39,7 +39,8 @@
* hb_face_t
*/
-struct hb_face_t {
+struct hb_face_t
+{
hb_object_header_t header;
ASSERT_POD ();
@@ -55,15 +56,13 @@
struct hb_shaper_data_t shaper_data; /* Various shaper data. */
- /* Various non-shaping data. */
- /* ... */
-
/* Cache */
- struct plan_node_t {
+ struct plan_node_t
+ {
hb_shape_plan_t *shape_plan;
plan_node_t *next;
- } *shape_plans;
-
+ };
+ hb_atomic_ptr_t<plan_node_t> shape_plans;
inline hb_blob_t *reference_table (hb_tag_t tag) const
{
@@ -97,8 +96,7 @@
HB_INTERNAL void load_upem (void) const;
HB_INTERNAL void load_num_glyphs (void) const;
};
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
+DECLARE_NULL_INSTANCE (hb_face_t);
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 2fef09d..49f29d3 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -31,9 +31,6 @@
#include "hb-face-private.hh"
#include "hb-blob-private.hh"
#include "hb-open-file-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-maxp-table.hh"
-
/**
@@ -52,17 +49,22 @@
if (unlikely (!blob))
return 0;
- hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
+ /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
+ /* Make API signature const after. */
+ hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
+ unsigned int ret = ot.get_face_count ();
+ hb_blob_destroy (sanitized);
- return ot.get_face_count ();
+ return ret;
}
/*
* hb_face_t
*/
-const hb_face_t _hb_face_nil = {
+DEFINE_NULL_INSTANCE (hb_face_t) =
+{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@@ -76,12 +78,12 @@
0, /* num_glyphs */
{
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
+#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
},
- nullptr, /* shape_plans */
+ HB_ATOMIC_PTR_INIT (nullptr), /* shape_plans */
};
@@ -188,7 +190,7 @@
if (unlikely (!blob))
blob = hb_blob_get_empty ();
- hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
+ hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
if (unlikely (!closure))
return hb_face_get_empty ();
@@ -214,7 +216,7 @@
hb_face_t *
hb_face_get_empty (void)
{
- return const_cast<hb_face_t *> (&_hb_face_nil);
+ return const_cast<hb_face_t *> (&Null(hb_face_t));
}
@@ -247,7 +249,7 @@
{
if (!hb_object_destroy (face)) return;
- for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
+ for (hb_face_t::plan_node_t *node = face->shape_plans.get (); node; )
{
hb_face_t::plan_node_t *next = node->next;
hb_shape_plan_destroy (node->shape_plan);
@@ -301,7 +303,7 @@
* Since: 0.9.2
**/
void *
-hb_face_get_user_data (hb_face_t *face,
+hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (face, key);
@@ -335,7 +337,7 @@
* Since: 0.9.2
**/
hb_bool_t
-hb_face_is_immutable (hb_face_t *face)
+hb_face_is_immutable (const hb_face_t *face)
{
return face->immutable;
}
@@ -353,8 +355,8 @@
* Since: 0.9.2
**/
hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
- hb_tag_t tag)
+hb_face_reference_table (const hb_face_t *face,
+ hb_tag_t tag)
{
return face->reference_table (tag);
}
@@ -405,7 +407,7 @@
* Since: 0.9.2
**/
unsigned int
-hb_face_get_index (hb_face_t *face)
+hb_face_get_index (const hb_face_t *face)
{
return face->index;
}
@@ -440,20 +442,11 @@
* Since: 0.9.2
**/
unsigned int
-hb_face_get_upem (hb_face_t *face)
+hb_face_get_upem (const hb_face_t *face)
{
return face->get_upem ();
}
-void
-hb_face_t::load_upem (void) const
-{
- hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
- const OT::head *head_table = head_blob->as<OT::head> ();
- upem = head_table->get_upem ();
- hb_blob_destroy (head_blob);
-}
-
/**
* hb_face_set_glyph_count:
* @face: a face.
@@ -484,20 +477,11 @@
* Since: 0.9.7
**/
unsigned int
-hb_face_get_glyph_count (hb_face_t *face)
+hb_face_get_glyph_count (const hb_face_t *face)
{
return face->get_num_glyphs ();
}
-void
-hb_face_t::load_num_glyphs (void) const
-{
- hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
- const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
- num_glyphs = maxp_table->get_num_glyphs ();
- hb_blob_destroy (maxp_blob);
-}
-
/**
* hb_face_get_table_tags:
* @face: a face.
@@ -509,7 +493,7 @@
* Since: 1.6.0
**/
unsigned int
-hb_face_get_table_tags (hb_face_t *face,
+hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */)
diff --git a/src/hb-face.h b/src/hb-face.h
index 983ee56..208092e 100644
--- a/src/hb-face.h
+++ b/src/hb-face.h
@@ -76,19 +76,19 @@
hb_bool_t replace);
HB_EXTERN void *
-hb_face_get_user_data (hb_face_t *face,
+hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key);
HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
HB_EXTERN hb_bool_t
-hb_face_is_immutable (hb_face_t *face);
+hb_face_is_immutable (const hb_face_t *face);
HB_EXTERN hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
- hb_tag_t tag);
+hb_face_reference_table (const hb_face_t *face,
+ hb_tag_t tag);
HB_EXTERN hb_blob_t *
hb_face_reference_blob (hb_face_t *face);
@@ -98,24 +98,24 @@
unsigned int index);
HB_EXTERN unsigned int
-hb_face_get_index (hb_face_t *face);
+hb_face_get_index (const hb_face_t *face);
HB_EXTERN void
hb_face_set_upem (hb_face_t *face,
unsigned int upem);
HB_EXTERN unsigned int
-hb_face_get_upem (hb_face_t *face);
+hb_face_get_upem (const hb_face_t *face);
HB_EXTERN void
hb_face_set_glyph_count (hb_face_t *face,
unsigned int glyph_count);
HB_EXTERN unsigned int
-hb_face_get_glyph_count (hb_face_t *face);
+hb_face_get_glyph_count (const hb_face_t *face);
HB_EXTERN unsigned int
-hb_face_get_table_tags (hb_face_t *face,
+hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */);
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index 3f09c3f..eff20f7 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -36,16 +36,16 @@
* shaper face data
*/
-struct hb_fallback_shaper_face_data_t {};
+struct hb_fallback_face_data_t {};
-hb_fallback_shaper_face_data_t *
+hb_fallback_face_data_t *
_hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
{
- return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
+_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
{
}
@@ -54,16 +54,16 @@
* shaper font data
*/
-struct hb_fallback_shaper_font_data_t {};
+struct hb_fallback_font_data_t {};
-hb_fallback_shaper_font_data_t *
+hb_fallback_font_data_t *
_hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
- return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
+_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
{
}
@@ -72,20 +72,20 @@
* shaper shape_plan data
*/
-struct hb_fallback_shaper_shape_plan_data_t {};
+struct hb_fallback_shape_plan_data_t {};
-hb_fallback_shaper_shape_plan_data_t *
+hb_fallback_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_fallback_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shape_plan_data_t *data HB_UNUSED)
{
}
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 9f657db..d3a4138 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -35,7 +35,6 @@
#include "hb-shaper-private.hh"
-
/*
* hb_font_funcs_t
*/
@@ -47,6 +46,8 @@
HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
@@ -57,7 +58,8 @@
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
/* ^--- Add new callbacks here */
-struct hb_font_funcs_t {
+struct hb_font_funcs_t
+{
hb_object_header_t header;
ASSERT_POD ();
@@ -89,14 +91,15 @@
]) (void);
} get;
};
-
+DECLARE_NULL_INSTANCE (hb_font_funcs_t);
/*
* hb_font_t
*/
-struct hb_font_t {
+struct hb_font_t
+{
hb_object_header_t header;
ASSERT_POD ();
@@ -233,6 +236,32 @@
klass->user_data.glyph_v_advance);
}
+ inline void get_glyph_h_advances (unsigned int count,
+ hb_codepoint_t *first_glyph,
+ unsigned int glyph_stride,
+ hb_position_t *first_advance,
+ unsigned int advance_stride)
+ {
+ return klass->get.f.glyph_h_advances (this, user_data,
+ count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride,
+ klass->user_data.glyph_h_advances);
+ }
+
+ inline void get_glyph_v_advances (unsigned int count,
+ hb_codepoint_t *first_glyph,
+ unsigned int glyph_stride,
+ hb_position_t *first_advance,
+ unsigned int advance_stride)
+ {
+ return klass->get.f.glyph_v_advances (this, user_data,
+ count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride,
+ klass->user_data.glyph_v_advances);
+ }
+
inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y)
{
@@ -341,13 +370,23 @@
hb_direction_t direction,
hb_position_t *x, hb_position_t *y)
{
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+ *x = *y = 0;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
*x = get_glyph_h_advance (glyph);
- *y = 0;
- } else {
- *x = 0;
+ else
*y = get_glyph_v_advance (glyph);
- }
+ }
+ inline void get_glyph_advances_for_direction (hb_direction_t direction,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride)
+ {
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+ else
+ get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
}
inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
@@ -553,6 +592,7 @@
return (float) v * scale / face->get_upem ();
}
};
+DECLARE_NULL_INSTANCE (hb_font_t);
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 4d62b9e..857b8f5 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -29,6 +29,7 @@
#include "hb-private.hh"
#include "hb-font-private.hh"
+#include "hb-machinery-private.hh"
/*
@@ -45,10 +46,10 @@
return false;
}
static hb_bool_t
-hb_font_get_font_h_extents_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
- void *user_data HB_UNUSED)
+hb_font_get_font_h_extents_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_font_extents_t *metrics,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_h_extents (metrics);
if (ret) {
@@ -69,10 +70,10 @@
return false;
}
static hb_bool_t
-hb_font_get_font_v_extents_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
- void *user_data HB_UNUSED)
+hb_font_get_font_v_extents_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_font_extents_t *metrics,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_v_extents (metrics);
if (ret) {
@@ -94,11 +95,11 @@
return false;
}
static hb_bool_t
-hb_font_get_nominal_glyph_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
return font->parent->get_nominal_glyph (unicode, glyph);
}
@@ -115,12 +116,12 @@
return false;
}
static hb_bool_t
-hb_font_get_variation_glyph_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_font_get_variation_glyph_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
}
@@ -129,16 +130,16 @@
static hb_position_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
return font->x_scale;
}
static hb_position_t
-hb_font_get_glyph_h_advance_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_h_advance_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
{
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
}
@@ -146,21 +147,85 @@
static hb_position_t
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
/* TODO use font_extents.ascender+descender */
return font->y_scale;
}
static hb_position_t
-hb_font_get_glyph_v_advance_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_v_advance_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
{
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
}
+#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
+static void
+hb_font_get_glyph_h_advances_default (hb_font_t* font,
+ void* font_data HB_UNUSED,
+ unsigned int count,
+ hb_codepoint_t *first_glyph,
+ unsigned int glyph_stride,
+ hb_position_t *first_advance,
+ unsigned int advance_stride,
+ void *user_data HB_UNUSED)
+{
+ if (font->has_glyph_h_advance_func ())
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->get_glyph_h_advance (*first_glyph);
+ first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+ return;
+ }
+
+ font->parent->get_glyph_h_advances (count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->parent_scale_x_distance (*first_advance);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+}
+
+#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default
+static void
+hb_font_get_glyph_v_advances_default (hb_font_t* font,
+ void* font_data HB_UNUSED,
+ unsigned int count,
+ hb_codepoint_t *first_glyph,
+ unsigned int glyph_stride,
+ hb_position_t *first_advance,
+ unsigned int advance_stride,
+ void *user_data HB_UNUSED)
+{
+ if (font->has_glyph_v_advance_func ())
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->get_glyph_v_advance (*first_glyph);
+ first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+ return;
+ }
+
+ font->parent->get_glyph_v_advances (count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->parent_scale_y_distance (*first_advance);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+}
+
static hb_bool_t
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
@@ -173,12 +238,12 @@
return true;
}
static hb_bool_t
-hb_font_get_glyph_h_origin_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_position_t *x,
- hb_position_t *y,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_h_origin_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
if (ret)
@@ -198,12 +263,12 @@
return false;
}
static hb_bool_t
-hb_font_get_glyph_v_origin_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_position_t *x,
- hb_position_t *y,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_v_origin_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
if (ret)
@@ -221,11 +286,11 @@
return 0;
}
static hb_position_t
-hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_h_kerning_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data HB_UNUSED)
{
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
}
@@ -240,11 +305,11 @@
return 0;
}
static hb_position_t
-hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t top_glyph,
- hb_codepoint_t bottom_glyph,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_v_kerning_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph,
+ hb_codepoint_t bottom_glyph,
+ void *user_data HB_UNUSED)
{
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
}
@@ -260,11 +325,11 @@
return false;
}
static hb_bool_t
-hb_font_get_glyph_extents_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_extents_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
if (ret) {
@@ -287,13 +352,13 @@
return false;
}
static hb_bool_t
-hb_font_get_glyph_contour_point_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- unsigned int point_index,
- hb_position_t *x,
- hb_position_t *y,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_contour_point_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
if (ret)
@@ -312,11 +377,11 @@
return false;
}
static hb_bool_t
-hb_font_get_glyph_name_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- char *name, unsigned int size,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_name_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size,
+ void *user_data HB_UNUSED)
{
return font->parent->get_glyph_name (glyph, name, size);
}
@@ -332,16 +397,17 @@
return false;
}
static hb_bool_t
-hb_font_get_glyph_from_name_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- const char *name, int len, /* -1 means nul-terminated */
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_font_get_glyph_from_name_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
return font->parent->get_glyph_from_name (name, len, glyph);
}
-static const hb_font_funcs_t _hb_font_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@@ -364,7 +430,8 @@
}
}
};
-static const hb_font_funcs_t _hb_font_funcs_parent = {
+
+static const hb_font_funcs_t _hb_font_funcs_default = {
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@@ -381,7 +448,7 @@
},
{
{
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
}
@@ -406,7 +473,7 @@
if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
return hb_font_funcs_get_empty ();
- ffuncs->get = _hb_font_funcs_parent.get;
+ ffuncs->get = _hb_font_funcs_default.get;
return ffuncs;
}
@@ -423,7 +490,7 @@
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
- return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
+ return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
}
/**
@@ -562,9 +629,9 @@
ffuncs->user_data.name = user_data; \
ffuncs->destroy.name = destroy; \
} else { \
- ffuncs->get.f.name = hb_font_get_##name##_parent; \
- ffuncs->user_data.name = nullptr; \
- ffuncs->destroy.name = nullptr; \
+ ffuncs->get.f.name = hb_font_get_##name##_default; \
+ ffuncs->user_data.name = nullptr; \
+ ffuncs->destroy.name = nullptr; \
} \
}
@@ -574,9 +641,8 @@
bool
hb_font_t::has_func (unsigned int i)
{
- if (parent && parent != hb_font_get_empty () && parent->has_func (i))
- return true;
- return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
+ return (this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]) ||
+ (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
}
/* Public getters */
@@ -718,6 +784,43 @@
}
/**
+ * hb_font_get_glyph_h_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride)
+{
+ font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+/**
+ * hb_font_get_glyph_v_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride)
+{
+ font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+
+/**
* hb_font_get_glyph_h_origin:
* @font: a font.
* @glyph:
@@ -921,6 +1024,26 @@
{
return font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
+/**
+ * hb_font_get_glyph_advances_for_direction:
+ * @font: a font.
+ * @direction:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+ hb_direction_t direction,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride)
+{
+ font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
/**
* hb_font_get_glyph_origin_for_direction:
@@ -1100,6 +1223,37 @@
* hb_font_t
*/
+DEFINE_NULL_INSTANCE (hb_font_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ true, /* immutable */
+
+ nullptr, /* parent */
+ const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
+
+ 1000, /* x_scale */
+ 1000, /* y_scale */
+
+ 0, /* x_ppem */
+ 0, /* y_ppem */
+ 0, /* ptem */
+
+ 0, /* num_coords */
+ nullptr, /* coords */
+
+ const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t), /* klass */
+ nullptr, /* user_data */
+ nullptr, /* destroy */
+
+ {
+#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+ }
+};
+
+
/**
* hb_font_create: (Xconstructor)
* @face: a face.
@@ -1187,36 +1341,7 @@
hb_font_t *
hb_font_get_empty (void)
{
- static const hb_font_t _hb_font_nil = {
- HB_OBJECT_HEADER_STATIC,
-
- true, /* immutable */
-
- nullptr, /* parent */
- const_cast<hb_face_t *> (&_hb_face_nil),
-
- 1000, /* x_scale */
- 1000, /* y_scale */
-
- 0, /* x_ppem */
- 0, /* y_ppem */
- 0, /* ptem */
-
- 0, /* num_coords */
- nullptr, /* coords */
-
- const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
- nullptr, /* user_data */
- nullptr, /* destroy */
-
- {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
- }
- };
-
- return const_cast<hb_font_t *> (&_hb_font_nil);
+ return const_cast<hb_font_t *> (&Null(hb_font_t));
}
/**
diff --git a/src/hb-font.h b/src/hb-font.h
index c95b61d..6cd4869 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -132,6 +132,16 @@
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
+typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride,
+ void *user_data);
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
+
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y,
@@ -265,6 +275,38 @@
void *user_data, hb_destroy_func_t destroy);
/**
+ * hb_font_funcs_set_glyph_h_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_h_advances_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_advances_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/**
* hb_font_funcs_set_glyph_h_origin_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
@@ -417,6 +459,21 @@
hb_font_get_glyph_v_advance (hb_font_t *font,
hb_codepoint_t glyph);
+HB_EXTERN void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride);
+HB_EXTERN void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride);
+
HB_EXTERN hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
hb_codepoint_t glyph,
@@ -472,6 +529,14 @@
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+ hb_direction_t direction,
+ unsigned count,
+ hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride);
+HB_EXTERN void
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 6670d9a..01341b6 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -32,6 +32,7 @@
#include "hb-ft.h"
#include "hb-font-private.hh"
+#include "hb-machinery-private.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
@@ -416,30 +417,13 @@
return true;
}
-static hb_font_funcs_t *static_ft_funcs = nullptr;
+static void free_static_ft_funcs (void);
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ft_funcs (void)
+static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
{
-retry:
- hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
- goto retry;
-
- hb_font_funcs_destroy (ft_funcs);
-}
-#endif
-
-static void
-_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
-{
-retry:
- hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-
- if (unlikely (!funcs))
+ static inline hb_font_funcs_t *create (void)
{
- funcs = hb_font_funcs_create ();
+ hb_font_funcs_t *funcs = hb_font_funcs_create ();
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
@@ -458,20 +442,35 @@
hb_font_funcs_make_immutable (funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
- hb_font_funcs_destroy (funcs);
- goto retry;
- }
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_ft_funcs);
+#endif
+
+ return funcs;
+ }
+} static_ft_funcs;
#ifdef HB_USE_ATEXIT
- atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
+static
+void free_static_ft_funcs (void)
+{
+ static_ft_funcs.free_instance ();
+}
#endif
- };
+static hb_font_funcs_t *
+_hb_ft_get_font_funcs (void)
+{
+ return static_ft_funcs.get_unconst ();
+}
+
+static void
+_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+{
bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
hb_font_set_funcs (font,
- funcs,
+ _hb_ft_get_font_funcs (),
_hb_ft_font_create (ft_face, symbol, unref),
_hb_ft_font_destroy);
}
@@ -497,7 +496,10 @@
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
if (error)
+ {
+ free (buffer);
return nullptr;
+ }
return hb_blob_create ((const char *) buffer, length,
HB_MEMORY_MODE_WRITABLE,
@@ -681,46 +683,45 @@
}
-/* Thread-safe, lock-free, FT_Library */
+static void free_static_ft_library (void);
-static FT_Library ft_library;
+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_ptr_t<FT_Library>::value,
+ hb_ft_library_lazy_loader_t>
+{
+ static inline FT_Library create (void)
+ {
+ FT_Library l;
+ if (FT_Init_FreeType (&l))
+ return nullptr;
+
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_ft_library);
+#endif
+
+ return l;
+ }
+ static inline void destroy (FT_Library l)
+ {
+ FT_Done_FreeType (l);
+ }
+ static inline FT_Library get_null (void)
+ {
+ return nullptr;
+ }
+} static_ft_library;
#ifdef HB_USE_ATEXIT
static
-void free_ft_library (void)
+void free_static_ft_library (void)
{
-retry:
- FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
- if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
- goto retry;
-
- FT_Done_FreeType (library);
+ static_ft_library.free_instance ();
}
#endif
static FT_Library
get_ft_library (void)
{
-retry:
- FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-
- if (unlikely (!library))
- {
- /* Not found; allocate one. */
- if (FT_Init_FreeType (&library))
- return nullptr;
-
- if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
- FT_Done_FreeType (library);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_ft_library); /* First person registers atexit() callback. */
-#endif
- }
-
- return library;
+ return static_ft_library.get_unconst ();
}
static void
diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index 246380a..809b22f 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -31,6 +31,7 @@
#include "hb-glib.h"
#include "hb-unicode-private.hh"
+#include "hb-machinery-private.hh"
#if !GLIB_CHECK_VERSION(2,29,14)
@@ -364,30 +365,15 @@
return utf8_decomposed_len;
}
-static hb_unicode_funcs_t *static_glib_funcs = nullptr;
-#ifdef HB_USE_ATEXIT
-static
-void free_static_glib_funcs (void)
+
+static void free_static_glib_funcs (void);
+
+static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
{
-retry:
- hb_unicode_funcs_t *glib_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, glib_funcs, nullptr))
- goto retry;
-
- hb_unicode_funcs_destroy (glib_funcs);
-}
-#endif
-
-hb_unicode_funcs_t *
-hb_glib_get_unicode_funcs (void)
-{
-retry:
- hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
-
- if (unlikely (!funcs))
+ static inline hb_unicode_funcs_t *create (void)
{
- funcs = hb_unicode_funcs_create (nullptr);
+ hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
@@ -396,18 +382,29 @@
hb_unicode_funcs_make_immutable (funcs);
- if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) {
- hb_unicode_funcs_destroy (funcs);
- goto retry;
- }
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_glib_funcs);
+#endif
+
+ return funcs;
+ }
+} static_glib_funcs;
#ifdef HB_USE_ATEXIT
- atexit (free_static_glib_funcs); /* First person registers atexit() callback. */
-#endif
- };
-
- return hb_unicode_funcs_reference (funcs);
+static
+void free_static_glib_funcs (void)
+{
+ static_glib_funcs.free_instance ();
}
+#endif
+
+hb_unicode_funcs_t *
+hb_glib_get_unicode_funcs (void)
+{
+ return static_glib_funcs.get_unconst ();
+}
+
+
#if GLIB_CHECK_VERSION(2,31,10)
diff --git a/src/hb-gobject-structs.cc b/src/hb-gobject-structs.cc
index a96c358..0c8e557 100644
--- a/src/hb-gobject-structs.cc
+++ b/src/hb-gobject-structs.cc
@@ -71,6 +71,7 @@
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
HB_DEFINE_OBJECT_TYPE (set)
+HB_DEFINE_OBJECT_TYPE (map)
HB_DEFINE_OBJECT_TYPE (shape_plan)
HB_DEFINE_OBJECT_TYPE (unicode_funcs)
HB_DEFINE_VALUE_TYPE (feature)
diff --git a/src/hb-gobject-structs.h b/src/hb-gobject-structs.h
index 302dc95..800beed 100644
--- a/src/hb-gobject-structs.h
+++ b/src/hb-gobject-structs.h
@@ -90,6 +90,10 @@
#define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
HB_EXTERN GType
+hb_gobject_map_get_type (void);
+#define HB_GOBJECT_TYPE_MAP (hb_gobject_map_get_type ())
+
+HB_EXTERN GType
hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index c20f6be..1f42a36 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -42,22 +42,24 @@
* shaper face data
*/
-typedef struct hb_graphite2_tablelist_t {
+typedef struct hb_graphite2_tablelist_t
+{
struct hb_graphite2_tablelist_t *next;
hb_blob_t *blob;
unsigned int tag;
} hb_graphite2_tablelist_t;
-struct hb_graphite2_shaper_face_data_t {
+struct hb_graphite2_face_data_t
+{
hb_face_t *face;
gr_face *grface;
- hb_graphite2_tablelist_t *tlist;
+ hb_atomic_ptr_t<hb_graphite2_tablelist_t> tlist;
};
static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
{
- hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
- hb_graphite2_tablelist_t *tlist = face_data->tlist;
+ hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
+ hb_graphite2_tablelist_t *tlist = face_data->tlist.get ();
hb_blob_t *blob = nullptr;
@@ -80,10 +82,10 @@
p->tag = tag;
retry:
- hb_graphite2_tablelist_t *tlist = (hb_graphite2_tablelist_t *) hb_atomic_ptr_get (&face_data->tlist);
+ hb_graphite2_tablelist_t *tlist = face_data->tlist.get ();
p->next = tlist;
- if (!hb_atomic_ptr_cmpexch (&face_data->tlist, tlist, p))
+ if (unlikely (!face_data->tlist.cmpexch (tlist, p)))
goto retry;
}
@@ -93,7 +95,7 @@
return d;
}
-hb_graphite2_shaper_face_data_t *
+hb_graphite2_face_data_t *
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
{
hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
@@ -106,7 +108,7 @@
}
hb_blob_destroy (silf_blob);
- hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
+ hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
if (unlikely (!data))
return nullptr;
@@ -122,9 +124,9 @@
}
void
-_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
+_hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
{
- hb_graphite2_tablelist_t *tlist = data->tlist;
+ hb_graphite2_tablelist_t *tlist = data->tlist.get ();
while (tlist)
{
@@ -154,16 +156,16 @@
* shaper font data
*/
-struct hb_graphite2_shaper_font_data_t {};
+struct hb_graphite2_font_data_t {};
-hb_graphite2_shaper_font_data_t *
+hb_graphite2_font_data_t *
_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
- return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_graphite2_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
+_hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED)
{
}
@@ -181,20 +183,20 @@
* shaper shape_plan data
*/
-struct hb_graphite2_shaper_shape_plan_data_t {};
+struct hb_graphite2_shape_plan_data_t {};
-hb_graphite2_shaper_shape_plan_data_t *
+hb_graphite2_shape_plan_data_t *
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_graphite2_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shape_plan_data_t *data HB_UNUSED)
{
}
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index c52e165..2e3ad36 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -32,6 +32,7 @@
#include "hb-icu.h"
#include "hb-unicode-private.hh"
+#include "hb-machinery-private.hh"
#include <unicode/uchar.h>
#include <unicode/unorm2.h>
@@ -164,10 +165,6 @@
return hb_icu_script_to_script (scriptCode);
}
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-static const UNormalizer2 *normalizer;
-#endif
-
static hb_bool_t
hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t a,
@@ -177,6 +174,7 @@
{
#if U_ICU_VERSION_MAJOR_NUM >= 49
{
+ const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
UChar32 ret = unorm2_composePair (normalizer, a, b);
if (ret < 0) return false;
*ab = ret;
@@ -222,6 +220,7 @@
{
#if U_ICU_VERSION_MAJOR_NUM >= 49
{
+ const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
UChar decomposed[4];
int len;
UErrorCode icu_err = U_ZERO_ERROR;
@@ -345,55 +344,46 @@
}
-static hb_unicode_funcs_t *static_icu_funcs = nullptr;
+static void free_static_icu_funcs (void);
+
+static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
+{
+ static inline hb_unicode_funcs_t *create (void)
+ {
+ void *user_data = nullptr;
+#if U_ICU_VERSION_MAJOR_NUM >= 49
+ UErrorCode icu_err = U_ZERO_ERROR;
+ user_data = (void *) unorm2_getNFCInstance (&icu_err);
+ assert (user_data);
+#endif
+
+ hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
+
+#define HB_UNICODE_FUNC_IMPLEMENT(name) \
+ hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, user_data, nullptr);
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+ hb_unicode_funcs_make_immutable (funcs);
+
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_icu_funcs);
+#endif
+
+ return funcs;
+ }
+} static_icu_funcs;
#ifdef HB_USE_ATEXIT
static
void free_static_icu_funcs (void)
{
-retry:
- hb_unicode_funcs_t *icu_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, icu_funcs, nullptr))
- goto retry;
-
- hb_unicode_funcs_destroy (icu_funcs);
+ static_icu_funcs.free_instance ();
}
#endif
hb_unicode_funcs_t *
hb_icu_get_unicode_funcs (void)
{
-retry:
- hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
-
- if (unlikely (!funcs))
- {
-#if U_ICU_VERSION_MAJOR_NUM >= 49
- if (!hb_atomic_ptr_get (&normalizer)) {
- UErrorCode icu_err = U_ZERO_ERROR;
- /* We ignore failure in getNFCInstace(). */
- (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
- }
-#endif
-
- funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
- hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr);
- HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
- hb_unicode_funcs_make_immutable (funcs);
-
- if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) {
- hb_unicode_funcs_destroy (funcs);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
-#endif
- };
-
- return hb_unicode_funcs_reference (funcs);
+ return static_icu_funcs.get_unconst ();
}
diff --git a/src/hb-iter-private.hh b/src/hb-iter-private.hh
new file mode 100644
index 0000000..314133a
--- /dev/null
+++ b/src/hb-iter-private.hh
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ITER_PRIVATE_HH
+#define HB_ITER_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+/* Unified iterator object.
+ *
+ * The goal of this template is to make the same iterator interface
+ * available to all types, and make it very easy and compact to use.
+ * Iterator objects are small, light-weight, objects that can be
+ * copied by value. If the collection / object being iterated on
+ * is writable, then the iterator points to lvalues, otherwise it
+ * returns rvalues.
+ *
+ * The way to declare, initialize, and use iterators, eg.:
+ *
+ * Iter<const int *> s (src);
+ * Iter<int *> t (dst);
+ * for (; s && t; s++, t++)
+ * *s = *t;
+ */
+
+template <typename T>
+struct Iter;
+
+#if 0
+template <typename T>
+struct Iter
+{
+ explicit inline Iter (const T &c);
+};
+#endif
+
+template <typename T>
+struct Iter<T *>
+{
+ /* Type of items. */
+ typedef T Value;
+
+ /* Constructors. */
+ inline Iter (T *array_, int length_) :
+ array (array_), length (MAX (length_, 0)) {}
+ template <unsigned int length_>
+ explicit inline Iter (T (&array_)[length_]) :
+ array (array_), length (length_) {}
+
+ /* Emptiness. */
+ explicit_operator inline operator bool (void) const { return bool (length); }
+
+ /* Current item. */
+ inline T &operator * (void)
+ {
+ if (unlikely (!length)) return CrapOrNull(T);
+ return *array;
+ }
+ inline T &operator -> (void)
+ {
+ return (operator *);
+ }
+
+ /* Next. */
+ inline Iter<T *> & operator ++ (void)
+ {
+ if (unlikely (!length)) return *this;
+ array++;
+ length--;
+ return *this;
+ }
+ /* Might return void, or a copy of pre-increment iterator. */
+ inline void operator ++ (int)
+ {
+ if (unlikely (!length)) return;
+ array++;
+ length--;
+ }
+
+ /* Some iterators might implement len(). */
+ inline unsigned int len (void) const { return length; }
+
+ /* Some iterators might implement fast-forward.
+ * Only implement it if it's constant-time. */
+ inline void operator += (unsigned int n)
+ {
+ n = MIN (n, length);
+ array += n;
+ length -= n;
+ }
+
+ /* Some iterators might implement random-access.
+ * Only implement it if it's constant-time. */
+ inline Iter<T *> & operator [] (unsigned int i)
+ {
+ if (unlikely (i >= length)) return CrapOrNull(T);
+ return array[i];
+ }
+
+ private:
+ T *array;
+ unsigned int length;
+};
+
+/* XXX Remove
+ * Just to test these compile. */
+static inline void
+m (void)
+{
+ const int src[10] = {};
+ int dst[20];
+
+ Iter<const int *> s (src);
+ Iter<const int *> s2 (src, 5);
+ Iter<int *> t (dst);
+
+ s2 = s;
+
+ for (; s && t; ++s, ++t)
+ {
+ *t = *s;
+ }
+}
+
+#endif /* HB_ITER_PRIVATE_HH */
diff --git a/src/hb-machinery-private.hh b/src/hb-machinery-private.hh
new file mode 100644
index 0000000..99ef485
--- /dev/null
+++ b/src/hb-machinery-private.hh
@@ -0,0 +1,792 @@
+/*
+ * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2012,2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MACHINERY_PRIVATE_HH
+#define HB_MACHINERY_PRIVATE_HH
+
+#include "hb-private.hh"
+#include "hb-blob-private.hh"
+
+#include "hb-iter-private.hh"
+
+
+/*
+ * Casts
+ */
+
+/* Cast to struct T, reference to reference */
+template<typename Type, typename TObject>
+static inline const Type& CastR(const TObject &X)
+{ return reinterpret_cast<const Type&> (X); }
+template<typename Type, typename TObject>
+static inline Type& CastR(TObject &X)
+{ return reinterpret_cast<Type&> (X); }
+
+/* Cast to struct T, pointer to pointer */
+template<typename Type, typename TObject>
+static inline const Type* CastP(const TObject *X)
+{ return reinterpret_cast<const Type*> (X); }
+template<typename Type, typename TObject>
+static inline Type* CastP(TObject *X)
+{ return reinterpret_cast<Type*> (X); }
+
+/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
+ * location pointed to by P plus Ofs bytes. */
+template<typename Type>
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
+{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
+template<typename Type>
+static inline Type& StructAtOffset(void *P, unsigned int offset)
+{ return * reinterpret_cast<Type*> ((char *) P + offset); }
+
+/* StructAfter<T>(X) returns the struct T& that is placed after X.
+ * Works with X of variable size also. X must implement get_size() */
+template<typename Type, typename TObject>
+static inline const Type& StructAfter(const TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+template<typename Type, typename TObject>
+static inline Type& StructAfter(TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+
+
+/*
+ * Size checking
+ */
+
+/* Check _assertion in a method environment */
+#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
+ inline void _instance_assertion_on_line_##_line (void) const \
+ { \
+ static_assert ((_assertion), ""); \
+ ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
+ }
+# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
+# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
+
+/* Check that _code compiles in a method environment */
+#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
+ inline void _compiles_assertion_on_line_##_line (void) const \
+ { _code; }
+# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
+# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
+
+
+#define DEFINE_SIZE_STATIC(size) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
+ static const unsigned int static_size = (size); \
+ static const unsigned int min_size = (size); \
+ inline unsigned int get_size (void) const { return (size); }
+
+#define DEFINE_SIZE_UNION(size, _member) \
+ DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
+ static const unsigned int min_size = (size)
+
+#define DEFINE_SIZE_MIN(size) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
+ static const unsigned int min_size = (size)
+
+#define DEFINE_SIZE_ARRAY(size, array) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
+ DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
+ static const unsigned int min_size = (size)
+
+#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
+ DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
+ static const unsigned int min_size = (size)
+
+
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+ static const unsigned int max_debug_depth = MaxDebugDepth;
+ typedef Return return_t;
+ template <typename T, typename F>
+ inline bool may_dispatch (const T *obj, const F *format) { return true; }
+ static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
+};
+
+
+/*
+ * Sanitize
+ */
+
+/* This limits sanitizing time on really broken fonts. */
+#ifndef HB_SANITIZE_MAX_EDITS
+#define HB_SANITIZE_MAX_EDITS 32
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_FACTOR
+#define HB_SANITIZE_MAX_OPS_FACTOR 8
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MIN
+#define HB_SANITIZE_MAX_OPS_MIN 16384
+#endif
+
+struct hb_sanitize_context_t :
+ hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
+{
+ inline hb_sanitize_context_t (void) :
+ debug_depth (0),
+ start (nullptr), end (nullptr),
+ writable (false), edit_count (0), max_ops (0),
+ blob (nullptr),
+ num_glyphs (65536),
+ num_glyphs_set (false) {}
+
+ inline const char *get_name (void) { return "SANITIZE"; }
+ template <typename T, typename F>
+ inline bool may_dispatch (const T *obj, const F *format)
+ { return format->sanitize (this); }
+ template <typename T>
+ inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
+ static return_t default_return_value (void) { return true; }
+ static return_t no_dispatch_return_value (void) { return false; }
+ bool stop_sublookup_iteration (const return_t r) const { return !r; }
+
+ inline void init (hb_blob_t *b)
+ {
+ this->blob = hb_blob_reference (b);
+ this->writable = false;
+ }
+
+ inline void set_num_glyphs (unsigned int num_glyphs_)
+ {
+ num_glyphs = num_glyphs_;
+ num_glyphs_set = true;
+ }
+ inline unsigned int get_num_glyphs (void) { return num_glyphs; }
+
+ inline void start_processing (void)
+ {
+ this->start = this->blob->data;
+ this->end = this->start + this->blob->length;
+ assert (this->start <= this->end); /* Must not overflow. */
+ this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+ (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+ this->edit_count = 0;
+ this->debug_depth = 0;
+
+ DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
+ "start [%p..%p] (%lu bytes)",
+ this->start, this->end,
+ (unsigned long) (this->end - this->start));
+ }
+
+ inline void end_processing (void)
+ {
+ DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
+ "end [%p..%p] %u edit requests",
+ this->start, this->end, this->edit_count);
+
+ hb_blob_destroy (this->blob);
+ this->blob = nullptr;
+ this->start = this->end = nullptr;
+ }
+
+ inline bool check_range (const void *base, unsigned int len) const
+ {
+ const char *p = (const char *) base;
+ bool ok = this->max_ops-- > 0 &&
+ this->start <= p &&
+ p <= this->end &&
+ (unsigned int) (this->end - p) >= len;
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ p, p + len, len,
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
+
+ inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
+ {
+ const char *p = (const char *) base;
+ bool overflows = hb_unsigned_mul_overflows (len, record_size);
+ unsigned int array_size = record_size * len;
+ bool ok = !overflows && this->check_range (base, array_size);
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
+ p, p + (record_size * len), record_size, len, (unsigned int) array_size,
+ this->start, this->end,
+ overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
+
+ template <typename Type>
+ inline bool check_struct (const Type *obj) const
+ {
+ return likely (this->check_range (obj, obj->min_size));
+ }
+
+ inline bool may_edit (const void *base, unsigned int len)
+ {
+ if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
+ return false;
+
+ const char *p = (const char *) base;
+ this->edit_count++;
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ this->edit_count,
+ p, p + len, len,
+ this->start, this->end,
+ this->writable ? "GRANTED" : "DENIED");
+
+ return this->writable;
+ }
+
+ template <typename Type, typename ValueType>
+ inline bool try_set (const Type *obj, const ValueType &v) {
+ if (this->may_edit (obj, obj->static_size)) {
+ const_cast<Type *> (obj)->set (v);
+ return true;
+ }
+ return false;
+ }
+
+ template <typename Type>
+ inline hb_blob_t *sanitize_blob (hb_blob_t *blob)
+ {
+ bool sane;
+
+ init (blob);
+
+ retry:
+ DEBUG_MSG_FUNC (SANITIZE, start, "start");
+
+ start_processing ();
+
+ if (unlikely (!start))
+ {
+ end_processing ();
+ return blob;
+ }
+
+ Type *t = CastP<Type> (const_cast<char *> (start));
+
+ sane = t->sanitize (this);
+ if (sane)
+ {
+ if (edit_count)
+ {
+ DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
+
+ /* sanitize again to ensure no toe-stepping */
+ edit_count = 0;
+ sane = t->sanitize (this);
+ if (edit_count) {
+ DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
+ sane = false;
+ }
+ }
+ }
+ else
+ {
+ if (edit_count && !writable) {
+ start = hb_blob_get_data_writable (blob, nullptr);
+ end = start + blob->length;
+
+ if (start)
+ {
+ writable = true;
+ /* ok, we made it writable by relocating. try again */
+ DEBUG_MSG_FUNC (SANITIZE, start, "retry");
+ goto retry;
+ }
+ }
+ }
+
+ end_processing ();
+
+ DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
+ if (sane)
+ {
+ hb_blob_make_immutable (blob);
+ return blob;
+ }
+ else
+ {
+ hb_blob_destroy (blob);
+ return hb_blob_get_empty ();
+ }
+ }
+
+ template <typename Type>
+ inline hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
+ {
+ if (!num_glyphs_set)
+ set_num_glyphs (hb_face_get_glyph_count (face));
+ return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
+ }
+
+ mutable unsigned int debug_depth;
+ const char *start, *end;
+ private:
+ bool writable;
+ unsigned int edit_count;
+ mutable int max_ops;
+ hb_blob_t *blob;
+ unsigned int num_glyphs;
+ bool num_glyphs_set;
+};
+
+
+/*
+ * Serialize
+ */
+
+struct hb_serialize_context_t
+{
+ inline hb_serialize_context_t (void *start_, unsigned int size)
+ {
+ this->start = (char *) start_;
+ this->end = this->start + size;
+
+ this->ran_out_of_room = false;
+ this->head = this->start;
+ this->debug_depth = 0;
+ }
+
+ template <typename Type>
+ inline Type *start_serialize (void)
+ {
+ DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
+ "start [%p..%p] (%lu bytes)",
+ this->start, this->end,
+ (unsigned long) (this->end - this->start));
+
+ return start_embed<Type> ();
+ }
+
+ inline void end_serialize (void)
+ {
+ DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
+ "end [%p..%p] serialized %d bytes; %s",
+ this->start, this->end,
+ (int) (this->head - this->start),
+ this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
+ }
+
+ template <typename Type>
+ inline Type *copy (void)
+ {
+ assert (!this->ran_out_of_room);
+ unsigned int len = this->head - this->start;
+ void *p = malloc (len);
+ if (p)
+ memcpy (p, this->start, len);
+ return reinterpret_cast<Type *> (p);
+ }
+
+ template <typename Type>
+ inline Type *allocate_size (unsigned int size)
+ {
+ if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
+ this->ran_out_of_room = true;
+ return nullptr;
+ }
+ memset (this->head, 0, size);
+ char *ret = this->head;
+ this->head += size;
+ return reinterpret_cast<Type *> (ret);
+ }
+
+ template <typename Type>
+ inline Type *allocate_min (void)
+ {
+ return this->allocate_size<Type> (Type::min_size);
+ }
+
+ template <typename Type>
+ inline Type *start_embed (void)
+ {
+ Type *ret = reinterpret_cast<Type *> (this->head);
+ return ret;
+ }
+
+ template <typename Type>
+ inline Type *embed (const Type &obj)
+ {
+ unsigned int size = obj.get_size ();
+ Type *ret = this->allocate_size<Type> (size);
+ if (unlikely (!ret)) return nullptr;
+ memcpy (ret, obj, size);
+ return ret;
+ }
+
+ template <typename Type>
+ inline Type *extend_min (Type &obj)
+ {
+ unsigned int size = obj.min_size;
+ assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
+ if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
+ return reinterpret_cast<Type *> (&obj);
+ }
+
+ template <typename Type>
+ inline Type *extend (Type &obj)
+ {
+ unsigned int size = obj.get_size ();
+ assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
+ if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
+ return reinterpret_cast<Type *> (&obj);
+ }
+
+ unsigned int debug_depth;
+ char *start, *end, *head;
+ bool ran_out_of_room;
+};
+
+
+/*
+ * Supplier
+ */
+
+template <typename Type>
+struct Supplier
+{
+ inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
+ {
+ head = array;
+ len = len_;
+ stride = stride_;
+ }
+ inline const Type operator [] (unsigned int i) const
+ {
+ if (unlikely (i >= len)) return Type ();
+ return * (const Type *) (const void *) ((const char *) head + stride * i);
+ }
+
+ inline Supplier<Type> & operator += (unsigned int count)
+ {
+ if (unlikely (count > len))
+ count = len;
+ len -= count;
+ head = (const Type *) (const void *) ((const char *) head + stride * count);
+ return *this;
+ }
+
+ private:
+ inline Supplier (const Supplier<Type> &); /* Disallow copy */
+ inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
+
+ unsigned int len;
+ unsigned int stride;
+ const Type *head;
+};
+
+
+/*
+ * Big-endian integers.
+ */
+
+template <typename Type, int Bytes> struct BEInt;
+
+template <typename Type>
+struct BEInt<Type, 1>
+{
+ public:
+ inline void set (Type V)
+ {
+ v = V;
+ }
+ inline operator Type (void) const
+ {
+ return v;
+ }
+ private: uint8_t v;
+};
+template <typename Type>
+struct BEInt<Type, 2>
+{
+ public:
+ inline void set (Type V)
+ {
+ v[0] = (V >> 8) & 0xFF;
+ v[1] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 8)
+ + (v[1] );
+ }
+ private: uint8_t v[2];
+};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+ public:
+ inline void set (Type V)
+ {
+ v[0] = (V >> 16) & 0xFF;
+ v[1] = (V >> 8) & 0xFF;
+ v[2] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 16)
+ + (v[1] << 8)
+ + (v[2] );
+ }
+ private: uint8_t v[3];
+};
+template <typename Type>
+struct BEInt<Type, 4>
+{
+ public:
+ inline void set (Type V)
+ {
+ v[0] = (V >> 24) & 0xFF;
+ v[1] = (V >> 16) & 0xFF;
+ v[2] = (V >> 8) & 0xFF;
+ v[3] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] );
+ }
+ private: uint8_t v[4];
+};
+
+
+/*
+ * Lazy loaders.
+ */
+
+template <typename Data, unsigned int WheresData>
+struct hb_data_wrapper_t
+{
+ static_assert (WheresData > 0, "");
+
+ inline Data * get_data (void) const
+ {
+ return *(((Data **) (void *) this) - WheresData);
+ }
+
+ template <typename Stored, typename Subclass>
+ inline Stored * call_create (void) const
+ {
+ Data *data = this->get_data ();
+ return likely (data) ? Subclass::create (data) : nullptr;
+ }
+};
+template <>
+struct hb_data_wrapper_t<void, 0>
+{
+ template <typename Stored, typename Funcs>
+ inline Stored * call_create (void) const
+ {
+ return Funcs::create ();
+ }
+};
+
+template <typename T1, typename T2> struct hb_non_void_t { typedef T1 value; };
+template <typename T2> struct hb_non_void_t<void, T2> { typedef T2 value; };
+
+template <typename Returned,
+ typename Subclass = void,
+ typename Data = void,
+ unsigned int WheresData = 0,
+ typename Stored = Returned>
+struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
+{
+ typedef typename hb_non_void_t<Subclass,
+ hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
+ >::value Funcs;
+
+ inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */
+ inline void init (void) { instance.set_relaxed (nullptr); }
+ inline void fini (void)
+ {
+ do_destroy (instance.get ());
+ }
+ inline void free_instance (void)
+ {
+ retry:
+ Stored *p = instance.get ();
+ if (unlikely (p && !this->instance.cmpexch (p, nullptr)))
+ goto retry;
+ do_destroy (p);
+ }
+
+ inline Stored * do_create (void) const
+ {
+ Stored *p = this->template call_create<Stored, Funcs> ();
+ if (unlikely (!p))
+ p = const_cast<Stored *> (Funcs::get_null ());
+ return p;
+ }
+ static inline void do_destroy (Stored *p)
+ {
+ if (p && p != Funcs::get_null ())
+ Funcs::destroy (p);
+ }
+
+ inline const Returned * operator -> (void) const { return get (); }
+ inline const Returned & operator * (void) const { return *get (); }
+
+ inline Data * get_data (void) const
+ {
+ return *(((Data **) this) - WheresData);
+ }
+
+ inline Stored * get_stored (void) const
+ {
+ retry:
+ Stored *p = this->instance.get ();
+ if (unlikely (!p))
+ {
+ p = do_create ();
+ if (unlikely (!this->instance.cmpexch (nullptr, p)))
+ {
+ do_destroy (p);
+ goto retry;
+ }
+ }
+ return p;
+ }
+
+ inline void set_stored (Stored *instance_)
+ {
+ /* This *must* be called when there are no other threads accessing.
+ * However, to make TSan, etc, happy, we using cmpexch. */
+ retry:
+ Stored *p = this->instance.get ();
+ if (unlikely (!this->instance.cmpexch (p, instance_)))
+ goto retry;
+ do_destroy (p);
+ }
+
+ inline const Returned * get (void) const { return Funcs::convert (get_stored ()); }
+ inline Returned * get_unconst (void) const { return const_cast<Returned *> (Funcs::convert (get_stored ())); }
+
+ /* To be possibly overloaded by subclasses. */
+ static inline Returned* convert (Stored *p) { return p; }
+
+ /* By default null/init/fini the object. */
+ static inline const Stored* get_null (void) { return &Null(Stored); }
+ static inline Stored *create (Data *data)
+ {
+ Stored *p = (Stored *) calloc (1, sizeof (Stored));
+ if (likely (p))
+ p->init (data);
+ return p;
+ }
+ static inline Stored *create (void)
+ {
+ Stored *p = (Stored *) calloc (1, sizeof (Stored));
+ if (likely (p))
+ p->init ();
+ return p;
+ }
+ static inline void destroy (Stored *p)
+ {
+ p->fini ();
+ free (p);
+ }
+
+ private:
+ /* Must only have one pointer. */
+ hb_atomic_ptr_t<Stored *> instance;
+};
+
+/* Specializations. */
+
+template <unsigned int WheresFace, typename T>
+struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
+ hb_face_lazy_loader_t<WheresFace, T>,
+ hb_face_t, WheresFace> {};
+
+template <typename T, unsigned int WheresFace>
+struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
+ hb_table_lazy_loader_t<T, WheresFace>,
+ hb_face_t, WheresFace,
+ hb_blob_t>
+{
+ static inline hb_blob_t *create (hb_face_t *face)
+ {
+ return hb_sanitize_context_t ().reference_table<T> (face);
+ }
+ static inline void destroy (hb_blob_t *p)
+ {
+ hb_blob_destroy (p);
+ }
+ static inline const hb_blob_t *get_null (void)
+ {
+ return hb_blob_get_empty ();
+ }
+ static inline const T* convert (const hb_blob_t *blob)
+ {
+ return blob->as<T> ();
+ }
+
+ inline hb_blob_t* get_blob (void) const
+ {
+ return this->get_stored ();
+ }
+};
+
+template <typename Subclass>
+struct hb_font_funcs_lazy_loader_t : hb_lazy_loader_t<hb_font_funcs_t, Subclass>
+{
+ static inline void destroy (hb_font_funcs_t *p)
+ {
+ hb_font_funcs_destroy (p);
+ }
+ static inline const hb_font_funcs_t *get_null (void)
+ {
+ return hb_font_funcs_get_empty ();
+ }
+};
+template <typename Subclass>
+struct hb_unicode_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unicode_funcs_t, Subclass>
+{
+ static inline void destroy (hb_unicode_funcs_t *p)
+ {
+ hb_unicode_funcs_destroy (p);
+ }
+ static inline const hb_unicode_funcs_t *get_null (void)
+ {
+ return hb_unicode_funcs_get_empty ();
+ }
+};
+
+
+#endif /* HB_MACHINERY_PRIVATE_HH */
diff --git a/src/hb-map.cc b/src/hb-map.cc
index e3ddae4..138a856 100644
--- a/src/hb-map.cc
+++ b/src/hb-map.cc
@@ -157,8 +157,6 @@
*
*
*
- * Return value:
- *
* Since: 1.7.7
**/
void
@@ -188,7 +186,7 @@
/**
* hb_map_del:
* @map: a map.
- * @codepoint:
+ * @key:
*
*
*
@@ -204,7 +202,7 @@
/**
* hb_map_has:
* @map: a map.
- * @codepoint:
+ * @key:
*
*
*
diff --git a/src/hb-null.hh b/src/hb-null.hh
new file mode 100644
index 0000000..91efee6
--- /dev/null
+++ b/src/hb-null.hh
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_NULL_HH
+#define HB_NULL_HH
+
+#include "hb-private.hh"
+
+
+/*
+ * Static pools
+ */
+
+/* Global nul-content Null pool. Enlarge as necessary. */
+
+#define HB_NULL_POOL_SIZE 264
+
+extern HB_INTERNAL
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* Generic nul-content Null objects. */
+template <typename Type>
+static inline Type const & Null (void) {
+ static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+ return *reinterpret_cast<Type const *> (_hb_NullPool);
+}
+#define Null(Type) Null<Type>()
+
+/* Specializaitons for arbitrary-content Null objects expressed in bytes. */
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+} /* Close namespace. */ \
+extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
+template <> \
+/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
+ return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+} \
+namespace Namespace { \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
+
+/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
+#define DECLARE_NULL_INSTANCE(Type) \
+extern HB_INTERNAL const Type _hb_Null_##Type; \
+template <> \
+/*static*/ inline const Type& Null<Type> (void) { \
+ return _hb_Null_##Type; \
+} \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_INSTANCE(Type) \
+const Type _hb_Null_##Type
+
+/* Global writable pool. Enlarge as necessary. */
+
+/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
+ * for correct operation. It only exist to catch and divert program logic bugs instead of
+ * causing bad memory access. So, races there are not actually introducing incorrectness
+ * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
+extern HB_INTERNAL
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* CRAP pool: Common Region for Access Protection. */
+template <typename Type>
+static inline Type& Crap (void) {
+ static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+ Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
+ *obj = Null(Type);
+ return *obj;
+}
+#define Crap(Type) Crap<Type>()
+
+template <typename Type>
+struct CrapOrNull {
+ static inline Type & get (void) { return Crap(Type); }
+};
+template <typename Type>
+struct CrapOrNull<const Type> {
+ static inline Type const & get (void) { return Null(Type); }
+};
+#define CrapOrNull(Type) CrapOrNull<Type>::get ()
+
+
+#endif /* HB_NULL_HH */
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index fcdc925..4955a68 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -35,9 +35,107 @@
#include "hb-private.hh"
#include "hb-atomic-private.hh"
#include "hb-mutex-private.hh"
+#include "hb-vector-private.hh"
-/* reference_count */
+/*
+ * Lockable set
+ */
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+ hb_vector_t <item_t, 1> items;
+
+ inline void init (void) { items.init (); }
+
+ template <typename T>
+ inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item) {
+ if (replace) {
+ item_t old = *item;
+ *item = v;
+ l.unlock ();
+ old.fini ();
+ }
+ else {
+ item = nullptr;
+ l.unlock ();
+ }
+ } else {
+ item = items.push (v);
+ l.unlock ();
+ }
+ return item;
+ }
+
+ template <typename T>
+ inline void remove (T v, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item) {
+ item_t old = *item;
+ *item = items[items.len - 1];
+ items.pop ();
+ l.unlock ();
+ old.fini ();
+ } else {
+ l.unlock ();
+ }
+ }
+
+ template <typename T>
+ inline bool find (T v, item_t *i, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item)
+ *i = *item;
+ l.unlock ();
+ return !!item;
+ }
+
+ template <typename T>
+ inline item_t *find_or_insert (T v, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (!item) {
+ item = items.push (v);
+ }
+ l.unlock ();
+ return item;
+ }
+
+ inline void fini (lock_t &l)
+ {
+ if (!items.len) {
+ /* No need for locking. */
+ items.fini ();
+ return;
+ }
+ l.lock ();
+ while (items.len) {
+ item_t old = items[items.len - 1];
+ items.pop ();
+ l.unlock ();
+ old.fini ();
+ l.lock ();
+ }
+ items.fini ();
+ l.unlock ();
+ }
+
+};
+
+
+/*
+ * Reference-count.
+ */
#define HB_REFERENCE_COUNT_INERT_VALUE 0
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
@@ -45,16 +143,16 @@
struct hb_reference_count_t
{
- hb_atomic_int_t ref_count;
+ mutable hb_atomic_int_t ref_count;
- inline void init (int v) { ref_count.set_unsafe (v); }
- inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
- inline int inc (void) { return ref_count.inc (); }
- inline int dec (void) { return ref_count.dec (); }
- inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
+ inline void init (int v = 1) { ref_count.set_relaxed (v); }
+ inline int get_relaxed (void) const { return ref_count.get_relaxed (); }
+ inline int inc (void) const { return ref_count.inc (); }
+ inline int dec (void) const { return ref_count.dec (); }
+ inline void fini (void) { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
- inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
- inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
+ inline bool is_inert (void) const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
+ inline bool is_valid (void) const { return ref_count.get_relaxed () > 0; }
};
@@ -89,21 +187,25 @@
};
-/* object_header */
+/*
+ * Object header
+ */
struct hb_object_header_t
{
hb_reference_count_t ref_count;
- hb_user_data_array_t *user_data;
+ hb_atomic_ptr_t<hb_user_data_array_t> user_data;
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
+#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)}
private:
ASSERT_POD ();
};
-/* object */
+/*
+ * Object
+ */
template <typename Type>
static inline void hb_object_trace (const Type *obj, const char *function)
@@ -111,7 +213,7 @@
DEBUG_MSG (OBJECT, (void *) obj,
"%s refcount=%d",
function,
- obj ? obj->header.ref_count.get_unsafe () : 0);
+ obj ? obj->header.ref_count.get_relaxed () : 0);
}
template <typename Type>
@@ -129,8 +231,8 @@
template <typename Type>
static inline void hb_object_init (Type *obj)
{
- obj->header.ref_count.init (1);
- obj->header.user_data = nullptr;
+ obj->header.ref_count.init ();
+ obj->header.user_data.init ();
}
template <typename Type>
static inline bool hb_object_is_inert (const Type *obj)
@@ -169,10 +271,11 @@
static inline void hb_object_fini (Type *obj)
{
obj->header.ref_count.fini (); /* Do this before user_data */
- if (obj->header.user_data)
+ hb_user_data_array_t *user_data = obj->header.user_data.get ();
+ if (user_data)
{
- obj->header.user_data->fini ();
- free (obj->header.user_data);
+ user_data->fini ();
+ free (user_data);
}
}
template <typename Type>
@@ -187,14 +290,14 @@
assert (hb_object_is_valid (obj));
retry:
- hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data);
+ hb_user_data_array_t *user_data = obj->header.user_data.get ();
if (unlikely (!user_data))
{
user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
if (unlikely (!user_data))
return false;
user_data->init ();
- if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data)))
+ if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
{
user_data->fini ();
free (user_data);
@@ -209,10 +312,13 @@
static inline void *hb_object_get_user_data (Type *obj,
hb_user_data_key_t *key)
{
- if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data))
+ if (unlikely (!obj || hb_object_is_inert (obj)))
return nullptr;
assert (hb_object_is_valid (obj));
- return obj->header.user_data->get (key);
+ hb_user_data_array_t *user_data = obj->header.user_data.get ();
+ if (!user_data)
+ return nullptr;
+ return user_data->get (key);
}
diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 226c48f..d47bff6 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -484,8 +484,6 @@
struct OpenTypeFontFile
{
- static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
-
enum {
CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 207f6e0..5580565 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -32,484 +32,12 @@
#include "hb-private.hh"
#include "hb-blob-private.hh"
#include "hb-face-private.hh"
+#include "hb-machinery-private.hh"
namespace OT {
-
-/*
- * Casts
- */
-
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
-/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
- * location pointed to by P plus Ofs bytes. */
-template<typename Type>
-static inline const Type& StructAtOffset(const void *P, unsigned int offset)
-{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
-template<typename Type>
-static inline Type& StructAtOffset(void *P, unsigned int offset)
-{ return * reinterpret_cast<Type*> ((char *) P + offset); }
-
-/* StructAfter<T>(X) returns the struct T& that is placed after X.
- * Works with X of variable size also. X must implement get_size() */
-template<typename Type, typename TObject>
-static inline const Type& StructAfter(const TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-template<typename Type, typename TObject>
-static inline Type& StructAfter(TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-
-
-
-/*
- * Size checking
- */
-
-/* Check _assertion in a method environment */
-#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
- inline void _instance_assertion_on_line_##_line (void) const \
- { \
- static_assert ((_assertion), ""); \
- ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
- }
-# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
-# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
-
-/* Check that _code compiles in a method environment */
-#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
- inline void _compiles_assertion_on_line_##_line (void) const \
- { _code; }
-# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
-# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
-
-
-#define DEFINE_SIZE_STATIC(size) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
- static const unsigned int static_size = (size); \
- static const unsigned int min_size = (size); \
- inline unsigned int get_size (void) const { return (size); }
-
-#define DEFINE_SIZE_UNION(size, _member) \
- DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
- static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_MIN(size) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
- static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY(size, array) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
- DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
- static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
- DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
- static const unsigned int min_size = (size)
-
-
-
-/*
- * Dispatch
- */
-
-template <typename Context, typename Return, unsigned int MaxDebugDepth>
-struct hb_dispatch_context_t
-{
- static const unsigned int max_debug_depth = MaxDebugDepth;
- typedef Return return_t;
- template <typename T, typename F>
- inline bool may_dispatch (const T *obj, const F *format) { return true; }
- static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
-};
-
-
-/*
- * Sanitize
- */
-
-/* This limits sanitizing time on really broken fonts. */
-#ifndef HB_SANITIZE_MAX_EDITS
-#define HB_SANITIZE_MAX_EDITS 32
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_MIN
-#define HB_SANITIZE_MAX_OPS_MIN 16384
-#endif
-
-struct hb_sanitize_context_t :
- hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-{
- inline hb_sanitize_context_t (void) :
- debug_depth (0),
- start (nullptr), end (nullptr),
- writable (false), edit_count (0), max_ops (0),
- blob (nullptr),
- num_glyphs (0) {}
-
- inline const char *get_name (void) { return "SANITIZE"; }
- template <typename T, typename F>
- inline bool may_dispatch (const T *obj, const F *format)
- { return format->sanitize (this); }
- template <typename T>
- inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
- static return_t default_return_value (void) { return true; }
- static return_t no_dispatch_return_value (void) { return false; }
- bool stop_sublookup_iteration (const return_t r) const { return !r; }
-
- inline void init (hb_blob_t *b)
- {
- this->blob = hb_blob_reference (b);
- this->writable = false;
- }
-
- inline void start_processing (void)
- {
- this->start = hb_blob_get_data (this->blob, nullptr);
- this->end = this->start + this->blob->length;
- assert (this->start <= this->end); /* Must not overflow. */
- this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
- (unsigned) HB_SANITIZE_MAX_OPS_MIN);
- this->edit_count = 0;
- this->debug_depth = 0;
-
- DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
- "start [%p..%p] (%lu bytes)",
- this->start, this->end,
- (unsigned long) (this->end - this->start));
- }
-
- inline void end_processing (void)
- {
- DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
- "end [%p..%p] %u edit requests",
- this->start, this->end, this->edit_count);
-
- hb_blob_destroy (this->blob);
- this->blob = nullptr;
- this->start = this->end = nullptr;
- }
-
- inline bool check_range (const void *base, unsigned int len) const
- {
- const char *p = (const char *) base;
- bool ok = this->max_ops-- > 0 &&
- this->start <= p &&
- p <= this->end &&
- (unsigned int) (this->end - p) >= len;
-
- DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
- "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
- p, p + len, len,
- this->start, this->end,
- ok ? "OK" : "OUT-OF-RANGE");
-
- return likely (ok);
- }
-
- inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
- {
- const char *p = (const char *) base;
- bool overflows = hb_unsigned_mul_overflows (len, record_size);
- unsigned int array_size = record_size * len;
- bool ok = !overflows && this->check_range (base, array_size);
-
- DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
- "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
- p, p + (record_size * len), record_size, len, (unsigned int) array_size,
- this->start, this->end,
- overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
-
- return likely (ok);
- }
-
- template <typename Type>
- inline bool check_struct (const Type *obj) const
- {
- return likely (this->check_range (obj, obj->min_size));
- }
-
- inline bool may_edit (const void *base, unsigned int len)
- {
- if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
- return false;
-
- const char *p = (const char *) base;
- this->edit_count++;
-
- DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
- "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
- this->edit_count,
- p, p + len, len,
- this->start, this->end,
- this->writable ? "GRANTED" : "DENIED");
-
- return this->writable;
- }
-
- template <typename Type, typename ValueType>
- inline bool try_set (const Type *obj, const ValueType &v) {
- if (this->may_edit (obj, obj->static_size)) {
- const_cast<Type *> (obj)->set (v);
- return true;
- }
- return false;
- }
-
- mutable unsigned int debug_depth;
- const char *start, *end;
- bool writable;
- unsigned int edit_count;
- mutable int max_ops;
- hb_blob_t *blob;
- unsigned int num_glyphs;
-};
-
-
-
-/* Template to sanitize an object. */
-template <typename Type>
-struct Sanitizer
-{
- inline Sanitizer (void) {}
-
- inline hb_blob_t *sanitize (hb_blob_t *blob) {
- bool sane;
-
- /* TODO is_sane() stuff */
-
- c->init (blob);
-
- retry:
- DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
-
- c->start_processing ();
-
- if (unlikely (!c->start)) {
- c->end_processing ();
- return blob;
- }
-
- Type *t = CastP<Type> (const_cast<char *> (c->start));
-
- sane = t->sanitize (c);
- if (sane) {
- if (c->edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
-
- /* sanitize again to ensure no toe-stepping */
- c->edit_count = 0;
- sane = t->sanitize (c);
- if (c->edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
- sane = false;
- }
- }
- } else {
- unsigned int edit_count = c->edit_count;
- if (edit_count && !c->writable) {
- c->start = hb_blob_get_data_writable (blob, nullptr);
- c->end = c->start + blob->length;
-
- if (c->start) {
- c->writable = true;
- /* ok, we made it writable by relocating. try again */
- DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
- goto retry;
- }
- }
- }
-
- c->end_processing ();
-
- DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
- if (sane)
- {
- blob->lock ();
- return blob;
- }
- else
- {
- hb_blob_destroy (blob);
- return hb_blob_get_empty ();
- }
- }
-
- inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
-
- private:
- hb_sanitize_context_t c[1];
-};
-
-
-
-/*
- * Serialize
- */
-
-
-struct hb_serialize_context_t
-{
- inline hb_serialize_context_t (void *start_, unsigned int size)
- {
- this->start = (char *) start_;
- this->end = this->start + size;
-
- this->ran_out_of_room = false;
- this->head = this->start;
- this->debug_depth = 0;
- }
-
- template <typename Type>
- inline Type *start_serialize (void)
- {
- DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
- "start [%p..%p] (%lu bytes)",
- this->start, this->end,
- (unsigned long) (this->end - this->start));
-
- return start_embed<Type> ();
- }
-
- inline void end_serialize (void)
- {
- DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
- "end [%p..%p] serialized %d bytes; %s",
- this->start, this->end,
- (int) (this->head - this->start),
- this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
-
- }
-
- template <typename Type>
- inline Type *copy (void)
- {
- assert (!this->ran_out_of_room);
- unsigned int len = this->head - this->start;
- void *p = malloc (len);
- if (p)
- memcpy (p, this->start, len);
- return reinterpret_cast<Type *> (p);
- }
-
- template <typename Type>
- inline Type *allocate_size (unsigned int size)
- {
- if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
- this->ran_out_of_room = true;
- return nullptr;
- }
- memset (this->head, 0, size);
- char *ret = this->head;
- this->head += size;
- return reinterpret_cast<Type *> (ret);
- }
-
- template <typename Type>
- inline Type *allocate_min (void)
- {
- return this->allocate_size<Type> (Type::min_size);
- }
-
- template <typename Type>
- inline Type *start_embed (void)
- {
- Type *ret = reinterpret_cast<Type *> (this->head);
- return ret;
- }
-
- template <typename Type>
- inline Type *embed (const Type &obj)
- {
- unsigned int size = obj.get_size ();
- Type *ret = this->allocate_size<Type> (size);
- if (unlikely (!ret)) return nullptr;
- memcpy (ret, obj, size);
- return ret;
- }
-
- template <typename Type>
- inline Type *extend_min (Type &obj)
- {
- unsigned int size = obj.min_size;
- assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
- if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
- return reinterpret_cast<Type *> (&obj);
- }
-
- template <typename Type>
- inline Type *extend (Type &obj)
- {
- unsigned int size = obj.get_size ();
- assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
- if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
- return reinterpret_cast<Type *> (&obj);
- }
-
- inline void truncate (void *new_head)
- {
- assert (this->start < new_head && new_head <= this->head);
- this->head = (char *) new_head;
- }
-
- unsigned int debug_depth;
- char *start, *end, *head;
- bool ran_out_of_room;
-};
-
-template <typename Type>
-struct Supplier
-{
- inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
- {
- head = array;
- len = len_;
- stride = stride_;
- }
- inline const Type operator [] (unsigned int i) const
- {
- if (unlikely (i >= len)) return Type ();
- return * (const Type *) (const void *) ((const char *) head + stride * i);
- }
-
- inline Supplier<Type> & operator += (unsigned int count)
- {
- if (unlikely (count > len))
- count = len;
- len -= count;
- head = (const Type *) (const void *) ((const char *) head + stride * count);
- return *this;
- }
-
- private:
- inline Supplier (const Supplier<Type> &); /* Disallow copy */
- inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
-
- unsigned int len;
- unsigned int stride;
- const Type *head;
-};
-
-
/*
*
* The OpenType Font File: Data Types
@@ -523,78 +51,6 @@
* Int types
*/
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
- public:
- inline void set (Type V)
- {
- v = V;
- }
- inline operator Type (void) const
- {
- return v;
- }
- private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
- public:
- inline void set (Type V)
- {
- v[0] = (V >> 8) & 0xFF;
- v[1] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[0] << 8)
- + (v[1] );
- }
- private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
- public:
- inline void set (Type V)
- {
- v[0] = (V >> 16) & 0xFF;
- v[1] = (V >> 8) & 0xFF;
- v[2] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[0] << 16)
- + (v[1] << 8)
- + (v[2] );
- }
- private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
- public:
- inline void set (Type V)
- {
- v[0] = (V >> 24) & 0xFF;
- v[1] = (V >> 16) & 0xFF;
- v[2] = (V >> 8) & 0xFF;
- v[3] = (V ) & 0xFF;
- }
- inline operator Type (void) const
- {
- return (v[0] << 24)
- + (v[1] << 16)
- + (v[2] << 8)
- + (v[3] );
- }
- private: uint8_t v[4];
-};
-
/* Integer types in big-endian order and no alignment requirement */
template <typename Type, unsigned int Size>
struct IntType
@@ -684,7 +140,6 @@
public:
DEFINE_SIZE_STATIC (4);
};
-DEFINE_NULL_DATA (OT, Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
typedef HBUINT16 GlyphID;
@@ -696,7 +151,7 @@
struct Index : HBUINT16 {
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
};
-DEFINE_NULL_DATA (OT, Index, "\xff\xff");
+DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
/* Offset, Null offset = 0 */
template <typename Type>
@@ -765,7 +220,6 @@
};
-
/*
* Template subclasses of Offset that do the dereferencing.
* Use: (base+offset)
@@ -831,7 +285,6 @@
* Array Types
*/
-
/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
template <typename Type>
struct UnsizedArrayOf
@@ -913,7 +366,6 @@
}
};
-
/* An array with a number of elements. */
template <typename Type, typename LenType=HBUINT16>
struct ArrayOf
@@ -1066,7 +518,6 @@
}
};
-
/* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf
@@ -1131,10 +582,7 @@
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
-
-/*
- * An array with sorted elements. Supports binary searching.
- */
+/* An array with sorted elements. Supports binary searching. */
template <typename Type, typename LenType=HBUINT16>
struct SortedArrayOf : ArrayOf<Type, LenType>
{
@@ -1159,10 +607,7 @@
}
};
-/*
- * Binary-search arrays
- */
-
+/* Binary-search arrays */
struct BinSearchHeader
{
inline operator uint32_t (void) const { return len; }
@@ -1198,101 +643,6 @@
struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
- inline void init (hb_face_t *face_)
- {
- face = face_;
- instance = nullptr;
- }
-
- inline void fini (void)
- {
- if (instance && instance != &Null(T))
- {
- instance->fini();
- free (instance);
- }
- }
-
- inline const T* get (void) const
- {
- retry:
- T *p = (T *) hb_atomic_ptr_get (&instance);
- if (unlikely (!p))
- {
- p = (T *) calloc (1, sizeof (T));
- if (unlikely (!p))
- p = const_cast<T *> (&Null(T));
- else
- p->init (face);
- if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
- {
- if (p != &Null(T))
- p->fini ();
- goto retry;
- }
- }
- return p;
- }
-
- inline const T* operator-> (void) const
- {
- return get ();
- }
-
- private:
- hb_face_t *face;
- T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_table_lazy_loader_t
-{
- inline void init (hb_face_t *face_)
- {
- face = face_;
- blob = nullptr;
- }
-
- inline void fini (void)
- {
- hb_blob_destroy (blob);
- }
-
- inline const T* get (void) const
- {
- retry:
- hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
- if (unlikely (!blob_))
- {
- blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
- if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
- {
- hb_blob_destroy (blob_);
- goto retry;
- }
- blob = blob_;
- }
- return blob_->as<T> ();
- }
-
- inline const T* operator-> (void) const
- {
- return get();
- }
-
- private:
- hb_face_t *face;
- mutable hb_blob_t *blob;
-};
-
-
} /* namespace OT */
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 0ea3720..67a9c7d 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -37,6 +37,9 @@
*/
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
+#ifndef HB_MAX_UNICODE_CODEPOINT_VALUE
+#define HB_MAX_UNICODE_CODEPOINT_VALUE 0x10FFFF
+#endif
namespace OT {
@@ -437,8 +440,10 @@
{
for (unsigned int i = 0; i < this->groups.len; i++) {
hb_set_add_range (out,
- this->groups[i].startCharCode,
- this->groups[i].endCharCode);
+ MIN ((unsigned int) this->groups[i].startCharCode,
+ (unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE),
+ MIN ((unsigned int) this->groups[i].endCharCode,
+ (unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE));
}
}
@@ -800,37 +805,37 @@
{
hb_serialize_context_t c (dest, dest_sz);
- OT::cmap *cmap = c.start_serialize<OT::cmap> ();
- if (unlikely (!c.extend_min (*cmap)))
+ cmap *table = c.start_serialize<cmap> ();
+ if (unlikely (!c.extend_min (*table)))
{
return false;
}
- cmap->version.set (0);
+ table->version.set (0);
- if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
+ if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
return false;
// TODO(grieger): Convert the below to a for loop
// Format 4, Plat 0 Encoding Record
- EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
+ EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
format4_plat0_rec.platformID.set (0); // Unicode
format4_plat0_rec.encodingID.set (3);
// Format 4, Plat 3 Encoding Record
- EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
+ EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
format4_plat3_rec.platformID.set (3); // Windows
format4_plat3_rec.encodingID.set (1); // Unicode BMP
// Format 12 Encoding Record
- EncodingRecord &format12_rec = cmap->encodingRecord[2];
+ EncodingRecord &format12_rec = table->encodingRecord[2];
format12_rec.platformID.set (3); // Windows
format12_rec.encodingID.set (10); // Unicode UCS-4
// Write out format 4 sub table
{
- CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
+ CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
subtable.u.format.set (4);
@@ -841,7 +846,7 @@
// Write out format 12 sub table.
{
- CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
+ CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
subtable.u.format.set (12);
CmapSubtableFormat12 &format12 = subtable.u.format12;
@@ -894,57 +899,57 @@
{
inline void init (hb_face_t *face)
{
- this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
- const OT::cmap *cmap = this->blob->as<OT::cmap> ();
- const OT::CmapSubtable *subtable = nullptr;
- const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
+ this->blob = hb_sanitize_context_t().reference_table<cmap> (face);
+ const cmap *table = this->blob->as<cmap> ();
+ const CmapSubtable *subtable = nullptr;
+ const CmapSubtableFormat14 *subtable_uvs = nullptr;
bool symbol = false;
/* 32-bit subtables. */
- if (!subtable) subtable = cmap->find_subtable (3, 10);
- if (!subtable) subtable = cmap->find_subtable (0, 6);
- if (!subtable) subtable = cmap->find_subtable (0, 4);
+ if (!subtable) subtable = table->find_subtable (3, 10);
+ if (!subtable) subtable = table->find_subtable (0, 6);
+ if (!subtable) subtable = table->find_subtable (0, 4);
/* 16-bit subtables. */
- if (!subtable) subtable = cmap->find_subtable (3, 1);
- if (!subtable) subtable = cmap->find_subtable (0, 3);
- if (!subtable) subtable = cmap->find_subtable (0, 2);
- if (!subtable) subtable = cmap->find_subtable (0, 1);
- if (!subtable) subtable = cmap->find_subtable (0, 0);
+ if (!subtable) subtable = table->find_subtable (3, 1);
+ if (!subtable) subtable = table->find_subtable (0, 3);
+ if (!subtable) subtable = table->find_subtable (0, 2);
+ if (!subtable) subtable = table->find_subtable (0, 1);
+ if (!subtable) subtable = table->find_subtable (0, 0);
if (!subtable)
{
- subtable = cmap->find_subtable (3, 0);
+ subtable = table->find_subtable (3, 0);
if (subtable) symbol = true;
}
/* Meh. */
- if (!subtable) subtable = &Null(OT::CmapSubtable);
+ if (!subtable) subtable = &Null(CmapSubtable);
/* UVS subtable. */
if (!subtable_uvs)
{
- const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+ const CmapSubtable *st = table->find_subtable (0, 5);
if (st && st->u.format == 14)
subtable_uvs = &st->u.format14;
}
/* Meh. */
- if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
+ if (!subtable_uvs) subtable_uvs = &Null(CmapSubtableFormat14);
this->uvs_table = subtable_uvs;
this->get_glyph_data = subtable;
if (unlikely (symbol))
{
- this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
+ this->get_glyph_func = get_glyph_from_symbol<CmapSubtable>;
this->get_all_codepoints_func = null_get_all_codepoints_func;
} else {
switch (subtable->u.format) {
/* Accelerate format 4 and format 12. */
default:
- this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
+ this->get_glyph_func = get_glyph_from<CmapSubtable>;
this->get_all_codepoints_func = null_get_all_codepoints_func;
break;
case 12:
- this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
- this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
+ this->get_glyph_func = get_glyph_from<CmapSubtableFormat12>;
+ this->get_all_codepoints_func = get_all_codepoints_from<CmapSubtableFormat12>;
break;
case 4:
{
@@ -977,9 +982,9 @@
variation_selector,
glyph))
{
- case OT::GLYPH_VARIANT_NOT_FOUND: return false;
- case OT::GLYPH_VARIANT_FOUND: return true;
- case OT::GLYPH_VARIANT_USE_DEFAULT: break;
+ case GLYPH_VARIANT_NOT_FOUND: return false;
+ case GLYPH_VARIANT_FOUND: return true;
+ case GLYPH_VARIANT_USE_DEFAULT: break;
}
return get_nominal_glyph (unicode, glyph);
@@ -1046,9 +1051,9 @@
const void *get_glyph_data;
hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
- OT::CmapSubtableFormat4::accelerator_t format4_accel;
+ CmapSubtableFormat4::accelerator_t format4_accel;
- const OT::CmapSubtableFormat14 *uvs_table;
+ const CmapSubtableFormat14 *uvs_table;
hb_blob_t *blob;
};
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index d1dd9de..21c2f47 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -394,8 +394,8 @@
{
upem = hb_face_get_upem (face);
- cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
- cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
+ cblc_blob = hb_sanitize_context_t().reference_table<CBLC> (face);
+ cbdt_blob = hb_sanitize_context_t().reference_table<CBDT> (face);
cbdt_len = hb_blob_get_length (cbdt_blob);
if (hb_blob_get_length (cblc_blob) == 0) {
diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh
index 09a9517..0461afa 100644
--- a/src/hb-ot-color-sbix-table.hh
+++ b/src/hb-ot-color-sbix-table.hh
@@ -68,7 +68,7 @@
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
+ imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
}
protected:
@@ -96,14 +96,9 @@
{
inline void init (hb_face_t *face)
{
- num_glyphs = hb_face_get_glyph_count (face);
-
- OT::Sanitizer<OT::sbix> sanitizer;
- sanitizer.set_num_glyphs (num_glyphs);
- sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
+ sbix_blob = hb_sanitize_context_t().reference_table<sbix> (face);
sbix_len = hb_blob_get_length (sbix_blob);
- sbix_table = sbix_blob->as<OT::sbix> ();
-
+ sbix_table = sbix_blob->as<sbix> ();
}
inline void fini (void)
@@ -134,7 +129,6 @@
unsigned int sbix_len;
unsigned int num_glyphs;
-
};
protected:
diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh
index ed6cf97..3976694 100644
--- a/src/hb-ot-color-svg-table.hh
+++ b/src/hb-ot-color-svg-table.hh
@@ -96,11 +96,9 @@
{
inline void init (hb_face_t *face)
{
- OT::Sanitizer<OT::SVG> sanitizer;
- svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
+ svg_blob = hb_sanitize_context_t().reference_table<SVG> (face);
svg_len = hb_blob_get_length (svg_blob);
- svg = svg_blob->as<OT::SVG> ();
-
+ svg = svg_blob->as<SVG> ();
}
inline void fini (void)
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 8310230..9da8fc7 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -29,6 +29,7 @@
#include "hb-ot.h"
#include "hb-font-private.hh"
+#include "hb-machinery-private.hh"
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
@@ -41,13 +42,39 @@
struct hb_ot_font_t
{
+ inline void init (hb_face_t *face)
+ {
+ cmap.init (face);
+ h_metrics.init (face);
+ v_metrics.init (face, h_metrics.ascender - h_metrics.descender); /* TODO Can we do this lazily? */
+
+ this->face = face;
+ glyf.init ();
+ cbdt.init ();
+ post.init ();
+ kern.init ();
+ }
+ inline void fini (void)
+ {
+ cmap.fini ();
+ h_metrics.fini ();
+ v_metrics.fini ();
+
+ glyf.fini ();
+ cbdt.fini ();
+ post.fini ();
+ kern.fini ();
+ }
+
OT::cmap::accelerator_t cmap;
OT::hmtx::accelerator_t h_metrics;
OT::vmtx::accelerator_t v_metrics;
- OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
- OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
- OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
- OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
+
+ hb_face_t *face; /* MUST be JUST before the lazy loaders. */
+ hb_face_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
+ hb_face_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
+ hb_face_lazy_loader_t<3, OT::post::accelerator_t> post;
+ hb_face_lazy_loader_t<4, OT::kern::accelerator_t> kern;
};
@@ -59,13 +86,7 @@
if (unlikely (!ot_font))
return nullptr;
- ot_font->cmap.init (face);
- ot_font->h_metrics.init (face);
- ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
- ot_font->glyf.init (face);
- ot_font->cbdt.init (face);
- ot_font->post.init (face);
- ot_font->kern.init (face);
+ ot_font->init (face);
return ot_font;
}
@@ -75,13 +96,7 @@
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
- ot_font->cmap.fini ();
- ot_font->h_metrics.fini ();
- ot_font->v_metrics.fini ();
- ot_font->glyf.fini ();
- ot_font->cbdt.fini ();
- ot_font->post.fini ();
- ot_font->kern.fini ();
+ ot_font->fini ();
free (ot_font);
}
@@ -211,30 +226,14 @@
return ot_font->v_metrics.has_font_extents;
}
-static hb_font_funcs_t *static_ot_funcs = nullptr;
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ot_funcs (void)
+static void free_static_ot_funcs (void);
+
+static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
{
-retry:
- hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr))
- goto retry;
-
- hb_font_funcs_destroy (ot_funcs);
-}
-#endif
-
-static hb_font_funcs_t *
-_hb_ot_get_font_funcs (void)
-{
-retry:
- hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-
- if (unlikely (!funcs))
+ static inline hb_font_funcs_t *create (void)
{
- funcs = hb_font_funcs_create ();
+ hb_font_funcs_t *funcs = hb_font_funcs_create ();
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
@@ -253,17 +252,26 @@
hb_font_funcs_make_immutable (funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
- hb_font_funcs_destroy (funcs);
- goto retry;
- }
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_ot_funcs);
+#endif
+
+ return funcs;
+ }
+} static_ot_funcs;
#ifdef HB_USE_ATEXIT
- atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
+static
+void free_static_ot_funcs (void)
+{
+ static_ot_funcs.free_instance ();
+}
#endif
- };
- return funcs;
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs (void)
+{
+ return static_ot_funcs.get_unconst ();
}
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 89c867d..bcf89e4 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -103,14 +103,14 @@
static bool
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
{
- hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
+ hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
hb_blob_destroy (head_blob);
if (unlikely (!head_prime_blob))
return false;
- OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+ head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
@@ -236,20 +236,20 @@
{
memset (this, 0, sizeof (accelerator_t));
- hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
+ hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (face);
const head *head_table = head_blob->as<head> ();
- if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
+ if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
{
- /* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */
+ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
hb_blob_destroy (head_blob);
return;
}
short_offset = 0 == head_table->indexToLocFormat;
hb_blob_destroy (head_blob);
- loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
+ loca_blob = hb_sanitize_context_t().reference_table<loca> (face);
loca_table = loca_blob->as<loca> ();
- glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
+ glyf_blob = hb_sanitize_context_t().reference_table<glyf> (face);
glyf_table = glyf_blob->as<glyf> ();
num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
@@ -270,7 +270,7 @@
inline bool get_composite (hb_codepoint_t glyph,
CompositeGlyphHeader::Iterator *composite /* OUT */) const
{
- if (this->glyf_table == &Null(glyf) || !num_glyphs)
+ if (unlikely (!num_glyphs))
return false;
unsigned int start_offset, end_offset;
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 965e30a..fded120 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -141,8 +141,8 @@
* -1: Only strongly right to left;
* -2: Like -1 but also contains neutrals. */
public:
- HBINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
- HBINT16 glyphDataFormat; /* 0 for current format. */
+ HBUINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
+ HBUINT16 glyphDataFormat; /* 0 for current format. */
DEFINE_SIZE_STATIC (54);
};
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 2c62664..13fa9d6 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -69,7 +69,7 @@
inline bool subset_update_header (hb_subset_plan_t *plan,
unsigned int num_hmetrics) const
{
- hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
+ hb_blob_t *src_blob = hb_sanitize_context_t().reference_table<H> (plan->source, H::tableTag);
hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
hb_blob_destroy (src_blob);
@@ -195,7 +195,7 @@
bool got_font_extents = false;
if (T::os2Tag)
{
- hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
+ hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table<os2> (face);
const os2 *os2_table = os2_blob->as<os2> ();
#define USE_TYPO_METRICS (1u<<7)
if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
@@ -208,7 +208,7 @@
hb_blob_destroy (os2_blob);
}
- hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
+ hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
@@ -222,7 +222,7 @@
has_font_extents = got_font_extents;
- blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
+ blob = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
unsigned int len = hb_blob_get_length (blob);
@@ -240,7 +240,7 @@
}
table = blob->as<hmtxvmtx> ();
- var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
+ var_blob = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
var_table = var_blob->as<HVARVVAR> ();
}
diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh
index b0fdea4..b4d8109 100644
--- a/src/hb-ot-kern-table.hh
+++ b/src/hb-ot-kern-table.hh
@@ -362,7 +362,7 @@
{
inline void init (hb_face_t *face)
{
- blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
+ blob = hb_sanitize_context_t().reference_table<kern> (face);
table = blob->as<kern> ();
table_length = blob->length;
}
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 33dce89..96da07f 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -33,13 +33,16 @@
namespace OT {
-#define NOT_INDEXED ((unsigned int) -1)
-
/*
* BASE -- Baseline
* https://docs.microsoft.com/en-us/typography/opentype/spec/base
*/
+
+/* XXX Review this. */
+#define NOT_INDEXED ((unsigned int) -1)
+
+
struct BaseCoordFormat1
{
inline int get_coord (void) const { return coordinate; }
@@ -52,7 +55,7 @@
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- HBINT16 coordinate; /* X or Y value, in design units */
+ FWORD coordinate; /* X or Y value, in design units */
public:
DEFINE_SIZE_STATIC (4);
};
@@ -73,7 +76,7 @@
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- HBINT16 coordinate; /* X or Y value, in design units */
+ FWORD coordinate; /* X or Y value, in design units */
GlyphID referenceGlyph; /* Glyph ID of control glyph */
HBUINT16 coordPoint; /* Index of contour point on the
* reference glyph */
@@ -97,7 +100,7 @@
protected:
HBUINT16 format; /* Format identifier--format = 3 */
- HBINT16 coordinate; /* X or Y value, in design units */
+ FWORD coordinate; /* X or Y value, in design units */
OffsetTo<Device> deviceTable; /* Offset to Device table for X or
* Y value, from beginning of
* BaseCoord table (may be NULL). */
@@ -109,6 +112,7 @@
{
inline int get_coord (void) const
{
+ /* XXX wire up direction and font. */
switch (u.format) {
case 1: return u.format1.get_coord ();
case 2: return u.format2.get_coord ();
@@ -142,14 +146,10 @@
struct FeatMinMaxRecord
{
- inline int get_min_value (void) const
- { return (this+minCoord).get_coord(); }
+ inline int get_min_value (void) const { return (this+minCoord).get_coord(); }
+ inline int get_max_value (void) const { return (this+maxCoord).get_coord(); }
- inline int get_max_value (void) const
- { return (this+maxCoord).get_coord(); }
-
- inline const Tag &get_tag () const
- { return tag; }
+ inline const Tag& get_tag () const { return tag; }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@@ -181,7 +181,7 @@
unsigned int count = featMinMaxRecords.len;
for (unsigned int i = 0; i < count; i++)
{
- Tag tag = featMinMaxRecords[i].get_tag();
+ Tag tag = featMinMaxRecords[i].get_tag ();
int cmp = tag.cmp(featureTableTag);
if (cmp == 0) return i;
if (cmp > 0) return NOT_INDEXED;
@@ -233,13 +233,13 @@
{ return baseLangSysTag; }
inline unsigned int get_feature_tag_index (Tag featureTableTag) const
- { return (this+minMax).get_feature_tag_index(featureTableTag); }
+ { return (this+minMax).get_feature_tag_index( featureTableTag); }
inline int get_min_value (unsigned int featureTableTagIndex) const
- { return (this+minMax).get_min_value(featureTableTagIndex); }
+ { return (this+minMax).get_min_value( featureTableTagIndex); }
inline int get_max_value (unsigned int featureTableTagIndex) const
- { return (this+minMax).get_max_value(featureTableTagIndex); }
+ { return (this+minMax).get_max_value (featureTableTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@@ -263,34 +263,34 @@
inline int get_base_coord (unsigned int baselineTagIndex) const
{
- return (this+baseCoords[baselineTagIndex]).get_coord();
+ return (this+baseCoords[baselineTagIndex]).get_coord ();
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- defaultIndex <= baseCoordCount &&
- baseCoords.sanitize (c, this));
+ baseCoords.sanitize (c, this));
}
protected:
Index defaultIndex;
- HBUINT16 baseCoordCount;
OffsetArrayOf<BaseCoord> baseCoords;
public:
- DEFINE_SIZE_ARRAY (6, baseCoords);
-
+ DEFINE_SIZE_ARRAY (4, baseCoords);
};
struct BaseScript {
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
{
+ /* XXX bsearch */
Tag tag;
int cmp;
- for (unsigned int i = 0; i < baseLangSysCount; i++) {
- tag = baseLangSysRecords[i].get_tag();
+ unsigned int count = baseLangSysRecords.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ tag = baseLangSysRecords[i].get_tag ();
// taking advantage of alphabetical order
cmp = tag.cmp(baseLangSysTag);
if (cmp == 0) return i;
@@ -301,51 +301,50 @@
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
{
- if (baseLangSysIndex == NOT_INDEXED) {
+ if (baseLangSysIndex == NOT_INDEXED)
+ {
if (unlikely(defaultMinMax)) return NOT_INDEXED;
- return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
+ return (this+defaultMinMax).get_feature_tag_index (featureTableTag);
}
- if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
- return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
+ return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index (featureTableTag);
}
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
if (baseLangSysIndex == NOT_INDEXED)
- return (this+defaultMinMax).get_min_value(featureTableTagIndex);
- return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+ return (this+defaultMinMax).get_min_value (featureTableTagIndex);
+ return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
}
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
if (baseLangSysIndex == NOT_INDEXED)
- return (this+defaultMinMax).get_min_value(featureTableTagIndex);
- return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+ return (this+defaultMinMax).get_min_value (featureTableTagIndex);
+ return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
}
inline unsigned int get_default_base_tag_index (void) const
- { return (this+baseValues).get_default_base_tag_index(); }
+ { return (this+baseValues).get_default_base_tag_index (); }
inline int get_base_coord (unsigned int baselineTagIndex) const
- { return (this+baseValues).get_base_coord(baselineTagIndex); }
+ { return (this+baseValues).get_base_coord (baselineTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- baseValues.sanitize (c, this) &&
- defaultMinMax.sanitize (c, this) &&
- baseLangSysRecords.sanitize (c, this));
+ baseValues.sanitize (c, this) &&
+ defaultMinMax.sanitize (c, this) &&
+ baseLangSysRecords.sanitize (c, this));
}
protected:
- OffsetTo<BaseValues> baseValues;
- OffsetTo<MinMax> defaultMinMax;
- HBUINT16 baseLangSysCount;
- ArrayOf<BaseLangSysRecord> baseLangSysRecords;
+ OffsetTo<BaseValues> baseValues;
+ OffsetTo<MinMax> defaultMinMax;
+ ArrayOf<BaseLangSysRecord> baseLangSysRecords;
public:
- DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+ DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
};
@@ -355,29 +354,28 @@
{ return baseScriptTag; }
inline unsigned int get_default_base_tag_index(void) const
- { return (this+baseScript).get_default_base_tag_index(); }
+ { return (this+baseScript).get_default_base_tag_index (); }
inline int get_base_coord(unsigned int baselineTagIndex) const
- { return (this+baseScript).get_base_coord(baselineTagIndex); }
+ { return (this+baseScript).get_base_coord (baselineTagIndex); }
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
- { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
+ { return (this+baseScript).get_lang_tag_index (baseLangSysTag); }
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
- { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+ { return (this+baseScript).get_feature_tag_index (baseLangSysIndex, featureTableTag); }
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
- { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+ { return (this+baseScript).get_max_value (baseLangSysIndex, featureTableTagIndex); }
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
- { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
+ { return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- baseScript != Null(OffsetTo<BaseScript>) &&
- baseScript.sanitize (c, base));
+ baseScript.sanitize (c, base));
}
protected:
@@ -392,7 +390,9 @@
inline unsigned int get_base_script_index (Tag baseScriptTag) const
{
- for (unsigned int i = 0; i < baseScriptCount; i++)
+ /* XXX bsearch? */
+ unsigned int count = baseScriptRecords.len;
+ for (unsigned int i = 0; i < count; i++)
if (baseScriptRecords[i].get_tag() == baseScriptTag)
return i;
return NOT_INDEXED;
@@ -400,7 +400,6 @@
inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
{
- if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
}
@@ -411,13 +410,11 @@
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
- if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
}
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
- if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
}
@@ -435,24 +432,23 @@
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- baseScriptRecords.sanitize (c, this));
+ baseScriptRecords.sanitize (c, this));
}
protected:
- HBUINT16 baseScriptCount;
- ArrayOf<BaseScriptRecord> baseScriptRecords;
+ ArrayOf<BaseScriptRecord> baseScriptRecords;
public:
- DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
+ DEFINE_SIZE_ARRAY (2, baseScriptRecords);
};
struct BaseTagList
{
-
- inline unsigned int get_tag_index(Tag baselineTag) const
+ inline unsigned int get_tag_index (Tag baselineTag) const
{
- for (unsigned int i = 0; i < baseTagCount; i++)
+ /* TODO bsearch? */
+ unsigned int count = baselineTags.len;
+ for (unsigned int i = 0; i < count; i++)
if (baselineTags[i] == baselineTag)
return i;
return NOT_INDEXED;
@@ -465,42 +461,37 @@
}
protected:
- HBUINT16 baseTagCount;
SortedArrayOf<Tag> baselineTags;
public:
- DEFINE_SIZE_ARRAY (4, baselineTags);
+ DEFINE_SIZE_ARRAY (2, baselineTags);
};
struct Axis
{
- inline unsigned int get_base_tag_index(Tag baselineTag) const
+ inline unsigned int get_base_tag_index (Tag baselineTag) const
{
- if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
return (this+baseTagList).get_tag_index(baselineTag);
}
inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
- if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
}
- inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+ inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
}
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
- if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
}
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
- if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
}
@@ -518,13 +509,13 @@
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
- baseTagList.sanitize (c, this) &&
- baseScriptList.sanitize (c, this));
+ baseTagList.sanitize (c, this) &&
+ baseScriptList.sanitize (c, this));
}
protected:
- OffsetTo<BaseTagList> baseTagList;
- OffsetTo<BaseScriptList> baseScriptList;
+ OffsetTo<BaseTagList> baseTagList;
+ OffsetTo<BaseScriptList> baseScriptList;
public:
DEFINE_SIZE_STATIC (4);
@@ -534,96 +525,78 @@
{
static const hb_tag_t tableTag = HB_OT_TAG_BASE;
- inline bool has_vert_axis(void)
- { return vertAxis != Null(OffsetTo<Axis>); }
+ inline bool has_v_axis(void) { return vAxis != 0; }
- inline bool has_horiz_axis(void)
- { return horizAxis != Null(OffsetTo<Axis>); }
+ inline bool has_h_axis(void) { return hAxis != 0; }
- // horizontal axis base coords:
-
- inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+ inline unsigned int get_h_base_tag_index (Tag baselineTag) const
{
- if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+horizAxis).get_base_tag_index(baselineTag);
+ return (this+hAxis).get_base_tag_index(baselineTag);
}
- inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+ inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
- if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+ return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
}
- inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+ inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
- return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+ return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
}
- // vertical axis base coords:
-
- inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+ inline unsigned int get_v_base_tag_index(Tag baselineTag) const
{
- if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+vertAxis).get_base_tag_index(baselineTag);
+ return (this+vAxis).get_base_tag_index(baselineTag);
}
- inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+ inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
- if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+ return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
}
- inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+ inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
- return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+ return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
}
- // horizontal axis min/max coords:
-
- inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+ inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
- if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+ return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
}
- inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+ inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
- if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+ return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
}
- inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+ inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
- return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+ return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
- inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+ inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
- return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+ return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
- // vertical axis min/max coords:
-
- inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+ inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
- if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+ return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
}
- inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+ inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
- if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
- return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+ return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
}
- inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+ inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
- return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+ return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
- inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+ inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
- return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+ return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -631,15 +604,15 @@
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
likely (version.major == 1) &&
- horizAxis.sanitize (c, this) &&
- vertAxis.sanitize (c, this) &&
+ hAxis.sanitize (c, this) &&
+ vAxis.sanitize (c, this) &&
(version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
}
protected:
FixedVersion<> version;
- OffsetTo<Axis> horizAxis;
- OffsetTo<Axis> vertAxis;
+ OffsetTo<Axis> hAxis;
+ OffsetTo<Axis> vAxis;
LOffsetTo<VariationStore>
varStore; /* Offset to the table of Item Variation
* Store--from beginning of BASE
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 21a8382..89d5eae 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -41,6 +41,15 @@
#ifndef HB_MAX_CONTEXT_LENGTH
#define HB_MAX_CONTEXT_LENGTH 64
#endif
+#ifndef HB_CLOSURE_MAX_STAGES
+/*
+ * The maximum number of times a lookup can be applied during shaping.
+ * Used to limit the number of iterations of the closure algorithm.
+ * This must be larger than the number of times add_pause() is
+ * called in a collect_features call of any shaper.
+ */
+#define HB_CLOSURE_MAX_STAGES 32
+#endif
namespace OT {
@@ -164,7 +173,7 @@
public:
DEFINE_SIZE_STATIC (6);
};
-DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
struct IndexArray : ArrayOf<Index>
@@ -181,6 +190,11 @@
}
return this->len;
}
+
+ inline void add_indexes_to (hb_set_t* output /* OUT */) const
+ {
+ output->add_array (arrayZ, len);
+ }
};
@@ -199,6 +213,8 @@
unsigned int *feature_count /* IN/OUT */,
unsigned int *feature_indexes /* OUT */) const
{ return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+ inline void add_feature_indexes_to (hb_set_t *feature_indexes) const
+ { featureIndex.add_indexes_to (feature_indexes); }
inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
inline unsigned int get_required_feature_index (void) const
@@ -224,8 +240,7 @@
public:
DEFINE_SIZE_ARRAY (6, featureIndex);
};
-DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
-
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
struct Script
{
@@ -540,9 +555,6 @@
c->try_set (&featureParams, new_offset) &&
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
return_trace (false);
-
- if (c->edit_count > 1)
- c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
}
return_trace (true);
@@ -597,6 +609,14 @@
inline OffsetArrayOf<SubTableType>& get_subtables (void)
{ return CastR<OffsetArrayOf<SubTableType> > (subTable); }
+ inline unsigned int get_size (void) const
+ {
+ const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
+ if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+ return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
+ return (const char *) &markFilteringSet - (const char *) this;
+ }
+
inline unsigned int get_type (void) const { return lookupType; }
/* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
@@ -639,6 +659,7 @@
if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{
+ if (unlikely (!c->extend (*this))) return_trace (false);
HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
markFilteringSet.set (lookup_props >> 16);
}
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 60a8d3a..d2b41a8 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -349,6 +349,7 @@
ComponentGlyph = 4
};
+ inline bool has_data (void) const { return version.to_int () != 0; }
inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
{ return (this+glyphClassDef).get_class (glyph); }
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index b52c014..fe34a32 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1628,14 +1628,14 @@
template <typename context_t>
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
+ const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
const PosLookup &l = gpos.get_lookup (lookup_index);
return l.dispatch (c);
}
/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
+ const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
const PosLookup &l = gpos.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 91b898b..1d5a02a 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -47,7 +47,7 @@
* https://github.com/harfbuzz/harfbuzz/issues/363 */
hb_codepoint_t glyph_id = iter.get_glyph ();
if (c->glyphs->has (glyph_id))
- c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
+ c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
}
}
@@ -132,7 +132,7 @@
if (unlikely (iter.get_coverage () >= count))
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
- c->glyphs->add (substitute[iter.get_coverage ()]);
+ c->out->add (substitute[iter.get_coverage ()]);
}
}
@@ -263,7 +263,7 @@
TRACE_CLOSURE (this);
unsigned int count = substitute.len;
for (unsigned int i = 0; i < count; i++)
- c->glyphs->add (substitute[i]);
+ c->out->add (substitute[i]);
}
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@@ -464,7 +464,7 @@
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
unsigned int count = alt_set.len;
for (unsigned int i = 0; i < count; i++)
- c->glyphs->add (alt_set[i]);
+ c->out->add (alt_set[i]);
}
}
}
@@ -605,7 +605,7 @@
for (unsigned int i = 1; i < count; i++)
if (!c->glyphs->has (component[i]))
return;
- c->glyphs->add (ligGlyph);
+ c->out->add (ligGlyph);
}
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@@ -957,7 +957,7 @@
if (unlikely (iter.get_coverage () >= count))
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
- c->glyphs->add (substitute[iter.get_coverage ()]);
+ c->out->add (substitute[iter.get_coverage ()]);
}
}
@@ -1163,7 +1163,12 @@
return_trace (HB_VOID);
c->set_recurse_func (dispatch_closure_recurse_func);
- return_trace (dispatch (c));
+
+ hb_closure_context_t::return_t ret = dispatch (c);
+
+ c->flush ();
+
+ return_trace (ret);
}
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
@@ -1265,7 +1270,12 @@
{
if (!c->should_visit_lookup (lookup_index))
return HB_VOID;
- return dispatch_recurse_func (c, lookup_index);
+
+ hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+
+ c->flush ();
+
+ return ret;
}
template <typename context_t>
@@ -1325,7 +1335,7 @@
{
_hb_buffer_assert_gsubgpos_vars (buffer);
- const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
+ const GDEF &gdef = *hb_ot_layout_from_face (font->face)->table.GDEF;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
{
@@ -1349,14 +1359,14 @@
template <typename context_t>
/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
- const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
+ const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
const SubstLookup &l = gsub.get_lookup (lookup_index);
return l.dispatch (c);
}
/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
- const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
+ const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
const SubstLookup &l = gsub.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index aed00f1..40a2fc4 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -69,12 +69,13 @@
bool is_lookup_done (unsigned int lookup_index)
{
- // Have we visited this lookup with the current set of glyphs?
+ /* Have we visited this lookup with the current set of glyphs? */
return done_lookups->get (lookup_index) == glyphs->get_population ();
}
hb_face_t *face;
hb_set_t *glyphs;
+ hb_auto_t<hb_set_t> out[1];
recurse_func_t recurse_func;
unsigned int nesting_level_left;
unsigned int debug_depth;
@@ -90,8 +91,19 @@
debug_depth (0),
done_lookups (done_lookups_) {}
+ ~hb_closure_context_t (void)
+ {
+ flush ();
+ }
+
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+ void flush (void)
+ {
+ hb_set_union (glyphs, out);
+ hb_set_clear (out);
+ }
+
private:
hb_map_t *done_lookups;
};
@@ -468,7 +480,7 @@
iter_input (), iter_context (),
font (font_), face (font->face), buffer (buffer_),
recurse_func (nullptr),
- gdef (*hb_ot_layout_from_face (face)->gdef),
+ gdef (*hb_ot_layout_from_face (face)->table.GDEF),
var_store (gdef.get_var_store ()),
direction (buffer_->props.direction),
lookup_mask (1),
@@ -2308,6 +2320,7 @@
struct GSUBGPOS
{
+ inline bool has_data (void) const { return version.to_int () != 0; }
inline unsigned int get_script_count (void) const
{ return (this+scriptList).len; }
inline const Tag& get_script_tag (unsigned int i) const
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index b2f974b..612bc7f 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -121,25 +121,6 @@
* hb_ot_layout_t
*/
-namespace OT {
- struct BASE;
- struct COLR;
- struct CPAL;
- struct GDEF;
- struct GSUB;
- struct GPOS;
- struct MATH;
- struct fvar;
- struct avar;
-}
-
-namespace AAT {
- struct ankr;
- struct kerx;
- struct morx;
- struct trak;
-}
-
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
@@ -161,27 +142,73 @@
hb_set_digest_t digest;
};
+/* Most of these tables are NOT needed for shaping. But we need to hook them *somewhere*.
+ * This is as good as any place. */
+#define HB_OT_LAYOUT_TABLES \
+ /* OpenType shaping. */ \
+ HB_OT_LAYOUT_TABLE(OT, GDEF) \
+ HB_OT_LAYOUT_TABLE(OT, GSUB) \
+ HB_OT_LAYOUT_TABLE(OT, GPOS) \
+ HB_OT_LAYOUT_TABLE(OT, JSTF) \
+ HB_OT_LAYOUT_TABLE(OT, BASE) \
+ /* AAT shaping. */ \
+ HB_OT_LAYOUT_TABLE(AAT, morx) \
+ HB_OT_LAYOUT_TABLE(AAT, kerx) \
+ HB_OT_LAYOUT_TABLE(AAT, ankr) \
+ HB_OT_LAYOUT_TABLE(AAT, trak) \
+ /* OpenType variations. */ \
+ HB_OT_LAYOUT_TABLE(OT, fvar) \
+ HB_OT_LAYOUT_TABLE(OT, avar) \
+ HB_OT_LAYOUT_TABLE(OT, MVAR) \
+ /* OpenType color. */ \
+ HB_OT_LAYOUT_TABLE(OT, COLR) \
+ HB_OT_LAYOUT_TABLE(OT, CPAL) \
+ HB_OT_LAYOUT_TABLE(OT, CBDT) \
+ HB_OT_LAYOUT_TABLE(OT, CBLC) \
+ HB_OT_LAYOUT_TABLE(OT, sbix) \
+ HB_OT_LAYOUT_TABLE(OT, svg) \
+ /* OpenType math. */ \
+ HB_OT_LAYOUT_TABLE(OT, MATH) \
+ /* OpenType fundamentals. */ \
+ HB_OT_LAYOUT_TABLE(OT, post) \
+ /* */
+
+/* Declare tables. */
+#define HB_OT_LAYOUT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
+HB_OT_LAYOUT_TABLES
+#undef HB_OT_LAYOUT_TABLE
+
struct hb_ot_layout_t
{
- hb_blob_t *gdef_blob;
- hb_blob_t *gsub_blob;
- hb_blob_t *gpos_blob;
-
- const struct OT::GDEF *gdef;
- const struct OT::GSUB *gsub;
- const struct OT::GPOS *gpos;
-
- /* TODO Move the following out of this struct. */
- OT::hb_table_lazy_loader_t<struct OT::BASE> base;
- OT::hb_table_lazy_loader_t<struct OT::MATH> math;
- OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
- OT::hb_table_lazy_loader_t<struct OT::avar> avar;
-
unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count;
hb_ot_layout_lookup_accelerator_t *gsub_accels;
hb_ot_layout_lookup_accelerator_t *gpos_accels;
+
+ /* Various non-shaping tables. */
+ struct tables_t
+ {
+ HB_INTERNAL void init0 (hb_face_t *face);
+ HB_INTERNAL void fini (void);
+
+#define HB_OT_LAYOUT_TABLE_ORDER(Namespace, Type) \
+ HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
+ enum order_t
+ {
+ ORDER_ZERO,
+#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
+ HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type),
+ HB_OT_LAYOUT_TABLES
+#undef HB_OT_LAYOUT_TABLE
+ };
+
+ hb_face_t *face; /* MUST be JUST before the lazy loaders. */
+#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
+ hb_table_lazy_loader_t<struct Namespace::Type, HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type)> Type;
+ HB_OT_LAYOUT_TABLES
+#undef HB_OT_LAYOUT_TABLE
+ } table;
};
@@ -192,7 +219,7 @@
_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
+#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot.get_relaxed ())
/*
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 655c36c..09ff0e6 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -31,6 +31,7 @@
#include "hb-open-type-private.hh"
#include "hb-ot-layout-private.hh"
#include "hb-ot-map-private.hh"
+#include "hb-map-private.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
@@ -44,9 +45,124 @@
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
#include "hb-ot-name-table.hh"
-#include "hb-map-private.hh"
+static bool
+_hb_ot_blacklist_gdef (unsigned int gdef_len,
+ unsigned int gsub_len,
+ unsigned int gpos_len)
+{
+ /* The ugly business of blacklisting individual fonts' tables happen here!
+ * See this thread for why we finally had to bend in and do this:
+ * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+ *
+ * In certain versions of Times New Roman Italic and Bold Italic,
+ * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
+ * in GDEF. Many versions of Tahoma have bad GDEF tables that
+ * incorrectly classify some spacing marks such as certain IPA
+ * symbols as glyph class 3. So do older versions of Microsoft
+ * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
+ *
+ * Nuke the GDEF tables of to avoid unwanted width-zeroing.
+ *
+ * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
+ */
+#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z))
+ switch ENCODE(gdef_len, gsub_len, gpos_len)
+ {
+ /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
+ case ENCODE (442, 2874, 42038):
+ /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
+ case ENCODE (430, 2874, 40662):
+ /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
+ case ENCODE (442, 2874, 39116):
+ /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
+ case ENCODE (430, 2874, 39374):
+ /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
+ case ENCODE (490, 3046, 41638):
+ /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
+ case ENCODE (478, 3046, 41902):
+ /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
+ case ENCODE (898, 12554, 46470):
+ /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
+ case ENCODE (910, 12566, 47732):
+ /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
+ case ENCODE (928, 23298, 59332):
+ /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
+ case ENCODE (940, 23310, 60732):
+ /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+ case ENCODE (964, 23836, 60072):
+ /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+ case ENCODE (976, 23832, 61456):
+ /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
+ case ENCODE (994, 24474, 60336):
+ /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
+ case ENCODE (1006, 24470, 61740):
+ /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+ case ENCODE (1006, 24576, 61346):
+ /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+ case ENCODE (1018, 24572, 62828):
+ /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
+ case ENCODE (1006, 24576, 61352):
+ /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
+ case ENCODE (1018, 24572, 62834):
+ /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
+ case ENCODE (832, 7324, 47162):
+ /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
+ case ENCODE (844, 7302, 45474):
+ /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
+ case ENCODE (180, 13054, 7254):
+ /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
+ case ENCODE (192, 12638, 7254):
+ /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
+ case ENCODE (192, 12690, 7254):
+ /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
+ /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
+ case ENCODE (188, 248, 3852):
+ /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
+ /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
+ case ENCODE (188, 264, 3426):
+ /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
+ case ENCODE (1058, 47032, 11818):
+ /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
+ case ENCODE (1046, 47030, 12600):
+ /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
+ case ENCODE (1058, 71796, 16770):
+ /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
+ case ENCODE (1046, 71790, 17862):
+ /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
+ case ENCODE (1046, 71788, 17112):
+ /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
+ case ENCODE (1058, 71794, 17514):
+ /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
+ case ENCODE (1330, 109904, 57938):
+ /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
+ case ENCODE (1330, 109904, 58972):
+ /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
+ * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+ case ENCODE (1004, 59092, 14836):
+ return true;
+#undef ENCODE
+ }
+ return false;
+}
+
+void hb_ot_layout_t::tables_t::init0 (hb_face_t *face)
+{
+ this->face = face;
+#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.init0 ();
+ HB_OT_LAYOUT_TABLES
+#undef HB_OT_LAYOUT_TABLE
+}
+void hb_ot_layout_t::tables_t::fini (void)
+{
+#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.fini ();
+ HB_OT_LAYOUT_TABLES
+#undef HB_OT_LAYOUT_TABLE
+}
+
hb_ot_layout_t *
_hb_ot_layout_create (hb_face_t *face)
{
@@ -54,143 +170,33 @@
if (unlikely (!layout))
return nullptr;
- layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
- layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
+ layout->table.init0 (face);
- layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
- layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
+ const OT::GSUB &gsub = *layout->table.GSUB;
+ const OT::GPOS &gpos = *layout->table.GPOS;
- layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
- layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
+ if (unlikely (_hb_ot_blacklist_gdef (layout->table.GDEF.get_blob ()->length,
+ layout->table.GSUB.get_blob ()->length,
+ layout->table.GPOS.get_blob ()->length)))
+ layout->table.GDEF.set_stored (hb_blob_get_empty ());
- layout->math.init (face);
- layout->fvar.init (face);
- layout->avar.init (face);
+ unsigned int gsub_lookup_count = layout->gsub_lookup_count = gsub.get_lookup_count ();
+ unsigned int gpos_lookup_count = layout->gpos_lookup_count = gpos.get_lookup_count ();
- {
- /*
- * The ugly business of blacklisting individual fonts' tables happen here!
- * See this thread for why we finally had to bend in and do this:
- * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
- */
- unsigned int gdef_len = layout->gdef_blob->length;
- unsigned int gsub_len = layout->gsub_blob->length;
- unsigned int gpos_len = layout->gpos_blob->length;
- if (0
- /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
- || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
- /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
- || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
- /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
- || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
- /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
- || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
- /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
- || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
- /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
- || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
- )
- {
- /* In certain versions of Times New Roman Italic and Bold Italic,
- * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
- * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width
- * double-quote. See:
- * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
- */
- if (3 == layout->gdef->get_glyph_class (5))
- layout->gdef = &Null(OT::GDEF);
- }
- else if (0
- /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
- || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
- /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
- || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
- /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
- || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
- /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
- || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
- /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
- || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
- /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
- || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
- /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
- || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
- /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
- || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
- /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
- || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
- /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
- || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
- /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
- || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
- /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
- || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
- /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
- || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
- /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
- || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
- /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
- || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
- /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
- || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
- /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
- || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
- /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
- /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
- || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
- /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
- /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
- || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
- /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
- || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
- /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
- || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
- /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
- || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
- /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
- || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
- /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
- || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
- /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
- || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
- /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
- || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
- /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
- || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
- /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
- * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
- || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
- )
- {
- /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
- * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
- * and the version of Cantarell shipped by Ubuntu 16.04.
- * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
- * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
- * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
- * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
- */
- layout->gdef = &Null(OT::GDEF);
- }
- }
+ layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gsub_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
+ layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gpos_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
- layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
- layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
-
- layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
- layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-
- if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
- (layout->gpos_lookup_count && !layout->gpos_accels)))
+ if (unlikely ((gsub_lookup_count && !layout->gsub_accels) ||
+ (gpos_lookup_count && !layout->gpos_accels)))
{
_hb_ot_layout_destroy (layout);
return nullptr;
}
- for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
- layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
- for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
- layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
+ for (unsigned int i = 0; i < gsub_lookup_count; i++)
+ layout->gsub_accels[i].init (gsub.get_lookup (i));
+ for (unsigned int i = 0; i < gpos_lookup_count; i++)
+ layout->gpos_accels[i].init (gpos.get_lookup (i));
return layout;
}
@@ -208,13 +214,7 @@
free (layout->gsub_accels);
free (layout->gpos_accels);
- hb_blob_destroy (layout->gdef_blob);
- hb_blob_destroy (layout->gsub_blob);
- hb_blob_destroy (layout->gpos_blob);
-
- layout->math.fini ();
- layout->fvar.fini ();
- layout->avar.fini ();
+ layout->table.fini ();
free (layout);
}
@@ -231,19 +231,19 @@
_get_gdef (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
- return *hb_ot_layout_from_face (face)->gdef;
+ return *hb_ot_layout_from_face (face)->table.GDEF;
}
static inline const OT::GSUB&
_get_gsub (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
- return *hb_ot_layout_from_face (face)->gsub;
+ return *hb_ot_layout_from_face (face)->table.GSUB;
}
static inline const OT::GPOS&
_get_gpos (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
- return *hb_ot_layout_from_face (face)->gpos;
+ return *hb_ot_layout_from_face (face)->table.GPOS;
}
/*
@@ -518,6 +518,19 @@
return l.has_required_feature ();
}
+static void
+_hb_ot_layout_language_add_feature_indexes_to (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_index,
+ hb_set_t *feature_indexes /* OUT */)
+{
+ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+ const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
+ l.add_feature_indexes_to (feature_indexes);
+}
+
+
unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
hb_tag_t table_tag,
@@ -656,12 +669,12 @@
}
static void
-_hb_ot_layout_collect_lookups_features (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int script_index,
- unsigned int language_index,
- const hb_tag_t *features,
- hb_set_t *lookup_indexes /* OUT */)
+_hb_ot_layout_collect_features_features (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_index,
+ const hb_tag_t *features,
+ hb_set_t *feature_indexes /* OUT */)
{
if (!features)
{
@@ -672,33 +685,14 @@
language_index,
&required_feature_index,
nullptr))
- _hb_ot_layout_collect_lookups_lookups (face,
- table_tag,
- required_feature_index,
- lookup_indexes);
+ feature_indexes->add (required_feature_index);
/* All features */
- unsigned int feature_indices[32];
- unsigned int offset, len;
-
- offset = 0;
- do {
- len = ARRAY_LENGTH (feature_indices);
- hb_ot_layout_language_get_feature_indexes (face,
- table_tag,
- script_index,
- language_index,
- offset, &len,
- feature_indices);
-
- for (unsigned int i = 0; i < len; i++)
- _hb_ot_layout_collect_lookups_lookups (face,
- table_tag,
- feature_indices[i],
- lookup_indexes);
-
- offset += len;
- } while (len == ARRAY_LENGTH (feature_indices));
+ _hb_ot_layout_language_add_feature_indexes_to (face,
+ table_tag,
+ script_index,
+ language_index,
+ feature_indexes);
}
else
{
@@ -711,28 +705,25 @@
language_index,
*features,
&feature_index))
- _hb_ot_layout_collect_lookups_lookups (face,
- table_tag,
- feature_index,
- lookup_indexes);
+ feature_indexes->add (feature_index);
}
}
}
static void
-_hb_ot_layout_collect_lookups_languages (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int script_index,
- const hb_tag_t *languages,
- const hb_tag_t *features,
- hb_set_t *lookup_indexes /* OUT */)
+_hb_ot_layout_collect_features_languages (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ const hb_tag_t *languages,
+ const hb_tag_t *features,
+ hb_set_t *feature_indexes /* OUT */)
{
- _hb_ot_layout_collect_lookups_features (face,
- table_tag,
- script_index,
- HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
- features,
- lookup_indexes);
+ _hb_ot_layout_collect_features_features (face,
+ table_tag,
+ script_index,
+ HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
+ features,
+ feature_indexes);
if (!languages)
{
@@ -742,12 +733,12 @@
script_index,
0, nullptr, nullptr);
for (unsigned int language_index = 0; language_index < count; language_index++)
- _hb_ot_layout_collect_lookups_features (face,
- table_tag,
- script_index,
- language_index,
- features,
- lookup_indexes);
+ _hb_ot_layout_collect_features_features (face,
+ table_tag,
+ script_index,
+ language_index,
+ features,
+ feature_indexes);
}
else
{
@@ -759,12 +750,58 @@
script_index,
*languages,
&language_index))
- _hb_ot_layout_collect_lookups_features (face,
- table_tag,
- script_index,
- language_index,
- features,
- lookup_indexes);
+ _hb_ot_layout_collect_features_features (face,
+ table_tag,
+ script_index,
+ language_index,
+ features,
+ feature_indexes);
+ }
+ }
+}
+
+/**
+ * hb_ot_layout_collect_features:
+ *
+ * Since: 1.8.5
+ **/
+void
+hb_ot_layout_collect_features (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_tag_t *scripts,
+ const hb_tag_t *languages,
+ const hb_tag_t *features,
+ hb_set_t *feature_indexes /* OUT */)
+{
+ if (!scripts)
+ {
+ /* All scripts */
+ unsigned int count = hb_ot_layout_table_get_script_tags (face,
+ table_tag,
+ 0, nullptr, nullptr);
+ for (unsigned int script_index = 0; script_index < count; script_index++)
+ _hb_ot_layout_collect_features_languages (face,
+ table_tag,
+ script_index,
+ languages,
+ features,
+ feature_indexes);
+ }
+ else
+ {
+ for (; *scripts; scripts++)
+ {
+ unsigned int script_index;
+ if (hb_ot_layout_table_find_script (face,
+ table_tag,
+ *scripts,
+ &script_index))
+ _hb_ot_layout_collect_features_languages (face,
+ table_tag,
+ script_index,
+ languages,
+ features,
+ feature_indexes);
}
}
}
@@ -782,37 +819,10 @@
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */)
{
- if (!scripts)
- {
- /* All scripts */
- unsigned int count = hb_ot_layout_table_get_script_tags (face,
- table_tag,
- 0, nullptr, nullptr);
- for (unsigned int script_index = 0; script_index < count; script_index++)
- _hb_ot_layout_collect_lookups_languages (face,
- table_tag,
- script_index,
- languages,
- features,
- lookup_indexes);
- }
- else
- {
- for (; *scripts; scripts++)
- {
- unsigned int script_index;
- if (hb_ot_layout_table_find_script (face,
- table_tag,
- *scripts,
- &script_index))
- _hb_ot_layout_collect_lookups_languages (face,
- table_tag,
- script_index,
- languages,
- features,
- lookup_indexes);
- }
- }
+ hb_auto_t<hb_set_t> feature_indexes;
+ hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
+ for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; hb_set_next (&feature_indexes, &feature_index);)
+ _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes);
}
/**
@@ -841,13 +851,13 @@
{
case HB_OT_TAG_GSUB:
{
- const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+ const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
l.collect_glyphs (&c);
return;
}
case HB_OT_TAG_GPOS:
{
- const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
+ const OT::PosLookup& l = hb_ot_layout_from_face (face)->table.GPOS->get_lookup (lookup_index);
l.collect_glyphs (&c);
return;
}
@@ -894,7 +904,7 @@
hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face)
{
- return &_get_gsub (face) != &Null(OT::GSUB);
+ return _get_gsub (face).has_data ();
}
/**
@@ -923,7 +933,7 @@
if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
- const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+ const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
}
@@ -969,6 +979,7 @@
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
const OT::GSUB& gsub = _get_gsub (face);
+ unsigned int iteration_count = 0;
unsigned int glyphs_length;
do
{
@@ -983,7 +994,9 @@
for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
gsub.get_lookup (i).closure (&c, i);
}
- } while (glyphs_length != glyphs->get_population ());
+ iteration_count++;
+ } while (iteration_count <= HB_CLOSURE_MAX_STAGES
+ && glyphs_length != glyphs->get_population ());
}
/*
@@ -993,7 +1006,7 @@
hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face)
{
- return &_get_gpos (face) != &Null(OT::GPOS);
+ return _get_gpos (face).has_data ();
}
void
@@ -1078,7 +1091,7 @@
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
- table (*hb_ot_layout_from_face (face)->gsub),
+ table (*hb_ot_layout_from_face (face)->table.GSUB),
accels (hb_ot_layout_from_face (face)->gsub_accels) {}
const OT::GSUB &table;
@@ -1092,7 +1105,7 @@
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
- table (*hb_ot_layout_from_face (face)->gpos),
+ table (*hb_ot_layout_from_face (face)->table.GPOS),
accels (hb_ot_layout_from_face (face)->gpos_accels) {}
const OT::GPOS &table;
@@ -1101,7 +1114,7 @@
struct hb_get_subtables_context_t :
- OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
+ hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
@@ -1328,5 +1341,5 @@
// hb_bool_t
// hb_ot_base_has_data (hb_face_t *face)
// {
-// return &_get_base (face) != &Null(OT::BASE);
+// return _get_base (face).has_data ();
// }
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 0278796..586fb15 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -194,6 +194,13 @@
hb_ot_layout_table_get_lookup_count (hb_face_t *face,
hb_tag_t table_tag);
+HB_EXTERN void
+hb_ot_layout_collect_features (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_tag_t *scripts,
+ const hb_tag_t *languages,
+ const hb_tag_t *features,
+ hb_set_t *feature_indexes /* OUT */);
HB_EXTERN void
hb_ot_layout_collect_lookups (hb_face_t *face,
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index 5fef2d2..2dd7145 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -686,6 +686,8 @@
{
static const hb_tag_t tableTag = HB_OT_TAG_MATH;
+ inline bool has_data (void) const { return version.to_int () != 0; }
+
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc
index 1667a7d..66ce207 100644
--- a/src/hb-ot-math.cc
+++ b/src/hb-ot-math.cc
@@ -34,7 +34,7 @@
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::MATH);
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- return *(layout->math.get ());
+ return *(layout->table.MATH.get ());
}
/*
@@ -55,7 +55,7 @@
hb_bool_t
hb_ot_math_has_data (hb_face_t *face)
{
- return &_get_math (face) != &Null(OT::MATH);
+ return _get_math (face).has_data ();
}
/**
diff --git a/src/hb-ot-maxp-table.hh b/src/hb-ot-maxp-table.hh
index 390b60d..75aac4f 100644
--- a/src/hb-ot-maxp-table.hh
+++ b/src/hb-ot-maxp-table.hh
@@ -100,14 +100,14 @@
inline bool subset (hb_subset_plan_t *plan) const
{
- hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
+ hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
hb_blob_destroy (maxp_blob);
if (unlikely (!maxp_prime_blob)) {
return false;
}
- OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
+ maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
maxp_prime->set_num_glyphs (plan->glyphs.len);
if (plan->drop_hints)
@@ -118,7 +118,7 @@
return result;
}
- static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
+ static inline void drop_hint_fields (hb_subset_plan_t *plan, maxp *maxp_prime)
{
if (maxp_prime->version.major == 1)
{
diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index c52b7eb..56bbab7 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -51,12 +51,12 @@
inline bool subset (hb_subset_plan_t *plan) const
{
- hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
+ hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table<os2> (plan->source);
hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
// TODO(grieger): move to hb_blob_copy_writable_or_fail
hb_blob_destroy (os2_blob);
- OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
+ os2 *os2_prime = (os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
if (unlikely (!os2_prime)) {
hb_blob_destroy (os2_prime_blob);
return false;
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index d05fc09..4f08a51 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -85,7 +85,7 @@
inline bool subset (hb_subset_plan_t *plan) const
{
unsigned int post_prime_length;
- hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
+ hb_blob_t *post_blob = hb_sanitize_context_t().reference_table<post>(plan->source);
hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size);
post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
hb_blob_destroy (post_blob);
@@ -110,7 +110,7 @@
{
index_to_offset.init ();
- blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
+ blob = hb_sanitize_context_t().reference_table<post> (face);
const post *table = blob->as<post> ();
unsigned int table_length = blob->length;
@@ -130,7 +130,7 @@
inline void fini (void)
{
index_to_offset.fini ();
- free (gids_sorted_by_name);
+ free (gids_sorted_by_name.get ());
}
inline bool get_glyph_name (hb_codepoint_t glyph,
@@ -162,7 +162,7 @@
return false;
retry:
- uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
+ uint16_t *gids = gids_sorted_by_name.get ();
if (unlikely (!gids))
{
@@ -174,7 +174,8 @@
gids[i] = i;
hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
- if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
+ if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
+ {
free (gids);
goto retry;
}
@@ -255,7 +256,7 @@
const ArrayOf<HBUINT16> *glyphNameIndex;
hb_vector_t<uint32_t, 1> index_to_offset;
const uint8_t *pool;
- mutable uint16_t *gids_sorted_by_name;
+ hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
};
public:
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index 5a257f0..a55511a 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -79,12 +79,12 @@
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
- OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
- OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
+ Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
+ Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
/* Each glyph takes four bytes max, and there's some overhead. */
char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
- OT::hb_serialize_context_t c (buf, sizeof (buf));
+ hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_single (&c,
OT::LookupFlag::IgnoreMarks,
@@ -155,15 +155,15 @@
if (!num_ligatures)
return nullptr;
- OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
- OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
- OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
- OT::Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
- OT::Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
+ Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
+ Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
+ Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
+ Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
+ Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
/* 16 bytes per ligature ought to be enough... */
char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
- OT::hb_serialize_context_t c (buf, sizeof (buf));
+ hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_ligature (&c,
OT::LookupFlag::IgnoreMarks,
@@ -205,8 +205,6 @@
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
};
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
#define HB_WITH_WIN1256
#endif
@@ -215,7 +213,8 @@
#include "hb-ot-shape-complex-arabic-win1256.hh"
#endif
-struct ManifestLookup {
+struct ManifestLookup
+{
OT::Tag tag;
OT::OffsetTo<OT::SubstLookup> lookupOffset;
};
@@ -299,7 +298,7 @@
{
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
if (unlikely (!fallback_plan))
- return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+ return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
fallback_plan->num_lookups = 0;
fallback_plan->free_lookups = false;
@@ -314,14 +313,15 @@
if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
return fallback_plan;
+ assert (fallback_plan->num_lookups == 0);
free (fallback_plan);
- return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+ return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
}
static void
arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
{
- if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
+ if (!fallback_plan || fallback_plan->num_lookups == 0)
return;
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index b1cba1c..f4b397b 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -250,7 +250,7 @@
* mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
- arabic_fallback_plan_t *fallback_plan;
+ hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
unsigned int do_fallback : 1;
unsigned int has_stch : 1;
@@ -280,7 +280,7 @@
{
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
- arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
+ arabic_fallback_plan_destroy (arabic_plan->fallback_plan.get ());
free (data);
}
@@ -403,12 +403,13 @@
return;
retry:
- arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan);
+ arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan.get ();
if (unlikely (!fallback_plan))
{
/* This sucks. We need a font to build the fallback plan... */
fallback_plan = arabic_fallback_plan_create (plan, font);
- if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) {
+ if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
+ {
arabic_fallback_plan_destroy (fallback_plan);
goto retry;
}
diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index 9554994..bb7fff3 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -300,7 +300,9 @@
0x0CB0u, /* Kannada */
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
- 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
+ 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
+
+ 0x179Au, /* Khmer */
};
static inline bool
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index b8d9a3a..b52656f 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -251,10 +251,10 @@
{
ASSERT_POD ();
- inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+ inline bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
{
- hb_codepoint_t glyph = virama_glyph;
- if (unlikely (virama_glyph == (hb_codepoint_t) -1))
+ hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+ if (unlikely (glyph == (hb_codepoint_t) -1))
{
if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
glyph = 0;
@@ -262,8 +262,8 @@
* Maybe one day... */
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
- * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
- virama_glyph = glyph;
+ * during shape planning... Instead, overwrite it here. */
+ virama_glyph.set_relaxed ((int) glyph);
}
*pglyph = glyph;
@@ -273,7 +273,7 @@
const indic_config_t *config;
bool is_old_spec;
- mutable hb_codepoint_t virama_glyph;
+ mutable hb_atomic_int_t virama_glyph;
would_substitute_feature_t rphf;
would_substitute_feature_t pref;
@@ -298,7 +298,7 @@
}
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
- indic_plan->virama_glyph = (hb_codepoint_t) -1;
+ indic_plan->virama_glyph.set_relaxed (-1);
/* Use zero-context would_substitute() matching for new-spec of the main
* Indic scripts, and scripts with one spec only, but not for old-specs.
@@ -419,7 +419,7 @@
return;
hb_codepoint_t virama;
- if (indic_plan->get_virama_glyph (font, &virama))
+ if (indic_plan->load_virama_glyph (font, &virama))
{
hb_face_t *face = font->face;
unsigned int count = buffer->len;
@@ -667,10 +667,10 @@
* last consonant.
*
* Reports suggest that in some scripts Uniscribe does this only if there
- * is *not* a Halant after last consonant already (eg. Kannada), while it
- * does it unconditionally in other scripts (eg. Malayalam, Bengali). We
- * don't currently know about other scripts, so we whitelist Malayalam and
- * Bengali for now.
+ * is *not* a Halant after last consonant already. We know that is the
+ * case for Kannada, while it reorders unconditionally in other scripts,
+ * eg. Malayalam, Bengali, and Devanagari. We don't currently know about
+ * other scripts, so we blacklist Kannada.
*
* Kannada test case:
* U+0C9A,U+0CCD,U+0C9A,U+0CCD
@@ -681,15 +681,19 @@
* U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
* With lohit-ttf-20121122/Lohit-Malayalam.ttf
*
- * Bengali test case
+ * Bengali test case:
* U+0998,U+09CD,U+09AF,U+09CD
* With Windows XP vrinda.ttf
* https://github.com/harfbuzz/harfbuzz/issues/1073
+ *
+ * Devanagari test case:
+ * U+091F,U+094D,U+0930,U+094D
+ * With chandas.ttf
+ * https://github.com/harfbuzz/harfbuzz/issues/1071
*/
if (indic_plan->is_old_spec)
{
- bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM &&
- buffer->props.script != HB_SCRIPT_BENGALI;
+ bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
for (unsigned int i = base + 1; i < end; i++)
if (info[i].indic_category() == OT_H)
{
@@ -1036,9 +1040,11 @@
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
* class of OT_H is desired but has been lost. */
- if (indic_plan->virama_glyph)
+ /* We don't call load_virama_glyph(), since we know it's already
+ * loaded. */
+ hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+ if (virama_glyph)
{
- unsigned int virama_glyph = indic_plan->virama_glyph;
for (unsigned int i = start; i < end; i++)
if (info[i].codepoint == virama_glyph &&
_hb_glyph_info_ligated (&info[i]) &&
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index 7876d36..264515e 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -42,7 +42,7 @@
{
/*
* Basic features.
- * These features are applied in order, one at a time, after initial_reordering.
+ * These features are applied in order, one at a time, after reordering.
*/
{HB_TAG('p','r','e','f'), F_NONE},
{HB_TAG('b','l','w','f'), F_NONE},
@@ -51,9 +51,7 @@
{HB_TAG('c','f','a','r'), F_NONE},
/*
* Other features.
- * These features are applied all at once, after final_reordering.
- * Default Bengali font in Windows for example has intermixed
- * lookups for init,pres,abvs,blws features.
+ * These features are applied all at once.
*/
{HB_TAG('p','r','e','s'), F_GLOBAL},
{HB_TAG('a','b','v','s'), F_GLOBAL},
@@ -92,13 +90,9 @@
hb_font_t *font,
hb_buffer_t *buffer);
static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
@@ -111,20 +105,28 @@
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
+ map->add_gsub_pause (reorder);
+ /* Testing suggests that Uniscribe does NOT pause between basic
+ * features. Test with KhmerUI.ttf and the following three
+ * sequences:
+ *
+ * U+1789,U+17BC
+ * U+1789,U+17D2,U+1789
+ * U+1789,U+17D2,U+1789,U+17BC
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/974
+ */
map->add_global_bool_feature (HB_TAG('l','o','c','l'));
- /* The Indic specs do not require ccmp, but we apply it here since if
- * there is a use of it, it's typically at the beginning. */
map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
unsigned int i = 0;
- map->add_gsub_pause (initial_reordering);
for (; i < KHMER_BASIC_FEATURES; i++) {
map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
- map->add_gsub_pause (nullptr);
}
- map->add_gsub_pause (final_reordering);
+
+ map->add_gsub_pause (clear_syllables);
+
for (; i < KHMER_NUM_FEATURES; i++) {
map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
}
@@ -132,7 +134,6 @@
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
map->add_global_bool_feature (HB_TAG('c','l','i','g'));
- map->add_gsub_pause (clear_syllables);
}
static void
@@ -264,162 +265,58 @@
buffer->unsafe_to_break (start, end);
}
-static int
-compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
- int a = pa->khmer_position();
- int b = pb->khmer_position();
-
- return a < b ? -1 : a == b ? 0 : +1;
-}
-
/* Rules from:
* https://docs.microsoft.com/en-us/typography/script-development/devanagari */
static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
+reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
{
const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
- /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
-
- /* The first consonant is always the base. */
- unsigned int base = start;
- info[base].khmer_position() = POS_BASE_C;
-
- /* Mark all subsequent consonants as below. */
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant_or_vowel (info[i]))
- info[i].khmer_position() = POS_BELOW_C;
-
- /* Mark final consonants. A final consonant is one appearing after a matra,
- * like in Khmer. */
- for (unsigned int i = base + 1; i < end; i++)
- if (info[i].khmer_category() == OT_M) {
- for (unsigned int j = i + 1; j < end; j++)
- if (is_consonant_or_vowel (info[j])) {
- info[j].khmer_position() = POS_FINAL_C;
- break;
- }
- break;
- }
-
- /* Attach misc marks to previous char to move with them. */
+ /* Setup masks. */
{
- khmer_position_t last_pos = POS_START;
- for (unsigned int i = start; i < end; i++)
- {
- if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
- {
- info[i].khmer_position() = last_pos;
- if (unlikely (info[i].khmer_category() == OT_Coeng &&
- info[i].khmer_position() == POS_PRE_M))
- {
- /*
- * Uniscribe doesn't move the Halant with Left Matra.
- * TEST: U+092B,U+093F,U+094DE
- * We follow. This is important for the Sinhala
- * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
- * where U+0DD9 is a left matra and U+0DCA is the virama.
- * We don't want to move the virama with the left matra.
- * TEST: U+0D9A,U+0DDA
- */
- for (unsigned int j = i; j > start; j--)
- if (info[j - 1].khmer_position() != POS_PRE_M) {
- info[i].khmer_position() = info[j - 1].khmer_position();
- break;
- }
- }
- } else if (info[i].khmer_position() != POS_SMVD) {
- last_pos = (khmer_position_t) info[i].khmer_position();
- }
- }
- }
- /* For post-base consonants let them own anything before them
- * since the last consonant or matra. */
- {
- unsigned int last = base;
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant_or_vowel (info[i]))
- {
- for (unsigned int j = last + 1; j < i; j++)
- if (info[j].khmer_position() < POS_SMVD)
- info[j].khmer_position() = info[i].khmer_position();
- last = i;
- } else if (info[i].khmer_category() == OT_M)
- last = i;
- }
-
- {
- /* Use syllable() for sort accounting temporarily. */
- unsigned int syllable = info[start].syllable();
- for (unsigned int i = start; i < end; i++)
- info[i].syllable() = i - start;
-
- /* Sit tight, rock 'n roll! */
- hb_stable_sort (info + start, end - start, compare_khmer_order);
- /* Find base again */
- base = end;
- for (unsigned int i = start; i < end; i++)
- if (info[i].khmer_position() == POS_BASE_C)
- {
- base = i;
- break;
- }
-
- if (unlikely (end - start >= 127))
- buffer->merge_clusters (start, end);
- else
- /* Note! syllable() is a one-byte field. */
- for (unsigned int i = base; i < end; i++)
- if (info[i].syllable() != 255)
- {
- unsigned int max = i;
- unsigned int j = start + info[i].syllable();
- while (j != i)
- {
- max = MAX (max, j);
- unsigned int next = start + info[j].syllable();
- info[j].syllable() = 255; /* So we don't process j later again. */
- j = next;
- }
- if (i != max)
- buffer->merge_clusters (i, max + 1);
- }
-
- /* Put syllable back in. */
- for (unsigned int i = start; i < end; i++)
- info[i].syllable() = syllable;
- }
-
- /* Setup masks now */
-
- {
- hb_mask_t mask;
-
/* Post-base */
- mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
- for (unsigned int i = base + 1; i < end; i++)
+ hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
+ for (unsigned int i = start + 1; i < end; i++)
info[i].mask |= mask;
}
- unsigned int pref_len = 2;
- if (khmer_plan->mask_array[PREF] && base + pref_len < end)
+ unsigned int num_coengs = 0;
+ for (unsigned int i = start + 1; i < end; i++)
{
- /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
- for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
- hb_codepoint_t glyphs[2];
- for (unsigned int j = 0; j < pref_len; j++)
- glyphs[j] = info[i + j].codepoint;
- if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
+ /* """
+ * When a COENG + (Cons | IndV) combination are found (and subscript count
+ * is less than two) the character combination is handled according to the
+ * subscript type of the character following the COENG.
+ *
+ * ...
+ *
+ * Subscript Type 2 - The COENG + RO characters are reordered to immediately
+ * before the base glyph. Then the COENG + RO characters are assigned to have
+ * the 'pref' OpenType feature applied to them.
+ * """
+ */
+ if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+ {
+ num_coengs++;
+
+ if (info[i + 1].khmer_category() == OT_Ra)
{
- for (unsigned int j = 0; j < pref_len; j++)
- info[i++].mask |= khmer_plan->mask_array[PREF];
+ for (unsigned int j = 0; j < 2; j++)
+ info[i + j].mask |= khmer_plan->mask_array[PREF];
+
+ /* Move the Coeng,Ro sequence to the start. */
+ buffer->merge_clusters (start, i + 2);
+ hb_glyph_info_t t0 = info[i];
+ hb_glyph_info_t t1 = info[i + 1];
+ memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
+ info[start] = t0;
+ info[start + 1] = t1;
/* Mark the subsequent stuff with 'cfar'. Used in Khmer.
* Read the feature spec.
@@ -428,12 +325,22 @@
* U+1784,U+17D2,U+1782,U+17D2,U+179A
*/
if (khmer_plan->mask_array[CFAR])
- for (; i < end; i++)
- info[i].mask |= khmer_plan->mask_array[CFAR];
+ for (unsigned int j = i + 2; j < end; j++)
+ info[j].mask |= khmer_plan->mask_array[CFAR];
- break;
+ num_coengs = 2; /* Done. */
}
}
+
+ /* Reorder left matra piece. */
+ else if (info[i].khmer_position() == POS_PRE_M)
+ {
+ /* Move to the start. */
+ buffer->merge_clusters (start, i + 1);
+ hb_glyph_info_t t = info[i];
+ memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
+ info[start] = t;
+ }
}
}
@@ -448,7 +355,7 @@
{
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case consonant_syllable:
- initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+ reorder_consonant_syllable (plan, face, buffer, start, end);
break;
case non_khmer_cluster:
@@ -518,263 +425,26 @@
}
static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
- hb_glyph_info_t *info = buffer->info;
-
-
- /* This function relies heavily on halant glyphs. Lots of ligation
- * and possibly multiple substitutions happened prior to this
- * phase, and that might have messed up our properties. Recover
- * from a particular case of that where we're fairly sure that a
- * class of OT_Coeng is desired but has been lost. */
- if (khmer_plan->virama_glyph)
- {
- unsigned int virama_glyph = khmer_plan->virama_glyph;
- for (unsigned int i = start; i < end; i++)
- if (info[i].codepoint == virama_glyph &&
- _hb_glyph_info_ligated (&info[i]) &&
- _hb_glyph_info_multiplied (&info[i]))
- {
- /* This will make sure that this glyph passes is_coeng() test. */
- info[i].khmer_category() = OT_Coeng;
- _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
- }
- }
-
-
- /* 4. Final reordering:
- *
- * After the localized forms and basic shaping forms GSUB features have been
- * applied (see below), the shaping engine performs some final glyph
- * reordering before applying all the remaining font features to the entire
- * syllable.
- */
-
- bool try_pref = !!khmer_plan->mask_array[PREF];
-
- /* Find base again */
- unsigned int base;
- for (base = start; base < end; base++)
- if (info[base].khmer_position() >= POS_BASE_C)
- {
- if (try_pref && base + 1 < end)
- {
- for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
- {
- if (!(_hb_glyph_info_substituted (&info[i]) &&
- _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
- {
- /* Ok, this was a 'pref' candidate but didn't form any.
- * Base is around here... */
- base = i;
- while (base < end && is_coeng (info[base]))
- base++;
- info[base].khmer_position() = POS_BASE_C;
-
- try_pref = false;
- }
- break;
- }
- }
-
- if (start < base && info[base].khmer_position() > POS_BASE_C)
- base--;
- break;
- }
- if (base == end && start < base &&
- is_one_of (info[base - 1], FLAG (OT_ZWJ)))
- base--;
- if (base < end)
- while (start < base &&
- is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
- base--;
-
-
- /* o Reorder matras:
- *
- * If a pre-base matra character had been reordered before applying basic
- * features, the glyph can be moved closer to the main consonant based on
- * whether half-forms had been formed. Actual position for the matra is
- * defined as “after last standalone halant glyph, after initial matra
- * position and before the main consonant”. If ZWJ or ZWNJ follow this
- * halant, position is moved after it.
- */
-
- if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
- {
- /* If we lost track of base, alas, position before last thingy. */
- unsigned int new_pos = base == end ? base - 2 : base - 1;
-
- while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
- new_pos--;
-
- /* If we found no Halant we are done.
- * Otherwise only proceed if the Halant does
- * not belong to the Matra itself! */
- if (is_coeng (info[new_pos]) &&
- info[new_pos].khmer_position() != POS_PRE_M)
- {
- /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
- if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
- new_pos++;
- }
- else
- new_pos = start; /* No move. */
-
- if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
- {
- /* Now go see if there's actually any matras... */
- for (unsigned int i = new_pos; i > start; i--)
- if (info[i - 1].khmer_position () == POS_PRE_M)
- {
- unsigned int old_pos = i - 1;
- if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
- base--;
-
- hb_glyph_info_t tmp = info[old_pos];
- memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
- info[new_pos] = tmp;
-
- /* Note: this merge_clusters() is intentionally *after* the reordering.
- * Indic matra reordering is special and tricky... */
- buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
- new_pos--;
- }
- } else {
- for (unsigned int i = start; i < base; i++)
- if (info[i].khmer_position () == POS_PRE_M) {
- buffer->merge_clusters (i, MIN (end, base + 1));
- break;
- }
- }
- }
-
-
- /* o Reorder pre-base-reordering consonants:
- *
- * If a pre-base-reordering consonant is found, reorder it according to
- * the following rules:
- */
-
- if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
- {
- for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
- {
- /* 1. Only reorder a glyph produced by substitution during application
- * of the <pref> feature. (Note that a font may shape a Ra consonant with
- * the feature generally but block it in certain contexts.)
- */
- /* Note: We just check that something got substituted. We don't check that
- * the <pref> feature actually did it...
- *
- * Reorder pref only if it ligated. */
- if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
- {
- /*
- * 2. Try to find a target position the same way as for pre-base matra.
- * If it is found, reorder pre-base consonant glyph.
- *
- * 3. If position is not found, reorder immediately before main
- * consonant.
- */
-
- unsigned int new_pos = base;
- while (new_pos > start &&
- !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
- new_pos--;
-
- /* In Khmer coeng model, a H,Ra can go *after* matras. If it goes after a
- * split matra, it should be reordered to *before* the left part of such matra. */
- if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
- {
- unsigned int old_pos = i;
- for (unsigned int j = base + 1; j < old_pos; j++)
- if (info[j].khmer_category() == OT_M)
- {
- new_pos--;
- break;
- }
- }
-
- if (new_pos > start && is_coeng (info[new_pos - 1]))
- {
- /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
- if (new_pos < end && is_joiner (info[new_pos]))
- new_pos++;
- }
-
- {
- unsigned int old_pos = i;
-
- buffer->merge_clusters (new_pos, old_pos + 1);
- hb_glyph_info_t tmp = info[old_pos];
- memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
- info[new_pos] = tmp;
-
- if (new_pos <= base && base < old_pos)
- base++;
- }
- }
-
- break;
- }
- }
-
-
- /*
- * Finish off the clusters and go home!
- */
- if (hb_options ().uniscribe_bug_compatible)
- {
- /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
- * This means, half forms are submerged into the main consonant's cluster.
- * This is unnecessary, and makes cursor positioning harder, but that's what
- * Uniscribe does. */
- buffer->merge_clusters (start, end);
- }
-}
-
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- if (unlikely (!count)) return;
-
- foreach_syllable (buffer, start, end)
- final_reordering_syllable (plan, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
}
-
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ /* TODO: In USE, we clear syllables right after reorder. Figure out
+ * what Uniscribe does. */
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh
index ed6849b..37a4d91 100644
--- a/src/hb-ot-shape-complex-private.hh
+++ b/src/hb-ot-shape-complex-private.hh
@@ -279,20 +279,7 @@
return &_hb_ot_complex_shaper_indic;
case HB_SCRIPT_KHMER:
- /* A number of Khmer fonts in the wild don't have a 'pref' feature,
- * and as such won't shape properly via the Indic shaper;
- * however, they typically have 'liga' / 'clig' features that implement
- * the necessary "reordering" by means of ligature substitutions.
- * So we send such pref-less fonts through the generic shaper instead. */
- if (planner->map.found_script[0] &&
- hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
- planner->map.script_index[0],
- planner->map.language_index[0],
- HB_TAG ('p','r','e','f'),
- nullptr))
return &_hb_ot_complex_shaper_khmer;
- else
- return &_hb_ot_complex_shaper_default;
case HB_SCRIPT_MYANMAR:
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index 25f7bf4..9c796f0 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -510,8 +510,8 @@
/* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv,
- /* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B,
+ /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
+ /* 11130 */ VBlw, VAbv, VAbv, H, CMAbv, O, B, B, B, B, B, B, B, B, B, B,
/* 11140 */ O, O, O, O, B, VPst, VPst, O, O, O, O, O, O, O, O, O,
/* Mahajani */
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 66b9571..f8e86c9 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -561,25 +561,6 @@
}
static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t ab,
- hb_codepoint_t *a,
- hb_codepoint_t *b)
-{
- switch (ab)
- {
- /* Chakma:
- * Special case where the Unicode decomp gives matras in the wrong order
- * for cluster validation.
- */
- case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
- case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
- }
-
- return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
compose_use (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t a,
hb_codepoint_t b,
@@ -602,7 +583,7 @@
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- decompose_use,
+ nullptr, /* decompose */
compose_use,
setup_masks_use,
nullptr, /* disable_otl */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 1189b20..71632b5 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -27,8 +27,8 @@
*/
#define HB_SHAPER ot
-#define hb_ot_shaper_face_data_t hb_ot_layout_t
-#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
+#define hb_ot_face_data_t hb_ot_layout_t
+#define hb_ot_shape_plan_data_t hb_ot_shape_plan_t
#include "hb-shaper-impl-private.hh"
#include "hb-ot-shape-private.hh"
@@ -41,7 +41,7 @@
#include "hb-set-private.hh"
#include "hb-ot-layout-gsubgpos-private.hh"
-//#include "hb-aat-layout-private.hh"
+#include "hb-aat-layout-private.hh"
static hb_tag_t common_features[] = {
HB_TAG('c','c','m','p'),
@@ -132,14 +132,14 @@
HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
-hb_ot_shaper_face_data_t *
+hb_ot_face_data_t *
_hb_ot_shaper_face_data_create (hb_face_t *face)
{
return _hb_ot_layout_create (face);
}
void
-_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
+_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
{
_hb_ot_layout_destroy (data);
}
@@ -151,16 +151,16 @@
HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
-struct hb_ot_shaper_font_data_t {};
+struct hb_ot_font_data_t {};
-hb_ot_shaper_font_data_t *
+hb_ot_font_data_t *
_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
- return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
+_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data)
{
}
@@ -169,7 +169,7 @@
* shaper shape_plan data
*/
-hb_ot_shaper_shape_plan_data_t *
+hb_ot_shape_plan_data_t *
_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,
unsigned int num_user_features,
@@ -194,14 +194,17 @@
if (plan->shaper->data_create) {
plan->data = plan->shaper->data_create (plan);
if (unlikely (!plan->data))
+ {
+ free (plan);
return nullptr;
+ }
}
return plan;
}
void
-_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
+_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shape_plan_data_t *plan)
{
if (plan->shaper->data_destroy)
plan->shaper->data_destroy (const_cast<void *> (plan->data));
@@ -623,8 +626,8 @@
c->plan->substitute (c->font, buffer);
- /* XXX Call morx instead. */
- //hb_aat_layout_substitute (c->font, c->buffer);
+ if (0) /* XXX Call morx instead. */
+ hb_aat_layout_substitute (c->font, c->buffer);
}
static inline void
@@ -677,8 +680,8 @@
if (HB_DIRECTION_IS_HORIZONTAL (direction))
{
- for (unsigned int i = 0; i < count; i++)
- pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
+ c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
+ &pos[0].x_advance, sizeof(pos[0]));
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
if (c->font->has_glyph_h_origin_func ())
for (unsigned int i = 0; i < count; i++)
@@ -688,9 +691,10 @@
}
else
{
+ c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
+ &pos[0].y_advance, sizeof(pos[0]));
for (unsigned int i = 0; i < count; i++)
{
- pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
c->font->subtract_glyph_v_origin (info[i].codepoint,
&pos[i].x_offset,
&pos[i].y_offset);
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index 82d2996..101476e 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -87,6 +87,8 @@
{
static const hb_tag_t tableTag = HB_OT_TAG_fvar;
+ inline bool has_data (void) const { return version.to_int () != 0; }
+
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index f0612a6..6081ddf 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -41,14 +41,14 @@
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar);
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- return *(layout->fvar.get ());
+ return *(layout->table.fvar.get ());
}
static inline const OT::avar&
_get_avar (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
- return *(layout->avar.get ());
+ return *(layout->table.avar.get ());
}
/**
@@ -65,7 +65,7 @@
hb_bool_t
hb_ot_var_has_data (hb_face_t *face)
{
- return &_get_fvar (face) != &Null(OT::fvar);
+ return _get_fvar (face).has_data ();
}
/**
diff --git a/src/hb-private.hh b/src/hb-private.hh
index ff339df..efe7bda 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -84,19 +84,9 @@
#endif
-/* Compiler attributes */
-
-
-template <typename T>
-struct _hb_alignof
-{
- struct s
- {
- char c;
- T t;
- };
- static constexpr unsigned int value = offsetof (s, t);
-};
+/*
+ * Compiler attributes
+ */
#if __cplusplus < 201103L
@@ -108,7 +98,6 @@
#define constexpr const
#endif
-// Static assertions
#ifndef static_assert
#define static_assert(e, msg) \
HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
@@ -122,11 +111,34 @@
#define thread_local
#endif
+template <typename T>
+struct _hb_alignof
+{
+ struct s
+ {
+ char c;
+ T t;
+ };
+ static constexpr size_t value = offsetof (s, t);
+};
#ifndef alignof
#define alignof(x) (_hb_alignof<x>::value)
-#endif // alignof
+#endif
-#endif // __cplusplus < 201103L
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator
+#endif
+
+#else /* __cplusplus >= 201103L */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator explicit
+#endif
+
+#endif /* __cplusplus < 201103L */
+
#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
#define likely(expr) (__builtin_expect (!!(expr), 1))
@@ -161,7 +173,11 @@
#ifndef HB_INTERNAL
# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
+# elif defined(__MINGW32__)
+ /* We use -export-symbols on mingw32, since it does not support visibility
+ * attribute. */
+# define HB_INTERNAL
+#else
# define HB_INTERNAL
# define HB_NO_VISIBILITY 1
# endif
@@ -282,13 +298,12 @@
#define HB_STMT_START do
#define HB_STMT_END while (0)
+/* Static-assert as expression. */
template <unsigned int cond> class hb_assert_constant_t;
template <> class hb_assert_constant_t<1> {};
-
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
/* Lets assert int types. Saves trouble down the road. */
-
static_assert ((sizeof (int8_t) == 1), "");
static_assert ((sizeof (uint8_t) == 1), "");
static_assert ((sizeof (int16_t) == 2), "");
@@ -297,7 +312,6 @@
static_assert ((sizeof (uint32_t) == 4), "");
static_assert ((sizeof (int64_t) == 8), "");
static_assert ((sizeof (uint64_t) == 8), "");
-
static_assert ((sizeof (hb_codepoint_t) == 4), "");
static_assert ((sizeof (hb_position_t) == 4), "");
static_assert ((sizeof (hb_mask_t) == 4), "");
@@ -334,95 +348,37 @@
TypeName(const TypeName&); \
void operator=(const TypeName&)
+
/*
- * Static pools
+ * Compiler-assisted vectorization parameters.
*/
-/* Global nul-content Null pool. Enlarge as necessary. */
+/*
+ * Disable vectorization for now. To correctly use them, we should
+ * use posix_memalign() to allocate in hb_vector_t. Otherwise, can
+ * cause misaligned access.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
+ */
+#if !defined(HB_VECTOR_SIZE)
+# define HB_VECTOR_SIZE 0
+#endif
-#define HB_NULL_POOL_SIZE 264
-static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-
-#ifdef HB_NO_VISIBILITY
-static
+/* The `vector_size' attribute was introduced in gcc 3.1. */
+#if !defined(HB_VECTOR_SIZE)
+# if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
+# define HB_VECTOR_SIZE 128
+# else
+# define HB_VECTOR_SIZE 0
+# endif
+#endif
+static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
+static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
+#if HB_VECTOR_SIZE
+typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
#else
-extern HB_INTERNAL
+typedef uint64_t hb_vector_size_impl_t;
#endif
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline Type const & Null (void) {
- static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
- return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
-#define Null(Type) Null<Type>()
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Namespace, Type, data) \
-} /* Close namespace. */ \
-static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
- return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
-} \
-namespace Namespace { \
-/* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.")
-
-
-/* Global writable pool. Enlarge as necessary. */
-
-/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
- * for correct operation. It only exist to catch and divert program logic bugs instead of
- * causing bad memory access. So, races there are not actually introducing incorrectness
- * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* CRAP pool: Common Region for Access Protection. */
-template <typename Type>
-static inline Type& Crap (void) {
- static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
- Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
- *obj = Null(Type);
- return *obj;
-}
-#define Crap(Type) Crap<Type>()
-
-template <typename Type>
-struct CrapOrNull {
- static inline Type & get (void) { return Crap(Type); }
-};
-template <typename Type>
-struct CrapOrNull<const Type> {
- static inline Type const & get (void) { return Null(Type); }
-};
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
-
-
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
/* HB_NDEBUG disables some sanity checks that are very safe to disable and
@@ -435,41 +391,7 @@
#endif
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
- /* The sizeof() is here to force template instantiation.
- * I'm sure there are better ways to do this but can't think of
- * one right now. Declaring a variable won't work as HB_UNUSED
- * is unusable on some platforms and unused types are less likely
- * to generate a warning than unused variables. */
- static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
- /* The casts below are important as if T is smaller than int,
- * the subtract results will become a signed int! */
- return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
- return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
- return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
+/* Flags */
/* Enable bitwise ops on enums marked as flags_t */
/* To my surprise, looks like the function resolver is happy to silently cast
@@ -493,7 +415,6 @@
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
}
-
/* Useful for set-operations on small enums.
* For example, for testing "x ∈ {x1, x2, x3}" use:
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
@@ -503,58 +424,6 @@
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-
-/* Compiler-assisted vectorization. */
-
-/*
- * Disable vectorization for now. To correctly use them, we should
- * use posix_memalign() to allocate them. Otherwise, can cause
- * misaligned access.
- *
- * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
- */
-#if !defined(HB_VECTOR_SIZE)
-# define HB_VECTOR_SIZE 0
-#endif
-
-/* The `vector_size' attribute was introduced in gcc 3.1. */
-#if !defined(HB_VECTOR_SIZE)
-# if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
-# define HB_VECTOR_SIZE 128
-# else
-# define HB_VECTOR_SIZE 0
-# endif
-#endif
-
-
-/* Global runtime options. */
-
-struct hb_options_t
-{
- unsigned int initialized : 1;
- unsigned int uniscribe_bug_compatible : 1;
-};
-
-union hb_options_union_t {
- unsigned int i;
- hb_options_t opts;
-};
-static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
-
-HB_INTERNAL void
-_hb_options_init (void);
-
-extern HB_INTERNAL hb_options_union_t _hb_options;
-
-static inline hb_options_t
-hb_options (void)
-{
- if (unlikely (!_hb_options.i))
- _hb_options_init ();
-
- return _hb_options.opts;
-}
-
/* Size signifying variable-sized array */
#define VAR 1
@@ -605,6 +474,7 @@
#include "hb-debug.hh"
#include "hb-dsalgs.hh"
#include "hb-mutex-private.hh"
+#include "hb-null.hh"
#include "hb-object-private.hh"
#endif /* HB_PRIVATE_HH */
diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh
index c2c4987..7d020ff 100644
--- a/src/hb-shape-plan-private.hh
+++ b/src/hb-shape-plan-private.hh
@@ -51,6 +51,7 @@
struct hb_shaper_data_t shaper_data;
};
+DECLARE_NULL_INSTANCE (hb_shape_plan_t);
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
, const hb_feature_t *user_features \
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 37ff1a6..0d61d9e 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -49,11 +49,13 @@
#define HB_SHAPER_PLAN(shaper) \
HB_STMT_START { \
- if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
- HB_SHAPER_DATA (shaper, shape_plan) = \
+ if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) \
+ { \
+ /* XXX-MT-bug What happened to *ensure*ing this?!!!! */ \
+ HB_SHAPER_DATA (shaper, shape_plan).set_relaxed ( \
HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
user_features, num_user_features, \
- coords, num_coords); \
+ coords, num_coords)); \
shape_plan->shaper_func = _hb_##shaper##_shape; \
shape_plan->shaper_name = #shaper; \
return; \
@@ -88,6 +90,31 @@
* hb_shape_plan_t
*/
+DEFINE_NULL_INSTANCE (hb_shape_plan_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ true, /* default_shaper_list */
+ nullptr, /* face */
+ HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
+
+ nullptr, /* shaper_func */
+ nullptr, /* shaper_name */
+
+ nullptr, /* user_features */
+ 0, /* num_user_featurs */
+
+ nullptr, /* coords */
+ 0, /* num_coords */
+
+ {
+#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+ },
+};
+
+
/**
* hb_shape_plan_create: (Xconstructor)
* @face:
@@ -188,30 +215,7 @@
hb_shape_plan_t *
hb_shape_plan_get_empty (void)
{
- static const hb_shape_plan_t _hb_shape_plan_nil = {
- HB_OBJECT_HEADER_STATIC,
-
- true, /* default_shaper_list */
- nullptr, /* face */
- HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
- nullptr, /* shaper_func */
- nullptr, /* shaper_name */
-
- nullptr, /* user_features */
- 0, /* num_user_featurs */
-
- nullptr, /* coords */
- 0, /* num_coords */
-
- {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
- }
- };
-
- return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
+ return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
}
/**
@@ -337,7 +341,7 @@
#define HB_SHAPER_EXECUTE(shaper) \
HB_STMT_START { \
- return HB_SHAPER_DATA (shaper, shape_plan) && \
+ return HB_SHAPER_DATA (shaper, shape_plan).get () && \
hb_##shaper##_shaper_font_data_ensure (font) && \
_hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
} HB_STMT_END
@@ -515,7 +519,7 @@
retry:
- hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
+ hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans.get ();
/* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
if (!hb_coords_present (coords, num_coords))
@@ -550,7 +554,8 @@
node->shape_plan = shape_plan;
node->next = cached_plan_nodes;
- if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) {
+ if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node)))
+ {
hb_shape_plan_destroy (shape_plan);
free (node);
goto retry;
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index c1e7365..3c2e6c4 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -32,6 +32,7 @@
#include "hb-shape-plan-private.hh"
#include "hb-buffer-private.hh"
#include "hb-font-private.hh"
+#include "hb-machinery-private.hh"
/**
* SECTION:hb-shape
@@ -45,21 +46,50 @@
* contains the output glyphs and their positions.
**/
-static const char **static_shaper_list;
+
+static void free_static_shaper_list (void);
+static const char *nil_shaper_list[] = {nullptr};
+
+static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+ hb_shaper_list_lazy_loader_t>
+{
+ static inline const char ** create (void)
+ {
+ const char **shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
+ if (unlikely (!shaper_list))
+ return nullptr;
+
+ const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+ unsigned int i;
+ for (i = 0; i < HB_SHAPERS_COUNT; i++)
+ shaper_list[i] = shapers[i].name;
+ shaper_list[i] = nullptr;
+
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_shaper_list);
+#endif
+
+ return shaper_list;
+ }
+ static inline void destroy (const char **l)
+ {
+ free (l);
+ }
+ static inline const char ** get_null (void)
+ {
+ return nil_shaper_list;
+ }
+} static_shaper_list;
#ifdef HB_USE_ATEXIT
static
void free_static_shaper_list (void)
{
-retry:
- const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
- if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
- goto retry;
-
- free (shaper_list);
+ static_shaper_list.free_instance ();
}
#endif
+
/**
* hb_shape_list_shapers:
*
@@ -73,35 +103,7 @@
const char **
hb_shape_list_shapers (void)
{
-retry:
- const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-
- if (unlikely (!shaper_list))
- {
- /* Not found; allocate one. */
- shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
- if (unlikely (!shaper_list)) {
- static const char *nil_shaper_list[] = {nullptr};
- return nil_shaper_list;
- }
-
- const hb_shaper_pair_t *shapers = _hb_shapers_get ();
- unsigned int i;
- for (i = 0; i < HB_SHAPERS_COUNT; i++)
- shaper_list[i] = shapers[i].name;
- shaper_list[i] = nullptr;
-
- if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
- free (shaper_list);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_static_shaper_list); /* First person registers atexit() callback. */
-#endif
- }
-
- return shaper_list;
+ return static_shaper_list.get_unconst ();
}
diff --git a/src/hb-shaper-impl-private.hh b/src/hb-shaper-impl-private.hh
index 7844081..4a10279 100644
--- a/src/hb-shaper-impl-private.hh
+++ b/src/hb-shaper-impl-private.hh
@@ -36,7 +36,7 @@
#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object)
+#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object).get ()
#endif
diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh
index ce2d9f2..fb04bbc 100644
--- a/src/hb-shaper-private.hh
+++ b/src/hb-shaper-private.hh
@@ -49,25 +49,14 @@
_hb_shapers_get (void);
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
/* Means: succeeded, but don't need to keep any data. */
#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-
/* Means: tried but failed to create. */
#define HB_SHAPER_DATA_INVALID ((void *) -1)
-#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t
+#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_##object##_data_t
#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
+#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* reinterpret_cast<hb_atomic_ptr_t<HB_SHAPER_DATA_TYPE(shaper, object) *> *> (&(instance)->shaper_data.shaper))
#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object)
#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create
#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy
@@ -83,7 +72,7 @@
HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
#define HB_SHAPER_DATA_DESTROY(shaper, object) \
- if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
+ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object).get ()) \
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
@@ -95,12 +84,24 @@
HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
{\
retry: \
- HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
+ HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object).get (); \
if (likely (data) && !(condition)) { \
+ /* XXX-MT-bug \
+ * Note that evaluating condition above can be dangerous if another thread \
+ * got here first and destructed data. That's, as always, bad use pattern. \
+ * If you modify the font (change font size), other threads must not be \
+ * using it at the same time. However, since this check is delayed to \
+ * when one actually tries to shape something, this is a XXX race condition \
+ * (and the only know we have that I know of) right now. Ie. you modify the \
+ * font size in one thread, then (supposedly safely) try to use it from two \
+ * or more threads and BOOM! I'm not sure how to fix this. We want RCU. \
+ * Maybe when it doesn't matter when we finally implement AAT shaping, as
+ * this (condition) is currently only used by hb-coretext. */ \
/* Drop and recreate. */ \
/* If someone dropped it in the mean time, throw it away and don't touch it. \
* Otherwise, destruct it. */ \
- if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \
+ if (likely (HB_SHAPER_DATA (shaper, object).cmpexch (data, nullptr))) \
+ { \
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
} \
goto retry; \
@@ -109,7 +110,7 @@
data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
if (unlikely (!data)) \
data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
- if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \
+ if (unlikely (!HB_SHAPER_DATA (shaper, object).cmpexch (nullptr, data))) { \
if (data && \
data != HB_SHAPER_DATA_INVALID && \
data != HB_SHAPER_DATA_SUCCEEDED) \
@@ -117,8 +118,17 @@
goto retry; \
} \
} \
- return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
+ return data != nullptr && (void *) data != HB_SHAPER_DATA_INVALID; \
}
+/* For embedding in face / font / ... */
+struct hb_shaper_data_t {
+#define HB_SHAPER_IMPLEMENT(shaper) hb_atomic_ptr_t<void *> shaper;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+};
+#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
+
+
#endif /* HB_SHAPER_PRIVATE_HH */
diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc
index d44d8c9..e423f25 100644
--- a/src/hb-shaper.cc
+++ b/src/hb-shaper.cc
@@ -26,7 +26,7 @@
#include "hb-private.hh"
#include "hb-shaper-private.hh"
-#include "hb-atomic-private.hh"
+#include "hb-machinery-private.hh"
static const hb_shaper_pair_t all_shapers[] = {
@@ -36,51 +36,28 @@
};
-/* Thread-safe, lock-free, shapers */
+static void free_static_shapers (void);
-static const hb_shaper_pair_t *static_shapers;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shapers (void)
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_t,
+ hb_shapers_lazy_loader_t>
{
-retry:
- hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
- if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr))
- goto retry;
-
- if (unlikely (shapers != all_shapers))
- free ((void *) shapers);
-}
-#endif
-
-const hb_shaper_pair_t *
-_hb_shapers_get (void)
-{
-retry:
- hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-
- if (unlikely (!shapers))
+ static inline hb_shaper_pair_t *create (void)
{
char *env = getenv ("HB_SHAPER_LIST");
- if (!env || !*env) {
- (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
- return (const hb_shaper_pair_t *) all_shapers;
- }
+ if (!env || !*env)
+ return nullptr;
- /* Not found; allocate one. */
- shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
- if (unlikely (!shapers)) {
- (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
- return (const hb_shaper_pair_t *) all_shapers;
- }
+ hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
+ if (unlikely (!shapers))
+ return nullptr;
memcpy (shapers, all_shapers, sizeof (all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
char *end, *p = env;
- for (;;) {
+ for (;;)
+ {
end = strchr (p, ',');
if (!end)
end = p + strlen (p);
@@ -102,15 +79,32 @@
p = end + 1;
}
- if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) {
- free (shapers);
- goto retry;
- }
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_shapers);
+#endif
+
+ return shapers;
+ }
+ static inline void destroy (const hb_shaper_pair_t *p)
+ {
+ free ((void *) p);
+ }
+ static inline const hb_shaper_pair_t *get_null (void)
+ {
+ return all_shapers;
+ }
+} static_shapers;
#ifdef HB_USE_ATEXIT
- atexit (free_static_shapers); /* First person registers atexit() callback. */
+static
+void free_static_shapers (void)
+{
+ static_shapers.free_instance ();
+}
#endif
- }
- return shapers;
+const hb_shaper_pair_t *
+_hb_shapers_get (void)
+{
+ return static_shapers.get_unconst ();
}
diff --git a/src/hb-static.cc b/src/hb-static.cc
index e26e5c8..ddecbba 100644
--- a/src/hb-static.cc
+++ b/src/hb-static.cc
@@ -26,7 +26,41 @@
#include "hb-private.hh"
+#include "hb-open-type-private.hh"
+#include "hb-ot-layout-common-private.hh"
+
+#include "hb-face-private.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
+
#ifndef HB_NO_VISIBILITY
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
+
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+
+DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+
+
+void
+hb_face_t::load_num_glyphs (void) const
+{
+ hb_sanitize_context_t c = hb_sanitize_context_t ();
+ c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
+ hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
+ const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+ num_glyphs = maxp_table->get_num_glyphs ();
+ hb_blob_destroy (maxp_blob);
+}
+
+void
+hb_face_t::load_upem (void) const
+{
+ hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (this);
+ const OT::head *head_table = head_blob->as<OT::head> ();
+ upem = head_table->get_upem ();
+ hb_blob_destroy (head_blob);
+}
+
#endif
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index c8fa39b..36af3be 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -292,7 +292,7 @@
hb_blob_t **glyf_prime, /* OUT */
hb_blob_t **loca_prime /* OUT */)
{
- hb_blob_t *glyf_blob = OT::Sanitizer<OT::glyf>().sanitize (plan->source->reference_table (HB_OT_TAG_glyf));
+ hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
const char *glyf_data = hb_blob_get_data(glyf_blob, nullptr);
OT::glyf::accelerator_t glyf;
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 55c4e3f..1256682 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -56,11 +56,15 @@
static void
_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
{
- // TODO(grieger): This uses all lookups, instead collect
- // the set of lookups that are relevant.
- // See fontTools implementation.
+ hb_auto_t<hb_set_t> lookup_indices;
+ hb_ot_layout_collect_lookups (face,
+ HB_OT_TAG_GSUB,
+ nullptr,
+ nullptr,
+ nullptr,
+ &lookup_indices);
hb_ot_layout_lookups_substitute_closure (face,
- nullptr,
+ &lookup_indices,
gids_to_retain);
}
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index a65b58d..411c6b8 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -78,14 +78,12 @@
static bool
_subset (hb_subset_plan_t *plan)
{
- OT::Sanitizer<TableType> sanitizer;
-
- hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag));
+ hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
const TableType *table = source_blob->as<TableType> ();
hb_tag_t tag = TableType::tableTag;
hb_bool_t result = false;
- if (table != &Null(TableType))
+ if (source_blob->data)
{
result = table->subset(plan);
} else {
@@ -159,14 +157,14 @@
if (unlikely (!buf))
return nullptr;
- OT::hb_serialize_context_t c (buf, face_length);
+ hb_serialize_context_t c (buf, face_length);
OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
- OT::Supplier<hb_tag_t> tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
- OT::Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
+ Supplier<hb_tag_t> tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
+ Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
bool ret = f->serialize_single (&c,
sfnt_tag,
tags_supplier,
diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc
index 2c08718..56d13e7 100644
--- a/src/hb-ucdn.cc
+++ b/src/hb-ucdn.cc
@@ -17,6 +17,7 @@
#include "hb-private.hh"
#include "hb-unicode-private.hh"
+#include "hb-machinery-private.hh"
#include "ucdn.h"
@@ -238,31 +239,14 @@
return ucdn_compat_decompose(u, decomposed);
}
-static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ucdn_funcs (void)
+static void free_static_ucdn_funcs (void);
+
+static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
{
-retry:
- hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr))
- goto retry;
-
- hb_unicode_funcs_destroy (ucdn_funcs);
-}
-#endif
-
-extern "C" HB_INTERNAL
-hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs (void)
-{
-retry:
- hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-
- if (unlikely (!funcs))
+ static inline hb_unicode_funcs_t *create (void)
{
- funcs = hb_unicode_funcs_create (nullptr);
+ hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
@@ -271,15 +255,25 @@
hb_unicode_funcs_make_immutable (funcs);
- if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
- hb_unicode_funcs_destroy (funcs);
- goto retry;
- }
+#ifdef HB_USE_ATEXIT
+ atexit (free_static_ucdn_funcs);
+#endif
+
+ return funcs;
+ }
+} static_ucdn_funcs;
#ifdef HB_USE_ATEXIT
- atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
+static
+void free_static_ucdn_funcs (void)
+{
+ static_ucdn_funcs.free_instance ();
+}
#endif
- };
- return hb_unicode_funcs_reference (funcs);
+extern "C" HB_INTERNAL
+hb_unicode_funcs_t *
+hb_ucdn_get_unicode_funcs (void)
+{
+ return static_ucdn_funcs.get_unconst ();
}
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
index b2c203d..fb16ba4 100644
--- a/src/hb-unicode-private.hh
+++ b/src/hb-unicode-private.hh
@@ -60,7 +60,8 @@
HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
/* ^--- Add new simple callbacks here */
-struct hb_unicode_funcs_t {
+struct hb_unicode_funcs_t
+{
hb_object_header_t header;
ASSERT_POD ();
@@ -263,9 +264,7 @@
#undef HB_UNICODE_FUNC_IMPLEMENT
} destroy;
};
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
+DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
/* Modified combining marks */
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 2d16c2e..8cb4172 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -185,7 +185,8 @@
}
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
+{
HB_OBJECT_HEADER_STATIC,
nullptr, /* parent */
@@ -209,7 +210,7 @@
hb_unicode_funcs_t *
hb_unicode_funcs_get_empty (void)
{
- return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
+ return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
}
/**
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index b17fa31..11b7384 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -190,7 +190,8 @@
}
-struct hb_uniscribe_shaper_funcs_t {
+struct hb_uniscribe_shaper_funcs_t
+{
SIOT ScriptItemizeOpenType;
SSOT ScriptShapeOpenType;
SPOT ScriptPlaceOpenType;
@@ -220,47 +221,49 @@
}
}
};
-static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
+
+
+static void free_static_uniscribe_shaper_funcs (void);
+
+static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
+ hb_uniscribe_shaper_funcs_lazy_loader_t>
+{
+ static inline hb_uniscribe_shaper_funcs_t *create (void)
+ {
+ hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
+ if (unlikely (!funcs))
+ return nullptr;
+
+ funcs->init ();
#ifdef HB_USE_ATEXIT
-static inline void
-free_uniscribe_funcs (void)
-{
-retry:
- hb_uniscribe_shaper_funcs_t *local_uniscribe_funcs =
- (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
- if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, local_uniscribe_funcs, nullptr))
- goto retry;
+ atexit (free_static_uniscribe_shaper_funcs);
+#endif
- free (uniscribe_funcs);
+ return funcs;
+ }
+ static inline void destroy (hb_uniscribe_shaper_funcs_t *p)
+ {
+ free ((void *) p);
+ }
+ static inline hb_uniscribe_shaper_funcs_t *get_null (void)
+ {
+ return nullptr;
+ }
+} static_uniscribe_shaper_funcs;
+
+#ifdef HB_USE_ATEXIT
+static
+void free_static_uniscribe_shaper_funcs (void)
+{
+ static_uniscribe_shaper_funcs.free_instance ();
}
#endif
static hb_uniscribe_shaper_funcs_t *
hb_uniscribe_shaper_get_funcs (void)
{
-retry:
- hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
-
- if (unlikely (!funcs))
- {
- funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
- if (unlikely (!funcs))
- return nullptr;
-
- funcs->init ();
-
- if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, nullptr, funcs)) {
- free (funcs);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
-#endif
- }
-
- return funcs;
+ return static_uniscribe_shaper_funcs.get_unconst ();
}
@@ -309,7 +312,7 @@
* shaper face data
*/
-struct hb_uniscribe_shaper_face_data_t {
+struct hb_uniscribe_face_data_t {
HANDLE fh;
hb_uniscribe_shaper_funcs_t *funcs;
wchar_t face_name[LF_FACESIZE];
@@ -358,7 +361,7 @@
* full, PS. All of them point to the same name data with our unique name.
*/
- blob = OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (blob);
+ blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (blob);
unsigned int length, new_length, name_str_len;
const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
@@ -383,7 +386,7 @@
memcpy(new_sfnt_data, orig_sfnt_data, length);
- OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
+ OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
name.format.set (0);
name.count.set (ARRAY_LENGTH (name_IDs));
name.stringOffset.set (name.get_size ());
@@ -399,7 +402,7 @@
}
/* Copy string data from new_name, converting wchar_t to UTF16BE. */
- unsigned char *p = &OT::StructAfter<unsigned char> (name);
+ unsigned char *p = &StructAfter<unsigned char> (name);
for (unsigned int i = 0; i < name_str_len; i++)
{
*p++ = new_name[i] >> 8;
@@ -439,10 +442,10 @@
HB_MEMORY_MODE_WRITABLE, nullptr, free);
}
-hb_uniscribe_shaper_face_data_t *
+hb_uniscribe_face_data_t *
_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
{
- hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
+ hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
if (unlikely (!data))
return nullptr;
@@ -479,7 +482,7 @@
}
void
-_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
+_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_face_data_t *data)
{
RemoveFontMemResourceEx (data->fh);
free (data);
@@ -490,7 +493,7 @@
* shaper font data
*/
-struct hb_uniscribe_shaper_font_data_t {
+struct hb_uniscribe_font_data_t {
HDC hdc;
LOGFONTW log_font;
HFONT hfont;
@@ -508,19 +511,19 @@
lf->lfCharSet = DEFAULT_CHARSET;
hb_face_t *face = font->face;
- hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+ hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
return true;
}
-hb_uniscribe_shaper_font_data_t *
+hb_uniscribe_font_data_t *
_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
- hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
+ hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
if (unlikely (!data))
return nullptr;
@@ -559,7 +562,7 @@
}
void
-_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
+_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_font_data_t *data)
{
if (data->hdc)
ReleaseDC (nullptr, data->hdc);
@@ -574,7 +577,7 @@
hb_uniscribe_font_get_logfontw (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+ hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
return &font_data->log_font;
}
@@ -582,7 +585,7 @@
hb_uniscribe_font_get_hfont (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+ hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
return font_data->hfont;
}
@@ -591,20 +594,20 @@
* shaper shape_plan data
*/
-struct hb_uniscribe_shaper_shape_plan_data_t {};
+struct hb_uniscribe_shape_plan_data_t {};
-hb_uniscribe_shaper_shape_plan_data_t *
+hb_uniscribe_shape_plan_data_t *
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
- return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+ return (hb_uniscribe_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
-_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shape_plan_data_t *data HB_UNUSED)
{
}
@@ -622,8 +625,8 @@
unsigned int num_features)
{
hb_face_t *face = font->face;
- hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+ hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+ hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
/*
diff --git a/src/hb-vector-private.hh b/src/hb-vector-private.hh
new file mode 100644
index 0000000..1ef20d4
--- /dev/null
+++ b/src/hb-vector-private.hh
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2017,2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_VECTOR_PRIVATE_HH
+#define HB_VECTOR_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+template <typename Type, unsigned int StaticSize=8>
+struct hb_vector_t
+{
+ unsigned int len;
+ unsigned int allocated; /* == 0 means allocation failed. */
+ Type *arrayZ;
+ Type static_array[StaticSize];
+
+ void init (void)
+ {
+ len = 0;
+ allocated = ARRAY_LENGTH (static_array);
+ arrayZ = static_array;
+ }
+
+ inline Type& operator [] (unsigned int i)
+ {
+ if (unlikely (i >= len))
+ return Crap (Type);
+ return arrayZ[i];
+ }
+ inline const Type& operator [] (unsigned int i) const
+ {
+ if (unlikely (i >= len))
+ return Null(Type);
+ return arrayZ[i];
+ }
+
+ inline Type *push (void)
+ {
+ if (unlikely (!resize (len + 1)))
+ return &Crap(Type);
+ return &arrayZ[len - 1];
+ }
+ inline Type *push (const Type& v)
+ {
+ Type *p = push ();
+ *p = v;
+ return p;
+ }
+
+ /* Allocate for size but don't adjust len. */
+ inline bool alloc (unsigned int size)
+ {
+ if (unlikely (!allocated))
+ return false;
+
+ if (likely (size <= allocated))
+ return true;
+
+ /* Reallocate */
+
+ unsigned int new_allocated = allocated;
+ while (size >= new_allocated)
+ new_allocated += (new_allocated >> 1) + 8;
+
+ Type *new_array = nullptr;
+
+ if (arrayZ == static_array)
+ {
+ new_array = (Type *) calloc (new_allocated, sizeof (Type));
+ if (new_array)
+ memcpy (new_array, arrayZ, len * sizeof (Type));
+ }
+ else
+ {
+ bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
+ if (likely (!overflows))
+ new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
+ }
+
+ if (unlikely (!new_array))
+ {
+ allocated = 0;
+ return false;
+ }
+
+ arrayZ = new_array;
+ allocated = new_allocated;
+
+ return true;
+ }
+
+ inline bool resize (int size_)
+ {
+ unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+ if (!alloc (size))
+ return false;
+
+ if (size > len)
+ memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
+
+ len = size;
+ return true;
+ }
+
+ inline void pop (void)
+ {
+ if (!len) return;
+ len--;
+ }
+
+ inline void remove (unsigned int i)
+ {
+ if (unlikely (i >= len))
+ return;
+ memmove (static_cast<void *> (&arrayZ[i]),
+ static_cast<void *> (&arrayZ[i + 1]),
+ (len - i - 1) * sizeof (Type));
+ len--;
+ }
+
+ inline void shrink (int size_)
+ {
+ unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+ if (size < len)
+ len = size;
+ }
+
+ template <typename T>
+ inline Type *find (T v) {
+ for (unsigned int i = 0; i < len; i++)
+ if (arrayZ[i] == v)
+ return &arrayZ[i];
+ return nullptr;
+ }
+ template <typename T>
+ inline const Type *find (T v) const {
+ for (unsigned int i = 0; i < len; i++)
+ if (arrayZ[i] == v)
+ return &arrayZ[i];
+ return nullptr;
+ }
+
+ inline void qsort (int (*cmp)(const void*, const void*))
+ {
+ ::qsort (arrayZ, len, sizeof (Type), cmp);
+ }
+
+ inline void qsort (void)
+ {
+ ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
+ }
+
+ inline void qsort (unsigned int start, unsigned int end)
+ {
+ ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
+ }
+
+ template <typename T>
+ inline Type *lsearch (const T &x)
+ {
+ for (unsigned int i = 0; i < len; i++)
+ if (0 == this->arrayZ[i].cmp (&x))
+ return &arrayZ[i];
+ return nullptr;
+ }
+
+ template <typename T>
+ inline Type *bsearch (const T &x)
+ {
+ unsigned int i;
+ return bfind (x, &i) ? &arrayZ[i] : nullptr;
+ }
+ template <typename T>
+ inline const Type *bsearch (const T &x) const
+ {
+ unsigned int i;
+ return bfind (x, &i) ? &arrayZ[i] : nullptr;
+ }
+ template <typename T>
+ inline bool bfind (const T &x, unsigned int *i) const
+ {
+ int min = 0, max = (int) this->len - 1;
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+ int c = this->arrayZ[mid].cmp (&x);
+ if (c < 0)
+ max = mid - 1;
+ else if (c > 0)
+ min = mid + 1;
+ else
+ {
+ *i = mid;
+ return true;
+ }
+ }
+ if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
+ max++;
+ *i = max;
+ return false;
+ }
+
+ inline void fini (void)
+ {
+ if (arrayZ != static_array)
+ free (arrayZ);
+ arrayZ = nullptr;
+ allocated = len = 0;
+ }
+};
+
+
+#endif /* HB_VECTOR_PRIVATE_HH */
diff --git a/src/hb-version.h b/src/hb-version.h
index c3c38de..e0816d1 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -38,9 +38,9 @@
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 8
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MICRO 8
-#define HB_VERSION_STRING "1.8.3"
+#define HB_VERSION_STRING "1.8.8"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \
diff --git a/src/main.cc b/src/main.cc
index 873d240..98a1320 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -51,10 +51,9 @@
const char *font_data = hb_blob_get_data (blob, &len);
printf ("Opened font file %s: %d bytes long\n", argv[1], len);
- Sanitizer<OpenTypeFontFile> sanitizer;
- hb_blob_t *font_blob = sanitizer.sanitize (blob);
+ hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob<OpenTypeFontFile> (blob);
const OpenTypeFontFile* sanitized = font_blob->as<OpenTypeFontFile> ();
- if (sanitized == &Null(OpenTypeFontFile))
+ if (!font_blob->data)
{
printf ("Sanitization of the file wasn't successful. Exit");
return 1;
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 65ceeda..a203344 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -9,6 +9,8 @@
# Convenience targets:
lib:
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+ @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
EXTRA_DIST += CMakeLists.txt
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872
new file mode 100644
index 0000000..6307ddd
--- /dev/null
+++ b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872
Binary files differ
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480
new file mode 100644
index 0000000..49bcb30
--- /dev/null
+++ b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480
Binary files differ
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648
new file mode 100644
index 0000000..b506d2a
--- /dev/null
+++ b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648
Binary files differ
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912
new file mode 100644
index 0000000..ffcea64
--- /dev/null
+++ b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912
Binary files differ
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 0ca5566..d071c88 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -396,8 +396,8 @@
initFreeType();
openFont("fonts/MathTestFontEmpty.otf");
- g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
- g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
+ g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 0); // MathVariants not available
+ g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 0); // MathVariants not available
closeFont();
openFont("fonts/MathTestFontPartial1.otf");
diff --git a/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf b/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf
new file mode 100644
index 0000000..a1fef49
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf b/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf
new file mode 100644
index 0000000..3dd30ed
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf b/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf
new file mode 100644
index 0000000..ca23ef8
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/tests/indic-old-spec.tests b/test/shaping/data/in-house/tests/indic-old-spec.tests
index cd56319..eb967ad 100644
--- a/test/shaping/data/in-house/tests/indic-old-spec.tests
+++ b/test/shaping/data/in-house/tests/indic-old-spec.tests
@@ -1,2 +1,4 @@
../fonts/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf::U+0C9A,U+0CCD,U+0C9A,U+0CCD:[U0C9A_U0CCD.haln=0+1066|U0C9A_0CCD.blwf=0+0]
../fonts/270b89df543a7e48e206a2d830c0e10e5265c630.ttf::U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D:[glyph201=0+1183|U0D4D=0+0]
+../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+094D,U+0020:[Tra=0+550|virAma=0@-73,-110+0|space=4+500]
+../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+0942:[Tra=0+550|UT=0@42,-150+0]
diff --git a/test/shaping/data/in-house/tests/khmer-misc.tests b/test/shaping/data/in-house/tests/khmer-misc.tests
new file mode 100644
index 0000000..a7a1c6d
--- /dev/null
+++ b/test/shaping/data/in-house/tests/khmer-misc.tests
@@ -0,0 +1,89 @@
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1781,U+17D2,U+1798,U+17C2:[uni17C2=0+288|uni1781=0+635|uni17D21798=0@22,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1787,U+17B6:[uni178717B6=0+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1790,U+17D2,U+1784,U+17C3:[uni17C3=0+288|uni1790=0+635|uni17D21784=0@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17B6:[uni179817B6=0+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+1796,U+17BB:[uni1798=0+635|uni17D21796=0@-1,-26+0|uni17BB=0@-22,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A:[uni179A=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17B8:[uni179A=0+288|uni17B8.r=0@76,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17CD:[uni179A=0+288|uni17CD.r=0@18,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17C5:[uni17C1=0+288|uni179F17C5=0+1216]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+17A5:[uni179A=0+288|uni17D2=0+0|uni17A5=2+635]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17B9,U+17D2,U+1788:[uni1784=0+635|uni17B9=0@-46,30+0|uni17D21788=0+234]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1788,U+17B9:[uni1784=0+635|uni17D21788=0+234|uni17B9=0@8,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1782,U+17D2,U+179A:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+179A,U+17D2,U+1782:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+200C,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|space=0+0|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1794,U+17CA,U+17D0:[uni1794=0+635|uni17CA=0@-46,-29+0|uni17D0=0@-46,113+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1793,U+17C2,U+17CE:[uni17C2=0+288|uni1793=0+635|uni17CE=0@-36,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C1,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C0,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636|uni17C0.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C4,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017B6=0+924]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C5,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017C5=0+924]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1796,U+17D1,U+17B6:[uni179617B6=0+923|uni17D1=0@-311,-19+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+178F,U+17D2,U+179A,U+17B6,U+1780,U+17CB:[uni1780=0+636|uni17D2179A.low=1+287|uni179317B6=1+924|uni17D2178F=1@-290,-26+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B7,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B7=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B8,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B8=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B6,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F17B6=0+584|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B7,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B7=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B8,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B8=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B9,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B9=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BA,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BA=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BB,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BB=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BC,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BC=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BD,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BD=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BF,U+1793,U+17D2,U+178F:[uni17C1=0+288|uni1780=0+636|uni17D2179F=0+302|uni17BF.right2=0+288|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B6,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C6=0@39,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B7,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17B7=0@-4,30+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C6=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C1,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C4,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C6=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17BC:[uni1789=0+952|uni17BC=0@-173,-260+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BB:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BB=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BC:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BC=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BD:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BD=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302|uni17C0.right2=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C4:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17B6=0+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C5:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17C5=0+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17BB,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17BB=0@-19,-296+0|uni17C6=0@-46,-29+0|uni1780=5+636|uni17CB=5@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C4,U+1780,U+17CB:[uni17C1=0+288|uni179217B6=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C5,U+1780,U+17CB:[uni17C1=0+288|uni179217C5=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17C6=0@-46,-29+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17B6:[uni179817B6=0+923|uni17D2178F=0@-289,-26+0|uni17D2179B=0@-289,-296+0|uni17C9=0@-334,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BB:[uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BB=0@-18,-566+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BF:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17C0:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17C0.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1799,U+17D2,U+1799,U+17BE,U+17A0,U+17D2,U+179C,U+17D2,U+179B,U+17C3:[uni17C1=0+288|uni1799=0+953|uni17D21799=0+298|uni17B8=0@1,30+0|uni17C3=4+288|uni17A0=4+928|uni17D2179C=4@20,-26+0|uni17D2179B=4@19,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+179A:[uni17D2179A=0+287|uni179A=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B6:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni178417B6=10+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B7:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B7=10@-46,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B8:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B8=10@-46,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+178F,U+17D2,U+179A,U+17B8,U+179C,U+17D0,U+1781,U+17D2,U+1789,U+17D2,U+179F,U+17B6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0|uni179C=6+326|uni17D0=6@139,40+0|uni1781=8+635|uni17D21789=8@-4,-26+0|uni17D2179F17B6.low=8+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B6:[uni17D2179A=0+287|uni179F17B6=0+1216|uni17D2178F=0@-274,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B7:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B7=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B8:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B9:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B9=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BA:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BB:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BB=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BC:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BC=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BD:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BD=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BE:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BF.right2=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C0.right1.high=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C6=0@-32,113+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BE:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17B8=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BF:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17C0:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17C0.right1.high=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+1784,U+17D2,U+1780:[uni17D2179A=0+287|uni17A0=0+928|uni17D2179C=0@20,-26+0|uni1784=5+635|uni17D21780=5@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+17B6,U+17C6,U+1784:[uni17D2179A=0+287|uni17A017B6=0+1216|uni17D2179C=0@-268,-26+0|uni17C6=0@47,-29+0|uni1784=7+635]
diff --git a/test/shaping/data/in-house/tests/use.tests b/test/shaping/data/in-house/tests/use.tests
index 172946c..4b46620 100644
--- a/test/shaping/data/in-house/tests/use.tests
+++ b/test/shaping/data/in-house/tests/use.tests
@@ -2,4 +2,9 @@
../fonts/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+0|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212]
../fonts/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+1211|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212]
../fonts/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf:--font-funcs=ot:U+11103,U+11128:[u11103=0+837|u11128=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+1112E:[u11124=0+514|u11131=0+0|u11127=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11131,U+11127:[u11124=0+514|u11131=0+0|u11127=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11127,U+11131:[u11124=0+514|u11127=0+0|uni25CC=0+547|u11131=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11134,U+11131:[u11124=0+514|u11134=0+0|u11131=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11131,U+11134:[u11124=0+514|u11131=0+0|uni25CC=0+547|u11134=0+0]
../fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf:--font-funcs=ft:U+11410,U+11442,U+11411,U+11440,U+11443,U+11410,U+11442,U+11411,U+11441,U+11443:[E_dv.alt=0+275|Ga.icd=0+367|Gha.diag=0@100,0+386|AA_dv.alt=0+208|Candrabindu=0@17,-8+0|E_dv.alt=5+275|Ga.icd=5+367|Gha.diag=5@100,0+386|AU_dv_part.alt=5+213|Candrabindu.sm=5@-52,179+0]
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/reph.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/misc/reph.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/reph.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/misc/reph.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/dottedcircle.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/dottedcircle.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/dottedcircle.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/dottedcircle.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/eyelash.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/eyelash.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/eyelash.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/eyelash.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/joiners.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/joiners.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/joiners.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/joiners.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/spec-deviations.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/spec-deviations.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/spec-deviations.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/spec-deviations.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/tricky-reordering.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/tricky-reordering.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/tricky-reordering.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/tricky-reordering.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/right-matras.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/misc/right-matras.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/right-matras.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/misc/right-matras.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/cibu.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/cibu.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/cibu.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/cibu.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/dot-reph.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/dot-reph.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/dot-reph.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/dot-reph.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/bindu.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/misc/bindu.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/bindu.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/misc/bindu.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/extensive.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/extensive.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/extensive.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/extensive.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/reph.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/reph.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/reph.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/reph.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/split-matras.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/split-matras.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/split-matras.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/split-matras.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/misc/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/misc/misc.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/misc/misc.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/LICENSE b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/LICENSE
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/LICENSE
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/LICENSE
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/README b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/README
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/README
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/README
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/SOURCES b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/SOURCES
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/SOURCES
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/SOURCES
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt
rename to test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt
deleted file mode 100644
index 945dd1d..0000000
--- a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-ខ្មែ
-ជា
-ថ្ងៃ
-មា
-ម្ពុ
-រ
-រី
-រ៍
-សៅ
-រ្ឥ
-ងឹ្ឈ
-ង្ឈឹ
-ង្គ្រ
-ង្រ្គ
-ម៉្លេះ
-ម៉្លេះ
-ប៊័
-នែ៎
-កេ្រ
-កៀ្រ
-កោ្រ
-កៅ្រ
-ព៑ា
diff --git a/test/shaping/texts/in-house/shaper-khmer/misc.txt b/test/shaping/texts/in-house/shaper-khmer/misc.txt
new file mode 100644
index 0000000..3bbffe7
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-khmer/misc.txt
@@ -0,0 +1,89 @@
+ខ្មែ
+ជា
+ថ្ងៃ
+មា
+ម្ពុ
+រ
+រី
+រ៍
+សៅ
+រ្ឥ
+ងឹ្ឈ
+ង្ឈឹ
+ង្គ្រ
+ង្រ្គ
+ម៉្លេះ
+ម៉្លេះ
+ប៊័
+នែ៎
+កេ្រ
+កៀ្រ
+កោ្រ
+កៅ្រ
+ព៑ា
+កន្ត្រាក់
+កន្រ្សិក់
+កន្រ្សីក់
+ក្សាន្ត
+ក្សិន្ត
+ក្សីន្ត
+ក្សឹន្ត
+ក្សឺន្ត
+ក្សុន្ត
+ក្សូន្ត
+ក្សួន្ត
+ក្សឿន្ត
+ឃ្ល្សាំ
+ឃ្ល្សិះ
+ឃ្ល្សុំ
+ឃ្ល្សុះ
+ឃ្ល្សេះ
+ឃ្ល្សោះ
+ឃ្ល្សំ
+ឃ្ល្សះ
+ញូ
+ញ្ញ
+ញ្ញុ
+ញ្ញូ
+ញ្ញួ
+ត្រ្សៀ
+ត្រ្សេ
+ត្រ្សែ
+ត្រ្សៃ
+ត្រ្សោ
+ត្រ្សៅ
+ធ្លុំក់
+ធ្លោក់
+ធ្លៅក់
+ធ្លំក់
+ម្ត្ល៉ា
+ម្ត្ល៉ុ
+ម្ត្ល៉ឿ
+ម្ត្ល៉ៀ
+យ្យើហ្វ្លៃ
+រ្រ
+សាស្ត្រឃ្ឈងា
+សាស្ត្រឃ្ឈងិ
+សាស្ត្រឃ្ឈងី
+ស្ត្រីវ័ខ្ញ្សា
+ស្រ្តា
+ស្រ្តិ
+ស្រ្តី
+ស្រ្តឹ
+ស្រ្តឺ
+ស្រ្តុ
+ស្រ្តូ
+ស្រ្តួ
+ស្រ្តើ
+ស្រ្តឿ
+ស្រ្ត៊ឿ
+ស្រ្ត៊ៀ
+ស្រ្ត៊េ
+ស្រ្ត៊ែ
+ស្រ្ត៊ៃ
+ស្រ្ត៊ំ
+ហ្គ្ស៊ើ
+ហ្គ្ស៊ឿ
+ហ្គ្ស៊ៀ
+ហ្រ្វង្ក
+ហ្រ្វាំង
diff --git a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks-invalid.txt b/test/shaping/texts/in-house/shaper-khmer/other-marks-invalid.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks-invalid.txt
rename to test/shaping/texts/in-house/shaper-khmer/other-marks-invalid.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks.txt b/test/shaping/texts/in-house/shaper-khmer/other-marks.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks.txt
rename to test/shaping/texts/in-house/shaper-khmer/other-marks.txt
diff --git a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-javanese/misc.txt b/test/shaping/texts/in-house/shaper-use/script-javanese/misc.txt
similarity index 100%
rename from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-javanese/misc.txt
rename to test/shaping/texts/in-house/shaper-use/script-javanese/misc.txt