Merge pull request #2699 from googlefonts/gpos_8
[subset] Add a more complex layout subsetting test case and fix the issues it exposed.
This commit is contained in:
commit
6a3fd94f3b
|
@ -1128,7 +1128,7 @@ struct Lookup
|
||||||
out->lookupType = lookupType;
|
out->lookupType = lookupType;
|
||||||
out->lookupFlag = lookupFlag;
|
out->lookupFlag = lookupFlag;
|
||||||
|
|
||||||
const hb_set_t *glyphset = c->plan->glyphset ();
|
const hb_set_t *glyphset = c->plan->glyphset_gsub ();
|
||||||
unsigned int lookup_type = get_type ();
|
unsigned int lookup_type = get_type ();
|
||||||
+ hb_iter (get_subtables <TSubTable> ())
|
+ hb_iter (get_subtables <TSubTable> ())
|
||||||
| hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
|
| hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
|
||||||
|
@ -1506,7 +1506,7 @@ struct Coverage
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto it =
|
auto it =
|
||||||
|
@ -1733,7 +1733,7 @@ struct ClassDefFormat1
|
||||||
hb_map_t *klass_map = nullptr /*OUT*/) const
|
hb_map_t *klass_map = nullptr /*OUT*/) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
hb_sorted_vector_t<HBGlyphID> glyphs;
|
hb_sorted_vector_t<HBGlyphID> glyphs;
|
||||||
|
@ -1907,7 +1907,7 @@ struct ClassDefFormat2
|
||||||
hb_map_t *klass_map = nullptr /*OUT*/) const
|
hb_map_t *klass_map = nullptr /*OUT*/) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
hb_sorted_vector_t<HBGlyphID> glyphs;
|
hb_sorted_vector_t<HBGlyphID> glyphs;
|
||||||
|
|
|
@ -755,7 +755,7 @@ struct SinglePosFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto it =
|
auto it =
|
||||||
|
@ -870,7 +870,7 @@ struct SinglePosFormat2
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
unsigned sub_length = valueFormat.get_len ();
|
unsigned sub_length = valueFormat.get_len ();
|
||||||
|
@ -1129,7 +1129,7 @@ struct PairSet
|
||||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
out->len = 0;
|
out->len = 0;
|
||||||
|
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
unsigned len1 = valueFormats[0].get_len ();
|
unsigned len1 = valueFormats[0].get_len ();
|
||||||
|
@ -1250,7 +1250,7 @@ struct PairPosFormat1
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -1441,7 +1441,7 @@ struct PairPosFormat2
|
||||||
})
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto it =
|
auto it =
|
||||||
|
@ -1728,7 +1728,7 @@ struct CursivePosFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -1904,7 +1904,7 @@ struct MarkBasePosFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -2288,7 +2288,7 @@ struct MarkMarkPosFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
|
|
@ -356,7 +356,7 @@ struct Sequence
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
if (!intersects (&glyphset)) return_trace (false);
|
if (!intersects (&glyphset)) return_trace (false);
|
||||||
|
@ -447,7 +447,7 @@ struct MultipleSubstFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -582,7 +582,7 @@ struct AlternateSet
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto it =
|
auto it =
|
||||||
|
@ -682,7 +682,7 @@ struct AlternateSubstFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -840,7 +840,7 @@ struct Ligature
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
|
if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
|
||||||
|
@ -1058,7 +1058,7 @@ struct LigatureSubstFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
|
|
@ -1388,9 +1388,11 @@ struct Rule
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c,
|
||||||
|
ContextClosureLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
if (unlikely (c->lookup_limit_exceeded ())) return;
|
if (unlikely (c->lookup_limit_exceeded ())) return;
|
||||||
|
if (!intersects (c->glyphs, lookup_context)) return;
|
||||||
|
|
||||||
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
||||||
(inputZ.as_array (inputCount ? inputCount - 1 : 0));
|
(inputZ.as_array (inputCount ? inputCount - 1 : 0));
|
||||||
|
@ -1520,14 +1522,13 @@ struct RuleSet
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c,
|
||||||
|
ContextClosureLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
if (unlikely (c->lookup_limit_exceeded ())) return;
|
if (unlikely (c->lookup_limit_exceeded ())) return;
|
||||||
|
|
||||||
return
|
|
||||||
+ hb_iter (rule)
|
+ hb_iter (rule)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const Rule &_) { _.closure_lookups (c); })
|
| hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); })
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1646,9 +1647,16 @@ struct ContextFormat1
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
+ hb_iter (ruleSet)
|
struct ContextClosureLookupContext lookup_context = {
|
||||||
|
{intersects_glyph},
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hb_zip (this+coverage, ruleSet)
|
||||||
|
| hb_filter (*c->glyphs, hb_first)
|
||||||
|
| hb_map (hb_second)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
|
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); })
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1707,7 @@ struct ContextFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -1790,10 +1798,24 @@ struct ContextFormat2
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
|
if (!(this+coverage).intersects (c->glyphs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ClassDef &class_def = this+classDef;
|
||||||
|
|
||||||
|
struct ContextClosureLookupContext lookup_context = {
|
||||||
|
{intersects_class},
|
||||||
|
&class_def
|
||||||
|
};
|
||||||
|
|
||||||
+ hb_iter (ruleSet)
|
+ hb_iter (ruleSet)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
|
| hb_enumerate
|
||||||
;
|
| hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
|
||||||
|
{ return class_def.intersects_class (c->glyphs, p.first); })
|
||||||
|
| hb_map (hb_second)
|
||||||
|
| hb_apply ([&] (const RuleSet & _)
|
||||||
|
{ _.closure_lookups (c, lookup_context); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||||
|
@ -1944,6 +1966,8 @@ struct ContextFormat3
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
|
if (!intersects (c->glyphs))
|
||||||
|
return;
|
||||||
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
|
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
|
||||||
recurse_lookups (c, lookupCount, lookupRecord);
|
recurse_lookups (c, lookupCount, lookupRecord);
|
||||||
}
|
}
|
||||||
|
@ -2237,9 +2261,11 @@ struct ChainRule
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c,
|
||||||
|
ChainContextClosureLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
if (unlikely (c->lookup_limit_exceeded ())) return;
|
if (unlikely (c->lookup_limit_exceeded ())) return;
|
||||||
|
if (!intersects (c->glyphs, lookup_context)) return;
|
||||||
|
|
||||||
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
|
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
|
||||||
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
|
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
|
||||||
|
@ -2357,7 +2383,7 @@ struct ChainRule
|
||||||
|
|
||||||
if (!backtrack_map)
|
if (!backtrack_map)
|
||||||
{
|
{
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
if (!hb_all (backtrack, glyphset) ||
|
if (!hb_all (backtrack, glyphset) ||
|
||||||
!hb_all (input, glyphset) ||
|
!hb_all (input, glyphset) ||
|
||||||
!hb_all (lookahead, glyphset))
|
!hb_all (lookahead, glyphset))
|
||||||
|
@ -2430,14 +2456,14 @@ struct ChainRuleSet
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c,
|
||||||
|
ChainContextClosureLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
if (unlikely (c->lookup_limit_exceeded ())) return;
|
if (unlikely (c->lookup_limit_exceeded ())) return;
|
||||||
|
|
||||||
return
|
|
||||||
+ hb_iter (rule)
|
+ hb_iter (rule)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); })
|
| hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); })
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2558,9 +2584,16 @@ struct ChainContextFormat1
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
+ hb_iter (ruleSet)
|
struct ChainContextClosureLookupContext lookup_context = {
|
||||||
|
{intersects_glyph},
|
||||||
|
{nullptr, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hb_zip (this+coverage, ruleSet)
|
||||||
|
| hb_filter (*c->glyphs, hb_first)
|
||||||
|
| hb_map (hb_second)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
|
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); })
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2610,7 +2643,7 @@ struct ChainContextFormat1
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -2707,9 +2740,28 @@ struct ChainContextFormat2
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
|
if (!(this+coverage).intersects (c->glyphs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ClassDef &backtrack_class_def = this+backtrackClassDef;
|
||||||
|
const ClassDef &input_class_def = this+inputClassDef;
|
||||||
|
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
|
||||||
|
|
||||||
|
struct ChainContextClosureLookupContext lookup_context = {
|
||||||
|
{intersects_class},
|
||||||
|
{&backtrack_class_def,
|
||||||
|
&input_class_def,
|
||||||
|
&lookahead_class_def}
|
||||||
|
};
|
||||||
|
|
||||||
+ hb_iter (ruleSet)
|
+ hb_iter (ruleSet)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
|
| hb_enumerate
|
||||||
|
| hb_filter([&] (unsigned gid)
|
||||||
|
{ return input_class_def.intersects_class (c->glyphs, gid); }, hb_first)
|
||||||
|
| hb_map (hb_second)
|
||||||
|
| hb_apply ([&] (const ChainRuleSet &_)
|
||||||
|
{ _.closure_lookups (c, lookup_context); })
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2800,9 +2852,10 @@ struct ChainContextFormat2
|
||||||
if (unlikely (!c->serializer->check_success (!lookahead_klass_map.in_error ())))
|
if (unlikely (!c->serializer->check_success (!lookahead_klass_map.in_error ())))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
unsigned non_zero_index = 0, index = 0;
|
int non_zero_index = -1, index = 0;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||||
|
auto last_non_zero = c->serializer->snapshot ();
|
||||||
for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
|
for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
|
||||||
| hb_filter (input_klass_map, hb_first)
|
| hb_filter (input_klass_map, hb_first)
|
||||||
| hb_map (hb_second))
|
| hb_map (hb_second))
|
||||||
|
@ -2818,19 +2871,20 @@ struct ChainContextFormat2
|
||||||
&backtrack_klass_map,
|
&backtrack_klass_map,
|
||||||
&input_klass_map,
|
&input_klass_map,
|
||||||
&lookahead_klass_map))
|
&lookahead_klass_map))
|
||||||
|
{
|
||||||
|
last_non_zero = c->serializer->snapshot ();
|
||||||
non_zero_index = index;
|
non_zero_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret) return_trace (ret);
|
if (!ret) return_trace (ret);
|
||||||
|
|
||||||
//prune empty trailing ruleSets
|
// prune empty trailing ruleSets
|
||||||
--index;
|
if (index > non_zero_index) {
|
||||||
while (index > non_zero_index)
|
c->serializer->revert (last_non_zero);
|
||||||
{
|
out->ruleSet.len = non_zero_index + 1;
|
||||||
out->ruleSet.pop ();
|
|
||||||
index--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (bool (out->ruleSet));
|
return_trace (bool (out->ruleSet));
|
||||||
|
@ -2914,6 +2968,9 @@ struct ChainContextFormat3
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const
|
void closure_lookups (hb_closure_lookups_context_t *c) const
|
||||||
{
|
{
|
||||||
|
if (!intersects (c->glyphs))
|
||||||
|
return;
|
||||||
|
|
||||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
|
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
|
||||||
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
|
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
|
||||||
|
@ -2992,13 +3049,16 @@ struct ChainContextFormat3
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
|
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
|
||||||
|
|
||||||
if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false);
|
if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
+ it
|
for (auto& offset : it) {
|
||||||
| hb_apply (subset_offset_array (c, *out, base))
|
auto *o = out->serialize_append (c->serializer);
|
||||||
;
|
if (unlikely (!o) || !o->serialize_subset (c, offset, base))
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
|
||||||
return_trace (out->len);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
@ -3326,20 +3386,31 @@ struct GSUBGPOS
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_features (const hb_map_t *lookup_indexes, /* IN */
|
void prune_features (const hb_map_t *lookup_indices, /* IN */
|
||||||
hb_set_t *feature_indexes /* OUT */) const
|
hb_set_t *feature_indices /* IN/OUT */) const
|
||||||
{
|
{
|
||||||
unsigned int feature_count = hb_min (get_feature_count (), (unsigned) HB_MAX_FEATURES);
|
#ifndef HB_NO_VAR
|
||||||
for (unsigned i = 0; i < feature_count; i++)
|
// This is the set of feature indices which have alternate versions defined
|
||||||
|
// if the FeatureVariation's table and the alternate version(s) intersect the
|
||||||
|
// set of lookup indices.
|
||||||
|
hb_set_t alternate_feature_indices;
|
||||||
|
if (version.to_int () >= 0x00010001u)
|
||||||
|
(this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
|
||||||
|
if (alternate_feature_indices.in_error()) {
|
||||||
|
feature_indices->successful = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (unsigned i : feature_indices->iter())
|
||||||
{
|
{
|
||||||
const Feature& f = get_feature (i);
|
const Feature& f = get_feature (i);
|
||||||
if ((!f.featureParams.is_null ()) || f.intersects_lookup_indexes (lookup_indexes))
|
|
||||||
feature_indexes->add (i);
|
if (f.featureParams.is_null ()
|
||||||
|
&& !f.intersects_lookup_indexes (lookup_indices)
|
||||||
|
&& !alternate_feature_indices.has (i))
|
||||||
|
feature_indices->del (i);
|
||||||
}
|
}
|
||||||
#ifndef HB_NO_VAR
|
|
||||||
if (version.to_int () >= 0x00010001u)
|
|
||||||
(this+featureVars).closure_features (lookup_indexes, feature_indexes);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_size () const
|
unsigned int get_size () const
|
||||||
|
|
|
@ -88,10 +88,17 @@ _gsub_closure_glyphs_lookups_features (hb_face_t *face,
|
||||||
&lookup_indices);
|
&lookup_indices);
|
||||||
_remap_indexes (&lookup_indices, gsub_lookups);
|
_remap_indexes (&lookup_indices, gsub_lookups);
|
||||||
|
|
||||||
//closure features
|
// Collect and prune features
|
||||||
hb_set_t feature_indices;
|
hb_set_t feature_indices;
|
||||||
gsub->closure_features (gsub_lookups, &feature_indices);
|
hb_ot_layout_collect_features (face,
|
||||||
|
HB_OT_TAG_GSUB,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&feature_indices);
|
||||||
|
gsub->prune_features (gsub_lookups, &feature_indices);
|
||||||
_remap_indexes (&feature_indices, gsub_features);
|
_remap_indexes (&feature_indices, gsub_features);
|
||||||
|
|
||||||
gsub.destroy ();
|
gsub.destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,9 +121,15 @@ _gpos_closure_lookups_features (hb_face_t *face,
|
||||||
&lookup_indices);
|
&lookup_indices);
|
||||||
_remap_indexes (&lookup_indices, gpos_lookups);
|
_remap_indexes (&lookup_indices, gpos_lookups);
|
||||||
|
|
||||||
//closure features
|
// Collect and prune features
|
||||||
hb_set_t feature_indices;
|
hb_set_t feature_indices;
|
||||||
gpos->closure_features (gpos_lookups, &feature_indices);
|
hb_ot_layout_collect_features (face,
|
||||||
|
HB_OT_TAG_GPOS,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&feature_indices);
|
||||||
|
gpos->prune_features (gpos_lookups, &feature_indices);
|
||||||
_remap_indexes (&feature_indices, gpos_features);
|
_remap_indexes (&feature_indices, gpos_features);
|
||||||
gpos.destroy ();
|
gpos.destroy ();
|
||||||
}
|
}
|
||||||
|
@ -243,7 +256,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
if (close_over_gdef)
|
if (close_over_gdef)
|
||||||
_collect_layout_variation_indices (plan->source, plan->_glyphset, plan->gpos_lookups, plan->layout_variation_indices, plan->layout_variation_idx_map);
|
_collect_layout_variation_indices (plan->source,
|
||||||
|
plan->_glyphset_gsub,
|
||||||
|
plan->gpos_lookups,
|
||||||
|
plan->layout_variation_indices,
|
||||||
|
plan->layout_variation_idx_map);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HB_NO_SUBSET_CFF
|
#ifndef HB_NO_SUBSET_CFF
|
||||||
|
|
|
@ -18,6 +18,7 @@ TESTS = \
|
||||||
tests/layout.gpos4.tests \
|
tests/layout.gpos4.tests \
|
||||||
tests/layout.gpos6.tests \
|
tests/layout.gpos6.tests \
|
||||||
tests/layout.gpos8.tests \
|
tests/layout.gpos8.tests \
|
||||||
|
tests/layout.gpos8.amiri.tests \
|
||||||
tests/layout.gsub3.tests \
|
tests/layout.gsub3.tests \
|
||||||
tests/layout.gsub6.tests \
|
tests/layout.gsub6.tests \
|
||||||
tests/layout.tests \
|
tests/layout.tests \
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,2 +1,2 @@
|
||||||
--drop-tables-=GSUB,GPOS
|
--drop-tables-=GSUB,GPOS,GDEF
|
||||||
--retain-gids
|
--retain-gids
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
--drop-tables-=GSUB,GPOS
|
--drop-tables-=GSUB,GPOS,GDEF
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
FONTS:
|
||||||
|
Amiri-Regular.ttf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
keep-layout.txt
|
||||||
|
keep-layout-retain-gids.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
ال
|
||||||
|
الأحلام.
|
||||||
|
غير
|
||||||
|
سماء لا
|
||||||
|
الحب
|
|
@ -11,6 +11,7 @@ tests = [
|
||||||
'layout.gpos4',
|
'layout.gpos4',
|
||||||
'layout.gpos6',
|
'layout.gpos6',
|
||||||
'layout.gpos8',
|
'layout.gpos8',
|
||||||
|
'layout.gpos8.amiri',
|
||||||
'layout.gsub3',
|
'layout.gsub3',
|
||||||
'layout.gsub6',
|
'layout.gsub6',
|
||||||
'layout.gdef',
|
'layout.gdef',
|
||||||
|
|
Loading…
Reference in New Issue