From 1f0a9d9be979de01527c05f4dbe6fbc62799597c Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Tue, 17 Sep 2019 11:10:08 -0700 Subject: [PATCH] [subset] GPOS Lookup Type 2: PairPos --- src/hb-ot-layout-gpos-table.hh | 131 +++++++++++++++++- test/subset/data/Makefile.am | 1 + test/subset/data/Makefile.sources | 1 + ...font7.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1764 bytes ..._1_font7.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1632 bytes ...ayout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3688 bytes .../gpos2_1_font7.keep-layout.21,23,25.otf | Bin 0 -> 1428 bytes .../gpos2_1_font7.keep-layout.21,23.otf | Bin 0 -> 1308 bytes ...font7.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3688 bytes ...font5.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1776 bytes ..._2_font5.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1644 bytes ...ayout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3684 bytes .../gpos2_2_font5.keep-layout.21,23,25.otf | Bin 0 -> 1440 bytes .../gpos2_2_font5.keep-layout.21,23.otf | Bin 0 -> 1320 bytes ...font5.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3684 bytes test/subset/data/fonts/gpos2_1_font7.otf | Bin 0 -> 4584 bytes test/subset/data/fonts/gpos2_2_font5.otf | Bin 0 -> 4580 bytes test/subset/data/tests/layout.gpos2.tests | 12 ++ 18 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.21,23,25.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.21,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.retain-all-codepoint.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23,25.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.retain-all-codepoint.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23,25.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.retain-all-codepoint.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23,25.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.retain-all-codepoint.otf create mode 100644 test/subset/data/fonts/gpos2_1_font7.otf create mode 100644 test/subset/data/fonts/gpos2_2_font5.otf create mode 100644 test/subset/data/tests/layout.gpos2.tests diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 2b535af2f..e129ae418 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -558,7 +558,7 @@ struct SinglePosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -647,7 +647,7 @@ struct SinglePosFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; unsigned sub_length = valueFormat.get_len (); @@ -761,6 +761,18 @@ struct PairValueRecord { friend struct PairSet; + bool serialize (hb_serialize_context_t *c, + unsigned size, + const hb_map_t &glyph_map) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (*this); + if (unlikely (!c->extend_min (out))) return_trace (false); + + out->secondGlyph = glyph_map[secondGlyph]; + return_trace (c->copy (values, size)); + } + protected: HBGlyphID secondGlyph; /* GlyphID of second glyph in the * pair--first glyph is listed in the @@ -846,6 +858,37 @@ struct PairSet return_trace (false); } + bool subset (hb_subset_context_t *c, + const ValueFormat valueFormats[2]) const + { + TRACE_SUBSET (this); + auto snap = c->serializer->snapshot (); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->len = 0; + + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + unsigned len1 = valueFormats[0].get_size (); + unsigned len2 = valueFormats[1].get_size (); + unsigned record_size = HBUINT16::static_size + len1 + len2; + + const PairValueRecord *record = &firstPairValueRecord; + unsigned count = len, num = 0; + for (unsigned i = 0; i < count; i++) + { + if (!glyphset.has (record->secondGlyph)) continue; + if (record->serialize (c->serializer, record_size, glyph_map)) num++; + record = &StructAtOffset (record, record_size); + } + + out->len = num; + if (!num) c->serializer->revert (snap); + return_trace (num); + } + struct sanitize_closure_t { const void *base; @@ -919,8 +962,43 @@ struct PairPosFormat1 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; + out->valueFormat[0] = valueFormat[0]; + out->valueFormat[1] = valueFormat[1]; + + hb_sorted_vector_t new_coverage; + + + hb_zip (this+coverage, pairSet) + | hb_filter (glyphset, hb_first) + | hb_filter ([this, c, out] (const OffsetTo& _) + { + auto *o = out->pairSet.serialize_append (c->serializer); + if (unlikely (!o)) return false; + auto snap = c->serializer->snapshot (); + bool ret = o->serialize_subset (c, _, this, out, valueFormat); + if (!ret) + { + out->pairSet.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 @@ -1011,8 +1089,49 @@ struct PairPosFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + out->valueFormat1 = valueFormat1; + out->valueFormat2 = valueFormat2; + + hb_map_t klass1_map; + out->classDef1.serialize_subset (c, classDef1, this, out, &klass1_map); + out->class1Count = klass1_map.get_population (); + + hb_map_t klass2_map; + out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map); + out->class2Count = klass2_map.get_population (); + + unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len (); + + + hb_range ((unsigned) class1Count) + | hb_filter (klass1_map) + | hb_apply ([&] (const unsigned class1_idx) + { + + hb_range ((unsigned) class2Count) + | hb_filter (klass2_map) + | hb_apply ([&] (const unsigned class2_idx) + { + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len; + for (unsigned i = 0; i < record_len; i++) + c->serializer->copy (values[idx+i]); + }) + ; + }) + ; + + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto it = + + hb_iter (this+coverage) + | hb_filter (glyphset) + | hb_map_retains_sorting (glyph_map) + ; + + out->coverage.serialize (c->serializer, out).serialize (c->serializer, it); + return_trace (out->class1Count && out->class2Count && bool (it)); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index b50029f5e..4508fcde8 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.gpos2 \ expected/layout.gpos3 \ expected/layout.gsub6 \ expected/cmap14 \ diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index ccc0cdce5..5b93f27df 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.gpos2.tests \ tests/layout.gpos3.tests \ tests/layout.gsub6.tests \ tests/cmap14.tests \ diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.21,23,25.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.21,23,25.otf new file mode 100644 index 0000000000000000000000000000000000000000..49039feeb61b24f4061b8261e1bf6c70507672d1 GIT binary patch literal 1764 zcmc&#eNa?Y6hCjjc>4hevZ$c&_*jyW(S2`$1v6y>F-yZiZ73UbgY~Y+vg_`mz_^Yn zvh0^`q==va`O)U2JlbISrC3!<&IX6+)bd1!qP zfK-KiQ-j551GlIHc?5Zz*<@_|xbWh;0Fv3rOU-DQF)a%r{}Fk<+2U-QWs{5`UxU2Q zVr;WPfdF9$Mb=`pm}D(k`8Z!Qa<9$ma7Nz%4qZ0n3;@O!08k(i0Yy==##W1^T|kQ? z$q=caA_h^!AdbwI@F^;B)(JS^^To9)VIIKg>BK=^cJK1t71Ho%@12Y@lzF*)hk!k)UL1FP;YD`?++7}a70InNeL+>dQwKp z39BV6OIVJuI>HtcwuG>ygw+$ajIiZ|(-IEHaD>wlu9$EogexVSo^WM^Dwhx zc`@8{Wt686?%40>Zr#PF)tPzKK9hHK*S1qFgH6_frVr}A^IZ;12ERY?$=7sf*f-jH z?)ddh=Zzn&{)*Sxm%Y8?{D+tJefjH=-@0ylM|ync%)LD2=S4vtI%u!o=ksUShw8T- zGtrR+4@%U^Um|zZ*N$A>`GtobeA6Eo%yu-jnOaSyeBn~Qu#Gny*nHl7_|)-m`L|)s zWH|TKSZMsx@QJrv?``$a`(A!&?}p5(z%%{JI~rUAb!T6vBc%@(sg;p#pIV8R4KG4!P|t;hYy z$1tbym~~M4WNe3zCs_a@`4|-hDX6GvY8vhV7wZ8rA^?#>CYDK+B9R1#3HAA_8LFOM z4i%6Cn)n)mo?1plqfud1WCr|%CWGg(R+L1J<1>)Qu?Uio#j*G?yW}w}g*2G|XN)Xn zCtw3BIPiVk2rSBGWG&zXJ=B5;2(&^o7{LxNAhToKmYAP~g`kb)A`)gpl!mg~CiI$cvWYI`9Y1fN} zDf@0$0!Rzh)~p&+ERFP`#b~6YMH8d3iBdxdzpN&jXoF?x#o*js+Y)2qPv_>GnQvy! znK^UrnVLO&YCs7`K@3b~bv5%t$SDSZ%K)MW+jiCLUbuhP3?NgZuC`|PlU(cA-T;7P z6mdhN*=Pk5nF5fy5H~fOj7=YJ`RqLa@g>9s&8S$nD0>_I4KI-7XYi42P`EXg0~(QgrCQg4koV*d42H0f+nlf|vn7U$hdCh=33xYic)}y9B8u zq=C>@5-Jmg%EY1d5zdS+I3E}K_a@^pD+_4XY#wR`Jct~UnXr!3{Df#%VCT0jeF5iO>y zp0X@uIm#L+n@8Dv$`(+zkg`RTEvB5Fa=3=0oPlzAl*^}F0p$uQS46pDYS2>yOAWZC zfg19tA-~dM?Xn%9%?>83aSOxg^&C^tWO>EJ?C!EVOlCW?y{*w=vs!FMhp8!-sc3Cw zY6W*YQ){xDY#peKlmqMGOa~p7CrYkRs?^ajnsu>p@d?_*C)RIBO5V6BC6!4_&(LLV z&dy=emFdcu{~|`opcA7^Q^weW%b7vm8CrW3-mb}k;oc$F|rQi<+vXjVJ?`f&g0Q=gA4?eGnh_76WZ=vjvoo*WFP+d| z=cA748|7B}+5O}F@=(sotX6e-IZ^Aw*q)?be{Y~K{coSHGS9z3-mqQor{~^AJybyePoKVY$cW_4<-*WAz8mn&hGEKl8P!kjtx8 z;VU4K;hyTq+ovi01Bi4EHE<;J(ouomdH2gWNL)QB;Y1S%#UK*2_=4t0PDJ|u=7%|i zIi5o?jk(N((Rt}p;ghXRP6r~zGzowd)MSw?!UN#K98g9HJCsr;mPu72kp!0sb$LV; zRnI&N<&Xv$kr=|fP)1f)SB0pED)19X1}|WZh(v+wlMqK_5yT*h$l^76$r@P-36S-- zk1VXGU27RP=>ZQy`Hs09;HXoprXf(>3oWJA9LVLJ=CpbzIF5_Ur=0l5-+ zDM&DakfQ|kBH=Vb{*Ug-sNUPD& p26Bvygi!?xahU85)IIzMCE-W}H3Zb*3<<;`Cm5Yzu0hm literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.retain-all-codepoint.otf new file mode 100644 index 0000000000000000000000000000000000000000..8f18b89c6eafb66b9c388bcff406a362b5caa48d GIT binary patch literal 3688 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 P_lF{4mHm)-@AZEHrNU~d literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23,25.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23,25.otf new file mode 100644 index 0000000000000000000000000000000000000000..47fea1ac694d2ae6e27847b48d557d969ec17f57 GIT binary patch literal 1428 zcmZuxdrX^E6hHUtgO9f3C0z_Ce86f(BpWLmbCYb~81scJfChD8)bdfr=wodek5HWB z(f6nbjK_wc^_B5h9H5RxqmaR7jK;;u5`x4(T>L|$1Zml~rJk>ah{k(z9=~(WJ@?$3 zdv8H;aREr+3I@(} ziY5#ri*+h3E7m1!!+MV(b{O;~bKq@I;`$6?WXu%;5D-#82oaapXtnjcwcj5J{siJr zr2L5j|HDEqS|&&sgm$MhBxPZb0*tO~8REqEuCE;t`LZGxe8*yZ+0h^(L>MN?FVtjY zXfpO_GWH(Q8|sZGG?iv%yE>Iorl%{JoO1nZEK^i(GP7C}^NdcdHyZRtm6Rqm3NL5%`f_`|@^al? zv2VZ$YzcKosSokH$lJt^Hw&am*!EJ@l#0I5&;i2HUKo3bIW>SCGKQHfj zv!|oC{mXve^RCYQt|nWP&2qMsi?XPiX}jI!h_{Dn8$Ie#>ulQ%>(#QwY!0}%eYM#Q zkNu*u)HJu$cb#_I-FBC~>y2((mz#FG9j^HPmOi9m%dlm%Wx0Og*Qq<7FFyC%fibJg z=C-;obo6)jou8jOxtet){VErBHeF2{OcyK0I%t2|{du``d~K`Tg=;(FTHGz3wuHXC z+~m2^?_c&+%}#N2XYDzYt)_{KEve*Wt*j%z?bL{Fs7l{o^>N8<=XLj@=f}Zo-_hPN z=T!H^z^$@L)u;L2av8>h@6}FzGTr*kAH9FJEjuoEI43H*IpX3d4+jmj!{v0k;*7(k zr!KOz|M3TVLA?dv(>pkD(9(1Quz^KsaP zT!BajX4ngbz=8&9pc+(QgqIK*G4Dh$z6*9hdaxIYuZC7EY6kmjJ}OKAq;j(&_h6mjQ<$KAcu$wJb~-L-}{-Fm;e9( literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.21,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..99e813fc5dd0909daf51047ec70670bc2e1dbe49 GIT binary patch literal 1308 zcmZuxdu&rx82`?_x9we9wlP;?MyPjV7>Em&P84y4cIxP-S>C{)E{R-lc+vWA;-UTD({}8bNfW9mM0geGeh|<>SaCB2`bG8Vwt4LPQ zWc6(JQBGQ}W%cLaWH_APwW?JBlj&s>lJeg5#chhrrlMrVT#~6-4jdtzYP+eey1K1; z<5riu+q1vT?i1Ep*9k_0!6?+(T(65lQ@7VAI=sTmPOHn~c6ls5(Y9Ww>*x^7)ZHtX zMX%^Nh-AJeY|2l7#U3@q73vCgp`aG%R<17e#244ZC4W3qKl)W%8i^}2Q}O%P;&yDs?%uy`9VN**JXce3-k(YHqjPo4a7JhL-0 zv^mln=neGrwMfN1mScP{7zwQmsvJjR)=B@3fv^2nTNi32kjkFzsy+Pp&z7FfWBuL3 z2cyAgFcKVoYa}on<)hJ1WaW7O7|ujbqGz)IZg=vRncJT)?D+MCDSspo^+!(+jt`B! zGe7snpEVZ^S0z=S!OFY6XZB4E^4Y5U^E%C?#TB{;)((~RNBd&~`mu)kin*5WU(2-L zn34FQt`pusXRlP+Y?rjh#n7&S10Ojj+Fj%AA2?U2z}?V=!SJ+wL?RK1iAivn4@JV^NSP_KY%Ebls>ZN!ci)3zyD1MtjL|P$Wqe zoix5+7Ku5^z=YyCIiu{ev=LwmW=RYbpe1RNhI?R?C7_NPej#clt5j$hhQkQj&x27{ z|Kdwf3+1pnUxV(cEhLxA(W;2*aMGcKSFkt26<~ZB;=Im4A)>s_KE!hm=?W-?wM#xq znQsF(xWJ3w+FsazYab#f_~02Zg9vTV2_0Yo54?)VgMRyE`vzDK2Dul8W<#wMr5a@o za9Dx%$RW?r)6o9&GMCEz^x(`|WI^_&lHPRr(xUlRFD;s19=X%>fABwpdaFSX_;flf oJ}2;483$IS7UC1VKIHy+_MBXaAVWYacSxWFWqvZbO;`v12BQ^bz5oCK literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.retain-all-codepoint.otf new file mode 100644 index 0000000000000000000000000000000000000000..8f18b89c6eafb66b9c388bcff406a362b5caa48d GIT binary patch literal 3688 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 P_lF{4mHm)-@AZEHrNU~d literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23,25.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23,25.otf new file mode 100644 index 0000000000000000000000000000000000000000..b34a49fa011689689137f23264e67276a469fb7f GIT binary patch literal 1776 zcmc&#dr(wW82|3RxcdM^Swv8{JeFi+bnjhQ#7x;l%+hdB8_EXVU_FQ|yY4Q^GOlBa zEc?=p6cN;*wq{ZkCm)qGH63Iz&(4|e@%tX< zeCM2d&aGOrrV3QB6QsZ_sjOuBDBl zDAkF{Dbvzs%*@W!&7L!tEiPT~MER1+yPl`6F+F)4XU%G7D8+O+BEGcqz~&dSPW za&q(Xbp>;ZSgtfrm8VMjug0ht3}RF{BF|MNIU=`p5#Ae#R`h%l;kzS>=uqVDg~*l2 z(~*RK`sjx~<#E+@^>K~ndRUW)C!-um6}fh7ns~I(LuFGg%6%htRonAQPuHP+ANNI9 z1otlp?&#dn>Dg7wPw|*{(>`C&pXp1mZV%U;^j_+?>^;9>yqpIv7d&oeK`KiFN=n}!OoC3bhxW; zfA7JoqnmFnJgq;^C+yPK(RSyNjYC~@tmy7lt@_OEG;I*)_Gh$*+QS`Ly_FTYqqSc@ zA8oue%+vd~?R9px?BG*t8hFhfi+^RumJ`hbjkdnVcWS;3Tnvqezw7_tD>^b1816oM z^vZ^F=J!^9$r~Jt-`sZY-3xoZ`0dc|9XI`_x&mh#x_K(dOTs*~(f(i{5X^84)^0gs zp<{FIm1xz!#%^gpJ9K&b=RSJi^{tZ}!o9UVLHqy3C5uQ@u;u>O6flXI`aa#(VR$>R4w$tH#TQmrSI) z$LyEZColX1D7o-1z;@lKor1jf)~BtIHn~^ENlqh_f<&<5%^jnP;@bbmAJp(SiR)30 zU`?ZxN)d=7zMUrbF-P71RkGGP~*0-nXaqGU?U&p;g4C6I(Du1g=W%O26?kP5T!$0$TQ z0Xx{hiSOfjkv1Y~1{ah-HCTW^3p9Zl9Pk_>2gYp@{VdD{y;zGx7!9>llq!@JAQL?_ z(Bf(4KpyCX72vuaXhPz{l?#6XfMSsgYY`$J629Y@7bhLcI0;eMCJzhm`oA<`bQNSl y5l~HLS2NZk>^5K>f`@WhoG!G*tH2+DSSck|oGwOWVXoxC*NC%F*mLd^j_@a((!hQI literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.21,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..2ad1d293d19c034e40e42b9129f0eff255039698 GIT binary patch literal 1644 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 literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..d10d3621bcfaaa01116c5ad599a9583ede331bae GIT binary patch literal 1320 zcmZuxeQZ-z6hHU9*Y>ULKG2nr5$f9j198FHIU_h_lQ|-aB^#Rghhuenw9J03?bu4_ z#4*-yD9bj-HjpLNm{2z&A0jg*%7poc(MX~rY3BS#qKS!;YC9gLp8Gm+G2WYd&iVb$ zIrp4<--l`MUK6O{2(TdRXlM}nde1Ziz(oM&>79E_O+RkE{R;p$hg^%P=~1IC`Ene9 zr7^8-cC!l_NGtm55w}}KbNk1eX9_Vljra*G5+!Nnn;8E%;tf{2w@1Y@n9Eio=I!Pl z7qENKgd{Gd!)zCo4*h!cUqKvpIX&LoJ7C29-$yI}U@QwjfMb9VqHOQ7+kMp9mMw3HSuh$5Mxn0V`MM}H`8;0H?h&4Mv^m`_r`zlm+qVdHHk;5$ z!#zTy=n>rqk<9mmO$7+B*rTSTLS3OQ64U|}QWB^i?;!z0;)~5?E{QAsvAR3GXViSYo zLt}5x&%N~0%N!4d)<6WN9`=RuaZj+TS1N6`O4?&$c=tf(2ad@O=Xl45&EG|?#}?w>pZ(+;J~17c8M$=k zX6t41mEB)URqpNYc3=MJ+Oe;GJN5g(o$&d=$R+EDM4}QCm*5Z|jz%KUGIz42^R&ok zANi|Vr^yB*It{)^cw6!^&ArySuejz9Ac_>F4{tnwgz8)GebED}bH_O&a{(a>3}pcn zDN;!%%`ccmVvaH}sd!4>QI1&_1ek(Z5(fonNt&eLE*NDEXrqN+h+4@i6&i-&FoX7U zf7I1K`yA9lIjqmupmK3L$>nmiDxx}^bSU8^?2T{*m|uoCZ!=JYC~vbXcy5KQfKu4B z9HW$Z3%I}u9{kq!$!k9%2Y8_x8bJgLbb$@b;D%QaxiRj5?0*clfI;qsp}V0~idv1j z1~{xhd*qO3=xJ#Gd7WF#{c!)xT4X_vrJCM!`SPOs;lDs$bboo|Cg}g*e+G?KgC6kd r*vwuB@K_lKR;3=|6+K?${(1JCT!|pVz#2J1kGYJ@(yR&OR!;aE+9+kd literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.retain-all-codepoint.otf new file mode 100644 index 0000000000000000000000000000000000000000..88e60461ce4a37fd398b4f2aa9f212408acd875e GIT binary patch literal 3684 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 Y`}xzKi-A`Zwf?%gie&n_n`! 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 J{~sCPzX641D|Y|@ literal 0 HcmV?d00001 diff --git a/test/subset/data/tests/layout.gpos2.tests b/test/subset/data/tests/layout.gpos2.tests new file mode 100644 index 000000000..94fe78a56 --- /dev/null +++ b/test/subset/data/tests/layout.gpos2.tests @@ -0,0 +1,12 @@ +FONTS: +gpos2_1_font7.otf +gpos2_2_font5.otf + +PROFILES: +keep-layout.txt +keep-layout-retain-gids.txt + +SUBSETS: +!# +!#% +*