From 8e4a7a54d5d7e813e5e5c93423d2dc18cce52a40 Mon Sep 17 00:00:00 2001 From: John Daggett Date: Mon, 11 Jun 2012 10:04:39 +0900 Subject: [PATCH] No bug. Add reftest fonts for feature testing. r=me --- .../fonts/gsubtest/gsubtest-features.js | 85 +++ .../fonts/gsubtest/gsubtest-features.txt | 251 +++++++++ .../fonts/gsubtest/gsubtest-lookup1.otf | Bin 0 -> 119784 bytes .../fonts/gsubtest/gsubtest-lookup3.otf | Bin 0 -> 289724 bytes .../fonts/gsubtest/gsubtest-shell.ttx | 304 +++++++++++ .../reftests/fonts/gsubtest/makegsubfonts.py | 486 ++++++++++++++++++ 6 files changed, 1126 insertions(+) create mode 100644 layout/reftests/fonts/gsubtest/gsubtest-features.js create mode 100644 layout/reftests/fonts/gsubtest/gsubtest-features.txt create mode 100644 layout/reftests/fonts/gsubtest/gsubtest-lookup1.otf create mode 100644 layout/reftests/fonts/gsubtest/gsubtest-lookup3.otf create mode 100644 layout/reftests/fonts/gsubtest/gsubtest-shell.ttx create mode 100644 layout/reftests/fonts/gsubtest/makegsubfonts.py diff --git a/layout/reftests/fonts/gsubtest/gsubtest-features.js b/layout/reftests/fonts/gsubtest/gsubtest-features.js new file mode 100644 index 00000000000..c1bdbe3db42 --- /dev/null +++ b/layout/reftests/fonts/gsubtest/gsubtest-features.js @@ -0,0 +1,85 @@ + +/* This file is autogenerated by makegsubfonts.py */ + +/* + Features defined in gsubtest fonts with associated base + codepoints for each feature: + + cp = codepoint for feature featX + + cp default PASS + cp featX=1 FAIL + cp featX=2 FAIL + + cp+1 default FAIL + cp+1 featX=1 PASS + cp+1 featX=2 FAIL + + cp+2 default FAIL + cp+2 featX=1 FAIL + cp+2 featX=2 PASS + +*/ + +var gFeatures = { + "MWL1": 0xe000, "NUM2": 0xe004, "PRIV": 0xe008, "T3ST": 0xe00c, + "TPSP": 0xe010, "abvf": 0xe014, "abvm": 0xe018, "abvs": 0xe01c, + "afrc": 0xe020, "akhn": 0xe024, "blwf": 0xe028, "blwm": 0xe02c, + "blws": 0xe030, "c2pc": 0xe034, "c2sc": 0xe038, "calt": 0xe03c, + "case": 0xe040, "ccmp": 0xe044, "cfar": 0xe048, "cjct": 0xe04c, + "clig": 0xe050, "cpct": 0xe054, "cpsp": 0xe058, "cswh": 0xe05c, + "curs": 0xe060, "cv00": 0xe064, "cv01": 0xe068, "cv02": 0xe06c, + "cv03": 0xe070, "cv04": 0xe074, "cv05": 0xe078, "cv06": 0xe07c, + "cv07": 0xe080, "cv08": 0xe084, "cv09": 0xe088, "cv10": 0xe08c, + "cv11": 0xe090, "cv12": 0xe094, "cv13": 0xe098, "cv14": 0xe09c, + "cv15": 0xe0a0, "cv16": 0xe0a4, "cv17": 0xe0a8, "cv18": 0xe0ac, + "cv19": 0xe0b0, "cv20": 0xe0b4, "cv21": 0xe0b8, "cv22": 0xe0bc, + "cv23": 0xe0c0, "cv24": 0xe0c4, "cv25": 0xe0c8, "cv26": 0xe0cc, + "cv27": 0xe0d0, "cv28": 0xe0d4, "cv29": 0xe0d8, "cv30": 0xe0dc, + "cv31": 0xe0e0, "cv32": 0xe0e4, "cv33": 0xe0e8, "cv34": 0xe0ec, + "cv35": 0xe0f0, "cv36": 0xe0f4, "cv37": 0xe0f8, "cv38": 0xe0fc, + "cv39": 0xe100, "cv40": 0xe104, "cv41": 0xe108, "cv42": 0xe10c, + "cv43": 0xe110, "cv44": 0xe114, "cv45": 0xe118, "cv46": 0xe11c, + "cv47": 0xe120, "cv48": 0xe124, "cv49": 0xe128, "cv50": 0xe12c, + "cv51": 0xe130, "cv52": 0xe134, "cv53": 0xe138, "cv54": 0xe13c, + "cv55": 0xe140, "cv56": 0xe144, "cv57": 0xe148, "cv58": 0xe14c, + "cv59": 0xe150, "cv60": 0xe154, "cv61": 0xe158, "cv62": 0xe15c, + "cv63": 0xe160, "cv64": 0xe164, "cv65": 0xe168, "cv66": 0xe16c, + "cv67": 0xe170, "cv68": 0xe174, "cv69": 0xe178, "cv70": 0xe17c, + "cv71": 0xe180, "cv72": 0xe184, "cv73": 0xe188, "cv74": 0xe18c, + "cv75": 0xe190, "cv76": 0xe194, "cv77": 0xe198, "cv78": 0xe19c, + "cv79": 0xe1a0, "cv80": 0xe1a4, "cv81": 0xe1a8, "cv82": 0xe1ac, + "cv83": 0xe1b0, "cv84": 0xe1b4, "cv85": 0xe1b8, "cv86": 0xe1bc, + "cv87": 0xe1c0, "cv88": 0xe1c4, "cv89": 0xe1c8, "cv90": 0xe1cc, + "cv91": 0xe1d0, "cv92": 0xe1d4, "cv93": 0xe1d8, "cv94": 0xe1dc, + "cv95": 0xe1e0, "cv96": 0xe1e4, "cv97": 0xe1e8, "cv98": 0xe1ec, + "cv99": 0xe1f0, "dist": 0xe1f4, "dlig": 0xe1f8, "dnom": 0xe1fc, + "expt": 0xe200, "falt": 0xe204, "fin2": 0xe208, "fin3": 0xe20c, + "fina": 0xe210, "frac": 0xe214, "fwid": 0xe218, "half": 0xe21c, + "haln": 0xe220, "halt": 0xe224, "hist": 0xe228, "hkna": 0xe22c, + "hlig": 0xe230, "hngl": 0xe234, "hojo": 0xe238, "hwid": 0xe23c, + "init": 0xe240, "isol": 0xe244, "ital": 0xe248, "jalt": 0xe24c, + "jp04": 0xe250, "jp78": 0xe254, "jp83": 0xe258, "jp90": 0xe25c, + "kern": 0xe260, "lfbd": 0xe264, "liga": 0xe268, "ljmo": 0xe26c, + "lnum": 0xe270, "locl": 0xe274, "ltra": 0xe278, "ltrm": 0xe27c, + "mark": 0xe280, "med2": 0xe284, "medi": 0xe288, "mgrk": 0xe28c, + "mkmk": 0xe290, "mset": 0xe294, "nalt": 0xe298, "nlck": 0xe29c, + "nukt": 0xe2a0, "numr": 0xe2a4, "onum": 0xe2a8, "opbd": 0xe2ac, + "ordn": 0xe2b0, "ornm": 0xe2b4, "palt": 0xe2b8, "pcap": 0xe2bc, + "pkna": 0xe2c0, "pnum": 0xe2c4, "pref": 0xe2c8, "pres": 0xe2cc, + "pstf": 0xe2d0, "psts": 0xe2d4, "pwid": 0xe2d8, "qwid": 0xe2dc, + "rand": 0xe2e0, "rkrf": 0xe2e4, "rlig": 0xe2e8, "rphf": 0xe2ec, + "rtbd": 0xe2f0, "rtla": 0xe2f4, "rtlm": 0xe2f8, "ruby": 0xe2fc, + "salt": 0xe300, "sinf": 0xe304, "size": 0xe308, "smcp": 0xe30c, + "smpl": 0xe310, "ss00": 0xe314, "ss01": 0xe318, "ss02": 0xe31c, + "ss03": 0xe320, "ss04": 0xe324, "ss05": 0xe328, "ss06": 0xe32c, + "ss07": 0xe330, "ss08": 0xe334, "ss09": 0xe338, "ss10": 0xe33c, + "ss11": 0xe340, "ss12": 0xe344, "ss13": 0xe348, "ss14": 0xe34c, + "ss15": 0xe350, "ss16": 0xe354, "ss17": 0xe358, "ss18": 0xe35c, + "ss19": 0xe360, "ss20": 0xe364, "ss21": 0xe368, "subs": 0xe36c, + "sups": 0xe370, "swsh": 0xe374, "titl": 0xe378, "tjmo": 0xe37c, + "tnam": 0xe380, "tnum": 0xe384, "trad": 0xe388, "twid": 0xe38c, + "unic": 0xe390, "valt": 0xe394, "vatu": 0xe398, "vert": 0xe39c, + "vhal": 0xe3a0, "vjmo": 0xe3a4, "vkna": 0xe3a8, "vkrn": 0xe3ac, + "vpal": 0xe3b0, "vrt2": 0xe3b4, "zero": 0xe3b8 +}; diff --git a/layout/reftests/fonts/gsubtest/gsubtest-features.txt b/layout/reftests/fonts/gsubtest/gsubtest-features.txt new file mode 100644 index 00000000000..c78addb96b3 --- /dev/null +++ b/layout/reftests/fonts/gsubtest/gsubtest-features.txt @@ -0,0 +1,251 @@ +# Feature To Unicode Mapping +# -------------------------- +# This file is structured as: +# feature tag target first alternate second alternate third alternate +# with tab being the delimiter. +# +# Lines beginning with # should be ignored. +# Empty or whitespace only lines should be ignored. + +abvf +abvm +abvs +afrc +akhn +blwf +blwm +blws +calt +case +ccmp +cfar +cjct +clig +cpct +cpsp +cswh +curs +# cv00 is a deliberately invalid feature tag +cv00 +cv01 +cv02 +cv03 +cv04 +cv05 +cv06 +cv07 +cv08 +cv09 +cv10 +cv11 +cv12 +cv13 +cv14 +cv15 +cv16 +cv17 +cv18 +cv19 +cv20 +cv21 +cv22 +cv23 +cv24 +cv25 +cv26 +cv27 +cv28 +cv29 +cv30 +cv31 +cv32 +cv33 +cv34 +cv35 +cv36 +cv37 +cv38 +cv39 +cv40 +cv41 +cv42 +cv43 +cv44 +cv45 +cv46 +cv47 +cv48 +cv49 +cv50 +cv51 +cv52 +cv53 +cv54 +cv55 +cv56 +cv57 +cv58 +cv59 +cv60 +cv61 +cv62 +cv63 +cv64 +cv65 +cv66 +cv67 +cv68 +cv69 +cv70 +cv71 +cv72 +cv73 +cv74 +cv75 +cv76 +cv77 +cv78 +cv79 +cv80 +cv81 +cv82 +cv83 +cv84 +cv85 +cv86 +cv87 +cv88 +cv89 +cv90 +cv91 +cv92 +cv93 +cv94 +cv95 +cv96 +cv97 +cv98 +cv99 +c2pc +c2sc +dist +dlig +dnom +expt +falt +fin2 +fin3 +fina +frac +fwid +half +haln +halt +hist +hkna +hlig +hngl +hojo +hwid +init +isol +ital +jalt +jp78 +jp83 +jp90 +jp04 +kern +lfbd +liga +ljmo +lnum +locl +ltra +ltrm +mark +med2 +medi +mgrk +mkmk +mset +nalt +nlck +nukt +numr +onum +opbd +ordn +ornm +palt +pcap +pkna +pnum +pref +pres +pstf +psts +pwid +qwid +rand +rkrf +rlig +rphf +rtbd +rtla +rtlm +ruby +salt +sinf +size +smcp +smpl +# ss00 is a deliberately invalid feature tag +ss00 +ss01 +ss02 +ss03 +ss04 +ss05 +ss06 +ss07 +ss08 +ss09 +ss10 +ss11 +ss12 +ss13 +ss14 +ss15 +ss16 +ss17 +ss18 +ss19 +ss20 +# ss21 is a deliberately invalid feature tag +ss21 +subs +sups +swsh +titl +tjmo +tnam +tnum +trad +twid +unic +valt +vatu +vert +vhal +vjmo +vkna +vkrn +vpal +vrt2 +zero +MWL1 +NUM2 +PRIV +T3ST +TPSP diff --git a/layout/reftests/fonts/gsubtest/gsubtest-lookup1.otf b/layout/reftests/fonts/gsubtest/gsubtest-lookup1.otf new file mode 100644 index 0000000000000000000000000000000000000000..9f359e51d2b27dec88efa2c8ece724412c4ba7a6 GIT binary patch literal 119784 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 Jf8BB5e*wUN*6;uT literal 0 HcmV?d00001 diff --git a/layout/reftests/fonts/gsubtest/gsubtest-lookup3.otf b/layout/reftests/fonts/gsubtest/gsubtest-lookup3.otf new file mode 100644 index 0000000000000000000000000000000000000000..86d79a0d8f07a3ab149999ec8a36b6e2cacbadc0 GIT binary patch literal 289724 zcmeFZ32;(Z@T+}A(loC5GX3FOu@-3JftyenWf6Fr3@VxG0qndsnlFBOUr%b{#QrcwbWZfdv%aa|1YQK&8FU3>d1lq(2ZWhMB1N9=ho91 zb+l&DW2)(YlWDgGTri0CCsJKO&r}O})St`$Ye#>M0Wg^U-|l}qBkO-m8AfN;^6Ozg zSDf3_|J~L6&q=cVw*=D@bb|rkymI?C?Qz`%w{PFRc>C~e zwpq-<{%G`nE9KNqiSwc?`hYJ4Kp>qOOlb^<2#ACjh@}(aAqkQp1yUg$G9Z)QWV!T5 zaMByACA5Op&<5JWUC;qKLTBhgBf1BAKu;Q4Z|FyF^Z_uC-gHA@7!0RmkA{0;3>4BE zcRY=&l-`tOJf=!|!?2)OBvWBJjeREE2Xo+lm<#h@0Xzr`;UQQ8OJNx-hn27jR>LE( z4jzT|umLu~X4nFc!xQi%Y=iBv6P|`$up9QlGq4|?g%{vOH~=rf%kT;uh9htkUWa4w z2HoAa;3T{ar{Fy}4e!H;@DZGakKr7A2A{(h@Fjc&O>mLk<9!R?!T0bZT!E`}3x9>* z;CJ`~{)T3_2G`*x{0q0>Ho}M?4Ox&Kc_0V!L_WwD`5}K4go05B3Plkp5=EhC6o=wb z0!l5ol7AO;Cp=^|coXCapQ2}a=+Mu?m9qNEOqE6^;)D_)>x}ol<7wV1rpuT7T z8i)p=!Dtv7jz*x7=w37ijYZ?ocvOrgpb}Ju%F!e=8C9WbRD-6VdNdU^plN6(x)04l zv(a2M56wpppoQomv*ybJ1KmQm zDbNUO*n+Lth8@@wdtqf{$;r940+zH=}JL4|68}5#K;GVb-?u+~3{&)}`jECT%cmy7aN8!Tkh$rF6xB^$=8axHp;yT=br{U>%2A+jy<2m?#JRd)R7vKl+BD|PB z(k#U*@WXf|UWM1-wRjzV6mP_j;Z1lmZp2&h6ZlEI13!g#;-~Q*ych4o&*10q^Y{h) zB0h)@;g|6%_*MKGK8jz*$MKu^1bz#@gWtuc@O$_S{s4c7Kf<5jPw_eY89t9M;4kr4 z_-p(PzJ$NUm+=qyM|=hUjDNwu;@|L}_%Hl7ZpQ!M8~7&vmjFQo6GE)SM(o6ccoA>n zLwrd92_!)zn1qpV53?swIC^DMdOU95wQbfj+Vp2*bk}^_G zDo7=%BGsgp)RB5Jl}sly$V_q{nM3X;bIClifILVRl849=vXm?%%gIWzimWD&kagry zvYu=po5*Ieg*;B4AWxEQWINeOo+i7@;&*HTp?G< zPvlqf8~L65LH;Jq!5YiI%#)nUA23( zZd!M(m)2YBqxIDWXaluD+F)&%He4H_jnwYd#%N=;aoTvTSeu}gXk}WtHc6YTRcX~) zjW$KA*QRO>+B9vZcAqv&o2|{&=4tb_2egISL)s#3v9?TGuC34>)>dneXlt~!+Inq+ zwo!Xb+oC-O_Gbz=ABA#bU8qY!-*b)8b|Ew)k26EdiE5 zONb@Z5@rdvL|LLOF_u_Mf+f+CWJ$K9Sz1`qEg6<P>>0;?->2B#^>1pX>>1*j{>2Dci8EhG18EP3}8EF}18EqMB8D}Z96j>%% zN-U+8iIz#0$(9OBrKQF)#Zqgjvou(yS*BZNSY}yfTjp5qx6HRZU|C>!(6Y#~*s{d3 z)Uv|zuw|uXm1T`(t!16%QOiclW0p;p&HT}uKK$N(kv$*&zyCp?X@C$4|6e|*qTh5~ z^Mz>oOg$d+N?1+MepyQYwr{#V-$MWH^qudc(e%mxlL73DW`D~jOdtLo^g%ur(&$5Y zTl#R_2S(5b<4N>^cNTq+T?HHIL+Bp*aQP~{Lmv#!(+9qvp_x9cdC`Zk82WIPi`vr% zqki;(r;t9#Oht3(L&!?{aPb7%M;{E1(mVbS>7D%d=vQm=GtTta;m@VFxZgbf>+IrXq+D6%mZ56iZwt2QCwnuE6Y};+m z+FrK3VLN5}*!HFEN82B^n|6!c#~x}=v}f82>>cdg?E~!h+Dq(J_G$LH_Qm$K_AU0O z?ECG9?8oe_6Clx8LxvdH8vRdn9;dc;tI@^62R?$YZp}1dmFO86NXJmU^u5 z*zB>x<2jF4JdS(3=kbZhR~}b9{`C0QVRiUA!W>DCEJsU6M@J9GK*tzIsiWF4-7(Lx z#IertxMQc|S;xzcHyrOf&N(hResuidxan#4^!JSLO!Un3EbzSBvzO;!&wD*fJgYos zdOqN}%yX^h7SE?VpZ7fM`KIS-&rdy@Jg<8G<$24?=H=%V?v?D7?bXVwlUGl#L0)6M zCVJI)&G4GVcO*Lgqgz0>;z?<3wPyx;de=Y7%pC-1+#Z~NGN{Cy&PQhaiJ zTKnAX)5~YD&p4klpD8{weID>x=Cj^stIsZ<=Y0`tR~T;QyNcN&gT0 zKllH}{}=yj0Vu!`5Eu{@kQR^^&^Dk;K%ao20Yw3m0_p;01w0tAB4A^{lL31IUJQ6O z;H`j<0?r3~8}M^Lb07qI1qKJk1f~Y&2DS;jC$L}O@W8^r^1#}_Ie`xat_<7|_(b6D zz?TA#2EHBmVc-{mmjZtcydH#uJcELQqJvrlIfL2-bq(qpG%RR*(Bz={pxHqSgB}ig zENENM-k<|PuLYe9IvaE$=)0g_g02OlVDI3N;Mm}_;Jo0r!QF!U2agCY3Z4{P7kq#4 zqTp4*8-t$=-V=N<`1Rm-fQh6$gd&SLvg52XlQ6$Xp2y1XuHtvp#wrk zhK>)N99kbbH*|66>d?nRw}tKvJrsH@^xe?2p%+5G3;jLxMwk}n9TpN68!B34bJfQ~37qec>;MzY%^a{NwO1!@m#zBm8EBCBi2n zG$Jk{Gom1(Lqzw80TCl3N+PNvrbWz+SRAoBVoStR5&I(!MI4KGH{#QXridRRevh~j zsYUulhDRnuW<=&k-WAz1a!};x$O(~^kqwdaBbP?5iQF8yBl4NZS0ax`z8CpP)MgI`}SM;qITZ~^!cuYb}c1)|7PBA@W2E~kynHWTF2cT*DG#t+`VySaZ}=E z#yt?XEN*Sw*0^19&&M5(do%8I+~;xM#9fX1EACdjEj}iKLeG`Wzj!P^{oRT;*abe=aiR%-$ChkgnKJm50lZhWBexCSE;?=}!NhryY6qpp1 zl$?~8)HbP0QlF%uNn?{HCDkR(N_sG9Mbe{5PbTe2dNJwMq_>jJB%M$CHtFZ2=443r zNDfYpNls19O>UFiIk{i*@Z`ee^5oj&`;s3@UYWch`HAG+$uA@yO@2H1!{jfLFD3t! zd_4uHc%}rUM5m;rI8)lCbWQ1-GAw0W%H)*#l-Vf@QyxxPpRz4wZ_0s`*HTWVe2{V> z<-3$$Qm&<jBGK!#pD+CEoQe^++uZ$ z$69P_vA4y67ROq=+v04C3oX8D@k@&v=~}vXdPsU~dRlsZ`d#VW()*{6NH0pSOm9fP zKYda9s`QQNJJO#?KbZb{`a9_#rGJ%vIsLcve=!wTISr$#hI%!AIp3ybARTc%ww7FW}eM#%KRbo_sknvT9$WKcveDIMpk~- zU0L0-24#)TnvhkQ)sS_6*3zssS(~$VWIdC0Fza~Mds&}keU)`N>$j|bv#r^_*7Fw<=iZ!>oT{8@IdgNC<*d!wlJiu~{+vTOZ|0oN`81~~=ZBo% zb8h9@a{Y3{a}#nia$Dtg%I%puD0g)3gxs3k8M*Uwm*%d?-JJV$?sK`Xm$y7`UEbq)JM*5+dpYk! z-urpy@-F86nDI zf{O_yrA1RK>bWkesLwNn(-f|LL;E_pkqc(z!Z32pjHYm!!Zlz}&tcri1v7GC7`bLf zQ#eiG8sZu}gd4eFMlK8^*UV@Nrzu?Q)n47m1UE8a8ky!sLpb^IwBsro-%!epTreXS zhLLM#G=r7*vd8z!n#u@9_1ZL#IRa9DA ztQ(o&m&$~BMy9#Z5KewP?YN32msROTCb*Fa)5tV88p6qsXU6dr)ASpM3uffPFmla| zrf`~q8TA{73&U7xo{={VBfm|UQNMAh&~F?r4C9>}hc^wQe&d)OSFy83zj3%=MlOs? z<(e5y;WPy`)|o~sbR!jaj8yAJT~MPgT*b7_Z&fb1k#$TX)7)qXCqImSL5+1KhLH;0 zNW~o^)w)p^)Tj$radBmhZe)TRnJ|q^bE6@g{CIxG(xO`3$OJbsVH%m{MngD@4dE)D zRBZf=OmHI;rjcoGG=!5M&(BydOqfQdxzP|#empxnM>vn6ag4Y-t)>x*1!VMlP6<3ubI(8e5shR&K^trjZL~8+WY-1X^U`8&eG0!B23Oz?E?vO*ZPL3|9Q5Vc;l0$`IbR&m0 z4Wmhp-eE?Q94ZW>8#%OT7)^5Y4l|nMP+=I|$e~TcXp*CMn9(GM3d86|4s9AnlN`On zj3zl$7)Cd8Xwxv7j%WdWRWJa;Pwj zZsgFWVKm9nJIrX3Lxo{`ts8Yg$#a=td508b*^Gy~B(qIaC-%H*#pxFq-7(9cDDip~5h_kwcq?(IiLj zFr!Hh6^7A`9NILDCOLYC8BKDiFpO^G(57KD$4x zqZ>K2X&6m%^bRwcO$!)TJDcc{^2l0$`Vq~Z=aRO?1vP;zv^j3zl$7)Cd8 zXwxv7j%WdWRWJa;PwjZsgFWVKm9n zJIrX3Lxo{*=OGn(X3VHn-Wp-sbRlB0K+(Ikfo z!{|m1Z5l?C9KFMgCOK3XMmKV3(=eLk=pAazH_4$wH&Stj9IADrE+{#=U`CT1Dh#6= zIkagQO>*=OGn(X3VHn-Wp-sbRlB0K+(Ikfo!{|m1Z5l?C9KFMgCOK3XMmKV3(=eLk z=pAM>$)Un9x{*VhhS4NP?=YiD4i$#cjU3uEj3zmHhZ#+Bs4$Ff#a=td508b*^Gy~B(qIaC-%H*#pxFq-7(9cDDi zp~5h_kwcq?(IiLjFr!Hh6^7A`9NILDCOLYC8e5v=P@x;CxI+%rx=|OD99=M@Ne&f; z(TyD1G>j%WdWRWJa;PwjZsgFWVKm9nJIrX3Lxo{*=OGn(X3VHn-Wp-sbRlB0K+(Ikfo!{|m1Z5l?C9KFMgCOK3XMmKV3(=eLk=pAM> z$)Un9x{*VhhS4NP?=YiD4i$#cjU3uEj3zmHhZ(F(jBe!6reQS6(L2m&l0$`IbR&m04Wmhp-eE?Q94ZW>8#%OT z7)^5Y4l|nMP+=I|$e~TcXp*CMn9(GM3d86|4s9AnlN`Onj3zl$7)Cd8Xwxv7j%WdWRZYo8(ZT8>zTM4%NC*7nB@bFr!Hh z6^7A`9NILDCOLYC8BKDiFpO^G(57KD$4xqZ>K2 zX&6m%^bRwcO$!)TJDcbL&6hYG{!Mh#a=td508b*^Gy~B(qIaC-%H*#pxFq-7( z9cDDip~5h_kwcq?(IiLjFr!Hh6^7A`9NILDCOLY?HKDw&p1*|11v7GCki#`In!;%c z*97)TJNwr_F1V3(Or!BSd>;QUo!~TuYeH4E{%<;5a3kxOMyB~04dLX6(T=NRdX0Xm zTreXShLLM#G=B`Uc9^k9zf>j+W0Bh#i_9}}!OqBqtF*RA|K}$zxRG_tOJ$m$(GX64 z7{AnMDVv*RkOnpnZ(;DQ@j$2=p`+-L|VKa8KT zdQ!D+WP%%+FpW%eqamDShH#a!K-nU5!HukA8jZN~_;=|9rzu?JRpojdTreXShLLM_ zMpHOV;VQ4I)_+DWxRG^CBh%by2q!;`c3kE4MTU_HZe+qVGR=*KaPs4saS|>3XXJtz zxiE}eGovY-rf^NFG5-093vOf`)5tV88p6pB<7ccfo;^-tLN`)z$EZJ7%;Vps$5W%; zp=UInS#hBoY3Gj7cxJ`Fs~e4HR+DPzV>-)`3*AUNcZ~WYK0Tu@=oxk4np{$=?;{t? z$c16#n*EHXaGJtZQ952HhYM!p!Z32pjHYm!!bPdq@8!7QM%FQnOmm|locu7_aaByJ z)FJ1B8(GIRGR=*KaPq^rv1+RRpi{vFH!@)wndU}AIQe1RSY50mSHT1~GGQ8-=0-y} z`C;5xUu*n~OmHI;rjcoGG=#Il5H2c=OJ%|^{&%UYX&AX+MlM{HMYWST09-I57seU6 zW=2yuP2s96nV>(+alwtOV;Y&}MngFHVYI`H<@y)ecW zrjZL~GqR>(G|p&rTs7v?6)w2Z z?db|{a-;FQ#c6h2Q%oZl%*cgtsa!LoDV(No)fQFh4|7~FBNv8|Yi2Zs(-f}S$+h~8 z!v#08j%j3?8x7&)htZC!mOU+GK%xlOM*K%xlOM*Vg_|;i{`M-b=;>H?odtWSScd;pB($Gu9dJC8Hhv6(lbH zGwQD(@g_Z<8F`1DQGeFKg>l9^&pLS1IHUdwlG$NK{g-Pl4C9?=$h>J7UF@3K8M$D_ zd>sHL4C9?A^ZdJpkw2?vMlP69e+7vP!+7TvB;GWP`YT9ghZ*%(khn06cV0o_O~a_a zf@F4>QGW%A3&VKl6(rs?jQT4`W``N|SCF_cjCX$T;7!A*zk+0Tm{ETPi3`Jc=M^O0 zG>rNyNM?r`>3hT2ofQ|lk#_C?pucl0kAIg=ptq{=UNS25*B-erjCWpp%U>F4ZK*crO|6{CBCG6J|8YG2Tl?J0>|)7?e@6YaN8U7yyu*wpImUa*c;`Q({@NpN8b;osM*7|` zJx40^Ta}7CM*W>*G!9)*0Cd5OCOO7?$#~~Kqj{gBzlDq$4RWTA*PnIJPkhmzb#P%C zS(9F29&hqXH9D@ksWqmN3Vx}qbH_-vZq$X7A5S~3x@mR#yMnpkM%FQnOmm|locu6m ztS_(E@5#AfMlK8^*UV@Nrzu?Z=I_W{aHHGr$h^so=I_X6$5l^1v53dP1vj#ec}AwW z(GX647{65W`D#5Ay79l~tGuZj^(U^>s0$bUl~;de#RWIAj(J9=xzP|#ei%Qa`CP7^ z32tPK%xlOInzt_J$Lr+!8zxRD9d$TT+^ z!pV>4Mw6TdCb-d!9Ny$clN__-YA}D(;es38e$(MiZZv<>F+0>~y!6C{ZloRaQrUNP zqb{8MFn+1@*E9WRWP%%+FpW%eqamCPhHy31*6WWQTyP`nm`0|#(GX647(3(4l3M+x zCoY(g3&Y4YGn&F_3fKSq2!nprwUtE`KtJAqeHH=G4;2FXNd$l%vTU$yp`U6*d-U^- zs2C6EF~DbmxIn7_?Om{>gJm&TkI|1j0Q)Gg9|Dgs@R$aU{ov^fUOm9;De$&}cM14x z0iS=tuO;}c1;0PRe=r0rgMcd#lmtN!K+x9^d^d#5gpki5EC9l$K-d`w&w+?ChY`vM*FEgsN|$x+_#a2{q?oN;{~nhuV*z&Ixs^ zp#B}0+5#HJL&NJZjedOC{V@F?%m{^<17PMeaGwv{R|&Irz-$Z5=>T&!!mPy* zM`2?uY@7odFTkb{*fbS3?}IJgu%!aFybFyQG#10wO|bO_JTVHMI0R4r4%-I8_9d|W z2iVaAc02`7HNnn~@bq+e`cv4|5_YYH-KSws7VIsBy>G(4B-r-=JaZWKN5Zp1;MwQl zxd3=>3Ov6HUhseyJHv}x=|^3`fpPHCdU&ZB4&}n3hvCrA@N!>xWg)!sEgXq~BeUVi zd3d!QyjBmdeFU$2!RwRZ^>^S{3wUEZyzx35{|DY232z>R6QS_d0C?*eIC&Y~?hbG7 zfOjnLZU=aGGo1Pa-YbCj*1&sz!26l-{!%z|96m^d59Y%M7vZA__-F>4eGWeMhmULE z~`0NOL{x^Iv6wa@J^FP6bK5$_-e0d4J>H;^*cL8s zfUiGTBi9pUfk@b{;1%@3|s!?n|JJq!LR zg@4|J8@J%*7`S;D{*8oNL*Ul)aQiBP-UxOf`mtWPGs0UD`5b9&khUIa&B&UItPdmG zNn}q&_Jzp)Epo&l$86+z0C@!?uX^P55%TduK9iB}HsnW;-+1KrI`aPq1&l<2t5M)@ zC};o*dIkkwMj_o%=v)-~6$>J4%{}k{eO-ZIs#?r9O&M|3+y;QHvF*#ZM?B1!X*lGA^Oa zE+}gj%K8H31fiTdl=C6V%|m&UP~O|fg^{ZWxsIazSX3|q6}*I6{)$@lN3Hgu*50U1 zH`Hc3YWpQ>cNc263AMX{?#f4ZJ%T!%LLDM-QSEJ1-x}3F zil&}H4LPV`1#0*SO;177A4D@=MKhz(%vosW7id-xnpKBp??H1s(VR(W&f91%MsthM zyp3qybu@njn*S1d;8(PuKYDNxdhmO+up3&q9X<3VT67m$+<+E;jF#l1C6Az`r_izt zw0r_u{svl+fL6>y55J67hND%3(5h$AYCp8P8a=WTt+AoCozU9H(b`*R-5B)fI`rsY zXhSyIupDi;iZ=E}k1arteS5aD_Tgyz0kk6+J=G6AwHNLD4n2JjdU_k$MbPf{X!m1i&sntBh4!vSdw)aEq@!mR zqy5Lwv+?NJx#-!i(DPyF`Dy5d{pdws^kNly@jdjC6}?n~4sJmQ|3!!HMTcHNFaL>N z8H^4uLx-=RBfZd(r_rllqu1_6M`xm=pP|=Vqt_or$IhTPa?tTIbo?#!W(s=qL3H9( z^j0)FISieA5xpIR-mXLM>_P8(qElVbsVC8U7`<17PH#k~ucI?gbY>Mg^DFwGKl*SH z`tW;nHV&P=AD#UYeS8=Cqyc^MF*@gi&Q+pwr_g5^=<^Ba^Ec2JH_`dg=={s*LOA+z z5c=|2^wp23sV8dMi7wjE*PYPUkE3tSp-ZjMrFH1iU+BAR^xbmw{RwnA8C_n0E`Ni5 zj6y%&hpxPUt_Gs3wdm>x=w}D|xg7oS1pQzn^lKsd^)>X{HT3&%^v6o{$1mv5e(2A= z=&$e4-}j*AIjH#py4D_DdkkGai~ez;8x`oryXa;*y15wrdko!*N4H0z+lMfOVVH)| zevExF>4C{pShHfS1Y5RX%fHyx65G~d+n?Az7<(+k9#^nu683xmdwz|*?#A9TvG-@# zHvs!i!M&!!~SpKK)`|HaNw&rC>jS3!@)1&ke_jAUmUszhk4@gt~mTj9C02; zw!@JdapZLz?ZnZmaLhY6wgrw|gk!(Q@o_l*ew=U+Cx+t02AudYPWHjcl{jSwPPO3F z2{`o)oOTnp7>(1{;PgLm#vq*WEYAE9XZ6I{^Kte?oYM*CJdShE;k;JZS%aPLV^=nI zEywvMa6vL|ITp7(f?Gx5R`=o7FW@$TxNRTYb~kS4!0pO$`zP>S2zO|UJ8ZxmuHlZu zai^8I(=WJl8t(iM?))9@au4o02Y0=IyM^FxQ*pPmxVsDYsK7nm#l1A#s~Gn>hI_~3 zKBI7-L%8qnxZgnBZ$IwuiwE?;1D?VIoA98Hc+eI+=wCdfB_6UC4?T^CW#M7V@USa* zL=qnH03LZ5kBY>jX5vww;d=w{y;Ja*U3jbq9$SXTzJ&_`7mmY4>v2&t9zP6^e-Rh| zj3@NPB@1!Mx45(`E`1VDJdexT;qrQ1{t=$!#FJLx$?xEb7PxXeu6!L=#o?;^arHr5 z6N;w{z*C;VwLZAE64&j(^%gv}1D?7WPrZp7M&oH~@U%bhj7&UZDW35op4k)MHy_`3 z5zmgmvuEJh=kT0X`2HGv|ND5J9nYJH=bgawlko#%@dHQjg1_;DL-B(z;Dv$sp+5Mb z-FVR@ytoTq`~+Tt@Y1$;=?1*)L%ci>FJFn5|AHS*!w)}%S02TyV)3duc+~~`NCul2@jEAZNP@uM1kv>317gxBA|8%E&`hw#SV@nZw=rX_gO4|sDAy!k1-r3pXY z5jRf9ji2JJE%Da1_=(f_$t=9B6mNSIZ%@M8AHX{f&CM zgb#Y*gOl;WckrPW_~r5V<=62m|KP(T@!^B`NGN`F0Dkou{Mu!Fv^ze!1HW#;$2#C+ zoADc;;Nu1O_!@lt4}2mMpID0DI*v~!;*<07$&2`%2>i|r{O)u3ls`UIgHOGWPuub7 ziTM3S{QhlxW-LB)1b^^1{%|P%Xa)Z0Cw#UKKD!%#d zkCDW&nmB$Vo&$*IGsNpM@$OE1<`SQ;h;IktyP5cXLi`IzKotpij|66tz@;SUI0;T9 zA@`DyS4e0C37tX0o+IJ@B%&9Ic$!4oN#sNl)kvallbF^d=1~&!H;Ele;#QEjpGZOq zNqCSXTq22GNYX5l^aV)?A}MtwxdoaEi3dAT5`WmOqfz38eKr(&lB-Hk`Db zPTGD-+WV3A)#R?7q=SugC?y@&V@IkHazC(T4P_B|SeNy>dyfhe_{~q)#g8TS)r8M*78&ezQsc17tuj8Q6~u+)D;| zkwKHm;BEA?Hp$TTWawjL=s#rGNHTmi8U7m?nNCJ7CL=GCQQgVtxn%TLWK0+tGmVV- zgp4g9mCgqK! z{5F}~noNF_RGcA|Iizw0sr-plr;zFgNzJQdN;H`=i%j`~)CG~cI#R!fO!XvFCy}Xd zlWCYtD?NdosHlnZ2FN`I6j!7n$2Y=6+1(<&$}j zkol*`0~ut&1hU`_@?Zjaa2{FsGI=PREE+@>Jxdn*k;T~aC1G3&h)|Zp@C&`9X zvayhCe2qMIjcgiDHXR_FgUObDWXoRi_;;l79@4mtY$fE0_T-7j$dhNuHW%5pnr!=x z>_{g&7L%urk)82m=UlS$E3zw$?3zY)?}vM3G>^0HzCr(5 zV!cs*eSqc0Vfy#K11vYEgf!1&%_id}L!v^Gnw2UN>F}p4Gf_V-MSn)z`aO?zi5kzWJ@CTkV+Y0g(%5H9xv>inT}C z-Ve9O9%!~(nrB%*yD`Ob?aKAu!PRpYJ~(^oxV?8p-tf!q9H04G@8;BgvCRR)pB~pf zqV158ZIfDl(A<7z%&Z%$Hd?nnynf^6gS$(Aifj(~{z9|;%gOKExchAE4X-1U4tx~x z;j4!)e0wVAhUfa2jm-_#Tfg5Z4!+?zs!v8tn`>~vdgXAR8=kSvr;Y|U!;LpBH>Oyl zEX%Hq6LnM1!$$w`&UMb2CVucP4ciYhs&Qn|>Pi{Nz>JYG>HCsisJIdc)b zj)KQ4s^p|f-ctw?*RH6;*OlrE-xo z7s2Z&c)X%YPO4Nca^@m<9R-h9RLMz|%0iI z!Q&NGa#E#okuw*;>nM1!$$w`&UMb2CVucP4ciYhs& zQn|>Pi{Nz>JYG>HCsisJIdc)bj)KQ4s^p|f-ctw?*RH6;*OlrE-xo7s2Z&c)X%YPO4Nca^@m<9R-h9RLMz|%0iI!Q&NGa#E#okuw*;>nM1!$$w`&UMb2CVucP4ciYhs&Qn|>Pi{Nz>JYG>HCsisJIdc)bj)KQ4s^p|f-ctw?*RH6;*OlrE-xo7s2Z&c)X%YPO4Nc za^@m<9R-h9RLMz|%0iI!Q&NGa#E#okuw*; z>nM1!$$w`&UMb2CVucP4ciYhs&Qn|>Pi{Nz>JYG>H zCsisJIdc)bj)KQ4s^p|f-ctw?*RH z6;*OlrE-xo7s2Z&c)X%YPO4Nca^@m<9R-h9RLMz|%0iI!Q&NGa#E#okuw*;>nM1!$$w`&UMb2CV zucP4ciYhs&Qn|>Pi{Nz>JYG>HCsisJIdc)bj)KQ4s^p|f-ctw?*RH6;*OlrE-xo7s2Z&c)X%YPO4Nca^@m<9R-h9RLMz| z%0iI!Q&NGa#E#okuw*;>nM1!$$w`&UMb2CVucP4ciYhs&Qn|>Pi{Nz>JYG>HCsisJIdc)bj)KQ4 zs^p|f-ctw?*RH6;*OlrE-xo7s2Z& zc)X%YPO4Nca^@m<9R-h9RLMz|%0iI!Q&NG za#E#okuw*;>nM1!$$w`&UMb2CVucP4ciYhs&Qn|>P zi{Nz>JYG>HCsisJIdc)bj)KQ4s^p|f-ctw?*RH6;*OlrE-xo7s2Z&c)X%YPO4Nca^@m<9R-h9RLMz|%0iI!Q&NGa#E#okuw*;>nM1P&9x?X)pi+00;WVI~P#bZheM;9W>g3+qdBt`WFHWgmx@o1snaI2ROhJyucfL zz!&_$9|9l{f*=?|AQZwN93mhRq97V#AQs{v9ugoCk{}sUAQjS}1*Ag;WI`5XLk{FZ z9yq}T`A`5Yp%t`-HqaK@L3_9hIzUJ01b0Jc=mK5g9_R+$p$GJYUeFu*Kwszw{b2wM zgh4PEhQLr52E$k*aVwl3p@^uuoa$wCt(|GhaK<~?1ZOb7wm>Tuow2hGq4|? zh3DXTcmZC71Mm_YghTK$yaI>e2)qif!BKb}j=>vn9NvTz@D`kex8WUl7f!)@a2no+ zGw=a?2p_>&_!vHcPvIPV2A{(ha2_tem+%!d!A1BQzJW{dEqn*x!)5pZeuOJ<6@G%B z;g`O{`{Y?R^&8sPX?bG6pq|4lJBPRi53%eUGGOok%L_&08%ixN(^_dcN^70vL{VvN zvE@|JtPb#jr`V?1`PqYRV*H9f%TvJzLjVrF3R%T5po?2UH%`9%n&9ypd&9kuGIm-9l>{>$c(sXRdV@t$Eh{v^uQ^Xmwc+)0%HRMr(of zB&{v2r)h0vJxgnA>*ut#u{ISqxN@!E(VAzyN~_cQJFPD3HCpqnw`eV}X|%SqIcRNV z^P{!3ErixKwy5HU{9IcCt$DUITAj9RT3xn$TJvpfX)UmIqP3;18?CKueQ0fM8$@dx z+lb+ptZm@i`JI5`LwpOEuyuxZ3V4uY-@@eTISj| z(wb*$q}6HLL95HQht_=CbF>!N4$|7v_A0HdY{zMBZF`5-Hnuax4Xtu*pU|3TJ5Q_A z_BE|8+htnwZ9mgmVEdESmbQOrZDj{qTidO)wy}E^H?+>R2hf^l52Mv-kD=9NPog#7 zo=$6lJ(t#&_Lj7^vbU$TwY@W~ZR|aY8`|XB`_Y`Rb6RcS2De(-oB}nvTA>#w7kk`-$|>> zzK_--`wOMDMaA})OQ)4jupcceswlOeptZ_=iq?Ajhh=Qqxw6Uh$S=#-%u8ie6D#aL zmQ_!xw*OkjTz{8WmDk&Eme*BRc;NE-q6!cDBnN*XT?-4Yqrd4Z?h)FfAT^@0h zYTD#_q)aZUt@6mMC>=k+!%0ULd9<#WR9WrOp`vPPrAOC_>f#EIUKRDVMIHlat@IdH zSyVgO;cglRfGy>q_c9W>&E?&aJ8_p6s!(YU<>Ak7aaN zt;gzWHgkP-4L#SE>e>la9^0yGt13Nq)v)9D*Ay4kcpRvqKb^v^=O*H>UXt8RTDg})=sW1_4vJ({s11=YHP|$J#N+3kDuVs zYU?YC91dD59e%Y_$Iozt)X{S}qUy@4N*xJxH}0Kx=EqBwE`zYU=9pavcq{<~e53>U7Mf z)#X@3YrbOztp$!Xw6=6?q_vf!k=E9Z9kjM_?5V4B<~p9EHP3OdZtD0t$E$TyYw8@w z>!#I}Io_!+udi^Nsi(O(KB=!Ns&t&Mr?-#eYZ}W0$K`r@J2-xxT2)@`__KlibpJFI z)lc<=hLYNPPiq53$J48UdOZUg=xys6)-buY$}^^c-sql54Yl=7&-9rkwbh=v{E?SE z3?u&d%pQfACcLu8XG9;7S+(+NjMs2pBY2JEHHugIe1aYy!)q+BalFR!n!sx!uSvWn^P0kIDz9n0w%|3L z*9=}WdClTAo7Ws(^;;>AYbUQRUh{b^;I$>Mt$1zCYa3qM^4gBq_PpN3YX@FC^4f{l zyLs)*YZqR-@_G-i-FWTJYY$#~^4g2n-n{nVwJ)#zcm*($^IE}c zC9hSyR`XiJ>l9vVd9CBMp4X|oHt;%)*Xg{@;B_Xi_whQ5*V(+z;q`uA=khv_*ZI6Y z!0Q5DALMl*uMhFMh}XruF5z`4ugiE{&g%+ZALex>ud8@n&Fdq)uHkhpuj_byl-KpV zZs2tzuaEJ%iPz1%ZsGNDUK@Gc%Ig!nKFRAgUbpkQgV(2c-O20Iyzb(4H?Mnm-OKAf zUZ3H0Kd;a7`W&y%^ZEj>FY)X7(!|S`ep5paAUQhG-KCfqZ{eagGdHsmjv%G%H>nFT^%Ii5^ zKjZatUccb=Jg*mc{gT(Ocx~eKBClWb`VFs_c>R{w?|A*5*UP;A!0V5^Ug7mBuRrlh zpEaW<9ES^WBW@ybq>wa{CM`}Y)Ec!WOPr<9(r9V2##sxkjn*bxoUPE-Xlt^^*$eHB z_9l-wk3x?|k0wW)qtMalX!4BnEc9&jZ1RfpD)egfYVwZrF7$5nZt{uqDfDUdY4VNp zE%a^lZSsrrEA(shYx0ltFZ6HpZwiPDC=6%}XbOxAEDUT6Yzm4CDhz52Y6^}EE(~rA zZVHJDDGX^0X$p-CEevf8Z3>GED-3H4YYLAGFAQ%CZ;FVED2!-~Xo`%BER1Z7Y>JAD zDvWB3YKo4FE{txBZiNteK; zyE~Oo1SOPELfIgtgc3?9p@b3&sDuK#!2kmcFu(u<3^2d|1KbJ*7+`<_>V2Ncblfw> zJ$wEG_wyN?C!D|GIQX&QTc(ofWTry0LaIW#LZ)J}Vya@gVy05EQmRtAQl@gUa;kE= za;8eMN~%h_N~UVEYN~3wYNlGUTB=&QTBdrkda8Q5dZtFQMyf`-My6)6W~yeoW~NrM zR;pIIR;G5ccB*!|cBW3UPO472PNr_MZmMp&Zl+$cUaDTYUZ#GseyV=Dex^aPL8?Kz zL8f7{VX9%eVWv^CQL0h8QKoUSajJ2;ai&SKNvcV@Nv3JCX{u?uX{K4SS*lsOS*Cfi zd8&E3d8S3OMXE)*MW$u4WvXSmWu{fKRjO6GRi<^ab*go`b*4?SO-g@{&5hs7>f-y} z0*T^@a*3)~W6|mFg=6XbuK4sG@cT1=FV2In5sx2H;{Wn_6O>Qz`)7JyNpvRi`4R;U zzEFbl34YH_FC>Z1M80sMn8BAwP#*t(PJ0PSURrVCOD4(~eAxu$6a3zuURDyFiU0g^ zi3$c^DM9%J-vj8CB+;43S58zj_!n9o+e3Jy_6MU2!(heNo zMCk1#(V57%$16#8z7yV0I)URm3cZsgIurQ|@UoJf?}|5vFWz?gg5w(xy{{xX6Zw94^~uf;#Cy;{aC{e{50pe_ zBA>!bQFeYP-jIfZ<69Das3bZQ`C)in%Fd6(yVFQ;e1D>kltgDDKMF5W+4-?}s~QWA zZ&viNlITq2$Ke$#J3kTcTNA>8yH2O?QbSCn%@WPgzpNqG*x#0K)N1rQ+&P0A5Ugfg$3-MmJ5FFp_=nEy$ znaD4~OI~(<3EudYfa6;qeTgJG6Zxfh{mag;z`NiIaC{%6uaHD%BEJ$ZhS~YmcuQOj zj&F+e)spB;;Rv-3ys-!qPa!=K>A zk4o~=eiZ&#;unKIo}hfjcq@>jy+ zK?r}r@jvP?@{x;TgU=N~;LcFb#e~lN4B>M}c?~{)1mQlPdVVH!?)ii-5EU}`A`yi9 z!s`>j37vau;oC;-48B7I;l90k2PSmx?S=0cbu#$Q5rq2- z)H^ewbH70NE>Ty5?;b(8@21|J37va4;d?|q4Ze2-;l7u8Zzgo^y@c-*^)>kZ5rq4G z>iwC}x%U%(Ks3Q|g15(7C6C9~=!e_~8+R`(f(Cnb5fp6MjTA(%?r&5bj5* zk7h#WK1%p8(O82YA3?Yur#_wuo%=Z9CqxqsesToievkHTdZfg!^gg z)0xn@PZNGdG}GW`M-c93sn2FY=RQmLIni8$pC3WEpQk>b37z{q;TJ>;4SsP1;eL_& zVkUI%i-f-;T4M0aA_(_O)t51$b6+a_@@R#@uZketuT)>fgwB1X@b^Zm4gUTJ!u=Zc z`J%Vt* zL;ZCobnZKZe3dD6FT>O!haI&H~7yZ2=@onKW9Scen9w4bkN|xiXhw{QvZqxo%}f^dIK{U;`L?#G1xIXZ6ezeN!4PpJRKgwFkh@V`eV4gRkP z!u=`rznIXupA!CWhd+qoPq_c}{nL3W;hj^Lgibl~F1TCsW z4Zfg*a9=>ZAQL+G0>Yo=iWqz`2jRY`dNC$+?nQ+!?n)Va83*CMw0apPbnc~vKiicz z_zDifeNw#w6FT>#@D*JZgRkZw+*ehv#)Qtjs_@laErYM)Al%nhufv4Sy|(amT?2z} zX$O1bMGVkWv;)$U+y5>4^Y3H37z`@;jeIm4E{<7;eN3Cl}zZ|2Ma&M4LA6! z9EAH3>Q^zLa~~o6)o!%GU*jO$k5Rvd37z{G;jeY$4gNX@;eLYpbxi2oCkTJNn{4nm zI0*Ms)Nf!y=RQUF8{Kq+zsW(kpP_ye6FT=9!r$y>8~iN}!u=feTbR(f&k_DsH{alI za}e$qsNcqf&V7OKx4Xp#f2V_Re~0>=Oz7P25dJQ=%;4{K5bl?&-_3;1eYx=WxK##! zpM!9JuljvV=-lrWKJD%|_y-+?`v=q?WJ2fufbb8whYkKw2jTt^^+%b|xj!QOWA1T- zf6_s?e?t99CUovk2>+CO+Tfpc5bmE*f0hZI`!m8n=bktC7afHA7t~*5Lg)U1@GrTS z4gOUJ;r=mkFKwJHo%` z-Z%IU9fbQ2)IVfG=l+54AGwbW{!<6x{uA|2nb5g^BK&9WbA$iFLAcMTf5C*#JtO>= z?kj`;#zDCMTKyX)bnagZ|E>GZ;D2xs?!Q<6feD@a_rm|^elqx99EAIy)qi0^=l-+s zzq;QH{tpM?{&)31n9#ZZF8rVFFN6QbLAd{0{U0WD?thc_3C};f^2dMq@Ap2Ya1zvG zCUovW_%nPSgU{;K*cUVS5+1^RarF{R z=-i77U(%N`__7|t{n_eenb5hPEqpm&!Qd--2=^7$D>0#SuPA(FU(MiacnJ5^)oU=J zbFVIZO<%|0>v;(Gb=B)Jp>wY*e0|@@;G1{|_l?z?FrjmAEPPYn!r)tZ2=^`3TQQ+? zZz+6he~!Vo^APUORd2_H&i!2B+xznjzLSS=f4+JrCUoxS3x9#X(BQjz2=^DMcV$B7 zev$Cq{KW>}(?htwM7<{yI`>P2@8vHw_`V*({blNXnb5gkCVW4Cxxo+g5bm!~AIOBx z{R-hz{z`)%>LJ_@Q6I{L&V7jR!~9hSKhi_Ezgm4H6FT>+g&*awG5E0_!u_@CW0}yo zUn~4Lf1SZk^bqc^SD(m)&i#7fC;1x;eyWFXf1~ml6Vsy>$qo%^lA&-1q#{6Y`m{&w|+Oz7Ni7k-hy)8LnQ2={lXFJVIG zewXk|{oMw?!b7;fM|}koI`?~oU+M2N_|+c5eOi4r6FT>_@N4{o2EW!rxPM4}EfYHT zhlF3}A2s;(9>V=&>g$=%xj!cS2LGhNZ}brEpHkn*gwFjb;Wznb4SutSaQ~e8W+rs* z&k4W9zi9AVJ%sz0)VDIBbAL(rZT?k*-|ivYzox#O37z|E!td~J8vITV;r=c4olNN5 z-x7Y8f7jr5dkFXMsqbb&=l-7Xd;Et6zt=;!|44l=6FT>ggx}{sHTeA=!u@CJ`CACUoxK3V+1^VDLvhg!>=Wk20Zi z|55m3{uhHk?jhX&s(zdao%^rCpYVSe{7Dbt{!jIjOz7PI6#kU|Cp#Y^DuF+0sz*%d z+!N%33$elH3J~tkP|wAL&ixGGbBDYJpFcpj&!?WB37vaB;R}R9245sVxG$_;gbAH{ zVd0C05(Zx?K)5fdUWy5wdr9F-hq4A=K0vrHr(T{3oqIXqlcAEqR|ydAE2~#wLg!vt z_^P3X!Pg29?rW;oVnXL$Q~27Up20T=5bo=%H()~NUSIfzp^3pa3lQ#`syAao=iXHK z=Ao6rw+RsLTdTKWLg(IE__m>)!FLD{?%S((U_$5KUiglolficm5biHf@63eG{Q}{; zgsukPJwUkcrrw+o)Ug=7;5mt1BClw>cg4PxepV5L>OuCqXUHdQR<_a(7BHieoPo^ z@Z$r7`*G^ynb5h96MjONXz-H*g!@VAlbO)DPZEAgm}>CT1BCl&>eHFfxla>*Mwn^v zvjc?tS?aTy(7DeNeomNc@bd$N`+4f~nb5h<6MjKhXz+^zg!@J6itm;{Jmkd!QUSs+^JNLX+1j|T|%8`K|XLg&6g_$R_fgMT_exZkAyG!r`aO~OADHXHo& z0mA(j_2-$;xo;8vg|OA&Uk(uNx2eC(gwB1N@UMjJ2LF11aKA(SbtZJ~JA{8D>@@hd z1BCls>TfflbKfQWJ7KrMzaJpn?@@oB37z{M;Xep_4gTW*;eMa`$4uzl_X+<=*l+Nk z2MG5E)IVoJ=YBx=OgL!pUj+#Fht$7fLg#)+_^-oZga0l-xId!)9TPhDBf@_ljvD+= z0mA(;^`Dr~xgQh$=WyKMe+v-qPpJRKgwFkh@V|$X2LD%paDPhuFD7*Er-c7IjxkI{F!lngD)6ExG$hykO`f80pZVzix_;d z7{Yx~^r=S{Mm7NgRc-nxKFBAU_$4f6ux3y#o(*O z5bmq0S7SowURC(&aV>+d6GOPKtzL%-oqKKJ>&6WXzEKR}zM*;}CUou%g>M`;Gx!!U zg!|^|Ett@`Hy6HT+{WO~i6Pv#RX>LboqJp1&y716{CP2i`;O}8F`;wsDE#?xXM?{m zhH&3S{X!;m?p=hxDDH0X7sn9pd#GQ`gwDN(@R!8B4gS&?!hIk0OPSEQ_YwZGxWB<) z9z(bvpnf?MI`;v>Ul9*7_$y-w_k-21WJ2dYSok6FaD%@phHyVZ{VFDO?jwZ1Iv#EC z*TfL+$EaV!gwB18@YlxU4gR_q!uzL5FPZ0k4c(TFY5JR}1qJ9GtI`=8U-xyCf z_?uz~_cPRQVnXLWL-?EH*#>`04B>u``YlZ8+~){?YdqiJZ;K(^FHpaY37z`_;ct%@ z8~mLyg!? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __familyName__ + + + Regular + + + 1.000;TPSP;__familyName__-Regular + + + __familyName__ + + + Version 1.000 + + + __familyName__-Regular + + + Tal Leming with modifications by John Daggett + + + http://scripts.sil.org/OFL + + + __familyName__ + + + Regular + + + 1.000;TPSP;__familyName__-Regular + + + __familyName__ + + + Version 1.000 + + + __familyName__-Regular + + + Tal Leming with modifications by John Daggett + + + http://scripts.sil.org/OFL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endchar + + + -102 787 hmoveto + 31 119 rlineto + 203 hlineto + 32 -119 rlineto + 246 hlineto + -213 700 rlineto + -296 hlineto + -213 -700 rlineto + -477 hmoveto + 237 244 245 162 -245 130 287 164 -524 hlineto + 1586 -700 rmoveto + 518 180 -281 520 -237 hlineto + -332 -700 rmoveto + 237 700 -237 hlineto + -434 -196 rmoveto + 60 -228 rlineto + -120 hlineto + endchar + + + -107 394 306 rmoveto + 153 86 82 115 115 -86 82 -153 hvcurveto + -294 -15 91 -670 -91 -15 297 15 -101 291 hlineto + 632 -291 rmoveto + -15 276 15 -67 vlineto + -254 690 rlineto + -12 hlineto + -219 -593 rlineto + -69 -25 -46 -28 -59 hhcurveto + -5 -15 259 15 -26 hlineto + -67 -35 34 71 26 hvcurveto + 43 116 rlineto + 232 hlineto + 78 -221 rlineto + 599 695 rmoveto + -28 -11 -5 -6 -14 -22 -44 34 -78 hhcurveto + -124 -91 -73 -106 -95 52 -64 147 -61 hvcurveto + 126 -52 30 -44 -79 vvcurveto + -81 -55 -50 -81 -103 -85 70 168 -17 vhcurveto + -15 -253 15 hlineto + 22 4 13 15 18 45 32 -37 98 hhcurveto + 130 92 82 116 83 -32 66 -173 73 hvcurveto + -120 50 -33 43 72 vvcurveto + 71 51 49 82 90 65 -92 -119 13 vhcurveto + 15 226 hlineto + -1118 -207 rmoveto + -119 -49 -63 -96 vhcurveto + -82 364 82 hlineto + 96 49 -63 -119 hvcurveto + 312 53 rmoveto + 108 -305 rlineto + -221 hlineto + 1420 459 rmoveto + -28 -11 -5 -6 -14 -22 -44 34 -78 hhcurveto + -124 -91 -73 -106 -95 52 -64 147 -61 hvcurveto + 126 -52 30 -44 -79 vvcurveto + -81 -55 -50 -81 -103 -85 70 168 -17 vhcurveto + -15 -253 15 hlineto + 22 4 13 15 18 45 32 -37 98 hhcurveto + 130 92 82 116 83 -32 66 -173 73 hvcurveto + -120 50 -33 43 72 vvcurveto + 71 51 49 82 90 65 -92 -119 13 vhcurveto + 15 226 hlineto + endchar + + + endchar + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/fonts/gsubtest/makegsubfonts.py b/layout/reftests/fonts/gsubtest/makegsubfonts.py new file mode 100644 index 00000000000..a8aedef0f26 --- /dev/null +++ b/layout/reftests/fonts/gsubtest/makegsubfonts.py @@ -0,0 +1,486 @@ + +import os +import textwrap +from xml.etree import ElementTree +from fontTools.ttLib import TTFont, newTable +from fontTools.misc.psCharStrings import T2CharString +from fontTools.ttLib.tables.otTables import GSUB,\ + ScriptList, ScriptRecord, Script, DefaultLangSys,\ + FeatureList, FeatureRecord, Feature,\ + LookupList, Lookup, AlternateSubst, SingleSubst + +# paths +directory = os.path.dirname(__file__) +shellSourcePath = os.path.join(directory, "gsubtest-shell.ttx") +shellTempPath = os.path.join(directory, "gsubtest-shell.otf") +featureList = os.path.join(directory, "gsubtest-features.txt") +javascriptData = os.path.join(directory, "gsubtest-features.js") +outputPath = os.path.join(os.path.dirname(directory), "gsubtest-lookup%d") + +baseCodepoint = 0xe000 + +# ------- +# Features +# ------- + +f = open(featureList, "rb") +text = f.read() +f.close() +mapping = [] +for line in text.splitlines(): + line = line.strip() + if not line: + continue + if line.startswith("#"): + continue + # parse + values = line.split("\t") + tag = values.pop(0) + mapping.append(tag); + +# -------- +# Outlines +# -------- + +def addGlyphToCFF(glyphName=None, program=None, private=None, globalSubrs=None, charStringsIndex=None, topDict=None, charStrings=None): + charString = T2CharString(program=program, private=private, globalSubrs=globalSubrs) + charStringsIndex.append(charString) + glyphID = len(topDict.charset) + charStrings.charStrings[glyphName] = glyphID + topDict.charset.append(glyphName) + +def makeLookup1(): + # make a variation of the shell TTX data + f = open(shellSourcePath) + ttxData = f.read() + f.close() + ttxData = ttxData.replace("__familyName__", "gsubtest-lookup1") + tempShellSourcePath = shellSourcePath + ".temp" + f = open(tempShellSourcePath, "wb") + f.write(ttxData) + f.close() + + # compile the shell + shell = TTFont(sfntVersion="OTTO") + shell.importXML(tempShellSourcePath) + shell.save(shellTempPath) + os.remove(tempShellSourcePath) + + # load the shell + shell = TTFont(shellTempPath) + + # grab the PASS and FAIL data + hmtx = shell["hmtx"] + glyphSet = shell.getGlyphSet() + + failGlyph = glyphSet["F"] + failGlyph.decompile() + failGlyphProgram = list(failGlyph.program) + failGlyphMetrics = hmtx["F"] + + passGlyph = glyphSet["P"] + passGlyph.decompile() + passGlyphProgram = list(passGlyph.program) + passGlyphMetrics = hmtx["P"] + + # grab some tables + hmtx = shell["hmtx"] + cmap = shell["cmap"] + + # start the glyph order + existingGlyphs = [".notdef", "space", "F", "P"] + glyphOrder = list(existingGlyphs) + + # start the CFF + cff = shell["CFF "].cff + globalSubrs = cff.GlobalSubrs + topDict = cff.topDictIndex[0] + topDict.charset = existingGlyphs + private = topDict.Private + charStrings = topDict.CharStrings + charStringsIndex = charStrings.charStringsIndex + + features = sorted(mapping) + + # build the outline, hmtx and cmap data + cp = baseCodepoint + for index, tag in enumerate(features): + + # tag.pass + glyphName = "%s.pass" % tag + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=passGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = passGlyphMetrics + + for table in cmap.tables: + if table.format == 4: + table.cmap[cp] = glyphName + else: + raise NotImplementedError, "Unsupported cmap table format: %d" % table.format + cp += 1 + + # tag.fail + glyphName = "%s.fail" % tag + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=failGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = failGlyphMetrics + + for table in cmap.tables: + if table.format == 4: + table.cmap[cp] = glyphName + else: + raise NotImplementedError, "Unsupported cmap table format: %d" % table.format + + # bump this up so that the sequence is the same as the lookup 3 font + cp += 3 + + # set the glyph order + shell.setGlyphOrder(glyphOrder) + + # start the GSUB + shell["GSUB"] = newTable("GSUB") + gsub = shell["GSUB"].table = GSUB() + gsub.Version = 1.0 + + # make a list of all the features we will make + featureCount = len(features) + + # set up the script list + scriptList = gsub.ScriptList = ScriptList() + scriptList.ScriptCount = 1 + scriptList.ScriptRecord = [] + scriptRecord = ScriptRecord() + scriptList.ScriptRecord.append(scriptRecord) + scriptRecord.ScriptTag = "DFLT" + script = scriptRecord.Script = Script() + defaultLangSys = script.DefaultLangSys = DefaultLangSys() + defaultLangSys.FeatureCount = featureCount + defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount) + defaultLangSys.ReqFeatureIndex = 65535 + defaultLangSys.LookupOrder = None + script.LangSysCount = 0 + script.LangSysRecord = [] + + # set up the feature list + featureList = gsub.FeatureList = FeatureList() + featureList.FeatureCount = featureCount + featureList.FeatureRecord = [] + for index, tag in enumerate(features): + # feature record + featureRecord = FeatureRecord() + featureRecord.FeatureTag = tag + feature = featureRecord.Feature = Feature() + featureList.FeatureRecord.append(featureRecord) + # feature + feature.FeatureParams = None + feature.LookupCount = 1 + feature.LookupListIndex = [index] + + # write the lookups + lookupList = gsub.LookupList = LookupList() + lookupList.LookupCount = featureCount + lookupList.Lookup = [] + for tag in features: + # lookup + lookup = Lookup() + lookup.LookupType = 1 + lookup.LookupFlag = 0 + lookup.SubTableCount = 1 + lookup.SubTable = [] + lookupList.Lookup.append(lookup) + # subtable + subtable = SingleSubst() + subtable.Format = 2 + subtable.LookupType = 1 + subtable.mapping = { + "%s.pass" % tag : "%s.fail" % tag, + "%s.fail" % tag : "%s.pass" % tag, + } + lookup.SubTable.append(subtable) + + path = outputPath % 1 + ".otf" + if os.path.exists(path): + os.remove(path) + shell.save(path) + + # get rid of the shell + if os.path.exists(shellTempPath): + os.remove(shellTempPath) + +def makeLookup3(): + # make a variation of the shell TTX data + f = open(shellSourcePath) + ttxData = f.read() + f.close() + ttxData = ttxData.replace("__familyName__", "gsubtest-lookup3") + tempShellSourcePath = shellSourcePath + ".temp" + f = open(tempShellSourcePath, "wb") + f.write(ttxData) + f.close() + + # compile the shell + shell = TTFont(sfntVersion="OTTO") + shell.importXML(tempShellSourcePath) + shell.save(shellTempPath) + os.remove(tempShellSourcePath) + + # load the shell + shell = TTFont(shellTempPath) + + # grab the PASS and FAIL data + hmtx = shell["hmtx"] + glyphSet = shell.getGlyphSet() + + failGlyph = glyphSet["F"] + failGlyph.decompile() + failGlyphProgram = list(failGlyph.program) + failGlyphMetrics = hmtx["F"] + + passGlyph = glyphSet["P"] + passGlyph.decompile() + passGlyphProgram = list(passGlyph.program) + passGlyphMetrics = hmtx["P"] + + # grab some tables + hmtx = shell["hmtx"] + cmap = shell["cmap"] + + # start the glyph order + existingGlyphs = [".notdef", "space", "F", "P"] + glyphOrder = list(existingGlyphs) + + # start the CFF + cff = shell["CFF "].cff + globalSubrs = cff.GlobalSubrs + topDict = cff.topDictIndex[0] + topDict.charset = existingGlyphs + private = topDict.Private + charStrings = topDict.CharStrings + charStringsIndex = charStrings.charStringsIndex + + features = sorted(mapping) + + # build the outline, hmtx and cmap data + cp = baseCodepoint + for index, tag in enumerate(features): + + # tag.pass + glyphName = "%s.pass" % tag + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=passGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = passGlyphMetrics + + # tag.fail + glyphName = "%s.fail" % tag + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=failGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = failGlyphMetrics + + # tag.default + glyphName = "%s.default" % tag + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=passGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = passGlyphMetrics + + for table in cmap.tables: + if table.format == 4: + table.cmap[cp] = glyphName + else: + raise NotImplementedError, "Unsupported cmap table format: %d" % table.format + cp += 1 + + # tag.alt1,2,3 + for i in range(1,4): + glyphName = "%s.alt%d" % (tag, i) + glyphOrder.append(glyphName) + addGlyphToCFF( + glyphName=glyphName, + program=failGlyphProgram, + private=private, + globalSubrs=globalSubrs, + charStringsIndex=charStringsIndex, + topDict=topDict, + charStrings=charStrings + ) + hmtx[glyphName] = failGlyphMetrics + for table in cmap.tables: + if table.format == 4: + table.cmap[cp] = glyphName + else: + raise NotImplementedError, "Unsupported cmap table format: %d" % table.format + cp += 1 + + # set the glyph order + shell.setGlyphOrder(glyphOrder) + + # start the GSUB + shell["GSUB"] = newTable("GSUB") + gsub = shell["GSUB"].table = GSUB() + gsub.Version = 1.0 + + # make a list of all the features we will make + featureCount = len(features) + + # set up the script list + scriptList = gsub.ScriptList = ScriptList() + scriptList.ScriptCount = 1 + scriptList.ScriptRecord = [] + scriptRecord = ScriptRecord() + scriptList.ScriptRecord.append(scriptRecord) + scriptRecord.ScriptTag = "DFLT" + script = scriptRecord.Script = Script() + defaultLangSys = script.DefaultLangSys = DefaultLangSys() + defaultLangSys.FeatureCount = featureCount + defaultLangSys.FeatureIndex = range(defaultLangSys.FeatureCount) + defaultLangSys.ReqFeatureIndex = 65535 + defaultLangSys.LookupOrder = None + script.LangSysCount = 0 + script.LangSysRecord = [] + + # set up the feature list + featureList = gsub.FeatureList = FeatureList() + featureList.FeatureCount = featureCount + featureList.FeatureRecord = [] + for index, tag in enumerate(features): + # feature record + featureRecord = FeatureRecord() + featureRecord.FeatureTag = tag + feature = featureRecord.Feature = Feature() + featureList.FeatureRecord.append(featureRecord) + # feature + feature.FeatureParams = None + feature.LookupCount = 1 + feature.LookupListIndex = [index] + + # write the lookups + lookupList = gsub.LookupList = LookupList() + lookupList.LookupCount = featureCount + lookupList.Lookup = [] + for tag in features: + # lookup + lookup = Lookup() + lookup.LookupType = 3 + lookup.LookupFlag = 0 + lookup.SubTableCount = 1 + lookup.SubTable = [] + lookupList.Lookup.append(lookup) + # subtable + subtable = AlternateSubst() + subtable.Format = 1 + subtable.LookupType = 3 + subtable.alternates = { + "%s.default" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.fail" % tag], + "%s.alt1" % tag : ["%s.pass" % tag, "%s.fail" % tag, "%s.fail" % tag], + "%s.alt2" % tag : ["%s.fail" % tag, "%s.pass" % tag, "%s.fail" % tag], + "%s.alt3" % tag : ["%s.fail" % tag, "%s.fail" % tag, "%s.pass" % tag] + } + lookup.SubTable.append(subtable) + + path = outputPath % 3 + ".otf" + if os.path.exists(path): + os.remove(path) + shell.save(path) + + # get rid of the shell + if os.path.exists(shellTempPath): + os.remove(shellTempPath) + +def makeJavascriptData(): + features = sorted(mapping) + outStr = [] + + outStr.append("") + outStr.append("/* This file is autogenerated by makegsubfonts.py */") + outStr.append("") + outStr.append("/* ") + outStr.append(" Features defined in gsubtest fonts with associated base") + outStr.append(" codepoints for each feature:") + outStr.append("") + outStr.append(" cp = codepoint for feature featX") + outStr.append("") + outStr.append(" cp default PASS") + outStr.append(" cp featX=1 FAIL") + outStr.append(" cp featX=2 FAIL") + outStr.append("") + outStr.append(" cp+1 default FAIL") + outStr.append(" cp+1 featX=1 PASS") + outStr.append(" cp+1 featX=2 FAIL") + outStr.append("") + outStr.append(" cp+2 default FAIL") + outStr.append(" cp+2 featX=1 FAIL") + outStr.append(" cp+2 featX=2 PASS") + outStr.append("") + outStr.append("*/") + outStr.append("") + outStr.append("var gFeatures = {"); + cp = baseCodepoint + + taglist = [] + for tag in features: + taglist.append("\"%s\": 0x%x" % (tag, cp)) + cp += 4 + + outStr.append(textwrap.fill(", ".join(taglist), initial_indent=" ", subsequent_indent=" ")) + outStr.append("};"); + outStr.append(""); + + if os.path.exists(javascriptData): + os.remove(javascriptData) + + f = open(javascriptData, "wb") + f.write("\n".join(outStr)) + f.close() + + +# build fonts + +print "Making lookup type 1 font..." +makeLookup1() + +print "Making lookup type 3 font..." +makeLookup3() + +# output javascript data + +print "Making javascript data file..." +makeJavascriptData() \ No newline at end of file