From 190b7a98f8af54cc42d3ccdb6979e432dfd41aa9 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 8 Oct 2020 14:44:54 -0700 Subject: [PATCH] [subset] Update PairPosFormat2 subsetting to match fontTools updated subsetting (https://github.com/fonttools/fonttools/pull/2221) - subset class def 1 against the coverage table. - Don't re-use class 0 in class def 2. - Ignore class 0 glyphs for the purposes of determing format 1 vs format 2 encoding for ClassDef. Add an additional test case which demonstrates these issues. --- src/hb-ot-layout-common.hh | 43 +++++++++++------- src/hb-ot-layout-gpos-table.hh | 14 ++++-- ...VFPrototype.keep-gdef-gpos.41,42,43,57.otf | Bin 5444 -> 5400 bytes ...obeVFPrototype.keep-gdef-gpos.41,42,43.otf | Bin 4916 -> 4872 bytes .../AdobeVFPrototype.keep-gdef-gpos.41,42.otf | Bin 4436 -> 4392 bytes ...obeVFPrototype.keep-gdef-gpos.41,56,57.otf | Bin 4556 -> 4540 bytes .../AdobeVFPrototype.keep-gdef-gpos.41.otf | Bin 3692 -> 3688 bytes .../AdobeVFPrototype.keep-gdef-gpos.42,57.otf | Bin 4556 -> 4524 bytes ..._1_font7.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 1944 bytes .../gpos2_1_font7.keep-layout.2E,23.otf | Bin 0 -> 1508 bytes ...font5.keep-layout-retain-gids.21,23,25.otf | Bin 1776 -> 1824 bytes ..._2_font5.keep-layout-retain-gids.21,23.otf | Bin 1644 -> 1692 bytes ..._2_font5.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 2024 bytes ...font5.keep-layout-retain-gids.41,42,43.otf | Bin 1988 -> 1988 bytes ...ayout-retain-gids.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes .../gpos2_2_font5.keep-layout.21,23,25.otf | Bin 1440 -> 1488 bytes .../gpos2_2_font5.keep-layout.21,23.otf | Bin 1320 -> 1368 bytes .../gpos2_2_font5.keep-layout.2E,23.otf | Bin 0 -> 1588 bytes .../gpos2_2_font5.keep-layout.41,42,43.otf | Bin 1288 -> 1288 bytes ...font5.keep-layout.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes test/subset/data/fonts/gpos2_2_font5.otf | Bin 4580 -> 4632 bytes test/subset/data/tests/layout.gpos2.tests | 1 + 22 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.2E,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.2E,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.2E,23.otf create mode 100644 test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.2E,23.otf diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 0ba7e3c06..a0ea8c164 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -92,6 +92,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_map_t &gid_klass_map, hb_sorted_vector_t &glyphs, const hb_set_t &klasses, + bool use_class_zero, hb_map_t *klass_map /*INOUT*/); struct hb_subset_layout_context_t : @@ -1649,6 +1650,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_map_t &gid_klass_map, hb_sorted_vector_t &glyphs, const hb_set_t &klasses, + bool use_class_zero, hb_map_t *klass_map /*INOUT*/) { if (!klass_map) @@ -1660,7 +1662,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, /* any glyph not assigned a class value falls into Class zero (0), * if any glyph assigned to class 0, remapping must start with 0->0*/ - if (glyphset.get_population () > gid_klass_map.get_population ()) + if (!use_class_zero || glyphset.get_population () > gid_klass_map.get_population ()) klass_map->set (0, 0); unsigned idx = klass_map->has (0) ? 1 : 0; @@ -1730,10 +1732,12 @@ struct ClassDefFormat1 } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool use_class_zero = true, + const hb_set_t* glyph_filter = nullptr) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t *glyphset = glyph_filter ? glyph_filter : c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; hb_sorted_vector_t glyphs; @@ -1753,8 +1757,8 @@ struct ClassDefFormat1 orig_klasses.add (klass); } - ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, - glyphs, orig_klasses, klass_map); + ClassDef_remap_and_serialize (c->serializer, *glyphset, gid_org_klass_map, + glyphs, orig_klasses, use_class_zero, klass_map); return_trace ((bool) glyphs); } @@ -1903,10 +1907,12 @@ struct ClassDefFormat2 } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool use_class_zero = true, + const hb_set_t* glyph_filter = nullptr) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t *glyphset = glyph_filter != nullptr ? glyph_filter : c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; hb_sorted_vector_t glyphs; @@ -1922,15 +1928,15 @@ struct ClassDefFormat2 hb_codepoint_t end = rangeRecord[i].last + 1; for (hb_codepoint_t g = start; g < end; g++) { - if (!glyphset.has (g)) continue; + if (!glyphset->has (g)) continue; glyphs.push (glyph_map[g]); gid_org_klass_map.set (glyph_map[g], klass); orig_klasses.add (klass); } } - ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, - glyphs, orig_klasses, klass_map); + ClassDef_remap_and_serialize (c->serializer, *glyphset, gid_org_klass_map, + glyphs, orig_klasses, use_class_zero, klass_map); return_trace ((bool) glyphs); } @@ -2045,10 +2051,9 @@ struct ClassDef if (likely (it)) { hb_codepoint_t glyph_min = (*it).first; - hb_codepoint_t glyph_max = + it - | hb_map (hb_first) - | hb_reduce (hb_max, 0u); + hb_codepoint_t glyph_max = glyph_min; + unsigned num_glyphs = 0; unsigned num_ranges = 1; hb_codepoint_t prev_gid = glyph_min; unsigned prev_klass = (*it).second; @@ -2057,7 +2062,9 @@ struct ClassDef { hb_codepoint_t cur_gid = gid_klass_pair.first; unsigned cur_klass = gid_klass_pair.second; + if (cur_klass) num_glyphs++; if (cur_gid == glyph_min || !cur_klass) continue; + if (cur_gid > glyph_max) glyph_max = cur_gid; if (cur_gid != prev_gid + 1 || cur_klass != prev_klass) num_ranges++; @@ -2066,7 +2073,7 @@ struct ClassDef prev_klass = cur_klass; } - if (1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) + if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) format = 1; } u.format = format; @@ -2080,12 +2087,14 @@ struct ClassDef } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool use_class_zero = true, + const hb_set_t* glyph_filter = nullptr) const { TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (u.format1.subset (c, klass_map)); - case 2: return_trace (u.format2.subset (c, klass_map)); + case 1: return_trace (u.format1.subset (c, klass_map, use_class_zero, glyph_filter)); + case 2: return_trace (u.format2.subset (c, klass_map, use_class_zero, glyph_filter)); default:return_trace (false); } } diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index f523e35c0..19060c762 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1366,7 +1366,10 @@ struct PairPosFormat2 class2_set.add (klass2); } - if (class1_set.is_empty () || class2_set.is_empty ()) return; + if (class1_set.is_empty () + || class2_set.is_empty () + || (class2_set.get_population() == 1 && class2_set.has(0))) + return; unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); @@ -1434,12 +1437,17 @@ struct PairPosFormat2 out->valueFormat1 = valueFormat1; out->valueFormat2 = valueFormat2; + hb_set_t coverage_glyphs; + + hb_iter (this + coverage) + | hb_filter (c->plan->glyphset_gsub()) + | hb_sink (coverage_glyphs); + hb_map_t klass1_map; - out->classDef1.serialize_subset (c, classDef1, this, &klass1_map); + out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, &coverage_glyphs); out->class1Count = klass1_map.get_population (); hb_map_t klass2_map; - out->classDef2.serialize_subset (c, classDef2, this, &klass2_map); + out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, false); out->class2Count = klass2_map.get_population (); unsigned len1 = valueFormat1.get_len (); diff --git a/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf b/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf index cf686c366276025c315aafa8233d2104d824248a..f46824945ffc0ed249ebb349f3ec5ed009acef5e 100644 GIT binary patch delta 314 zcmX@2HA8EHf`$ASXBh?tfjbNg4C(Fx{=xGmuC!!e5OiT+U^MUua}0VJ$^L|aL8t^M zpXdwZuVtQ{1mxeC7$Gkh02F+cSe96%l&4b1z##HuVuw7V&Bhf+I9VbO{a>@WfUB2{ z6KEQPD+3b)(_{l-NhL-g4~Rt=SilU%Z(RH$49q|_6Nt~n%EdL=Rj{mn4NwtC#SEZ$ z0t3)73|S0iKoM3Ti{bw_h6(>~FtjjmF)aE&hoK831_g_N^dgWvi2wgN!!#g!&i_XY zAaOVV>Rs`F62m&M029zAh+T|8yO@EPk%3tVD##3^nSj=UTwfxj$;hyIp3pKT0Kz3g AmH+?% delta 354 zcmbQCbwq1|f`#e>txyIAfjbNg4B74h{=sru>s%NZ1U(oS7$ZEw9D`m)vOi&95Ly6~ zPxJ-y*D}veVqg$vnHV82SOXM%l~|Toq?D&p$G{*eFtJ0PF=OM3Bb+RLJJlpM7jX5m zv04Kaxlf)UB&)^@WHB-@eB%;fU;#53zj5(H*i0Zk7b_Q+$hXOkf@SqrfC@os4lpn= zlrR7t#8Ai3!@vrJK=A(!!z>`R;QtMVQ~!4{ECY*uW7q-YuVLTd9sI)CL`14BB5nW0P=%P!TKzzdfP6285C&!j79fk^ z|2Kw&|2G)Y7`PZJKzt|wvBCWR&lz%nYKs0p0`eJwx)_0`LP(&6AdA4F5D}nF4PeWG VBm)Bzn9TrYLrBKW(*))*0RXR+HZlMJ delta 300 zcmeBB+oCo>!GixGzYPNe2s5O*2lxle3oa7?@|OVlA3VYwgWel`d&$5cFa^ku^9AzP zGS5x|^1n=skQdAW3cgA#ODs~#Q>kNM5N4RzAF(##=ruEK=A(!LlKaw_%BL1I7vl7q-UXXyI>jbXz7M?gL!&`w4MCNK$MGXr^yU~z~HP+J2K eGcW>4ptvNE0xAG=n80k1G|-6+o6`jrG64WKLOvG& diff --git a/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41,42.otf b/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41,42.otf index 749daaf4dfc3d31aae854a5f50ce0cfb520c1bb7..5e81cb48687a324353e0c0736e856248a89aa339 100644 GIT binary patch delta 226 zcmcbjv_ffuf`z}4nF0d??+OM6221w<|6qC71rLGzCqVuRk1)redzL>QGcfS=0Qu3r zK>k|h*-1eDi-{5Pf(byuSBYhbMM`-pbqovwUnX|QGx}^?v4D+*8ruu0u(V|umGwA$ua!@#^A)j#oz~KKWFgx g{|Lxt1e*gg3xpw%3CsqX)&Nq<1R^(Y;ak820C3wbbpQYW delta 242 zcmZ3XbVX@`f(2j44?YG4-W3cC3_Bi-zy)PLXNdX#2*_pxnhL?FERZM=G=Pl_kmtn^!obYH0%S2Ta4{tOuVYC2KZhX)#QopFPz0i3;Qu6s r3K*M#5vYq1XdZ-Q0<#%WL>U^u_5n$tIv@$8!6Zl=$lk2SKaU9jS$Z%G delta 257 zcmdm^d`5YKf`#O3xhMt(-W?1K45{t`{=u^Imgq4s@F_4bFmic>IR?Gg{PvQ8fnNtG zALk3?uVtQ{1myQjjF1x&U;&E0N-Rq(Qp!`QV_*=RF|k9Q@x#UyOW0U~+zwi74q!jP z#?J&)1j39W-{j;N7$!^ewbTbNxBx|>fRF_Uf#ClQhMfN!7+U`CVn_q=8MuJ_I)-2WX6KnoDy|0ISMIFFHmnSl{#2Z%(lfp#_kZ3UA|42)nl6OaUoZ5HBR#RLGo Ca5VP- diff --git a/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41.otf b/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.41.otf index 96374c4b76a25827f970a6cec7d5b393957099ba..5c166ed6440361cfdb18bc8a2205adf06f9b617b 100644 GIT binary patch delta 122 zcmaDO^Fn5Vp?aSDb_ND+9|i`77LPE;pl_NC=YaeRKz@WTkiV9Bb`k>vkH*9ZdBFuh z!B>f8iA73zDs>DDd?ph+;ny5t delta 126 zcmaDM^G0TZp}N2PX9fmt9|i`74v#R$pl_NC=YaexKz@WTkiV9Bb`k>vkIuvhdBG(> z!B>f8iA73zDs>DDd=?Wsu3jHs diff --git a/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.42,57.otf b/test/subset/data/expected/layout.gdef-varstore/AdobeVFPrototype.keep-gdef-gpos.42,57.otf index e17e1ec73404af278e0228dea6010a8ee894db89..43a416592bc2ba6ce33f73e63268be7f0dfbc6eb 100644 GIT binary patch delta 237 zcmX@3yheF~f(1jph!Fz=?-vFJh7k7v|6uvM3$hp(_&k986CPoXLH8^;-Z3!n3jq1i zzCiw3=GjR=e$K=QIU)WhK+#u;Wr;;fc`9`b41yICJLDNJY+Uh#jin>}@3zeo*sIyN z1sIrs%5;F(Y_b%etSE@b$iT?O4Os0VfEdJMV$cAqG+?j*vYA1m|DQ8BP5#3tEyx5^3xOaOP}gQ1{sl|`3k)oT delta 265 zcmZ3Zd`5YKf`!bjPX-JOyk8g?7?Rxs{DbGuQ%2TOhU=W-!u|uBm!^Ra)*jNJO?b|m`V6SH5 z7hzxqDgzl{3B=BmP52dM85tP9F)#tSj0}ui{9qQC$HgV`jbX9}U!->&g9}iaiGhzn z2B?VX{|yEXkg^7l7LZa7APwR%F_?f=+A!Dv?E%@u@c#{i+y7k*K4A89hM>t0_@qTa Tx*$3sx)_0a88`FrFJJ-y><%+- diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.2E,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout-retain-gids.2E,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..849a7c5b1ea6ac647aa08fdca20baedf304e0bbd GIT binary patch literal 1944 zcmc&#YfMx}6h3#Kmu2OlED9*BJS}NDs8$fgh*~UYqiu?8*=1H?S=a>?6|1nY zZ&)Z$5MQL*CkRH-TAxv=ucoQdq-sK}Nt>GfFi}H$7cUK+%Niw3lcv9VCNuMW=bSs| z%(;`9g7xbQKmvP#5Axi+Jb8YyS_S~a0D}CL>k5h>0;B+98`gys6s6J?gByAQL~}4N zDK%)SU>ETi+Xa|w^*W9Ao1}}M0|+sNbUjvtjERn7K8AU`-cYk6w1aQKJOlG{2F;Et zNL|PI4&W}T)EIQ4%IJ6ucVOU(=8^K&RD2!byZ z2L#Rt4xJSqF*hbQA#q^}rBY`t$)(1=zdT7~E|M5iNKjpz(S zXCkEnDJi7HODd64g_LPXnU0idq|89dOr%mE6@^qZQsIayq)J1o^ju?AooNfw*T@q~ zljO8QLCbTr#t(GzqB?Vp&R~|Wsw_2{s*EO0jZT{) =87jo`qd7;j%Gi}34f9Y`T ztcxHOmr_gyNCKrZf`UUrXU+OB1wwonpqp4o9OotRQXcv4$-3LR+k09s^)hQ*9a*kDwmr7` zhGI6PUeie0?Jh@@U2NFxDIK(4YrbJUQ}Q621vWBsd-l!+ziR4h8!dI6+uU}y-DU6G z*JbN;lWw=e71e9mkJ~`~K>eWQS>5PwXYXHlu=??vLspl~ZFL`L@9o(C@xANie=I(s zIKzq?6s2U9`C!>lJLyZFxF-u_ei;|bmMvP6y5jZnVy)I*GH%3f7EnIVJ$mU&Ojto|Pq34eaban+}t{Xx1nT z93Bssxo|lgkrubb(;U4&Z+YzX;@g{;t=G=7WXJXvv#oXy8@5r;N}F_!wawK>EBm$@ zd$%6n_@ncx`+?`~k#o05?~wCs*U3Y7N=|7`ul<2lnwEaL{nXc2n!bP1^R)Sy<5;`% zq`r$KaC{F7J4uJj>2yV!28yc>>PX+hKhtD^zPRy38FH6(>KobQ@*;L#85^l*!!NVB z%zO=_c%O-4+Ez2c+WY0Ute$EQsyFXLyNz|#)rX$kWWpKIL9*ZTRb&5)P$b*SPRK5f zFiE#hvb+KHo9qTwIFR&Z<+IjD9hM$PPY3BsU@zjZHm58Q-ztQ^SKPYWvN?G1??4Dg zu?BW09NWvy_dmNi6T&B31T^mirhMRWT6}|z63Kq_|BwGAmnmPo=YSEM_w^~(Cwyb7 z3ez`|3cP?3!hOeX22LD0G>p|7YPG-JnrV_YWPxemM>cY*$@XQ{utc& za49i4Imt!EEC)AEMDP}_Cm{&H-$!EZ$2poT)w0fJhn01cSn9n4JFZ_AXOf)r3p<-+4u!zc{T5v4 literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.2E,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_1_font7.keep-layout.2E,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..7ffd4689adfebd398b37722bf4ac5e3a2b36ec8a GIT binary patch literal 1508 zcmZuxdrXs86hGhB*GF3cm9hyDtKb5YA>wn6DfrBE4gV zCifI=+g1c}I0Pb4uidagJw)%e0l*-DX!FLcMI|r`lmL>uXiF?AS(sPdzdZmT)*>#i zFlx-Oi?X7BD`Krdr_p|&b?Hm=BZOrJG$f8oKSo@DIKyDH?Uyn14#X=EGe*sRGl+zv z5JHyLXpA~(OV;Af|z$D5UrGS^#n>kT$_W<{1dFE=+&U8psEs8g5JTWva{RsBv)g~?(zSu{4CHb-4pU9Bz_ z!ma9JomFSqi^f<_*p!0;5%#D^%#dfuYDBKU3)o}V?Auw;cjOa$8em>lNzue!4+xqI6O|y z!5!@k_>O$~;6~M7`Db#^6IoMk1!J}zs~qTL!r7A#R0{sr37Klm8*eXM|9VxaR?C)f zA9?M5`+Y5+9C+Hrma%27@^;PTHg3>!j>E-tbhtg7@SB}dGI-0DR$28ZB09}VconNrMGwTd#(=?#<#D{>a1%dNjnTg z*`jl8X|4UXrgx7iu;=uSd+ux8nD_q4AAVti1McDOq2qVT&uY$X`I#)Xtp0r8+3&8l z{Pe{CwDp)_FGA}*G^m)H& z?wcybkN}xfT^ixDZVwSUw0srWP9&kMuWO#QKla)EF29cn&nK6#tkbPh2%jm+p?mg< zvV{CUfs%}(1rE+Xbx4p8zqmC6k|S;6Jo*em5zvAaf8;2YEiB=DobX$32o~s-ycNwD zjhWggpyNg;FGxU1jZ@?B9P*+PP)7}bmP+>Vd={sE9j=3)Q< 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 index b34a49fa011689689137f23264e67276a469fb7f..15aae117624f52c61ee77280f203034567d5c4cd 100644 GIT binary patch delta 156 zcmeysyMS+kBKPDM)eH=56Brm6CQQ^(VcD&rShq3c471FS%0(07`E9;3FtXkON;1@_ zZfF3}x0h$SXPC>fPooF WmI17S38+FDtd1G1iV4gH>I49gv>Yq| delta 108 zcmZ3$_knkUB6sEUR}2hn6Brm6;wI{-u_&ATz=471FiRRzc6`E9;3FtXkON;1@_ vZfF3}H 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 index 2ad1d293d19c034e40e42b9129f0eff255039698..4f7f45c512933e8e1e1619c42f944c48f1467421 100644 GIT binary patch delta 156 zcmaFEGlzGABKPDM)eH=5JPZsB6DI1Yu47&7=hw`K*$7yVDNtqP>hj55y+PT%c?LKFfb#@ VGJsVu0aYl2)iHxrF@f1YodDw28u|bL delta 108 zcmbQk`-W$NB6sEUR}2hnJPZsBaT9e^Saxde=G_>Q!YtFVr!FO)-{va=BkLWYBtwnr uh6WIQbJ@{~%~zOnnY0-hI2f21Bp4WhqH;jU1cYGle-2QLkwFoPf${)56&B3^ diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.2E,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.2E,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..5cbcb37cc9b4c5eef2b63468e1a66017cb6f0ff3 GIT binary patch literal 2024 zcmc&#X-rgC6h3b@9>WNt3@RuNAQmgayf?#U-4K_ES}bUzZHi8r@s7$cFf%TwP=$fn zVX$C9T+^{>3odc15tq2st!dh5QZ*&krcJFsOw`c6!DmCyo3Uz|CQX0!+}wM<@7(k5 zIrqGqdy5w@E(SSl0Wqiw=gd(RW#lRW;240UXzrro(jPbcS_}~3L|a*LX%<^?a7h<{ zY$Wm(%2{k>J~dT~?_x8Dy17sR%b9cUPIMw!uBX;`&D9DggA&0-!)50*az!`n4ugjesTx zV<0$>3KofiMdIK{2_LHvC+&q6k0(4TBE|q5>>sj^mp#2aFjva`5YrcYYZ&)aET}0; zERBea8WIybJbu*Zu_APh*Jy~t4vaYMy{6YPf*9k*d zq9Iz6O>#&s$s_rMQ4@wC3`-adVYGzFCQJ@tatV`1n0&&j35(ybgw+sMOW16}<`6cQ zuz7^dCmJ=;Fhqk(YKTTlG}%OxLo~TWlSef9M5`uRhG%_iEMLUUD(Wfd{n zRO#gtRIFOfstWYx_YJDj8mrA(Cf3 z9oEh<39_)15p<+HN--olW@zlN;c?3N5hF(>B#s`FG**?Ik~%JJ{A=lxGPBeStI=lX z=GV)SfXjJwM2Pqx~=%6N2M?@1unfHUYl^v}e+d5m$cX126ZIiuq z&N^ppeHlNrR@XqgTwZsgE5fwdUw+VWrRkdE)QY<^c;FNA*U#8E{uf>C+6H?~`#PV? z=kmJRw{CZ~`)Hrf?M>{m@4(hm+f#ec{-mbwLGPWjcjrHxcF5s%`W(KU+q&9ze02Nj zn%}1!RiEM`>ec0Rm37z3L)++J#v6klxof$5MT_oyv+tPqqz@b2+UoK8#~%Bz@x0DSyPR%UVhfk(zl34wRL>lQX{WuG`JTw zRUfF_x7ysb`pDAnJePfU{kQg>{+13L^7L*$zWe5i6S|WNzu`5O>HF88_~K&Y*N-|M zH$8D5-sU-O+|E-N-_OHF+U@mtya|?`vg%z1Iymu&GOnL4SH{r%{UeuF2jbFk`dnSBV`K0B3o4wQB*+vJ`_;VQ6=}|`EtwM$SCvk<* z%VVbe29&f9EwDN5@D@RTzklKbh#zd0u%e?##UK)_c!Tv(8DaGQkN+i?kT32z@)G8K zHN^Hw-w0LV)s19N2i8lpJVa@12mf)Ruq zC1@83yAkq#p(kOUb(Rp@M$Kx1SS oj4I4fHiOlMw!hA+Bov84iwJWTJQ5%Uv48|03Nr|IA$ycR0bEZdKL7v# literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout-retain-gids.41,42,43.otf index 5d9fe7725d1f833e79c8d7ac427f87e27a07d211..1fb3d12e8a8402c61dfc9d01340f5d8fa66d23e5 100644 GIT binary patch delta 49 zcmX@Ye}sQR0LyL-#k!3lOIT!dSTEd-=ePOFz{q-s0SIbTH#C6g+e@`yZWdwPzytuJ CI1m^B delta 49 zcmX@Ye}sQR0LxCz-Mkw^maxbeFwNZ`&u{aUfsyqN0}#}xZfF3}HfRG6Y!QlTKpco^AB9JcwmQ`UeU|>d) VWdN&S0;*63t78VMVgj>)IswOx8o~eo delta 108 zcmbOt`$T4fB6sEUR}2h%EDQ_`aT9e^Saxde=G_=#!Y!k@yk%27zs*+$M%Ft(NroEL v4Gkdr=CY#|o0o7;WzuG3;9y{4kYHd0ipl{Y6A*&I|2aT0Mg~PF2Fe2fDohrY diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23,25.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.21,23,25.otf index 195c8dc32458d8e15c250210cd2c926a313febd1..965951353a329cfdf88b955af58d907cc298a4ed 100644 GIT binary patch delta 141 zcmZ3$eSv#|B6rdAFANN<4h#$oeG_$5SaxeD)@=;oU}oVFXL>L>fmwv*_EPPan=6?A zGDb5oa4~2wFfm9lFankP03j0)g2DeeKrs+xVvqsLsxas=FeAw_fK@PoRY25%)I#(C GO#=XD2NqHQ delta 93 zcmcb>y?}dyBDdx9R}2iS4h#$oaT9e^Saxde=G_>=!OSAidVy_n0<#Fq&1FX`HdiqJ fWz=S5;9y{4kYHd0DwYF6CLjcZ|8sz1$dCa5VgV8* 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 index d10d3621bcfaaa01116c5ad599a9583ede331bae..f49296ce1c447d625542400cb0e80d87c41b1066 100644 GIT binary patch delta 140 zcmZ3%b%SeyB6rdAFANMUCm0wQ`X=hAu1^T0Z|813(*5K F4FJq=7bgG! delta 92 zcmcb?wSsGcBDdx9R}2g+Cm0wQ;wI{-u_&ATyV1rv+^iP*wP%pxo|mmRIxEW!Mg eQJay0gMo=bf`JjJRt^Z6fDjD+&jE@dLk0kzU=sQO diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.2E,23.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.2E,23.otf new file mode 100644 index 0000000000000000000000000000000000000000..e2834af616e8955b0a73d245aef55441c95fcae5 GIT binary patch literal 1588 zcmZuxdrXs86hGhB*GF4HCuJK%te^`_h72Ebjwy(bOy@A5i<%7RXlWJtpe-s+m_ng% zD6BAQeUa5<8w`wsGcq+Q@v&vuqGoDFh|3n8e=JkO_7yKncW%p^S$1#kJ?Hm3=iYPf zy}74o)21Sj!afjyvT)5B+*QW49n)ikQ=@cAG#z zmqH&7u|cKRhz+UfXdglBG8rw_$PviJ{V^X<0-&z|fB_*348w@kwR(LW)s}@5AUul+ zr?TNxLHGqBnIRXX9)&iyJ2uNDvjFipr0LRlb7*2-h}c8?s_u&+(iIZ( z1EI-Fp&OxfA<2Jj+`qQCUg=#~uUvlDC!dCgi5p3b&Wh2QAi~>#Ze~7ng3V;J?}u+I zy4$-u0&N$9{M#P?GEak}!BO8>N~YJVnmDJ^<4SQ#^m~03{q`#@*X(D?$MOk~-0K3&d&W^j!rM<^}0MMLE8cBef53y{kF$-qYsAfoEuyJ+wuXs z$Kkbm4|W9o2R^=iwd&8jlR0OIq%o(0Gg%H*4s>wgtjXI78UM?KM6vRfHy5maxvEsH zc9wWQ@Yw>kTWUTj_^8ua<}7oSx2Z0)dIvqHz1X?-cDKhjd+?*?3n~Zabhw-;ZG4J@ ze{mZ>)7k34{F>XF+8SM4bF;&4pY3$f#*safSqgukJ>c&SescWW!Jgr7&R#ov?b9?5 zVeN!j)JUFh*m{HurxK$=HaL-_@Zfd0l5Jj_uO;=snpJ66ORsO`cU&1JoPSrV#ZlWp z61V7xyjkPg&{Fe-p=XCNxZ}i@AKaI{W4>EQzxtjF4Y-H9h7R8-Kczao;XAU>yyDod zQ(s^t-0VG9Qg}LlWgaTkGi$8Ld$)cUEkE6f!DrKNY z^hR{YsL#~I02?>L_&@}5W}F#^Cy*PJfI4abtW+!zi)1WI%LdKoX)9Q@ay8^bI%LOU z(E08PCK8FzsE7)%((!~5iD4D z%A%tZkpZl*7>YpyTBwC;P=OiVMPx?5?NR%ykPSJ}Tv)mrYKbVNDD$u!W}p6zuoLe!T^dec}7ql503JvHe5(H1#KYvcbk>Mey-z}Kl(Sq;F&3Nl8e i7RIWvSdshZ?S;`u3^FX{Og)kz4RxwfpJ#jY_5TJDqwib* literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.gpos2/gpos2_2_font5.keep-layout.41,42,43.otf index 83e2e61dacdf93e40bde603aec565b14f1a36713..3766e7f65f9a7610ef555d5f2ddbe9f1a67ad27b 100644 GIT binary patch delta 34 qcmeC+>fo9Xz_MFIv2J6?3nrEngX!lcJ1~o|++M2va&rXp21Wqaatyct delta 34 qcmeC+>fo9Xz_L?wH}A%f7fdV}x+xnbJ1~o|++23FVsixZ21WqbaSXTs 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 index 88e60461ce4a37fd398b4f2aa9f212408acd875e..f2c35943d17a894e5d266a4166e02863922428ff 100644 GIT binary patch delta 156 zcmaDNGevfSBKPDM)eH=LEDQ_`6DI1YufRG6Y!QlTKpco^AB9JcwmQ`UeU|>d) VWdN&S0;*63t78VMVgj>)IswOx8o~eo delta 108 zcmbOt`$T4fB6sEUR}2h%EDQ_`aT9e^Saxde=G_=#!Y!k@yk%27zs*+$M%Ft(NroEL v4Gkdr=CY#|o0o7;WzuG3;9y{4kYHd0ipl{Y6A*&I|2aT0Mg~PF2Fe2fDohrY diff --git a/test/subset/data/fonts/gpos2_2_font5.otf b/test/subset/data/fonts/gpos2_2_font5.otf index 63af3bca1038941a1de1175f524504ceaee593ad..19833cf8fd17abf64c0fbf2ea796ec23c47a6b51 100644 GIT binary patch delta 202 zcmaE&JVRxIB6r)1ZUzQ{9SjT%lP2n@uVk}85E&+-$Fff65K*$1S zF)?s4XaHFfU{!t$en2)z1rYq716HR940OU3$9{>OV delta 166 zcmbQC@_%{wtfnNeb5g^f(-1yRR%ew(ihjI4Kn z3K(isH#C6go6C+?Y`pN1KT?N*F(Vk}85E&+-GSzye