[subset] support subsetting GSUB8

This commit is contained in:
Qunxin Liu 2021-03-18 17:41:25 -07:00 committed by Behdad Esfahbod
parent d18915f920
commit 95230e291d
24 changed files with 91 additions and 2 deletions

View File

@ -1274,11 +1274,80 @@ struct ReverseChainSingleSubstFormat1
return_trace (false); return_trace (false);
} }
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
{
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
return_trace (false);
for (auto& offset : it) {
auto *o = out->serialize_append (c->serializer);
if (unlikely (!o) || !o->serialize_subset (c, offset, this))
return_trace (false);
}
return_trace (true);
}
template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
hb_requires (hb_is_iterator (BacktrackIterator)),
hb_requires (hb_is_iterator (LookaheadIterator))>
bool serialize (hb_subset_context_t *c,
Iterator coverage_subst_iter,
BacktrackIterator backtrack_iter,
LookaheadIterator lookahead_iter) const
{
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed (this);
if (unlikely (!c->serializer->check_success (out))) return_trace (false);
if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
auto *substitute_out = c->serializer->start_embed<ArrayOf<HBGlyphID>> ();
auto substitutes =
+ coverage_subst_iter
| hb_map (hb_second)
;
auto glyphs =
+ coverage_subst_iter
| hb_map_retains_sorting (hb_first)
;
if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
return_trace (false);
if (unlikely (!out->coverage.serialize (c->serializer, out).serialize (c->serializer, glyphs)))
return_trace (false);
return_trace (true);
}
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
// TODO(subset) const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
return_trace (false); const hb_map_t &glyph_map = *c->plan->glyph_map;
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
auto it =
+ hb_zip (this+coverage, substitute)
| hb_filter (glyphset, hb_first)
| hb_filter (glyphset, hb_second)
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
;
return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
} }
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const

View File

@ -25,6 +25,7 @@ EXTRA_DIST += \
expected/layout.gsub3 \ expected/layout.gsub3 \
expected/layout.gsub5 \ expected/layout.gsub5 \
expected/layout.gsub6 \ expected/layout.gsub6 \
expected/layout.gsub8 \
expected/layout.gdef \ expected/layout.gdef \
expected/layout.context \ expected/layout.context \
expected/layout.gdef-varstore \ expected/layout.gdef-varstore \

View File

@ -24,6 +24,7 @@ TESTS = \
tests/layout.gsub3.tests \ tests/layout.gsub3.tests \
tests/layout.gsub5.tests \ tests/layout.gsub5.tests \
tests/layout.gsub6.tests \ tests/layout.gsub6.tests \
tests/layout.gsub8.tests \
tests/layout.tests \ tests/layout.tests \
tests/sbix.tests \ tests/sbix.tests \
$(NULL) $(NULL)

Binary file not shown.

View File

@ -0,0 +1,17 @@
FONTS:
gsub8_manually_created.otf
PROFILES:
keep-layout.txt
keep-layout-retain-gids.txt
SUBSETS:
a
A
ABC
ABCDEF
ABCDEFG
ABCDEFGHI
ABCDEFM
ABCDEFQ
*

View File

@ -17,6 +17,7 @@ tests = [
'layout.gsub3', 'layout.gsub3',
'layout.gsub5', 'layout.gsub5',
'layout.gsub6', 'layout.gsub6',
'layout.gsub8',
'layout.gdef', 'layout.gdef',
'layout.context', 'layout.context',
'layout.gdef-varstore', 'layout.gdef-varstore',