From b0c3eb06b64dcfcfee09a25dde8250804484f77d Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Wed, 18 Sep 2019 16:11:44 -0700 Subject: [PATCH] [subset] GPOS Lookup Type 3: CursivePos --- src/hb-ot-layout-common.hh | 33 +++++++ src/hb-ot-layout-gpos-table.hh | 87 +++++++++++++++++- test/subset/data/Makefile.am | 1 + test/subset/data/Makefile.sources | 1 + ...s3_font3.keep-layout-retain-gids.28,29.otf | Bin 0 -> 1712 bytes ...s3_font3.keep-layout-retain-gids.28,2B.otf | Bin 0 -> 1860 bytes ...s3_font3.keep-layout-retain-gids.29,2B.otf | Bin 0 -> 1772 bytes ...ayout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3692 bytes .../gpos3_font3.keep-layout.28,29.otf | Bin 0 -> 1328 bytes .../gpos3_font3.keep-layout.28,2B.otf | Bin 0 -> 1456 bytes .../gpos3_font3.keep-layout.29,2B.otf | Bin 0 -> 1368 bytes ...font3.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3692 bytes test/subset/data/fonts/gpos3_font3.otf | Bin 0 -> 4624 bytes test/subset/data/tests/layout.gpos3.tests | 12 +++ 14 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.28,29.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.28,2B.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.29,2B.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.retain-all-codepoint.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.28,29.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.28,2B.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.29,2B.otf create mode 100644 test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.retain-all-codepoint.otf create mode 100644 test/subset/data/fonts/gpos3_font3.otf create mode 100644 test/subset/data/tests/layout.gpos3.tests diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 6d349e242..73c28caab 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2057,6 +2057,8 @@ struct HintingDevice hb_position_t get_y_delta (hb_font_t *font) const { return get_delta (font->y_ppem, font->y_scale); } + public: + unsigned int get_size () const { unsigned int f = deltaFormat; @@ -2070,6 +2072,12 @@ struct HintingDevice return_trace (c->check_struct (this) && c->check_range (this, this->get_size ())); } + HintingDevice* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + private: int get_delta (unsigned int ppem, int scale) const @@ -2131,6 +2139,12 @@ struct VariationDevice hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const { return font->em_scalef_y (get_delta (font, store)); } + VariationDevice* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2216,6 +2230,25 @@ struct Device } } + Device* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.b.format) { +#ifndef HB_NO_HINTING + case 1: + case 2: + case 3: + return_trace (reinterpret_cast (u.hinting.copy (c))); +#endif +#ifndef HB_NO_VAR + case 0x8000: + return_trace (reinterpret_cast (u.variation.copy (c))); +#endif + default: + return_trace (nullptr); + } + } + protected: union { DeviceHeader b; diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 7b9ccf4f9..73107f490 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -257,6 +257,12 @@ struct AnchorFormat1 TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } + + AnchorFormat1* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } protected: HBUINT16 format; /* Format identifier--format = 1 */ @@ -296,6 +302,12 @@ struct AnchorFormat2 return_trace (c->check_struct (this)); } + AnchorFormat2* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + protected: HBUINT16 format; /* Format identifier--format = 2 */ FWORD xCoordinate; /* Horizontal value--in design units */ @@ -326,6 +338,17 @@ struct AnchorFormat3 return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); } + AnchorFormat3* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + + out->xDeviceTable.serialize_copy (c, xDeviceTable, this, out); + out->yDeviceTable.serialize_copy (c, yDeviceTable, this, out); + return_trace (out); + } + protected: HBUINT16 format; /* Format identifier--format = 3 */ FWORD xCoordinate; /* Horizontal value--in design units */ @@ -368,6 +391,17 @@ struct Anchor } } + Anchor* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 1: return_trace (reinterpret_cast (u.format1.copy (c))); + case 2: return_trace (reinterpret_cast (u.format2.copy (c))); + case 3: return_trace (reinterpret_cast (u.format3.copy (c))); + default:return_trace (nullptr); + } + } + protected: union { HBUINT16 format; /* Format identifier */ @@ -1064,6 +1098,19 @@ struct EntryExitRecord return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); } + EntryExitRecord* copy (hb_serialize_context_t *c, + const void *src_base, + const void *dst_base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + + out->entryAnchor.serialize_copy (c, entryAnchor, src_base, dst_base); + out->exitAnchor.serialize_copy (c, exitAnchor, src_base, dst_base); + return_trace (out); + } + protected: OffsetTo entryAnchor; /* Offset to EntryAnchor table--from @@ -1191,11 +1238,47 @@ struct CursivePosFormat1 return_trace (true); } + template + void serialize (hb_serialize_context_t *c, + Iterator it, + const void *src_base) + { + if (unlikely (!c->extend_min ((*this)))) return; + this->format = 1; + this->entryExitRecord.len = it.len (); + + for (const EntryExitRecord& entry_record : + it + | hb_map (hb_second)) + c->copy (entry_record, src_base, this); + + auto glyphs = + + it + | hb_map_retains_sorting (hb_first) + ; + + coverage.serialize (c, this).serialize (c, glyphs); + } + 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 (!out)) return_trace (false); + + auto it = + + hb_zip (this+coverage, entryExitRecord) + | hb_filter (glyphset, hb_first) + | hb_map_retains_sorting ([&] (hb_pair_t p) -> hb_pair_t + { return hb_pair (glyph_map[p.first], p.second);}) + ; + + bool ret = bool (it); + out->serialize (c->serializer, it, this); + return_trace (ret); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index fb281e0a3..0b2745206 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -14,6 +14,7 @@ EXTRA_DIST += \ expected/cff-japanese \ expected/layout \ expected/layout.gpos \ + expected/layout.gpos3 \ expected/cmap14 \ fonts \ profiles \ diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index 0b2f1a14d..c6a3042c9 100644 --- a/test/subset/data/Makefile.sources +++ b/test/subset/data/Makefile.sources @@ -6,6 +6,7 @@ TESTS = \ tests/cff-japanese.tests \ tests/layout.tests \ tests/layout.gpos.tests \ + tests/layout.gpos3.tests \ tests/cmap14.tests \ $(NULL) diff --git a/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.28,29.otf b/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout-retain-gids.28,29.otf new file mode 100644 index 0000000000000000000000000000000000000000..17aa6d8332275e2861ce1e4f8795d56ff45e070c GIT binary patch literal 1712 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 E12@KXwEzGB literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.28,2B.otf b/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.28,2B.otf new file mode 100644 index 0000000000000000000000000000000000000000..2a8114ad6c552edbe2993802101ce50084994975 GIT binary patch literal 1456 zcmZuxeN0nV6hHU%>(N%gNtqi1-%uAeQCT6&25bXAFmualz z0J8fOS6GZTFc24j{CmWvYO~RFC9~@ej<+Iyts05MW#w_iUnAa9ZE+q|vCPMarx3Fi z<53&PXlfY6uB;PGiDpvhYT^v|cMqI|qTz&Y0G!QUNY5uRAX(AAh^DPa(dZuqYNkBj&FMIU#b@ zenVAGR#i^+ZmX@qez>aI$z@c$%;~eT^jx9I`l*>KX>d5r76$goCD;%4<`b$q&-qv}Ose9b^9;iyKidX-2f#rEcvy+)Ug|QdH{}H$+bZ+Q>#SLdM0dE8BI2 z<4bja6kU*fOel%>k*?6Vqp-&un@I$cg3_lbQ1V6Sx zKFAN?jOJBIr}-^BuM74Bdj|v4!{U2FU#`&NZSgj@ACeNAjU6n{3%(RyWohcJxahfc zV$O55{9b_s((`Y8R&ea4UyaT69j=D{BYxh`3w(dufVbbz`u#p3W!N=@ZM1o``J(Gl z!{YDP7H-^o_u*S(9>MGP_)qr^_YIwzpRM^jea8qCcebq*zFp0-8G5H!+-YkWqg^hJYbye@=pp=er#+{Pp8nmY4W6d z+UR9@ua8d&h$&w2xlhCme3uvNbN6%v+I_6s?e%yz@jfc7bZj+K*EiTR*cTlBeEi1g z^Ve=)pSwQyMYFC*xhZF4P^=We*sY}A_GlZ z$6Kjg_;N50k|SMmJu`t&1`K8KMl6y{+UVT486;*Y1LqZa(TvfUHAR4ln<3qx04-T2 z%kUWVQ48p!hc{iVlqnS&hLPh8TF(*QR(%U2wiO^LM6=I{Jg!i#F zB9FuQ$%tb<1M!GrzU(Pp{*pX^tQEahWDPnr6( z(|p_3I?W%I$Z7g6{g2RSHKYN4nOdW>4p>|n1y`jb#A$Xok&9);hYa)KTZRn5vtn@n XFW^`@BFfTkf&tXC_|*t}2dn=8C8x57 literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.29,2B.otf b/test/subset/data/expected/layout.gpos3/gpos3_font3.keep-layout.29,2B.otf new file mode 100644 index 0000000000000000000000000000000000000000..1426d50af5c31725db2d1b4570c7740fe9659bbe GIT binary patch literal 1368 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 literal 0 HcmV?d00001 diff --git a/test/subset/data/tests/layout.gpos3.tests b/test/subset/data/tests/layout.gpos3.tests new file mode 100644 index 000000000..409272f3d --- /dev/null +++ b/test/subset/data/tests/layout.gpos3.tests @@ -0,0 +1,12 @@ +FONTS: +gpos3_font3.otf + +PROFILES: +keep-layout.txt +keep-layout-retain-gids.txt + +SUBSETS: +() +(+ +)+ +*