diff options
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-0.9.7-PATCHES/patch-01-from-git')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-0.9.7-PATCHES/patch-01-from-git | 4921 |
1 files changed, 4921 insertions, 0 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-0.9.7-PATCHES/patch-01-from-git b/Build/source/libs/harfbuzz/harfbuzz-0.9.7-PATCHES/patch-01-from-git new file mode 100644 index 00000000000..d507194fcc4 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-0.9.7-PATCHES/patch-01-from-git @@ -0,0 +1,4921 @@ +diff -ur harfbuzz-0.9.7.orig/src/hb-open-file-private.hh harfbuzz-0.9.7/src/hb-open-file-private.hh +--- harfbuzz-0.9.7.orig/src/hb-open-file-private.hh 2012-11-17 03:44:11.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-open-file-private.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -54,7 +54,7 @@ + typedef struct TableRecord + { + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -103,7 +103,7 @@ + + public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); + } + +@@ -131,7 +131,7 @@ + inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (table.sanitize (c, this)); + } + +@@ -170,7 +170,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ +@@ -232,7 +232,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); + switch (u.tag) { + case CFFTag: /* All the non-collection tags */ +diff -ur harfbuzz-0.9.7.orig/src/hb-open-type-private.hh harfbuzz-0.9.7/src/hb-open-type-private.hh +--- harfbuzz-0.9.7.orig/src/hb-open-type-private.hh 2012-11-17 03:44:17.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-open-type-private.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -37,6 +37,7 @@ + namespace OT { + + ++ + /* + * Casts + */ +@@ -165,12 +166,24 @@ + #endif + + +-#define TRACE_SANITIZE() \ +- hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, HB_FUNC, ""); ++#define TRACE_SANITIZE(this) \ ++ hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ ""); + + + struct hb_sanitize_context_t + { ++ inline const char *get_name (void) { return "SANITIZE"; } ++ static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; ++ typedef bool return_t; ++ template <typename T> ++ inline return_t process (const T &obj) { return obj.sanitize (this); } ++ static return_t default_return_value (void) { return true; } ++ bool stop_sublookup_iteration (const return_t r) const { return false; } ++ return_t recurse (unsigned int lookup_index) ++ { return default_return_value (); } ++ + inline void init (hb_blob_t *b) + { + this->blob = hb_blob_reference (b); +@@ -205,10 +218,11 @@ + { + const char *p = (const char *) base; + +- hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, +- "check_range [%p..%p] (%d bytes) in [%p..%p]", +- p, p + len, len, +- this->start, this->end); ++ hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace ++ (&this->debug_depth, "SANITIZE", this->blob, NULL, ++ "check_range [%p..%p] (%d bytes) in [%p..%p]", ++ p, p + len, len, ++ this->start, this->end); + + return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); + } +@@ -218,10 +232,11 @@ + const char *p = (const char *) base; + bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); + +- hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, +- "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", +- p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, +- this->start, this->end); ++ hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace ++ (&this->debug_depth, "SANITIZE", this->blob, NULL, ++ "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", ++ p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, ++ this->start, this->end); + + return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); + } +@@ -237,11 +252,12 @@ + const char *p = (const char *) base; + this->edit_count++; + +- hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, +- "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", +- this->edit_count, +- p, p + len, len, +- this->start, this->end); ++ hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace ++ (&this->debug_depth, "SANITIZE", this->blob, NULL, ++ "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", ++ this->edit_count, ++ p, p + len, len, ++ this->start, this->end); + + return TRACE_RETURN (this->writable); + } +@@ -336,8 +352,10 @@ + #endif + + +-#define TRACE_SERIALIZE() \ +- hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, ""); ++#define TRACE_SERIALIZE(this) \ ++ hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ ++ (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ ++ ""); + + + struct hb_serialize_context_t +@@ -531,7 +549,7 @@ + inline int cmp (IntType<Type> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } + inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (likely (c->check_struct (this))); + } + protected: +@@ -556,7 +574,7 @@ + struct LONGDATETIME + { + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (likely (c->check_struct (this))); + } + private: +@@ -620,7 +638,7 @@ + inline uint32_t to_int (void) const { return (major << 16) + minor; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -660,7 +678,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + unsigned int offset = *this; + if (unlikely (!offset)) return TRACE_RETURN (true); +@@ -669,7 +687,7 @@ + } + template <typename T> + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + unsigned int offset = *this; + if (unlikely (!offset)) return TRACE_RETURN (true); +@@ -733,7 +751,7 @@ + inline bool serialize (hb_serialize_context_t *c, + unsigned int items_len) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); +@@ -744,7 +762,7 @@ + Supplier<Type> &items, + unsigned int items_len) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < items_len; i++) + array[i] = items[i]; +@@ -753,7 +771,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + + /* Note: for structs that do not reference other structs, +@@ -768,7 +786,7 @@ + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) +@@ -778,7 +796,7 @@ + } + template <typename T> + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) +@@ -789,7 +807,7 @@ + + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); + } + +@@ -831,12 +849,12 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); + } + template <typename T> + inline bool sanitize (hb_sanitize_context_t *c, T user_data) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); + } + }; +@@ -859,7 +877,7 @@ + Supplier<Type> &items, + unsigned int items_len) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!items_len)) return TRACE_RETURN (true); +@@ -876,7 +894,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + + /* Note: for structs that do not reference other structs, +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-head-table.hh harfbuzz-0.9.7/src/hb-ot-head-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-head-table.hh 2012-11-17 03:44:21.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-head-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -52,7 +52,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + } + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-hhea-table.hh harfbuzz-0.9.7/src/hb-ot-hhea-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-hhea-table.hh 2012-11-17 03:44:25.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-hhea-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -45,7 +45,7 @@ + static const hb_tag_t Tag = HB_OT_TAG_hhea; + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + } + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-hmtx-table.hh harfbuzz-0.9.7/src/hb-ot-hmtx-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-hmtx-table.hh 2012-11-17 03:44:28.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-hmtx-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -53,7 +53,7 @@ + static const hb_tag_t Tag = HB_OT_TAG_hmtx; + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + /* We don't check for anything specific here. The users of the + * struct do all the hard work... */ + return TRACE_RETURN (true); +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout-common-private.hh harfbuzz-0.9.7/src/hb-ot-layout-common-private.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-layout-common-private.hh 2012-11-17 03:44:32.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout-common-private.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -61,7 +61,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base)); + } + +@@ -115,7 +115,7 @@ + { return this+RecordArrayOf<Type>::operator [](i).offset; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this)); + } + }; +@@ -129,7 +129,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -193,7 +193,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); + } + +@@ -231,7 +231,7 @@ + inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); + } + +@@ -248,6 +248,33 @@ + + typedef RecordListOf<Script> ScriptList; + ++struct FeatureParamsSize ++{ ++ inline bool sanitize (hb_sanitize_context_t *c) { ++ TRACE_SANITIZE (this); ++ return TRACE_RETURN (c->check_struct (this)); ++ } ++ ++ USHORT params[5]; ++ public: ++ DEFINE_SIZE_STATIC (10); ++}; ++ ++struct FeatureParams ++{ ++ /* Note: currently the only feature with params is 'size', so we hardcode ++ * the length of the table to that of the FeatureParamsSize. */ ++ ++ inline bool sanitize (hb_sanitize_context_t *c) { ++ TRACE_SANITIZE (this); ++ return TRACE_RETURN (c->check_struct (this)); ++ } ++ ++ union { ++ FeatureParamsSize size; ++ } u; ++ DEFINE_SIZE_STATIC (10); ++}; + + struct Feature + { +@@ -260,12 +287,17 @@ + unsigned int *lookup_tags /* OUT */) const + { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); } + ++ inline const FeatureParams &get_feature_params (void) const ++ { return this+featureParams; } ++ + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); +- return TRACE_RETURN (c->check_struct (this) && lookupIndex.sanitize (c)); ++ TRACE_SANITIZE (this); ++ return TRACE_RETURN (c->check_struct (this) && lookupIndex.sanitize (c) && ++ featureParams.sanitize (c, this)); + } + +- Offset featureParams; /* Offset to Feature Parameters table (if one ++ OffsetTo<FeatureParams> ++ featureParams; /* Offset to Feature Parameters table (if one + * has been defined for the feature), relative + * to the beginning of the Feature Table; = Null + * if not required */ +@@ -318,7 +350,7 @@ + uint32_t lookup_props, + unsigned int num_subtables) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + lookupType.set (lookup_type); + lookupFlag.set (lookup_props & 0xFFFF); +@@ -332,7 +364,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + /* Real sanitize of the subtables is done by GSUB/GPOS/... */ + if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false); + if (lookupFlag & LookupFlag::UseMarkFilteringSet) +@@ -377,7 +409,7 @@ + Supplier<GlyphID> &glyphs, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + glyphArray.len.set (num_glyphs); + if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false); +@@ -388,7 +420,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (glyphArray.sanitize (c)); + } + +@@ -445,7 +477,7 @@ + Supplier<GlyphID> &glyphs, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + + if (unlikely (!num_glyphs)) return TRACE_RETURN (true); +@@ -474,7 +506,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (rangeRecord.sanitize (c)); + } + +@@ -541,8 +573,6 @@ + + struct Coverage + { +- inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); } +- + inline unsigned int get_coverage (hb_codepoint_t glyph_id) const + { + switch (u.format) { +@@ -556,7 +586,7 @@ + Supplier<GlyphID> &glyphs, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) +@@ -571,7 +601,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -682,7 +712,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c)); + } + +@@ -725,7 +755,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (rangeRecord.sanitize (c)); + } + +@@ -756,8 +786,6 @@ + + struct ClassDef + { +- inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_class (glyph_id); } +- + inline unsigned int get_class (hb_codepoint_t glyph_id) const + { + switch (u.format) { +@@ -768,7 +796,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -860,7 +888,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ())); + } + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout-gdef-table.hh harfbuzz-0.9.7/src/hb-ot-layout-gdef-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-layout-gdef-table.hh 2012-11-17 03:44:36.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout-gdef-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -51,7 +51,7 @@ + unsigned int *point_count /* IN/OUT */, + unsigned int *point_array /* OUT */) const + { +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (index == NOT_COVERED) + { + if (point_count) +@@ -72,7 +72,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); + } + +@@ -102,7 +102,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -128,7 +128,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -151,7 +151,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this)); + } + +@@ -179,7 +179,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -220,7 +220,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (carets.sanitize (c, this)); + } + +@@ -242,7 +242,7 @@ + unsigned int *caret_count /* IN/OUT */, + hb_position_t *caret_array /* OUT */) const + { +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (index == NOT_COVERED) + { + if (caret_count) +@@ -254,7 +254,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); + } + +@@ -276,7 +276,7 @@ + { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this)); + } + +@@ -300,7 +300,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -365,7 +365,7 @@ + { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (version.sanitize (c) && + likely (version.major == 1) && + glyphClassDef.sanitize (c, this) && +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout-gpos-table.hh harfbuzz-0.9.7/src/hb-ot-layout-gpos-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-layout-gpos-table.hh 2012-11-17 03:44:41.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout-gpos-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -172,12 +172,12 @@ + } + + inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); + } + + inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + unsigned int len = get_len (); + + if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false); +@@ -195,7 +195,7 @@ + + /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ + inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + + if (!has_device ()) return TRACE_RETURN (true); + +@@ -212,9 +212,6 @@ + + struct AnchorFormat1 + { +- friend struct Anchor; +- +- private: + inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + hb_position_t *x, hb_position_t *y) const + { +@@ -223,7 +220,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -237,9 +234,6 @@ + + struct AnchorFormat2 + { +- friend struct Anchor; +- +- private: + inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + hb_position_t *x, hb_position_t *y) const + { +@@ -255,7 +249,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -270,9 +264,6 @@ + + struct AnchorFormat3 + { +- friend struct Anchor; +- +- private: + inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + hb_position_t *x, hb_position_t *y) const + { +@@ -286,7 +277,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); + } + +@@ -321,7 +312,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -351,7 +342,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!c->check_struct (this)) return TRACE_RETURN (false); + if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false); + unsigned int count = rows * cols; +@@ -376,7 +367,7 @@ + friend struct MarkArray; + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base)); + } + +@@ -396,7 +387,7 @@ + const AnchorMatrix &anchors, unsigned int class_count, + unsigned int glyph_pos) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index); + unsigned int mark_class = record.klass; + +@@ -418,7 +409,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this)); + } + }; +@@ -428,9 +419,11 @@ + + struct SinglePosFormat1 + { +- friend struct SinglePos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -439,8 +432,8 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + valueFormat.apply_value (c->font, c->direction, this, +@@ -451,7 +444,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values)); + } + +@@ -471,9 +464,11 @@ + + struct SinglePosFormat2 + { +- friend struct SinglePos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -482,8 +477,8 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + if (likely (index >= valueCount)) return TRACE_RETURN (false); +@@ -497,7 +492,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount)); + } + +@@ -517,31 +512,19 @@ + + struct SinglePos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return u.format1.get_coverage (); +- case 2: return u.format2.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- case 2: return TRACE_RETURN (u.format2.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ case 2: return TRACE_RETURN (c->process (u.format2)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -577,17 +560,34 @@ + { + friend struct PairPosFormat1; + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c, ++ const ValueFormat *valueFormats) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ unsigned int len1 = valueFormats[0].get_len (); ++ unsigned int len2 = valueFormats[1].get_len (); ++ unsigned int record_size = USHORT::static_size * (1 + len1 + len2); ++ ++ const PairValueRecord *record = CastP<PairValueRecord> (array); ++ unsigned int count = len; ++ for (unsigned int i = 0; i < count; i++) ++ { ++ c->input.add (record->secondGlyph); ++ record = &StructAtOffset<PairValueRecord> (record, record_size); ++ } ++ } ++ + inline bool apply (hb_apply_context_t *c, + const ValueFormat *valueFormats, + unsigned int pos) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + unsigned int len1 = valueFormats[0].get_len (); + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = USHORT::static_size * (1 + len1 + len2); + +- unsigned int count = len; + const PairValueRecord *record = CastP<PairValueRecord> (array); ++ unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + if (c->buffer->info[pos].codepoint == record->secondGlyph) +@@ -615,7 +615,7 @@ + }; + + inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!(c->check_struct (this) + && c->check_array (array, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false); + +@@ -635,9 +635,14 @@ + + struct PairPosFormat1 + { +- friend struct PairPos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ unsigned int count = pairSet.len; ++ for (unsigned int i = 0; i < count; i++) ++ (this+pairSet[i]).collect_glyphs (c, &valueFormat1); ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -646,11 +651,11 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + if (!skippy_iter.next ()) return TRACE_RETURN (false); +@@ -659,7 +664,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + + unsigned int len1 = valueFormat1.get_len (); + unsigned int len2 = valueFormat2.get_len (); +@@ -693,9 +698,23 @@ + + struct PairPosFormat2 + { +- friend struct PairPos; ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ /* (this+coverage).add_coverage (&c->input); // Don't need this. */ + +- private: ++ /* TODO only add values for pairs that have nonzero adjustments. */ ++ ++ unsigned int count1 = class1Count; ++ const ClassDef &klass1 = this+classDef1; ++ for (unsigned int i = 0; i < count1; i++) ++ klass1.add_class (&c->input, i); ++ ++ unsigned int count2 = class2Count; ++ const ClassDef &klass2 = this+classDef2; ++ for (unsigned int i = 0; i < count2; i++) ++ klass2.add_class (&c->input, i); ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -704,11 +723,11 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + if (!skippy_iter.next ()) return TRACE_RETURN (false); +@@ -717,8 +736,8 @@ + unsigned int len2 = valueFormat2.get_len (); + unsigned int record_len = len1 + len2; + +- unsigned int klass1 = (this+classDef1) (c->buffer->cur().codepoint); +- unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].codepoint); ++ unsigned int klass1 = (this+classDef1).get_class (c->buffer->cur().codepoint); ++ unsigned int klass2 = (this+classDef2).get_class (c->buffer->info[skippy_iter.idx].codepoint); + if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false); + + const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; +@@ -735,7 +754,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!(c->check_struct (this) + && coverage.sanitize (c, this) + && classDef1.sanitize (c, this) +@@ -783,31 +802,19 @@ + + struct PairPos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return u.format1.get_coverage (); +- case 2: return u.format2.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- case 2: return TRACE_RETURN (u.format2.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ case 2: return TRACE_RETURN (c->process (u.format2)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -830,7 +837,7 @@ + friend struct CursivePosFormat1; + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); + } + +@@ -849,9 +856,11 @@ + + struct CursivePosFormat1 + { +- friend struct CursivePos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -860,7 +869,7 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + + /* We don't handle mark glyphs here. */ + if (c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK) return TRACE_RETURN (false); +@@ -868,12 +877,12 @@ + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + +- const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->cur().codepoint)]; ++ const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->cur().codepoint)]; + if (!this_record.exitAnchor) return TRACE_RETURN (false); + + if (!skippy_iter.next ()) return TRACE_RETURN (false); + +- const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[skippy_iter.idx].codepoint)]; ++ const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->info[skippy_iter.idx].codepoint)]; + if (!next_record.entryAnchor) return TRACE_RETURN (false); + + unsigned int i = c->buffer->idx; +@@ -941,7 +950,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); + } + +@@ -959,29 +968,18 @@ + + struct CursivePos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1004,9 +1002,13 @@ + + struct MarkBasePosFormat1 + { +- friend struct MarkBasePos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+markCoverage).add_coverage (&c->input); ++ (this+baseCoverage).add_coverage (&c->input); ++ /* TODO only add combinations that have nonzero adjustment. */ ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -1015,8 +1017,8 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int mark_index = (this+markCoverage).get_coverage (c->buffer->cur().codepoint); + if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); + + /* now we search backwards for a non-mark glyph */ +@@ -1032,14 +1034,14 @@ + /* The following assertion is too strong, so we've disabled it. */ + if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/} + +- unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.idx].codepoint); ++ unsigned int base_index = (this+baseCoverage).get_coverage (c->buffer->info[skippy_iter.idx].codepoint); + if (base_index == NOT_COVERED) return TRACE_RETURN (false); + + return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) && + markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount)); + } +@@ -1065,29 +1067,18 @@ + + struct MarkBasePos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1115,9 +1106,13 @@ + + struct MarkLigPosFormat1 + { +- friend struct MarkLigPos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+markCoverage).add_coverage (&c->input); ++ (this+ligatureCoverage).add_coverage (&c->input); ++ /* TODO only add combinations that have nonzero adjustment. */ ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -1126,8 +1121,8 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int mark_index = (this+markCoverage).get_coverage (c->buffer->cur().codepoint); + if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); + + /* now we search backwards for a non-mark glyph */ +@@ -1139,7 +1134,7 @@ + if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE)) {/*return TRACE_RETURN (false);*/} + + unsigned int j = skippy_iter.idx; +- unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoint); ++ unsigned int lig_index = (this+ligatureCoverage).get_coverage (c->buffer->info[j].codepoint); + if (lig_index == NOT_COVERED) return TRACE_RETURN (false); + + const LigatureArray& lig_array = this+ligatureArray; +@@ -1166,7 +1161,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) && + markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount)); + } +@@ -1193,29 +1188,18 @@ + + struct MarkLigPos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1238,9 +1222,13 @@ + + struct MarkMarkPosFormat1 + { +- friend struct MarkMarkPos; +- +- private: ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+mark1Coverage).add_coverage (&c->input); ++ (this+mark2Coverage).add_coverage (&c->input); ++ /* TODO only add combinations that have nonzero adjustment. */ ++ } + + inline const Coverage &get_coverage (void) const + { +@@ -1249,8 +1237,8 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int mark1_index = (this+mark1Coverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int mark1_index = (this+mark1Coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); + + /* now we search backwards for a suitable mark glyph until a non-mark glyph */ +@@ -1283,14 +1271,14 @@ + return TRACE_RETURN (false); + + good: +- unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoint); ++ unsigned int mark2_index = (this+mark2Coverage).get_coverage (c->buffer->info[j].codepoint); + if (mark2_index == NOT_COVERED) return TRACE_RETURN (false); + + return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) && + mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this) + && mark2Array.sanitize (c, this, (unsigned int) classCount)); +@@ -1319,29 +1307,18 @@ + + struct MarkMarkPos + { +- friend struct PosLookupSubTable; +- +- private: +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1357,50 +1334,13 @@ + }; + + +-static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index); ++struct ContextPos : Context {}; + +-struct ContextPos : Context +-{ +- friend struct PosLookupSubTable; +- +- private: +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- return TRACE_RETURN (Context::apply (c, position_lookup)); +- } +-}; ++struct ChainContextPos : ChainContext {}; + +-struct ChainContextPos : ChainContext ++struct ExtensionPos : Extension<ExtensionPos> + { +- friend struct PosLookupSubTable; +- +- private: +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- return TRACE_RETURN (ChainContext::apply (c, position_lookup)); +- } +-}; +- +- +-struct ExtensionPos : Extension +-{ +- friend struct PosLookupSubTable; +- +- private: +- inline const struct PosLookupSubTable& get_subtable (void) const +- { +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return Null(PosLookupSubTable); +- return StructAtOffset<PosLookupSubTable> (this, offset); +- } +- +- inline const Coverage &get_coverage (void) const; +- +- inline bool apply (hb_apply_context_t *c) const; +- +- inline bool sanitize (hb_sanitize_context_t *c); ++ typedef struct PosLookupSubTable LookupSubTable; + }; + + +@@ -1426,41 +1366,26 @@ + Extension = 9 + }; + +- inline const Coverage &get_coverage (unsigned int lookup_type) const +- { +- switch (lookup_type) { +- case Single: return u.single.get_coverage (); +- case Pair: return u.pair.get_coverage (); +- case Cursive: return u.cursive.get_coverage (); +- case MarkBase: return u.markBase.get_coverage (); +- case MarkLig: return u.markLig.get_coverage (); +- case MarkMark: return u.markMark.get_coverage (); +- case Context: return u.context.get_coverage (); +- case ChainContext: return u.chainContext.get_coverage (); +- case Extension: return u.extension.get_coverage (); +- default: return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c, unsigned int lookup_type) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.apply (c)); +- case Pair: return TRACE_RETURN (u.pair.apply (c)); +- case Cursive: return TRACE_RETURN (u.cursive.apply (c)); +- case MarkBase: return TRACE_RETURN (u.markBase.apply (c)); +- case MarkLig: return TRACE_RETURN (u.markLig.apply (c)); +- case MarkMark: return TRACE_RETURN (u.markMark.apply (c)); +- case Context: return TRACE_RETURN (u.context.apply (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); +- case Extension: return TRACE_RETURN (u.extension.apply (c)); +- default: return TRACE_RETURN (false); ++ case Single: return TRACE_RETURN (u.single.process (c)); ++ case Pair: return TRACE_RETURN (u.pair.process (c)); ++ case Cursive: return TRACE_RETURN (u.cursive.process (c)); ++ case MarkBase: return TRACE_RETURN (u.markBase.process (c)); ++ case MarkLig: return TRACE_RETURN (u.markLig.process (c)); ++ case MarkMark: return TRACE_RETURN (u.markMark.process (c)); ++ case Context: return TRACE_RETURN (u.context.process (c)); ++ case ChainContext: return TRACE_RETURN (u.chainContext.process (c)); ++ case Extension: return TRACE_RETURN (u.extension.process (c)); ++ default: return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.header.sub_format.sanitize (c)) + return TRACE_RETURN (false); + switch (lookup_type) { +@@ -1480,7 +1405,7 @@ + protected: + union { + struct { +- USHORT sub_format; ++ USHORT sub_format; + } header; + SinglePos single; + PairPos pair; +@@ -1502,35 +1427,54 @@ + inline const PosLookupSubTable& get_subtable (unsigned int i) const + { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } + ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const ++ { ++ TRACE_PROCESS (this); ++ unsigned int lookup_type = get_type (); ++ unsigned int count = get_subtable_count (); ++ for (unsigned int i = 0; i < count; i++) { ++ typename context_t::return_t r = get_subtable (i).process (c, lookup_type); ++ if (c->stop_sublookup_iteration (r)) ++ return TRACE_RETURN (r); ++ } ++ return TRACE_RETURN (c->default_return_value ()); ++ } ++ template <typename context_t> ++ static inline typename context_t::return_t process_recurse_func (context_t *c, unsigned int lookup_index); ++ ++ inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ c->set_recurse_func (process_recurse_func<hb_collect_glyphs_context_t>); ++ return TRACE_RETURN (process (c)); ++ } ++ + template <typename set_t> + inline void add_coverage (set_t *glyphs) const + { ++ hb_get_coverage_context_t c; + const Coverage *last = NULL; + unsigned int count = get_subtable_count (); + for (unsigned int i = 0; i < count; i++) { +- const Coverage *c = &get_subtable (i).get_coverage (get_type ()); +- if (c != last) { +- c->add_coverage (glyphs); +- last = c; ++ const Coverage *coverage = &get_subtable (i).process (&c, get_type ()); ++ if (coverage != last) { ++ coverage->add_coverage (glyphs); ++ last = coverage; + } + } + } + + inline bool apply_once (hb_apply_context_t *c) const + { +- unsigned int lookup_type = get_type (); +- ++ TRACE_APPLY (this); + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->property)) +- return false; +- +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) +- if (get_subtable (i).apply (c, lookup_type)) +- return true; +- +- return false; ++ return TRACE_RETURN (false); ++ return TRACE_RETURN (process (c)); + } + ++ static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); ++ + inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const + { + bool ret = false; +@@ -1538,6 +1482,7 @@ + if (unlikely (!c->buffer->len || !c->lookup_mask)) + return false; + ++ c->set_recurse_func (apply_recurse_func); + c->set_lookup (*this); + + c->buffer->idx = 0; +@@ -1556,7 +1501,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); + OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable); + return TRACE_RETURN (list.sanitize (c, this, get_type ())); +@@ -1584,7 +1529,7 @@ + static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attahced_marks); + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); + OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList); + return TRACE_RETURN (list.sanitize (c, this)); +@@ -1673,38 +1618,25 @@ + + /* Out-of-class implementation for methods recursing */ + +-inline const Coverage & ExtensionPos::get_coverage (void) const +-{ +- return get_subtable ().get_coverage (get_type ()); +-} +- +-inline bool ExtensionPos::apply (hb_apply_context_t *c) const +-{ +- TRACE_APPLY (); +- return TRACE_RETURN (get_subtable ().apply (c, get_type ())); +-} +- +-inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c) ++template <typename context_t> ++inline typename context_t::return_t PosLookup::process_recurse_func (context_t *c, unsigned int lookup_index) + { +- TRACE_SANITIZE (); +- if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return TRACE_RETURN (true); +- return TRACE_RETURN (StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type ())); ++ const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); ++ const PosLookup &l = gpos.get_lookup (lookup_index); ++ return l.process (c); + } + +-static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index) ++inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index) + { + const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); + const PosLookup &l = gpos.get_lookup (lookup_index); +- +- if (unlikely (c->nesting_level_left == 0)) +- return false; +- +- hb_apply_context_t new_c (*c); +- new_c.nesting_level_left--; +- new_c.set_lookup (l); +- return l.apply_once (&new_c); ++ unsigned int saved_lookup_props = c->lookup_props; ++ unsigned int saved_property = c->property; ++ c->set_lookup (l); ++ bool ret = l.apply_once (c); ++ c->lookup_props = saved_lookup_props; ++ c->property = saved_property; ++ return ret; + } + + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout-gsub-table.hh harfbuzz-0.9.7/src/hb-ot-layout-gsub-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-layout-gsub-table.hh 2012-11-21 04:48:45.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout-gsub-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -37,13 +37,9 @@ + + struct SingleSubstFormat1 + { +- friend struct SingleSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + hb_codepoint_t glyph_id = iter.get_glyph (); +@@ -54,6 +50,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + hb_codepoint_t glyph_id = iter.get_glyph (); +@@ -67,11 +64,17 @@ + return this+coverage; + } + ++ inline bool would_apply (hb_would_apply_context_t *c) const ++ { ++ TRACE_WOULD_APPLY (this); ++ return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ } ++ + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + /* According to the Adobe Annotated OpenType Suite, result is always +@@ -87,7 +90,7 @@ + unsigned int num_glyphs, + int delta) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ +@@ -95,7 +98,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); + } + +@@ -112,13 +115,9 @@ + + struct SingleSubstFormat2 + { +- friend struct SingleSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + if (c->glyphs->has (iter.get_glyph ())) +@@ -128,6 +127,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); +@@ -140,11 +140,17 @@ + return this+coverage; + } + ++ inline bool would_apply (hb_would_apply_context_t *c) const ++ { ++ TRACE_WOULD_APPLY (this); ++ return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ } ++ + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + if (unlikely (index >= substitute.len)) return TRACE_RETURN (false); +@@ -160,7 +166,7 @@ + Supplier<GlyphID> &substitutes, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); +@@ -168,7 +174,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)); + } + +@@ -186,47 +192,14 @@ + + struct SingleSubst + { +- friend struct SubstLookupSubTable; +- friend struct SubstLookup; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: u.format1.closure (c); break; +- case 2: u.format2.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.collect_glyphs (c); break; +- case 2: u.format2.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- case 2: return u.format2.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- case 2: return TRACE_RETURN (u.format2.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ case 2: return TRACE_RETURN (c->process (u.format2)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + +@@ -235,7 +208,7 @@ + Supplier<GlyphID> &substitutes, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 2; + int delta; +@@ -258,7 +231,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -278,13 +251,9 @@ + + struct Sequence + { +- friend struct MultipleSubstFormat1; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + unsigned int count = substitute.len; + for (unsigned int i = 0; i < count; i++) + c->glyphs->add (substitute[i]); +@@ -292,6 +261,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + unsigned int count = substitute.len; + for (unsigned int i = 0; i < count; i++) + c->output.add (substitute[i]); +@@ -299,7 +269,7 @@ + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + if (unlikely (!substitute.len)) return TRACE_RETURN (false); + + unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; +@@ -317,15 +287,14 @@ + Supplier<GlyphID> &glyphs, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + +- public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (substitute.sanitize (c)); + } + +@@ -338,13 +307,9 @@ + + struct MultipleSubstFormat1 + { +- friend struct MultipleSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + if (c->glyphs->has (iter.get_glyph ())) +@@ -354,6 +319,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + (this+coverage).add_coverage (&c->input); + unsigned int count = sequence.len; + for (unsigned int i = 0; i < count; i++) +@@ -365,11 +331,17 @@ + return this+coverage; + } + ++ inline bool would_apply (hb_would_apply_context_t *c) const ++ { ++ TRACE_WOULD_APPLY (this); ++ return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ } ++ + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + return TRACE_RETURN ((this+sequence[index]).apply (c)); +@@ -381,7 +353,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &substitute_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_glyphs; i++) +@@ -394,7 +366,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this)); + } + +@@ -412,42 +384,13 @@ + + struct MultipleSubst + { +- friend struct SubstLookupSubTable; +- friend struct SubstLookup; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- switch (u.format) { +- case 1: u.format1.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + +@@ -457,7 +400,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &substitute_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); +@@ -468,7 +411,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -489,13 +432,9 @@ + + struct AlternateSubstFormat1 + { +- friend struct AlternateSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + if (c->glyphs->has (iter.get_glyph ())) { +@@ -509,6 +448,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); +@@ -524,12 +464,18 @@ + return this+coverage; + } + ++ inline bool would_apply (hb_would_apply_context_t *c) const ++ { ++ TRACE_WOULD_APPLY (this); ++ return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ } ++ + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const AlternateSet &alt_set = this+alternateSet[index]; +@@ -558,7 +504,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &alternate_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_glyphs; i++) +@@ -571,7 +517,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); + } + +@@ -589,42 +535,13 @@ + + struct AlternateSubst + { +- friend struct SubstLookupSubTable; +- friend struct SubstLookup; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- switch (u.format) { +- case 1: u.format1.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + +@@ -634,7 +551,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &alternate_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); +@@ -645,7 +562,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -663,13 +580,9 @@ + + struct Ligature + { +- friend struct LigatureSet; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + unsigned int count = component.len; + for (unsigned int i = 1; i < count; i++) + if (!c->glyphs->has (component[i])) +@@ -679,6 +592,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + unsigned int count = component.len; + for (unsigned int i = 1; i < count; i++) + c->input.add (component[i]); +@@ -687,25 +601,26 @@ + + inline bool would_apply (hb_would_apply_context_t *c) const + { ++ TRACE_WOULD_APPLY (this); + if (c->len != component.len) +- return false; ++ return TRACE_RETURN (false); + + for (unsigned int i = 1; i < c->len; i++) + if (likely (c->glyphs[i] != component[i])) +- return false; ++ return TRACE_RETURN (false); + +- return true; ++ return TRACE_RETURN (true); + } + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + unsigned int count = component.len; + if (unlikely (count < 1)) return TRACE_RETURN (false); + +- unsigned int end_offset; +- bool is_mark_ligature; +- unsigned int total_component_count; ++ unsigned int end_offset = 0; ++ bool is_mark_ligature = false; ++ unsigned int total_component_count = 0; + + if (likely (!match_input (c, count, + &component[1], +@@ -736,7 +651,7 @@ + Supplier<GlyphID> &components, /* Starting from second */ + unsigned int num_components /* Including first component */) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + ligGlyph = ligature; + if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false); +@@ -745,7 +660,7 @@ + + public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); + } + +@@ -761,13 +676,9 @@ + + struct LigatureSet + { +- friend struct LigatureSubstFormat1; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + (this+ligature[i]).closure (c); +@@ -775,6 +686,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + (this+ligature[i]).collect_glyphs (c); +@@ -782,19 +694,20 @@ + + inline bool would_apply (hb_would_apply_context_t *c) const + { ++ TRACE_WOULD_APPLY (this); + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + { + const Ligature &lig = this+ligature[i]; + if (lig.would_apply (c)) +- return true; ++ return TRACE_RETURN (true); + } +- return false; ++ return TRACE_RETURN (false); + } + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + { +@@ -811,7 +724,7 @@ + unsigned int num_ligatures, + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_ligatures; i++) +@@ -824,9 +737,8 @@ + return TRACE_RETURN (true); + } + +- public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (ligature.sanitize (c, this)); + } + +@@ -840,13 +752,9 @@ + + struct LigatureSubstFormat1 + { +- friend struct LigatureSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + if (c->glyphs->has (iter.get_glyph ())) +@@ -856,6 +764,7 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + Coverage::Iter iter; + for (iter.init (this+coverage); iter.more (); iter.next ()) { + c->input.add (iter.get_glyph ()); +@@ -870,15 +779,20 @@ + + inline bool would_apply (hb_would_apply_context_t *c) const + { +- return (this+ligatureSet[(this+coverage) (c->glyphs[0])]).would_apply (c); ++ TRACE_WOULD_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); ++ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); ++ ++ const LigatureSet &lig_set = this+ligatureSet[index]; ++ return TRACE_RETURN (lig_set.would_apply (c)); + } + + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + +- unsigned int index = (this+coverage) (glyph_id); ++ unsigned int index = (this+coverage).get_coverage (glyph_id); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const LigatureSet &lig_set = this+ligatureSet[index]; +@@ -893,7 +807,7 @@ + Supplier<unsigned int> &component_count_list, + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_first_glyphs; i++) +@@ -908,7 +822,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); + } + +@@ -926,50 +840,13 @@ + + struct LigatureSubst + { +- friend struct SubstLookupSubTable; +- friend struct SubstLookup; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- switch (u.format) { +- case 1: u.format1.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool would_apply (hb_would_apply_context_t *c) const +- { +- switch (u.format) { +- case 1: return u.format1.would_apply (c); +- default:return false; +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + +@@ -981,7 +858,7 @@ + Supplier<unsigned int> &component_count_list, + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); +@@ -993,7 +870,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1009,83 +886,13 @@ + }; + + +-static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index); +-static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index); +-static inline void collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int lookup_index); +- +-struct ContextSubst : Context +-{ +- friend struct SubstLookupSubTable; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- return Context::closure (c, closure_lookup); +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- return Context::collect_glyphs (c, collect_glyphs_lookup); +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- return TRACE_RETURN (Context::apply (c, substitute_lookup)); +- } +-}; +- +-struct ChainContextSubst : ChainContext +-{ +- friend struct SubstLookupSubTable; +- +- private: ++struct ContextSubst : Context {}; + +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- return ChainContext::closure (c, closure_lookup); +- } ++struct ChainContextSubst : ChainContext {}; + +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- return ChainContext::collect_glyphs (c, collect_glyphs_lookup); +- } +- +- inline bool apply (hb_apply_context_t *c) const +- { +- TRACE_APPLY (); +- return TRACE_RETURN (ChainContext::apply (c, substitute_lookup)); +- } +-}; +- +- +-struct ExtensionSubst : Extension ++struct ExtensionSubst : Extension<ExtensionSubst> + { +- friend struct SubstLookupSubTable; +- friend struct SubstLookup; +- +- private: +- inline const struct SubstLookupSubTable& get_subtable (void) const +- { +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return Null(SubstLookupSubTable); +- return StructAtOffset<SubstLookupSubTable> (this, offset); +- } +- +- inline void closure (hb_closure_context_t *c) const; +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const; +- +- inline const Coverage &get_coverage (void) const; +- +- inline bool would_apply (hb_would_apply_context_t *c) const; +- +- inline bool apply (hb_apply_context_t *c) const; +- +- inline bool sanitize (hb_sanitize_context_t *c); ++ typedef struct SubstLookupSubTable LookupSubTable; + + inline bool is_reverse (void) const; + }; +@@ -1093,13 +900,9 @@ + + struct ReverseChainSingleSubstFormat1 + { +- friend struct ReverseChainSingleSubst; +- +- private: +- + inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + + unsigned int count; +@@ -1124,6 +927,8 @@ + + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); ++ + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + + unsigned int count; +@@ -1149,13 +954,19 @@ + return this+coverage; + } + ++ inline bool would_apply (hb_would_apply_context_t *c) const ++ { ++ TRACE_WOULD_APPLY (this); ++ return TRACE_RETURN (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); ++ } ++ + inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL)) + return TRACE_RETURN (false); /* No chaining to this type */ + +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); +@@ -1178,7 +989,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) + return TRACE_RETURN (false); + OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); +@@ -1210,46 +1021,18 @@ + + struct ReverseChainSingleSubst + { +- friend struct SubstLookupSubTable; +- +- private: +- +- inline void closure (hb_closure_context_t *c) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- switch (u.format) { +- case 1: u.format1.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return u.format1.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool apply (hb_apply_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1285,98 +1068,25 @@ + ReverseChainSingle = 8 + }; + +- inline void closure (hb_closure_context_t *c, +- unsigned int lookup_type) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c, unsigned int lookup_type) const + { +- TRACE_CLOSURE (); ++ TRACE_PROCESS (this); + switch (lookup_type) { +- case Single: u.single.closure (c); break; +- case Multiple: u.multiple.closure (c); break; +- case Alternate: u.alternate.closure (c); break; +- case Ligature: u.ligature.closure (c); break; +- case Context: u.context.closure (c); break; +- case ChainContext: u.chainContext.closure (c); break; +- case Extension: u.extension.closure (c); break; +- case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c, +- unsigned int lookup_type) const +- { +- switch (lookup_type) { +- case Single: u.single.collect_glyphs (c); break; +- case Multiple: u.multiple.collect_glyphs (c); break; +- case Alternate: u.alternate.collect_glyphs (c); break; +- case Ligature: u.ligature.collect_glyphs (c); break; +- case Context: u.context.collect_glyphs (c); break; +- case ChainContext: u.chainContext.collect_glyphs (c); break; +- case Extension: u.extension.collect_glyphs (c); break; +- case ReverseChainSingle: u.reverseChainContextSingle.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (unsigned int lookup_type) const +- { +- switch (lookup_type) { +- case Single: return u.single.get_coverage (); +- case Multiple: return u.multiple.get_coverage (); +- case Alternate: return u.alternate.get_coverage (); +- case Ligature: return u.ligature.get_coverage (); +- case Context: return u.context.get_coverage (); +- case ChainContext: return u.chainContext.get_coverage (); +- case Extension: return u.extension.get_coverage (); +- case ReverseChainSingle: return u.reverseChainContextSingle.get_coverage (); +- default: return Null(Coverage); +- } +- } +- +- inline bool would_apply (hb_would_apply_context_t *c, +- unsigned int lookup_type) const +- { +- TRACE_WOULD_APPLY (); +- if (get_coverage (lookup_type).get_coverage (c->glyphs[0]) == NOT_COVERED) return false; +- if (c->len == 1) { +- switch (lookup_type) { +- case Single: +- case Multiple: +- case Alternate: +- case ReverseChainSingle: +- return true; +- } +- } +- +- /* Only need to look further for lookups that support substitutions +- * of input longer than 1. */ +- switch (lookup_type) { +- case Ligature: return u.ligature.would_apply (c); +- case Context: return u.context.would_apply (c); +- case ChainContext: return u.chainContext.would_apply (c); +- case Extension: return u.extension.would_apply (c); +- default: return false; +- } +- } +- +- inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const +- { +- TRACE_APPLY (); +- switch (lookup_type) { +- case Single: return TRACE_RETURN (u.single.apply (c)); +- case Multiple: return TRACE_RETURN (u.multiple.apply (c)); +- case Alternate: return TRACE_RETURN (u.alternate.apply (c)); +- case Ligature: return TRACE_RETURN (u.ligature.apply (c)); +- case Context: return TRACE_RETURN (u.context.apply (c)); +- case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); +- case Extension: return TRACE_RETURN (u.extension.apply (c)); +- case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.apply (c)); +- default: return TRACE_RETURN (false); ++ case Single: return TRACE_RETURN (u.single.process (c)); ++ case Multiple: return TRACE_RETURN (u.multiple.process (c)); ++ case Alternate: return TRACE_RETURN (u.alternate.process (c)); ++ case Ligature: return TRACE_RETURN (u.ligature.process (c)); ++ case Context: return TRACE_RETURN (u.context.process (c)); ++ case ChainContext: return TRACE_RETURN (u.chainContext.process (c)); ++ case Extension: return TRACE_RETURN (u.extension.process (c)); ++ case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.process (c)); ++ default: return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.header.sub_format.sanitize (c)) + return TRACE_RETURN (false); + switch (lookup_type) { +@@ -1427,63 +1137,68 @@ + return lookup_type_is_reverse (type); + } + +- inline void closure (hb_closure_context_t *c) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { ++ TRACE_PROCESS (this); + unsigned int lookup_type = get_type (); + unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) +- get_subtable (i).closure (c, lookup_type); ++ for (unsigned int i = 0; i < count; i++) { ++ typename context_t::return_t r = get_subtable (i).process (c, lookup_type); ++ if (c->stop_sublookup_iteration (r)) ++ return TRACE_RETURN (r); ++ } ++ return TRACE_RETURN (c->default_return_value ()); ++ } ++ template <typename context_t> ++ static inline typename context_t::return_t process_recurse_func (context_t *c, unsigned int lookup_index); ++ ++ inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const ++ { ++ TRACE_CLOSURE (this); ++ c->set_recurse_func (process_recurse_func<hb_closure_context_t>); ++ return TRACE_RETURN (process (c)); ++ } ++ ++ inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ c->set_recurse_func (process_recurse_func<hb_collect_glyphs_context_t>); ++ return TRACE_RETURN (process (c)); + } + + template <typename set_t> + inline void add_coverage (set_t *glyphs) const + { ++ hb_get_coverage_context_t c; + const Coverage *last = NULL; + unsigned int count = get_subtable_count (); + for (unsigned int i = 0; i < count; i++) { +- const Coverage *c = &get_subtable (i).get_coverage (get_type ()); +- if (c != last) { +- c->add_coverage (glyphs); +- last = c; ++ const Coverage *coverage = &get_subtable (i).process (&c, get_type ()); ++ if (coverage != last) { ++ coverage->add_coverage (glyphs); ++ last = coverage; + } + } + } + +- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const +- { +- unsigned int lookup_type = get_type (); +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) +- get_subtable (i).collect_glyphs (c, lookup_type); +- } +- + inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const + { +- if (unlikely (!c->len)) return false; +- if (!digest->may_have (c->glyphs[0])) return false; +- unsigned int lookup_type = get_type (); +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) +- if (get_subtable (i).would_apply (c, lookup_type)) +- return true; +- return false; ++ TRACE_WOULD_APPLY (this); ++ if (unlikely (!c->len)) return TRACE_RETURN (false); ++ if (!digest->may_have (c->glyphs[0])) return TRACE_RETURN (false); ++ return TRACE_RETURN (process (c)); + } + + inline bool apply_once (hb_apply_context_t *c) const + { +- unsigned int lookup_type = get_type (); +- ++ TRACE_APPLY (this); + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->property)) +- return false; +- +- unsigned int count = get_subtable_count (); +- for (unsigned int i = 0; i < count; i++) +- if (get_subtable (i).apply (c, lookup_type)) +- return true; +- +- return false; ++ return TRACE_RETURN (false); ++ return TRACE_RETURN (process (c)); + } + ++ static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); + inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const + { + bool ret = false; +@@ -1491,6 +1206,7 @@ + if (unlikely (!c->buffer->len || !c->lookup_mask)) + return false; + ++ c->set_recurse_func (apply_recurse_func); + c->set_lookup (*this); + + if (likely (!is_reverse ())) +@@ -1532,11 +1248,9 @@ + return ret; + } + +- private: + inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) + { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c, this); } +- public: + + inline bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, +@@ -1544,7 +1258,7 @@ + Supplier<GlyphID> &substitutes, + unsigned int num_glyphs) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); + } +@@ -1556,7 +1270,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &substitute_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (serialize_subtable (c, 0).u.multiple.serialize (c, glyphs, substitute_len_list, num_glyphs, + substitute_glyphs_list)); +@@ -1569,7 +1283,7 @@ + unsigned int num_glyphs, + Supplier<GlyphID> &alternate_glyphs_list) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (serialize_subtable (c, 0).u.alternate.serialize (c, glyphs, alternate_len_list, num_glyphs, + alternate_glyphs_list)); +@@ -1584,7 +1298,7 @@ + Supplier<unsigned int> &component_count_list, + Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + { +- TRACE_SERIALIZE (); ++ TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (serialize_subtable (c, 0).u.ligature.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, + ligatures_list, component_count_list, component_list)); +@@ -1592,7 +1306,7 @@ + + inline bool sanitize (hb_sanitize_context_t *c) + { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); + OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable); + if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false); +@@ -1634,12 +1348,8 @@ + static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); + static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); + +- inline void closure_lookup (hb_closure_context_t *c, +- unsigned int lookup_index) const +- { return get_lookup (lookup_index).closure (c); } +- + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); + OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList); + return TRACE_RETURN (list.sanitize (c, this)); +@@ -1672,83 +1382,33 @@ + + /* Out-of-class implementation for methods recursing */ + +-inline void ExtensionSubst::closure (hb_closure_context_t *c) const +-{ +- get_subtable ().closure (c, get_type ()); +-} +- +-inline void ExtensionSubst::collect_glyphs (hb_collect_glyphs_context_t *c) const +-{ +- get_subtable ().collect_glyphs (c, get_type ()); +-} +- +-inline const Coverage & ExtensionSubst::get_coverage (void) const +-{ +- return get_subtable ().get_coverage (get_type ()); +-} +- +-inline bool ExtensionSubst::would_apply (hb_would_apply_context_t *c) const +-{ +- return get_subtable ().would_apply (c, get_type ()); +-} +- +-inline bool ExtensionSubst::apply (hb_apply_context_t *c) const +-{ +- TRACE_APPLY (); +- return TRACE_RETURN (get_subtable ().apply (c, get_type ())); +-} +- +-inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) +-{ +- TRACE_SANITIZE (); +- if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); +- unsigned int offset = get_offset (); +- if (unlikely (!offset)) return TRACE_RETURN (true); +- return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_type ())); +-} +- + inline bool ExtensionSubst::is_reverse (void) const + { + unsigned int type = get_type (); + if (unlikely (type == SubstLookupSubTable::Extension)) +- return CastR<ExtensionSubst> (get_subtable()).is_reverse (); ++ return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_reverse (); + return SubstLookup::lookup_type_is_reverse (type); + } + +-static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index) +-{ +- const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); +- const SubstLookup &l = gsub.get_lookup (lookup_index); +- +- if (unlikely (c->nesting_level_left == 0)) +- return; +- +- c->nesting_level_left--; +- l.closure (c); +- c->nesting_level_left++; +-} +- +-static inline void collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int lookup_index) ++template <typename context_t> ++inline typename context_t::return_t SubstLookup::process_recurse_func (context_t *c, unsigned int lookup_index) + { + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const SubstLookup &l = gsub.get_lookup (lookup_index); +- +- /* XXX TODO */ +- l.collect_glyphs (c); ++ return l.process (c); + } + +-static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) ++inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index) + { + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); + const SubstLookup &l = gsub.get_lookup (lookup_index); +- +- if (unlikely (c->nesting_level_left == 0)) +- return false; +- +- hb_apply_context_t new_c (*c); +- new_c.nesting_level_left--; +- new_c.set_lookup (l); +- return l.apply_once (&new_c); ++ unsigned int saved_lookup_props = c->lookup_props; ++ unsigned int saved_property = c->property; ++ c->set_lookup (l); ++ bool ret = l.apply_once (c); ++ c->lookup_props = saved_lookup_props; ++ c->property = saved_property; ++ return ret; + } + + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout-gsubgpos-private.hh harfbuzz-0.9.7/src/hb-ot-layout-gsubgpos-private.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-layout-gsubgpos-private.hh 2012-11-21 04:48:45.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout-gsubgpos-private.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -37,44 +37,83 @@ + namespace OT { + + ++ ++#define TRACE_PROCESS(this) \ ++ hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ ""); ++ ++ + #ifndef HB_DEBUG_CLOSURE + #define HB_DEBUG_CLOSURE (HB_DEBUG+0) + #endif + +-#define TRACE_CLOSURE() \ +- hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, ""); +- ++#define TRACE_CLOSURE(this) \ ++ hb_auto_trace_t<HB_DEBUG_CLOSURE, void_t> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ ""); + + struct hb_closure_context_t + { ++ inline const char *get_name (void) { return "CLOSURE"; } ++ static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; ++ typedef void_t return_t; ++ typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); ++ template <typename T> ++ inline return_t process (const T &obj) { obj.closure (this); return VOID; } ++ static return_t default_return_value (void) { return VOID; } ++ bool stop_sublookup_iteration (const return_t r) const { return false; } ++ return_t recurse (unsigned int lookup_index) ++ { ++ if (unlikely (nesting_level_left == 0 || !recurse_func)) ++ return default_return_value (); ++ ++ nesting_level_left--; ++ recurse_func (this, lookup_index); ++ nesting_level_left++; ++ return default_return_value (); ++ } ++ + hb_face_t *face; + hb_set_t *glyphs; ++ recurse_func_t recurse_func; + unsigned int nesting_level_left; + unsigned int debug_depth; + +- + hb_closure_context_t (hb_face_t *face_, + hb_set_t *glyphs_, + unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : + face (face_), + glyphs (glyphs_), ++ recurse_func (NULL), + nesting_level_left (nesting_level_left_), + debug_depth (0) {} ++ ++ void set_recurse_func (recurse_func_t func) { recurse_func = func; } + }; + + + +-/* TODO Add TRACE_RETURN annotation to gsub. */ + #ifndef HB_DEBUG_WOULD_APPLY + #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0) + #endif + +-#define TRACE_WOULD_APPLY() \ +- hb_auto_trace_t<HB_DEBUG_WOULD_APPLY> trace (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, "%d glyphs", c->len); +- ++#define TRACE_WOULD_APPLY(this) \ ++ hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ "%d glyphs", c->len); + + struct hb_would_apply_context_t + { ++ inline const char *get_name (void) { return "WOULD_APPLY"; } ++ static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; ++ typedef bool return_t; ++ template <typename T> ++ inline return_t process (const T &obj) { return obj.would_apply (this); } ++ static return_t default_return_value (void) { return false; } ++ bool stop_sublookup_iteration (const return_t r) const { return r; } ++ return_t recurse (unsigned int lookup_index) { return true; } ++ + hb_face_t *face; + const hb_codepoint_t *glyphs; + unsigned int len; +@@ -89,40 +128,85 @@ + glyphs (glyphs_), + len (len_), + zero_context (zero_context_), +- debug_depth (0) {}; ++ debug_depth (0) {} + }; + + + +-/* TODO Add TRACE_RETURN annotation to gsub. */ + #ifndef HB_DEBUG_COLLECT_GLYPHS + #define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) + #endif + +-#define TRACE_COLLECT_GLYPHS() \ +- hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS> trace (&c->debug_depth, "COLLECT_GLYPHS", this, HB_FUNC, ""); +- ++#define TRACE_COLLECT_GLYPHS(this) \ ++ hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, void_t> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ ""); + + struct hb_collect_glyphs_context_t + { ++ inline const char *get_name (void) { return "COLLECT_GLYPHS"; } ++ static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; ++ typedef void_t return_t; ++ typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); ++ template <typename T> ++ inline return_t process (const T &obj) { obj.collect_glyphs (this); return VOID; } ++ static return_t default_return_value (void) { return VOID; } ++ bool stop_sublookup_iteration (const return_t r) const { return false; } ++ return_t recurse (unsigned int lookup_index) ++ { ++ if (unlikely (nesting_level_left == 0 || !recurse_func)) ++ return default_return_value (); ++ ++ nesting_level_left--; ++ /* Only collect output glyphs in the recursion. */ ++ hb_collect_glyphs_context_t new_c (this->face, NULL, NULL, NULL, &output, nesting_level_left); ++ recurse_func (&new_c, lookup_index); ++ nesting_level_left++; ++ return default_return_value (); ++ } ++ + hb_face_t *face; + hb_set_t &before; + hb_set_t &input; + hb_set_t &after; + hb_set_t &output; ++ recurse_func_t recurse_func; ++ unsigned int nesting_level_left; + unsigned int debug_depth; + + hb_collect_glyphs_context_t (hb_face_t *face_, + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ +- hb_set_t *glyphs_output /* OUT. May be NULL */) : ++ hb_set_t *glyphs_output, /* OUT. May be NULL */ ++ unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : + face (face_), + before (glyphs_before ? *glyphs_before : *hb_set_get_empty ()), + input (glyphs_input ? *glyphs_input : *hb_set_get_empty ()), + after (glyphs_after ? *glyphs_after : *hb_set_get_empty ()), + output (glyphs_output ? *glyphs_output : *hb_set_get_empty ()), +- debug_depth (0) {}; ++ recurse_func (NULL), ++ nesting_level_left (nesting_level_left_), ++ debug_depth (0) {} ++ ++ void set_recurse_func (recurse_func_t func) { recurse_func = func; } ++}; ++ ++ ++ ++struct hb_get_coverage_context_t ++{ ++ inline const char *get_name (void) { return "GET_COVERAGE"; } ++ static const unsigned int max_debug_depth = 0; ++ typedef const Coverage &return_t; ++ template <typename T> ++ inline return_t process (const T &obj) { return obj.get_coverage (); } ++ static return_t default_return_value (void) { return Null(Coverage); } ++ ++ hb_get_coverage_context_t (void) : ++ debug_depth (0) {} ++ ++ unsigned int debug_depth; + }; + + +@@ -131,23 +215,44 @@ + #define HB_DEBUG_APPLY (HB_DEBUG+0) + #endif + +-#define TRACE_APPLY() \ +- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); +- ++#define TRACE_APPLY(this) \ ++ hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ ++ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ++ "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); + + struct hb_apply_context_t + { ++ inline const char *get_name (void) { return "APPLY"; } ++ static const unsigned int max_debug_depth = HB_DEBUG_APPLY; ++ typedef bool return_t; ++ typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index); ++ template <typename T> ++ inline return_t process (const T &obj) { return obj.apply (this); } ++ static return_t default_return_value (void) { return false; } ++ bool stop_sublookup_iteration (const return_t r) const { return r; } ++ return_t recurse (unsigned int lookup_index) ++ { ++ if (unlikely (nesting_level_left == 0 || !recurse_func)) ++ return default_return_value (); ++ ++ nesting_level_left--; ++ recurse_func (this, lookup_index); ++ nesting_level_left++; ++ return default_return_value (); ++ } ++ + hb_font_t *font; + hb_face_t *face; + hb_buffer_t *buffer; + hb_direction_t direction; + hb_mask_t lookup_mask; ++ recurse_func_t recurse_func; + unsigned int nesting_level_left; + unsigned int lookup_props; + unsigned int property; /* propety of first glyph */ +- unsigned int debug_depth; + const GDEF &gdef; + bool has_glyph_classes; ++ unsigned int debug_depth; + + + hb_apply_context_t (hb_font_t *font_, +@@ -156,18 +261,16 @@ + font (font_), face (font->face), buffer (buffer_), + direction (buffer_->props.direction), + lookup_mask (lookup_mask_), ++ recurse_func (NULL), + nesting_level_left (MAX_NESTING_LEVEL), +- lookup_props (0), property (0), debug_depth (0), ++ lookup_props (0), property (0), + gdef (*hb_ot_layout_from_face (face)->gdef), +- has_glyph_classes (gdef.has_glyph_classes ()) {} ++ has_glyph_classes (gdef.has_glyph_classes ()), ++ debug_depth (0) {} + +- void set_lookup_props (unsigned int lookup_props_) { +- lookup_props = lookup_props_; +- } +- +- void set_lookup (const Lookup &l) { +- lookup_props = l.get_props (); +- } ++ void set_recurse_func (recurse_func_t func) { recurse_func = func; } ++ void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } ++ void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } + + struct mark_skipping_forward_iterator_t + { +@@ -373,22 +476,23 @@ + + + typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data); ++typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data); + typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); +-typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index); +-typedef void (*collect_glyphs_lookup_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); +-typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index); + + struct ContextClosureFuncs + { + intersects_func_t intersects; +- closure_lookup_func_t closure; ++}; ++struct ContextCollectGlyphsFuncs ++{ ++ collect_glyphs_func_t collect; + }; + struct ContextApplyFuncs + { + match_func_t match; +- apply_lookup_func_t apply; + }; + ++ + static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED) + { + return glyphs->has (value); +@@ -417,6 +521,32 @@ + } + + ++static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED) ++{ ++ glyphs->add (value); ++} ++static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data) ++{ ++ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); ++ class_def.add_class (glyphs, value); ++} ++static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data) ++{ ++ const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; ++ (data+coverage).add_coverage (glyphs); ++} ++static inline void collect_array (hb_collect_glyphs_context_t *c, ++ hb_set_t *glyphs, ++ unsigned int count, ++ const USHORT values[], ++ collect_glyphs_func_t collect_func, ++ const void *collect_data) ++{ ++ for (unsigned int i = 0; i < count; i++) ++ collect_func (glyphs, values[i], collect_data); ++} ++ ++ + static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED) + { + return glyph_id == value; +@@ -432,7 +562,6 @@ + return (data+coverage).get_coverage (glyph_id) != NOT_COVERED; + } + +- + static inline bool would_match_input (hb_would_apply_context_t *c, + unsigned int count, /* Including the first glyph (not matched) */ + const USHORT input[], /* Array of input values--start with second glyph */ +@@ -457,7 +586,7 @@ + bool *p_is_mark_ligature = NULL, + unsigned int *p_total_component_count = NULL) + { +- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); ++ TRACE_APPLY (NULL); + + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); +@@ -614,7 +743,7 @@ + match_func_t match_func, + const void *match_data) + { +- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); ++ TRACE_APPLY (NULL); + + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); + if (skippy_iter.has_no_chance ()) +@@ -639,7 +768,7 @@ + const void *match_data, + unsigned int offset) + { +- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); ++ TRACE_APPLY (NULL); + + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); + if (skippy_iter.has_no_chance ()) +@@ -662,7 +791,7 @@ + struct LookupRecord + { + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -675,22 +804,22 @@ + }; + + +-static inline void closure_lookup (hb_closure_context_t *c, +- unsigned int lookupCount, +- const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ +- closure_lookup_func_t closure_func) ++template <typename context_t> ++static inline void recurse_lookups (context_t *c, ++ unsigned int lookupCount, ++ const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) + { + for (unsigned int i = 0; i < lookupCount; i++) +- closure_func (c, lookupRecord->lookupListIndex); ++ c->recurse (lookupRecord->lookupListIndex); + } + + static inline bool apply_lookup (hb_apply_context_t *c, + unsigned int count, /* Including the first glyph */ + unsigned int lookupCount, +- const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ +- apply_lookup_func_t apply_func) ++ const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) + { +- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); ++ TRACE_APPLY (NULL); ++ + unsigned int end = c->buffer->len; + if (unlikely (count == 0 || c->buffer->idx + count > end)) + return TRACE_RETURN (false); +@@ -719,7 +848,7 @@ + unsigned int old_pos = c->buffer->idx; + + /* Apply a lookup */ +- bool done = apply_func (c, lookupRecord->lookupListIndex); ++ bool done = c->recurse (lookupRecord->lookupListIndex); + + lookupRecord++; + lookupCount--; +@@ -753,6 +882,12 @@ + const void *intersects_data; + }; + ++struct ContextCollectGlyphsLookupContext ++{ ++ ContextCollectGlyphsFuncs funcs; ++ const void *collect_data; ++}; ++ + struct ContextApplyLookupContext + { + ContextApplyFuncs funcs; +@@ -769,11 +904,23 @@ + if (intersects_array (c, + inputCount ? inputCount - 1 : 0, input, + lookup_context.funcs.intersects, lookup_context.intersects_data)) +- closure_lookup (c, +- lookupCount, lookupRecord, +- lookup_context.funcs.closure); ++ recurse_lookups (c, ++ lookupCount, lookupRecord); + } + ++static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, ++ unsigned int inputCount, /* Including the first glyph (not matched) */ ++ const USHORT input[], /* Array of input values--start with second glyph */ ++ unsigned int lookupCount, ++ const LookupRecord lookupRecord[], ++ ContextCollectGlyphsLookupContext &lookup_context) ++{ ++ collect_array (c, &c->input, ++ inputCount ? inputCount - 1 : 0, input, ++ lookup_context.funcs.collect, lookup_context.collect_data); ++ recurse_lookups (c, ++ lookupCount, lookupRecord); ++} + + static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, + unsigned int inputCount, /* Including the first glyph (not matched) */ +@@ -798,19 +945,14 @@ + lookup_context.funcs.match, lookup_context.match_data) + && apply_lookup (c, + inputCount, +- lookupCount, lookupRecord, +- lookup_context.funcs.apply); ++ lookupCount, lookupRecord); + } + + struct Rule + { +- friend struct RuleSet; +- +- private: +- + inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + context_closure_lookup (c, + inputCount, input, +@@ -818,23 +960,33 @@ + lookup_context); + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); ++ context_collect_glyphs_lookup (c, ++ inputCount, input, ++ lookupCount, lookupRecord, ++ lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context)); + } + + inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context)); + } + + public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return inputCount.sanitize (c) + && lookupCount.sanitize (c) + && c->check_range (input, +@@ -859,15 +1011,23 @@ + { + inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + (this+rule[i]).closure (c, lookup_context); + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ unsigned int num_rules = rule.len; ++ for (unsigned int i = 0; i < num_rules; i++) ++ (this+rule[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + { +@@ -879,7 +1039,7 @@ + + inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + { +@@ -890,7 +1050,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (rule.sanitize (c, this)); + } + +@@ -905,18 +1065,14 @@ + + struct ContextFormat1 + { +- friend struct Context; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + + const Coverage &cov = (this+coverage); + + struct ContextClosureLookupContext lookup_context = { +- {intersects_glyph, closure_func}, ++ {intersects_glyph}, + NULL + }; + +@@ -928,35 +1084,55 @@ + } + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ ++ struct ContextCollectGlyphsLookupContext lookup_context = { ++ {collect_glyph}, ++ NULL ++ }; ++ ++ unsigned int count = ruleSet.len; ++ for (unsigned int i = 0; i < count; i++) ++ (this+ruleSet[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + +- const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])]; ++ const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; + struct ContextApplyLookupContext lookup_context = { +- {match_glyph, NULL}, ++ {match_glyph}, + NULL + }; + return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ return this+coverage; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const ++ { ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) + return TRACE_RETURN (false); + + const RuleSet &rule_set = this+ruleSet[index]; + struct ContextApplyLookupContext lookup_context = { +- {match_glyph, apply_func}, ++ {match_glyph}, + NULL + }; + return TRACE_RETURN (rule_set.apply (c, lookup_context)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + +@@ -975,20 +1151,16 @@ + + struct ContextFormat2 + { +- friend struct Context; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + if (!(this+coverage).intersects (c->glyphs)) + return; + + const ClassDef &class_def = this+classDef; + + struct ContextClosureLookupContext lookup_context = { +- {intersects_class, closure_func}, ++ {intersects_class}, + NULL + }; + +@@ -1000,38 +1172,58 @@ + } + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ ++ struct ContextCollectGlyphsLookupContext lookup_context = { ++ {collect_class}, ++ NULL ++ }; ++ ++ unsigned int count = ruleSet.len; ++ for (unsigned int i = 0; i < count; i++) ++ (this+ruleSet[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + + const ClassDef &class_def = this+classDef; +- unsigned int index = class_def (c->glyphs[0]); ++ unsigned int index = class_def.get_class (c->glyphs[0]); + const RuleSet &rule_set = this+ruleSet[index]; + struct ContextApplyLookupContext lookup_context = { +- {match_class, NULL}, ++ {match_class}, + &class_def + }; + return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const ++ { ++ return this+coverage; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const ClassDef &class_def = this+classDef; +- index = class_def (c->buffer->cur().codepoint); ++ index = class_def.get_class (c->buffer->cur().codepoint); + const RuleSet &rule_set = this+ruleSet[index]; + struct ContextApplyLookupContext lookup_context = { +- {match_class, apply_func}, ++ {match_class}, + &class_def + }; + return TRACE_RETURN (rule_set.apply (c, lookup_context)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + +@@ -1053,19 +1245,15 @@ + + struct ContextFormat3 + { +- friend struct Context; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + if (!(this+coverage[0]).intersects (c->glyphs)) + return; + + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount); + struct ContextClosureLookupContext lookup_context = { +- {intersects_coverage, closure_func}, ++ {intersects_coverage}, + this + }; + context_closure_lookup (c, +@@ -1074,34 +1262,56 @@ + lookup_context); + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage[0]).add_coverage (&c->input); ++ ++ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount); ++ struct ContextCollectGlyphsLookupContext lookup_context = { ++ {collect_coverage}, ++ NULL ++ }; ++ ++ context_collect_glyphs_lookup (c, ++ glyphCount, (const USHORT *) (coverage + 1), ++ lookupCount, lookupRecord, ++ lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount); + struct ContextApplyLookupContext lookup_context = { +- {match_coverage, NULL}, ++ {match_coverage}, + this + }; + return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage[0]) (c->buffer->cur().codepoint); ++ return this+coverage[0]; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const ++ { ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount); + struct ContextApplyLookupContext lookup_context = { +- {match_coverage, apply_func}, ++ {match_coverage}, + this + }; + return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!c->check_struct (this)) return TRACE_RETURN (false); + unsigned int count = glyphCount; + if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false); +@@ -1127,63 +1337,20 @@ + + struct Context + { +- protected: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_PROCESS (this); + switch (u.format) { +- case 1: u.format1.closure (c, closure_func); break; +- case 2: u.format2.closure (c, closure_func); break; +- case 3: u.format3.closure (c, closure_func); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c, collect_glyphs_lookup_func_t closure_func) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +-// case 1: u.format1.collect_glyphs (c); break; +-// case 2: u.format2.collect_glyphs (c); break; +-// case 3: u.format2.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return this + u.format1.coverage; +- case 2: return this + u.format2.coverage; +- case 3: return this + u.format3.coverage[0]; +- default:return Null(Coverage); +- } +- } +- +- inline bool would_apply (hb_would_apply_context_t *c) const +- { +- switch (u.format) { +- case 1: return u.format1.would_apply (c); +- case 2: return u.format2.would_apply (c); +- case 3: return u.format3.would_apply (c); +- default:return false; +- } +- } +- +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c, apply_func)); +- case 2: return TRACE_RETURN (u.format2.apply (c, apply_func)); +- case 3: return TRACE_RETURN (u.format3.apply (c, apply_func)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ case 2: return TRACE_RETURN (c->process (u.format2)); ++ case 3: return TRACE_RETURN (c->process (u.format3)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1211,6 +1378,12 @@ + const void *intersects_data[3]; + }; + ++struct ChainContextCollectGlyphsLookupContext ++{ ++ ContextCollectGlyphsFuncs funcs; ++ const void *collect_data[3]; ++}; ++ + struct ChainContextApplyLookupContext + { + ContextApplyFuncs funcs; +@@ -1237,9 +1410,32 @@ + && intersects_array (c, + lookaheadCount, lookahead, + lookup_context.funcs.intersects, lookup_context.intersects_data[2])) +- closure_lookup (c, +- lookupCount, lookupRecord, +- lookup_context.funcs.closure); ++ recurse_lookups (c, ++ lookupCount, lookupRecord); ++} ++ ++static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, ++ unsigned int backtrackCount, ++ const USHORT backtrack[], ++ unsigned int inputCount, /* Including the first glyph (not matched) */ ++ const USHORT input[], /* Array of input values--start with second glyph */ ++ unsigned int lookaheadCount, ++ const USHORT lookahead[], ++ unsigned int lookupCount, ++ const LookupRecord lookupRecord[], ++ ChainContextCollectGlyphsLookupContext &lookup_context) ++{ ++ collect_array (c, &c->before, ++ backtrackCount, backtrack, ++ lookup_context.funcs.collect, lookup_context.collect_data[0]); ++ collect_array (c, &c->input, ++ inputCount ? inputCount - 1 : 0, input, ++ lookup_context.funcs.collect, lookup_context.collect_data[1]); ++ collect_array (c, &c->after, ++ lookaheadCount, lookahead, ++ lookup_context.funcs.collect, lookup_context.collect_data[2]); ++ recurse_lookups (c, ++ lookupCount, lookupRecord); + } + + static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c, +@@ -1270,7 +1466,7 @@ + const LookupRecord lookupRecord[], + ChainContextApplyLookupContext &lookup_context) + { +- unsigned int lookahead_offset; ++ unsigned int lookahead_offset = 0; + return match_input (c, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data[1], +@@ -1284,19 +1480,14 @@ + lookahead_offset) + && apply_lookup (c, + inputCount, +- lookupCount, lookupRecord, +- lookup_context.funcs.apply); ++ lookupCount, lookupRecord); + } + + struct ChainRule + { +- friend struct ChainRuleSet; +- +- private: +- + inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +@@ -1308,9 +1499,23 @@ + lookup_context); + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); ++ const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); ++ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); ++ chain_context_collect_glyphs_lookup (c, ++ backtrack.len, backtrack.array, ++ input.len, input.array, ++ lookahead.len, lookahead.array, ++ lookup.len, lookup.array, ++ lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +@@ -1323,7 +1528,7 @@ + + inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); +@@ -1334,9 +1539,8 @@ + lookup.array, lookup_context)); + } + +- public: + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!backtrack.sanitize (c)) return TRACE_RETURN (false); + HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + if (!input.sanitize (c)) return TRACE_RETURN (false); +@@ -1368,15 +1572,23 @@ + { + inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + (this+rule[i]).closure (c, lookup_context); + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ unsigned int num_rules = rule.len; ++ for (unsigned int i = 0; i < num_rules; i++) ++ (this+rule[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if ((this+rule[i]).would_apply (c, lookup_context)) +@@ -1387,7 +1599,7 @@ + + inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if ((this+rule[i]).apply (c, lookup_context)) +@@ -1397,7 +1609,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (rule.sanitize (c, this)); + } + +@@ -1411,17 +1623,13 @@ + + struct ChainContextFormat1 + { +- friend struct ChainContext; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + const Coverage &cov = (this+coverage); + + struct ChainContextClosureLookupContext lookup_context = { +- {intersects_glyph, closure_func}, ++ {intersects_glyph}, + {NULL, NULL, NULL} + }; + +@@ -1433,34 +1641,54 @@ + } + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ ++ struct ChainContextCollectGlyphsLookupContext lookup_context = { ++ {collect_glyph}, ++ {NULL, NULL, NULL} ++ }; ++ ++ unsigned int count = ruleSet.len; ++ for (unsigned int i = 0; i < count; i++) ++ (this+ruleSet[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + +- const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])]; ++ const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; + struct ChainContextApplyLookupContext lookup_context = { +- {match_glyph, NULL}, ++ {match_glyph}, + {NULL, NULL, NULL} + }; + return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ return this+coverage; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const ++ { ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const ChainRuleSet &rule_set = this+ruleSet[index]; + struct ChainContextApplyLookupContext lookup_context = { +- {match_glyph, apply_func}, ++ {match_glyph}, + {NULL, NULL, NULL} + }; + return TRACE_RETURN (rule_set.apply (c, lookup_context)); + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); + } + +@@ -1478,13 +1706,9 @@ + + struct ChainContextFormat2 + { +- friend struct ChainContext; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + if (!(this+coverage).intersects (c->glyphs)) + return; + +@@ -1493,7 +1717,7 @@ + const ClassDef &lookahead_class_def = this+lookaheadClassDef; + + struct ChainContextClosureLookupContext lookup_context = { +- {intersects_class, closure_func}, ++ {intersects_class}, + {&backtrack_class_def, + &input_class_def, + &lookahead_class_def} +@@ -1507,35 +1731,55 @@ + } + } + ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const ++ { ++ TRACE_COLLECT_GLYPHS (this); ++ (this+coverage).add_coverage (&c->input); ++ ++ struct ChainContextCollectGlyphsLookupContext lookup_context = { ++ {collect_class}, ++ {NULL, NULL, NULL} ++ }; ++ ++ unsigned int count = ruleSet.len; ++ for (unsigned int i = 0; i < count; i++) ++ (this+ruleSet[i]).collect_glyphs (c, lookup_context); ++ } ++ + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + + const ClassDef &input_class_def = this+inputClassDef; + +- unsigned int index = input_class_def (c->glyphs[0]); ++ unsigned int index = input_class_def.get_class (c->glyphs[0]); + const ChainRuleSet &rule_set = this+ruleSet[index]; + struct ChainContextApplyLookupContext lookup_context = { +- {match_class, NULL}, ++ {match_class}, + {NULL, &input_class_def, NULL} + }; + return TRACE_RETURN (rule_set.would_apply (c, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const ++ { ++ return this+coverage; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); +- unsigned int index = (this+coverage) (c->buffer->cur().codepoint); ++ TRACE_APPLY (this); ++ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const ClassDef &backtrack_class_def = this+backtrackClassDef; + const ClassDef &input_class_def = this+inputClassDef; + const ClassDef &lookahead_class_def = this+lookaheadClassDef; + +- index = input_class_def (c->buffer->cur().codepoint); ++ index = input_class_def.get_class (c->buffer->cur().codepoint); + const ChainRuleSet &rule_set = this+ruleSet[index]; + struct ChainContextApplyLookupContext lookup_context = { +- {match_class, apply_func}, ++ {match_class}, + {&backtrack_class_def, + &input_class_def, + &lookahead_class_def} +@@ -1544,7 +1788,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) && + inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) && + ruleSet.sanitize (c, this)); +@@ -1576,13 +1820,9 @@ + + struct ChainContextFormat3 + { +- friend struct ChainContext; +- +- private: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const ++ inline void closure (hb_closure_context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_CLOSURE (this); + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + + if (!(this+input[0]).intersects (c->glyphs)) +@@ -1591,7 +1831,7 @@ + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); + struct ChainContextClosureLookupContext lookup_context = { +- {intersects_coverage, closure_func}, ++ {intersects_coverage}, + {this, this, this} + }; + chain_context_closure_lookup (c, +@@ -1602,21 +1842,36 @@ + lookup_context); + } + +- inline const Coverage &get_coverage (void) const ++ inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { ++ TRACE_COLLECT_GLYPHS (this); + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); +- return this+input[0]; ++ ++ (this+input[0]).add_coverage (&c->input); ++ ++ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); ++ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); ++ struct ChainContextCollectGlyphsLookupContext lookup_context = { ++ {collect_coverage}, ++ {this, this, this} ++ }; ++ chain_context_collect_glyphs_lookup (c, ++ backtrack.len, (const USHORT *) backtrack.array, ++ input.len, (const USHORT *) input.array + 1, ++ lookahead.len, (const USHORT *) lookahead.array, ++ lookup.len, lookup.array, ++ lookup_context); + } + + inline bool would_apply (hb_would_apply_context_t *c) const + { +- TRACE_WOULD_APPLY (); ++ TRACE_WOULD_APPLY (this); + + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); + struct ChainContextApplyLookupContext lookup_context = { +- {match_coverage, NULL}, ++ {match_coverage}, + {this, this, this} + }; + return TRACE_RETURN (chain_context_would_apply_lookup (c, +@@ -1626,18 +1881,24 @@ + lookup.len, lookup.array, lookup_context)); + } + +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const ++ inline const Coverage &get_coverage (void) const ++ { ++ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); ++ return this+input[0]; ++ } ++ ++ inline bool apply (hb_apply_context_t *c) const + { +- TRACE_APPLY (); ++ TRACE_APPLY (this); + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + +- unsigned int index = (this+input[0]) (c->buffer->cur().codepoint); ++ unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); + struct ChainContextApplyLookupContext lookup_context = { +- {match_coverage, apply_func}, ++ {match_coverage}, + {this, this, this} + }; + return TRACE_RETURN (chain_context_apply_lookup (c, +@@ -1648,7 +1909,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); + OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + if (!input.sanitize (c, this)) return TRACE_RETURN (false); +@@ -1681,63 +1942,20 @@ + + struct ChainContext + { +- protected: +- +- inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const +- { +- TRACE_CLOSURE (); +- switch (u.format) { +- case 1: u.format1.closure (c, closure_func); break; +- case 2: u.format2.closure (c, closure_func); break; +- case 3: u.format3.closure (c, closure_func); break; +- default: break; +- } +- } +- +- inline void collect_glyphs (hb_collect_glyphs_context_t *c, collect_glyphs_lookup_func_t closure_func) const ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const + { +- TRACE_CLOSURE (); ++ TRACE_PROCESS (this); + switch (u.format) { +-// case 1: u.format1.collect_glyphs (c); break; +-// case 2: u.format2.collect_glyphs (c); break; +-// case 3: u.format2.collect_glyphs (c); break; +- default: break; +- } +- } +- +- inline const Coverage &get_coverage (void) const +- { +- switch (u.format) { +- case 1: return this + u.format1.coverage; +- case 2: return this + u.format2.coverage; +- case 3: return u.format3.get_coverage (); +- default:return Null(Coverage); +- } +- } +- +- inline bool would_apply (hb_would_apply_context_t *c) const +- { +- switch (u.format) { +- case 1: return u.format1.would_apply (c); +- case 2: return u.format2.would_apply (c); +- case 3: return u.format3.would_apply (c); +- default:return false; +- } +- } +- +- inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const +- { +- TRACE_APPLY (); +- switch (u.format) { +- case 1: return TRACE_RETURN (u.format1.apply (c, apply_func)); +- case 2: return TRACE_RETURN (u.format2.apply (c, apply_func)); +- case 3: return TRACE_RETURN (u.format3.apply (c, apply_func)); +- default:return TRACE_RETURN (false); ++ case 1: return TRACE_RETURN (c->process (u.format1)); ++ case 2: return TRACE_RETURN (c->process (u.format2)); ++ case 3: return TRACE_RETURN (c->process (u.format3)); ++ default:return TRACE_RETURN (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1759,14 +1977,11 @@ + + struct ExtensionFormat1 + { +- friend struct Extension; +- +- protected: + inline unsigned int get_type (void) const { return extensionLookupType; } + inline unsigned int get_offset (void) const { return extensionOffset; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + +@@ -1781,6 +1996,7 @@ + DEFINE_SIZE_STATIC (8); + }; + ++template <typename T> + struct Extension + { + inline unsigned int get_type (void) const +@@ -1798,8 +2014,22 @@ + } + } + +- inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ template <typename X> ++ inline const X& get_subtable (void) const ++ { ++ unsigned int offset = get_offset (); ++ if (unlikely (!offset)) return Null(typename T::LookupSubTable); ++ return StructAtOffset<typename T::LookupSubTable> (this, offset); ++ } ++ ++ template <typename context_t> ++ inline typename context_t::return_t process (context_t *c) const ++ { ++ return get_subtable<typename T::LookupSubTable> ().process (c, get_type ()); ++ } ++ ++ inline bool sanitize_self (hb_sanitize_context_t *c) { ++ TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return TRACE_RETURN (false); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.sanitize (c)); +@@ -1807,6 +2037,14 @@ + } + } + ++ inline bool sanitize (hb_sanitize_context_t *c) { ++ TRACE_SANITIZE (this); ++ if (!sanitize_self (c)) return TRACE_RETURN (false); ++ unsigned int offset = get_offset (); ++ if (unlikely (!offset)) return TRACE_RETURN (true); ++ return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ())); ++ } ++ + protected: + union { + USHORT format; /* Format identifier */ +@@ -1856,7 +2094,7 @@ + { return (this+lookupList)[i]; } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && + scriptList.sanitize (c, this) && + featureList.sanitize (c, this) && +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout.cc harfbuzz-0.9.7/src/hb-ot-layout.cc +--- harfbuzz-0.9.7.orig/src/hb-ot-layout.cc 2012-11-17 04:06:56.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout.cc 2012-11-28 09:32:35.000000000 +0100 +@@ -401,6 +401,103 @@ + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); + } + ++static void ++_hb_ot_layout_collect_lookups_lookups (hb_face_t *face, ++ hb_tag_t table_tag, ++ unsigned int feature_index, ++ hb_set_t *lookup_indexes /* OUT */) ++{ ++ unsigned int lookup_indices[32]; ++ unsigned int offset, len; ++ ++ offset = 0; ++ do { ++ len = ARRAY_LENGTH (lookup_indices); ++ hb_ot_layout_feature_get_lookups (face, ++ table_tag, ++ feature_index, ++ offset, &len, ++ lookup_indices); ++ ++ for (unsigned int i = 0; i < len; i++) ++ lookup_indexes->add (lookup_indices[i]); ++ ++ offset += len; ++ } while (len == ARRAY_LENGTH (lookup_indices)); ++} ++ ++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 */) ++{ ++ if (!features) ++ { ++ /* All features */ ++ unsigned int count = hb_ot_layout_language_get_feature_tags (face, table_tag, script_index, language_index, 0, NULL, NULL); ++ for (unsigned int feature_index = 0; feature_index < count; feature_index++) ++ _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes); ++ } else { ++ for (; *features; features++) ++ { ++ unsigned int feature_index; ++ if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index, *features, &feature_index)) ++ _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes); ++ } ++ } ++} ++ ++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 */) ++{ ++ if (!languages) ++ { ++ /* All languages */ ++ unsigned int count = hb_ot_layout_script_get_language_tags (face, table_tag, script_index, 0, NULL, NULL); ++ 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); ++ } else { ++ for (; *languages; languages++) ++ { ++ unsigned int language_index; ++ if (hb_ot_layout_script_find_language (face, table_tag, script_index, *languages, &language_index)) ++ _hb_ot_layout_collect_lookups_features (face, table_tag, script_index, language_index, features, lookup_indexes); ++ } ++ } ++} ++ ++void ++hb_ot_layout_collect_lookups (hb_face_t *face, ++ hb_tag_t table_tag, ++ const hb_tag_t *scripts, ++ const hb_tag_t *languages, ++ const hb_tag_t *features, ++ hb_set_t *lookup_indexes /* OUT */) ++{ ++ if (!scripts) ++ { ++ /* All scripts */ ++ unsigned int count = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL); ++ 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); ++ } ++ } ++} ++ + void + hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, +@@ -418,13 +515,13 @@ + case HB_OT_TAG_GSUB: + { + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); +- l.collect_glyphs (&c); ++ l.collect_glyphs_lookup (&c); + return; + } + case HB_OT_TAG_GPOS: + { + const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index); +-// l.collect_glyphs (&c); ++ l.collect_glyphs_lookup (&c); + return; + } + } +@@ -500,7 +597,10 @@ + hb_set_t *glyphs) + { + OT::hb_closure_context_t c (face, glyphs); +- _get_gsub (face).closure_lookup (&c, lookup_index); ++ ++ const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index); ++ ++ l.closure (&c); + } + + /* +@@ -539,3 +639,34 @@ + { + OT::GPOS::position_finish (font, buffer, zero_width_attached_marks); + } ++ ++hb_bool_t ++hb_ot_layout_position_get_size (hb_face_t *face, ++ uint16_t *data /* OUT, 5 items */) ++{ ++ const OT::GPOS &gpos = _get_gpos (face); ++ unsigned int script_index; ++ gpos.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, &script_index); ++ const OT::LangSys &l = gpos.get_script (script_index).get_lang_sys (HB_OT_TAG_DEFAULT_LANGUAGE); ++ ++ unsigned int num_features = l.get_feature_count (); ++ for (unsigned int i = 0; i < num_features; i++) { ++ unsigned int f_index = l.get_feature_index (i); ++ ++ if (HB_TAG ('s','i','z','e') == gpos.get_feature_tag (f_index)) ++ { ++ const OT::Feature &f = gpos.get_feature (f_index); ++ const OT::FeatureParams ¶ms = f.get_feature_params (); ++ ++ for (unsigned int i = 0; i < 5; i++) ++ data[i] = params.u.size.params[i]; ++ ++ return true; ++ } ++ } ++ ++ for (unsigned int i = 0; i < 5; i++) ++ data[i] = 0; ++ ++ return false; ++} +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-layout.h harfbuzz-0.9.7/src/hb-ot-layout.h +--- harfbuzz-0.9.7.orig/src/hb-ot-layout.h 2012-11-17 03:50:38.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-layout.h 2012-11-28 09:32:35.000000000 +0100 +@@ -179,15 +179,13 @@ + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */); + +-#ifdef HB_NOT_IMPLEMENTED + void +-Xhb_ot_layout_collect_lookups (hb_face_t *face, ++hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, + hb_set_t *lookup_indexes /* OUT */); +-#endif + + void + hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, +@@ -279,6 +277,11 @@ + hb_glyph_position_t *positions /* IN / OUT */); + #endif + ++/* Optical 'size' feature info. Returns true if found. */ ++hb_bool_t ++hb_ot_layout_position_get_size (hb_face_t *face, ++ uint16_t *data /* OUT, 5 items */); ++ + + HB_END_DECLS + +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-maxp-table.hh harfbuzz-0.9.7/src/hb-ot-maxp-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-maxp-table.hh 2012-11-17 03:44:57.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-maxp-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -48,7 +48,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && + likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000))); + } +diff -ur harfbuzz-0.9.7.orig/src/hb-ot-name-table.hh harfbuzz-0.9.7/src/hb-ot-name-table.hh +--- harfbuzz-0.9.7.orig/src/hb-ot-name-table.hh 2012-11-17 03:45:06.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-ot-name-table.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -57,7 +57,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + /* We can check from base all the way up to the end of string... */ + return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); + } +@@ -99,7 +99,7 @@ + } + + inline bool sanitize_records (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + char *string_pool = (char *) this + stringOffset; + unsigned int _count = count; + for (unsigned int i = 0; i < _count; i++) +@@ -108,7 +108,7 @@ + } + + inline bool sanitize (hb_sanitize_context_t *c) { +- TRACE_SANITIZE (); ++ TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && + likely (format == 0 || format == 1) && + c->check_array (nameRecord, nameRecord[0].static_size, count) && +diff -ur harfbuzz-0.9.7.orig/src/hb-private.hh harfbuzz-0.9.7/src/hb-private.hh +--- harfbuzz-0.9.7.orig/src/hb-private.hh 2012-11-16 22:33:18.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-private.hh 2012-11-28 09:32:35.000000000 +0100 +@@ -62,6 +62,12 @@ + #endif + + ++/* Void! */ ++struct _void_t; ++typedef const _void_t &void_t; ++#define VOID (* (const _void_t *) NULL) ++ ++ + /* Basics */ + + +@@ -582,7 +588,11 @@ + } else + fprintf (stderr, " " VRBAR LBAR); + +- if (func) { ++ if (func) ++ { ++ /* Skip "typename" */ ++ if (0 == strncmp (func, "typename ", 9)) ++ func += 9; + /* Skip return type */ + const char *space = strchr (func, ' '); + if (space) +@@ -657,10 +667,39 @@ + + + /* ++ * Printer ++ */ ++ ++template <typename T> ++struct hb_printer_t {}; ++ ++template <> ++struct hb_printer_t<bool> { ++ const char *print (bool v) { return v ? "true" : "false"; } ++}; ++ ++template <> ++struct hb_printer_t<void_t> { ++ const char *print (void_t v) { return ""; } ++}; ++ ++ ++/* + * Trace + */ + +-template <int max_level> ++template <typename T> ++static inline void _hb_warn_no_return (bool returned) ++{ ++ if (unlikely (!returned)) { ++ fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a bug, please report.\n"); ++ } ++} ++template <> ++inline void _hb_warn_no_return<void_t> (bool returned) ++{} ++ ++template <int max_level, typename ret_t> + struct hb_auto_trace_t { + explicit inline hb_auto_trace_t (unsigned int *plevel_, + const char *what_, +@@ -678,23 +717,23 @@ + } + inline ~hb_auto_trace_t (void) + { +- if (unlikely (!returned)) { +- fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a bug, please report. Level was %d.\n", plevel ? *plevel : -1); ++ _hb_warn_no_return<ret_t> (returned); ++ if (!returned) { + _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " "); +- return; + } +- + if (plevel) --*plevel; + } + +- inline bool ret (bool v, unsigned int line = 0) ++ inline ret_t ret (ret_t v, unsigned int line = 0) + { + if (unlikely (returned)) { + fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, please report.\n"); + return v; + } + +- _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, "return %s (line %d)", v ? "true" : "false", line); ++ _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, ++ "return %s (line %d)", ++ hb_printer_t<ret_t>().print (v), line); + if (plevel) --*plevel; + plevel = NULL; + returned = true; +@@ -703,12 +742,12 @@ + + private: + unsigned int *plevel; +- bool returned; + const char *what; + const void *obj; ++ bool returned; + }; +-template <> /* Optimize when tracing is disabled */ +-struct hb_auto_trace_t<0> { ++template <typename ret_t> /* Optimize when tracing is disabled */ ++struct hb_auto_trace_t<0, ret_t> { + explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, + const char *what HB_UNUSED, + const void *obj HB_UNUSED, +@@ -716,8 +755,7 @@ + const char *message HB_UNUSED, + ...) {} + +- template <typename T> +- inline T ret (T v, unsigned int line = 0) { return v; } ++ inline ret_t ret (ret_t v, unsigned int line = 0) { return v; } + }; + + #define TRACE_RETURN(RET) trace.ret (RET, __LINE__) +diff -ur harfbuzz-0.9.7.orig/src/hb-shape-plan.cc harfbuzz-0.9.7/src/hb-shape-plan.cc +--- harfbuzz-0.9.7.orig/src/hb-shape-plan.cc 2012-11-16 22:33:18.000000000 +0100 ++++ harfbuzz-0.9.7/src/hb-shape-plan.cc 2012-11-28 09:32:35.000000000 +0100 +@@ -304,4 +304,5 @@ + const char * + hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) + { ++ return shape_plan->shaper_name; + } |