From d3378825d7da31b912a82739894c1833f9a49307 Mon Sep 17 00:00:00 2001 From: James Maes Date: Thu, 12 Nov 2026 13:23:09 -0600 Subject: [PATCH 1/3] feat(renderer): bundle five OFL fonts for version 2 label text Version 2 label scenes draw text in faces shipped inside the renderer, so a label needs no printer font, no installed font and no object storage: qqq-sans, qqq-sans-bold IBM Plex Sans Regular and Bold (@ibm/plex-sans@1.1.0) qqq-condensed-bold IBM Plex Sans Condensed Bold (@ibm/plex-sans-condensed@2.0.0) qqq-mono, qqq-mono-bold JetBrains Mono Regular and Bold (v2.304) The files are unmodified, taken from each project's official release archive. Each licence was confirmed as the SIL Open Font License 1.1 from the archive's own licence file, which is shipped byte for byte beside the fonts with a provenance note (release, archive URL and hash, path in the archive, font version). /fonts/SHA256SUMS lists the hashes. git is told never to rewrite anything under /fonts. THIRD-PARTY.md and NOTICE record the fonts. The OFL is not on the K22-DEP-02 allowlist; the maintainer approved one recorded exception for unmodified OFL fonts shipped as data, and the register entry is proposed with the pull request. Co-Authored-By: Claude Fable 5.2 --- .gitattributes | 3 + renderer/NOTICE | 9 ++ renderer/THIRD-PARTY.md | 29 ++++++ renderer/src/main/resources/fonts/SHA256SUMS | 8 ++ .../IBMPlexSansCondensed-Bold.ttf | Bin 0 -> 201156 bytes .../fonts/ibm-plex-sans-condensed/LICENSE.txt | 93 ++++++++++++++++++ .../fonts/ibm-plex-sans-condensed/SOURCE.md | 23 +++++ .../fonts/ibm-plex-sans/IBMPlexSans-Bold.ttf | Bin 0 -> 200872 bytes .../ibm-plex-sans/IBMPlexSans-Regular.ttf | Bin 0 -> 200500 bytes .../resources/fonts/ibm-plex-sans/LICENSE.txt | 93 ++++++++++++++++++ .../resources/fonts/ibm-plex-sans/SOURCE.md | 24 +++++ .../jetbrains-mono/JetBrainsMono-Bold.ttf | Bin 0 -> 277828 bytes .../jetbrains-mono/JetBrainsMono-Regular.ttf | Bin 0 -> 273900 bytes .../resources/fonts/jetbrains-mono/OFL.txt | 93 ++++++++++++++++++ .../resources/fonts/jetbrains-mono/SOURCE.md | 24 +++++ 15 files changed, 399 insertions(+) create mode 100644 renderer/src/main/resources/fonts/SHA256SUMS create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans-condensed/LICENSE.txt create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans-condensed/SOURCE.md create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans/IBMPlexSans-Bold.ttf create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans/LICENSE.txt create mode 100644 renderer/src/main/resources/fonts/ibm-plex-sans/SOURCE.md create mode 100644 renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf create mode 100644 renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf create mode 100644 renderer/src/main/resources/fonts/jetbrains-mono/OFL.txt create mode 100644 renderer/src/main/resources/fonts/jetbrains-mono/SOURCE.md diff --git a/.gitattributes b/.gitattributes index 0958615..e70a41d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16,3 +16,6 @@ # Stored renderer outputs are compared byte for byte: git must never rewrite them. renderer/src/test/resources/compat-v1/** -text renderer/src/test/resources/scene2/golden/** -text + +# Bundled fonts and their licence texts are shipped exactly as released and are hashed: git must never rewrite them. +renderer/src/main/resources/fonts/** -text diff --git a/renderer/NOTICE b/renderer/NOTICE index 1b7dd8e..1cdc466 100644 --- a/renderer/NOTICE +++ b/renderer/NOTICE @@ -26,3 +26,12 @@ The encoder and prime-field ECC helper retain the MIT license. See META-INF/licenses/bwipp-code93i-MIT.txt and Code93i.java. Pinned corresponding upstream source, helper, tests and provenance are retained under src/test/resources/barcodes/code93i. + +Bundled fonts (2026-11-12). This distribution contains, unmodified and as data, +IBM Plex Sans Regular and Bold and IBM Plex Sans Condensed Bold, Copyright (c) +2017 IBM Corp. with Reserved Font Name "Plex", and JetBrains Mono Regular and +Bold, Copyright 2020 The JetBrains Mono Project Authors +(https://github.com/JetBrains/JetBrainsMono). They are licensed under the SIL +Open Font License, Version 1.1, separately from the renderer's Apache license, +which does not replace it. Each font is in /fonts of the renderer JAR beside +the full license text and a provenance note; /fonts/SHA256SUMS lists the hashes. diff --git a/renderer/THIRD-PARTY.md b/renderer/THIRD-PARTY.md index 36d2467..18ffbfd 100644 --- a/renderer/THIRD-PARTY.md +++ b/renderer/THIRD-PARTY.md @@ -58,3 +58,32 @@ the Java file preserves the full license and identifies the dated port. Unmodified source, tests, hashes and maintenance policy are retained in `src/test/resources/barcodes/coop2of5`. No interpreter or additional runtime dependency is introduced. See [the capability contract](BARCODES.md#coop-2-of-5). + +## Bundled fonts for version 2 label text (2026-11-12) + +Version 2 label scenes draw text in five TrueType faces shipped inside the renderer JAR under `/fonts`. They are +data, not code: unmodified files taken from each project's official release archive, each beside its licence text +and a provenance note, with their SHA-256 in `/fonts/SHA256SUMS`. A test (`FaceTest`) fails the build when a +licence, a provenance note or a hash is missing or a file's bytes change. + +| Scene name | Family and style | File | Release | SHA-256 | Licence | +| --- | --- | --- | --- | --- | --- | +| `qqq-sans` | IBM Plex Sans Regular | `ibm-plex-sans/IBMPlexSans-Regular.ttf` | [`@ibm/plex-sans@1.1.0`](https://github.com/IBM/plex/releases/download/%40ibm/plex-sans%401.1.0/ibm-plex-sans.zip), font version 3.005 | `975dcda37d80f038dcd143c22e33ca2d97a0cc5a929aace1c749153b0fe1afa5` | SIL OFL 1.1 | +| `qqq-sans-bold` | IBM Plex Sans Bold | `ibm-plex-sans/IBMPlexSans-Bold.ttf` | the same archive, font version 3.005 | `9e6c74a889a700d707613d24548fe4ffa6bc59559a0689d2cf9e133bdcdafb2f` | SIL OFL 1.1 | +| `qqq-condensed-bold` | IBM Plex Sans Condensed Bold | `ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf` | [`@ibm/plex-sans-condensed@2.0.0`](https://github.com/IBM/plex/releases/download/%40ibm/plex-sans-condensed%402.0.0/ibm-plex-sans-condensed.zip), font version 3.000 | `723e245902b45a49f8cf602d15891bae08c31309dce7c56d209d10cd471b88c7` | SIL OFL 1.1 | +| `qqq-mono` | JetBrains Mono Regular | `jetbrains-mono/JetBrainsMono-Regular.ttf` | [`v2.304`](https://github.com/JetBrains/JetBrainsMono/releases/download/v2.304/JetBrainsMono-2.304.zip), font version 2.304 | `a0bf60ef0f83c5ed4d7a75d45838548b1f6873372dfac88f71804491898d138f` | SIL OFL 1.1 | +| `qqq-mono-bold` | JetBrains Mono Bold | `jetbrains-mono/JetBrainsMono-Bold.ttf` | the same archive, font version 2.304 | `5590990c82e097397517f275f430af4546e1c45cff408bde4255dad142479dcb` | SIL OFL 1.1 | + +Each licence was confirmed from the release archive itself and not from memory: the archive's own licence file +(`LICENSE.txt` for the two IBM Plex archives, `OFL.txt` for JetBrains Mono) states the SIL Open Font License, +Version 1.1 and carries its full text, the licence field of every font's name table says the same, and every +font's embedding bits are 0 (installable embedding). The licence files are shipped byte for byte. IBM Plex +declares the Reserved Font Name "Plex"; the files are neither modified nor renamed, and the scene names +(`qqq-sans` and so on) are names of the renderer's faces, not of derived fonts. + +The SIL Open Font License 1.1 is not on the allowlist of `K22-DEP-02`. The maintainer approved one recorded +exception for unmodified OFL 1.1 fonts shipped as data on 2026-11-12. The register is kept in the standards +repository (`exceptions/register.md`), not here; the entry was proposed with the pull request that added the +fonts. The OFL permits bundling and redistribution with software provided the copyright and +licence notices accompany the fonts, the fonts are not sold by themselves and a Reserved Font Name is not used +for a modified version; it does not apply to documents made with the fonts. diff --git a/renderer/src/main/resources/fonts/SHA256SUMS b/renderer/src/main/resources/fonts/SHA256SUMS new file mode 100644 index 0000000..2aaeee6 --- /dev/null +++ b/renderer/src/main/resources/fonts/SHA256SUMS @@ -0,0 +1,8 @@ +9e6c74a889a700d707613d24548fe4ffa6bc59559a0689d2cf9e133bdcdafb2f ibm-plex-sans/IBMPlexSans-Bold.ttf +975dcda37d80f038dcd143c22e33ca2d97a0cc5a929aace1c749153b0fe1afa5 ibm-plex-sans/IBMPlexSans-Regular.ttf +7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da ibm-plex-sans/LICENSE.txt +723e245902b45a49f8cf602d15891bae08c31309dce7c56d209d10cd471b88c7 ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf +7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da ibm-plex-sans-condensed/LICENSE.txt +5590990c82e097397517f275f430af4546e1c45cff408bde4255dad142479dcb jetbrains-mono/JetBrainsMono-Bold.ttf +a0bf60ef0f83c5ed4d7a75d45838548b1f6873372dfac88f71804491898d138f jetbrains-mono/JetBrainsMono-Regular.ttf +30f0c136e3c88e422d0791acd97238870f9054a9729bc34cf2ff0d4ed8cac4ad jetbrains-mono/OFL.txt diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf b/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7cd6f34f8cb667eeae2e7eab3b4ee7535f4c2518 GIT binary patch literal 201156 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\FmmkHp8~nE0#s zM0_ef6UW8h#NWjU@egrQd@jBa{}f+}Q{uGvO7sga)^o5R9wZ!no$YV|G&(%R80)!9 z9c%o4%bYYWR9RNCEKKJ1cJ-`|_NCNI1MbU0yE@y7>BZ3A&0R9#>|NX4rt-p8clCA4 z%&^t%=j!)*+Rsz(^|YPa)~S+hEC+&+o*q4CGL7%PQ3=NUYA#|!LHZk)$8)=b$Ru=ociVv&x&pk zjEZ%aHppU2n-qBXEq8b}cvg0IbvisxaReQZzyCPVn{mnZ6yGFlfer49x`aP>xcMeaRq+<9=i%8CuaL{;G!VA?K zvTCIV+ze@xOb=<3cg{B7bIn7|llpoGJa3ZyZHhGdx#nTL=6!?aWrOB@gXVpMHhIB~sMs(QT3+e#AA)V@Zr+VILdmi5D+1S<7+ugNsZJTK8Tock|M?ki6 z0IuoZ&>Y#dwhzs*yKh5>r?1!1rO*lQl1@5VNpRQNuI^67w?>V4ljcvOE~ioRu}Sl< z(frkN&}hD|+i+ubNVmcOUP6ddM7IrtkRJIcyvIhV9@}#Q1*Zo$$E<1VhTC@4iVods zgL=WdkX~7$e5tHd!s{-rDi7(ilR+xE(xxU2PE&PcpC1|eG*|l+SA*df1||C>Z-e_R zdNgVLnl-*nCVezrnj~G^rHxWM<5y}^{5B{g8tXzfD`YoY$cAk;l~KrMsd&P-SPvB+ znkz%L$Vd8CH=pL(kgc*f=T={%2&uCnZt}fO3vykVqfVn*r%-j)4OGusqt{CmppNyY zs>8s&rlsnLpcy4<_|@;L4hi>lj=Cm=YlDT3v%vziQ8F&15$eLz8`31f4r!8^&L-b$ z3S-qRq4qjQlSZJ)Pr+y?>NWHY8kz>P1)B{)LhmlEX%3%kK@~CCCT`BjzPf{^kan12 zy%^GBC$6c?WEY7>R^w>Vu(fFI(4w?M%T!0pR7r~v^%FkTDl=l5t@4mo^;)ZHCatzd zL9Ku*WQKY^Lp`5idoG$FvNLV)nT@hR)25**a;Bfu&s5Nc&$KoEnU=6OYP^~>?UWFg zHZ^J*H)-0MT2cu+o}2G$NolMKnWLbdqoAH+gF0lcd=x&{Mv%F-=ZgKcO+oXht~ik$C<^?c2v`MRyomu-E%YU}eY^qXYcEp2MnXf~PT z(By2AWI)?ieO76sY?QdyI;gQWWTC=sp@m!6LSI{7sM`7>>!EJk6(Ni4ZCy)pb4|!% zS)6mRPdh?T(oW0zRu<%vswNJePnF^HBSIUHdH5+<yGzH{Mw7xOFO&D-5Uvf(NsH7y4Do2w=-h_fI zG7&~pQO_x5mK&idqMm3f$eU<=W4`H}Nz9OsBxNef-O?h)ucC#{mA#m|qP#4cS`>bZ zJGxeO)K8wHpO@?W@&Wl3I=^B-zG?{-*XjJa z0r~YhzkWczY_Y&k_R{!OEw`e)S-;=x|9*vR@$QNWO`i%)pNawWsgSA$?`e8e44_Aa zrbmUQN5ueoR49#6QK9j#7=V9;#=l|!{uLVkiUIgnD9uw*(V+0EXc&N(#=oLTKW`fF zT+^ds06o;u*IiMn=}{^bJnl9Ar5gXz0r;z-Fy7Pnmkz+cRO4T&tfY!kX5%HR4PNLLRs|giUv)ST3t?+#zk5B?uuHCtFrj#-eW84=EOK|H z$t&e0a97mndg^pN%Bz6ybv??0cULr<^=O$<-U)Yw@=D-WKX2CbR9*|@YdD+rZ9~I>++S61?kZIZPfg9YdC6k zezUH>*5t4Go_-EToT^v9=Qia+^Gl7;!5{s+O7lY*fymeRC}R+Eq03d~m%9QEKgB0q zzuS}pT~4jOS0faZr}^ME<-q*TlmiW4lZK~SKUdZo_=;zJ4d^J2mzQ(^<|5lmhXg;|$|J){hwH&zh`)>1nQw~h}>gV+) z+$LN)zgogk=B}3X#;&3mS55KZL{L1g}E9qM1uF>DsNdDtq!hv5YKls(<)#&nS zba^$pyc%6zjViBH=_7bQ)pw

bufP^_*;m8y1*dxXvAjbAB0 z_?7tMSHWAYou$s4P@RsSqbrWTpcj`9A8aSwoa5*^AX*nWNX{SoB+|u0<<~P`Pmuan2R^JdTt;I;Q3d?pZ z*BYfSlHhVJ!R2lxx#e1ul)EJ*-Q`-c%XNz{*Davjtt7l$xA1apO_XbEp{)Pk$Ji?Q*ym@>jOlPMkL8{5f8J`m+ytbH6SbDR=X zm6TA)q^)xGNC^g&Z^{Ca(Uw>&qeoIU;faG zvAK1gkxHt@D1d)^z0us^>Fva99ytLBHPbvHI`EQVled&3Uks?^3=q$QbLMuQ+IQoYP)Ss)TRmQ?vgKdTz8Y}o*GGI_S9PS`>THS zyYHC#eQvwKo_k)Vr(x~cE5-?S4rcCjWB$#LFf(HUW?gh*9>YVJn{XKM{jEU>L34s$ z3SJ%jQb<(D0mt*9?$G8iBg`4LJM3`S38&L}b9i?6dErMQhDEH1xH97Th_@p{B7YZ^ z6qOq_A?kGW-k4P}kHowkJ0o^^?ESI7i|vmqh?^RBLENoz`{JGP?)Y=!cf>yue>5R3 zVO+wxgk1@H6W%r=d7lx(w;B=rdc(=@#&sXA2aG8Gv=Pludr$JOyeCDx5iG`g_lXJK z4@8sql;Pl8@#Fz|;yr>VhxC(^qQ!d*^Z)z2&+*OPV|)wV+G^DB?M5@d66IZkvak2P z#P9I#<#%}x@w>gRqpmvspi#h|_TIpsLH={dKkeNsf>3IxQH{EzMUMBMqR{(3YPt?J zT?ZKUp{D(4LF2tg(1JpZ45aQt-VuZIJFr3ka2esKI|Fr(Lw%=EPYUWO)6gH{ z_j#Y>_v6_Ec;`V}PkWC7i$lQTB>%nl1O5km|FZW(ei+Z*0S1JX11I8!diw$61HuIw zDkz+QA_|xtlUOi3#pd?-`*XD3%e`OVD<^RL0{DL+=3vdlT)@5nZ!83F7J2_J&PGcJ zH6nc2izwC?-zja6yQ6>AIAM3a2*Dpf`IKQ`Q#7yJ?uRRy+nVVm?xNk z35-rmR?Lv^Yy;o68^PeAQ_}K5BY{7R=aG0bn(EVU9_L%|);2ud?)@j;PQcqAfL5p* z)PETFhw*+2pxkd<(7aJOOdw{+9A)F>-`Kh-EVC1zG_^Cd5f1DVUTtwYJ3-x z9t7S&DkOitK&_aOV%sRsQ1adQeHgX8jCbDg9)}E`MomXh(+7~XQ>g88;O7KRPT=DNE>7Tb67U}f z{3iiFC<}I|W`IN3A4VCn0qwwbUI$?XQBj z$H3cTA_h>zqg|^Oa0>1F3m;UoLBToT|6Kge!#nc<$pY`+!1Lqa`7zMuui*I!(B}l` z zqzYUJ#SGIWm_6GK8Scf5*)7m*eW+zKa8~Uk1Jq9e4PKLa?P2J>XHbF*aJn_`P6FO_ zfR|>RIu+lbGtNgTS3+}MgOaXC`VKt1Pr`p3a{4P!at|nZOt#;bWlQ-4ygUxg5DZG* z3LFkWmwW&!ejs_3gzUZu z-v1oDKLpX_WUO#_5ft&32^HJaO(qLyH8*<9AI1q z4SE_f^jBd1G%!B~%)bzYSi?IWoSJ~E39``wZ010}&&8!EkO1rxfO&$(JQ|qq1Lk{y z`CeeYADHh2=KD0}`yusvfjJ#43e5woZveLML+U?;jC}^EKaf4;bFyuH1!xY5WFs8V z9EC)G23{NlFOC3`laQx>0Gb%h2jW2#B>8;_$#OtTS}Pbe?1gNdL@kGO+c}2$*>fS= z^U&_8&C^rT&X?g=wf)be^ilgiACx6(OZh`qJKID3V#6# zlg51u6h00LlWsT(>Sk!_z9oBp(h;WSormZ1aV_w^iPlIO7_AZVvlzeBPR@ZmVV5N- zGo&k^zwvYe@EQReNFQGZ%-*o+<1oETiZhff#32Cg0gR}X`$FN3SkfUB>7tFLNZ{1UkOfz-u^0MRMbbO1FSKrL^BL%~uT zs+L0i>v7UE5;L53Av}2AhW;xUyf`jf{}#~me5BFm%G}f7P!x0n*;nXsuogZC_@9v6 z1)qR_Hh33@r@_Ggeemc@(BN;7r}sgFFTn@0503iUGAtWFb{hDnLzE6VB%+s$RlEgPQ$cCd#`qZ0t?bw!^d)3d#7j+2{5~jJU_;FYW#*ukxuBLQ;eqxA z^#akTF&H&EQ5$3cypBYBA=pl$w3DEUscjO#AF>ma#yJbWi}01ww@$2T=tdvXYm5W^ z3m^%zpx08QUK6Cys50hvjE{Dz_b`+mKfbLegImWKubRX-T4)uChc@k<4?8~;ZL>|^|NGK9YV`K ziI)9=lxpwa!y!oEn<()hN+f&w1Kkt60?3u+5Cq*50;n7q9fZOvhyawTC%Aur z_TO*g2lao0Y5zlLEBnz_4xz0aL0j3U`@Q{;r9)^h)bH)bjt`{$AsfKpd9<5j;9D@D zI|V2rfHT=HrUV4*zJ_|+VDOCOC0NSKD*Te(5YQXPppTUm9fC6dA|?KMNd42WOy2Q+ ziXPs#0sRph z^fV?U=#M}%zBUB(du`B@!%EiBSN905&-QX(D)=qm!TTclOhOhlJr&#T7t4}RbM9i zF<7>9p~vRIMo`x6>$=swg;sYIt?oUvx=*2T(#2BnKb2D14k+B%JF$jU!~c6b8Zgl58J*Kfp8OUFS=;JLDNgJnq%P)U$2Dv8GV?}MUW zfLbR(tyADNjRj7@@+NEKGVfcU%Ja|;!Jr2D4L$*{K0*C^P(NBBFjBVsmyo27biMBa z(_fXiABcNYHfn_|fj6|D>1W&#MrqRGO9Ambvpzk}-Tsgq55cS7`6Q=>? ztB|2Lv@%1oS?Iul7*S?|lbvW4xiuRBs-#N$Qt) z^Ep{Ic@w_C+mLnrHkGNY_gjE7JgqUIR)oEh@a7*tU$QEXppAZrGGD`&&&f9WGA!ZK zDD5lIAP6$$Kp#bP9gq77xD@=)$+0&)GLR`nXN!7@&d;H)edM!&HFynRCJXjHTy}b> z^5GMbIMCaDge7bQ8bLn*AI{6L8O(kn9<`4LBoiQAEs$woEG>!@zM4aWZ`-#(J3f5YLG8Tx&b%7pt2)vZ&Mpky_NEv{Ty$St)bpb^1W%krJyk3 zJtW~J>>zWH1u1jT_U79PGb&U1Gt(p%hiG;3zr+{FEoRPl|EnCX* z%Rc<+O&T?RMLj!eegL)NDaurRhboismSsu~kpChWasfF5mDJk`_wnEpc~P3kf(P#G z=L^u<45I>l*?HK_j{Sm#~`ZG*(W9VwF?^Rz$h5`l%2ro#tV6Qis@vwL*7`AHWiF zz`jy{IrhSv zpYyHm-!d}{gULVt_j#YU`|0ZL>Z((xPMve=)Y=Y>bswjMhH{PO8pAaf>K?&$B-c2uDfmsLE|0Kc*sVowng0X&WhGY=t^PlA zy+*CRIrCUr?ru+*ad>?w*J!RWTw}S8 z;5w3P9M{p%XA1YJR#tf!+4Jr^pZw<(>ndom3p(r~MNi(hlA0$qPimgjJbB+r-nWwX zt>k?xDS1-zv<&A{MhmzWlArUqpU?dQ?pJbM#r1DoU*Y;H{lxdekxQs!9-=Szw{8gg zXYEf)jd4FTU_DoVuKlPl267E@J;9(63>v|pk^BxJzeC9H5b`@Do`5ZV4A(@i;|Y5L z*A&7{g-49KtUBInS?oPTfYj2>FFAG>Yf+Zz*N#DNtK?hrLPvZIkAO{2=YLUW()v){ zZKx6394}tlh|o|OC^`jj&VIPo~I0+-*ZZP_)^;1AB@9|xaR|fd^qz`=HblF%vO9&8;D*&NI9tj zzb&Fbj(?rBiDAAT3^@62I)(VaEHl2u2Wsc>yd_qT)+l!snfL7_?aB~-H~|{YakCNLT=`4Mpx=@Op5zT=G``F>aZdVc96Xa%X=1jcqq1XMUm#r zhlDhZxrulFgp^92_-UKH3)VWmzDbXDs{=SjE7QOq^1K;ZZ|80?c~e~Fkdh%Ky(f|# z-V(noj-m%SH*U%+61BlooGZDEIvX=jASd?kwQ9H%tsHVKEb0Hvd?oW7vP1|*W2oIozc|P! zA$J(Slo~v3%&Y_ZHAyKM?52Q)FbJ~MgPg7+?3My45G0`&aD*etZvsh>TkG3uASIHM z7t>0AtECDrH$#&=IkZrjO>#Gqr!{cnqqHrZpj3#yNM}|*?=qR={S7d!MOvCNFJ#`z zY|Fd_1o1vTZAr_Wgsv#$Odv^aH7BD)7(7Sp=j^Gy1KL`DdBL%F4M@K8YS$o1t>h`_ zWOh3&0B$dp>_yYoQ6RNR0Mlyk!+qP~%(vM6hTqjd*R}9Lf&=twhO#Ym0q^}X%LpH^ zNPuM_ZA>7o>ma12mXN?I=%GBE;fHmtWCYDaNa^p)Yw&XgCH#(fqyV#kptP$8_EVWv z;u~p1@k7uPsrEJPM?Ifk3P~1Q+`wsTOPpE+vDcE6CtH3a9q4PmnLmQlA1&XxFyh{< zPBIusB(m4WQ4AhvwmluD1#^dK%gp*9<*9Gb1^BNOk0Uiudjr z+~%-q{gf|31f5pu`FUbIk4R!_8}~D9xl4Z4Y9(v{9Pa@vPeQ7sqCEW>FIA8zj5-cqBMg(5HVOSRI(3JaVU_6(l$W;lHj52f?n!o zvbjevd@u@gy_H!JLc!Zl!3`Cz7x~(#^0)C13z=AO*>pk#+tFD^LIrCb)stqu=_|!l zYzvZTP{XHvoKz1Gehp<;N7>zvW=YE_;3Byr#LfVz1y0?CkU7>nV?10-?PT>wh1(xK zf5r4*im$#CB>QghS|0|*j$TOLMn-z;cv=eOmIiNJm7_F$(2dy-Egn*wYLHR%uOKZ4 zQmzh@G+C_tI;RB`d$qh7UY)UJ*1(^|;Dj!ht&&j4z8iJ&bxj+PjJgJ?H&%t&3|9UL zPS7Qkpg}U8%hOtIKnhqL1}0%1St;9NQ+CtY@#J?1}|xRSr@J zAHSyc;@@O8{@;Jlo4$k=!c&>Mke*j~rhkE+b!3Y)L_P9~&esFYfmMMFJ}+A(p!E@5aAc%r?|irS5FJMVyk8~F_C|<8*%W{@IhADb z&FGtcgvJ}Fq2TrWgZe=5DGSj&Ej3xJyQDEA`b*Su1D=(bdb9~=Y1<{f-&4LVMNURH zh|As5mc4I1IEJaNtVDz!ZhF>|I?jUc^^mP5>~lfsb9y%SmV1)M+8J_by$y*4+1Wxc z=9D}3D9yPbhJ6-ui~kaOV{7K65W+YxEBW@dS!rdtR-x$G$gB?Gd3qsz;@Nc4F8YkS zn_uRU^b4g(iCXQZ@2R)Te3L$t9*lv7VMP3&QI!xjJ7dPyc=!q zK7=;h>?jf4_7Ax+58+d+_C!{L!PQS^{>-tgL(~w!O7D0-sQFc|CC8 z{US6A@>R%%LB3vYDPIMAS|CY=SLpA}4}+iT{uancn$0g6Z`hFip7LeZBll1sLDE8| zZ-CKKQ_)vzaw`co&J>?nzUh#HAZ=llW8hh}sdH)X`H6U8EHDjXeR~`R z@1q_;b`?7*SLMfM%~%h%U6$``-h$spO>Ix{{+=A{31-{=CO_mMum0M5+BunR2@~p3 z`pJ>iqKpWby`M;iBfmQeH|qB$uEp2fXrP03a=?!|lxbSiBl^w)b_8;H3T z?OkLVJj@%w=V58rUP(-F%^qn^OR_%pU~xClzi+)nc}M04nZM+{CXc{}n)I$bgu9KJ z>TN7IumJC^)H~0UgY{_m&eU(rUPa$`lb&Yo8g*X&Q9>r@oVm>Fj&jCKp&u{<-3nP0%^P!a1$C+qCxA0aDvmr?nB0VtZ&^cgM8^TkQQ?(ty^p3 zGL}hem$4Xp!ub^SoAG6kFRc(=p9X=`})op}iJ_#`_ z<__MLGry29lDU`co=BBF*+qZ3TKP+viMWJ*vpZ=WuHnwJFcZD4e+9V9fol{sTy_E5 zMuN>gsfL=C9&*a_d5kJ5UA`g9e6fChbB$_7pJ3CNt;C;q41bRblTDk8DY|EEqC-)^O zFTOx?wU@KslF`+a0$Km$A;FG0KIs?pDWCxom6mgU9>|fUr=AVs7Mo>cNAL~L!6l5w zIkAP`;(OrV?AStz8KDG^yais9{zy~KhsSe4{)q{1v_A5&ZT&Up!wS0Wk*0?k2XY3ZL2J(ltYrRIsg18#{82*^Yo~>fz0?mZmS*~+Amgv=43OCn!9Ih zmYgM#`YApWvQ~lsNPmQgFp#AMV(8;@w>g|9mBga{0jps3i(10NMv(Il zqyZZ@8IcMajv9C~n7y1IEPck#-%Kq9ROu0-x9{Vf^=ug$>#5_C++83zyYmPJEV15iYZ?NHTT}$Q?TOc@6@(#0ml|C@SLn<;aIsMH)&4OT!bEx5DGfAwCDdT^P4P$>;rMDU0>?` zUjp+@IOJJux)ulBppdDJ;gR>6KcYhS&d5@<>x?q7uTeG z1zh_~VzsKL0*+jQ!~~1>g9M)CD{CdGXUbYn9HI0ASA?;>BnEhfrxxx3j7aY=DiG&Q z+zp9NwOS!q+cm7z@237JcrUfsE*p2Wpa#SYbY;W2U1wA8=(Ub#2q z3(8>guK_n?0NkwS&t@q;1NRzqYf-2tF>on9dHOJyGNrwp+F!knl!vvT7?HJ9DVt4P zNp4IplERNNciXqzA)Kt`5DrONVp~XVfp4{^wPAF?%jsN%)GOS}Sg+rgZzkFAqMt*Z zE6FmBgzn8qDKoX`+qU^;CSg12gJEV?A2_@(h$m5%29wG|XU`0i=LBJ*eJ z%D<@w-2fhMATNId1GB5Fwar+ZX)yt5SuY33Y0sSApeu9LfE)PGAktC|0nJVLFpr;Eisu$TRx+sMo23n< zSC;iHn^ksm`NZ-kE6(dw+3CW{n#xlu*LR-R`Hs#zs~W1VtXfjFwR%|fmDS5?e9g$3 zMK#N6KI}4~%Qao@>$0fIpB{_=#LoSsTsn6MhDJ z8O&mJ@*Gy=U&3`crBv=mvp#()Z)dQY_$;m&tZ1K2NOq<37qYj+<#1^?KO*yc-^ewR zFQZwbegwM|jAL)V@%T;1-0dgwK8Zd3CbO&LRMy7NVE?pPnLGV#!p_ND<}W1OOW2R# zGW;&jEcT1gR1u*z%DodjCV&S!_YkAP&v!%p0`_{lgmuT4ab3=}h!Li4emLvBM}T1? z7>@+Q(d>>ej=jN-0`_>W3G4(gk^3a@oXomtZ#;@Ho3L;W_m&9Fsges+@-z0;Emf!cO*Mtj3(ST?niM=AdQLKCxOFRmIJQY z;4lZuEwDWdS>-*Qy*y@cpUHg|QrA;^ha`J40(FbZU>s1529wB@VG_#2O6?UOZUN#3 zAXX=Pi?rOAaUJ`5*uGiC>}*!ST;emRx#wWZEGBLESh z)`DXRy98CTt5Y>)u@M|QgJT&uhTX>IvHQt=RPIFxfe<=iZ}o$n5Z z;>SU|`eYw8+mEw1*jqWX4;u8E2}ZNPZZ_A)p)chdFNAX4z;GwKD6nqy0na^Iw^ z>PXdg!?Uuo-SB#mYAyNRM!wguTh%7^d)f>Z8_EA>Fxd=eya5etN4yP;;n?m;`5G`S zN0ZlF8Jg@qLCRZA`$73;q-Iyx8;iX>g2tBG2o{^Bd&ZcA|ZQJg-Xfyox-pg164VjEZOc93w38_MVkPye z=}@azH={F*Qftu{o6x08pwtpSf%;$~_es!|4J?;Ir1S;K` z>|?f+e5L!C-3gVJz!`T!r90hzU}}56ZJ{iy-D1k}dM@@mO=_=QU}&}1&Y(-cbUat6 zg?EA7X0Y3-nrc2}zrY;?X0}IM*c&eFMOsX`u?s6#s`=p=^eh?xeqBiVR(}S12?K1E z+u74?I4K8iLUKrHG&)n<1c$LZ5Lm2&MjOCl6Ezr zp!A;0lj+R~ua|+{7I?i3USF5!HfnV2i}~yeZFTEEa`)OEV7U=2sh=sqV0$!!ozc$h zwq0Pj4IVR%vklsr-PR24)Fpk zn#9q8o43HtkCWQtq-Naw1gWhfwN-iCd;oMfrUTsEv3+b!YHd&KHOPCaZ8t&r9f?+5 z2lZctKXxMXF&ecT9#|L8C9kHtZCC9*?nFx-O=@?O$57@Yq2g$`EKs#MlsQs75$+2d zxe2OTYFpsOV)EHNTPwm#aAU`Jnyt^{z{|+rUDzHw!KfLGc7f4)m2=?2ZBTtJ*cio4 zHg+ZDyOX@9nDj-9raJ|$MT@S51`ne}*FcA7DD!pk0+st4*b|G<5!W;4=ZkJMR!u2o zS7j1LnH@;2*biAB3N_iS7CmUz=nO2pnd~4w3p;8yal5(8nTNmF9SfA9K$%Uusf>10 zE&8|^hz;06`vG;dpJNnqV}UvxsN;Y-o-*nV)bXnIX1b$+8g>Sy)dii80LnNwn0jR( za&`bvXwN{EOV}6xGOo+H7P)b*D`}RJp2b>6j4G_iQdzxL=TGE$679LE$O5~AqDPw5 zZkx?JS_^0uK&t>+1<)#p9cs^aNWTPVT}Zz>5NedZwfGE&5VL`p4a969W&nB;o`t*S{-&{~}{ zz-N|=6B-n@x@t+=w7FUTl|a~%P;Ut7TYChp4kagYpM-s6^-ah{1vrcbhtcF>G`X3JKzR{7 zUIfC6@a%io$ylu9ZWeq@4MOX9J5YuLWjIiV17$cl3DmSw9Y78a0Q>$(JeCZxL%M|& zG;7St;9b&vrw#gJr;Gj}|1Hylif~FJc`!O0!Sgt1eiZNHd7c2))&nq!oe|k*3{F~( ztgN9m4izb%%eXE_k1V1tsY&XzUg+faflx#2wZwdbn02%b>WICRd{+Qr2@tA*um%Wg zfbcL7HV~uHEE?+Falk!_5EF=PIyOM4RQdtJs-#C?H4s(3vc$E4RHj?%`q+Jd6)k)r80qc#VxsEiK6LXz$kL14# zvAdJ*2c+8t>d{I;vrYukB+4eG9@afLz&$_+P>gz8lzx}QE};z2%SVa+>xlhVQO;Ub zbEs>r=jAf4%gId|)ARs+81UQ#YAv&|umj=NO~h;pe4kBoZ9?z0z_%We(OgHscOgxK z@D32(P?~d~?Il1C<=jMi&0re(iFy*Nnl!tTSEKV=38$<{Vj8B~h`E*YERS1VbpEyK z-RkZ}xe5Hc#8%7&?K6MBd89NJZU^l(@ z*;#M{JLgzubSQS2C#cxH8dDN ztRci2LadR*8cD2?{uKI3=nL_ea{na#FosbMj~s5fr+}M)sQ59?x(Ie z;FBGLE+L(@0V?>^7QkmM2rv`+DF?zo7bc8(B=7twg7JXen%kgt8pO3#z?+z-{{u?> z7G}3m^63F=n=!EsTh}ocU^k(Snxx6Q<+F_4sqA};Ba8`aBq=vKVxw7=EdnO5VHSV> zx0Igv70@$;vAGR}C6jVsp>GN?!4L`6Q3TeuQ-ST%XClx3pxt!OcIc?PQL9~FKnx!I4jejH+0eh&m z6DrmbS_iSS^HK@F0a%*?K8$3En{Z#Y@l<3JS~AwEy~Dydk;*;YO{p$dn#_v{tLB#_ zsWdzOn+6P>i67ER9&DdH$#dcx_8-yc9=O?lXip^h-AM^q+N;3vPV#G-l^xRXX<|la zK8%-0YiF86gKLs*G$oWqGn2GzU!Sch*1%?`CC*KOdw6G_opiC4zoZ5~W{!r~_}SPj ztAiNVx;24lE2rP$OLm1+0(~6V3@1#=(a>>#`b-{d40{My*Y?Ac?`GpORxj;R_`V$pPky_T-@~%-b6TiH zbVfg$Sp8f9Eul@AGsWm)s-Ihg&U>}|+Et*9^S&pKl)mkR;Z#-wl@ngzr9B;;p?fWI z$ZP{@qC5?>rwHax_%-OVuzIJRd9{K8Es*)ua6}uLtc_GG{QbZ$PPBR(K?=MqJTtZl z|1SLjdppX>Z#nSID%icZ!0C6wo9w-t%3izWW#zgQ3Afztkq=VH;SPN^6Kj`CRz;-c zRv1ceHdoGehBDprp3Ti}=kRm*qos3;?pr*7afUMqSw#ugBLAj)swi`tCuj3IZ61a6 zDDTW6Xg7cDB-rLB`vYc;rAHd<&C*WZveCg{CpAtt<6E8|<$6gL)}3Z+p{pv)>eBg6 zS~F!Mf5ZpUSgq9Flg1<^M*aJ_V#toCO2n!N*}E?kR-Uk`8FzMxuz z21jmHc`FYImRVRG)G6&GO*&Q7zBX?boxow1{DyWS@QHa_Hs{E8R=uBdP38e0*eoCR zFipzXb{yd(|F0UXbaiq2aQFNbI1fO{C(#rS$ojVZm)2uR2>PDm*_W)njAjalASA0j zQ@{T+_Z)wI6!?;(j@23;1-!*Eey7&^`|!+5T)Q84v>wfi*YU>=)X~O^NL^K8<37im zTFh9Ro2Vz3=Msa16N^6V!;t&3?@#GEe3MD--ePUVHroq1*lpLrW(!lp?b&L{0r)6S zv_8_K?OE&T*Yu9$(FzTc#FMpLq&E|)ntp3_kaugjTI+5blDa|l_FCz}R$<%nFsY^7 zlGd)J#5^=`2uFTvA@#Gn=xLUmJzIZ)Xc%_fYulaz&!i5ZrMQ}Ouno{{wu;l*2DY!Z z&EBlgidh5O?vdArJ**54~YyE7I=Cv7>>;`FY?I0cEW%FvfzR)_e)w$iVPeLsa;#k>19bEp4%l*BC zvM=-eeqmV#$j0vqY20Eq<7%TDxLP@cy0udI75uDU`o>)|4N1-Jys<+HuGK9%3eyaJ z<{Dn$7|K1zC9((FuFY~~Vzz3i5ds#4ZrKG-F_oib`O zFChx$Lt7(x7H72t1(#;!tMFSJc5{}V7Lpv=`2An&cxQK{tH(@Eb! zT52uudAjhOx{)1Upl3nr6^i6!$94o(sR`e9>ak#56Dpar59bur2>Inu@Wl(VQY58p z$}KQ$^HsSoC}ALMQ>&J}=i7`T-Dmwg((YDA3(ErR*kPGdG7?}E;F||Fr!Nvun}=_! zwN2);7K%YjBk{bQx`djYl%-A6FX5ibq?L4DJzyNj+HLcT(Wjt@xUpe zuJw0Xd(~FBhrUm|FS(8F%REwh_8>=#2e$CMRi5Jiv|@9 zDVk7pUeV=6R~CJy=nF-672R8OU(wQ{^~K$bZ!BI}yt~Agl$BJKe7WS+lHH{POUIPX zD*b%v4@;Mqm6SDOnIpTA8G##_@zWg7Wwy_`JkR4kpZ5hkFGNCnxlxq0%_R$SC$}V6FcV&L z4(HmN2AI){7WdCSRQ`$&MP1%$dFt^B3>5`;kbIM2wiDllh&0HfD z`?qZPi#u}{g!f!#Xq^j=^SErz-~#S8Z?LoL%lJn<_2?+{-WclX7PB_nn4MXS<SjttK;nZsza zM`zkRWbVwfC+GHO?pL7k8gg#4s#b#ca_~<7zuH8pT5oneI&>7*7_754W*CyvEz#|n zTS#e7|G4Mh4DScS`$Y>@E@UR2p~+JT zX8Hf1Urt#rr)QS+ZD6y<8F-{v7f++)ZC>)3T>CPE&MVKO$ZJf_H$wL{(7lPaLwEAo zms-VIC!?rI#<;rZT>K*5Had&f#M4rHx0({Sjxfd_jnJeqI)Iqv`gV0@BEAPht%Lb; zFw`>6F=`zQ?);fip~gUWgH?yS7+cz&1B80$*oZ9ipGVDp8wV{Lpk*Va+(;?&-#)?y zmsK>xu6LdAF`eHPDX z3})^1#b&BU!i*C3&vBd2ay`$?u5>p*!7m|;)40OFchecR_U~Q$qw+>(SF-AZE6n<@ zkI$wA&*2KQY;CPYT|AGAc^dHou7yyghE#WwdQ7TFC1X%FC-`c-7%Ssq}Cw5o5@-S z)+)g_(rn~V@(s3QTrskE8X;LzL!OuwNJ;GgZYC+I9q|nQLp>9k&1#XG6#h0aNdF(b zllsO+_*+wxzu6Ni=%nqy-a+nm0(&=bcNpy`J?UHNLP`m`o7OQswA{3bYPqwScRd$4 z;UCnys4=#n8MnBiB;-nkJR3|)T0xvonhQw_N@mk~3cb4}o(ruF;(TbmFisCjpxj6=ZVmy zunibHlX`n+lJ}s8?Q6ojtfrU?tgwP-H=%d9XyOR+@7!f>eN++EvBGmqG%-3UnjT#h zeIdG)f9EzuYrOLnzQG@X&9>BUj#(EIUmJfvek|UO%{H>Qq`0QIck!U&;l*Q$rxjmZ zd_(c~iGhTl};#~QhH|TIi(krE-L*@>20Ntl&&c&Dyu5%SvIh2SlOtu31w5t&cx2Uplngu zXUc9UyQ%D!vOCJ|Eqk!+v9c9qFO{t>+fZIqUSB>2+i!9Ccgi0uUsb-lqP}86#jJ|O zl-pS6d_OMQI=(;G0IvPG26EY&Zjao*gxo*tN~mS(;Ox3+0M{U{!Cdz55DT-GFl%`l zfSouPN}Jyr{F?Hf%7Boo)pIp^17RN~?EMP+7Ef;}wGcMc`WB{%FZ{0vDET&01?icM zv_Bz!Mu?y71=DK@^JQ0>nmBXLJ(W7ZS1o|yH-toN*?_r1CLaG?d- zg=FbBkbWcSHvpvpC=EbqAXX#kHq0Ki{Lnh)hSou!5-4f&Dyz6xbJZ|gqYL+1 zF6)Jy&+J&6A-j;a*Lm0q=X1Y+`<2)OS8@Ft-@d~2Rj%Iw=W*=4UX)~SuD)Dm`%!|( zV6Xux!H5!!C_&`WY(i_FHAV+=HExlpVOWj`dQqX%w)!b96Ra@)VayODb z^MzQ6=W(6SbpiI-2bn)cA97_ffAsv{FHiTjrH}vL>9_Y<;-3?uuq1M2^3Q*IEn6?{ z`_o(5xNSd~T((`${$s!Fz1IH!Qiy-7w)107Fl+R*7fxTrng*;gjR;2A%$?EE74$z< zV=>t{DXR|{6UNG5q^xi>33cA`(5Og>W?k}$`pw3`Y;4o6WkBN(UOc_eZiF`5yG74? z3QePQ>5J}!Wxle(vx9gVYf8p2Z6@ElHiPhK9i=UN=ZxU;h>L2J@0(8o&1u~U>oDfy(J+vH#>{}GGZ{wl#GKU^M{o}!9Qv(U-@~12F!rR z{u>-!yJZ5Au=jZ)iIXVaq`w#!eZV2_rFSz`VOrC@r--?{*$- zWGj3Q@kGBn8ILVkS0e0F`q82Wi-g8)rIz)R{L#{23@N34JE)|el9{5(YnXMEertU{ zuBBJPb#R^?>?CP3KNy!P!~kod)lpbt`Jb~C*Qj^?mwkC|`FHXT$F&iA>$k8GW$O#D zF*#;jGD9wmAcm2<9Pip_t&a4brW8hEnd^~gGAn(JiRR*3(3q4=BDbgU^6s{FApbC| zjO)bzCVQe{8pcX5ISO#e@k1$d>R$uK>w@zvuI-AQ%4ERHw0Rqc!qt%%ONIX<64%y# zC{C_?1*;bQ;kuzR(|Ll#ZX*nZggTw*y5Ql8`~rDC?8F)kA%>Aa_e3+d*d z0N1b!xMV3K%uGh4RfrYjCE&7L?|51M!l4|c6izgT{Ooh;Z%`yV%8_XdMwB`8p`>A3 z(`SvLt~V_{nDR=O2U(WrSzI;H33c;ypnw?^ z(}gx?w$4JLDYsCo*|-6?%Tljnj_gion$jf)CCEXDOPYpD3P|}hnHHA=Z;f!awTSj7RN<3^4S5L|rZS;V zdC&qBtMx2z#Zbqf*mHWA%!Zxb6TO{&NT3)l!cKV$Pz;wP1yGDqCM6tMYNmkfp39Nx zBg46vy6P1;CqGBwxs4oUK`CZJXG_iK!pcd~&K+7&RRA~l&7N|&q#O~bTZl_uoHR!{ zx`vNXm4ozc)rQs8wiD(3c@Ya9+k|5Bqa*wE18B=0{|2`pddt$uFL9_6;uF(WgqRF1 zg}O@$AOz|brk3S9yp1kFQ!~d~!2-XKqZB)Z!bws~VkfexDD69x7JocwKg{00b`Xjm zcB8cmj$c3J0sbm=JXmi-Q3_<$MIekZvyz*`{LV+ha3jb_o_jKuHzKS|#|6_M&p$RIs zMwpva0K;Ca?PazBHT62m$taVq*|l}8$*!cWqP6m1ALb_GO-5UyFFPM zV|$QSrr{{boqXF#FYN&E&ibd{!#$si^S^vlj;5rtny=%UCBbF8(Gr|l+X|e&V^?V8 z!MOM-;3REi(-1-9=jXD+&$4kSmvCCyC7Qp(5EO7vRNa$*4m#S;)(;20U^DY%Nn5<| zlyH+Qk3^=xF?`QKQE0PQs+pg_ zVyJDv-A-v_EVyt=BNNm98zw11=alkc!s>U}t3AY){JLxCtsP-!-OMwLXX{mLW&~3dTWcX%}GDdvM;aV$$jhbPm_=c&H`9Q2gnLDf=UPKbQmnAmJ64(@$COY~i-6gO1}eDr)b>F*YX^qbodpT} zY8aaISbtSmcc1j7@Fw0g>RIsogKyR|XdJg2s5zJf!e3aX`?#kRv(*H-gHY)o*E;a8 zHK1B=8hC_Mb8zelTs8zBO8sH5F}^Wgp;o5k44duge-KjovMwd>fTl)G>nTlp9Zc() zh6!y7dlThF{VeC@$}JC=t$j5+#MZ-vc3HN*Ps%QjXY=AEk5K(d<5X<6pCOrh`TrM@ zWN#Q`(q!Ip3Xyf1)(dPq7`!ekJ^vqHf&0YG`FSv`IpV@S{cR?+=wta1T~gjtXmjjK zu;v9p*d+av*)Ti=U6y>!|Ip@hT2}cV?f)9q*VD2t7rkYLL3@)^wN&*#iGZ`z~nzaU|qmo`kcqqZOFvcF=67C>YNG)lJDtyvHPU8x@b~zvonY)9Vof*$4@y+4q(Y^mD%(RyQf-P){X+3T3%vOnWb&cHsZC zzE0l6xAaeCX_mqcJeUVma*Q=YxbnPOJO+v=HE~e*+?r0Q zF0t=z&~QB=g*28GJ z6$>V>Cl37#g-aQ&`4c-#qLr!tmq2xE+hf@?zN8fC`{husQX8PmxH~=IyX?QQLa6X1 z;2&Zdqy&QMrsO%vQ3{DL#`|x{uE_oQDttBx*Pq97q1$@0dLrdf-L0Krc{h4zd&7Vv zYYIQZj1nZ}R{93tt%S2$EUcB!OE9aovUv#gW(qe1r5>|?Q;PPX91}OBA0#Uesyzm( z=X<7@0o(rbjIAiFbAJqjHf_brhr#!C^efofnZT`P$ymH_8HZR8iv77V{Jqj>Vk>1B z#eh$ivc3!M4+lBo-;{7!Oq!OyoT zQ}FHFThk`NNIR#b*tGontxZ~2CG*-vY4&! zKFd2Qnb)C=H(%(~WVV4FK^}l${A42_p~l++zZ(ylZ^BFB$8V~n!pH#@L&DRBo0W@J zLCM+({|2#lv;w#-$=MX7VRqkA8(Fa$pYV6uohSZPs`saXT9G&_lf5_Y$9^pHD(*m2oN0|%J!B$5t0UOf`yG#;Om`NCG z0nkHE%f{+dlU9|Kv|*MTQ@ql+f8X6w$Z}gtP=RiVZfW^3ya#%<{jH_1QJ|$?;d?vS zgpr(lIa1wK5TCZUq-wOA#T>{>xvt{rQf6>|0ryhtr_gB}mhzbGFZl_e)G?dW4r{+R zGH1u`$$?}&#Tt==xf%(_kw}wq-ch`smhkW~NrYnv=~%H7u(5uU2I5)jq5mlKo1_{s z9!oe45CkO{XF8WnB-sU{0#;2Xk*EXX9GL>Dl5v zXg6IK@CZndV~O_v*03v{~ldux4Re-X4;v~RKf z3XlNf*5M06gqQu1wU>FcS-@6GmP5;J13d-3@^Mh`IxByCllnk@S%(&NKlU;ofkzQ- zSnH$cn*EsMC!N8S^WUc@(`vNwi6fm#3JDMFi!|<2ivQfemb12wsMgh1vI46T%G0wO zpTKoWdPTRy6XO%&QSm9bXU4PQx$${i7srcm&*b?k)_PnYe=PEzvk&nXDa%iW0pIbDnT^I%Miy8&#D(GUAG1_$Oya@{0d28PJL+EJ~?Z8cwdmjR)qi!M##o>_EF(KXo;xk_bgd{2o$??B(@;tfTU zIeU|1qheFhWEVwMj>Q99=58}LGVLEZtM?=Kq1^Auzl)x)lly)7d{@tF<^E1SHnJBv z+sh-0uFG^m)KOuL$d}tRD{&KlizecRO zFrON^Wpa;{J5(-hNWNM<9z_G?ep0U0HjzJA&)=5&tlTkjC(1ol?gqJ5H%8Gdaxap5 zkKFEZP4h>N6*_x zr@iwIuxNSS4PNb?OTfCL=L6)gy>l6VTWozk7PWsqnb7UYXl3+5vRcV+7cGq*;kwWM z#2G!uI?Y#ke{%)m(FaArE9w~;C6bEoVKuXIv z$8bKz^OK}HMX655wRFR|lC)n?>Xv>uZv^gczsj#B#Yg;Fzfn2Z3Z!om)1ai7Uka`_ z`0c!Z=x>ON;tIn$t^xB$;_h+Zcwn@f>yfwteBU4^O<-3Q506Kt5aT1_3BY?S3vrmg zG(HYkC&knJ&GC$Q2DDrO77vi_W1KgFtI_WiglfTgIM2{e;2v7!Z3>Zn(LmDyH-A(^!%QluhH`^x!dKwCI7<> zW;96dWVyrT_LbXR?(ycjC-mG+&o}CsRldYMMs7d3Wpa;{J5=scxs7rM%IzZeGs59I zxnDBZA1r*nt>{lVxyuzRlG|VIfpULhuKU2kRF0|~&vQ~EsTJ8k5B(ta(;mSZ{UJK- z$xh<{N)8Ud^?micTV>fT?!nit@|o(+V6TBWth4?kJ11Phehb&TFZxgUPy4I=zaVvA z_Fwlm`EU9E@OSy2`g{Cu{6qd>|A>FoKkr{e7GCv#^}GEC{zJIDBrc81;_|pUu8DiV zG4@`@l5Rc*{s?=J3c4=IF{16@w|9` zydYi(-XmG9xqy|L=dnuj0{1ERX;x=`#eEgrKI^~e@Am)g@Abb#l79;(fAKH-SNuA^ z-oNEH_`eC0u5n%5E$$Wfj{C&@;`(?{+z=0mhsML=5wt4CB4J0yHc^Aad#G)@@Y5I|AE?Tj(^Gj*)4$Tueb~R zYksx6$iMD)xl4Q|j@=D$am?Rb;)=M+eLe0HcX!{4d&Yg-e^Ltl-S^`C;(_k_l*S5SZ>ejvdC&Gs|uyCp+nL8jZ$cpBlHs;+6_=OJ8wIKXD5y;W1$M z^S%83{3olyH@FdgC>Haf{t$l%9CD~X6b?DeALd5+!~Nm#$rwKtJ~`4K>5lNn_+#9W z{#bt;|5Q8CPjTb@$^H~Kfx6~2HxYWA=_WywneJGBw!g^!CG8i1jZuZ2E@;^gq=(6L zQa**Un#Mg7^^5vP1ERqZI}1gP(d=jre>1u%`bG3Kb#1gyRI%OAt)FfXsUL&{d3OkB zF*9=yWuDeZcQ}${G%JTSLE@uyV84o~z9LU)Z z`V6CNj6MUQ&f$DB%GkaINAS(KX(-%u4n1gdIZYQ|N+{Dq$B45gx_{w+RFlMC$Ff#_ zw>!ao$h!8=L#3JSm(khLL+&rodBo9fKxU$3!`3?^rg{2O8QE8Z?L;M zI+!xPCOVXL`Jasri$=O@qfyal@-sF%%6%a^Iy&BcDLOGa$=wv45}o0`9epgC?rw=@ zL^Is25_>%XEO!2dsr{@eX2`g!y}ZcX&d=sx!*EuG)Eb){s;Eg=&h(U`Ww7ggZ=v+JEy!KZI60KJ30GC zA4DHU{h)qH)E_In6LwfT3?Tih&>*S#V$HHnqabzrFEP?KAMPKc~UeP-FIqq zyg%Jfi%#@s`ZJ@cXxQn|N$A*_(aC7p+0m)~GhN zCYnRtbbWNT|Em95bgtD+(E_WRqJ`KN{}G+d;aAA9DSM^XKi$i-|V+W*J5e!ivAS~q$v8L)&0>8ai_R4`ZBdo z*XS$Q0DYpbS&b9j6dxKN7X3R`$x+d_u}Y4O{(~Cl#OOQm$??gQN#uO|)A+Y=xchJxAxZo3EHI`16m1eHK2fg%7tOOBuNCaJa789Ub+7 z-;Nc(O%=bL0=Hb`PK8e{bu*(+MOV4m(U;(mkHaC~gG=v%A3g;?Jm@}$6tVx4c;Fk9 zT_<-FrB>x`@!fn+cdM0``#vRgocjSKHO2jqk~+ox$jZXqK`C71er$D>`-zo>`>B6U+=GX|810a_ZrRJ&!O-$Zi!LY-RIx*Z@OO@J*l0$#IPMhWQT(l#QNj4`_(68LdN}?w{{;O@yxy6m`lzVL3{kXEC2OUtpiNhLy1Sv1dLZ4s zplDyTQ9T-J0CXLQ9vTE?2P5wd&~^w~Xc(gr!_iYCD3eBanDqE4bk!K?sugJO*WEgL zsCGofQ8`@SCpySvIT{fi9*t(#pz+b9=(y+vbkCX5S<%es{OIE7vgni1=c60Z;lB;yO% zv|pta_ciS8ZA!eA-peQn;EwD*lWA7ygd;dH;F-m-uD> zWmiQ`zRsTkZ}Kvy-`%|Aas@E^DVw6j0tzq4on zH;^_+89Z1Xm-GMj>bTk+KzpRd4W>=f!yQPwq_1nBZ8Cs=R_`D0?}nH*;9s`mOhC{s*-66DFrnnKbT~2d{(tbJJHDZ%YbBEE6Im3;#UR!rK?U|3cQM75M zyV103&T?a{h0Y&sXT~$#5wvk;xg%-k%w`w5Iq@8K6z!d}`M2#k>Os!^*=goVWY5M}2dP%?3y)qw z%aOhh{-}7Rzmk%$_C{}MkQl!GEM@#TS{+63@4w=2I;GBE=da`0G)o;k{Y9R?M4P0T zHpy3b{;K~f|EYz~dA9aREdD5gZ_-vNRa+$%uT;}w`40Zy_1^{B&HiS1cX_sHA*_wo6W{}Ha~wQ^dC_riZmXzg_I_xtN}P zRHe315jE2r_?z~uqnGF{o;Uan;PyBFH>~iDo;kVxZT}Ab)Lz7W*T2j2d;UG1oBjLz z+m-qZIv7t^)251Cx7f#?e=J+esyCcn0k2oal`f7u)5_{8E{~<7%f;W_)z+#}TdRxo zbyr%xLtW?i;P_y6oud}y|H`A{QMjYyF|HHs;c>1~++Q0{h$p%p((hg2{;7PWb|mB} z@u}?mYLZ|*;$ILKM&d#*E{w#5UR)T93yZ{s#p1#uabdBzFcKG*hzm=_g(c#`(9$iF zg;^#pjKziJ;=&5r{+~kA7%x_e7dxx%TP2RH7Dv|jYyGv9wDD!7SsawNabXSpaW~*^ zyjUS#tPn4Df){VZ=WB3etvIr)c(GQzSSMcW1Q&i6UcVWhtAOWj<=MEc8-0(rp|@`L zx8whPIIo-kf&T$MKlFEi=a2oJ_!}4YK!@LrR{I$(?_R2Ddy6mo_@Dcqqt%Q%`=Q-` ziJrTU7I|OsXb*H)T61-9$_I{erB_4vO9zt)IfyTPw-lj}`>6M1|G z-t8>j?Ihl<^4t72dLWF0yTZZEr1d_0TqQoP^BJFk=crO#RUE;`6)^`qZQNWzKS3un zv~hDMadWl!xCb>^S9qO19QeCCy$FNpMd*qCHXEe3_2{@haesOg8pP%O#N`LkqtJl= zLGeNO4~d8IY#hHIeXGOa-9zF-cpedt0H(=6eLONAiT~m8;XpQd=#M;%Cap0@MK4Lk zfY|ycdZ~Y6KS{+w^iP~byq@(Ibwd6JV)s9qk=KBtRmgPG>OK$`mk)zJsi zPjVggh1Jvzs;Li>EX|iJ&6F&iAX$neOLJ9^50OO8Rc-DiSF!5!B1zYYlCCL|u3|~o zRMqwM(*1L#`!AI4pDW#ep`>oEycG5^9p^ zs!7h4te%CGK857`-v1tHS>ab8Csw!2l*FDOiJhssWv*LP2ZRyEHl zs(EIs=9w$Ys;eY+uI#Hi)j}6xb9QpaOL|X~^q!--=tNmuLnX(H$a-ZiFnlLuJvir!p4Z zVY28(%Az}57TqXWbfaa_O^`)5Mi$*zS#(FpqB}+w-9%Y*N6MlbCyVYVw8r7IW5!^4 zo9^(^9kH}Vk*x4yS>YwJze^?CW%Mi#$9fqN{x0qt;kJ=}Bz4^=KMLL&?d`AbN9dp9 z1ih{#L!GlG?;iBLnqTmQo@K8~(Q4~B(6dWlE9uCb8m9Fh7En6im z8%fJnNy|pkvenYEHPW(Oq-ATQWxGhrR!Pftla{TMmhC1jTPLkq?GN+^LL=)pt)<^| zD3qezhb?Hmr)BCrEm!Ypg?djrsU*7F2qUq^`muzup43>>kG=J$R?=2H7Q5M6?X~_y ze^t7nt$Ikf4$pX=ws0q1)5zV`F{0ytoyUkLp3 zJpGye6aEuGrlpA;c`5DwQvXT+N!oCpzB21K?n&EuG%fG3oW1`!Hk|eP!C5x))ywzu z`@>mA&2mw*0%{H;57v)SDVlZ`O{+xHYSFYt)T|UWJBylKM8{guv8(7jSA1 zHM@zL-9^oEdaBRB-)P!RH0>dpRzTBpNZoo%Dn;2UQMOu?tr2Crh_bb!Y*$+G7lQdk z^sCgVU!^I$ou9f=cT|Nx(Ff*{LeCGb8~=N*DE3nT?Z1id1q( zF*?Jp_bR{1(oV5T@mNX5H0h`!mFP5;=s4-CVwLN7#&gCYH>R~pq_s*VH{+$X%2evd zNq3b?cU2_1%jD^3@xiI$gHxr!I*AV^h!2htADk*a7%e`SAe~kzofhP5qBL8TG+VVa zTaCEn3`yRR;*X=mACtu&$BIA3i$9JNe;h6T=py->1bme%+s9vOLGpA z<~&@QbCfja0n(g@NOKN`M~Bi^U?bQzi`mnAFc1@cFlP~cZ6nYa#=9lr+EVdrnfSF_ zoLZs!sgvrbN^w|c)lyaBuxj^N&LNCsTuUluht`PCx-hCSn-P{d(Hz&+=4C(&I<097 zSpCsmROlfp^b{3(i3+_%g+8J}Us0i-sKEbC=u_!0Dhv=6_7fEbs{Y8Q!U3YfU{T>f zQK3OpIEZ}DCcj1WNfvWP^lz2oSH>C9YiWJI%tVGRojCd1JZD5dW@nzQPq>(T)zF8@ zL{|DytY@(G6haWfae2qA|E*qtl5yEjp9uk3};XjhhAc#NwU-jJeEZOl}@M=l!CqqtCFn z?`Nay*j4=c=myuFzVzGKr~LcT9j=^y-G^`=VGN}Qb7ubF_R~m81tTW!;{Sfc%x~$u zPV}z#q%C0eRHZauXFtdfhMt}tiNGHvl$#fq#FRxCXY0f_52x0tDCjKa4 zG^-0?jY}%TC8gq$PL#X#q!_Q1h*v7bE1ktDRpOOMyizS*sS&Sq5wFyWSGv+y$5Pe-kh2r~R1GK9z*U{ZRmI|}62|j-Q})JNCGgf@%Kkujt0Wo* zZKGXZhMN{2S{xEPF&!@wAMdG|lab9O}TUB&! zbS@k@k1?BwF@(kRq}#|%B>t-w|J8{9y1;+mL(kbCgSv?eyK1bsj&Yp_@v#x(KFs@i z2u{uMWq9{y(R6xYU+`!EjiHh+|{QRP02N4yK1ZBa9_VI15~99$0v zS7Dh~`#LvV<3s($%>%^E`-z(e!g1G0=S>t(kA?S2+_B>6QIvx1{cfCX9xwhrK>R%pKD0W> zG$MZy;Or@0KTy1Wn0UQGyneL!`)Kj^Na@AV;_0Ks(?^S&$B3H`5;sp${pH2eL-K5| zq2laec@|i`xcp$%Yc_}C9LAgGat;@-A0l2KAznXJygov_eyDhTxOn|=@%jYu`r+dB z30Q!agSU;M3{w3#Ko(d(Y15;mO^;GtS)}^0SoLFx||-#QR4N<;`Q;; zvW?QR$B6F_kd_@ME*~r|KTuqLn6zwz`1@!^(e7magX!9%#nU6DYbS}PM@!cpElwRH zPCZDvc9OVrh`4j8xHGiHOJxa^$r31+CBVPI;_37dnmtr0OQ5qXfht)7{DlikphlKJ z7g++mWeL>E66h*>h(GVd=h7c&qbvPo33QVs&|Q{*)z+*!ioRZUgDaYR+(~D;-t(_s zbg?_>{6z~da`#<)?&3=s*=3aqD~0%<1h-P8!2a8_zdIPNJJL;bC%V(zS#ZxnxZw(S zjr&*kWh5w?c>J^h@Lz}*Az#%w#1p0LLE!M<0a@O?A`UO!)JBIPFu^$Ja40E{9o6nq4GCHt%LM%vw0)6Na+Bi?NG2j8W}$syKgq*OP_$FKaEBA zMR#L@pVfQx(juh|)HIDq`2^ZLryx&rkev(R{j1#P+zqw{K>4v6vJSZ)h!hV)Vvk@p z$qCHWn2yvfK#~?A5ubNoa$k4fIQQI(7sqqtE|7b%+{JP~Blmi_H_o4b$>s64<=!gy z4!QTpy-)5kxyu(^df6rM3c1h8ZIb({+&AQIkh}T3Md!|so8^9JZc&NcD!JX|*2^7y z@h8qdw`jQBk#diaJ3;Poa!-;w?cz&6bxF|-x#!4TAooJKm&?6U?q@E(Z2rYXUy%D{ zxnC#hqM~ohy+!W#<=!dx9=X4e``~5Vihe71x!kAaJ|p)fxi8CIbJ?N=mlmy;yGiag zxjW4*c5+MPR$f6_6xYh_DYstkAh|>2j*vU*iceg6Uhz1&6Xl*D_Y}Ej%AF;5?iE*z zIJEdYxfjb_B=;)0*UG(K?pJUdi*J(q9l5v4{h{2u+qnA}F(Q6*#Kj+Z-G?i9JF z$(=5D&J~}UcSXrOxfjU2RPJKA*U0_6+#9a=)a6%{+$i^(a&MMr`=s2Ja$k_k3Iy~DD;+-4-R5jq{C&GyTgp=0yX&zypsn=HI^CSz$Wj+B~BOTWs&H)+kYXSjhI>P71RZmla(Ra~~JW z#ir%?0=e_#&XGG^uFVeV5}hK~W=wa9CdwTrm)Yj{jF3AVw>D~!J5a9KcePP>xixa_ zFN?L2wXwTKObDb7*)6wO?q<0gsI6~w-*&gUJKR0)KITO)cPp6x_%d@IH`40f9ThRZ&nRtxw$mavU{;#k-Rk7N zHo0$1?nYhvz7cst+9DU#2A`;Ravzr5Z5|gPX%~h2yyR|NWB!Yh`{l_!Nf~P}e7`rj z-;>;}JS^T_$^A~*E|DLY+=mIHGRE$fFxveBV_Mr8BQ_o)R-8bI?{+?3NgHh@vzT`A zhbla`*pAb%DqE~Qz}kv|x}Iy3!RP8NALtdoob~ZBd)>Dg z-^a`O($)$F4~~0^bJHH! z#7bSq{KL202Ij(UWG?I`_YU)6w=f^}UDo>?Oi%aXFqb9f|BlSs7dRWg)+#9G- zTn81R_#|^ZZClbg4lB?sy>ZxT`;=M=o4KDM-LRtKT1Jk)z$ozzj0=B_5#Mh!qI(PD zwzn}xdk5pO_b}>uALFc#Fha2QZg#8|$d*a6x=1GNl0{8y-DcoP>!Fr7Md*X+2 z{|DYOSdS_M{KAZjh#3`uU-}ro$Y*7q58s$&6xn(#d@YRmJi=vKDd%$^KBkp|PsGf) zi1iV9kmCXPXiaPyCLTweu#VSa`PlwwwvT-94=kB^l!wvZQyTU+oN=^KBF9V_Fgpd! z-kBEZLGiDd6Z&BMa{LNwyI+e}$A9Gy+pn{p`ptN4yw2ng={+l&8|^T4$oSBe%tp8- znHzZ>a|yo0i~(DR^c_b0|I2@m*)~67{QhTJ19U%g27k|-E32uC)M|=pkJ;Mc@w8qd zwX!R?M@YMI_%zyzW?>*x@j^ZMg7C-|t(fEaVtUx(+4tjdOMq`Sf%SPt8n^1H@uOav zS-CT6y;VrKix?iE`2f)mXqy>m!s-zmc!15w9nuE@pl&*NXl_w!VQL}@;#;fR!2 zPCMz@=Hnapv*wx^y}vhk;|y*MPe;w)vu7!fR*9YjWHiv@za4h zw}kG~k@>W3&Y>L#wf=9Fn-||0_gP<@?GQs5*gguBrBS0Oekgv(6|1DIHaBfzM+29q lk$HadTysTuww3WUC()xZY{2pKZVVeRiJp#@?}QPY{|7coP~`vs literal 0 HcmV?d00001 diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/LICENSE.txt b/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/LICENSE.txt new file mode 100644 index 0000000..c35c4c6 --- /dev/null +++ b/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/LICENSE.txt @@ -0,0 +1,93 @@ +Copyright © 2017 IBM Corp. with Reserved Font Name "Plex" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/SOURCE.md b/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/SOURCE.md new file mode 100644 index 0000000..0a82a4c --- /dev/null +++ b/renderer/src/main/resources/fonts/ibm-plex-sans-condensed/SOURCE.md @@ -0,0 +1,23 @@ +# IBM Plex Sans Condensed (Bold) + +An unmodified file from the official release of the IBM Plex project, retrieved 2026-11-12. + +| | | +| --- | --- | +| Project | https://github.com/IBM/plex | +| Release | `@ibm/plex-sans-condensed@2.0.0` | +| Archive | https://github.com/IBM/plex/releases/download/%40ibm/plex-sans-condensed%402.0.0/ibm-plex-sans-condensed.zip | +| Archive SHA-256 | `f86ba73abbeed7cf7690ead863192a87211dfc2b0cef0ac6bf4700533ec5ab9e` | +| Licence | SIL Open Font License 1.1, `LICENSE.txt` in this directory (the archive's `ibm-plex-sans-condensed/LICENSE.txt`, byte for byte) | +| Reserved Font Name | "Plex" (the file is not modified and not renamed) | + +| File here | Path in the archive | Font version (name table) | SHA-256 | +| --- | --- | --- | --- | +| `IBMPlexSansCondensed-Bold.ttf` | `ibm-plex-sans-condensed/fonts/complete/ttf/IBMPlexSansCondensed-Bold.ttf` | Version 3.000 | `723e245902b45a49f8cf602d15891bae08c31309dce7c56d209d10cd471b88c7` | +| `LICENSE.txt` | `ibm-plex-sans-condensed/LICENSE.txt` | | `7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da` | + +The licence was confirmed from the release archive itself: its `LICENSE.txt` states "This Font Software is +licensed under the SIL Open Font License, Version 1.1" and carries the full text; the licence field of the +font's name table says the same, and the font's embedding bits (`OS/2.fsType`) are 0, installable embedding. + +Scene name: `qqq-condensed-bold`. diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans/IBMPlexSans-Bold.ttf b/renderer/src/main/resources/fonts/ibm-plex-sans/IBMPlexSans-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1d66b1a2e96d5e33d6f5fa8e81e76b4e5621d240 GIT binary patch literal 200872 zcmcG12VhiH*8jctO?sX5GMP-vOv*`Ls zyzQ@ewgUHydr=VR7hu5kDqP!om#pebiMt-(7l1e7^x_NVc8$Jo|84l*NyY-cThi6H z%s);X$MZY!ylKh2Rb4r+tpxc*SuyWP@lT%U{|JxIc zStl%8F>l$PC0jN!W?YAF#DP+bDSXUV54Y}_9Z~T$3sOEs3HvbbmdDim;yc{0x⪻ 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±Lk;941wN9j(O#6{H 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 VkO`yz&)k7yBj|jf8c=D*002BjV;}$k literal 0 HcmV?d00001 diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans/LICENSE.txt b/renderer/src/main/resources/fonts/ibm-plex-sans/LICENSE.txt new file mode 100644 index 0000000..c35c4c6 --- /dev/null +++ b/renderer/src/main/resources/fonts/ibm-plex-sans/LICENSE.txt @@ -0,0 +1,93 @@ +Copyright © 2017 IBM Corp. with Reserved Font Name "Plex" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/renderer/src/main/resources/fonts/ibm-plex-sans/SOURCE.md b/renderer/src/main/resources/fonts/ibm-plex-sans/SOURCE.md new file mode 100644 index 0000000..dcb880a --- /dev/null +++ b/renderer/src/main/resources/fonts/ibm-plex-sans/SOURCE.md @@ -0,0 +1,24 @@ +# IBM Plex Sans (Regular, Bold) + +Unmodified files from the official release of the IBM Plex project, retrieved 2026-11-12. + +| | | +| --- | --- | +| Project | https://github.com/IBM/plex | +| Release | `@ibm/plex-sans@1.1.0` | +| Archive | https://github.com/IBM/plex/releases/download/%40ibm/plex-sans%401.1.0/ibm-plex-sans.zip | +| Archive SHA-256 | `fb365d910566e6d199cc2c15579a7dd9a267128e18431a394ed81f1970c69200` | +| Licence | SIL Open Font License 1.1, `LICENSE.txt` in this directory (the archive's `ibm-plex-sans/LICENSE.txt`, byte for byte) | +| Reserved Font Name | "Plex" (the files are not modified and not renamed) | + +| File here | Path in the archive | Font version (name table) | SHA-256 | +| --- | --- | --- | --- | +| `IBMPlexSans-Regular.ttf` | `ibm-plex-sans/fonts/complete/ttf/IBMPlexSans-Regular.ttf` | Version 3.005 | `975dcda37d80f038dcd143c22e33ca2d97a0cc5a929aace1c749153b0fe1afa5` | +| `IBMPlexSans-Bold.ttf` | `ibm-plex-sans/fonts/complete/ttf/IBMPlexSans-Bold.ttf` | Version 3.005 | `9e6c74a889a700d707613d24548fe4ffa6bc59559a0689d2cf9e133bdcdafb2f` | +| `LICENSE.txt` | `ibm-plex-sans/LICENSE.txt` | | `7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da` | + +The licence was confirmed from the release archive itself: its `LICENSE.txt` states "This Font Software is +licensed under the SIL Open Font License, Version 1.1" and carries the full text; the licence field of each +font's name table says the same, and each font's embedding bits (`OS/2.fsType`) are 0, installable embedding. + +Scene names: `qqq-sans` (Regular), `qqq-sans-bold` (Bold). diff --git a/renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf b/renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8c93043de6454ad2d5575f0751150c6551d9c588 GIT binary patch literal 277828 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

^Q2@p_nJptvCyhdNtfUDv9XvP^J$Tq^Yf}I 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 s3n!(`lCJDArN|NmBd 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

Zh7cd=34FaGWy`SDvi)66*nbC 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 RXt+-ctVzYaTEQjd{{RH8A$|Y= literal 0 HcmV?d00001 diff --git a/renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf b/renderer/src/main/resources/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dff66cc50702c75abd025dcf49f62a4dcc2d72de GIT binary patch literal 273900 zcmc${4V+a|`~QEfz1KQT&r?l_$#LeKnMzF=sZ2F8W_nU#Buo!9QxhSC5JCt^2yurH zLg?m{5aRA8gb+dqJt1@xLX_tJzRo%)!_EEueZSw|@AV(Ax6j(^@mlLzd+oLNIcFzE zM4ItGE7|?~^zE0k*4-fCeK{gQhyE2u95wEXTl-5mzf>e~bN{1`E^Ghc%hM!$b&bgA zoFk6fuS@f84X28j+0;@s=G5v5!}BXY5ZSw{NZH9_&Y2i%SJ`wgk<-W{^G}#?;;Eze z3ojNKHCLobqZ6yonm~Lu?KMKPP8@&U3FG(3yHI5McnMxE88^1NCbwgi*58Ko?&FA% zZuO4kcqqsD<4&D8Y3Ppwn{vEeB)4Sz>0_$1y5`l0oL8aI|CNy1<(}(m)a5b6A5?jT20}~pL^7f2!2h+ zYoXL%z5O3}%Ht$~7Xcs!1aWNwqCEO0^B}j>IHFox`Ea|3jkGtsDm< z{{s!uX{t5<7br{DF$%5x52#(*rs_%mO*)ZZ$@J?|!e@hOh8)5JK*#yd_)oU|Z_*O9 zr)VARL2cCbD?s~N7q#!t$doyd^gr@vefgip>HO1i`Xg$0rXT-Fk0xJT_T>1FWcsV) zQU3pseW+W}vHL6k9ZOn2I2d%yhW;Y!2aX)`mg>Z*>jru|p^u^sKpA%8(;tm^82x<1sYyLJb@{S#8YkJH{Csk_dr zJ$g>m<-h8erq^lze;w97s~vg{JpxaH_FdO9QMbxqSYGUM8ru&#B3K=YKO(J<(kYFtXY5!O1jj>92y&C=@-=XI)VaXK7DkAz{6 z@u&806zI87*KV~>?N=Kz*Tan689TN9aySOG{VUVxc;tfCsWb)kqvla`ZBTT~GPY~J zOuDwMtMg86)Hq%5 zG@P*|({HskgQjQDIx_WXyK0A01UfHtZ1w`JSI18Ks`&<{Rom3MGRHbjI=3{BmQ|Z| z{$|oMs`FaY^jPcEx^@2NfX+p=N$XHDYmKUsiOZyGJ!-2SYuQY?o?{x;eyd%Xb57gQ zu;$fxwSRE>I8(lq;~`K68rFR33+=DYL57T+%c=a#%f_(V-=N`YM?_lhH{hs*SsE5An zU_5uV0&Ld0ceWsWf@f!(yqgHq?#?ERk@~y_GCt6?K*v<)hx$tW@H_NwnYiOX&&Q6C zS)*wumDUASpXfa31Ui>AujbS9dvCY{v>t6o728v3?a^A$HSErG*r95t&IjsB%}K5E zUib`j4*d;uJ<#^FKAl5qhpLuIqB?)IZq1{r`BXEowx#OUHBQqMolDr9ir2m>T0Rrj z{-`b5UyWBAGI1K8iPQMHXj-P6wx@m5aaUi|%~v<9`Lu4$qnhd4kAzFoWb9Jgwf{Pv zy8fzt!$JL~W1Z=9M%7M*Ig#2o>6p%i%r#3@ZFwKkcBjUaxtFR-Rom41)ILRzwaj8r zdowm_d|m2}h1#k4wVcMM`?$LgnR4Z%={(Xgp`R)LXc}#3_&<>v6TP0QZ&h`S)HaQXYtbyUk}{O`)vInJc*)=XWhdY=5@ zxONM5fyQUTnd7=~e-%#UT|s%MTRs)f`uWFr(YQfAzHVCGaH{N{={%ah;Lr1GnY!ib zhW}_w-D9;OW8d%M^*qz|(&>MiN9{`IN!gVN*Xe&IJyUnx`Z95UrFF+Sljo29{9XKC z*jl%qy5myUmXw`3xB8^{59fbs?&zABLD##?+M#n_*P1%>G*N*p%NQ^^rY4uoqxJ#-Ur%2Q^>6OIv=#Y!|KFo zx}IlmfnJv~*9je?%(X|?YHeTZX%D)-#nR~7{XA${MZ=l){-CM#peyNrMsMO3t(S7C zyhjqIEj}ZttbG|C;8@qtI@g_)e}?!nnRYXCE|vBJX%SF6Gxh2i{T0JWJJjb*jh)Vk z#eiRS>Hex7do9kNUq3+E8~*wUyaO+C%(YR&yY45zgUy4Ng34d$M=Jd8 zAM$D4^nC~8uXXS0KzObvvzM&9m(}o&yU5oFeH5*RtKg0Fv6d%Z*?B5;eovVFKwUKd zj@Q^@mXrQ9VfwjiHu=xR&WkwyjAQNZvwz5=ZKUhcvYD{%!FTol?RW=cuW6~asawOT zei5(xS8Y?-bu4Mj!CgH#-cFc)r_N!WtMoH9H&xXadVbt1va102L}=GQmrd?ZFKtTOSDQ;6YM0hg$1dLo+W7C-r04T`Ekj*ee}_8gaqJK5$8lYLmrgx; zUYrD7I1kyo{BHd`n&YFnT@a1u&q4_KKHRi<>N7h%4yAzz$F|AWd=NOFkNN7!d}%EE zNe{Wm>~AhMGtCX=HglIrn%B)L^Ojj{-Zg8?2WGAL+{N2+OSdBG;AK`hKaC!SR9@mUKCCbXM{7uyTS*;WcYIUM);m>WcRWO+tZfY zBkV{!%HC*iv-jAA_6hs6ecyg!zpy_v_%eEV^p5DyF%xST%Z}y5TE*hA{8-yqQLJmM zXYAluzu1J>d9m|jlVexK7Q`NoEsi}C`$t}o*Ep|5UaP#l^7hV)=jG>h&MVEkI`5Xe zJM!k{-II5J-h+96&wDoS<-FB-ALf0M_i5hdyf5R8;w|DW<9o%U@q&2Ac#n8Vym!1j z-Zy?|d{F$b_|W*V@v-r<;*;Z7#czq<8($n>5`QMXJpN+*mH6xNRq+k+Zxb%jFwr`( zPoiz2eWGLH{KVCXn-YIdyq?&VpO>FsFstCsg1ZVHDp*NE4D*=BYIt%EKpPd$mJUc^&t zQl649vfEPyVfSz%o|=lMt_`mb?+G6a7lyBd?^t7-*j$@$d)YqrNPE1UX>YZ6+lTGr z_9?r@uC<%&Has;2Pt8qxss)~Eo%U3hSdUmqtPh@=nDW$=*h7EtRLi_Q>v(E<-pst) z@zmXU_vSs2_S7mo^)a6M98XES37%?=rxNjY@vgf))ql6AM#WE#pC7+8er^1=l&7AK zKZmDQq&@X@B1mN6sWyrHl&88UuEJBd;i(<@lAkD$f}0BF7Ccz6sNnU2)p+XjI-Z)l z+f%3EsX6Ulz*C>K`yu72EAf=WQ*+lP>v}4Dlyh+&{!0A?-D_F>^sn}S+M{Zx)K0Cv zxb~u2R)*jHcD=XjR!-Xa;XlIL(d@9XriCYjHQ~tc=x}J*KloY>VvSf2%Xa;P|1Zy! z{&gwq=DN($zw7qiBI~~p+4%IvMH>fg?6)zG@E#lMZQ?Wfjh!|Bh8s5Au<@T8Pu@_o zF?VBhW6O<=H-_uyuD^BD!<4*v{j5#1*Wa}1=8b&!AeH;$4Igb-%YScdczFYsY@oLr z?%Xhc<91D5zk;I(%6#3>eElQquUUTsp*`2%w*Hd!Kcp&1|8M=!^?gz$ZX|c3_1Wu- ze8Pq|RX04dVM!{LtHy>lK80^L?D0waPhxuX@fRO|^zo-3zxMIVpM3wxcc0{c(&*#c zKECziTRy%(WNqzQY+2g^?*6dT2lL*4{rz3<|MI~tZS&ji;nvva!mq=Bxu5l04(2|1 zE*Kb&w|qrGmrfg4tD)ci!tLQN;m&ZEwU*VBJXt=?=d%rL^WXBOQ<{*gwTAWoHf{@T zk?lu_E1tc=&asQ^V$P$b_F22!zGzq2SL`bL0cpyH-)eJQ5%tf_hFjfS4gdLHCZ|tz zQ{1I)*6(w=Y1DCTI(@pko1+JT?~*vYoQ_ZK4lQs?+$-*Nx7K~9agiW`Pb2A`Mz6_MBLW!FoONLJUZahV$bU9&1QE^CPA-_w7K37-u+hbMt2#8c~T(7T-QpaT#k?< z`BnDfHE?%A-PjdT9)7d{`p8ZHlCbN_Hp zM5eeU=EZQV%?m5tlacA}X}b^CN*B4z7P-g6E|IIl(7eQX9uM=la_%q9`SMHy*@N#L zwUX8nl`hg&_T~CKQ2Ize=`V2^C8tQWjFCxllHEhjky&z`TrW4s19E{GD6h-2@}j&g zE9EU&Eg#6&vOzwTuS}LP#u_Idn>^FmBurb=%M{wyriU46hM1$xG3E@@+ngmivWi{8 zKcuC+DQ#qp>?0p?%~>mZ^F%r!pRk8mCtYQ$w3CfoiMB{L`BvJ?Cf25(rI-992g?rW zEx$;a?2<#|S2^4?lEJ2d^fiGTW*W)>PPz)yREC&lrnw9?IdY8ILyk7BMD$SlU zg6~ruXZDeiCTjMU<4sH^ngeCD$(OTCcRA0Luv0lirkHZM*p$hormtLX2FO&?UoJEK zWQI9Ht~Q6ubaNP2$#HVK87ni*QF5m_QRbK$xx<_w^UQd8(3~j`$s%*UEH;znQFDPA zB-5n3oN9{XX1>Q%UtZuFOWWmaQ_S`DN7+-}k#kK?xxySO*O&@<#GD&BF)}uCW#p2` zw8)IeRgtNYlOv}@PK%rwIV&Y7#UJ zng=a{mO-mv5B3Fn1_gZEs(sKd*f;19bP75Lh3x8zgC0Rn&@;$p->`qsHRu*}5B3X+ z*hB0U!9nJiptso(9L!Fm)chJ8Vs-^(><`NW3Hk&k=o9Dw#E#}=X(F#kQ+ZVy$qE+WWqjl8IrgQ` zOO`C>J7)is{pDYBfP5nd%6HO1K9fS(ES=;F=`3GLNBLX^nfh|5sV66!PBPx?CpD&> zoM85q6HNyhXFAGQ(_T(9`^yA#fSh5v%9*B{oNl_vjb?=0WR8=+nNf0!sg_&KXt~Xd zk=dq7{%+2e1!kf=Y|fFSnG{xsqr>CEG2y7NDm*@{am(Cu;Q?-`dnP=I-ENPtBs@5b zh26sL!Qb8UuGa0c=h`#uS@vvuo;}}AvS-?f_8fbGz0l6ESJ~^`?+!*}g| z;g@!_EwCNKufh$sVYtyAXB&i{+QM*+?PObpKik8?)wXlEHvHJ`Z^wjh+EUv){3QH> zD^kqXw+Gw3!q06}JKRR?-r)|eR&TM>&bEzhGutHmDcoX9*lizVN3i2=VRP&uw#+&k z34gUm+hgr9wvyd=g`HqewWrzf_H=uaJ;k1EkFrDTQ1*UQ>qt+-Gi+8|&t}>)Z@?wY%P3 z=}vX0xI5iA_cwQiyV1?$I(56d!QJdma_6}--L-DIo8%sFv)z1mhP%aGH_! z%$?{ia2L6$?gY2az2jc8U2PY8fIZN5v)#iV!)@UYcAy<#4-LNyzYVvB@7sR1ukGW$ zaa-MY?tAyO`^D{W@3}SZ1GmV%;2w3KxUV9{edJzt+ucv@4fmE??cR28x-ITk_r6=< z-gP_Ohg>&5c0WYK{p?n`7u~;HXP4!Axt6Z0YvQ`Orfz@N&~x| z<|3}AJK7!La$FC0lsn8dcfDP;JKX-{j<>(Mp{}(%$W^()_6K*I-Qk9~JzPh(mn*eD z+wWbu+uJ!;>~h^9?npPt^>Ic1MPM<(#2dqx2HSU?s65buiMA9a_wE< z_I07%Y_~XLzq6k^vESOyT%|kIe&vpJ1MHWs#*MJwxG`?H{o2;rt@cxQjO%Z|aHHKY z`!5%Fc`o7dT|3v-6}bIecXxp6;Oe_<*VtKCgFAKCTxE&Hzh*lysy@I(8yeUH1tjdnHn9_zUG z_<%c*<@N>kPXDwoaqqayK4+f_2Zx7;gTlkYBiS!M9zGc^4xb1g3zx92@OMC^-%sd1 zj8!K^xD1VX!e`MuPuLlad%}~^geUBY=6k{yP@WVhwis>eagU+xJmD#5d)Sw~d^y^| z6Y>Orl`Dm9iSmtLCDimzo{(=6v%;kaDbF4tMaW$MS6*RfBf)A^ZQ|)msP&b2tnSJ* zAJ{$7-X6;n4zAECLan3J!=6dFT6?%abM+Q>O~O7(*mrnzZ2G3re(N~)2krZSG^OaF zX|(*nG)JI=(j18nPIDA`7#t46K=Ub8pu0ome9$uN6WO^5`#8@f=+HD*q51?wxfYHA z9lyIk{jPQ255viZt4nm(#RGUrDnss=idz z*DKQuMAer{A9x+!fPSzljrQ@)G^5bB(wu_6ou(RHon{RBPMS&RyJ>U|zvtmTNw}Bs zoP)lfW)}KEn(NRHVJ%z_AEnVb^>LaD&`&(vYl*B&qy1Q)Mt!m&jgH;MG-~^%G&&xi zrqTX=mPY&Zc^b8AbDFQwFVbk;U#8JIzN*6(!eFw{e|d~Swfr~4TXbt0?bEj&lZSri zF`d!xJx1r%Hjh#N{@^ja&>uaf5dF!Mdgig6Fqj_b&mJ=p{l#O3pgUkEd5%VZ^_Vlz zT^`dLt@UtEst;;XaCa)&pH!ciFWgh6;Eq*H8a)TJpQ*mKM4dbtC+K{?F zv`2G2ItRJK_P<&>2-QA-`pQH-x}V?qn5{?fUUnlJd7 zd-W8$k1z!u^{vjK)I2%_)xLrHpZl{Ex)0#K&7))7!K3>H?&Cb_6XslM-t|R0rO~;- z+)d5j!_fWGsNZzFK=&!!2YNWvszEq4pni z&%(10kNT~@NB1>68}X=b4^6W-I?$tg9G-o6VyKQa=pKP*C>|XH^$qAAhi5Dv^|Ov0 z=>9_Y5Gi#0bnNt8KMy@BjgF0u9q1lG&;JzKZyh_3DX5N%qW#vf0J#_)mPW^BxJNEU zbzBr35A8F^<*1H}qGO=_1euDCN~7ac<&n$K>NGl*+E0)f=$JIx?;4L>jgC#DV{?K> zrlTjO(eWGSk-6weX*BL+kKB%)l1A$r?~$44scCflPV>l}=;>*+oe3V9gPxH_Z9LN> zccAJUMQv2Sg6^|;#^KR6&++KK$()-;>zL%xJ(TYMQhUHf==pWHfH3GDh^J}4aUo&Q zeUedsE1Fk*sp!1B&co9;;WvdTcn&A#22Z#Gy)8{kRL2o?|7-3_Q-nU^k(<$E8vJcu z^XM-U&FdcB@L`O`~)3GmqYfna@3`YvGrK zLHF9`t2D*vHjm!JnIAlQT{SyBJarWFt4H@ZW|t?mN3SKUP&R1okt4`Akf~PzY=4!Ci6JfpuFTzXgX)i}# z_C%O(0pq4bu0-GWL@q%;@I>%?@S!KdxfU>%)e0PfPQjkwxal2 zKg-i|(KhrL=9X>b(evIm@tAdJQ;(k0HXB+{b_JRPEeX>P+Y0s~{3eS3^_hXecAF3Q z-mFL4ddw!YoyTlMnHP3n@_dSRfR2Q}Knp!)Gup{xzCk;~e&pGP7Qq3GmD=7Fx)EkR z+V0SkF!tGAP)=Cw>H~cVW0O7$Qvz+jzb8<;2Ed`jW0M^Sg9vN;gFS)Tb(lxj4|_Nq zK_2F`Wj-l^j?EBHfF1TIPoU#B)T8T=J=zoOj~)Y+l+}I=gW-hfryb$Z^~sL(=-Osk z-<3eec$6n#?CeaBuKo6UPtXj#!DD_xZ}bE@Hn)1rcJww+P=em=F+ZdCc!Gn_hdt&O z^bt?c8%=u54s@X>I2e80qwBhT!V{FDPkD5Ww@-V5L(nxIUGMGto}dh6T~u`4x2%my zfM4y$9!>|bpLhcGv(7UJ^t{oz1p&UdpLqfbSe?@l=v>fw20@7G{DVN}#Wqi1(H}f~ zrXvl$^ys=4o#N5wG|@{ux@U=A>d|LB(aSu#--%B3=rf+^I3ypJ7BF z^zf;aL?80VtLOrcK2eVT-J{P!qRaB-B>I>~pUXsLj9(^VeUFOke(@|{?^qE9d`vCf^I;wVqKA(uHtstGz7d-l`BKo37 zpLs{sAE3`UqB?e<&xWJw577JXsQLi(S#ngz9rS)Zy3(W1Mx(EJ^!_jUx<|&NZ+P_n zFS^PjHRzijz2}U+<6y=RJU^~h}WTaT$ibx`n$Xrn)P^j;xl#KYR3kC1yM!^F7wk6Efdp*`AOwiM4`RV>#N(yv$>*qc0zRV?ZWk4N|Mgv_^C%;T1!c^=0(6N`I7{2t5qguT$Vo{;$* zEArSLD1MER*J)q6dcu=XP3wsb%+**497MPn?d=IQ?qE--+Q$>BU45Y+`I$?x2_D@$ z#~AC_dBjK1^F6wEh)wo{%%Rv6xQgq-CiEe|SK*5&zEO0q7hCMnePK+;9dvIP`-dlF z9P(&S3GPN4dxHB>{GzyjqAfiE^CS-+Deid`|K#DD;1Lu*D8WKB?r~3{jIE;gE_t0j zZaG@&(S1YSbdRe=ulBfI=uD427rowNIXCle@Yu7^8$FhJn>Pz?V)`J&tuE?-P&v9A#}$>{L{bNw?Rb ztQ(5kAc8AW*s-Yb=$<|vcy#|74?Q7e;?`qFqt2uI<~Vav(LHgzo+tbY&GLlWR(+4| z<>L)J;YL)C!5)V;^60)l-oz8qhj>$u?zQ9Do^TD?%%l76cyo{L@#D-*CHxs>ek$Qd zXlsw|i{pEGLdG@DJXLhh9*=tTo*i;u5dM_B~ z99F`g(6c<@7W90N)p6w%h ziq-MB&0|kO=Xk7+>+K$^<9&xm@9pAudi0(zKG&o7dGWhEdQTX?+oSiB@q0X0eLl}) zbuQfNu_vO7J$m0BU*ZXOqECD5ICQB;p9{pF@z{FkbMQQU3DD)9@I&-PkKSL#S9rp= z(U(2p_vkAgy(f;p?g>9YS9!v9=mw8|`#1izC)|X7;|aH;TRrv!^jlB3p0AT&lj1ZS zdK_>Vi!z6Zl?n+fe$ig!nPR`KE-7bE1JKtUw!jLVS^E?QvhAZ9I;CB=+{W*HF%% z#6HyjDw^-n`{P7`$9;yj^*H*KXzy{Kq8&YMBg*=txUuMg9*6%E#U6JZ%KD?Y8E8+B zyBh7~aoXP!kGm2*$m5uw3DzgYor1DnD2}<7DD}8;=pi1*oKBQ^+!biK$K8nb@wl02 zUyr*K?dNgK>jeH*oQ}f)kK26aq3SKJPMMrrYYek~UjgIl)$sy%8LDN#sl949xC>DAF}RCRogd()qUsxP z+E?`-xOM1sk9!Bb+T&hAZ}PayQS~3_v%Q4c!92BHQ0))c15rI6<`V9P>R1DBY?Ord zpYaQ~q1rdF15x!WzOn;QokI|QhtBte-=YtA!mX%|DTME%4|(*tVPb*D_C^2hv3=0j zJ?=|%2kfN3-=M$3F2b~xFCOM*_&wBl+y`jH;})UyJnjWF%i|tJ>wDZM zXakS?3T^0#XgiHO?jy9Z$Gwa;@wn}1Q;+)z&GxuA&}JU@7TVn7R--LE?rk*3x{h#^ghEZ;$&Jje6V<=sq5XN%CVJ z_cNO3ajVdT$GwQ+0LA@l_tzN3btcRhDUNY1z$c39h2j^*(We6Zqd4Yd0X|Y3<5xiA zienxY;3LH`mIYcDxcyOlq&R$1fR7Z{1=VA4_@^L^>qHnIDVA|4&^Ev_w+pmhaM}(& zQd}X5j}*&XD!@mIKEEu$M~YJ$@sZ+sqS_yDN2B;iaYvx|NO77MA1ST}ijNd`6pD`& zcNmI~6sK+CE5-Fj@t5MNQT(O2!%_UDSmsy({!-lWDE?9`^Q0i|aYIpjr#Q7G-{THK z3p}n0ZR>G^(RLnvUR%)K<(0 z&|`2~cYlxFg%0qz3iMEq({kD#IOait_6?lQLG>Rv^_$KuZ~?0G2Auj(=P0-k)q25h zMs>WvZb8+r;0&ts73_DY&L`04{slVk0k=rOF&_IZdaOr3D=4V+IMrbur~Mf2v0tGh zJWk8$c!AS?>zo7oC93lqTn(z@4o=HedF(f6wa1M?M|+&MqsL&sMzuWHT6C<(ZbeV< z*iX?DJx=>H&g0Z4CwcU2Yn*vplWf$>Zvy=XqQ~Ss7DIR+_dI?NpJa0v>^4JH_=^pz4dbP*SM`w8K{pd9wdmnnO$KH!x z=dtt9nI8KPdOh4oTTh^~JoX;+Cb*OM1?XJ3i|`6m?Vy}}1zqH^Z=#QS>^taUkA5Cj z@R-N0M<4gtw@_^l?7Qd^kNp^Z(qlKEPkHS7=+hqiA-dFK-$tMD*!R$9J@ymyA0E3A zUFNZ?(SLgE8uU4jU57sJv76B49{U0Mf=55+D|itY1FPvTd#u){V*&Oh^i_{ldslj_ zw*R`vYMXC(toBcBV$7`e<1>#{TRw-ch}Sy4@mTHmj~+|^+Hx)^kt+0bPox^X(&O+` z+qrNT=LLRj$2?Qq!)Qy7dj#FX zq=d|)c0a&RwEH)aeOq~KIXci2evL9d`%WYO(Yt>FBH=E=4kE7sXkNZ|+9b>re zZpInEuVakXJxcf`z8*W;V|${MQ9|ZJ?FdhJD0-YHr2X1oJ?=-odX}9+f;+{$Qw%+L zHa-{a1-%L1gO)-c!t>F7DI|Cp9S9Y~FG7dFDTJ9zNhypa<><=3!(y>POQgw>gOZV> zhF2!L<|f+@t2!Yz{piYMP*DA3mSoA8F^SQ+d3i}0mXz{DA8L~Fsy&hb zvA(gSEvTkX^~x(Mll2m1$*e>f9-v57r(`5G+>Au5W?{Y2Wid_E?&f;)_5Vp%)ptzN zb;u*JJT^TxowgPhxdKM$$jYjU-0C62Dig!Qs#{9DgeQ{B4B5zm+CUMikg+b6aSySDoQ!=}dF2rKVrsV^* zX9Vz2GFy*^aFm_$S2HTgP7O+oF&Km4$!6tMvFTN@WHW}XQ?hyCprMruZB3tH`N_s( z6O%e6TNDmDvU1Q-J~B6t_!g=7oWh0Dy!`0Oh0U9nCrx!(vROwx<(OJ!3!CcyviV=q zw89r*K}F?4Jr5bKvgvr3X0towB`B5&Gaocvi*P1u>M(lJAN%_g`+H~og$oyov`8?> zHvDT1Z)0nT|jXX{LH% zPFBa{)g5!=Oz&3ov1P|j$vp}e8r9Z}x9XmS3q#et3Kv?{+`@%UwN2r|i0a;j3+t&y z3m0ao?o+t1zG}xpM#GPPGE&7zCt{tG<~TiDIwcG1B(~a}c!p2xR41|R?!+^FVysY- zO*{T&Kk3wCzN^~Ly8X+ee=+Qe(?8V&{Zq}Sf2sxaPqi)mQ*B58RNK=()qUxoY6tqK z+PN@Rk~)$0D~weoTUW(c^h}k`iE1?2S?6p~VRFBY$^AGV_vcjT&y4-k6EaaBD>d_8^teVJhO z`BQ5(URrS_=dVxiMDfC|rlt0^JL5qI{k zl2!$=&awWwBrvpxPM_XC(Vr!#k_#WJE?1;tV_N1g!aZ5LS|#@&n`JpINM&2tNXn88 z%R7#p-Z>GAl}xA3Ucb*4>+I`GMiOP2+_7Ypt|_HQRz7NDE|&YKZR_?LR;DX$0~T%C z$AUz^s$>Lj|NeC4%rYJQRmqlD)o}80QDw2S<<+@_tA?>Y{IN_mrm_Af`c)U_CTO7_ z{X|l&P~V?4f+4yjM_5E~hGW8U1^I&|)L5-oD>WkI|LK+Vx3-upC7H2^VS#I#9*aZ? z!*tN@q+|mYlUS@@qQ5q(UhJJoOLfMNbW(;^c8-;BL09VoA4#RVU6G6waC9h1yZ0{M ziT^(HsuF2$vGR9H9-L_{HTr3HRp|!jk6q5VxRmvyvyNiF?@j6ce>TDXC$m_` zTi3CYL~(9jo%xbCENy3h7T}&8Govzqqh1~J)Mq*_>E7%ffgLf0Bl39t|9=c{Fg0=Fz~hh1^R>IiX5IT-yl^D}2=WxZ#9++z8EQ zG8l!P;U z@DPG$>Y!`3WEn?iajhk&c_#Xx<~ci+M-w#9ITSu)XC z$uPfSQs#o*Nw@)AF@)`;xt434zvY{-Q0kR&e|^aQc}_a$L20AIdBH~athQOL>$wK$ zs3F0?pm(HmWFMD`YE<@Yi)GE0HC|SKS)`Qbk`2k$tn67S-Tj}&Jt-mA^o99m+L7EX zOsmx6nm!BL>+zB-@e$HzSnk4h8ue7x6fw4R+L)oKoFwR9X`_l@Ku{cMAKA;fCLNZT z+RKyn8ZP909(6Sl>BGJ7f9r3!43`StXZr#7$8EXy9vp1qO{zt;+iM4t@>|*mby7D4 zo&QsMSU+99zx3AuFuiIoFr~HUaFjX@dz*{Ga&unV&Kh(zY~k#+&<09?rypiKOochX zp2(~O@&)7z$QN{l!9X3sWS9jDc)~CVX2N`)ahUC_9-1XUxh&eKPaE}Vqdslar;YlwQGY66OMPsqzY;dVPQFo|1BK8BMv63y!B&w* zRM?2)M%(xzcO%G$5*P~Of%+P+5otpEO|Y%Wa##!GZ%Y2A;5g*d)@d4~&G_kc1VmPNcbo8lcV=r9e9^Xs5+AksNHx!Oom{uoPCq7Lk^eX_*ft zK)Wqzx8+or1B-z+TTO%+K-pH5ZAIBul-+}}d$bX0Ex_@f9Pi2TUXx+7NbX43Dbj}H zHnU&>Ea%@hoCGsrKHrGl1mxK#2S|?%2GU~N_@-VXSON4cUJCRlPJiOlU@k0yRX|&* zPuHiSb6_#71nSmLc2l2ta-7d`KF6s~7bwFCAZ;ENpDYjd(!vKhW3Ds`(oq1*tjow_a$$KSv)nH2H4vXdplxp$E_lTSrCI_ zsDN=W1;|%OzC!X9ZccrHT{^W!i(mj$@#Xb(uw7)oY>^^tD8h#Qv1fnU+n@e*$>EFj zh0q5^igYF1O@K1pw~8EyO$RQ3<**jE@sgBAK)zzi6jP>nBFun!uoPCq7LguSq$hcM z=EHJc?9yJO1UpJpOQ8}bz%-c43tmV&C~HCwl`&aQ?@r{ z4_*Q5V7o|Z1&o80unDmFkik#`qWwce+73Q&7AikVDeXzAp5e$GTb^mPNDXN+;}A#(a0emF4&WX-zqXiU?dQC3GG}m9w>9^P{7v9$Ul|xQ%RpnotKY; zog!B>f_&%-Ns%jOh)m0Y1tM2b&sCFQ9ni*f%1mD^a&-|<=hd52KUS9+tx@7;tOVM; zrUoVgbzMUn*G_6PrzTG)nWG>;k#NU+#;{coQqW!x^!V+F6gx)g|sPmqAu#_LX zSHc9Kt$QhVZw*X_&9GhMKJ31aeD|${wXlVk3{^lCQ11RIylf~2ML_%WXTn@a^5UU< z=n8#cC{WJ>)bjxKJU~4U>=bzr8y_P5p^<=X56ysiK;DN|1NjzMXafs?_`eSjc{m5K z@e#t0Y!gW?=Osk6zpw%*vxqtu4F&9Y6n(UYAL18639J@*Y&>k`Wkl0}dLE~*Pt1oU zyo9I-Ho;C_LX-oPdy@K|90?O)2F&BdM00ov5%nyc%FBncfpK_-a?fnz1w_REgX0tn zM3&9w$7$I5PuhB}5|;6@p_#m3s5MOH1w)NsE>QMG>V2sVtl_0XlX#g>g~%(^^(uK^ zod8>Tc~A{63@U*oBCn&bqpL*Z&3qv67J1%Y&bD_bF9Mn-@-Ff3!I~l<{(ba=DZJc= z^tH78QG1b(vG0={K3U5KY+hdo*tCIs8?bBRRG{8X^I<11>mmL#Z2D{xKU~WK%50{d zFR1Se!e3UvCSJxfkFEDOUcNH`wu^jCnXikX5+=cHSORNcJ3q>64aHCilVCP1fi-Tl^^iam+!G{+XRsx$o~U< z`H{RoZsEl}*#A=@42JPA0~Wvvpv-oGX}la}059;N>@WGy2da3954xiUsBgy{k)71B zb1E-%!OmTz)y{?`KwY()dDbw2=LmcXX)1wF7=wJ^ZN1@0SRuypsibQJ(O zz&uzkJO={eTkhngJvBgmt+tBUqX-7T6j&vuHT~X`GJ9E=0Bd+z&m>qarVaM&-3Gdf z;n%7rMmSa?CQqO>Ooq8);uB#8&<1;U!=BwFuq}}fw3Q%V0$U2Gqb>Q`CV~3fZV}Ti z8`=Z;+ASB;9vj+E1L|$R1lEY@fNdR$fIJ<>^CF%KG3=jBr)6UHqn)CmV!F`Q0p#gA zUrcw(AGl6T@oX_Y2=`b39QPamNin_XN3X6x{k^E4{jDjP1mroWHBfJF?Crgl7v<2_ z!IWX2YD!1KQXsw*+y9C~=tmj#m5&qCr<|%JnOR`C|H0?*Qx^uvyHZqz@Dzeh}fo z17NF|!)Cy0AbdD!M@$q`F&T(EG7D;8Hmra(Vuo~uxxDCxc7~EZbQUkR$%dtXoyYWn zC1Q>xojstbtOWWvjJV+yK-m%4H-a`skUnw%%mn&z9Q7SHSj_Pj=JE0xbksOlC8nxM zOtk>{MmGZL9lch}m{Oq5n$2QPpxzTpV40Y4MSKeYJ(+%-vWZ6mNnSET`f0RrdOpnO zg)&olkqmlf1?=R-F%yBfvzCgPNc|Hjb2eqp9tY$*CkIGBHw(JLY%!B4JBfVf%@K3{ zBv>Wpg7z>2wuqTb`s6BDBIZKkFPz28VFm#8UxeKkt>y(W*)SApfVhj-in)Zmm#z_W zSrJSF?3+qi_D|*tj<1+4=1THhxme6J;-_sAa}{-7Mfs~VyiLq>%1$2-OT=6~0kG$4 z>X|VBW{SBc2k6hW0@Qac<*us$!ZR(9Zzi@}KNyyYxq;&wR*Jc?7^c7qF|(-qrYbS) zd(7Vm&mIR0#N1LS=GGcsXww?D@F-@knA?YnxuZnPodT=G%*}^sfUS3tcGr9{cW1*y zSS{ur>b+;Vn0b`FcZQhzx&ra{j~A9zp#J&W#XL|6)b}9q4-x-RF>DpHU;xne-#Pv} zU5-Xv+s39wnrLh4!68fb43HauDcOL%lN85RS19%};?FcnC9jCvoB0rfpT z1C|1DPmu2k@;yPmC&>2%aZAXzgnUb;0r{3}74sx*JV~A>my3DILNUyQRbrl@j(?JG zc@|Uxb-XY|%!|aoI9tq1gT<`i_+`>wseyH3UM26Vr9c}ivw`r+S+GLPYpr2CEEDrO zX|Ge}b>d&&F6Ir=-Y9`8SO9CqtfHM&6)*v20_9d=!<)pvN!~Xp|K?O!3DogcSD^e` zo5Z|Lxwn_{a-kfc{nb1977h8|N%E2*^1Mqu?@a{Cu89HRHPrvUg^@59sPltLmiUGbJ|W*H)cpy^>jQ`DX>n==L3MUpKlklxdImOA`|j{LAftx z!)7sG((ad({c@?8uLSzQWLTVf9BH-?{#PR){$KOOeBB19>+4xS8{g!^IG6)F#cUl6 zgxL$3Z$|?4d`Fw#(Z+Yn#e7fx?`Oa!G24oP@U|_yaEb5_Gl4$*SP10*ag~^#+Q39u zB4&Fw427j)e$IjMKs~?E&tH;ab~FOo+_6B+PQp70?i+SNN+M<0`@Widzm1660DPeXPH6s8VOot18wE>k)UN8SRp|x^0wM60eg~Q zkGT@Gu7Yh6?73Wmy|ze@OB-!suu6ix$HP_$qC)}QhrIi2mmo$RG1|=|K0X*Gz%&UG zgcH=2zf^*P9GECUTk^D{{dQ|5XivTE$-}e0pgnoolXqXV!%hi0lHSQejRc+P$9^*< zD4H$7{8Mc+LmY^^7_9fhp{`a3I!GL8F99kj4 zz^*Vufad_*}}LJ6nQDZ6r94yywlA;QT7sD!~QRIeC)=7cQ0HBGN9R{fkRsy985`5?nGE zX#3J4SO(<1EDI`Orvy`DFjs=hi-EYymrHO3dAY6!SCa3_NiYYfW7<5RooQ<&xT;Em z=>i;IO?bvQ39gwX!L{VQj`G)SlVD~apxpK2CAgt0?3Ccf8GsEp5}q|#f}61UCem(R zA_2EA!7WoHxUB@{OE8D>w>OgD4*GE?_06Ts-COwL2|*z`aSRKaoy9vm#eLl!9e5NQiYTTlUn|K0}X!deL)ChlSE ze3-T#p{_?J!3-e%k;Op%N67ccRtb{SmuwA%Pzpm~983nvEF_)h3Bkgtutb7Ijez4t zvw-rCPLN=63@Tx@1dmbIW5hkSK!V3}pbCh8A`2+9Bpb%VJfOZMD`6dMlYq|#gD2?+ z*ZP2G4Z)Mt`6PLtoB~T>s{~Iili+FcJUv^2rPRN4vjopJ@1AnhOIT{aP@@1N*% zgC%$#o1UjX&y#QY0tsHAe=iVzaSku0n*j5Hx>ppzBne*5hmzfdd_Kow&1ZL^M5Mm# zU)s4oA9)65un3DZ=Z}QOgvSd1V#_E?$Q&V(RWIVmA2xH5JvtuHEU#IC;h!OEHr&kH zb*(AfwK|7?`1ONd+nyTq`gMBHi?zQCb+x69dXg=LrTaEEmKzSSToG(Aj)sa4b2Q06 z%W^m$hGmhhUbAM+BK7y|ctDE-S|r*f>a{qaUE8+pB9VGso;~lG5k(&rl`SdGZXN{9 zv$dh;o-<9>mmbr&@i7Ne8UJQjs=e@WK5sNc)QemnjQ-R3n}W(Z@jInmWU0mk5iO_n z)OHNo@?Gh6kyOsz^-cPHx!v*4{6#$fmSNp?cIW@c@8W;6ch+CT>%Rw>>EDUr&fWDa z%f#=tHPo4Un`-}MJe;2=Scm3C9;wrW$-t$l9yeU{aoq`UjR zVRs+-w+{tV8I|gfSnEbL zs24c?Jq^aWMe}CalxoT;rGE|U?@h1rS|(c3p=JlP%hD%uJo;@mQO^_S~aIGs-p1t5;vwkpsH4YMB$M*D@L)iSU3f-Me*do503& z;J7zx&gkEx;~@oS)m(8-&+@XK=T1KO&_fTN9DGnStay0C&~-Vi^YN#edwO^4*8A5L zfYt$y>~sX|F1rSVPhOq_N2x!H$9Fg{%QQIfRRnv-z{bTesWW3 zgZiePYi~@w%#80Yp^exuGDRZ%+cx|Hn`ejh%$fA&|6}gU1LM4^d%ye5KH5CmcWE@z zjP`vrT1TVBl4UI(OO`Er;8SkaP{ zUhg4#Md*7K`%2RHL8has%##2CpQb1|iYI_uK_h&rs(iFbzRbx=PemWQ)1>ocE|%JC zc6n%;4r0jpFOIHub*+xBtPGBi53Z;;I+lmR|2(wP5!^l~Tm#!dBfQG4y)Q#4QG9`R zFup}VIw`AI5_J)a(@9KcShNZQZc@TNEh#R-j>x3Fn(lNsY;^oNTwdN68^%DJcYb<0 zek8|^i5=r2kT9HIU>gu!Xgth!PK?iD<}>F1w{e2s4`Q5FUZd&DyGthZ0+dn|< zw3axp)3BCB%5ix@*KD$&HY=T0lL|DvMM$eY3q+JV($@@9SymEwKz_xf38f;Xh>mRf zkAzYzE4UJl?-aoMolOI90N?q$>@g!6uIsRwulWo9!KRv_#Gp zP1|6#qqW1=maYo#wp;yE{`LXiQef~#Q3?B4{ult9G{RgL?Tsj3B z@VIzCc43@R`yjDhw+|BAb^ScCUDwa&Zf>D@V?W5}Ur`}_Bk!esDBB-o-A<4Wg*yf5 zY@(A1$Am!`S5*+CbJA>5weulC*5O>h|6KUr{?N;z(97zL@H3)w-7SLQt5`}tf2Q!v zEG3ULA2P5~%xI<)$PN?EZe2ABI)zegs>RY}!P4eI|3d#PT3-Gy%~mGQAP~8YexNbZ z{~T>z*Z!FqyqErX`DHb2{1W~fU;h=oT|9OR=E`$o8V8uhOdHH?4RifD&lP+I+frzU zA&y36Q^}4~(B*~B3Vn6$eeVVW&zIGur8VHPrZnvL5 zJTx{oq*~WsIeZ?=j(6i7>TS#iKq>fq{Tcp-4M688crI0G2-I2xaEysfcUh{E>c|B5 zON|11EUV3sf>wJYF`!I;Va>L#Ln=i@!omtcRU~Kx0By{Mcdbx z@Ls|_OiCF{Puk8n#MA?rIW8R~S!z;D4u{c}k6lJb)}@fx4nX4q=_=>wyF8Z}e&$2s zhdf8^nRu6Mzg4^{+c5@dd&~AKpf1rQuD`GtYH%BAmSRK5`e#MfRc{^92XPZT&NM=2 z>^7?f#~UusC6Fe`pwpDJoE$l5i`R#N`*JKa_~XYzk3TN9i{|aY?IIL@@l5bc_=nh_ zNP58Yfz&{@GzRK2QVr0(@o1n+Fv2h5h#>&Th@@so6iA?4EP*^=+Oo(vh3VDd!&SjJ zA|2cA-oJGB9)sCxr5fj8I z%rwxA5P!Zzr*I#i!Ualxt|Q+`M3NR5j~D_{n*l87UkrHtuVLtW$!j@Y+P89CI_^McoPskv4O$#_PxRC_VQi6on~^S*-0bwCj3U^~ zX(G)We`sUpdNlJ%n$Dtr`Sj^!`swNK@97Q%?5B^4j-#hfuZ92T(bGGJ{9?OqI%8}+ z2Bz_WI2tFm>+(IZU6=3FE^#yY933~CgB~nxBWfr8obV>n&m|^9-z#Q)TYgW+&8S`K z?Xq3R&E)$DpOfu6ZYJA_#MU-76Aha8mmz6hPkOJTxQsu3YdvCuDo2Klosc@@?2@DSiBsO69;(Yb$Cg| zvaku7Y!QRr-0|kp#D#QQ3de)p1#RP-t!E~$=dFs|Gdi8?X#AL$Y}av1IWMAvY=5^p z%zIC^6CGsx2Q^$#wiBIY`}B(GspE}vuwRJxOO!h0pge({WWGym z1qX>FD8Lm$69_))Q((E2DhB-9psXb8OE_a*S*cLmm8ErMb;X70sTPw`B1&{Ux7|lL zqXsr%<5(=Z0b_{YLT~X6b*9N}ROcyi76OF)h_;))?yYX@kQmg7ntN57pA=fpLcY1lg)46NJae8^ySJU$^Wux7JJ9_$Wlvm%=&_`fVOV6D(-thJ1 zlXYWiclc@Xu9l(o|G<1}!W6X(Il^=0^(TcPUhh{}XOZi#%f4#tr+#hyUzF=_Pk|4l zKqzK)q9{PW*a`$rp^3ekf=0HW8MdGeTTCngfd;skVpYi=wAfYNaHwoS7x6RCKb2SzkOv3iW2R`sb_&-dB!bW>- zb8{_z?1$&X>AAxtHQB-Gm!`wh!K~VnU{9Mk-PY677Ji_u2jqvmBE5|CBRez$(h8v# zKrLJ)4wFzeoiVHwWI56R$|?3roOrA)F;)z4ID!t(|K#xPw;z7!p`Ovvo`=*M=a!ex zg`X97j`jJWec)X<)ifO^mrhvlDolA;q3}XMLIQ&&V@t>4a^3 z=QveeIgwX}LLVGl>Nvmh!4Gy14t0G{z41tEsCVD3*MxDv*BQV&gUE$T2mfR#PNg&8 z&4f^Z-jg7P@#g+XnrNRo1^Y`WF3bjsMRr(~%Yw<8JQd~yiI5k+7UC1DM!V_IZMPjd zbX&Lg-1mtD___99#JOb=SUz`dIs6wx2MfOP+wFZK;2#_FhyS7vD5c8Sy%Y3LhmF`4 zXtoKJ&<*LABb-uO1(@v`YM+8^w z!^55TsW*T}Y(JV4{)*@b|FyVxw7X{n`w=#x>g4@+C#VqJkBRNN?zA5|F2)PFF8k}c z(>CnWEueD^WBf)Fp)?o4OQ7o8Fb%^Jb_ccy=_?V8zZCw5+-$ZrYDA5GyW0bY z<3?B}FOQi(G#`CiXe!{}-c)~L>yGw?KL27zXxQr=tn-{6+j$4j|Gur;y6Xp0%d%HT zy60M2_H?!O_qSGerIcr%m^g5nWD$><=l+Lrb5CrSI4yK&oJBOpKFtqc=!o+Jn9M4m zf{O&QsD_9iz-%@yf!|m>Y~lw<_C@7l#1F9X3A!JkPw6eH$f~c%PT~i6b7YKq1^!lg z1$NB84pk2u)L0KeAmf&q*Qc`PEl5IZU9Z~)egaLwPjU@(ej>S4jD1l~ySC7x3KO=4 zgk{#E+k!;ylEoY`B+8ZYib`iyW~J3u43R;YUR#cZ83tlQcaylhIN#wunr~n1fAO)Y z#f}35LtVWiBfSlOe3x%PP4(|@n|sc5a$jJnV|rU(@5s~(gWc=D28)mkgAE-950L+J zC=h`4MDh}x4)>2RuY$p~<%SQ=6oJ(8^Mq1dlvkEt=Ez7(wOdU_C0FEX5Tw`ZBrh9A z=;ZRj<0qH>-M{FupILn7?f#)*c(hI~ho4+LGd?nK z>C(UmM&YCV47ynqXP}huE3t^fsdLh(%T>*_FO4mU=-hlpy!?!MAHbXom}B%A86>4m zLSVxJ8f2`B{kWZzR-xflFZuf1~4wq_DVY0p%YzSv02_E1(H@S=?Y_K*;bM# zzKCp;bJBTP^2`mC7J>~-h)^QnlAgva;SjKaHAg3q7Itn*$ff@9u~1K6Z*S-p`>7>0 zbNy$;t@QWuNxYYz&$N7iX{pCrB)03eSz^1s7iBx??D9FfZ4?5=ChcX}uG<8O&(Uoo z*-kcr>@RI2U;#KIW(?buLW*(8gKcLH!dR!MbZjmAUo!f1X|V6*dpz^{U^s9?H@Bo^rtz> z=jb@1>`ye5?X1UY@0E6sq=|0#NLmr@DBE@1F$CO^VuH$*-IDc-B~%O+7vwL8!9&VH z#Na6a%R`@1Rua0At&=5`vJ&!pq}XBSl#6oxsMYM8C|MoZQBy}q%M6!JmC${?0Uq(U_HXVgDBaL1nbh<>l>d7r$6{lMEv~Z5Z?`RonqrAr55V zP7u`^&ZXn|rAnzIKVRZpF%OTv#buB|Plj9e%ydC(R4vABOM^zMs+x>FJNBL$gqvSA znnr=;{J=SylQZg6i(~%fR^1f?nVAC>>o>pyJSOJ7$KrS|v0dMfvYluq`|JBLu|M-9 z<_rsqG1feqb57v$#$Zh?61?#1)K@vjI`_fJn=dDK9}vZ&*gLUeJqHV*7Nqgnuv7Ay>#NoUj6gGiO$eg})#^7XFNw38{_K zq4jS}6J7YZJpU)+=#tp3>+iCi{3x=&?*A&l`1&!vd_oxWuwNuVk8NY%!ZE`m%mVo{t1azr?BB#SS<`s(U0ej9EGiMNV{@MGb-Fe^8Wo$Mp&hxi|i0Yenlu91*!_^)+fkW8clbPNK=Dg?^mEGuvqy7O{U?MlAL*CjW3 ztYh#g861~jlHNZ&y?urd-h~-w(ec04aH(rM21_%JhjgU(z)5>iv1|Hw@tBmV3_;I* zO>G9^>{jl&o-eS18U_W7AfoeH%)%1Uc?TwKP{jahS|MfucND?I-?S@EuP&{>=A_>n zC@Luy3Zl~7CGNc3EJsE+{}rsLB=>yX$kHZ^BVV6Zet=ot^vI?7_xq z@8jp%18T^0V*cPQdsXZ1mcgkj^}as);$+)IUEM8^$+HJ`hwnMq)-w_CO?vAaz07w! zXM+QL^hI8~TL_cDnkKfNqUJC7J1&2 zaqU+k?VpKjkB;}mChf`c0$NRBsbhU@2CpDTBN-z(*JDaImEL+jseVdENz*c!vRHmk73FnKHzNJ^M_5jbI=c}l|+n>KvY z1k=#GqFaUoNub2&E|Kp_{08E2l0b}dKpq9?WcLY3`!a71TWUB0qZrO z{As|R19hTKSg=^*R~^7@+a!%oD^@`B*3)(&(vZ0g^E(9xt8~!~OlG7as6tt`rR&nj z8(A5A&1|(?d{f`s8}M}cgwogJ8|WNpZ*6KsBvEBWc}X#a&XS0NN{w)$EfEpb))r^Y zL%E`mRe-pWXjKp%f%I8=Kk_MP((BI#rgshPtSm2c?-=iG88(>)8V7>kttv0C+7%qA z8?ahO&b_k=pMJpU*-_@Mu`i5o-#1><;3*&2*-~BIvUl{|N2?pE%Lk@gtE*eZ)P$$8 z(Gz~6(Q~xDzOJ434%3!p)3ch4Tjo7NF|h(?VzyGD-14Lyu~h(EG^Ybt7Z$4q;tjy% z!0rb`vPdcKO!yquNtf11gZkiZ$;}Z;Nl{KkZbe2KCog1+Y|Y)`adA|MrA?!hbX00Y zBnV`}AGC;22>$S${+Z?FQ(b{Tmv3Oe-q(RRfGc-;{l^zSzHof1cj(G+&xrpKKj9$c ze@fx=Yx9`nfj1R%j6H${%yYRJqLHiU!zMz^@r4Tq7ta|&hQUt4dpig5&vQT?A6Y(m zc+T53=$&(8S_Li8) z6R5pUK&fiF2o56O%2ABDGkz~tIAJKdo%I#dX~%!~BvvV^ZdTgJ!wKVv zg^-U3+y?ZCRM&X*l@|j1U&)Ah8{!**Y*V@wAX+O5_zsw)g*3j!$o3C99mk#w_=^f%f zFl~t?t8Lp@jwT?^JoG z-{0BQ*9ZPR#QfVkK07%l6O5wUfM*?MF6gUyHP3T&$zZ{yeTE^f;=;c}RMYjxPJ3jXa0eo^*8C zeumn?6Ee=D8PV&F%3TuiY*tJ##sT)jWnnN`kb+>fsucIZ=QgtlP*7N$2W&zM`)Jtk z6*E3FBkN$}R|y$~eO+JcaaUFpq`(Nt;39qmsXL_M)Rd1|-#$IC0K5 z)MH;db7pDzbogq2-&#h<)au#7s&n|KulW6a{lHF}yk{04Sv+%QamhQdb$eYPD^13P zsHr6bBO?P5dXi2o>2q46596oUGdVyshXR}Wod)2ViSav8U{O(FZfRcWmh@C4Q^D_q z;GzV-lWt1`PM3x>olWF+n&|bfW`t}f_bi`;->LW4eegT+z_;$?X~64Lf^lR0q|bLUbn(3@CpTVXnnQu$#s_h0d7@z%3`@26V3rXh?oKS49qsn{QpYGQI8N9}m3n zf_TUDnSt@??laTj+n7ft5To79^76!!IY_UAcSy?1a!i}fJh29bP?rdD1eYLQZ;`ZB z#OoCWDx+Nth8|)Zota{~?G5Bmc#M>icu`SymB(p|MEJpRh&-eiF^Q9%66NB~g^z!z zsRIQTrg~m26j5r5-x!(3EhI_r0B--H zulMjAl9pHeLnDFkV>C~CDfyesD!ha@Z{CEZ0-wTPVO+1_Ul#Lmab3BlSP?&a^%{rI z;yV~Aun3GDqJU_&M%WF;&h7Z7O~&=hQ1_lm1G*U(lV?=OAZ)~&%s%~TVS8#?T$&Eo zQ#`PI2V}GMj$71IO#j68lNxT6*nVP@_TzEw(K#I1q@CwR;{lc(owG-qvjt~{#H|wF ze^j%(WjkcEHjlHh{Yf@!?PsVR`)(Gt2;PJ2hbrYsX@NITNE0u9fY`ve2<@bYLuky4 zDK^Af!6OUPd=YY&k{zW$uS1|P(f;S)%`~MdPyvO9B_$*ibYgY}z?Y4G zry&|X3%QVp(c=IH2OI(#arn|n#OK$p+=30f_G0+A;eYw} zf5#)hlS{zA@eaHjncUci>;p$TI0=}J8+#h4JmyZh%oKN)rc?*2^trQ0Q80HDBqogy z;0m1m6wFM1aVOT0a!|-K-j*ZYI=1IaBHvy9`0R-I>Gb+nDm=7D`MKmf5Lx{Ghd^I? zpY${SK*=Hhi-V6sgUa#sP!K3zv~v>i=vs^wdgbKgvZE?1Y6l^}3U(2E&W6^%F0XoETYE94#W1^xp);`0S``tf{nC}BV)G;^a@3A+Zltxk_4%ZOvl zhim~NA|5=bv|3C^Ex-$l0)-$d*oh-_DV`FliT)v{`QuTQt}ItpRV5N_ zDRczJ1|vXu8_tZ#;n6##np)hIttrCN;`a9MDlaZ7-(Fr+T&}vusv2u6D{FW3hZn>j zIX!M?cwYaT#xKvXX5d>B*X0o=ho1%dC`$qy2l1sPKokY?cHCmgRakB9fD%#qf74L5&-!G;aF;1#svth+U$4!Ux1t;Urw>Ic-_Ha7jo{XHzf>6`(bqm-gc5aCWPmiOnoLS zU^(UwX@u$y6u<^`DzVGn0Ld39NtKSQDnug|=@Lpi>M2)DUrS1c==b{jIy(EwS|0D8 zIUutk#NM6(I`~zMP9K@OB|1lvrE)G38z$TF71$4rkQ;Hi5CeSn$Xtj)Woolr2wj!m z05R6DoI88);MsF4R6d}4c-VUO$lKP=oLPI@k+Z?Uz{7z-{sXk<_w%|{FpZ;jA;uNc z9<>YO+oN`2e0$WsdqritP{`+RunW08nO*n_;yB^k(Y_b83ty3Tq1GO?3+eq=BK@Ow zA+?hZBHtgi3(5X#jI>AXzxa7X?LTTK9Ya2c?LS4XUorfhdC(rY`D0Ynp%Np$+JL6e{c$Rphn0cUC;|-Zpu?u<{<_ucM_E_4*_CKo1 zoC^6IqMhu2HeyrL^J!1W_R}%#TViE(L~|m{TEPP^SJH=2XP? z<(!K0GNE{?%IeGOONs#Vo0U>gs-raIX^I$5MDwT-9dAB~v%aB%3Y*NTXspX;6Z(;8 zRz+@88AI$Rmf!E+SD39ORX7F%kI*i~AD}(uRD2)$#uQHSQpKZe4~$Yyg}bUC71B*h zseoim%$1-SMe`}j%M_)|Q|>7)B!wU*QG&&YOq9SxC{eyCQJDb@ctqC*9pIInqUW-mpLX zqpf|9X8p?E!0r@bvsPk@A^S*&Qfz=y zY=%`k(iy~(JeE@}Dmiq_DJlbPwKe4J>h!fV)pXQ$ILk_k3jw=1GO(Q0qB;$VSYBiu zk)z;OW8GVXj$oPH9xYoTik3#)UDt-DriQB93K5-D&{jP(_1(&{!YbpeeWJ6vtpL&Q zg>9u}m6c`XZue8~aF>@=+V_n8cKhx^loqHe+`avggYJg%LjRcjeX_y*TXzHhA(Tn_ z7t|Ewf>Nj#o%I#UktZGTzAQpVh&Ti?y zIQAsMMx?-Offv*XreMEZjI4|wD-wdVT%gT*ssO6V3**8=Xl7^`D~=}^RhGSu`Bnd73WrtBa!O=O@{M8OnYnaXi-3`~yWWJtA4 z1a|Kao$K*KfAacQ7n_6l8{54PTs|~!otbdg)mM+&a;=m7+opE} zO5C-T-PY{vcTd6s$GmyGJa3$*Jn!YC?W~LO{JcEBZauG~?ak+PVBQ7;=XDH{`W#o^ z>CNSJ#5_UwwRS6AHLaQ5t()a_ydeqoQcvGvw`*Q-&+E}MEjFjaZ{9h&DRqmq;!jCv ztn06{;34n|cu3No?SIf1HjA3C{s5jXRANd+*c-)uBOt?Q;B<~9(2moC#1hgubThnG zsjYNYIvZlrIkaS_oQ*jhOcV`cgln>Y!8_3IpXyv0>~8i?ZtL!9^bQSqJBHNUzWwb@ z)4rZinjz)Lw%+;n>22NJ+k%709UAFee;H%_6SBb|b5j(m86fn!M+7R%h-8#Ja=K(3 ztA<=7o8(XSPh7=?xoXeoT(G`!{i~P}p4EhTTh*^XHh2RRRAjgt2^Bzk$e)RWhP)RR zXtxY^kZUW2OnCx5aEUmnP8#T;yW%ADu`)dU(T|2+c)?k8Wyhcxn*Pv-ro&%E6kp8y zirBM8?}PH3VplDw>9`vAYOB?D0C|sHHUgPYyeB^wki7ga6-7sUaQ{VIfP~A(;03c6 z`1RMWVE|W#r++^FC=KD!@db=w$KV3(L7un42|fT;3_JE#H52#7F=ji;m@SPJxFXS} zO1YQns#z_iLU4=^RT6AM2^QnsxOG7RN^_ASW(~k=*&@||MYdOMi*{kN_1Pd%>*Kzm zpw0^7XjhVc(~4s+6Vt9zDq*(cznpAm3MOsRQ-rvZT4eeXand)Hu<@=cZtl<*;e#?e zMAl6kPaE^btcjK-!Zg9&z$7ZPvtg-DXW}*Y~_^C!0||U$+@$`>(Zj zkD1%S3uH6D2wpIVt1s&K{bqgX-EX!p*`CS!{>_FlkS(;aFXg!)W?!3!Zl@*ATeop# zJK1S+-qOaEc`kG6dlAPxHGVY}yj%=}L@}HMilRX0=JOsNvL)y`{RFfW;bU07Nk82i zu(`4_k!5Q}MjKW7fCPY2i9Anfzq$wtu5gEV`A1yibxmg%7f(M!YwzE>)h`xcuGY1O zUtBtMiqAldS)JpvaUp>h>JW?YUd%-c8GYL3Cs$ zxjR!4;fBr$cW`NTE=D8RU z=cw_+Da{U-?L-qfM`^DKSZRt{fjK7RzL0lHKWUQZzWnm@OBYhM7)|N+3yYsu-QfqE zeGW&TQ=DGEL1zxkRvc7rvU~%Tg&AfboLce=W1M;v|C>*Kxji)1X@DR#8MlVE8ZAOK z8@jhItn?cJI$KSH7{Oa}y$**rSKJl-*ZK|d*5ZDLqrW(O7g!DS;c+qVA@(gs4kfnh zaz(b2T#@~CxsuqQc@p!M7{43XQeyr~&*blw|I+&OXO7-#Ni!PKEVmy0%wHZoZ%H#5 zGpy%Dkw|$wrO;|EOnE%~>+nn0Qc3__r(DCkJ79CtTBa!#fih5tka%bgFeYg+kynlx zBb!~OzvTI1(qF`%?fl!NOV)IQA>DHOV)$p*{z)~4|7&*rmM!(!V%IvkFF-qfKGP0b zeGKgq+jZK>cA}l^uhXsrSQN$?X}_SplJxodK9|p-eJ-D)?{jYFeJk5}-$uqsye`{y zUJtQOMSj?g`7eCjy;1&4NVKDvz(Xkev^6B|m=1;S;rthVF4N`qIJzXZN6s)B2jiQv zzaHO0`YG~_QFr=YJVz)4_`MD~V4U9=J|ZmX8~Tk0p1CH{pP}+xvW^r#i+xgW<1s#@ z#j$Je0Ig*Et(w1Z0D1zw+XL?zBG^?keGb}E|4&l80qOE0%fRjM4d4osNF6Ednb0NL z11;&$C!tH?vIlncNeAP`Nuc~v4*tj0o}l$1@DG|F`-p&P3_NrBGNyC+@-x%FS`04! zYC8NM_$&O6)0hhAM3_@0bhrYADk77(b_7-Ld^0aS}>K~OR5DEs6*p&5e_zckcalnGjeb< zyH+CV@Q^;dj24WnJE#&KU%F5-G)fr1_@NuOXNWC%}bQ0l8HDs&~8 zEQ8lklB1MKP?ifi`(svc#sptvw9@eKme5e*ifR$R%=d&#fF{@{bdZowne=7@YLO4B zBfwqUko*DV9|Lx)Fq$pG2E0=`xN1`b%8?@%95yC`C{4Ci1j@pvr{SJd(go&&)F8&M z5~c>vV!}5N#-QPAP(4(t8r(CP8u!gW(}pjh1D)WO>rI);zMpWC@fC)P#|yu#7&E7*=*}q+~ZILw&z3 z*swFu-hF(bvEaK;)wCU(w^?s%-_h8(qx~>pTb+Z0mQT1_THK$gYHj^e%~sLA(-m{-=+7x6dglY`=CIG=NrIl0oM zF$EB{@D(oZ?c(pI*Z-w^4q6N7i1De%n2vJX$K|+h z{toiB3^G4UX(f{wao!XutHp}Qc!?z%GDpa6$Gkil^!B!lkMB9mYbxK#=hb_dh7VznVT_Tncwo)LvxRdBpL6>b9%J;p zqVK8Pf0D;8Yh@Tsh~~uTk*Y)GXV(&@K{yDek&}&>#e(dzoU+*I#GDWu0HRMP3o=+% z&A>UaG(H0bJ5!hW)SX3S? zD=aKSu!Xy!#^tJs23!2?-^h>)q7=L?xcmrvEnh*c$vm<@5|WAI%#i#ykxYDS`*f25 z$CTB)b#BO%N(M;d)c7hK5bp3@xm_tKUAZD7{L5TlYN{_+ycMR$V))~{uXrrHuO7wN zqS!}byDo2JJINKdFj*-U!^o+Q6Y@s_3%IQ_z&XjqvzA!l6&rBvK=(`L60}9 zs4Wkg58!tj`sEVNh!hYrj1QITcp0cH3MGN)=yaErv>jZr;gDgtvRpR@#U(`ILi_s= zfW2++c~9V*-~8sZ=n9@27z=iv3x>Z&SmOxZ=~6v#f}yr}X>jg3-hq`aqQAkvNToz$ zpa5}Z&^*Zuq6k4`RU;-B0fNYw47gYX$d9nAlJ=6NTHt8Qa#jMV273^s^+^b6bY6%xQZklHjFbT2hL%cRHToW!pD=2*Fz~qabv!E zbm@e;aomfSFM|acU!t)CV^HouBp0&pHELEs#;5|pGnDP1DrwADCrgH6=fwHPZq`WjEA ztGu+ZAj^@OmzI}2Qku4xu3ROhhxky5%T6MLCqBW=de>ePX z<;s!k8GONmoH%rFI#ZNGsP9Pu=HO77+yOsaQJ^gGQw~tn@|62YOE2KK@bc91lA`>) z?9B8uIZs`g)aRC!Y^_DTQwD>7I(AC`OP`7QyNy$c;a>yf%dI#Fql#Q9GbRe57{%Q& z(^;m|kEa6_1H2vIL7&kw4i=tKKI;+r#{8TtQjfJ;;B3$)1hO@gZ^o1}2ai7-I|&sW zo0MPm{nw?Sj*s#Q#OI-^9kw1hF7$sB-Wi@8|aS$nOKe=p3wc)O&i?7!= zP`zn4eZOj|HaNE+0|nbMTp8fmqC(Wb+=3CNJ1c3!3LkE%;_7|~AFx=G(?D%aFAuJ{ zn;g}D5>JW#thDR_kE=YlJqbmkzMNv^!RrN7&QhaBDKs2mJW1gyP;L19CzqYsqOuXA z5u$|an{C=D;N0*zXHL+QNMD0BgsCG}mGU(+Q96(_xR9->2h~N-zNkNl>p6%F?G)VR z8gFQ#8FM|@@CUjB!#D_~Q>X|6OWK~gPw2C8ItKQo<`a_b8+}5uUDp{P>olK`Y}a)L z*-n_SY?rzL%SQ4EK}uQ>MSRbEDR(!Rkd?8HxU0XK4d{!I8c_(NpI^UY=amxN;?XPEk9%qw4cBwhw! zckAH@=0bLm_=MMSXMstVCVa>@7EuqV;r&n(d9zfMM^(x78#4VTdd3gq{Gv1duE-fr z(?M!%;Dv$(jTqPW<3A{j&IXGbc00gcLQ*Gmw5O45=vom#Aq0n2DG1SV0|0+ujIc3gae zoOdf0*=93C;7OxUvQjlVE5N$M+8g(8q&GzRBb^*?uo{)4`qNpa+H4lSg^%vF>O?rK zK-uhzNH|A#AmQ4(6k`ft+s(ha7aZm+EEGy%V_{=mjk^lfs*rD%h0I|@nHv?jG6=X8 z6^$xovjR#%?T}JL$V!Jna_XNhbrWj#$AAk${5SmB`mM~nzE(CG}7=lU|Nhb^ft@!dbR7uq8k83x+AWEK8BN4q~5q34- zHw3p#dxtnTb9kR-%5_C*!*LlFc2Dy)T3w}WQ)97klxD-hVH*d2J*Ah)s%r; zjTBIPQB^)I{!;ugXk3KYp$8*%(TD@1#m;0sbHJOh*HIr0RnY)??2Q&jGb=l(fIOB* zrP9GBm>wqZ;Kr|^4wUva_|EXHXo<9{k}ADK8dO@`kZDheBspTK2*8V^b;lNX0zfG; z8#+2$Lax%nN<*uuuf^+cGT7U4J@p}9h4{-RkEgLDuP8UuUE5syw6D0_jqvP-+(MfB zQ{s!_W2iksxi`ol#Qa#YVO8X>aKXN<$-#;?qza6)#ef#|K z(rwdPIeUzQe6x5j#sTtRESK;*`EBK0Ly@Sucm?3@@V34u!G=>=uybkoiVqfKrTKZ93bI? zy@6DEB46rkl5++|O(WPfOG8+Eg2w>L72G__bs*D0OVpzWo(Z&ahTK>LfEP}p);4*- zv9pWl5*)g|fHZLcbJ-4?g)_jYJ}ZhOLi#y#d~}hI*<8@zsDveVek2&aqvv;DHHq@e z-zmL)L|k1z^PS6=zoYhruT09=;V>mx7=( znD2S(!qLWw<|7Mt-n;)C{&7~k1z7S|L_hz~eN%hFe@Z_XLp$`{T*v~xm(VR^TH$Vo zzwu(kcZ3*MoMKeTpO2q18QDj!@Nx>1CTk`?H**Uh2#d+c_YzvT_JrHhmdk!5Vn#hG zQI-hDk-|@x9u8#T_ydV(tIs8F!uUw~kiv={4F)ZLO1Mo1(!`fX<%tTcD zz|2<{Q>k^IA+!hOEWdkUkHMsV51GM-D|e0+sHcEvKU%eOEPwq$tS7&NdHkEao_bAc zioc+`nUHe4?)*FT)9&-)n${R&_RZgk-(rjz%H;S}61#b%AxhrF1Jxx)5HVB^tBZVs z(Gx%`Yr|C-H9!%p>p*U`*`nRxM10F!V0L9^)_cHB7eaq!QFrb(?b>lbJdbOq?hBv4 z=T73wZFm>%)53W7@^~Q&=>9HYjCH^mwC|Yid84mD!Ng&DH@)BuJ41yl%+FU8qzISiqauG{0R{`?#F6Jn zWdVltB`Sl|L6Io5({NguT{#{Hxf!&m6l}_yy$imM#okcgLWggmcX#L5*gNslSrBaB z-~ZgeqIZ1UyEyP%|Ni#ihsBS^0?+l0j`lql7^8Kn#yUw}C#+m3@Zbn|e!$aI2Y}?O zs;m;IPze1+6SQ1t-z9k!Od7$xNrH)wU0ygE>hHqcbr}bCiM;TSo7=@(C~}N)f6r3A zW7sCR>k+BFs%e*eGTCCxn?(w7U*r~FkidlCAC`;|;^K$l+e6+bN&4D zJmy}^f$nEOO^85+CT{7$CWK__A~*J#Z3gX$c(Pxey>0vXU3lPG^)mlps2FQ6#yZ1v zK%Eg>F`!y@(Vdxe>JT0uGur4~>NZPB?09M1IjSMtwe!Nrg`NF8YW*c=Z!kUH&igQh z?3SJ6z6(xT)2^&>U%&aNksd}UbUx3ZpN$BCh z6`yZq@Zop$jE(iY3&QqU++sl&R*d!bj*;(Odmr5^6RQ(}&YG|!-8`ZbX}8LxMRX#Z zIZ57o@8y@)s^3@rqnWl{3ppDv*VaYgU1@;cG`qbOxr(l0rBzN_)4> z&278<7NZ#1CKh@ttE($}O~Ed|nje04cI3jytomTM?Z_gsNiI~%FwYBbEA}cDeKf7!6!ssrs68^||UDXA5EuS^oeLpyR{*d=B)eps41gTH4cY12u zCbu&~3(^AuSqqXWrsRkrPZLFG+oTqx*SL0J-KCc|ri>~IaGs4^VgJ4F4fXU;{)4=7 z?bH%oPjF)T9rV}IDGU)jIK{q58YAVgX<-$hDeMY`TGJheXCzz$AX^b;BLWUA776qeYSq1=%_|C4xhPN* z>0>Z3x0=W?#Ts!@Oet{mg`FF{5|OU0&~l;>Xl2(J1LBqiu4Yj}5haUKufPE-_ub=j z3o|ndbK_I<^HVjAjWzhOADn$G{AsZD*WS5%Wo38xuGxdzyS?JA-tKO1_%3fZ=GKYz zptG3dCL)5Mf*_IsnW*3rx}wY^FXY0Bq$zGNe{frKM&6b@X$E<$q#0*vH&?;>fl)!% zr-FO4b2}dyoak5{_?OVx`)|MJ9^cks5y(Ee9lAJFWV)2=9$_5q>4s{F{fu~WTHjL2 z$K!9%82{>5d9DMPYboBF zr64W~yv}+iHYH5f6{!>wL?#zc-a!t9lNK*g;Uw~k_vuP!Q!q~L#JoXA;1Yb7z0_&( z3&N3*e`qw4@u8bML{Ckp%_40>tD!^0d`f>hcIz(>>?u1!L8P0eCw|^t9UE0LdU)scaf3_j{EI1JDkDb8z zM3{dXq<@*x73cs>VD{oBMa>mbhFwU(f~2g(%{)6ZBOM1U0y(Vl2Q1{LK|js1NYSEm z7B>W=@FRYn`!|12kN@@_|G)LyPc4fvY7T#9>9qLN*}%|HAlx<_xchFDcE#M;mf<Lq#_1HAq&w1y?_T_b1qRz?EXC@ChYRbP1@0&<+%-5SmlWDByyxnKH@A ztzE%E*bN&L;+OZ|KXc#1>tA^IzFqIU|6>#SbsXYtVm@*$2aSucI%#u#j?Yv6-S8yh zyBJx(-b6d-IEOug+k9}*WjdX#u##wuU}$Iwa7j@e1t>ML##KrR?56Y-WLeO?n2w4} zsxu%*2-6Xg7W$U>9NiT1)nG6TP+#5^@=ftP8B@~c(XdR&0@Oi^i6=w&Ak%SI(W1#H#^2=zmYZBGUIEDv)d6-#&eI@?y3zB)@^slgYdKP z-@XP8D^qUMJo(hYq(EPWXhKx#8ZM}`;!qST;59Sde9%KWb6unxq8p870}jeack~8` zjRS0vzqkYDx5)^7HJ|(@xZ%TMEHjniod!hTB z1jA3*tg6_Kb;h}FzzGXG5J3%*?Ne5gSD9aln>TT7pIH|fa44dV8c+c)TSk^jBC5S| z=GLQ6e(KTGo&LquGb`PLgWdSCpIuqM{T{nxZ$|nbH#GasE-kN|4UYMj=~__y0aAh* z^I*m_pkEpAAvz@6RFNJs=JW61>Z||A{K&uvh5>fRn`>^B;X6TMLW1J#wT>hOj7 zY7e!zD$fS4(l$C0hSW5?t8`k;lEei(v5=s$ls^9Tonowc<>hWB0u*M&-+1G zV8FU5>?8r}F5V35j(o5=*4;5nLsjo_G-BH`OBA|7x(?Q z(YY4TfNLZ(U%tTmQr1jH?52X>K@*PM1g$|K=tUHBx+&IO{DxRJZWBf|Hobx)G!{$7 zTh8o0H)oh5e`aFZ^owh2P;nynE#4tKh?i-v{G%MltRR!nl!D zRa77`Zi*so5cRrs7byo4gK_Jgt9Z5*_R!H#SBtm3x3~Smxh5Y1>g&B~NIg8;6j~$h zJ+Ww+9dp$-cxsxaYAane6(s|c+qY^AJPwQ&bHSeCII|3;GT=-nPlm*|!8%cVn-)07 zA)O?IZ|m^3&oIB+VEy4q`U7#g->#c45r2a~^P2kkk}xDH){~#lJWcfj>AoMF`*<%< z9_W9R=L?+~C$rRR8UG=L7L2BW59l4Kxd|WvdpEjbtD##yu=;0TSo_#9)&1g&;a9@n z|K%_7PJTAOvw+`ui+YIPS#a}JZLYw%D5xZYlS5=+Jjrl!eDZtYv&i!Q#rtPt);LA+ z1S;`+aw^9mlSE|>D0k(|hyFDb`d1?G`i)=ylGaqKHwd$xlbEUs9E zfW|wtICZ=OdAR!ToCks5BfM!)nlYAY=sOax9}M(^1*GXNI4rezG78QsMUz0-O{J!( z*Tv5pRff-DtK^ibjGkLIqUU`J?YOi#6hy9i8OT)QSZ z7Vyu-4)xma#0N%t-b*zt-rF;R;bT5hZ$kcqIKec7;VV#S06qwkqL81go}JM`ty#8o*8L2QCIabw}>0kK*Te zavXlH-BWLKLX0qsoFk8tsBeEQ^pX9y9Gm~hN7{Y9_K&FUzuvzyxG>$+(9i@j;$4uW ztQRE46M)8qo#TaZ*m)GN*Ww8P3~qSmpImy@F2uKVtin-8fLD)I0BhV#N4-cb#<>0K+Jt~gd%h3uNQ*B1rkczC|{1}Z313C z2pSV!{^9Yf9-JEGAV(Zt4qk%Lj={?%u1;`5LO(oG??!O1{%C2xY@z6pOGIl;WUu_z7XZA1=qq0TJ|9dOVeW)2zQ;9DHVWYwgxq z@tyFG_Z{0&Us(%)ooV35+7k_uV(eIlH-WL!X%aiK7>wONbN^T$4e6fypY5xxsj2K! z-OoJp%Z`&2xCX_%0s(aI*0wG!J59|u9n$D7-JA) zq`HgJ2k-`w5HVUJAPPj(u{}r?3pm##>I2XNA-oa1Jrdc3lutL0Z_p>l=c6mQ&Msoy z_CvERUBi7f!BYQlXUncbJY=FP);C%+U%MwDNqeOBK57*vtKCkELa`FXWSimcAp|Z% zmxB>$K*R@}2yl2A&6MFvh^UU`6)VM*f(Zix{+QA_2OJ3C6wq9+k{l@^?ZQ0?pZZkH zO$i~jn{Ly2ifc*#wW#kIK+)vyQXz4P$2WuSuZzbQzb+onoXvPVugiZ1j|Z$vij>T$ z*k}viKRUBKga41>)}(QFU7fqCw$?sBHS;Ug{S(IMUz(a9>1ce3(#-J(&8r_Yro0fs zxi-h*A(1pJJ_Al!RQbux$i-KHJ-Zo;r&3-R6seLfDDyb?35xH3SNF)V`5%SOUOMu? z11&v0|CGMBFF3z`;~)M(ls?r`U)KVD1_qD!-%u)*p#ZLmAqXC!lnAJ_QbZ4mY5)qM z>UB{V-nK;5$V$1STBYLRm8RO*6mY~sE8?LbBtCKVA;^AP<=@IRvT>!-Cq5zTWM4RR zZDy!Xr0Gi@<%1tn!G9U&fl6zeVe-YBV)DGDIQk7d_y{n0*yx}B^iQULJpKOZpO8F^ z>OZfK$wNzg9Za5$7%E=ib>XhR`Oxx})u-;82)0~VVN>R}|M2`}Tpu8mebBW~nFjhx zax6aXEgP_S61!}P<25<^;DHAg|0C7?!yl5>{qvt=kM}~?h0cYX+1q$-+V8J}!}Gxl zeHY#1aCod`EdEAYm~i-~7vGv{HyCUwx6eNf9DaNp8q9kts4`N8xOM%;_!_hr%ySI$ zB;9W_96olz;&J!{rIko3-lr?B4Z(=&N>j$G@GgpvqYn18VessVhO^q zTtL!qxW@~48igFwLC&!^8Wc}r9%sA^xd9e^{`@lT@e*@ed$fDJa5FFN@lu=RMP7^j z`bA#hYuZI#SaZfssNRo?yi6TaK|A9b+@2fPE^T<~pBL9I>%OC15EXT7M#titH^<_g zZyt+}%Fbk1Joy<8oIZWy*Zn=+fjfHoe;u%&UV7j1$K`8N5C8AsfX4$Q zo^2$yiFl5l=$JA0^mD)Fe%=TxN#ltw}U|TG&@uj4AADtjN<()+!*fX0sQ$G;#{>Md>vpv zO%P*<+T@>1u*vaz#3oncaCnNQz-J7>zcIG{#=yEy%Ye}oKiu@lffW*1-*B1fBCa^q z!S%y)?cKw;(sZcHJ9n7Xsi+-JzD+tW6JnzA`z6pF{$l8{U*|QJc01KeNLAbc7qVgq z4^otB!k)wdGJ$I-98ybcG+F^+XSHPsgOe^_F`HYzbo&>>-#;vJR?{*~#w_xqh+l*c zh>x}J%gqhpLE2i!#t@UvXJG&96Z#mVv6>i(7OM#kD1z?FHxd%sZj3tA8nKDVBS5xK zlQLCYOabo2WyQEsF*iHCD5FR^)ofOIZ(Q_d_V}O#Tm+f}L3WxhWk0>Fm9#Ivrp2tB zSPoxbKDjgYCid_&)h@uP5f>u@83nY6XpUG}&|Rl#s)CR;rX}D^jgAZ`I*e9W!XP8v zVAIlU#tk+g3d%K6 zp%md3$5rw}uwMepX*8PP@iCcdOjBA8UWyfw95LB|@#jR7NNg-`v$QLK&jhG9|IF5rzA0$KxkDy07O$OIiugG6McWycSBkwRw{owJjE>S`bv+#>uW5+>fI=g87-6V$~OP{z|L-fA+ zF0_*@a4S`^J^Wwwc9H?`|2{!2SieA|9r0K(?HreN^D1mxg=mHTf6x67aR0aC-xSM1 z?T>N$r?~wp{tenf$;#(Le?`6Xi=+9n$yqBLZV?^TG@f^&Buwog*2yE7Z9123u zE!e^4i}=)HKzQhyVhR+eCg; zxc0fCw~W81zyw^!=x`_sGDeVphG?IR%*;%_WKqT{QNR?1@L-5lgv=hpn3~9o{`H~7 z`S7!$YcwF~O8+{BhwBsAm#zXcL9GSY!CAnsR-fDwd)G6{!-AtJw5CPV#|&nbWjRu0HlZA^2b7dUnL&_Q|Q zL(DbLa06@CJg*^}Prv1P826Wu@+R-FC6?-*M%&9sT_~CMaukTTl3}`gag7>-H9E3k1s3C_Pwnz}2ze7z4+AkW7RksWez` ztcjI#GuF6*pCHb%y2dn<{#1&ItfXp`smM76D+)*}#K;mzOx63UWpp$^9MaOwN=p|DD=x*Vbxo&gCo=)+O@bgRW7(2h*HB{v4_l<0|pE0M5fUBsO^wLwJa>VhVsA@V=%{7y zc<%&a0s0%aZl4?|si<*P)=o9mcp7S5W6-WJpS7E#q>~`{Fh7u!39W97nh7qiR;C=K zDi+k_p+XJX%@1&!gR1Z#=49jA2P)hkelXH#uej^b^75_sgg+<#{Bxn{cl=>fYtd7+ zV_VV-Q`{xXV?*znKQ$ftMDRq@WOY?quiL{ip8c+L@0pqJ3e)vDic#DoJ}L(#`EHvicLkz=7$sQCjf` zmcc^#bP{1M*msDXAt_3^APrRFyjc5)8u2+FQBC^C(i?<2aJWa#<*-+c$Cp5#L%Y zU~0F{({jJDgryB9w)%#LeGfk{ICJ*F?WMIfBX#Na;`rM}zyL7m%c>pjSWZpq z%VigPX)(`lpN{d6wA9@}%lt4cU{&7A@TKLGhv&RqL;kl{b*H;&ZD|awr?7vK?mq(3 zNuFeulyyuN1$7cwGs#8a7kSMTUEQr@i)@P&N?Ljv#qVqBX$f&>HGxI1cQGIwf7;rO zzqT?7>7D8<8VU6>g8TUu;LG6{^M9iIM__|CVSMUU|1B-+&^;9VKFN_&#*R#n48>TqUw zC?g|9AdqANh`@GmrS@v7{GlKa0q^E>o7Gx(Re2e{RGQ~3bD$PGGzEqYDFrnL2a3f^ zMo~=W9>fSI4&Ch8*H+=L&MgsQq%+vNue~kQYwg@R=rv!v21V!L_T62UMN^Oa!`)-z zd#!Ul480U0(6Zrg=dD#I!vdBGC#YfTt%0pK=;1K6 z$=oLEjmEptc!TXWf9o!P-&CJ}*RAu{t{q!I2)l%?1`5hh_M?2Nytu^aEFPX3?r9kSJ`%9c@A&+lGxkMOZ{yc$nwx9B z^de|$N1ZwXfT_vQn*s2o$yv_CtP(VrXBZLa=Y35 zXZV!*GY@eb3-J)1QySY&_$;++_-v#MB;mJ%?$_tnkajo4V! z7l#e>I^ZN)e~Ohw_q~DAf_&K7ND-%dEGhUf)o#o)A&v{7vMB_eplFeSf>_w)me-ct z{CN53!4rMSEf6XLwtnh$%nAR>2Bk#|jbF{e2@_CkcH7;ls7PnOTWYQ-3HGKG zR}@zv#T6O8*?7*thUb_r{@xFwtAhUT2lW47EL<9kyfPhJ>RpuAUfJrvqHGBa!rye_5D*=Yu*bvIFQ-c_^ zKuU~Ji%EknOPGzSWI*1HvA$Waj0Hw=+1su_w?wgri&k>}YNv(8jv+$y*`(+zED%bK z+vO}RDX1^3&(4&WYbp66KP5&CvQiTjd7Aky1tRvA%Y{Nd+1I;=J(XwF?lYC1p`I4M z)#5KLac*~(^!0tU&%S&73yp)0>1oGc;}^zvceS>5P1ILE{d9Hxu9tV=|4jFTm`H5B z-a_CePPG<3d*o$jLp|cSNUX#XffTr}1TFIZcNDHDbh_yNcazs3E%e;HtlV4_ZuS8v z$q}~u9p2K??wwnvQfvl8O3K;!FClpDlP%L7-tcdu-bZWabZzV5m^)gmB)K-pzq;(51yi*(B$U({m;F3 zGD%aw_kD%QEO$HSfBxscFZNYN#DQj-E}eebms1lT-tGUAy)mqhHN24@rKTtHmqp#? z%5{6?jM_1*KWYj9b`j{7WNmhm{BEZzACwL!>I`BkDUT1FO(CzCXOW=a3SV$sW`zBV zax=IIJmfP5>Jd>|uQ(KpRrlU=?=5vN*0C)ex3pjNy`Ic$QM6@}QR$_Z!s1o(Fe{Js zXITcJQQ(PWSEjtYY{aS-!D<%;L0gj;@)hT~u`yt;)zu+LUMCtQ>Td@CQ`a?8?r?Q8 zNJsGg)BB}|0p^&0KD zWQc?%B4mg72K|Cn%v^l&%udFimo)zfu5-_1Enp3B5#wcf-i#GWuvGgGcGfs ziMh4_2>o6G_OMomhW};XrI+q|2#_AmuW&dj@`s--E-ft_8UhTM-oRHul%tJDn;`NrflflXJd2?+bU>NRPhpaU{Bl2d{LhU^(A zHLuhSf;9^Dg91Q|arTJ(5;MtvXHoe;90}WD`PX6ju`tGfyTe<dhClv z-!iueZCmKph0jywP=#~01dM)-oNW}L8bP6tAQ5+Q=(Upot?@Q8L&*Xv#M)Z}MA!ydlj zhIis|JR%&PKdj+;x74TLQd2T{ZwJ>xJ zgDYH7EO>G}tq!*o7-Co#yKiCk;>fP?8vp0n&ATslDQkf}EFKSs<+5EzlJ0>j_8XeB z#P@I?V4n%UfK%v6BpgPO8J&pb1R|-xCnM+-)&vBVFTgf*d{NWnh?1g;gqB5N=6eRv zchno<{L~geG7g_;{eAuCzjN~FYFdP3_pRkvg|D!6Z^^mTI)E<&y9MF-v~P)blP{6t z62PqqX%%v==*VQiK=Doi(SI<(^1LSl%F@!BE4y^(305cXp@p6w;b6x+6Tu0G5%wq0;=>LMWY?u$xtb4xDzMK=I@V9S;R^0$G|@^_7_$tb^E zv1Mxn!{e}B&G|b?GJc^#7)bP11WJkv3vyj1Nrw(MDBTLE3gQ*C^CYI5h1m|9bb_pR zWG|D1wN3|>Z*dekizs;~;5A~D`Ve`QG#*bmRPGR$S5}1f_x3vSh~3Xz+|zOX3ul1* z)K?^p?aNOO?{$Cs1r6+BaRh{ec)yznNE6;^UV2VLTCrcVU`fmu%7maWk{Cv$h6~IG zC8rJ8U;?%l_Ua5miBRFeAkLz76wJ~f=#);01}ylB6$tvh9xmO2s^E56_FRvJqqMRN zi!=oi8ea)L@W{pk_#2QR@Rra~$KfC(nURDZh7KJX*XgB1rkkCc=-w9i49d;nm36w9Dgk#vF zFk>I3Z8!}w4Zey*61D1k6b4PNjdu@K3zuMskj@pW0ZNx}yQVW&@xsu;IZ|JYinOVm z9WxlZBGY57y|vMEI|eU1cgw!W#-UiEE_$GA^%VzqA8Bl>KewsVS6bWB*|@*CD^yk; zdwgi)>V!Yxs4bdl-**144ZWkCO{Fc4+TsiPXD&LIeZ6+vU6;SEIy&Uc+1k-M<*vye ziIlfnEKr$f-WrW0xgQouJ@&WaQsR=nQoRU8#}T)I0wJoHZzM5aWk0k;19u=n5J79Cnm1%gDR`n={7V^QNk z3nz_pVq0t@?xb)|O{hlD0Y?_9B|rfOK1m|hUpjtQ?IXYZ(x)C`Tl(d1^sydx zvwWKA<>%#%R9sB~DV`0}Adk(+#wWUDun@7$(Pjef4v@m;PqNZ*W)9$>mz82w05Cz)V!7ST_v-cCA4y33;brKjj;-Fj0H_oF*4JRnJcp2mDNkg#DF)O1OA)QK}~!-c>!BDyWwU*}^F~K=CPQi6x*P z1_NX%P)bNF68R4xDY$Y&jc`~0acpYq*loRSErU`-+B0+Tq7$~{Rq>(TV8!EoYj3k# z?QL=M>-zbqR9=^{7|bNWto zHz|W7B79B(O?JdzV8Yfh!iLK>RV&c!$z5xB888@esQ41#KouHR zI16Crj;EHi@=F|QY2}w(h|y8~(RPLs4V?akNUs2&Q=N09iaJyig%TP8Pd~X5*n!w; z+ldpl)v=Myo8@oC<8Nl67O3x7|$P*dtrA<+|+6Biqhj!|u%OiQXLTru8I# zP5R^V^$hsStY)mIM_bRuAI`d-T)0iGr*xL}RL{bCN@T)&zx5=c5^}M+o~l2HqC`kY zS5V)_v7QSD0E;3cyPR)e8AsG5y&@j}8rHFsuV`;knR)-_`?l<_i7?%KFd3=gi@9O& zzM&1GD3^$0E_>8DP<`Jvz^5PZ$-!E>Aa{Bdi-F%;l!wB(zAVZh0R4mjtdmIpfr(EK z6Q2Ri{UFp}O-b@hSqvbo=3`T9t-VnnOtToM>+15j$hbu5Y>3|=c^`EU2rvm#8U;OBo1J!lGmw}xNLfTSK{=&LpaPxlF^jx;}*}7;?uDqRnHn&?@ za^Po|N{5}GhKPf6^SWW$dXV9djMT)_+t$D~goYGoJZduWR&2R0Qsc;d~WEARq(- zz66~-jt@3W9>+(7g-!z1#@fK0Md*hqu6#D)=n4x2AyV!wD+m+@u$l850e`KTTBRZI ztS$!JBh5isJp9CsaH{*3lm|Ci6STEEcV2JS*@j}HTM(i+WIM5G_)ubCAmOsvei)DQ z#XA*dzbvofcv)4xX8tFuCtlzfsgp}|ca*FZv*Z~2uCu@TzUn^B_F%)l&EeV_RP0Zf+y)KwRs5FbUM>imV#@vTB@aX@j6QBU-9gTL_ld5MM7YnC(l!caCfphq_>R9 z1|4Mz6Xlwz5+SDqm`REaO2J(pYb&os2Tr`)g@tase*d-GSmZAG@0j|f5x+k|FJGPm z@nB9z-uyPgY*`HBP2rKN*(2)w{Rl+3`Wt~FkOr;6M0Bye#v&Xj`dpnEcA^pOkd4N6 z>i`DYTvA2PQijAxec&gaQzzxYpCaz#3Q&5&@&Ih%V!QZ&d zP8NH)dLjVXN;?tV#Lsdb>Q2KxQ4x)l z`+X(F7<`f47B*Jr)P*ias9HXB+hn-ZV$ zM?U6{u>N>i(NF6N-LC+Pg5ADy+DrXy@>&u8sIa^dVLc7y^2RW`%vWoa{p>PNl^KO2 zu(LFLA~{~6dmrJP;+q=nD@<52VeBr1w+Dt36@Ueb1&BemqP`mGl&~=2)pj5_0;!f9 zYD-U=NWg5gBE?i|X?-w?85}OJNGF(7UV{_NMH%D$?1o(*%xVh6o7Fk02}Xx)v}38jS3G`Wg3bpOovUtUtE-p z>az-LiU1q@k_}(eGT3N)lwiZd{oWfkT&W^iX2r8tgpDKMBiQJ%Z z80kpG=%%I=no`imhY(k?5gvo51cE4+>A(~y1;PkH)M#uWwiwmU0zH!`E{ViGHMnB= z*%JxqWh4#YY56E>pop%NnM5i?3N=#Aq!lkz<I25%I&{HjoN z{}!K*YER3LbB4dD?~%dA)BV)O($uWaf4U&+VCNBBxAItAzqSyMO*JB`?ej9Mgu3JwZ-m=hQ`X{p(;;7Rm*h^ z@ycLPBqM4aizT-VcU3o52J-@@kbO)0$mVsdJKAZ9B7D8HE;FOMx@IsdWQqBU8?wy3 zw2l&wmCF&o2kRhd6a9%E7Xl+8g-QZk9;O*(4W|(A$9vQgi8W)-bH)lK7fwjUHK(#z zSS`uYp|V)D<^VP?Ln#CYG22|$*4cK|RVTjpz3<9ck$Ai`(atUl-+nu(6k_n;{HIa3 z>Z9HYj$>5ggJML_Vmn1IFY?0t!?x4P-A7LN%g3f7hhOEkQ&g%kWKXZd+n0A88DZa+ zU#uET;W))RuWUQTI1hPwmU`9W&3c&{g-vz*omx?Pc^QxSOy!|1@o_P z(KBT`4RX1=hT@}YqBc;QC8kq_4W^q;LqU?8agoPfke_ZkMa@8@V)6ij$CzqJfugb;A_cFH|um^;S*a;@4S3mZ2~EaQk>WOSUHsC=e}X>Ma=m z`MDlfwhiU8Psr!xmbsj^jBGo*ZvK_Ka=J=#d-CqWq`)Mn3VU*MdkR}QOcfg{)uOUe zMCq9}RDkupZK$Y53g06{#}Hy`n6LG#&wcgi)s0_z>8qFD$ZCeY=1U zxTYd;juLS+THWp_dE?GoZ>f_1CvSbzDZS17x$aMyoQ_lB+GwwsBY%-?p1-}R^PS9! zJT@zT6K!5N3=}(RkjIX|C!pF<36Hsji~_P$11hx{UW}E1^^{wY7pr|9wjqC(@1fUV2rh#BO8LfcOY!Qen&i|0p^EmAYP>2bwpp3r z_ZEjs!fuzf$W{dFO*YHcj2&ut1k{XWRnTK;ni;F0(3xFFns)TW2dPWMV7yRi_hOt`jceAlvqU@o%8$3N`3q_{78e&50Y!L!Al~!CEWis6V?ILG$kfc5)htnp zS>wPVhb6N6C}xfLfw2*`)Oy$C4}bW@i|-l}TW_4Xc>cmMfF1XQD^9e+x0OejM**~S zN9;K!9iw$o-C0!cTy2SrUy&)2>&*!n$m!jvL`0FoiEJI zbm5L&M_T%Rz*etgy5>!h_`qPtjzbr0Z#cB-Idu%MM^Sz=R--48ATf*E@bL#e&ttHX zVCl)X#tqD>b0}q1gf^RVMZuyP3CQn|=z9M&qzA94~D7UF1FCLz0!a;HkFcDEY z0t&866jirk;0I?g=vT$3jK*_Xcg^%EQ+G4BY8z%jb;iA|KVrvGfc5aM1KNx$58cMsSWAWL6uC;5s@G`f}_SNi)v1<88qCE#4 zv~Xr}LtozpdU1RO%7~P&Z4$;HVL_-u2spKo$y2cQ0zz6!Gi>G&oY)P8iTregUUEz+ zRcjJVu>0}N0`Ch&&ag+BPJUyO{Zy94PaJ+~{rpF8TS@2!e5l`8G3+0WLSLdg7e#j< z7J*hE8bjncj$E|wfWA*ctBR%3NNEWZYO5oS(Z+zUq`b7;mMs*sVwHTPr3%sp;yXxf zEk;IQ4Qw#*r#`cazP)Xu-7URM)18TJO}#DMqiwVO&Aq+NvA(`oBAHC!WyZn2oycLD zXl>b8Tf4EPbpq|icJ_6mh|7cBjg8&(l0QEjZyz3Rk0V$Dpc4}KlZQDH4j_IH5C+m? z+3~Xk8y6fF)4&8J+5>?wZfH#k4&Vw`&~GFcsRPUuA|1^uH6e+T?K@K*PpeBHV2j+KPs3Y|BP)-TmN+0oeSS1Mp#s6w*f(EXNsw@k&zk_H#r_C z!PH%nSK@LgG&|)%PDP>^Bs&X|eUKn*XSwhsYn1varnmIg#s`nb2j$b2-lc?Ebj$zA z;+2hS=HCIycFIpyHWCb(fU2{i12FUoROkQwsHs=*7W#6c3N@wJA&S{jAm!^o>rw?F zC{q*0^oi(D<<4;Rs@B$3lVZ#E&hDMfLy6tdUbgL6!^Un$)V``bK0F*xY>UOVC3-I? zs&K4sEFZ(VB7Z`(V@!p>UBqz1LPO#cto_*A$DsEr<)!l|*FM>@9dKfHV9$l;mx{{D8n%$tV-HG>@w*R>qlQMBXG zp&jz$I}Wi!gB?XQ0sJAn(CEkOd<|lRyS2qG<9p$5Gy>mgEE)^=&@mGrS8DcW z!h6Co;%8+Pk?m#@@^dI`35@(0xHy>GQ3Q#=Lde%CotvlpNvKmz{!VmS=c`o4%9gJZ z-xx+8=Ww7dO*}b~MK&KK#6p3b-quh{)+A?iS*sd1@BA=o+?Ch%#|Ps5;SzS;*kAqS z>_a;Srq4&7!zULGv*%etLSUyL%+CuM4+-MK^YafjMll^6ziHuO_8ZoQ;~;;^ah87k z1|0t}zh1ZE@vCwF=lJ#d6^~zs>mT9A4J#hMmXD8~Z(Q;C6*&F^zuu%BUo!q1aew9c z8QSqBSL!u`!S{ui3R^zi&&QuDtW*FVeWXVI=-a{o`F7v%Ho2MYY;k16nz zKbE@wCLqOc*y9TPl;fx{vv~Xl9RD%D9`IY?_|>@obNqV1Z-wL6;rd7Talmhd z(enYn6^>tl<1g^*0YBxqm_EK6aew9cfZqz&Uy18~#>Wr%DaWPs>#xT3&+_Ad-wOBt zBy+Ln#a|W4RIcRGyb{#&uWXx}WiJnw4YH;&oT! zx@Y+@%hG#-)_;;+#GaRW5K&V|nVp(aHkM{8UZ;eZrWb!Qyl;==!O6)%dX?ALm*d4Q z+A?_A;O5QvvnA17d09nsbH!zq%?d5M2^~y+BXvNNTB>U$({!!1q=;&|mL(sxlv29Z zO((8BwCx}}+QoXu2M6TKx_}D84Y=ozF|UHN>sn)EKv8sxwY-8161?0#=vtNn+sv{MlaeG0m@^(?pN;w}2zx{bk5PrWs(gSrL){_?+Q=Cas~DI> z0ikeRUAX+?`P1 zNv>A`^H$Bx50!Ej4I@+ zTl~evfdJa3KUePYl+%mmC1Rf)WzS+>If|xo7F|jqYiq?33gs@ybCftsa7B*aZ?xng z$5^cwsAwx>TS;H%KOWVYgTsDi3f9+@BL$ot{ejIj+R?jyeXl3(`^rn& zQiHGD#$^JMd0ZM#Um_EnfK2fs=lRg=R*;D<$ML85aX3>~IDQ-FnIse7{wwgz6X2OI za-N9$ufP*8$ML85aom4}yHa2W`*D4f7Pc#-pm zAW6{6bTo`hP4VNp8tFWOej=r)>4mjLg-r046$XofDLoA|nj~n75K)7Av_cvyl8w5- zi4CiJH|Y9wwf<-w%U$2KZep;!t}YU(1G`+`bK}r>U#!sAP?=mk+SRkZQ$s8T-!I4b zpHj!aIx)CZN7Ho7MO_U57AG`4O-vs?RrJ?bj5_?3npR7ug>-kYrYu9n3HEH%_33N; z6}7qJG;+*l7$c8h2JE8VhCEM0#rW!xMEBTO_sxSFep4L^*1%0%L-N+5ER4MD6=dN> zSr5k*yj&vdUCC^abx3|H6mC`|>4lrQB)mx9NcWCW?DwMHhbUp_MbuFegm8iUeWE7NMNECG?rcjTCg97R4~QBL7&0T8JS zx7&obAl4r6y9#vS8Lo?zYII=rC(lhq$Re;?y;!A*CsRBF5x(e)=a20Us z8SteNA(>c{yP{5sB3&pEJCo8a7x4;uCGd)B+jFhbrgHKUR{ zQB@iBmQmysF_s)OTDNB*G4COR&BP*B>Ci=qBVxO3k+MFSt?Ln>|%@s4(n+*82e9k2f9x9iI zx`7{L&K@p8q9!Ih=V^1Cein0NS3GdE@5+Pm^m(~hcs|&leBcq=#LsB`(D+wf_X1#Q zMEE&h!7N3#4j>B3BC2-kZbi<%0P{f=W6Lq>a84=Q$ZSOs*NsSgMXoEc9gEp$*$Cyr zWHg)h2o{TRn>90AGFptu!bDF>SpVPOWg<~tT3QH>Q5q?Yl!rq>zt2-vSW*bMQ5x-{ zjBf+~AXIUH_$-t2>s2{l0z#*Q@V3_ec%ZZdGEvFeJAN@<+1&peNB0ycPqbF&mz3n^ zm$Y=&#kvj6k?L0YJlYJ4Fa=F{Kl_ZTCyJy$6Ak+0!fUWc+z;6U-{pO(Jz}3?kH8-L zG`pJpNLt19N|nIqFW+uevyY#JuH&K)Lp`jYpd3+TSc#M zWn~yIcJ*lgjeVn|eK+=xc2?&GNBhdxRy1s=d$OjtwoPC=hmhLuVE3M}eU?B`hf^I_ZWF>4n(-{*y@GeGYK@6~^^Z z#Me*^F6;ti;O7>9gq|Sk0Iq6L>=Z|`GNGlWMTnBoRAHQonkFq7czGmJp7vsQguUJ{ zz2r&l6GkKo&tfi@;n|eas8$_vrw@Rf)2gq$5TQ9DK8wMaUU9)M)=Tm6!6?2X)_qFjUv%jc>e{#kuDm*n@; zECdG%8D_ z!iGtido!C0yxxM6;!5f!9+|;8UKp8qbRIHA=@19u$*Wo)5GL4pz(` zRNyTw?#&#_WM88P`3myA^S9D-`P@E+xxJ3LQ60JSh9As=x*SB*7vvaJa0VKq6Ag8s z(UOA@^^eR6y}p|YGKSO>4aeU5OcVt~eu7Y3;PU2r@FZuh2Ytn%c*H0KgD4OfxZ)#1 zP3NTmd#)}qJlu8ZrTsH4HRH|gi;%mQ3OkQCZtHH@+$2pcf#E^a4Sboy&?_8L=LFFm z>dysO8dT!f? zjj89p7c;(S5~F7s3T`z(SCcgTd!Yl(C5W+_80BT=_qnm zWp?#-WqLF5|4i*UISo#o%@`gH8w#=uVvb8Mb;R(&fFF!DowLz?PVH8Eyr7^hhsOHs z!u9O?kg+Yqjew5ehscLVwGyNOp~3(H5vam|9@&fNR8IP@RuaVsDU#w)DLsZ>&;IrH z+i$<=fb`|0{7_Q9A&Gn6gnM7j?~UCLDM^ua(0>y2k*awJka-l6z=ToC!LjpPX+5x- z;uz`0u72w#-1n~slI+|h8>PbUqHrnh`!BdJ)xh^AO2ME|0ZwUBaTu<5A+5|kQ4`9n zqW>PhpFCpP^$U_Y63{S1PSg>`X0r8sI`n;sBppaI2&F~nRqVr+xtEyONiUAvnHjQn7Ui{ZZ=e> zcI&f$-MO>F+*7CQ*o_B_dtXQqJy9USNA=ICa{@9EkY_4cQEng5-IJXmvP`oGhAp7x zj850Q#+D^oEG-sTttpcP*YF}1uDfzQ}u|Lo?dR)Wq zmp?njb|@FoSOqiUA?zRD=aisO`Xq3nn#yh3rZjdbh2yItF z%CKEgCmG`g&7Hw$^}++W>5%tf}RT0#{$JA&QC)G<4BD;HAZ#N2H#X= zbNYN z4MriH2+#}^-at9+*ay6M2Qu1mK&kRZQB)d7AZ|dsVD4>o?iw#p?u8qH3t+a;bVvu_ z_Y#)hOJxIK0HFU;W)f7J^K#GtT6fTtKK@;WE57&BD1`&~Lv&p)lq3qta6;4@zo$qA z0GlHjV2t724*qid_}ua1Y#;lOe1m)g&btXG|KNjM@8Q?8;w!Jb=gKQnH{fHK#XX3J z=mpedM*#p(ISQ@>1rdb9IW`fcT0A}~f53L(;d95?x$Io|(>REe$T$A|4|HuCo_o)g z>DOv&rWgDP4@^i*yaIRAG%XqdEf_D9q{A4L^}=fL#kyO0{*rspfR1D7Mb50nDSpr8 z_aOd1N%xq$TV3xfu|{uTe+Pvv!w+UdIxa&DDaC`NNyn*s0vE(lG=or2VaG5IRf1l6 z&O{;$hk`<|!V`sagqz?~fu}swg>PNbPSazlT;E#X-#6xUUex68id}i-)WHl-;JC+G zQd;B}?8DrC_S( z!V9Yf)=FCxq+NCoS_U8ju!4}E!&DHL!W6h)Z@=mGNg)0fj`z6cLN50ZOxG(gg}D`0 z1K|SD4y3gc6~VSt>KMVcOdu^&&VX2cmQyCa8TC~7Yl zEaq>x*q0`K#ib=q&+&jKhIwJXCLIU#0zYWG1(JobT{L-w8YW%C63h!( z1hS2K9q10XV+cv+MOVrXcpo%e;`hPx1zfl3gIs6F^Km9Uex>Kf7w!;?7XFBNd_dXC zjr+yfZ*~q30}Yw*D(oCr2%m<$^N-nVP;bmlwrw>6jodY)$QWO3&M+6{@5;^3wp5X^5#m?sZ9en(=3)@6Jo)?tPLBVH(bk0XH4B*Ht`x5&v&_65WT2L|2Z&;2L z`My~gvDpN{R%$DSxJ?fx2_ISX6y`>8h$MzUR9*U={a4yZ4ySzr7gphR3!nNWkWTtb3S?tvu(jUc9$V?A0^#h0D3mE$)eC&!3Krwk?*f^@e zY58#3CGRmL;MuFV=N0gu(6a?`P?6Wf!IbX0_)JFvz)|Zo2_tTsh>%>y>jMESsKY=& zVwdc!v}EV!?#eGRXRt5r$ZvKQH#;3I#nuP}Y7PFxKMDSjvK9D4{$-ek+wHdLV1ihF zSL5=hyqWftyVE`|d*a0_JikN;i}j)j6xBkteRxg`b|N+TrM;Pk57?ea!4eD>1LQfP zz^Ls5^HB(ji`&EhvS%KDY|oQV%J)6~*xo0f48Qf(fB%_Ye4YV3r}h8kIk8Z^+vwqc zS8HaqZ{U)XeL?IMUjjZy7P`eAdWX-U2Y4M3p2zn>j@LaJ zUh@wk5S%{Hez=a^kN7jvnfF0VGD!RODr0*Gzfa+J?)xH@OtJJ)rCt1{_`Vp-dW@NN z8*y%h{34Esazl#t8ihzAwBi!4pwkm2MxKSMlHEDChuujek%*#n`qi}iSt!mHnR*;+ z=p8#lZKDaqIa^~qEP!_RdOX3(9(mWs9+^_ewelE2d}qzVA@;UZ2Cr^XxcuwT9-(|F zWg+|)h3TW?im$>+Oc{dJ3}sa*CR`=xiEJydSt$q8bRZ?@DP0Z1VKFZCdCKC0Wzt&|+4LLq>( zUNc(a^LdYA45x>5-@q8Y4G2H+sG~ryFLKdm-<#@i{={MJF4E~s^Z92QABO{b8*6H& zJPBYssYmHUqgrHX8YU&RDS0}95C#MKZgjiZRZq>gi9h)9?4wn6-}Wse7v7Au|4Es< zdhZ;XyDihS!rZa8>2tRrOxKcQ$w2{Io1O06eqjl@vI(9MM&zK{~lHi`u5L(`tN)c zeS0O)KEE&|j0)F&b7V~+X@x2J2ODH2s-n<{vzXp$$R-#0E~0!Aio;1#LI;OI6rU)| z48|JE(hHzUP2f71Y}89JStRtLclSVdSE94EIo4Q%sD{8$aA>J5hrHErO{VN3XSL

k`rao1i6vydQ%xjP$IoB8UQi}!T|(cEJa|d@CP^E zS#UGW7)i!~_@-StvlQ$)aG)zFnRUB19XwcFCz_?ky4ohmEY?*YJT(WT}!POF%e)sh7v zRH+EyDZ`D_N?J+@oRss!#ho7>&GBR>9&?5R1aqqAP7wK9FmV2ree?`JNVa?p8|x=$ zi2OL&Eaj)uJR(0jb&BZfi-={YLX1U7DxZIs!@T@K{62RAzZWRKpZ*4Zr{iBzj^9DY z&&TmT^k@p{iWa(+{NMStQ9iC8FZ@mTwetIE(rD;7-Ph++G$2e&8e3Oj$@dHQyUQ_CX;bGJ0nXn8d0UjY)*Yap%!HzUFv;I$1t^JzWxt* zqeS}$yocGGF`W(K-K~r(3l(EJjU%XN73l1!t?_vUp}(hNxO1qvv8KH?9tnA?eN|ep zfE9vpfW-af!2x24DAj3r?O?6a)N;W1@+?ef#?{&#_lt=#s65j zzw=^6Qul+(3gSjom(%Hu8{sm6NTJv5%D^InpiD!o?4oF+pddor0PR9GOFGwpZW8LL zq-iN9Qkagfs0h8j5JjXkm`8t-LVIDRH4{}`ln8)KkZ6@H@x%h+Rm;E2clj$S{CK?~ z2Irnx{LD^71N1ErHKSSM(-i@KH0lpjz%q#`Vn1AlJ#;7bP*7KRhrnn*+=HD2dZ_G} z)Hz3#eMUzym!gG3xZI@eFWlz`u;bP8{aT^!;|jiyAHi<@t@=Cd-;h+n_pec^;QN}! z@B{e1+c^EGntu)FfY&`q`+HA{R#%T_g_!)Jm>{#)7*+)nABYb#ioxV z3JR4xpfK%0u0EiQvcNND;BiX^*#sPj)6)J~Kze7wM5R^;U;KIj z)1{i`)d_kOmP1GnTyO%c6NptZW|=IK4z@N#W@t1Kv`?iy8Q4TEAXrAUIt0;M;c8|w z8&N@e#cM&U%1ZO|T?l3h`AaLxqWLBH2tsh>xxj?qmsSO^#q^C(eq9jm(@2y2xuwLY z2tnufgfhhN+?!{kIe$nd-|{>1lZ#Ol1j{=RuahZd0)`DLEE@pJlc>be09bN)Xv;>afg~6F{*3C|#XZ1ZA4D8jJ3y=O*9ZB<()>?U-$w`%e64^i ziIQT`G!%l~J7~!ejn*tg@1c7lBpFncAnB1d3<>OHdqo&ITH94sB3_rekDv*M`VZxM zfT-}BdyEvMf!C4%4iD)3qF>(A*wEk)<6BmDg9L1r|Oied%#?G>z! z9HaFD1nGghX3ru(#gyw5jSiD>4+uhz!I3lLvI7Y4h@;Wxj9^3k2Ai`SCPURIEo%qzgk@O9yFUW;;crjTXI%$gz0 za}dyhdGJf8Fb@VGX3e(lSb~Arzr3=R=e^}eQDeoZ+C3rRv+`vtL0|x~_5983 zkbJ)~PnJlVCTk)Mf?b9p%%F4gKLIr-e@med5~ARi_bJwv7zIPwVOPio{}HS%mW{~} z!U;JryJO2pESKe2SPt5%P;``2jgBfzG@o&$16SJAcq&{yBRJ?%$MQ=j5>=HIh^!Lo zYb#=vG1M9bIu(VALo0F@H#V(j*;Y-DwMv&M_8&geCq-6*lI5*s|iy z>bGTaS@&yF$nB@(?`T2@hb4H%)qthMwXIs=0Y%uYAyvz6hNT*u)MgPS5GbdPIV703 zsfr;C3JyosRBn#Ts^i*LVWQ26aCXXWI<~^Kq62(bz0$=MG`c~~G@zQ(odY4PDc~oQ ze?_^!HUI(FQ>H7`Em7K*?o5nVvb$lnk0EAU{~j=<_%*;47EF?E;Uo0@c+=kV=6-V) zXi`X<=qo7H>%)jT&PM}ICGPka%i!raB_okf3q|I8?KEVe*MtV48IfMuiliDRyaJku zXyb&O4v0gRj9Evv$m~|LB%qwqjF6eBn*v-2ABEgp+f<&*oujkaT5Ouyk$B&GDALpiq1hYdR)80zjq zuyiVHQEn(LD)f2_3(LULKx6&`vMu$Uj6xf&2aVa6*khrlG!hEnXCi+a3tEtuo26q; z6vIb}WD;~uu=Qdci(C%7&T4J3LguB^Dh)We7ZC`Jnl8a^4O;f%mB6)vSwdy|JU-J6 z94C4q=P$wPw^pFD%5MaoC*ShE#hmz{0Vj>#;v*tC=^tQWIE~N?4vRL<-v`j|X;io_ zaSciX0U`z|6!3XUZE$`8CP6?U7{&h7~6_IezWn#1tvhf6LFbR$m-?M?|V3cqd=AoOHY+o7}z zN%X-6+^F1uIV{YflK9lsi=vN}SX8!)S#z?jGn(i_+gHfR#icpRF9jn&@3v$+VnF%d$v&j;5go((GCIGwP@Ju zMq6MNA}ah`>(VfJRa&bM-<{itvF~I}TDUw-;ZMWt2$5O%Fb^)=fgFb(&T%FZ8>(0q z8xHtI!_YrA1L8NhN43(ja!IuR`_4cK>Q2)h`IP1kpJhtAgWanKuiTQ@+E8~+=exZt z%r0{0j(fM?dB8nx9X~pH@9Im|+tm3&fBp;fMi@iP_*m*(8+i`s+=oQvo&2z{TfKq%TBz<0bOqr!jD$Kp1#pslx(C)j^6a{ zuj2Y0?|yX2bL3n+=Vi>tCioI%R*MnLRDwsCA|lcPoNa=QXPaaAMkJ1=jJ*skR(DKw ziJdU4am%eIM=qA%#Z0~;|7qthCU4F_F=I={f6Nb)?FqgYt}_Ou_OFwzqn&%dMA)8` zF_0}5eQQx42#+S;)_Vaq6QLH0AvFbH>JXa_U=Ok|<{#le{>8jGF4fIFxOe{F@SUe} zsIXRiM{^F0;WG-poPLVq0>>NJ)7n1)P{_M+{5BjnQ9hRe#y%B7h!#=OMR?^;9pd9K z0_J1L$&+^@`-7hLsykPHm4cbqOXl9*xxbxpKbRtLKipIljsuCr!x#YW=d{!PjJTgW zhCeaNC-J*;nSYy-i}JVLUdhaZdD)y7`}+zWbJC?ydMg5k5N;w!J3xJ!$!JYwO&Ma= zd5}EbQc?2DqfJ03;brr<=DgzZN%8p3VaYi6&M?LVyX`Y8!g|hWoXcLX$!WC%Cup)gPR{zYj5nC)~c)`u)Zu1CAb;IhfjJhb_>2a0W95$rF zD+qhW406(DKrv!83;w>uJ~>yzXY%@m?Df-+GJ1RW+h@#&&uGb<81mb$MSe{+ssRIc z5k-N3k!AbaAQ&8!z@V2JQMG}wi{|EbLo6vd$UgHCv?r{TLFz(ZH-q)pn1wd%bYBDAmr(^{{LkOmhvhe!JtqH-l?}8a8@2N-ISmgtM#w?!kunG(G8bv!bA{lH3F+KpoM!aE5Q@nr#wv*mR z6)ho==mS@@$1VXPvkyGLM$xSNK&3QR38M7Tx%L3xc-XI5&j zL&f0G?LZK!D#8%-N{ex~B6|tfS+fv^=x)S-k@83{MW;_`_C6QlkrYp)UHkC04IAS9 z@!r*~4Q;*StKWf8v$S<^@Ss4NFH6_`+3;DGZ-L`OTK(=bJW;p2ZeqXF?{Nk{Pi zxSjcwz@%?fbJ_U#DWaTu3RCQ~(Ip{zni3S4eSGK6@%Z>|X;NyatZcyB?(y5}D=O-* zx!ip2#7z_DnlJyjapzc7vq9c#Xs#ODY5X`_-_T`dH<}S{!*L@joG(_17Xx|`VQ-?0 zsvaRdrZ6{?`o9*Tk&+H$UG0Q@Xb2!59DdLP1Gq_m`ae1M6Xs9_5_xa-IZ!9hz?^s{knW)7%MWr~S zuD!G+Z#=QOrDe4*9t_5P9QRgXjcn3xtPpj?Lmi}Wfx`x!rY=;NfvHBlQRCK}6LnEAAc#!w@rFE?)d>R?# z@Sp~(RVg1R9AhY3!!l;k4Gyxxgka8Q7PDoC5m76GQtO?9;;L7?0B%aN3F)EgHDI;M z6^H^zgrd=sVkShZqOd*(e6-SvrlQzLk>rTd_*S?r$dOOZGjy7)5254@-=v_oK58Aj zw4#X-?2KiOZJS!xF@kz3hYn3{-8#vPBW2AU9nCH6?KiW#>ke!!pE}Udcxilie0*3I zXPeqb`a4QG`g;>4iQb=*N1F)_Wc!+72aO8b66c^!k)_0&2Wc1wthh8EiYBI% zCQ-X}wPi)ciZDDuTh6#EBgnoQ_h-6K@_*lM@xsGJsaXUBHz;rjV_jeLTMx*g-6M&A>s{!$ZN61 z>Xj~a$lz0uA;o|WP(=T)yQiC)rn`^-;Sa}K zdU{%p-<}*#vZ4Ad9qs4Tk0)yh?uAKwhZRW#6&T~Tu<3j?RvNu(%r6g(~2hn8%Vj+g}>U{b= z!`UUyL)&*8WK-R-)l-X%dw8s zKOP;2uxUj}pFU1KdU8^z9TrlY1r_B)34Q0h&SI~VSJq%$CQG3h65KiCcll`Csrp`O zvS*CxCkHl6_M%ZlG<3n>+NrV0jk_mD5*%uLTGUta@ zuRoA^|5q&gH?{YzYOUzXEOpNGkLhXa#?Gutj&+l&=CP$N){3E{p}*a037UWGu1B0z{wTbqxfUXW0W z^L+W}1D5H|ax2kg87T2Zwbm34<}`THKBw2N+KG4q4_@p;>WBZ(et6JZT;fBIORx4W z_iLZ{I(%;7$H+xH2WVT3{M(8^7SEYQbd4(ZQuzfpYnT(>J2GLY!2=F>s| zzNewQxw^W!ydl}znoRo~j>ck9dc`U&Ih99;ox?{fb1aqFrKQ=+e_(Yz=ZC}R_c)a| zj1B6cPzPD+c0@=+`4G(Cgi8qoRjP}kGY9k(x810Zg;)i4@Xt@bEdTDMm+Hh>(nk?1 z;5f;yc;W|7eqYgxgtwpb759JkJ+Jp&erCN0=R6W~9>c7RSNj1?xr%87bJZIK86=vhxikutz$rT8Nk|B=9btD8dQo$lt+dDSa+dDStDO7q|O^%tzdRaF8 z8m^ZGIfFJAJFRTVF_#CGNKH;Q74O&!c0MpW0r~v{u;kB9(Oh{xv`A1U* z;`cI486XR78d=~MuS^!scJ)M}q^yi6M47M5=k+YQEjXRXdLKGLQqfsx1yUQIVK1La zFTT2Z^)FX*b8Q$jy#~C;Le++%@^aWY?)N zDL(fky#Qe*Ai|tYNOOSniZyaz-*Mmu3zPDT`tZAmaHDIG_b$f82!ipDL+rF=TCfX; zaO5!hA0ok;3cJwagFKXoZgkNTAQiU9*#uvv=((@W3ysf8eFbDjZ z0Bp`a2Li#uB(I_hTL{wLsP-x-ZW+J+Qe6Kp8f$*E=nDVCx{<$OrHgvCE6 zCr1ynODu*ECAiojrW-H)*krsPuWNqBF8$AKKa)THpWARQ=5vj3FP8QVTxJ!t`aNK} zC_0nMjQ|cKp^gHH6%(RD-VNAJY8Zo3l^ocE`iV;2o*%LVTdx)BxtGTT<5@nTA954b zi!7%c6F>x2cBV}QRMc|KG}hJrS^b&c#wP(biy6n1AJ97F&{QEs`r+?fOOo{6eR znlT3Gf?OGFs)tOkN+=#zNYxM_PN~14>P_CzhvM-M4Y6YR_rsHu!>su2=0u|T?Kh~8 z_#6H4{i}8k?u+-Ivu5X-bNX*@ZwfcH_ZPZL+=cyugsg#lal80&z=?QbSE2*fK#Yx7 zIzrzpP_O?zXQX0F8kbD}++G$6m6Zj9KULqKSKrzH36*F9xBU8A~Xjon)48yTn1F$vWfEWasgzP(J|ZEIorW% z<>y0*0PLncfkcSa_P6ZlIMK1AC5azPk|p?!Wc4o!-#~AZ-vMeLY%IA>$nx2|qLG`S zbljq{uP!AC$W)lh#R{4_JDa}ng;M_?{@^eD!Z$jbx|=#H{iXJZz0?mCK@$FeBKima zKd#vlbWd9|wOS$H2CPzDq_So2@40BGhk}Ls4U;kIv(Y(tMeG-{Jq*3vu$OK|$CoEz zCnP#V_E?CU(4m*)G%5RbdBV9xNeL%ne>1C;e~t+5k2E*m)7(t-KoZ8m&m?gbzpq6| zBoO%vO;x$G5zK69B|V6)sHAtc>~kW{cnm#?UgM}rHm1DT9A_MycTm6KgV5(ZyhcNB zq6@?gb~Ew~8(_Od6%yp2ksgYkSX95yFeMmthEbah@w6zNQH&H{SI%PfGNK72cBWS^ zW7u63Yem`u(SyHk*+1D{6t?SF+*0xpP8z|LAG87tWrXXagyWSovm1f2AJFPgN_#~0bwd)3eEGa5ZTm`r|4 z`;5UcWbF&c5hmVCbq|qKMwTex2zEXYg7aXUcNPu|UymIjtn{B9h62iMLz~CD$CxM=Py66(N0`G?KfQODkX zUsT$(Ubv@#@EqcEhz!G>@O z=~&QLmq}HqFHRLMrR^Zd62!!EI+Ii@e(F*gYU#O<6SK0i!dc;fkD{f4N$}qw@i^sW zMoJM=bSt#5Q>8>GS0ZOC1Ng0yY47B-bg1+3`eCS!e+JN7coBybi7?f?I#2|T} zvuz-+EH6K|DD^?1*IySK*stNqh$h0=$50qa{smhBR3`8S6F2|?8@SW&x8r3q8A^~G zt#S>hzN!nNk&__UvY__T06`}o>KPvDXY(f9x;=W$#*c}Lz4FJ5^}cW{ z7WN@d;HVtPD=p2#i#2-6W8w0qa?fi19lsIG7vRr&9de~v2qt`dZhTfs9|y2?UT>cQ zBN0Gq)&V8RDhnyiNu1~5P1BQ8R3cA$axT7s+lMPvIW?E0C`48(H2_2nVq}j>D-a5Z zp{%CU<0m=IVTUZLMAV~iBObx^Rr^AAGgQEB{q~3F@oGBmbSW*AEB(CjS>{uz&Wy z#Z^}h#4!2$wT7WO33A|NKH&Hp9uP2l4y%l+~5 zp4lgpWwuQAWHMQsq-nEFo21R8OS+`AX-k(BAzf0sP)b__Dq1N!3dkZB1%%!!D)wFx zrQ%gUyr2>gh0EoFEPpRty^0%`tDyc$bNc^&-}juEGigd&^xn^ZDI_zQIp;mk`@GNl zywCpNJ!zH(9C|fpr4wJdHvPwb2fVUhH>DOtDd7x3P8|gdWY|&Xz>6-6Ttn%g zp%nilzYEI_RgnJR<)PhlKs@uE#~xez*kj+(>jvH!dg6(pHze)$%q=l_CG}4^TD{^9}hk+7LVVTdEdYCKmbQoBu>aNni>0rxz9}c-bOr+lR@(o-b0XlEOHF*Mn$Q*9o6H78gEu zEc8Iz^2Ke7m$z-*)U|2r^LzI;?A;5&;jP8XmoL^s<8N))vSq`CAF2BY{^!1@j@AYp z?QSVYHfgYd17mQvz>;M3MbA1?q5go&$E$*nB`i74a18so;UB}#p-uaRaFsw+R|U*!nX9c zxaJx8J+1+~a2x5&sq|=w4P7- zh`TM6vq%5p;NbW_$cU*_RbN3tUzPDaz>vX9nCCTlu_b--kkdC1F+AjuiVN!EsoE}2 zIZ!>2WQzU4ri(7)sqD`H?rk`evZbP8k}jiY zCL`S@HSjw55d9TH=fG6g_#n<<0P$-fM*!C9AEx{67l=RlQmb$qulMxzEJ1?trQzwda7*+oh_{CS z3jUwoYJ!pU|xve@@jw& zk2NtF3^t&X5%3w4*tG0fX2lLiJCH{N(r*!_SbuKAhc0bdxv6{0{L7L9$sM2kuwne7 zSu8Z}XlU*0{_uvmi+1i@acS;_tDEO+>^g8@h4K9r7q8fCK|UxW8ebL7dTXUU=>zAV75MD_nOzP_k)mbN{9; zAY`X_W?8~`O(Ntt9>;1<44;G76uwjFkxu7{d0c+pL>_1N=#s~MKf~e9dN9r7zE?Fn z7@S=tQbqu4LfZ>Wb&xr!XBTLwQ;l;JoK8xe8UCs&xkA<~$StT~;3Opv@>eN(u*AF) zCYSt136p!p{S+LH3q*L24>>blp|&)&stz z@CIC<2S0YkGKy+A>*1$#?}6DC2Ps=W1-!mJs88Va2Xgno?VW=Pc92jUsNU-W)Gp6< z%q!s40^2lit{;&?h~3zT_#Z!X^p)um;UL}5Aziu$F(8<`FR)(@ihK5-)~LgXA7hwJ z->jaQGdkK@r`9Dxi7Q{nrZR8)qPw1IjuXvzP#H@rb<3m8-vyP zs~(^9wfa08!j0wfZBcFL9Z~H{LbP&#uYDhUEr2+>YD8Dun(`N5S5}$3lB+OX?JzEN zdRO{{?gvA|ae)2^C?JY*5D*YY0$xObx-+{HKIinVeE(a9Q!%6?)Yia(B;z5mEg6H7 zOOu1i?yW)#5NDMWmjk7p59mg((B;1%+GJ_>zF;%x3%wrseMyLcXJ|n%@=xC zHuTjF3?0IM`c=0UpEp3$@fBBytqt>ocMTna4H+wG!$~=z_r(;&IH%i>x9>*qd&dwM3oY- zkE;VYh(19`8TO9ff0c&aMLz|3w$GrGt8-uc#ZmCaA2^Z`9idfpcVD` z=iF0k%=bV35#Hn3y0+@rcK|SJ^A>4|R8?Upm=BX5vp^u&V2Lajm$*0@W0Cn}C#t}9 z;xur?q8@+%kDJo#R$bda_8+VJMh+Z1qc8QZGnzI@&ey+Y&Lf-F?f#4L`@zx6{{5fc zD%&@mMSAkgXS23L0Dg%o?fg`zq6Dpcav6w+r{{v%n&)7pBo(kKhjTZGi=obV(Gcnk zl^?OrrI3+GOj47b?1JGGpC?0)qQzj+rSfb;_z`B}0&Y1IB^`y+v)PpT!Vg;hAOfkr zMLWK?L7$}6gq(^~P}0RjYkrUXBvkV4nn25J}1u6+i)`28x6pdVi7cFNb5A_4I9Lhx8U+s$L zoZhXF!K5q@$O&9?s?UR5MD9Il`5MW+m8^+~E!$3`Y?Mf@`qQ=6&>@?w9{KTv%T-D3@qJl+GQ!@V7shy=Lis z=dHWcI3_L)Z>^OTq7)1hX%8+hxZil({}0h#aWqYP^_{hunOL-E&1co7rC%3S&3%<~ zMi+hc$@wPjOqvf#CRdw{DiL^wXNJ7v{B(7^dEJh)TpMU*_j~PF27K@C}LG&!x z`{CcMxLCZNmcVzS?s=p!a1OS8-E8 zYey#sz$gPl8+`7v;}0RG`5`ji5mEZW-nj!SAQZ1n^`-9k)&-)@c-H4jb+0?WXYQij z??!emrJiv3F!coSO>y&i#iENsF?EFRLq{NwtkmF_LtwLxKIH;%%6J0+Lsx)gAUIZ_ z@ypXi)qT*Iey9MYU>^(;P{&76!EFZNMrty}zdCcmt^o-?Fgazhp>pkX(6<%f5TRd%Fvsr%J=KK|R$Rsh2Yo1e} zuP`H{r8)pRqUO5>COa5`aYn(y37#OJXyTQzAgaPyR=qWBPNgP@(e#vKR{Wv3OCw4#Rm+NGA`DHow`t3eE3AgQD z=sTwE*D~@?H0Af(t@b89m7Zs6c^N+^2Dhwe$7y*JT#|IB+v*k4doaP*NF9%Bm;J1a zALD(VHNk0NX_Q9BJ;BG>=ViPpgM7FT={M;H6|Yu#BV|yaX%eI>+TrLq16Ehfv!00s zGf{#vRVH~!=9;Xphf@VW7!F~R7c=z$oY=M{+oJ=f6Tox<3}8jY^9i z{ML?LpamH@Im(P`G`To-0YfN32cz1z#XI79=&J)t-ibl!#~gO!yDXPoX$l+#R>o^4 zeleWN0g%d@#H=KG(xc)Y;|JpAZ(lL=JT4#5j_4urB=+@I_K7p=e}cnXF~XLm+;SwH zo(G#O%Zddi%VMWF)BuC7dwe|bWbu8+j*siZh=6-YoGI%#pqiZQZ&yaknJJayNLM0K zKnuW)hKbAG%68-K(1T}wefchLuEUw`kHn^Han zUXNTP2qAtchyHtLFA@W>_Sw+pW%Ms{#S(dXeH#M)ly@9jS)49?hJohkXg~j@o`p+h zom=B@mABXQEF7GTx6X>Tvhtd!UsM)0S0ekWm~mHSweo|5i)RhaTD+;SrAobtPOa*V zRh7BV>}aeWWVbr}Qh!U|ga+RP^FXS#W>#;=Mdb$6%_&DQd1nkRFBkL0aQxHx4;MQo zjV6=O+K_VU!nukQYy*rW`tq6tGRT^1nyV_9AW|Qyr;DeZYN&Knn6@&cTF}>{Y=)R0 z63CSAqTW#$8EWr=FJjr;z6ED?&VsXI%940@PEFO(sa<`Wx?jUjeSCb{B~$h-hA*S~ zoR3fW_!4+5!l5-{Yx|l?u{YMc)%a=ew*JoHO5@rR0No3}OBsB60p|Fgm`13<+3BO# zZum!h2r_N5ZT?x~;zR)Lk&$Hb)Iobi(uGSo42EY0nzTFq%WiDrxY>3#yPg04y}kr1 ze=9^gA=UuML5!bNP(eGk9&{ls7_W`fBNA0fTU76*^Is)v$y6(}20i7107~#v*U*_iFznufRcVOMvVMp(Z6)MJ8 zj+?}|tZS0P7(t}1VE;378RDis$O|wm!kNIH-(Jem|? z@jLO6!z;u^;-VERjO&f-Wz4qFn3J_g+8xlZfzC<97~mr&JE35i&d3%g z+*mNF@F_TcA`!Sd;Pr_+C}f}#Vmq1^g3?6bvJ1Yp$?HbyvB!7t%ooIqL&is|+jDX{ z;`&S#JGBlTc>~WXg{=koyfBs{!-~!`oezcJ??lx;1i&~D_X6tz<9yH&f!s|sybi&I zORi=`uS>307(?FORK31^T7`p&4cRG=qIu)44Qpl(di3c_*G;*$DV1v4wXu8lte)=K zv;7y24sG0(Y%A{CxMFs=v}@^>zOm5@hX(qG=FG>h{sGFgXQOxWdx-dQ>-#Z(UAq%& z!1}C||Ef>YqZZ1tEZ_i7qS&;~_?dD`BHRnJ{UEX2$Btd6H_14if)t(k+9H6Y0=d~~ zjgI5OnBH{uHH+5m-mo{e^WX;kt?|%Be;-rN!@Ua;`BIn)gI=}8U>_Rwdc?x$I3^Hz z1C|kmDJytv(KTmp*o`Qgw^-F>ZS3za8V?Z{Cd|6qiQRxPTTu6u@#uaH@NnB@;E8p@ zP)2~Q*uOeK%j($=5Zos8y-SrP{R1`5*x6I#EdiY zkgn(0kn7HII2<#XVBImv<+_e6HQob}aK;%qpu?H+M)!tXRRm)=)zmsQUKI|p=Xh7g z)SlL!hPtYjcuPr9s4`rcr&__I{D8=10xQBVlbz^1iWn^rrvr5caQLWmR&~VV=`6pW zNWAXC&!q;17);^!;4|V6i;cWFOaa1=n1j!j;ETZ&{;Dibh=jO#(d_=&i{vk37h?*= z3pJJfl{NC0QJ?vCe!}`Vp}CK}2VCw+<8r3908;X|9!gF@0e;&3rqa@0Ae`(v0jxq) z%|(8*Cuh42ui-$*;rF8jNDwVCOw`Vt^qy?w=1b(NyWO~3mqkW~Q^`dOd%7(Q4=r7| zYSF4WsqO_m3y@BUc)Y5a@tMctI-+o0KMAhs84qaih z{@RyJ3DKWS_KVba#6xq9#eF4}qN1dvvhq)DJ)&oN-BjJtTHDs$-G+D0*2-9^D2v6A zo&9k7o%pBOo&BA&k5Q9m3mFGiD^^o6bb#46fY_ zgeIonao?!e=*{5wvhoC2Cp3E0b-)>cuc^sHJA|%({NWR~sS3h#(@l$Sy6MxYTW?LF zD=Dr%D5j$x^&*VRp57<63gF`OiI#)jlJ-HJqoYHkqhk8Dfo=F7S7O|xmW15ARtss! ztyZia7Hx3({Vaumh$p<2p)uM9UQR=NNDGC-LDVZjjeB_0J0Ywk+aZ)9K}Fo}-SmZR z+rD5+MM=)zEb~>CTsYt5S$HY3zVJ-eEdMtQRH&hUcGgo7W&jT2bnVB(sB(ZoxZN)1 z0Jx!4!`ieg97gCwVHjpF3liTXkWi1G1RA4NJac#gM2A(*hf_-;m#_+P?J94gm9SyG zd^($l020diNKd1D>)epz_9J)FxxBVU#ilhi*0k2P9-mnl0PD8LPshPeB#D#T*xuVe z7eA?)in?x7ry94LZ}F_y+%4UEqHF^vm*|Mg~{QqVQFz6s*$gO)zd$cCt#+8AEDR0+r9q- z+>WB;H8oXLSU$6AT~(qA{=3rRNM*E=K`}M)ns`3rR;-$&5M)$DSR%_bL{kx$`PibO z^75i+x0PMMdSw?zYw$i3=kIK~Qc%A@f{@ zY%sS2DmG>VjRpBA_aX16nDIkI4peEF1EB0P@YiPHBt5v6puN99a z^&A>FRW`DMSNP^{>4uGy4z;<97R?pY$N!>x$GSH4)3~`};hcs!3s;P-pa7_H@;gm< zW~RC__%`F}CV>ZGbrK%TAp&ulIv3I*%~OpgO_gElmUaFr#B{ z>x7$=nyyW+57vib@mM^>&^j0$+hb(<$c9F*Gy7ZkOTb)EQUtLSwzos~+_Qb(b?|C> zigVX&-&bV4yX&s)Yy2g?+=gJ$KI`3e`v%9x4mxz7ySU(d>ve2wXD%|wh2x<0O6GPU z;(3+41YJvUB{FS>R6(03&qf<_)Y4#~UKwW{BV{Tv>L6m1*R9_f}VJp0v_5@g?(@Fx(O3UIkMKW4TK)RAy!BSi-l==^ZK8RW!)7#qD$w2F- zraZ=2tH5f8SSMN#ZQWeMIY_yU@ztvC7#{@Xgt6k3nRKx{UR~e-N$@!dwX-nxNK4D` zdd60-9$EuM0#>E0xN5(Os}3ezh^uzh*Sdn91QZD*1RH;@h5@AVMSX4UA5}*1e<$94 z97(};dDQU^#)JLJ#INiRp24pz)*R7-gv|xGP>^c)UG`yi!qbL(&3UPN@qwBb^&f#S zXrn4t#20=x~O3M&5xZV)8IPVna=4;HEPWo1P&1zn}P z7L^vki(^kjpLkqQTT*gQq|oAbqPc6%oG$(_y%#@^n2Aci?`v=G<48Ys}%y7d4Im39-wGB9K5oF2?c{@l^XjjTc@6SUd;~f$ZHmxKswExJu~eqVfb0o24Q?AcKM**YwHA!_WcX;W zcpb^JdTjjH;s-|0gt4;YAXV%r73NF~stOv7_pTGo>x?QrX7q?3u*fv`qo!4WMlP0m zW0-XW_$i_pktxN{Wf!97xsMdRG0RLWL+4vG8TE#JVObG}fumlil$`*y7I{jLX45#+ z*N(qJqtOvFz823KzmMjgpQOWSC%}+n!NA~Y1V+NP#`utlFl2gwO%4N&N9)<^L@NE* zpF!k7=5Bh?GvG>alh7SYpAYy@~RM1#?Tj> zC^#7aA=%SHIUieUC_P!av$ywV>wkbGX=pEKXf5O~ldmJt|T zClnZu7Z&$s3yK(j2s#|LovFhq2?I#c9Ms{MwSu=&0&r}gsA1}G5QSm=DQQZ=$w2!Y zLJ6a=y?chNA_D7t8>!1}^d*;Fy3pgAf8mn3o4Q7mo9C-JT6x>2n8#VFmBf({7-v|K z6h~oY0SU?!1-nq15YrKD$Bk6m*Fdopv3U4@z?Q0QCT|1R&?VFM*dQzP1oOP$U2d>R z@GrRXNCt4&QPjcey<-@Fh3{?lZ6%P?2t2t! zew;AAH(L#=zb?|Lp09$@iTPXr6D|s`B6Wd@<$jVCgy3ssrPgvx5eEuAya0Ci+ z^Y%nUFgL#-xCiSCrfjbZrTIN>zck$jklX=@p&&O zSv_URvLvFa(Y6aE3@hn#P9VBE5e4@#>rYLR+31l1+hjS9C;p~?pto-3)TSb2QuAGF zQ_OsK3ZIFW^JgzYl66tEBK_v2^t<$%Nj?I$GP&*^MBqbmgE1WL8p#5#1{FHV84$M1 z^Pe^Q1U*DZx>Kyd4JL#L6tpdAchoC)WHRwzkDk@`a@&W#yFNGUbcJ%e4(qQx{q%U< zZ#&j8_5Bs>_rG~<5&I@!+OlOEv%lBN%=#3@e_LL2Hg+hEY&_5 zC8%pa?*p%}5~ZN?b+#W{cMQGcAUFR-#ib~HN^2g^b=d!#yP z%z4Pq!%gt}dgxEK`+X@$WchyK{=0uH+y6VJ?2>NaJfd%ee=8pxwpMFH(!ijGY8Q(K z=FINyn$}!jTU}8S3!{*^X%*|bqf(*@AgzV_iuM?qY22a>p$RfG&Qq9`Pxx|h1`@A(*O!Ta+f|ed zZ7f^gyQ(Kq@7freT^5;Ye4;+lliLz0n;qH+@uaV-Cr};0|2f z@=_fB1)9L)6?zsPhUe~F;L~;Af}L~uZrs4TtSRc5+7SsR}Rwxe&xVn)(F^m^ClBJp9y1Y70=xb}@_0{#22o#Tm3sCq{&49rsP~^GC z=v`rsElkjuKwX`P#Nu4%IF=PNflV_jLv(O&mH1)RUgPU9eL0;5c?mu;x~uk1n9zcr zo(0CylA@v#{22eiKeN`M7&;N8wCZ>ytaMBz9P{kNg2}T}njzp;E=BleNuo3niz?_% zGej2j0t6{!#0bEqp`;$&6?rM?Bf;uZD_cg^QTsGQa6l^`xAqP@(kq?QqiOOO`38MoVIRtqY_5dVd;v6q< z<>R0S&Kny@Jq@jmtpzc3c9Xfq=@Ls5sD{}jiaXTRyT};erX%sxBmFIV9#fac@4lyM z$azn3X=#zsR8n-;T}6l^Zdq1!_vhn7S@Y7nON&2$Pf>~S-rZHpr%oM;-_tTwb=T*s zmKo2M#P0cg5vrxhwb8&2cYq&OBG1NL8<5Zk&YgzyC5x_L;vzLk%0lE-;c4Yg+qqcQ zI%QI)HTzmcA)LgqT8t@+;$*5X$0pO2rC740YamL>SP#B3+QW+qsZN*@>3T?1m&MEC zg{6h1!GiZ;R48;?@9Bh-&J~5a7f;YvXWu9-|K{yJYsT6cXLWl;3x6B`DnH3u9dXXg zvwD3mzwGNhYvz#r&A-WOK{VJ4(@>u`Pm88POjCe6niVJzG@vTk@vwjq4-C`OS?kiL z9WE%;hn$hThhS22iO(I(EAxyW(6{@_0)Kzrf4m{bY}I}*V{P(iC!~c33GxVGfbt;i z>mxYuRCx@XvO%Ukgp={0hvsup51yDjDM|{ebBx>Y zk%yXE1a|JF`bNYmpcV=&pFBeu@N%4L#YxgCiNxhdFiah;HVIbQ3GNA}1)4JY?=C4Z zW{4*O#s0guz4}_)Q`N2^S0wjo*Gl8EWw43uoN3&aQ(YiRRvI5w<2S&6$-0Je z4N!|8+Z}5FjA<7a%fO8&YCWL#Yz(di99a4^<2_^ip}dH5NG~i9{oCL8kMsUMQ0CLO zk00=sGEx%&QTAz+FxRJQ%r#g{#KW+J7ukkHA;wyST2DNfWMLQ)6F6w}z%t`9tb#ai zrg3XdBC>3mxO%1WODuxeflsgq@;QF2!#ueTu+h_aWy&(x@5lQ}f@t{1%=TK;Y-*=$ z0?i%hTDtYMSGV2mFAj(&j2R^*ZK7Djp3aS68LG{>{9bRA_{rdZ5$2d>BUAVnUw|GUVElI^kwct+1`8lA*RR(-T#g-B0pph|>C>TqtPM4YHX;WBy|_azL_o^e zFjWBK*$UwYR7j2pMIs@XkfE5M8b^9YCRxGjl|S`bfSUZv164Y?mcyERz z21mEKBe!#h9{nK*Ns6yj$N}rk&0c4OQmY1fc$ZPTW{*zv;!mQ(39A!d-NS5`v%P}=-4GbVoG7~!% zMG;B2swxb>tA9y%qPaX83znCyy5YwILua%vsBSJREDA*`zc_u?U@Q(ls@xhf^USsaC5^B;w&9f6+aPo$wp)Ubp`8-`)T~Z@A%x zp&M=hn3CQsI5#|$p9i9{;Dp%9tjAp{1!K38Ceh~wlFfSXK!*k}E2U<3H7^m&+5lt8 zx&oo`rqM`N@TsN48Qh)zXoYd{UzcCL{yO7b;lFOf<(C80E6@3@1dd>4!I!6P_*M=8 z${@1RL?kGIh|Dm8^@t9VSXA{>aO`9=3iErF>w_{m=-LyO*>M&EnP8Z~9(ovUz3Z+m z`%Kh5_)TDr`&8jAPh0n`007G%t^(@?bJZ>;J!oP#FlE}P*OTu8Ys`p1o-V&f1-%Jh z52t)U8JsX~W}b{k{VT+$<)p7L&L0t5<+LRc+vg46fXX0N)@leH*8pfswgJIF7{Gj$ zWr9)3Na)0-L5%WF@v&QPy<_06TW{6thK$>R#`n_b4Og#D)ehgWY^PWcD8*2uCSF&g zh+CoqSqe%`U`)EKSlBL4X@tE=%=~D{Mg9F3Evcv=a6eKw+esA7*gAkZv_s414-84X z;i1P6xBQM{0d_lmUl4bknTTJ+3o_ytDj4Yd*t<_0cD(mi|D#7Qk$67#GVr_tk+qkk zg1IP>;mE@Z>!_%MNImm#szsy{xFG`%HJnY#8MqY>%@TAJrs5M%bd@4?$-KdP zxI!+;7ERt5Wm34fexp$?e!kKCy#fE~FB!Vz!$X(sn|JBHc_<03ANv#hG#ll7b2NAy zu;V?PwO3mVT@-xfV%RWH_}$I=*DhJZP|iNVeI69&zx%{5pLo~8gX0sA_P=!$ljD@M z1pFbp!AEvH6d)$J$C(TMw?_i^JGh-h0xCx$x4T{*5Rm;n+l`yV1ATqQkl4L_+nc{i zT+8+**BUPyFUz^l!Q5wIW;tAKI;+9%P>Du)I->=Y_(eN6xT8IYEiTS)!))8$eZn#8 z=p~q|ZP8&eAGb7Bjms#lN^x}Z zi@?@7&5%j?6tQtcdt&${mT&*no7=XF-NsN~pLoEyDFIEZUQQPCd;n{4pInPDsM8lN zfL#r0fC(U^ddYOr49{e`n#V0XD0PH7xokHI}!EdD_3vom6V}TZB7b5A!Y9hW-gvR5xN|~JaY9%0{ zcPOyVe-x159F<$lq%ioau3cnI6VEL&J|Y&+{@)92k8 zFTJ8Pey1q<-eZsLx(goBH4HiuUqSHVJI_9A#8C=XK3m0$?U2ugFM`ho?$GL2EJmvf zD51*IhiDQ@#2BH7u`F0v8<(nFC!b6~zP(eRY-g0zR{vW*?6-Kc*ptPYd~!gV>u!=k^W4mS3JHMcylcWZtby6-u5q6CzyIJ}LyoGxt? z&z=U`61*0*MUpw9h=%!ah??^315CCkI#`tA@FgIPQq-Gn0(7iPL!vx1X>fQPqD&EL zpNorP)p=fk6K)6^?-nP}@W)d!CE!m)g1ObP^5FenEf}qiMGAZs^*CQ0Rk2tVxR);x z4HraWRmDGkHby!kzP178CfKrJ^MOu*H3Gg+$yAb1)&UkoMuM5c3YK}3@lkR0W81zv z@ZC557ULY+d5Gg2`zc~x_v?$Wez03pc?f!GoCx6;k{|)riDL;-H8$H9@0HH+rC z5ScH{R41`m0S-vzro~D{(`HeWM+{0Ruy9r4brnndiEYpRWKe=3977DA1sI6rGh={( zk49~7DplaYE~zOm%tvgmQ`DA$u{%r$(B)3A_<{f!vHwZ}dJ_Va$dd0|fs!X}THu@}DhMM<0TK1i!4 zu6rLu>>qDHZSsc{J*#`3IF)<;%Lv-;5onREov6OP^&I`S@g25%P*w5d_c&%AebRmp z>++xMIgXzlr3nq>F6YBIrjy>|yz)IrewlmTuP=%EWIB6sa%&%tFG95~jP z_ngwYI@V;?RU16Xv)Y4$X4@8t1MR>`uRoA={n$ybAG2RCnon|lJjf%)hA$A^B`3e< zl8N^`e)4-BpKy2sRkdIe$NrRcKhA3C z6}F7`^qh!6Nv}`q8*$5R`fcofB)C>5U1K}!9Q_00K`x?+*zx=1lR*M$WLSKSwcNQr zC!ULaeXN;ih_UKDR$$J>if3k3Df*7<;iGKT+Hp+}A~)tDgL4p$q?OPY&O&FyO-Ly^ zPrE?7P`gC?sCJolrFN}$y>^rKY3+98GT)S?h#)QUl#u$z9t?N-%^wd z6$-wZ%#X|V-um47%%XCBZl`eTa}Pe}dwy?yW?g5E#m}wJxMQqq?Vs^;>pJVbbsb?j zm1htZ>t5^Cg3tP!V_KhaOzX#b2CuWOo$NE~Ui;kmnFTBF<@?F-H`%@RXINtpFV;BL zys;|}oBxTenYXXwt??oG_uJ}?{A+KoXtuuD+iScaFTh85uP(+%xc&ufvcuf%Z(A4R z8l$RL+{?fDt-Od2#usnnZ`|Ii-pjA$Q{)49;|u&B(8;glxcCF3ALflO;NkLeIo4k5 zf%uElF~Le-!hv45K9%3n#usEPXci2j zix9}zLW>^DA-khzdSwLRcr-#H>XxZClALU{mk?HfV7!V7#0)1Y5~an3X1wZTag&Hw zMetQzc4TwQNW2Mv&DuUsl(`3X4=`Z0Jhi#cJpoF5$&&Sao2Y)Zwi%tT3#vmXvihUO#l^D{;@slJjm-(e@1KTte9mcpy-mIP$A8eA zm{q)3Y@3y6Ze0BP++aKusxHXI2>Na2)$4idto8W1c-HsQ1LxKjWv;Cq#6y}J9UQ8$ z+3$HK3w2jfFQeIb z8jPl^4Zo7cQ#M}5>+C(65mqK!G^^{4r{8?@P4lKV-~9EjGxV$OW6yTKmvt%7vmMXj zy)hK>wVo&Me-mw6ZJW}~^1*jJM2S2^=uYh<_&G< zwBX=C^^gcL*paa@IbPcs$Ft81HQ#|59X3Mbuu8uvUXVX59j9QEKrhZd>DYmR%^~qK zexJU!%{a<=$%+FL$CMQ?J^-$qYD^X_kn_&K>DCa*q;jJ8u&WXEV|f&1WFVHnTmWZg z0Tg&??AzzjR}Uy=Aa{>mF~hXct~ z4RP;q52nlZp@;>8cs5FJOzc;UPlb*rx9=o(8;@JbW9*^TSA@ zT^wZKcCCnWFY7ySue@eD_6nbA@fJ*G?fBjL#_6!ku+9KwC<`tZ<83%$I#DeLDuiqq zwT-v{07@wvfY!zx64vowi68!40^BAZ!}s*ub&LB|mOKQ5T}@`2)CubF}Wy znxo5_oI5lh@`UE6=J?sAPPXtg zt3!Zgu`B>p9IJ(=-%l5cKi`iQ7YLN~IVD4oher;!Au9xc-5?Ybhz#O7JM~SBEW}ON(@nY3^#O) zAP~#3%!+^`8&VD-FXO_PcyB&XoMU`SyeJ=M>~eIB9^I-Q#WgVJYk!uL5v8(#AHr_Z z8LD`!^90Wd%TgoAkH-`b;6a}n^%7tC+T2u1hN!?tCVXfQ$mn}}gCxH!s1yhgZK`|+!v{0S%aO=K6cbIW zh-Kna#W|yg#`hl@HU7Xy>yM1zH#!P7FpnT$y|mZFQ{7+^^!z#;PZ@UU9>$cWf8YD_sa`r4?Y>gdPD}1Ar=V5^ez!*tjEX(RA4U(o=D6zU>!V|GUWz8du5%B{g z883_)yIgM{Dc}#*#;Nv`i5qH}!>QFWMEUCcoID3>HDIlBT>-2TN(Lb#)#GuaMGxe{ z5!4$-;j2(ctyCx$q7fk+2%_^kwpsR?6=2OA5_McLbg#DWwnL+%qldCK9G6Z`Hf!T4 zTH@XVylVeL6XvOP+5}EhprJ+nshBY2@4>OgaptbSpac` z1s(+hPzb}WBvb%MG6BM(_NE;c@N9<(i<@EffCcf$C^ZEzRH;k$#XK1-VZg#43rzpVp=&<7ka)acF;$CngNP!H{(Xxt%OkNWki741OswVbhw^L%_Vs5JSHVhBvb4j2u8prlxB&3)`OegA9LtR;Msx8IDh z(T?wrtel0;)xJ*oe0=aWAGQF_svox&OeHXajL#N^^4YDan0G5r8Sj?Er(j&0N28 zAjA2XO{2CaMwqm^+Qf|jYT$p8BJxbCz_5_oto5^vD>1I{v^mdPaNCF+sAO3qeHT^54Nw>xn=Qgb61=6iRWkb&Pn$**{#XD<+ir=j%|!n z*neprE4Lr#gtgis*XktkiX>H#D3?XT4{d{d>7?EYReaB~AWM)%Ce6NlJRWj z2jFlopXxfYlpuJpS`UX-i~HKsIP6NbO9>1J&S?M~-FF-K4CRCI2Xe1H;Hsj@~cVRPrbZ5Bdb9;gQk)j*D?c z1`fz2fCC40n>?nU7O1%_3%+puu5E8fQG@#5%({z>~O%fo2vrr^;CJt#1DAh__ z$iE4z{dB>h2mK+9DN4o@$0Mcyq6EG3bsHT@b6hsQ$>FWiG9*Ha3@uSO z0Wy?Yz-zBrdH`3|uA|%wdWV(YriZGc_1ucf0XhggUL!sEXx)>}stz9M-nKB2IQPIx z2xPA>+R-z5=I6E;Rk+^LFEZm=^35>6-GB?k#Bq_^gbl;MkKmD&w{K1)7Hse4xLZDV z=4j83MQU8|`IImFTs;9Qa7 zkm4Dm1EVW=MN0CKT;`2|c~CyZkPK&#wfo`P7Fxg$kr$1Bm|raDqy}vuBm;2ki#FfB zadQE~$3p*jeHn$38F^JBLq8A1Bivj$j<|PptM1{ozStrdn%| z)j22CACACIHBo;!E!&Ue)7*KcT|nBr zNFF6$i1QHQsXwHkKTrq!-_Rc1WnEYP5y7{4JKKqusTPeKb-SFpg$;#z$LrFxZl_&mKxtMM#XaDYur6Y%roNsW!@vBHvNHe zq$!u4Twa$VL6Dj(_Y%#ArahMXNy?)2r>ui0p(`TIk=Q5F7Mb2-7)#0i>2nS|9vvxRFi>Dzk0~gdH zlq{~Sx*S{Dbw{dj76mC_&*($HX98mLrd=;Q%+QlaitJ4B)(t8ojdDn~IRBLzsL|_7V ziL?VIta40B$FiU|OG;6tmt)F8=UHlC8cgXTRov0!)RHz#8^i~(msm=gBxwu1Hg2bA z@AS_V6RosurB4+TR(a0(7$qn5N*4?p+$8u`381IwPa=@YQf0#U!E9#MaRmS@TaJQ_ zGQJ7hY5S94L^HWDV52?pbk9L$N3)K>ti5`=eK{?AkmBTNzoX46rtqh1eWzo;%#t0_ z7EH-k%r*Y2{lW@Lcp^<0<+*$MG6{jBVbs3HgpI5MYy83d!sl8iA;*FCF}KH3p8{z;9iaA3M;GT~bi-Q@H(JC}+DqV12;9|uMx z5M!IDgJ;gEFr&~Y#ON$s3MK6t7YrG=VhvxRx_aF_Q#iQ2g9?j~auZmLnP)8jJ8(!c zeJdb@3{^5!Gvq@0X(j)shKGu{>dB0Po6KN5X&)*3W7XrN22H_FMkbkYZ&LO%pFyllFU)_ej}ZK9X{ed{j2x)HAq|Oq;mnB+hW5$!+3N@l(?>`4FdrtwdJDnE*)W zziUy4El0&XQ7VKC3oE{qHu3!lgw5%|8n6e9A&N6>{2tXvelNl;`u>)d@%?Od3>G}^ z*t_~v)H{o4)!G@U#lbwbXomR|S{o`C?}vi}U~BsUh07^i$n3&jPBd_UL~1twD2xiN zyfj)}Sk3-mUbhwz5jOLUnYHOqqKXZ3Q1uNdFGy>$HH!Z~Lz_1b%^!B@T`M>5Sk)`s z!+p&i9nJX3*|O%bHCxs$JYc+Q{O6a3HZ1M!c&wvW{vzBCz+dt6HwV$gk?Y)h z>{h)DeZdsZpqxOG$qpY=A&A^5S)|&DzCbHB6HwSb#fS~ zaBk-YWW%|gXnvtOc~5U`NH!+pl|}W%_4Yof6I-*gULmXBu{te!eZGIj+nwc!L^*!m zGhbJ%y>WTEQG`s1T`Ye)rdO9&B&t3*>u^t2@?Uzs$OTcoFwpDkH1qvhnpM7E z`}F2yOR~PUswv)N&uKixe7`g%xGAiLwI|N=>sqv^i$95}Qxny#ttZa!yINh>wP zF_~^hdBVAgbf3x-&+0Q)2TSCkDmvDps4G`bA6`wOv?LPn37#U^o}Z`|Es>s|&Z#=^ zjY@v)(F&bid{CQSW)|n^F1YvVgR^xJUUB*2#h0&WQ!mEPky(taVcn}(De@!bK$lxb#h4T}A+KCZs{8{lI9l0-C#WSccPX7Yxk>U)1(UlD`9geHO zpAcjNb|E|3P96|PQ@aSaJ8lpu|%t`M&d4jMO_X`8UMz^M-2qxejzR-+;Q$%mfL zvgf&1_uybbOF-1KbxW+cN5G=o%T({@c-8TJpZ#FX_J+ajHs<1R#2xim?r=O@Soo;P zK>pc$efkmc&ZE7~aPDT~ciVD<$McV)&+4y?*A1Y5n>c8UbgTtN+CX#Un>pwd5+vmL z0i+1YgOcGKj6K&}`xy;%6?i8a8c5rUdj!@e;Rd@77UbooSvHIAx;oKG5!Bf3NJJgz zof$>}+1f|mXnW()nil7tzu&WG=T7|Vsi{E2X&qggNyNggH~e6nCj zlIFUGW-rYR@d~LB2Gaf^Ad&@&~}ro3(M|q=;z3sXl^{2$%xXUAar~7jO-#{>+fc!HZolhhgP^Y z?!X4bjwB7YefJ}e8XptUEx92VR_Ik>a4CkwJ?N)bxUOUTJV~s;gGo!pTDexI-9Gq0 z1ODK9B6D=mzMgLwfTvWnrVE2iWis#&)nilRcY+XlK(bYjUP z(B^F9DfU#3dv4V~HbaqT*Mi==R>t-YLg$GAtL!zmssj9N1y0khHM-A^tydckA z(FAcy2`cD-DFc0FwPhAt_Lzn2J7Z?S{phiEE;e*`u?M1y?cH52Hg|W8$lvg+q@q<$Y$>c3BIObKdJt-AKV5r-3;2H4Mz52)YlH_UUXypA~y_l1k`+{ z4w1*qW9gq^pv*Jxg^ZzMxs(){B>8YT zpkO2zpi_;a8tpQiM!rG)jCSM(@k|=*IBQ4$KzGmR+Nmqg^NqM>G)+Bw+SHF;+1{C) z-Z8buIpROxcwF4=S-WWV0+cN8p1xq&k~!t^!I~*cr!~}0t1L+^x|?VO{jbvc5o+$! z>zt)nJC7UH80F_lEMy)2bL%YN${x#S@o)Gcg5;3+#N>)R{2feWOdtNlmup#Gp3w4w zc}VaIsKVKZxuJL!$El_=CpkGeoqHCo857lYRo5DY;y0@X#LN}OMb-5y|Zz zU)8@R<#|>%IdyrywnoYGO^r3JwXK!qMTz3XX~^@FOSH$y@!TNXF5DdW(OW0V@5UF7 zFAsseegooSo)M4Bd6k}`Or^w!)vW;k>jwXe z;5ktdj07G&E@(AgyJ)Rk$p9-7RAfq2LLNcnnED15Z z?vlIix&+KX%s)6bc2IHy`7F@>pY%9v3R77ByMa7qNkut&SLll+T7VEdO*VYeHaJ~0 zpCZnzuBNCk9LmqtridvlD`hI($tZ&3q7k+>;mL`zIJ6(sccRG{&QV|pg2Okv=MDCk zl+P-UFOHYbsw|&(#@wFieI8GrfA!$AE6?|jxVoF4JF~gri6i=^pWKU;gai z>X~hA2#!*FRlz$|Tbx=jDa1}RU4z3A?Gn@ZhA7~Tgu|vLp*2lyn%dHAp8?71G-g2a z!3k&aHSwEMn8=-^M4lzLpr-0<>=rY246Ca-PFmw53R7+^>_o7j$r2bBIKFyxWs74a z78GY}dQ3Mg=%@+dbHhPSfe%a`sjG-A6^JZFktqn8&>0|TdOfxRA{^Wi7p^!eF0>g_ zkR%-tKQ$WUGaUPmzS81o#86J#a{^kKR;#T_t*EW^d(cBdK1)u7q9)QMUE3gGfc-i> zFy}z(r8x(||CE21<>lhpS|VOiUKq(O%PT_@#DI&nEgV5+q!Sv!y6JILP!CV&TIq?i zf;y;*m3xP-tTzG;R}3xO-QT}^;ey?B=Ink@yic=Hr2Lpi*0sV$}f$GNX~U3Z4KQp)oizesvF8yg@KSoCJ$&Fxg%#i$;82 zO)D*qR7NZFbG>07`rVmGwWh%pvui*On+9a9N4{&g^7D2XFJF)sG3g_jJo;7r&*OuT{%($~>p(`- z`VNM^+UdoI&P|2dQ0k0)6lp>a6lBw61duemPQdE~ykLDYWmrH|ftgdn%lzsbKg$<* z+>%t%@IomH2Sr*(fkBn6e z;Ps;CN06MD$9<09%T)dM-A{SBCRi-UBhiSOXu&Xw7CF$qQ&Q^@BX9&Yk3!;|BS#b{ zdGCqyjZYh|L3}q>i=9V~z>=5Q%cMzGK7;KP#zd$;k}Ly2AjuNV`QYx_qWN-#*X{G# zcbQ-Avf?5vFV;W_3CvGdL~2{|JPTIte;a9H`Qv1cmL*WFzeT9V>qMsYmx)xUgjX3a zSadr6vbgFG)*nD^7T>GT7Nq7y!e|2KbcArm*{xe?zh-)~tp^F{Vh9bj%8QF+e^CVW zo7s-UGqxCeym(~crl<#vhER?UEvz7uDX@R+(EYB`!u3x+HBwma1Xud81R1<@{GSV3 za^2;j<=ejUm2E?za!+ncq28CpPxEl*qh4Mln3n@)KoUT{0*VUm=bW6`td)8-St~?g z*x4nJtX3|81WepaU};2k!U67eI49(Eh5avq*S_=W>{lgFZwA zls-}`x7WBzd@LOI`l_*$GyC^rN5sX(&PR;lhkd!ao@Xo&A2|ZBAp4tp2eSVeS_2OM ztMRe->ze*R!vmd76KHTt5hCK#`<8-6( zRGKKw6M#fnR>Jl6TAbhFN+e61QnDpV!qzDT-Xt}-chK9zSK?o@{jR&VugNX;pkInL z#TIdeL-^1(1?}I?FDQ2VP%Z27{}H^Sq=#^!Du5gPtsU{sS_K->Zd@f1zr}`k;}b{r z8U2rlFPnHD{dhLNQdPZ6wJoX9d;z-#+RyFRz&vvT{{2`8$-m$(XXy+uE(mA2umQMp zwrJp2{xzE4FGliMSW2?{(vspLSyKbWz(~E$>|EyplX@NK=mf$|iuR-|N=wd#Ml0C* zpGw^YA`YdD`@hruj?muuj`2gx<*nHRv+q(YtL|%{>OX(Y*l_TmB<(|o0Ax08mq9}Q z^56pjSgyJQ!s|hyjXj(R=z&Cmvr6qd?5k~>KNlVuzt1iwl*V^&FZbxB2eWpzoKKR$Ap&F)uquAejWtS-m4=h3sbI$lzen8?qumvW&& zm4pKhj}u*)J={yME>IY8dmuc45G=V$v8hS-Qdt!9@@LAG+4d6R7$)naW3qT7@Q&)9 zqjnR!4>bhev8G{M#;!TV1?P{A?Zid{-vlfcufRLX%&-8kGn<`xA;N}IGh4}9VzURL zE_i~^)-f%BtDU{xc%&?W z`3-Ighs2Z{Ky3jJrND_7NSyKz#MuIVQyMGu`^<&+TIWkU8-&Y>g`G(>SY-J^c6m0r z&5xbJ?<_AIdFsjag{3aP?)b4O47KPf9D$zl&=8Nn<)Lynj==HnNwp#iM?P@*xv5m7 zAmD{r1pWDd7M$D;EHEY}d3{F6#6f5ZnOOo`8dYIz*)Z6RWmU#u_{Ud`z^ku{cV6~~ zA+F{8RBh2kH~?=N-;G$JU(C^$mi7dL-DTt7z!S4z^T39KTBiZjh@@EyWCsuVeil#w z2l_ZKhQwf3uy8^`d_O@OG*hOChwGuvdaSMTVqkqvnw~y?0ROn2(%u1^oeLCXMj=`L zEnq{H6JVxbrWltjd*p+>=3$t8i1LAu50WMgFP`!P#FyUB2aJCe3Zt%_gPxiOboC(g z6HsX$Or$K_i-4MIFf}^+QP-H1IxH!50}KXYc{rqLB}Jjia3$^wqU|qA5XC?u?Qrax zT6rQCO;Tr9eoZLu=j__BVdu!o*-LSTUp#ZxteG=s^&QrWM$SKf`aU899)0!po#JLIFn}o5 z4jsEi+<*Eu18N}f86^%0=ko^-TI36i?bBXK+aKc^d}U?O)y0x{Rb{c$xd@gp#NMh^ zGmStVa3)%TSW*_|-V(dXkv32hgEDLYVozFefd12-jG>uxy_jfZ^rcw ztsi!~80MbPZcf4Q3P8$=b&t-TVOvw!wMJw=^-)mec?#PYcFUYb3 z+7UgZe+{y1HMW|xV;}pH=KH$P|LNG5D9%pm>#4)6(c>CKNi*jL*gFs~QdvRXQJbh}tZXcfh04R_MoG#qiP(eQ2riZ z6BEtfFG-HLkfMSZ;MbX zf7gigb6qQc-$G2&$3pvIWxvC5_H9 z7YK%DKnBGIt|y$B&{}~U-TUq!Hkumu7s{_CU0T?!x&v{B6l@^g;FUFvP!2)b)|FpN z#OTwLA-PDRPl%Q$O~01@3plpWBy>I;TlnYD*20#p$upq>o|LtzRpr>v2?0rp&P}N7 zsvD}PmGKF)`x#=4ry)~eQ$qDUyOBEJIeFL-%K zIxeh%Mg4FOw^c}2v3YpXO4->7v!rq+M+!yr#yxvB;^&T%L}^8&p|7VqmA9j(FRw%W zo$~M5F1ohw*|W`fYWp7XujRGnEgzjdckb*P<{BTLJNu5g{NNL_=UTB}wpb|miZCx( z`y3)pjvL{CvlMC|XunrgU*FPr2sWtI_6F*7*;^ z{FSI}52O7_xUI8;uE?JG;Xf3_;|2d6nQ#1Qx_@50xw&~p$y9xIUETQOQ%h!yiP(Y# z#yL~)kFrh#=g>UILeNTCsu;Tfmg4lLz}Hpk1Y*Z93-p|J}V`+G4r z0gL&CdWXIfW4IqgKto&8|IOT&z{gotecyYZ*)x-5GMP-4NivhkWU}wcWX~i`leTHn zbZ^o^nl{}_Te`5x5?KYSs4Rj--iqJ?Dg`R?qJYY)A|NUvsJOf!pu#JnuM0HIlkb1- z^UP$jwL$&9-&dF=&pgYy=bn4+*^eviad~*K{bS>c)$j8qogd`~D^)5U&RHiL6=|XY ztI_n3&46>mA^hhFd(0kl=mQNW9%y>tgnZu?_Z`>evW=oq9GUyN!N#Aw(DcId@_kd| z^Z5P~`Ht&CsI6Ry`o>ew3y1KuF!pY9D0JVwFO`+PbnksHm6f3!?b6@;dI`P%1`8?) z^VI|ykSsyjY$S3nY$+lgJzmMcYY^8YVC%tvxs=GEGn+2A+rSPj#9R>f0Y|IJYL)H* z>o9|43@(6R9JJ#g2Ci8El9OhZda{v}!(s5w7FxQ}Pj~nr;W)I?5-Mqzn zBCGr6WjEhxNf9E&l6RT2bH(Om=YODo`wITyjt;&;ec(A)vBOd9S~c+=UvcfVpZUs- zHsyq&qX)8y%A6vYQ`^TwgfX;C66()CBbZw`h;#=*X?e0_zw+;r@>xj zvnIe@ZZcU0;Vw6gIJn7TTIu&O*51<87_J3(3HW;b%W|_Zveaa1@@@B%^6nz_7Ck1Q zvq1t4MKySxs|Ny*uR=9c(?N3i5XPR?%2O(_~|JCjm{%~V@ZMfD315HPtM^z$0% zsE(pM&?y;OBIv_xQq15^sGw>zLGnOS+Xxm;TOYP<8CA|&S$|O>XO-oJbwzbxzu6vl zaw2-4gm}nim5eu@^U_|Zi(NIk?t*F;aJ(zilo`Hw?d6LZxw3? zhDP_CvoBCkTwH+H$)2k=@HN*RyXv6&=l+cwdJZpJ>GO849Xh;I{nF^6US3{Ra-_7P zvh;9Cl^kEjX{Hjkx`3w+X^4UN4PU88>=ra zT3OS1yt$^arkUuV1N!QFSVuN+aFQdi$dMY(c|)HG^kmv8H>EFoLnmg+P^(KcUQd7`CW~ef@5AlAlK~fKZMs_`58tsal z3(FfUgw`iWY9PDcus;(Ytk?$Q1ix)REbanVMv;64pl$xuTw4iRytQ#%#oG4TD{I@^Yw7GO>8-Y1^7J^oRI*04RbpmC3D`1Uo?s@9 z1P3XtSu8_^BA?(Qfd$tBG0_4)q(lrBF+(&x{#cox&sk%*rYgTOAHh#$rHCxg@whdd z*yqJbkgD-a!wWP<$?oNr6|>h)!-o1+6c>b%p@a49EuE3(`ufbAoXq+e$an`Bn8L>? zer{vs;>=r*9(^3akJ+?llK4SUC->+AiZ#m1KuAX-)D&#dZ_{}*|>9iVo4(Y->%;FD{q@CwZ^(* zr?ooO)#gPPJ&fa4RAl}(=$!H(8s%J`sTbO;{x|vz#TzT)byi-wX!Ytv^eU*RCIb6&6-k7Z%c10KNNp{#kxR{8TY35Dmp5XyuGQA{LQWE`Q&J4n2Po zFS3wQJo!n{g{`odT_UsO|W5HlbI@{#^_Yd8F z|2}cSz#DH2Oxyr?yK(csV%~CCA=ycNFd&id!XijS(8POkXh$ns!A2-6TZMw@X?7dS z;W^XehGrgX@eSXAsPc31et(%-uLLu;27#Npvz%8j$;mUv`r z<`iat9XGHe@dFH<8bAUNmCyS1068#G`4lMF06aOQ6m@aLmIq&o8$vQ!yV4;Px5S?d3qC_sKD@S;+DS~tYO1TIjK?4yw@y28RUST*~SX5s>aeDZODcOlt zZRj38i2mQ;vI@T?(d|xjQ0u&=iZ?2nB{X|ET747qYqq>_4bhYzA*@7Fr9J1h zw4B$obWe+VwS8&0c}r?_a@WRh@^t%>hVW8b#|3?F^dITyIK1Lwb;4cRT2V6NAHvyiS;K%rLUk5g!iIKfY@LF%UB4Z1WNLci;oDn8}6gMEH)` zXYqmIkgEkvf}uatj6>ejc4ev^SV!^;a*p`gS2n-5?bQ|imo4e98EQbEIy9kMap{sJ zm-6(V;g_HNz30-t#-X~pp~l9IwLLwT^!HubqrvL~&?VwG=r~r!Hb>4W%oP@yeFATk zFp_N<-q6b_=L5opWh?>7dzPzXyiZy*D9xS(4Fg;0^>XGd^Ol8>@JMklq%0y_3;oP^ z7DZSiri{dUB3Y>cYVqz`KsEGX7uG5qDggxx)&0Zj73JkCsvC!ryAtYh%UfH^bL$ei zl80Oa4?_Ow7wtgSj7Sq@blIq6mH>Lr-=f8-QYmhMs?;8t%zRT&x3 zXq@eGoJGj-*b~{A&n-5vaX8!J2I@d;5~X%TnY#gw17uwwN(oA`DPbqGSuE1$PbnTY z%L*EBb!BO>x5$f}w}K!@d)lBA&pv4Be9)`_F_CKCv46LrtF~mv!04K5GIDb=uAOiE ztrdmUrmH^q!H2TkXpZFVua|8#(`F|Wd{-t3WjSi_fJ1f zysxCUx~jLNv9+qIb>dS^d_~i`igg5GjDHi{8Ei44$B}9ckHgp${1jLz;hzzGEWyo4 zmBB1AKq;_6^6D9Y>il^+h&p4A2X3>*kYlhV#&8Pzccw>}%vg{{Y%Rw4tp!_(M6uaK zTZ)MpkOu`s$F`Pu%wqLT;Wf6k%m9~zNMKTMli)WKufsq1Z2yBFjm$*r=FY*B-?MFf z1)%GAt<+)9VJjp3K$Di;4(uZ7VvNqx_C(~e;Two>@qvLcPzr68#Hd+lH($Bh+1 z8%3Vao0;xOEq9m42yNaK0RfK;9@5?sz$`*Wb!*ng8A##I&Q+ad!C-k=FlXJPr{Li$6F8xmUb!wk&b1h z`D?yBb7Y&_HYWOJpg~+;@Mw}%6X2~Fj%@N}rzl9zTTYUT6{dPJC*gl-#FqjLjgdrc+3bm8 zKbR5hnvA=&A)-YB8kq&{LF}^N)p04d4#a)LGiI#S85RVX4@iDNe>jarAJ`bSB^V5L zTisB^U|Y9n1Jcy^cXU3jHuDu9NXv3MGt)0o9~kZ$DR}yO8Fk&YfFgcO0iwj*43`7U zPaD*9actUXG&dnSeoY@uz>cKEbWc(uaFif@miC!rLD)lVFeH-bzKW@#Tz*-9rvo_{ zR(quHvddOgCoXL!UzL*fEb!R z!=8?uqbQ~mXJYznj*}?yTrsy-B%XZc@O%)yC%-GYCB7@z*CO_!tW3pfE9bD`LnluG z+i!y`Yqi=AGBoO&H4$>q+C)IkHN!7pHJPk~3@)!N@D5o`2uEqB8(3^uTL0V~um!-9 z&dR_c3k&jmZkN5nQ86#ZpxZ}P2W;nNpeA6OgE#}Vm53kl_%>{JMx%KU z3)DCQS}_|}CLqS1{Dl4-7b+6i>Jn>3h!6>I(#$L)aVW>(qA`3bKqCKh0rn4k_LUg?L zY2!uED8;_urH$s=nAk4CJwoDo(>2%R<*i=Bc`qom``Cw<~gPh5Y z1=`ouSE~=)c%ynm-&tTci<7hbu!xpX{#a=sgMz;xk3hNryR~RS7OYNi@*zuJQH;Yj zlNEGmTv1qBT zQ{VWbDY7FH*&Z?d54ZtzV1zSPVkecICc*F!FkzaruQfJL2$mT8cXY3t?nT z;AT4#`^~f^BX)sO{mJ!gq1rBqiDt8woSo=N^rSk?4zt6Fz};jizoCl;4jg2?9?%y{^+BR?!BWzdgUta;IF^h_$(G*8dcWC-V|jB!VWtFi4(F?1-k$G_)h>tOc zVBJI1iYQk%sXyj5{CFv#x%1efW1m`b$L))6JJ!KVd3}AUx}_w1>m7G2I(Dq*j@!F# zKZfUjAJ3nd^ZC|U&xfU4e?ECP$sqwSf)p*I!%$pOUthwH^BVQXYR{5mw=KT?jwPQ0 z6dmCberG9KVxw1e&oMmtj-F%37Tv*^b@GdN{{47<5_qWxku-kD-$kJLDmEG!Vccdm zqJbV)cECfah~z|JHwpWWBu4_0QBs_ylpS#XGUs}R=$Xwfjz0!CtCCL2l45C5BZILo z&T1mjYc;_)n3xJg#s;DxGr$pb=b^|uELwL>0N+pyM;?(!kua88(NbR`x`5!)iT~KU z_qM%z`6YWFUiRwVy>H0Ba6rA5zoBM!v{dk0N(t*DCH4Hyv9U4r1zt+;_$ogz|Co0M zdoRTiB~Wc6#Lt_J2<(#$c4Dmq$^NTo{z%z23}=%a*#eW9Uje&yY2D5Eu5Wzy^~dgd z_E~Ymz{CXuc-L%bqm!?~5A`xAtUc0_!YxZF67d=oA(5?q5i@}8fNTudj?wUq!_Z9y z=$IJ+W{7vu|0T=Pp+E)<3DV&uH>DagMPu%}>86|3;dRrezx~{&Z{jx(4%~U?z~I2; zuf2xdhO<%R;{R2=i|2PmI`A}@4vDJ4Nhz=u;t>26%&>!ME}>^GK8#XqM-n@hNE!na z8Vo5;r=9AT0)jwTi9eh_}DtJS(9bAGbyPOF^xGZi3Sv)30@tAEk^B_LVwvm)HVKduS zR#lSgXw$|G>sAe{=v&&;wJ6fo)DW(#9IhHJFD)$aO30P zlxHHM0^;-tl{6y?lIvCplwXQkwWHZf(Lh*`C>TsMIhCrvNZYSuJ-C61-_hX>2EE?k z=l1UXKnHyZ^2@bP^-2Aw4p{GNJLG#^_uih`y6*0}jt+XS?b+Kc^7Yf-Jsj3Acr|*V z_RFTO+S;ze^wveU!TYp7fo9ozyBaY=zrbqDq)5gLL=qS>v0)j-@)U#>ECop*?jBny zRAuaHkU(NxJ|Pm5H8=$^i&Wboh>kmQ$TUmeUGE6KNbk=%5Vhz6P!m=}ItKEHc=eJO)M!dT%3@G$%!x{j^L$+|KDt z!^)trgy}vIDSt#`1k2(aAJ=tGMF&cEN3bf+-9aE(k1H6y$BoR*ezYQ34M=45BJyQHdW!{Ju~8T`_WKp;cC zIwSB_<@$r29S2L&%+BOWkGHq9b-2EMxV5y`>#0n3n$wC8b#xwF54WhIk83Y>@BsF0 z8SntT5cT7%O6br8GbcV^Q?8WlLk@mX?;0rlye=9SJrX6~P_-9Bv+MZ5?ga-n#=C zCu#h6o0>0uT#+-y+|U@}p{MCO8}w&{_snpDa{e|s&bPt>=^%fcq$J1;BqVC|LP8=u z{BiUWqXQ#m`LA-8?KDhWYeJ0YcI4~1Sz5%Egn}~5Bx{8Dd4W4yfX5*{9R^tnZX&9} zr#Vp+j8;_e%F0kljzor(n6I-EdtoBS27<1v0#3#-e^V8@qmjfM z^_#l05f37N#Z*jlC;4ijEx|wy9)UD$TsAg4w%Lf352_`Aya^z6zL4g04`cN;Rh8u> zK4gP=I@3G!aAt=y4FS!Pv&lVqhClZGsKI43eY6XWV4mi*o!E3%y_af%{!Qi_q(aNA zlhtOUxwzP%;fkV=5|d)2TryZJgarvCW(bE!Ac3HW#3_iOD~l1sT!k3s;<`}KpPS>Q zJqarqwU)K?k&ptjTQnH~3<+IuA^d38x0nP20b6&;NZE&%1_Cd5vwj-Dzn>;Lyf5S} zsVl8%t7~uf`u$$ND<#qCOiXb&oe9NU2?X-Q- zMF|Ne7{pDc1lVd}u3S-C3Z@kvNtsqlb8>%U z0oIP}%P!+BcwKkqX;v?8d8q~e)A~b?G5GP?<@lRf4_WPKmgmF(!ZE-GV5Nh}8kR`p z@l$X=J`mlHI?IUeZ*3_93Kn&=^tARMFuu90c{&0dU_c1hSU3Wv*=J3%Aa_(eUI;?I z9<$iOj6~*Iyv~Z9!!ZMHRexC%jJKVgFyLyq05a5cke-T-l`5$HncP!>(AxJ8IqM@s+ z;j+sq_~VMRV&`JMqP?QL?a2Mv?z9}BL$03^ef?~YY@LA-hlY7{wTY{T$<*#7-%D9+lp5N!A~OWawPP}D{Ty3lZ-(ZwR7iuT5uGU-#BfsC0E zPcdBJ9$Ft$EwozlkwvA8nxQ;aluxG$J>qHMOK2YV+d^>RoX<0NR_x5_uro+n(eTvB zI+0g&USxNT<{z8Bj%HKI+1zA=vfibO7j;Hjno1i>8)h!1_sx3G;!9fy`h0V{+0Kf* zIrENUbf&GfR))B`h6*jNZaVVb7nQY^w$gT0K7;qXZz`LiV=f3iajM-y*v_o@JI+uG z40++NAvY2lXqr12Wmd>I3SEgK7?ONTD1!if8c~ppA^Qj^(wmV0(@425Wb;E2Fv@)K za<7>peIcdk`9WlPK@bS?cqXGpnd>$VFU7k@`RDSok9Jsln_ zZs}Rtw)OC#k-9@mo?8XJ6qR|MNGuzStV2{N)#0#MjaG|s42rpxLUY87eLYS$)=&I-W~jvPXODj>rZHc*01=0OFkXXJKX7JAhj?=m z-pG$*hZg`9K7j*NcYs<1GY`y7oI36)CL~~DPS8BwprEcW$Or|%9jOkO7-3%Y$fohp zj1CkmtBJa8zD$Xg$>#M-kYu@-XOZ_t*j+`5iAApG5GT33$5G#L^=HZ zSwL2_U^x`CK?>X5f&z?Cn&8YYg33RwQaSiK4I9ZtI72%bD--7qMqsC(UXh$uB;{3+ z#*7qYI9JHXsim5e*=3GGQMx9XxCJhTL;XXtBC4>U77^4=9V%M40hE-Y0B z15z_V35sEi1_}^m!s0Nd1o?RgBMAC^D9~p_z6cs>r+HAItxl`X7UE=e0I%>!vkKA^ z0yH17U^1k_$yKZVXeiPl`qdF0a``M)zf-j=Us~5$5<1wkdU(~)`t3vgk+x-3#rqep zIJZx^`tF2)`t;~aL!U%#1QgNYw&M2c!o~z&>iK=E&a;2z%L#iov@Y&xC|hLDP2JJm zzY`gR7^fNW=vX zdRCv8nq7`OL?p7*A+fP8i2CPL6U}4Pt}Da`4AW2_NcNf@glP%t7tf%0fj(W<=w!39)x2h%E)xKToTHMAONlo1xG zslq5tR$1BoY@?h$=QAf={o3pS_pOKyxE zT&&om;X;}C1^CJq@Re$0fp)P?kwMgrgHIT2#F1cCxXsAXyo&f5l|*XjOSUH|2r?KJ zi9&Li)|T2D&LV9sU9DZ{H_}|&48^sqC`8G}l$cG0)mSyJc1C$l7>4$Fc#ouZ?3;1C zC>Z5M{^%E;vg6{&FMk>3O!wYf*Va+Xf8fjCf9}bX^83Ky)6ZOW71)%xS$^yrSyQEc zY2S#>vj(>gG&j_@y4ynfH*l{3Zs=-j>(btdMhxRu>UdekRB74GJMXqbGL0+ zw`SAYO)L6(S1(_^bV<+Rj`p^ea9tHLLp4(ec(g;}Y#CpcF%xI+19uC;xofy;hL4F^9dH%gH1)fqd@zcpW zWUf^RR_sf@s-^Pxp73MyE11gUHzEddMC*!`q`PkQ~}g4RqTl=_cKT~uBz=Shd0q$n)ohk!BmGNpDku9 z**WalNW$8soyht(ITE8;{~b1LH?+H>h!juei4LBKbZW}{M>&>g>c2h3Y;qbIvj0<) zT#CcNMq)>(1VHoI?_nCY!{XK$yFSJ2#4?q|0P0q+>glF}0Pw$_v-+In%eq(gtn7$1 zH-=%JEiDNyE?7LXNPrt;YF!9^yw=bG=2#4d5%7x+u1>OIlF;PL>yOMuzM@b zs>PKWoz?ziR7ljOHPIq?dYVXe@lYVL;Ii75{*XVMw zk@&+j#fuksL(_1I9gMj#?p9fjOmhYi4^@8X8@uB0p`AOl3BTs5D{dIO;o=JqU4HoT z^Y-jGxbxtakxfGz)~{LBx4e6M&-ODDLGHhe2>xj*iKmz!%p!`Z8WiIVvwnIB62UfY1TA7 z`2-(Vi%-rdGQxk(U!Hqz{xtBb>6J#dV4vdZ=O^#ucZ;`SZSB$Wqf>!48B0uofRus2 z8WdnCL+UtaB&r7*!v}zpV=zptn3j!7f-!;^FcPQw`62PyiF4K}i`1(J)axOCKhFZf zAL{9y8+PJP+!xuDbYna^g{1^ipiYxo5rj$Bk1T*tjY|oH z;Y0Mh$DbcEZZueokM926?{__pS^}r;35fnlqs{o1`g8T?e==AMlT4^zN8aCK$h*r& z?mR3$aNR?PMrsKjO<6NYyukD$f&>~gISq}&NSjlT2Dl;!FHf*Ah-^w+8}JAHrG6VA zK?ZDfJ=7U0wH*%Eqb&~(q#;3otUr)qq1Pe01ZW5!s;Cw=rM{}VPO*vVibID6w;63p zLC3y*kq`<2Z5vdt7}_^bQgV0WGOKl2^|Dlf4*z1nAB*b( z

EEToLXFWwNs|a3YS9g5P8vgq_@4oHbUi==#Tjs{NaLc#%Wvpj^p78*S8IS)oMb(kC$$8?xr6Oe<}VB&6G zhlolLQ;46wa0p{p#E@7$@n!y4TF7P#rKyX6jMI;4FZH9N>P#GW{sY9-rz$i$I?> zHeVD%&K}S^*ztqQKAYw~F{QzXM#ju+MD9Or31yeNCx`{ae zvvdG`yXa?$)|99>A1WrbF)&S`a~djNq;&W>@i+^IQ+zOi4Qd$l&PEJb*sv%h`uu=t z4(v(xAuHEn{uA+6H0y>qSUk#f?il5e5?5GnF&=401S>M)QV=u<<&!X>u}L$^9qfc> z5HZY#9fTPLB&V}WnH*+kcCtP?tx=Y#@k_tE&QDB}7^ok7(=fh=nC6~wqp{iL$}}3i z?&MS71^2w}I%1vIUH4MD$7?X=W*`U}aDj*3$9H1>jEH&ch}aTsuz<(So*mH_m^+** zR|NuTY3A@J$9!tjhUipWjV=Y+bj44V`t{lKG;59&*yIkwCbu0iWVPtgS0AZqsjfmd zV^5kZ*_yz3U1>%-9EXT_)gqk%HoFG496^cYWvtAbYCx4N>c|&@tho zmdesjhk-Dt`q(i4Z&8Pss3A>-%tV|E-00|Eg4kXgg8R&}{-=;?qmL?qno;#U?i?Hv z2*kyi!VJQsav&}i3&(XPpwLQCkH$sLyPHx(s3?*8nM4QPN3z5Exf48EToSeNP4l>`wcpb#f0 zG~Hpxo-eCz8wFL`#$E;jCp&{|JuZwSki;+ND8>j|uy<;UD_CcAtIz!T&l~>yXWqf< zWd{f+>N0($>~8~q!~dz$Xekmcw-3EE$_#2T8|7a??gH`dEM(j4*SJp}I2%)tVvdAf z^f#qWN=CyrSVlk(BUoDxS?%P@0B#lY0ZvIjUQ*DfLI$FRVxUv5Op!7y|kFhJ}|M~nUIX!ScEs&&>T03(kr(m8Xbxq z`r6buOK~zCr8?yZps{EdS&(a?UqW)Yb~=r>CO_ZjLz+sm9mh3GkT2j1VKd9g7BjcCWDTH|4l0BBd|^!E-1R_F~xwaQqE+9RCjSS2yGPemTx{>dDKKH6ifQi&8z?s@eSQaM zk7vg7X$4|PJ0UDgt0R&X3E(_~Uc`RBvosMwa^iGN$st$m)IMG3r_K8tdrn<${B~@U zZZ}>@TX*2Pf#?oBAh&EjKc<9O2uSH%Wh#shox6KWRddR4;*V2{-al&IkAQ5ZrDj8uQJDn`{wsH<=E1ax&Ugdy+i}BTr&U z(rZj`heIF&4fq1dC!T*d=JEhKa=5XeIa7Op(AZ@kaz%Lop5V zrLJz9NLCV?PCue-k1UCZM<)uKl$6syYP%QG{{8pk?Ovio)ebsTfR{v89w{M=Ai^Rl z!%E!{XGJXt_=;8*PG`Ci%4#q+K^}UhYL89FQ{p=l&EF41r(kkm5@UQwr}qqocnK$( z6P(?sfZFh6R7jUbg}A3pvn`m%ACeEwPJMLuQ-;r=k73NnFn+EML{8>g(`^mVqeq}e zQys#PAqzObj;1VmPIl1ZCz52XLY#9wE8|yS*QRrj`;RDAiXye3FTshhR?kqVKb(9R z`qDR`i#nO*tI3H8OjJWgBPoLfSQ0Zhe5}Y@dDEF|Hs?CkG_hskPO;_Ip)a5a7X(hz zeH&gGRojPNp>UTNo*eMRcShPXTySJBT(gj+8XU|)nnjA#EL=*BM{=h?*l!L`u`JK{ zLvOvcd$-}Zu3il9{-WWo*b*CV5AXtBI7`RCz6iV&vj~4ltY+vt`~sy_X2J3|N&Oo5 zBa@R7G1@qYt}GxK^m0KHZiu-Yt$(Hw7g;2xj3Ve1z^sW@X!E$tf)QAV&g2M)s`168 zoc;~KeoFbv>BR4=d+-%&pCAR1(FdtSpi&)=^n3?a3)Xu|5(NZEJ~gL4I9;1gghrU? zN<>%yuGf%B>pcpJM_Xl6@a#4WjKAI9Zb%uwe|J1o+G?KyY;yASd8`BLZ8g!<>2yG< z(I53LrykCH;(u8{@~K2t87ZTH9=RSFaz?NrBWDSsIZOduYzChdB&N`c45Y{vN$dx{ zd@M(}^F8V>bYq+Hfz#K*!uDuDvK)LHFeDg>?;MM*{eSgYr?1qXWqkEirqO1adRDK| zVb-68YGUUjP6swcxQyV#)&zGXAEJmMDjw}5Vvq%tVLiaWpdgceENzNhCRF=9)Un3Q zFC7{>^|_}p^}C+o2PY>UM5-Z}=_KJ#j)`oS4&tRU2Ot^_MAk|Jp%7j?LZM+Zuz83eqGZ;%}KQ4@&BM|cI zk28Gc`@4SkyWLNXZ;n0g7wXUGanpE`cW$0EIXV6V@U1UOzU3Xi2;&PWB@{cH$Z$Di~7UQqwG!N5u)l6Q_1h7jaKYlD1d|Y__*1A;kZDO3?-2OdmH?f(FW<0n}M=1d+RAI5R;u|LC>s?-8Y;2r91u%RrTvY{aG1oR2U zrP~)5ZbNaA4aEbiVU0871gEDko3|#uELIN0lNqm%^9$fQE*Q945uy!eAi94!@5vv z)EWojzhZ~AC&b%^35&X2*gqZUGBU%?3HQ9PE8}lq@Bg+!ZA+<-11h&?XT(zQ(QXcD zcskPs_vK`iBCP4=FlRVs1FnN<4A8jsiG^))Xdizpl}y2@>LRiF^o4{@b&;zeA)&y< zAKRx~a{AizJv`YClW>}yr|lry*~j^Q5WpVwEqj{L=uS}I#`Bnhc(22d|DrZDb@`4w2<`0J0Y=6$zOL$GZlrml?q25Yd7gb+UfE!>E>;kqZNC zCYjZyheJ&_u%X5#>}T_t)wto}T@$az#eRLK^qg?kvQ@CLtsdn=Rb|u6YLz80s~IZZ zjs}3)E&t_$t=Mew>{&(@wyP{VS5-8dVN^S>cOIjfGX6MhiEjcAVb;dFDTBAWrMUtH ziT*}x9VHP;w2T2Q#EO@~R zSt+|La!EE%P69C}LdQ*1#ys2!1C}#k4D|*SmqmyqXc(zHDcvoSc~bJu6lBVwWeFmG zHO;M|FU=tm5*icwi;BEn6zeH1qRLAM+41Ik^(qT<+5j_P1N2j+J^89JQ_~Wd-{cD| zOU*&K%ewuZAT={3{rtYTjt$fopr!EsZ$%lf4yl_oNmUJT@3jS%DjwC5vP9(+LEQPl{ zhVh}HapRtQjZLS%(<*7@y6Yw$gx};igv==!*a7~|j7e=hEWL+oJ3|%33mk3gFF9A3LRd+t2_9iUTCIZz&pa$toa>eR` z@Z9G~w*&QRjmgDQk(?$Mhy1X8m`@dBZSFCtnhN=z*mJM>vX0JouZp5scTlZZN#eXV z-!iV?|F?1Igz`CE6&?by1UouUz1*gg%N*m-Wqudw=&|`A^q$@OHxFu~IzWglN>SQ9 zzI)g2f4_V8_{g4n4aZ?n8jhhB8Ubi{U|jQ-h5Nz?Y-)0 zlJixJIZ8+9>3KHY9;;AusV_{o*Fn)1WE?zu4CUjWXpb1q8-IR}gz67}h+Caga6zy5 z8}Rj*hA;S3NVoS+d|AWWqfxx20Pf|eO7gjgb!C4qGS97~R#1WYT4sjV&3rHkRFuf1 zTadCU;fmW$zBg(mmMAQ{@iR*tPDyqu(EPEe>*zAnY#V!D*P+#RAF`ABR`sEl4FFoc zY)MyVTT4TIb!8wWpZ@t%T;#|jv>-1-si|(mEB;d}kAX&jN+2&0uei^EIetcO%PFYJ z^X9nSIo`bLV6ZknJ2%yxo1I@13|8l%WnjhHp5|b+KMQB%=H%BD1Z!}HJiDquyK*S) z&3M#5kr@hQ&U}Rn(M@RPLHgUP{wy|2(!K(};`zv!Ivz=ALAw$vY61aTn*++?LE?}J zZ8uE^Q6NTvls#tW=!$kNY@={#am)aWvk3nk#D`+u0@N#JB*Qest`w+w|2{57zQ8}HinE4o;j}ykud;wgjS(!_F7In0>HaAkn zbx{b#C37?Tvihi9SWHr(WS40o5|WTWz_BExIHXS}@`*FbP^Ui_rROD0!75O;+nt@| z2gT2%avZJdm{-!OA&i5Xn|tC>KaIR~xrOL>J9{XSkb<7)NpMHnsZcBNk}wbkeb8pG zE2!2AhH@>U5DZjGO)=PaS;@1HNgR}46t)Gm)tpczDXFU=cBR2)2OTf?(!od(XInOJ z8d|qzpr5!2GAEkqYb(o(p{$`sM4A&dKG}A@oxHd~AUvemLo}OSJY#tuj0TM7^o#kG zd0AO5t6dl}+|u}eS7so_ZvIu)L(8e^_4ND#uae+U47r)oar3M_6v~R9p7`(6rYimi z`VMJPEr$K!P52&?Ss>zbz~TU@6A>aaj1I{xIY-)$!sI}RCTZ~+URW~m5-A-{ui5N% z@*i;Tu=?qJ=W{nDl>rUHZhb?%gYHRq*7)D>tcUO{Y3J~!%TjpyBWK$=vRSr#q;bY0 z&2idr5Il4?0Ii~VO4n6=>OW?|^I7$kDW&M0iB90b$$rWI${#^xtbJOCYl^0j?10+- zAcGJA!boGKcwjbykQgup6p$~1v7BlPjLkk7eR8yuflZt{7(ugC^!t(RHDH27F9@DP zP4Gf;y`yQHo^^-?k7`el#7(BrqK2aUP*!ee?b`0*#-czd(^nu;)CyPkFSAQZvkQDJ zEgb{&tuV(p;78mk{OND&{UE!ruRo(@P9~IRV6Alm46!^b68#H{ayi1*D76w5^cmVG zqx5QQ$dHX$0vd-P3L1gY2`IsWGGHT!c13D4sxG5|g00ntaFX^YH=KP72P*5G^$vrP zVE1Cq`g#|y>R#2>(%e{EU0RGb*oZrE!paCVb@46=f}VyZ%FZM_h4oMis?4SZNyBD4 zElUNuG8OhfIF^yns->?WjdDxX;_9N}%$<h215kE#<{E`HjnMb9S!WhuoHorTja3 z1Itsia)RELmcsTReQm3;UpHSjOQgO0&=(k+*3uGwmA7>rO78pE@Zo=Gf!q|^_ff$Z z1tWMoz&?fX38T8dPI1J=ZLBfJOKp&KvEuv-+mh2)pfE79|1?0sAs+xMH% zE*0`to(pe5+V{iZI8jQ9RzN0lVrPk9HRKTc#=|*9zB~^JRMiC#u5w6p!Uj{&v}A2X zYEBl3TvDJ)#Tm6hjUOhz4f#6ox+N#i6VITQG!+(x;}4KTK!M2QRpaV<_6Gk7e~8tv ztF&$A|N3^$S#%T6%0OX7gy(`fYj_Q9=Nfg!ui@y%F@4h>j_$t;*p=U)!Jl>Sy;Y~B z5%!Nr!a3*(v>7#~WaBd0dmC7?Eg5O}Xwzajn8J}oe{G^2?PC%Cf;ah;W zFIK)q#@SgxOuZ*OxV|xVJsNk7y{{WYBGGFF;-{52^|< zTeNwfft(9q3eR=Nld~rCYNVZ(lb!GVJdrmqNagAIf%JHSj{iQ3+T(xB3x`G6KQ;Us4^M>l6| zGl*y<>Bmf#Pqp!>HOKh-=?m76@1T$3{h0Q77&PvKzs+N55q(GEPR^G!w3YlCK*w5 z6A?fZ?x%s2>Pbad=UIc{r~n+yc@nfJhy-Q}e-@n@o;?akeH@imghUE9~C*8YU;7u$u6&G!ibP!eGfZ2 z#7*@@P2K3VSXWdY^!tN0@tXS0P=(fDu_-kp`x!qmtIn}B?|&F(N>D2R%e3&%Qk z?b_9Hv<2_<(Qyl*Z27M3@Le-B9PLh)lr9~qG}__-kG z<9MNT7fE-Q1*P|3l(}c%$}4edSp7bJh7bDr$<6!-`-Ctl#rl1I%r8_dxKFO^Qi?Ei z;C80tj4D0E?)GEtZm5~TZ%4k^k8rJ-70au0LC?5cOEI{Be93WcKng#k8(|SCe!TcH zz@~nh0KA=UsofSZ9u;?D&i?@O=Al@9i>dK07*2iELJf-RC$CaaAP}@(BjGH>_K$%M z;sbs*Bh+1hjb05L!P<6@!-HK4vV#e`6alQn#ix?YBoliPtNK`WAdrpMxc(`w&&$pU z1ah+TqMtx9_T7)*`C0P$A^CJldBDS^k53{D?H;u!D*6-SBVyGTkd5WXYwGs6=Q454 zq*rk+VBR(ZIeJvW^D$hzabefO@1uTf_sD+zTA?=M+DGKIW>zgnquZ}% zq>s!u_Y~qrH+_5GrbFuA@kV#n;F{bl3MQYFu?!kb#}XX?b<~Bc;Ns&+Ytlu*$&-ZJ zT)=ZZ;4v{Bw~+Co+#Rf4^Z!EMKx6}w5+wPBsd0!|&HeD|qgz)E(DVDr$vVfq;C8~j zaKpF+2iz-V>R!MtjpjbO)3y)eUj6+Vj%&r(u?CF%cd?HOgB+B0wD6lA75 z(H*i-|57Dxh}N8merj;v2`~L0KwAZJju63xxsK1K!SJGlCrJm}7Hselac6HY#(fEB zuR&?V-qcUm_nx5EY91mQ2Fnhuaf(x-Y#nr_&WfbbFM^y*(|#C?P=y#6gZ=qaB#JZ` zE!z>*H_ht3)rr1=T?G}+LUB#I%aPg<3i#3x(Foo39l&s&z8-^e6qy=tqtpsKTk;oF z=XNF=5IrCVfhy)kywpe6AKJwIc#}&|A5V{RV2Y>6edQWFCq9Tmazt|={GS7tU8x*+ z>n;4u_+&bNee$@t8MWHuaUsWg0B{O6NZ>;40t%pZrQsK>hM7NTxPauH;*a7&LC&YH z5d1zf(A!kOU+)O?4wTUF0rN*DOD3}r%aRaX|MHP%;;nihzO4BglXa7wke5OvX6i|5Ezi^y zW;gk*-ZC^bMMYFTaRbkT6^ML8?_FCx0dS7lK!q>L#AyU)!iI z$q{=eZq{&{Hu;IkPk_$PE-x8zy_&{b+tnxcDdMz>>ml1*Ca&i%Ll!Wbc51Q>j=hd! zhvczcv150MYdGy6X4CH2vESp^L-N?3*s+_$H6mFa+Z#J}A3s%gjM_`zfy{}kxXZ2Ca#y#K_p4}vbt zrc0y8qO=Xw;u0VQ@|jWv`RoC?-bx}1m(3O`mnl`z)gArR=JF#-CFHUbcy4aw%re=W z@|aR7r9Vi3p#Nn`G32p_K^LA#>YQseCWk4-Q8^6PY&`Qdw6;n9(yxL1g=-#>*Fffu zELis9xY2aEi|(kyk&Am?k9(R34`-C0aGQA9iS7}Vo#O9tM!AXbK*Q2yCfp+?GbusH z5f4LVLRXyy%1bmebIM9eaE7d;LRNZJ(pc3Q>%z~a1;o$)oV+|HBdPPrNJ<69_5ft0 zZU0Yd^DSI9QYxY{QS_7ed9AVp@ZJP^*7`rsD;IHHCQ_DYGLhn&tWjQoJk$N}k%u@H zK#iA$$`XCO0~JkZ8SZOOwWoFz<#{u7SqLP!wo}3?!F>9Cwrk3nBs1 z@6m94N=zBS9wt_Tdmt7lFD1_idjr?BLA}nNTDxHh#PzD8!b&CBF`$tk;qwx})}WlG zeIw!}xe78MY1z7Th+9SlO$D;mQyrHbQcgeryyR1pS>pD|&nZhlyDb_{Q>2h{0Lx6k z)Q4Pf0k?t^2f56{jvmvbDKwmRNok5CDZMF1;PvceS8rpbxV^)btP4}|veeo5VZ3ZJ zw+t18Ty~X|%RFqsJRSAN^#(dpIy;lD9TV7MEInRknvVycNmlCrswO7&o^V5qPo0vM zG&xCW)ylKXCq!xGS*GNue@TYw)PTU0N+C)x5}y!cfN6&0JeOcK7=iC7UbfPv2#j_? za+O*OdGj#j%?0yby;;Say!V|r)=O(@vK9CK&{=p13W!L1D)g%-!AeM0QmP;;JpkF^ zqfyy`y{=S3Ryu)WH^z?Lr4&O}dKkw(7CZKP9D7I}`*`fwO-eCjB|7gDv11qFyjSG0 zo8~xnbL`krB?uXauDvC8?4(d3E4_+ix5kbgRVr{E!Tia%V@q)CCLFs>JBF3|JY=-v zkiE_zN5XMnu!`{0Lve`x2PE!PL1UR8VjA5k6^EyB~4=h(`GlKS&@bDXz5yV&-6*%^bXPj%K9zt`U zJQ(r7uY%$eaP7O2vz^&^W|BYO3KQM5{oa%$rsMCPGHX`2qol@a3HaiM(rS04w}gC- zjD+eL_^gF}T%?`jb5Z)al@JqZyQ)C-aUHskfs30 zXH0%ye+D`hqRuZpL)$EYXF{}cIi49Uq$S;{dWC{n&jao1&%5=?(aY5J^E~f4p;RAqRzwtXNfm+*#LSO(aIXOiahYcWEdK5@QwDKgP<HHjvB2G5N0SCp7pIDegevd&+Ce@tTD$P3WzSDx?aT@FUl(=HO6=)*1>=2&-gd;%3~Le9#S{y%aEu){&~;gdDD3%k>443rF314 zEPz+Wo%lX^<;hA*Qs-J}$*O=ZpiTwdno;%=gf2Vhrcy+P$?Y7v=%Ui#$1}3`-Fxr8Lf^3rFW)Q9 zofw}e4#jk+3H6D!>-9r{wK(@h@Yfd3i81W!E*%04%%O+ zWjZ2YuokJuhH03>J`AQ6vVm%jDJN5=*E;OTKc>QR&V;xYsx>Y|W7kw8UJwum6a>Zu z&~?DMYv5OZKIemWw-GV-mflTcc8|$sOyD0w55SS$i3joVvbV=m*^$Lvu#pGxJ!_>; z{UhN_Vbzl-M1isg7z?m!))ncfE|8gJ7z&!c8F!Ic2FesSQ|m4!bEMcX*ouj*;H(Ta zp!~VstW;E$L|?^Bo zFn5tGs_znYZjg;Z6HNohSi(#6Krmb_IOV!z-P2ipx z{vah3q9|i_30hvG=P*iUx&u)Yh^B6a*FJeaxBll3{p4Wk4=?hCR`DxWsimv3q?f6# zFta{K`fAormJqC{#)g}N;4VU#82w8_evdqaH`x01?}#12U)phjNRyEMU4h+>>Zx*r z73Y3~E!Dq+8)0+QjwASr`}OY%YvC38cLOWsd-U%{wuXOF|88Q%{4M>v87*Dh`gaRU z5f|#;t!$aNUjLrJs>M(A?{-#A1^6U94xXok_3w$S9x|dljzJU}Zq&bX)K~bL{#~$g z!>{!33QIF4EZRGA=+LgMzODQB9XfpQ$kxNV_U~J?cmJVnqtgy`9^AiY+dkj6^N)<| zJ>=WFYsbjpBL}w~S~Wr^ZW%e~+s+oT{pj_-#Kw~cL;*LScZ_}qzO2j!WC^1g@hoI|V$?Zhka zq+RliBWw#R$5s2;c{n=zDRUi*KDTI&^QWL%1!#5vj=g~RAVyP;@Y_mOi*_K(Fb;a3 zIil!&%Mgwpf9>our=H@Qaqc=?Nn_rH5$%(hoO-SgBR-78lM#uX{lE!flJH#!M}HL{ zY{07)uP`bP)Ui>#wy?QI`OiVROU}gzo_829j^O^=fOW#o9vs^b$mX8sLxAWYUimF~dmTY)<)|0l0n zB;h(F@3|GvrWLKtIMD)e1#LypdHZpehR^xVB0jSpRH5N>8#^EO7{Qgqb!b+0$T1R~ zZNsru_$zwHE%;8evz=r>`EPO?7Qen%Xh*bn(+}~P&%TeX9bv#oN`PF$E$n-c&umCw zuyY67!V}q-c@o-oI5C8;u#fQ+7Gwo%f=!~TDH=XtulWP&n51C=Z{r@G&YnUNUnbAu zUY^aK<~cl_@zX{g}7%Hr~!7yo2rFo$M!k z5%1!Qc{lIjOZZa0jQ8^8?Bl$T-Oo;d3H}i*rjGaX6?}lz^Ofv1HqKY^)qD+Ki^$S- zd_CU)gG~c_fe*2tvYmV*dy#MA=kRm+FyG8a_!hpEkMeDNI|{TnvL?Qh@8Y|$TQ;L+ z@mqW^`#L|5@8kRV0gh}@eh|42hxlQBgkQifB z+kTuK|9VtxF}{41=V-_K7#wtav<$RFY-`B&L*vDK~Q z5A(0_NBDp8N7+RnzKi+S`8U`H_+$KW{sjLf{}#KHf16#xpXC3=zr(-FzsH~A-{(*B zXZW-1GyDhaGWGzN#@pCh*YfB15BZPSI{st!Iy=pu=RaZB^B359{!{)Ue~JH$ZD5z9 z+e<-g^x@z?nq{CE8K{15z1NG5}9i2o1&BY&I! ziETuGr~l#aut)iy`Cs_|B4g}t>>U1g_B;L${w{xypW@^EG@sxqpM-N2E=^bu48n*u zb!cCW1PGf*K&M6rI$|Y>WZ^{iuS=u~w@5>LcDl$AnIa2O$k`%Cktl`?S1QWTMY=*%iYiepYD6u1n%9f4Xb_F)7~Cvc&`YijT^=Ls)9g;sAv(n( z(Ipm(ZqXx_pg-X<(JPh#Q|}?I4BN@!{UgzKwKy;5*Le0#0SKs;xci$ zxI&DH4~i?rRpM$y_FOBj6CV=SiyOp;#ZmDQ@lkQ3_?Y-OMEjc{o8KaC6`vHhiQC1e z#4&M)__VlF{D(L$J|pfDpA~nDd&K9&=fxMq7sb8eKJg{-W$_hpzc?Wt5D$un#7Xg0 z@v!)sctrfCcvO5{d_z1Y9v4rDZ;Ee;Z;L0ze~Isi?~3nnlFMc9k5I+?!ikHOC#LvYq#LMEB;#cC=;y2>I#Vg`f@muklcwM|9ekXn}{vh5I zZ;AgAe-v+vKZ$q5pT%Fq|BAngzlpz#e~5R*d*YNB7pK`VF(Fhj39~c#qEMp)egzY{ zO;{AGVp9?nyW&t1l_Ul6PD+a6Qc@MSlBRf+bR|Q{RI(JWlC9(@xr$HmD|t#l$yb6( zff7;*l_I5BDN#z5GNoLpP%4!wr5YuAYn3{sUI{CR;Z&NGW~Bu_-ZrIOi6|XPr?N=t zQWh)SN{_NcS*k2kdZm2tM$ZBdONXwJ344TBS+4Xc{mKeuKv}7*QdTQ#l(ot_WxcXN z8B~UpjmjqF9OYbPSlO(MC|i`R%Ku^QUEr%as{Qf(oSeMQD7@9%H&*)wacS+i!%n&+OGGkbyAVJ^7H} zJ!Y@jXMW7=Hn_n;= zG{0zWGQWho)Ha(B;e_Ca%q`}Z&8_BF@RpLN-LB2WyGo<^u=!PUoB1_!yZLo$8xv?sJDweOj`&F^a8(spTwv>#%B*4A>& z$IQLvFU{x8e>G2nf|-8f(>9N?1v&)~d7Wtp;m?b+vU3K6!Yp^&zX#YOP|8-1&HuH61H>|EZnV_G4o4IqeFpB7aePQ2T=RO>GCJ8%^2+*3H%o>lW))EaPmo zW@=lshqP~Ko2`#nv#fuyW?LV%Znx&(+C-1`tkrJKv*ue1tPX3TwaDtUx~#?49agus z#Okqntv>5xR=>5>8n6bfW!7?Qg>|R3()zfy%KC)0+PceHW8H17weGR*wLWRxXMM_A zXMNgQZ+*tP-}-R6taH{Mtyir-S+7}t*1m7O zZvCfq-uf@=4eKw~1?#WYo7P*_MeA?Y+tzE?e(l)kU`r+r&?_Y+Kk_w#UxK z=WufEJUid^+CJNF2kf9-U>D*Jmm+((U2K=wAv zWskA1va9W}c8xvG9&dlZj@VHowRH1I=dd9MV??^ZC`^AfnIBW$ZoWo>}I>g zo@lq)ZT5BcB>Q@Mvi)IuihYAU)xOc5X5VB_w{Ny**tgiX+PB#=?T^^_h>tzn{-}Ms zJ;$DFx7+jV`St?4!(M1FvODcAd$E0o-EA+id+c7j&;FR*Z!fh6>_K~(z1&`5-)XP3 zKW?wGKVh%7@3Pm}ciU_2d+dAdPulm{pR(84pSIWApRw<^KWlHWKWA^WKW{%^f5Cpx z{-V9f{*t}fe#qWpf7#w@f5m>-{;Ivr{+hkr{<^)x{)YXC{Y`tP{VjW!{cZbE`#bh- z`@8lY`!Rd3{kXl)e!_mz{+_+x{=R*{{(*hae#$;%|Ij{c|HwXKKW#r_|JZ)k{)v6m z{;7S;{+a!p{d4=c{R{hq{Y(3K`(N#o_OI+0?0>UQ*}ukWVz#zUyHEQJzNdD-c8~p{ z{Tm#=I;X9*U($})zqL=>zq8NSzqenu|6spj|GRzG{tx?{{YU#%`%m_3_Mh$7?f!@2QZYi5iE>dPt`H-|m12|_EhV!F6l%n-MTTg7c+ruc}MCH_Us79SP2i#cMhXczOue6c`uh=pR2 z=oDRIvA9EYizT8*^ol<5G0`uUiUBbwmWkzJg}76!6dxC>#3#gRahF&l?iOpsJ>p*R zNpYX}lvpP|E!Kj(;xVyTJTCT$C&ZKDdt$%%zBnL$AP$PB#3AuRaajCF91%~8XT*=iv*IV>sQ9Tk zCVnQK6F(Qn#V^DO@k{Z%_*ZdK{7Sqa{!N?`zZNfw--xDp{T<6XvIcv)qODD>%5Sb^ zKf->D{e<)*(Uyq{Zz3G=S{UbeP4$d7vCndvVp&Z~+UNK8_GC5nF6!;+xFf5nwSE5J zKu2!N{I34_gG&~6cdW>1SuA>xluS+W_MMa{qSk84R>DDAH z_2o`V^N8zRwrycswA5!^LoQWe(^bagN2$eo;ysieni#T2rRn3BqIBpPqFrXWo* zRRv9T1tpSZYtJHaqbu2ooSBK7>4|KYiClCO9lLQ6wzS$ecJ}u7C{s;jrCXg?%r%j% z-Wtijv2(CzQG5U3lJ54wfvg)jYh<0)rraBsVg?>xtqSumIkyx}z+~Ue}E9b4X*1jd3msS?o#ujOH^2T{;ZOy+WBQLjb zUT#svWZ%-?1>@dAg(YrNYTuStJNvc;T^(5U?OG~sTh!matRwd$=|E*p)TED45Tj)K zNG#6QZL1fvNNmomRHYKPji0|PQkSdJBiQdslnCBb%FIh?5G+0{z4|;Vk9aL1;wE^} zTG8$@SyP)*skx5*DEo2tlhQ}a=Ynq{94+7J2{>L;gW_*$W}oFW#k1PkobBA!+B=j9 z=clcdGe4d01ys(WgOn53xH>Qe?)pR!zKYI!T*>966|-CA`!f) zqGVoICw+$`Ih`~qTOV*Yb_x~?rPm;&fuoUJ)h-xzl#WJ}(n%>K8WDF&FPeKN)c}J1 zt_nm1@10H+BUHwZwo+Nhh>nucCgNkrAWB@tD9QX;~>nt38zbxMh- z8g&y9C!U%xB%-R3C)6AX{A$=rL{;aNh^Wph5vA@3;SR2bxkOaWsS;7@kRu64&lsl@ zWBp=|e#{?Zy<)6ajP;1IUNM?tK_2T9apZIQG1f1}dPN*QM{g&;PCBe_gyly#y$Gih zVL35JKTa>g`ZqW}%g6hN9AXmcJtvZA=5kT*JHVNb2ZIC;0tq$UjU?2>5VJD1nZaJbP{ap z1nZS#{sillV7(HoM}qZAus#XaC+W!N^b@RKg7xAVTO#S`?c~=QmfZYmyoDiAGa3ek2m#KCGC`< zctawqwQp$`W>3~E1evV}p3w=&x*l)i_J`a1`r7e2x@6vhcH@RYW9pzWvkR|#UGi<- znAT-Z@9ed2?pm~@-JH=rn01R1WlrntGF$LWTiT_PX==!!^apx-dY9&LiiCKOA_3Vl zK^4yO6~ZzJ$+>Y!2Ts|L5XtTgB0gqvaFu9FTMp@;ZiDd_+51Q8?RGN8Jmk|}B#mJ& z=;$73&+1@PtVDn*0|&?yUD6bHkSV&!6iR+`i_tS^tmw+>RrWCZJ9|0hn7x#YG616t zvQheAkokCk+PyL#*;1~`jD#HJ18zhGvj{?bj5zFtLvR&?RU#yZQd1yhT(NLw3GpDa z1StL0L_ZQ&6My)%Ih1`eUJh9dAZ7~690ZHOXl(-~AA`|}$#}i;s5Qr;k(fd;2bX~@ z%A2S>YJuQUXhI1{L@6+#A|~PrqsASJMw1Gqwhfe1QNti`mei!URH6x$XoAC9RahH& zN$SL6(O5#ED$%4$G|5DjCRQ$F7Vs)Up2}vjL18Mvq)ITU5=^QDlPbZaO0ZUCvQ}lX zR;5>~(yLYJ)vEMrReH55y;_xCtxB&}rB~aWy|Safcf52w1Iv45Vbpt;cC8>FyQizC zgP@#_u0@@4!X9nNUf8uv64eAC7O7VTh}2WB2Aq09_|)scSB8(&Q!fTwSw2!vy%})o zRpB=%RTlL0F7aTUZ#)4~Ckf;XbmB#p!0d&+gZ&IiRftcjOnghRGTEa*rL&}}j1WZG z?HOFsPiYV!(~tnCAwiXff@B)RC(|H4l?H(-4Pqo?Nk}$>SfoykZjoj+Dn**r=n!dU zyVS8=a1WZ|XS>v~UFz5_bq%sFhkasH5{$@MLzKF2X*ojj9a|~Pu?S&aQcfBm%_>z* zv!*b`nnGzHf%3$u60dV7UZ)agwd6wb=OP9O7SG5P>Lr}R$H-BC)K1@@?se7l=anIA{L3(W_PTZkDdu{x+)|- z(Tm!MH&`sAbhIz%;Nn%2nOG#=mNUN>BOu<2mv)5vI{LeM7szF3EbA?xg`AeA85CCZ z-eEG4wl+1TfKNkztWH&)SY55^;OgpB-qgSd8)Fk=J?24BG`E+mVkQZC~v$xrdpCga)*q` z44H@5O_&4y#+)=rB0`yrSfXl&3KZnyAh{?YQ!8NH%@fX~&2fkMIjp;5=~5Cf%te@! zq82f=9jifV6^)pSNzv|(g{-oKD4_B^0yyh#3tX9IQ?=+lcuL>JqgW}OU^>vTK!`~1 zX~#ktbVtX4QkX3^%uP&Xm{J9+l7p5p59Qsps7Ix$s^%Q!5ve4D{u$#Jd>CJ6X}>UQT)_e=BPF!OSs5Ict3JFdV%83NF0W* zikEg^P9_`moD@X5k4&NIfHXubK`wV!nU2UH4Q&enCsZB;ClSNllsRe53!O~6OQRq~ zB!x*pQHtgOL@sx*Iqw1}JS{4nW_kNkw9Kxhcg%SgKyikp$Zmrcq^N4yi@J?;otx9w z-Y+{-Zd)a;kW}?2>ER(ET-8;|t}s{DT~t>Q6uZby=1EG(6_5rgXmlE%^PV7aMcy;$ z??f2pijcOmTaUpW3^GgS_x5*C3Zq;R(m_LPSU`qO6%s`(&7@@p`c+_BgCZBfRq29? z>@Ho7N&%D*M|BB!H#yB+sQBig=W-EK=$tgM%#~gAhI7&=$q%LRp+QCNCPd6wS&KH5 zy2-9gQXma|b!vGgR>$*$I<;&AT)ijMsnvSmb=mDb7&yB-y7*hMKMZj{^_9E=Y`tZ9>te%U83p&OHA5$w>u~?)fM^&!0 zO>5asJOhmJj4-D5v!OEEnrDu&)>t+~EFGM;w1Z2#KI!RL(l>A?2sz!oi@LClgAJW* z27CMSy5y{NX$Spc$%fr<Y{!JNX$R6|rvaN|6ojjLlNC}}Q1b%X*q z>)hncuxLlczsWUW4l$DDlva!|# z^I*(SY9^Yqp{|_Mx2xBfm^#9MI9!No(GiNVp|}uZT&S@IuJR4FUb+2(<~`Uw(AC#{ zC)=eVN0Ixw2bX5G_xJZMAMB%`XhU5N;WX7`Qhhd&7W6Jxbt>A>peS+{z&y2zGOu@_ zQ$d4$3mk4$!=hZuQMP)Ntsdo4jIu$ZoXIGcc9i>rs9H(I*$>tJqTKOC)rp{3w536* zj+ei|zI>(fyl%=!o`cCeq!6io3Xz(tyr|vmSX8ap!smV|qH0l`JJLF?RdsCiIxd7d z&R<=dDy+ITRcq?nR6mmBwU#8WwIs3DvY=-kjt$&F=_h%uCCO_o$@)5*L;GA@oO+V$ zY?6DoWc|df?u9PCdR0Y|^{U+_(R=j|xWXHhmdOUCWwL>_58p1syiISqtt^zHEWXmNubkp2{kB-AQ#gDV9{Lj_5;JnHJT#BzY)E zwzTG;+4amD?C$1{G0AN*sSbxAg?g-UA$Y;O-W4hlZuLp7FG=oQl3cz?F5e{25|TW7 zNMg2tH?H<$q%;_wV4b3Ib3aaBHyeJuTmvroL`>uCF2gx z`HOQ4p84k|zsEo?j(-K9uCiMKZySN9}YWKdf(z>1vZ2c4D08 zMM+-UOx8Jc)&C`VVwkMs`o{fXlIKtIn-J8->zsUXIjT)-*pG3wSsTM{fa2%=G^sYN zVMms)HhICvIL{xGYDW}wE+3wECDl$N>M!f7b~I6M9X_ttJONIsO>F4Jc2}F^z&Sm& zGl_H@yE%L;Pi>lmpYvVId}=um>9QU?A5HQMD#Jz+jxlTWH0R?t~)lx(Yqi6QLm5inIM?Gimrq>n(8l6ypE$SYINLGKdc?UN#@SwRPAAU##?{U!Dq3B!>RFZ*j|d6X$js=k_0GJI2|rac)O( zu4i#>pK%_+;%v`2*Q+@9W4I23^-*?=b32Q3{fTqG8RzyA=lT)n`V{B(ALsrl&h0Yp zEa!4NjB|a7bH5ko{ulQ)sPvuk;(8J1b{6OQ9_Mx*=kkwpy^C|d9Ow2Q=lUJz_8#Yc zJcWF&i#9w`^z}@^R>L3T+8#XS{@(kxc{u<`dp_Doy6+mwL!e@_w+8upt`67 zZ=pC^*zKox{yr=cGeIor>cP2gfme{;o&}WSC`*jWb$Ki+F2O?ag4}r>-Q66AxDwn? z#_OB&=eOh4(g_`gLr!x1?U>$y+ZB4;apK(P#<|VLdCZA(TZu zGMeAv&Tt_nLmfAFV9^e{yiWFfc-L6c*3q$mqYPWr-#gehlq-y5k6kNaoA&M*?U-`4 z%Y|W%p=xw}gWcIXxKzEi;B2s>^7w}vtQc4Q8$NqLcvPK?h(*;Qn^>I3hj>e?uNzyI zF1m_dmo`U4mt&wx75`ThAkav?;p5v;Uw%g;ruu&6=bTb zxC8R-aiD7et%jM3mfqPjzZ2&xVASgubUS2aHlD~w>zfMET@DOYw*>Et19Dm5U1jBM zUn1W>v0Nb6qNoreu{P?I;MWzawW*AScUrU>CfC&G@XD231t#hU7xmq7Mx@f3lY-O| zo=mzbMN5aKp)_AfnlHV^Ny-P?2Zk;e7N?n05Q!R@LepuaAz~>^v!oO9$>mD5#Y9ZQ z(|AUP3nV?gzeBvk9GbIRL)1K?I-6pQxRXF{3Q_8z7{x9^MxsF{AgynqLvpY4dL=Q< zQTS-NVsFu75Rt8|1?g9*F(lTV1IAOfEM=KH} zDd>cx_drslbb29&OR2*c2`F@e+{BbFPN1tUr(`){>10YB(hy%22U*4?Xt;~uHbkMD zj!H+di`_&PPXVfn;q6?>L{uNKr){ES5}w`!E+ZzcH!Q)WUyy>Gtt=87${=MFQ9cDZ z>INK4Hc6MBvJLSwgzCo4cqPa#bO#PzWo-N_5krWj#GWQ*WUPE>V49E8R|ZXQW+_9cj=-J6qI5iWBM7?4?dlA|a2Lrf zA>^W`K~iF58h7P5BOfY#b;91&DGqZLD2bvyvapNlVovX$)$$ugt$MSG@EZzzo;0W( zl1Pk?P4f;7aC#$-@WB@Nb=h=~e}3(cik-;s?CrgyeO~V}%#KnrX+~TKB&acrCe(i!^uM~~dN=4-uM`zl0rr2|N4}j{8-WBKf3>ix3$~z(GA|@8ZCz?=*qZ97@QLL8%YrP%>m2Y{eco z`?R_QoZ4h-MEzs}KGW4nNZ@fV|B?~qDZ5jDms5?HU`@Sc$`teFX)PLVj@0q}3m<&k z45{u3)6W3D0hEv8nS&djbZsU6b!`=HG|;tA<5%8s2AX#!d*`~?s+-`_htPLaQ~>k z3ir=CP!_hRBM zrtxs2MlIZWqXF*K1~kMiOdo{XXtcqdgzx<7xOeGBxHlO$!@b48UBmLWCAhe43GN)+ z9I6}bMmya3#sattjfHT#j2^gs#vt4~jXU9f-1s4+@F{~f%|jw7n&|_!hpNW-Uau^HY|x- zCr-fqll>>Sf42XO&r9PL2+hDP3U_HHZa~-p_i^zwT--Z=GLn}8YxriKrpd4IHUiI0 z-Kg-{)U5}&^8jUULJBT?#Vrb3H6KZVRY6^XTNu8A*tnDocN2}m9sf4&a!cSAv^Lxl zW=w3GGD9oHVnh$__A!>U_urv4F1cgL9k{b>1!CaK6^OZ-{k6D57v+W;g@g!N2TVch zp@X{3PNqb6>?2k}^EAzBtjp&v>C=RxVKu*;%e~2q7(22{Oh=1XqgPvP!{?*?JVG+Rtk3%?kX}y;7j3v9SfkX zkR@Qz5kWk~c*@vrcOg5{`o(0o$op6`xAc7JtEF$2Ucz%8|A0mqBRojs{Y%9{so<(! z+>NnJv#D&nxPjtn+`fdbdX_#r1-hx~4*5O9DJ?J-P>o1~z=*3NKhSo=|`(wB%txfBv_P7-HoGsA?sC^Am`&xz@ z%O2F0Q%m_cwUkxVQa(W~Wi_>wyKwQNR*LTd(lZ#g@(cr)s z4Xz9NUvZBk#%TSd9HaH$$T3>~ogAa}Gjfd9|6PvJ`dK+f>*r)E*3ZlP6ZQX+_b2Lq zkt4PKS2xT6tcG;V3c7!8RSqj5tc#%SEoh%p*> zG-8a#EsYqXaZ@A4Xx!F_F&g(ZVvI(r7^87pBgSal(}*z|cQs;+#(j+#qmeeoXx!R} zF&Z~FVvL3!7^886BgSal+=ww6GX{*&xVsT!wDBQ1MjMTCj5eC&7;QAmG1_RAJ&$pn z9CI@}+6-1xY@Zmx7A%>Ap0LrJQnT#ivtH zI<-`&)KA4IsdV^C3R6(XfztUX@i??_hLqBYsE3?O38@$aNqLZjyh$43%=qDwYPIKgyPE$4*LOYDKpAA2UG+-Bo`u{G3ku=R$ypiIrNYU{9AP&9Pfx?(K zF>SpAg^@1D-Q>`U(IYV*`XvQPJ_R}X0G^VUrb(z6y$wQPD~6Dx_lGD3`aN7pU*YgM z^8TLH!l*S|Cncn6Qzmpu+FtTW$qJH^QC}oY)fWlL5>$LB+ccko!YL`?hzymQ7VmQ) zM^oTZ@*xU+791$a(rLv9Qc#*Ep~DoKNuwB<@`lz)r{=g*Q~JqtOY2LoEuC0888vK1 z3R?JXsQ7s|Ep$%CC_d%TichDYR~#su3YBT77$ucXXi1?1g{L}D@v9CbX`IG+hgSS% z3cBP#B}NJgIgm_E=1k@-yw9;l3UX-$4l0@dyZzEJRBe)}W!jn3UFc3jm9!K0@6}Vp zqP8z%NT|ds%ShJU6twU?pi>S_#*p@tHP)e(6gtp*$@}{;!YRomh9jjUljTMbknA=605Ag!pKr`ua8-q1=zVf4r)mmMgS<3J@f4kT$Mw-R59RuXeU zOHjs2N;+;DDv=haG+a{9IyhaKYo$R-O35^bCiUZVXFIf#c`2yVfn52JZw4wgym2e2 z6q>5PF!k3GcG;x@7)l!{4Wyuz4pf>BP0>o$q(Wuhkc03gnFhBHq`?rzllO;0Meb15 zQbMH;Ei^I(jd7sxtM7(nx*Yd{6B>Hkfx>wXT}3vEt? zKAeJfNXdAnmF#k$@V%6pEGb!nx0V7b*^`2v{Cg0^r5Hn?c_igvD(;aKbku>;F-nf7 zXzNi@+bNePQ_zbJYKr%HM6FfnO7A|(6ba|wq_p-C<&7>5mfm6rd4gLMN zl#iD)rKtW-(p3LP5OS26hHOWQ28c@<5cRQ$c`39C?z1F$Sqe(i0EPBaXa-HiAUbME zXv6;kLM;hxpnOmdEVWX7vDE7Qq0ob=Q0UBjTcPQ8N^@HZdL#wy2lPCJKAM8kG(eoA z44R4|^~xQhw;WC-G6hv*6XlaOAsHCZuC!x>{@4mGM30t!hvZax-F?=wTwNNezZ&``;)u|in` zZ6JI~Y7mxCB&AD6epR|ITh)U18c7W|BZe3LBuD48_MlExF&(KC1F5M$mF`fQV;32! z{?d}uHqFe3;&YXPffQ-x8}4_cgjYC_YBN+5sf9{N($t>{m2jFS+qC*i&w|3M9U5ve z&qiEvD-gd@a-?bLo*_+3r;!Pz`xli;Iy60-b3yB2YwGLLd}%1WQOSTVH7ST{oWx{G z$iXH^fHl-#y61A!oLstSsXo?~8hS$Ym!?Tb<;Z0N)G*Y#_iK%Zp%1k|r}W+L=ZY3a zjdeob4{~bLyZO@c-W^wJ_3qU&Cx%M*-IBwovD}Ubl2&+kx*4>TUD6gx&x_Ngm9BLz zK3A=KkNHNbq{FYM(m=W?n(TLZ9+sM4rD^Y3pVOMkwx#+j(A1yQiXoILLmu#7)XR3j*cOH+xKDnFy&H-~0+?$L_xE8rt2KM$Z zpTwsMq&pVwv3IcNd-*r-B#9#7lkZ?3{_-&-16a9cHsHt20NlTl`!{k=vO7_7n%Mcr z_dfp!_tz$N^)K(H&@*Nqh3i0(9eF9mx90WB7s!1J-+`B*+dv;qoNti(7RQotPs_YtK1S}7WP#J<9#hsJ`bi1v z^RauW9V+uGbPg zgW!)aMbRZ^ttDqTm+ZhzvOEM>udn36u zHJ=bW*9^PUTxb^{1ZlUUONVulXM3<$ILYXo^+E@@4%TNwMyr&_?Ov+fTBF zG?IpADfBriiyCsrlB*Mclr$ep{5KJ$hHO|vWmH3U_&J5%p=?OCor$48dch zRrQes-=_2=xQcjci1JHnb3cMxR?xiw_%D8XZtOL3zlGfHrR=m~$j6zLw2~D;H!!AYO*=zQIduyM=RD#)ma?tQF#`}+M|ta$1zEJpS)k(enp;5 zvtF1#e@UPH47sOp`DWC532w}K8E)J<2RC884mW9CfLm+54Y$tL;MU{Y$hi92&cm-p zB6bjN)Gme_v&-Nn>``!&b~W5uI|8@Pu7z7~Ujw(nZkCtP*^}g5y7ttCxMj;eE-&S` zXOKIK+_~f~B)6N~esWikyBfa->ahz4%=L77`aGLGD?Dr9ZuYG6Y=pbbvomk5XOCyU zx6yOhbJTOfa|-ww&pFR|&&6yl+v9D__GcHvt;inZZG<1mu7}&0Jt=!y_RQ?L*`0Y~ z^2TKMWv_s{CVO4>#_Y}6+p>4&pUU2oy+3bm_TlWK*(b730Y8&{E?@fRvoGdoIi4JU zPH|2}&X}A?4kYF@=1j`(%bAulGiPp2XMS-`U(Sl0H96~YHs);3*@lpvIeXyl&pDiP zH0K1MQ#r^x{Bt?y;a<$uay_~J+~VAd+%dV4+-KZf+-N+j9GI zSLCkAU6;EtcQde^xqGDcx%+bu!#$dNBKK7889?W9&%?c#r{#I_{CUNB72t~G)#uI4 zYs{MjcUs;|xO4M5^ZN4E<*mqD19x5C#=OmW+wyki?aAApcR258-ub)}d8hKuok^FjZV}4`)B)HS^XM!>}zZ33?{57!By8MlBH|KAIyEA_e z-2M57^N;4A0CXn*T>km|i{AZS&Fk^{y~W-NuPmF07ZSabywkihy>q>t-ahXN?;7tq z??!NL_HOg;^zH$4*n8A_!h6bl#(U0t-h0uf`8+`N8{>=k>V1vANxo^mnZCKc zPG6sIg>Q{-oo}OWvu~Skr*DsMzwfZ`sPBaDl<$o1obSBvqF?iS{Cm`r|ET|H;JE*U z|CIlX|D6B4|6)K3cmn=FaiAhFCJ+hK2O0yD0@DIB19JnNfxf_sz?#6iz{bGlz_!3n z?-Wh*KA_I_d0&!e`+Q^M**@QZJlp3xEYJ4&^W@n+|4ezd&%Z;S?em|P{hhv-T-7sw zpJ2Q{fc^t=50d*7xrfO8A-RXi{SmoG$bFjJXUP3AxzCdO6LOD|`%`jhrmFvp;4hOa z-~MzR?_+SkLhjed-A3-i2`wlL7bv$!MV-r@u}*mIK4STyA9t@{U}cFEx^Zy7vmeW@*~LuI2Cy( z&J?ZD?$JJp?>c@4C;B#O58!Kno3$-C+xInm^YI(_D&V)YNAa!Q$FzO;KI8Xs&hLlX zk8q;$sP;2_<@XobFSV2S^6YQ$)ve#-d$MP>SMf#O|HS#>ziMx3f5Qplcko4Gfv*tf zr;Bojma2($QZoo;UYxO34?Y9lz`JJrapijehd}rVb zzBBcI!S{OS;!C{?@Ri<9e4V!&U*zr6`|%y#W%vf~N}O_9t*_D7;%wo4`Z|1P_kMi? zzN7m9Sy-=-r%Yk(5zpZSDtzn%$gx!S9$m3?kir9{ z?3XdUg7J~;k7Bx<0V4gt7{*y{phn?1A3@>8CpcW5&z1ZYj1Q6LbM*15a3AN}YcalF z#m|46{fmn3e_i2dZDbce=8Q5O{{_a`PJV}<r_-o8J?;r9hz5hWzyxUnG-m;{g`9(@D`Xz1ps4Vg66P zWB&mTU&is}*?po&CK8x|$jNh*C{E-UJ-O4!Er`!jazmfTy z8UH8iH|(I2KkP8e{|EWaTdVkUF0%h7$E#;OCop~uPH5xd_!}I~?Z(IU&mF14 zv$wLpMe*eZ8Q;k9POzNk6`u1phc9D)faz?n?8S_8{<7yXAKTIQAj{jt@;5Wi>HAn8 z-@`0tJICj7!ncw6AK>uy9G=6zhvlwfzSYdPSm7S-7d@{rUnldi-o9?edpNw0@qUE| zxqO2>KKK@J_(J7-oP2P;ecX?@_*8lRAJg>>a5`*vPyKuAm(BL@l(D{CUxPE5pK;%< zjB|hEo5lESPUm*zXL0`>Admp!ZU$sgn@SKtxIPnkDC3%5;%)g)c3t2Cxoes%IU@Pf2aYN~IGyP{-r8Ib0-PVTFEx%&Vn3*S>rM7A zC_iwP!z1k1D?k5bvX9|E=0C&GYXO6y9{(DK*7;TcV)@?=Ob+A)%INoABjpSN??NVi zohI-;=M8N!I^wNmu?q=oES%t^QwRh5w1NO8<$nM*I_HmHiWCmH!iERs0iWUGZMBsHwrx zv0|W`njUOM&DMjpS{!eLhqWl&1Lmitt6|?Qu+Kzqf}R~?bYM5$_4U9`trPBc6TMF` zPeUIO6dFeQpk{s^^o`nlxa-X=(ltDA?=`S;9$0OBU%J|@a93dUKo9hr-;k~mgWGM$ zw7Lyw5?E-Ue+VqZ+JYXKYi^US{QYiVmXQnhLG2@OXHe)=tsU?rxhE1>rOkr7%=|js zYqVS7*6J8P0<|)Cfe6~J9;h~#OBZVvdSH~+0k_P2Sh}Q7v4(yq5Y$VgOA_+Te!LC6 zY&-$?gz-4&n*2?$|B$g4?gaz=rN0k-hK@I1{3aUjok+1@nsohdyz>XZ6VXrT1&Mdi zlliBhU(qq{7aAror>lGKLPn$;2#B!84t;o^h1aTeS8POKN9{v z;C=A-f`0)1F7UU(-wC`2K1#T#89quP*a;tL7Egr_*+Iy=0_pfR1Mb$0;OyW6xbyIf z+T$oo10x3@aU7wyYKH&KA`fU&G{fux%|Oj|LMI{gbg&V$YY}=U#kfW@hMmD&&Irax z-sfOn#P_ug!>|2SUUhagRc>_Q}WHi%8-FoCrSGdXs?1cEq^~~XNYz!;?{!J zmM`s8BWWgTXaFhtk9l7LZ3WR#ivvBd_={L!G6D;T)(aZ!P;BK7fHsY29|P@L&B$Lc z>=0-P(8kMr_;-Oe!!M<718p49mVq|0_!`h)KT$*Z4S|*z9z$F|Xx9-s9YMc9h~tr&dA&5h8-i+t32^FXtR zhQ1mt*2sHq7$l$%khVf=^+UhmC-P8cq~CE-2|lEo_vkR#6mQOw?+VaPBi&JXTR}TX z@-Slf4glMmhqClRZ=|~(wB6tnd8XxvvGGkx$yMMAH0kBJT6Dbz@dRAn`Lk0eFgHoM0*w3%em{| zo&oK+c@N^k&bccJU|BEOSzHBO7K7G_vDfg=m3#stiuVQ3W){FM-sgxm1+-l#^X}Y9 zplu`CXwWvHmc5wg2km~MRe`n^aYx}T&%jJy%KHFlJ)ji^(2BhaK#P%nuyd{zK;7`p z1T9LmshW{t4G-;P>h!57x-;{k6?t_xg#E2+4viIjd0NO^-ZY91=z&2zHor<~tVHR& zojnt@KH}Q}zGdK>l-~ndH~1bVzJAc^^B05G3EEePCOH;nkAb^@;$prgIkJoM=YfX$ zY_0~Mk$<~p;P>Uv079Q&i9V6&=RuETC;TXL|0_iQFwysbUXeY@cMa(BMwH{Cj_BJ# z_xozH3qjumdXr2U@*mVpUnzFaEzs8y|8Y56#(TDz_l)PfAGY(~OZ3Uazg9CnFL^I` z&VarQ^cgH?0QBd)uXv>Xol1_Vg`7Un5Be8+4uigc>61X82l}I)J>G+$-%9il$)5rG zR?jvsYNme@(fvek1O0x_M((LYG^ zQqX66=6X@Wem~J~Bf3{Jy|X=2JkvnOn>0%08gHV zm%Ge|d7*p6X_-73dfp zblaw<~P5+u<?ZTZZMV_1Gpi{z#eJ=?u2;^H&i^1`zfB#pVYsHyD7e}AJBiGAJm`H59vSD59>dY zw@nqipp6P#bWRuq_5}6^4hN0~P6UnM>cFXBUT}J#J6IGP8SDx4<21sV;P}Amz`5X& z;Do@v!M5Pb1(Sn2gL4Dx1LuS2i?MoE>9W|0bM$%ffcS!VP<&Br5?{gzq=&>7u~mEpH!^J#UlZHKH^d|2n>dy9EwM{{TRbYh zBX*1LipRu3@sv0uekcx$ABiL4X|$V>+Er$w+4N7B`-1iXT+H;G_?hlS3&y~&fBv7I z#xd<`ssY6vJ0b?!#H%yfA1Y^wup*7OA@%|1ND>QH;M8Wz8;Mvl( z&|3kHq35G89eo~f%<$miZ1ymWe{#PA?}_rQQLZlO=&j}ZxgMO0XEAsN;G@S1uEcY% z!iTK^j5&XBBXCKBkJh9IF)tbRApGrk9>wz{p2K*K;W>#gncj=ce+K?$;OI5w%17{R zv~5epFL?$&WEB|jci`Eh!V1ub7Zl?`z6y~40*t!_jR@a{2k8ylk4MHmf#)SW=Mav( z4TJmwShfJ~k_8x(37-mhCZ2hCy74T-vj)$4JjerP=X$|TJbUpR#Pcj3$Sr{W1+Us?QxYv|mv@E%`WFg$Xk~MJGmtf{tvZDku-I7E2t+7#Zs^lEpH$n#1Ci3u$ zZoOg`9^}0OI)*}cD)FGyL&&dO4GN(=L&#^S2hU18_u)Z#g^_yW0eWbth}~zTID>VmqMNyURS1- zA3^-vhdm$OK=CJ0dzX41B7D46g7C>j+rz5}AIsrmsdq5Uu`;}9SrJCeAw;7)`o+O%kU>rzJB6QQ2f2a z=7qhC%kbTWyYTy6l`k1T2s`93F2lDJJR;Xzk=_K>Ay9u(2P-uQEhOikHVYMsJ>Ba;cgg(9uWMuA)lINkJvV1_o(fo_KrHD*`+lF z&xH1l*fZh~=!ZufA9Y~Vu~9E-_LZeqR*yP8>h)2VL4Rh%^P`Q?!O@t1hc*->LR&_h z9Pu*fuZ(zObZB(-=m~%?ggZxHJ9_Hq+X25Bo;rHo=>E}b!N07a6gA*tnb7PqPg&9E zm7~{>-U7I|ta9|jqj!%+x@BX^YDXU#{rqUiEUPbT8+~^4o0USdDsw7BW8bdH)2y;< z%cfLTR7P+^TP*lo=*6;WfD+-=1zXByAarKg!pf1AF+hvUR#etkPD1F&(D>kvvQ?n1 zDcevvu~PCqP`0gdR^?(qJIW51?X5)b6RIwIG88O(22f$BBDksSC_>1D)?H*D5zvqUWl7 zwA`vZSos|IjNqiuo^lT$E3`Lwwj4PMi6G*a`vDaOpAS7;UWh)dxV*A*SLFdf)s=@s zd6g#sjlbe(>v7 zX7-rH)elzh(Cn*v93%S}6Kz?JI@Z{! z**)Z6q3cOBE`8>X}X16QeJ)#*P^`cWnK*e#s|$ z*EAn`N+}O=5yPrFFt(!V=-3GJu@o7DnP)_Vr`r;w%=bm{9N_f>I+&{)q~@Ws_j*~eG97J7^`WbYFE{hzPTvVJ8p~;~p8ezIu!I@VLzgvvD8c zk3}g~DqAFGykxv)yon_YIa1liuZ=(A9p-;bte#-*^}6vE`hVyoS9GA+wV)apjZr6Q z^$M6AB~Wjf3NC?D*@ZZlJsc;qOSJ59G3eGaZvD6|<0g;0b=iksSD7(0ZXU9q zl@i>y)k<93u04We7wbJZO(DaVi#t(8J}&PoMr;pGfoJKtu-`@_VbscXBCHb9Jkc74 zcOA@!k&~0gX=p5UGf_9uCP;6?K7{%#rOJ`_AZo%<{W5Zjg$uYg-4%V4F#vd*+_RQ^ zq@9ktbXOqPD+TlyYs7lEdjw{2xL5ZF%(p>o0lrl{40oH@4)+`4yKo;9kHI~NH}AAO zc{lG0+|4WH`AJ>@$txpySes(~G}7-N>Gv1X?*i_$9MImD`sroh!wxj^@elZCrcjIp+sv}Z*+qB^ShwRvK&#ib`6cra?1;+MciUWTZZp4TZYQ|M{J8l!+Vi!| z9p)bMG1?Qht*gZdQAVr!!dz>9%6!oLBCVGTb5KkdH;Y@uzaV~=Sz$h8e%t&G_IBlp zeYV+X-fMo+`~ud;E3ii>cR+K@K69nHN)(7%ajp1}kiS1WuH~6a%>nZh=H2FJ@XNG% zF+ofbQ^idP@tNJ`5_7q^0{d5m*n^2;zcneY789`pD|a$V%zMoH%uman$J}Io-P~z@ z%X}1jPQ$Ucb%huydn0ib_AF!Ad%PZdjdEAR&^#DP&@G$IC^4N{fI&4ji)w6;YV0to zu@zKfaoWV}H9uzdo9oQ==4Nx3@MF)eScI@6S1QWIXi+Ju#8~kG{HiXFmGuu|9lb@g ziOJ%_*bAN^Zo^KD+@CRU`ifdVRx~bXw(LvLqZDDS!$a@F`P3@}QD0YR!(|=SDr7Cy zMxvfB*G3t4p|)bD3(!g9SE#f9W}HHw_M-6{^mD&OuQS%H!AKiH?~}loiuW#zR;_r? zyUv`1zG61s1cs^cQocjjPoS?bG%r?N-a(tm($Ut?@8n{4B45u(``M^(L`_N<3G_F$ z=*fj~J$j=ovX_VKl~496CVPd+UX^68D#$I6Ee8Fo%&CEvQwWJg=rcWfBi``ysHOU; zr4~?29Y(pn60Pf(T8(UB+BmYn2lR{jMJ4{W>iRzn+;4oo>WvmQC;FIaDhO ztt+i7wPBRkBFbx+@>)rGy^8Xhpu8sSr;)RfYW+!@h595%6BrcFhztz-U#_rm85s5@ zU18A-ES`ZSGcZ|y)9GQ{cVQTxUD)gl4EvF;FzhC}u+L>+*iCnZJ(PjTQ6QZ<-sWA{ zBN-UhhFoF0GBB*cxxx--U|4~0g&{2$b|M2ilYzaSf#Lnp6%TKhX-xNKV0Z&|g<)PN%C^4(3kfU(L37_R(7eZcr7VP3t*Tbbn9NBjytM6gU(@gHJ+T1k$q zSG;SWUDFKdJLRf_027l3&G@ zC8^`q4dyX_Ot7S+WfBkBisaCnfJ|4#O-SixVkke>StVWB++9WzcIem1WDyhVxoB}| zx?F`<^cGXX4nLIz%N*~bD_c=oDqmDfR9P!I6R6x3d=hN&G&s;2!1q`UD#r0lM(;Jsc_XRVpk|5eCm+!8;68{Bo!{(v8K;T;nXY2S)^MY@CFcLvVd;W;o`p8S>J&DnI?EA^bNv{2YGsknsPntZNJPwW#9j+y8w; zP!um=oRG>e3{#Pa0xKhg2t*%5MDWFg^x)+vazH$o7(_utNDn1Ogc^hrgcA959txEt zA{3=0L!!`7q!2_3rQdDMciH=}|7X^>)~uOXvu0gp=G*^k8ZWzt{CR`Fc7wlegU75b z$2T3>;E!zZM>qJR8~m{i{@4b8e1qS@4>mn47w5BK6tOx^#xE@{{XpTJ828<{Q-Y)a zsycOr`*?7)aaHY^UGG}sxdM0B3U_zv(W4e(W_ z8+)u}6hbdY&i2Zhx3_xMB^ed`|f9h8d4=J|!dPQFmIZm-?m0L@ zN7#bxadk6ODJTZDo*cKrV+)jI0AZVKv%< zbcX+j$c2`p>Q9lG?0CHv>G_TcP@qxIh9ul;S~bgBT3_!PimcxYPV<2MDN!0Xoiilp z+Y4%e=be!t?a=Y zJS?iAwxi7jQdgGDdIP7qs0q7Ao};vGJ%Y{;O6YvAvCQVoh3#eiHJ4$5VAY~a))iVX zS#{}3+xu>vH)!}n+ryJ$QKmhd7dH+TWQF4ia^rNGyr_rUK{Jl$%fiLhEqxWr$-lW$ zC&hR1pkp-DTJDWmlKkWkd&^UFx5`;u_)x66o_oz&e7tJ0ysR~}f^y-ywRNL(P*zUK zTV0)f?^qrXC2Kl+XO`6pCGJ*aac4hgjc*UcRd)J;4EeN$zw{b9-CXTyFxINPx3IA1 z-<@m4CP2g7y0n3{aD#)Mcv0){TnmyQ4emQ_Xl^+`bL0Tcod;;{nx8-t;EYT!{gFQM z$)^VmrB;0FR(-QytU4dhXwT^piT~t={!4?N(O%W%p{FM#{N)Y($Q83!z%v~3=Zunm zlRNUwV)rMx&-JF4HzhsZXjw_~#-@)~{d)M*i<17P4gGyhuk}{=-dy!Z7LWAzZ|HwI z=p|8n=c?(cYo!0#hW^h@FF#!M7t_lFlm3+r{a**Y{p72mr&lKZ-`4aKZXRU59P6JF zdU|TmPp59^VZlwGyzj8-<-JLdQAi6Jm)VDNeEWv%)6<@FymQhXJv{sO;pQKCI%D!J zOya-M_~`nrt}owC{B7(0Vh3IFl}9K3o~|#eUiCoN5Bx2|W4(>Nr+B}|2fcE*dScVw zlU?6FqMjP^6^^!_uyyvKQnz>NYjVkJ53)Lr<+Ut#tyyZ zK}!jFOjwVI%9!=FUlv}rkN8VB^=U;(OMgWCXV>GKJ{LTExA32Dyyt7u-a6X~eA$M7 zuYYDV{%& zFlFQq*~)UySwHpG;{zee9jQJ7N=5gr$I=+=5#fJRVvaVr&bUvIXXpK?$NS7(4`o4# zkN_?H`m9H`RfY3W_slx=H9`B<5b4Cs$I%Muum(nigDg7nn)q;(;Bk_<8k&Br|M?uh z(?j^&V@bbvKo;DGX*s!H&S>3s%91T(8q|}=bD3Oxa~+73eF~&g7iX37V4R(%`J(uU zK4VE+mYrtDG1)x+A!AAyI)~cQ1!rs=&l!Bi*iQDJPrP^5D~?a>HG0kQ33dh)AuI)hV%)WYM{Y87zp~g#ls;tF*E57)h&9SRmSA}o? zkX&Pz>PLp9XYBtkH!#j~+HOUoSN+4utoc#fSs&*%gWg)crvH8D+iyHS`+-GlteuQi z+}eBkZ@T`lTW>Ae^U7JZhm&3R&u#d=V|huC|>OKj{p|i!%!2 zDM9HG@%x4Z4|y!snb#coBhCZ8*BSZse3DDmZ`GT&G{4JS8uz|&){FWekfTT3P>J=L zGX&=gy=n|`ZIN5==UiwZJ#;W5hU3oY-_wOf>X^)Yu^!Q-UZNa0>mOd#Zf8o}1{vq&IKOwu$O}R()%;Gt< z&Moj(1IyeQOgZ*n&wUzin)nFQ)4DW0BYKY?zHQ8yJxk9QdsOvIq~K9hJZBaNtPX{G24on(GS%o>_}n2y~{N4 zv1{!$#%k#~!`l Date: Thu, 12 Nov 2026 13:23:55 -0600 Subject: [PATCH 2/3] feat(renderer): scene 2 text: bundled faces, measurement before drawing, stated fit rules (P2) A version 2 `text` element is now drawn. It replaces the placeholder that parsed and placed a text and refused it as RENDERER_TOO_OLD. What a scene can say - `font` names one of the five bundled faces (or comes from `defaults`); any other name is FONT_UNKNOWN. There is no printer font and no installed font. - `size` is the em as a physical length (1 pt to 1000 pt), not rounded to dots. - `value` or `valuePath`; `align`/`valign` place the block in the box and each line in the block; `lineHeight`, `rotation`, `reverse`, `threshold`. - `fit`: one line by default, shrunk in quarter-point steps to 70% of the size (not below 5 pt), then refused. Opt in to more lines (`maxLines`) and to cutting with an ellipsis (`overflow: truncate`). - `maxLength`: validation proves the longest value fits, so a length refusal happens when a scene is published; printing refuses a longer value first. How it is measured and drawn - Measurement is integer arithmetic on the face's own numbers (thousandths of the em, read once at a reference size), so it is the same on every machine. Every character sits at a whole-dot pen position and is drawn there by the Java rasteriser that version 1 raster text uses, then reduced to ink at the threshold. A line's box is its advance widened to its ink plus two dots a side; a render whose ink would leave it fails instead of clipping. - At each size a line is broken between words while that fits and at any character when it does not, which is also what makes a length provable. - One glyph for each character, left to right: no kerning, ligatures, mark placement or bidirectional text. A character that cannot be drawn that way is FONT_MISSING_GLYPH with a count. Diagnostics (ids and numbers only; no value ever enters one) TEXT_DOES_NOT_FIT, VALUE_MISSING, VALUE_TOO_LONG, FONT_UNKNOWN, FONT_MISSING_GLYPH, RESERVED_FONT_NAME; TEXT_TRUNCATED, TEXT_SMALL_FOR_DPI, TEXT_LIGHT_FACE, FIT_NOT_PROVEN; TEXT_SHRUNK, TEXT_WRAPPED. Core seams added: `ElementSource.inherit` gives an element the scene's `defaults` for the properties its type reads, and `ElementSource.refuse` raises a coded refusal at a property (FONT_UNKNOWN at the place that names the face, in the element, the defaults or an override). Tests: goldens for the five faces and for fit, rotation and reverse at 203, 300 and 600 dpi, generated in the CI image (Linux, Temurin 21.0.9) and the same bytes on Windows (21.0.12) and on Linux Temurin 21.0.13; every character of every face drawn inside its measured line; seeded property tests of fit (never shrunk when it fits, the largest size that fits, never below the floor, never more lines than allowed, cut only when asked and always with the mark, a proven length never refused); licence, provenance and hash of every face; the version 2 mutation campaign extended to text. The version 1 corpus is untouched. 100% line coverage of the scene 2 packages. Co-Authored-By: Claude Fable 5.2 --- docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md | 58 ++ docs/security/fuzzing.md | 19 +- renderer/README.md | 7 +- renderer/schema/zpl-scene-2.schema.json | 22 +- .../qbits/renderer/scene2/ElementSource.java | 35 +- .../qbits/renderer/scene2/SceneParser.java | 1 + .../qbits/renderer/scene2/text/Face.java | 345 +++++++++ .../renderer/scene2/text/TextElement.java | 409 ++++++++++ .../renderer/scene2/text/TextFactory.java | 18 +- .../qbits/renderer/scene2/text/TextFit.java | 405 ++++++++++ .../renderer/scene2/text/TextRaster.java | 199 +++++ .../qbits/renderer/MutationCampaignTest.java | 118 ++- .../qbits/renderer/scene2/Scene2Test.java | 17 +- .../renderer/scene2/SceneGoldenTest.java | 8 +- .../qbits/renderer/scene2/text/FaceTest.java | 297 ++++++++ .../renderer/scene2/text/TextElementTest.java | 720 ++++++++++++++++++ .../renderer/scene2/text/TextFitTest.java | 600 +++++++++++++++ .../renderer/scene2/text/TextRasterTest.java | 392 ++++++++++ .../resources/scene2/cases/text-faces.json | 15 + .../test/resources/scene2/cases/text-fit.json | 21 + .../resources/scene2/cases/text-turned.json | 18 + .../scene2/golden/text-faces-203.png | Bin 0 -> 1928 bytes .../scene2/golden/text-faces-203.zpl | 3 + .../scene2/golden/text-faces-300.png | Bin 0 -> 3044 bytes .../scene2/golden/text-faces-300.zpl | 7 + .../scene2/golden/text-faces-600.png | Bin 0 -> 7616 bytes .../scene2/golden/text-faces-600.zpl | 7 + .../resources/scene2/golden/text-fit-203.png | Bin 0 -> 2041 bytes .../resources/scene2/golden/text-fit-203.zpl | 3 + .../resources/scene2/golden/text-fit-300.png | Bin 0 -> 3495 bytes .../resources/scene2/golden/text-fit-300.zpl | 3 + .../resources/scene2/golden/text-fit-600.png | Bin 0 -> 8638 bytes .../resources/scene2/golden/text-fit-600.zpl | 5 + .../scene2/golden/text-turned-203.png | Bin 0 -> 1350 bytes .../scene2/golden/text-turned-203.zpl | 3 + .../scene2/golden/text-turned-300.png | Bin 0 -> 2195 bytes .../scene2/golden/text-turned-300.zpl | 3 + .../scene2/golden/text-turned-600.png | Bin 0 -> 5352 bytes .../scene2/golden/text-turned-600.zpl | 5 + 39 files changed, 3721 insertions(+), 42 deletions(-) create mode 100644 renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/Face.java create mode 100644 renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java create mode 100644 renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java create mode 100644 renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java create mode 100644 renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java create mode 100644 renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java create mode 100644 renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java create mode 100644 renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java create mode 100644 renderer/src/test/resources/scene2/cases/text-faces.json create mode 100644 renderer/src/test/resources/scene2/cases/text-fit.json create mode 100644 renderer/src/test/resources/scene2/cases/text-turned.json create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-203.png create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-203.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-300.png create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-300.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-600.png create mode 100644 renderer/src/test/resources/scene2/golden/text-faces-600.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-203.png create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-203.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-300.png create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-300.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-600.png create mode 100644 renderer/src/test/resources/scene2/golden/text-fit-600.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-203.png create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-203.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-300.png create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-300.zpl create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-600.png create mode 100644 renderer/src/test/resources/scene2/golden/text-turned-600.zpl diff --git a/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md b/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md index 0173744..35b178f 100644 --- a/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md +++ b/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md @@ -346,6 +346,64 @@ Legibility on thermal heads: - Guidance for the authoring guide: at 203 dpi use a bold face below 10 pt, keep text at or above 6 pt, prefer the condensed bold over shrinking. +**Decided while building text (P2).** The code is `scene2/text`; the renderer README states the rules for authors. + +- **The set as shipped.** `qqq-sans` and `qqq-sans-bold` are IBM Plex Sans Regular and Bold (release + `@ibm/plex-sans@1.1.0`), `qqq-condensed-bold` is IBM Plex Sans Condensed Bold (`@ibm/plex-sans-condensed@2.0.0`), + `qqq-mono` and `qqq-mono-bold` are JetBrains Mono Regular and Bold (`v2.304`). Every licence was confirmed as SIL + OFL 1.1 from the release archive's own licence file. A scene names a face with `font`; the name carries family + and weight, and there is no separate weight or style property (the set has no italic). Only bundled faces are + drawn: a supplied `font/ttf` asset named by a version 2 text is `FONT_UNKNOWN` until the asset package (P8). +- **One glyph for each character, left to right.** No kerning, ligatures, mark placement or bidirectional + reordering, which is what version 1 raster text does too and what an identifier wants (JetBrains Mono would + otherwise join `->` and `!=`). A character that cannot be drawn that way (a control or format character, a + combining mark, a script that needs shaping, anything outside the Basic Multilingual Plane, or a character the + face lacks) is `FONT_MISSING_GLYPH` with the count; the value prints whole or not at all. +- **Measurement is integer arithmetic.** The faces have 1000 units to the em. Advances and outline boxes are + read once at a reference size and scaled as `units x millipoints x dpi / 72 000 000`, so the same value is the + same width on every machine. Each character sits at a whole-dot pen position. A line's box is its advance, + widened to the ink of its characters plus two dots on each inked side: the rasteriser fits an outline to the + dot grid within 1.4 dots of its exact scale (measured over every character of the five faces), and a render + whose ink would leave the measured box fails rather than clip or print outside it. +- **Wrapping.** At each size a line is broken between words while the text then fits, and at any character when + it does not. So a larger size is preferred to whole words, a value with no space wraps (the example's GS1 line + has none), and a length is provable: n characters need no more lines than n of the widest. +- **Truncation.** At the floor size, as many lines as the box holds; the last ends with the ellipsis after as + many of its characters as fit with it, down to the ellipsis alone. A cut text is also reported as shrunk. +- **The proof of `maxLength`** lays out that many copies of a worst character: the face's greatest advance, + reaching as far left, right, above and below as the furthest-reaching character of the face (in IBM Plex Sans + Bold the per mille sign is 1.382 em wide, the fraction slash reaches 0.245 em past its advance on each side, and + a capital A with ring and acute rises to 1.15 em against an ascent of 1.025). It is therefore sound for any + value, and stricter than a typical value needs. The example scene of section 2.1 does not pass it: two lines at + the 7 pt floor need 59 dots at 203 dpi (53 from rounding the ascent, the line pitch and the descent up to whole + dots, 6 for the accent and the descender) and the 6.5 mm caption box has 51. A box of exactly `lines x line + height` is not proven; 7.5 mm is. The proof is for the render target of the request, so a host that prints + one revision at several resolutions validates at each (P5 or P6b). +- **Validation reads no record.** A bound value is laid out only when rendering; `FIT_NOT_PROVEN` is raised for + a bound element without `maxLength` in both operations. Legibility is judged at the stated size when a bound + element is validated and at the size chosen when it is rendered. +- **Bounds.** A size from 1 pt to 1000 pt, `shrinkTo` from 1 pt up to the size, `lineHeight` from 0.5 to 5 with + three decimals, 64 lines, 1024 characters. Anything inside `fit` that is wrong is reported at `fit`, since a + pointer is made only of declared property names of an element. +- **The members of `fit` are not schema properties.** The published schema states `maxLines`, `shrinkTo` and + `overflow` in the description of `fit` and does not declare them under `properties`. The host admits in a + pointer exactly the names the schema declares (`SceneFacts.VOCABULARY`, held to the schema by a test in the + bridge), and the renderer admits the same set (`ElementFactory.VOCABULARY`); declaring three names that no + pointer carries would have widened the host's list for nothing. If a pointer should one day say + `/elements/1/fit/maxLines`, the three names are added to the schema and to both lists in one change. +- **Rotation and reverse.** A text turned a quarter is fitted along the box's height, and `align` and `valign` + follow the direction of reading. Reverse text fills its own box black and clears the letters; it counts twice + against the painted-area cap. +- **`RESERVED_FONT_NAME`** is raised by a text element (with the count of supplied assets under `qqq-`), not for + the scene as a whole: a scene with no text has no face to shadow. +- **Determinism (section 10.2).** No tolerance was needed. The goldens are generated in the CI image (Linux, + Temurin 21.0.9) and are the same bytes on Windows (Temurin 21.0.12), at 203, 300 and 600 dpi, for the glyph + bitmaps (up to 100 dots to the em) and for the outline path above that; they are compared exactly on both. + One case depends on more than the scene: a line whose strip is over 8 million dots (type of several hundred + points) is drawn in bands of rows, and the rasteriser may shade a few edge dots at a band's border differently + than in one piece (fewer than 1 in 10 000 ink dots). Where the bands fall is a function of the line's box, so + the result is still the same on every machine. + ## 4. Barcodes ### 4.1 Symbologies diff --git a/docs/security/fuzzing.md b/docs/security/fuzzing.md index 557d18b..6603cfd 100644 --- a/docs/security/fuzzing.md +++ b/docs/security/fuzzing.md @@ -28,16 +28,25 @@ crashes: - **Version 2 scene parser.** The target is the worker's own routing, so a mutated source may also become a version 1 scene, which is then held to the version 1 property. An accepted version 2 scene, read by the second parser, has only the declared top-level properties, a physical design size, at most 1000 elements - with unique ids of the fixed pattern, only `box` and `group` elements with only their declared properties - (the other types are refused until their packages exist), groups at most four deep, every length a number - and a unit, and overrides only for the three resolutions and for declared ids. About one version 2 input in + with unique ids of the fixed pattern, only `box`, `group` and `text` elements with only their declared + properties (barcodes and images are refused until their packages exist), groups at most four deep, every + length a number and a unit, and overrides only for the three resolutions and for declared ids. A `text` + element is read as it stands at each resolution (the defaults, then the element, then the overrides for that + resolution): it names a bundled face, has a physical size from 1 to 1000 pt, exactly one of a literal value + and a pointer into the record, and only fit, length, threshold, rotation, reverse and line height settings of + the documented kinds and ranges. The corpus holds the three text cases (`text-faces`, `text-fit`, + `text-turned`) beside the layout cases, and the spliced tokens include the text properties, a combining + mark, a tab, half of a surrogate pair, a size of `1000pt` and the number `1e400`. About one version 2 input in four, chosen by its bytes so that a replay does the same, is rendered instead of validated: the label is read back into a page, must be only the header, uncompressed graphic fields and the end of a label, must put no ink outside the printable area, and validation of the same input must give the same answer (accepted with the same - findings, or refused with the same diagnostic). A refusal is the scene's own `Refusal`, the exception that + findings, or refused with the same diagnostic). The one difference allowed is `VALUE_MISSING`: a text bound to + the record has no value in the campaign's empty record, and validation reads no record. A refusal is the scene's own `Refusal`, the exception that carries a diagnostic, and nothing else: the routing turns unreadable JSON and an unknown schema into one. A plain `IllegalArgumentException` is a finding, because the package raises those for its own broken invariants - (`CANVAS_BOUNDS`, `CANVAS_LIMIT`, `LENGTH_NOT_ABSOLUTE`, `LENGTH_NOT_PHYSICAL`), which no scene may reach. The + (`CANVAS_BOUNDS`, `CANVAS_LIMIT`, `LENGTH_NOT_ABSOLUTE`, `LENGTH_NOT_PHYSICAL`), which no scene may reach; so is + the text package's `IllegalStateException` for ink outside a measured line (`TEXT_INK_OUTSIDE_MEASURE`), and + any arithmetic or number-format failure. The one exception is a source the routing sends to the frozen version 1 parser, whose own refusal is a plain `IllegalArgumentException`; such sources are validated only. The campaign also asserts that it rendered labels. - **Printer gate.** An accepted input contains only the commands the renderer may emit and no tilde command. diff --git a/renderer/README.md b/renderer/README.md index 29a159e..9d5b634 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -124,7 +124,12 @@ A source with schema `qqq-zpl-scene/2` is a layout in physical units that render - **Coordinates** start at the top left of the printable area, the stock less its margins. In dots the printable area is `floor((width - left - right) x dpi)` wide and `floor((height - top - bottom) x dpi)` high, which is how a box size is rounded, and it starts at `ceil(left x dpi)`, `ceil(top x dpi)`, moved back by one dot where it would otherwise pass the page edge. So a box of exactly the printable width and height fits at 203, 300 and 600 dpi alike. No ink is ever a whole dot inside a margin; the right and bottom edges may pass theirs by a fraction of a dot (less than 0.125 mm at 203 dpi). `design` states the stock the layout was drawn for; the request's stock must match it within 0.5 mm on each side (`STOCK_MISMATCH`). - **Every element** has a unique `id` (`[A-Za-z][A-Za-z0-9_-]{0,31}`), a `type`, an `anchor` (one of nine points, default `top-left`: the same point of the box is placed on that point of its container), `x` and `y` (distances inward from the anchored edge; on a centred axis a shift that may be negative), `width` and `height` (omitted: the rest of the container), and `align` and `valign` (where content sits in the box). - **`box`** has `thickness` and optional `fill`; a line is a box whose width or height is its thickness. **`group`** has `children`, placed relative to its box; groups nest four deep. A scene holds at most 1000 elements, and its elements may paint at most sixteen times its printable area in all, an overlap counted each time: a filled box counts its area, an outline its four bars, a group nothing. The element that would pass that is refused as `SCENE_INVALID` at its pointer, with its box and `measured.paintedPercent` against `limit.paintedPercent` of 1600. A real label paints less than twice its area; the limit holds the worst scene to sixteen fills of the canvas where 1000 were possible. -- **`text`, `barcode` and `image`** are parsed and placed by renderer `0.2.0` and then refused as `RENDERER_TOO_OLD`, with the box they would have had, until their packages are in the renderer. +- **`text`** draws one value in a face bundled with the renderer: `qqq-sans`, `qqq-sans-bold` (IBM Plex Sans), `qqq-condensed-bold` (IBM Plex Sans Condensed) and `qqq-mono`, `qqq-mono-bold` (JetBrains Mono). There is no printer font in version 2 and no installed font is used; any other `font` is `FONT_UNKNOWN`, and a request that supplies an asset whose name begins `qqq-` is refused as `RESERVED_FONT_NAME`. `font` and `size` may come from the scene's `defaults`. The value is `value` or, read from the record when rendering, `valuePath`; at most 1024 characters, each of which the face must draw as one glyph from left to right (no control or format characters, combining marks, shaping or right-to-left scripts: `FONT_MISSING_GLYPH`, with the count). + - **Size and measurement.** `size` is the em as a physical length from `1pt` to `1000pt`, not rounded to dots. A text is measured before it is drawn, by integer arithmetic on the face's own numbers, so the measurement is the same on every machine. A line's box is its pen advance widened to hold the ink of every character in it, plus two dots on each inked side for the rasteriser. The block of lines is placed in the element's box by `align` and `valign`, and each line in the block by `align`. `lineHeight` is the distance between baselines as a multiple of the size (default: the face's own). `rotation` turns the text clockwise in a box given as it appears on the label; `reverse` prints white letters on the box filled black. + - **Fit.** In this order: lay the value out at `size` within `fit.maxLines` (default 1); if it does not fit, take the largest size, in steps of 0.25 pt down to `fit.shrinkTo`, at which it does (`TEXT_SHRUNK`); if none does, apply `fit.overflow`. `shrinkTo` defaults to 70% of the size and not below 5 pt. `overflow` is `refuse` (the default: `TEXT_DOES_NOT_FIT`, with the measured width, height, lines and size against the box) or `truncate`, which cuts at a character, ends with an ellipsis and warns `TEXT_TRUNCATED`. At each size a line is broken between words while that fits and at any character when it does not, so a value with no space wraps and a larger size is preferred to whole words (`TEXT_WRAPPED`). + - **Proving the fit.** `maxLength` is the longest value in characters. When a scene is validated, that many of the face's widest character must fit, each taken to reach as far above, below and beside its advance as the furthest-reaching character of the face; otherwise the scene is refused as `TEXT_DOES_NOT_FIT`. A scene that passes cannot be refused at that render target because a value of up to that length does not fit, whichever of the face's characters it holds. The proof is therefore stricter than a typical value needs, and a box that is exactly `lines x lineHeight` high is not proven: leave room for an accent above a capital. When printing, a longer value is `VALUE_TOO_LONG` before any layout. A bound element without `maxLength` warns `FIT_NOT_PROVEN`. Validation reads no record. The proof is for the render target of the request; validate at each resolution the document prints at. + - **Legibility.** Glyphs are drawn antialiased and a dot is ink when its grey is darker than `threshold` (1 to 254, default 128), so a higher value prints heavier. `TEXT_SMALL_FOR_DPI` warns when the capitals are under 12 dots high at the render target (about 6 pt at 203 dpi), `TEXT_LIGHT_FACE` when a regular weight is used with capitals under 20 dots (about 10 pt at 203 dpi). An override is how a scene answers for one resolution: a bold face or a higher `threshold` at 203 dpi. +- **`barcode` and `image`** are parsed and placed by renderer `0.2.0` and then refused as `RENDERER_TOO_OLD`, with the box they would have had, until their packages are in the renderer. - **`overrides`** replace properties of declared elements at the listed resolutions and are the only place a scene may depend on resolution. They are checked for all three resolutions whatever the request's target. **`samples`** are accepted and ignored by rendering. - **Output.** The whole label is composed on one 1-bit canvas and emitted as uncompressed `^GFA` fields: rows are cut into bands wherever eight or more blank rows separate ink, each band is trimmed to its inked columns, and a band is continued in a further field at 99,999 bytes. Only `^XA`, `^PW`, `^LL`, `^LH`, `^CI28`, `^FO`, `^GFA`, `^FS` and `^XZ` are emitted. - **Diagnostics.** A refusal is one diagnostic: `code`, `severity`, the `element` id, the element's `box` in dots from the top left of the printable area, and `measured` and `limit` as named integers. `SCENE_INVALID` also carries `pointer`, the JSON pointer of the offending place. A diagnostic names only an id the scene declares and points only through schema property names, array indexes and declared ids, so no record value, sample or unknown property name can leave the worker in one. A stock the printer language cannot address stays the opaque `RENDER_FAILED`, as for version 1. diff --git a/renderer/schema/zpl-scene-2.schema.json b/renderer/schema/zpl-scene-2.schema.json index 502055f..9d4d272 100644 --- a/renderer/schema/zpl-scene-2.schema.json +++ b/renderer/schema/zpl-scene-2.schema.json @@ -15,7 +15,7 @@ "properties": {"width": {"$ref": "#/$defs/physical"}, "height": {"$ref": "#/$defs/physical"}} }, "defaults": { - "description": "Defaults for text elements.", + "description": "The face and size of a text element that states none.", "type": "object", "additionalProperties": false, "properties": {"font": {"type": "string", "pattern": "^[A-Za-z0-9_-][A-Za-z0-9_.-]{0,99}$"}, "size": {"$ref": "#/$defs/physical"}} @@ -98,9 +98,25 @@ }, { "$ref": "#/$defs/placement", - "description": "Text. Parsed and placed by renderer 0.2.0 and refused as RENDERER_TOO_OLD until the text package; the values of these properties are not yet read.", + "description": "Text in a face bundled with the renderer, measured before it is drawn and placed in its box by `align` and `valign`. `font` and `size` may come from `defaults`. The renderer is the authority: it also enforces a size from 1pt to 1000pt, a `shrinkTo` from 1pt up to the size, at most three decimals in `lineHeight`, at most 1024 characters, only characters the face draws as one glyph each from left to right (FONT_MISSING_GLYPH), and no supplied asset whose name begins `qqq-` (RESERVED_FONT_NAME).", "unevaluatedProperties": false, - "properties": {"type": {"const": "text"}, "value": {}, "valuePath": {}, "font": {}, "size": {}, "lineHeight": {}, "fit": {}, "maxLength": {}, "threshold": {}, "reverse": {}, "rotation": {"enum": [0, 90, 180, 270]}} + "oneOf": [{"required": ["value"]}, {"required": ["valuePath"]}], + "properties": { + "type": {"const": "text"}, + "value": {"type": "string", "maxLength": 1024, "description": "The text itself."}, + "valuePath": {"type": "string", "pattern": "^/", "maxLength": 256, "description": "A JSON pointer into the record. Text is printed as it is, a number or true/false as JSON writes it; anything else is VALUE_MISSING. No record is read when a scene is validated."}, + "font": {"enum": ["qqq-sans", "qqq-sans-bold", "qqq-condensed-bold", "qqq-mono", "qqq-mono-bold"], "description": "A bundled face: IBM Plex Sans Regular and Bold, IBM Plex Sans Condensed Bold, JetBrains Mono Regular and Bold. Any other name is FONT_UNKNOWN."}, + "size": {"$ref": "#/$defs/physical", "description": "The em size. Type scales continuously: the size is not rounded to dots."}, + "lineHeight": {"type": "number", "minimum": 0.5, "maximum": 5, "description": "The distance between baselines as a multiple of the size. Default: the face's own ascent, descent and line gap."}, + "fit": { + "type": "object", + "description": "What happens when the value does not fit the box. In order: lay out at `size` within `maxLines`; else the largest size, in steps of 0.25pt down to `shrinkTo`, that fits; else `overflow`. At each size a line is broken between words while that fits and at any character when it does not. Its members, which the renderer enforces and refuses any other: `maxLines`, a whole number from 1 to 64, default 1; `shrinkTo`, a physical length from 1pt up to `size`, the smallest size the text may be reduced to, default 70% of `size` and not below 5pt (or `size` itself when that is smaller); `overflow`, `refuse` (the default, TEXT_DOES_NOT_FIT) or `truncate` (cut at a character, end with an ellipsis, warn TEXT_TRUNCATED). The members are described here and not declared as schema properties because a diagnostic points at `fit` itself: the names this schema declares are exactly the names a diagnostic's pointer may hold." + }, + "maxLength": {"type": "integer", "minimum": 1, "maximum": 1024, "description": "The longest value, in characters. Validation proves that this many of the face's widest character fit, so a length refusal happens when the scene is published; a longer value is VALUE_TOO_LONG when printing. Without it a bound element warns FIT_NOT_PROVEN."}, + "threshold": {"type": "integer", "minimum": 1, "maximum": 254, "default": 128, "description": "Glyphs are drawn antialiased; a dot is ink when its grey is darker than this. Higher prints heavier."}, + "reverse": {"type": "boolean", "default": false, "description": "White letters on the element's box filled black."}, + "rotation": {"enum": [0, 90, 180, 270], "description": "Clockwise. The box is given as it appears on the label; a text turned a quarter is fitted along the box's height."} + } }, { "$ref": "#/$defs/placement", diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java index 04cc702..3bbdf44 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java @@ -209,7 +209,18 @@ public final class ElementSource ***************************************************************************/ public Refusal invalid(String name) { - return (diagnostics.refuse("SCENE_INVALID", id, pointer(name), null, null, null)); + return (refuse("SCENE_INVALID", name)); + } + + + + /*************************************************************************** + ** The refusal, by its own code, for a property that is well formed but names + ** something this renderer does not have, such as a font. + ***************************************************************************/ + public Refusal refuse(String code, String name) + { + return (diagnostics.refuse(code, id, pointer(name), null, null, null)); } @@ -230,8 +241,26 @@ public final class ElementSource /*************************************************************************** - ** Where a property is stated: in the override that set it, else in the - ** element. + ** Give the element the scene's `defaults` for the properties its type reads + ** and it does not state. A default is reported where the scene states it. + ***************************************************************************/ + void inherit(JsonNode defaults, Set properties) + { + for(Map.Entry property : defaults.properties()) + { + if(properties.contains(property.getKey()) && !values.containsKey(property.getKey())) + { + values.put(property.getKey(), property.getValue()); + pointers.put(property.getKey(), "/defaults/" + property.getKey()); + } + } + } + + + + /*************************************************************************** + ** Where a property is stated: in the override that set it, in the scene's + ** defaults, else in the element. ***************************************************************************/ private String pointer(String name) { diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/SceneParser.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/SceneParser.java index 1429f52..94ee6c6 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/SceneParser.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/SceneParser.java @@ -278,6 +278,7 @@ final class SceneParser { ElementFactory factory = ElementFactory.FACTORIES.get(source.type()); source.only(factory.properties()); + source.inherit(root.path("defaults"), factory.properties()); built.add(factory.create(source)); } } diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/Face.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/Face.java new file mode 100644 index 0000000..ca0c9de --- /dev/null +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/Face.java @@ -0,0 +1,345 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + + +/******************************************************************************* + ** The faces bundled with the renderer, by the name a scene writes. Each is an + ** unmodified TrueType file under the SIL Open Font License 1.1, shipped in the + ** jar beside its licence, provenance and hash (`/fonts`). No installed font is + ** ever used and there is no fallback between faces. + ** + ** Every number here is in thousandths of the em, read once from the face at a + ** reference size of 1000, where the bundled faces (1000 units to the em) give + ** whole numbers. Layout multiplies those integers by the size and never asks + ** the font for a measurement at the size it draws, so a measurement is the + ** same on every machine. + ** + ** The four numbers after the widest character are the most any character of + ** the face reaches past its own advance on the left and on the right, above + ** the baseline and below it. They bound every character, so a value that was + ** never seen can be proven to fit; a test recomputes them from the font file. + *******************************************************************************/ +public final class Face +{ + public static final Face SANS = new Face("qqq-sans", "ibm-plex-sans/IBMPlexSans-Regular.ttf", false, 0x2030, 203, 203, 1119, 245); + public static final Face SANS_BOLD = new Face("qqq-sans-bold", "ibm-plex-sans/IBMPlexSans-Bold.ttf", true, 0x2030, 245, 245, 1150, 275); + public static final Face CONDENSED_BOLD = new Face("qqq-condensed-bold", "ibm-plex-sans-condensed/IBMPlexSansCondensed-Bold.ttf", true, 0x2030, 241, 241, 1150, 275); + public static final Face MONO = new Face("qqq-mono", "jetbrains-mono/JetBrainsMono-Regular.ttf", false, 0x21, 165, 165, 1120, 400); + public static final Face MONO_BOLD = new Face("qqq-mono-bold", "jetbrains-mono/JetBrainsMono-Bold.ttf", true, 0x21, 165, 165, 1120, 400); + + static final FontRenderContext CONTEXT = new FontRenderContext(null, true, true); + static final int REFERENCE = 1000; + + private static final List ALL = List.of(SANS, SANS_BOLD, CONDENSED_BOLD, MONO, MONO_BOLD); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // characters that cannot be drawn one glyph each from left to right: controls and formats // + // (which would print nothing), marks (which need placing on the letter before) and the like // + ///////////////////////////////////////////////////////////////////////////////////////////////// + private static final Set UNDRAWN = Set.of((int) Character.CONTROL, (int) Character.FORMAT, (int) Character.SURROGATE, (int) Character.PRIVATE_USE, (int) Character.UNASSIGNED, + (int) Character.LINE_SEPARATOR, (int) Character.PARAGRAPH_SEPARATOR, (int) Character.NON_SPACING_MARK, (int) Character.ENCLOSING_MARK, (int) Character.COMBINING_SPACING_MARK); + + private final String scene; + private final String file; + private final boolean bold; + private final int widest; + private final int left; + private final int right; + private final int top; + private final int bottom; + private final Map glyphs = new ConcurrentHashMap<>(); + private Font font; + + + + /*************************************************************************** + ** One character of a face: how far the pen moves, and the box its outline + ** fills, from the pen (`left`, `right`) and from the baseline (`top` above, + ** `bottom` below), rounded outward. A space has no ink; only U+0020 is a + ** `space`, the one place a line may be broken between words. + ***************************************************************************/ + public record Glyph(int advance, int left, int right, int top, int bottom, boolean ink, boolean space) + { + } + + + + /*************************************************************************** + ** A face, where its file is, and the bounds a test holds it to. + ***************************************************************************/ + private Face(String scene, String file, boolean bold, int widest, int left, int right, int top, int bottom) + { + this.scene = scene; + this.file = file; + this.bold = bold; + this.widest = widest; + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + } + + + + /*************************************************************************** + ** The bundled set: a proportional sans in regular and bold, a condensed bold + ** for long values on narrow labels, and a monospace in regular and bold. + ***************************************************************************/ + public static List all() + { + return (ALL); + } + + + + /*************************************************************************** + ** The face a scene names, or null. + ***************************************************************************/ + public static Face of(String scene) + { + for(Face face : ALL) + { + if(face.scene.equals(scene)) + { + return (face); + } + } + return (null); + } + + + + /*************************************************************************** + ** The name a scene writes. + ***************************************************************************/ + public String scene() + { + return (scene); + } + + + + /*************************************************************************** + ** The font file, under `/fonts` in the jar. + ***************************************************************************/ + public String file() + { + return (file); + } + + + + /*************************************************************************** + ** Whether the strokes are bold. A regular face prints light when small. + ***************************************************************************/ + public boolean bold() + { + return (bold); + } + + + + /*************************************************************************** + ** The character with the greatest advance, the lowest when several share it. + ***************************************************************************/ + public int widest() + { + return (widest); + } + + + + /*************************************************************************** + ** A character no real one exceeds in any direction: the greatest advance and + ** the greatest reach on each side. A line of these is at least as wide and + ** as tall as a line of the same number of any characters of the face. + ***************************************************************************/ + public Glyph worst() + { + int advance = glyph(widest).advance(); + return (new Glyph(advance, -left, advance + right, top, bottom, true, false)); + } + + + + /*************************************************************************** + ** The face at a size in dots, for drawing only. + ***************************************************************************/ + Font font(float size) + { + return (reference().deriveFont(size)); + } + + + + /*************************************************************************** + ** Height above the baseline that a line reserves. + ***************************************************************************/ + public int ascent() + { + return (Math.round(metrics().getAscent())); + } + + + + /*************************************************************************** + ** Depth below the baseline that a line reserves. + ***************************************************************************/ + public int descent() + { + return (Math.round(metrics().getDescent())); + } + + + + /*************************************************************************** + ** Extra space the face asks for between lines. + ***************************************************************************/ + public int leading() + { + return (Math.round(metrics().getLeading())); + } + + + + /*************************************************************************** + ** The height of a capital letter, which is what legibility is judged by. + ***************************************************************************/ + public int capHeight() + { + return (glyph('H').top()); + } + + + + /*************************************************************************** + ** Whether the face can draw a character as one glyph, left to right. + ***************************************************************************/ + public boolean draws(int codePoint) + { + return (codePoint <= Character.MAX_VALUE && !UNDRAWN.contains(Character.getType(codePoint)) && reference().canDisplay(codePoint) + && !Font.textRequiresLayout(new char[] {(char) codePoint}, 0, 1)); + } + + + + /*************************************************************************** + ** How many characters of a text the face cannot draw. + ***************************************************************************/ + public int missing(String text) + { + return (Math.toIntExact(text.codePoints().filter(codePoint -> !draws(codePoint)).count())); + } + + + + /*************************************************************************** + ** The measurements of one character the face draws. + ***************************************************************************/ + public Glyph glyph(int codePoint) + { + return (glyphs.computeIfAbsent(codePoint, this::measure)); + } + + + + /*************************************************************************** + ** The measurements of a text the face draws, one for each character. + ***************************************************************************/ + public Glyph[] glyphs(String text) + { + return (text.codePoints().mapToObj(this::glyph).toArray(Glyph[]::new)); + } + + + + /*************************************************************************** + ** Read one character from the face at the reference size. + ***************************************************************************/ + private Glyph measure(int codePoint) + { + GlyphVector vector = reference().createGlyphVector(CONTEXT, new char[] {(char) codePoint}); + int advance = Math.round(vector.getGlyphMetrics(0).getAdvanceX()); + Rectangle2D bounds = vector.getGlyphOutline(0).getBounds2D(); + if(bounds.isEmpty()) + { + return (new Glyph(advance, 0, 0, 0, 0, false, codePoint == ' ')); + } + return (new Glyph(advance, (int) Math.floor(bounds.getMinX()), (int) Math.ceil(bounds.getMaxX()), (int) Math.ceil(-bounds.getMinY()), (int) Math.ceil(bounds.getMaxY()), true, false)); + } + + + + /*************************************************************************** + ** The line metrics of the face at the reference size. + ***************************************************************************/ + private LineMetrics metrics() + { + return (reference().getLineMetrics("H", CONTEXT)); + } + + + + /*************************************************************************** + ** The face at the reference size, read from the jar the first time. + ***************************************************************************/ + private synchronized Font reference() + { + if(font == null) + { + font = load("/fonts/" + file); + } + return (font); + } + + + + /*************************************************************************** + ** Read a TrueType file from the jar. A file that is not a font is a broken + ** build, not a mistake in a scene, so it is an illegal state. + ***************************************************************************/ + static Font load(String resource) + { + try(InputStream stream = Face.class.getResourceAsStream(resource)) + { + return (Font.createFont(Font.TRUETYPE_FONT, stream).deriveFont((float) REFERENCE)); + } + catch(IOException | FontFormatException broken) + { + throw new IllegalStateException("BUNDLED_FONT_UNREADABLE", broken); + } + } +} diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java new file mode 100644 index 0000000..83278d2 --- /dev/null +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java @@ -0,0 +1,409 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.kingsrook.qbits.renderer.RenderInput; +import com.kingsrook.qbits.renderer.scene2.Canvas; +import com.kingsrook.qbits.renderer.scene2.Diagnostics; +import com.kingsrook.qbits.renderer.scene2.ElementSource; +import com.kingsrook.qbits.renderer.scene2.Frame; +import com.kingsrook.qbits.renderer.scene2.Layout; +import com.kingsrook.qbits.renderer.scene2.Length; +import com.kingsrook.qbits.renderer.scene2.Placement; +import com.kingsrook.qbits.renderer.scene2.SceneElement; + + +/******************************************************************************* + ** A `text` element: one value in one bundled face, measured before it is + ** drawn, placed in its box by `align` and `valign`, and fitted by the rule the + ** element states (`TextFit`). The value is a literal (`value`) or is read from + ** the record by a JSON pointer (`valuePath`). + ** + ** Every refusal names the element and carries numbers only: a width, a line + ** count, a size, a count of characters. The value itself never enters a + ** diagnostic or an exception. + ** + ** A bound value is not known when a scene is validated, so validation reads no + ** record. With `maxLength` it proves instead that the longest value fits: that + ** many of the face's widest character, each taken to reach as far in every + ** direction as the furthest-reaching character of the face. Without + ** `maxLength` it warns `FIT_NOT_PROVEN`. When rendering, a value longer than + ** `maxLength` is refused before any layout. + *******************************************************************************/ +final class TextElement implements SceneElement +{ + static final int MAXIMUM_CHARACTERS = 1024; + static final int MAXIMUM_LINES = 64; + static final int MINIMUM_MILLIPOINTS = 1000; + static final int MAXIMUM_MILLIPOINTS = 1_000_000; + static final int DEFAULT_FLOOR_PERCENT = 70; + static final int DEFAULT_FLOOR_MILLIPOINTS = 5000; + static final int DEFAULT_THRESHOLD = 128; + ///////////////////////////////////////////////////////////////////////////////////////////////// + // capital heights in dots below which thermal print is hard to read: any face under 12 (about // + // 6 pt at 203 dpi), a regular weight under 20 (about 10 pt at 203 dpi). Starting values, to // + // be confirmed on the printed specimen // + ///////////////////////////////////////////////////////////////////////////////////////////////// + static final int SMALL_CAPITAL_DOTS = 12; + static final int LIGHT_CAPITAL_DOTS = 20; + + private static final Set FIT = Set.of("maxLines", "shrinkTo", "overflow"); + + private final String id; + private final Placement placement; + private final int rotation; + private final boolean reverse; + private final Face face; + private final int size; + private final int floor; + private final Integer lineHeight; + private final int maxLines; + private final boolean truncate; + private final Integer maxLength; + private final int threshold; + private final String value; + private final String path; + + + + /*************************************************************************** + ** Read the element. A property that is not what the schema says is + ** `SCENE_INVALID` at that property; a face this renderer does not bundle is + ** `FONT_UNKNOWN`. + ***************************************************************************/ + TextElement(ElementSource source) + { + id = source.id(); + placement = source.placement(); + rotation = source.rotation(); + reverse = source.flag("reverse", false); + JsonNode font = source.value("font"); + if(font == null || !font.isTextual()) + { + throw source.invalid("font"); + } + face = Face.of(font.textValue()); + if(face == null) + { + throw source.refuse("FONT_UNKNOWN", "font"); + } + Length stated = source.length("size", null, ElementSource.PHYSICAL); + size = stated == null ? 0 : milliPoints(stated); + if(size < MINIMUM_MILLIPOINTS || size > MAXIMUM_MILLIPOINTS) + { + throw source.invalid("size"); + } + lineHeight = lineHeight(source); + threshold = integer(source, "threshold", source.value("threshold"), 1, 254, DEFAULT_THRESHOLD); + maxLength = source.value("maxLength") == null ? null : Integer.valueOf(integer(source, "maxLength", source.value("maxLength"), 1, MAXIMUM_CHARACTERS, 0)); + JsonNode fit = source.value("fit") == null ? JsonNodeFactory.instance.objectNode() : source.value("fit"); + if(!fit.isObject() || fit.properties().stream().anyMatch(property -> !FIT.contains(property.getKey()))) + { + throw source.invalid("fit"); + } + maxLines = integer(source, "fit", fit.get("maxLines"), 1, MAXIMUM_LINES, 1); + floor = floor(source, fit.get("shrinkTo")); + String overflow = fit.has("overflow") ? fit.get("overflow").textValue() : "refuse"; + if(!"refuse".equals(overflow) && !"truncate".equals(overflow)) + { + throw source.invalid("fit"); + } + truncate = "truncate".equals(overflow); + JsonNode literal = source.value("value"); + JsonNode pointer = source.value("valuePath"); + if((literal == null) == (pointer == null)) + { + throw source.invalid("value"); + } + if(literal != null && (!literal.isTextual() || literal.textValue().codePointCount(0, literal.textValue().length()) > MAXIMUM_CHARACTERS)) + { + throw source.invalid("value"); + } + if(pointer != null && (!pointer.isTextual() || pointer.textValue().length() > 256 || !pointer.textValue().startsWith("/"))) + { + throw source.invalid("valuePath"); + } + value = literal == null ? null : literal.textValue(); + path = pointer == null ? null : pointer.textValue(); + } + + + + /*************************************************************************** + ** A type size in thousandths of a point. A point is a 72nd of an inch and an + ** inch is 25400 micrometres, so a micrometre is 360/127 of a millipoint. + ***************************************************************************/ + private static int milliPoints(Length length) + { + long thousandths = length.thousandths(); + return (Math.toIntExact(switch(length.unit()) + { + case IN -> thousandths * 72; + case MM -> Math.floorDiv(thousandths * 360 + 63, 127); + default -> thousandths; + })); + } + + + + /*************************************************************************** + ** A whole number in a range, or the fallback when the scene states none. + ***************************************************************************/ + private static int integer(ElementSource source, String name, JsonNode stated, int minimum, int maximum, int fallback) + { + if(stated == null) + { + return (fallback); + } + if(!stated.isIntegralNumber() || !stated.canConvertToInt() || stated.intValue() < minimum || stated.intValue() > maximum) + { + throw source.invalid(name); + } + return (stated.intValue()); + } + + + + /*************************************************************************** + ** The distance between baselines as a multiple of the size, in thousandths: + ** a number from 0.5 to 5 with at most three decimals. Null is the face's own. + ** A number too large to be a number at all (`1e400`) is refused like any + ** other, not left to fail as arithmetic. + ***************************************************************************/ + private static Integer lineHeight(ElementSource source) + { + JsonNode stated = source.value("lineHeight"); + if(stated == null) + { + return (null); + } + BigDecimal thousandths = stated.isNumber() && Double.isFinite(stated.doubleValue()) ? stated.decimalValue().movePointRight(3) : BigDecimal.ZERO; + if(thousandths.stripTrailingZeros().scale() > 0 || thousandths.compareTo(BigDecimal.valueOf(500)) < 0 || thousandths.compareTo(BigDecimal.valueOf(5000)) > 0) + { + throw source.invalid("lineHeight"); + } + return (thousandths.intValueExact()); + } + + + + /*************************************************************************** + ** The smallest size the text may be reduced to. Stated, it is a physical + ** length from one point up to the size. Otherwise it is 70% of the size and + ** not below 5 pt, or the size itself when that is smaller still. + ***************************************************************************/ + private int floor(ElementSource source, JsonNode stated) + { + if(stated == null) + { + return (Math.min(size, Math.max(size * DEFAULT_FLOOR_PERCENT / 100, DEFAULT_FLOOR_MILLIPOINTS))); + } + try + { + Length length = Length.parse(stated.textValue()); + if(length.physical() && milliPoints(length) >= MINIMUM_MILLIPOINTS && milliPoints(length) <= size) + { + return (milliPoints(length)); + } + } + catch(IllegalArgumentException expected) + { + // Refused below, at the property; the cause holds nothing more. + } + throw source.invalid("fit"); + } + + + + /*************************************************************************** + ** The id the scene declares for the text. + ***************************************************************************/ + @Override + public String id() + { + return (id); + } + + + + /*************************************************************************** + ** The element's box, by the standing rules. + ***************************************************************************/ + @Override + public Frame place(Layout layout) + { + return (layout.place(placement)); + } + + + + /*************************************************************************** + ** Everything that can refuse the text, with no ink: run when a scene is + ** validated and again before it is painted. + ***************************************************************************/ + @Override + public void check(Frame frame, RenderInput input, Diagnostics diagnostics) + { + compose(frame, input, diagnostics); + } + + + + /*************************************************************************** + ** Reverse text paints its box and then clears its letters, so it is counted + ** twice against what one scene may paint. + ***************************************************************************/ + @Override + public long paintedDots(Frame frame, int dpi) + { + return ((reverse ? 2L : 1L) * frame.width() * frame.height()); + } + + + + /*************************************************************************** + ** Draw the fitted text. Reverse text is white letters on its own box filled + ** black. + ***************************************************************************/ + @Override + public void paint(Canvas canvas, Frame frame, RenderInput input, Diagnostics diagnostics) + { + TextRaster.Drawing drawing = compose(frame, input, diagnostics); + if(reverse) + { + canvas.fill(frame, true); + } + TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS); + } + + + + /*************************************************************************** + ** Resolve the value, hold it to its length and to the face, and fit it. The + ** answer is what to draw, or null when a bound value is only being + ** validated. + ***************************************************************************/ + private TextRaster.Drawing compose(Frame frame, RenderInput input, Diagnostics diagnostics) + { + int reserved = input.reservedAssetNames().size(); + if(reserved > 0) + { + throw diagnostics.refuse("RESERVED_FONT_NAME", id, null, frame, Map.of("reservedAssets", reserved), Map.of("reservedAssets", 0)); + } + int dpi = input.targetDpi == null ? input.stock.dpi() : input.targetDpi; + boolean upright = rotation % 180 == 0; + TextFit.Request request = new TextFit.Request(face, upright ? frame.width() : frame.height(), upright ? frame.height() : frame.width(), dpi, size, floor, lineHeight, maxLines, truncate); + if(path != null && maxLength == null) + { + diagnostics.warn("FIT_NOT_PROVEN", id, null, frame, null, null); + } + String text = value; + if(path != null && "VALIDATE".equals(input.operation)) + { + if(maxLength != null) + { + Face.Glyph[] worst = new Face.Glyph[maxLength]; + Arrays.fill(worst, face.worst()); + fitted(request, worst, frame, diagnostics); + } + legibility(size, dpi, frame, diagnostics); + return (null); + } + if(path != null) + { + JsonNode bound = input.context.at(path); + if(!bound.isTextual() && !bound.isNumber() && !bound.isBoolean()) + { + throw diagnostics.refuse("VALUE_MISSING", id, null, frame, null, null); + } + text = bound.asText(); + } + int characters = text.codePointCount(0, text.length()); + int longest = maxLength == null ? MAXIMUM_CHARACTERS : maxLength; + if(characters > longest) + { + throw diagnostics.refuse("VALUE_TOO_LONG", id, null, frame, Map.of("characters", characters), Map.of("characters", longest)); + } + int missing = face.missing(text); + if(missing > 0) + { + throw diagnostics.refuse("FONT_MISSING_GLYPH", id, null, frame, Map.of("missingGlyphs", missing, "characters", characters), Map.of("missingGlyphs", 0)); + } + TextFit.Block block = fitted(request, face.glyphs(text), frame, diagnostics); + if(block.milliPoints() < size) + { + diagnostics.inform("TEXT_SHRUNK", id, null, frame, Map.of("sizeCentipoints", block.milliPoints() / 10), Map.of("sizeCentipoints", size / 10, "floorCentipoints", floor / 10)); + } + if(block.lines().size() > 1) + { + diagnostics.inform("TEXT_WRAPPED", id, null, frame, Map.of("lines", block.lines().size()), Map.of("lines", maxLines)); + } + if(block.truncated()) + { + diagnostics.warn("TEXT_TRUNCATED", id, null, frame, Map.of("characters", block.characters(), "shownCharacters", block.shown(), "lines", block.lines().size()), Map.of("lines", maxLines)); + } + legibility(block.milliPoints(), dpi, frame, diagnostics); + return (new TextRaster.Drawing(face, text, block, placement.align(), placement.valign(), rotation, threshold, !reverse)); + } + + + + /*************************************************************************** + ** Fit, or refuse with what was measured at the floor size against the box. + ***************************************************************************/ + private TextFit.Block fitted(TextFit.Request request, Face.Glyph[] glyphs, Frame frame, Diagnostics diagnostics) + { + TextFit.Block block = TextFit.fit(request, glyphs, face.glyph(TextFit.MARK)); + if(!block.fits()) + { + throw diagnostics.refuse("TEXT_DOES_NOT_FIT", id, null, frame, + Map.of("widthDots", block.width(), "heightDots", block.height(), "lines", block.lines().size(), "sizeCentipoints", block.milliPoints() / 10, "characters", block.characters()), + Map.of("widthDots", request.width(), "heightDots", request.height(), "lines", maxLines)); + } + return (block); + } + + + + /*************************************************************************** + ** Warn when the type is small for the printer: any face whose capitals are + ** under 12 dots, and a regular weight whose capitals are under 20. + ***************************************************************************/ + private void legibility(int milliPoints, int dpi, Frame frame, Diagnostics diagnostics) + { + int capitals = new TextFit.Scale(milliPoints, dpi).floor(face.capHeight()); + if(capitals < SMALL_CAPITAL_DOTS) + { + diagnostics.warn("TEXT_SMALL_FOR_DPI", id, null, frame, Map.of("capHeightDots", capitals, "sizeCentipoints", milliPoints / 10), Map.of("capHeightDots", SMALL_CAPITAL_DOTS)); + } + if(!face.bold() && capitals < LIGHT_CAPITAL_DOTS) + { + diagnostics.warn("TEXT_LIGHT_FACE", id, null, frame, Map.of("capHeightDots", capitals, "sizeCentipoints", milliPoints / 10), Map.of("capHeightDots", LIGHT_CAPITAL_DOTS)); + } + } +} diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFactory.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFactory.java index 0a4b65f..e5a97ed 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFactory.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFactory.java @@ -25,22 +25,18 @@ import java.util.Set; import com.kingsrook.qbits.renderer.scene2.ElementFactory; import com.kingsrook.qbits.renderer.scene2.ElementSource; import com.kingsrook.qbits.renderer.scene2.SceneElement; -import com.kingsrook.qbits.renderer.scene2.UnavailableElement; /******************************************************************************* - ** Text: a TrueType face rasterised by the renderer, with size, fit and legibility - ** rules. - ** - ** This is the placeholder of the scene 2 core: a `text` element is parsed and - ** placed, then refused as `RENDERER_TOO_OLD`. The package that draws it - ** replaces this class and nothing else. + ** Text: a TrueType face bundled with the renderer, rasterised by it, with + ** size, fit and legibility rules. Version 2 has no printer font: a face the + ** renderer cannot measure can be neither fitted nor previewed truthfully. *******************************************************************************/ public final class TextFactory implements ElementFactory { /*************************************************************************** - ** The property names the design gives a `text` element. Their values are - ** not read yet. + ** The properties of a `text` element beyond the common ones. `font` and + ** `size` may come from the scene's `defaults`. ***************************************************************************/ @Override public Set properties() @@ -51,11 +47,11 @@ public final class TextFactory implements ElementFactory /*************************************************************************** - ** The element, placed and then refused by name. + ** Build one text element. ***************************************************************************/ @Override public SceneElement create(ElementSource source) { - return (new UnavailableElement(source)); + return (new TextElement(source)); } } diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java new file mode 100644 index 0000000..1f7b25f --- /dev/null +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java @@ -0,0 +1,405 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qbits.renderer.scene2.text.Face.Glyph; + + +/******************************************************************************* + ** Measurement and fit of one text in one box, in whole dots, by integer + ** arithmetic on the face's own numbers. Nothing is drawn here, and what is + ** drawn later is drawn from this answer: the pen position of every character + ** and the box of every line are decided once. + ** + ** The order is fixed. Lay the text out at the nominal size within the allowed + ** lines. If it does not fit, take the largest size, in steps of a quarter of + ** a point down to the floor, at which it does. If none does, the text is + ** refused, or, only when the element asked for it, cut at a character and + ** ended with an ellipsis at the floor size. + ** + ** At each size a line is first broken between words only. If that does not + ** fit, it is broken at any character. So a value with no spaces wraps, a + ** sentence keeps its words while it can, and a larger size is preferred to + ** whole words. Breaking at any character is also what makes a length provable: + ** a text of n characters needs no more lines than n of the face's widest. + ** + ** A line's box is its pen advance, widened to hold the ink of every character + ** in it (a `j` that starts left of the pen, an accent above the ascent) plus + ** `SLOP` dots on each inked side. The drawn glyph is the font's outline fitted + ** to the dot grid by the rasteriser, which moves an edge by less than two dots + ** from the outline scaled exactly; the slop is that allowance, and a test + ** holds every character of every bundled face to it. + *******************************************************************************/ +public final class TextFit +{ + public static final int SLOP = 2; + public static final int STEP_MILLIPOINTS = 250; + public static final int MARK = 0x2026; + + + + /*************************************************************************** + ** Utility class. + ***************************************************************************/ + private TextFit() + { + } + + + + /*************************************************************************** + ** What is asked: a face, a box in dots as the text reads (before any + ** rotation), the resolution, the nominal size and the floor in thousandths + ** of a point, the line pitch in thousandths of the size (null for the + ** face's own), the most lines, and whether a text that fits at no size is + ** cut short rather than refused. + ***************************************************************************/ + public record Request(Face face, int width, int height, int dpi, int nominal, int floor, Integer lineHeight, int maxLines, boolean truncate) + { + } + + + + /*************************************************************************** + ** One line: the characters `from` to `to` of the text, followed by the + ** ellipsis when `marked`. `left` (never positive) and `right` are the sides + ** of its box measured from the pen at the start of the line; `above` and + ** `below` are how far its ink reaches from the baseline. + ***************************************************************************/ + public record Line(int from, int to, boolean marked, int left, int right, int above, int below) + { + /************************************************************************ + ** The width of the line's box. + ************************************************************************/ + public int width() + { + return (right - left); + } + } + + + + /*************************************************************************** + ** The answer: the size chosen, the lines, the size of the block they make, + ** the baseline of the first line from the top of the block, the distance + ** between baselines, how many characters there were (trailing spaces never + ** print and are not counted), how many are shown, and whether it fits. When + ** it does not, the numbers are those of the text broken at any character at + ** the floor size, which is what a refusal reports. + ***************************************************************************/ + public record Block(int milliPoints, List lines, int width, int height, int baseline, int pitch, int characters, int shown, boolean fits) + { + /************************************************************************ + ** Whether the text was cut short. + ************************************************************************/ + public boolean truncated() + { + return (shown < characters); + } + } + + + + /*************************************************************************** + ** Dots from thousandths of the em at one size and resolution. A size of + ** `milliPoints` is `milliPoints * dpi / 72000` dots to the em, so a length + ** of `units` is `units * milliPoints * dpi / 72000000` dots, rounded as the + ** use says. The products stay far inside a long. + ***************************************************************************/ + public record Scale(int milliPoints, int dpi) + { + private static final long DIVISOR = 72_000_000L; + + + + /************************************************************************ + ** Rounded down. + ************************************************************************/ + public int floor(long units) + { + return (Math.toIntExact(Math.floorDiv(units * milliPoints * dpi, DIVISOR))); + } + + + + /************************************************************************ + ** Rounded up. + ************************************************************************/ + public int ceil(long units) + { + return (-floor(-units)); + } + + + + /************************************************************************ + ** To the nearest dot, a half upward. + ************************************************************************/ + public int round(long units) + { + return (Math.toIntExact(Math.floorDiv(units * milliPoints * dpi + DIVISOR / 2, DIVISOR))); + } + + + + /************************************************************************ + ** The size of the em in dots, for the font that draws. + ************************************************************************/ + public float size() + { + return ((float) ((double) milliPoints * dpi / 72_000)); + } + } + + + + /*************************************************************************** + ** The box of a line as characters are added to it from the left. + ***************************************************************************/ + private static final class Extent + { + private final Scale scale; + private long units; + private int left; + private int right; + private int above; + private int below; + + + + /************************************************************************ + ** An empty line at one size. + ************************************************************************/ + Extent(Scale scale) + { + this.scale = scale; + } + + + + /************************************************************************ + ** Add the next character at the pen. A space moves the pen and widens + ** nothing, so spaces at the end of a line take no room. + ************************************************************************/ + void add(Glyph glyph) + { + int pen = scale.round(units); + units += glyph.advance(); + if(!glyph.space()) + { + right = Math.max(right, scale.ceil(units)); + } + if(glyph.ink()) + { + left = Math.min(left, pen + scale.floor(glyph.left()) - SLOP); + right = Math.max(right, pen + scale.ceil(glyph.right()) + SLOP); + above = Math.max(above, scale.ceil(glyph.top()) + SLOP); + below = Math.max(below, scale.ceil(glyph.bottom()) + SLOP); + } + } + + + + /************************************************************************ + ** The width of the box so far. + ************************************************************************/ + int width() + { + return (right - left); + } + } + + + + /*************************************************************************** + ** Fit a text, given as the measurements of its characters, by the fixed + ** order. `mark` is the face's ellipsis, used only when the request allows + ** cutting. + ***************************************************************************/ + public static Block fit(Request request, Glyph[] glyphs, Glyph mark) + { + int count = glyphs.length; + while(count > 0 && glyphs[count - 1].space()) + { + count--; + } + int size = request.nominal(); + while(true) + { + Scale scale = new Scale(size, request.dpi()); + Block words = block(request, scale, lines(request, scale, glyphs, count, true), count, count); + if(words.fits()) + { + return (words); + } + Block characters = block(request, scale, lines(request, scale, glyphs, count, false), count, count); + if(characters.fits() || size == request.floor()) + { + return (characters.fits() || !request.truncate() ? characters : cut(request, scale, glyphs, mark, characters)); + } + size = Math.max(request.floor(), size - STEP_MILLIPOINTS); + } + } + + + + /*************************************************************************** + ** Break a text into lines at one size, between words or at any character. + ** Spaces where a line is broken are dropped. + ***************************************************************************/ + private static List lines(Request request, Scale scale, Glyph[] glyphs, int count, boolean words) + { + List lines = new ArrayList<>(); + int from = 0; + while(from < count) + { + int to = end(request, scale, glyphs, from, count, words); + lines.add(line(scale, glyphs, from, to, null)); + from = to; + while(from < count && glyphs[from].space()) + { + from++; + } + } + return (lines); + } + + + + /*************************************************************************** + ** Where the line that starts at `from` ends: after the last word, or the + ** last character, that still fits the width. The first one is taken even + ** when it is too wide, so the line is then wider than the box and the + ** layout does not fit. Broken at any character, a line may end after a + ** space, which takes no room; so spaces at the start of a text cannot push + ** its first letter out of the box. + ***************************************************************************/ + private static int end(Request request, Scale scale, Glyph[] glyphs, int from, int count, boolean words) + { + Extent extent = new Extent(scale); + int accepted = from; + for(int index = from; index < count; index++) + { + extent.add(glyphs[index]); + if(!words || (!glyphs[index].space() && (index + 1 == count || glyphs[index + 1].space()))) + { + boolean wide = extent.width() > request.width(); + if(wide && accepted > from) + { + return (accepted); + } + accepted = index + 1; + if(wide) + { + return (accepted); + } + } + } + return (accepted); + } + + + + /*************************************************************************** + ** Measure one line, with the ellipsis after it when one is given. + ***************************************************************************/ + private static Line line(Scale scale, Glyph[] glyphs, int from, int to, Glyph mark) + { + Extent extent = new Extent(scale); + for(int index = from; index < to; index++) + { + extent.add(glyphs[index]); + } + if(mark != null) + { + extent.add(mark); + } + return (new Line(from, to, mark != null, extent.left, extent.right, extent.above, extent.below)); + } + + + + /*************************************************************************** + ** Stack lines into a block and hold it against the box. A line reserves the + ** face's ascent above its baseline and its descent below; the block grows + ** where the ink of a line reaches further. + ***************************************************************************/ + private static Block block(Request request, Scale scale, List lines, int characters, int shown) + { + if(lines.isEmpty()) + { + return (new Block(scale.milliPoints(), lines, 0, 0, 0, 0, characters, shown, true)); + } + Face face = request.face(); + int ascent = scale.ceil(face.ascent()); + int pitch = Math.max(1, scale.ceil(request.lineHeight() == null ? face.ascent() + face.descent() + face.leading() : request.lineHeight())); + int top = 0; + int bottom = ascent + (lines.size() - 1) * pitch + scale.ceil(face.descent()); + int width = 0; + for(int index = 0; index < lines.size(); index++) + { + Line line = lines.get(index); + int baseline = ascent + index * pitch; + top = Math.min(top, baseline - line.above()); + bottom = Math.max(bottom, baseline + line.below()); + width = Math.max(width, line.width()); + } + boolean fits = lines.size() <= request.maxLines() && width <= request.width() && bottom - top <= request.height(); + return (new Block(scale.milliPoints(), lines, width, bottom - top, ascent - top, pitch, characters, shown, fits)); + } + + + + /*************************************************************************** + ** Cut a text that fits at no size: keep as many lines as the box holds, and + ** end the last of them with the ellipsis after as many of its characters as + ** still fit with it, down to the ellipsis alone. Something is always left + ** out, so the ellipsis always stands for text, and spaces before it are + ** dropped. When not even the ellipsis fits, the answer is the refusal that + ** was passed in. + ***************************************************************************/ + private static Block cut(Request request, Scale scale, Glyph[] glyphs, Glyph mark, Block refused) + { + int all = refused.lines().size(); + for(int kept = Math.min(request.maxLines(), all); kept > 0; kept--) + { + List lines = new ArrayList<>(refused.lines().subList(0, kept)); + int from = lines.get(kept - 1).from(); + for(int to = lines.get(kept - 1).to() - (kept == all ? 1 : 0); to >= from; to--) + { + if(to > from && glyphs[to - 1].space()) + { + continue; + } + lines.set(kept - 1, line(scale, glyphs, from, to, mark)); + Block block = block(request, scale, lines, refused.characters(), to); + if(block.fits()) + { + return (block); + } + } + } + return (refused); + } +} diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java new file mode 100644 index 0000000..64e67b1 --- /dev/null +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java @@ -0,0 +1,199 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import com.kingsrook.qbits.renderer.scene2.Canvas; +import com.kingsrook.qbits.renderer.scene2.Frame; +import com.kingsrook.qbits.renderer.scene2.Layout; +import com.kingsrook.qbits.renderer.scene2.Placement; + + +/******************************************************************************* + ** Draws a fitted text onto the label. Each glyph is drawn antialiased at the + ** whole-dot pen position the fit decided, by the same Java rasteriser version 1 + ** raster text uses, and a dot is ink when its grey is darker than the + ** element's threshold, so a higher threshold prints heavier. + ** + ** A line is drawn on a strip: its measured box and a guard of `GUARD` dots all + ** round. Ink found in the guard, or a glyph whose bitmap the runtime places + ** anywhere outside the measured box, means the measurement was wrong. Such + ** ink is never clipped away and never printed outside the box: the render + ** fails instead. + ** + ** A strip of more than `BAND_DOTS` dots (very large type) is drawn in bands of + ** whole rows, so one line never needs more grey than that. Where the bands + ** fall depends only on the box of the line, so the picture is the same on + ** every machine; the rasteriser may shade an edge dot at the border of a band + ** differently than it would in one piece. + *******************************************************************************/ +final class TextRaster +{ + static final int GUARD = 2; + static final int BAND_DOTS = 1 << 23; + + + + /*************************************************************************** + ** Utility class. + ***************************************************************************/ + private TextRaster() + { + } + + + + /*************************************************************************** + ** What to draw and how: the face, the text, its fitted block, where lines + ** sit across the block, the clockwise rotation, the grey below which a dot + ** is ink, and whether the dots are ink or (for reverse text) cleared. + ***************************************************************************/ + record Drawing(Face face, String text, TextFit.Block block, Placement.Align align, Placement.Valign valign, int rotation, int threshold, boolean ink) + { + } + + + + /*************************************************************************** + ** Draw into the element's box, which is given as it appears on the label: + ** a text turned a quarter reads along the box's height. + ***************************************************************************/ + static void paint(Canvas canvas, Frame frame, Drawing drawing, int bandDots) + { + TextFit.Block block = drawing.block(); + boolean upright = drawing.rotation() % 180 == 0; + Frame reading = new Frame(0, 0, upright ? frame.width() : frame.height(), upright ? frame.height() : frame.width()); + Frame content = Layout.align(reading, block.width(), block.height(), drawing.align(), drawing.valign()); + TextFit.Scale scale = new TextFit.Scale(block.milliPoints(), canvas.dpi()); + Font font = drawing.face().font(scale.size()); + for(int index = 0; index < block.lines().size(); index++) + { + TextFit.Line line = block.lines().get(index); + int left = content.x() + drawing.align().position().place(block.width(), line.width(), 0); + int top = content.y() + block.baseline() + index * block.pitch() - line.above(); + strip(canvas, frame, reading, drawing, scale, font, line, left, top, bandDots); + } + } + + + + /*************************************************************************** + ** Draw one line whose box has its top left at `left`, `top` of the reading + ** frame, a band of rows at a time. + ***************************************************************************/ + private static void strip(Canvas canvas, Frame frame, Frame reading, Drawing drawing, TextFit.Scale scale, Font font, TextFit.Line line, int left, int top, int bandDots) + { + int width = line.width() + 2 * GUARD; + int height = line.above() + line.below() + 2 * GUARD; + int rows = Math.max(1, bandDots / width); + for(int first = 0; first < height; first += rows) + { + BufferedImage band = new BufferedImage(width, Math.min(rows, height - first), BufferedImage.TYPE_BYTE_GRAY); + Graphics2D graphics = band.createGraphics(); + boolean clipped = false; + try + { + graphics.setColor(Color.WHITE); + graphics.fillRect(0, 0, band.getWidth(), band.getHeight()); + graphics.setColor(Color.BLACK); + graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + long units = 0; + for(int index = line.from(); index < line.to() + (line.marked() ? 1 : 0); index++) + { + char character = index < line.to() ? drawing.text().charAt(index) : (char) TextFit.MARK; + Face.Glyph glyph = drawing.face().glyph(character); + if(glyph.ink()) + { + GlyphVector vector = font.createGlyphVector(Face.CONTEXT, new char[] {character}); + int pen = GUARD - line.left() + scale.round(units); + Rectangle pixels = vector.getGlyphPixelBounds(0, Face.CONTEXT, pen, GUARD + line.above()); + clipped |= !pixels.isEmpty() && (pixels.x < GUARD || pixels.y < GUARD || pixels.x + pixels.width > width - GUARD || pixels.y + pixels.height > height - GUARD); + graphics.drawGlyphVector(vector, pen, GUARD + line.above() - first); + } + units += glyph.advance(); + } + } + finally + { + graphics.dispose(); + } + byte[] grey = ((DataBufferByte) band.getRaster().getDataBuffer()).getData(); + for(int y = 0; y < band.getHeight(); y++) + { + for(int x = 0; x < width; x++) + { + if((grey[y * width + x] & 255) < drawing.threshold()) + { + int row = first + y; + if(x < GUARD || x >= width - GUARD || row < GUARD || row >= height - GUARD) + { + throw new IllegalStateException("TEXT_INK_OUTSIDE_MEASURE"); + } + dot(canvas, frame, reading, drawing, left + x - GUARD, top + row - GUARD); + } + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + // ink that fell wholly beyond the guard was clipped by the strip and left no dot // + // to find; the bounds of its glyph say so // + ///////////////////////////////////////////////////////////////////////////////////// + if(clipped) + { + throw new IllegalStateException("TEXT_INK_OUTSIDE_MEASURE"); + } + } + } + + + + /*************************************************************************** + ** Put one dot of the reading frame on the label, turned clockwise. + ***************************************************************************/ + private static void dot(Canvas canvas, Frame frame, Frame reading, Drawing drawing, int x, int y) + { + int turnedX = switch(drawing.rotation()) + { + case 90 -> reading.height() - 1 - y; + case 180 -> reading.width() - 1 - x; + case 270 -> y; + default -> x; + }; + int turnedY = switch(drawing.rotation()) + { + case 90 -> x; + case 180 -> reading.height() - 1 - y; + case 270 -> reading.width() - 1 - x; + default -> y; + }; + canvas.set(frame.x() + turnedX, frame.y() + turnedY, drawing.ink()); + } +} diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/MutationCampaignTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/MutationCampaignTest.java index 96136b8..81107b0 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/MutationCampaignTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/MutationCampaignTest.java @@ -22,6 +22,8 @@ package com.kingsrook.qbits.renderer; import java.io.InputStream; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -31,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.exc.StreamConstraintsException; @@ -83,6 +86,8 @@ class MutationCampaignTest private static final Pattern LENGTH = Pattern.compile("-?[0-9]{1,5}(\\.[0-9]{1,3})?(mm|in|pt|%|dot)"); private static final Pattern ELEMENT_ID = Pattern.compile("[A-Za-z][A-Za-z0-9_-]{0,31}"); + private static final Pattern TYPE_SIZE = Pattern.compile("([0-9]{1,5}(?:\\.[0-9]{1,3})?)(mm|in|pt)"); + private static final Set FACES = Set.of("qqq-sans", "qqq-sans-bold", "qqq-condensed-bold", "qqq-mono", "qqq-mono-bold"); @@ -305,13 +310,15 @@ class MutationCampaignTest ** second parser, either a version 1 scene (as above) or a version 2 scene ** that keeps every rule this checks on its own: only the declared top-level ** properties, a physical design size, at most 1000 elements with unique ids - ** of the fixed pattern, only boxes and groups (the types this renderer - ** draws), groups at most four deep, every length a number and a unit, and + ** of the fixed pattern, only boxes, groups and text (the types this renderer + ** draws), groups at most four deep, every length a number and a unit, every + ** text in a bundled face at a physical size with one value and only + ** documented fit, length and legibility settings at each resolution, and ** overrides only for the three resolutions and for declared ids. About one ** version 2 input in four is rendered instead of validated: its label must ** then be the commands and graphic fields a version 2 label is made of, with ** no ink outside the printable area, and validation must give the same - ** answer. Every other input is refused with a `Refusal`, which carries a + ** answer (but for a text bound to the record, which has no value here). Every other input is refused with a `Refusal`, which carries a ** diagnostic (or, for a version 1 source, with that parser's own refusal). ** Any other exception, an `IllegalArgumentException` of the package's own ** invariants among them, is a finding. @@ -320,7 +327,7 @@ class MutationCampaignTest void theVersionTwoSceneParserAcceptsOnlyVersionTwoScenes() throws Exception { List corpus = new ArrayList<>(); - for(String name : List.of("anchors", "rules", "groups")) + for(String name : List.of("anchors", "rules", "groups", "text-faces", "text-fit", "text-turned")) { try(InputStream stream = MutationCampaignTest.class.getResourceAsStream("/scene2/cases/" + name + ".json")) { @@ -329,6 +336,8 @@ class MutationCampaignTest } MutationCampaign campaign = new MutationCampaign(corpus, List.of("\"schema\"", "\"qqq-zpl-scene/2\"", "\"qqq-zpl-scene/1\"", "\"design\"", "\"elements\"", "\"overrides\"", "\"when\"", "\"dpi\"", "\"set\"", "\"children\"", "\"group\"", "\"box\"", "\"text\"", "\"barcode\"", "\"image\"", "\"id\"", "\"type\"", "\"anchor\"", "\"thickness\"", "\"fill\"", "\"rotation\"", "\"center\"", "true", "false", "null", + "\"defaults\"", "\"font\"", "\"size\"", "\"value\"", "\"valuePath\"", "\"lineHeight\"", "\"fit\"", "\"maxLines\"", "\"shrinkTo\"", "\"overflow\"", "\"truncate\"", "\"refuse\"", "\"maxLength\"", "\"threshold\"", + "\"reverse\"", "\"qqq-sans\"", "\"qqq-mono-bold\"", "\"qqq-\"", "\"/record/name\"", "90", "180", "270", "1000pt", "0.5", "1e400", "\\u0301", "\\t", "\\uD83D", "mm", "in", "pt", "%", "dot", "-", ".", "203", "300", "600", "99999999999", "4294967499", "{", "}", "[", "]", ":", ",", "\\u0000")); int iterations = MutationCampaign.iterations(ITERATIONS); for(long seed : MutationCampaign.seeds(SEEDS)) @@ -406,7 +415,12 @@ class MutationCampaignTest } catch(Refusal refusal) { - if(render) + /////////////////////////////////////////////////////////////////////////////////////// + // a text bound to the record has no value here, since the campaign's record is // + // empty: that is the one refusal a render gives that validation, which reads no // + // record, cannot // + /////////////////////////////////////////////////////////////////////////////////////// + if(render && !"VALUE_MISSING".equals(refusal.diagnostic().code())) { Refusal validated = assertThrows(Refusal.class, () -> RendererMain.process(SceneFixture.request("VALIDATE", stock, source)), "refused to render what validation accepts"); assertEquals(refusal.diagnostic().wire(), validated.diagnostic().wire()); @@ -436,7 +450,7 @@ class MutationCampaignTest assertTrue(length != null && LENGTH.matcher(length).matches() && !length.startsWith("-") && !length.endsWith("%") && !length.endsWith("dot"), () -> "accepted design " + side + " " + length); } Set ids = new HashSet<>(); - assertVersionTwoElements(accepted.path("elements"), 1, ids); + assertVersionTwoElements(accepted.path("elements"), 1, ids, accepted); assertTrue(ids.size() <= 1000, () -> "accepted " + ids.size() + " elements"); for(JsonNode override : accepted.path("overrides")) { @@ -451,7 +465,7 @@ class MutationCampaignTest /*************************************************************************** ** The independent reading of a version 2 element list. ***************************************************************************/ - private static void assertVersionTwoElements(JsonNode elements, int depth, Set ids) + private static void assertVersionTwoElements(JsonNode elements, int depth, Set ids, JsonNode scene) { assertTrue(elements.isArray(), "accepted elements that are not a list"); for(JsonNode element : elements) @@ -459,23 +473,109 @@ class MutationCampaignTest String id = element.path("id").textValue(); assertTrue(id != null && ELEMENT_ID.matcher(id).matches() && ids.add(id), () -> "accepted element id " + element.path("id")); String type = element.path("type").textValue(); - assertTrue("box".equals(type) || "group".equals(type), () -> "accepted element type " + element.path("type")); + assertTrue("box".equals(type) || "group".equals(type) || "text".equals(type), () -> "accepted element type " + element.path("type")); for(String name : List.of("x", "y", "width", "height", "thickness")) { assertTrue(!element.has(name) || (element.get(name).isTextual() && LENGTH.matcher(element.get(name).textValue()).matches()), () -> "accepted " + name + " " + element.get(name)); } Set allowed = "box".equals(type) ? Set.of("id", "type", "anchor", "x", "y", "width", "height", "align", "valign", "thickness", "fill") + : "text".equals(type) ? Set.of("id", "type", "anchor", "x", "y", "width", "height", "align", "valign", "value", "valuePath", "font", "size", "lineHeight", "fit", "maxLength", "threshold", "reverse", "rotation") : Set.of("id", "type", "anchor", "x", "y", "width", "height", "align", "valign", "children"); element.fieldNames().forEachRemaining(name -> assertTrue(allowed.contains(name), () -> "accepted " + type + " property " + name)); if("group".equals(type)) { assertTrue(depth <= 4, "accepted groups more than four deep"); - assertVersionTwoElements(element.path("children"), depth + 1, ids); + assertVersionTwoElements(element.path("children"), depth + 1, ids, scene); + } + if("text".equals(type)) + { + assertVersionTwoText(element, scene); } } } + + /*************************************************************************** + ** The independent reading of an accepted text element, as it stands at each + ** resolution: the scene's defaults, then the element, then the overrides + ** for that resolution in order. It names a bundled face, has a physical + ** size from 1 to 1000 pt, exactly one of a literal and a pointer into the + ** record, and only fit, length, threshold, rotation, reverse and line + ** height values of the documented kinds and ranges. + ***************************************************************************/ + private static void assertVersionTwoText(JsonNode element, JsonNode scene) + { + for(int dpi : List.of(203, 300, 600)) + { + ObjectNode stated = INDEPENDENT.createObjectNode(); + scene.path("defaults").properties().forEach(property -> stated.set(property.getKey(), property.getValue())); + element.properties().forEach(property -> stated.set(property.getKey(), property.getValue())); + for(JsonNode override : scene.path("overrides")) + { + boolean applies = false; + for(JsonNode resolution : override.path("when").path("dpi")) + { + applies |= resolution.intValue() == dpi; + } + if(applies) + { + override.path("set").path(element.path("id").textValue()).properties().forEach(property -> stated.set(property.getKey(), property.getValue())); + } + } + String about = "accepted text " + element.path("id") + " at " + dpi + " dpi with "; + assertTrue(stated.path("font").isTextual() && FACES.contains(stated.path("font").textValue()), () -> about + "font " + stated.path("font")); + assertTrue(typeSize(stated.path("size"), 1, 1000), () -> about + "size " + stated.path("size")); + assertTrue(stated.has("value") != stated.has("valuePath"), () -> about + "both or neither of value and valuePath"); + assertTrue(!stated.has("value") || (stated.get("value").isTextual() && stated.get("value").textValue().codePointCount(0, stated.get("value").textValue().length()) <= 1024), () -> about + "a value that is not text"); + assertTrue(!stated.has("valuePath") || (stated.get("valuePath").isTextual() && stated.get("valuePath").textValue().startsWith("/")), () -> about + "valuePath " + stated.path("valuePath")); + JsonNode fit = stated.path("fit"); + assertTrue(fit.isMissingNode() || fit.isObject(), () -> about + "fit " + fit); + fit.fieldNames().forEachRemaining(name -> assertTrue(Set.of("maxLines", "shrinkTo", "overflow").contains(name), () -> about + "fit property " + name)); + assertTrue(whole(fit.path("maxLines"), 1, 64) && whole(stated.path("threshold"), 1, 254) && whole(stated.path("maxLength"), 1, 1024), () -> about + "a count out of range"); + assertTrue(fit.path("shrinkTo").isMissingNode() || typeSize(fit.path("shrinkTo"), 1, 1000), () -> about + "shrinkTo " + fit.path("shrinkTo")); + assertTrue(fit.path("overflow").isMissingNode() || Set.of("refuse", "truncate").contains(String.valueOf(fit.path("overflow").textValue())), () -> about + "overflow " + fit.path("overflow")); + assertTrue(stated.path("rotation").isMissingNode() || (stated.path("rotation").isInt() && Set.of(0, 90, 180, 270).contains(stated.path("rotation").intValue())), () -> about + "rotation " + stated.path("rotation")); + assertTrue(stated.path("reverse").isMissingNode() || stated.path("reverse").isBoolean(), () -> about + "reverse " + stated.path("reverse")); + JsonNode lineHeight = stated.path("lineHeight"); + assertTrue(lineHeight.isMissingNode() || (lineHeight.isNumber() && lineHeight.doubleValue() >= 0.5 && lineHeight.doubleValue() <= 5), () -> about + "lineHeight " + lineHeight); + } + } + + + + /*************************************************************************** + ** Whether a value is absent or a whole number in a range. + ***************************************************************************/ + private static boolean whole(JsonNode value, int minimum, int maximum) + { + return (value.isMissingNode() || (value.isInt() && value.intValue() >= minimum && value.intValue() <= maximum)); + } + + + + /*************************************************************************** + ** Whether a value is a type size: an unsigned physical length between two + ** numbers of points, by decimal arithmetic with a hair of tolerance for the + ** renderer's rounding to thousandths of a point. + ***************************************************************************/ + private static boolean typeSize(JsonNode value, int minimum, int maximum) + { + Matcher matcher = TYPE_SIZE.matcher(value.isTextual() ? value.textValue() : ""); + if(!matcher.matches()) + { + return (false); + } + BigDecimal points = new BigDecimal(matcher.group(1)).multiply(switch(matcher.group(2)) + { + case "in" -> BigDecimal.valueOf(72); + case "mm" -> BigDecimal.valueOf(72).divide(new BigDecimal("25.4"), 12, RoundingMode.HALF_EVEN); + default -> BigDecimal.ONE; + }); + return (points.compareTo(new BigDecimal(minimum).subtract(new BigDecimal("0.001"))) >= 0 && points.compareTo(new BigDecimal(maximum).add(new BigDecimal("0.001"))) <= 0); + } + + /*************************************************************************** ** The target: static validation of one scene on a stock all corpus scenes fit. ***************************************************************************/ diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/Scene2Test.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/Scene2Test.java index 96363dc..4af86c4 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/Scene2Test.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/Scene2Test.java @@ -508,9 +508,10 @@ class Scene2Test /*************************************************************************** - ** Text, barcodes and images are parsed and placed by this renderer and then + ** Barcodes and images are parsed and placed by this renderer and then ** refused by name, with the box they would have had. The design's own - ** example scene is the case. + ** example scene is the case: its barcode is refused, and its caption, a text + ** bound to the record, is refused for the value the empty record lacks. ***************************************************************************/ @Test void anElementThisRendererCannotDrawIsRefusedByName() throws Exception @@ -523,7 +524,7 @@ class Scene2Test + "\"align\":\"center\",\"valign\":\"middle\",\"size\":\"11pt\",\"maxLength\":48,\"fit\":{\"maxLines\":2,\"shrinkTo\":\"7pt\",\"overflow\":\"refuse\"}}]," + "\"overrides\":[{\"when\":{\"dpi\":[203]},\"set\":{\"caption\":{\"threshold\":144}}}]}"; Map code = Map.of("code", "RENDERER_TOO_OLD", "severity", "ERROR", "element", "code", "box", List.of(6, 4, 751, 87)); - Map caption = Map.of("code", "RENDERER_TOO_OLD", "severity", "ERROR", "element", "caption", "box", List.of(6, 100, 751, 51)); + Map caption = Map.of("code", "VALUE_MISSING", "severity", "ERROR", "element", "caption", "box", List.of(6, 100, 751, 51)); assertEquals(code, refused(example)); assertEquals(code, SceneFixture.refusal(() -> RendererMain.process(SceneFixture.request("RENDER", example)))); @@ -539,10 +540,10 @@ class Scene2Test assertEquals(invalid("logo", "/elements/0/rotation"), refusedElements("{\"id\":\"logo\",\"type\":\"image\",\"asset\":\"logo\",\"rotation\":" + rotation + "}"), rotation); } assertEquals(Map.of("code", "SCENE_INVALID", "severity", "ERROR", "element", "t", "pointer", "/elements/0", "measured", Map.of("unknownProperties", 1), "limit", Map.of("unknownProperties", 0)), - refusedElements("{\"id\":\"t\",\"type\":\"text\",\"value\":\"TEST-0001\",\"symbology\":\"qr\"}")); + refusedElements("{\"id\":\"t\",\"type\":\"text\",\"value\":\"TEST-0001\",\"font\":\"qqq-sans\",\"size\":\"9pt\",\"symbology\":\"qr\"}")); assertEquals(Map.of("code", "SCENE_INVALID", "severity", "ERROR", "element", "t", "pointer", "/elements/0", "measured", Map.of("widthDots", 0, "heightDots", 155), "limit", Map.of("widthDots", 1, "heightDots", 1)), - refusedElements("{\"id\":\"t\",\"type\":\"text\",\"value\":\"TEST-0001\",\"width\":\"0.1mm\"}")); + refusedElements("{\"id\":\"t\",\"type\":\"text\",\"value\":\"TEST-0001\",\"font\":\"qqq-sans\",\"size\":\"9pt\",\"width\":\"0.1mm\"}")); Diagnostics diagnostics = new Diagnostics(false); diagnostics.declare("t", "/elements/0"); @@ -554,7 +555,7 @@ class Scene2Test assertEquals(144, source.value("threshold").intValue()); assertNull(source.value("size")); assertEquals(new Placement(Placement.Anchor.TOP_LEFT, Length.ZERO, Length.ZERO, null, null, Placement.Align.LEFT, Placement.Valign.TOP), source.placement()); - SceneElement placeholder = ElementFactory.FACTORIES.get("text").create(source); + SceneElement placeholder = ElementFactory.FACTORIES.get("image").create(source); assertEquals("t", placeholder.id()); assertEquals(List.of(), placeholder.children()); assertEquals(Map.of("code", "RENDERER_TOO_OLD", "severity", "ERROR", "element", "t", "box", List.of(1, 2, 3, 4)), @@ -574,8 +575,8 @@ class Scene2Test { String source = SceneFixture.scene("{\"id\":\"good\",\"type\":\"box\",\"x\":\"5dot\",\"width\":\"16dot\",\"height\":\"4dot\",\"fill\":true}," + "{\"id\":\"wide\",\"type\":\"box\",\"x\":\"90mm\",\"width\":\"10mm\",\"height\":\"5mm\",\"thickness\":\"1pt\"}," - + "{\"id\":\"g\",\"type\":\"group\",\"width\":\"0.1mm\",\"children\":[{\"id\":\"unseen\",\"type\":\"text\",\"value\":\"TEST-0001\"}]}," - + "{\"id\":\"words\",\"type\":\"text\",\"value\":\"TEST-0001\",\"y\":\"10mm\",\"height\":\"5mm\"}," + + "{\"id\":\"g\",\"type\":\"group\",\"width\":\"0.1mm\",\"children\":[{\"id\":\"unseen\",\"type\":\"barcode\",\"value\":\"TEST-0001\"}]}," + + "{\"id\":\"words\",\"type\":\"barcode\",\"value\":\"TEST-0001\",\"y\":\"10mm\",\"height\":\"5mm\"}," + "{\"id\":\"also\",\"type\":\"box\",\"anchor\":\"bottom-left\",\"width\":\"8dot\",\"height\":\"2dot\",\"fill\":true}"); List> expected = List.of( Map.of("code", "DEVICE_UNIT_USED", "severity", "WARNING", "element", "good", "pointer", "/elements/0/x"), diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java index ff6a480..1f1a19b 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java @@ -48,8 +48,12 @@ import static org.junit.jupiter.api.Assertions.fail; ** Golden labels for the layout cases in `scene2/cases`, at 203, 300 and 600 ** dpi. Each case has a picture (the page a printer would draw, compared dot ** for dot) and the exact ZPL. A box is whole dots of pure ink, so both are - ** exact on every machine. A golden changes only with a reviewed change to the - ** layout rules: what this build drew is left in `target/scene2-actual`. + ** exact on every machine. Text is measured by integer arithmetic and drawn + ** by the Java runtime's rasteriser from the bundled faces only; the text + ** goldens were generated on Linux (Temurin 21.0.9, the CI image) and are the + ** same bytes on Windows (Temurin 21.0.12), and they are compared exactly on + ** both. A golden changes only with a reviewed change to the layout rules or + ** the runtime: what this build drew is left in `target/scene2-actual`. *******************************************************************************/ class SceneGoldenTest { diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java new file mode 100644 index 0000000..099fa24 --- /dev/null +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java @@ -0,0 +1,297 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.awt.Font; +import java.awt.Rectangle; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HexFormat; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import com.kingsrook.qbits.renderer.scene2.Scene2; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** The bundled faces: what ships, under which licence, with which hash, and + ** that the numbers layout relies on are the font files' own. + *******************************************************************************/ +class FaceTest +{ + /*************************************************************************** + ** A resource of the renderer jar, or null. + ***************************************************************************/ + private static byte[] resource(String path) throws Exception + { + try(InputStream stream = Face.class.getResourceAsStream(path)) + { + return (stream == null ? null : stream.readAllBytes()); + } + } + + + + /*************************************************************************** + ** The lowercase hexadecimal SHA-256 of some bytes. + ***************************************************************************/ + private static String sha256(byte[] bytes) throws Exception + { + return (HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(bytes))); + } + + + + /*************************************************************************** + ** Every character of the Basic Multilingual Plane a face draws. + ***************************************************************************/ + static List drawn(Face face) + { + List drawn = new ArrayList<>(); + for(int codePoint = 0; codePoint <= Character.MAX_VALUE; codePoint++) + { + if(face.draws(codePoint)) + { + drawn.add(codePoint); + } + } + return (drawn); + } + + + + /*************************************************************************** + ** The set is the five faces the design names, by the names it gives them, + ** and no other name is a face. + ***************************************************************************/ + @Test + void theBundledSetIsFiveNamedFaces() + { + assertEquals(List.of("qqq-sans", "qqq-sans-bold", "qqq-condensed-bold", "qqq-mono", "qqq-mono-bold"), Face.all().stream().map(Face::scene).toList()); + assertEquals(List.of(false, true, true, false, true), Face.all().stream().map(Face::bold).toList()); + for(Face face : Face.all()) + { + assertEquals(face, Face.of(face.scene())); + assertTrue(face.scene().startsWith("qqq-"), "a bundled face has the reserved prefix"); + } + for(String other : List.of("", "qqq-", "qqq-serif", "QQQ-SANS", "qqq-sans ", "Abel", "IBM Plex Sans")) + { + assertNull(Face.of(other), other); + } + assertNull(Face.of(null)); + } + + + + /*************************************************************************** + ** Every bundled face ships with its licence text, a provenance note and a + ** hash, and the bytes in the jar are the bytes that were hashed. The build + ** fails when any of the three is missing or a file changes. + ***************************************************************************/ + @Test + void everyBundledFaceHasItsLicenceProvenanceAndAMatchingHash() throws Exception + { + Map sums = new HashMap<>(); + for(String line : new String(resource("/fonts/SHA256SUMS"), StandardCharsets.US_ASCII).lines().toList()) + { + assertTrue(line.matches("[0-9a-f]{64} [A-Za-z0-9./-]+"), line); + assertNull(sums.put(line.substring(66), line.substring(0, 64)), "listed twice: " + line); + } + Set licences = Set.of("ibm-plex-sans/LICENSE.txt", "ibm-plex-sans-condensed/LICENSE.txt", "jetbrains-mono/OFL.txt"); + assertEquals(Face.all().size() + licences.size(), sums.size(), "the list is exactly the faces and their licences"); + for(Face face : Face.all()) + { + String directory = face.file().substring(0, face.file().indexOf('/') + 1); + byte[] font = resource("/fonts/" + face.file()); + assertNotNull(font, face.file()); + assertTrue(font[0] == 0 && font[1] == 1 && font[2] == 0 && font[3] == 0, "static TrueType outlines: " + face.file()); + assertEquals(sums.get(face.file()), sha256(font), face.file()); + + String licence = licences.stream().filter(name -> name.startsWith(directory)).findFirst().orElseThrow(); + byte[] text = resource("/fonts/" + licence); + assertNotNull(text, licence); + assertEquals(sums.get(licence), sha256(text), licence); + String words = new String(text, StandardCharsets.UTF_8); + assertTrue(words.contains("This Font Software is licensed under the SIL Open Font License, Version 1.1."), licence); + assertTrue(words.contains("SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007") && words.contains("PERMISSION & CONDITIONS") && words.contains("TERMINATION"), "the whole licence text: " + licence); + + byte[] provenance = resource("/fonts/" + directory + "SOURCE.md"); + assertNotNull(provenance, "provenance of " + face.file()); + String note = new String(provenance, StandardCharsets.UTF_8); + String name = face.file().substring(directory.length()); + assertTrue(note.contains("`" + name + "`") && note.contains(sums.get(face.file())) && note.contains(sums.get(licence)), "the provenance names the file and both hashes: " + name); + assertTrue(note.contains("https://github.com/") && note.contains("/releases/download/") && note.contains("Archive SHA-256") && (note.contains("Unmodified") || note.contains("unmodified")), name); + assertTrue(note.contains("`" + face.scene() + "`"), "the provenance gives the scene name " + face.scene()); + } + } + + + + /*************************************************************************** + ** A file that is not a font is a broken build and says so; it is never a + ** silent fallback to another face. + ***************************************************************************/ + @Test + void aFileThatIsNotAFontIsABrokenBuild() + { + assertEquals("BUNDLED_FONT_UNREADABLE", assertThrows(IllegalStateException.class, () -> Face.load("/fonts/SHA256SUMS")).getMessage()); + } + + + + /*************************************************************************** + ** The bounds each face states are the font file's: the widest character + ** (the lowest of those that share the greatest advance, among characters + ** with ink), and the furthest any character reaches past its advance on the + ** left and right, above the baseline and below it. They are what a length + ** is proven against, so they are recomputed here from every character. + ***************************************************************************/ + @Test + void theBoundsOfAFaceAreThoseOfItsFontFile() + { + for(Face face : Face.all()) + { + int widest = -1; + int advance = 0; + int left = 0; + int right = 0; + int top = 0; + int bottom = 0; + List drawn = drawn(face); + for(int codePoint : drawn) + { + Face.Glyph glyph = face.glyph(codePoint); + assertTrue(glyph.advance() >= 0 && glyph.advance() <= 2 * Face.REFERENCE, "advance of " + codePoint); + assertEquals(glyph.space(), codePoint == ' '); + if(!glyph.ink()) + { + assertEquals(new Face.Glyph(glyph.advance(), 0, 0, 0, 0, false, codePoint == ' '), glyph); + continue; + } + if(glyph.advance() > advance) + { + advance = glyph.advance(); + widest = codePoint; + } + left = Math.max(left, -glyph.left()); + right = Math.max(right, glyph.right() - glyph.advance()); + top = Math.max(top, glyph.top()); + bottom = Math.max(bottom, glyph.bottom()); + } + assertTrue(drawn.size() > 800, face.scene() + " draws " + drawn.size() + " characters"); + assertEquals(new Face.Glyph(advance, -left, advance + right, top, bottom, true, false), face.worst(), face.scene()); + assertEquals(widest, face.widest(), face.scene()); + assertEquals(face.glyph(face.widest()).advance(), face.worst().advance()); + + ///////////////////////////////////////////////////////////////////////////////////// + // the faces have 1000 units to the em, so the reference size reads whole numbers // + ///////////////////////////////////////////////////////////////////////////////////// + assertTrue(face.ascent() > 900 && face.ascent() < 1100 && face.descent() > 200 && face.descent() < 350 && face.leading() == 0, face.scene()); + assertTrue(face.capHeight() > 650 && face.capHeight() < 760, face.scene()); + } + assertEquals(List.of(1025, 275, 698), List.of(Face.SANS.ascent(), Face.SANS.descent(), Face.SANS.capHeight())); + assertEquals(List.of(1020, 300, 730), List.of(Face.MONO_BOLD.ascent(), Face.MONO_BOLD.descent(), Face.MONO_BOLD.capHeight())); + assertEquals(new Face.Glyph(600, 0, 0, 0, 0, false, true), Face.MONO.glyph(' ')); + assertEquals(Set.of(600), drawn(Face.MONO).stream().map(codePoint -> Face.MONO.glyph(codePoint).advance()).collect(Collectors.toSet()), "the monospace has one advance"); + } + + + + /*************************************************************************** + ** A face draws a character only as one glyph of its own, left to right. + ** Controls, formats (which would print nothing), marks that must be placed + ** on another letter, scripts that need shaping, and characters outside the + ** Basic Multilingual Plane are not drawn; nor is a character the face lacks. + ***************************************************************************/ + @Test + void aFaceDrawsOnlyWhatItCanDrawFaithfully() + { + for(Face face : Face.all()) + { + for(int codePoint = 0x20; codePoint < 0x7F; codePoint++) + { + assertTrue(face.draws(codePoint), face.scene() + " draws " + codePoint); + } + assertTrue(face.draws(TextFit.MARK), "the ellipsis that marks a cut"); + assertTrue(face.draws(0xE9) && face.draws(0xC5) && face.draws(0xA0) && face.draws(0x20AC)); + for(int codePoint : List.of(0x00, 0x09, 0x0A, 0x0D, 0x7F, 0x85, 0xAD, 0x200B, 0x200D, 0x202E, 0x2028, 0x2029, 0xFEFF, 0x0301, 0x0627, 0x05D0, 0x0915, 0x4E2D, 0xD83D, 0xE0A0, 0xFFFF, 0x1F600, 0x10FFFF)) + { + assertFalse(face.draws(codePoint), face.scene() + " must not draw " + Integer.toHexString(codePoint)); + } + assertEquals(0, face.missing("TEST-0001 (01)00012345678905 café")); // e acute + assertEquals(0, face.missing("")); + assertEquals(4, face.missing("A\tB́😀C中")); // a tab, a combining acute, one emoji (two units, one character), a CJK ideograph + assertEquals(3, face.glyphs("A B").length); + assertTrue(face.glyphs("A B")[1].space() && !face.glyphs("A B")[0].space()); + } + } + + + + /*************************************************************************** + ** The rasteriser keeps every glyph inside the box layout measures for it: + ** the outline at the reference size, scaled exactly, and `TextFit.SLOP` + ** dots. Held for every character of every face over the sizes and + ** resolutions labels use. (That the ink itself stays inside is held where + ** text is drawn: `TextRasterTest`.) + ***************************************************************************/ + @Test + void everyGlyphIsRasterisedInsideItsMeasuredBox() + { + for(Face face : Face.all()) + { + List drawn = drawn(face); + for(int dpi : Scene2.RESOLUTIONS) + { + for(int milliPoints : List.of(5000, 6250, 7000, 8000, 9000, 10_500, 12_000, 18_000, 36_000, 72_000)) + { + TextFit.Scale scale = new TextFit.Scale(milliPoints, dpi); + Font font = face.font(scale.size()); + for(int codePoint : drawn) + { + Face.Glyph glyph = face.glyph(codePoint); + Rectangle pixels = font.createGlyphVector(Face.CONTEXT, new char[] {(char) codePoint}).getGlyphPixelBounds(0, Face.CONTEXT, 0, 0); + if(!glyph.ink()) + { + assertTrue(pixels.isEmpty(), "ink where none is measured"); + continue; + } + boolean inside = pixels.x >= scale.floor(glyph.left()) - TextFit.SLOP && pixels.x + pixels.width <= scale.ceil(glyph.right()) + TextFit.SLOP + && -pixels.y <= scale.ceil(glyph.top()) + TextFit.SLOP && pixels.y + pixels.height <= scale.ceil(glyph.bottom()) + TextFit.SLOP; + assertTrue(inside, () -> face.scene() + " U+" + Integer.toHexString(codePoint) + " at " + milliPoints + " millipoints, " + dpi + " dpi: " + pixels + " outside " + glyph); + } + } + } + } + } +} diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java new file mode 100644 index 0000000..794d41c --- /dev/null +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java @@ -0,0 +1,720 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.kingsrook.qbits.renderer.RendererMain; +import com.kingsrook.qbits.renderer.Wire; +import com.kingsrook.qbits.renderer.scene2.Refusal; +import com.kingsrook.qbits.renderer.scene2.SceneFixture; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** The `text` element through the worker's entry point: what a scene may say, + ** what each refusal reports, and what reaches the label. The stock is the + ** design document's example: 4 x 1 in with 3 mm margins, a printable area of + ** 764 x 155 dots at 24, 24 on a page of 812 x 203 dots at 203 dpi. + *******************************************************************************/ +class TextElementTest +{ + private static final String HEAD = "{'schema':'qqq-zpl-scene/2','design':{'width':'4in','height':'1in'},'defaults':{'font':'qqq-sans-bold','size':'9pt'},'elements':["; + + + + /*************************************************************************** + ** JSON written with single quotes, for reading. + ***************************************************************************/ + private static String json(String text) + { + return (text.replace('\'', '"')); + } + + + + /*************************************************************************** + ** A scene with the default face and size and these elements. + ***************************************************************************/ + private static String scene(String elements) + { + return (json(HEAD + elements + "]}")); + } + + + + /*************************************************************************** + ** A scene of one text element `t` with these properties. + ***************************************************************************/ + private static String text(String properties) + { + return (scene("{'id':'t','type':'text'," + properties + "}")); + } + + + + /*************************************************************************** + ** A request whose record holds one value at `/record/name`. + ***************************************************************************/ + private static ObjectNode bound(String operation, String source, String value) + { + ObjectNode request = SceneFixture.request(operation, source); + ((ObjectNode) request.get("context")).putObject("record").put("name", value); + return (request); + } + + + + /*************************************************************************** + ** The refusal a request ends in. + ***************************************************************************/ + private static Map refused(ObjectNode request) + { + return (SceneFixture.refusal(() -> RendererMain.process(request))); + } + + + + /*************************************************************************** + ** The findings of a request that is answered. + ***************************************************************************/ + @SuppressWarnings("unchecked") + private static List> findings(ObjectNode request) throws Exception + { + Map answer = RendererMain.process(request); + assertEquals("OK", answer.get("outcome")); + return ((List>) answer.get("diagnostics")); + } + + + + /*************************************************************************** + ** The findings with one code. + ***************************************************************************/ + private static List> findings(ObjectNode request, String code) throws Exception + { + return (findings(request).stream().filter(finding -> code.equals(finding.get("code"))).toList()); + } + + + + /*************************************************************************** + ** The page a request prints. + ***************************************************************************/ + private static boolean[][] page(ObjectNode request) throws Exception + { + return (SceneFixture.raster(SceneFixture.render(request))); + } + + + + /*************************************************************************** + ** The ink of a page: left, top, right and bottom (the last two exclusive), + ** and how many dots. + ***************************************************************************/ + private static List ink(boolean[][] page) + { + int left = Integer.MAX_VALUE; + int top = Integer.MAX_VALUE; + int right = 0; + int bottom = 0; + int dots = 0; + for(int y = 0; y < page.length; y++) + { + for(int x = 0; x < page[y].length; x++) + { + if(page[y][x]) + { + left = Math.min(left, x); + top = Math.min(top, y); + right = Math.max(right, x + 1); + bottom = Math.max(bottom, y + 1); + dots++; + } + } + } + return (List.of(left, top, right, bottom, dots)); + } + + + + /*************************************************************************** + ** `SCENE_INVALID` for element `t` at a pointer. + ***************************************************************************/ + private static Map invalid(String pointer) + { + return (Map.of("code", "SCENE_INVALID", "severity", "ERROR", "element", "t", "pointer", pointer)); + } + + + + /*************************************************************************** + ** A literal value in the default face is drawn in its box, at the top left + ** unless the scene says otherwise, and a render is the same bytes twice, + ** whatever the locale of the machine. + ***************************************************************************/ + @Test + void aLiteralValueIsDrawnInItsBoxTheSameEveryTime() throws Exception + { + String source = text("'value':'LOT L240611A','x':'10mm','y':'5mm','width':'40mm','height':'6mm'"); + byte[] label = SceneFixture.render(SceneFixture.request("RENDER", source)); + List ink = ink(SceneFixture.raster(label)); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the box is 319 x 47 dots at 24 + 80, 24 + 40. Bold capitals of 9 pt are 17 dots high // + // and sit under the ascent of 27 dots // + //////////////////////////////////////////////////////////////////////////////////////////// + assertTrue(ink.get(0) >= 104 && ink.get(0) <= 108 && ink.get(2) < 104 + 319 && ink.get(2) > 104 + 150, "ink " + ink); + assertEquals(List.of(64 + 27 - 18, 64 + 27), List.of(ink.get(1), ink.get(3)), "capital height above the baseline: " + ink); + assertEquals(List.of(), findings(SceneFixture.request("RENDER", source))); + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", source))); + + assertArrayEquals(label, SceneFixture.render(SceneFixture.request("RENDER", source))); + Locale standing = Locale.getDefault(); + try + { + Locale.setDefault(Locale.forLanguageTag("tr-TR")); + assertArrayEquals(label, SceneFixture.render(SceneFixture.request("RENDER", source))); + } + finally + { + Locale.setDefault(standing); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // an empty value and one of spaces print nothing and are not refused // + //////////////////////////////////////////////////////////////////////////////////////////// + for(String blank : List.of("", " ")) + { + assertEquals(0, ink(page(SceneFixture.request("RENDER", text("'value':'" + blank + "'")))).get(4)); + } + } + + + + /*************************************************************************** + ** The size is a physical length: 9 pt, an eighth of an inch and 3.175 mm + ** are one size and one picture. Each bundled face is drawn, and they + ** differ. + ***************************************************************************/ + @Test + void theSizeIsAPhysicalLengthAndEveryFaceIsDrawn() throws Exception + { + boolean[][] points = page(SceneFixture.request("RENDER", text("'value':'Sample 0123','size':'9pt'"))); + assertTrue(ink(points).get(4) > 500); + for(String size : List.of("0.125in", "3.175mm")) + { + assertTrue(Arrays.deepEquals(points, page(SceneFixture.request("RENDER", text("'value':'Sample 0123','size':'" + size + "'")))), size); + } + assertFalse(Arrays.deepEquals(points, page(SceneFixture.request("RENDER", text("'value':'Sample 0123','size':'9.25pt'"))))); + + List> pictures = new ArrayList<>(); + for(Face face : Face.all()) + { + List ink = ink(page(SceneFixture.request("RENDER", text("'value':'Sample 0123','font':'" + face.scene() + "','size':'12pt'")))); + assertTrue(ink.get(4) > 600, face.scene() + " " + ink); + assertFalse(pictures.contains(ink), face.scene() + " is not another face's picture"); + pictures.add(ink); + } + assertTrue(pictures.get(1).get(4) > pictures.get(0).get(4) && pictures.get(4).get(4) > pictures.get(3).get(4), "a bold face has more ink than its regular"); + assertTrue(pictures.get(2).get(2) < pictures.get(1).get(2), "the condensed bold is narrower than the bold"); + } + + + + /*************************************************************************** + ** A property that is not what the schema says is `SCENE_INVALID` at that + ** property, in the element, in the defaults or in the override that states + ** it; whatever is wrong inside `fit` is reported at `fit`. + ***************************************************************************/ + @Test + void aPropertyTheSchemaDoesNotAllowIsRefusedAtThatProperty() throws Exception + { + Map> wrong = Map.ofEntries( + Map.entry("font", List.of("'font':12", "'font':null", "'font':['qqq-sans']")), + Map.entry("size", List.of("'size':'9'", "'size':9", "'size':'0.999pt'", "'size':'1000.001pt'", "'size':'50%'", "'size':'12dot'", "'size':'-9pt'", "'size':'0.3mm'", "'size':'14in'")), + Map.entry("lineHeight", List.of("'lineHeight':'1.2'", "'lineHeight':0.499", "'lineHeight':5.001", "'lineHeight':1.2345", "'lineHeight':true", "'lineHeight':1e400", "'lineHeight':-1", "'lineHeight':99999999999999999999")), + Map.entry("threshold", List.of("'threshold':0", "'threshold':255", "'threshold':127.5", "'threshold':'128'", "'threshold':4294967424")), + Map.entry("maxLength", List.of("'maxLength':0", "'maxLength':1025", "'maxLength':'48'", "'maxLength':4294967297", "'maxLength':null")), + Map.entry("fit", List.of("'fit':[]", "'fit':'shrink'", "'fit':{'maxLines':0}", "'fit':{'maxLines':65}", "'fit':{'maxLines':'2'}", "'fit':{'maxLines':1.5}", "'fit':{'shrinkTo':'small'}", "'fit':{'shrinkTo':'50%'}", + "'fit':{'shrinkTo':'6dot'}", "'fit':{'shrinkTo':'0.999pt'}", "'fit':{'shrinkTo':'9.001pt'}", "'fit':{'shrinkTo':7}", "'fit':{'overflow':'clip'}", "'fit':{'overflow':true}", "'fit':{'lines':2}", + "'fit':{'maxLines':2,'Overflow':'refuse'}")), + Map.entry("valuePath", List.of("'valuePath':12", "'valuePath':'record/name'", "'valuePath':''", "'valuePath':'/" + "a".repeat(256) + "'")), + Map.entry("reverse", List.of("'reverse':'yes'", "'reverse':1")), + Map.entry("rotation", List.of("'rotation':45", "'rotation':'90'"))); + wrong.forEach((name, cases) -> + { + for(String stated : cases) + { + String rest = name.equals("valuePath") ? "" : ",'value':'TEST-0001'"; + assertEquals(invalid("/elements/0/" + name), refused(SceneFixture.request("VALIDATE", text(stated + rest))), stated); + assertEquals(invalid("/elements/0/" + name), refused(SceneFixture.request("RENDER", text(stated + rest))), stated); + } + }); + for(String value : List.of("'value':'A','valuePath':'/record/name'", "'size':'9pt'", "'value':12", "'value':null", "'value':['A']", "'value':'" + "A".repeat(1025) + "'")) + { + assertEquals(invalid("/elements/0/value"), refused(SceneFixture.request("VALIDATE", text(value))), value); + } + assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", text("'value':'" + "A".repeat(1024) + "','fit':{'maxLines':64,'overflow':'truncate'}"))).get("outcome"), "1024 characters is the most a value may have"); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a face and a size are required, in the element or in the defaults; a wrong default is // + // reported where the scene states it, for the element that takes it, and a default the // + // element does not take is not read // + //////////////////////////////////////////////////////////////////////////////////////////// + String bare = "{'schema':'qqq-zpl-scene/2','design':{'width':'4in','height':'1in'},'elements':[{'id':'t','type':'text','value':'A'%s}]}"; + assertEquals(invalid("/elements/0/font"), refused(SceneFixture.request("VALIDATE", json(String.format(bare, ",'size':'9pt'"))))); + assertEquals(invalid("/elements/0/size"), refused(SceneFixture.request("VALIDATE", json(String.format(bare, ",'font':'qqq-mono'"))))); + String defaults = "{'schema':'qqq-zpl-scene/2','design':{'width':'4in','height':'1in'},'defaults':{%s},'elements':[{'id':'b','type':'box','fill':true,'width':'1mm','height':'1mm'},{'id':'t','type':'text','value':'A'%s}]}"; + assertEquals(invalid("/defaults/size"), refused(SceneFixture.request("VALIDATE", json(String.format(defaults, "'font':'qqq-mono','size':'1001pt'", ""))))); + assertEquals(invalid("/elements/1/size"), refused(SceneFixture.request("VALIDATE", json(String.format(defaults, "'font':'qqq-mono','size':'9pt'", ",'size':'1001pt'"))))); + assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", json(String.format(defaults, "'font':'qqq-mono','size':'1001pt'", ",'size':'9pt'")))).get("outcome")); + assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", json(String.format(defaults, "'size':'9pt'", ",'font':'qqq-mono'")))).get("outcome")); + } + + + + /*************************************************************************** + ** A face the renderer does not bundle is `FONT_UNKNOWN` where the scene + ** names it. Every resolution is read, so a face named only in an override + ** for another printer is refused now and not when that printer is used. + ***************************************************************************/ + @Test + void aFaceThatIsNotBundledIsRefusedByNameAtEveryResolution() + { + for(String font : List.of("qqq-serif", "qqq-sans-italic", "Abel", "QQQ-SANS", "IBM Plex Sans")) + { + assertEquals(Map.of("code", "FONT_UNKNOWN", "severity", "ERROR", "element", "t", "pointer", "/elements/0/font"), refused(SceneFixture.request("VALIDATE", text("'value':'A','font':'" + font + "'"))), font); + } + String defaults = "{'schema':'qqq-zpl-scene/2','design':{'width':'4in','height':'1in'},'defaults':{'font':'Abel','size':'9pt'},'elements':[{'id':'t','type':'text','value':'A'}]}"; + assertEquals(Map.of("code", "FONT_UNKNOWN", "severity", "ERROR", "element", "t", "pointer", "/defaults/font"), refused(SceneFixture.request("RENDER", json(defaults)))); + String override = json(HEAD + "{'id':'t','type':'text','value':'A'}],'overrides':[{'when':{'dpi':[600]},'set':{'t':{'font':'qqq-heavy'}}}]}"); + assertEquals(Map.of("code", "FONT_UNKNOWN", "severity", "ERROR", "element", "t", "pointer", "/overrides/0/set/t/font"), refused(SceneFixture.request("RENDER", override))); + } + + + + /*************************************************************************** + ** A bound value is read from the record when rendering: text as it is, a + ** number or a truth value as JSON writes it. Anything else, or nothing, is + ** `VALUE_MISSING`. Validation reads no record. + ***************************************************************************/ + @Test + void aBoundValueIsReadFromTheRecordOnlyWhenRendering() throws Exception + { + String source = text("'valuePath':'/record/name','maxLength':12,'width':'60mm','height':'6mm'"); + boolean[][] literal = page(SceneFixture.request("RENDER", text("'value':'TEST-0001','width':'60mm','height':'6mm'"))); + assertTrue(Arrays.deepEquals(literal, page(bound("RENDER", source, "TEST-0001")))); + for(String scalar : List.of("12345", "12.5", "true")) + { + ObjectNode request = SceneFixture.request("RENDER", source); + ((ObjectNode) request.get("context")).putObject("record").set("name", Wire.JSON.readTree(scalar)); + assertTrue(Arrays.deepEquals(page(SceneFixture.request("RENDER", text("'value':'" + scalar + "','width':'60mm','height':'6mm'"))), page(request)), scalar); + } + Map missing = Map.of("code", "VALUE_MISSING", "severity", "ERROR", "element", "t", "box", List.of(0, 0, 479, 47)); + assertEquals(missing, refused(SceneFixture.request("RENDER", source))); + for(String other : List.of("null", "{\"first\":\"A\"}", "[\"A\"]")) + { + ObjectNode request = SceneFixture.request("RENDER", source); + ((ObjectNode) request.get("context")).putObject("record").set("name", Wire.JSON.readTree(other)); + assertEquals(missing, refused(request), other); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // validation accepts the scene with no record, and with a record it would refuse to // + // print: the record is not its business // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", source))); + assertEquals(List.of(), findings(bound("VALIDATE", source, "A value far longer than twelve characters"))); + } + + + + /*************************************************************************** + ** `maxLength` makes a length refusal a design-time event. When the scene is + ** validated, that many of the face's widest character must fit, or the + ** scene is refused; when printing, a longer value is refused before layout. + ** A bound element without `maxLength` is warned about; a literal needs none. + ***************************************************************************/ + @Test + void maxLengthProvesTheFitWhenValidatingAndBoundsTheValueWhenPrinting() throws Exception + { + String proven = text("'valuePath':'/record/name','font':'qqq-mono-bold','maxLength':20,'width':'60mm','height':'6mm'"); + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", proven))); + assertEquals(List.of(), findings(bound("RENDER", proven, "L240611A-RETURNED-01"))); + assertEquals(Map.of("code", "VALUE_TOO_LONG", "severity", "ERROR", "element", "t", "box", List.of(0, 0, 479, 47), "measured", Map.of("characters", 21), "limit", Map.of("characters", 20)), + refused(bound("RENDER", proven, "L240611A-RETURNED-012"))); + + //////////////////////////////////////////////////////////////////////////////////////////// + // 40 of the monospace's characters at 9 pt need 609 dots and more; shrunk to the floor // + // of 6.3 pt they still need 427 of the 319 the box has // + //////////////////////////////////////////////////////////////////////////////////////////// + String unproven = text("'valuePath':'/record/name','font':'qqq-mono-bold','maxLength':40,'width':'40mm','height':'6mm'"); + Map refusal = refused(SceneFixture.request("VALIDATE", unproven)); + assertEquals("TEXT_DOES_NOT_FIT", refusal.get("code")); + assertEquals("t", refusal.get("element")); + assertEquals(List.of(0, 0, 319, 47), refusal.get("box")); + assertEquals(Map.of("widthDots", 319, "heightDots", 47, "lines", 1), refusal.get("limit")); + Map measured = (Map) refusal.get("measured"); + assertEquals(40, measured.get("characters")); + assertEquals(630, measured.get("sizeCentipoints")); + assertTrue((int) measured.get("lines") > 1 && (int) measured.get("widthDots") <= 319, "measured broken at any character at the floor: " + measured); + assertTrue(findings(bound("RENDER", unproven, "SHORT")).isEmpty(), "the record decides when printing"); + + //////////////////////////////////////////////////////////////////////////////////////////// + // with no stated length nothing is proven, which the author is told at validation and // + // at render; the hard limit of 1024 characters still holds // + //////////////////////////////////////////////////////////////////////////////////////////// + String open = text("'valuePath':'/record/name','width':'60mm','height':'6mm'"); + Map warning = Map.of("code", "FIT_NOT_PROVEN", "severity", "WARNING", "element", "t", "box", List.of(0, 0, 479, 47)); + assertEquals(List.of(warning), findings(SceneFixture.request("VALIDATE", open))); + assertEquals(List.of(warning), findings(bound("RENDER", open, "TEST-0001"))); + assertEquals(Map.of("characters", 1025), refused(bound("RENDER", open, "A".repeat(1025))).get("measured")); + assertEquals(Map.of("characters", 1024), refused(bound("RENDER", open, "A".repeat(1025))).get("limit")); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a literal is laid out as it is; its stated length is still its limit // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", text("'value':'TEST-0001'")))); + assertEquals("VALUE_TOO_LONG", refused(SceneFixture.request("VALIDATE", text("'value':'TEST-0001','maxLength':8"))).get("code")); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the proof holds for the worst value: 20 per mille signs, the widest character of the // + // sans, print in the box that proved 20 // + //////////////////////////////////////////////////////////////////////////////////////////// + String sans = text("'valuePath':'/record/name','font':'qqq-sans','size':'8pt','maxLength':20,'width':'90mm','height':'6mm'"); + assertTrue(findings(SceneFixture.request("VALIDATE", sans), "TEXT_DOES_NOT_FIT").isEmpty()); + assertTrue(ink(page(bound("RENDER", sans, "\u2030".repeat(20)))).get(4) > 1000); // per mille + } + + + + /*************************************************************************** + ** A character the face cannot draw as one glyph is refused with a count; the + ** value is drawn whole or not at all. + ***************************************************************************/ + @Test + void aValueTheFaceCannotDrawIsRefusedWithACount() + { + String source = text("'valuePath':'/record/name','maxLength':40"); + assertEquals(Map.of("code", "FONT_MISSING_GLYPH", "severity", "ERROR", "element", "t", "box", List.of(0, 0, 764, 155), "measured", Map.of("missingGlyphs", 3, "characters", 9), "limit", Map.of("missingGlyphs", 0)), + refused(bound("RENDER", source, "A\tB\u4E2DC\uD83D\uDE00DEF"))); // a tab, a CJK ideograph and one emoji + assertEquals("FONT_MISSING_GLYPH", refused(bound("RENDER", source, "line\nbreak")).get("code")); + assertEquals("FONT_MISSING_GLYPH", refused(SceneFixture.request("VALIDATE", text("'value':'e\u0301'"))).get("code")); // e and a combining acute + } + + + + /*************************************************************************** + ** The default fit: one line, shrink to 70% of the size and not below 5 pt, + ** then refuse. The refusal names the element and gives the measured width, + ** height, lines and size against the box. + ***************************************************************************/ + @Test + void theDefaultIsOneLineShrunkToSeventyPercentThenRefused() throws Exception + { + String value = "'value':'(01)00012345678905(10)L240611A','font':'qqq-mono-bold','height':'8mm'"; + assertEquals(List.of(), findings(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'90mm'")))); + + Map shrunk = findings(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'60mm'")), "TEXT_SHRUNK").get(0); + assertEquals("INFO", shrunk.get("severity")); + assertEquals(List.of(0, 0, 479, 63), shrunk.get("box")); + assertEquals(Map.of("sizeCentipoints", 1000, "floorCentipoints", 700), shrunk.get("limit")); + int chosen = (int) ((Map) shrunk.get("measured")).get("sizeCentipoints"); + assertTrue(chosen < 1000 && chosen >= 700 && chosen % 25 == 0, "a quarter-point step: " + chosen); + assertEquals(findings(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'60mm'"))), findings(SceneFixture.request("VALIDATE", text(value + ",'size':'10pt','width':'60mm'")))); + + Map refusal = refused(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'40mm'"))); + assertEquals("TEXT_DOES_NOT_FIT", refusal.get("code")); + assertEquals(List.of(0, 0, 319, 63), refusal.get("box")); + assertEquals(Map.of("widthDots", 319, "heightDots", 63, "lines", 1), refusal.get("limit")); + Map measured = (Map) refusal.get("measured"); + assertEquals(List.of(700, 30, 2), List.of(measured.get("sizeCentipoints"), measured.get("characters"), measured.get("lines"))); + assertEquals(refusal, refused(SceneFixture.request("VALIDATE", text(value + ",'size':'10pt','width':'40mm'")))); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the floor is 70% of the size, 5 pt when that is less, and the size itself when the // + // size is under 5 pt; a stated floor is used as it is // + //////////////////////////////////////////////////////////////////////////////////////////// + for(int[] sizes : new int[][] { {10, 700}, {8, 560}, {7, 500}, {6, 500}, {4, 400}}) + { + Map small = refused(SceneFixture.request("RENDER", text(value + ",'size':'" + sizes[0] + "pt','width':'10mm'"))); + assertEquals(sizes[1], ((Map) small.get("measured")).get("sizeCentipoints"), sizes[0] + " pt"); + } + Map stated = refused(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'10mm','fit':{'shrinkTo':'1mm'}"))); + assertEquals(283, ((Map) stated.get("measured")).get("sizeCentipoints"), "1 mm is 2.835 pt"); + assertEquals("TEXT_DOES_NOT_FIT", refused(SceneFixture.request("RENDER", text(value + ",'size':'10pt','width':'60mm','fit':{'shrinkTo':'10pt'}"))).get("code"), "a floor at the size allows no shrinking"); + } + + + + /*************************************************************************** + ** The fit an element may choose instead: more lines, and cutting with an + ** ellipsis. Each is reported: lines as information, a cut as a warning with + ** how many characters are shown. + ***************************************************************************/ + @Test + void wrappingAndTruncationAreChosenByTheElementAndReported() throws Exception + { + String value = "'value':'(01)00012345678905(10)L240611A-RETURNED-000123','font':'qqq-mono-bold','size':'10pt','width':'45mm','height':'12mm'"; + assertEquals("TEXT_DOES_NOT_FIT", refused(SceneFixture.request("RENDER", text(value))).get("code")); + + List> wrapped = findings(SceneFixture.request("RENDER", text(value + ",'fit':{'maxLines':2}"))); + assertEquals(List.of("TEXT_SHRUNK", "TEXT_WRAPPED"), wrapped.stream().map(finding -> finding.get("code")).toList()); + assertEquals(Map.of("code", "TEXT_WRAPPED", "severity", "INFO", "element", "t", "box", List.of(0, 0, 359, 95), "measured", Map.of("lines", 2), "limit", Map.of("lines", 2)), wrapped.get(1)); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the line height is the distance between baselines as a multiple of the size. The text // + // is shrunk to 9 pt: at 1 its lines are 26 dots apart, where the face's own 1.32 is 34 // + //////////////////////////////////////////////////////////////////////////////////////////// + List natural = ink(page(SceneFixture.request("RENDER", text(value + ",'fit':{'maxLines':2}")))); + List tight = ink(page(SceneFixture.request("RENDER", text(value + ",'fit':{'maxLines':2},'lineHeight':1")))); + assertEquals(List.of(natural.get(0), natural.get(1), natural.get(2), natural.get(3) - 8), tight.subList(0, 4)); + assertEquals(tight, ink(page(SceneFixture.request("RENDER", text(value + ",'fit':{'maxLines':2},'lineHeight':1.000"))))); + assertEquals(natural.get(3) - 5, ink(page(SceneFixture.request("RENDER", text(value + ",'fit':{'maxLines':2},'lineHeight':1.125")))).get(3), "9 pt x 1.125 is 28.5 dots, drawn 29 apart"); + + List> cut = findings(SceneFixture.request("RENDER", text(value + ",'fit':{'overflow':'truncate'}"))); + assertEquals(List.of("TEXT_SHRUNK", "TEXT_TRUNCATED"), cut.stream().map(finding -> finding.get("code")).toList(), "a text is cut at the floor size, so it is shrunk as well"); + assertEquals(Map.of("sizeCentipoints", 700), cut.get(0).get("measured")); + assertEquals("WARNING", cut.get(1).get("severity")); + assertEquals(Map.of("lines", 1), cut.get(1).get("limit")); + Map measured = (Map) cut.get(1).get("measured"); + assertEquals(List.of(46, 1), List.of(measured.get("characters"), measured.get("lines"))); + assertTrue((int) measured.get("shownCharacters") > 20 && (int) measured.get("shownCharacters") < 46, "shown " + measured); + + //////////////////////////////////////////////////////////////////////////////////////////// + // cut, the line ends in the three dots of the ellipsis, which the whole value does not: // + // the last ink is lower than the capitals are and near the right of the box // + //////////////////////////////////////////////////////////////////////////////////////////// + boolean[][] page = page(SceneFixture.request("RENDER", text(value + ",'fit':{'overflow':'truncate'},'align':'right'"))); + List ink = ink(page); + assertTrue(ink.get(2) <= 24 + 359 && ink.get(2) >= 24 + 359 - 6, "against the right of the box: " + ink); + int column = ink.get(2) - 1; + int first = 0; + while(!page[first][column]) + { + first++; + } + assertTrue(first > ink.get(1) + (ink.get(3) - ink.get(1)) / 2, "the last character is dots on the baseline"); + } + + + + /*************************************************************************** + ** Small type is warned about, by the height of its capitals in dots at the + ** render target: any face under 12 dots, and a regular weight under 20. A + ** resolution override is how a scene answers: a heavier face or a higher + ** threshold for the coarse printer only. + ***************************************************************************/ + @Test + void smallTypeIsWarnedAboutAndAnOverrideAnswersForOneResolution() throws Exception + { + String small = text("'value':'Lot 0O1lI','font':'qqq-sans','size':'5.5pt'"); + Map tiny = Map.of("code", "TEXT_SMALL_FOR_DPI", "severity", "WARNING", "element", "t", "box", List.of(0, 0, 764, 155), "measured", Map.of("capHeightDots", 10, "sizeCentipoints", 550), "limit", Map.of("capHeightDots", 12)); + Map light = Map.of("code", "TEXT_LIGHT_FACE", "severity", "WARNING", "element", "t", "box", List.of(0, 0, 764, 155), "measured", Map.of("capHeightDots", 10, "sizeCentipoints", 550), "limit", Map.of("capHeightDots", 20)); + assertEquals(List.of(tiny, light), findings(SceneFixture.request("RENDER", small))); + assertEquals(List.of(tiny, light), findings(SceneFixture.request("VALIDATE", small))); + assertEquals(List.of("TEXT_LIGHT_FACE"), findings(SceneFixture.request("RENDER", text("'value':'Lot 0O1lI','font':'qqq-mono','size':'9pt'"))).stream().map(finding -> finding.get("code")).toList()); + assertEquals(List.of("TEXT_SMALL_FOR_DPI"), findings(SceneFixture.request("RENDER", text("'value':'Lot 0O1lI','font':'qqq-mono-bold','size':'5.5pt'"))).stream().map(finding -> finding.get("code")).toList()); + assertEquals(List.of(), findings(SceneFixture.request("RENDER", text("'value':'Lot 0O1lI','font':'qqq-sans','size':'11pt'")))); + assertEquals(List.of(), findings(SceneFixture.request("RENDER", small).put("targetDpi", 600)), "the same type is 31 dots high at 600 dpi"); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a bound element is judged at its stated size when validated, and at the size it was // + // shrunk to when rendered // + //////////////////////////////////////////////////////////////////////////////////////////// + String shrinking = text("'valuePath':'/record/name','font':'qqq-sans-bold','size':'8pt','width':'28mm','height':'5mm','fit':{'shrinkTo':'5pt'}"); + assertEquals(List.of("FIT_NOT_PROVEN"), findings(SceneFixture.request("VALIDATE", shrinking)).stream().map(finding -> finding.get("code")).toList()); + assertEquals(List.of("FIT_NOT_PROVEN", "TEXT_SHRUNK", "TEXT_SMALL_FOR_DPI"), findings(bound("RENDER", shrinking, "L240611A-RETURNED-000123")).stream().map(finding -> finding.get("code")).toList()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the override: bold and a heavier threshold at 203 dpi only // + //////////////////////////////////////////////////////////////////////////////////////////// + String plain = json(HEAD + "{'id':'t','type':'text','value':'Lot 0O1lI','font':'qqq-sans','size':'8pt'}]}"); + String heavier = json(HEAD + "{'id':'t','type':'text','value':'Lot 0O1lI','font':'qqq-sans','size':'8pt'}],'overrides':[{'when':{'dpi':[203]},'set':{'t':{'threshold':200}}}]}"); + String bolder = json(HEAD + "{'id':'t','type':'text','value':'Lot 0O1lI','font':'qqq-sans','size':'8pt'}],'overrides':[{'when':{'dpi':[203]},'set':{'t':{'font':'qqq-sans-bold'}}}]}"); + int ink = ink(page(SceneFixture.request("RENDER", plain))).get(4); + assertTrue(ink(page(SceneFixture.request("RENDER", heavier))).get(4) > ink * 23 / 20, "a threshold of 200 prints heavier than 128"); + assertTrue(ink(page(SceneFixture.request("RENDER", bolder))).get(4) > ink * 23 / 20, "the bold face prints heavier than the regular"); + assertEquals(List.of("TEXT_LIGHT_FACE"), findings(SceneFixture.request("RENDER", heavier)).stream().map(finding -> finding.get("code")).toList()); + assertEquals(List.of(), findings(SceneFixture.request("RENDER", bolder))); + for(String scene : List.of(heavier, bolder)) + { + assertTrue(Arrays.deepEquals(page(SceneFixture.request("RENDER", plain).put("targetDpi", 300)), page(SceneFixture.request("RENDER", scene).put("targetDpi", 300))), "at 300 dpi the override does not apply"); + } + } + + + + /*************************************************************************** + ** Reverse text is white letters on its own box filled black: the picture is + ** the plain one with every dot of the box reversed. It is counted twice + ** against what one scene may paint, since it paints the box and then the + ** letters. + ***************************************************************************/ + @Test + void reverseTextIsWhiteOnItsOwnBlackBox() throws Exception + { + String element = "'value':'ZONE 7','size':'14pt','x':'5mm','y':'3mm','width':'30mm','height':'8mm','align':'center','valign':'middle'"; + boolean[][] plain = page(SceneFixture.request("RENDER", text(element))); + boolean[][] reverse = page(SceneFixture.request("RENDER", text(element + ",'reverse':true"))); + assertTrue(ink(plain).get(4) > 800); + for(int y = 0; y < plain.length; y++) + { + for(int x = 0; x < plain[y].length; x++) + { + boolean inside = x >= 24 + 40 && x < 24 + 40 + 239 && y >= 24 + 24 && y < 24 + 24 + 63; + assertEquals(inside != plain[y][x], reverse[y][x], "dot " + x + ", " + y); + assertFalse(plain[y][x] && !inside, "plain ink outside the box at " + x + ", " + y); + } + } + assertEquals(List.of(), findings(SceneFixture.request("RENDER", text(element + ",'reverse':true")))); + + //////////////////////////////////////////////////////////////////////////////////////////// + // sixteen plain texts the size of the label are sixteen coats and are allowed; eight // + // reverse ones are too, and a ninth is refused as painting 1800% of the label // + //////////////////////////////////////////////////////////////////////////////////////////// + StringBuilder plainTexts = new StringBuilder(); + StringBuilder reverseTexts = new StringBuilder(); + for(int index = 0; index < 16; index++) + { + plainTexts.append(index == 0 ? "" : ",").append("{'id':'p").append(index).append("','type':'text','value':'A'}"); + } + for(int index = 0; index < 9; index++) + { + reverseTexts.append(index == 0 ? "" : ",").append("{'id':'r").append(index).append("','type':'text','value':'A','reverse':true}"); + } + assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", scene(plainTexts.toString()))).get("outcome")); + assertEquals(Map.of("code", "SCENE_INVALID", "severity", "ERROR", "element", "r8", "pointer", "/elements/8", "box", List.of(0, 0, 764, 155), "measured", Map.of("paintedPercent", 1800), "limit", Map.of("paintedPercent", 1600)), + refused(SceneFixture.request("VALIDATE", scene(reverseTexts.toString())))); + } + + + + /*************************************************************************** + ** Rotation turns the text clockwise in a box given as it appears on the + ** label: turned a quarter, the line runs down the box, is fitted to the + ** box's height and aligned along it. + ***************************************************************************/ + @Test + void rotationTurnsTheTextInABoxGivenAsItAppears() throws Exception + { + String element = "'value':'TEST-001','font':'qqq-mono-bold','size':'10pt','x':'10mm','width':'6mm','height':'19mm'"; + assertEquals("TEXT_DOES_NOT_FIT", refused(SceneFixture.request("RENDER", text(element + ",'fit':{'shrinkTo':'10pt'}"))).get("code"), "upright, eight letters do not fit 6 mm"); + for(int rotation : List.of(90, 270)) + { + List ink = ink(page(SceneFixture.request("RENDER", text(element + ",'fit':{'shrinkTo':'10pt'},'rotation':" + rotation)))); + assertTrue(ink.get(0) >= 24 + 80 && ink.get(2) <= 24 + 80 + 47 && ink.get(1) >= 24 && ink.get(3) <= 24 + 151, rotation + ": " + ink); + assertTrue(ink.get(3) - ink.get(1) > 3 * (ink.get(2) - ink.get(0)), "the line runs down the box: " + ink); + assertEquals(rotation == 90, ink.get(1) < 24 + 4, "its start is at the top when turned clockwise, at the bottom when turned the other way: " + ink); + } + List upright = ink(page(SceneFixture.request("RENDER", text("'value':'TEST-0001','font':'qqq-mono-bold','size':'10pt','width':'40mm','height':'6mm'")))); + List turned = ink(page(SceneFixture.request("RENDER", text("'value':'TEST-0001','font':'qqq-mono-bold','size':'10pt','width':'40mm','height':'6mm','rotation':180")))); + assertEquals(upright.get(4), turned.get(4)); + assertEquals(List.of(24 + 319 - (upright.get(2) - 24), 24 + 47 - (upright.get(3) - 24)), List.of(turned.get(0), turned.get(1)), "the same picture turned about the middle of the box"); + } + + + + /*************************************************************************** + ** The prefix `qqq-` belongs to the bundled faces. A request that supplies an + ** asset under that prefix could shadow one, so a text element refuses it + ** with the count, whatever face the element itself names. + ***************************************************************************/ + @Test + void aSuppliedAssetWithTheReservedPrefixIsRefused() throws Exception + { + byte[] font; + try(InputStream stream = Face.class.getResourceAsStream("/fonts/" + Face.MONO.file())) + { + font = stream.readAllBytes(); + } + String source = text("'value':'TEST-0001','font':'qqq-sans-bold'"); + for(String name : List.of("qqq-sans-bold", "qqq-brand")) + { + ObjectNode request = SceneFixture.request("RENDER", source); + ((ArrayNode) request.get("assets")).addObject().put("name", name).put("mediaType", "font/ttf").put("base64", Base64.getEncoder().encodeToString(font)).put("sha256", Wire.sha256(font)).put("fontFamily", "Brand"); + assertEquals(Map.of("code", "RESERVED_FONT_NAME", "severity", "ERROR", "element", "t", "box", List.of(0, 0, 764, 155), "measured", Map.of("reservedAssets", 1), "limit", Map.of("reservedAssets", 0)), refused(request), name); + request.put("operation", "VALIDATE"); + assertEquals("RESERVED_FONT_NAME", refused(request).get("code")); + } + ObjectNode other = SceneFixture.request("RENDER", source); + ((ArrayNode) other.get("assets")).addObject().put("name", "brand-sans").put("mediaType", "font/ttf").put("base64", Base64.getEncoder().encodeToString(font)).put("sha256", Wire.sha256(font)).put("fontFamily", "Brand"); + assertEquals(List.of(), findings(other)); + assertEquals("FONT_UNKNOWN", refused(SceneFixture.request("RENDER", text("'value':'TEST-0001','font':'brand-sans'"))).get("code"), "a supplied font is not a face of version 2 text yet"); + } + + + + /*************************************************************************** + ** No answer and no exception carries a value: the record holds a marker, + ** the element is refused in every way a value can cause, with and without + ** collecting, and the marker is nowhere in what comes back. + ***************************************************************************/ + @Test + void noRefusalCarriesTheValue() throws Exception + { + String marker = "Jane-Example-0012345"; + List elements = List.of("'valuePath':'/record/name','maxLength':8", "'valuePath':'/record/name','width':'10mm'", "'valuePath':'/record/name','width':'10mm','fit':{'overflow':'truncate','maxLines':2}", + "'valuePath':'/record/name','font':'qqq-mono','size':'5pt'", "'valuePath':'/record/missing'", "'valuePath':'/record/name','rotation':90,'reverse':true,'width':'4mm'"); + for(String element : elements) + { + for(String value : List.of(marker, marker + "\t" + marker, marker + "\u4E2D")) // a CJK ideograph + { + for(boolean collect : List.of(false, true)) + { + ObjectNode request = bound("RENDER", text(element), value); + if(collect) + { + request.put("diagnostics", "COLLECT"); + } + String answer; + try + { + Map answered = new LinkedHashMap<>(RendererMain.process(request)); + answered.remove("base64"); + answer = Wire.JSON.writeValueAsString(answered); + } + catch(Refusal refusal) + { + answer = refusal.getMessage() + " " + refusal + " " + Wire.JSON.writeValueAsString(refusal.diagnostic().wire()); + } + assertFalse(answer.contains("Jane") || answer.contains("0012345"), element + ": " + answer); + } + } + } + assertThrows(Refusal.class, () -> RendererMain.process(bound("RENDER", text(elements.get(0)), marker))); + } +} diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java new file mode 100644 index 0000000..9da8db4 --- /dev/null +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java @@ -0,0 +1,600 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import com.kingsrook.qbits.renderer.scene2.Scene2; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** The fit rules, by example and as properties over seeded, deterministic + ** generators (fixed seeds, no clock): text, face, box, size, floor, lines and + ** resolution. + *******************************************************************************/ +class TextFitTest +{ + static final long[] SEEDS = {20261112L, 7L, 4242L}; + static final int CASES = 600; + + + + /*************************************************************************** + ** One generated case. + ***************************************************************************/ + record Case(TextFit.Request request, String text) + { + /************************************************************************ + ** The same case with another nominal size and floor, and no cutting. + ************************************************************************/ + Case at(int nominal, int floor) + { + TextFit.Request from = request; + return (new Case(new TextFit.Request(from.face(), from.width(), from.height(), from.dpi(), nominal, floor, from.lineHeight(), from.maxLines(), false), text)); + } + + + + /************************************************************************ + ** The same case for another text. + ************************************************************************/ + Case of(String other) + { + return (new Case(request, other)); + } + + + + /************************************************************************ + ** Fit it. + ************************************************************************/ + TextFit.Block fit() + { + return (TextFit.fit(request, request.face().glyphs(text), request.face().glyph(TextFit.MARK))); + } + } + + + + /*************************************************************************** + ** A request in a box, with the face's own line pitch, one line, no cutting. + ***************************************************************************/ + static TextFit.Request request(Face face, int width, int height, int nominal, int floor) + { + return (new TextFit.Request(face, width, height, 203, nominal, floor, null, 1, false)); + } + + + + /*************************************************************************** + ** The same request with more lines, and cutting or not. + ***************************************************************************/ + static TextFit.Request lines(TextFit.Request request, int maxLines, boolean truncate) + { + return (new TextFit.Request(request.face(), request.width(), request.height(), request.dpi(), request.nominal(), request.floor(), request.lineHeight(), maxLines, truncate)); + } + + + + /*************************************************************************** + ** Fit a text of a face's own characters. + ***************************************************************************/ + static TextFit.Block fit(TextFit.Request request, String text) + { + return (new Case(request, text).fit()); + } + + + + /*************************************************************************** + ** The characters of each line, with `~` where the ellipsis is. + ***************************************************************************/ + static List shown(TextFit.Block block, String text) + { + return (block.lines().stream().map(line -> text.substring(line.from(), line.to()) + (line.marked() ? "~" : "")).toList()); + } + + + + /*************************************************************************** + ** A generated case: labels are small boxes, short values and type from 5 to + ** 30 pt. A third of the texts have no space, as identifiers do. + ***************************************************************************/ + static Case generate(Random random) + { + Face face = Face.all().get(random.nextInt(Face.all().size())); + int dpi = Scene2.RESOLUTIONS.get(random.nextInt(3)); + int nominal = 5000 + random.nextInt(101) * 250 + (random.nextInt(4) == 0 ? random.nextInt(250) : 0); + int floor = switch(random.nextInt(4)) + { + case 0 -> nominal; + case 1 -> Math.max(1000, nominal * 7 / 10); + default -> 1000 + random.nextInt(nominal - 999); + }; + Integer lineHeight = random.nextInt(3) == 0 ? Integer.valueOf(700 + random.nextInt(1500)) : null; + int width = (20 + random.nextInt(700)) * dpi / 203; + int height = (8 + random.nextInt(160)) * dpi / 203; + String alphabet = switch(random.nextInt(3)) + { + case 0 -> "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-()/."; + case 1 -> "abcdefghijklmnopqrstuvwxyzWMfjgyÅé‰ "; // A ring, e acute, per mille + default -> "il1.,' WM@‰⁄ǺĢ "; // per mille, fraction slash, A ring acute, G cedilla: the widest and furthest-reaching + }; + StringBuilder text = new StringBuilder(); + int length = random.nextInt(48); + boolean spaces = random.nextInt(3) != 0; + for(int index = 0; index < length; index++) + { + text.append(spaces && random.nextInt(6) == 0 ? ' ' : alphabet.charAt(random.nextInt(alphabet.length()))); + } + return (new Case(new TextFit.Request(face, width, height, dpi, nominal, floor, lineHeight, 1 + random.nextInt(4), random.nextInt(3) == 0), text.toString())); + } + + + + /*************************************************************************** + ** Dots are thousandths of the em times the size times the resolution over + ** 72 000 000, rounded down, up or to the nearest: checked against exact + ** decimal arithmetic, negative lengths included. + ***************************************************************************/ + @Test + void theScaleRoundsExactly() + { + Random random = new Random(SEEDS[0]); + for(int index = 0; index < 5000; index++) + { + TextFit.Scale scale = new TextFit.Scale(1000 + random.nextInt(999_001), Scene2.RESOLUTIONS.get(random.nextInt(3))); + long units = random.nextInt(3_000_001) - 1_500_000L; + BigDecimal exact = BigDecimal.valueOf(units).multiply(BigDecimal.valueOf(scale.milliPoints())).multiply(BigDecimal.valueOf(scale.dpi())).divide(BigDecimal.valueOf(72_000_000L), 12, RoundingMode.HALF_EVEN); + assertEquals(exact.setScale(0, RoundingMode.FLOOR).intValueExact(), scale.floor(units)); + assertEquals(exact.setScale(0, RoundingMode.CEILING).intValueExact(), scale.ceil(units)); + assertEquals(exact.add(new BigDecimal("0.5")).setScale(0, RoundingMode.FLOOR).intValueExact(), scale.round(units)); + } + assertEquals(25.375f, new TextFit.Scale(9000, 203).size()); + assertEquals(100f, new TextFit.Scale(12_000, 600).size()); + assertEquals(List.of(25, 26, 25), List.of(new TextFit.Scale(9000, 203).floor(1000), new TextFit.Scale(9000, 203).ceil(1000), new TextFit.Scale(9000, 203).round(1000))); + assertEquals(List.of(-26, -25, -25), List.of(new TextFit.Scale(9000, 203).floor(-1000), new TextFit.Scale(9000, 203).ceil(-1000), new TextFit.Scale(9000, 203).round(-1000))); + } + + + + /*************************************************************************** + ** The default: one line. A text that fits at its size keeps it; one that + ** does not is reduced a quarter point at a time to the largest size that + ** fits; one that does not fit at the floor is refused with what it + ** measured there. + ***************************************************************************/ + @Test + void oneLineShrinksToTheLargestSizeThatFitsThenRefuses() + { + //////////////////////////////////////////////////////////////////////////////////////////// + // 9 pt at 203 dpi is 25.375 dots to the em and the monospace advances 0.6 em: 12 letters // + // are 183 dots, and the line is 2 dots wider on each inked side // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block fits = fit(request(Face.MONO_BOLD, 200, 40, 9000, 6300), "ABCDEFGHIJKL"); + assertTrue(fits.fits() && !fits.truncated()); + assertEquals(9000, fits.milliPoints()); + assertEquals(List.of("ABCDEFGHIJKL"), shown(fits, "ABCDEFGHIJKL")); + assertEquals(12, fits.characters()); + assertTrue(fits.width() >= 183 && fits.width() <= 187, "width " + fits.width()); + assertEquals(fits.width(), fits.lines().get(0).width()); + assertEquals(List.of(26, 34), List.of(fits.baseline(), fits.height()), "ascent 1.02 em and descent 0.3 em, each rounded up"); + + TextFit.Block shrunk = fit(request(Face.MONO_BOLD, 160, 40, 9000, 6300), "ABCDEFGHIJKL"); + assertTrue(shrunk.fits() && shrunk.milliPoints() < 9000 && shrunk.milliPoints() >= 6300 && shrunk.milliPoints() % 250 == 0); + assertTrue(shrunk.width() <= 160); + assertFalse(fit(request(Face.MONO_BOLD, 160, 40, shrunk.milliPoints() + 250, shrunk.milliPoints() + 250), "ABCDEFGHIJKL").fits(), "a quarter point larger does not fit"); + + TextFit.Block refused = fit(request(Face.MONO_BOLD, 100, 40, 9000, 6300), "ABCDEFGHIJKL"); + assertFalse(refused.fits()); + assertEquals(6300, refused.milliPoints()); + assertTrue(refused.lines().size() > 1 && refused.width() <= 100, "measured broken at any character: " + refused); + assertEquals(12, refused.shown()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the floor need not be on the quarter-point grid from the size: it is the last size // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block floor = fit(request(Face.MONO_BOLD, 134, 40, 9000, 6400), "ABCDEFGHIJKL"); + assertTrue(floor.fits()); + assertEquals(6400, floor.milliPoints()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // too tall is refused as too wide is: the box is 20 dots high and the floor needs 25 // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block tall = fit(request(Face.MONO_BOLD, 400, 20, 9000, 6300), "ABC"); + assertFalse(tall.fits()); + assertTrue(tall.height() > 20 && tall.lines().size() == 1); + } + + + + /*************************************************************************** + ** Nothing to draw always fits: an empty value, or one of spaces only. + ** Spaces at the end of a text take no room; spaces at its start do. + ***************************************************************************/ + @Test + void spacesAtTheEndTakeNoRoom() + { + for(String blank : List.of("", " ", " ")) + { + TextFit.Block block = fit(request(Face.SANS, 1, 1, 9000, 9000), blank); + assertTrue(block.fits() && block.lines().isEmpty() && !block.truncated()); + assertEquals(List.of(0, 0, 0, 0), List.of(block.width(), block.height(), block.characters(), block.shown())); + } + TextFit.Request request = request(Face.SANS_BOLD, 300, 40, 9000, 9000); + TextFit.Block plain = fit(request, "AB"); + assertEquals(plain, fit(request, "AB ")); + TextFit.Block led = fit(request, " AB"); + int shift = new TextFit.Scale(9000, 203).round(2L * Face.SANS_BOLD.glyph(' ').advance()); + assertTrue(shift > 8 && led.width() >= plain.width() + shift - 2 * TextFit.SLOP && led.width() <= plain.width() + shift + 1, plain.width() + " then " + led.width()); + assertEquals(4, led.characters()); + } + + + + /*************************************************************************** + ** With more lines allowed, a line is broken between words while that fits, + ** and at any character when it does not: a larger size is preferred to + ** whole words, and a value with no space wraps. + ***************************************************************************/ + @Test + void linesBreakBetweenWordsAndThenAtAnyCharacter() + { + //////////////////////////////////////////////////////////////////////////////////////////// + // the monospace at 9 pt, 203 dpi advances 15.225 dots: a 100 dot box holds 6 letters // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Request box = request(Face.MONO, 100, 200, 9000, 9000); + assertEquals(List.of("AAA", "BBB", "CCC"), shown(fit(lines(box, 3, false), "AAA BBB CCC"), "AAA BBB CCC")); + assertEquals(List.of("AAA BB", "CCC"), shown(fit(lines(box, 2, false), "AAA BB CCC"), "AAA BB CCC"), "spaces at a break are dropped"); + assertEquals(List.of("AAA BB", "B CCC"), shown(fit(lines(box, 2, false), "AAA BBB CCC"), "AAA BBB CCC"), "two lines only when broken at any character"); + assertEquals(List.of("L24061", "1A-RET", "URNED"), shown(fit(lines(box, 3, false), "L240611A-RETURNED"), "L240611A-RETURNED")); + assertEquals(9000, fit(lines(box, 2, false), "AAA BBB CCC").milliPoints()); + + TextFit.Block refused = fit(lines(box, 2, false), "L240611A-RETURNED"); + assertFalse(refused.fits()); + assertEquals(3, refused.lines().size()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a stated line height sets the distance between baselines; the block is one ascent, // + // the pitches between, and one descent // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block natural = fit(lines(box, 3, false), "AAA BBB CCC"); + assertEquals(List.of(34, 26, 26 + 2 * 34 + 8), List.of(natural.pitch(), natural.baseline(), natural.height())); + TextFit.Block tight = TextFit.fit(new TextFit.Request(Face.MONO, 100, 200, 203, 9000, 9000, 1000, 3, false), Face.MONO.glyphs("AAA BBB CCC"), null); + assertEquals(List.of(26, 26, 26 + 2 * 26 + 8), List.of(tight.pitch(), tight.baseline(), tight.height())); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a character wider than the box stands alone on a line that does not fit // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block narrow = fit(lines(request(Face.MONO, 10, 200, 9000, 9000), 4, false), "AB"); + assertFalse(narrow.fits()); + assertEquals(List.of("A", "B"), shown(narrow, "AB")); + assertTrue(narrow.width() > 10); + } + + + + /*************************************************************************** + ** Cutting happens only when the element asked for it and only when the text + ** fits at no size down to the floor. The last line that fits ends with the + ** ellipsis after as many characters as fit beside it; when not even the + ** ellipsis fits, the text is refused. + ***************************************************************************/ + @Test + void truncationIsOnlyWhenAskedAndAlwaysShowsTheMark() + { + String text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + TextFit.Request box = request(Face.MONO, 100, 80, 9000, 9000); + assertFalse(fit(box, text).fits()); + assertFalse(fit(lines(box, 2, false), text).truncated()); + + TextFit.Block cut = fit(lines(box, 1, true), text); + assertTrue(cut.fits() && cut.truncated()); + assertEquals(List.of("ABCDE~"), shown(cut, text)); + assertEquals(List.of(26, 5), List.of(cut.characters(), cut.shown())); + assertTrue(cut.width() <= 100); + + TextFit.Block two = fit(lines(box, 2, true), text); + assertEquals(List.of("ABCDEF", "GHIJK~"), shown(two, text)); + assertEquals(11, two.shown()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the box is high enough for one line only: the second is given up for the mark // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Block low = fit(lines(request(Face.MONO, 100, 40, 9000, 9000), 3, true), text); + assertEquals(List.of("ABCDE~"), shown(low, text)); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a text that fits is not cut and has no mark, though cutting is allowed; one that fits // + // after shrinking is shrunk, not cut // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of("ABCDEF"), shown(fit(lines(box, 1, true), "ABCDEF"), "ABCDEF")); + TextFit.Block shrunk = fit(lines(request(Face.MONO, 100, 80, 9000, 6000), 1, true), "ABCDEFGH"); + assertTrue(shrunk.fits() && !shrunk.truncated() && shrunk.milliPoints() < 9000); + + //////////////////////////////////////////////////////////////////////////////////////////// + // spaces before the mark are dropped; the mark may stand alone; and where it cannot // + // stand at all, or a line is too high, the answer is the refusal // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of("ABC~"), shown(fit(lines(box, 1, true), "ABC DEFGHIJKL"), "ABC DEFGHIJKL")); + assertEquals(List.of("~"), shown(fit(lines(request(Face.MONO, 22, 80, 9000, 9000), 1, true), text), text)); + assertFalse(fit(lines(request(Face.MONO, 12, 80, 9000, 9000), 1, true), text).fits()); + assertFalse(fit(lines(request(Face.MONO, 100, 20, 9000, 9000), 1, true), text).fits()); + assertFalse(fit(lines(request(Face.MONO, 400, 20, 9000, 9000), 1, true), "ABC").fits(), "a line that is too high is too high with the mark"); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the last line of a text is cut too when the text fits at no size: here one letter is // + // wider than the box and the mark is not, and here an accent above the ascent is too // + // high for the box and is given up for the mark // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of("~"), shown(fit(lines(request(Face.SANS, 26, 80, 9000, 9000), 1, true), "\u2030"), "\u2030")); // per mille + TextFit.Request shallow = lines(request(Face.SANS_BOLD, 200, 36, 9000, 9000), 1, true); + assertTrue(fit(shallow, "ABC").fits() && !fit(shallow, "ABC").truncated()); + assertEquals(List.of("AB~"), shown(fit(shallow, "AB\u01FA"), "AB\u01FA")); // A ring acute + assertFalse(fit(lines(shallow, 1, false), "AB\u01FA").fits()); // A ring acute + + //////////////////////////////////////////////////////////////////////////////////////////// + // broken at any character, spaces at the start of a text stay on a line of their own // + // rather than push the first letter out of the box // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of(" ", "ABCDE"), shown(fit(lines(box, 2, false), " ABCDE"), " ABCDE")); + assertEquals(List.of(" ABCD", "E"), shown(fit(lines(box, 2, false), " ABCDE"), " ABCDE")); + } + + + + /*************************************************************************** + ** Property: the answer is a layout inside the box or a refusal whose + ** measurement exceeds its limit. The size is never above the nominal and + ** never below the floor; it is on the quarter-point steps from the nominal + ** or is the floor. The lines are the text in order, whole unless cut, and + ** never more than allowed. A text is cut only when asked, only at the + ** floor, and then its last line carries the mark. + ***************************************************************************/ + @Test + void theAnswerIsALayoutInsideTheBoxOrARefusalThatMeasuresMore() + { + int fitted = 0; + int refused = 0; + int cut = 0; + for(long seed : SEEDS) + { + Random random = new Random(seed); + for(int index = 0; index < CASES; index++) + { + Case generated = generate(random); + TextFit.Request request = generated.request(); + TextFit.Block block = generated.fit(); + String about = "seed " + seed + " case " + index + ": " + request + " for " + generated.text().length() + " characters gave " + block; + String trimmed = generated.text().stripTrailing(); + assertEquals(trimmed.length(), block.characters(), about); + assertTrue(block.milliPoints() <= request.nominal() && block.milliPoints() >= request.floor(), about); + assertTrue(block.milliPoints() == request.floor() || (request.nominal() - block.milliPoints()) % TextFit.STEP_MILLIPOINTS == 0, about); + int next = 0; + for(int line = 0; line < block.lines().size(); line++) + { + TextFit.Line each = block.lines().get(line); + assertTrue(trimmed.substring(next, each.from()).isBlank() && each.to() >= each.from() && each.left() <= 0 && each.width() <= block.width(), about); + assertTrue(each.to() > each.from() || each.marked(), about); + assertTrue(each.to() == each.from() || trimmed.charAt(each.to() - 1) != ' ' || !each.marked(), about + ": a space before the mark"); + assertEquals(each.marked(), block.truncated() && line == block.lines().size() - 1, about); + next = each.to(); + } + assertEquals(block.shown(), next, about); + if(block.fits()) + { + fitted++; + assertTrue(block.lines().size() <= request.maxLines() && block.width() <= request.width() && block.height() <= request.height(), about); + } + else + { + refused++; + assertTrue(block.lines().size() > request.maxLines() || block.width() > request.width() || block.height() > request.height(), about); + assertEquals(request.floor(), block.milliPoints(), about); + assertFalse(block.truncated(), about); + } + if(block.truncated()) + { + cut++; + assertTrue(request.truncate() && block.fits() && block.milliPoints() == request.floor() && block.shown() < block.characters(), about); + assertFalse(generated.at(request.floor(), request.floor()).fit().fits(), about); + } + else + { + assertEquals(trimmed.length(), block.shown(), about); + } + } + } + assertTrue(fitted > 300 && refused > 300 && cut > 50, "the cases must reach every outcome: " + fitted + " fitted, " + refused + " refused, " + cut + " cut"); + } + + + + /*************************************************************************** + ** Property: a text that fits at its nominal size is never shrunk, and the + ** size chosen is the largest that fits: the step above it does not. + ***************************************************************************/ + @Test + void aTextThatFitsIsNeverShrunkAndTheChosenSizeIsTheLargestThatFits() + { + int kept = 0; + int shrunk = 0; + for(long seed : SEEDS) + { + Random random = new Random(seed); + for(int index = 0; index < CASES; index++) + { + Case generated = generate(random); + TextFit.Request request = generated.request(); + TextFit.Block block = generated.fit(); + String about = "seed " + seed + " case " + index + ": " + request + " gave " + block; + TextFit.Block nominal = generated.at(request.nominal(), request.nominal()).fit(); + if(nominal.fits()) + { + kept++; + assertEquals(nominal, block, about); + assertEquals(request.nominal(), block.milliPoints(), about); + } + else if(block.fits() && !block.truncated()) + { + shrunk++; + assertTrue(block.milliPoints() < request.nominal(), about); + int steps = (request.nominal() - block.milliPoints() - 1) / TextFit.STEP_MILLIPOINTS; + int above = request.nominal() - steps * TextFit.STEP_MILLIPOINTS; + assertTrue(above > block.milliPoints() && above - block.milliPoints() <= TextFit.STEP_MILLIPOINTS, about); + assertFalse(generated.at(above, above).fit().fits(), about + ", yet it fits at " + above); + assertEquals(block, generated.at(block.milliPoints(), block.milliPoints()).fit(), about); + } + } + } + assertTrue(kept > 200 && shrunk > 100, "the cases must reach both: " + kept + " kept, " + shrunk + " shrunk"); + } + + + + /*************************************************************************** + ** Property: in the same box a shorter text never gets a smaller size than a + ** longer one that starts with it, and fits whenever the longer one does. + ***************************************************************************/ + @Test + void aShorterTextNeverGetsASmallerSizeThanALongerOne() + { + int compared = 0; + for(long seed : SEEDS) + { + Random random = new Random(seed); + for(int index = 0; index < CASES; index++) + { + Case generated = generate(random); + if(generated.text().isEmpty()) + { + continue; + } + Case all = generated.at(generated.request().nominal(), generated.request().floor()); + TextFit.Block longer = all.fit(); + TextFit.Block shorter = all.of(generated.text().substring(0, random.nextInt(generated.text().length()))).fit(); + String about = "seed " + seed + " case " + index + ": " + all.request() + " gave " + shorter + " and then " + longer; + if(longer.fits()) + { + compared++; + assertTrue(shorter.fits() && shorter.milliPoints() >= longer.milliPoints() && shorter.lines().size() <= longer.lines().size(), about); + } + else + { + assertTrue(!shorter.fits() || shorter.milliPoints() >= longer.milliPoints(), about); + } + } + } + assertTrue(compared > 300, "compared " + compared); + } + + + + /*************************************************************************** + ** Property: when the longest value is proven to fit (that many of the + ** face's worst character), no text of up to that many characters is + ** refused, whatever its characters, with spaces or without, cut or not. + ***************************************************************************/ + @Test + void aProvenLengthImpliesNoRefusalForAnyTextUpToThatLength() + { + int proven = 0; + int tried = 0; + for(long seed : SEEDS) + { + Random random = new Random(seed); + for(int index = 0; index < CASES; index++) + { + Case generated = generate(random); + TextFit.Request request = generated.request(); + Face face = request.face(); + int maxLength = 1 + random.nextInt(40); + Face.Glyph[] worst = new Face.Glyph[maxLength]; + Arrays.fill(worst, face.worst()); + TextFit.Block proof = TextFit.fit(request, worst, face.glyph(TextFit.MARK)); + if(!proof.fits()) + { + continue; + } + proven++; + List drawn = FaceTest.drawn(face); + for(int attempt = 0; attempt < 12; attempt++) + { + StringBuilder text = new StringBuilder(); + int length = attempt == 0 ? maxLength : 1 + random.nextInt(maxLength); + for(int character = 0; character < length; character++) + { + int choice = attempt % 4; + text.appendCodePoint(choice == 0 ? face.widest() : choice == 1 && random.nextInt(5) == 0 ? ' ' : choice == 3 ? "⁄Ǻ̉Wj".charAt(random.nextInt(6)) : drawn.get(random.nextInt(drawn.size()))); + } + tried++; + TextFit.Block block = generated.of(text.toString()).fit(); + assertTrue(block.fits(), () -> "seed " + seed + ": " + request + " proves " + maxLength + " characters with " + proof + " yet refuses " + text.length() + " as " + block); + assertTrue(block.milliPoints() >= proof.milliPoints(), "a real text is never smaller than the proof"); + } + } + } + assertTrue(proven > 150 && tried > 1500, "proven " + proven + ", tried " + tried); + } + + + + /*************************************************************************** + ** The proof agrees with rendering for the widest character: the longest + ** length it proves is drawn, and it is short of the longest that is really + ** drawn by no more than one character a line, which is the room the proof + ** keeps for characters that reach past their advance. + ***************************************************************************/ + @Test + void theProofAgreesWithTheWidestCharacters() + { + for(Face face : Face.all()) + { + for(int dpi : Scene2.RESOLUTIONS) + { + for(int maxLines : List.of(1, 2, 3)) + { + TextFit.Request request = new TextFit.Request(face, 700 * dpi / 203, 150 * dpi / 203, dpi, 11_000, 7000, null, maxLines, false); + int proven = 0; + int drawn = 0; + for(int length = 1; length <= 200; length++) + { + Face.Glyph[] worst = new Face.Glyph[length]; + Arrays.fill(worst, face.worst()); + proven = TextFit.fit(request, worst, null).fits() ? length : proven; + drawn = fit(request, new String(Character.toChars(face.widest())).repeat(length)).fits() ? length : drawn; + } + String about = face.scene() + " at " + dpi + " dpi on " + maxLines + " lines: proven " + proven + ", drawn " + drawn; + assertTrue(proven >= 20 * maxLines && drawn < 200, about); + assertTrue(proven <= drawn && drawn - proven <= maxLines, about); + } + } + } + } +} diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java new file mode 100644 index 0000000..7490073 --- /dev/null +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java @@ -0,0 +1,392 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.kingsrook.qbits.renderer.scene2.text; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import com.kingsrook.qbits.renderer.scene2.Canvas; +import com.kingsrook.qbits.renderer.scene2.Frame; +import com.kingsrook.qbits.renderer.scene2.Layout; +import com.kingsrook.qbits.renderer.scene2.Placement; +import com.kingsrook.qbits.renderer.scene2.Scene2; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** What is drawn is what was measured: the ink of every line is inside the + ** line's measured box, the block is where `align` and `valign` put it, and + ** nothing is clipped. These read the canvas the renderer composes. + *******************************************************************************/ +class TextRasterTest +{ + private static final int MARGIN = 8; + + + + /*************************************************************************** + ** Fit a text and draw it in a box that sits `MARGIN` dots inside a canvas, + ** so that ink outside the box would be seen. The box is given as the text + ** reads; turned a quarter, it is laid on its side. + ***************************************************************************/ + private static Canvas draw(TextFit.Request request, String text, Placement.Align align, Placement.Valign valign, int rotation, int threshold, int bandDots) + { + TextFit.Block block = TextFit.fit(request, request.face().glyphs(text), request.face().glyph(TextFit.MARK)); + assertTrue(block.fits(), "the case must fit: " + request); + boolean upright = rotation % 180 == 0; + Frame frame = new Frame(MARGIN, MARGIN, upright ? request.width() : request.height(), upright ? request.height() : request.width()); + Canvas canvas = new Canvas(frame.width() + 2 * MARGIN, frame.height() + 2 * MARGIN, request.dpi()); + TextRaster.paint(canvas, frame, new TextRaster.Drawing(request.face(), text, block, align, valign, rotation, threshold, true), bandDots); + return (canvas); + } + + + + /*************************************************************************** + ** The box of the ink on a canvas: left, top, right and bottom (the last two + ** exclusive), or null when it is blank. + ***************************************************************************/ + private static Frame ink(Canvas canvas) + { + int left = Integer.MAX_VALUE; + int top = -1; + int right = -1; + int bottom = -1; + for(int y = 0; y < canvas.height(); y++) + { + int first = canvas.firstInk(y); + if(first >= 0) + { + top = top < 0 ? y : top; + bottom = y + 1; + left = Math.min(left, first); + right = Math.max(right, canvas.lastInk(y) + 1); + } + } + return (top < 0 ? null : new Frame(left, top, right - left, bottom - top)); + } + + + + /*************************************************************************** + ** How many dots of a canvas hold ink. + ***************************************************************************/ + private static int dots(Canvas canvas) + { + int dots = 0; + for(int y = 0; y < canvas.height(); y++) + { + for(int x = 0; x < canvas.width(); x++) + { + dots += canvas.get(x, y) ? 1 : 0; + } + } + return (dots); + } + + + + /*************************************************************************** + ** Whether two canvases hold the same picture. + ***************************************************************************/ + private static void assertSamePicture(Canvas expected, Canvas actual, String about) + { + assertEquals(expected.width(), actual.width(), about); + assertEquals(expected.height(), actual.height(), about); + for(int y = 0; y < expected.height(); y++) + { + for(int x = 0; x < expected.width(); x++) + { + if(expected.get(x, y) != actual.get(x, y)) + { + assertEquals(expected.get(x, y), actual.get(x, y), about + ": dot " + x + ", " + y); + } + } + } + } + + + + /*************************************************************************** + ** Every character of every bundled face, at sizes and resolutions labels + ** use, is drawn with all of its ink inside the box that was measured for + ** its line. The renderer itself fails a render whose ink leaves that box + ** (the guard round each line), so drawing them all is the test; the ink is + ** then also read back from the canvas and held to the line's box. + ***************************************************************************/ + @Test + void everyCharacterOfEveryFaceIsDrawnInsideItsMeasuredLine() + { + int[][] sizes = {{203, 6000}, {203, 9000}, {203, 14_250}, {300, 7000}, {300, 11_000}, {600, 5000}, {600, 12_250}}; + for(Face face : Face.all()) + { + List drawn = FaceTest.drawn(face); + for(int[] size : sizes) + { + TextFit.Scale scale = new TextFit.Scale(size[1], size[0]); + int inked = 0; + for(int start = 0; start < drawn.size(); start += 16) + { + StringBuilder text = new StringBuilder(); + drawn.subList(start, Math.min(drawn.size(), start + 16)).forEach(text::appendCodePoint); + TextFit.Request request = new TextFit.Request(face, scale.ceil(1500) * 16 + 16, scale.ceil(2000), size[0], size[1], size[1], null, 1, false); + Canvas canvas = draw(request, text.toString(), Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, TextRaster.BAND_DOTS); + TextFit.Block block = TextFit.fit(request, face.glyphs(text.toString()), null); + Frame ink = ink(canvas); + if(ink != null) + { + inked++; + TextFit.Line line = block.lines().get(0); + Frame measured = new Frame(MARGIN, MARGIN + block.baseline() - line.above(), line.width(), line.above() + line.below()); + assertTrue(measured.contains(ink), () -> face.scene() + " at " + size[1] + " millipoints, " + size[0] + " dpi: ink " + ink + " outside the measured " + measured); + assertTrue(new Frame(MARGIN, MARGIN, block.width(), block.height()).contains(measured)); + } + } + assertTrue(inked >= drawn.size() / 16 - 4, face.scene() + " drew " + inked + " lines"); + } + } + } + + + + /*************************************************************************** + ** Property: for generated texts, faces, boxes, sizes and resolutions, at + ** every rotation, no ink is outside the element's box and none is clipped, + ** and the upright picture turned is the turned picture. Up to 100 dots to + ** the em, where glyphs are drawn as bitmaps, the picture is also exactly + ** the same drawn a row at a time, so bands lose and repeat nothing. + ***************************************************************************/ + @Test + void inkIsNeverOutsideTheBoxAndNeverClipped() + { + Random random = new Random(TextFitTest.SEEDS[0]); + List aligns = List.of(Placement.Align.values()); + List valigns = List.of(Placement.Valign.values()); + int drawn = 0; + int banded = 0; + for(int index = 0; drawn < 160; index++) + { + TextFitTest.Case generated = TextFitTest.generate(random); + if(!generated.fit().fits() || generated.text().isBlank()) + { + continue; + } + drawn++; + TextFit.Request request = generated.request(); + Placement.Align align = aligns.get(random.nextInt(3)); + Placement.Valign valign = valigns.get(random.nextInt(3)); + int threshold = 1 + random.nextInt(254); + String about = "case " + index + ": " + request; + Canvas upright = draw(request, generated.text(), align, valign, 0, threshold, TextRaster.BAND_DOTS); + Frame ink = ink(upright); + Frame box = new Frame(MARGIN, MARGIN, request.width(), request.height()); + assertTrue(ink == null || box.contains(ink), about + ": ink " + ink + " outside " + box); + if(new TextFit.Scale(generated.fit().milliPoints(), request.dpi()).size() <= 100) + { + banded++; + assertSamePicture(upright, draw(request, generated.text(), align, valign, 0, threshold, 1), about + ", row by row"); + } + for(int rotation : List.of(90, 180, 270)) + { + Canvas turned = draw(request, generated.text(), align, valign, rotation, threshold, TextRaster.BAND_DOTS); + Canvas expected = new Canvas(turned.width(), turned.height(), request.dpi()); + for(int y = 0; y < request.height(); y++) + { + for(int x = 0; x < request.width(); x++) + { + if(upright.get(MARGIN + x, MARGIN + y)) + { + int turnedX = rotation == 90 ? request.height() - 1 - y : rotation == 180 ? request.width() - 1 - x : y; + int turnedY = rotation == 90 ? x : rotation == 180 ? request.height() - 1 - y : request.width() - 1 - x; + expected.set(MARGIN + turnedX, MARGIN + turnedY, true); + } + } + } + assertSamePicture(expected, turned, about + ", turned " + rotation); + } + } + assertTrue(banded > 60, "drawn row by row: " + banded); + } + + + + /*************************************************************************** + ** The block sits in the box where `align` and `valign` say, a centred block + ** within one dot of the middle, and each line sits in the block the same + ** way. Read from the ink of a two-line text. + ***************************************************************************/ + @Test + void theBlockIsPlacedByAlignAndValignAndCentredWithinOneDot() + { + String text = "HHHHHHHH HH"; + TextFit.Request request = new TextFit.Request(Face.SANS_BOLD, 241, 151, 203, 12_000, 12_000, null, 2, false); + TextFit.Block block = TextFit.fit(request, Face.SANS_BOLD.glyphs(text), null); + assertEquals(List.of("HHHHHHHH", "HH"), TextFitTest.shown(block, text)); + TextFit.Line wide = block.lines().get(0); + TextFit.Line narrow = block.lines().get(1); + for(Placement.Align align : Placement.Align.values()) + { + for(Placement.Valign valign : Placement.Valign.values()) + { + Canvas canvas = draw(request, text, align, valign, 0, 128, TextRaster.BAND_DOTS); + Frame content = Layout.align(new Frame(MARGIN, MARGIN, 241, 151), block.width(), block.height(), align, valign); + Frame ink = ink(canvas); + assertTrue(content.contains(ink), align + " " + valign + ": ink " + ink + " outside the block " + content); + int slackLeft = content.x() - MARGIN; + int slackRight = MARGIN + 241 - content.right(); + int slackTop = content.y() - MARGIN; + int slackBottom = MARGIN + 151 - content.bottom(); + switch(align) + { + case LEFT -> assertEquals(0, slackLeft); + case CENTER -> assertTrue(slackLeft >= 0 && Math.abs(slackLeft - slackRight) <= 1); + default -> assertEquals(0, slackRight); + } + switch(valign) + { + case TOP -> assertEquals(0, slackTop); + case MIDDLE -> assertTrue(slackTop >= 0 && Math.abs(slackTop - slackBottom) <= 1); + default -> assertEquals(0, slackBottom); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // the ink of each line, read from the rows of its own baseline, is in the line's // + // box, and that box is against the same side of the block (or in its middle) // + ////////////////////////////////////////////////////////////////////////////////////// + int capitals = new TextFit.Scale(12_000, 203).floor(Face.SANS_BOLD.capHeight()); + int first = content.y() + block.baseline() - capitals / 2; + int second = first + block.pitch(); + int narrowLeft = content.x() + align.position().place(block.width(), narrow.width(), 0); + assertTrue(canvas.firstInk(first) >= content.x() && canvas.lastInk(first) < content.x() + wide.width(), "the widest line fills the block"); + assertTrue(canvas.firstInk(second) >= narrowLeft && canvas.lastInk(second) < narrowLeft + narrow.width(), align + ": the short line " + canvas.firstInk(second) + " to " + canvas.lastInk(second)); + int gapLeft = canvas.firstInk(second) - canvas.firstInk(first); + int gapRight = canvas.lastInk(first) - canvas.lastInk(second); + switch(align) + { + case LEFT -> assertTrue(Math.abs(gapLeft) <= 1 && gapRight > 50); + case CENTER -> assertTrue(Math.abs(gapLeft - gapRight) <= 2 && gapLeft > 25); + default -> assertTrue(Math.abs(gapRight) <= 1 && gapLeft > 50); + } + } + } + } + + + + /*************************************************************************** + ** A dot is ink when its grey is darker than the threshold, so a higher + ** threshold prints every dot a lower one prints and more: heavier strokes, + ** which is the control for small type on a thermal head. + ***************************************************************************/ + @Test + void aHigherThresholdPrintsHeavier() + { + TextFit.Request request = new TextFit.Request(Face.SANS, 500, 60, 203, 14_000, 14_000, null, 1, false); + List pictures = new ArrayList<>(); + for(int threshold : List.of(1, 60, 128, 200, 254)) + { + pictures.add(draw(request, "Lot L240611A 0O1lI", Placement.Align.LEFT, Placement.Valign.TOP, 0, threshold, TextRaster.BAND_DOTS)); + } + for(int index = 1; index < pictures.size(); index++) + { + Canvas lighter = pictures.get(index - 1); + Canvas heavier = pictures.get(index); + assertTrue(dots(heavier) > dots(lighter), "threshold step " + index + ": " + dots(lighter) + " then " + dots(heavier)); + for(int y = 0; y < lighter.height(); y++) + { + for(int x = 0; x < lighter.width(); x++) + { + assertFalse(lighter.get(x, y) && !heavier.get(x, y), "a dot printed at the lower threshold is printed at the higher"); + } + } + } + assertTrue(dots(pictures.get(0)) > 100, "full ink is black at every threshold"); + } + + + + /*************************************************************************** + ** Ink outside the measured line is never clipped away and never printed: + ** the render fails. Forced here with lines whose boxes are stated too + ** small: one that ends in the gap between two letters, so the second + ** letter is wholly beyond the guard and only its bounds tell, and two that + ** cut through the letters, whose ink is found in the guard. + ***************************************************************************/ + @Test + void inkOutsideTheMeasuredLineFailsTheRender() + { + TextFit.Request request = new TextFit.Request(Face.SANS_BOLD, 200, 60, 203, 12_000, 12_000, null, 1, false); + TextFit.Block honest = TextFit.fit(request, Face.SANS_BOLD.glyphs("HH"), null); + TextFit.Line line = honest.lines().get(0); + Canvas canvas = new Canvas(220, 80, 203); + Frame frame = new Frame(10, 10, 200, 60); + for(TextFit.Line wrong : List.of(new TextFit.Line(0, 2, false, line.left(), line.right() / 2, line.above(), line.below()), new TextFit.Line(0, 2, false, line.left(), line.right(), line.above() / 3, line.below()), + new TextFit.Line(0, 2, false, line.left(), line.right(), line.above(), -line.above() / 2))) + { + TextFit.Block forged = new TextFit.Block(honest.milliPoints(), List.of(wrong), wrong.width(), honest.height(), honest.baseline(), honest.pitch(), 2, 2, true); + TextRaster.Drawing drawing = new TextRaster.Drawing(Face.SANS_BOLD, "HH", forged, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, true); + assertEquals("TEXT_INK_OUTSIDE_MEASURE", assertThrows(IllegalStateException.class, () -> TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS)).getMessage()); + } + Canvas clean = new Canvas(220, 80, 203); + TextRaster.paint(clean, frame, new TextRaster.Drawing(Face.SANS_BOLD, "HH", honest, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, true), TextRaster.BAND_DOTS); + assertTrue(new Frame(10, 10, honest.width(), honest.height()).contains(ink(clean))); + } + + + + /*************************************************************************** + ** Very large type is drawn in bands of whole rows, so a line never needs + ** more grey than the band allows. 200 pt at 600 dpi is 1667 dots to the em. + ** The bands lose no row and repeat none: the picture is the one drawn in + ** one piece, but for a few edge dots where the rasteriser, given a band, + ** shades a curve differently: fewer than one ink dot in ten thousand (4 of + ** 121 thousand, 5 of 265 thousand and 40 of 1.06 million were seen). + ***************************************************************************/ + @Test + void veryLargeTypeIsDrawnInBands() + { + for(int dpi : Scene2.RESOLUTIONS) + { + TextFit.Request request = new TextFit.Request(Face.CONDENSED_BOLD, 2400 * dpi / 600, 2400 * dpi / 600, dpi, 200_000, 200_000, null, 1, false); + Canvas whole = draw(request, "7g", Placement.Align.CENTER, Placement.Valign.MIDDLE, 0, 128, Integer.MAX_VALUE); + assertSamePicture(whole, draw(request, "7g", Placement.Align.CENTER, Placement.Valign.MIDDLE, 0, 128, TextRaster.BAND_DOTS), "200 pt at " + dpi + " dpi fits one band"); + Canvas banded = draw(request, "7g", Placement.Align.CENTER, Placement.Valign.MIDDLE, 0, 128, 1 << 16); + int different = 0; + for(int y = 0; y < whole.height(); y++) + { + for(int x = 0; x < whole.width(); x++) + { + different += whole.get(x, y) == banded.get(x, y) ? 0 : 1; + } + } + assertTrue(different * 10_000L <= dots(whole), "200 pt at " + dpi + " dpi: " + different + " dots differ of " + dots(whole)); + System.out.println("200 pt at " + dpi + " dpi in bands: " + different + " of " + dots(whole) + " ink dots differ from the picture drawn in one piece"); + assertEquals(ink(whole), ink(banded)); + int capitals = new TextFit.Scale(200_000, dpi).floor(Face.CONDENSED_BOLD.capHeight()); + assertTrue(ink(banded).height() > capitals && ink(banded).height() < 2 * capitals && ink(banded).width() > capitals, "the digits are the size asked: " + ink(banded)); + } + } +} diff --git a/renderer/src/test/resources/scene2/cases/text-faces.json b/renderer/src/test/resources/scene2/cases/text-faces.json new file mode 100644 index 0000000..7a7e3ea --- /dev/null +++ b/renderer/src/test/resources/scene2/cases/text-faces.json @@ -0,0 +1,15 @@ +{ + "stock": {"widthMicrons": 50800, "heightMicrons": 25400, "topMicrons": 2000, "rightMicrons": 2000, "bottomMicrons": 2000, "leftMicrons": 2000, "dpi": 203}, + "scene": { + "schema": "qqq-zpl-scene/2", + "design": {"width": "2in", "height": "1in"}, + "defaults": {"size": "8pt"}, + "elements": [ + {"id": "sans", "type": "text", "value": "Sans 0O 1lI 5S 8B Åéj", "font": "qqq-sans", "y": "0mm", "height": "4.2mm"}, + {"id": "sans-bold", "type": "text", "value": "Bold 0O 1lI 5S 8B Åéj", "font": "qqq-sans-bold", "y": "4.2mm", "height": "4.2mm"}, + {"id": "condensed-bold", "type": "text", "value": "Condensed 0O 1lI 5S 8B Åéj", "font": "qqq-condensed-bold", "y": "8.4mm", "height": "4.2mm"}, + {"id": "mono", "type": "text", "value": "Mono 0O 1lI 5S 8B Åéj", "font": "qqq-mono", "y": "12.6mm", "height": "4.2mm"}, + {"id": "mono-bold", "type": "text", "value": "Bold 0O 1lI 5S 8B Åéj", "font": "qqq-mono-bold", "y": "16.8mm", "height": "4.2mm"} + ] + } +} diff --git a/renderer/src/test/resources/scene2/cases/text-fit.json b/renderer/src/test/resources/scene2/cases/text-fit.json new file mode 100644 index 0000000..9cb48ca --- /dev/null +++ b/renderer/src/test/resources/scene2/cases/text-fit.json @@ -0,0 +1,21 @@ +{ + "stock": {"widthMicrons": 50800, "heightMicrons": 25400, "topMicrons": 2000, "rightMicrons": 2000, "bottomMicrons": 2000, "leftMicrons": 2000, "dpi": 203}, + "scene": { + "schema": "qqq-zpl-scene/2", + "design": {"width": "2in", "height": "1in"}, + "defaults": {"font": "qqq-sans-bold", "size": "10pt"}, + "elements": [ + {"id": "kept-box", "type": "box", "width": "22mm", "height": "5mm", "thickness": "0.1mm"}, + {"id": "kept", "type": "text", "value": "LOT 240611", "width": "22mm", "height": "5mm", "align": "center", "valign": "middle"}, + {"id": "right-box", "type": "box", "anchor": "top-right", "width": "22mm", "height": "5mm", "thickness": "0.1mm"}, + {"id": "right", "type": "text", "value": "9.5 kg", "font": "qqq-condensed-bold", "size": "11pt", "anchor": "top-right", "width": "22mm", "height": "5mm", "align": "right", "valign": "bottom"}, + {"id": "shrunk-box", "type": "box", "y": "5.5mm", "width": "44mm", "height": "4mm", "thickness": "0.1mm"}, + {"id": "shrunk", "type": "text", "value": "(01)00012345678905(10)L240611A", "font": "qqq-mono-bold", "size": "9pt", "y": "5.5mm", "width": "44mm", "height": "4mm", "valign": "middle"}, + {"id": "wrapped-box", "type": "box", "y": "10mm", "width": "36mm", "height": "7.5mm", "thickness": "0.1mm"}, + {"id": "wrapped", "type": "text", "value": "(01)00012345678905(10)L240611A-RETURNED-000123", "font": "qqq-mono", "size": "7pt", "y": "10mm", "width": "36mm", "height": "7.5mm", "align": "center", "valign": "middle", + "maxLength": 46, "fit": {"maxLines": 2}}, + {"id": "cut-box", "type": "box", "anchor": "bottom-left", "width": "30mm", "height": "3.6mm", "thickness": "0.1mm"}, + {"id": "cut", "type": "text", "value": "A description of the item that is too long", "font": "qqq-sans", "size": "7pt", "anchor": "bottom-left", "width": "30mm", "height": "3.6mm", "fit": {"overflow": "truncate", "shrinkTo": "7pt"}} + ] + } +} diff --git a/renderer/src/test/resources/scene2/cases/text-turned.json b/renderer/src/test/resources/scene2/cases/text-turned.json new file mode 100644 index 0000000..06f4820 --- /dev/null +++ b/renderer/src/test/resources/scene2/cases/text-turned.json @@ -0,0 +1,18 @@ +{ + "stock": {"widthMicrons": 50800, "heightMicrons": 25400, "topMicrons": 2000, "rightMicrons": 2000, "bottomMicrons": 2000, "leftMicrons": 2000, "dpi": 203}, + "scene": { + "schema": "qqq-zpl-scene/2", + "design": {"width": "2in", "height": "1in"}, + "defaults": {"font": "qqq-sans-bold", "size": "10pt"}, + "elements": [ + {"id": "up", "type": "text", "value": "TEST-0001", "font": "qqq-mono-bold", "rotation": 90, "width": "5mm", "align": "center"}, + {"id": "down", "type": "text", "value": "TEST-0001", "font": "qqq-mono-bold", "rotation": 270, "anchor": "top-right", "width": "5mm", "align": "center"}, + {"id": "flip", "type": "text", "value": "THIS WAY UP", "rotation": 180, "x": "7mm", "width": "30mm", "height": "5mm", "align": "center"}, + {"id": "panel", "type": "text", "value": "ZONE 7", "font": "qqq-condensed-bold", "size": "16pt", "reverse": true, "x": "7mm", "y": "6mm", "width": "30mm", "height": "8mm", "align": "center", "valign": "middle"}, + {"id": "fine", "type": "text", "value": "Best before 2027-06-11", "font": "qqq-sans", "size": "6.5pt", "x": "7mm", "y": "15mm", "width": "32mm", "height": "5mm", "valign": "bottom"} + ], + "overrides": [ + {"when": {"dpi": [203]}, "set": {"fine": {"font": "qqq-sans-bold", "threshold": 150}}} + ] + } +} diff --git a/renderer/src/test/resources/scene2/golden/text-faces-203.png b/renderer/src/test/resources/scene2/golden/text-faces-203.png new file mode 100644 index 0000000000000000000000000000000000000000..2c5a94bbd61bb0d13705ad89ddcfd391061b5aaf GIT binary patch literal 1928 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 literal 0 HcmV?d00001 diff --git a/renderer/src/test/resources/scene2/golden/text-faces-300.zpl b/renderer/src/test/resources/scene2/golden/text-faces-300.zpl new file mode 100644 index 0000000..b2271de --- /dev/null +++ b/renderer/src/test/resources/scene2/golden/text-faces-300.zpl @@ -0,0 +1,7 @@ +^XA^PW600^LL300^LH0,0^CI28 +^FO27,26^GFA,1640,1640,41,0000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000007C00000000000000000000000000000000000000000000000000000000000000000000000000000000E600000000000000000000000000000000000000000000000000000000000000000000000000000000C200000000000000000000000000000000000000000000000000000000000000000000000000000000C300000000000000000000000000000000000000000000000000000000000000000000000000000000C6000000000000000000000000000000000000000000000000000000000000000000000000000000007E000000000000000000000000000000000000000000000000000000000000000000000000000000003C0000C000000000000000000000000000000000000000000600000000000000000000000000000000000000E01800380000000000000000003C0000E000000000070000000000000E000001E00000000000000001C01C01FF800000000000000000FF0007FE000007C00707FC000FFF807FE0000FFC03FFE000003C0001C01C03FFC00000000000000001FF800FFF00000FC00707FC000FFF80FFF0001FFE03FFF000007C000380180781E0000000000000000381C01E0780001DC00700E0000E0001E078003C0F03807800007C000300000E00E0000000000000000700E03803C00039C00700E0000C0003803800380703803800006E000000000E0000000000000000000700E07001C00071C00700E0000C0003800000380703801C0000EE000000000E00000E0000600060000600607000E000E1C00700E0000C0003800000380703801C0000C6000300000E00007F803BF803FC000E00706000E00041C00700E0000C0003800000380703801C0000C7001FE01C0E0000FFE03FFC07FE000E0070E000E00001C00700E0000C0003800000380703801C0001C7003FF01C078001C0E03C1E0E07000E0070E000600001C00700E0000C0001E000001C0E0380380001838078381C07E0008070380E0E00000E0070E000700001C00700E0001DFC01F800000F3C03807000038380601C1C01FE000070380E0E00000E0070E000700001C00700E0001FFF007F800007F803FFE000038180E01C1C007F80007038060E00000E0070E000700001C00700E0001E07801FE0000FFC03FFF0000301C0E00C1C000FC0007038060F00000E0070E000700001C00700E0000C038003F0001C0E038078000701C0C00E1C0001E01FF0380607F0000E0070E000700001C00700E000000380007800380703801C000701C0FFFE1C0000E0FFF0380603FE000E0070E000600001C00700E0000001C0003800700383801C0007FFE0FFFE1C000071E0703806003F000E0070E000E00001C00700E0000001C0001C00700383800E000FFFE0C0001C000071C07038060007000600606000E00001C00700E0000001C0001C00700383800E000E00E0C0001C000071807038060003000700E07000E00001C00700E000000180001C00700383800E000C0070E0001C0C00E3807038060003000700E07801C00001C00700E000080383003800700383801C001C0070E0081C0E00E1C07038060C07000381C03C03C00001C00700E0001C0383803800380703801C001C0070701C1C0F83C1C1F038060E070003C3C01E0F800001E00700E0001F0F03E0F0003C0F0380F80018003878381C03FF80FF3C380607FE0001FF800FFF00007FFF07C7FC000FFE00FFE0001FFE03FFF0003800383FF81C01FF007E1C380603FC0000FF0003FC00007FFF03C7FC0003FC007FC00007F803FFE0003800380FE01C000000000000000000000000000000000000000000000000000000000000000000000000000000001C000000000000000000000000000000000000000000000000000000000000000000000000000000001C0000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000F800000000000000000000000000000000000000000000000000000000000000000000000000000000F800000000000000000000000000000000000000000000000000000000000000000000000000000000E00^FS +^FO27,77^GFA,1680,1680,42,000000000000000000000000000000000000000000000000000000000000000000000001F80000000000000000000000000000000000000000000000000000000000000000000000000000000003FC00000000000000000000000000000000000000000000000000000000000000000000000000000000039E00000000000000000000000000000000000000000000000000000000000000000000000000000000078E00000000000000000000000000000000000000000000000000000000000000000000000000000000078E00000000000000000000000000000000000000000000000000000000000000000000000000000000038E0000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0000C00000000000000000000000000000000000000000000000000000000000000000000000000001FC0000F000000000000000780007C000000000000000000001E000000000000000000000000000000000F80001F00F000000000000F80007C0000F00003C0000000003E000000000000078000007800000000000000001E01F00FFFC000000F80007C0007FE001FF800003FC03E0FFE001FFF803FF00003FF00FFFC00001FC0003E01F80FFFE000000F80007C000FFF007FFC00007FC03E0FFE001FFF80FFFC0007FF80FFFE00001FC0003C01F80FFFF000000F80007C001FFF80FFFE00007FC03E0FFE001FFF81FFFC000FFFC0FFFF00003FC0003801F00FFFF800000F80007C001FFF80FFFF0000FFC03E0FFE001FFF81FFFC001F87E0FFFF80003FE0000000600F81F800000F80007C003F0FC1F83F8001F7C03E01F0001E0003F078001F03E0F81F80003FE0000000000F80F803E00F803C7C003E07C1F00F8003E7C03E01F0001E0003E010001F03E0F80F80007DE0007C00F00F80F80FF80F80FF7C003E07C3F00F8003E7C03E01F0001E0003E000001F03E0F80F80007DF001FF01F00F80F83FFC0F81FF7C007E07E3E007C003C7C03E01F0001E0003E000001F03E0F80F800079F007FF81F00F81F03FFE0F81FFFC007C03E3E007C00187C03E01F0001E7E03FC00000F87C0F81F0000F8F007FFC1F00FFFF07E3F0F83F0FC007C03E3E007C00007C03E01F0001CFF01FFC00007FF80FFFF0000F8F80F87E1F00FFFC07C1F0F83E07C007C03E3E007C00007C03E01F0003DFF81FFF80003FF00FFFC0000F0F80F83E1F00FFFE0781F0F83E07C007C03E3E007C00007C03E01F0003FFFC0FFFC0003FF00FFFE0001F0780F03E1F00FFFF0F81F0F83E07C007C03E3E007C00007C03E01F0003F0FC03FFC000FFFC0FFFF0001F07C1F83E1F00F81F8F81F8F87E07C007C03E3E007C00007C03E01F0000007E003FE001F87E0F81F8001FFFC1FFFE1F00F80FCF81F8F87E07C007E07E3E007C00007C03E01F0000007E0007E001F03E0F80FC003FFFC1FFFF1F00F807CF81F8F87E07C007E07E3E00FC00007C03E01F0000007E0003E003F03F0F807C003FFFE1FFFE1F00F807CF81F0F83E07C003E07C3F00F800007C03E01F0000007E0003E003F03F0F807C003FFFE1F0001F00F80FC7C1F0F83E07C003E07C1F01F800007C03E01F0001C07C1C03E003F03F0F80FC007E03E0F8001F00F81FC7C1F0F83F0FC003F0FC1FC3F800007C03E01F0003E0FC3F07E001F03E0F81FC007C01F0F8181F00FFFF87FFE0FE3FFFC001FFF80FFFF0001FFFE3F8FFE003FFFC3FFFC001FFFE0FFFF8007C01F0FFFC1F00FFFF83FFE07E1FFFC001FFF807FFE0001FFFE1F8FFE001FFF83FFFC000FFFC0FFFF800FC01F07FFE1F00FFFF01FFC07E0FF7C000FFF003FFC0001FFFE1F8FFE000FFF01FFF80007FF80FFFF000F801F83FFC1F00FFFC00FF001E07E7C0003FC001FF00001FFFE078FFE0007FC007FE00003FF00FFFC000F800F80FF01F00000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000000000000000000000000000000000000000000000000000000000000000000000000000007F00000000000000000000000000000000000000000000000000000000000000000000000000000000007F00000000000000000000000000000000000000000000000000000000000000000000000000000000007E00000000000000000000000000000000000000000000000000000000000000000000000000000000007800^FS +^FO26,126^GFA,1960,1960,49,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007BC000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F8000780000000000000000003C00000000000000000001E0000000000000000001E000000000000000000000000000001F0000F80E00F00000000000003C00000000000000000001E0001E0001C000000001F000000000000E0000078000000000000000F01F07FC0000000000003C00000000000000000001E0007F800FF80000FE01F1FFC007FFC07FC0003FF03FFF00003F8001E01F0FFF0000000000003C00000000000000000001E001FFC01FFE0001FE01F1FFC007FFC1FFF0007FF83FFF80003F8001E01F1FFF0000000000003C00000000000000000001E001FFE03FFF0003FE01F1FFC00FFFC1FFF800FFFC3FFF80007F8001C01F3FFF8000000000003C00000000000000000001E003F3F07FFF0003DE01F0FF800FFFC3FFF000F87C3FFFC0007F800000003E0FC000000000003C00000000000000000001E003E1F07C1F8007DE01F03E000F0003E06000F03C3E07C0007BC00000007C07007C01C3801E3C03E00E1C00F800F800F1E003C0F0F80F800F9E01F03E000F0003C00000F03C3E07C0007BC003E00E7C0001FF03EFE07F3C0FF81F7F03FF03FE03F9E007C0F8F80780071E01F03E000F0003C00000F03C3E07C000F3C00FF81F7C0003FF83EFE07FBC1FFC1F7F07FF87FF03FDE007C0F8F807C0001E01F03E000F0003E00000F03C3E07C000F3E01FFC1F7C0007FFC3FFF0FFFC3FFE1FFF87FF0FFF87FFE007C0F8F807C0001E01F03E000F3F03F0000078783E07C000F3E03FFE1F7C0007C7C3F1F0F87C3E3E1F8F8F860F8F87C3E007C0F8F807C0001E01F03E000F7F83FF00007FF83FFF8001F1E03E3E1F7C000F83C3E1F0F07C7C1E1F0F8F801F078783E007C0F8F807C0001E01F03E000F7FC1FFE0001FE03FFE0001F1E07C1E1FFC000F83E3E1F1F03C7C1F1F0F8F801F07CF81E007C0F9F807C0001E01F03E000FFFC0FFF0003FF03FFF0001E1F07C1F1F7C000F83E3E1F1F03C7C1F1F0F87F01F07CF81E007C0F8F807C0001E01F03E000F87E03FF8007FF83FFF8001E1F07C1F1F7C000F83E3E1F1F03C7FFF1F0F87FE1FFFCF81E007C0F8F807C0001E01F03E000003E003F800F87C3E07C003FFF07FFF1F7C000F83E3E1F1F03C7FFF1F0F83FF1FFFCF81E007C0F8F807C0001E01F03E000003E000F801F03E3E03E003FFF87FFF1F7C000F83E3E1F1F03C7C001F0F80FF9F000F81E007C0F8F807C0001E01F03E000003E000F801F03E3E03E003FFF87C001F7C020F83E3E1F1F03C7C001F0F800F9F000F81E007C0F8F80780001E01F03E000003E000F801F03E3E03E003FFF87C001F7C078F83E3E1F1F03C7C001F0F80079F000F81E003C0F0F80F80001E01F03E000603E180F801F03E3E03E007C0787C001F3E0F8783C3E1F0F87C3E0C1F0F86078F8307C3E003E1F07C1F80001E01F03E000F07E3C0F801F87E3E07E007807C3E0C1F3FFF87CFC3E1F0FCFC3F1E1F0F8F8F8FC787E7E003FFF07FFF0003FFF1F8FFC00FFFC7FFF800FCFC3FFFC007807C3F1E1F1FFF07FF83E1F0FFBC1FFE1F0F8FFF87FF87FDE001FFE03FFE0003FFF1FDFFC00FFFC3FFF000FFFC3FFFC00F803C1FFE1F0FFE03FF83E1F07F3C0FFC1F0F87FF03FF03F9E000FFC01FFC0003FFF0FDFFC007FF81FFE0007FF83FFF800F803E0FFC1F07FC00FE03E1F03F3C07F81F0F83FE01FE01F9E0007F800FF80003FFF07DFFC001FE007FC0003FF03FFF000F003E07F81F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078^FS +^FO26,176^GFA,2028,2028,52,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007000070000000000000000000000000003C0003C00000000000000000000000000000000038000000003C0000000000000000000F0000F8F81F0000000000000000000000FF000FF000000007E01FF0007FFE0000007FFC00FF00000000FF007FF000000003C0000E0000F8F81F0000000000000000000003FF801FF80000000FE01FF0007FFE0000007FFC01FF80000001FF807FF800000003E0001C000078FC3F0000000000000000000003C3C03C3C0000001FE000700003C0000000700003C3C0000003C3C0707C00000007E00018000000EC37000000000000000000000781E0781E0000007CE000700003C000000070000781C000000781E0701E00000007E00000000000EC37000000000000000000000700E0700E00000078E000700003C000000070000700E000000700E0700E00000006E00000000000EE7700180000C000180000000700E0700E00000060E000700003C000000070000700E000000700E0700E0000000E700038000000E66700FF0077F800FF0000000700E0700E00000040E000700003C0000000700007000000000700E0700E0000000E7000FF007FF8E66701FF8077FC01FF8000000700E0700E00000000E000700003C0000000700007000000000700E0700E0000000E7001FF807FF8E6E703C3C07C3C03C3C000000700E0700E00000000E000700003C0000000700003800000000381C0701C0000000E700381C00078E7C70781E0781E0781E000000700E0700E00000000E000700003C00000007FF003E000000003C3C0703C0000001C380700E00078E3C70700E0700E0700E000000718E0700E00000000E000700003C00000007FF801FE00000000FF007FF80000001C380700E00078E3C70700E0700E0700E00000073CE0700E00000000E000700003C00000003FFC00FF80000000FF007FF00000001C380700E00078E3870700E0700E0700E00000073CE0700E00000000E000700003C0000000001E001FC0000003FFC07FFC0000001C380700E00078E0070700E0700E0700E000000718E0700E00000000E000700003C0000000000E0003E000000781E0701C000000381C07FFE00078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000000E0000E000000700E0700E000000381C07FFE00078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000000E0000E000000E0070700E0000003FFC07FFE00078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000000E00007000000E007070070000003FFC0700000078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000600E06007000000E007070070000007FFE0700000078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000700E07006000000E0070700F000000700E0700000078E0070700E0700E0700E000000700E0700E00000000E000700003C0000000700E0700E000000700E0700E000000700E0700E00078E0070381C0700E0381C000000781E0381C00000000E000380003C0000000781E0781E000000781E0701E000000700E0381E00078E00703E7C0700E03E7C0000003C3C03E7C0000007FFF003FF03FFC0000003C7C03E7C0000003E7C07FFC000000E00703C3C00078E00701FF80700E01FF80000001FF801FF80000007FFF001FF07FFE0000001FF801FF80000001FF807FF8000000E00701FF800070E00700FF00700E00FF00000000FF000FF00000007FFF000FF07FFE0000000FF000FF00000000FF007FF0000000E00700FF0000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F00^FS +^FO27,225^GFA,2028,2028,52,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001CE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780001F0000F00000000000000000000000000078000780000000000000000000000000000000007000000000780000000000000000001E0001F0FFE0000003FF000003C0000001FE001FE00000000FC03FF000FFFC000000FFFC03FE00000001FE00FFE00000000FC0003C0001F8FFF8000003FF000003C0000007FF807FF80000001FC03FF000FFFC000000FFFC07FF80000007FF80FFF80000000FC000780000F0FFFC000003FF000003C000000FFFC07FF80000007FC03FF000FFFC000000FFFC0FFF8000000FFFC0FFFC0000000FC00070000060F07C0000000F000003C000000F87C0F87C000000FFC000F0000780000000F0000F87C000000F87C0F07C0000001FE00000000000F03E0000000F000003C000000F03C0F03C000000FBC000F0000780000000F0000F03C000000F03C0F03E0000001FE00000000000F03E0078000F0000C3C000001E01E0F03C000000F3C000F0000780000000F0001F03C000000F03E0F03E0000001FE00030000000F03E01FE000F0003FBC000001E01E1F03E000000C3C000F0000780000000F0001F000000000F03E0F03E0000001CE001FE00FFF0F03C07FF800F0007FFC000001E01E1F03E00000083C000F0000780000000F0000F000000000F03C0F03C0000003CF007FF80FFF0F03C0FFFC00F000FFFC000001E01E1F03E00000003C000F0000780000000FE000F800000000F03C0F03C0000003CF007FF80FFF0F0F80F87C00F000F87C000001E01E1F03E00000003C000F0000780000000FFE00FF000000007CF80F0F80000003CF00F03C000F0FFF00F03C00F000F03C000001E79E1F03E00000003C000F0000780000000FFF807FE00000003FF00FFF000000038700F03C000F0FFF01F03E00F001F03C000001E79E1F03E00000003C000F0000780000000FFFC03FF80000003FF00FFF000000078781E01E000F0FFF81F03E00F001F03C000001E79E1F03E00000003C000F0000780000000007C00FFC0000007FF80FFF800000078781E01E000F0F07C1F03E00F001F03C000001E31E1F03E00000003C000F0000780000000003C001FC000000F87C0F07C00000078781FFFE000F0F03E1F03E00F001F03C000001E01E1F03E00000003C000F0000780000000003E0003E000001F03E0F03E00000078781FFFE000F0F01E1F03E00F001F03C000001E01E1F03E00000003C000F0000780000000003E0001E000001E01E0F01E000000FFFC1FFFE000F0F01E1F03E00F001F03C000001E01E1F03E00000003C000F0000780000000003E0001E000001E01E0F01E000000FFFC1E000000F0F01E1F03E00F001F03C000001E01E1F03E00000003C000F0000780000001E03E1E01E000001E01E0F01E000000FFFC1E000000F0F01E1F03E00F001F03C000001E01E0F03C00000003C000F0000780000001E03E1E01E000001E01E0F01E000000F03C1F000000F0F03E0F03C00F800F03C000000F03C0F03C00000003C000F8000780000001F03C1F03E000001F03E0F03E000001E01E0F03C000F0F1FC0FCFC00FFE0FCFC000000FCFC0FCFC000000FFFE00FFE0FFFC000000FCFC0FCFC000000F87C0F1FC000001E01E0F87C000F0FFFC07FF8007FF0FFFC0000007FF807FF8000000FFFE007FF0FFFC000000FFF80FFFC000000FFFC0FFFC000001E01E07FF8000F0FFF803FF0003FF07FBC0000003FF003FF0000000FFFE003FF0FFFC0000007FF007FF80000007FF80FFF8000001E01E03FF0000F0FFE001FE0001FF03F3C0000001FE001FE0000000FFFE001FF0FFFC0000001FE001FE00000001FE00FFE0000003E01F01FE0000F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00^FS +^XZ diff --git a/renderer/src/test/resources/scene2/golden/text-faces-600.png b/renderer/src/test/resources/scene2/golden/text-faces-600.png new file mode 100644 index 0000000000000000000000000000000000000000..5a8f536d810731f9405a8c6aea7e6f3c0bd1689f GIT binary patch literal 7616 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 literal 0 HcmV?d00001 diff --git a/renderer/src/test/resources/scene2/golden/text-faces-600.zpl b/renderer/src/test/resources/scene2/golden/text-faces-600.zpl new file mode 100644 index 0000000..e623013 --- /dev/null +++ b/renderer/src/test/resources/scene2/golden/text-faces-600.zpl @@ -0,0 +1,7 @@ +^XA^PW1200^LL600^LH0,0^CI28 +^FO51,52^GFA,6318,6318,81,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E3E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000780F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C1E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F0000000003800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E00000000000000000000000000000000000000000000000000000000000000000000000000000000003E00000000000000000000000000000000000000000000000000000000000000000000000000007C0000F800000000000000000000000000000000000000000000000000000000000000000000000000003E0000000000000000000000000000000000000000000000000000000000000000000000000000FC0001F8003FFE0000000000000000000000000000000000000FFC00000001FFE000000000000FF000003E003FFFF00000003FFFFFC00003FFE00000000007FF800003FFFF80000000000007F000000000F80001FC00FFFF8000000000000000000000000000000000007FFF8000000FFFF800000000001FF000003E003FFFF80000007FFFFFC0000FFFF8000000003FFFF00007FFFFFC00000000000FF000000001F00001FC03FFFFE00000000000000000000000000000000000FFFFC000003FFFFE00000000003FF000003E003FFFF80000007FFFFFC0003FFFFE000000007FFFF80007FFFFFF00000000000FF800000001F00001F807FFFFF00000000000000000000000000000000001FFFFE000007FFFFF0000000000FFF000003E003FFFF80000007FFFFFC0007FFFFF00000001FFFFFE0007FFFFFF80000000000FF800000003E00000F80FFFFFFC0000000000000000000000000000000003FFFFF00000FFFFFFC000000001FFF000003E003FFFF80000007FFFFFC000FFFFFFC0000001FFFFFE0007FFFFFFC0000000001FF800000003C00000201FE003FE0000000000000000000000000000000007F807F80001FF007FE000000003F9F000003E0000FC000000007C00000001FE003FE0000003FC00FF0007E0007FE0000000001FFC00000007C00000001F8000FE0000000000000000000000000000000007E001F80003FC001FE000000007F1F000003E00007C000000007C00000001F8000FE0000007F0003F8007E0000FE0000000001F7C00000007800000003F00007F000000000000000000000000000000000FC000FC0007F00007F00000000FE1F000003E00007C000000007C00000003F00007F0000007E0001F8007E00007F0000000003E7C00000001000000003F00003C000000000000000000000000000000000F80007C000FE00003F80000001FC1F000003E00007C000000007C00000003F00003C0000007E0001F8007E00003F0000000003E7E00000000000000003E000018000000000000000000000000000000001F80007E000FC00001F80000003F81F000003E00007C000000007800000003E000018000000FC0000FC007E00003F0000000003E3E00000000000000007E000000000000000000000000000000000000001F00003E001F800000FC0000007F01F000003E00007C000000007800000007E000000000000FC0000FC007E00001F8000000007C3E00000000000000007E000000000000000000000000000000000000003F00003E001F800000FC000000FE01F000003E00007C000000007800000007E000000000000FC0000FC007E00001F8000000007C3F00000000000000007E0000000000FFC0000000FF000000FFC00000003F00003F001F0000007E000000FC01F000003E00007C00000000F800000007E000000000000FC0000FC007E00001F8000000007C1F0000001FF00000007E0000000007FFF00007C3FFC00003FFF00000003E00003F003F0000007E0000007801F000003E00007C00000000F800000007E000000000000FC0000FC007E00001F800000000F81F000000FFFE0000F87E000000000FFFFC0007C7FFF0000FFFFC0000003E00001F003F0000003E0000003001F000003E00007C00000000F800000007E0000000000007C0000F8007E00001F800000000F81F800001FFFF0000F83E000000001FFFFE0007CFFFF8001FFFFE0000003E00001F003E0000003E0000000001F000003E00007C00000000F800000003E0000000000007C0000F8007E00001F000000000F80F800003FFFF8000F83F000000003FE3FF0007DFFFF8003FE1FF0000007E00001F803E0000003F0000000001F000003E00007C00000000F800000003F0000000000007E0001F8007E00003F000000001F00FC00007F83FC000F83F800000007F007F0007DC03FC003F003F8000007E00001F807E0000003F0000000001F000003E00007C00000000F800000003F8000000000003F0003F0007E00003F000000001F00FC0000FE00FE000F81FE00000007C003F8007F000FC007E001F0000007E00001F807E0000003F0000000001F000003E00007C00000000F81FC00001FE000000000001F8007E0007E00007E000000003F007C0001F8003F000F81FFC00000078001F8007E0007E007C00060000007E00001F807E0000003F0000000001F000003E00007C00000000F87FF80001FFC00000000000FC01FC0007E0000FC000000003E007E0003F0001F000F80FFFC0000030000F8007E0007E007C00000000007E00001F807E0000003F0000000001F000003E00007C00000000F9FFFE0000FFFC00000000007FFFF80007E0007F8000000003E003E0003F0001F800F803FFFC000000000FC007C0003E007C00000000007E00001F807E0000003F0000000001F000003E00007C00000000FBFFFF00003FFFC0000000003FFFE00007FFFFFF0000000007E003E0003E0000F800F801FFFF800000000FC007C0003E007C00000000007E00001F807E0000003F0000000001F000003E00007C00000000FFFFFF80001FFFF8000000000FFFC00007FFFFFC0000000007C003F0007E0000FC00F8007FFFE00000000FC007C0003E007C00000000007E00001F807E0000003F0000000001F000003E00007C00000000FF807FC00007FFFE000000003FFFF00007FFFFFF0000000007C001F0007C0000FC00F8000FFFF00000000FC007C0003F007E00000000007E00001F807E0000003F0000000001F000003E00007C00000000FE001FC00000FFFF00000000FFFFFC0007FFFFFFC00000000FC001F0007C00007C00F80000FFF80000000FC007C0003F007F00000000007E00001F807E0000003F0000000001F000003E00007C00000000FC000FE000000FFF80000001FC01FE0007E0003FE00000000F8001F800FC00007C00F800000FFC0000000FC007C0003F003FC0000000007E00001F807E0000003F0000000001F000003E00007C00000000180007E0000000FFC0000003F0003F0007E00007F00000000F8000F800FC00007C00F8000003FE00003FFFC007C0003F001FFF000000007E00001F807E0000003F0000000001F000003E00007C00000000000007F00000003FE0000007E0001F8007E00003F80000001F0000F800FFFFFFFC00F8000000FE0007FFFFC007C0003F001FFFF00000007E00001F807E0000003F0000000001F000003E00007C00000000000003F00000000FE000000FC0000FC007E00001F80000001FFFFFFC00FFFFFFFC00F80000007F001FFFFFC007C0003F0007FFFC0000007E00001F807E0000003F0000000001F000003E00007C00000000000003F000000007F000000FC0000FC007E00000FC0000001FFFFFFC00FFFFFFFC00F80000003F003FFFFFC007C0003F0001FFFE0000007E00001F807E0000003F0000000001F000003E00007C00000000000003F000000003F000001F800007E007E00000FC0000003FFFFFFC00FFFFFFFC00F80000003F007FE00FC007C0003F00003FFF0000003E00001F003E0000003F0000000001F000003E00007C00000000000003F000000003F000001F800007E007E00000FC0000003FFFFFFE00FC00000000F80000001F00FE000FC007C0003F000000FF8000003E00001F003F0000003E0000000001F000003E00007C00000000000003F000000001F000001F800007E007E00000FC0000003FFFFFFE00FC00000000F80000001F00FC000FC007C0003F0000003F8000003E00001F003F0000007E0000000001F000003E00007C00000000000003F000000001F000001F800007E007E00000FC0000007E00003E00FC00000000F80000001F01F8000FC007C0003F0000001F8000003F00003F003F0000007E0000000001F000003E00007C00000000000003F000000001F000001F800007E007E00000FC0000007C00003F007C00000000F80000001F01F8000FC007C0003F0000000FC000003F00003F001F8000007C0000000001F000003E00007C00000000000003F000000001F000001F800007E007E00000FC0000007C00003F007C00000000F80000003F01F8000FC007C0003F0000000FC000001F00003E001F800000FC0000000001F000003E00007C00000000000003F000000003F000001F800007E007E00000FC000000FC00001F807C00000000F83800003F01F8000FC007C0003F00000007C000001F80007E000FC00001FC0000000001F000003E00007C00000000600003F003800003F000001F800007E007E00000FC000000F800001F807E00004000F87C00003F01F8000FC007C0003F00100007C000001F80007E000FE00001F80000000001F000003E00007C00000000F00007E007C00003F000001FC0000FE007E00000FC000001F800001F803E00006000F8FE00007E01F8000FC007C0003F0078000F8000000FC000FC0007F00003F00000000001F000003E00007C00000001F00007E00FE00007E000000FC0000FC007E00001F8000001F800000FC03F0000F800F8FF0000FE01F8001FC007C0003F00FC000F8000000FE001FC0007F8000FF00000000001F000003E00007C00000001F8000FC00FF0000FE000000FE0001FC007E00003F8000001F000000FC01F8001F800F87FC001FC00FC003FC007C0003F00FE001F80000007F003F80003FE001FE00000000001F000003E00007C00000001FE003FC007FC001FC0000007F8007F8007E0000FF0000003F000000FC01FC003F000F83FF80FF800FE00F7F807C0003F007F807F00000003FC0FF00001FFC0FFC00000003FFFFFFF003FF03FFFF0000000FFC1FF8003FF80FF80000003FE01FF0007FFFFFFE0000003F0000007E00FF00FF000F81FFFFFF0007FFFE7FC07C0003F003FFFFF00000003FFFFF00000FFFFFF800000003FFFFFFF003FF03FFFF80000007FFFFF0001FFFFFF00000001FFFFFE0007FFFFFFE0000003E0000007E007FFFFE000F807FFFFE0003FFFE3FC07C0003F001FFFFE00000001FFFFE000007FFFFF000000003FFFFFFF003FF03FFFF80000003FFFFE00007FFFFE00000000FFFFFC0007FFFFFF80000007E0000007E003FFFFC000F803FFFFC0001FFFC3FC07C0003F000FFFF8000000007FFF8000001FFFFC000000003FFFFFFF001FF03FFFF80000000FFFFC00003FFFFC000000007FFFF80007FFFFFF00000007E0000003F001FFFF0000F8007FFF00000FFF00FC07C0003F0003FFF0000000003FFF00000007FFF0000000003FFFFFFF0007F03FFFF800000003FFF0000007FFF0000000001FFFE00007FFFFFC00000007C0000003F0007FFC0000F8000FF0000001F800000000000000003F000000000003F0000000007F000000000000000000000000000000000000007F00000000FF000000000001FE000000000000000000000000000000000FE00000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F80^FS +^FO53,149^GFA,6640,6640,83,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F1FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FE0FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FE0FE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F0FE000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFC000000007C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFF8000000007F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFF000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE000000000FFC0007C00000000000000000000003FE00000001FF8000000000000000000000000000000000000000003FE0000000000000000000000000000000000000000000000000000000000000000003F8000000001FF8001FF00000000000000000000003FE00000001FF8000000000000000000000000000000000000000003FE000000000000000000000000000000000000000000000000000000000000000000000000000003FF0003FF807FFFFE000000000000003FE00000001FF800000000FFF00000000FFF000000000001FFF80003FE007FFFFC0000007FFFFFF000007FFC00000000007FF800007FFFFE000000000000FFF000000003FE0003FF80FFFFFFF00000000000003FE00000001FF800000003FFFC0000007FFFE00000000003FFFC0003FE00FFFFFC000000FFFFFFF80003FFFF8000000003FFFF0000FFFFFFF00000000001FFF800000007FE0003FF80FFFFFFFC0000000000003FE00000001FF80000000FFFFF000001FFFFF80000000007FFFC0003FE00FFFFFC000000FFFFFFF8000FFFFFE00000000FFFFFC000FFFFFFFC0000000001FFF800000007FC0003FF80FFFFFFFE0000000000003FE00000001FF80000001FFFFF800007FFFFFC000000000FFFFC0003FE00FFFFFC000000FFFFFFF8001FFFFFF80000001FFFFFE000FFFFFFFE0000000001FFF80000000FF80003FF80FFFFFFFF0000000000003FE00000001FF80000003FFFFFC0000FFFFFFE000000001FFFFC0003FE00FFFFFC000000FFFFFFF8003FFFFFFC0000003FFFFFF000FFFFFFFF0000000003FFFC0000000FF00003FF80FFFFFFFF8000000000003FE00000001FF80000007FFFFFE0001FFFFFFF000000001FFFFC0003FE00FFFFFC000000FFFFFFF8007FFFFFFE0000007FFFFFF800FFFFFFFF8000000003FFFC0000000FE00003FF80FFFFFFFFC000000000003FE00000001FF8000000FFFFFFF0003FFFFFFF800000003FFFFC0003FE00FFFFFC000000FFFFFFF800FFFFFFFE000000FFFFFFFC00FFFFFFFFC000000003FFFC00000007E00001FF00FFFFFFFFC000000000003FE00000001FF8000000FFFFFFF0003FFFFFFFC00000007FFFFC0003FE00FFFFFC000000FFFFFFF801FFFFFFFC000000FFF87FFC00FFFFFFFFC000000007FFFC00000001C00000FE00FFFFFFFFC000000000003FE00000001FF8000001FFF0FFF8007FFFFFFFE0000000FFEFFC0003FE007FFFFC000000FFFFFFF801FFFFFFF8000000FFE01FFC00FFFFFFFFC000000007FFFE000000000000000000FFC001FFE000000000003FE00000001FF8000001FFC03FF800FFFC03FFE0000000FFCFFC0003FE0003FF00000000FF00000001FFC00FF0000001FFC00FFE00FFC001FFE000000007FFFE000000000000000000FFC000FFE000000000003FE00000001FF8000003FF801FFC00FFF000FFF0000001FF8FFC0003FE0003FF00000000FF00000003FF8003E0000001FF8007FE00FFC000FFE00000000FFBFE000000000000000000FFC000FFE00003F800003FE00003F01FF8000003FF000FFC01FFE0007FF0000003FF0FFC0003FE0003FF00000000FF00000003FF0001C0000001FF8007FE00FFC000FFE00000000FFBFF0000000FE000000000FFC0007FE0001FFF80003FE0001FFC1FF8000007FF000FFC01FFC0003FF0000007FF0FFC0003FE0003FF00000000FE00000003FF000080000001FF8007FE00FFC0007FE00000000FF9FF0000007FFE0001FF00FFC0007FE0007FFFE0003FE0003FFF1FF8000007FF000FFE01FF80003FF8000007FE0FFC0003FE0003FF00000001FE00000003FF000000000001FF0003FE00FFC0007FE00000001FF1FF000001FFFF8001FF00FFC0007FE001FFFFF0003FE000FFFF9FF8000007FE0007FE03FF80001FF800000FFC0FFC0003FE0003FF00000001FE00000003FF000000000001FF8007FE00FFC0007FE00000001FF1FF800007FFFFC001FF00FFC0007FE003FFFFF8003FE000FFFFDFF8000007FE0007FE03FF80001FF800000FF80FFC0003FE0003FF00000001FE00000003FF800000000000FF8007FC00FFC0007FE00000001FF0FF80000FFFFFE001FF00FFC000FFC007FFFFFC003FE001FFFFDFF8000007FE0007FE03FF00001FFC000007F80FFC0003FE0003FF00000001FE00000003FF800000000000FF8007FC00FFC000FFC00000003FE0FF80001FFFFFF001FF00FFC000FFC007FFFFFE003FE003FFFFFFF800000FFE0007FF03FF00001FFC000003F00FFC0003FE0003FF00000001FE0FFE0003FFE00000000000FFC00FF800FFC000FFC00000003FE0FFC0001FFFFFF801FF00FFC001FFC00FFFFFFF003FE003FFFFFFF800000FFE0007FF03FF00001FFC000000E00FFC0003FE0003FF00000001FE1FFF8001FFFF00000000007FE01FF800FFC001FFC00000003FE0FFC0003FFFFFFC01FF00FFE007FF800FFE0FFF003FE007FFE1FFF800000FFE0007FF03FF00001FFC000000400FFC0003FE0003FF00000001FE3FFFC001FFFFF8000000003FFCFFF000FFE007FF800000007FE07FC0007FF01FFC01FF00FFFFFFFF001FFC03FF803FE007FF807FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FE7FFFE001FFFFFF000000001FFFFFE000FFFFFFFF000000007FC07FE0007FE00FFE01FF00FFFFFFFC001FF801FF803FE007FF003FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FEFFFFF000FFFFFFC000000007FFFF8000FFFFFFFC000000007FC07FE0007FE007FE01FF00FFFFFFE0003FF001FF803FE007FE001FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FEFFFFF8007FFFFFF000000001FFFE0000FFFFFFE000000000FFC03FE000FFC007FE01FF00FFFFFFFC003FF000FFC03FE00FFE001FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FFFFFFFC003FFFFFF800000007FFFF8000FFFFFFFC00000000FF803FF000FFC003FE01FF00FFFFFFFF003FF000FFC03FE00FFC001FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FFFFFFFC001FFFFFFC0000001FFFFFE000FFFFFFFF00000000FF803FF000FFC003FF01FF00FFFFFFFF803FF000FFC03FE00FFC001FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FFC03FFE0007FFFFFE0000003FFFFFF000FFFFFFFF80000001FF803FF000FFC003FF01FF00FFFFFFFFC03FF000FFC03FE00FFC001FF800000FFE0007FF07FF00000FFC000000000FFC0003FE0003FF00000001FF001FFE0001FFFFFE0000007FFFFFF800FFFFFFFFC0000001FF801FF800FFFFFFFF01FF00FFFFFFFFE07FF000FFC03FE00FFC001FF800000FFE0007FF03FF00000FFC000000000FFC0003FE0003FF000000000E000FFE00001FFFFF000000FFF03FFC00FFFFFFFFE0000001FFFFFFF801FFFFFFFF01FF00FFC0007FF07FF000FFC03FE00FFC001FF800000FFE0007FF03FF00001FFC000000000FFC0003FE0003FF0000000000000FFE0000003FFF000001FFC00FFE00FFC0007FF0000003FFFFFFF801FFFFFFFF01FF00FFC0003FF07FF000FFC03FE00FFC001FF800000FFE0007FF03FF00001FFC000000000FFC0003FE0003FF00000000000007FE0000000FFF000001FF8007FE00FFC0003FF0000003FFFFFFFC01FFFFFFFF01FF00FFC0003FF07FF000FFC03FE00FFC001FF8000007FE0007FE03FF00001FFC000000000FFC0003FE0003FF00000000000007FE00000007FF000003FF8007FF00FFC0003FF0000003FFFFFFFC01FFFFFFFF01FF00FFC0003FF87FF000FFC03FE00FFC001FF8000007FE0007FE03FF80001FF8000000000FFC0003FE0003FF00000000000007FF00000003FF000003FF0003FF00FFC0003FF8000007FFFFFFFC01FFFFFFFF01FF00FFC0003FF83FF000FFC03FE00FFC001FF8000007FE0007FE03FF80001FF8000000000FFC0003FE0003FF00000000000007FE00000003FF000003FF0003FF00FFC0003FF8000007FFFFFFFE00FFC0000001FF00FFC0003FF83FF000FFC03FE00FFC001FF8000007FE0007FE01FF80003FF8000000000FFC0003FE0003FF00000000000007FE00000003FF000003FF0003FF00FFC0003FF8000007FFFFFFFE00FFC0000001FF00FFC0003FF83FF000FFC03FE00FFC001FF8000007FF000FFE01FFC0003FF8000000000FFC0003FE0003FF00000000180007FE00300003FF000003FF0003FF00FFC0003FF800000FFFFFFFFE00FFC0000001FF00FFC0003FF83FF000FF803FE00FFE001FF8000003FF000FFC01FFC0007FF0000000000FFC0003FE0003FF000000007C000FFE00780003FF000003FF0003FF00FFC0003FF800000FFFFFFFFF00FFC0000001FF00FFC0003FF83FF001FF803FE007FE001FF8000003FF801FFC00FFE000FFF0000000000FFC0003FE0003FF00000000FE000FFE00FE0007FF000003FF8007FF00FFC0003FF800000FFC0003FF00FFC0004001FF00FFC0007FF01FF801FF803FE007FF003FF8000003FF801FFC00FFF801FFE0000000000FFC0003FE0003FF00000001FF001FFC01FF000FFF000003FF8007FF00FFC0007FF000001FF80003FF007FE000E001FF00FFFFFFFFF01FFC03FF003FE007FF807FF8000001FFE07FF8007FFE0FFFE0000000000FFC0003FE0003FF80000003FF803FFC03FFE03FFE000003FFC00FFF00FFFFFFFFF000001FF80003FF807FF001F001FF00FFFFFFFFF00FFE0FFF003FFF07FFE1FFF8000001FFFFFFF8007FFFFFFFC0000001FFFFFFFF03FFF0FFFFFC000007FFF0FFFC07FFFFFFFE000001FFE01FFE00FFFFFFFFF000001FF80001FF803FFC07F801FF00FFFFFFFFE00FFFFFFE003FFF03FFFFFFF8000000FFFFFFF0003FFFFFFFC0000001FFFFFFFF03FFF0FFFFFC000003FFFFFFF807FFFFFFFC000001FFFFFFFE00FFFFFFFFE000003FF80001FF803FFFFFFC01FF00FFFFFFFFE007FFFFFE003FFF03FFFFFFF8000000FFFFFFE0001FFFFFFF80000001FFFFFFFF03FFF0FFFFFC000001FFFFFFF003FFFFFFFC000000FFFFFFFC00FFFFFFFFE000003FF00001FFC01FFFFFFC01FF00FFFFFFFFC003FFFFFC001FFF01FFFFDFF80000007FFFFFE0000FFFFFFF00000001FFFFFFFF01FFF0FFFFFC000000FFFFFFE001FFFFFFF80000007FFFFFF800FFFFFFFFC000003FF00001FFC01FFFFFFC01FF00FFFFFFFF8003FFFFF8001FFF00FFFFDFF80000003FFFFFC00007FFFFFE00000001FFFFFFFF01FFF0FFFFFC0000007FFFFFC000FFFFFFF00000003FFFFFF000FFFFFFFF8000007FF00000FFC00FFFFFF801FF00FFFFFFFF0001FFFFF0000FFF00FFFF9FF80000001FFFFF800003FFFFF800000001FFFFFFFF00FFF0FFFFFC0000003FFFFF80003FFFFFC00000001FFFFFE000FFFFFFFF0000007FE00000FFE003FFFFF001FF00FFFFFFFC00007FFFE00007FF003FFF1FF800000007FFFE000000FFFFF000000001FFFFFFFF007FF0FFFFFC0000000FFFFF00001FFFFF8000000007FFFF8000FFFFFFFC0000007FE00000FFE001FFFFC001FF00FFFFFFF000001FFF800000FF001FFC1FF800000001FFF80000003FFFC000000001FFFFFFFF000FF0FFFFFC00000003FFF8000003FFFC0000000001FFFE0000FFFFFFF0000000FFE000007FE0007FFF0001FF0000000000000003F8000000000003F00000000000003FC000000003FC000000000000000000000000000000000000003FC00000003FC000000000001FE00000000000000000000000000000000007F00001FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF000^FS +^FO51,248^GFA,7840,7840,98,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E0FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC07E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E0FC0000000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFC0000000F8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFF80000001FE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFF80000001FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE00000003FF0003F0000000000000000000000000000000007FE0000000000000000000000000000000000000000FFC00000000000000000000000000000000000007FC000000000000000000000000000000000000000000000000000000000003F800000003FE0007F8000000000000000000000000000000007FE0000000000000000000000000000000000000000FFC00000000000000000000000000000000000007FC0000000000000000000000000000000000000000000000000000000000000000000007FC000FFC0007FF800000000000000000000000007FE0000000000000000000000000000000000000000FFC0000000FFF0000001FFE0000000000FFF80007FC03FFFFC000003FFFFFE0000FFF8000000001FFE0000FFFFF80000000000FFE00000007FC000FFC003FFFE00000000000000000000000007FE0000000000000000000000000000000000000000FFC0000003FFFC000007FFFC000000001FFFC0007FC03FFFFC000007FFFFFE0003FFFF00000000FFFFC000FFFFFF8000000001FFF00000007F8000FFC00FFFFF80000000000000000000000007FE0000000000000000000000000000000000000000FFC000000FFFFF00001FFFFF000000003FFFC0007FC03FFFFC000007FFFFFE000FFFFFC0000001FFFFE000FFFFFFE000000001FFF0000000FF0000FFC01FFFFFC0000000000000000000000007FE0000000000000000000000000000000000000000FFC000001FFFFF80003FFFFF800000007FFFC0007FC03FFFFC000007FFFFFE001FFFFFE0000007FFFFF800FFFFFFF000000001FFF8000000FF0000FFC03FFFFFE0000000000000000000000007FE0000000000000000000000000000000000000000FFC000003FFFFFC0007FFFFFC00000007FFFC0007FC03FFFFC000007FFFFFE003FFFFFF8000007FFFFF800FFFFFFF800000003FFF8000001FE0000FFC07FFFFFF0000000000000000000000007FE0000000000000000000000000000000000000000FFC000003FFFFFC000FFFFFFE0000000FFFFC0007FC03FFFFC000007FFFFFE007FFFFFF800000FFFFFFC00FFFFFFFC00000003FFF8000001FC0000FFC0FFFFFFF0000000000000000000000007FE0000000000000000000000000000000000000000FFC000007FFFFFE001FFFFFFF0000001FFFFC0007FC03FFFFC000007FFFFFE007FFFFFFC00000FFFFFFC00FFFFFFFC00000003FFF8000000F800007F80FFFFFFF8000000000000000000000007FE0000000000000000000000000000000000000000FFC000007FFFFFE003FFFFFFF0000003FFFFC0007FC03FFFFC000007FFFFFE00FFFFFFF800001FFC0FFE00FFFFFFFC00000003FFFC0000003800001E01FFF07FF8000000000000000000000007FE0000000000000000000000000000000000000000FFC00000FFE07FF003FFE0FFF8000003FE7FC0007FC001FF80000007FFFFFE00FFF03FF000001FF807FE00FFFFFFFE00000007FFFC0000000000000001FFC01FFC000000000000000000000007FE0000000000000000000000000000000000000000FFC00000FFC03FF007FF003FF8000007FC7FC0007FC001FF80000007F8000000FFC007E000001FF003FE00FF800FFE00000007FBFC0000000000000003FF000FFC000000000000000000000007FE0000000000000000000000000000000000000000FFC00001FF801FF007FE000FFC00000FFC7FC0007FC001FF80000007F8000000FF8003C000001FF003FE00FF8007FE00000007FBFE0000000000000003FF0007F80007F000000003E000007C07FE0000FE000000007C000007F000000FE000000F80FFC00001FF801FF807FE000FFC00000FF87FC0007FC001FF80000007F0000001FF80018000001FE001FE00FF8007FE0000000FF3FE000001FC00000007FE0007E0003FFF0003FE0FFC0001FF07FE0007FFE0007FC1FF80007FFF00007FFE00003FE0FFC00001FF001FF80FFC0007FC00000FF07FC0007FC001FF80000007F0000001FF80000000001FE001FE00FF8007FE0000000FF1FE00000FFFC000FFC7FE00038000FFFFC003FE1FFE0007FFC7FE001FFFF8007FC3FFC000FFFFC001FFFF8000FFF8FFC00001FF000FF80FFC0007FE000007F07FC0007FC001FF80000007F0000001FF80000000001FE001FE00FF8007FE0000000FF1FE00003FFFF000FFC7FC00020001FFFFE003FE3FFF000FFFE7FE003FFFFC007FC7FFE003FFFFE003FFFFC001FFFCFFC00001FF000FF80FF80007FE000001E07FC0007FC001FF8000000FF0000001FF80000000001FE001FE00FF8007FE0000000FF1FF00007FFFF800FFC7FC00000003FFFFF003FE7FFF800FFFE7FE007FFFFE007FCFFFF003FFFFF007FFFFE001FFFCFFC00003FF000FFC0FF80003FE000000C07FC0007FC001FF8000000FF0000001FF80000000001FE001FE00FF8007FE0000001FF1FF0000FFFFFC00FFC7FC00000007FFFFF803FE7FFF801FFFF7FE00FFFFFF007FCFFFF007FFFFF80FFFFFF003FFFEFFC00003FF000FFC1FF80003FE000000007FC0007FC001FF8000000FF0000000FFC0000000001FF003FE00FF8007FE0000001FF1FF0001FFFFFE00FFCFFC00000007FFFFF803FE7FFF803FFFF7FE00FFFFFF007FCFFFF00FFFFFF00FFFFFF007FFFEFFC00003FF000FFC1FF80003FE000000007FC0007FC001FF8000000FF03FC000FFE0000000000FF003FC00FF8007FC0000001FE1FF0001FFFFFE00FFCFFC0000000FFFFFFC03FFFFFFC03FFFFFFE01FFC3FF807FFFFFF80FFE7FE01FFC3FF807FFFFFFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF0FFF000FFFC000000000FF807FC00FF8007FC0000003FE0FF8003FF87FF00FFCFFC0000000FFC0FFC03FFC1FFC03FF81FFE01FF00FF807FF83FF80FF807C01FF00FF807FF03FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF1FFFC00FFFFE000000007FE1FF800FF801FF80000003FE0FF8003FE01FF00FFCFFC0000001FF807FE03FF80FFC07FF00FFE03FF00FFC07FF01FF80FF803803FF00FFC0FFE01FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF3FFFE007FFFFC00000003FFFFF000FFFFFFF00000003FE0FF8007FE01FF80FFCFFC0000001FF003FE03FF00FFC07FE007FE03FE007FC07FE01FF80FF001003FE007FC0FFC00FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF3FFFF007FFFFF80000000FFFFC000FFFFFFE00000003FC07FC007FC00FF80FFCFFC0000001FF003FE03FF007FC07FE007FE03FE007FC07FE00FF80FF000003FE007FC0FFC00FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF7FFFF003FFFFFC00000007FFF8000FFFFFF000000007FC07FC007FC00FF80FFCFFC0000001FF003FE03FE007FC07FC007FE03FE007FC07FC00FF80FF800003FE007FC0FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF7FFFF801FFFFFE00000007FFF8000FFFFFF000000007FC07FC007FC00FF80FFCFFC0000003FF003FE03FE007FC07FC007FE07FE007FC07FC00FF80FFC00007FE007FC0FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FFF9FFF8007FFFFF0000003FFFFF000FFFFFFF00000007FC07FC00FFC00FF80FFCFFC0000003FF003FF03FE007FC07FC007FE07FE007FE07FC00FF80FFF80007FE007FE0FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FFC03FF8003FFFFF8000007FFFFF800FFFFFFF8000000FF803FE00FFC00FFC0FFCFFC0000003FF003FF03FE007FC07FC007FE07FFFFFFE07FC00FF80FFFFC007FFFFFFE0FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF8000000FF801FFC0007FFFF800000FFFFFFC00FFFFFFFC000000FF803FE00FFFFFFFC0FFCFFC0000003FF003FF03FE007FC07FC007FE07FFFFFFE07FC00FF807FFFF007FFFFFFE0FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF800000003001FFC00007FFFC00001FFC0FFE00FFC00FFE000000FF803FE00FFFFFFFC0FFCFFC0000003FF003FF03FE007FC0FFC007FE07FFFFFFE07FC00FF807FFFFC07FFFFFFE1FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF800000000000FFC000003FFC00001FF003FE00FF8003FF000000FFFFFFF00FFFFFFFC0FFCFFC0000003FF003FF03FE007FC0FFC007FE07FFFFFFE07FC00FF803FFFFE07FFFFFFE1FF800FFC00003FF000FFC1FF80003FF000000007FC0007FC001FF800000000000FFC000001FFC00003FF003FF00FF8001FF000001FFFFFFF00FFFFFFFC0FFCFFC0000003FF003FF03FE007FC0FFC007FE07FFFFFFE07FC00FF801FFFFF07FFFFFFE1FF800FFC00003FF000FFC1FF80003FE000000007FC0007FC001FF800000000000FFC000000FFC00003FE001FF00FF8001FF000001FFFFFFF00FFFFFFFC0FFCFFC0000003FF003FF03FE007FC07FC007FE07FFFFFFE07FC00FF8007FFFF87FFFFFFE0FF800FFC00003FF000FFC0FF80003FE000000007FC0007FC001FF800000000000FFC0000007FC00003FE001FF00FF8001FF800001FFFFFFF00FFFFFFFC0FFC7FC0000003FF003FF03FE007FC07FC007FE07FE0000007FC00FF8000FFFF87FE000000FF800FFC00001FF000FF80FF80003FE000000007FC0007FC001FF800000000000FFC0000007FE00007FE001FF80FF8001FF800003FFFFFFF80FFC000000FFC7FE0003803FF003FF03FE007FC07FC007FE07FE0000007FC00FF80000FFF87FE000000FF800FFC00001FF000FF80FF80007FE000000007FC0007FC001FF800000000000FFC0000007FC00007FE001FF80FF8001FF800003FFFFFFF80FFC000000FFC7FE0003E03FF003FE03FE007FC07FC007FE07FE0000007FC00FF800000FF87FE000000FF800FFC00001FF000FF80FFC0007FE000000007FC0007FC001FF80000000C000FFC0000007FC00007FE001FF80FF8001FF800003FFFFFFF80FFC000000FFC7FE0007F01FF003FE03FE007FC07FC007FE03FE0000007FC00FF800000FF83FE000000FF800FFC00001FF801FF80FFC0007FC000000007FC0007FC001FF80000001C000FFC0180007FC00007FE001FF80FF8001FF800003FFFFFFFC07FC000000FFC3FF0007FC1FF003FE03FE007FC07FE007FE03FE0004007FC00FF8010007F83FE000400FFC00FFC00001FF801FF807FE000FFC000000007FC0007FC001FF80000003E000FFC03C000FFC00007FE001FF80FF8001FF800007FC0007FC07FC000800FFC3FF800FFC1FF003FE03FE007FC07FE007FE03FF000E007FC00FF8038007F83FF000E00FFC00FFC00000FF801FF007FF001FFC000000007FC0007FC001FF8000000FF001FF807E000FFC00003FF003FF00FF8003FF000007FC0007FC07FE001C00FFC1FFC03FFC1FF807FE03FE007FC07FF00FFE03FF001E007FC00FF807C00FF83FF001E00FFE01FFC00000FFC03FF003FF803FF8000000007FC0007FC001FF8000001FF803FF80FF801FFC00003FF003FF00FF8007FF000007FC0007FC07FE003C00FFC1FFFFFFF80FFC0FFC03FE007FC03FF81FFE01FFC03F007FC00FF80FF00FF81FFC03F007FF03FFC00000FFF0FFF003FFFFFFF8000003FFFFFFE07FE03FFFFC00001FFE07FF81FFFFFFF800003FF807FF00FFFFFFFF00000FF80003FE03FF807E00FFC0FFFFFFF00FFFFFFC03FE007FC03FFFFFFE01FFFFFF807FC00FF81FFE7FF81FFFFFF807FFFFFFC000007FFFFFE001FFFFFFF0000003FFFFFFE07FFC3FFFFC00001FFFFFFF03FFFFFFF800001FFFFFFE00FFFFFFFE00000FF80003FE03FFFFFF00FFC0FFFFFFF007FFFFF803FE007FC03FFFF7FE00FFFFFFC07FC00FF81FFFFFF00FFFFFFC07FFFEFFC000007FFFFFE001FFFFFFE0000003FFFFFFE07FFC3FFFFC00000FFFFFFF01FFFFFFF000001FFFFFFE00FFFFFFFE00000FF80003FE01FFFFFF80FFC07FFFFFE007FFFFF803FE007FC01FFFF7FE007FFFFF807FC00FF81FFFFFF007FFFFF803FFFEFFC000003FFFFFC000FFFFFFE0000003FFFFFFE03FFC3FFFFC000007FFFFFE00FFFFFFF000000FFFFFFC00FFFFFFFC00000FF80003FF00FFFFFF00FFC03FFFFFC003FFFFF003FE007FC01FFFE7FE003FFFFF007FC00FF80FFFFFE003FFFFF003FFFCFFC000001FFFFF80007FFFFFC0000003FFFFFFE03FFC3FFFFC000003FFFFFC007FFFFFE0000007FFFFF800FFFFFFFC00001FF00001FF007FFFFE00FFC01FFFFF8001FFFFE003FE007FC00FFFE7FE001FFFFE007FC00FF807FFFFC001FFFFE001FFFCFFC000000FFFFF00003FFFFF80000003FFFFFFE01FFC3FFFFC000001FFFFF8003FFFFFC0000003FFFFF000FFFFFFF800001FF00001FF003FFFFC00FFC007FFFF0000FFFFC003FE007FC007FFC7FE000FFFFC007FC00FF801FFFF8000FFFFC000FFF8FFC0000007FFFE00000FFFFE00000003FFFFFFE00FFC3FFFFC0000007FFFF0000FFFFF00000001FFFFE000FFFFFFE000001FF00001FF001FFFF800FFC001FFFC00003FFF0003FE007FC001FF07FE0003FFF0007FC00FF8007FFE00003FFF00003FE0FFC0000001FFF8000003FFF800000003FFFFFFE003FC3FFFFC0000001FFFC00003FFFC000000007FFF8000FFFFFF8000003FF00001FF8007FFE000FFC0001FC0000007F0000000000000007C000000007F0000000000000007F0000007F000000F8000000000003FC00000003F800000000000000000000000000000000003FC0000003FC00000000007F8000000000000000000000000000000FE0000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF80^FS +^FO53,349^GFA,8112,8112,104,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F87C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F03E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E01E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E01E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E01E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E01E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F03E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC0000000003F000000003C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E000000007F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FC00000000FF80FF8007FC000000000000000000000000000000000000000000003FF00000003FF000000000000000000FF00007FFFE0000003FFFFFF00000000000003FFFFFE000003FF000000000000000003FF000007FFF8000000000000000001FE000000001FC00000000FF80FF8007FC00000000000000000000000000000000000000000001FFFE000001FFFE00000000000000003FF00007FFFF0000003FFFFFF00000000000003FFFFFF00001FFFC0000000000000001FFFE00007FFFFC00000000000000001FE000000001F800000000FF80FF8007FC00000000000000000000000000000000000000000003FFFF000003FFFF00000000000000007FF00007FFFF0000003FFFFFF00000000000003FFFFFF00003FFFF0000000000000003FFFF00007FFFFF00000000000000003FF000000003F000000000FF80FFC00FFC0000000000000000000000000000000000000000000FFFFFC00007FFFF8000000000000000FFF00007FFFF0000003FFFFFF00000000000003FFFFFF00007FFFF800000000000000FFFFFC0007FFFFF80000000000000003FF000000007E000000000FF80FFC00FFC0000000000000000000000000000000000000000000FFFFFC0000FFFFFC000000000000003FFF00007FFFF0000003FFFFFF00000000000003FFFFFF0000FFFFFC00000000000000FFFFFC0007FFFFFC0000000000000003FF00000000FC0000000007F00FBC00F7C0000000000000000000000000000000000000000001FE01FE0001FF03FE000000000000007FFF00007FFFF0000003FFFFFF00000000000003FFFFFE0001FF03FE00000000000001FF03FE0007FFFFFE0000000000000003FF00000000FC0000000001C00FBC01F7C0000000000000000000000000000000000000000003FC00FF0001FC00FE00000000000000FFBF00000003F000000000FC0000000000000003E000000003FC00FE00000000000003FC00FF0007E001FF0000000000000007FF80000000000000000000000FBE01F7C0000000000000000000000000000000000000000003F0007F0003F8007F00000000000003FF3F00000003F000000000FC0000000000000003E000000003F8007F00000000000003F8007F0007E0007F0000000000000007FF80000000000000000000000FBE01E7C0000000000000000000000000000000000000000007F0003F8003F0003F00000000000007FC3F00000003F000000000FC0000000000000003E000000003F0003F00000000000007F0003F8007E0003F0000000000000007CF80000000000000000000000F9E01E7C0000000000000000000000000000000000000000007E0001F8007F0003F80000000000007F83F00000003F000000000FC0000000000000003E000000007E0003F80000000000007E0001F8007E0003F8000000000000007CF80000000000000000000000F9F03E7C0000000000000000000000000000000000000000007E0001F8007E0001F80000000000007F03F00000003F000000000FC0000000000000003E000000007E0001F80000000000007E0001F8007E0001F800000000000000FCFC0000000000000000000000F9F03C7C0000000000000000000000000000000000000000007C0000F8007E0001F80000000000007C03F00000003F000000000FC0000000000000003E000000007E0001F80000000000007E0001F8007E0001F800000000000000FCFC0000000000000000000000F8F03C7C00003FF000007E0FFC0000003FF000000000000000FC0000FC007E0001F80000000000007803F00000003F000000000FC0000000000000003E000000007E0001F00000000000007E0001F8007E0001F800000000000000F87C0000003FF000007FFFFF00F8F87C7C0000FFFC00007E3FFF000000FFFC00000000000000FC0000FC007E0001F80000000000007003F00000003F000000000FC0000000000000003E000000007E0000000000000000007E0001F8007E0001F800000000000000F87C000001FFFE00007FFFFF00F8F8787C0003FFFF00007E7FFF800003FFFF00000000000000FC0000FC007E0001F80000000000004003F00000003F000000000FC0000000000000003E000000007E0000000000000000007E0001F8007E0001F800000000000001F87E000003FFFF00007FFFFF00F878787C0007FFFF80007E7FFFC00007FFFF80000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003E000000007E0000000000000000007E0001F8007E0001F800000000000001F87E000007FFFF80007FFFFF00F878F87C000FFFFFC0007EFFFFE0000FFFFFC0000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003E000000003F0000000000000000007F0001F8007E0001F800000000000001F03E00000FFFFFC0007FFFFF00F87CF07C001FF03FE0007EF01FE0001FF03FE0000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003E000000003F8000000000000000003F0003F0007E0003F000000000000001F03F00001FE01FE0007FFFFF00FC3CF0FC003FC00FF0007FC00FF0003FC00FF0000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003F000000003FC000000000000000003F8007F0007E0007F000000000000003F03F00003F8007F00000003F00FC3DF0FC003F8007F0007F8007F0003F8007F0000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003FFFF800001FF000000000000000001FC00FE0007E000FE000000000000003F03F00003F0003F00000003F00FC3FF0FC003F0003F0007F0003F8003F0003F0000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC0000000000000003FFFFE00001FFE00000000000000000FF03FC0007E003FC000000000000003E01F00003F0003F80000003F00FC3FE0FC007E0001F8007F0003F8007E0001F8000000000000FC0FC0FC007E0001F80000000000000003F00000003F000000000FC0000000000000003FFFFF80000FFFE00000000000000007FFFF80007FFFFF8000000000000007E01F80007E0001F80000003F00FC1FE0FC007E0001F8007F0001F8007E0001F8000000000000FC1FE0FC007E0001F80000000000000003F00000003F000000000FC0000000000000003FFFFFC00007FFFC0000000000000001FFFE00007FFFFE0000000000000007E01F80007E0001F80000003F00FC1FE0FC007E0001F8007E0001F8007E0001F8000000000000FC1FE0FC007E0001F80000000000000003F00000003F000000000FC0000000000000003FFFFFE00001FFFF0000000000000000FFF800007FFFF80000000000000007E01F80007E0001F80000003F00FC1FC0FC007E0001F8007E0001F8007E0001F8000000000000FC1FE0FC007E0001F80000000000000003F00000003F000000000FC00000000000000000003FE00000FFFF8000000000000003FFFF00007FFFFF0000000000000007C00F80007E0001F80000003F00FC0FC0FC007E0001F8007E0001F8007E0001F8000000000000FC1FE0FC007E0001F80000000000000003F00000003F000000000FC00000000000000000000FF000001FFFC00000000000000FFFFFC0007FFFFFC00000000000000FC00FC0007C0000F80000003F00FC0FC0FC007E0001F8007E0001F8007E0001F8000000000000FC1FE0FC007E0001F80000000000000003F00000003F000000000FC000000000000000000007F0000003FFE00000000000001FF03FE0007E003FE00000000000000FC00FC0007C0000F80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0FC0FC007E0001F80000000000000003F00000003F000000000FC000000000000000000003F80000003FF00000000000003FC00FF0007E000FF00000000000000FC00FC0007E0001F80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000003F80000000FF00000000000007F0003F8007E0003F00000000000000F800FC0007FFFFFF80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000003F80000000000007E0001F8007E0001F80000000000001F8007E0007FFFFFF80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000001F8000000000000FE0001FC007E0001F80000000000001F8007E0007FFFFFF80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000001FC000000000000FC0000FC007E0000FC0000000000001FFFFFE0007FFFFFF80000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000000FC000000000000FC0000FC007E0000FC0000000000001FFFFFE0007E0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000000FC000000000000FC0000FC007E0000FC0000000000003FFFFFF0007C0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000000FC000000000001F800007E007E0000FC0000000000003FFFFFF0007C0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000000001F800000000FC000000000001F800007E007E0000FC0000000000003FFFFFF0007C0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000FC0001F800FC0000FC000000000001F80000FE007E0000FC0000000000003F0003F0007E0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F8000000000000FC0000FC007E0001F80000000000000003F00000003F000000000FC000000000000000FC0001F800FC0000FC000000000000FC0000FC007E0000FC0000000000007E0001F8007E0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F80000000000007E0001F8007E0001F80000000000000003F00000003F000000000FC000000000000000FC0001F800FC0000FC000000000000FC0000FC007E0000FC0000000000007E0001F8007E0000000000003F00FC0000FC007E0001F8007E0001F8007E0001F80000000000007E0001F8007E0001F80000000000000003F00000003F000000000FC000000000000000FE0001F800FE0000FC000000000000FC0000FC007E0001FC0000000000007E0001F8007E0000000000003F00FC0000FC007F0003F8007E0001F8007F0003F80000000000007E0001F8003F0003F00000000000000003F00000003F000000000FC0000000000000007E0003F800FE0001F8000000000000FE0001FC007E0001FC0000000000007E0001F8007F0001F80000003F00FC0000FC003F0003F0007E0001F8003F0003F00000000000007F0003F8003F8007F00000000000000003F00000003F000000000FC0000000000000007F0007F0007F0003F80000000000007F0003F8007E0003F8000000000000FC0000FC003F0003F80000003F00FC0000FC003F8007F0007E0001F8003F8007F00000000000003F8007F0003FC00FF00000000000000003F00000003F800000000FC0000000000000003F800FF0007F8007F80000000000007F8007F8007E000FF8000000000000FC0000FC003F8007F00000003F00FC0000FC001FE01FE0007E0001F8001FE01FE00000000000003FE01FE0001FE01FE00000000000000003F80000001FF00000001FE0000000000000003FE01FE0003FE01FF00000000000003FE01FF0007E007FF0000000000000FC0000FC001FE00FF00000003F00FC0000FC000FFFFFC0007E0001F8000FFFFFC00000000000001FFFFFE0000FFFFFC00000000000007FFFFFFE00001FFFFF003FFFFFF00000000000001FFFFFE0001FFFFFE00000000000001FFFFFE0007FFFFFE0000000000001FC0000FC000FFFFFE00000003F00FC0000FC000FFFFFC0007E0001F8000FFFFFC00000000000000FFFFFC0000FFFFFC00000000000007FFFFFFE00000FFFFF003FFFFFF00000000000000FFFFFC0000FFFFFC00000000000000FFFFFC0007FFFFFC0000000000001F800007E000FFFFFC00000003F00FC0000FC0003FFFF00007E0001F80003FFFF0000000000000007FFFF800007FFFF800000000000007FFFFFFE000007FFFF003FFFFFF000000000000007FFFF800007FFFF8000000000000007FFFF80007FFFFF80000000000001F800007E0007FFFF800000003F00FC0000FC0001FFFE00007E0001F80001FFFE0000000000000001FFFE000001FFFE000000000000007FFFFFFE000003FFFF003FFFFFF000000000000003FFFE000003FFFF0000000000000003FFFF00007FFFFE00000000000001F800007E0001FFFF000000003F00FC0000FC00007FF800007E0001F800007FF800000000000000007FF80000007FF8000000000000007FFFFFFE0000007FFF003FFFFFF000000000000000FFF8000000FFFC0000000000000000FFFC00007FFFF000000000000003F800007F00007FFC000000003F00000000000000000000000000000000000000000000000000000007C00000000780000000000000000000000000000000000000000000000000000000000F8000000007C000000000000000000FC000000000000000000000000000000000000007C0000000003F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFC0000^FS +^FO53,447^GFA,8216,8216,104,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FCFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F03E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E01F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E01F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E01F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E01F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003F03F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F87E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE000000000FF800000007F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000FFC0FFFF8000000000000007FFFF800000000003FC000000000000007FF80000007FF800000000000000000FF80007FFFF8000007FFFFFF80000000000007FFFFFF000007FF800000000000000007FF80000FFFF8000000000000000003FF000000003FE00000001FFC0FFFFFC00000000000007FFFF800000000003FC00000000000001FFFE000001FFFE00000000000000003FFC0007FFFF8000007FFFFFF80000000000007FFFFFF80001FFFE0000000000000001FFFE0000FFFFFC00000000000000007FF800000007FC00000001FFC0FFFFFF00000000000007FFFF800000000003FC00000000000007FFFF800007FFFF80000000000000007FFC0007FFFF8000007FFFFFF80000000000007FFFFFF80007FFFF8000000000000007FFFF8000FFFFFF00000000000000007FF800000007F800000001FFC0FFFFFFC0000000000007FFFF800000000003FC0000000000000FFFFFC0000FFFFFC000000000000001FFFC0007FFFF8000007FFFFFF80000000000007FFFFFF8000FFFFFC00000000000000FFFFFC000FFFFFFC0000000000000007FF80000000FF000000000FFC0FFFFFFE0000000000007FFFF800000000003FC0000000000001FFFFFE0001FFFFFE000000000000003FFFC0007FFFF8000007FFFFFF80000000000007FFFFFF8001FFFFFE00000000000001FFFFFE000FFFFFFE0000000000000007FF80000001FF000000000FF80FFFFFFF0000000000007FFFF800000000003FC0000000000003FFFFFF0003FFFFFF000000000000007FFFC0007FFFF8000007FFFFFF80000000000007FFFFFF8003FFFFFF00000000000003FFFFFF000FFFFFFF000000000000000FFFC0000003FE0000000003F00FFFFFFF8000000000007FFFF800000000003FC0000000000007FFFFFF8003FFFFFF00000000000001FFFFC0007FFFF8000007FFFFFF80000000000007FFFFFF8007FFFFFF00000000000003FFFFFF800FFFFFFF800000000000000FFFC0000000000000000000000FF007FF8000000000007FFFF800000000003FC0000000000007FF03FF8007FF03FF80000000000003FFFFC0007FFFF8000007FFFFFF80000000000007FFFFFF0007FE03FF80000000000007FE01FF800FF007FF800000000000000FFFC0000000000000000000000FF001FFC000000000000007F800000000003FC0000000000007FC00FF8007FC00FF80000000000007FFFFC0000007F800000001FE0000000000000007F800000007FC00FF80000000000007FC00FF800FF001FFC00000000000000FFFC0000000000000000000000FF0007FC000000000000007F800000000003FC000000000000FF8007FC00FF8007F80000000000007FF7FC0000007F800000001FE0000000000000007F80000000FF8007F8000000000000FF8007FC00FF0007FC00000000000001FFFE0000000000000000000000FF0007FC000000000000007F800000000003FC000000000000FF0003FC00FF8007FC0000000000007FC7FC0000007F800000001FE0000000000000007F80000000FF0007FC000000000000FF8007FC00FF0007FC00000000000001FCFE0000000000000000000000FF0003FC000000000000007F800000000003FC000000000000FF0003FC00FF0003FC0000000000007F87FC0000007F800000001FE0000000000000007F80000000FF0003FC000000000000FF0003FC00FF0003FC00000000000001FCFE0000000000000000000000FF0003FC00003FF00000007F80000001FF03FC000000000000FF0003FC00FF0003FC0000000000007F07FC0000007F800000001FE0000000000000007F80000000FF0003FC000000000000FF0003FC00FF0003FC00000000000001FCFE0000007FF80000FFFFFF80FF0003FC0001FFFE0000007F80000007FFC3FC000000000000FE0001FC00FF0003FC0000000000007C07FC0000007F800000001FE0000000000000007F80000000FF000000000000000000FF0003FC00FF0003FC00000000000003FCFF000001FFFE0000FFFFFF80FF0003FC0007FFFF8000007F8000000FFFE3FC000000000000FE0001FC00FF0003FC0000000000007807FC0000007F800000001FE0000000000000007F80000000FF000000000000000000FF0003FC00FF0003FC00000000000003FCFF000007FFFF8000FFFFFF80FF0003FC000FFFFFC000007F8000001FFFF3FC000000000000FE0001FC00FF0003FC0000000000007007FC0000007F800000001FE0000000000000007F80000000FF000000000000000000FF0003FC00FF0003FC00000000000003F87F00000FFFFFC000FFFFFF80FF0003FC001FFFFFE000007F8000003FFFFBFC000000000000FE0001FC00FF0003FC0000000000004007FC0000007F800000001FE0000000000000007F80000000FF8000000000000000007F8007FC00FF0003FC00000000000003F87F00001FFFFFE000FFFFFF80FF0007F8003FFFFFF000007F8000003FFFFBFC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007F80000000FFC000000000000000007F8007F800FF0007F800000000000007F87F80003FFFFFF000FFFFFF80FF000FF8003FFFFFF000007F8000007FFFFFFC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFF000007FF000000000000000007FC00FF800FF000FF800000000000007F87F80003FF03FF000FFFFFF80FF001FF0007FF03FF800007F8000007FF03FFC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFE00007FFE00000000000000003FF03FF000FF001FF000000000000007F07F80007FC00FF800FFFFFF80FFFFFFE0007FC00FF800007F800000FFC01FFC000000000000FE0301FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFF80003FFFE0000000000000001FFFFFE000FFFFFFE000000000000007F03F80007F8007F80000007F80FFFFFFC000FF8007FC00007F800000FF800FFC000000000000FE0FC1FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFFC0003FFFFC000000000000000FFFFFC000FFFFFFC00000000000000FF03FC000FF8007FC0000007F80FFFFFF0000FF8007FC00007F800000FF8007FC000000000000FE1FE1FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFFE0001FFFFF0000000000000003FFFF0000FFFFFF000000000000000FF03FC000FF0003FC0000007F80FFFFFE0000FF0003FC00007F800000FF0007FC000000000000FE1FE1FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFFF0000FFFFFC000000000000001FFFE0000FFFFFE000000000000000FF03FC000FF0003FC0000007F80FFFFFFC000FF0003FC00007F800000FF0007FC000000000000FE1FE1FC00FF0003FC0000000000000007FC0000007F800000001FE0000000000000007FFFFFF00003FFFFE000000000000007FFFF8000FFFFFFC00000000000000FE01FC000FF0003FC0000007F80FFFFFFE000FF0003FC00007F800000FF0007FC000000000000FE1FE1FC00FF0003FC0000000000000007FC0000007F800000001FE00000000000000000007FF80001FFFFF00000000000001FFFFFE000FFFFFFE00000000000001FE01FE000FF0003FC0000007F80FFFFFFF000FF0003FC00007F800000FF0003FC000000000000FE1FE1FC00FF0003FC0000000000000007FC0000007F800000001FE00000000000000000001FF800003FFFF00000000000003FFFFFF000FFFFFFF00000000000001FE01FE000FF0003FC0000007F80FF003FF800FF0003FC00007F800000FF0003FC000000000000FE0FC1FC00FF0003FC0000000000000007FC0000007F800000001FE00000000000000000000FFC000007FFF80000000000007FF03FF800FF003FF80000000000001FE01FE000FFFFFFFC0000007F80FF000FFC00FF0003FC00007F800000FF0003FC000000000000FE0301FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000007FC0000007FFC000000000000FFC00FFC00FF000FFC0000000000003FC01FE000FFFFFFFC0000007F80FF0007FC00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC0000000FFC000000000000FF8007FC00FF0007FC0000000000003FC00FF000FFFFFFFC0000007F80FF0003FE00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC00000007FC000000000001FF0003FE00FF0003FE0000000000003FFFFFF000FFFFFFFC0000007F80FF0001FE00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC00000003FE000000000001FE0001FE00FF0001FE0000000000003FFFFFF000FFFFFFFC0000007F80FF0001FE00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC00000003FE000000000001FE0001FE00FF0001FE0000000000007FFFFFF000FFFFFFFC0000007F80FF0001FE00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC00000001FE000000000001FE0001FE00FF0001FE0000000000007FFFFFF800FF0000000000007F80FF0001FE00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC00000001FE000000000001FE0001FE00FF0001FE0000000000007FFFFFF800FF0000000000007F80FF0001FF00FF0003FC00007F800000FF0003FC000000000000FE0001FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000000000003FC01FE0001FE000000000001FE0001FE00FF0001FF0000000000007FFFFFF800FF0000000000007F80FF0001FE00FF0003FC00007F800000FF0007FC000000000000FF0003FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000001FF0003FC01FE0001FE000000000001FE0001FE00FF0001FE000000000000FFFFFFF800FF0000000000007F80FF0001FE00FF0003FC00007F800000FF0007FC000000000000FF0003FC00FF0003FC0000000000000007FC0000007F800000001FE000000000000001FF0003FC01FE0001FE000000000001FE0001FE00FF0001FE000000000000FF8007FC00FF0000000000007F80FF0003FE00FF8007FC00007F800000FF8007FC000000000000FF0003FC00FF8007FC0000000000000007FC0000007F800000001FE000000000000001FF0007FC01FF0003FE000000000001FF0003FE00FF0003FE000000000000FF0003FC00FF0000000000007F80FF0003FE00FF8007FC00007FC00000FF800FFC000000000000FF8007FC00FF8007FC0000000000000007FC0000007FC00000001FE000000000000000FF8007FC01FF0003FE000000000001FF0003FE00FF0003FE000000000000FF0003FC00FF8003FC0000007F80FF0007FE007FC00FF800007FE00000FFC00FFC000000000000FFC00FFC007FC00FF80000000000000007FC0000007FE00000001FE000000000000000FF800FFC00FF8007FC000000000001FF8007FE00FF0007FE000000000001FF0003FE007F8007FC0000007F80FF001FFC007FE01FF800003FFFFF007FE01FFC0000000000007FE01FF8007FE01FF80000000000007FFFFFFE00003FFFFF007FFFFFF8000000000000FFE01FF800FFE01FFC000000000000FFC00FFC00FF001FFC000000000001FF0003FE007FC00FF80000007F80FFFFFFFC007FFFFFF800003FFFFF007FFFFFFC0000000000007FFFFFF8003FFFFFF00000000000007FFFFFFF00003FFFFF007FFFFFF80000000000007FFFFFF8007FFFFFF8000000000000FFFCFFFC00FFFFFFFC000000000001FE0001FE007FF83FF80000007F80FFFFFFF8003FFFFFF000003FFFFF007FFFFFFC0000000000003FFFFFF0003FFFFFF00000000000007FFFFFFF00003FFFFF007FFFFFF80000000000007FFFFFF0007FFFFFF80000000000007FFFFFF800FFFFFFF8000000000001FE0001FE003FFFFFF00000007F80FFFFFFF0001FFFFFE000001FFFFF003FFFFBFC0000000000001FFFFFE0001FFFFFE00000000000007FFFFFFF00001FFFFF007FFFFFF80000000000003FFFFFE0003FFFFFF00000000000003FFFFFF000FFFFFFF0000000000003FE0001FF001FFFFFE00000007F80FFFFFFE0000FFFFFC000000FFFFF001FFFF3FC0000000000000FFFFFC0000FFFFFC00000000000007FFFFFFF00000FFFFF007FFFFFF80000000000001FFFFFE0001FFFFFE00000000000001FFFFFE000FFFFFFE0000000000003FE0001FF000FFFFFE00000007F80FFFFFFC00007FFFF80000007FFFF000FFFE3FC00000000000007FFFF800007FFFF800000000000007FFFFFFF000007FFFF007FFFFFF80000000000000FFFFF80000FFFFFC00000000000000FFFFFC000FFFFFFC0000000000003FC0000FF0007FFFF800000007F80FFFFFF000003FFFF00000001FFFF0007FFC3FC00000000000003FFFF000003FFFF000000000000007FFFFFFF000001FFFF007FFFFFF800000000000003FFFF000003FFFF0000000000000003FFFF0000FFFFFF00000000000003FC0000FF0003FFFF000000007F80FFFFF8000000FFFC000000007FFF0003FF83FC00000000000000FFFC000000FFFC000000000000007FFFFFFF0000007FFF007FFFFFF800000000000000FFFC000000FFFC0000000000000000FFFC0000FFFFF800000000000007FC0000FF8000FFFC000000007F80000000000000030000000000000000003C0000000000000000000FC00000000780000000000000000000000000000000000000000000000000000000000F800000000FC000000000000000000FC00000000000000000000000000000000000000FC000000000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFE0000^FS +^XZ diff --git a/renderer/src/test/resources/scene2/golden/text-fit-203.png b/renderer/src/test/resources/scene2/golden/text-fit-203.png new file mode 100644 index 0000000000000000000000000000000000000000..81e3ff7a8db4ee0d74a9fde5f144246333238e9e GIT binary patch literal 2041 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 Fe*xS={9gb7 literal 0 HcmV?d00001 diff --git a/renderer/src/test/resources/scene2/golden/text-fit-300.zpl b/renderer/src/test/resources/scene2/golden/text-fit-300.zpl new file mode 100644 index 0000000..b98f266 --- /dev/null +++ b/renderer/src/test/resources/scene2/golden/text-fit-300.zpl @@ -0,0 +1,3 @@ +^XA^PW600^LL300^LH0,0^CI28 +^FO24,24^GFA,17388,17388,69,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000001F8000000001800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000003F000000000000001F800000000180000000000300000000000000180000000000020000000000000000000000002000000004000000000000000000000000000000000001FFE000003FFFE0001F80000000018007F000007FF001FFFFF80001FFC00007F8007FF00003FE000FFC0007FE00002000000004000000000000000000000000000000000003FFF000007FFFE0001F80000000018007F00000FFFC01FFFFF80003FFE00007F800FFF80007FC001FFC000FFE00002000000004000000000000000000000000000000000007FFF800007FFFE0001F80000000018007F00003FFFE01FFFFF8000FFFF0000FF801FFFC000FF0003FFC001FFE0000200000000400000000000000000000000000000000000FFFFC00007FFFE0001F80000001F18007F00007FFFF01FFFFF8001FFFF8001FF803FFFE001FE0003FFC001FFE0000200000000400000000000000000000000000000000001FF3FC00007FFFE0001F80000003F18007F00007FFFF81FFFFF8001FFFFC001FF807FFFF003FC0007FFC003FFE0000200000000400000000000000000000000000000000001FC0FE00007E0000001F80000003F18007F0000FF07FC0FFFFF8003FC3FC003FF807F07F007F8000FEFC007F7E0000200000000400000000000000000000000000000000001F807E00007C0000001F80000003F18007F0000FE01FC001F800003F01FC007FF807E03F007F0001FCFC00FE7E0000200000000400000000000000000000000000000000003F807E00007C0000001F80FC03FFF18007F0001FC00FE001F800001F00FC007DF80FE03F80FE0001F8FC00FC7E0000200000000400000000000000000000000000000000003F807E00007C0000001F81FC0FFF018007F0001F800FE001F800000200FC00F9F80FC01F81FC0003F0FC01F87E0000200000000400000000000000000000000000000000003F807F00007C0000001F81FC1FFF818007F0001F8007E001F800000000FC00F9F80FC01F81F80003F0FC01F87E0000200000000400000000000000000000000000000000003F807F00007C0000001F83F83FFFC18007F0003F8007E001F800000001FC01F1F80FC01F83F8F001E0FC00F07E0000200000000400000000000000000000000000000000003F807F00007C7F00001F87F07F0FC18007F0003F8007E001F800000001FC03F1F81FC01FC3F3FE0040FC00207E0000200000000400000000000000000000000000000000003F807F00007CFFC0001F8FE07E07E18007F0003F8007F001F800000003F803E1F81FC01FC3F7FF0000FC00007E0000200000000400000000000000000000000000000000001FC0FF00007DFFE0001F8FC07E07E18007F0003F8007F001F800000003F807C1F81FC01FC7FFFF8000FC00007E0000200000000400000000000000000000000000000000001FF3FE00007DFFF0001F9FC07E07E18007F0003F8007F001F800000007F00FC1F81FC01FC7FFFF8000FC00007E0000200000000400000000000000000000000000000000001FFF7E00007FFFF0001F9F807E07E18007F0003F8007F001F80000001FE00F81F81FC01FC7F83FC000FC00007E0000200000000400000000000000000000000000000000000FFF7E00007F07F0001FBF007E07E18007F0003F8007F001F80000003FC01F81F81FC01FC7F01FC000FC00007E00002000000004000000000000000000000000000000000007FEFE00007C03F8001FFF007E07E18007F0003F8007E001F80000007F801F01F81FC01FC7F00FC000FC00007E00002000000004000000000000000000000000000000000003FCFE00000003F8001FFF803F9FE18007F0003F8007E001F8000000FF003F01F80FC01F87E00FE000FC00007E00002000000004000000000000000000000000000000000000F0FC00000003F8001FFF803FFFC18007F0001F8007E001F8000001FE003FFFFF8FC01F87E00FE000FC00007E0000200000000400000000000000000000000000000000000001FC00000003F8001FFFC01FFF818007F0001FC00FE001F8000003F8003FFFFF8FC01F87E00FC000FC00007E0000200000000400000000000000000000000000000000000001F800000003F8001FEFC00FFF018007F0001FC00FE001F800000FF0003FFFFF8FE03F87E00FC000FC00007E0000200000000400000000000000000000000000000000000003F800000803F8001FCFE00DF8018007F0000FE01FC001F800001FE0003FFFFF87E03F07F00FC000FC00007E0000200000000400000000000000000000000000000000000007F000003803F8001FC7E03800018007FFFC0FF87FC001F800003FC0000001F807F07F03F01FC000FC00007E000020000000040000000000000000000000000000000000000FF007C07C03F0001F87F07800018007FFFE07FFFF8001F800003FFFFE0001F807FFFF03FC7F80FFFFF07FFFF80020000000040000000000000000000000000000000000001FE00FE0FE07F0001F83F07C00018007FFFE07FFFF0001F800003FFFFE0001F803FFFE01FFFF80FFFFF07FFFF80020000000040000000000000000000000000000000000003FC00FE0FFFFF0001F83F87FFF818007FFFE03FFFE0001F800003FFFFE0001F801FFFC00FFFF00FFFFF07FFFF80020000000040000000000000000000000000000000000007F800FE07FFFE0001F81FC7FFFE18007FFFE00FFFC0001F800003FFFFE0001F800FFF8007FFC00FFFFF07FFFF8002000000004000000000000000000000000000000000000FF000FE03FFFC0001F81FC7FFFF18007FFFE003FF00001F800003FFFFE0001F8003FE0001FF800FFFFF07FFFF8002000000004000000000000000000000000000000000001FE000FE01FFF80001F80FE3FFFF980000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000007FC0007C007FE00001F80FE0FFFF98000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000004000000000003807F98000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000007801FD800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000F800F9800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000F801F9800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000F801F9800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000FFFFF9800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000FFFFF18000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000007FFFE18000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000000000000000000000000000001FFF81800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000020000000040000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000801C000000000380000000000000000000000000000000000000000000000000000000000000001C0000000007000000000000000000000000000000000000000200000000807C0000000003E0000000000000000000000000000000000000000000000000000000000000007C0000000007C0000000000000000000000000000000000000020000000080FC01F0007803F0003E003E001F00078007C01FFC001C07FF001C07FFC03E001F000F803FF800FC00F000F807E00180003E0001C00F8001C001E000F000E000020000000081F007FC00F800F800FF80FF807FC00F801FF03FFC00380FFF003C07FFE0FF807FC03FE07FF801F001F003FE01F003C000FF8003803FE003C003E001F001F000020000000083E00FFE03F8007C01FFC1FFC0FFE03F803FF83FFC00780FFF003C07FFE1FFC0FFE07FF07FF803E007F007FF00F803C001FFC007807FF003C00FE007F001F000020000000083C00F1E07F8003C01E3C1E3C0F1E07F803CF81FFC00F00FFF007807FFE1E3C1F1F078F07FF803C00FF0078F007803C001E7C00F0078F007801FE00FF003F000020000000087801E0F0FB8001E03C1E3C1E1E0F0FB80783C007800E00F0000780701C3C1E1E0F0F078780007801F700F07803C03C003C1E00E00F07807803EE01F7003F800020000000087801C070E38001E0380E380E1C070E380703C00F001E00F0000F00703C3C1E1C070E038780007801C700E03803C03C00381E01E00E0380F0038E01C7003B800020000000087001C070C38001E0380E380E1C070C380703C01E003C00F0000E0070383C1E1C070E0387800070018700E03803C03C00381E03C00E0380E0030E0187003B800020000000087001C070038000E0380E380E1C0700380003C03C003C00F0001E0000783C1C1C070E0387800070000700E03801C03C00001E03C00E0381E0000E0007007B800020000000087001C070038000E0380E380E1C0700380003803E007800FFC03DC000781E3C1C070E0387FE0070000700E03801C03C00001C07800E0383DC000E00070073C00020000000087001CE70038000E039CE39CE1CE700380007803F80F0E0FFE03FF000F00FF81E0F0E7387FF0070000700E73801C03C00003C0F0E0E7383FF000E00070071C00020000000087001CE70038000E039CE39CE1CE70038000F003FC0F0E0FFF07FF800F00FF01FFF0E7387FF8070000700E73801C03C0000780F0E0E7387FF800E00070071C00020000000087001CE70038000E039CE39CE1CE70038001F0003C1E0E000F07C7C00E01FFC0FFE0E7380078070000700E73801C03C0000F81E0E0E7387C7C00E000700F1C00020000000087001C070038000E0380E380E1C070038003E0001E1C0E00078783C01E03C1E03FE0E038003C070000700E03801C03C0001F01C0E0E038783C00E000700F1E00020000000087001C070038000E0380E380E1C070038007C0001E1C0E00078701C01E0380E003C0E038003C070000700E03801C03C0003E01C0E0E038701C00E000700FFE00020000000087001C070038000E0380E380E1C07003800F80001E1FFE00078701C03C0380E003C0E038003C070000700E03801C03C0007C01FFE0E038701C00E000700FFE00020000000087001C070038001E0380E380E1C07003801F00381E1FFE0E078701C03C0380E00780E038703C070000700E03803C03C000F801FFE0E038701C00E000701FFE00020000000087801E0F0038001E03C1E3C1E1E0F003803E00381E1FFE0F078703C0780380E00700F078783C078000700F07803C03C001F001FFE0F078703C00E000701E0F00020000000087801E0F0038001C03C1E3C1E1E0F003807C003C3C000E0F0F8783C07803C1E00F00F078787C078000700F07803803C003E00000E0F078783C00E000701C0700020000000083C00FFE0FFFC03C01FFC1FFC0FFE0FFFC7FFC3FFC000E07FF03FF807003FFC01E007FF03FF803C01FFF87FF007803FFE3FFE000E07FF03FF83FFF1FFF9C0700020000000083E007FC0FFFC07C00FF80FF807FC0FFFC7FFC1FF8000E07FE01FF00F001FF801E003FE03FF003E01FFF83FE00F803FFE3FFE000E03FE01FF03FFF1FFFBC0780020000000081F803F80FFFC1F8007F007F003F80FFFC7FFC07F0000E01FC00FE00F0007F003C001FC00FE001F81FFF81FC03F003FFE3FFE000E01FC00FE03FFF1FFFBC0780020000000080FC0000000003F000000000000000000000000000000000000000000000000000000000000000FC0000000007E00000000000000000000000000000000000000200000000807C0000000003E0000000000000000000000000000000000000000000000000000000000000007C0000000007C00000000000000000000000000000000000000200000000801C000000000380000000000000000000000000000000000000000000000000000000000000001C0000000007000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008007000000000038000000000000000000000000000000000000000000000000000000000000000000E0000000000700000000000080000000000000000000000000000000800F00000000003E000000000000000000000000000000000000000000000000000000000000000001E00000000007C0000000000080000000000000000000000000000000801E000C0000000F0000C0003000180000000300000000000000000000000001000040003000000003C0000000C001E00000000600800000000000000000000000000000008038007F801F00078007F801FE00FF001F001FE01FFC003803FF800E00FFFC0FF003FC01FE01FFC0070007C007F800F00180003FC080000000000000000000000000000000807000FFC03F0003800FFC03FF01FF803F003FF01FFC003803FF800E00FFFC1FF807FE03FF01FFC00E000FC00FFC00700180007FE08000000000000000000000000000000080E001C1C07F0001C01C1C07070383807F007070001C00700300001C00E01C38380E0F07070180001C001FC01C1C0038018000E0E08000000000000000000000000000000080E00180E0E70000C0180E06038301C0E7006038003800E00300001800E018381C1C0706038180001C0039C0180E0018018000C0708000000000000000000000000000000080E00380E0C70000E0380E0E038701C0C700E038007000E00300003800E038301C1C030E038180001C0031C0380E001C018001C0708000000000000000000000000000000080C0038060870000E038060E018700C08700E03800E001C003000030006038301C1C038E01818000180021C03806001C018001C0708000000000000000000000000000000081C0038060070000E038060E018700C00700003801C001C003000070000070301C1C038E01818000380001C03806001C01800000708000000000000000000000000000000081C0038060070000E038060E018700C00700003803C00380038000E000007038381C030E0181C000380001C03806001C01800000708000000000000000000000000000000081C0038060070000E038060E018700C00700003003F0070003FE00FF0000601E701C030E0181FF00380001C03806001C01800000608000000000000000000000000000000081C0039C60070000E039C60E718738C00700007003F8070603FF81FFC000E00FE00E070E7181FFC0380001C039C6001C01800000E08000000000000000000000000000000081C0039C60070000E039C60E718738C0070000E0001C0E06000381E1C000E01FF00F1F0E718001C0380001C039C6001C01800001C08000000000000000000000000000000081C0038C60070000E038C60E318718C0070001C0000E1C060001C380E001C03C3807FE0E318000E0380001C038C6001C01800003808000000000000000000000000000000081C0038060070000E038060E018700C0070003C0000E1C060001C3806001C0301C01FC0E018000E0380001C03806001C01800007808000000000000000000000000000000081C0038060070000E038060E018700C007000780000E1C060001C380700180700C001C0E018000E0380001C03806001C0180000F008000000000000000000000000000000081C0038060070000E038060E018700C007000F00000E1FFE0001C380700380700E00380E018000E0380001C03806001C0180001E008000000000000000000000000000000080C0038060070000E038060E018700C007001E00380E1FFE0701C380600380700E00380E018380E0180001C03806001C0180003C008000000000000000000000000000000080E00380E0070000E0380E0E038701C007003C00380E000E0701C380600700700C00700E038380E01C0001C0380E001C01800078008000000000000000000000000000000080E001C0E0070000C01C0E07038381C007003800380C00060301C1C0E00700701C007007038180E01C0001C01C0E001801800070008000000000000000000000000000000080E001E1C0070001C01E1C078703C380070070001C3C000603C381E1C006003C3C00E0078701E1C01C0001C01E1C003801C000E00080000000000000000000000000000000807000FF80FFF803800FF803FE01FF00FFF8FFF80FF8000601FF00FFC00E001FF800E003FE00FF800E003FFE0FF8007001FFE1FFF0800000000000000000000000000000008038007F00FFF8078007F001FC00FE00FFF8FFF807F0000600FE007F000E000FE001C001FC007F0007003FFE07F000F001FFE1FFF080000000000000000000000000000000801E00000000000F000000000000000000000000000000000000000000000000000000000000000003C00000000001E0000000000080000000000000000000000000000000800F00000000003E000000000000000000000000000000000000000000000000000000000000000001E00000000007C00000000000800000000000000000000000000000008007000000000038000000000000000000000000000000000000000000000000000000000000000000E000000000070000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000300000000000000000000000000000000000000000000000000000000000000000C00030001800000003000000000008000000000000000000000000000000080000007001FE001C001F000F8001E0000003FF01FFE0FFFC301C0FFC070381FFE0FF80000007F801FE00FF001F001FE01FFC000008000000000000000000000000000000080000007003FF001C003F001F8001E0000003FF81FFE0FFFC301C0FFE078381FFE0FFC000000FFC03FF01FF803F003FF01FFC00000800000000000000000000000000000008000000E007070038007F003F8003E000000303C1C0000700301C0C0F078381C000C1E000001C1C07070383807F007070001C00000800000000000000000000000000000008000001C00603803000E7007380037000000301C1C0000700301C0C07078381C000C0E00000180E06038301C0E7006038003800000800000000000000000000000000000008000001C00E03807000C7006380037000000300C1C0000700301C0C0307C381C000C0700000380E0E038701C0C700E038007000000800000000000000000000000000000008000003800E0180600087004380073000000300E1C0000700301C0C0386C381C000C070000038060E018700C08700E03800E000000800000000000000000000000000000008000003800E0180E00007000380073000000300E1C0000700301C0C0386E381C000C070000038060E018700C00700003801C000000800000000000000000000000000000008000007000E0181C00007000380063800000300C1C0000700301C0C03066381C000C070000038060E018700C00700003803C00000080000000000000000000000000000000800000E000E0181FE0007000380063800000301C1C0000700301C0C07066381C000C070000038060E018700C00700003003F00000080000000000000000000000000000000800000E0C0E7183FF80070003800E180000038781FFC00700301C0E1E067381FFC0C070000039C60E718738C00700007003F80000080000000000000000000000000000000800001C0C0E7183C380070003800E1807FC03FF81FFC00700301C0FFE063381FFC0C0701FF039C60E718738C0070000E0001C000008000000000000000000000000000000080000380C0E318701C0070003800C1C07FC03FE01C0000700301C0FF8063381C000C0701FF038C60E318718C0070001C0000E000008000000000000000000000000000000080000380C0E018700C0070003800C1C07FC030E01C0000700301C0C38063B81C000C0701FF038060E018700C0070003C0000E000008000000000000000000000000000000080000380C0E018700E0070003801FFC0000030601C0000700301C0C18061B81C000C070000038060E018700C007000780000E0000080000000000000000000000000000000800003FFC0E018700E0070003801FFC0000030701C0000700301C0C1C061B81C000C070000038060E018700C007000F00000E0000080000000000000000000000000000000800003FFC0E018700C0070003801C0E0000030701C0000700301C0C1C061F81C000C070000038060E018700C007001E00380E000008000000000000000000000000000000080000001C0E038700C007000380180E0000030381C0000700301C0C0E060F81C000C0700000380E0E038701C007003C00380E000008000000000000000000000000000000080000000C07038381C00700038038060000030381C0000700381C0C0E060F81C000C0E000001C0E07038381C007003800380C000008000000000000000000000000000000080000000C078703C38007000380380600000301C1C00007003C380C07060F81C000E1E000001E1C078703C380070070001C3C000008000000000000000000000000000000080000000C03FE01FF80FFF87FFC380700000301C1FFE007001FF00C07060781FFE0FFC000000FF803FE01FF00FFF8FFF80FF8000008000000000000000000000000000000080000000C01FC00FE00FFF87FFC300700000300E1FFE007000FE00C03860781FFE0FF00000007F001FC00FE00FFF8FFF807F00000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000008000000000C0000000000000010000000020000000000000000C000008000000001000000000000000000000400000000000000000000000000000000000000000000000008000000000C0000000000000038000000070000000000000003E00001C000000003800000000000000000000400000000000000000000000000000000000000000000000008078000000C0000000000000038000000070000000000000003000001C00000000380000000000000000000040000000000000000000000000000000000000000000000000807C000000C000000000000000000000C000000000000000007000301C00000000001800000000000000000040000000000000000000000000000000000000000000000000806C000000C000000000000000000000C000000000000000007000301C0000000000180000000000000000004000000000000000000000000000000000000000000000000080EC000000C000000000000000000000C000000000000000007000301C0000000000180000000000000000004000000000000000000000000000000000000000000000000080CE000000C000000000000000000001C000000000000000007000701C0000000000380000000000000000004000000000000000000000000000000000000000000000000080C600007CC07E007E00FC1CE3877E07F8701F80EFC0001F81FE01FE1DF803F00038FF01F80EFC7E000000004000000000000000000000000000000000000000000000000081C60001FEC1FF81FF83FF1DE387FF87F8703FE0FFE0003FE1FE01FE1FFC0FFC0038FF07FE0FFEFF000000004000000000000000000000000000000000000000000000000081870001C1C181818183031F03878381C0707070F0700070707000701E0E0C0C00383806060F078380000000400000000000000000000000000000000000000000000000008183000380C380C18007031C038701C1C070E030E07000E0307000701C0E1C060038380E030E070380000000400000000000000000000000000000000000000000000000008383000300C300C18006001C038700C1C070C038E03000C0387000701C0618060038380C030E070180000000400000000000000000000000000000000000000000000000008303800300C300E1C006001C038700C1C070C038E03000C0387000701C0618070038380C038E030180000000400000000000000000000000000000000000000000000000008301800300C7FFE1F80E001C038700C1C071C038E03001C0387000701C063FFF0038381FFF8E0301800000004000000000000000000000000000000000000000000000000087FF800700C7FFE07F0E001C038700C1C071C038E03001C0387000701C063FFF0038381FFF8E0301800000004000000000000000000000000000000000000000000000000087FFC00300C700000F8E001C038700C1C071C038E03001C0387000701C0638000038381C000E030180000000400000000000000000000000000000000000000000000000008600C00300C300000186001C038700C1C070C038E03000C0387000701C0618000038380C000E030180000000400000000000000000000000000000000000000000000000008E00C00300C3000001C6001C038700C1C070C038E03000C0387000701C0618000038380C000E030180000000400000000000000000000000000000000000000000000000008C00E00380C380C10187011C038701C1C070E030E03000E0307000701C061C060038380E030E030180000000400000000000000000000000000000000000000000000000008C006001C1C1C1C38183831C03878381C0707070E0300070707000701C060E0E00383807070E030187870700400000000000000000000000000000000000000000000000009C006001FEC0FF81FF83FF1C03877F80F8703FE0E030003FE070003E1C0607FC00381F03FE0E03018787070040000000000000000000000000000000000000000000000000980070007CC07F00FE00FC1C03873E00F8701F80E030001F8070003E1C0603F800381F01FC0E03018787070040000000000000000000000000000000000000000000000000800000000000000000000000000700000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000700000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000700000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000700000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000700000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000300000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000^FS +^XZ diff --git a/renderer/src/test/resources/scene2/golden/text-fit-600.png b/renderer/src/test/resources/scene2/golden/text-fit-600.png new file mode 100644 index 0000000000000000000000000000000000000000..2473e8fbf61bfae832791809fd14b0c51cdc7569 GIT binary patch literal 8638 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 literal 0 HcmV?d00001 diff --git a/renderer/src/test/resources/scene2/golden/text-turned-600.zpl b/renderer/src/test/resources/scene2/golden/text-turned-600.zpl new file mode 100644 index 0000000..ab9d160 --- /dev/null +++ b/renderer/src/test/resources/scene2/golden/text-turned-600.zpl @@ -0,0 +1,5 @@ +^XA^PW1200^LL600^LH0,0^CI28 +^FO81,79^GFA,11830,11830,130,0000000000001FF80000000000000000000000000000000000000000000000000000000007FFC000000000000000000000000000000000000000000000000000000000000000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF800000000000000000000000000000000000000000000000FFF800000FFFFFC000000000000007FF800000FFF8000000FFF80001FFF800003FFF80000000000007FFFF80000FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF800003FFFFFF000000000000007FF800000FFF8000000FFF80003FFFC00003FFF8000000000003FFFFFE0000FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF80000FFFFFFFC00000000000007FF800000FFFC000000FFF80003FFFC00007FFF800000000000FFFFFFF8000FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF80001FFFFFFFE00000000000007FF8000007FFC000001FFF00003FFFC00007FFF800000000001FFFFFFFE000FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF80003FFFFFFFF00000000000007FF8000007FFC000001FFF00003FFFC00007FFF800000000003FFFFFFFF000FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF80007FFFFFFFF80000000000007FF8000007FFC000001FFF00003FFFE00007FFFC00000000007FFFFFFFFC00FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8000FFFFFFFFFC0000000000007FF8000003FFE000001FFE00007FFFE0000FFFFC0000000000FFFFFFFFFE00FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8000FFFFFFFFFE0000000000007FF8000003FFE000003FFE00007FFFE0000FFFFC0000000001FFFFFFFFFF00FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8001FFFFFFFFFE0000000000007FF8000003FFE000003FFE00007FFFE0000FFFFC0000000003FFFFFFFFFF80FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8001FFFFFFFFFF0000000000007FF8000001FFF000003FFC00007FFFE0000FFFFE0000000003FFFFFFFFFF00FFFFFFF003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8003FFFF03FFFF0000000000007FF8000001FFF000007FFC0000FFFFF0001FFFFE0000000003FFFE03FFFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8003FFF8007FFF0000000000007FF8000001FFF000007FFC0000FFFFF0001FFFFE0000000007FFF0007FFC0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000003FE0000000000001FF800000000000000000000000000000000000000000000000FFF8003FFF0003FFF8000000000007FF8000000FFF800007FF80000FFFFF0001FFFFE0000000007FFE0001FF80000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000007FE0000000000001FF800000000000000000000000000000000000000000000000FFF8007FFE0001FFF8000000000007FF8000000FFF80000FFF80000FFFFF0001FFFFE0000000007FFC00007F00000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFE0000000000001FF800000000000000000000000000000000000000000000000FFF8007FFC0000FFF8000000000007FF8000000FFFFFFFFFFF80001FFFFF8001FFFFF000000000FFF800003E00000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF8007FFC0000FFF8000000000007FF80000007FFFFFFFFFF00001FFDFF8003FF7FF000000000FFF800001C00000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF8007FF800007FF8000000000007FF80000007FFFFFFFFFF00001FFDFF8003FF7FF000000000FFF800000800000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF8007FF800007FFC000000000007FF80000007FFFFFFFFFF00001FF9FF8003FE7FF000000000FFF800000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF8007FF800007FFC000000000007FF80000003FFFFFFFFFE00001FF9FFC003FE7FF800000000FFF800000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF800FFF800007FFC000000000007FF80000003FFFFFFFFFE00003FF9FFC007FE3FF800000000FFF800000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000000000FFF800FFF800007FFC000000000007FF80000003FFFFFFFFFE00003FF8FFC007FE3FF800000000FFFC00000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF80000000000000000000000000000000000000000007FFFFFFF800FFF800003FFC000000000007FF80000001FFFFFFFFFC00003FF8FFC007FE3FF800000000FFFC00000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF8000000000000000000000000000000000000000007FFFFFFFF800FFF800003FFC000000000007FF80000001FFFFFFFFFC00003FF0FFC007FC3FFC000000007FFF00000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFEFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FFFFFFFFF800FFF800003FFC00000000000FFFC0000001FFFFFFFFFC00007FF0FFE00FFC3FFC000000007FFFF0000000000FFF00003FFE000007FFC000003FFE000000000000000000000000000000000000000000000000000000000003FF80000000007FEFFFFFFFFFFFFFFF800000000000000000000000000000000000000003FFFFFFFFF800FFF800003FFC00000000000FFFC0000000FFFFFFFFF800007FF07FE00FFC3FFC000000007FFFFFE00000000FFF00003FFFFFFFFFFFC000003FFE000000000000000000000000000000000000000000000000000000000003FF80000000003FE0000000000001FF800000000000000000000000000000000000000007FFFFFFFFF800FFF800003FFC00000000001FFFE0000000FFF0007FF800007FF07FE00FFC1FFC000000003FFFFFFE0000000FFF00003FFFFFFFFFFFC000003FFE000000000000000000000000000000000000000000000000000000000003FFC0000000003FE0000000000001FF80000000000000000000000000000000000000000FFFFFFFFFF800FFF800003FFC00000000001FFFE0000000FFF8007FF800007FF07FE00FF81FFC000000003FFFFFFFC000000FFF00003FFFFFFFFFFFC000003FFE000000000000000000000000000000000000000000000000000000000001FFE0000000003FE0000000000001FF80000000000000000000000000000000000000001FFFFFFFFFF800FFF800003FFC00000000003FFFF00000007FF800FFF00000FFE07FF00FF81FFE000000001FFFFFFFF000000FFF00003FFFFFFFFFFFC000003FFE000000000000000000000000000000000000000000000000000000000000FFE0000000003FE0000000000001FF80000000000000000000000000000000000000003FFFFFFFFFF800FFF800003FFC00000000007FFFF80000007FF800FFF00000FFE07FF01FF81FFE000000001FFFFFFFF800000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000007FF0000000003FE0000000000001FF80000000000000000000000000000000000000003FFFFFFFFFF800FFF800003FFC00000000007FFFF80000007FF800FFF00000FFE03FF01FF81FFE000000000FFFFFFFFE00000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000007FF8000000003FE0000000000001FF80000000000000000000000000000000000000007FFFFFFFFFF800FFF800003FFC0000000000FFFFFC0000003FFC00FFE00000FFE03FF01FF80FFE0000000007FFFFFFFE00000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000003FFC000000003FE0000000000001FF80000000000000000000000000000000000000007FFFFFFFFFF800FFF800003FFC0000000000FFFFFC0000003FFC01FFE00000FFE03FF81FF00FFF0000000001FFFFFFFF00000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000001FFC000000003FE0000000000001FF80000000000000000000000000000000000000007FFF0000FFF800FFF800003FFC0000000001FFFFFE0000003FFC01FFE00001FFC03FF83FF00FFF00000000007FFFFFFF80000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000000FFE000000003FE0000000000001FF8000000000000000000000000000000000000000FFFC0000FFF800FFF800003FFC0000000001FFFFFE0000003FFE01FFC00001FFC01FF83FF00FFF00000000001FFFFFFF80000FFF00003FFFFFFFFFFFC000003FFE0000000000000000000000000000000000000000000000000000000000000FFF000000003FE0000000000001FF8000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC0000000003FFFFFF0000001FFE03FFC00001FFC01FF83FF00FFF000000000003FFFFFFC0000FFF00003FFFFFFFFFFFC000003FFE00000000000000000000000000000000000000000000000000000000000007FF800000003FE0000000000001FF8000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC0000000007FFDFFF8000001FFE03FFC00001FFC01FF83FE007FF0000000000000FFFFFC0000FFF00003FFE000007FFC000003FFE00000000000000000000000000000000000000000000000000000000000003FF800000003FE0000000000001FF8000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC0000000007FFDFFF8000001FFF03FF800003FFC01FFC7FE007FF800000000000007FFFC0000FFF00003FFE000007FFC000003FFE00000000000000000000000000000000000000000000000000000000000003FFC00000003FE0000000000001FF8000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC000000000FFF8FFFC000000FFF03FF800003FF800FFC7FE007FF800000000000000FFFE0000FFF00003FFE000007FFC000003FFE00000000000000000000000000000000000000000000000000000000000001FFE00000003FE0000000000001FF8000000000000000000000000000000000000001FFF80000FFF800FFF800003FFC000000000FFF8FFFC000000FFF07FF800003FF800FFC7FE007FF8000000000000007FFE0000FFF00003FFE000007FFC000003FFE00000000000000000000000000000000000000000000000000000000000000FFF00000003FE0000000000001FF8000000000000000000000000000000000000001FFF80000FFF800FFF800003FFC000000001FFF07FFE000000FFF07FF000003FF800FFC7FC007FF8000000000000003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF8000000000000000000000000000000000000001FFF80000FFF800FFF800003FFC000000001FFF03FFE0000007FF87FF000007FF800FFE7FC003FFC000000000000003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC000000003FFE03FFF0000007FF8FFF000007FF800FFEFFC003FFC000000000000003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC000000007FFE01FFF0000007FF8FFE000007FF0007FEFFC003FFC000000000000003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC000000007FFC01FFF8000003FFCFFE000007FF0007FEFFC003FFC000000000600003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF80000FFF800FFF800003FFC00000000FFFC00FFFC000003FFCFFE000007FF0007FFFF8003FFC000000000F00003FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC0000FFF800FFF800003FFC00000000FFF800FFFC000003FFDFFC00000FFF0007FFFF8001FFE000000001F80007FFE0000FFF00003FFE000007FFC000003FFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFE0000FFF800FFF800003FFC00000001FFF0007FFE000001FFFFFC00000FFF0003FFFF8001FFE000000003FE000FFFC0000FFF00003FFE000007FFC000003FFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFF800FFF800003FFC00000001FFF0007FFE000001FFFFFC00000FFE0003FFFF8001FFE000000007FF803FFFC0000FFF00003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFF800FFF800003FFC00000003FFE0003FFF000001FFFFF800000FFE0003FFFF0001FFE00000000FFFFFFFFFC00FFFFFFF003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFF800FFF800003FFC00000003FFE0003FFF000000FFFFF800001FFE0003FFFF0001FFF00000001FFFFFFFFF800FFFFFFF003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFF800FFF800003FFC00000007FFC0001FFF800000FFFFF800001FFE0001FFFF0000FFF00000003FFFFFFFFF800FFFFFFF003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFF800FFF800003FFC0000000FFFC0001FFFC00000FFFFF000001FFE0001FFFF0000FFF00000003FFFFFFFFF000FFFFFFF003FFE000007FFC01FFFFFFFFFFE00000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFF80000000000000000000000000000000000000000FFFFFFFFFF800FFF800003FFC0000000FFF80000FFFC000007FFFF000001FFC0001FFFE0000FFF00000001FFFFFFFFE000FFFFFFF003FFE000007FFC01FFFFFFFFFFE00000000000000000000000000000000000000000000000000000000003FFFFFFFFF000FFFFFFFFFFFFFFF800000000000000000000000000000000000000007FFFFFFFFF800FFF800003FFC0000001FFF800007FFE000007FFFF000003FFC0001FFFE0000FFF80000000FFFFFFFFC000FFFFFFF003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000001FFFFFFFFFFC00FFFFFFFFFFFFFFF800000000000000000000000000000000000000003FFFFFFFFF800FFF800003FFC0000001FFF000007FFE000007FFFE000003FFC0001FFFE0000FFF800000007FFFFFFF8000FFFFFFF003FFE000007FFC01FFFFFFFFFFE0000000000000000000000000000000000000000000000000000000007FFFFFFFFFFF00FFFFFFFFFFFFFFF800000000000000000000000000000000000000001FFFFFFFFF800FFF800003FFC0000003FFF000003FFF000003FFFE000003FFC0000FFFE00007FF800000001FFFFFFF0000FFFFFFF003FFE000007FFC01FFFFFFFFFFE000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFF80FFFFFFFFFFFFFFF8000000000000000000000000000000000000000007FFFFFFFF800FFF800003FFC0000003FFE000003FFF000003FFFE000003FFC0000FFFE00007FF800000000FFFFFFC0000FFFFFFF003FFE000007FFC01FFFFFFFFFFE000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFC0FFFFFFFFFFFFFFF8000000000000000000000000000000000000000000FFFFFFFF800FFF800003FFC0000007FFE000001FFF800003FFFC000007FF80000FFFC00007FF8000000001FFFFE00000FFFFFFF003FFE000007FFC01FFFFFFFFFFE000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFE0FFFFFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFF0FFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF8FFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF8FFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFCFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFE000000003FFCFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFC000000000FFEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000007FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000007FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE00007F00003FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0000FF80003FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FE0000FF80001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FC0001FF80001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FC0001FFC0001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FC0001FFC0001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FC0001FF80001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FE0000FF80001FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0000FF80003FFFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE00007F00003FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000007FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF00000000007FEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF8000000000FFEFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFE000000003FFCFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFCFF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF8FF80001FF0000FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF8FF80001FF0000FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFF0FF80001FF0000FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFE0FF80001FF0000FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFC0FF80000000000FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFF80FF80000000000FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFF00FF80000000000FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFF000^FS +^FO80,180^GFA,31571,31571,131,0007C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FC000003FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFC00001FFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFF8000001FFC00007FFFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFE000003FFC0001FFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFF800007FFC0003FFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFC0000FFFC0007FFFFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFE0001FFFC000FFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFF0001FFFC000FFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFF8003FFFC001FFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFC003FFE0003FFFFFFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC003FF80003FFF0FFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFFFFFFFFFFFFFE007FF00007FFC03FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFF000000001FFE007FE00007FF800FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFE0000000007FF007FE00007FF000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF007FC0000FFE0007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF00FFC0000FFE0007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00003F80001FF00FFC0000FFE0007FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00007FC0001FF80FF80000FFC0003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FF00007FC0000FF80FF80001FFC0003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFC0000FF80FF80001FFC0003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFE0000FF80FF80001FFC0003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFE0000FF80FF80001FF80007FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFC0000FF80FFC0003FF80007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FF00007FC0000FF807FC0003FF80007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00007FC0001FF807FC0003FF8000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00003F80001FF007FE0007FF0001FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF007FF000FFF0003FF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF007FF801FFF003FFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFC0000000007FF003FFE07FFE003FFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFF000000001FFE003FFFFFFFE003FFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFFFFFFFFFFFFFE001FFFFFFFC003FFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC001FFFFFFFC003FFE0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC000FFFFFFF8003FFC0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000003FFFFFFFFFFFFF80007FFFFFF0003FF80000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000001FFFFFFFFFFFFF00003FFFFFE0003FF00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000FFFFFFFFFFFFE00001FFFFFC0003FC00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000007FFFFFFFFFFFC00000FFFFF00003F000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000003FFFFFFFFFFF8000003FFFC000030000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000FFFFFFFFFFE00000007FF0000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000001FFFFFFFFF800000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000001FFFFFFFFF800000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000FFFFFFFFFFE00000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000003FFFFFFFFFFF80000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000007FFFFFFFFFFFC0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000FFFFFFFFFFFFE0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000001FFFFFFFFFFFFF0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000003FFFFFFFFFFFFF8000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFFFE0000001FFFFFFFFF000007FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFFFFFFFFFFFFFE000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFFF000000007FFFFFFFF000003FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFF000000001FFE000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFFC000000001FFFFFFFF000003FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFE0000000007FF000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFF80000000007FFFFFFF000001FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF007FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFE00000000001FFFFFFF000001FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF007FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFFC00000000000FFFFFFF000001FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00003F80001FF007FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFF8000000000007FFFFFF000000FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00007FC0001FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFF0000000000003FFFFFF000000FFFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FF00007FC0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFE0000000000001FFFFFF0000007FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFC0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFFC0000000000000FFFFFF0000007FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFE0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFF80000000000000FFFFFF0000003FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFE0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFF000000000000007FFFFF0000003FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FE0000FFC0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFF000000000000003FFFFF0000001FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000003FF00007FC0000FF807FFFFFFFFFFFFFFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFE000000000000003FFFFF0000001FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00007FC0001FF800000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFE000000000000001FFFFF0000000FFFFFE00007FFFF000000000000003FFFFFFFFFC000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF00003F80001FF000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFFC0000007F8000000FFFFF0000000FFFFFE00007FFFF000000000000003FFFFFFFFFC0001FFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000FFFF8000007FFF000000FFFFF00000007FFFFE00007FFFF000000000000007FFFFFFFFFC0003FFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000003FF000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000FFFF800001FFFFC000007FFFF00000007FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFC0000000007FF000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFF800003FFFFF000007FFFF00000003FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFF000000001FFE000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFF000007FFFFF800007FFFF00000003FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000FFFFFFFFFFFFFFE000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000003FFFF00000FFFFFFC00003FFFF00000001FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFE00001FFFFFFC00003FFFF00000001FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000007FFFFFFFFFFFFFC000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFE00001FFFFFFE00001FFFF00000001FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000003FFFFFFFFFFFFF8000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFE00003FFFFFFE00001FFFF00000000FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000001FFFFFFFFFFFFF0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFC00003FFFFFFF00001FFFF00000000FFFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000FFFFFFFFFFFFE0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFC00007FFFFFFF00001FFFF000000007FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000007FFFFFFFFFFFC0000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFC00007FFFFFFF80000FFFF000000007FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000003FFFFFFFFFFF80000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFC00007FFFFFFF80000FFFF000000003FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000FFFFFFFFFFE00000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFF800007FFFFFFF80000FFFF000060003FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000001FFFFFFFFF800000000000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFF80000FFFFFFFF80000FFFF000060001FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFF80000FFFFFFFF80000FFFF000070001FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFF80000FFFFFFFF800007FFF000070000FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFC0003FFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFF80000FFFFFFFF800007FFF000078000FFFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFF80000FFFFFFFF800007FFF0000780007FFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFF80000FFFFFFFF800007FFF0000780007FFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFF00000FFFFFFFF800007FFF00007C0003FFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFF00000FFFFFFFF800007FFF00007C0003FFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFF00000FFFFFFFF800007FFF00007E0001FFE00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFF00000FFFFFFFF800007FFF00003E0001FFE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFF00000FFFFFFFF800003FFF00003E0001FFE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFF00000FFFFFFFF800003FFF00003F0000FFE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFF00000FFFFFFFF800003FFF00003F0000FFE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFF00000FFFFFFFF800003FFF00003F80007FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFF00000FFFFFFFF800003FFF00003F80007FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFF00000FFFFFFFF800003FFF00003F80003FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFF00000FFFFFFFF800003FFF00003FC0003FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFF00000FFFFFFFF800003FFF00003FC0001FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFF00000FFFFFFFF800003FFF00003FE0001FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFF00000FFFFFFFF800003FFF00003FE0000FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFF00000FFFFFFFF800003FFF00003FF0000FE00007FFFF0000000000000FFFFFFFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFFF00000FFFFFFFF800003FFF00003FF00007E00007FFFF0000000000000FFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFF00000FFFFFFFF800003FFF00003FF80007E00007FFFF0000000000000FFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFF00000FFFFFFFF800003FFF00003FF80007F00007FFFF0000000000000FFFFFFFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFFF00000FFFFFFFF800003FFF00003FFC0003F00007FFFF0000000000000FFFFFFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFF00000FFFFFFFF800007FFF00003FFC0003F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFF00000FFFFFFFF800007FFF00003FFE0001F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFFFF00000FFFFFFFF800007FFF00003FFE0001F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFF00000FFFFFFFF800007FFF00003FFF0001F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFF80000FFFFFFFF800007FFF00003FFF0000F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFFFF80000FFFFFFFF800007FFF00003FFF8000F00007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFFF80000FFFFFFFF800007FFF00003FFF8000700007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFFF80000FFFFFFFF800007FFF00003FFFC000700007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFFFFF80000FFFFFFFF80000FFFF00003FFFC000700007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFFF80000FFFFFFFF80000FFFF00003FFFC000300007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFFFC00007FFFFFFF80000FFFF00003FFFE000300007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFFFFFC00007FFFFFFF80000FFFF00003FFFE000000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFFFFC00007FFFFFFF80000FFFF00003FFFF000000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFFFFC00007FFFFFFF00001FFFF00003FFFF000000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFF80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFFFFFFC00003FFFFFFF00001FFFF00003FFFF800000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFFFFE00003FFFFFFE00001FFFF00003FFFF800000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00001FFFFFFFFFFFFE00001FFFFFFE00003FFFF00003FFFFC00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFF00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF80000000000000FF80000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFFFFFFE00001FFFFFFC00003FFFF00003FFFFC00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF800000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000003FFFFFFFFFFFFF00000FFFFFFC00003FFFF00003FFFFE00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000000000000000000000000000000000000FF800000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000007FFFFFFFFFFFFF000007FFFFF800007FFFF00003FFFFE00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFE00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000007FFFFFFFFFFFFF800003FFFFF000007FFFF00003FFFFF00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000FFFFFFFFFFFFFF800000FFFFC000007FFFF00003FFFFF00000007FFFF00001FFFFFFFFFFFFFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFC000003FFF000000FFFFF00003FFFFF80000007FFFF000000000000007FFFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFC0000007F0000000FFFFF00003FFFFF80000007FFFF000000000000003FFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFE000000000000001FFFFF00003FFFFFC0000007FFFF000000000000003FFFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFE000000000000003FFFFF00003FFFFFC0000007FFFF000000000000003FFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFF000000000000003FFFFF00003FFFFFC0000007FFFF000000000000003FFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFF000000000000007FFFFF00003FFFFFE0000007FFFF000000000000003FFFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFF80000000000000FFFFFF00003FFFFFE0000007FFFF000000000000003FFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFC0000000000000FFFFFF00003FFFFFF0000007FFFF000000000000003FFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFE0000000000001FFFFFF00003FFFFFF0000007FFFF000000000000003FFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFF0000000000003FFFFFF00003FFFFFF8000007FFFF000000000000003FFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFF8000000000007FFFFFF00003FFFFFF8000007FFFF000000000000003FFFFFFFFFFFFFC00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFC00000000000FFFFFFF00003FFFFFFC000007FFFF000000000000003FFFFFFFFFFFFFC00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFE00000000003FFFFFFF00003FFFFFFC000007FFFF000000000000003FFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFF80000000007FFFFFFF00003FFFFFFE000007FFFF000000000000003FFFFFFFFFFFFF800007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF800000000000000000FFFFFFFFFC000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFFC000000001FFFFFFFF00003FFFFFFE000007FFFF000000000000003FFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF800000000000000003FFFFFFFFFF800000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFFF000000007FFFFFFFF00003FFFFFFF000007FFFF000000000000003FFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000000FFFFFFFFFFFE00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000000000007FFFFFFFE0000001FFFFFFFFF00003FFFFFFF000007FFFF000000000000003FFFFFFFFFFFFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000001FFFFFFFFFFFF00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000003FFFFFFFFFFFF80000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000007FFFFFFFFFFFFC0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000FFFFFFFFFFFFFE0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000001FFFFFFFFFFFFFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000001FFFFFFFFFFFFFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000003FFFFFFFFFFFFFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000003FFC000000007FF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000007FF0000000001FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000007FE0000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000007FE0000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000007FC0000FE00007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF800000000000000FFC0001FF00007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80001FF00007FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80001FF80003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80003FF80003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80003FF80003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80001FF80003FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FF80001FF00007FE000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF00FFC0001FF00007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF007FC0000FE00007FC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF007FE0000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FFFFFFFFFFFFFFF007FE0000000000FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000007FF0000000003FFC000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000003FFC000000007FF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000003FFFFFFFFFFFFFF8000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000001FFFFFFFFFFFFFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000001FFFFFFFFFFFFFF0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000FFFFFFFFFFFFFE0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000007FFFFFFFFFFFFC0000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000003FFFFFFFFFFFF80000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000001FFFFFFFFFFFF00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF80000000000000000FFFFFFFFFFFE00000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF800000000000000003FFFFFFFFFF800000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF800000000000000000FFFFFFFFFC000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000001FF8000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FF00000003FFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600001FFFE000000FFFFFFFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E00007FFFF800001FFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0001FFFFFC00003FFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FE0003FFFFFE00007FFFFFFFFFFFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE0007FFFFFF0000FFFFFFFFFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFE000FFFFFFF8001FFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFE001FFFFFFFC001FFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFE001FFFFFFFC003FFFFFFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFE003FFFFFFFE003FFC000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFE003FFF03FFE007FF0000000001FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFE007FFC00FFF007FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFE0007FF8007FF007FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFC0007FF0003FF007FC0000FE00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF8000FFE0001FF00FFC0001FF00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FFE0001FF00FF80001FF00007FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FFE0001FF80FF80001FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF0000FFC0000FF80FF80003FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0001FFC0000FF80FF80003FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0001FFC0000FF80FF80001FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0001FFC0000FF80FF80001FF00007FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FE0001FF80000FF80FFC0001FF00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FF0003FF80001FF807FC0000FE00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0003FF80001FF807FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0003FF80001FF007FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF8007FF00003FF007FF0000000003FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF800FFF00003FF003FFC000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFE01FFF00007FF003FFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFF87FFE0000FFE001FFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFE0003FFE001FFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFFC001FFFE000FFFFFFFFFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFFF8001FFFC0007FFFFFFFFFFFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFF8001FFFC0003FFFFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFF0001FFF80001FFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFE0001FFF00000FFFFFFFFFFFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFFFC0001FFE000003FFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFF00001FFC000000FFFFFFFFFC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFC00001FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE000001FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F00000^FS +^FO80,431^GFA,11830,11830,130,000FFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFFFFFFF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000001FF00FFFFFFFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000001FF01FFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF00000000001FF03FFFFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF07FFFFFFFFFFFFC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF0FFFFFFFFFFFFFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF1FFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF1FFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF3FFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF3FFC000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FF0000000001FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FC0000FE00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFFC0001FF00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80001FF00007FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80001FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80003FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80003FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80001FF80003FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFF80001FF00007FE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FFFFC0001FF00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FC0000FE00007FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FE0000000000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF7FF0000000003FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF0000FF80001FF3FFC000000007FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF3FFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF1FFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF1FFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF0FFFFFFFFFFFFFE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF07FFFFFFFFFFFFC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF03FFFFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF01FFFFFFFFFFFF00000000000000000000000000000000000000000000000000078000000000000003F800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF00FFFFFFFFFFFE00000000000000000000000000000000000000000000000000078000000000000007F800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF003FFFFFFFFFF8000000000000000000003FFFF000000000000000000000000007800000000000000FF800000000000000000000000001FF800001FF800000FFC0007FFFFF8000000003FF00000007C00000000003FC000003FC00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF000FFFFFFFFFC0000000000000000000003FFFFE00000000000000000000000007800000000000000FF800000000000000000000000007FFE00007FFE00003FFF0007FFFFFC00000000FFFC000001F800000000007FC000007FC00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF00000000000000000000000000000000003FFFFF800000000000000001C0000007800000000000001E000000000000000000000000001FFFF0000FFFF0000FFFF8007FFFFFC00000001FFFE000003F00000000000FFC00000FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFFF800000000000000001E0000007800000000000001E000000000000000000000000003FFFF8001FFFF8001FFFFC007FFFFFC00000003FFFF000007E00000000001FFC00001FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E001FC00000000000000001E0000007800000000000001E000000000000000000000000003F00FC001F00FC001F807E00780007800000003E01F80000FC00000000003F7C00003F7C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0007E00000000000000001E0000007800000000000001E000000000000000000000000007C007C003E007E003E003E0078000F800000007C00FC0001F800000000007E7C00007E7C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0003E00000000000000001E0000007800000000000001E0000000000000000000000000078003E007C003E003C001F0078000F80000000F8007C0003F00000000000FC7C0000FC7C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0003E00000000000000001E0000007800000000000001E00000000000000000000000000F8003E007C001E007C001F0078001F00000000F8003C0007E00000000001F87C0001F87C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0001F00000000000000003E0000007800000000000001E00000000000000000000000000F0003E0078001F0078001F0078001F00000000F0003E0007C00000000003F07C0003F07C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0001F00003800000380003E000000780E000000380001E000007000000000001C000000030001E00F8000F0018000F0078001E00000001F0001E000F800000000007E07C0007E07C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0001F0003FF00003FF803FFF80000787FC00003FF001FFF8007FE0003C1F001FF800000000001E00F8000F0000000F0078003E00000001F0001E000F000000000003C07C0003C07C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0001F000FFFC000FFFC03FFF8000079FFF0000FFFC01FFF801FFF8003C7F007FFE00000000001E00F0000F8000000F0000003C00000001E0001F001F000000000001007C0001007C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0001E001FFFE001FFFE03FFF800007BFFF8001FFFE01FFF803FFFC003CFF00FFFF00000000001E00F0000F8000000F0000007C00000001E0001F003E000000000000007C0000007C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0003E003F03F003F03F03FFF800007BC3FC003F03F01FFF807F0FE003DFF01F81F80000000003E00F0000F8000001F0000007C00000001E0001F003E000000000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF800000000000000000000000000000000000000000000003E0003E007C00F803C00F003E0000007F007C007C00F801E000FC01F003DF003E007C0000000003E01F0000F8000001F000000F800000003E0001F003C000000000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC0000000FFF0000000000000000000003E0007C0078007807C006003E0000007C003E0078007801E000F000F803F0003C003C0000000003C01F0000F8000001E000000F800000003E0001F007C7FE000000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000007FF8000000000000000000003E003F800F8007C078000003E0000007C001E00F8007C01E001F0007803E0007C003E0000000007C01F0000F8000003E000000F000000003E0001F0078FFF000000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000003FFC000000000000000000003FFFFE000F0003C078000003E00000078001F00F0003C01E001E0007C03C00078001E000000000FC01F0000F8000007E000001F000000003E0001F00FBFFFC00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000001FFC000000000000000000003FFFFE001F0003E078000003E00000078000F01F0003E01E003E0003C03C000F8001F000000000F801F0000F8000007C000001F000000003E0001F00FBC3FC00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000001FFE000000000000000000003FFFFF801E0003E07C000003E00000078000F01E0003E01E003C0003C03C000F0001F000000001F001F0000F800000F8000003E0003FFF03E0001F00FF007E00FFFC00007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000FFF000000000000000000003E003FC01E0003E03E000003E00000078000F01E0003E01E003C0003C03C000F0001F000000003E001F0000F800001F0000003E0003FFF03E0001F00FC003F00FFFC00007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC000000007FF000000000000000000003E0003E01E0003E03F800003E00000078000F81E0003E01E003C0003E03C000F0001F000000007E001F0000F800003F0000003C0003FFF03E0001F00FC001F00FFFC00007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC000000003FF800000000000000000003E0001F01FFFFFE01FFE0003E00000078000F81FFFFFE01E003C0003E03C000FFFFFF00000000FC001F0000F800007E0000007C0003FFF03E0001F00F8001F00FFFC00007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC000000003FFC00000000000000000003E0000F01FFFFFE00FFFC003E00000078000F81FFFFFE01E003C0003E03C000FFFFFF00000001F8001F0000F80000FC000000780003FFF03E0001F00F8000F80FFFC00007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC000000001FFE00000000000000000003E0000F81FFFFFE003FFE003E00000078000F81FFFFFE01E003C0003E03C000FFFFFF00000003F0000F0000F80001F8000000F8000000001E0001F00F0000F80000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC000000000FFE00000000000000000003E0000F81E000000007FF003E00000078000F81E0000001E003C0003E03C000F0000000000007C0000F0000F80003E0000000F8000000001E0001F00F0000F80000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC0000000007FF00000000000000000003E0000F81E0000000003F803E00000078000F81E0000001E003C0003E03C000F000000000001F80000F0000F8000FC0000001F0000000001E0001F00F0000F80000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC0000000007FF80000000000000000003E0000F81E0000000000F803E00000078000F01E0000001E003C0003C03C000F000000000003F00000F8000F0001F80000001F0000000001F0001E00F0000F80000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC0000000003FFC0000000000000000003E0000F81E00000000007803E00000078000F01E0000001E003C0003C03C000F000000000007E00000F8000F0003F00000001E0000000001F0001E00F0000F80000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC0000000001FFC0000000000000000003E0000F81F00000000007803E00000078000F01F0000001E003E0003C03C000F80000000000FC0000078001F0007E00000003E0000000000F0003E00F8000F00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FE0000000001FFC0000000000000000003E0000F00F00010000007803E00000078001F00F0001001E001E0007C03C000780008000001F8000007C001F000FC00000003C0000000000F8003E0078001F00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003E0001F00F80038030007803E0000007C001E00F8003801E001F0007803C0007C001C000003F0000007C003E001F800000007C0000000000F8007C007C001F00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003E0003F0078007C078007803E0000007C003E0078007C01E000F000F803C0003C003E000007E0000003E003E003F000000007C00000000007C007C007C003E00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003E0007E007E00F80FC00F803E0000007E007C007E00F801E000FC01F003C0003F007C00000FC0000003F00FC007E00000000F800000000007E01F8003F007E00000000007C0000007C00000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003FFFFFC003F83F807F03F003FF000007BC3FC003F83F801E0007F07E003C0001FC1FC00000FFFFFF801FC3F8007FFFFFC000F800000000003F87F0001FC3FC00000001FFFFFF01FFFFFF000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003FFFFF8001FFFF003FFFE001FF000007BFFF8001FFFF001E0003FFFC003C0000FFFF800000FFFFFF800FFFF8007FFFFFC000F000000000001FFFF0000FFFF800000001FFFFFF01FFFFFF000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003FFFFF0000FFFC000FFFC001FF0000079FFF0000FFFC001E0001FFF8003C00007FFE000000FFFFFF8007FFE0007FFFFFC001F000000000000FFFC00007FFF000000001FFFFFF01FFFFFF000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000003FFFFC00003FF80007FF8000FF00000787FC00003FF8001E00007FE0003C00001FFC000000FFFFFF8001FFC0007FFFFFC001F0000000000003FF800001FFC000000001FFFFFF01FFFFFF000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000000000000000078000007800000000000000E000000780000000000F000000000003C000000000000000003C0000000000000000000000000000780000001C000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF80000000000007FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF8000000000000^FS +^XZ -- 2.54.0 From 589b6d41ee0da4dbe4540f31b579a57c86836ef2 Mon Sep 17 00:00:00 2001 From: James Maes Date: Thu, 12 Nov 2026 14:53:49 -0600 Subject: [PATCH 3/3] fix(renderer): scene 2 text after independent review: a proof that never cuts, a bounded shrink search, named refusals The proof of `maxLength` - The proof never cuts. With `overflow: truncate` the proof was given a cut block, which counts as fitting, so a bound element whose box held ten characters validated clean with `maxLength: 40` and every long value was cut at print. The proof now runs with cutting off. When it fails, an element that did not ask for cutting is refused as before; one that did still validates, since cutting is what its author chose, with the warning FIT_NOT_PROVEN at every validation carrying `measured.provenCharacters`, the longest length proven to fit whole (found by halving: fewer characters never fit worse), against `limit.characters`. No new code: FIT_NOT_PROVEN already means that the fit of a bound value is not proven. - A bound element with `maxLength` is judged for legibility, when validated, at the size the proof shrank to (the floor when it fails and the element cuts), not at its stated size. The shrink search - The size chosen is still exactly the one a search of every quarter-point step gives, but that search is no longer made. A count that errs only toward yes says whether a size could hold the text: lines filled at any character, each held to a width no real line can be under, and a block to its lines' ascent, pitches and descent. It never refuses a size that fits and, once it allows a size, allows every smaller one, so the largest size it allows is found by halving and only the steps from there are laid out. When one line at the floor is higher than the box nothing is searched, and a cut tries no line count the box is too low for. - 1024 characters at 600 dpi from 1000 pt to 1 pt took 180 to 250 ms a fit and now takes under 1 ms: at most 21 555 characters visited where the search of every size visits 15.6 million. - A text is fitted once: what `check` composed is what `paint` draws. - The text of one scene may take 64 million steps (a character visited while fitting is one, a character to be drawn 16, a glyph the scene draws for the first time at a size 4096, since the runtime rasterises it once). The element that passes it, and every text after it, is SCENE_INVALID at the element with `textWorkSteps`, as the painted-area limit is. The count is integer arithmetic: the same on every machine, and the same validated or rendered. A thousand of the worst elements validate in well under a second. Ink outside the measure - TEXT_INK_OUTSIDE_MEASURE was an IllegalStateException thrown while painting, which failed the whole render after part of the text was on the label. The dots of a text are now gathered first and reach the label only when none strayed; otherwise the one element is refused as TEXT_DOES_NOT_FIT with `glyphsOutsideMeasure` and `dotsOutsideMeasure`. A literal is held to the glyph bounds when the scene is validated. - The bound is tested at 1, 2, 300 and 1000 pt as well as from 5 to 72 pt, for every character of every face at the three resolutions; nothing strays. Schema and vocabulary - `fit` declares `maxLines`, `shrinkTo` and `overflow` under `properties` with `additionalProperties: false`. The three names are in the renderer's and the host bridge's pointer vocabularies, and a wrong member is reported at the member (`/elements/3/fit/maxLines`, or in the override that states `fit`). - A bound number is printed as the schema says: plain decimal digits, no exponent, no fraction that is only zeros (`1.0E10` prints `10000000000`, `2.50` prints `2.5`). A number that is not finite is VALUE_MISSING. Tests - The widest-advance check covers every character a face draws, inked or not (a no-break space advances the pen), so a font update cannot break the proof unseen. - Property: `fit` equals the search of every size, block for block, over 3600 generated texts, boxes, sizes, floors and line counts. - The goldens are unchanged. A README beside them records the JDK builds and the FreeType each ships. Co-Authored-By: Claude Fable 5.2 --- .../renderer/SceneFacts.java | 2 +- .../renderer/SceneFactsTest.java | 2 +- docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md | 51 ++- renderer/README.md | 10 +- renderer/schema/zpl-scene-2.schema.json | 14 +- .../qbits/renderer/scene2/ElementFactory.java | 7 +- .../qbits/renderer/scene2/ElementSource.java | 10 +- .../renderer/scene2/text/TextElement.java | 240 +++++++++--- .../qbits/renderer/scene2/text/TextFit.java | 310 ++++++++++++++-- .../renderer/scene2/text/TextRaster.java | 168 +++++++-- .../renderer/scene2/SceneGoldenTest.java | 4 +- .../qbits/renderer/scene2/text/FaceTest.java | 24 +- .../renderer/scene2/text/TextElementTest.java | 341 +++++++++++++++++- .../renderer/scene2/text/TextFitTest.java | 271 ++++++++++++++ .../renderer/scene2/text/TextRasterTest.java | 120 +++++- renderer/src/test/resources/scene2/README.md | 31 ++ 16 files changed, 1439 insertions(+), 166 deletions(-) create mode 100644 renderer/src/test/resources/scene2/README.md diff --git a/bridges/renderer/src/main/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFacts.java b/bridges/renderer/src/main/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFacts.java index 43262cd..20e06e7 100644 --- a/bridges/renderer/src/main/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFacts.java +++ b/bridges/renderer/src/main/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFacts.java @@ -58,7 +58,7 @@ final class SceneFacts static final Set VOCABULARY = Set.of("schema", "design", "defaults", "samples", "elements", "overrides", "when", "dpi", "set", "children", "id", "type", "anchor", "x", "y", "width", "height", "align", "valign", "thickness", "fill", - "value", "valuePath", "font", "size", "lineHeight", "fit", "maxLength", "threshold", "reverse", "rotation", + "value", "valuePath", "font", "size", "lineHeight", "fit", "maxLines", "shrinkTo", "overflow", "maxLength", "threshold", "reverse", "rotation", "symbology", "symbologyPath", "allowedSymbologies", "minModule", "maxModule", "quiet", "gs1", "hri", "scannerSymbologyPath", "aimIdentifierPath", "asset", "mode"); diff --git a/bridges/renderer/src/test/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFactsTest.java b/bridges/renderer/src/test/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFactsTest.java index 378e90b..6051361 100644 --- a/bridges/renderer/src/test/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFactsTest.java +++ b/bridges/renderer/src/test/java/com/kingsrook/qbits/documentgeneration/renderer/SceneFactsTest.java @@ -60,7 +60,7 @@ class SceneFactsTest Set declared = new TreeSet<>(); names(RendererJson.JSON.readTree(Files.readAllBytes(Path.of("..", "..", "renderer", "schema", "zpl-scene-2.schema.json"))), declared); assertEquals(declared, new TreeSet<>(SceneFacts.VOCABULARY)); - assertEquals(43, SceneFacts.VOCABULARY.size()); + assertEquals(46, SceneFacts.VOCABULARY.size()); } diff --git a/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md b/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md index 35b178f..225354e 100644 --- a/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md +++ b/docs/design/LABEL-LAYOUT-FONTS-PREVIEW.md @@ -363,8 +363,24 @@ Legibility on thermal heads: read once at a reference size and scaled as `units x millipoints x dpi / 72 000 000`, so the same value is the same width on every machine. Each character sits at a whole-dot pen position. A line's box is its advance, widened to the ink of its characters plus two dots on each inked side: the rasteriser fits an outline to the - dot grid within 1.4 dots of its exact scale (measured over every character of the five faces), and a render - whose ink would leave the measured box fails rather than clip or print outside it. + dot grid within 1.4 dots of its exact scale (measured over every character of the five faces, from 1 pt to + 1000 pt at the three resolutions). A text whose ink would leave the measured box is neither clipped nor printed + outside it nor printed in part: its dots are gathered first and reach the label only when none strayed, and + otherwise the one element is refused as `TEXT_DOES_NOT_FIT` with `glyphsOutsideMeasure` and + `dotsOutsideMeasure`. A literal is held to the glyph bounds when the scene is validated. +- **The size is found without trying every size.** The answer is defined as the one a search of every + quarter-point step from the size down to the floor gives, and a property test holds the implementation to that + search exactly. The implementation first asks, by halving, for the largest step at which the text could fit at + all: a count that fills lines at any character with a width no real line can be under, so it never refuses a + size that fits and, once it allows a size, allows every smaller one. Only the few steps from there are laid + out. When one line at the floor is higher than the box nothing is searched. The case of 1024 characters from + 1000 pt to 1 pt, which took about 200 ms a fit, takes under 1 ms. +- **The work of a scene's text is bounded.** Every character visited while fitting is one step, every character + to be drawn 16, and every glyph a scene draws for the first time at a size 4096 (the runtime rasterises it + once). One scene may take 64 million steps, about a second of a worker; the element that passes it, and every + text after it, is `SCENE_INVALID` at the element with `textWorkSteps`. The count is integer arithmetic, so the + refusal is the same on every machine and the same whether the scene is validated or rendered. A text is + fitted once: what the check composed is what is painted. - **Wrapping.** At each size a line is broken between words while the text then fits, and at any character when it does not. So a larger size is preferred to whole words, a value with no space wraps (the example's GS1 line has none), and a length is provable: n characters need no more lines than n of the widest. @@ -378,19 +394,26 @@ Legibility on thermal heads: the 7 pt floor need 59 dots at 203 dpi (53 from rounding the ascent, the line pitch and the descent up to whole dots, 6 for the accent and the descender) and the 6.5 mm caption box has 51. A box of exactly `lines x line height` is not proven; 7.5 mm is. The proof is for the render target of the request, so a host that prints - one revision at several resolutions validates at each (P5 or P6b). + one revision at several resolutions validates at each (P5 or P6b). The proof never cuts: a cut value is not a + value that fits. An element with `overflow: truncate` whose `maxLength` is not proven stays valid, because + cutting is what its author chose, and carries the warning `FIT_NOT_PROVEN` at every validation with + `provenCharacters`, the longest length proven to fit whole, against the `characters` stated. - **Validation reads no record.** A bound value is laid out only when rendering; `FIT_NOT_PROVEN` is raised for - a bound element without `maxLength` in both operations. Legibility is judged at the stated size when a bound - element is validated and at the size chosen when it is rendered. + a bound element without `maxLength` in both operations. When a bound element is validated, legibility is + judged at the size its `maxLength` is proven at, which is the smallest any value is printed at (the floor when + the proof fails and the element cuts), and at the stated size when it has no `maxLength`; when it is rendered, + at the size chosen. +- **A bound number** is printed in plain decimal digits: no exponent and no fraction that is only zeros + (`1.0E10` prints `10000000000`, `2.50` prints `2.5`, `12.0` prints `12`). A number that is not finite is + `VALUE_MISSING`. - **Bounds.** A size from 1 pt to 1000 pt, `shrinkTo` from 1 pt up to the size, `lineHeight` from 0.5 to 5 with - three decimals, 64 lines, 1024 characters. Anything inside `fit` that is wrong is reported at `fit`, since a - pointer is made only of declared property names of an element. -- **The members of `fit` are not schema properties.** The published schema states `maxLines`, `shrinkTo` and - `overflow` in the description of `fit` and does not declare them under `properties`. The host admits in a - pointer exactly the names the schema declares (`SceneFacts.VOCABULARY`, held to the schema by a test in the - bridge), and the renderer admits the same set (`ElementFactory.VOCABULARY`); declaring three names that no - pointer carries would have widened the host's list for nothing. If a pointer should one day say - `/elements/1/fit/maxLines`, the three names are added to the schema and to both lists in one change. + three decimals, 64 lines, 1024 characters. +- **The members of `fit` are schema properties.** The published schema declares `maxLines`, `shrinkTo` and + `overflow` under `fit` with `additionalProperties: false`, so a host can check them by machine, and a member + that is wrong is reported at the member (`/elements/1/fit/maxLines`, or in the override that states `fit`). + The three names are in the host's list (`SceneFacts.VOCABULARY`, held to the schema by a test in the bridge) + and in the renderer's (`ElementFactory.VOCABULARY`). A member `fit` does not have is reported at `fit`, + because its name is not one the schema declares. - **Rotation and reverse.** A text turned a quarter is fitted along the box's height, and `align` and `valign` follow the direction of reading. Reverse text fills its own box black and clears the letters; it counts twice against the painted-area cap. @@ -399,6 +422,8 @@ Legibility on thermal heads: - **Determinism (section 10.2).** No tolerance was needed. The goldens are generated in the CI image (Linux, Temurin 21.0.9) and are the same bytes on Windows (Temurin 21.0.12), at 203, 300 and 600 dpi, for the glyph bitmaps (up to 100 dots to the em) and for the outline path above that; they are compared exactly on both. + Glyph bitmaps come from the FreeType each JDK ships; the versions are recorded beside the goldens + (`renderer/src/test/resources/scene2/README.md`). One case depends on more than the scene: a line whose strip is over 8 million dots (type of several hundred points) is drawn in bands of rows, and the rasteriser may shade a few edge dots at a band's border differently than in one piece (fewer than 1 in 10 000 ink dots). Where the bands fall is a function of the line's box, so diff --git a/renderer/README.md b/renderer/README.md index 9d5b634..bad950d 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -124,11 +124,11 @@ A source with schema `qqq-zpl-scene/2` is a layout in physical units that render - **Coordinates** start at the top left of the printable area, the stock less its margins. In dots the printable area is `floor((width - left - right) x dpi)` wide and `floor((height - top - bottom) x dpi)` high, which is how a box size is rounded, and it starts at `ceil(left x dpi)`, `ceil(top x dpi)`, moved back by one dot where it would otherwise pass the page edge. So a box of exactly the printable width and height fits at 203, 300 and 600 dpi alike. No ink is ever a whole dot inside a margin; the right and bottom edges may pass theirs by a fraction of a dot (less than 0.125 mm at 203 dpi). `design` states the stock the layout was drawn for; the request's stock must match it within 0.5 mm on each side (`STOCK_MISMATCH`). - **Every element** has a unique `id` (`[A-Za-z][A-Za-z0-9_-]{0,31}`), a `type`, an `anchor` (one of nine points, default `top-left`: the same point of the box is placed on that point of its container), `x` and `y` (distances inward from the anchored edge; on a centred axis a shift that may be negative), `width` and `height` (omitted: the rest of the container), and `align` and `valign` (where content sits in the box). - **`box`** has `thickness` and optional `fill`; a line is a box whose width or height is its thickness. **`group`** has `children`, placed relative to its box; groups nest four deep. A scene holds at most 1000 elements, and its elements may paint at most sixteen times its printable area in all, an overlap counted each time: a filled box counts its area, an outline its four bars, a group nothing. The element that would pass that is refused as `SCENE_INVALID` at its pointer, with its box and `measured.paintedPercent` against `limit.paintedPercent` of 1600. A real label paints less than twice its area; the limit holds the worst scene to sixteen fills of the canvas where 1000 were possible. -- **`text`** draws one value in a face bundled with the renderer: `qqq-sans`, `qqq-sans-bold` (IBM Plex Sans), `qqq-condensed-bold` (IBM Plex Sans Condensed) and `qqq-mono`, `qqq-mono-bold` (JetBrains Mono). There is no printer font in version 2 and no installed font is used; any other `font` is `FONT_UNKNOWN`, and a request that supplies an asset whose name begins `qqq-` is refused as `RESERVED_FONT_NAME`. `font` and `size` may come from the scene's `defaults`. The value is `value` or, read from the record when rendering, `valuePath`; at most 1024 characters, each of which the face must draw as one glyph from left to right (no control or format characters, combining marks, shaping or right-to-left scripts: `FONT_MISSING_GLYPH`, with the count). - - **Size and measurement.** `size` is the em as a physical length from `1pt` to `1000pt`, not rounded to dots. A text is measured before it is drawn, by integer arithmetic on the face's own numbers, so the measurement is the same on every machine. A line's box is its pen advance widened to hold the ink of every character in it, plus two dots on each inked side for the rasteriser. The block of lines is placed in the element's box by `align` and `valign`, and each line in the block by `align`. `lineHeight` is the distance between baselines as a multiple of the size (default: the face's own). `rotation` turns the text clockwise in a box given as it appears on the label; `reverse` prints white letters on the box filled black. - - **Fit.** In this order: lay the value out at `size` within `fit.maxLines` (default 1); if it does not fit, take the largest size, in steps of 0.25 pt down to `fit.shrinkTo`, at which it does (`TEXT_SHRUNK`); if none does, apply `fit.overflow`. `shrinkTo` defaults to 70% of the size and not below 5 pt. `overflow` is `refuse` (the default: `TEXT_DOES_NOT_FIT`, with the measured width, height, lines and size against the box) or `truncate`, which cuts at a character, ends with an ellipsis and warns `TEXT_TRUNCATED`. At each size a line is broken between words while that fits and at any character when it does not, so a value with no space wraps and a larger size is preferred to whole words (`TEXT_WRAPPED`). - - **Proving the fit.** `maxLength` is the longest value in characters. When a scene is validated, that many of the face's widest character must fit, each taken to reach as far above, below and beside its advance as the furthest-reaching character of the face; otherwise the scene is refused as `TEXT_DOES_NOT_FIT`. A scene that passes cannot be refused at that render target because a value of up to that length does not fit, whichever of the face's characters it holds. The proof is therefore stricter than a typical value needs, and a box that is exactly `lines x lineHeight` high is not proven: leave room for an accent above a capital. When printing, a longer value is `VALUE_TOO_LONG` before any layout. A bound element without `maxLength` warns `FIT_NOT_PROVEN`. Validation reads no record. The proof is for the render target of the request; validate at each resolution the document prints at. - - **Legibility.** Glyphs are drawn antialiased and a dot is ink when its grey is darker than `threshold` (1 to 254, default 128), so a higher value prints heavier. `TEXT_SMALL_FOR_DPI` warns when the capitals are under 12 dots high at the render target (about 6 pt at 203 dpi), `TEXT_LIGHT_FACE` when a regular weight is used with capitals under 20 dots (about 10 pt at 203 dpi). An override is how a scene answers for one resolution: a bold face or a higher `threshold` at 203 dpi. +- **`text`** draws one value in a face bundled with the renderer: `qqq-sans`, `qqq-sans-bold` (IBM Plex Sans), `qqq-condensed-bold` (IBM Plex Sans Condensed) and `qqq-mono`, `qqq-mono-bold` (JetBrains Mono). There is no printer font in version 2 and no installed font is used; any other `font` is `FONT_UNKNOWN`, and a request that supplies an asset whose name begins `qqq-` is refused as `RESERVED_FONT_NAME`. `font` and `size` may come from the scene's `defaults`. The value is `value` or, read from the record when rendering, `valuePath` (text as it is, `true` or `false`, or a number in plain decimal digits with no exponent and no fraction that is only zeros: `1.0E10` prints `10000000000`, `2.50` prints `2.5`; anything else is `VALUE_MISSING`); at most 1024 characters, each of which the face must draw as one glyph from left to right (no control or format characters, combining marks, shaping or right-to-left scripts: `FONT_MISSING_GLYPH`, with the count). + - **Size and measurement.** `size` is the em as a physical length from `1pt` to `1000pt`, not rounded to dots. A text is measured before it is drawn, by integer arithmetic on the face's own numbers, so the measurement is the same on every machine. A line's box is its pen advance widened to hold the ink of every character in it, plus two dots on each inked side for the rasteriser. A text whose ink the rasteriser puts outside that box is not printed in part and does not fail the render: the one element is refused as `TEXT_DOES_NOT_FIT` with `measured.glyphsOutsideMeasure` and `measured.dotsOutsideMeasure`, when the scene is validated if its value is a literal. No bundled face does so at any size from 1 pt to 1000 pt. The block of lines is placed in the element's box by `align` and `valign`, and each line in the block by `align`. `lineHeight` is the distance between baselines as a multiple of the size (default: the face's own). `rotation` turns the text clockwise in a box given as it appears on the label; `reverse` prints white letters on the box filled black. + - **Fit.** In this order: lay the value out at `size` within `fit.maxLines` (default 1); if it does not fit, take the largest size, in steps of 0.25 pt down to `fit.shrinkTo`, at which it does (`TEXT_SHRUNK`); if none does, apply `fit.overflow`. `shrinkTo` defaults to 70% of the size and not below 5 pt. `overflow` is `refuse` (the default: `TEXT_DOES_NOT_FIT`, with the measured width, height, lines and size against the box) or `truncate`, which cuts at a character, ends with an ellipsis and warns `TEXT_TRUNCATED`. At each size a line is broken between words while that fits and at any character when it does not, so a value with no space wraps and a larger size is preferred to whole words (`TEXT_WRAPPED`). A member of `fit` that is wrong is `SCENE_INVALID` at that member (`/elements/3/fit/maxLines`). The size chosen is exactly the one a search of every quarter-point step gives, found without making that search, and all the text of one scene is held to a stated amount of work: 64 million steps, where a character visited while fitting is one step, a character to be drawn is 16 and a glyph the scene draws for the first time at a size is 4096. A scene that passes it is refused as `SCENE_INVALID` at the element that did, with `measured.textWorkSteps` against `limit.textWorkSteps`, the same whether it is validated or rendered and on every machine. That is about a second of a worker; a label of a hundred values takes a few percent of it. + - **Proving the fit.** `maxLength` is the longest value in characters. When a scene is validated, that many of the face's widest character must fit whole, each taken to reach as far above, below and beside its advance as the furthest-reaching character of the face; otherwise the scene is refused as `TEXT_DOES_NOT_FIT`. The proof never cuts. An element with `overflow: truncate` whose stated length is not proven is still valid, since cutting is what its author chose, but every validation warns `FIT_NOT_PROVEN` with `measured.provenCharacters`, the longest length that is proven to fit whole, against `limit.characters`: longer values may be cut. A scene that passes cannot be refused at that render target because a value of up to that length does not fit, whichever of the face's characters it holds. The proof is therefore stricter than a typical value needs, and a box that is exactly `lines x lineHeight` high is not proven: leave room for an accent above a capital. When printing, a longer value is `VALUE_TOO_LONG` before any layout. A bound element without `maxLength` warns `FIT_NOT_PROVEN` with no number. Validation reads no record. The proof is for the render target of the request; validate at each resolution the document prints at. + - **Legibility.** Glyphs are drawn antialiased and a dot is ink when its grey is darker than `threshold` (1 to 254, default 128), so a higher value prints heavier. `TEXT_SMALL_FOR_DPI` warns when the capitals are under 12 dots high at the render target (about 6 pt at 203 dpi), `TEXT_LIGHT_FACE` when a regular weight is used with capitals under 20 dots (about 10 pt at 203 dpi). A literal is judged at the size it is drawn at; a bound value, when validated, at the size its `maxLength` is proven at, which is the smallest any value is printed at (the floor when the proof fails and the element cuts), and at its stated size when it has no `maxLength`. An override is how a scene answers for one resolution: a bold face or a higher `threshold` at 203 dpi. - **`barcode` and `image`** are parsed and placed by renderer `0.2.0` and then refused as `RENDERER_TOO_OLD`, with the box they would have had, until their packages are in the renderer. - **`overrides`** replace properties of declared elements at the listed resolutions and are the only place a scene may depend on resolution. They are checked for all three resolutions whatever the request's target. **`samples`** are accepted and ignored by rendering. - **Output.** The whole label is composed on one 1-bit canvas and emitted as uncompressed `^GFA` fields: rows are cut into bands wherever eight or more blank rows separate ink, each band is trimmed to its inked columns, and a band is continued in a further field at 99,999 bytes. Only `^XA`, `^PW`, `^LL`, `^LH`, `^CI28`, `^FO`, `^GFA`, `^FS` and `^XZ` are emitted. diff --git a/renderer/schema/zpl-scene-2.schema.json b/renderer/schema/zpl-scene-2.schema.json index 9d4d272..e7a74bc 100644 --- a/renderer/schema/zpl-scene-2.schema.json +++ b/renderer/schema/zpl-scene-2.schema.json @@ -98,21 +98,27 @@ }, { "$ref": "#/$defs/placement", - "description": "Text in a face bundled with the renderer, measured before it is drawn and placed in its box by `align` and `valign`. `font` and `size` may come from `defaults`. The renderer is the authority: it also enforces a size from 1pt to 1000pt, a `shrinkTo` from 1pt up to the size, at most three decimals in `lineHeight`, at most 1024 characters, only characters the face draws as one glyph each from left to right (FONT_MISSING_GLYPH), and no supplied asset whose name begins `qqq-` (RESERVED_FONT_NAME).", + "description": "Text in a face bundled with the renderer, measured before it is drawn and placed in its box by `align` and `valign`. `font` and `size` may come from `defaults`. The renderer is the authority: it also enforces a size from 1pt to 1000pt, a `shrinkTo` from 1pt up to the size, at most three decimals in `lineHeight`, at most 1024 characters, only characters the face draws as one glyph each from left to right (FONT_MISSING_GLYPH), no supplied asset whose name begins `qqq-` (RESERVED_FONT_NAME), and a stated amount of work for all the text of one scene (SCENE_INVALID with `textWorkSteps`).", "unevaluatedProperties": false, "oneOf": [{"required": ["value"]}, {"required": ["valuePath"]}], "properties": { "type": {"const": "text"}, "value": {"type": "string", "maxLength": 1024, "description": "The text itself."}, - "valuePath": {"type": "string", "pattern": "^/", "maxLength": 256, "description": "A JSON pointer into the record. Text is printed as it is, a number or true/false as JSON writes it; anything else is VALUE_MISSING. No record is read when a scene is validated."}, + "valuePath": {"type": "string", "pattern": "^/", "maxLength": 256, "description": "A JSON pointer into the record. Text is printed as it is; true and false as those words; a number in plain decimal digits, with no exponent and no fraction that is only zeros (`1.0E10` prints `10000000000`, `2.50` prints `2.5`, `12.0` prints `12`). Anything else, a number that is not finite among them, is VALUE_MISSING. No record is read when a scene is validated."}, "font": {"enum": ["qqq-sans", "qqq-sans-bold", "qqq-condensed-bold", "qqq-mono", "qqq-mono-bold"], "description": "A bundled face: IBM Plex Sans Regular and Bold, IBM Plex Sans Condensed Bold, JetBrains Mono Regular and Bold. Any other name is FONT_UNKNOWN."}, "size": {"$ref": "#/$defs/physical", "description": "The em size. Type scales continuously: the size is not rounded to dots."}, "lineHeight": {"type": "number", "minimum": 0.5, "maximum": 5, "description": "The distance between baselines as a multiple of the size. Default: the face's own ascent, descent and line gap."}, "fit": { "type": "object", - "description": "What happens when the value does not fit the box. In order: lay out at `size` within `maxLines`; else the largest size, in steps of 0.25pt down to `shrinkTo`, that fits; else `overflow`. At each size a line is broken between words while that fits and at any character when it does not. Its members, which the renderer enforces and refuses any other: `maxLines`, a whole number from 1 to 64, default 1; `shrinkTo`, a physical length from 1pt up to `size`, the smallest size the text may be reduced to, default 70% of `size` and not below 5pt (or `size` itself when that is smaller); `overflow`, `refuse` (the default, TEXT_DOES_NOT_FIT) or `truncate` (cut at a character, end with an ellipsis, warn TEXT_TRUNCATED). The members are described here and not declared as schema properties because a diagnostic points at `fit` itself: the names this schema declares are exactly the names a diagnostic's pointer may hold." + "additionalProperties": false, + "description": "What happens when the value does not fit the box. In order: lay out at `size` within `maxLines`; else the largest size, in steps of 0.25pt down to `shrinkTo`, that fits; else `overflow`. At each size a line is broken between words while that fits and at any character when it does not. A member that is wrong is SCENE_INVALID at that member (`/fit/maxLines`); a member `fit` does not have is SCENE_INVALID at `fit`.", + "properties": { + "maxLines": {"type": "integer", "minimum": 1, "maximum": 64, "default": 1, "description": "The most lines the value may take."}, + "shrinkTo": {"$ref": "#/$defs/physical", "description": "The smallest size the text may be reduced to: from 1pt up to `size`, which the renderer enforces. Default: 70% of `size` and not below 5pt, or `size` itself when that is smaller."}, + "overflow": {"enum": ["refuse", "truncate"], "default": "refuse", "description": "What is done with a value that fits at no size: `refuse` (TEXT_DOES_NOT_FIT), or `truncate` (cut at a character, end with an ellipsis, warn TEXT_TRUNCATED)."} + } }, - "maxLength": {"type": "integer", "minimum": 1, "maximum": 1024, "description": "The longest value, in characters. Validation proves that this many of the face's widest character fit, so a length refusal happens when the scene is published; a longer value is VALUE_TOO_LONG when printing. Without it a bound element warns FIT_NOT_PROVEN."}, + "maxLength": {"type": "integer", "minimum": 1, "maximum": 1024, "description": "The longest value, in characters. Validation proves that this many of the face's widest character fit whole, never cut, so a length refusal happens when the scene is published; a longer value is VALUE_TOO_LONG when printing. When the proof fails and `fit.overflow` is `truncate` the scene stands and warns FIT_NOT_PROVEN with the longest length that is proven (`provenCharacters`): longer values may be cut. Without `maxLength` a bound element warns FIT_NOT_PROVEN."}, "threshold": {"type": "integer", "minimum": 1, "maximum": 254, "default": 128, "description": "Glyphs are drawn antialiased; a dot is ink when its grey is darker than this. Higher prints heavier."}, "reverse": {"type": "boolean", "default": false, "description": "White letters on the element's box filled black."}, "rotation": {"enum": [0, 90, 180, 270], "description": "Clockwise. The box is given as it appears on the label; a text turned a quarter is fitted along the box's height."} diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementFactory.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementFactory.java index dd5ae45..bec149f 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementFactory.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementFactory.java @@ -50,10 +50,11 @@ public interface ElementFactory Map FACTORIES = Map.of("box", new BoxElement.Factory(), "text", new TextFactory(), "barcode", new BarcodeFactory(), "image", new GraphicsFactory()); /*************************************************************************** - ** Every property name the version 2 schema declares. A diagnostic's pointer - ** is made only of these, of array indexes and of declared element ids. + ** Every property name the version 2 schema declares, the members of a text + ** element's `fit` among them. A diagnostic's pointer is made only of these, + ** of array indexes and of declared element ids. ***************************************************************************/ - Set VOCABULARY = Stream.concat(Stream.of("schema", "design", "defaults", "font", "size", "samples", "elements", "overrides", "when", "dpi", "set", "children"), + Set VOCABULARY = Stream.concat(Stream.of("schema", "design", "defaults", "font", "size", "samples", "elements", "overrides", "when", "dpi", "set", "children", "maxLines", "shrinkTo", "overflow"), Stream.concat(COMMON.stream(), FACTORIES.values().stream().flatMap(factory -> factory.properties().stream()))).collect(Collectors.toUnmodifiableSet()); diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java index 3bbdf44..21cec4a 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/ElementSource.java @@ -205,7 +205,8 @@ public final class ElementSource /*************************************************************************** - ** The refusal for a property the element states wrongly, or lacks. + ** The refusal for a property the element states wrongly, or lacks. A member + ** of a property that is an object is named with a slash: `fit/maxLines`. ***************************************************************************/ public Refusal invalid(String name) { @@ -260,11 +261,14 @@ public final class ElementSource /*************************************************************************** ** Where a property is stated: in the override that set it, in the scene's - ** defaults, else in the element. + ** defaults, else in the element. A member of a property that is an object + ** (`fit/maxLines`) is in that property, wherever the property is stated. ***************************************************************************/ private String pointer(String name) { - return (pointers.getOrDefault(name, pointer + "/" + name)); + int member = name.indexOf('/'); + String property = member < 0 ? name : name.substring(0, member); + return (pointers.getOrDefault(property, pointer + "/" + property) + (member < 0 ? "" : name.substring(member))); } diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java index 83278d2..114b612 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextElement.java @@ -23,8 +23,11 @@ package com.kingsrook.qbits.renderer.scene2.text; import java.math.BigDecimal; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.kingsrook.qbits.renderer.RenderInput; @@ -49,11 +52,23 @@ import com.kingsrook.qbits.renderer.scene2.SceneElement; ** diagnostic or an exception. ** ** A bound value is not known when a scene is validated, so validation reads no - ** record. With `maxLength` it proves instead that the longest value fits: that - ** many of the face's widest character, each taken to reach as far in every - ** direction as the furthest-reaching character of the face. Without - ** `maxLength` it warns `FIT_NOT_PROVEN`. When rendering, a value longer than - ** `maxLength` is refused before any layout. + ** record. With `maxLength` it proves instead that the longest value fits whole: + ** that many of the face's widest character, each taken to reach as far in + ** every direction as the furthest-reaching character of the face. The proof + ** never cuts. When it fails the scene is refused, unless the element asked for + ** cutting: then the scene stands, with the warning `FIT_NOT_PROVEN` and the + ** longest length that is proven. Without `maxLength` it warns `FIT_NOT_PROVEN` + ** with no number. When rendering, a value longer than `maxLength` is refused + ** before any layout. + ** + ** The text of one scene is held to a stated amount of work (`SCENE_WORK_STEPS`): + ** every character visited while fitting counts one step, every character of + ** a text that is to be drawn counts `TextRaster.PEN_STEPS`, and every glyph + ** the scene draws for the first time at a size, which the runtime must + ** rasterise, counts `TextRaster.GLYPH_STEPS`. A scene that passes it is + ** refused by name at the element that did, and so is every text after it. + ** The count is integer arithmetic, the same on every machine, and the same + ** whether the scene is validated or rendered. *******************************************************************************/ final class TextElement implements SceneElement { @@ -71,9 +86,24 @@ final class TextElement implements SceneElement ///////////////////////////////////////////////////////////////////////////////////////////////// static final int SMALL_CAPITAL_DOTS = 12; static final int LIGHT_CAPITAL_DOTS = 20; + ///////////////////////////////////////////////////////////////////////////////////////////////// + // the work the text of one scene may take, in steps. A value of forty characters costs // + // about a hundred thousand at a size its scene has not drawn, nearly all of it for the // + // glyphs the runtime must rasterise, and under two thousand at a size it has. The // + // allowance is fifteen thousand glyphs rasterised, or three thousand fits of the longest // + // value over the widest range of sizes: about a second of the worker, where one hostile // + // scene took minutes // + ///////////////////////////////////////////////////////////////////////////////////////////////// + static final int SCENE_WORK_STEPS = 64_000_000; private static final Set FIT = Set.of("maxLines", "shrinkTo", "overflow"); + ///////////////////////////////////////////////////////////////////////////////////////////////// + // the work of each scene, by the collector of its one render or validation, which is all a // + // text element is given that belongs to the scene; it is forgotten with the collector // + ///////////////////////////////////////////////////////////////////////////////////////////////// + private static final Map SCENES = Collections.synchronizedMap(new WeakHashMap<>()); + private final String id; private final Placement placement; private final int rotation; @@ -88,13 +118,44 @@ final class TextElement implements SceneElement private final int threshold; private final String value; private final String path; + private Composed composed; + + + + /*************************************************************************** + ** What the text of one scene has cost so far: the steps counted, and the + ** glyphs it has drawn, each a face, a size and a character in one number. + ** There are never more of those than the steps allow. + ***************************************************************************/ + private record Scene(TextFit.Work work, Set glyphs) + { + } + + + + /*************************************************************************** + ** What `check` composed, kept for the `paint` of the same pass, so a text + ** is fitted once. + ***************************************************************************/ + private record Composed(Frame frame, RenderInput input, Diagnostics diagnostics, TextRaster.Drawing drawing) + { + /************************************************************************ + ** Whether this is the answer for the same box of the same pass. + ************************************************************************/ + boolean of(Frame other, RenderInput request, Diagnostics collector) + { + return (frame.equals(other) && input == request && diagnostics == collector); + } + } /*************************************************************************** ** Read the element. A property that is not what the schema says is - ** `SCENE_INVALID` at that property; a face this renderer does not bundle is - ** `FONT_UNKNOWN`. + ** `SCENE_INVALID` at that property, a member of `fit` at that member; a + ** member `fit` does not have is reported at `fit`, since only names the + ** schema declares leave the renderer. A face this renderer does not bundle + ** is `FONT_UNKNOWN`. ***************************************************************************/ TextElement(ElementSource source) { @@ -126,12 +187,12 @@ final class TextElement implements SceneElement { throw source.invalid("fit"); } - maxLines = integer(source, "fit", fit.get("maxLines"), 1, MAXIMUM_LINES, 1); + maxLines = integer(source, "fit/maxLines", fit.get("maxLines"), 1, MAXIMUM_LINES, 1); floor = floor(source, fit.get("shrinkTo")); String overflow = fit.has("overflow") ? fit.get("overflow").textValue() : "refuse"; if(!"refuse".equals(overflow) && !"truncate".equals(overflow)) { - throw source.invalid("fit"); + throw source.invalid("fit/overflow"); } truncate = "truncate".equals(overflow); JsonNode literal = source.value("value"); @@ -235,7 +296,7 @@ final class TextElement implements SceneElement { // Refused below, at the property; the cause holds nothing more. } - throw source.invalid("fit"); + throw source.invalid("fit/shrinkTo"); } @@ -264,12 +325,14 @@ final class TextElement implements SceneElement /*************************************************************************** ** Everything that can refuse the text, with no ink: run when a scene is - ** validated and again before it is painted. + ** validated and before it is painted. What it composed is kept for the + ** paint that follows. ***************************************************************************/ @Override public void check(Frame frame, RenderInput input, Diagnostics diagnostics) { - compose(frame, input, diagnostics); + composed = null; + composed = new Composed(frame, input, diagnostics, compose(frame, input, diagnostics)); } @@ -287,18 +350,52 @@ final class TextElement implements SceneElement /*************************************************************************** - ** Draw the fitted text. Reverse text is white letters on its own box filled - ** black. + ** Draw the text as `check` fitted it, or not at all: a text whose ink the + ** rasteriser put outside what was measured is refused and leaves the label + ** as it was. Reverse text is white letters on its own box filled black. ***************************************************************************/ @Override public void paint(Canvas canvas, Frame frame, RenderInput input, Diagnostics diagnostics) { - TextRaster.Drawing drawing = compose(frame, input, diagnostics); - if(reverse) + Composed checked = composed; + composed = null; + TextRaster.Drawing drawing = checked != null && checked.of(frame, input, diagnostics) ? checked.drawing() : compose(frame, input, diagnostics); + measured(diagnostics, id, frame, TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS), drawing.block().milliPoints()); + } + + + + /*************************************************************************** + ** Refuse a text whose ink is not where it was measured: the element, by + ** name, with how many glyphs and dots strayed and at what size. The label + ** holds none of it. + ***************************************************************************/ + static void measured(Diagnostics diagnostics, String id, Frame frame, TextRaster.Stray stray, int milliPoints) + { + if(stray.any()) { - canvas.fill(frame, true); + throw diagnostics.refuse("TEXT_DOES_NOT_FIT", id, null, frame, Map.of("glyphsOutsideMeasure", stray.glyphs(), "dotsOutsideMeasure", stray.dots(), "sizeCentipoints", milliPoints / 10), + Map.of("glyphsOutsideMeasure", 0, "dotsOutsideMeasure", 0)); + } + } + + + + /*************************************************************************** + ** Compose the text within the work its scene may take, or refuse the + ** element by name with the steps counted against the steps allowed. + ***************************************************************************/ + private TextRaster.Drawing compose(Frame frame, RenderInput input, Diagnostics diagnostics) + { + Scene scene = SCENES.computeIfAbsent(diagnostics, collector -> new Scene(new TextFit.Work(SCENE_WORK_STEPS), new HashSet<>())); + try + { + return (compose(frame, input, diagnostics, scene)); + } + catch(TextFit.Exhausted exhausted) + { + throw diagnostics.refuse("SCENE_INVALID", id, diagnostics.pointer(id), frame, Map.of("textWorkSteps", Math.toIntExact(Math.min(scene.work().spent(), Integer.MAX_VALUE))), Map.of("textWorkSteps", SCENE_WORK_STEPS)); } - TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS); } @@ -306,10 +403,12 @@ final class TextElement implements SceneElement /*************************************************************************** ** Resolve the value, hold it to its length and to the face, and fit it. The ** answer is what to draw, or null when a bound value is only being - ** validated. + ** validated. A text that is only validated is also held to what the + ** rasteriser would do with it, glyph by glyph, with no ink. ***************************************************************************/ - private TextRaster.Drawing compose(Frame frame, RenderInput input, Diagnostics diagnostics) + private TextRaster.Drawing compose(Frame frame, RenderInput input, Diagnostics diagnostics, Scene scene) { + TextFit.Work work = scene.work(); int reserved = input.reservedAssetNames().size(); if(reserved > 0) { @@ -317,32 +416,18 @@ final class TextElement implements SceneElement } int dpi = input.targetDpi == null ? input.stock.dpi() : input.targetDpi; boolean upright = rotation % 180 == 0; + boolean validate = "VALIDATE".equals(input.operation); TextFit.Request request = new TextFit.Request(face, upright ? frame.width() : frame.height(), upright ? frame.height() : frame.width(), dpi, size, floor, lineHeight, maxLines, truncate); if(path != null && maxLength == null) { diagnostics.warn("FIT_NOT_PROVEN", id, null, frame, null, null); } - String text = value; - if(path != null && "VALIDATE".equals(input.operation)) + if(path != null && validate) { - if(maxLength != null) - { - Face.Glyph[] worst = new Face.Glyph[maxLength]; - Arrays.fill(worst, face.worst()); - fitted(request, worst, frame, diagnostics); - } - legibility(size, dpi, frame, diagnostics); + legibility(maxLength == null ? size : proven(request, frame, diagnostics, work), dpi, frame, diagnostics); return (null); } - if(path != null) - { - JsonNode bound = input.context.at(path); - if(!bound.isTextual() && !bound.isNumber() && !bound.isBoolean()) - { - throw diagnostics.refuse("VALUE_MISSING", id, null, frame, null, null); - } - text = bound.asText(); - } + String text = path == null ? value : bound(input.context.at(path), frame, diagnostics); int characters = text.codePointCount(0, text.length()); int longest = maxLength == null ? MAXIMUM_CHARACTERS : maxLength; if(characters > longest) @@ -354,7 +439,10 @@ final class TextElement implements SceneElement { throw diagnostics.refuse("FONT_MISSING_GLYPH", id, null, frame, Map.of("missingGlyphs", missing, "characters", characters), Map.of("missingGlyphs", 0)); } - TextFit.Block block = fitted(request, face.glyphs(text), frame, diagnostics); + TextFit.Block block = fitted(request, face.glyphs(text), frame, diagnostics, work); + long drawn = (long) Face.all().indexOf(face) << 48 | (long) block.milliPoints() << 16; + long fresh = text.codePoints().filter(codePoint -> scene.glyphs().add(drawn | codePoint)).count(); + work.spend(fresh * TextRaster.GLYPH_STEPS + (long) characters * TextRaster.PEN_STEPS); if(block.milliPoints() < size) { diagnostics.inform("TEXT_SHRUNK", id, null, frame, Map.of("sizeCentipoints", block.milliPoints() / 10), Map.of("sizeCentipoints", size / 10, "floorCentipoints", floor / 10)); @@ -368,7 +456,75 @@ final class TextElement implements SceneElement diagnostics.warn("TEXT_TRUNCATED", id, null, frame, Map.of("characters", block.characters(), "shownCharacters", block.shown(), "lines", block.lines().size()), Map.of("lines", maxLines)); } legibility(block.milliPoints(), dpi, frame, diagnostics); - return (new TextRaster.Drawing(face, text, block, placement.align(), placement.valign(), rotation, threshold, !reverse)); + TextRaster.Drawing drawing = new TextRaster.Drawing(face, text, block, placement.align(), placement.valign(), rotation, threshold, !reverse); + measured(diagnostics, id, frame, new TextRaster.Stray(validate ? TextRaster.outside(drawing, dpi) : 0, 0), block.milliPoints()); + return (drawing); + } + + + + /*************************************************************************** + ** The value the record holds at the element's pointer, as it is printed. + ** Text is printed as it is and a truth value as `true` or `false`. A number + ** is printed in plain decimal digits, as the schema says: no exponent, and + ** no fraction that is only zeros, so `1.0E10` prints `10000000000`, `2.50` + ** prints `2.5` and `12.0` prints `12`. Anything else, a number that is not + ** finite among them, is `VALUE_MISSING`. + ***************************************************************************/ + private String bound(JsonNode bound, Frame frame, Diagnostics diagnostics) + { + if(bound.isTextual() || bound.isBoolean()) + { + return (bound.asText()); + } + if(bound.isIntegralNumber()) + { + return (bound.bigIntegerValue().toString()); + } + if(bound.isNumber() && Double.isFinite(bound.doubleValue())) + { + return (BigDecimal.valueOf(bound.doubleValue()).stripTrailingZeros().toPlainString()); + } + throw diagnostics.refuse("VALUE_MISSING", id, null, frame, null, null); + } + + + + /*************************************************************************** + ** Prove that the longest value fits whole, and answer the size it is + ** proven at, which is the smallest any value is printed at. The proof never + ** cuts: a cut value is not a value that fits. When it fails, an element + ** that did not ask for cutting is refused; one that did stands, since + ** cutting is what its author chose, with a warning that says how many + ** characters are proven to fit whole. Fewer characters never fit worse, so + ** that number is found by halving. The size is then the floor, where a cut + ** value is printed. + ***************************************************************************/ + private int proven(TextFit.Request request, Frame frame, Diagnostics diagnostics, TextFit.Work work) + { + TextFit.Request whole = new TextFit.Request(face, request.width(), request.height(), request.dpi(), size, floor, lineHeight, maxLines, false); + Face.Glyph[] worst = new Face.Glyph[maxLength]; + Arrays.fill(worst, face.worst()); + TextFit.Block proof = truncate ? TextFit.fit(whole, worst, null, work) : fitted(whole, worst, frame, diagnostics, work); + if(!proof.fits()) + { + int low = 0; + int high = maxLength - 1; + while(low < high) + { + int middle = (low + high + 1) >>> 1; + if(TextFit.fit(whole, Arrays.copyOf(worst, middle), null, work).fits()) + { + low = middle; + } + else + { + high = middle - 1; + } + } + diagnostics.warn("FIT_NOT_PROVEN", id, null, frame, Map.of("provenCharacters", low), Map.of("characters", maxLength)); + } + return (proof.milliPoints()); } @@ -376,9 +532,9 @@ final class TextElement implements SceneElement /*************************************************************************** ** Fit, or refuse with what was measured at the floor size against the box. ***************************************************************************/ - private TextFit.Block fitted(TextFit.Request request, Face.Glyph[] glyphs, Frame frame, Diagnostics diagnostics) + private TextFit.Block fitted(TextFit.Request request, Face.Glyph[] glyphs, Frame frame, Diagnostics diagnostics, TextFit.Work work) { - TextFit.Block block = TextFit.fit(request, glyphs, face.glyph(TextFit.MARK)); + TextFit.Block block = TextFit.fit(request, glyphs, face.glyph(TextFit.MARK), work); if(!block.fits()) { throw diagnostics.refuse("TEXT_DOES_NOT_FIT", id, null, frame, diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java index 1f7b25f..d5c8dbc 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextFit.java @@ -38,6 +38,18 @@ import com.kingsrook.qbits.renderer.scene2.text.Face.Glyph; ** refused, or, only when the element asked for it, cut at a character and ** ended with an ellipsis at the floor size. ** + ** The answer is the one a search of every step from the nominal size down + ** gives, and is found without making it. A count that errs only toward yes + ** (`possible`) says whether a size could hold the text; it never says no to a + ** size that fits and never says yes to a larger size after no to a smaller, + ** so the largest size it allows is found by halving, and no size above that + ** one fits. From there the steps are laid out one by one as before; the count + ** is within a few dots of the layout, so they are few. When one line at the + ** floor is higher than the box, no size fits and none is searched. + ** + ** Every character visited is counted against the `Work` the caller gives, so + ** a caller can hold all the fitting of one scene to a stated amount. + ** ** At each size a line is first broken between words only. If that does not ** fit, it is broken at any character. So a value with no spaces wraps, a ** sentence keeps its words while it can, and a larger size is preferred to @@ -174,6 +186,115 @@ public final class TextFit + /*************************************************************************** + ** The work fitting may do, in characters visited, shared by as many fits + ** as the caller wants held to one amount. It is counted by integer + ** arithmetic alone, so it is the same on every machine. + ***************************************************************************/ + public static final class Work + { + private final long limit; + private long spent; + + + + /************************************************************************ + ** An allowance of this many steps. + ************************************************************************/ + public Work(long limit) + { + this.limit = limit; + } + + + + /************************************************************************ + ** Count steps, and end the work when the allowance is passed. It stays + ** passed: whatever is asked next ends at once. + ************************************************************************/ + public void spend(long steps) + { + spent += steps; + if(spent > limit) + { + throw new Exhausted(); + } + } + + + + /************************************************************************ + ** The steps counted so far. + ************************************************************************/ + public long spent() + { + return (spent); + } + } + + + + /*************************************************************************** + ** The allowance of a `Work` was passed. It says nothing else: what was + ** being fitted is not in it. + ***************************************************************************/ + public static final class Exhausted extends RuntimeException + { + private static final long serialVersionUID = 1L; + + + + /************************************************************************ + ** No message beyond the name, no cause and no stack. + ************************************************************************/ + Exhausted() + { + super("TEXT_WORK_EXHAUSTED", null, false, false); + } + } + + + + /*************************************************************************** + ** What a line reserves, in thousandths of the em, read from the face once + ** for a fit: the ascent above the baseline, the descent below it, and the + ** distance between baselines. + ***************************************************************************/ + record Leading(int ascent, int descent, int pitch) + { + /************************************************************************ + ** The face's own, with the line height the request states if it does. + ************************************************************************/ + static Leading of(Request request) + { + Face face = request.face(); + return (new Leading(face.ascent(), face.descent(), request.lineHeight() == null ? face.ascent() + face.descent() + face.leading() : request.lineHeight())); + } + + + + /************************************************************************ + ** The distance between baselines in dots, never less than one. + ************************************************************************/ + int pitch(Scale scale) + { + return (Math.max(1, scale.ceil(pitch))); + } + + + + /************************************************************************ + ** The least a block of this many lines is high: one ascent, the pitches + ** between and one descent. Ink that reaches further makes it higher. + ************************************************************************/ + int height(Scale scale, int lines) + { + return (scale.ceil(ascent) + (lines - 1) * pitch(scale) + scale.ceil(descent)); + } + } + + + /*************************************************************************** ** The box of a line as characters are added to it from the left. ***************************************************************************/ @@ -234,47 +355,175 @@ public final class TextFit /*************************************************************************** ** Fit a text, given as the measurements of its characters, by the fixed - ** order. `mark` is the face's ellipsis, used only when the request allows - ** cutting. + ** order, with no limit on the work. `mark` is the face's ellipsis, used + ** only when the request allows cutting. ***************************************************************************/ public static Block fit(Request request, Glyph[] glyphs, Glyph mark) + { + return (fit(request, glyphs, mark, new Work(Long.MAX_VALUE))); + } + + + + /*************************************************************************** + ** Fit a text by the fixed order, counting the work against an allowance + ** and ending as `Exhausted` when it is passed. The floor is never above + ** the nominal size and no character has a negative advance. + ***************************************************************************/ + public static Block fit(Request request, Glyph[] glyphs, Glyph mark, Work work) { int count = glyphs.length; while(count > 0 && glyphs[count - 1].space()) { count--; } - int size = request.nominal(); - while(true) + Leading leading = Leading.of(request); + int last = (request.nominal() - request.floor() + STEP_MILLIPOINTS - 1) / STEP_MILLIPOINTS; + Block block = at(request, leading, request.nominal(), glyphs, count, mark, work); + int step = block.fits() || last == 0 ? last + 1 : first(request, leading, glyphs, count, last, work); + while(step <= last) { - Scale scale = new Scale(size, request.dpi()); - Block words = block(request, scale, lines(request, scale, glyphs, count, true), count, count); - if(words.fits()) - { - return (words); - } - Block characters = block(request, scale, lines(request, scale, glyphs, count, false), count, count); - if(characters.fits() || size == request.floor()) - { - return (characters.fits() || !request.truncate() ? characters : cut(request, scale, glyphs, mark, characters)); - } - size = Math.max(request.floor(), size - STEP_MILLIPOINTS); + block = at(request, leading, size(request, step), glyphs, count, mark, work); + step = block.fits() ? last + 1 : step + 1; } + return (block); + } + + + + /*************************************************************************** + ** The size a number of quarter-point steps below the nominal, which is the + ** floor once the steps reach it. + ***************************************************************************/ + private static int size(Request request, int step) + { + return (Math.max(request.floor(), request.nominal() - step * STEP_MILLIPOINTS)); + } + + + + /*************************************************************************** + ** The answer at one size: the text broken between words if that fits, else + ** broken at any character; and at the floor, when that does not fit either + ** and the request allows it, cut. This is one step of the search of every + ** size, which a test makes in full to hold `fit` to it. + ***************************************************************************/ + static Block at(Request request, Leading leading, int size, Glyph[] glyphs, int count, Glyph mark, Work work) + { + Scale scale = new Scale(size, request.dpi()); + Block words = block(request, leading, scale, lines(request, scale, glyphs, count, true, work), count, count); + if(words.fits()) + { + return (words); + } + Block characters = block(request, leading, scale, lines(request, scale, glyphs, count, false, work), count, count); + return (characters.fits() || size > request.floor() || !request.truncate() ? characters : cut(request, leading, scale, glyphs, mark, characters, work)); + } + + + + /*************************************************************************** + ** The fewest steps below the nominal, from one, at which the text could + ** fit; `last`, the floor, when it could at none above it. No size above the + ** answer fits, because `possible` never refuses a size that fits and, once + ** it allows a size, allows every smaller one. One line at the floor higher + ** than the box settles it for every text without a count. + ***************************************************************************/ + private static int first(Request request, Leading leading, Glyph[] glyphs, int count, int last, Work work) + { + if(leading.height(new Scale(request.floor(), request.dpi()), 1) > request.height()) + { + return (last); + } + int low = 1; + int high = last; + while(low < high) + { + int middle = (low + high) >>> 1; + if(possible(request, leading, new Scale(size(request, middle), request.dpi()), glyphs, count, work)) + { + high = middle; + } + else + { + low = middle + 1; + } + } + return (low); + } + + + + /*************************************************************************** + ** Whether a text could fit at one size, erring only toward yes. Lines are + ** filled at any character, each held to a width no layout of it can be + ** under: its advance to the end of its last character that is not a space, + ** or, when wider, the span of its ink scaled exactly and the allowance at + ** both ends less the one dot two roundings can give back. A line of a real + ** layout, by words or by characters, is never narrower than this, and a + ** line that holds more is never narrower than one that holds less, so no + ** layout has fewer lines than are counted here; and a block is never lower + ** than its lines' ascent, pitches and descent. Every one of these numbers + ** grows with the size, so a yes at one size is a yes at every smaller one. + ***************************************************************************/ + private static boolean possible(Request request, Leading leading, Scale scale, Glyph[] glyphs, int count, Work work) + { + work.spend(count); + int lines = 0; + int index = 0; + while(index < count) + { + lines++; + if(lines > request.maxLines() || leading.height(scale, lines) > request.height()) + { + return (false); + } + int from = index; + long units = 0; + long end = 0; + long reach = Long.MIN_VALUE; + long lead = Long.MAX_VALUE; + while(index < count) + { + Glyph glyph = glyphs[index]; + long after = units + glyph.advance(); + long ended = glyph.space() ? end : after; + long reached = glyph.ink() ? Math.max(reach, units + glyph.right()) : reach; + long led = glyph.ink() ? Math.min(lead, units + glyph.left()) : lead; + int width = Math.max(scale.ceil(ended), reached < led ? 0 : scale.ceil(reached - led) + 2 * SLOP - 1); + if(width > request.width() && index > from) + { + break; + } + if(width > request.width()) + { + return (false); + } + units = after; + end = ended; + reach = reached; + lead = led; + index++; + } + } + return (true); } /*************************************************************************** ** Break a text into lines at one size, between words or at any character. - ** Spaces where a line is broken are dropped. + ** Spaces where a line is broken are dropped. A line is measured twice, to + ** find its end and to box it, and is counted so. ***************************************************************************/ - private static List lines(Request request, Scale scale, Glyph[] glyphs, int count, boolean words) + private static List lines(Request request, Scale scale, Glyph[] glyphs, int count, boolean words, Work work) { List lines = new ArrayList<>(); int from = 0; while(from < count) { int to = end(request, scale, glyphs, from, count, words); + work.spend(2L * (to - from) + 1); lines.add(line(scale, glyphs, from, to, null)); from = to; while(from < count && glyphs[from].space()) @@ -345,17 +594,16 @@ public final class TextFit ** face's ascent above its baseline and its descent below; the block grows ** where the ink of a line reaches further. ***************************************************************************/ - private static Block block(Request request, Scale scale, List lines, int characters, int shown) + private static Block block(Request request, Leading leading, Scale scale, List lines, int characters, int shown) { if(lines.isEmpty()) { return (new Block(scale.milliPoints(), lines, 0, 0, 0, 0, characters, shown, true)); } - Face face = request.face(); - int ascent = scale.ceil(face.ascent()); - int pitch = Math.max(1, scale.ceil(request.lineHeight() == null ? face.ascent() + face.descent() + face.leading() : request.lineHeight())); + int ascent = scale.ceil(leading.ascent()); + int pitch = leading.pitch(scale); int top = 0; - int bottom = ascent + (lines.size() - 1) * pitch + scale.ceil(face.descent()); + int bottom = leading.height(scale, lines.size()); int width = 0; for(int index = 0; index < lines.size(); index++) { @@ -377,12 +625,19 @@ public final class TextFit ** still fit with it, down to the ellipsis alone. Something is always left ** out, so the ellipsis always stands for text, and spaces before it are ** dropped. When not even the ellipsis fits, the answer is the refusal that - ** was passed in. + ** was passed in. A box lower than a number of lines holds no cut of that + ** many, which is known without trying; so one lower than a single line + ** holds no ellipsis at all. ***************************************************************************/ - private static Block cut(Request request, Scale scale, Glyph[] glyphs, Glyph mark, Block refused) + private static Block cut(Request request, Leading leading, Scale scale, Glyph[] glyphs, Glyph mark, Block refused, Work work) { int all = refused.lines().size(); - for(int kept = Math.min(request.maxLines(), all); kept > 0; kept--) + int most = Math.min(request.maxLines(), all); + while(most > 0 && leading.height(scale, most) > request.height()) + { + most--; + } + for(int kept = most; kept > 0; kept--) { List lines = new ArrayList<>(refused.lines().subList(0, kept)); int from = lines.get(kept - 1).from(); @@ -392,8 +647,9 @@ public final class TextFit { continue; } + work.spend(to - from + 1L + kept); lines.set(kept - 1, line(scale, glyphs, from, to, mark)); - Block block = block(request, scale, lines, refused.characters(), to); + Block block = block(request, leading, scale, lines, refused.characters(), to); if(block.fits()) { return (block); diff --git a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java index 64e67b1..d3664ff 100644 --- a/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java +++ b/renderer/src/main/java/com/kingsrook/qbits/renderer/scene2/text/TextRaster.java @@ -29,6 +29,7 @@ import java.awt.RenderingHints; import java.awt.font.GlyphVector; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; +import java.util.BitSet; import com.kingsrook.qbits.renderer.scene2.Canvas; import com.kingsrook.qbits.renderer.scene2.Frame; import com.kingsrook.qbits.renderer.scene2.Layout; @@ -44,8 +45,10 @@ import com.kingsrook.qbits.renderer.scene2.Placement; ** A line is drawn on a strip: its measured box and a guard of `GUARD` dots all ** round. Ink found in the guard, or a glyph whose bitmap the runtime places ** anywhere outside the measured box, means the measurement was wrong. Such - ** ink is never clipped away and never printed outside the box: the render - ** fails instead. + ** ink is never clipped away and never printed outside the box, and a text is + ** never printed in part: the dots of a text are gathered first and reach the + ** label only when none strayed. What strayed is counted (`Stray`), for the + ** element to be refused by name. ** ** A strip of more than `BAND_DOTS` dots (very large type) is drawn in bands of ** whole rows, so one line never needs more grey than that. Where the bands @@ -57,6 +60,14 @@ final class TextRaster { static final int GUARD = 2; static final int BAND_DOTS = 1 << 23; + ///////////////////////////////////////////////////////////////////////////////////////////////// + // what drawing counts against the work of a scene, in characters visited while fitting, // + // which take about 15 ns each. A glyph the runtime has not drawn at a size is rasterised // + // once, in 20 to 50 microseconds; after that, asking for it and for where its bitmap // + // falls takes about a quarter of a microsecond // + ///////////////////////////////////////////////////////////////////////////////////////////////// + static final int GLYPH_STEPS = 4096; + static final int PEN_STEPS = 16; @@ -72,7 +83,8 @@ final class TextRaster /*************************************************************************** ** What to draw and how: the face, the text, its fitted block, where lines ** sit across the block, the clockwise rotation, the grey below which a dot - ** is ink, and whether the dots are ink or (for reverse text) cleared. + ** is ink, and whether the dots are ink or (for reverse text) cleared from + ** the element's box filled black. ***************************************************************************/ record Drawing(Face face, String text, TextFit.Block block, Placement.Align align, Placement.Valign valign, int rotation, int threshold, boolean ink) { @@ -81,10 +93,48 @@ final class TextRaster /*************************************************************************** - ** Draw into the element's box, which is given as it appears on the label: - ** a text turned a quarter reads along the box's height. + ** What the rasteriser put outside the measure: glyphs whose bitmap is not + ** wholly inside the box of their line, and dots of ink found in the guard + ** round a line or outside the element's box. ***************************************************************************/ - static void paint(Canvas canvas, Frame frame, Drawing drawing, int bandDots) + record Stray(int glyphs, int dots) + { + /************************************************************************ + ** Whether anything strayed. + ************************************************************************/ + boolean any() + { + return (glyphs > 0 || dots > 0); + } + } + + + + /*************************************************************************** + ** How many glyphs of a fitted text the runtime would place outside the box + ** measured for their line at this resolution, without drawing any: what + ** can be known of a text when a scene is only validated. + ***************************************************************************/ + static int outside(Drawing drawing, int dpi) + { + TextFit.Scale scale = new TextFit.Scale(drawing.block().milliPoints(), dpi); + Font font = drawing.face().font(scale.size()); + int outside = 0; + for(TextFit.Line line : drawing.block().lines()) + { + outside += glyphs(drawing, scale, font, line, null, 0); + } + return (outside); + } + + + + /*************************************************************************** + ** Draw into the element's box, which is given as it appears on the label: + ** a text turned a quarter reads along the box's height. The answer is what + ** strayed; when anything did, the label is left as it was. + ***************************************************************************/ + static Stray paint(Canvas canvas, Frame frame, Drawing drawing, int bandDots) { TextFit.Block block = drawing.block(); boolean upright = drawing.rotation() % 180 == 0; @@ -92,31 +142,50 @@ final class TextRaster Frame content = Layout.align(reading, block.width(), block.height(), drawing.align(), drawing.valign()); TextFit.Scale scale = new TextFit.Scale(block.milliPoints(), canvas.dpi()); Font font = drawing.face().font(scale.size()); + BitSet ink = new BitSet(); + int glyphs = 0; + int dots = 0; for(int index = 0; index < block.lines().size(); index++) { TextFit.Line line = block.lines().get(index); int left = content.x() + drawing.align().position().place(block.width(), line.width(), 0); int top = content.y() + block.baseline() + index * block.pitch() - line.above(); - strip(canvas, frame, reading, drawing, scale, font, line, left, top, bandDots); + Stray stray = strip(ink, reading, drawing, scale, font, line, left, top, bandDots); + glyphs += stray.glyphs(); + dots += stray.dots(); } + Stray stray = new Stray(glyphs, dots); + if(!stray.any()) + { + if(!drawing.ink()) + { + canvas.fill(frame, true); + } + for(int dot = ink.nextSetBit(0); dot >= 0; dot = ink.nextSetBit(dot + 1)) + { + dot(canvas, frame, reading, drawing, dot % reading.width(), dot / reading.width()); + } + } + return (stray); } /*************************************************************************** - ** Draw one line whose box has its top left at `left`, `top` of the reading - ** frame, a band of rows at a time. + ** Gather the ink of one line whose box has its top left at `left`, `top` of + ** the reading frame, a band of rows at a time, and count what strayed. ***************************************************************************/ - private static void strip(Canvas canvas, Frame frame, Frame reading, Drawing drawing, TextFit.Scale scale, Font font, TextFit.Line line, int left, int top, int bandDots) + private static Stray strip(BitSet ink, Frame reading, Drawing drawing, TextFit.Scale scale, Font font, TextFit.Line line, int left, int top, int bandDots) { int width = line.width() + 2 * GUARD; int height = line.above() + line.below() + 2 * GUARD; int rows = Math.max(1, bandDots / width); + int glyphs = 0; + int dots = 0; for(int first = 0; first < height; first += rows) { BufferedImage band = new BufferedImage(width, Math.min(rows, height - first), BufferedImage.TYPE_BYTE_GRAY); Graphics2D graphics = band.createGraphics(); - boolean clipped = false; try { graphics.setColor(Color.WHITE); @@ -125,21 +194,14 @@ final class TextRaster graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - long units = 0; - for(int index = line.from(); index < line.to() + (line.marked() ? 1 : 0); index++) - { - char character = index < line.to() ? drawing.text().charAt(index) : (char) TextFit.MARK; - Face.Glyph glyph = drawing.face().glyph(character); - if(glyph.ink()) - { - GlyphVector vector = font.createGlyphVector(Face.CONTEXT, new char[] {character}); - int pen = GUARD - line.left() + scale.round(units); - Rectangle pixels = vector.getGlyphPixelBounds(0, Face.CONTEXT, pen, GUARD + line.above()); - clipped |= !pixels.isEmpty() && (pixels.x < GUARD || pixels.y < GUARD || pixels.x + pixels.width > width - GUARD || pixels.y + pixels.height > height - GUARD); - graphics.drawGlyphVector(vector, pen, GUARD + line.above() - first); - } - units += glyph.advance(); - } + + ////////////////////////////////////////////////////////////////////////////////// + // ink that fell wholly beyond the guard is clipped by the strip and leaves no // + // dot to find; the bounds of its glyph say so, and they are the same for every // + // band, so those of the first are the count // + ////////////////////////////////////////////////////////////////////////////////// + int beyond = glyphs(drawing, scale, font, line, graphics, first); + glyphs = first == 0 ? beyond : glyphs; } finally { @@ -153,24 +215,54 @@ final class TextRaster if((grey[y * width + x] & 255) < drawing.threshold()) { int row = first + y; - if(x < GUARD || x >= width - GUARD || row < GUARD || row >= height - GUARD) + int dotX = left + x - GUARD; + int dotY = top + row - GUARD; + if(x < GUARD || x >= width - GUARD || row < GUARD || row >= height - GUARD || dotX < 0 || dotY < 0 || dotX >= reading.width() || dotY >= reading.height()) { - throw new IllegalStateException("TEXT_INK_OUTSIDE_MEASURE"); + dots++; + } + else + { + ink.set(dotY * reading.width() + dotX); } - dot(canvas, frame, reading, drawing, left + x - GUARD, top + row - GUARD); } } } - - ///////////////////////////////////////////////////////////////////////////////////// - // ink that fell wholly beyond the guard was clipped by the strip and left no dot // - // to find; the bounds of its glyph say so // - ///////////////////////////////////////////////////////////////////////////////////// - if(clipped) - { - throw new IllegalStateException("TEXT_INK_OUTSIDE_MEASURE"); - } } + return (new Stray(glyphs, dots)); + } + + + + /*************************************************************************** + ** The glyphs of one line at their pens on its strip: how many the runtime + ** places outside the line's measured box, drawing each on a band of the + ** strip whose first row is `first` when one is given. + ***************************************************************************/ + private static int glyphs(Drawing drawing, TextFit.Scale scale, Font font, TextFit.Line line, Graphics2D band, int first) + { + int width = line.width() + 2 * GUARD; + int height = line.above() + line.below() + 2 * GUARD; + int outside = 0; + long units = 0; + for(int index = line.from(); index < line.to() + (line.marked() ? 1 : 0); index++) + { + char character = index < line.to() ? drawing.text().charAt(index) : (char) TextFit.MARK; + Face.Glyph glyph = drawing.face().glyph(character); + if(glyph.ink()) + { + GlyphVector vector = font.createGlyphVector(Face.CONTEXT, new char[] {character}); + int pen = GUARD - line.left() + scale.round(units); + Rectangle pixels = vector.getGlyphPixelBounds(0, Face.CONTEXT, pen, GUARD + line.above()); + outside += !pixels.isEmpty() && (pixels.x < GUARD || pixels.y < GUARD || pixels.x + pixels.width > width - GUARD || pixels.y + pixels.height > height - GUARD) ? 1 : 0; + if(band != null) + { + band.drawGlyphVector(vector, pen, GUARD + line.above() - first); + } + } + units += glyph.advance(); + } + return (outside); } diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java index 1f1a19b..203aab1 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/SceneGoldenTest.java @@ -53,7 +53,9 @@ import static org.junit.jupiter.api.Assertions.fail; ** goldens were generated on Linux (Temurin 21.0.9, the CI image) and are the ** same bytes on Windows (Temurin 21.0.12), and they are compared exactly on ** both. A golden changes only with a reviewed change to the layout rules or - ** the runtime: what this build drew is left in `target/scene2-actual`. + ** the runtime: what this build drew is left in `target/scene2-actual`. The + ** runtimes, and the FreeType each ships, are recorded beside the goldens + ** (`scene2/README.md`). *******************************************************************************/ class SceneGoldenTest { diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java index 099fa24..4936a97 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/FaceTest.java @@ -175,6 +175,12 @@ class FaceTest ** with ink), and the furthest any character reaches past its advance on the ** left and right, above the baseline and below it. They are what a length ** is proven against, so they are recomputed here from every character. + ** + ** A character with no ink still moves the pen (a no-break space, an em + ** quad), so the greatest advance is taken over every character the face + ** draws, inked or not, and the widest inked character must have it: were a + ** font ever to carry a blank wider than its widest letter, a line of that + ** blank would be wider than the proof allows, and this fails. ***************************************************************************/ @Test void theBoundsOfAFaceAreThoseOfItsFontFile() @@ -183,6 +189,8 @@ class FaceTest { int widest = -1; int advance = 0; + int inked = 0; + int blanks = 0; int left = 0; int right = 0; int top = 0; @@ -193,14 +201,16 @@ class FaceTest Face.Glyph glyph = face.glyph(codePoint); assertTrue(glyph.advance() >= 0 && glyph.advance() <= 2 * Face.REFERENCE, "advance of " + codePoint); assertEquals(glyph.space(), codePoint == ' '); + advance = Math.max(advance, glyph.advance()); if(!glyph.ink()) { assertEquals(new Face.Glyph(glyph.advance(), 0, 0, 0, 0, false, codePoint == ' '), glyph); + blanks++; continue; } - if(glyph.advance() > advance) + if(glyph.advance() > inked) { - advance = glyph.advance(); + inked = glyph.advance(); widest = codePoint; } left = Math.max(left, -glyph.left()); @@ -209,6 +219,8 @@ class FaceTest bottom = Math.max(bottom, glyph.bottom()); } assertTrue(drawn.size() > 800, face.scene() + " draws " + drawn.size() + " characters"); + assertTrue(blanks >= 2 && face.draws(0xA0) && !face.glyph(0xA0).ink() && face.glyph(0xA0).advance() > 0, face.scene() + " draws " + blanks + " characters with no ink, the no-break space among them"); + assertEquals(advance, inked, face.scene() + ": no character without ink advances further than the widest with ink"); assertEquals(new Face.Glyph(advance, -left, advance + right, top, bottom, true, false), face.worst(), face.scene()); assertEquals(widest, face.widest(), face.scene()); assertEquals(face.glyph(face.widest()).advance(), face.worst().advance()); @@ -262,8 +274,10 @@ class FaceTest ** The rasteriser keeps every glyph inside the box layout measures for it: ** the outline at the reference size, scaled exactly, and `TextFit.SLOP` ** dots. Held for every character of every face over the sizes and - ** resolutions labels use. (That the ink itself stays inside is held where - ** text is drawn: `TextRasterTest`.) + ** resolutions labels use, and at the ends of what the renderer accepts: + ** 1 pt and 2 pt, where a glyph is a few dots, and 300 pt and 1000 pt, + ** where it is drawn from its outline. (That the ink itself stays inside is + ** held where text is drawn: `TextRasterTest`.) ***************************************************************************/ @Test void everyGlyphIsRasterisedInsideItsMeasuredBox() @@ -273,7 +287,7 @@ class FaceTest List drawn = drawn(face); for(int dpi : Scene2.RESOLUTIONS) { - for(int milliPoints : List.of(5000, 6250, 7000, 8000, 9000, 10_500, 12_000, 18_000, 36_000, 72_000)) + for(int milliPoints : List.of(1000, 2000, 5000, 6250, 7000, 8000, 9000, 10_500, 12_000, 18_000, 36_000, 72_000, 300_000, 1_000_000)) { TextFit.Scale scale = new TextFit.Scale(milliPoints, dpi); Font font = face.font(scale.size()); diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java index 794d41c..2ec54e7 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextElementTest.java @@ -22,6 +22,8 @@ package com.kingsrook.qbits.renderer.scene2.text; import java.io.InputStream; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -29,10 +31,13 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.function.IntFunction; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.kingsrook.qbits.renderer.RendererMain; import com.kingsrook.qbits.renderer.Wire; +import com.kingsrook.qbits.renderer.scene2.Diagnostics; +import com.kingsrook.qbits.renderer.scene2.Frame; import com.kingsrook.qbits.renderer.scene2.Refusal; import com.kingsrook.qbits.renderer.scene2.SceneFixture; import org.junit.jupiter.api.Test; @@ -130,6 +135,20 @@ class TextElementTest + /*************************************************************************** + ** The errors of a request that is refused while its findings are + ** collected, so that every element is tried. + ***************************************************************************/ + @SuppressWarnings("unchecked") + private static List> errors(ObjectNode request) throws Exception + { + Map answer = RendererMain.process(request.put("diagnostics", "COLLECT")); + assertEquals("REFUSED", answer.get("outcome")); + return (((List>) answer.get("diagnostics")).stream().filter(finding -> "ERROR".equals(finding.get("severity"))).toList()); + } + + + /*************************************************************************** ** The page a request prints. ***************************************************************************/ @@ -257,7 +276,9 @@ class TextElementTest /*************************************************************************** ** A property that is not what the schema says is `SCENE_INVALID` at that ** property, in the element, in the defaults or in the override that states - ** it; whatever is wrong inside `fit` is reported at `fit`. + ** it. A member of `fit` that is wrong is reported at that member; a member + ** `fit` does not have is reported at `fit`, since its name is not one the + ** schema declares. ***************************************************************************/ @Test void aPropertyTheSchemaDoesNotAllowIsRefusedAtThatProperty() throws Exception @@ -268,9 +289,11 @@ class TextElementTest Map.entry("lineHeight", List.of("'lineHeight':'1.2'", "'lineHeight':0.499", "'lineHeight':5.001", "'lineHeight':1.2345", "'lineHeight':true", "'lineHeight':1e400", "'lineHeight':-1", "'lineHeight':99999999999999999999")), Map.entry("threshold", List.of("'threshold':0", "'threshold':255", "'threshold':127.5", "'threshold':'128'", "'threshold':4294967424")), Map.entry("maxLength", List.of("'maxLength':0", "'maxLength':1025", "'maxLength':'48'", "'maxLength':4294967297", "'maxLength':null")), - Map.entry("fit", List.of("'fit':[]", "'fit':'shrink'", "'fit':{'maxLines':0}", "'fit':{'maxLines':65}", "'fit':{'maxLines':'2'}", "'fit':{'maxLines':1.5}", "'fit':{'shrinkTo':'small'}", "'fit':{'shrinkTo':'50%'}", - "'fit':{'shrinkTo':'6dot'}", "'fit':{'shrinkTo':'0.999pt'}", "'fit':{'shrinkTo':'9.001pt'}", "'fit':{'shrinkTo':7}", "'fit':{'overflow':'clip'}", "'fit':{'overflow':true}", "'fit':{'lines':2}", - "'fit':{'maxLines':2,'Overflow':'refuse'}")), + Map.entry("fit", List.of("'fit':[]", "'fit':'shrink'", "'fit':null", "'fit':{'lines':2}", "'fit':{'maxLines':2,'Overflow':'refuse'}", "'fit':{'maxLines':0,'lines':2}")), + Map.entry("fit/maxLines", List.of("'fit':{'maxLines':0}", "'fit':{'maxLines':65}", "'fit':{'maxLines':'2'}", "'fit':{'maxLines':1.5}", "'fit':{'maxLines':null}", "'fit':{'maxLines':0,'shrinkTo':'small','overflow':'clip'}")), + Map.entry("fit/shrinkTo", List.of("'fit':{'shrinkTo':'small'}", "'fit':{'shrinkTo':'50%'}", "'fit':{'shrinkTo':'6dot'}", "'fit':{'shrinkTo':'0.999pt'}", "'fit':{'shrinkTo':'9.001pt'}", "'fit':{'shrinkTo':7}", + "'fit':{'maxLines':2,'shrinkTo':'small','overflow':'clip'}")), + Map.entry("fit/overflow", List.of("'fit':{'overflow':'clip'}", "'fit':{'overflow':true}", "'fit':{'overflow':'Truncate'}", "'fit':{'maxLines':2,'shrinkTo':'6pt','overflow':null}")), Map.entry("valuePath", List.of("'valuePath':12", "'valuePath':'record/name'", "'valuePath':''", "'valuePath':'/" + "a".repeat(256) + "'")), Map.entry("reverse", List.of("'reverse':'yes'", "'reverse':1")), Map.entry("rotation", List.of("'rotation':45", "'rotation':'90'"))); @@ -289,6 +312,19 @@ class TextElementTest } assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", text("'value':'" + "A".repeat(1024) + "','fit':{'maxLines':64,'overflow':'truncate'}"))).get("outcome"), "1024 characters is the most a value may have"); + //////////////////////////////////////////////////////////////////////////////////////////// + // a member of `fit` is reported where `fit` is stated: here in an override, for the // + // resolution it is for and not for another // + //////////////////////////////////////////////////////////////////////////////////////////// + for(String member : List.of("'maxLines':0", "'shrinkTo':'12pt'", "'overflow':'clip'")) + { + String override = json(HEAD + "{'id':'t','type':'text','value':'A','fit':{'maxLines':2}}],'overrides':[{'when':{'dpi':[600]},'set':{'t':{'fit':{" + member + "}}}}]}"); + String name = member.substring(1, member.indexOf('\'', 1)); + assertEquals(invalid("/overrides/0/set/t/fit/" + name), refused(SceneFixture.request("VALIDATE", override)), member); + } + String unknown = json(HEAD + "{'id':'t','type':'text','value':'A'}],'overrides':[{'when':{'dpi':[203]},'set':{'t':{'fit':{'lines':2}}}}]}"); + assertEquals(invalid("/overrides/0/set/t/fit"), refused(SceneFixture.request("VALIDATE", unknown))); + //////////////////////////////////////////////////////////////////////////////////////////// // a face and a size are required, in the element or in the defaults; a wrong default is // // reported where the scene states it, for the element that takes it, and a default the // @@ -328,8 +364,9 @@ class TextElementTest /*************************************************************************** ** A bound value is read from the record when rendering: text as it is, a - ** number or a truth value as JSON writes it. Anything else, or nothing, is - ** `VALUE_MISSING`. Validation reads no record. + ** truth value as its word, and a number in plain decimal digits: no + ** exponent, and no fraction that is only zeros. Anything else, or nothing, + ** is `VALUE_MISSING`. Validation reads no record. ***************************************************************************/ @Test void aBoundValueIsReadFromTheRecordOnlyWhenRendering() throws Exception @@ -345,6 +382,67 @@ class TextElementTest } Map missing = Map.of("code", "VALUE_MISSING", "severity", "ERROR", "element", "t", "box", List.of(0, 0, 479, 47)); assertEquals(missing, refused(SceneFixture.request("RENDER", source))); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a number is printed as its digits, however the record wrote it: the left of each pair // + // is the JSON of the record and the right is what is printed // + //////////////////////////////////////////////////////////////////////////////////////////// + String roomy = text("'valuePath':'/record/name','font':'qqq-mono','size':'6pt','fit':{'maxLines':4},'width':'90mm','height':'12mm'"); + Map numbers = new LinkedHashMap<>(); + numbers.put("1.0E10", "10000000000"); + numbers.put("1e10", "10000000000"); + numbers.put("2.50", "2.5"); + numbers.put("12.0", "12"); + numbers.put("-0.0", "0"); + numbers.put("0", "0"); + numbers.put("-17", "-17"); + numbers.put("1E-7", "0.0000001"); + numbers.put("0.1", "0.1"); + numbers.put("123456.789", "123456.789"); + numbers.put("-2.5e3", "-2500"); + numbers.put("1.7976931348623157E308", "17976931348623157" + "0".repeat(292)); + numbers.put("123456789012345678901234567890", "123456789012345678901234567890"); + numbers.forEach((written, printed) -> + { + try + { + ObjectNode request = SceneFixture.request("RENDER", roomy); + ((ObjectNode) request.get("context")).putObject("record").set("name", Wire.JSON.readTree(written)); + assertTrue(Arrays.deepEquals(page(SceneFixture.request("RENDER", text("'value':'" + printed + "','font':'qqq-mono','size':'6pt','fit':{'maxLines':4},'width':'90mm','height':'12mm'"))), page(request)), written + " prints " + printed); + } + catch(Exception failed) + { + throw new IllegalStateException(written, failed); + } + }); + List records = new ArrayList<>(); + for(int index = 0; index < 5; index++) + { + records.add(SceneFixture.request("RENDER", roomy)); + } + ((ObjectNode) records.get(0).get("context")).putObject("record").put("name", new BigDecimal("2.500")); + ((ObjectNode) records.get(1).get("context")).putObject("record").put("name", 2.5f); + ((ObjectNode) records.get(2).get("context")).putObject("record").put("name", new BigInteger("25").multiply(BigInteger.TEN.pow(40))); + ((ObjectNode) records.get(3).get("context")).putObject("record").put("name", 25L); + ((ObjectNode) records.get(4).get("context")).putObject("record").put("name", (short) 25); + List shown = List.of("2.5", "2.5", "25" + "0".repeat(40), "25", "25"); + for(int index = 0; index < records.size(); index++) + { + assertTrue(Arrays.deepEquals(page(SceneFixture.request("RENDER", text("'value':'" + shown.get(index) + "','font':'qqq-mono','size':'6pt','fit':{'maxLines':4},'width':'90mm','height':'12mm'"))), page(records.get(index))), "record " + index); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // a number that is not finite has no digits: it is missing, as an object or a list is // + //////////////////////////////////////////////////////////////////////////////////////////// + for(double infinite : List.of(Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY)) + { + ObjectNode request = SceneFixture.request("RENDER", source); + ((ObjectNode) request.get("context")).putObject("record").put("name", infinite); + assertEquals(missing, refused(request), String.valueOf(infinite)); + } + ObjectNode huge = SceneFixture.request("RENDER", source); + ((ObjectNode) huge.get("context")).putObject("record").set("name", Wire.JSON.readTree("1e400")); + assertEquals(missing, refused(huge), "a number too large to be a number"); for(String other : List.of("null", "{\"first\":\"A\"}", "[\"A\"]")) { ObjectNode request = SceneFixture.request("RENDER", source); @@ -421,6 +519,71 @@ class TextElementTest + /*************************************************************************** + ** The proof never cuts: a value that is cut does not fit. An element that + ** asks for cutting and states a length its box cannot hold whole is still a + ** valid scene, since cutting is what its author chose, but it carries a + ** warning at every validation that says how many characters are proven to + ** fit whole of the length stated. A length the box does hold whole is + ** proven as for any other element and carries no warning. + ***************************************************************************/ + @Test + void theProofOfALengthNeverCutsAndACuttingElementIsWarnedHowMuchIsProven() throws Exception + { + //////////////////////////////////////////////////////////////////////////////////////////// + // the bold monospace at 9 pt, shrinking to 6.3 pt, in a box 12 mm wide: 95 dots, which // + // hold seven of the face's worst character at the floor // + //////////////////////////////////////////////////////////////////////////////////////////// + String bound = "'valuePath':'/record/name','font':'qqq-mono-bold'"; + String element = bound + ",'width':'12mm','height':'6mm'"; + Map refusal = refused(SceneFixture.request("VALIDATE", text(element + ",'maxLength':40"))); + assertEquals("TEXT_DOES_NOT_FIT", refusal.get("code")); + + List> standing = findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':40,'fit':{'overflow':'truncate'}"))); + assertEquals(1, standing.size(), "one warning and nothing else: " + standing); + Map warning = standing.get(0); + assertEquals(List.of("FIT_NOT_PROVEN", "WARNING", "t", List.of(0, 0, 95, 47)), List.of(warning.get("code"), warning.get("severity"), warning.get("element"), warning.get("box"))); + assertEquals(Map.of("characters", 40), warning.get("limit")); + int proven = (int) ((Map) warning.get("measured")).get("provenCharacters"); + assertEquals(Map.of("provenCharacters", proven), warning.get("measured")); + assertEquals(7, proven, "the longest length proven to fit whole"); + assertEquals(standing, findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':40,'fit':{'overflow':'truncate'}"))), "it stands: the same at every validation"); + + //////////////////////////////////////////////////////////////////////////////////////////// + // the number is the truth: that length is proven with or without cutting, and one more // + // is not. The author's remedy is to state the length that is proven // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':" + proven + ",'fit':{'overflow':'truncate'}")))); + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':" + proven)))); + assertEquals(Map.of("provenCharacters", proven), findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':" + (proven + 1) + ",'fit':{'overflow':'truncate'}"))).get(0).get("measured")); + assertEquals("TEXT_DOES_NOT_FIT", refused(SceneFixture.request("VALIDATE", text(element + ",'maxLength':" + (proven + 1)))).get("code")); + + //////////////////////////////////////////////////////////////////////////////////////////// + // and what it says happens: a value of the proven length prints whole, a longer one is // + // cut, and the warning is the validation's, not the print's // + //////////////////////////////////////////////////////////////////////////////////////////// + String cutting = text(element + ",'maxLength':40,'fit':{'overflow':'truncate'}"); + assertEquals(List.of("TEXT_SHRUNK"), findings(bound("RENDER", cutting, "W".repeat(proven))).stream().map(finding -> finding.get("code")).toList()); + List> cut = findings(bound("RENDER", cutting, "W".repeat(40))); + assertEquals(List.of("TEXT_SHRUNK", "TEXT_TRUNCATED"), cut.stream().map(finding -> finding.get("code")).toList()); + assertEquals(40, ((Map) cut.get(1).get("measured")).get("characters")); + assertTrue((int) ((Map) cut.get(1).get("measured")).get("shownCharacters") < 40, "cut: " + cut.get(1)); + + //////////////////////////////////////////////////////////////////////////////////////////// + // more lines prove more; a box that holds no character at all proves none; and the type // + // is judged at the floor, where a cut value is printed: 6.3 pt bold is 12 dots high and // + // passes, 5 pt is 9 and is warned about // + //////////////////////////////////////////////////////////////////////////////////////////// + assertEquals(Map.of("provenCharacters", 2 * proven), findings(SceneFixture.request("VALIDATE", text(bound + ",'width':'12mm','height':'12mm','maxLength':40,'fit':{'overflow':'truncate','maxLines':2}"))).get(0).get("measured")); + assertEquals(Map.of("provenCharacters", 0), findings(SceneFixture.request("VALIDATE", text(bound + ",'width':'1mm','height':'6mm','maxLength':2,'fit':{'overflow':'truncate'}"))).get(0).get("measured")); + assertEquals(Map.of("provenCharacters", 0), findings(SceneFixture.request("VALIDATE", text(bound + ",'width':'1mm','height':'6mm','maxLength':1,'fit':{'overflow':'truncate'}"))).get(0).get("measured")); + List> small = findings(SceneFixture.request("VALIDATE", text(element + ",'maxLength':40,'fit':{'overflow':'truncate','shrinkTo':'5pt'}"))); + assertEquals(List.of("FIT_NOT_PROVEN", "TEXT_SMALL_FOR_DPI"), small.stream().map(finding -> finding.get("code")).toList()); + assertEquals(Map.of("capHeightDots", 10, "sizeCentipoints", 500), small.get(1).get("measured")); + } + + + /*************************************************************************** ** A character the face cannot draw as one glyph is refused with a count; the ** value is drawn whole or not at all. @@ -552,13 +715,30 @@ class TextElementTest assertEquals(List.of(), findings(SceneFixture.request("RENDER", small).put("targetDpi", 600)), "the same type is 31 dots high at 600 dpi"); //////////////////////////////////////////////////////////////////////////////////////////// - // a bound element is judged at its stated size when validated, and at the size it was // - // shrunk to when rendered // + // a bound element whose length is not stated is judged at its stated size when // + // validated, since nothing says how far it will shrink, and at the size it was shrunk // + // to when rendered // //////////////////////////////////////////////////////////////////////////////////////////// String shrinking = text("'valuePath':'/record/name','font':'qqq-sans-bold','size':'8pt','width':'28mm','height':'5mm','fit':{'shrinkTo':'5pt'}"); assertEquals(List.of("FIT_NOT_PROVEN"), findings(SceneFixture.request("VALIDATE", shrinking)).stream().map(finding -> finding.get("code")).toList()); assertEquals(List.of("FIT_NOT_PROVEN", "TEXT_SHRUNK", "TEXT_SMALL_FOR_DPI"), findings(bound("RENDER", shrinking, "L240611A-RETURNED-000123")).stream().map(finding -> finding.get("code")).toList()); + //////////////////////////////////////////////////////////////////////////////////////////// + // with its length stated it is judged, when validated, at the size the proof shrank to, // + // which is the smallest any value is printed at: 8 pt bold is 15 dots high and passes, // + // but nine of the widest character are proven only at 5.75 pt, 11 dots. A value that // + // needs no shrinking prints at 8 pt with no warning; the worst value is shrunk, and to // + // no less than was proven // + //////////////////////////////////////////////////////////////////////////////////////////// + String stated = text("'valuePath':'/record/name','font':'qqq-sans-bold','size':'8pt','width':'28mm','height':'5mm','fit':{'shrinkTo':'5pt'},'maxLength':9"); + List> judged = findings(SceneFixture.request("VALIDATE", stated)); + assertEquals(List.of("TEXT_SMALL_FOR_DPI"), judged.stream().map(finding -> finding.get("code")).toList()); + assertEquals(Map.of("capHeightDots", 11, "sizeCentipoints", 575), judged.get(0).get("measured")); + assertEquals(List.of(), findings(bound("RENDER", stated, "L240611A"))); + List> worst = findings(bound("RENDER", stated, "\u2030".repeat(9)), "TEXT_SHRUNK"); // per mille + assertTrue((int) ((Map) worst.get(0).get("measured")).get("sizeCentipoints") >= 575, "no value is printed smaller than the proof: " + worst); + assertEquals(List.of(), findings(SceneFixture.request("VALIDATE", text("'valuePath':'/record/name','font':'qqq-sans-bold','size':'8pt','width':'28mm','height':'5mm','fit':{'shrinkTo':'5pt'},'maxLength':6"))), "six fit at 8 pt"); + //////////////////////////////////////////////////////////////////////////////////////////// // the override: bold and a heavier threshold at 203 dpi only // //////////////////////////////////////////////////////////////////////////////////////////// @@ -717,4 +897,149 @@ class TextElementTest } assertThrows(Refusal.class, () -> RendererMain.process(bound("RENDER", text(elements.get(0)), marker))); } + + + /*************************************************************************** + ** A scene of `count` text elements `t0`, `t1` and so on, each with these + ** properties, and with the value its index gives when one is given. + ***************************************************************************/ + private static String many(int count, String properties, IntFunction value) throws Exception + { + ObjectNode scene = (ObjectNode) Wire.JSON.readTree(scene("")); + ArrayNode elements = (ArrayNode) scene.get("elements"); + for(int index = 0; index < count; index++) + { + ObjectNode element = ((ObjectNode) Wire.JSON.readTree(json("{'type':'text'," + properties + "}"))).put("id", "t" + index); + elements.add(value == null ? element : element.put("value", value.apply(index))); + } + return (Wire.JSON.writeValueAsString(scene)); + } + + + + /*************************************************************************** + ** The scene an independent review measured: text of 1024 characters, type + ** of 1000 pt that may shrink to 1 pt, at 600 dpi, in a box it fits at no + ** size. Each fit took 140 to 250 ms, twice an element, and a scene may hold + ** a thousand elements: minutes, ended by the worker's 15 s of processor + ** with no refusal named. A thousand of them are now each refused by name, + ** validated (the proof of 1024 characters) and rendered (a value of 1024 + ** characters), inside the work one scene may take: so in a known number of + ** steps on any machine. The time is printed, and held inside the worker's + ** limit. + ***************************************************************************/ + @Test + void aThousandOfTheWorstTextsAreRefusedByNameInsideTheWorkOfOneScene() throws Exception + { + String worst = "'valuePath':'/record/name','maxLength':1024,'font':'qqq-sans','size':'1000pt','width':'1mm','height':'1mm'"; + String refusing = many(1000, worst + ",'fit':{'shrinkTo':'1pt','maxLines':64}", null); + for(String operation : List.of("VALIDATE", "RENDER")) + { + long start = System.nanoTime(); + List> errors = errors(bound(operation, refusing, "W".repeat(1024)).put("targetDpi", 600)); + long milliseconds = (System.nanoTime() - start) / 1_000_000; + assertEquals(1000, errors.size()); + for(Map diagnostic : errors) + { + assertEquals("TEXT_DOES_NOT_FIT", diagnostic.get("code"), "each is refused for what it is, none for the work: " + diagnostic); + assertEquals(List.of(100, 1024), List.of(((Map) diagnostic.get("measured")).get("sizeCentipoints"), ((Map) diagnostic.get("measured")).get("characters"))); + } + System.out.println("1000 text elements of 1024 characters, 1000 pt to 1 pt at 600 dpi: " + operation + " refused them in " + milliseconds + " ms"); + assertTrue(milliseconds < 15_000, "inside the processor time a worker is allowed: " + milliseconds + " ms"); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // cut instead of refused, the same thousand are within the work too: validated, each is // + // proven not to fit and then how much of it does, and each is warned; rendered, each is // + // cut // + //////////////////////////////////////////////////////////////////////////////////////////// + String cutting = many(1000, worst + ",'fit':{'shrinkTo':'1pt','maxLines':64,'overflow':'truncate'}", null); + long start = System.nanoTime(); + List> warned = findings(SceneFixture.request("VALIDATE", cutting).put("targetDpi", 600), "FIT_NOT_PROVEN"); + List> cut = findings(bound("RENDER", cutting, "W".repeat(1024)).put("targetDpi", 600), "TEXT_TRUNCATED"); + long milliseconds = (System.nanoTime() - start) / 1_000_000; + assertEquals(1000, warned.size()); + assertEquals(1000, cut.size()); + assertEquals(Map.of("provenCharacters", 1), warned.get(999).get("measured")); + assertEquals(Map.of("characters", 1024), warned.get(999).get("limit")); + System.out.println("1000 text elements of 1024 characters, 1000 pt to 1 pt at 600 dpi, cut: validated and rendered in " + milliseconds + " ms"); + assertTrue(milliseconds < 15_000, "inside the processor time a worker is allowed: " + milliseconds + " ms"); + } + + + + /*************************************************************************** + ** The text of one scene may take a stated amount of work. A scene that + ** passes it is refused at the element that did, by name and with the count + ** against the allowance, and every text after it is refused the same way + ** without being fitted. The count is the same whether the scene is + ** validated or rendered. Here the work is glyphs: each element draws eight + ** hundred different characters at a size of its own, each of which the + ** runtime must rasterise once. + ***************************************************************************/ + @Test + void aSceneWhoseTextPassesItsWorkIsRefusedByName() throws Exception + { + StringBuilder characters = new StringBuilder(); + FaceTest.drawn(Face.MONO_BOLD).stream().filter(codePoint -> Face.MONO_BOLD.glyph(codePoint).ink()).limit(800).forEach(characters::appendCodePoint); + String properties = "'font':'qqq-mono-bold','height':'6mm','fit':{'maxLines':8}"; + ObjectNode scene = (ObjectNode) Wire.JSON.readTree(many(30, properties, index -> characters.toString())); + for(int index = 0; index < 30; index++) + { + ((ObjectNode) scene.get("elements").get(index)).put("size", "2." + String.format(Locale.ROOT, "%03d", index) + "pt"); + } + String source = Wire.JSON.writeValueAsString(scene); + + Map refusal = refused(SceneFixture.request("VALIDATE", source)); + int steps = (int) ((Map) refusal.get("measured")).get("textWorkSteps"); + assertEquals(Map.of("code", "SCENE_INVALID", "severity", "ERROR", "element", "t19", "pointer", "/elements/19", "box", List.of(0, 0, 764, 47), "measured", Map.of("textWorkSteps", steps), "limit", Map.of("textWorkSteps", 64_000_000)), refusal); + assertEquals(TextElement.SCENE_WORK_STEPS, 64_000_000); + assertTrue(steps > 64_000_000 && steps < 64_000_000 + 800 * TextRaster.GLYPH_STEPS + 800 * TextRaster.PEN_STEPS + 1, "passed by no more than the glyphs of one element: " + steps); + assertEquals(refusal, refused(SceneFixture.request("RENDER", source)), "rendering counts what validation counts"); + + List> collected = errors(SceneFixture.request("VALIDATE", source)); + assertEquals(11, collected.size(), "the element that passed the work and every text after it: " + collected); + for(int index = 0; index < collected.size(); index++) + { + Map diagnostic = collected.get(index); + assertEquals(List.of("SCENE_INVALID", "t" + (19 + index), "/elements/" + (19 + index)), List.of(diagnostic.get("code"), diagnostic.get("element"), diagnostic.get("pointer"))); + assertTrue((int) ((Map) diagnostic.get("measured")).get("textWorkSteps") >= steps); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // the same glyphs at one size are rasterised once, however many elements draw them: all // + // thirty are within the work // + //////////////////////////////////////////////////////////////////////////////////////////// + String same = many(30, properties + ",'size':'2pt'", index -> characters.toString()); + assertEquals("OK", RendererMain.process(SceneFixture.request("VALIDATE", same)).get("outcome")); + assertEquals("OK", RendererMain.process(SceneFixture.request("RENDER", same)).get("outcome")); + } + + + + /*************************************************************************** + ** A text whose ink the rasteriser puts outside what was measured is refused + ** as the one element, by name, with how many glyphs and dots strayed and at + ** what size; it is not an exception that ends the whole render. No bundled + ** face does this at any size from 1 pt to 1000 pt (`FaceTest`, + ** `TextRasterTest`), so the refusal is made here from the counts + ** `TextRaster` gives, which `TextRasterTest` forces. + ***************************************************************************/ + @Test + void inkOutsideTheMeasureIsARefusalOfTheOneElement() + { + Diagnostics diagnostics = new Diagnostics(true); + diagnostics.declare("t", "/elements/0"); + Frame frame = new Frame(4, 6, 200, 40); + TextElement.measured(diagnostics, "t", frame, new TextRaster.Stray(0, 0), 9000); + for(TextRaster.Stray stray : List.of(new TextRaster.Stray(2, 0), new TextRaster.Stray(0, 31), new TextRaster.Stray(1, 7))) + { + Refusal refusal = assertThrows(Refusal.class, () -> TextElement.measured(diagnostics, "t", frame, stray, 9250)); + assertEquals(Map.of("code", "TEXT_DOES_NOT_FIT", "severity", "ERROR", "element", "t", "box", List.of(4, 6, 200, 40), + "measured", Map.of("glyphsOutsideMeasure", stray.glyphs(), "dotsOutsideMeasure", stray.dots(), "sizeCentipoints", 925), "limit", Map.of("glyphsOutsideMeasure", 0, "dotsOutsideMeasure", 0)), refusal.diagnostic().wire()); + diagnostics.keep(refusal); + } + assertTrue(diagnostics.refused()); + assertEquals(3, diagnostics.findings().size()); + } } diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java index 9da8db4..a91f375 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextFitTest.java @@ -30,6 +30,7 @@ import com.kingsrook.qbits.renderer.scene2.Scene2; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -158,6 +159,91 @@ class TextFitTest + /*************************************************************************** + ** The search `fit` must agree with, made in full: every quarter-point step + ** from the nominal size down to the floor, each laid out between words and + ** then at any character, the first that fits taken. This is the search the + ** fit was first written as. It shares with `fit` only the layout at one + ** size (`TextFit.at`), and none of what `fit` uses to skip sizes. + ***************************************************************************/ + static TextFit.Block linear(TextFit.Request request, Face.Glyph[] glyphs, Face.Glyph mark, TextFit.Work work) + { + int count = glyphs.length; + while(count > 0 && glyphs[count - 1].space()) + { + count--; + } + int size = request.nominal(); + while(true) + { + TextFit.Block block = TextFit.at(request, TextFit.Leading.of(request), size, glyphs, count, mark, work); + if(block.fits() || size == request.floor()) + { + return (block); + } + size = Math.max(request.floor(), size - TextFit.STEP_MILLIPOINTS); + } + } + + + + /*************************************************************************** + ** A generated case over everything a scene may state: type from 1 pt to + ** 1000 pt with a floor anywhere under it, boxes from a few dots to a large + ** label, up to 64 lines, any line height, and texts of up to 160 + ** characters, some without a space, some of the widest and + ** furthest-reaching characters, some led or followed by spaces. + ***************************************************************************/ + static Case wide(Random random) + { + Face face = Face.all().get(random.nextInt(Face.all().size())); + int dpi = Scene2.RESOLUTIONS.get(random.nextInt(3)); + int nominal = switch(random.nextInt(4)) + { + case 0 -> 1000 + random.nextInt(9001); + case 1 -> 5000 + random.nextInt(30_001); + case 2 -> 20_000 + random.nextInt(280_001); + default -> 1000 + random.nextInt(999_001); + }; + int floor = switch(random.nextInt(4)) + { + case 0 -> 1000; + case 1 -> Math.max(1000, nominal / 10); + case 2 -> Math.max(1000, nominal - random.nextInt(4000)); + default -> 1000 + random.nextInt(nominal - 999); + }; + Integer lineHeight = random.nextInt(3) == 0 ? Integer.valueOf(500 + random.nextInt(4501)) : null; + int width = switch(random.nextInt(3)) + { + case 0 -> 1 + random.nextInt(60); + case 1 -> 20 + random.nextInt(700); + default -> 200 + random.nextInt(6000); + }; + int height = switch(random.nextInt(3)) + { + case 0 -> 1 + random.nextInt(40); + case 1 -> 8 + random.nextInt(300); + default -> 100 + random.nextInt(4000); + }; + String alphabet = switch(random.nextInt(4)) + { + case 0 -> "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-()/."; + case 1 -> "abcdefghijklmnopqrstuvwxyzWMfjgyÅé‰ "; // A ring, e acute, per mille + case 2 -> "il1.,' WM@‰⁄ǺĢ "; // per mille, fraction slash, A ring acute, G cedilla: the widest and furthest-reaching + default -> new String(Character.toChars(face.widest())) + "j "; // the widest, a letter that starts left of the pen, a no-break space + }; + StringBuilder text = new StringBuilder(random.nextInt(5) == 0 ? " " : ""); + int length = random.nextInt(4) == 0 ? random.nextInt(160) : random.nextInt(40); + int spaces = random.nextInt(3); + for(int index = 0; index < length; index++) + { + text.append(spaces > 0 && random.nextInt(spaces == 1 ? 6 : 2) == 0 ? ' ' : alphabet.charAt(random.nextInt(alphabet.length()))); + } + return (new Case(new TextFit.Request(face, width, height, dpi, nominal, floor, lineHeight, 1 + random.nextInt(random.nextInt(3) == 0 ? 64 : 4), random.nextInt(3) == 0), text.toString())); + } + + + /*************************************************************************** ** Dots are thousandths of the em times the size times the resolution over ** 72 000 000, rounded down, up or to the nearest: checked against exact @@ -597,4 +683,189 @@ class TextFitTest } } } + + + /*************************************************************************** + ** Property: the answer is exactly the one the search of every size gives: + ** the same size, the same lines, the same numbers, fitted, refused or cut. + ** Held over the cases labels use and over everything a scene may state, + ** and for a proof of the face's worst character as for a text. The search + ** of every size visits far more characters than `fit` does. + ***************************************************************************/ + @Test + void theAnswerIsExactlyThatOfTheSearchOfEverySize() + { + int fitted = 0; + int shrunk = 0; + int refused = 0; + int cut = 0; + int deep = 0; + long spent = 0; + long searched = 0; + for(long seed : SEEDS) + { + Random random = new Random(seed); + for(int index = 0; index < 2 * CASES; index++) + { + Case generated = index < CASES ? generate(random) : wide(random); + TextFit.Request request = generated.request(); + Face face = request.face(); + Face.Glyph[] glyphs = face.glyphs(generated.text()); + if(index % 7 == 0) + { + glyphs = new Face.Glyph[1 + random.nextInt(60)]; + Arrays.fill(glyphs, face.worst()); + } + TextFit.Work work = new TextFit.Work(Long.MAX_VALUE); + TextFit.Work every = new TextFit.Work(Long.MAX_VALUE); + TextFit.Block block = TextFit.fit(request, glyphs, face.glyph(TextFit.MARK), work); + TextFit.Block expected = linear(request, glyphs, face.glyph(TextFit.MARK), every); + int length = glyphs.length; + assertEquals(expected, block, () -> "seed " + seed + " case " + request + " for " + length + " characters"); + assertEquals(block, TextFit.fit(request, glyphs, face.glyph(TextFit.MARK)), "the same with no allowance stated"); + spent += work.spent(); + searched += every.spent(); + fitted += block.fits() && !block.truncated() ? 1 : 0; + shrunk += block.fits() && !block.truncated() && block.milliPoints() < request.nominal() ? 1 : 0; + deep += block.fits() && request.nominal() - block.milliPoints() > 40 * TextFit.STEP_MILLIPOINTS ? 1 : 0; + refused += block.fits() ? 0 : 1; + cut += block.truncated() ? 1 : 0; + } + } + assertTrue(fitted > 900 && shrunk > 300 && deep > 100 && refused > 500 && cut > 150, "the cases must reach every outcome: " + fitted + " fitted, " + shrunk + " shrunk, " + deep + " by more than 10 pt, " + refused + " refused, " + cut + " cut"); + assertTrue(searched > 20L * spent, "the search of every size visited " + searched + " characters, the fit " + spent); + System.out.println("3600 fits: " + spent + " characters visited, where the search of every size visits " + searched); + } + + + + /*************************************************************************** + ** The case an independent review measured at 140 to 250 ms a fit: 1024 + ** characters at 600 dpi, type of 1000 pt that may shrink to 1 pt (four + ** thousand sizes), in boxes it fits at no size, at a small size, or only + ** cut. The answer is the one the search of every size gives, for under + ** forty times the characters of the text where that search visits more + ** than ten thousand times them. The time is printed; the count is held, + ** because it is the same on every machine. + ***************************************************************************/ + @Test + void theWorstCaseOfTheShrinkSearchIsHeldToAStatedWork() + { + String wide = "W".repeat(1024); + String words = "The quick brown fox jumps over the lazy dog 0123456789 ".repeat(19).substring(0, 1024); + long most = 0; + long least = Long.MAX_VALUE; + long nanoseconds = 0; + long linearNanoseconds = 0; + int fits = 0; + for(int[] box : new int[][] {{20, 20, 64}, {20, 20, 1}, {40, 40, 64}, {200, 30, 1}, {600, 300, 64}, {2400, 1200, 64}, {2400, 1200, 1}, {9000, 30_000, 64}, {9000, 30_000, 2}}) + { + for(String text : List.of(wide, words)) + { + for(boolean truncate : List.of(false, true)) + { + TextFit.Request request = new TextFit.Request(Face.SANS, box[0], box[1], 600, 1_000_000, 1000, null, box[2], truncate); + Face.Glyph[] glyphs = Face.SANS.glyphs(text); + TextFit.Work work = new TextFit.Work(Long.MAX_VALUE); + TextFit.Work every = new TextFit.Work(Long.MAX_VALUE); + long start = System.nanoTime(); + TextFit.Block block = TextFit.fit(request, glyphs, Face.SANS.glyph(TextFit.MARK), work); + nanoseconds += System.nanoTime() - start; + start = System.nanoTime(); + assertEquals(linear(request, glyphs, Face.SANS.glyph(TextFit.MARK), every), block, () -> "in " + request); + linearNanoseconds += System.nanoTime() - start; + assertTrue(work.spent() <= 40L * 1024, "in " + request + ": " + work.spent() + " characters visited"); + most = Math.max(most, work.spent()); + least = Math.min(least, every.spent()); + fits += block.fits() ? 1 : 0; + } + } + } + assertTrue(least > 10_000L * 1024, "the search of every size visited at least " + least + " characters"); + assertTrue(fits > 20 && fits < 36, fits + " of 36 fit or are cut"); + System.out.println("1024 characters, 1000 pt to 1 pt at 600 dpi, 36 fits: at most " + most + " characters visited in a fit and " + nanoseconds / 36_000 + " microseconds a fit; the search of every size visited at least " + + least + " and took " + linearNanoseconds / 36_000 + " microseconds a fit"); + } + + + + /*************************************************************************** + ** When one line at the floor is higher than the box, no text fits at any + ** size, and that is known without searching: the text is laid out once at + ** its size and once at the floor, for the numbers a refusal reports, and + ** nothing is tried for a cut. The answer is still that of the search of + ** every size. + ***************************************************************************/ + @Test + void aBoxLowerThanOneLineAtTheFloorIsRefusedWithoutASearch() + { + String text = "The quick brown fox jumps over the lazy dog 0123456789 ".repeat(19).substring(0, 1024); + Face.Glyph[] glyphs = Face.MONO.glyphs(text); + for(boolean truncate : List.of(false, true)) + { + for(int maxLines : List.of(1, 64)) + { + //////////////////////////////////////////////////////////////////////////////////////// + // 1 pt at 600 dpi is 8.3 dots to the em: a line reserves 9 dots above its baseline // + // and 3 below, and the box is 11 high // + //////////////////////////////////////////////////////////////////////////////////////// + TextFit.Request request = new TextFit.Request(Face.MONO, 5000, 11, 600, 1_000_000, 1000, null, maxLines, truncate); + TextFit.Work work = new TextFit.Work(Long.MAX_VALUE); + TextFit.Block block = TextFit.fit(request, glyphs, Face.MONO.glyph(TextFit.MARK), work); + assertFalse(block.fits() || block.truncated()); + assertEquals(List.of(1000, 1024, 1024), List.of(block.milliPoints(), block.characters(), block.shown())); + assertTrue(block.height() > 11 && block.width() <= 5000, "measured at the floor: " + block); + assertEquals(linear(request, glyphs, Face.MONO.glyph(TextFit.MARK), new TextFit.Work(Long.MAX_VALUE)), block); + assertTrue(work.spent() <= 12L * 1024, "two layouts at each of two sizes, each at most three times the text, and no more: " + work.spent()); + } + } + assertTrue(fit(new TextFit.Request(Face.MONO, 5000, 12, 600, 1_000_000, 1000, null, 1, true), text).truncated(), "one dot higher holds a line, and so a cut"); + } + + + + /*************************************************************************** + ** Fitting counts the characters it visits against the allowance it is + ** given and ends, by name and with nothing of the text, when the allowance + ** is passed: at once when it is already passed, however little is asked. + ** The count is the same every time. + ***************************************************************************/ + @Test + void fittingEndsWhenItsAllowanceIsPassed() + { + String text = "The quick brown fox jumps over the lazy dog"; + Face.Glyph[] glyphs = Face.SANS.glyphs(text); + TextFit.Request request = new TextFit.Request(Face.SANS, 300, 60, 203, 40_000, 5000, null, 2, true); + TextFit.Work measure = new TextFit.Work(Long.MAX_VALUE); + TextFit.Block block = TextFit.fit(request, glyphs, Face.SANS.glyph(TextFit.MARK), measure); + assertTrue(block.fits() && block.milliPoints() < 40_000 && measure.spent() > 500 && measure.spent() < 2000, measure.spent() + " characters visited for " + block); + + TextFit.Work exact = new TextFit.Work(measure.spent()); + assertEquals(block, TextFit.fit(request, glyphs, Face.SANS.glyph(TextFit.MARK), exact)); + assertEquals(measure.spent(), exact.spent()); + + for(long allowance : List.of(0L, 1L, 43L, 200L, measure.spent() - 1)) + { + TextFit.Work work = new TextFit.Work(allowance); + TextFit.Exhausted exhausted = assertThrows(TextFit.Exhausted.class, () -> TextFit.fit(request, glyphs, Face.SANS.glyph(TextFit.MARK), work)); + assertEquals("TEXT_WORK_EXHAUSTED", exhausted.getMessage()); + assertEquals(0, exhausted.getStackTrace().length); + assertTrue(work.spent() > allowance && work.spent() <= allowance + 2L * text.length() + 1, "passed by no more than one line: " + work.spent() + " of " + allowance); + long passed = work.spent(); + assertThrows(TextFit.Exhausted.class, () -> TextFit.fit(request, Face.SANS.glyphs("A"), null, work)); + assertThrows(TextFit.Exhausted.class, () -> work.spend(0)); + assertTrue(work.spent() >= passed); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // a cut is counted too: every try of the last line with the mark // + //////////////////////////////////////////////////////////////////////////////////////////// + TextFit.Request narrow = new TextFit.Request(Face.SANS, 120, 40, 203, 9000, 9000, null, 1, true); + TextFit.Work cutting = new TextFit.Work(Long.MAX_VALUE); + TextFit.Work whole = new TextFit.Work(Long.MAX_VALUE); + assertTrue(TextFit.fit(narrow, glyphs, Face.SANS.glyph(TextFit.MARK), cutting).truncated()); + assertFalse(TextFit.fit(lines(narrow, 1, false), glyphs, null, whole).fits()); + assertTrue(cutting.spent() > whole.spent(), cutting.spent() + " with a cut, " + whole.spent() + " without"); + assertThrows(TextFit.Exhausted.class, () -> TextFit.fit(narrow, glyphs, Face.SANS.glyph(TextFit.MARK), new TextFit.Work(whole.spent()))); + } } diff --git a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java index 7490073..1223a8b 100644 --- a/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java +++ b/renderer/src/test/java/com/kingsrook/qbits/renderer/scene2/text/TextRasterTest.java @@ -32,14 +32,14 @@ import com.kingsrook.qbits.renderer.scene2.Scene2; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /******************************************************************************* ** What is drawn is what was measured: the ink of every line is inside the ** line's measured box, the block is where `align` and `valign` put it, and - ** nothing is clipped. These read the canvas the renderer composes. + ** nothing is clipped. These read the canvas the renderer composes. Every + ** text drawn here is also held to have nothing stray from its measure. *******************************************************************************/ class TextRasterTest { @@ -59,7 +59,9 @@ class TextRasterTest boolean upright = rotation % 180 == 0; Frame frame = new Frame(MARGIN, MARGIN, upright ? request.width() : request.height(), upright ? request.height() : request.width()); Canvas canvas = new Canvas(frame.width() + 2 * MARGIN, frame.height() + 2 * MARGIN, request.dpi()); - TextRaster.paint(canvas, frame, new TextRaster.Drawing(request.face(), text, block, align, valign, rotation, threshold, true), bandDots); + TextRaster.Drawing drawing = new TextRaster.Drawing(request.face(), text, block, align, valign, rotation, threshold, true); + assertEquals(new TextRaster.Stray(0, 0), TextRaster.paint(canvas, frame, drawing, bandDots), "nothing strays from the measure: " + request); + assertEquals(0, TextRaster.outside(drawing, request.dpi())); return (canvas); } @@ -329,29 +331,117 @@ class TextRasterTest /*************************************************************************** - ** Ink outside the measured line is never clipped away and never printed: - ** the render fails. Forced here with lines whose boxes are stated too - ** small: one that ends in the gap between two letters, so the second - ** letter is wholly beyond the guard and only its bounds tell, and two that - ** cut through the letters, whose ink is found in the guard. + ** The ends of what the renderer accepts. At 1 pt and 2 pt, where a letter + ** is a few dots, every character of every face is drawn inside its + ** measured line. At 300 pt and 1000 pt, where a letter is drawn from its + ** outline in bands, the characters of each face that reach furthest are: + ** its widest, and those that reach furthest left, right, up and down. ***************************************************************************/ @Test - void inkOutsideTheMeasuredLineFailsTheRender() + void theSmallestAndTheLargestTypeAreDrawnInsideTheirMeasuredLine() + { + for(Face face : Face.all()) + { + List drawn = FaceTest.drawn(face); + for(int[] size : new int[][] {{203, 1000}, {300, 1000}, {600, 1000}, {203, 2000}, {600, 2000}}) + { + TextFit.Scale scale = new TextFit.Scale(size[1], size[0]); + for(int start = 0; start < drawn.size(); start += 16) + { + StringBuilder text = new StringBuilder(); + drawn.subList(start, Math.min(drawn.size(), start + 16)).forEach(text::appendCodePoint); + TextFit.Request request = new TextFit.Request(face, scale.ceil(1500) * 16 + 16 * 2 * TextFit.SLOP, scale.ceil(2000) + 2 * TextFit.SLOP, size[0], size[1], size[1], null, 1, false); + Canvas canvas = draw(request, text.toString(), Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, TextRaster.BAND_DOTS); + TextFit.Line line = TextFit.fit(request, face.glyphs(text.toString()), null).lines().get(0); + Frame ink = ink(canvas); + assertTrue(ink == null || new Frame(MARGIN, MARGIN, line.width(), request.height()).contains(ink), () -> face.scene() + " at " + size[1] + " millipoints, " + size[0] + " dpi: ink " + ink); + } + } + + Face.Glyph worst = face.worst(); + StringBuilder extremes = new StringBuilder().appendCodePoint(face.widest()); + for(int codePoint : drawn) + { + Face.Glyph glyph = face.glyph(codePoint); + if(glyph.ink() && extremes.length() < 5 && (glyph.left() == worst.left() || glyph.right() - glyph.advance() == worst.right() - worst.advance() || glyph.top() == worst.top() || glyph.bottom() == worst.bottom())) + { + extremes.appendCodePoint(codePoint); + } + } + assertTrue(extremes.length() >= 3, face.scene() + " has " + extremes.length() + " furthest-reaching characters"); + for(int milliPoints : List.of(300_000, 1_000_000)) + { + TextFit.Scale scale = new TextFit.Scale(milliPoints, 203); + for(int index = 0; index < (milliPoints == 300_000 ? extremes.length() : 2); index++) + { + String text = extremes.substring(index, index + 1); + TextFit.Request request = new TextFit.Request(face, scale.ceil(2000), scale.ceil(2000), 203, milliPoints, milliPoints, null, 1, false); + Canvas canvas = draw(request, text, Placement.Align.CENTER, Placement.Valign.MIDDLE, 0, 128, TextRaster.BAND_DOTS); + Frame ink = ink(canvas); + assertTrue(ink.width() > scale.floor(100) && ink.height() > scale.floor(100), () -> face.scene() + " U+" + Integer.toHexString(text.codePointAt(0)) + " at " + milliPoints + " millipoints: ink " + ink); + } + } + } + } + + + + /*************************************************************************** + ** Ink outside the measured line is never clipped away and never printed, + ** and a text is never printed in part: what strayed is counted and the + ** label is left as it was, reverse text included, whose box is not filled. + ** Forced here with lines whose boxes are stated too small: one that ends in + ** the gap between two letters, so the second letter is wholly beyond the + ** guard and only its bounds tell, and two that cut through the letters, + ** whose ink is found in the guard. The bounds alone, which is what a + ** validation asks, count the same glyphs. Ink that would fall outside the + ** element's box is counted too, and none of that text is printed. + ***************************************************************************/ + @Test + void inkOutsideTheMeasuredLineIsCountedAndNothingIsPainted() { TextFit.Request request = new TextFit.Request(Face.SANS_BOLD, 200, 60, 203, 12_000, 12_000, null, 1, false); TextFit.Block honest = TextFit.fit(request, Face.SANS_BOLD.glyphs("HH"), null); TextFit.Line line = honest.lines().get(0); Canvas canvas = new Canvas(220, 80, 203); Frame frame = new Frame(10, 10, 200, 60); - for(TextFit.Line wrong : List.of(new TextFit.Line(0, 2, false, line.left(), line.right() / 2, line.above(), line.below()), new TextFit.Line(0, 2, false, line.left(), line.right(), line.above() / 3, line.below()), - new TextFit.Line(0, 2, false, line.left(), line.right(), line.above(), -line.above() / 2))) + List wrong = List.of(new TextFit.Line(0, 2, false, line.left(), line.right() / 2, line.above(), line.below()), new TextFit.Line(0, 2, false, line.left(), line.right(), line.above() / 3, line.below()), + new TextFit.Line(0, 2, false, line.left(), line.right(), line.above(), -line.above() / 2)); + List strays = new ArrayList<>(); + for(TextFit.Line each : wrong) { - TextFit.Block forged = new TextFit.Block(honest.milliPoints(), List.of(wrong), wrong.width(), honest.height(), honest.baseline(), honest.pitch(), 2, 2, true); - TextRaster.Drawing drawing = new TextRaster.Drawing(Face.SANS_BOLD, "HH", forged, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, true); - assertEquals("TEXT_INK_OUTSIDE_MEASURE", assertThrows(IllegalStateException.class, () -> TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS)).getMessage()); + TextFit.Block forged = new TextFit.Block(honest.milliPoints(), List.of(each), each.width(), honest.height(), honest.baseline(), honest.pitch(), 2, 2, true); + for(boolean reverse : List.of(false, true)) + { + TextRaster.Drawing drawing = new TextRaster.Drawing(Face.SANS_BOLD, "HH", forged, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, !reverse); + TextRaster.Stray stray = TextRaster.paint(canvas, frame, drawing, TextRaster.BAND_DOTS); + assertTrue(stray.any() && stray.glyphs() > 0, "strayed: " + stray); + assertEquals(stray.glyphs(), TextRaster.outside(drawing, 203)); + assertEquals(stray, TextRaster.paint(canvas, frame, drawing, 1 << 10), "the same count drawn in bands"); + assertEquals(null, ink(canvas), "nothing of a text that strayed is on the label"); + strays.add(stray); + } } + assertEquals(List.of(new TextRaster.Stray(1, 0), new TextRaster.Stray(1, 0)), strays.subList(0, 2), "the second letter is wholly beyond the guard: only its bounds tell"); + assertTrue(strays.get(2).glyphs() == 2 && strays.get(2).dots() > 20 && strays.get(4).glyphs() == 2 && strays.get(4).dots() > 20, "ink in the guard: " + strays); + assertFalse(new TextRaster.Stray(0, 0).any()); + assertTrue(new TextRaster.Stray(0, 1).any() && new TextRaster.Stray(1, 0).any()); + + //////////////////////////////////////////////////////////////////////////////////////////// + // a block measured honestly but handed a box too small for it: its ink would fall // + // outside the element, to the right and below // + //////////////////////////////////////////////////////////////////////////////////////////// + TextRaster.Drawing whole = new TextRaster.Drawing(Face.SANS_BOLD, "HH", honest, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, true); + for(Frame small : List.of(new Frame(10, 10, 20, 60), new Frame(10, 10, 200, 12))) + { + TextRaster.Stray stray = TextRaster.paint(canvas, small, whole, TextRaster.BAND_DOTS); + assertTrue(stray.glyphs() == 0 && stray.dots() > 20, "outside the element: " + stray); + assertEquals(null, ink(canvas)); + } + Canvas clean = new Canvas(220, 80, 203); - TextRaster.paint(clean, frame, new TextRaster.Drawing(Face.SANS_BOLD, "HH", honest, Placement.Align.LEFT, Placement.Valign.TOP, 0, 128, true), TextRaster.BAND_DOTS); + assertEquals(new TextRaster.Stray(0, 0), TextRaster.paint(clean, frame, whole, TextRaster.BAND_DOTS)); + assertEquals(0, TextRaster.outside(whole, 203)); assertTrue(new Frame(10, 10, honest.width(), honest.height()).contains(ink(clean))); } diff --git a/renderer/src/test/resources/scene2/README.md b/renderer/src/test/resources/scene2/README.md new file mode 100644 index 0000000..fd8a7b6 --- /dev/null +++ b/renderer/src/test/resources/scene2/README.md @@ -0,0 +1,31 @@ +# Golden labels of version 2 scenes + +Each case in `cases` has, in `golden`, at 203, 300 and 600 dpi, the exact ZPL the renderer emits +(`-.zpl`) and the page a printer draws from it (`-.png`). `SceneGoldenTest` compares both +exactly, on every machine, and holds `golden` to exactly those files, which is why this note is beside it. + +## What the pictures depend on + +A box is whole dots of ink and depends on the scene alone. Text is measured by integer arithmetic on the bundled +faces, which is the same everywhere, but its glyph bitmaps are drawn by the Java runtime: the Java 2D rasteriser +and the FreeType library that the JDK itself ships (`lib/libfreetype.so` on Linux, `bin/freetype.dll` on +Windows). The system's FreeType is not used: in the images below `libfontmanager.so` loads the JDK's own copy. +The version of that copy is the one the JDK states in `legal/java.desktop/freetype.md`. + +The text goldens (`text-*`) were generated and compared on these runtimes, all x86-64: + +| Where | JDK | FreeType in the JDK | The goldens there | +|---|---|---|---| +| CI image `maven:3.9.11-eclipse-temurin-21` (Ubuntu 24.04) | Temurin 21.0.9+10 | 2.13.3 | generated here; compared exactly by the build | +| Windows 11 | Temurin 21.0.12.1+1 | 2.14.3 | the same bytes; compared exactly by the build | +| The worker image's runtime (`renderer/Dockerfile` requires `jdk-21.0.13+9` on Ubuntu 24.04), as `eclipse-temurin:21-jre-noble` | Temurin 21.0.13+9 | 2.14.3 | the same bytes; the 21 labels were rendered there and compared by hand, not by a build | + +So the same bytes came from two FreeType versions and three JDK builds. That is an observation about these +versions, not a promise about the next: a golden that changes with a runtime is a reviewed change. + +## Changing a golden + +A golden changes only with a reviewed change to the layout rules or to the runtime. Run `SceneGoldenTest` in the +CI image; what the build drew is left in `renderer/target/scene2-actual`. Copy the files to `golden`, then run the +test on Windows as well: it must pass there on the same bytes. Say in the change which goldens changed and why, and +update the table above when a runtime changes. -- 2.54.0