From 4c30c097925949dccbf8db11159480e6b42123a9 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 13 Aug 2016 10:48:48 +0000 Subject: [PATCH] Correctly draw vector text for constraints free in 3d. --- src/drawconstraint.cpp | 8 +++++--- test/constraint/angle/skew.png | Bin 0 -> 4851 bytes test/constraint/angle/skew.slvs | Bin 0 -> 6115 bytes test/constraint/angle/test.cpp | 5 +++++ .../at_midpoint/line_plane_free_in_3d.png | Bin 4350 -> 4395 bytes .../at_midpoint/line_pt_free_in_3d.png | Bin 4338 -> 4372 bytes .../cubic_line_tangent/free_in_3d.png | Bin 5145 -> 5142 bytes 7 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 test/constraint/angle/skew.png create mode 100644 test/constraint/angle/skew.slvs diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index 6442989..b744805 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -437,7 +437,7 @@ void Constraint::DoArcForAngle(Canvas *canvas, Canvas::hStroke hcs, Vector trans = (*ref).Plus(gu.ScaledBy(-1.5*VectorFont::Builtin()->GetCapHeight(textHeight))); canvas->DrawVectorText("angle between skew lines", textHeight, - trans, gr.WithMagnitude(pixels), gu.WithMagnitude(pixels), + trans, gr.WithMagnitude(1), gu.WithMagnitude(1), hcs); } } @@ -925,7 +925,8 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas, } Vector ex = VectorFont::Builtin()->GetExtents(textHeight, "T"); - canvas->DrawVectorText("T", textHeight, textAt.Minus(ex.ScaledBy(0.5)), u, v, hcs); + canvas->DrawVectorText("T", textHeight, textAt.Minus(ex.ScaledBy(0.5)), + u.WithMagnitude(1), v.WithMagnitude(1), hcs); if(refs) refs->push_back(textAt); return; } @@ -1122,7 +1123,8 @@ s: } Vector o = m.Plus(offset).Plus(u.WithMagnitude(textHeight/5)), ex = VectorFont::Builtin()->GetExtents(textHeight, s); - canvas->DrawVectorText(s, textHeight, o.Minus(ex.ScaledBy(0.5)), r, u, hcs); + canvas->DrawVectorText(s, textHeight, o.Minus(ex.ScaledBy(0.5)), + r.WithMagnitude(1), u.WithMagnitude(1), hcs); if(refs) refs->push_back(o); } else { Vector a = SK.GetEntity(ptA)->PointGetNum(); diff --git a/test/constraint/angle/skew.png b/test/constraint/angle/skew.png new file mode 100644 index 0000000000000000000000000000000000000000..76191f56d4e65e419526099e3defe3238f4d5cc0 GIT binary patch literal 4851 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 literal 0 HcmV?d00001 diff --git a/test/constraint/angle/skew.slvs b/test/constraint/angle/skew.slvs new file mode 100644 index 0000000000000000000000000000000000000000..e793f9371a167a3a31b92b92982e8b2aa2e2b2ee GIT binary patch literal 6115 zcmdT|%}(1u5Wf30dX8l~p(+O-D5bqsCv?fLT z)BEL}Etd?T7NDXAP%^E&T+&h{$zZDI@xqhn_kU13q<>j9PbG)Vkw>)+#yh@w90EbR`BQ z^9~?lBg~`MnNP=?PdiaXts7O;x={t~YfwdV6V=H;Skc~ub&S1<>rnd{16H$Qa?*Z$ zxi%8ooArmmaC1a5@P*A(Q>nl13R~U6I2y_&xYx4md)U z<>i{BN&!c&P{43@qvlOu6c>9^E%?NTC1E15P(IqT>Frr3!#u;$e86)@oe=aZFV#5_ z4l11Y)hyiVOnc>ae&`~Uc$$3xg)Y4xT9&V)_Q6VKR3EI|%sx1-X59zTvF)>KIND#j z>%a8n@X{VT09mPM$?zFW1a#3#1RO?`?|wwEd>xetRx+cAVC6QF2(EdmjS2nNzQl*u z_TT~xUrjC`8RQ=Cb10w-#RYy|gyP&rRV012-f|j*p2@06k||2ip6h|Amw3Xkh!QNSFx62}Cm(>rP*Fh6RxutLJ2{6QD0i8g;wrC>5UiE{W=JneVV zSdm7c-V#-U*_S^r@xlJ|ppS*iaSJ(^907#tBT^0A2lDpX0usvYF2Bm-^G(X1I*pZ#Wa8m+F<~nCb}fg`v<@mL;wH) literal 0 HcmV?d00001 diff --git a/test/constraint/angle/test.cpp b/test/constraint/angle/test.cpp index 57d7820..a117b23 100644 --- a/test/constraint/angle/test.cpp +++ b/test/constraint/angle/test.cpp @@ -47,3 +47,8 @@ TEST_CASE(reference_free_in_3d_migrate_from_v20) { CHECK_RENDER("reference_free_in_3d.png"); CHECK_SAVE("reference_free_in_3d.slvs"); } + +TEST_CASE(skew_render) { + CHECK_LOAD("skew.slvs"); + CHECK_RENDER("skew.png"); +} diff --git a/test/constraint/at_midpoint/line_plane_free_in_3d.png b/test/constraint/at_midpoint/line_plane_free_in_3d.png index 81d1acbbf9bca6ef6ead0dc0871b14b079663516..510aa890e9ec35c5d975bff4608d853e2a0645b6 100644 GIT binary patch literal 4395 zcmeHLc~H`M8~;M0=8>9dW~P~&THcjMX_DnpsbyJ49!Qy$nOEj5g4X7kc33;=W_fIz z7oz05c%%Yl8>M;VL6+-Pn~+FWLcU)3{wQ%G$JU*l_m6kxodNz}9=^x(d@g=TE_)ng zrBtN=0J6Jw+U^GcjuN~j#i4H~$20x_K>p({Tbl!sH#yxlXS(cFFZA2jJ3Q7lfBf>( zuCk`qA9v)|+}wQMQ|m)?;8hQqd0IVHlVEvTCEqs`HPK>vOp1 z5a8yqD4HUp%yjqn=dA(2{^-o*=C+kZw>ne`Fp9G~4Z<4=G=R!ai)TRd=-_WY3j_#0 zPT!Fyh3{E5XDa>yM6?*7?G#>aE*z&an1f2-^cvy$QC^r8yhY&LhWlS|ORKyX{#10< z^8&f$if-D^VqA z7)^V2rw&BgJ|r;K74j>EaFRa%AVigK3Y7*yt#;kLpjq;L26!IhrF*R;z^DF0@xba< zttU~DhBd<@-EOeponLkLexEge;;qU9oZtkfUxkt|F3f$r$xjvD!&GJbZIk;6=T;oQ zfp||7QEfXCx{wZkgX;hvV&M417a?LTVetol(~$xsbKzLNYb_lJhE=+k zD!}Z8I;81cv>aH;#3NRraEE(&aqnLH$6VCUMacas7_5yBI$1Y_hoY1Z=OWb7Y4FZ? zKV`K{TEZSDoHNpi!0=|6O_?eYS$p^vo6*q|@z|*ehg1Yzil#b&t zvvIN0x2=%Kn=yU?o5#p)+1XfDx`+CXTq7d6)FZ3T9C>2pX6lH>*rX+-x26-aBe7kw ztCkGKx`%N%S9GR1+3Ys&4}052M{!+2g;Dw0{^X~`MxD`1%@N*>)mD2;Dd-N`1bn zAmO1>i~E~H3h?R`g9J&-qmJ^C#}g3pYfA7ZX2~*-n-QdoqYSGz0b16KEVsyA59)LK z*39O&9SDPmcN^*nCHr&X7t6sHU(rEMhhoR|_YnIy0Q(*8RD%^5C}` z`yB^=?Vfh6K}r}y7OI3_N$UUG@Htce549n@hUO089i+UAgbai^Hjs;w%|cYv^_`1kc)5OG+EPt1b}-=;EA+jd)tqWq}}R9pfu2FZ`%;DRgFPPYu; zYxNK+55v%@aP%t za}61CYEY}HMRJe1SPXN zyva7Fm=hBW16O=oX!owFyY?RWsFt`DDGpS+bK*_4UG)I#9BmL^s03>EJtN3S7E7Es zg#c3uD7pG}DKP%VS5^ILB^*x~ON)?ul(rghhbt9}C9rFwLJ-TXSiK(jP`Yff4b^57 za2c+Q@3;XqF+605cFOq}41~Z5rl|;EySVto8fhS@fXcs!-UFrm1|I}tOzbT=srAmT zHb&@a>~zny=QwuNe*c14Ljq0%*7p#qa4QX9)^h#R%lQK@+NGjj4ePZeSubK=OAn+O z*`*~pWZ@=34w(^(x#iH7=GPu|U@@GPJZ%CGJb1SE-!5l5LYcYT)(LcSF0m^%-zL17 zc)!B7+mT%zp4CPV=lGP=2C=s^-zuFT8+29N93?VejMsQsR#-^%*|Y1^MqfXy(x#sG+{z{(iy&!J2 zoy85u>-R>UTz&fl8^woJ?(@Q|>JMF4PKkW0kR=T)u2PT^?6YO>3yi9QRS%aEhq)#- zd0QT!tNAh6BehL2oXLYsSf9MQ773mFtHY%{k6RM$cUq!3CWnx6Fo79p8i7i2x+JUUpFoVIKvNR9$oh&xwE-rm0<&r^Rek(aW z)AHyphGR`!>qt~jXvqkfYvx@2sndHL8_9{PKKN=(BFDbJcHE`ZvH!!_$jHD|&520q zC5gAM`_vdbSg+K!5%g(x1S+7VuZ^bg${#kVGxvIpZoNA&*@XN!rZ{>jHCuxj5y!-J zMb+hf+EkxFH?4071Hmc+vw6xCN#fsei8+z{>m(^yN|eS6Ux_d6_SPdcgq<1%Jp=)} M?Dp7}Y{w-02fC-|Bme*a literal 4350 zcmeHLc~nz(8vSKMb}ST7K~WgNQ9#5ch^(?z1*}Ukge?}WOJq^1marr^?p9N@4O);@ zK!K1(~Q|QyKJv%BU&d~4FD5!hC1^t;Mw zpyr$Fp@9U{|+aLi1lL-KNk-YO(V9NJ8FM+80;_LeN z#Yu^y^-c$zzgNU+Yk*oL5aBsGfRcXtt$+_N;5RP=Lf`QN%nGh^?B} zyk}3mJZXibNnUYB%Plmz%)G$56cUF7gumHpp!5m@D5*CS1`WZI35t|CGQS;0P`uB) zEQ}EDxA*3IlB9vU`9d3_Au}I3sKKZm+v)V?OaP`F83*|_w&hw$!#OBQ(8QZc_3R5$ z0pauU%BO6&GkxJi( zgr+H#dmg2DdhRd>#hYFcBmDtsbntQ$8!I6bme2;m}qHvaMHby_)vvm;icn(a%2C!D1Wr z-LtAbYVTr|hLLp~QdNySe@4q|*e8V@!HDo9ru*3iS)Y~SH`V4Fj1*!J6jq%vNLD-= z&QU(^s27M6Mn~C0zl(M~-I7sFewr60Nz^}3bxBYalV~VbX2onufpQX+XM^Z0R_9G= zvKTX6*eAUvAxGtST&oUj%pngcuZ}3b<1twHEamy!6=7mmvbSf3R0jRCF3=xkV#_aC0uenvxD-{4feNMbfG*Z?r?UN%8i z(`j*e!=2qe<6iSF_wT^dPB!Xlbnst}HWPXc1B8pkU+=X#jr1J4fsJSU*(%1qC#9qf zFi(*q6GvJCV$to%Xfyo*UUgBg1IRiNw%;jN($Xextht1U$0PN$W}gGSm;JO+CZXKN z4y$f#3!0b+_-IKEOse?Eb;KBY8yavwdyi-Vyk46NO6uuklzi@=UH&bshNYDd&Re?+ zui;k0CVW^a76F`$|L1VMV&|^}x;mEq>|#?5-&eDlWCDQAg8xb$KEf~-D*u0B=u1vx zg~Y)*>%Ib(Wx^H>ZB`Hcx5Utu!Sf~tM6D#5qPvl#gqYP-ScdJ!!`6RX6kwA{bX>L= zaI;|-QZEn1?n zw;67LJL7~phoZ*9=-ABG`q29yuR(#nTJ$^C7ib~#Mc;DJ&K=gb_nbKmxG+6XrL2uM zQ26{(BM{w-W#TQIf66BBNpIM=f}HIr!vZKt1+08bZT9ookd+f@M;PI?e{4%ps1< zy9_ANQx`GI&($~WJ?&P%kxxYcf9zJm@f%ILV0b3em9QNHB@y;8g8_Y-Rwbho=0Y{xE($tjgwP6BNSO zl$&&U%>C|F^W{o`!##P~NZam99&v1eSvP3i=6-VlzeSu1kuN^#7zj;Z)F(jE0mb!1fP>Iu2y8(TMo`PceH`%$_S5x?DYY{u&gaGsb;;@Q|hAx)eu^W~K*-PynRX?vwbw^~=WuQ^#(0w#|oRW{X^r!3o64Wf#R`5n{4o* jm-;tb&cC<1KC&gk{nnK$Q$ykZ8eoNAuy6Tt!oEKMKk?Sr diff --git a/test/constraint/at_midpoint/line_pt_free_in_3d.png b/test/constraint/at_midpoint/line_pt_free_in_3d.png index 314734ea249391454937c1e95d08291c3814364d..fe283089e4a2e716c8d6cb2cf55a2f91d2bd300b 100644 GIT binary patch literal 4372 zcmeHLYgAKL8a;Vo5J7yR2n1nptff3u3ThyzC@3nvMFJ8<#DWP>UV;JvT{==UW0~Qh zfmoFyl0eYLfHfpkYm5w_0*Sm57_318iG+kKBMEb%h1FE)*qJpyW-Wi*KX;vb?>_tN zZ}0EB=eBS2HJxrb9ROgu$90{FvZp)PW)8$M1tidt6i3NcngoSDZIJLa?XCio2S@Qf3ONRAEJBNq~87@=FOB;mtF_jK>qm zdzRe|`#{x_(;WTPW@Pc)5O+g~?}{Qa#7MyNn;`jJ`G1s$fkAwfhoL)ukUUbCt@<=f zJ20Bw_ZFwuHZ;!c6!1rs%6f$)Rad&hhA&Aw*}Dyx`4TF>;-0!5W{*81JYd8B{vwJ; z>aars^orU;Nu&BNhyx{kA;&cLE1D#dQ8|vG8?4AvXhuBF6dckem5vqdlCdgV64)<4 z8(QKNY9($Hz1kC%io3A*+kL>=wf2z3wUJX^k9$B@?5U2qfeap&s~<^lG2Jtt)Bi4T}t zUZAJyT`PmQA?+$@d^Z=6)0fv~uIQML>^cBFFu1yMIS1Zl12<_f-wQhY3AHFY6Y_~k zpPQ^<$aw4HT1&gB{?3t_%p`EpwVp^wh<8P1QEP;e1)-U;7RpRX{n>ll zDr$m9mfGID;qK)*k`1P*s*OMOn4N)Ag~_A)h>@rtv*fwPj$PG-Vx#{4V$`>LV}ju( zw*P3J{`zxMu=bzRk1~|E(J-T)T-(>1$Ks-T1N!$Hf)TOzHB%{9; za^&t+5IBPE7{X(akG5PseuKrqMgnqSzCpkH&d$KWRHNLA5H!G6dLim8{$d1*0%;j7 zZOn@abau-$va5PgAj5Rw{)*7={f^eIF?##f4D0CHegQA`Aj#lb-M_b4up{)mlOVuX#F;4(o$5X?IrDa={U zf|JvdFQ57IpUT0N=$aRuIkEocK%3NIEX=9NxmT5GQlwIR#>4YX>1(;(E5UX}RYuFD zM{tlB+s}*KdKd;`;bm?YQNYKTzR%7Cpl1b^WQn(7z=FCsl(60SS@pSR#haRhZg=!r z@z+vr5~JB>8Lh5Q;tM(WSAgdtl#) zO9M}WWUH9sjZL{btdkneSgOroR+F! z$yw?$A*{>1$e!7-;o0qtO$@P7bMcean*1`_Sxy62+S8^K!0~%DQshw5Iepn}z#DSLH>V4yBViSUP_(Ko#}O?`Al4ZaksFofeT~4r1J^ghC2k zo#@Qj+Eng2tVzQ(ct*1~V@E;r(tCR`eW{;di_B&=GJ4dnBWk;2;=jyJ`ii;vN7W2) zd^3xUu0RQVAEw|BMNrhcq&h$Peu>t;f>uS!9vKOQCTnhVCo~FY-|9*}uS~QCR^vfE sWH~WwzNbzMs(=dY4cmOm*AX)R1>KeIEC2ui literal 4338 zcmeHLX;hPE7QRUU(Fp1wipT&Ki%ty?R0bq0717kP*byVputae=f*2NKBoULi))u8m z58wu+T9BBK%m^ePSr7-bQLzGHN>~L%pnw`7KuDON=oC9t=7;CZ4}W|o=X~epy!Sr$ zxzBUo@6;Fmc%xb7vjD(o<7eKR0gyrCkD-C?jd)i^1Hjzkjoxdw9K6`u=pNTDH$Bmc zs@;3@+`50BJz#S@AZY&A*@cUP|L(QB>9_*1-pDU?@9N>~P0fm`faB*qM;`rvKbnvz z-D6Lnd;+jt+|vXg-K)0%KFyFK!O%o^);1&>tbIucI5ralOe{+u=GyWBZoaRe@cR3u z`2@wF#M7g5xRTL+NG=c$aLI{1#O9H}xX3l~!p>6TlMxN&iRG;^A+*(v&Tb#+y(?Ah znH*=do`HOS^V~@#*$oUi#RC{RmQ7V{QbgztD)7H~14kljXU!b&{Yh^E7G)%D`!oSz z#_lDmjF~^{a-NKy58+aYGXk(CCR0Hyb&(g+XTS}^*8%c{K^rt6z2ZC33oI{Z*{*4} z%B-@8(hp{S)rspS^|feAZ64hOVATgW#%cZmjt}fWqTlzh4F1@`x!WZe8_ToO4k>Yx z5X!PFWpX9?@R(My>0aEQ8N*#{972dgezR`WbSdgWt2x_}*H(KQ*@Cs4hlFG2NU=hO z_7Hodn7&Z08R~gnr;>~X)><(bquSebj`!yGcH^Ib(jaH8}U+X@ZcKXmmhh#cqrHleG?z$B2JzqGA zsYAq2i!vD&ZS$7=)+k=77++S$rafuWlP1_slG?Z3!!3T~0@V)Dq8yjPpl}j5N|D!U zCzGW2*#Q>uS_to6>pFGrjrP7n-yRo6+vS>0I@OLq>DJ|9AAYSnTPJOu=O$5l3f<;7 z@a2WQH30aPWk|!}dJ&>!mm!Av?MYe^CR^Y6%FC1tX;;bF`V9^&{TQgm2+2saFk0e{ z3sXNcq7NyFDf%ir3DGvRuauEEI+~LG;D~w&AM&NE(S5Sbgxs`MjKS+80y~Me*lFC{ ztRz}lVI4P8K^61TL)KkC>CS7#hhGS)iMO@Yn# za^3uRmQ9-F*6ciIafl`fs86D1t`II8C#`E!jiP4Oc_()}lOSm{U27J@-(-g^Jfi-X z4>x_eK(2f$SA`8d7pXj69z%ZrX$ z!=2R9y?N{al`X)o?MJ4uUGT-yFYAf|P+)Oq!h_qe!v^-XZ+rXOg!>OwrKLsOj)F-k z@_%IeH(mh9I5l%R%g+chDpcWb1Tjk|h?-R1zF4^BZ9|=cU*p@9vc4#-de&<*YFc8aP-BFk|Y)@He-D2{A{& znH{g@nHigL2$ddLLVmNo{_bGdCSrADg`mKs+lUiw5)9J)BUbai#z4z*g*>iaD`iLC zI0#Ieh7CGm`g)JE^QE-kB3$Zz#zuhgJEi0Fq9E~sB@k0yF&h(ZZ4Sb15e8dp3sNZI zj8d`@zo7Yv_%C8gze^}awbiyO9*L>H|^PJg439~MwgizJ5&+J`+$ zwnomm#M`Orw*j|!BCD{Dn5+y_7pp8a+-rHJNw=~BNpm9%t6^W5?|m z?IopJ2)XLO?`w_!%b+-+%e`~~#NaEm7M#x1D_6-Fbn=XB zjPIdxQPNQ1X(?^R*?msu?FUwV--PB0@{83Jm+nz~SY0Lq!w*#T%#nUkp|Rl9c{n_- z4>;jd)#zta~)r3reV nW#7v&%sM&^uYIrAeYHcC!3N*`7&%Y(Edw^L_xH~CA|3fRRq(|n diff --git a/test/constraint/cubic_line_tangent/free_in_3d.png b/test/constraint/cubic_line_tangent/free_in_3d.png index 1583d9351f38be916b0e3172d660bb6f014eb8b3..5784a678f75016af3b50405c0b77478924b564b4 100644 GIT binary patch literal 5142 zcmcgw3pkW%-@l*7%B`dpqry_G@>q@4CMCx@NBD`QOL?;l6+W-~TzY-^@^$ zBuxSU2=Cjw#{vM9KKmyUU`xfZ#Fqd_yxO;C_rZXx{8x_)-c*-Iy-s)09WamzP*wz; z?f*E)xp{KqvLBBHC)B?tsM1`Ivtyh}haDryBKJjpm_lOuLQ@nj9ed=&e)wZm*@U`C z;5TWjg#g&x_RJ0dst1k?sEJ$@5GCNY4yX{2HDMwkLQn}{sw_MZmFEEP^Z(bN)U4#d zB%{lnag|}ePW9Mpq`uLtSo}>J#9FyG9qcS~cX#KvGSpwbe3?>ib=#e{4)<5eHpUux zkcr!J{_U%`#1_AA>~*$&1u#*GFIh*`OwSx80kYVlGji;hQX>K&c}vy2i>Q?f{KUWM z95!W$5sat0DjZf{>cA+A+Jez_00cRPf62qnHQS!qA>4Jp2jrQM(vP8lZ7IK?Sr;vh zvh{BUsL(0JH6J*eru9TFiFEINBaLP|9H5$;d@;)W#PsKifWBwZk(?mb(WfH7rxv$x zR6b@EI{nQSUZ4{%8HP6oh&~--eOUIE-X*w8;2j_^3p|e)u zd_RF;W|tQtwQ(@VrDpGMD6Tnrn6qKWxfGB7PCa!FjmD)z4-qacLJVrhRsVj3wC@ z+ludJ36iM~a!YT2oyQJCg=E|97|G`O*k+;W+!J4> z%S2wv=3z8wh2lNQf#obbG<>^8Oexwb#{u=xin6|zkB=*dqqOhHfl*Dw}$ zC1}(nE*dGH$M&8Jh^mq&K1ZL4=!w&~NjS3VYA8Z;^~7jgG8C72;@xI@MQPkiIC7&l z6k+dSxQZ|;5L*Nzl2Q zF2hCOvoBha?TZTW;_rBlBvgi!n#0xPIM^$=QqWqsf+&q@jwA0+E=7ajf>|kNvvsB% zPD>(X=1k<7miDcr&Sxz+pY%E0vf`0(LGm2zF*MpAu6eN(H8=^eTP9SJioth>aJ-u? z16eOd=l*t2QdOFT&oP3cIGyVPMFl9%_DayHFI_yy5bS!HY z+4N}lB)J|Y9IWJwA{K`u50E|ay@%$IrObqZFg9?oglI+V1?<`8i9eajMN`)0fi=)n z#|{!xiiKB#;w32Rb&%RMP@z&|2BHOxQRi>Udlz`_CeWU{>s+fl=M=F>qEfp*+%Fie z22Wl<+qH{cA!Alt(R-5ANI~*`BQYA-hYE?(W-lFKLmqgKBQJwmL^1&P;iazZfpL@&W3p#lll2#~XAKER4oS?)2vySbKYp z%*-N}QimE{HQK&%vSR9e>%q^0Xk?r?-D*@v+v$F z7eYD0wh@g|(0Rx5hVE`gg?2)ZjaHG@`gFvX?hFkp3!ZsRyG9rw!ASwWUcOTMYx?7^ zlVsVgWQR2E16?sEc4Hq0rInl$p^+O{_!w~-n1nZQHYsm=Fic{$!6!7cHd0WeqThGvxmCd{fi4~AWoQtMhCh#%st zpMx7}W9NHYXXFhuK)flt;PSC59*)fMu&;M-39WQWt^86P+4iQ-(D@AvN|Vr}Ue$DfyKXgDP>_kJBF2)qiN( z8h7nRgK^4TTI$WT)op`@8lm60>b>H+bU6}@DRG9jr}uT{7bRunSNXnw^DaBE?%SY| z@je=IAU^0#)4Suim5t{5^s2o$GA_CJE1QQ;Tc5soN>a!!w1pS`lx7>jtv3yyZmqhB zg?F$E`z}+m{e-may;0dT2+-LY5!4GR5eu}5 z+%xmJen9@kX}}Pl&$npVGzs$_L0yxwlBEIDbb(DcM?F*@$T4aWo+lLT!mZa4%=Isl z>9A``_EqaeUI59W$Bxy@ixL2LIZWrfdIVZeYOVQ>3}h0SyRn9^aqU+>;U2BOj?jKr zO1G?$f=SG8Ez9lUfE_dyPI~6^Ob6v+LFAkJI3Y)q02(Yk+nwA;*Ows6?^ zjXtwV0Y0ncIkLUm?u*+17x^F{x{Zkh%DuRVR_Kt5N zEpq(1x?*|SMJK*K0K@kdqxPrO>0g1{f+D;CmTyiu0Brv^crxJD{sHW|TC`{yxu0Mb zknP=X5Zv?FX?)@*1XzE$cKf7+{=Xd!Yjw`l12xci?KVrTVVw}@GW)2kdmayRjzYvO z4rRt$@T;Jc9b{mz8s`cTKS&H+RU9pA-j5uBJ%8yb*R7lozqNqlbb@e6B$@#HavpOP z(q24}?m01nu+8}d>y3vEn!9hFiy$+e{F3U=6o8O>;w$TouMC<4WW)u*M`s<5QTLV` zMw=g_nDvMlJuM_AXE~(;rdNcj`5WFkN+P4^s)rOw8SpAY<>>;daNPEgta8lvrST7X zD_CAimG~8aqmoQ$P9EM-NRiLj;WoY*Q2TcZ=j^(C2%)aRSqqrtf_DA*)}vG=|7xZr zC^Tg9FU~&eUTm9XD_HUPgFDFuazwyiG5M-X$o<6F&SKv!J_+T#`O<9gl4GuMd zg;5>LSIX2l{XoJ2IU-wm`Yv%645~8}j+gsL8MXA?k<>FT8LvO>R+n2vyWaPFVhyEp zsz7@p$?${n;m))=-?ryBPQ5M7Uvs>BXtayhu^QVz@%O%xK3Q2gGGp`Jw_&w+Zp~1a zYoGQdIeY*9kcQR|wL^u!PA2T=%bv+AyIGyqwxPt=BgJ1`z2vwDj2z!xZ1i30zxuqk z90|Ii+@J%@vsTd8mtAt~zLF3-zyMt8^HAaD@golT9=A@eu_aC1@1 zeK+l+0iz+)7YNwe!d3JVHz}LA>wWP>T0@&gw2qw<#Ym$C`eQl4FPv>>^v9fSRR*W` zWxOf#&Z#RZ+-@2?%*#I|b?6bVs9`j sg97g?2a$7-R7Uvke(?Gu`i{zM?{?X~OhTj{e(wYO^v(9<=`zFr1Fq(kNB{r; literal 5145 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