From bc5ef765a874ecd9fc0634dccf0848d1ee839c9a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Aug 2019 14:51:28 -0700 Subject: [PATCH] [subset] Subset ligature substitutes! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test with: $ ./hb-subset -o out.ttf NotoSansArabic-Regular.ttf --drop-tables= سلام && ./hb-view out.ttf سلام --- src/hb-ot-layout-gsub-table.hh | 79 ++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 84e1b1578..b64bdd0f5 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -735,7 +735,7 @@ struct Ligature template bool serialize (hb_serialize_context_t *c, - GlyphID ligature, + hb_codepoint_t ligature, Iterator components /* Starting from second */) { TRACE_SERIALIZE (this); @@ -745,6 +745,25 @@ struct Ligature return_trace (true); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + if (!glyphset.has (ligGlyph) || !hb_all (component, glyphset)) return_trace (false); + + auto it = + + hb_iter (component) + | hb_map (glyph_map) + ; + + auto *out = c->serializer->start_embed (*this); + return out->serialize (c->serializer, + glyph_map[ligGlyph], + it); + } + public: bool sanitize (hb_sanitize_context_t *c) const { @@ -834,6 +853,31 @@ struct LigatureSet return_trace (true); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + + hb_iter (ligature) + | hb_filter ([this, c, out] (const OffsetTo& _) + { + auto *o = out->ligature.serialize_append (c->serializer); + if (unlikely (!o)) return false; + auto snap = c->serializer->snapshot (); + bool ret = o->serialize_subset (c, _, this, out); + if (!ret) + { + out->ligature.pop (); + c->serializer->revert (snap); + } + return ret; + }) + | hb_drain; + ; + return_trace (bool (out->ligature)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -932,8 +976,37 @@ struct LigatureSubstFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + + hb_sorted_vector_t new_coverage; + + hb_zip (this+coverage, ligatureSet) + | hb_filter (glyphset, hb_first) + | hb_filter ([this, c, out] (const OffsetTo& _) + { + auto *o = out->ligatureSet.serialize_append (c->serializer); + if (unlikely (!o)) return false; + auto snap = c->serializer->snapshot (); + bool ret = o->serialize_subset (c, _, this, out); + if (!ret) + { + out->ligatureSet.pop (); + c->serializer->revert (snap); + } + return ret; + }, + hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage); + ; + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } bool sanitize (hb_sanitize_context_t *c) const