[subset] closure lookups for GSUB/GPOS
This commit is contained in:
parent
9cd76813ab
commit
0b39c48064
|
@ -551,6 +551,7 @@ HB_OT_TAG_GPOS
|
|||
HB_OT_TAG_GSUB
|
||||
HB_OT_TAG_JSTF
|
||||
hb_ot_layout_baseline_tag_t
|
||||
hb_ot_layout_closure_lookups
|
||||
hb_ot_layout_collect_lookups
|
||||
hb_ot_layout_collect_features
|
||||
hb_ot_layout_feature_get_characters
|
||||
|
|
|
@ -2299,6 +2299,11 @@ struct FeatureTableSubstitutionRecord
|
|||
{
|
||||
friend struct FeatureTableSubstitution;
|
||||
|
||||
void collect_lookups (hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
return (this+feature).add_lookup_indexes_to (lookup_indexes);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -2326,6 +2331,18 @@ struct FeatureTableSubstitution
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
+ hb_iter (substitutions)
|
||||
| hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
|
||||
| hb_apply ([=] (const FeatureTableSubstitutionRecord& r)
|
||||
{
|
||||
r.collect_lookups (lookup_indexes);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -2346,6 +2363,12 @@ struct FeatureVariationRecord
|
|||
{
|
||||
friend struct FeatureVariations;
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
return (this+substitutions).collect_lookups (feature_indexes, lookup_indexes);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -2396,6 +2419,13 @@ struct FeatureVariations
|
|||
return_trace (c->embed (*this));
|
||||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
for (const FeatureVariationRecord& r : varRecords)
|
||||
r.collect_lookups (feature_indexes, lookup_indexes);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -519,6 +519,8 @@ struct SinglePosFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
|
||||
|
||||
|
@ -601,6 +603,8 @@ struct SinglePosFormat2
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
|
||||
|
||||
|
@ -923,6 +927,8 @@ struct PairPosFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -1034,6 +1040,8 @@ struct PairPosFormat2
|
|||
(this+classDef2).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -1239,6 +1247,8 @@ struct CursivePosFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
|
||||
|
||||
|
@ -1438,6 +1448,8 @@ struct MarkBasePosFormat1
|
|||
{ return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+baseCoverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
|
||||
|
@ -1559,6 +1571,8 @@ struct MarkLigPosFormat1
|
|||
{ return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+ligatureCoverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
|
||||
|
@ -1679,6 +1693,8 @@ struct MarkMarkPosFormat1
|
|||
{ return (this+mark1Coverage).intersects (glyphs) &&
|
||||
(this+mark2Coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
|
||||
|
@ -1885,6 +1901,23 @@ struct PosLookup : Lookup
|
|||
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ return dispatch (c); }
|
||||
|
||||
hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
|
||||
{
|
||||
if (c->is_lookup_visited (this_index))
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
|
||||
c->set_lookup_visited (this_index);
|
||||
if (!intersects (c->glyphs))
|
||||
{
|
||||
c->set_lookup_inactive (this_index);
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
}
|
||||
c->set_recurse_func (dispatch_closure_lookups_recurse_func);
|
||||
|
||||
hb_closure_lookups_context_t::return_t ret = dispatch (c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void add_coverage (set_t *glyphs) const
|
||||
{
|
||||
|
@ -1897,6 +1930,8 @@ struct PosLookup : Lookup
|
|||
template <typename context_t>
|
||||
static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
||||
|
||||
HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
|
||||
|
@ -2053,6 +2088,13 @@ template <typename context_t>
|
|||
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
|
||||
{
|
||||
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
|
||||
return l.closure_lookups (c, this_index);
|
||||
}
|
||||
|
||||
/*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
|
|
|
@ -56,6 +56,8 @@ struct SingleSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -154,6 +156,8 @@ struct SingleSubstFormat2
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -395,6 +399,8 @@ struct MultipleSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -605,6 +611,8 @@ struct AlternateSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -966,6 +974,8 @@ struct LigatureSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -1156,6 +1166,8 @@ struct ReverseChainSingleSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
|
@ -1372,6 +1384,24 @@ struct SubstLookup : Lookup
|
|||
return ret;
|
||||
}
|
||||
|
||||
hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
|
||||
{
|
||||
if (c->is_lookup_visited (this_index))
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
|
||||
c->set_lookup_visited (this_index);
|
||||
if (!intersects (c->glyphs))
|
||||
{
|
||||
c->set_lookup_inactive (this_index);
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
}
|
||||
|
||||
c->set_recurse_func (dispatch_closure_lookups_recurse_func);
|
||||
|
||||
hb_closure_lookups_context_t::return_t ret = dispatch (c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
|
||||
|
@ -1477,6 +1507,8 @@ struct SubstLookup : Lookup
|
|||
return ret;
|
||||
}
|
||||
|
||||
HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
|
||||
|
@ -1529,6 +1561,13 @@ template <typename context_t>
|
|||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
|
||||
return l.closure_lookups (c, this_index);
|
||||
}
|
||||
|
||||
/*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
|
|
|
@ -122,6 +122,63 @@ struct hb_closure_context_t :
|
|||
hb_map_t *done_lookups;
|
||||
};
|
||||
|
||||
struct hb_closure_lookups_context_t :
|
||||
hb_dispatch_context_t<hb_closure_lookups_context_t, hb_empty_t, 0>
|
||||
{
|
||||
const char *get_name () { return "CLOSURE_LOOKUPS"; }
|
||||
typedef return_t (*recurse_func_t) (hb_closure_lookups_context_t *c, unsigned lookup_index);
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.closure_lookups (this); return hb_empty_t (); }
|
||||
static return_t default_return_value () { return hb_empty_t (); }
|
||||
void recurse (unsigned lookup_index)
|
||||
{
|
||||
if (unlikely (nesting_level_left == 0 || !recurse_func))
|
||||
return;
|
||||
|
||||
/* Return if new lookup was recursed to before. */
|
||||
if (is_lookup_visited (lookup_index))
|
||||
return;
|
||||
|
||||
set_lookup_visited (lookup_index);
|
||||
nesting_level_left--;
|
||||
recurse_func (this, lookup_index);
|
||||
nesting_level_left++;
|
||||
}
|
||||
|
||||
void set_lookup_visited (unsigned lookup_index)
|
||||
{ visited_lookups->add (lookup_index); }
|
||||
|
||||
void set_lookup_inactive (unsigned lookup_index)
|
||||
{ inactive_lookups->add (lookup_index); }
|
||||
|
||||
bool is_lookup_visited (unsigned lookup_index)
|
||||
{ return visited_lookups->has (lookup_index); }
|
||||
|
||||
hb_face_t *face;
|
||||
const hb_set_t *glyphs;
|
||||
recurse_func_t recurse_func;
|
||||
unsigned int nesting_level_left;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_closure_lookups_context_t (hb_face_t *face_,
|
||||
const hb_set_t *glyphs_,
|
||||
hb_set_t *visited_lookups_,
|
||||
hb_set_t *inactive_lookups_,
|
||||
unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
|
||||
face (face_),
|
||||
glyphs (glyphs_),
|
||||
recurse_func (nullptr),
|
||||
nesting_level_left (nesting_level_left_),
|
||||
debug_depth (0),
|
||||
visited_lookups (visited_lookups_),
|
||||
inactive_lookups (inactive_lookups_) {}
|
||||
|
||||
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||
|
||||
private:
|
||||
hb_set_t *visited_lookups;
|
||||
hb_set_t *inactive_lookups;
|
||||
};
|
||||
|
||||
struct hb_would_apply_context_t :
|
||||
hb_dispatch_context_t<hb_would_apply_context_t, bool, 0>
|
||||
|
@ -1061,6 +1118,17 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
|
|||
|
||||
struct LookupRecord
|
||||
{
|
||||
LookupRecord* copy (hb_serialize_context_t *c,
|
||||
const hb_map_t *lookup_map)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (*this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
|
||||
out->lookupListIndex = hb_map_get (lookup_map, lookupListIndex);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -1315,6 +1383,13 @@ struct Rule
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
||||
(inputZ.as_array (inputCount ? inputCount - 1 : 0));
|
||||
recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
ContextCollectGlyphsLookupContext &lookup_context) const
|
||||
{
|
||||
|
@ -1395,6 +1470,15 @@ struct RuleSet
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
return
|
||||
+ hb_iter (rule)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const Rule &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
ContextCollectGlyphsLookupContext &lookup_context) const
|
||||
{
|
||||
|
@ -1478,6 +1562,14 @@ struct ContextFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).add_coverage (c->input);
|
||||
|
@ -1592,6 +1684,14 @@ struct ContextFormat2
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).add_coverage (c->input);
|
||||
|
@ -1699,6 +1799,12 @@ struct ContextFormat3
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
|
||||
recurse_lookups (c, lookupCount, lookupRecord);
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverageZ[0]).add_coverage (c->input);
|
||||
|
@ -1964,6 +2070,14 @@ struct ChainRule
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
|
||||
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
|
||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
|
||||
recurse_lookups (c, lookup.len, lookup.arrayZ);
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
ChainContextCollectGlyphsLookupContext &lookup_context) const
|
||||
{
|
||||
|
@ -2131,6 +2245,15 @@ struct ChainRuleSet
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
return
|
||||
+ hb_iter (rule)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
|
||||
{
|
||||
return
|
||||
|
@ -2244,6 +2367,14 @@ struct ChainContextFormat1
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).add_coverage (c->input);
|
||||
|
@ -2380,6 +2511,14 @@ struct ChainContextFormat2
|
|||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).add_coverage (c->input);
|
||||
|
@ -2570,6 +2709,14 @@ struct ChainContextFormat3
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||
{
|
||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
|
||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
|
||||
recurse_lookups (c, lookup.len, lookup.arrayZ);
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
|
@ -2879,7 +3026,7 @@ struct GSUBGPOS
|
|||
bool find_variations_index (const int *coords, unsigned int num_coords,
|
||||
unsigned int *index) const
|
||||
{
|
||||
#ifdef HB_NOVAR
|
||||
#ifdef HB_NO_VAR
|
||||
return false;
|
||||
#endif
|
||||
return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
|
||||
|
@ -2901,6 +3048,15 @@ struct GSUBGPOS
|
|||
return get_feature (feature_index);
|
||||
}
|
||||
|
||||
void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
if (version.to_int () >= 0x00010001u)
|
||||
(this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename TLookup>
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -1191,6 +1191,50 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
|||
for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
|
||||
hb_set_next (&feature_indexes, &feature_index);)
|
||||
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
|
||||
|
||||
g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_layout_closure_lookups:
|
||||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
|
||||
* @lookup_indexes: (inout): lookup_indices collected from feature
|
||||
* list
|
||||
*
|
||||
* Returns all inactive lookups reachable from lookup_indices
|
||||
* Since: 2.6.4
|
||||
**/
|
||||
void
|
||||
hb_ot_layout_closure_lookups (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
const hb_set_t *glyphs,
|
||||
hb_set_t *lookup_indexes /* IN/OUT */)
|
||||
{
|
||||
hb_set_t visited_lookups, inactive_lookups;
|
||||
OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
|
||||
|
||||
for (unsigned lookup_index : + hb_iter (lookup_indexes))
|
||||
{
|
||||
switch (table_tag)
|
||||
{
|
||||
case HB_OT_TAG_GSUB:
|
||||
{
|
||||
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
l.closure_lookups (&c, lookup_index);
|
||||
break;
|
||||
}
|
||||
case HB_OT_TAG_GPOS:
|
||||
{
|
||||
const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
|
||||
l.closure_lookups (&c, lookup_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hb_set_union (lookup_indexes, &visited_lookups);
|
||||
hb_set_subtract (lookup_indexes, &inactive_lookups);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -263,6 +263,12 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
|||
const hb_tag_t *features,
|
||||
hb_set_t *lookup_indexes /* OUT */);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ot_layout_closure_lookups (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
const hb_set_t *glyphs,
|
||||
hb_set_t *lookup_indexes /* IN/OUT */);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
|
|
|
@ -50,8 +50,21 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
|
|||
#endif
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
static void
|
||||
_remap_lookups (const hb_set_t *lookup_indices,
|
||||
hb_map_t *lookups /* OUT */)
|
||||
{
|
||||
unsigned count = lookup_indices->get_population ();
|
||||
|
||||
for (auto _ : + hb_zip (lookup_indices->iter (), hb_range (count)))
|
||||
lookups->set (_.first, _.second);
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
|
||||
_gsub_closure_glyphs_and_lookups (hb_face_t *face,
|
||||
hb_set_t *gids_to_retain,
|
||||
hb_map_t *gsub_lookups)
|
||||
{
|
||||
hb_set_t lookup_indices;
|
||||
hb_ot_layout_collect_lookups (face,
|
||||
|
@ -63,6 +76,30 @@ _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
|
|||
hb_ot_layout_lookups_substitute_closure (face,
|
||||
&lookup_indices,
|
||||
gids_to_retain);
|
||||
hb_ot_layout_closure_lookups (face,
|
||||
HB_OT_TAG_GSUB,
|
||||
gids_to_retain,
|
||||
&lookup_indices);
|
||||
_remap_lookups (&lookup_indices, gsub_lookups);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_gpos_closure_lookups (hb_face_t *face,
|
||||
const hb_set_t *gids_to_retain,
|
||||
hb_map_t *gpos_lookups)
|
||||
{
|
||||
hb_set_t lookup_indices;
|
||||
hb_ot_layout_collect_lookups (face,
|
||||
HB_OT_TAG_GPOS,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&lookup_indices);
|
||||
hb_ot_layout_closure_lookups (face,
|
||||
HB_OT_TAG_GPOS,
|
||||
gids_to_retain,
|
||||
&lookup_indices);
|
||||
_remap_lookups (&lookup_indices, gpos_lookups);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -93,7 +130,8 @@ static void
|
|||
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
const hb_set_t *unicodes,
|
||||
const hb_set_t *input_glyphs_to_retain,
|
||||
bool close_over_gsub)
|
||||
bool close_over_gsub,
|
||||
bool close_over_gpos)
|
||||
{
|
||||
OT::cmap::accelerator_t cmap;
|
||||
OT::glyf::accelerator_t glyf;
|
||||
|
@ -127,8 +165,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (close_over_gsub)
|
||||
// Add all glyphs needed for GSUB substitutions.
|
||||
_gsub_closure (plan->source, plan->_glyphset_gsub);
|
||||
// closure all glyphs/lookups needed for GSUB substitutions.
|
||||
_gsub_closure_glyphs_and_lookups (plan->source, plan->_glyphset_gsub, plan->gsub_lookups);
|
||||
|
||||
if (close_over_gpos)
|
||||
_gpos_closure_lookups (plan->source, plan->_glyphset_gsub, plan->gpos_lookups);
|
||||
#endif
|
||||
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||
|
||||
|
@ -231,11 +272,14 @@ hb_subset_plan_create (hb_face_t *face,
|
|||
plan->codepoint_to_glyph = hb_map_create ();
|
||||
plan->glyph_map = hb_map_create ();
|
||||
plan->reverse_glyph_map = hb_map_create ();
|
||||
plan->gsub_lookups = hb_map_create ();
|
||||
plan->gpos_lookups = hb_map_create ();
|
||||
|
||||
_populate_gids_to_retain (plan,
|
||||
input->unicodes,
|
||||
input->glyphs,
|
||||
!input->drop_tables->has (HB_OT_TAG_GSUB));
|
||||
!input->drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->drop_tables->has (HB_OT_TAG_GPOS));
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->retain_gids,
|
||||
|
@ -267,6 +311,8 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
|||
hb_map_destroy (plan->reverse_glyph_map);
|
||||
hb_set_destroy (plan->_glyphset);
|
||||
hb_set_destroy (plan->_glyphset_gsub);
|
||||
hb_map_destroy (plan->gsub_lookups);
|
||||
hb_map_destroy (plan->gpos_lookups);
|
||||
|
||||
free (plan);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,10 @@ struct hb_subset_plan_t
|
|||
hb_set_t *_glyphset;
|
||||
hb_set_t *_glyphset_gsub;
|
||||
|
||||
//active lookups we'd like to retain
|
||||
hb_map_t *gsub_lookups;
|
||||
hb_map_t *gpos_lookups;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
|
|
|
@ -74,6 +74,11 @@ test_face (hb_face_t *face,
|
|||
hb_ot_color_has_png (face);
|
||||
hb_blob_destroy (hb_ot_color_glyph_reference_png (font, cp));
|
||||
|
||||
hb_set_t *lookup_indexes = hb_set_create ();
|
||||
hb_set_add (lookup_indexes, 0);
|
||||
hb_ot_layout_closure_lookups (face, HB_OT_TAG_GSUB, set, lookup_indexes);
|
||||
hb_set_destroy (lookup_indexes);
|
||||
|
||||
hb_ot_layout_get_baseline (font, HB_OT_LAYOUT_BASELINE_TAG_HANGING, HB_DIRECTION_RTL, HB_SCRIPT_HANGUL, HB_TAG_NONE, NULL);
|
||||
|
||||
hb_ot_layout_has_glyph_classes (face);
|
||||
|
|
Loading…
Reference in New Issue