From 1b972d893a5066a988833e9a6699e06cbf132d9c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 24 Apr 2013 16:42:05 -0400 Subject: [PATCH] [OTLayout] Add is_inplace() method to GSUB --- src/hb-ot-layout-gsub-table.hh | 56 ++++++++++ src/hb-ot-layout-gsubgpos-private.hh | 158 +++++++++++++++++++++++++++ src/hb-ot-layout-private.hh | 22 ++++ src/hb-ot-layout.cc | 28 +++++ 4 files changed, 264 insertions(+) diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 3b6635bf9..4844709d7 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -37,6 +37,12 @@ namespace OT { struct SingleSubstFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -115,6 +121,12 @@ struct SingleSubstFormat1 struct SingleSubstFormat2 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -251,6 +263,13 @@ struct SingleSubst struct Sequence { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + /* For len==0 we don't do anything, so it's harmless. */ + return TRACE_RETURN (substitute.len <= 1); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -315,6 +334,18 @@ struct Sequence struct MultipleSubstFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + /* Some tools generate MultipleSubst with each substitute having length 1! + * So, check them. */ + unsigned int count = sequence.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+sequence[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -440,6 +471,12 @@ typedef ArrayOf AlternateSet; /* Array of alternate GlyphIDs--in struct AlternateSubstFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -760,6 +797,12 @@ struct LigatureSet struct LigatureSubstFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + return TRACE_RETURN (false); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -908,6 +951,12 @@ struct ExtensionSubst : Extension struct ReverseChainSingleSubstFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1145,6 +1194,13 @@ struct SubstLookup : Lookup return lookup_type_is_reverse (type); } + inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + c->set_recurse_func (dispatch_recurse_func); + return TRACE_RETURN (dispatch (c)); + } + inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index f46b3782e..f502ec1b5 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -44,6 +44,55 @@ namespace OT { ""); + +#ifndef HB_DEBUG_IS_INPLACE +#define HB_DEBUG_IS_INPLACE (HB_DEBUG+0) +#endif + +#define TRACE_IS_INPLACE(this) \ + hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); + +struct hb_is_inplace_context_t +{ + inline const char *get_name (void) { return "IS_INPLACE"; } + static const unsigned int max_debug_depth = HB_DEBUG_IS_INPLACE; + typedef bool return_t; + typedef return_t (*recurse_func_t) (hb_is_inplace_context_t *c, unsigned int lookup_index); + template + inline return_t dispatch (const T &obj) { return obj.is_inplace (this); } + static return_t default_return_value (void) { return true; } + 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; + } + + hb_face_t *face; + recurse_func_t recurse_func; + unsigned int nesting_level_left; + unsigned int debug_depth; + + hb_is_inplace_context_t (hb_face_t *face_, + unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : + face (face_), + recurse_func (NULL), + nesting_level_left (nesting_level_left_), + debug_depth (0) {} + + void set_recurse_func (recurse_func_t func) { recurse_func = func; } +}; + + + #ifndef HB_DEBUG_CLOSURE #define HB_DEBUG_CLOSURE (HB_DEBUG+0) #endif @@ -1096,6 +1145,17 @@ static inline bool context_apply_lookup (hb_apply_context_t *c, struct Rule { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + unsigned int count = lookupCount; + for (unsigned int i = 0; i < count; i++) + if (!c->recurse (lookupRecord[i].lookupListIndex)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1155,6 +1215,16 @@ struct Rule struct RuleSet { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if (!(this+rule[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1211,6 +1281,16 @@ struct RuleSet struct ContextFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int count = ruleSet.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+ruleSet[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1297,6 +1377,16 @@ struct ContextFormat1 struct ContextFormat2 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int count = ruleSet.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+ruleSet[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1392,6 +1482,17 @@ struct ContextFormat2 struct ContextFormat3 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); + unsigned int count = lookupCount; + for (unsigned int i = 0; i < count; i++) + if (!c->recurse (lookupRecord[i].lookupListIndex)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1633,6 +1734,19 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, struct ChainRule { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + const HeadlessArrayOf &input = StructAfter > (backtrack); + const ArrayOf &lookahead = StructAfter > (input); + const ArrayOf &lookup = StructAfter > (lookahead); + unsigned int count = lookup.len; + for (unsigned int i = 0; i < count; i++) + if (!c->recurse (lookup.array[i].lookupListIndex)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1718,6 +1832,16 @@ struct ChainRule struct ChainRuleSet { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int num_rules = rule.len; + for (unsigned int i = 0; i < num_rules; i++) + if (!(this+rule[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1771,6 +1895,16 @@ struct ChainRuleSet struct ChainContextFormat1 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int count = ruleSet.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+ruleSet[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1854,6 +1988,16 @@ struct ChainContextFormat1 struct ChainContextFormat2 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + unsigned int count = ruleSet.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+ruleSet[i]).is_inplace (c)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1978,6 +2122,20 @@ struct ChainContextFormat2 struct ChainContextFormat3 { + inline bool is_inplace (hb_is_inplace_context_t *c) const + { + TRACE_IS_INPLACE (this); + const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &lookahead = StructAfter > (input); + const ArrayOf &lookup = StructAfter > (lookahead); + + unsigned int count = lookup.len; + for (unsigned int i = 0; i < count; i++) + if (!c->recurse (lookup.array[i].lookupListIndex)) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 4866c4191..b016542e6 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -189,6 +189,23 @@ static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) { } + +/* + * GSUBGPOS + */ + +/* Always returns true for GPOS, but make writing code easier. */ +HB_INTERNAL bool +hb_ot_layout_lookup_is_inplace (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index); + + + +/* + * GSUB + */ + HB_INTERNAL hb_bool_t hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, unsigned int lookup_index, @@ -215,6 +232,11 @@ hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer); + +/* + * GPOS + */ + /* Should be called before all the position_lookup's are done. Resets positions to zero. */ HB_INTERNAL void hb_ot_layout_position_start (hb_font_t *font, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3b7ea47ea..a9c02aabc 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -651,6 +651,33 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, } +/* + * GSUBGPOS + */ + +bool +hb_ot_layout_lookup_is_inplace (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index) +{ + OT::hb_is_inplace_context_t c (face); + + switch (table_tag) + { + case HB_OT_TAG_GSUB: + { + const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index); + return l.is_inplace (&c); + } + + default: + case HB_OT_TAG_GPOS: + { + return true; + } + } +} + /* * OT::GSUB */ @@ -727,6 +754,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, l.closure (&c); } + /* * OT::GPOS */