From efcb7d3de1efbd17b01263e3cea757c9579b555a Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 11 Apr 2025 23:34:06 +0000 Subject: [PATCH] [subset] close unicodes over bidi mirror variants during subsetting. Fixes #5281. Does the closure by default, but I've introduced a new flag and option to disable this behaviour since some users may want to get the minimal set if they know they don't need the mirrored variants. --- src/hb-subset-plan.cc | 53 ++++++++++++++---- src/hb-subset.h | 7 ++- .../Roboto-Regular.default.61,62,63,3C.ttf | Bin 0 -> 2768 bytes .../Roboto-Regular.default.61,62,63,3E.ttf | Bin 0 -> 2768 bytes ...to-Regular.no_bidi_closure.61,62,63,3C.ttf | Bin 0 -> 2688 bytes ...to-Regular.no_bidi_closure.61,62,63,3E.ttf | Bin 0 -> 2688 bytes .../data/profiles/layout-test-retain-gids.txt | 1 + test/subset/data/profiles/layout-test.txt | 1 + test/subset/data/profiles/no_bidi_closure.txt | 1 + test/subset/data/tests/bidi.tests | 10 ++++ test/subset/meson.build | 1 + util/hb-subset.cc | 1 + 12 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3C.ttf create mode 100644 test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3E.ttf create mode 100644 test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3C.ttf create mode 100644 test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3E.ttf create mode 100644 test/subset/data/profiles/no_bidi_closure.txt create mode 100644 test/subset/data/tests/bidi.tests diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 11a40fccd..a56965246 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -29,6 +29,8 @@ #include "hb-map.hh" #include "hb-multimap.hh" #include "hb-set.hh" +#include "hb-subset.h" +#include "hb-unicode.h" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" @@ -209,15 +211,46 @@ _fill_unicode_and_glyph_map(hb_subset_plan_t *plan, _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator); } +/* + * Finds additional unicode codepoints which are reachable from the input unicode set. + * Currently this adds in mirrored variants (needed for bidi) of any input unicodes. + */ +static hb_set_t +_unicode_closure (const hb_set_t* unicodes, bool bidi_closure) { + // TODO: we may want to also consider pulling in reachable unicode composition and decompositions. + // see: https://github.com/harfbuzz/harfbuzz/issues/2283 + hb_set_t out = *unicodes; + if (!bidi_closure) return out; + + if (out.is_inverted()) { + // don't closure inverted sets, they are asking to specifically exclude certain codepoints. + // otherwise everything is already included. + return out; + } + + auto unicode_funcs = hb_unicode_funcs_get_default (); + for (hb_codepoint_t cp : *unicodes) { + hb_codepoint_t mirror = hb_unicode_mirroring(unicode_funcs, cp); + if (unlikely (mirror != cp)) { + out.add(mirror); + } + } + + return out; +} + static void -_populate_unicodes_to_retain (const hb_set_t *unicodes, +_populate_unicodes_to_retain (const hb_set_t *unicodes_in, const hb_set_t *glyphs, hb_subset_plan_t *plan) { + hb_set_t unicodes = _unicode_closure(unicodes_in, + !(plan->flags & HB_SUBSET_FLAGS_NO_BIDI_CLOSURE)); + OT::cmap::accelerator_t cmap (plan->source); unsigned size_threshold = plan->source->get_num_glyphs (); - if (glyphs->is_empty () && unicodes->get_population () < size_threshold) + if (glyphs->is_empty () && unicodes.get_population () < size_threshold) { const hb_map_t* unicode_to_gid = nullptr; @@ -227,9 +260,9 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, // This is approach to collection is faster, but can only be used if glyphs // are not being explicitly added to the subset and the input unicodes set is // not excessively large (eg. an inverted set). - plan->unicode_to_new_gid_list.alloc (unicodes->get_population ()); + plan->unicode_to_new_gid_list.alloc (unicodes.get_population ()); if (!unicode_to_gid) { - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { hb_codepoint_t gid; if (!cmap.get_nominal_glyph (cp, &gid)) { return HB_MAP_VALUE_INVALID; @@ -241,7 +274,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, // the map. This code is mostly duplicated from above to avoid doing // conditionals on the presence of the unicode_to_gid map each // iteration. - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { return unicode_to_gid->get (cp); }); } @@ -258,7 +291,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, if (!plan->accelerator) { cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage); - plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population () + plan->unicode_to_new_gid_list.alloc (hb_min(unicodes.get_population () + glyphs->get_population (), cmap_unicodes->get_population ())); } else { @@ -267,10 +300,10 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, } if (plan->accelerator && - unicodes->get_population () < cmap_unicodes->get_population () && + unicodes.get_population () < cmap_unicodes->get_population () && glyphs->get_population () < cmap_unicodes->get_population ()) { - plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ()); + plan->codepoint_to_glyph->alloc (unicodes.get_population () + glyphs->get_population ()); auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; @@ -285,7 +318,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, }); } - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { /* Don't double-add entry. */ if (plan->codepoint_to_glyph->has (cp)) return HB_MAP_VALUE_INVALID; @@ -306,7 +339,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, { _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) { hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; - if (!unicodes->has (cp) && !glyphs->has (gid)) + if (!unicodes.has (cp) && !glyphs->has (gid)) return HB_MAP_VALUE_INVALID; return gid; }, diff --git a/src/hb-subset.h b/src/hb-subset.h index 51bc7e793..1ce9c6934 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -71,10 +71,12 @@ typedef struct hb_subset_plan_t hb_subset_plan_t; * in the final subset. * @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in * OS/2 will not be recalculated. - * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout + * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set do not perform glyph closure on layout * substitution rules (GSUB). Since: 7.2.0. * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the * remaining gvar table's deltas. Since: 8.5.0 + * @HB_SUBSET_FLAGS_NO_BIDI_CLOSURE: If set do not pull mirrored versions of input +* codepoints into the subset. Since: REPLACEME * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset * to allow it to be used with incremental font transfer IFTB patches. Primarily, * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL @@ -96,8 +98,9 @@ typedef enum { /*< flags >*/ HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u, HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u, HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000400u, + HB_SUBSET_FLAGS_NO_BIDI_CLOSURE = 0x00000800u, #ifdef HB_EXPERIMENTAL_API - HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000800u, + HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00001000u, #endif } hb_subset_flags_t; diff --git a/test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3C.ttf b/test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3C.ttf new file mode 100644 index 0000000000000000000000000000000000000000..743de85d50a3a09d93370694f97077015506eb39 GIT binary patch literal 2768 zcmZuydu)@}6+id;KEINXeD<6e?2>$r$&1)Y$ivVyqA55JnvJ+gpr0cOac$=TdANy_ z1~yjuAY?9-!I&!1cB`tYVr&}MUR#pVO_2!NOJ%HUt1)$xChd=IVp}J56=KBRIiC}f zR=t+bJ->6$Irn$Yy}kwp02UMyC~dx$R`?p|0ho%`f;N9=x9;|lEkZ$q3r5}b|-UJ?1RS;Wd{ za3o@pJQCLTG1{!rv58oE1j49ap!Mi@B>GzaonK>fus*g67zoH$NT(qW*8z%PJIpZ~ zJES4%q|v04bTrTxE7I&p7m)~>O*{!<$qemM70gJzFd`j=lTr=r)BN>t8VaB%{#%)fgub znvn3yAdOgCQBoEw-mw~-jnqS&o3MK!Z5Psl>2&&9dNKXl8s3}X6*vZQn1&Cq>fO)_ zC!i1ZLcP!g??Mt@fJMri>I19r5-6e*vZY3_N~b{9aj@#wLq2;0%=!h$)!(FhjYE`X z*mtqRpgXUt!}5wUv-o@HCsM2Q5fJNpqph>E4Vsa4NDnE1e#3bI6ktCj2dNSFQ}C0i zGz;t8zT9K`SM+$Lzm%UHij0q9M>4xH>=995T91km0c-;|=3PF2#H)jDg@`_Mvq;NC zW^&M7#Vdh5LrxOjdDxG)ETc2Lnf_&6z+1LsSr^yXr8T+^O5wg`A3bUST`&fZ<2Qz1 z526SRz$6Sq5XSL*A}A+d2-iljC$&%oTc8fM!UGzrLA3QtF>CYf#JDIN#vDVKbrAQU z92B($wKiNGL;Eo9qQEZPA%yuAcnB@SICtHPn$S=LnGl~TlwqjiIh7nLA<1N+k|oUy z?GIErt*BlW)b?%VnkIJbtS>1bo3#HMO_du+(|O&+8}dlgKk-;= zt%EefnJ4!(x=1sAd%%CcoitNVi?>wEk~P)W;oV5K>}SKfGk!TYlkrd!+16R*9Fv~3 z+@{*H`^==}HP=^c)M91-Lm5_(v}7Bw0Hx*V(0X6;K|7mB9w6})iE2BGB|AxskvL7_ z5{Wd4B0HO;h)If=q=?C6ULnPj_&157Li9U8;xvihkw}wxun?WcNK`B6H--W)0S9*n zH~G~BV=n~eSo%1BZezkE9@y{U%&jObLq5*>JX~;dw%O_7qFZU@Vo7V4>Ix`vCB7>h zS6Y?9V3`|S(IpDabMgoCG50@wnMxb{*fC&yRC%{=VRWEtC z&fTGKvDB|VqVi)t2XFQT98Raw!WaB1U+_7cfq;kW?{P$~)K87A!OiuXJ=~bd(5>=j z2ZumBPWif3my;ih#~pF3U zp}J-Z)8(@Umd}jB_}%Mbt?=B^BKzi9b_5??1~afIek^sYMhh4%P_*s_X2NJKwn20( z9TNB6y(q+)_>0uc+0^j`e3?elx5R%)yP*)u;af>t#b&eRer}Vwaw9{Mu~AYDU3v6bqEx)AJyS2fk^hVBNlfXQdF%NfUD*?y2)8}*qI%`^RPOgx`BZQFUw--MJMj*>S5{X^Qn(gOS+$5znF4gypHF+4^QkCp4dj{NXmspxOwKJWF#i9P&Ohk zBFhATg{xk_2{+9_bmh3%np#!I@XYomWo{V#U&+}r;# nUNW8@I`z`|XQz7~yAWn&42pj6`Rt#5I&|W<3$81_!8hsu4|940 literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3E.ttf b/test/subset/data/expected/bidi/Roboto-Regular.default.61,62,63,3E.ttf new file mode 100644 index 0000000000000000000000000000000000000000..743de85d50a3a09d93370694f97077015506eb39 GIT binary patch literal 2768 zcmZuydu)@}6+id;KEINXeD<6e?2>$r$&1)Y$ivVyqA55JnvJ+gpr0cOac$=TdANy_ z1~yjuAY?9-!I&!1cB`tYVr&}MUR#pVO_2!NOJ%HUt1)$xChd=IVp}J56=KBRIiC}f zR=t+bJ->6$Irn$Yy}kwp02UMyC~dx$R`?p|0ho%`f;N9=x9;|lEkZ$q3r5}b|-UJ?1RS;Wd{ za3o@pJQCLTG1{!rv58oE1j49ap!Mi@B>GzaonK>fus*g67zoH$NT(qW*8z%PJIpZ~ zJES4%q|v04bTrTxE7I&p7m)~>O*{!<$qemM70gJzFd`j=lTr=r)BN>t8VaB%{#%)fgub znvn3yAdOgCQBoEw-mw~-jnqS&o3MK!Z5Psl>2&&9dNKXl8s3}X6*vZQn1&Cq>fO)_ zC!i1ZLcP!g??Mt@fJMri>I19r5-6e*vZY3_N~b{9aj@#wLq2;0%=!h$)!(FhjYE`X z*mtqRpgXUt!}5wUv-o@HCsM2Q5fJNpqph>E4Vsa4NDnE1e#3bI6ktCj2dNSFQ}C0i zGz;t8zT9K`SM+$Lzm%UHij0q9M>4xH>=995T91km0c-;|=3PF2#H)jDg@`_Mvq;NC zW^&M7#Vdh5LrxOjdDxG)ETc2Lnf_&6z+1LsSr^yXr8T+^O5wg`A3bUST`&fZ<2Qz1 z526SRz$6Sq5XSL*A}A+d2-iljC$&%oTc8fM!UGzrLA3QtF>CYf#JDIN#vDVKbrAQU z92B($wKiNGL;Eo9qQEZPA%yuAcnB@SICtHPn$S=LnGl~TlwqjiIh7nLA<1N+k|oUy z?GIErt*BlW)b?%VnkIJbtS>1bo3#HMO_du+(|O&+8}dlgKk-;= zt%EefnJ4!(x=1sAd%%CcoitNVi?>wEk~P)W;oV5K>}SKfGk!TYlkrd!+16R*9Fv~3 z+@{*H`^==}HP=^c)M91-Lm5_(v}7Bw0Hx*V(0X6;K|7mB9w6})iE2BGB|AxskvL7_ z5{Wd4B0HO;h)If=q=?C6ULnPj_&157Li9U8;xvihkw}wxun?WcNK`B6H--W)0S9*n zH~G~BV=n~eSo%1BZezkE9@y{U%&jObLq5*>JX~;dw%O_7qFZU@Vo7V4>Ix`vCB7>h zS6Y?9V3`|S(IpDabMgoCG50@wnMxb{*fC&yRC%{=VRWEtC z&fTGKvDB|VqVi)t2XFQT98Raw!WaB1U+_7cfq;kW?{P$~)K87A!OiuXJ=~bd(5>=j z2ZumBPWif3my;ih#~pF3U zp}J-Z)8(@Umd}jB_}%Mbt?=B^BKzi9b_5??1~afIek^sYMhh4%P_*s_X2NJKwn20( z9TNB6y(q+)_>0uc+0^j`e3?elx5R%)yP*)u;af>t#b&eRer}Vwaw9{Mu~AYDU3v6bqEx)AJyS2fk^hVBNlfXQdF%NfUD*?y2)8}*qI%`^RPOgx`BZQFUw--MJMj*>S5{X^Qn(gOS+$5znF4gypHF+4^QkCp4dj{NXmspxOwKJWF#i9P&Ohk zBFhATg{xk_2{+9_bmh3%np#!I@XYomWo{V#U&+}r;# nUNW8@I`z`|XQz7~yAWn&42pj6`Rt#5I&|W<3$81_!8hsu4|940 literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3C.ttf b/test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3C.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3586ec85a33f48a69c41493a31846e2656217e30 GIT binary patch literal 2688 zcmZuy3v8QL6+ZX>f4>qp`E8uIwb$f#+`JmQPMyTS{`OdxPyWctY#sLNZMl=#AT|R#&7(oTVMlo9173l3({rm5)0f=72i(UQu?*GDu z;{vX~i@3G7-{ns3K3)bOyn}cs5)UWf93&A35O+jolSD&|JryFONp!b7dtu;wQ-M}w3Ic4PXdCto{Q-tiyUq|Jvf|I@IIoVQuud$+8sZ|j=1(+G7acx{kJ zs!eE##e{FG0cSPN)WHsjY1!CP4EUKoU@VF*3}twIO9 z3K@6?E)!pN2u#9rpolgomD<51odQ|K!KB^@73|w!P_ICl`Wl``LzGUi&tqpnbxzfS zWmOku@z*d+Lf2&@D0H8)aCG(dc7d1Fsv!$7tT`uu0_^LwCbi>v3VsR|mOwM?D)!d$ z5xrgOEAg|(Vp9|NiVCMO>Lz6&xDp( z?kWD{=Cn>cc)-b-Ls9%=KF)@mTySu<)#l`)L+RvVZD(K59#T?DYELw!bSk6aD3@yU zGcLqZA(z6TKRAYVAZX*>koC433x(R9Tp}9Gz}=}35*#WL;G7S+R-Ihs=ux;>7YIHS z#W%9tCs8jN>yv&@w@3uI;_GZPsx zO9&)m5dZ=}kP*xhCS^+V6EAgPdb*tPlBS^T_ty79_}0xtD#_{U^(Zfu)An`Pyxmq; zueR6JwY6?(X=!V%v)8CA?5!S8i@VZnFqtcA-JTt7cBR5pDK^L@pZ&oLZ!q@Pmy?f2 zPP{UGW%klrQeC$6;jh}yWWSeG`cC}t)$F9zjPgWZ4n$-|FQ z&5OAkl7jz6%3u==XN(pr$ur7a#G19Pe5HCUPQO;Rh(KH`Ta7?XWvjFzm0hBziRs;rnAx|6;{{>F4l&<-uhN literal 0 HcmV?d00001 diff --git a/test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3E.ttf b/test/subset/data/expected/bidi/Roboto-Regular.no_bidi_closure.61,62,63,3E.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0810670efcf7040818fcc0bfe654e8c941fd35cc GIT binary patch literal 2688 zcmZuy3v8QL6+ZX>e?Q|Uzl{^O_L}^To3|aOagugf)Owqpv}811l5Td?wef7{(Z-3F zI9ZA)gpH=bOIJFI7#)Lw0F8p^wHY*72MVkc;;}JcLlglT(vS)&;-P`6ve=wsJ54w3 zT0ZxD=ic+(@0@$%00RIM8VQshpT8SSpaNiH7_I0D^bM%~{r4XOh+f3YJp%{t`Rta* z1YCa`aa-SjyEW;5tQ0_a3-NFy9!|j1FpoHZxGOT3RGOaGJd1c4@!&{eH2&y~;co$` zoyhUhXm}<8TKEw9h`}&AaeSmRD~$qZu3^s8W6}70sa}Wt%!ljpSS%cU_vo)bifdaD zcZ^{`|Dx*axW0yX$5=c$Z~l?67x5rs^Tbpn%q;9Lh<774#KZFmp#lGEpRBm!$3(mggld!k5Q%y&OikW;!FsDIts!LP$L%e z5y%}ST^}$oLo<;@X5Idqw(N&>Ek%yatp!#+wBkqdb>BA#m67Aq6JQ;kjvWK*L^wGK z*8Fzt1OQe?gOmskQ={k9(IaJD|AB4VeE7;gjm_k|$@<^9XEIb2>XonK16U@?SkX0Pa>a9@Dz5zz{8kDN9;(0VgX_0*fI}57wDi4-b zRhY$J!3YW6l#QU!eagbo)7RGnUQ(-uEWn87yZ{QYFVmXTiRUT!DO9M37Tj0pt@Q(X zyU|zTXUAgGllY1Xr!njaNnrG@pc)atZg3)R@!k<{4tfm&ehYmhpE3(k>MTA5>=|m3 z@QuS^e02q%fdK+VU%=OOPtg}|i%YlpDyW4!ihI=P0rbNZJdEEYeqD%SFbcCU0b!WN z`-!2QfpJ`$#GbT5GwcKp?1H=Us0Gok_vPHqcQ588;5c%OBkLHRK^&B|6TKc>ox=D8 zo}$2hJRySo3fzs637q?HWzFPK43&_cIkZt|=7uH?O^{)-(8MxEhW3)Nv!%u+gSH7S zv3++n+s)`+5`z17*XKR4|K7Hm3W`aGKho8-jXYI{vwB+@dFn?V>Tb1>r#buRp-u;R z+K-P0?zEDp8}xV7=2`S}!@V8bDOU1$^gv;s;c6xo>7v*cvux0*$t&$@t-HfWUYWP8 zVS7GT4%}T(1sPL`1`AO9C&st>GJCCTCUb<$C&;+1ESc#eGezbMnTup{WU8!emNI53 zW0o>zGi8;OOXeSBsw#2c5i)1U{E|$L%-%}eJVnN>;Jzs|_y{;Sd$}$UOf&XmXoclY z@=t9~>%=36U7R@;#Xs)jY}myGCufaz7Z;sMHy3NV`-6^NfngxXy*3V^REqcpf(|=h zNTqBktY8DLy%(=Acz?iqdjLD&UttRYq{7Kzw^6`hci2&3$milZXYWAJj}q-DQSapS zeitus@&=p?&U77HQc?rKRWJU{M^?13G#FfkdhuE!WaADLt1PX^*tcSgs@&q_-lY`< zhJxt^@YzS*x$swF5w3`Tkb3cVu>!BsALN4DmKLmgLR|GaSGikuGS<$@S-WUk zKPEo#?gb&m#2;oCpUR$G!{3&8?z;Fl=>SyXZ~4bEmWD>7=}vBux$=5}%z|VVA|qxA zfn+KIKmZ6bf zc}_6i$o}T+2{o+0{6zM**>%+qUb~QWUU&`f`w-sPb-c0d(3_DftMKr`P01)s-jJ+C zphcBw*i^x_R3evUZYKL)fz)45DT)MRd$H|~+WakG%Y{9WbJ~llxmPCtnEhY!>bdX# nOM6j!X8iOs=O3RRdg%Emt7B00rT;Gd{yXERe!k|o{4@AJ9@=LI literal 0 HcmV?d00001 diff --git a/test/subset/data/profiles/layout-test-retain-gids.txt b/test/subset/data/profiles/layout-test-retain-gids.txt index 63c67eb97..4fe71eb7e 100644 --- a/test/subset/data/profiles/layout-test-retain-gids.txt +++ b/test/subset/data/profiles/layout-test-retain-gids.txt @@ -1,3 +1,4 @@ --layout-features=* --notdef-outline +--no-bidi-closure --retain-gids diff --git a/test/subset/data/profiles/layout-test.txt b/test/subset/data/profiles/layout-test.txt index d98633a00..895f69db5 100644 --- a/test/subset/data/profiles/layout-test.txt +++ b/test/subset/data/profiles/layout-test.txt @@ -1,2 +1,3 @@ --layout-features=* --notdef-outline +--no-bidi-closure diff --git a/test/subset/data/profiles/no_bidi_closure.txt b/test/subset/data/profiles/no_bidi_closure.txt new file mode 100644 index 000000000..31adb7199 --- /dev/null +++ b/test/subset/data/profiles/no_bidi_closure.txt @@ -0,0 +1 @@ +--no-bidi-closure diff --git a/test/subset/data/tests/bidi.tests b/test/subset/data/tests/bidi.tests new file mode 100644 index 000000000..fb5732871 --- /dev/null +++ b/test/subset/data/tests/bidi.tests @@ -0,0 +1,10 @@ +FONTS: +Roboto-Regular.ttf + +PROFILES: +default.txt +no_bidi_closure.txt + +SUBSETS: +abc< +abc> diff --git a/test/subset/meson.build b/test/subset/meson.build index 7037223c7..f87bab543 100644 --- a/test/subset/meson.build +++ b/test/subset/meson.build @@ -1,5 +1,6 @@ tests = [ 'basics', + 'bidi', 'cmap', 'cmap14', 'preprocess', diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 431edda34..bdb71c332 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -985,6 +985,7 @@ subset_main_t::add_options () {"notdef-outline", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Keep the outline of \'.notdef\' glyph", nullptr}, {"no-prune-unicode-ranges", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Don't change the 'OS/2 ulUnicodeRange*' bits.", nullptr}, {"no-layout-closure", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Don't perform glyph closure for layout substitution (GSUB).", nullptr}, + {"no-bidi-closure", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Don't perform bidi closure (adding mirrored variants) for input codepoints.", nullptr}, {"glyph-names", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Keep PS glyph names in TT-flavored fonts. ", nullptr}, {"passthrough-tables", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag, "Do not drop tables that the tool does not know how to subset.", nullptr}, {"preprocess-face", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &this->preprocess,