Index: third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh |
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh |
index 57fc1e05f767a4b0fcbc5e73451831b91d45b1c7..cbc6840bc86214eaf280c399ae9d833c23770941 100644 |
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh |
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh |
@@ -37,12 +37,6 @@ |
namespace OT { |
- |
-#define TRACE_DISPATCH(this, format) \ |
- hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ |
- (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
- "format %d", (int) format); |
- |
#ifndef HB_DEBUG_CLOSURE |
#define HB_DEBUG_CLOSURE (HB_DEBUG+0) |
#endif |
@@ -58,6 +52,8 @@ struct hb_closure_context_t |
static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; |
typedef hb_void_t return_t; |
typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); |
+ template <typename T, typename F> |
+ inline bool may_dispatch (const T *obj, const F *format) { return true; } |
template <typename T> |
inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; } |
static return_t default_return_value (void) { return HB_VOID; } |
@@ -107,6 +103,8 @@ 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, typename F> |
+ inline bool may_dispatch (const T *obj, const F *format) { return true; } |
template <typename T> |
inline return_t dispatch (const T &obj) { return obj.would_apply (this); } |
static return_t default_return_value (void) { return false; } |
@@ -146,6 +144,8 @@ struct hb_collect_glyphs_context_t |
static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; |
typedef hb_void_t return_t; |
typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); |
+ template <typename T, typename F> |
+ inline bool may_dispatch (const T *obj, const F *format) { return true; } |
template <typename T> |
inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; } |
static return_t default_return_value (void) { return HB_VOID; } |
@@ -232,18 +232,28 @@ struct hb_collect_glyphs_context_t |
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) |
#endif |
-struct hb_get_coverage_context_t |
+template <typename set_t> |
+struct hb_add_coverage_context_t |
{ |
inline const char *get_name (void) { return "GET_COVERAGE"; } |
static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE; |
typedef const Coverage &return_t; |
+ template <typename T, typename F> |
+ inline bool may_dispatch (const T *obj, const F *format) { return true; } |
template <typename T> |
inline return_t dispatch (const T &obj) { return obj.get_coverage (); } |
static return_t default_return_value (void) { return Null(Coverage); } |
+ bool stop_sublookup_iteration (return_t r) const |
+ { |
+ r.add_coverage (set); |
+ return false; |
+ } |
- hb_get_coverage_context_t (void) : |
+ hb_add_coverage_context_t (set_t *set_) : |
+ set (set_), |
debug_depth (0) {} |
+ set_t *set; |
unsigned int debug_depth; |
}; |
@@ -260,61 +270,6 @@ struct hb_get_coverage_context_t |
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 dispatch (const T &obj) { return obj.apply (this); } |
- static return_t default_return_value (void) { return false; } |
- bool stop_sublookup_iteration (return_t r) const { return r; } |
- return_t recurse (unsigned int lookup_index) |
- { |
- if (unlikely (nesting_level_left == 0 || !recurse_func)) |
- return default_return_value (); |
- |
- nesting_level_left--; |
- bool ret = recurse_func (this, lookup_index); |
- nesting_level_left++; |
- return ret; |
- } |
- |
- unsigned int table_index; /* GSUB/GPOS */ |
- hb_font_t *font; |
- hb_face_t *face; |
- hb_buffer_t *buffer; |
- hb_direction_t direction; |
- hb_mask_t lookup_mask; |
- bool auto_zwj; |
- recurse_func_t recurse_func; |
- unsigned int nesting_level_left; |
- unsigned int lookup_props; |
- const GDEF &gdef; |
- bool has_glyph_classes; |
- unsigned int debug_depth; |
- |
- |
- hb_apply_context_t (unsigned int table_index_, |
- hb_font_t *font_, |
- hb_buffer_t *buffer_) : |
- table_index (table_index_), |
- font (font_), face (font->face), buffer (buffer_), |
- direction (buffer_->props.direction), |
- lookup_mask (1), |
- auto_zwj (true), |
- recurse_func (NULL), |
- nesting_level_left (MAX_NESTING_LEVEL), |
- lookup_props (0), |
- gdef (*hb_ot_layout_from_face (face)->gdef), |
- has_glyph_classes (gdef.has_glyph_classes ()), |
- debug_depth (0) {} |
- |
- inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } |
- inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } |
- inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } |
- inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } |
- inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } |
- |
struct matcher_t |
{ |
inline matcher_t (void) : |
@@ -390,29 +345,24 @@ struct hb_apply_context_t |
const void *match_data; |
}; |
- struct skipping_forward_iterator_t |
- { |
- inline skipping_forward_iterator_t (hb_apply_context_t *c_, |
- unsigned int start_index_, |
- unsigned int num_items_, |
- bool context_match = false) : |
- idx (start_index_), |
- c (c_), |
- match_glyph_data (NULL), |
- num_items (num_items_), |
- end (c->buffer->len) |
+ struct skipping_iterator_t |
+ { |
+ inline void init (hb_apply_context_t *c_, bool context_match = false) |
{ |
+ c = c_; |
+ match_glyph_data = NULL, |
+ matcher.set_match_func (NULL, NULL); |
matcher.set_lookup_props (c->lookup_props); |
/* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ |
matcher.set_ignore_zwnj (context_match || c->table_index == 1); |
/* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ |
matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); |
- if (!context_match) |
- matcher.set_mask (c->lookup_mask); |
- matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); |
+ matcher.set_mask (context_match ? -1 : c->lookup_mask); |
+ } |
+ inline void set_lookup_props (unsigned int lookup_props) |
+ { |
+ matcher.set_lookup_props (lookup_props); |
} |
- inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } |
- inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } |
inline void set_match_func (matcher_t::match_func_t match_func, |
const void *match_data, |
const USHORT glyph_data[]) |
@@ -421,12 +371,21 @@ struct hb_apply_context_t |
match_glyph_data = glyph_data; |
} |
- inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); } |
+ inline void reset (unsigned int start_index_, |
+ unsigned int num_items_) |
+ { |
+ idx = start_index_; |
+ num_items = num_items_; |
+ end = c->buffer->len; |
+ matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); |
+ } |
+ |
inline void reject (void) { num_items++; match_glyph_data--; } |
+ |
inline bool next (void) |
{ |
assert (num_items > 0); |
- while (!has_no_chance ()) |
+ while (idx + num_items < end) |
{ |
idx++; |
const hb_glyph_info_t &info = c->buffer->info[idx]; |
@@ -450,53 +409,10 @@ struct hb_apply_context_t |
} |
return false; |
} |
- |
- unsigned int idx; |
- protected: |
- hb_apply_context_t *c; |
- matcher_t matcher; |
- const USHORT *match_glyph_data; |
- |
- unsigned int num_items; |
- unsigned int end; |
- }; |
- |
- struct skipping_backward_iterator_t |
- { |
- inline skipping_backward_iterator_t (hb_apply_context_t *c_, |
- unsigned int start_index_, |
- unsigned int num_items_, |
- bool context_match = false) : |
- idx (start_index_), |
- c (c_), |
- match_glyph_data (NULL), |
- num_items (num_items_) |
- { |
- matcher.set_lookup_props (c->lookup_props); |
- /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ |
- matcher.set_ignore_zwnj (context_match || c->table_index == 1); |
- /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ |
- matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); |
- if (!context_match) |
- matcher.set_mask (c->lookup_mask); |
- matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); |
- } |
- inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } |
- inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } |
- inline void set_match_func (matcher_t::match_func_t match_func, |
- const void *match_data, |
- const USHORT glyph_data[]) |
- { |
- matcher.set_match_func (match_func, match_data); |
- match_glyph_data = glyph_data; |
- } |
- |
- inline bool has_no_chance (void) const { return unlikely (idx < num_items); } |
- inline void reject (void) { num_items++; } |
inline bool prev (void) |
{ |
assert (num_items > 0); |
- while (!has_no_chance ()) |
+ while (idx >= num_items) |
{ |
idx--; |
const hb_glyph_info_t &info = c->buffer->out_info[idx]; |
@@ -528,8 +444,75 @@ struct hb_apply_context_t |
const USHORT *match_glyph_data; |
unsigned int num_items; |
+ unsigned int end; |
}; |
+ |
+ 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, typename F> |
+ inline bool may_dispatch (const T *obj, const F *format) { return true; } |
+ template <typename T> |
+ inline return_t dispatch (const T &obj) { return obj.apply (this); } |
+ static return_t default_return_value (void) { return false; } |
+ bool stop_sublookup_iteration (return_t r) const { return r; } |
+ return_t recurse (unsigned int lookup_index) |
+ { |
+ if (unlikely (nesting_level_left == 0 || !recurse_func)) |
+ return default_return_value (); |
+ |
+ nesting_level_left--; |
+ bool ret = recurse_func (this, lookup_index); |
+ nesting_level_left++; |
+ return ret; |
+ } |
+ |
+ unsigned int table_index; /* GSUB/GPOS */ |
+ hb_font_t *font; |
+ hb_face_t *face; |
+ hb_buffer_t *buffer; |
+ hb_direction_t direction; |
+ hb_mask_t lookup_mask; |
+ bool auto_zwj; |
+ recurse_func_t recurse_func; |
+ unsigned int nesting_level_left; |
+ unsigned int lookup_props; |
+ const GDEF &gdef; |
+ bool has_glyph_classes; |
+ skipping_iterator_t iter_input, iter_context; |
+ unsigned int debug_depth; |
+ |
+ |
+ hb_apply_context_t (unsigned int table_index_, |
+ hb_font_t *font_, |
+ hb_buffer_t *buffer_) : |
+ table_index (table_index_), |
+ font (font_), face (font->face), buffer (buffer_), |
+ direction (buffer_->props.direction), |
+ lookup_mask (1), |
+ auto_zwj (true), |
+ recurse_func (NULL), |
+ nesting_level_left (MAX_NESTING_LEVEL), |
+ lookup_props (0), |
+ gdef (*hb_ot_layout_from_face (face)->gdef), |
+ has_glyph_classes (gdef.has_glyph_classes ()), |
+ iter_input (), |
+ iter_context (), |
+ debug_depth (0) {} |
+ |
+ inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } |
+ inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } |
+ inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } |
+ inline void set_lookup (const Lookup &l) { set_lookup_props (l.get_props ()); } |
+ inline void set_lookup_props (unsigned int lookup_props_) |
+ { |
+ lookup_props = lookup_props_; |
+ iter_input.init (this, false); |
+ iter_context.init (this, true); |
+ } |
+ |
inline bool |
match_properties_mark (hb_codepoint_t glyph, |
unsigned int glyph_props, |
@@ -741,9 +724,9 @@ static inline bool match_input (hb_apply_context_t *c, |
hb_buffer_t *buffer = c->buffer; |
- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1); |
+ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
+ skippy_iter.reset (buffer->idx, count - 1); |
skippy_iter.set_match_func (match_func, match_data, input); |
- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
/* |
* This is perhaps the trickiest part of OpenType... Remarks: |
@@ -910,9 +893,9 @@ static inline bool match_backtrack (hb_apply_context_t *c, |
{ |
TRACE_APPLY (NULL); |
- hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); |
+ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; |
+ skippy_iter.reset (c->buffer->backtrack_len (), count); |
skippy_iter.set_match_func (match_func, match_data, backtrack); |
- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
for (unsigned int i = 0; i < count; i++) |
if (!skippy_iter.prev ()) |
@@ -930,9 +913,9 @@ static inline bool match_lookahead (hb_apply_context_t *c, |
{ |
TRACE_APPLY (NULL); |
- hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); |
+ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; |
+ skippy_iter.reset (c->buffer->idx + offset - 1, count); |
skippy_iter.set_match_func (match_func, match_data, lookahead); |
- if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
for (unsigned int i = 0; i < count; i++) |
if (!skippy_iter.next ()) |
@@ -945,7 +928,8 @@ static inline bool match_lookahead (hb_apply_context_t *c, |
struct LookupRecord |
{ |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (c->check_struct (this)); |
} |
@@ -1168,7 +1152,8 @@ struct Rule |
} |
public: |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return inputCount.sanitize (c) |
&& lookupCount.sanitize (c) |
@@ -1232,7 +1217,8 @@ struct RuleSet |
return TRACE_RETURN (false); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (rule.sanitize (c, this)); |
} |
@@ -1314,7 +1300,8 @@ struct ContextFormat1 |
return TRACE_RETURN (rule_set.apply (c, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); |
} |
@@ -1406,7 +1393,8 @@ struct ContextFormat2 |
return TRACE_RETURN (rule_set.apply (c, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this)); |
} |
@@ -1494,7 +1482,8 @@ struct ContextFormat3 |
return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
if (!c->check_struct (this)) return TRACE_RETURN (false); |
unsigned int count = glyphCount; |
@@ -1502,7 +1491,7 @@ struct ContextFormat3 |
if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false); |
for (unsigned int i = 0; i < count; i++) |
if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false); |
- LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count); |
+ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count); |
return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount)); |
} |
@@ -1526,6 +1515,7 @@ struct Context |
inline typename context_t::return_t dispatch (context_t *c) const |
{ |
TRACE_DISPATCH (this, u.format); |
+ if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ()); |
switch (u.format) { |
case 1: return TRACE_RETURN (c->dispatch (u.format1)); |
case 2: return TRACE_RETURN (c->dispatch (u.format2)); |
@@ -1534,17 +1524,6 @@ struct Context |
} |
} |
- inline bool sanitize (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)); |
- case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
- case 3: return TRACE_RETURN (u.format3.sanitize (c)); |
- default:return TRACE_RETURN (true); |
- } |
- } |
- |
protected: |
union { |
USHORT format; /* Format identifier */ |
@@ -1726,14 +1705,15 @@ struct ChainRule |
lookup.array, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
if (!backtrack.sanitize (c)) return TRACE_RETURN (false); |
- HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); |
+ const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); |
if (!input.sanitize (c)) return TRACE_RETURN (false); |
- ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); |
+ const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); |
if (!lookahead.sanitize (c)) return TRACE_RETURN (false); |
- ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); |
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); |
return TRACE_RETURN (lookup.sanitize (c)); |
} |
@@ -1795,7 +1775,8 @@ struct ChainRuleSet |
return TRACE_RETURN (false); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (rule.sanitize (c, this)); |
} |
@@ -1874,7 +1855,8 @@ struct ChainContextFormat1 |
return TRACE_RETURN (rule_set.apply (c, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); |
} |
@@ -1984,7 +1966,8 @@ struct ChainContextFormat2 |
return TRACE_RETURN (rule_set.apply (c, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) && |
inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) && |
@@ -2105,15 +2088,16 @@ struct ChainContextFormat3 |
lookup.len, lookup.array, lookup_context)); |
} |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); |
- OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); |
+ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); |
if (!input.sanitize (c, this)) return TRACE_RETURN (false); |
if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */ |
- OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); |
+ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); |
if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false); |
- ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); |
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); |
return TRACE_RETURN (lookup.sanitize (c)); |
} |
@@ -2144,6 +2128,7 @@ struct ChainContext |
inline typename context_t::return_t dispatch (context_t *c) const |
{ |
TRACE_DISPATCH (this, u.format); |
+ if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ()); |
switch (u.format) { |
case 1: return TRACE_RETURN (c->dispatch (u.format1)); |
case 2: return TRACE_RETURN (c->dispatch (u.format2)); |
@@ -2152,17 +2137,6 @@ struct ChainContext |
} |
} |
- inline bool sanitize (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)); |
- case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
- case 3: return TRACE_RETURN (u.format3.sanitize (c)); |
- default:return TRACE_RETURN (true); |
- } |
- } |
- |
protected: |
union { |
USHORT format; /* Format identifier */ |
@@ -2173,14 +2147,32 @@ struct ChainContext |
}; |
+template <typename T> |
struct ExtensionFormat1 |
{ |
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) { |
+ template <typename X> |
+ inline const X& get_subtable (void) const |
+ { |
+ unsigned int offset = extensionOffset; |
+ if (unlikely (!offset)) return Null(typename T::LookupSubTable); |
+ return StructAtOffset<typename T::LookupSubTable> (this, offset); |
+ } |
+ |
+ template <typename context_t> |
+ inline typename context_t::return_t dispatch (context_t *c) const |
+ { |
+ TRACE_DISPATCH (this, format); |
+ if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ()); |
+ return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()); |
+ } |
+ |
+ /* This is called from may_dispatch() above with hb_sanitize_context_t. */ |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
- return TRACE_RETURN (c->check_struct (this)); |
+ return TRACE_RETURN (c->check_struct (this) && extensionOffset != 0); |
} |
protected: |
@@ -2204,49 +2196,30 @@ struct Extension |
default:return 0; |
} |
} |
- inline unsigned int get_offset (void) const |
- { |
- switch (u.format) { |
- case 1: return u.format1.get_offset (); |
- default:return 0; |
- } |
- } |
- |
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); |
+ switch (u.format) { |
+ case 1: return u.format1.template get_subtable<typename T::LookupSubTable> (); |
+ default:return Null(typename T::LookupSubTable); |
+ } |
} |
template <typename context_t> |
inline typename context_t::return_t dispatch (context_t *c) const |
{ |
- return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()); |
- } |
- |
- inline bool sanitize_self (hb_sanitize_context_t *c) { |
- TRACE_SANITIZE (this); |
- if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
+ TRACE_DISPATCH (this, u.format); |
+ if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ()); |
switch (u.format) { |
- case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
- default:return TRACE_RETURN (true); |
+ case 1: return TRACE_RETURN (u.format1.dispatch (c)); |
+ default:return TRACE_RETURN (c->default_return_value ()); |
} |
} |
- 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 */ |
- ExtensionFormat1 format1; |
+ ExtensionFormat1<T> format1; |
} u; |
}; |
@@ -2291,7 +2264,8 @@ struct GSUBGPOS |
inline const Lookup& get_lookup (unsigned int i) const |
{ return (this+lookupList)[i]; } |
- inline bool sanitize (hb_sanitize_context_t *c) { |
+ inline bool sanitize (hb_sanitize_context_t *c) const |
+ { |
TRACE_SANITIZE (this); |
return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && |
scriptList.sanitize (c, this) && |