From 219e739c9f21a16942162a53935f1dfbaf0414fa Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 20 Apr 2023 15:10:29 -0600 Subject: [PATCH] [beyond-64k/subset] Lower CompositeGlyph GID24's when possible --- src/OT/glyf/CompositeGlyph.hh | 20 +++++++++++++++++ src/OT/glyf/SubsetGlyph.hh | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/OT/glyf/CompositeGlyph.hh b/src/OT/glyf/CompositeGlyph.hh index ad9ce82fb..fe86e3591 100644 --- a/src/OT/glyf/CompositeGlyph.hh +++ b/src/OT/glyf/CompositeGlyph.hh @@ -246,6 +246,26 @@ struct CompositeGlyphRecord StructAfter (flags) = gid; } +#ifndef HB_NO_BEYOND_64K + void lower_gid_24_to_16 () + { + hb_codepoint_t gid = get_gid (); + if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu) + return; + + unsigned size = get_size (); + char *end = (char *) this + size; + char *p = &StructAfter (flags); + p += HBGlyphID24::static_size; + + flags = flags & ~GID_IS_24BIT; + set_gid (gid); + + memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p); + return; + } +#endif + protected: HBUINT16 flags; HBUINT24 pad; diff --git a/src/OT/glyf/SubsetGlyph.hh b/src/OT/glyf/SubsetGlyph.hh index b783567de..79c7f7dd2 100644 --- a/src/OT/glyf/SubsetGlyph.hh +++ b/src/OT/glyf/SubsetGlyph.hh @@ -54,6 +54,47 @@ struct SubsetGlyph const_cast (_).set_gid (new_gid); } +#ifndef HB_NO_BEYOND_64K + auto _ = Glyph (dest_glyph).get_composite_iterator (); + if (_) + { + /* lower GID24 to GID16 in components if possible. */ + char *p = _ ? (char *) &*_ : nullptr; + char *q = p; + const char *end = dest_glyph.arrayZ + dest_glyph.length; + while (_) + { + auto &rec = const_cast (*_); + ++_; + + q += rec.get_size (); + + rec.lower_gid_24_to_16 (); + + unsigned size = rec.get_size (); + + memmove (p, &rec, size); + + p += size; + } + memmove (p, q, end - q); + p += end - q; + + /* We want to shorten the glyph, but we can't do that without + * updating the length in the loca table, which is already + * written out :-(. So we just fill the rest of the glyph with + * harmless instructions, since that's what they will be + * interpreted as. */ + + memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p); + p += end - p; + dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ); + + // TODO: Padding; & trim serialized bytes. + // TODO: Update length in loca. Ugh. + } +#endif + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) Glyph (dest_glyph).drop_hints ();