Refactor / finish would_apply() operation

Untested.
This commit is contained in:
Behdad Esfahbod 2012-07-19 14:35:23 -04:00
parent 8c973ebf0f
commit e72b360ac6
5 changed files with 308 additions and 75 deletions

View File

@ -1333,7 +1333,7 @@ struct PosLookupSubTable
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.c.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);
@ -1352,7 +1352,7 @@ struct PosLookupSubTable
case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c));
case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c));
case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c));
case Context: return TRACE_RETURN (u.c.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
default: return TRACE_RETURN (true);
@ -1371,7 +1371,7 @@ struct PosLookupSubTable
MarkBasePos markBase;
MarkLigPos markLig;
MarkMarkPos markMark;
ContextPos c;
ContextPos context;
ChainContextPos chainContext;
ExtensionPos extension;
} u;

View File

@ -50,9 +50,9 @@ struct SingleSubstFormat1
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
return (this+coverage) (glyph_id) != NOT_COVERED;
return c->len == 1 && (this+coverage) (c->first) != NOT_COVERED;
}
inline bool apply (hb_apply_context_t *c) const
@ -102,9 +102,9 @@ struct SingleSubstFormat2
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
return (this+coverage) (glyph_id) != NOT_COVERED;
return c->len == 1 && (this+coverage) (c->first) != NOT_COVERED;
}
inline bool apply (hb_apply_context_t *c) const
@ -155,11 +155,11 @@ struct SingleSubst
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
switch (u.format) {
case 1: return u.format1.would_apply (glyph_id);
case 2: return u.format2.would_apply (glyph_id);
case 1: return u.format1.would_apply (c);
case 2: return u.format2.would_apply (c);
default:return false;
}
}
@ -252,9 +252,9 @@ struct MultipleSubstFormat1
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
return (this+coverage) (glyph_id) != NOT_COVERED;
return c->len == 1 && (this+coverage) (c->first) != NOT_COVERED;
}
inline bool apply (hb_apply_context_t *c) const
@ -299,10 +299,10 @@ struct MultipleSubst
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
switch (u.format) {
case 1: return u.format1.would_apply (glyph_id);
case 1: return u.format1.would_apply (c);
default:return false;
}
}
@ -356,9 +356,9 @@ struct AlternateSubstFormat1
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
return (this+coverage) (glyph_id) != NOT_COVERED;
return c->len == 1 && (this+coverage) (c->first) != NOT_COVERED;
}
inline bool apply (hb_apply_context_t *c) const
@ -421,10 +421,10 @@ struct AlternateSubst
}
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
switch (u.format) {
case 1: return u.format1.would_apply (glyph_id);
case 1: return u.format1.would_apply (c);
default:return false;
}
}
@ -471,9 +471,9 @@ struct Ligature
c->glyphs->add (ligGlyph);
}
inline bool would_apply (hb_codepoint_t second) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
return component.len == 2 && component[1] == second;
return c->len == 1 || (c->len == 2 && component.len == 2 && component[1] == c->second);
}
inline bool apply (hb_apply_context_t *c) const
@ -568,13 +568,13 @@ struct LigatureSet
(this+ligature[i]).closure (c);
}
inline bool would_apply (hb_codepoint_t second) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
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 (second))
if (lig.would_apply (c))
return true;
}
return false;
@ -623,11 +623,11 @@ struct LigatureSubstFormat1
}
}
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
unsigned int index;
return (index = (this+coverage) (first)) != NOT_COVERED &&
(this+ligatureSet[index]).would_apply (second);
return (index = (this+coverage) (c->first)) != NOT_COVERED &&
(this+ligatureSet[index]).would_apply (c);
}
inline bool apply (hb_apply_context_t *c) const
@ -674,10 +674,10 @@ struct LigatureSubst
}
}
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
switch (u.format) {
case 1: return u.format1.would_apply (first, second);
case 1: return u.format1.would_apply (c);
default:return false;
}
}
@ -764,8 +764,7 @@ struct ExtensionSubst : Extension
}
inline void closure (hb_closure_context_t *c) const;
inline bool would_apply (hb_codepoint_t glyph_id) const;
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
inline bool would_apply (hb_would_apply_context_t *c) const;
inline bool apply (hb_apply_context_t *c) const;
@ -935,7 +934,7 @@ struct SubstLookupSubTable
case Multiple: u.multiple.closure (c); break;
case Alternate: u.alternate.closure (c); break;
case Ligature: u.ligature.closure (c); break;
case Context: u.c.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;
@ -943,28 +942,6 @@ struct SubstLookupSubTable
}
}
inline bool would_apply (hb_codepoint_t glyph_id,
unsigned int lookup_type) const
{
switch (lookup_type) {
case Single: return u.single.would_apply (glyph_id);
case Multiple: return u.multiple.would_apply (glyph_id);
case Alternate: return u.alternate.would_apply (glyph_id);
case Extension: return u.extension.would_apply (glyph_id);
default: return false;
}
}
inline bool would_apply (hb_codepoint_t first,
hb_codepoint_t second,
unsigned int lookup_type) const
{
switch (lookup_type) {
case Ligature: return u.ligature.would_apply (first, second);
case Extension: return u.extension.would_apply (first, second);
default: return false;
}
}
inline bool can_use_fast_path (unsigned int lookup_type) const
{
/* Fast path, for those that have coverage in the same place.
@ -975,6 +952,26 @@ struct SubstLookupSubTable
hb_in_range<unsigned int> (u.header.sub_format, 1, 2));
}
inline bool would_apply (hb_would_apply_context_t *c,
unsigned int lookup_type) const
{
TRACE_WOULD_APPLY ();
if (can_use_fast_path (lookup_type))
{
unsigned int index = (this+u.header.coverage) (c->first);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
}
switch (lookup_type) {
case Single: return u.single.would_apply (c);
case Multiple: return u.multiple.would_apply (c);
case Alternate: return u.alternate.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 ();
@ -989,7 +986,7 @@ struct SubstLookupSubTable
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.c.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));
@ -1007,7 +1004,7 @@ struct SubstLookupSubTable
case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
case Context: return TRACE_RETURN (u.c.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
@ -1025,7 +1022,7 @@ struct SubstLookupSubTable
MultipleSubst multiple;
AlternateSubst alternate;
LigatureSubst ligature;
ContextSubst c;
ContextSubst context;
ChainContextSubst chainContext;
ExtensionSubst extension;
ReverseChainSingleSubst reverseChainContextSingle;
@ -1059,21 +1056,12 @@ struct SubstLookup : Lookup
get_subtable (i).closure (c, lookup_type);
}
inline bool would_apply (hb_codepoint_t glyph_id) const
inline bool would_apply (hb_would_apply_context_t *c) const
{
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 (glyph_id, lookup_type))
return true;
return false;
}
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
{
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 (first, second, lookup_type))
if (get_subtable (i).would_apply (c, lookup_type))
return true;
return false;
}
@ -1173,6 +1161,9 @@ struct GSUB : GSUBGPOS
inline const SubstLookup& get_lookup (unsigned int i) const
{ return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
inline bool would_substitute_lookup (hb_would_apply_context_t *c, unsigned int lookup_index) const
{ return get_lookup (lookup_index).would_apply (c); }
inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) const
{ return get_lookup (lookup_index).apply_string (c); }
@ -1219,14 +1210,9 @@ inline void ExtensionSubst::closure (hb_closure_context_t *c) const
get_subtable ().closure (c, get_type ());
}
inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
inline bool ExtensionSubst::would_apply (hb_would_apply_context_t *c) const
{
return get_subtable ().would_apply (glyph_id, get_type ());
}
inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t second) const
{
return get_subtable ().would_apply (first, second, get_type ());
return get_subtable ().would_apply (c, get_type ());
}
inline bool ExtensionSubst::apply (hb_apply_context_t *c) const

View File

@ -69,7 +69,13 @@ static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
/* TODO Add TRACE_RETURN annotation for would_apply */
/* 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, "first %u second %u", c->first, c->second);
struct hb_closure_context_t
@ -83,13 +89,32 @@ struct hb_closure_context_t
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
face (face_), glyphs (glyphs_),
face (face_),
glyphs (glyphs_),
nesting_level_left (nesting_level_left_),
debug_depth (0) {}
};
struct hb_would_apply_context_t
{
hb_face_t *face;
hb_codepoint_t first;
hb_codepoint_t second;
unsigned int len;
unsigned int debug_depth;
hb_would_apply_context_t (hb_face_t *face_,
hb_codepoint_t first_,
hb_codepoint_t second_ = -1) :
face (face_),
first (first_), second (second_), len (second == (hb_codepoint_t) -1 ? 1 : 2),
debug_depth (0) {};
};
#ifndef HB_DEBUG_APPLY
#define HB_DEBUG_APPLY (HB_DEBUG+0)
#endif
@ -320,6 +345,21 @@ static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value,
}
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 */
match_func_t match_func,
const void *match_data)
{
if (count != c->len)
return false;
for (unsigned int i = 1; i < count; i++)
if (likely (!match_func (c->second, input[i - 1], match_data)))
return false;
return true;
}
static inline bool match_input (hb_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
const USHORT input[], /* Array of input values--start with second glyph */
@ -508,6 +548,17 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
}
static inline bool context_would_apply_lookup (hb_would_apply_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[],
ContextApplyLookupContext &lookup_context)
{
return would_match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data);
}
static inline bool context_apply_lookup (hb_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
const USHORT input[], /* Array of input values--start with second glyph */
@ -540,6 +591,13 @@ struct Rule
lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_WOULD_APPLY ();
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 ();
@ -580,6 +638,18 @@ struct RuleSet
(this+rule[i]).closure (c, lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_WOULD_APPLY ();
unsigned int num_rules = rule.len;
for (unsigned int i = 0; i < num_rules; i++)
{
if ((this+rule[i]).would_apply (c, lookup_context))
return TRACE_RETURN (true);
}
return TRACE_RETURN (false);
}
inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
@ -631,6 +701,21 @@ struct ContextFormat1
}
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
unsigned int index = (this+coverage) (c->first);
if (likely (index == NOT_COVERED))
return TRACE_RETURN (false);
const RuleSet &rule_set = this+ruleSet[index];
struct ContextApplyLookupContext lookup_context = {
{match_glyph, 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
{
TRACE_APPLY ();
@ -691,6 +776,22 @@ struct ContextFormat2
}
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
unsigned int index = (this+coverage) (c->first);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ClassDef &class_def = this+classDef;
index = class_def (c->first);
const RuleSet &rule_set = this+ruleSet[index];
struct ContextApplyLookupContext lookup_context = {
{match_class, NULL},
&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
{
TRACE_APPLY ();
@ -751,6 +852,20 @@ struct ContextFormat3
lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
unsigned int index = (this+coverage[0]) (c->first);
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, NULL},
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
{
TRACE_APPLY ();
@ -805,6 +920,16 @@ struct Context
}
}
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 ();
@ -876,6 +1001,24 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
lookup_context.funcs.closure);
}
static inline bool chain_context_would_apply_lookup (hb_would_apply_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[],
ChainContextApplyLookupContext &lookup_context)
{
return !backtrackCount
&& !lookaheadCount
&& would_match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data[1]);
}
static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
unsigned int backtrackCount,
const USHORT backtrack[],
@ -925,6 +1068,19 @@ struct ChainRule
lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_WOULD_APPLY ();
const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
return TRACE_RETURN (chain_context_would_apply_lookup (c,
backtrack.len, backtrack.array,
input.len, input.array,
lookahead.len, lookahead.array, lookup.len,
lookup.array, lookup_context));
}
inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
@ -978,6 +1134,17 @@ struct ChainRuleSet
(this+rule[i]).closure (c, lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_WOULD_APPLY ();
unsigned int num_rules = rule.len;
for (unsigned int i = 0; i < num_rules; i++)
if ((this+rule[i]).would_apply (c, lookup_context))
return TRACE_RETURN (true);
return TRACE_RETURN (false);
}
inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
@ -1026,6 +1193,20 @@ struct ChainContextFormat1
}
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
unsigned int index = (this+coverage) (c->first);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
{match_glyph, NULL},
{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
{
TRACE_APPLY ();
@ -1088,6 +1269,23 @@ struct ChainContextFormat2
}
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
unsigned int index = (this+coverage) (c->first);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ClassDef &input_class_def = this+inputClassDef;
index = input_class_def (c->first);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
{match_class, NULL},
{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
{
TRACE_APPLY ();
@ -1168,6 +1366,27 @@ struct ChainContextFormat3
lookup_context);
}
inline bool would_apply (hb_would_apply_context_t *c) const
{
TRACE_WOULD_APPLY ();
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
unsigned int index = (this+input[0]) (c->first);
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, NULL},
{this, this, this}
};
return TRACE_RETURN (chain_context_would_apply_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 apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
@ -1236,6 +1455,16 @@ struct ChainContext
}
}
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 ();

View File

@ -458,6 +458,17 @@ hb_ot_layout_has_substitution (hb_face_t *face)
return &_get_gsub (face) != &Null(GSUB);
}
hb_bool_t
hb_ot_layout_would_substitute_lookup (hb_face_t *face,
const hb_codepoint_t *glyphs,
unsigned int glyphs_length,
unsigned int lookup_index)
{
if (unlikely (glyphs_length < 1 || glyphs_length > 2)) return false;
hb_would_apply_context_t c (face, glyphs[0], glyphs_length == 2 ? glyphs[1] : -1);
return _get_gsub (face).would_substitute_lookup (&c, lookup_index);
}
void
hb_ot_layout_substitute_start (hb_buffer_t *buffer)
{

View File

@ -168,6 +168,13 @@ hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face);
/* Supports length 1 or 2 right now. */
hb_bool_t
hb_ot_layout_would_substitute_lookup (hb_face_t *face,
const hb_codepoint_t *glyphs,
unsigned int glyphs_length,
unsigned int lookup_index);
/* Should be called before all the substitute_lookup's are done. */
void
hb_ot_layout_substitute_start (hb_buffer_t *buffer);