From 7caa487d8b6a8c9287efd62370a8fc9d8586d45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Tue, 3 Nov 2026 17:48:35 +0800 Subject: [PATCH 1/6] Issue #60: the bundled Nerd Font ships its eight weights and their italics Nerd Fonts' JetBrainsMono release carries 98 faces across six variants, and the terminal drew one of them: JetBrainsMonoNerdFontMono-Regular. A family with one face has one weight, so every weight the picker offered above 400 was DirectWrite synthesising a bolder outline, every weight below 400 drew the same Regular, and every italic was a slant of the upright. assets/fonts now holds the sixteen faces of JetBrainsMonoNerdFontMono -- the eight weights and their italics -- in one xz archive, 1.87 MB against the 39 MB they unpack to. `scripts/fonts.sh` writes it from the release tarball after a bump. The archive is unpacked on the first run and kept in %LOCALAPPDATA%/ELYTerminal/fonts (XDG data on Unix), so later runs read it back without touching the archive: 249 ms once, none after. --- .gitignore | 3 ++ .../JetBrainsMonoNerdFontMono-Regular.ttf | Bin 2573248 -> 0 bytes assets/fonts/JetBrainsMonoNerdFontMono.tar.xz | Bin 0 -> 1958564 bytes scripts/fonts.sh | 39 ++++++++++++++++++ 4 files changed, 42 insertions(+) delete mode 100644 assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf create mode 100644 assets/fonts/JetBrainsMonoNerdFontMono.tar.xz create mode 100644 scripts/fonts.sh diff --git a/.gitignore b/.gitignore index ab584acb..f009ad65 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ .DS_Store /promo /voice +.kigi +.mimosa +.rpi diff --git a/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf b/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf deleted file mode 100644 index 7653ae018f929a9186b328a8a1990178f6afe5c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2573248 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
;W}6z!U?((yB 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%0D1C>^-dWPGHe|1i4}0ffof=71(iYPlYSc1pGz_dU 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

3mGmy=5!m+Ti!i)XUY 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

M)68;FLI*~*%Q^(`|Ju(W2eC#V;KTQB!p5vMVo z8A&AG8VJ*V(aON+@gB&yQay<;YsqXr(Hr^O+U(ll;VkO5By*B2W|7HA#8ju+wd3}M zg59q=0#=Dlm%iGmB5$LST3QQi-aM8a-b?jXXI(=D)tKlFV?et=^7tXBfnbz~l%@?g zdkmoV6GTSbN6Sr74zsxeT~f_u$Bh`F4MD-#u_2?R+ z*R#=wp$v(d<(t(>%FxQu+P?O1d-#u?dfl;uPAczx7*m9Ro2;NcnG3GWSAySdj5tn_ zoH`sMl|%cdr>3-r>f79QuoN6`&gLZ*BtO>}=V!Yk(Q`iiSgA!lTP!2x=rvqh2cs!f>ogDMokLdfNT zQI#?4F7bWZ%WIlN#@8=3I z4|z4Gpo1wDOkPqFBT*@+0oDyn$OmeCj{ky0$m(UZ3HQr?;JIzAjdo>Z=Z+&&JEnee z@@gvR>Q}(taa*oDsl9dQ&RoLr4vkd4bmXF`9e2F;WLvxJvg1m(2ot~g3$i8dCjY!E z?b;}B>Tg32H$)l?RK_OTQj)|dQterTFeEKv3jG5aFFqAfFD6FO3ehZ-xIkh^Lbv!G zI)9lSC#QpxEp}C!I~d5em}JrgNz@i0#OZ(pa7J8sL$$Qf_e{3r@Goi+oAQI87;vSM zER8BFBj_>45QF7-vZpYdjU;s{w3L$|Hl5@u2)@E`D+4?)QYl2sk}Hra;VO^ClF6zo zC5=T47zC&F@U~X;Aa%hJu?`OKfWu%4>fw5K_pp=bE%)6>sl^dsjlpuC-oV`{*ZjD^ z<+&pqa!@f=y!h%Ncxj^qi_wKL*=%pFSR{py`f`FU%-faC25&oIcjq=O7P4`wEAp2* z`ISD0j)FdfcVWTWbg7;PO3=MqF5Jp&RNfk_s75I^vSAe@QcUK!% z?sGE~pouuF2wHRu9B-~|MZlEjX8#=f>$Ef%Z6vaP?7TndtLyYn^lz$Bs9vp&-4 ze0Que@W6mp;a@r$4GtbVC9GsiOB-gZu+F6iG_4d2xiJ$S4r|18OAe`e(s7OT>5+)X2S^obBIY>^8k@%GRrV|D;Xng`$g+VNZX>PvF*-gdrmd|H$xx;BS;-5b z;gooAEy$<*hqUE#4(4Vov7R3kt+;;xd}Np9hU3oS`(8KTpXWGHq5mQWRct` ztk7f9X}O)&sL#@gn(aH>CuM)7J9lnRL};!h)7ZplJ2xcIW|gQzIa+B5xpN-7H9#9m z-&T(*D|iyMFQHzF#1A~*t-EhW@QCE$f7~Yn0A{RzKa@zoj`*#SwKLIbtJj|HE%g?y zo?M>PD!o8ajA#_cj@w-var)Nuc6Z17=Xwf`<3atYOI1oaXBfzoq!3c~#u%ahY9)x?U@qVq;AJ>_ zI2z{0`L=MHQl*(Q!$^p@(v1tX80r+y!mbp*4X~2k^$6!vOF*@OIE)#|wBmF$zT8axrprqN=yGFi(rSwO`&R@cW1WU;c$pYaIPz#IuE3THW+BRXNPqJMoV z8~Ogr$C35bu7+qkq<)AL5T}^38X0z&0OBIU$P|fB@8*{%ZaEna(#!GoF@jLqBrYY+ ziC?~}RjF)lJxDc=VoIglIJdVpZ*D!Ep~PI~S@E+NyIPTLG>>K7K}CQM*V^rxHVxxn zYcs3}nPT3wHXqom!*pz6`dilBl^K$0??PiQ7BcPn7i(?tyUKq*4iW9TPp}gLRhN4d zTM_dGL4l}HlZ*&13`Bk?G1W2tP%}iNN#YV7CBru^Iad6$ZGRs*gySSrLLOQ|8Y1VE zG+g{FNyPA?TkmJs|TML;@2m0QdwVePODhkOEt zg+E-1Ss4bv{!@8!*kZkd)1gqwNhadm7Wqa-JPPR3Vf;Y0XdB^l43N4Ox80FiHX$vm zYpc7vg@%iBK;e?ELJLw%$g-v1>oZ6nr_Yk0DR{Yju~3t5>fkWRmFn20^dQxNF;X!~ zq$kqBGeO=QdAa3c0jN%f>CMesd>%hQMRm2#m#(8VAOE2*SG zRX0bldjR64_#o+9ygO9VPF>%%^gKWLD4Rs&t3Jj=Koj~XALSpPObRfGMHM(X2HCom z+KcLSjGP?FDq=Z)pDgc%_Cazx_aX%N@}4~9vqbROS<;p`mOM`3*8D}+Ui~U`ojSN8 ziDkV-Y-rx5sEHMs%XqP?nH>?>^a`0^Npz9D^0dVus6=`ipB$%Kd!inD?H zm7vd1n+Fq?cU|dxFe0g=8GQP#_~78ySSr=u4I_Di=t)8EtD4)IuxZp{ z(%6WOQVgQqXk1e5ETcv)d^e z6}g?%VE4*q;Q%Ct!@;}WuYG6g#;IsPi-vO5g(;2V&u$;!f)g4>c{il z);bDS%Gk3T$@Je%+Th=H1EgPOTWa+!n|K#(EmoRZ=% z^Qv?~x-}V1GGVfPgDBt1$3TJwiZ37%at9m3c&dEmSK9s+t#% z``M5ez^H?)43~xrQ3pxN&qLJ&$mE%5^apaHdip?hU|^s%%I7+@BBQZpL9OsPKm2zr z^=D#4qzCAiQu2ZSL^pc%u?YoIA^O9kC=iegZe4$jKmXbF_~Vajk5}`sa#p=v>RX?E z{L;rY?QuRI*Dfn`4|tbgV|8~AXdh=gO)U6QVs#vZw^sC)e{koy+1UBpg zT_5fG6t>Va_(=bu>)*95jVd|q0B= z{L16^xvh4TV;L5#fo!!;R{La_ub~3om^vJ%xHQFEgVL)%A0MKa}EBMrr{59r_21|6!t%>g zeKl`=PBlL-p7xh3zM`qcH~do9LHNP1MW&4~ZwbGe41aNn`4xsmHIy}daM&v#h)6dP z>yu-XQ04fli3o4xJ$fRu+(!L7QV!NGQW*AokxVp`k7u*pb?E8_E~#30A`hCWjQ1bZ zOH7*SO3wSOXlVDFzzEoxjkQqTj$5HoORqLCtQw`nJJ8D`L)o~M&(*H0thLd~KIT-) z$#P2TyC-N~*owNZ5is2Lo};ix1oQT(3f-h*M+q)Makyga^=cC7K{=&J4S{wR&}~Ht z+W@~NeFRll8HqU-*fB*PQvMjRgtWDGCQ&F|_zo@)bJ~980ha#vLa-1V10GcCjn^{MdJpJZmB+S~p^ZKiaz)*jS3C=up<=HmD)m8BYYMK77e>n zUBm>O!@EVm_V^P}sJ~2i=+@o=v7kAZwt6n8l$~%-FlDaKJaIfLb=gFQ`Wzc+I3C8( z<_=(^yr=5}SgZXa>!gDzCH2_FaZ*@l>X^A>t%0!>RteCrj^d-B z9a3JDlle9a=R)CC&PrL86Wvy=8#=uX4~)NRAk;bPbTS2JdI1lB54-ce2|64@5B;`!J+^P*6qU%pV{1MZI*oaGqfFYq4&Cy%rCM^Wi()qG1Lo;$!K?m4FwaE0sD&FMS*LCL!OC z?&&)mJ>t{>ZQ+YJ)$v7)6!l9k$ulr2?kW!CaQEJ44ES?7M*Fm1C+Y1A*VUe#X3mxv zpnSfDX9)5P7bDA#latkk*X5F~E@JnBBoujrGg~Ha3EDByC;`nJ!~-fuFy;SJt`d<} z?5s<+t3=BNWCV-U-l(_3V?&>`QpwmGVk9ksjjLO+a=s4zEFAc;^?B#P9@9+kopqQe zPcQH9HZP*bhKlg`M&CewaUwxL*~nZJ(^}nEF@xS@mBBn&P3?`q?DLNIzNQ5$EJ(^X zl=I!W%-(!C#-xb4^XLw?GqqzNbLA8mXrGQ%O5=>t+1u_E1ukJ zb?evPWL2oj6kF}xP3wUc&~97}H*U;HS~ta~c=CK&J^4ubS3US|%5zKKeG5L=OW~hw z@Yd($$;s1^D5tz_dFiL$Io5_72GF$JUB$V?uVu&B%a+A95nEHNi3iM*xi3m=vKXyo zsPq+00DRY?msb1)623C_YfpbXDog6)pH*hbKTAs6yG-+H$xeuvHEmXQ@Sds($1kh2 zLj>Qc22jkri~sz)qw^)eEPhAKb3dp5h9#MTSB&#EiD0Cws>CHJ(D{GyoL5A3RmReP zO4|l|x6dqn@xSn#`qI@Z%edw}B~Pi%Er zRGf9dmWWr8K(l-(_A*Ozuz&Sc@(#&g>Y*w4w zH`lX)0uBjixT8DlW5@^6tcJB)957GbyN01^BthYr{bD|Y*OeMT6?cxfk)WN7%uh|2 z8zCnvaOsm~u~Z$Nn;Rak?!+-kLV{zf@x9zGGuR_nF}?*#A<&SsJ3xnNSai5w)h@)= zmRqFLLSgY4DfL^`VWMSFQBI|#VMxAqtU7nQiokr#(qpvCTa)K*m-Xpn$ZwOdG*E0! zrNLvA%QTF5fndYFRW%H4(e&<+hS82S`B9-=yw6$ZXc)tKQZ))qLj%p3Q?+66pVBmV z*YT+nhJnxIC30u>=tuEn`zeB?ErPIO@Uo@yE9I+2>$%&VJ`Ep~`HD?}w;9SZSnhT;pYbmlPz&ZdD}UNd{N ze0Sv%kq`$}+H0kg@ap{C(-e6;G>u13I6pr*tTP`vx6))-qh?9ygx-OB;mWwyLdl!9nZ&VzN+g+RW+fDkfbl2 z9CdMsAqJGCK+ab!><7oh0_3%nB*R&}mc0^N4xngED~5Hy{kGrw%xe$(AMc0P3XP4CZ_@^>7%{p20T zN19XfW&xH&wWnw~9}r>R1CaCYt%!Uj570>%8elqLLBK1Co9!YalE5d}vd&$r!t zJAaq#mZF5M#B`igb39*$V3d_R^7+FB3OyEVM~hz#x@zaeTIr!9uf2T#$=lv`cW9cS1xNqNRLEao4c{UoXa;i1lEo);}o*l3hG)vYc9PpAnfL7d|?(qUZp->F;}lP z;Vy-w6c+g~N?|Ht$K#)(+;6H0g=^%JWwE4x_?q(<sPIDp!Ih`J$l?uYRzhuYCPp~A8BLN zrei-fJe+~~ESel0zT%2Ctz?wYWViAed=y=KHQ4^u$ZOrG#U)66{S^n>HcYRN4Fa@RS*jztak*7gw7jgPP&ZVu@&9OBO;S zdNKPO5oWbqH|Z+*&z7}M>%Doa*3^1Fo00@c`U6q_J=&jBWvma+yLh?|a8F~o$uU)j zcnBh8)o}9CX(L{-J^{+eZ$h!R)@oo-{hTiQZlGR8l=Dum|s$HP=hQ1PD}WokSKkQ50Ou%Fr$W#SbF6X9hKGx&g&A3#`|Yp;gihq7_aI_9vwWW$!su@P4E< zwdOsC4j#IP@W;R84=pZf&$bTT<2~1U`s#b{z53@`b7}FA^h?oKegD3tau#aLSM*Nh z21kGq$f=zU#it3@AjX$7f^unTNg0q??Nu$<5n^VecimAxNdBjTgq&;%jE8@3W)ays zca`?}almjkoN}N4ZYOx{{qpBO*Iecnse=^pzQ5FJ)oMRKb6>*sS_Ch@4$TYPxEAVX ze0N+4wGAroa!^@LwjVEa1vE51RQ1ho3FgKiG^tf{iIjEsb})f^^|jqKAd+w;>4_s^4tw10l=_#SO_^Z1^3 zozCO`(Q?Vs56rJ6duV=m?N|29GOg}8-tCte5ceD}MCZRBYeUM6rzp>^R_zwSUh3Bwz)piIT42j}?}` zNUBD~vQ%1&rPA4S)dt-WCB!Q5OaNJCx|&WUa{gAozRNXZ2_)6Ov>Ud)5J(?O~bl^T>HF{9N+#|PE{ zP3V;rH-D@es{`r{h;p@2!xgnw8%1Et>)}mFTlzhIvfUYbd-m+nZbw6)S?T~okUdtR zR3=NYT%yd0T3?e^QjKBPs+)tGt2LXlW0wmC1|ZCy=M5`vlyY_+V5^J+(2P#E+dGym z&~-zF+-R=oropbjwit@#?OcgMyCZ$QqFMHmKPwpK4(CxDUb?+quSd>j$3!{gndDoE zGgL$TX*`L9SCzu39uD`lGOn)o z4VO{-5UQgqOWnf$2Ngs(9QzqxTEzeU)j#!b9ue|PpU2(FG)pg*IZ^3kxe1-%$r8)u z7fa0}4zt4#m=Xk*K+<5uIC$0%VEg_C1E-~cc>Vm@KI%klWpC(gjp`%K^Qkj+0Qkes*<}#AoF|EP4OlQ&{RLBxsH1 zF-hqa*I_AT%~+{#N-RZzaYj|y6_r`roIT|`ydYPH)VA4|*o&u+<2V3+pgK@}cwbRv zVR#&Lp&QEN$leZ$^xX(%Swck)|M>wvijHLWmXhICJ!8U?uXVgl2 zS8MNwY%i52L)-$X@M0>R*590}N5B4OR8y=1IQY5USF(RW+GS^KUruZzE0u=E`!ME~_o%wv(D(Sb&KI!?c*U@U2 zioWIAQ87rvlODH*IFYGS_T?@1_aXBcoq( z#~1^4ycP;tA@XQQ2<9u)-H7)T6FKm@#9V95p*OwE%k4ebX9uC?2Ty|HLLPEoWbNA7 zT2LE^03T7doN$|5ik32l&bATM47QxGtI@T61zlOx($PhW6MX?&+SUPo znW0U^Ojp?^CEttrvk$#u#O*5*JMGn&#go z`p|bc(|a=M23l9Vfk4{@$=5$>Aeu#+kfS0)#%7hpt%hovw6(Pi2)wd;L#au zlKd$$9L3d_^@0KspQ2LyrH}j{w#GZt8Sp{cChgbfJI(OAQZM9y)4Ph-K}45~lFXzi z>AJfmbP*JKwEsdg8MM!)r|UgWZ_1<}m)5@T0EpoOn=9|+#B`*{`Bn;*nSja|8m_dR z%xS(1N@C-!>6-H;&@zHZDmBwhls87^D`^hV;DI?P+oQiCRB$UIaI%AvC4j%Yrj&=? zA(QLFAQlbdbFf!vhYb*}-aQemASPJEgqBAN`XDmApK!-DD3y4MkC6k9XbFZ6^Iw)f z77oVqJoE78eBMyw75xf31E z0Xo0RzfnrxC=O61Zcv7O&VjQZ`6sXjfHwc3Jo!(T7k(HC!jF#$StytV-R0RaHVXm+ zhMraOg4Mbd^w1#A^EL%z0QA}ogd(*{Y`hk5f%9r=&`%Qc!!16om@89?D zX>b*3ZFIk>f5IiRelIM4#XF0&!d>h|&Jb$~HCbWXcTvpgj9uJ^G@E2}3sa$Zx8+6h z{*+3M1ENAslg!kjh6d@0YNJekygh#)XEXS5Wk3tgQM{X-opL;~o3GqR_zJT{uNFnw zCIL_Mb8mK;D$Q6fK=yseFI=fdc3oM05$rk?=!5vzfl0{9^*g-{P1JHQ>YrTZ%s8b0 z84zzQm3>0%-J;SigDvnWbZq}LRyJ-b6$xMN&WK|fhp;HCccEmlxK~7-g!@SzhVHrh zW$3Jkm~p8z0@_z;j^2kedM}wPaV@lc_Q%04>GND zUwDZbq|9@W@XB`!KQOE5w#(~gHELB9(rZqbF<0fMBMTeau z7%dbqbhiE?Ns@8jZ+nmF_vYQyFTX)EO36DuzVXYHoB!$Kw43P8;wyMSuqR!-K53`0 z8YCz}6W|=gR#6UJY0k+(eY!-&>ydJKei(q%bMyPl6u@Yhr7})SgM@ zbLnSr1bM3sbdaa;0e!5py4nACXOkW2Nh@4rK@8}`RY zh3zF{5ipZEvUWpw+xS-n@y)x%cH4;U_Fg%^O6W&gi`@bO+CV(h*TE%>wX|(Z59P6~ zZYl<;vUkrtnQE|jlViINEt#&X-*hSuG}<}(Fiuc&`*yS7K77<^1oNk4*wI&C>YAg5 z(R;B`hWSn0%&%6bE+UhF3a9FdwNqvbK{xrUhqOX9y#3=z(|T)fpqTj0-=y%HUOIu2 zoBG7|{CXqtuB%KvcPwt*?CQ}2@3O=Co%TZoy=U7^Z7{PifNbbB}$qIB83Q7wwnM2rPFCQ-bG7{wa#A{YqdW6 zme<@R;n|md=HwT)Xop%Y;pAww?rz<9*8zpJIJkL1@j+b4`@5dnfrIGK7j|6<&hy<} z@9+A!$U~X&un(2;EC%8PbcMdM(P6-4`dO(RNzap>NSs2PX!OK$?5EbV-z#=gzSGX> z{G-*`!t`rVa5^Vf6QaPLP{~%T9&+h*XUMu-cZ%LU=rg|xZ>#n@eiyF!U#jyDqC$up z^yS+ve{8&BvlU)G`V+2m$}f$23NT2G|EE{z1B!-?5)G~*AYLcObdC(g7(|_O$k%Q1 zAs$`6`GbWJIkU#R{j3}CYc8yOqCuo(3?V5uV*aTWOPu*FGEsC2|J^QQ=_`z(4wioK zG?sql>yX4bUuXPnWc)FAF*$a)3kA9ZPD!5yv+O+@uf%^lUZ}+1r%lC^tb?A? zd&IIHw{R`rrA=9<=fHbqww2@%CM1D=Vf4z}Cn8KHz)loDqc42rE2%2kT702DrBZ*) z&wO`Ees)*&;jesEzP036zbYJjt>jm~k{YSX)+!FPmGd8U^2E<@&iOB-_=JQd2!)ii z`(>XFLstgwxo5-|P%k6f1aq+sA?0i%0LkLHCdX%0O}woz>S;@||5B9NG4g)J-t%?3 z5_;4k8Dh+o%i=<0r{4+!;O&U3P)E=qQN-n2n-~(t2(h)$B$j=^B6Nw(D_ufK;D;57 zW@=ILa;-KgvBq_-vH`vAScck>Vy#y6P8O+PSJSpD3()%%MA}S25#zfVoJrzWGIby| z#`A`Gz%*04O!FhA@jRY?_((GK;`4HfZ$4jZbBqybG^U@I)40k5#nC+H%6B0?zF+w+ zI*qPg#kpJlbE>Hyk)}LXb1zEsN@J^Qw&=4TBs&MKS*cqxH=sVtyhIp})>F2#I9Wsw z@by*YO7OLUtfB3)VikcFfvNf3!N#pmzN1k?9|eaTCwfB+>51u9JgIU*Z}xsjG9m1( zT0V)qyR~mm>s9Y~$E#X<`b=nCK?pUDZ8?7Vo+sYA~Sr-53*^BxuwOX*eL=>AmXzx&ysHpZp#DpVxsr;CC2(L;$r9H6Qdmeu^g+j!+ zg3T3CzwxuMLP{OK{5M@l%?&=cGOk1fnB+y%xiQ23H}uL3T}a_ZiSS6HNqGb~iBzov z_+xNkoRd`1d7^BoSy4o)|;K%;o~>DuH~TyWY`80RO5f8qScXg$)H zF5X?Ld*iBffp1&+aqk$>60Y7QZWBW)zqKZ-0-2P~R7ulA#6chqX6$bP$LZz8^Pjm} zy8C^HFLDw&`{H@5< zoyaTU>J}YZDZL_9bLmcZ_NP&)Oo131p9DQKDMU*vq8=J~{Yawi*;F$87K*$kbKex{ zqyUQwZe{qM zij}NW6f%fis{Baa&u^Y^XWfaL&)_7`sK2WU#6fa%z4t$M$Eciu)9F;qNw~4y7DtxvP5P!^k0mdoBaLoEk5p1bMGobi zN-R~fA-FlLHKv>O+R)wF3~Ubb`f`01eY26t6sBee5RP_Xc;=9G|9P!W~rEX)YjsU+6nty!}23e z^cw2=My{dgXY%WGZDMc>_?9HUtqUbusZnCrit->5LHV)#*;G17C$K3lLx#ba_KdsX zvDpo`?7nn^RiU8Mr7t|D?V8%U^@62!0E8>#NhBYpmRVB!fxBVDhR1H%fSLny!ljSh zd~EkrI+Mvv=H`*9`P4_%XEM)&qZ9nHYl?f4d}Yiorgdp@9(pL8Q|bVde|u7U%mtJ> zj2-+Ng$KMJrwZ>Q!>U1*#kaazZkTa3^+1oTk2J`ydS3zaL;N7?)Oq7rY+VRB&bgM^ zvXu)XU_{SQGKaIb`a=9v%{*BV0EnL9N*lD)4Vev``e#y3`ewhT^s(-Rd?I@!t!2Kp z`&h4S#b6f6?|xE0v6dY-XlXgZrJo%mjHV9j?oMQmr1kXIF3TGMhEngb-M_13<3-5E z_u?IwdX@-ZbW3qEO}0^F{HFIM%&0#Sr1x>xcmk14XahVALq$o{)4nNjp)$tRi}Yil zP`*vJuQ%)jG4D`zO?z?iWSfCdkra*OdleSGky(Gq&h`CQQ6N^=?^3H)XV-sZra!@9 z2?>X1n>*ih^kUNQP;ezMp*_Z0%T72m%{I}W$!t>{^*%l^agzD$`t|*%xIo2qSz6^# za+Om#Gi!G4blH_Z$-BUXQb=0WlLDsEv2T)C*dtwY=!W}2v%J~2bC@SPdX4f4(kYcC zv#bUQlZZ%T5yl`vJAzG`Km>_#`uDkh)|4`^eE3->npeh<_M9?+UV2^(AfoLUKm^Fh z;qn9M=r#wCD9#unM&TLB)Fz+KW!vQ;U%s^v>wJE znaVPt<4if>K7YwMvw(rs*>CUZ{Z-#e((k{-c*2Gflb@CwlCHBnq-ii^DkvYAa*I9n z?Q$6(NNM-f^aqc)RcH}9d;^dnkh=iwZMk%KZpYNrksWib>VI}sTf*4eC6ohV^ZPYx zYjQOa9wIG$=ZG3pc*@0mmo6!|ORj$D6&EcIUps7N>xl9A@PU0hcI{Sa&=S|s??V_@ zbGfjY&v~DTQ&~J&T~p7xzwP5SPHFeA#>!XM^=kn&xC7=EPP}a9a49q^x&@&Y`i0EV zvb8p(z320H!YHGXPlt*4@$nHlJi2`iR98)?VokGE;%Q2RWQd=(T2yjm z5eh6R?V%fxVhL?m>Zt$3;@xp*Q+>L2`1s)(v73}p-gjuYSys=pJ-@i??2rzSePiJq zPk!es+K2by^9jpb-Ob%n%~9Lj3~Z6x*6JmztWGO$=dXCSCsuo zS*4Ni0fw=^WP|eail|x!wuo?Ig6)8Rl&GprxDu+BJ)m(_UUIcuE8YsnNv&{ev9^2n z<7a-QGP`&G==3HM7v8md_hVLMx0qLvCZG(A20|W&xf}luaV}O8-~S+Xn5r}fiH7k49*S|#OPpI4y!30U`h-6ajA%aN~5mZMK@qu4MRPWQf_>K?1 z{m(io*J}bWqJ;jhQy)r9VfW-aE6){_Y-CJ>#qACs>s*fdnj^2jMg>vNmAh5 zKWF6!T)z75RM2EX*}fhsGV}$>-?V@IBIpz5k3F2_NF+uh75rih`5c z$EjHPk|#78mug#m=Lm#v3;^XP!8yR3dD=H1ae7f{lm|fhxRu7&317O76@B3a;%X2> ze4<1>!k2b{xP0s}oF;gO#W(ER`3};1RAqYiO9z1ve_}|{7`L_lUcFx`I4i%ASXTaY zD3_F#_yuSjf&Nd7pVFe`?0~zi;{DI9ROI%)rLEpZ7~)%fO)S9WJ4!UgW)=2E{a&}? z_HEx@IdY`0=^ad`w{G1k;nc0J!-{4fR@a9dh|%ceF%|#x?JkMW^(woI*+Xy%KKX=t ziOT#E-z)eYg<(=r=ifnrO#ND_WLSGTMim8YNKxy%?DzK1&kH&*=D&6J z(biyUANgO5y$hTi^>ybv|LRwDb@i*dySk^Rr>Cc%~&R6_=o`{bbTz~Wxevuj5XW3 zds);&`Wqe9!LkN)scr#A)OzhxpOW==q~k;Cb=uQMlpo#)PZ}XXw*Q1a`>4`5Q`@lj`?*R;`;`AhVk ztDZj>phC6k+tJjyQd4k&*nYpa*N;Y13sja-KQ<%EBr>SkQEkz#yrnZU+foD16Ct?G zvFvRm{WG664?mX}J)yaOzmK{nGV3BX=vklWLt~Y3&>)^R>(}EUI*v9^ePpGNU-^pk zkq$T?Nw*1A%(;p5-O~%{Oz!zyF1bK`Y5g%v*WS5fq(wo$(KB^d>qpxNjMigg)3p*^ zYkzf8+X!c;f5L-Iex(F>#El&yB(tJ~2h#&MTRyXF+H8OKu|VpATv}`6!VbD(exR>c zcfe9#GMFaJ&0;D(>uc*n#Wd(`oft{Ox2;7C(;CNZPFT0L6IR9Jt&e6fOJw9`?mer? zuUh|oB^eUUJ*y98cEY#!LExiiUoma(Xfy40%lqHjMfI1(bnEBsJ}A$9@az_z`A@o~ zIvJNVT>a_Um&ez1;j8VGTjDzXMG|9~bX|YC+OM_kPvJ2gL1twR+GDD5k9rn#4>VoL zto(bkU|md;TiO49Fj6Gh`#(IP3fWb~j`qbT9rriV~pi_2^VbIy^Z0INrL8HRfFym9R9{w|FGz z66-+gcWv5w=L1Fs)R*uR6Plt;bL|@;mC0?j&BNTbd$Sf~<(19%57lJ=(8$Ko`b^4= zNp_C6eIHvv+VCJtv=0?&S3w zn1X<{fw*)@C?-Pntp3e0&yk;{5;Gjse$9Et=^^4(i%10HLb>E|k#IMST&?QF}zPOY{PgD zF2EQ<)3iX>UV+kuv)G-?d7Jg=)!6Qb91<>=;Z2KZaQhr}poC~w7{%)luj*(o%AfP0 zhj02UU*x^@gR?oyqxU*kTx0jz*2N}koGi%SGTcvRcRO56FR#lVu5cHXybgUR@lxE4 z9>ar5H}zhd2gIIhcOVyeM$Gbc2;L+3m41;IM>l`p03W1%(e0o0@tOJ0yG?I^006R-$#B{o> zGGj5Z;;lJJw;sOSP9~y#hwYO6X(FpylWzgwJUoQ;C!b2Gv^5EKs&$|JVb>kK&2hdJ zQ8(G)(5AP-aK2w9>lpdP@@bLd13!Pnx+pM>^xZM1h$wE8E6JN_T|lIn02#;c^iqWz z3)MSIzV`-klkOYe7`L24%BvR6yfN;#{uQjIus-sFEZf2b+rJU(LkHnoVwn~r_|`y= z6*BUX_{*^$WVG)jn+$AZ$VmV!dAC5LASJ5rcm4f}k^Jww;*FgHtv?fBSTPjny3`5( z4DAXVce)rK*f|jIYJ{9r=&=xH#<2QG*FSjnI%7uXmjgQ+-w{w*EaY6)6$q*S?)zfv zPRp5rc=2~bDTiOCC>1K>(ed-YVm<$?gPfu&s{y1P;y{zY)7G0QN)Wc*6oj^V;dJXM zQgbbxJ_X`h)0WX=LZC44hSdAgqeuy6om8#(U6)_p`k?mz9Q>JzJ$+Ye?!9f-qx`n5 zOBF<>Cy}S{Rr6O&Gn8Y}fQ^1=Mr+FgF`d-WBQRn0`JX-6(=$BM*VmKiv0Z??vBxMgf82z z)nqR&bzEf4S~p=$l5A<I-QbsDFshU^bInn|PNv3$cS z=m{g(HWe8$3H@klQoU|x?aD~Swp;%aQr=u7^vfeX`FTH{&wnS8xh{#_v?r9f;^tUH z$6k^pTwLybyeaYk+4gj!^*xEp?y@%9cF$;qyZtfPy{(i4cxdEkJ|EBbRJc>P90YEC zeJ1fZ0h}?cwXjn%rokq?n`1IIv6~yys;ksceGQ$HLj0*0K?AqI(GPUoLGPy;dd~}J zAE_7&1g38%amrQ%1bE5K~j3L*uKZ?(3bAXo>ql3uBTU5Wc0l_WV62y;g zMoB9TW>;KRA{nG7PM&lK^``C`5yh2(QLh?ywpCLkKn@eXL4+=w5rG4|;ORWF-K%<% zP2l5+#KROip}_M?+sq7algf$eD9(19;wSKgM=F#=@YS_fU!AT-ob8mk?kAzQ6RBpi zWnfT5G!xQHK^hC-H^v{*&IdyF=)2B8GLrP2kHo6(-O+4v>~F*)$pj^0tw+pgZexs7 z&bG=Bu$GECTJhm5@Wfekh!XXrM7|UBArA6Y#0SeIWcEUh?aSBrKYrS`%q%J15DVHs^9^?Jm`y~A3JW`h1qaT!yX!td*dyJSSCn7&ecMlA7 zw;t<;g_r)X`zZH*o}EqEV>r7aWbD-Izl|jqs+T9i0r5xyW6|v}PIcL;`*0LUlOTU- zrSJ&+UVR*Cf7k3@&W};`Qb0{&jl#^deMzDikudId9c);OuDj?|2noJhhkQ6oPT5_O z6Kl?Mxw$~zmq@^5-M34p+Kk%P2r&*7sTcd&-`hzF-1HP0w}^1AjB?09+YaLK2`)`IUn@ADtS zkbaW;yw|jz_k8deA9a$S`)J;g*R{{Q|8vP~;r`E==i+)bd;IPCxvtn7`x|6Ar5Bp2 z06}YoQ|5vGkum3aeRtpgd553PzLH41;`#nVpBouz-;ti&yd+P3#;v-~P%}GU{{+ua zL^U3?;?@UckI00e5vif8S=xV4dy2)@lch3Q%dM+lOwFghMGS7Q`cyTUg3q7mxJUia z+KDX`k2$6rZ7LSA(EM7&L@f|3ADVouUtBx=cze>RpYd71BmF=^s@6^t$o>xNi+x;O zC`aV02m$(gRmMWvc@OQB+RIp8jZDXUYBSoz5)c5&5@C>Qy;L4lXADRhL)oCj=Cdbt zm~o5=bx6%Yv1#>?_#saPcmc2()?c5PW6+w}=j-hu%r+kq^tJk6-cK=i}?`xR#Mchi?&$N}zYpUH&*+Rt+&5AQL%pgk?hJMivroGQ2@0(z%=d;b{ zvmae<_Wjc0&)u(gdnqgp?SJ%heEaCm^B~N7C=mi6fPfbLAC*$Xu(A7$c zTVEws2j`jCV+<6a4qdz2Pd+Z76N}M4%-(yPIjitpwpi`3LOzu(R)&6AG#7PBWk%C~ z)|m_^6RFmbG-*-`FMcnb_SL5ht+bBhQ`Yg!D_zx;9rcpErB_>xA<0`y##xQcRUHp> z>`^aRci=7R$V{}^tb}wxCYt*`@)K9`thq0}B;Zi@CoYwzUZcc-Ta9t3QgB~$X{aJE z`yTaY+=n@BlSZ58$u21O1wV~W^%`1LL2ib6CQ{ zXGcxsVl7KGG)PH6%!n1*e2Cjg`-VYa85}bLkruRmDyXkr0FA_Yy9*@`Rnj1nXE`tU znqSa*-7aGb-er6l0$@J-`H<}D^CcXj?f$CwiR`5x)%q(cIi%tmth;>k*K7mO)oW?F zFXVn&y;ldqLk~15z$*zFGGGWYcbKjpyOwOeT2`01xLpd3`HST?;k9mM@7GB*{o#OimfzlPB}i}3VB-z z>~KP58+sEQnx9+W(^Rhef3cV9ef6yNRY$FGeK_a#0ZFVnj&)KuM?oPG;_6y zXN10WIeMpEk-pSdF~OM2&AJJS$I`s%8p-P1ogJ;vz^IE zv6-zW6|Q!Hh)_x99KGUjJc#nZq6^5SBACc-4lYq|G~$?ml{7?7)jW|~v~MS+(@dSYiPS`iR(0+K2cp z35VnsFk9t9#eFL`yJ?>;5WjEpW;dR4T2GJF`(xzrfIk*ui{o1QQ0-$9 zi6{s49TxSgh%^k)nt2l};bxA!BWABdW3(70I-EyDlUF0@$*XWIiO_f_@ZKK@O|$x9 zn#RvsezMp&@Qy&f^(>R+i{EKwzP;^jOo(0xFuGN|VZh)Z#fSz^HGRmwLsR#hhDGcW z_TWdS?$nF&9h(+AO~wp;+MfQfTrQxt)%6-dpC#WIY1}B3CtOzpUL#hUABU^zORaA< z)m@kGcwdv3&5yN}-2bRHZ9f0sl`?E4$oV3V&jBaWy{WYl)cBdm=<4jSzDURMO~eFA~vB;@{QvBpxISjJ9F5u6~g8MpQWXZd`pt zy=*=|Xe{0j>Pugai*P0~ka-5u6l^nTUTR) zE~eG5KPY7ms`0;!qn_=2S=Up*IA1F~sLLx*h#@ULu=UvWHo!aN{xn$YQpkR?=BG%^ zyQ+^Y>RY%EnraIV@-Q0jrLB8bpR2nj59S*8FOhoJ+@CS(*Nzg1QM7s)tTaMOd(gs- zu;PAk8Z3=;;}6n2tkBZR9WS>B?>CH_q4nPO;Jr-O%otq>oqPZr1gJ{(ASQv?7eAuj zGutdo7oCR9Nrg#u)c2ls-Di;d!rc0JKz=eYQGO;((}NQTJ$eT=8(tOU@< z;ihKR+VS&ua8YZY0MU%o!rWi|MlmgCpvwb#3R?SaHy6|j=80xa8auF$4QhMG<@8y) zs_p#ku{D#53l(lD=gjtD*d>Mv?fR1iqJN`}8FHz<-W*=pau^UP7t-#DtQR-_1-?ni z6EW$U&Z@6nw9*gVdd@IprfbrF84>H+cGnm>Jqm8?lls=}%goKy#Rtrt`KqrsSLsJ- z;+CdB)_PrTegb znRw#c8QPPGXTDwXGKu)N<+`}|9)-+j$ai^KTMc=LHhnNY;^49llCq)|Hkm8l%p}yU z^*Ci1xq)db_+W<|Ro@i9yO9mFuB&5_m?Nz?tf=*({D?_P(7^`wreV4&PY$#%rE?@v z3WmHde>qLAHZoUvU&7;@D}O1S&5{`>l>Xh{O*`3KHvOff_02>w_tLc-^yF99UFYPo zp8V?Cm+;+|vz+2aoQiR(S;g?e2~nHY>?u)j(s035N!VhSHZmV{gEaMaS?_rw-9)-u zc)L`0Eal#%#kjlNAFK#)JkR(x1PkY4aXJ@mSUmJ~k=OKAW06!=?5jSzsF=R_#54=d zwv|wgGZF7iy{0t{E0uzEZYO?)cw*!F*+il+JX|Q1 z%j*kyMyIgTl#x?(&S+abW+rhy65B5*7;LY-d1GNxv|DzS9yO1<2&%M zYtEa?UT=w&FdUv=+9rv?i$!a2aAAh^hp_9-pQsiEsweQW^4uP+XQbfcUuU-;X9i@8 z$kPaUW5hKd5fw2bB^Dt~Q2?aH{6*TA=*7JMvh9Z_M@zn)bryz(bl}F^%yes5`_yL)2k_m;-W-Q%r?E3oGxKOk3CpJkC< zDjF#SkMG`ne772~dbW>logX>>{E_+jk=lNBQBQw=Pdt9X?0&Ux^X_5HS)zG3p4 zNnO6a!Z-NQ?x`u+CTX|fU*|E>v{=mc(o#*{ny#f*9WB?NHLHdn=m5r5zRiMY2)7Vo z$$vkKw{!B?u}Odv+2=?+0F=r|`=O^ngEzJ5f0)-#8gf$jLNcCsW9)e?Sl)>vtvJT9?KaVRfTVd7*7w zBEsFoFCs8sF}6cHJ-Uzt`!v+0i6<|@s+pa=iCz-?6IuKFHO%~MF3HRMpzIchgd7p%imx$1iwGCbbXrc5fdobv2sfn>K9yIwge$0p+>hE$^D# z9&`H#O64Aor>Y^6wV|vwdqjoCQ}@r1>>z8`j5Z<~ z;&!oIv^gZ(q2A;X!zo4r)wI%&{{XxA^u2!p+%FV~@>3zW(#W^-RjCnCQ)3zRjW-hYz9)pmIH%XT9D73sgkSDUzi z^=QOn?0TE=SDz1G-zS)F9VcL96u?H1ez#?8ov3qZMunNz5G2l!Uyd?Tj4MG7ml9yjp@2j+b|)RsB-FQHXcF}BMi_^6)yI!5FKm5?T zKAK*_wBqdYvW0r`+^r)URK2tHcf9)*Kl$q(@^$})pJFn{1~d3tvcJ=bdW)16m3dV7 zh~GoM1VbrEE112;>a#dEiPM3JV*Nr*A^|;l>%w$lU~JGONu6ZajfL}p=_h}7v3iBT zx}4`x-XSI@C`wkZZGG2!KX(2aIU|Dxw+^Dws-;XXc0)ECL^y53W?01NETdvRexcq^ zvFZLVJbCM>Cy^8{Lina2bNj;&Z=b01XX5tTC92{JB5W4Z2ikACUwBJjv(6*8Cbm?G z$udEKOoWk@*%4CI*7>P1o_@zzJE{1ljiPN6D|Xe208JJ5`m}YPdPVMqekEECTYrlCA})xYV-^pauqGiH8qGxc4O60uCz~_i3?0E0f-_9nxT>=5je;o5-q=1R zxH>rn>@J(Q5x;WwxtZoi!0w$(jhb@-?|lUPq6F!y3pk$5fmw9UP35v2W}9f|-sGVItND(AE?n^Qy0Bn79E&9X{ZdvU0H z$x80iom5g5q`d%b^%+AO2G=sh6rF zscPzZiopR7feufTaQr#!2qIjF9RYII>b+LRjf+4iQ)>Odfmpt{IL|*JfxyGVIt=&( zudy4%J2^6#L*i7fz^AvyQE!KE+Kf7w;q4z%T&v|v_pI3Hri<(wu-_7MU27;AwfS0j%j z+=oNPa-n{2j(Pwy&DIIt%BALf!XW_~I3B08SaRGs<)CXPbm*Twc`cyECj9qTv;w3_J@ zU4UkUI||JRnYNK@dcfI9R-tPeKx!N_>{Dc8P@n{nJtO&hcLiIg~Q_}unah&?T-8mGcgd%ZD4nF`&~1(%;eC+2o6-8B97godxWnXXtM-IEM=^;8DK7i9~1FB4ae zstl7^w=12ltAX7o+B9u))j`v%J;0GLHq{4zg_I_QNXRE3HI|nd#!8ySCoapLs5Sjm zY3RUSYsZeebg{(M_WYM?`{NJ?xonlou)nAC_YL1!r|ojQGYb7XYjo^Q3D8|(pBMGm|A=5+d7D_H@2|Bq(Z zuP>Kp50FiCSE+QOzh_W%M+$;;+iDFO?RO5$s-E(JS=wgt-;7HY*{-9%ivAHn4AZ+4 zFIsWcIaIVB2G49`Z~Q4)Sn7TXx!CSd3WZy|E%w)(TlOEAI4 z#XqizMSs7$ioI{k?BiQz)p~3G(>=A2C`wLQr%Lz4vTf z&GLfRWt5c;53j?MWM38At>_tAl0hYDOEj9>>m)B|U*_F6IYG4=E`F_skmlMu={t&{ zU+%H?p6qWcHz5NJtY0=mG@pdlo>v;W1}`Rg9r|*Xm2<;ZC_whtWLGj94kY4{aGX6* zg)^zHq#X$a0>QAG1Ny^-!2p?B^@SlkW|4SUk#9yIi5Y&}zV?qPHI6|lj+Kk-mH;86 znOL06X+)TjR@g2j5uq$AQHsRLstg=498EYG!aL+Ls)Zidg-`Rww)Q8L&^6 zf_*9p9x|iFU2RMp(VjXZ>>2?KPY=4Sj-6pX$2N(8CR{*Bqu!WPe>grwxMeht$2`PXFC%0XB<-McB zpA9ls!;L z5L9Agd_q)gP137xl*iJlh$dt@Q`hTA3VBK$PoZwPwMI_JQWvC&x@23`2?t}p09)|` z#Pd>cWU%Lkf!>|%G%h>6!VSRE0;FnogHe2op(tsLl^gj@FM?1SjZnLV9N$hL;&jep zIJE3pqW+zKLc_tQD0+_df$VHGAMcc6VXjm6F&+6mO@BBNbAcR%N91Nw)XfP{QYq+` z1Hoh@6f1>8am3$Lyr)`-aZVnS@9SP*6D!yYUOr#_v|vQF(N0lZz>KBnaqpvM_Xn|h z8df0^3?n3KS1(@~H9eSG88IU$OP+Nr*<{;qQsf165R)OpC?ltZVzEEzX%SHvg9mr) z*W+k38!fY_N4HVm!w#orZB~E5o-I&ISIQ5Owi!_!c_Z~G7CSdVDG=%a0w`qk$Q6we ze$vnG;7akOELH|imIp!dk**k#wR{|X)oER=&6`?zd>_?|!6SPMKy@NKX`!2O;t>Jl zs(iJFilL-ejI(MIZYYur2Fkp}gF#fz0K$uMha)6baQw)y-|Wfvg&e<*7(?-7zcZd^ z<4!TA4zikHarM5jm3*W*@=(OZf-YhxELcXyn#_!;_x(z?7SM@De|x9%m7sNhE3r1) z=$U7^h2DFvW`5p}wn*FzNH}fy(zbLa#n{v_uHYbSgwqp^5lz7CPlDdiNifZU5oV>T zZ0p78-E%u;P>7JlW_HZg2c}=Ns3t|hwsLs@Q|Z79FV-gq$|b}K%PxE%@b!tM;M^5) zlJ$~|BN*Xrc;j5~g7L2hD7&rhv-0^U+2(pG&EQ1e*S}sH4>spX>hJh@%hqi-@?58m zeic;*DH&#gFhP-2q%%jQ!Zunx)(PqQTc6uqzYl0X%aI4hN5H8_O1UZ!b{ zPc4ntw@>0c(N)%n7%cg*OuCQch7uoA*N7gn^rCu3Xn3S=g77&lAL)X8-O3s?4%c?j z)cu#_o1ovyQp!c8)Nc-ME$950y66(WC+<;^1QAI>W{guv!V%7#Q9Z3!)p;qjHJDq{ z_YJ8K{w{f@b=v%TjeOKaZZ)HcK$5a605ogsMxua`y;;-|9bd^%X@x= zI#qFgB(9l$KKZQh*1g0oI5xMDu$<&wWN_~4YN(q5YzsYL-tBmSH5Xt^#s95MR)~AT z6-9}ZhH8;i6R)-V&P2+4rJA_Yar7tZv)$>aeYa4Q+*?@i60utZ7JW&Am=$d$Ym=T9uw|i0+Bs3rSi&-j@3ex{r!?c)wQ+%3S{o(FtKUxW zdf>FyYnRuKsJf?PR-cT-!p7E18+&^(Qi1AGaIZmr_uWs5&U--PT`m?i_!Fqe#y@6k zt(&oUh`mn~ob0j_l2st`qLw4IV611Gud+G7fuJ{S$kK0PV&X>a2~AG*p%AH00}4Ox zB=$}pq--fOSrV&Ef}mG06eTpQf_HFwFL40JEz+{x6`m~*HC=UZ#y;pa2d(!flet(Z z5xZm0R3VgzQ-zR#SpqDv;7}(cRSXxV_S}Ib#0f*fAGmZ=Ik)T7!<#NWwJWFdQ5d;C z!|r#SYBRq?CW;3-9wwu)$vv`4i&LV|1+vTHgI1O41*A*itAq&GB+%9&nH=RRQ%jRh zvrEc4#9j!uQ`VQpT^rEgRzu!|23#Up1F)_!E;zAa(A+X4)`s=!W_$hbK5} z9V`}BGsrxFn)P~WVW7D%f7unM_G8-e2g2m+N1h5(4!nu9l}NC+vT_IvV>D-r)HYyY zIWS1Cr}-;YbGA> zXJ&R@wsr2*7&dO?%aOBGfW8iPz(P@+RFo8~nC3F_=}gzKY|s|$tvFA}4VWQ*g4Rnz*+X`jlj zr&m--Qmm-wmJ`fnTYoFuMwLi2Co7EK2vqKy8o9hSz1%ISn1*Az5qu{9vtz`%%K9yE zMmq%6AaN{*lq7b|(1aQmlJxg5;H@#s_ zzK`Fs`&}1w)sw$Eu{Rl{&T2Rk%#M$r7pLYY+U`D;im_E4ncuo;!(@aEpUO(P$y|19 z^tKs&z>S|n2BcJ?zqGXHUAJ@=GZ8na<~Ae~{oPBC-a^%ZNG$Yw$-U#KHCR{NZQ~PJ zvW65%>n^-_7X9QA#t8qKR&xEk_NTGXMDEwh2R&s2*1Y)-hQd(Hrr8e-JLSZQv>gd{ zQ!yuX?78!|uWM!#N7ESiK1e}@q_gouTZog4Y@~`o>S!|R>_2b&;rCoe=Ce{rC(l~d z`#rMNbg16dun^ceQ}65b`AEN*+Zm&`^7KDV@}@eJIj2Jn66bz&nmmaX#@2M z?iYT;zL$ib5A>m)uXf7Cr|l7kZeI`-g8Sks+E*oq$ugCxfX+fz(_ z-fSkL`LcGOloNH4pb#S^^E|gP43kyrZT5Wv1K3Gi*REbvq zeke9FI&!G5uQ_dvD~iFYV07D{N~R}!db>CER)a}*tiRTTso=O%w-~sZx{T&Yxk&x{RPmPZ?UdB3gAh0qA3g+gkl}|(7{X8)byn>Cs(A1 zp&RoO>7*AE36lDBb;*+IddXxY3|MubTucSrVkYB8#E=^2Mp2JCmc>p#r*fB`e0+jE zK#UfS>?5H-L-Txgk7z)OQa(diWKdE0G7zFV2{sff7*ck8UJQ>1#Qg$sCqy(cUxevX|ofJt8Ss%0NA9$&FouR3|P_#;9PJC6*h z9z(`n$mTgUzcwkHKRvU1=CT4w@?cDC)Wu?jUJ8|t7)@WAT{}3S=f@wSgkhDcz%}iwPm`{!{U@$dKS^QboJFhL4k-8!wg8YbmYkL*Ff`yEU{akEfupbBoZ%V$1QcJ zD4+Fw8yzA6SDM0SvP-OZ&{u8}p9u*2dPIYinDTZ_47fa}WvkMvB4{{L(MVIiQafvoj8n^fDHF9;65$~KPI)fq?|gW z*9|L0mqq4W)xKfOlM?q}urQHc;nV@Tf#^0yVHh{Dc;$?wM9ZG}p`3FBEr-9Rjv2TCp&S zu*5*&E11@@)A=Gh$z~xoA&t9Yc}Qe|Y!31&FaYx^yMgc~F;tmX4a#Jzk>5^D{?o(+ zYE{tNi5wfs?o7iECnw!tFugOY3ln-FT$OLRCJ>TqLc!GPHA(BEawwEsJ(P0CC#V%4 z%(QQv3Wnm`D7bP>CPZZF#5k({%Hz4l@Z_c0M#1%>T}_zz#x zl^xomgYYzMOw)mV8cWxhK)Mzag)yLL?x(#gqO=)bshEO{s=#+C*5r>(Wh3S>SU<6U z>Vs4Ih*(7XtoXN8{V^f?Q0u4Y+NGK1x~^hVb&)$5Di4MEr}}$3UvDpgD=jyc36-K` z`YK&`o3BXqgrHuNgM>4s9!(1gWj<%=P8CcE17I8F_}MZMN!!WEg#EdA|FkdKE=| z9_zOzbw_ljv@|@W3-_sNuA33k9M*HiK(mC0yU1RhP5S+jV4}Y^G`)G!Ij5a#W@sGLdoLg+2s&5u5Tj zKER_LAD{vg(gvndk^Qthv0A}|L7NJ*`RV`SzA!K>@%96h8)pjO^xX!U$UX!%1MNba z;k2)#-&iEp%+ zGJ|tKr~KLq^~qE~f9n3V#P+QSP5`_nD-_5$SUbOM^|zPQKVrcvZQlFV6;+o7#Z+Dy zD6A}|nHgD4dKs~t3^`vB2uR`%H`3p|yq@p}^T%E@*1}gV)? z46GSz!#UWEGDFK_Dl2?rF_$Z5QiksOH&8%+oxfWzY!X5AWYTTAL&RnLGwS{|^z|(d zT1L9oG^fXh!M?}Lm#id1pt3cm(@vLC&8{MBrj+t!A>Am;$oJQ-qt`q2I$B;VvW)cT z_qSIORK2o}*6O8ELG(zDEg{&^JTjBGGeiZ%1hNsRi;i!UFMvrcs>MsF>%o7#)3%8v zV-vNUy&%|#+TF`XyP*D-q$q@b9o(WbXzD;R!czCsk$pP2Z28$zrywd>0cJ7S=}n-D zd?t_7hM^v2T!&L?V`rXf^*W#bugMKRj2qA1_g#7FclT+K$dB4#WuIt2RD$#N@yPu; zIu-@r*cZ$*L0qgx9Pl`kLLExWqk{`fM8LE1O}OAn1n1fP*(WgwrbEl&n?JqFw(n}k z1MYj7kx98P?~^z>7ZB6h=Zo*4-Q)VW9%?#n2r>yTM;2gtM{*jw8}Zv6e{#8Na69_O zD^F1SO#iHh+a(Oz!^0J}z5ivFHjj_JykCz|+XgFRV3T=3BJMkSZ7OZglYCKnmQ0L|5zdSeVxMz5?oRs&RnUQ7w(xc^k}zXkbM zeF&i6LxDT)^ERG$toWsGIlh-mS5i68|9|i8nwZ$O@v{#FgAX}>n~RxKls3;D^fqog z)@2QL9oshKsiTcrZFj97(?FwEKD6!RR_}^)<~KHSsZ_49ah{Br-quIBptig9=EnK? zjRSJxlPBjrNv7$|-Pj&?!3s6CJS(^gz0nyA3EV?_v<=hMHW(&e%OYnL!uV9B@)EfN zhYBw_$CoIg8?+Bm;?`cU!-r6@EPHagb$i=9sk&p|%@0+3^WW|1z2JBxkPROS+2;xe z3?IU(8tp7zFgL69U+&l& z+lO}8?^zDk`HvMTE-JvgFE1b3mrm;>RYQOf1-oQyX%}?7r{n$5?5K~ZGG{@PROC$r z`j}e1D^JMY%KDuM_YE8B6q!Z;Wv2Ub0$wDAJ6i}t!InHV+0O@!J6N^L0hyOg0!t(( zM2(-CREg}24;DQI6dWyDtI=WVevu6e`#$G900S1jP>v8Fk#K`z$gfgwM$0Y5g0eMG zYt^IhvLtoeFInBx6B76KKYT1>RyY)R8S97G^D&_`L*$>jgX2!jvd|C%>P5^Vcscn* zDqmCxkeg2Q|9FdKvs2;Q{GvuDxAu8tievcDQ~sHl+joOOU_ikv3Ry$~Y>V*0Eh-Qx zcB`LtW2bq!>Fr9s%*ax1)o=aFC-T|&bS!hZ5}Sw2!)|P5cfwJ6r6LZJsP@v;`w(-q zAK74sBf0ft!@#RXp~$x0yG4N4@E8Vji~6fz_}OsqAE?Lv`L6nsh~%%Feicz%{ei$- zB`@x);#wnN@Xl~><3>y&U6g4kZRG3?Hz3Bn^2xRs|H-;3OIvT-uw}h3&{OyCjzhZ=DI#|~{5E=T-Tj}VE(9MP zyd>h=Baz4@8^}|x_kam)(^Nm*Um=^1qgfSt*e`u ze&E6%aV`NxZh<7o+tZiH#N=9@bCLr%mPwsven~TsQ29{@s7vMT#(zFgv zPVauYP)IE~&XNb*>FHr|=Yk_v53&;pkwSf>iUKg#*}t$6Du_8VoFP_2&S)ZyvIN?v z%=-Tfc9=o(qD{$81q#vRNy(>k7C%x41P&68fsOwo> zl|U#Lf-D1Y)~TtfX&hrpZ8;fu-~l`?0f31?Tm8UFhtwdSd7|1OmF?w*qf}=QY$5;i z1zf7mdAZ229AGiX{%-7s8LG#h07?H@(4=}@oCSPgGlyX%EZL_RCk8=}miQz!^s6ze zrpAXXJ~!%SHxpUK47Vg2Y^q2-QmylAjdhlDqf?`L=jTI4oZX`GAZ9B&zmFiySga7=G~1Z;ElJA&QGlEc zs`PnXIO3xImYK5El^V@uC&IqFmxeZsj21f+>Pn@Goz3R#=K1q)+c0;eoLE19=#cueQ{|re z$*preJ(6dGp}<&d%A1^xjQdIvXRS$ONqpV$X?>-VRmvj*2H`Bfvsa#9nAj z$WpOC%3_W{LZ}7M9WGKMR>=i=gO#N$dlbBMgQ~<5;iooEpLf`@#wT`c9om4)h(%N5 z4F~newqRhkIadou@BbfH?Kt03=Wl=S*v6PsibNN7Q;yBD4qgnh=*-u#Z+yB}siWuZ z7#;}*H*A>qb3h|1q3B?DS?w5U&RW6YXyjJ)Yi?5vF6A2|WkQ1L4SF zsn#e%ftYaa1NYLm%P)vVH{3R|VOz#4K;GbTg9)eiudjkxuq~uIr?<=vgtLKw8%P}g zzlTOfx>*}wE|8_YOmUO-#Ieg-2V4PwIQ60k6GMpN$H__NRg=N|oa;LK%_zD7IG!+Z{3H^;P0#evGV_BcJc3Aa9P5Kj_JhuXg-d z$F~`Yq%|e~6#p7i`Kbu0S3?cH>Q0)86zbFS-J|mWZf*aDOZD~10M|F*JNhSiU+|U< zT-ch2=ef~TBeId-aJl}6a=3g$1a6K^=6SNdYr~J^Bl2`}FBl=4gxp*+Ah{_-#^1BEsokF{BKvm23c!LihTg6I8WmzBoFp0PRu$F8@ITZHF2>)QCL&-{#~$HLS`BUc2sIXV3c?3~ z#L}9YL}um%9vo&}@SZ@zl099kr`m+H9wwcT!Q<~7EZZvRB1^5NuAgzVn5}wD9+fx|JPRt`{o+$&=yRI5D=I(b2E4#phF?7ZY8%_ZjL#qK_~+$Wlw1YL4MuNPv3`-3XVAXrU@ZMTjjscehei^JUS;0auXcvOk7Buhni$S1l%FPBZlqZATx_~2=ZYA zvgfs2do%m$!Hx(!OfPe}1^HHNn_^`jubFqEpd{uVXHj0{(h+7Tr1J`DLjihsAFgmw zU1h|p4N8mUS0+;wv!io^*v{2m`pwF=4iG0fKrYyU=h0eE4Om%!pb50B^|A4Ky~v-% z(v3SNkB`@C7-(8A&{XRnzib<+A_N z_@b)yk4q>p;2@D5Zl#YGp*f1CV^lF6HmzA#Bo}6-O$m5QTW)2s!m}W#3E^zHY>1CS z(gr^#i#MD7p;{@NC|JHf!{tS}+G>KwYO2dmG@Jbs6HUtrfEdWs%-ZoOJ?5JRO|c4C)O*j$3z&9sY1DX8qPV>CVH0yz3BxQPwg@J=}&1%gn6zk*RX0cSO zjs)q4l%jfu*J9&{LX!Phki9HR2dHV7J{tJG3T_{oJ%d+8{lj zY6xQz{~vA3PqB?@TJJF7l!jS(;?skl!F@QOhCkQ2qZ75I^<=cskgP6+!p4n-!j$BN zi7qZZ%_%NueW02L#X+{;;ne&vq1x$ufn31qsm~WAe3oAq3eyAi-Pi`~pYx;NxXdfIeq1A%TXOrg9yhmaHrwen_^F}8EOhv+!zQL&YtmTjPIc*vePY~ZHtRVQKHwO>Q%?`eZ&k3{liwjTRx$x%j z-B%3%xZE5lm&b*7U3b?{EMHxYEk0NufQVym5{# z^NGE~)#`BdJ?~J|=B-6<&MI>Ae*Lp_nm4Ig{TlbE4$mQc(fqG#SwbonaC8I{5zwN+NIX~TFL>E?4Rg`a zOu{`7dxXrN?UDJm#*y*ej2vHaQmy@FEeeMOgeCwwTzL3%Z?s$Az#rzJUWX}xUdD6o z6P-siIZdc0E_2lZS+_b}zxy>AUxMHKl@AP`-j|SwteeT6h&-Rsl6!t^L^B*s|FR{J zNlwcFjDslGZKZ~^D>zg!Nin{}7LFjw%4O(65Ep-0*OOmEu1ghnSZ@d$GWq2E)b%bE zX5Afgd#5Rr84MN^1C_af>PtcQ5HisAx&6hZpkpPF;KHQ@GU2?>hKo_^M_C~c6Qw8h zHQiKY(ArThCY)fflmPkVAiTP*mTQ;mJ1WIQut=2&LZwp)#7duY*d>*3tO;>iq$Al0R@6J;1?H4?Yv?nACuPNG(qc6ue|Y4qEO@?2#FGOMic?CGGZxeS z+}0=Ow`M&Ol%Bn++hu`@>WPVZT~YM%37zFqaH1SLxRpN#pKx2Tl@%`Z&VOT@4IstF z;5MkM8T>!u1d@~pFxH%srmbc{kX>)rGtWG;>skJ^-aHGE>HF&F4bR@dpItZHpdxFM z9Ow)#nm!(euWbkABBD|_lJ9HC3;E+CeHw|yEE@xipU>pwixC&YWakqqfIKEKs$dtl zx^m^EV;gg|>Vt)PHGizu=Xq-V+_CQ3SY^zp)ZH+97= zUAKN9J;d>JdYzOWYAvMG>bhIIZZ-Pw&5X@K`28px7O4Za;fs$0sg4TRP>xW@dV!>h zqSwc}h!%WCyqFBJ`>_!K-ylInh3!zQa^oA+`b<%6>`d?U6lio|S5dmN!(nGN0!uQOeqjY`GTDC)s@U33I4%&5Uk@${ke z&hN>OiX=baZSCH-$SCP{Hh{;LVVo!kFv?}){M5LF8MOst(SiuzoWomM*AiCN2k4I^ zrS$=vJA%78MTrJL+jW28(6K$2jpMl}QFYp~{KeVnT6J=uP!xSFOQI5ZfJIWq;Qn!7 zGY2&yCq7a>KastD_u>&XF|n(!+84(XR&oNRb>q9M)ydi2mApGxaXo@gdt5&px-C!i z%hCl`5GJu^KfjC)u5RV+ehEqjMzyAA6C6RI7P*!V!o9RaP6wf7xmGLYx`S}O{FrbC zEgnv-`2JqNAZHI2c8m_s%pACSX2#2wC7%KOr?7WnZmC=vDwN@8sdCBp83On<<KYs=?@sx%n-5$#IjJ_!?5)@9^ji#E0V|lr$W`7jb3iR_URd9(<$IlpM1RCC zAJe2ULWA!+rt8%JJD#U z{@P4DI+XP?G`X+PnXUFUJ}8&h^;&&`J*fshUUVfr9RmL_)EChtr|o7~ze%-?6rZDw z6XeBHzYrK5-Gejm`0mBAvGO2-#kOJ6^A!@f;odt%pQk3(ou0dQbkst}*nNC-xKynk z-fr8)qB|d+sD49jk#qnhQgl%v@eQ#YdRsM-r z$lw3ta;?8s>we8sBI7Dz3SYC{Lw*>33vX`If>t5a0sY%n-#|)!i%;;ppOpLh`)l1l z@$_?vGa6TaV?7GClw7o;g|tQF#z#HxC*3vvbgM1iX!MV@`u>N6n(_qA~sYD4Qg@}K?S=l}HcPg#ep@6#>@R-B2# zvyH$%m3iyHG9Yv^nHrD*N|b)`lTy32d}g4nZ+j~JS~s|_zVewDe_X2bq36dk>dY6< zd5;Q6|H*J@5FC2WBIJEWWcab3v%i+x?&U5&DfP=;^qBwrf2v!UFKOf1^Oc```+R-- zH8WpkvPDk#9cZ{0i6O^28j|cpDi`XX2+5|+ri@3`cv8j1!D^Rf#m>$bwy+2`A&jF3 zTQ9X%B{_^LuEc)cL{k!rm#878Nlx zvIUH5Nc7ni>&UeFA$q^mJn~!U{bUf%j%Hh=@@UN=2ks=ZaChqKDgJd+B<90kPbR-E zsClXat@6PD)QfI51;Ny{4ud`uAzS}AV0;|aYzbIY$+|dZ474J?{j%ko*BxCBT9Yf0GkM5;>KMco6lz zv>lpzSh$*GEMyxMbwfko(N#opF0(ET6Nc6q4=o!+J~l6u@)=&xd!`>=Ts)D@4ovTV zZ9fWA)t!6%mRla5Q-53V(x_9Pm6rv7dLWxUvAB48>Y|I>DwS8a-17J>gh+{f(Ci8Q zTAsrSC7E`$C?rM&p-%zsh`?e#LK}fR6%6#1=BPGQP5J635MaSmVba#|;Q=5Tk~`$K zpcDy{1H6CM+BUuo^Zi|7KA3jhJFz=h_jx4L4Bi%s#pJ^S`ppUb65li6Iv$L*ep{V4 zah~Gbhhwp60d#ygCJfB9-C$yS>Bb5UmyLT_=uE06@m}rxRBb5gAA6UCNWdx4eTM+6 z^$?sr=ljbL+-JM|CmfgTxkM6vQ4P-JeJT7Vxe85wl8lU#C_Y9aGC>R?)XGwsAex_D ziHXtxMP@FkK=tAJVW|rf5ntfP3#F0CYwy4RFYZ^(6yboKSK$aV*+AQALdzxm?zmPh zGXIb-G)4@&`cp6Fom|{`^5o7s!~98#@U4{sXU*jdPDwypEhNt^@491gvpiUggWdVOm^Gfojl=vd0*V!v^ywkz@R7Q8SK1E%c zysuvS#V@6bA-C8%8LuUhV0J$EC2Z88Sf~2scrD&*eYy2RFVUNC{dSB+;1Obyk4BS~ zytmdouYJX<@#fv82G|GogXGZm4$)v!p44t!)3(+I<(Y_$GBs_lI+U+q7gepf2rI%A5iWz<#* z_FY35f*6o=`+okrpcT47qVJMwBF1N=(_qLx#b3d}>AX@}I5&zD(=#G7rm^=U@C*2{ z!34r8MbyxCHBVD>FC0X@(l}@SsoU#;RB$MlkM0X6{aO%++XU=;B4kHH1719`FX|^J zLJ|AR)nUZ|$5I0W(^A6A9y-|=P)Lq9PHjIlKY#n7?NdQ7GT&IYskhh|jZorq*Lx)G z@q2brLp40vm#@tXlolz%`RBvE1RbQ@O^pFea8dir4Fdz4y1F(En0+RNUN3Q*^Yq&A zMcMSUV?g@QD?S>d=KESL)6Trry~f_M5vRkzElx8i_<|w?!l3S-GtiNwjgV%WcL3^6$2p zb{PQ?F-a_TT3Uh&R3ra(bHN8l14(aEv%Q49$ftk1ssEK`CeCW57pC~Nhe1GbbO&5IXR%qe|UnFrzXBJGOhS@4Pz zz)7*6;G7ldSK!f`qGVBQ{~N&|tN(6Rn+RK7`6_@@eJdTiJ2pyGfjpGOSf6N+Lx??# z+;g&P$ZACv5eE9!zZ&hTH}PCnuV?fMo!r8Q%-?gT8a=quLw9S>j5MLQprBbOc zI@U&@K3b?*^Ad_$)gH?MT-H+!L`ljpY(+g}I@Nh`e8<8nODLnu;BoPFWT-2(l;I_ z)UPXb9vMW_otJNkZj4gM^g%`3kdH8^ z(Yf47@SLDh$z7GJfLDqDSwh#RryK^`5R33luI9gFp~!bv4)z_XKM zLJGP8psOK!N0tGChGqXTKGQf6jL07y&`R6(BWi(AlPoc~0u-q!Ru1XdBghwFQV3Oq z-)`BYO?62f?%9~ovY}|xA|6v6o>y`5!R=2zfbE5<(A&pHN8cDN2Z7M63maYUbb~vfDpZk9Y!f}CdEF3dj7t1j>L!O)#AjS*kE^^3J&#B-jD6sH?#Tr z3*tu>?#pK~#2~j?(rW@_@ zL1KjwEtxKBC&P=x#C$#&o;G1It?%xl@L<;35E%eZ8YI9{jDSFQ~j;2 zgvF>0J$|mW)dbLdhtCipvf)2>c*OjC4f(sD?>I9^>wuhx45UelQDt;xGn>k2d*x;- z-UC2Yi&v_1q8Yz*=I2B>IrE2i#xLy@NAH1)tgjWkV)CX7I^VMx%Z-laVml9aUT{;A z^ay8uk&I_6?ea)L#V&v#-9>|7Kqlb#1cc>f^^oD=Nk-e z8%o5!f-}J=UQUW%1yeP9q?U=r{{~+YxB(U;x+i@zer%*=F{`wt zWXM#+>D6yXBsqQLm&mmFrbbJ_eVe6^b*q_myak{>$14?*X`COB{_Rp~r zZ-XJ7`8!s4i$^)%&oy^`k*qmvdz_AJ!skqMRl}~gug99lo;`c7z4luF^?&^SzdzU1w5JEvyH=R}A9CzP zZzouXDKBS|F`8dN-)P z^?e(RK3>m!K5OI8+i~?zjkRj!IABGY)-7dQoIAGxn>$OPRCFr94Tx zaBZmhlT`}s{||2qwOV0kDy{sNV^odvhuvz8FTX*vYLa&nR1*ND_$oZH{D%Ghzi-d* zOrE&(CXW5PoOLHu#xa~JL~8wzso^M#LC!0mc)Tc`vX1txM~dG-9rY?Yx@T%6qkOy!psXis*J~=Gaff#58+a=LoEvk_NPz zqcoo4^cX%qQ^B#bvj1{{{CP=|-P9rDxmk>tSgiTf1LebvsR&VjOACpi)4$fXu#5!&mv11sy1 zn`zNJu-q*!@O0fbaPQMA;;y4Z;LC1z%W28h&A+aSQaRM4o@nWmJOoUEobClpRRNcsZ~lRDeSXT`d7AU9aDc|uz3tWtmC4Wc-ZlaI`&{2 z=n0N!&`N(FHy1@j41bt&L@Ko9fu}%E^m)=jD99LEtoSU`)SDAwAufS-N65AJonW=Q zfd!8V8$WQw4()fG{g!p)02vOl?S>G*s8Fa_w}`Ru&`-8iFS2om_#piu%Fv0Idn)P4 z0GTuo`YVBApyGc}CXtjFC9S| z16oV-We#D7RPN`0S``~h2`9Z5k6b~4%GHy!(~1(xy^^J$vRA}f(L+Oz935yS%!)@5)xu-O7ycG0pUV6fGo@wKFrP@3 zTFsO%PSa-~`YcQjW!-8l?o&%kDsf46xX@h)_?MEsn|ca`o=v@^j8R(pRI_D^7zTz- z^TVTsWTNEYt+7)Fo1YmOSEgA?CeQEbq?}uKXCX~b>p7mGw)y#Bc%^=JM~a}Lp2|Xl zCxcuEMEk{oEq-3lyDQts80n*Ax|G6x{(0@Jl`86g>$!BXPs$*L$-#-lS#la={kO8Iyt1WYOU-unVSB3sDc0UB zcwMs6rR}zCq%GG|Ul3lTeym#VKRxdD34FdCv9T*jar?;rH> z2#EK?@5I6-Fd6O6)^mV4p`4fW2CppR7nc+7M{1aLf`K+UxBO!huBv8c>z|bA2o;6myBB} zMcn)n2&!JnQG-Mv^w(SKQbTMx|GRQMvW9#9o!Bzo1gSXD3wn%``aJwe%V{~;IHnHc zx|wM{K9fvtH^y0j28+$9;vi0p=|r;gNBrwdCYpatGA+=LBFiSnU-79XSUJlpYvzhI z@7MWxLQaU}OZ6stz4U^5t4gcd4PCD|%DGX`H+QLLj2i#|*UP7xI#(pA(ZEEvjdGK+ z;GC}&ql<%(0yfmrT{)dzma7wf7AgthxOF+#+_1WPc&=0$Zr(RMr+y_KAHf&-RP#P{ zw{dcKZf^M0%{Uh4MzSNZc*)I{j8C8XhVC~HJ1e}w9Uc0BLgiSW)U2=)B45M1-wwc&s@0mT?enbaO>957U3B`*T;JV-D0yBU(+#8&yR))#X7}USoUCSGWzv+ z&=Xrsth2t~HxCMw-m;5BOTv`A1g28$9vNA%yk3OJwY@#3J~+P*4qu0~Yr9@%b1q*Q z9NIrWI&${b)7wdXon@zrR^M3gTc(~Ub9hJt9+<~d?#}ww*u9Si*>*mz+aouW(>FgN zTY>g?8%bqhqpHvE6Cs_ak-5C=R@aS`mY=?jz7#*chvx}*%ysMqrPt!d6SoqfUQo^Q zM{wMnMsP#e5hL&f-~*L(pieeq%9G*+GZoJ+4#a^5i?ck+aC3l)>YJ?NDI~Nbk4eqE z4i=NIkW+nv57EJ)BIpw^zrwZW4_y@Pjpq3a+rwev?F4E7RO@ht%J|U6P~`@pr0R|O zlL4pK8Jx9K>nmGW-HE)Q+@j>+AWABVTM^p`niN-)qfihc5O91xGf1*Ip$rF2)#rni zTQm3_KYp^=9M3gE|zXgf61pd5ueFR^570mZ0FE5;0z#^^~sP$~pbF_LND)bRs zTNXjZ`%3Rd`h4pbuCM)LZ?}%tfy8awrw&3)R*ok zJ6M61(g>R2Xryz^y7_InbmFN5^Hw@#euV$iv!XU0f_bx>T-2qwR1uT^n0W8HlZ(}M(7d&p6D zy1^vDs$_bI`(fq$p+d1hh-;Kv6UvWU$)RGg)R?Z2aF(i+`SA54x*eWLN?V7)|@ ztzvbiGBcfw-#wJe4dqn-DCN#`#8nd8);hVQgK4A*Yy3Xy7{t=`3oe`KDHf`bBH1=f zNPRus#iPR&BXoll+y@NPzVrizAhALM0i{w8dVQ5 z&zo=e_EN*VMkhjgoJf7(%cVvAy`BajK74FzEn~F-(P{wA5aWw`Bg?jg+|@gqpY1GE zb;;nabQdLq>kuj3HCpcC+4Ki4)YXGwwV{0QJ=KD`WVvuKDE9z+Q7N+dqr0Sl@QVo< z-+|Y@PmQ+g$(Kzt+o!15{(8pmtnfRDfF#DJUl=i|HuVf4e4QW_Bt6DM|9PQuelVbi zo<#PwRYAUiUgZX4N7=}fAo^dFxGInFYc`xXF%6fG6}Ia4&z)BfM-XH89KF5UCtR6E zXMOCD4Mo&bk&p?A&;Em1ADrdB&Z!L_Beo&*#!fJBMLNA}ORr(18}n>>e7^|v)eiC9uWLetYc zL85wdn~!o1CO0Yg6^E}+^wX7V8pg-5<>y|LRJg<}M-^kR>l#*QkzhOiJr~tYp+(Cd z+f^TfZ^XN-O$l*9$w1_L&$}%Cp67nFcms9F7J0cr-R`x) zjT~RT1AkN0?m(;;T!KOQz#z5&Gm3}MDBQ5PI5Bab>OHUQbV)c_wd%mBUnJ z5B*W!89bdo_ZZ$0We-s@y<#X<@YMIPU{_@XJ^wOBY)GEwS)=1HxSn^?G20{Fw3pjW&ufFl%!j|4UZbdYIuu3f; z076y{-b{xAy;KIOx%mh1-eQy7KCkW_*Kcoce#$M>%XwQZj85llZytM?(E;!pR|}d7 zUKw&a&fQ#mGVSJOCo?8j#bbh;$UB1QyyvRX%f-6R>n_<~cYZM8O%} zcUE$*JL}Sx@LJ$$+q$$Ql##yiRIHdQZHUH)2D@`5E7K@sQ}H}@rMj}*o3zSnu2?hF zMJc1dAbUBRs${dKmCH8Y9wl2MS%JCQz1PEOykWPxVQtd>LGsGfmGE;>%qikmS18lE zD&bfA{V`aRjVoZ*+(jjA-vJc}U6*No*&j9c!}zuT8hanAL`&Xz_G$us;C!u7HFP<5 zQL(Xv1cAuv$xPF!6kNL8(MCWBAWNd1%OkG)3$jSDNug9svk{Awef9T<6$GeI)yR?b zzKF%I0fZ}78T9^YmHcx5o++k}R1%)s0yz;SsckN!Qm~o}z=FBUSck!MG9Uc<*F!_; zka3jjkl&Tb{x zR&+v<7(*>XP94nIzGHqjVnb?r%x@hC=dA0=YQ8>9O~LT4UE$`p^h+`qzCO%<wL@7Td3vKe61^&q3<2lQU+l}++1S|+}|+psaO!9#_wCdrr(7kyTgZW^L7 zPh%3d(!-4LA>)ZLBl3c>y{Gfky8p!qKmK?~QP>jgInbj~MHHv)o&}cVG*}b4Q{eJ*+K={#1kRm1}`%(17tX+k7RL z$p+TFn4;voO20Xt9=F^t|3=)`|CF!c&pD^Ic1GVBjVC)*?!{DRF0e**^!)IKjIZ>* zc=jsq*0vO z!0gs!zHDmwcP1w^fKK#z?N{|;x2RnJ0OY_D%}r+#q#nO;$u)x9MMW!5Fp+q^jS#P6i?=zim{W=tCmXaI=aVLOR=_B%R?qH5z zh0Q$$f68v;OSXYjr6;oDl#$6UVn)V>EV~#o3`Q|^m_H!ZB@w4bDnWAb>tR&ZVwWBD zF8q+~x;?)TZj|-$<1sHw`1$=|9N5J(BDq&}D!`ecV{0 zPTMejBUY=pen^{ZDWJ?s0YmG-p&>t9Hm?X1MnRJG2-za?<^dqR>7?<*k+~yJ%uVlh zQ3DHA*R3thZl9W)s@7gy7$t3fp>B-mZ1E#cJaHtnaC>Dcp7-M~s^Qn(*pB8B3GGCRw+xDE-j4aa*zY$j8{(mfJ;iI^G32zHPY#S zecR|lo-Zn8vf)IAi=Xf)me9pWl8n9_DXk@-2~MO(VAiEjcq{FJ%N1SQ%!)C5O@+w5v4Z)GO7beejT-M0m*BoV?)%@(kr&HEkU_DBF=T z$-{^7wz|eeRPHTd0J^WsI8Mw=!BDy}{;qeCJ%m|xLcX*j@>!(Oi4*dy`^>whH!;6F z+wR}lblnR`Qr!(`Ld*T&R{uSX_t@X114vtI_dvxsA`RAM?@ye7_>1r40?4xF0ua2- zFP+c=7{kxnCpm(lq~+@Sbb$MG1fLGRU{J^6q4PMDWB{)9$&$;_YLXJ^85Gr`HzG=Z;1# zd<(5PrHx`e#+iYh`K#A=|?gkb4J#n)n&$#_{drI|4vmRii`Z*!|D z4#E?MB z8UASB$mY~N_r`{|$I(t99kFND=Ek=yTJ`E=FcR)A`t9ZwxRDd#>6uVG8J-!nBmWYk zm^a1h_UtZ)9G{UiZ+*Rb%zQ3B+P5xDvDPi4nPShuH^P)2AW znoJ2peI%LD{O8So3dIudz zY6+yJu?JceYl1n0bkaHp%a0b(BBxYnk=%&ILOu@GN{33Tl5#z3LS*sm`uj7wYl6AKD?(6I!=!w(4OlrTxq6>wxgD zrLryUC!5Kh*6K4>RLFER#!8^KXI}-lZ$0EI&yr;TFA!XQ;=OSnJ7WP=S9f&{w_G~s zFYv~;hBwvLs3B4h(sASRw~c9rpie}*3hm1o8o2F@)w20!$A9((`c+?ueh`7EGv(6kXnm?04CUSL8z1%^3|Dh& zhK42^`}g$3V#Sf+{WlH|t;tox2erIOaQwdjeIi-1lAq#P`CcfA>=af#4`<}vWW57- znn(s6<>d~1_7hrx3NlNrJ(^&54C9rjSr4{2EM}xDZ6vckF*FH=Un3MhWFhM z+VqWTiFtWS#{}PtcVf<)mwFJ20IWhM#uTI=2bYh@u2m*4QlLHlE%7xbdX>+UP7Knd zo~bQO(pYprZ2XxO4*9lWZZv;3*t^gjzy(R^Mcf4Iam$I~yDiZ9XNiB*HAwFw>p~Yb z3>xpS6E`R9h_7md%*dK}sWkBP(*twy-pnQoglNFEhI)FevZOmiV%=`A-`~viOIf^r zbxi8?d36Q#82;A|;SGHZKc3{0YP&>Kq0OW&lAer#J*yK0We|&9#Y3i_Xn&i87D_Hj ztKEWh{F6%D42DSe3Wa7PRrgwdpsTNMezDNqoh2Xu-6!u1h3=H}@KET` zAv%BpO6~G%t1-P&vyzxk`nr=iN7J`K*Cv(9r`y}1El{`Eu-jt1l{KIr8@uh(u)C&z6yyB+-f zOSv3)0jN>N_uP%=MhBt{j)7*}}z(vs_K?gRSn7LV1U-lgeMvVl9`E<8oD4 z_Q0`D8>EOF2B0h;q@Ng{#u7vqOZ5880Rl|f-WWvVeS*IwqZ>N@#;dQWkA#{JfSnKR z+7(>1-fukaHh&NT{PNgkm#N>r_&Wz&cjorBYVc(iUT-XU*w`2!e1U;UuoE0=QXaXTZVMIInN^x7uFYf@t39!HT3w{z<~?c4z0xU_Bfjd zr@tyLD64x?4p;16gPhlW)Ry~1bHu7bmg?w0TiolbYcHu@R956JRqs7Kfu0-;Sw(7S z@fTH62S=1kE@5k92^crP*z=2usyBCHKneB;y^r=L`19mKo0~BOe^?hNr#@;{t_3eY z#`?7p8G1fD!&)X>jlkefdlfdbUv~R5&wS{_XP$CCbGZ-nqwfxlh zeLj9@`Kj^y7TU;lg9Ma2LUx11pjJ>{4O}M-T|IJjnZCBC#3ed{RAsC( z2#x6dAG`nlk2UXT;li%iE@j%bPpK~Bq5Asu>$hBRuznf(v|fqg5fzcW@4v1E8T;H+ zl?q>t+CbMo*4Mvdef{7CTh>2VYFFN)Rbb#0?1$=)iJ@f#*(Y`2Il1Rh9%vw%u}aF` zvrGjyHwTacoj&*C$lS=t+&AQD#8q48vivKR4heP4lv-F2vFXN#V zdmO-TgC`+{&=9T6q2_cepohAs4FV_;w2MpYjfDIp`luB+*t^0sO=t5wfRx;xk2a}g1YMx1^{aLRupKz!zY+P=Kmzli(AZ%yO;Mx9(Bpalo(XjSiqPDcKuT`{C zQA=<(i_2M7LvcyyX}C^_pGsT)sNqvjLOF0eK2(Z-B|Z}W8fH5P->To)Rox z?#YGy$2p-KlM{Z0H$(B`qzs=dafUpJ^|f=tXA}4>QX_OwxHP0YR7%zQ!DH*#0{tU6>8AuXlY1MrTAZangh$YoSRgaG+PBQx zy2~SAy;lTW$hrGD5p$09oc6b;?X#NHsZQv)@pG2U5*7ZVw|nV2FGaB`^u4+Qee*8* z2xvB_LajB+GK4P*54vb3o;#uy!Sgc47_t5A>J@F(UIAQL2%+WN8SQYE!L06N?M*un zNC8Q;3u)J}_slKfn6uyQIFE)Lzmsl$U1qpi3PC^RNTq_0XnU73KZtDg(0E_bu_EL` zDHTYjh&=So?U|3c)>|WG`+;ye_TMbC`LqZjevo#kiK23y6?J8$o-RaW(s_7e(cc9N zE;)dwp=?$(1FB*Pk2?PaoL3!h8MLUktC2Nrr1+maoyeQ#1!M9u7p#hZjDMwbft~)J z^UQqW>3HzGATP0vs}unr+^AD-t1; zZ=?zl#1?O((A^xa{(NUoDShSAmJ1dl*6{GchS^Px#@eBA;KUa#J`k?3dJk{y9Z&bn zE?udP$qza^=hBo)%Qt^NFgp796_?CzDit6*&Qz;6ZNBo|wSjM}*#SPYP>POy^I@lg z{9ZM$5+HvB^Qc7_zBcwHt8mU0G9TPNbxYW&1G+V;!Ie)0aaIXZrk;8(?B zh^D#C??EH?&@U4G>dK$fHr6GX(#u_@y*<8j$OMm=$4Og2P&vv}uJH{l#W7?ZIiliEQ{^uVCxi>A->Up!+wW@Nsz z3o%8B>*@6lptoSmajIierLKT4;IlLHzDo+-wiC1$GR27TD1nthi$Vt&mH@PDm;s>= zr0`ueU#iaKEdwM7_hB&P2IKSwSqKt%uyYQEvXgWnKq}T|^PylZE^%!iXymJn3GPh^ zRMaipA3Zo^$b(<>E?4LfH7kLRZJ-=^_Hdw8-+}9H?I%~Qot45CBe)wue4g1Se6{im zIuWtT4Sd}N_4?HCCa&G#;)CbaHAwK{sewjgU`h?)6!6(4V>pci!53P~QetOVdbqj( zbsdDv)F=l!qi_#E%@ykNuT4=%!*A{!%_d_eDsU7+&F*Z>G8XY7jMlf*cco9zJ9JLa z`JEFwp!czAqgHEtPFBN^jZU7-73yvhOb;7^bYvXDPYOx-0rybg)lX3~)O5En%DvFc zOB6*15+}SOs^d+J_wO3Fkkf&ep3ab}^g3&0|9`}9pqfRhcbUrNOzamduGs;?gQ3vHH zrp6rjutScwfkJ3t(;P6O-2ZiYcD90_+FhjMZ!%525Q$7pL92u=YG+rl%#xA+5fErbiDBtGpG=C=d;p2== zKmPD*jjQR$8T=gc60=EV$25{yW~025p|sMq7-f=%L^_g5kMgD^Oj@0p!m&0sK+JS; zez9(#(u6F3eQ}-vB=>G6C+!@a_otmgu-+IA7U(qp{HUHy?zE6=kv*Su_QykqnR>fE zP2D5-w?6f0DG9mCIg=0-qYQ>ksOZxfg0*830LZ!ngtDgh)p5jLzlae-D!mI_ zVL7TZ-ssKt3ARRj8``$j&JAzN85>U9+&G4W1iWdgTngjfnF&O9gUJx0r=>CKNIgJ!dl9UJ(Mb}|upV?-+L#v?U50_z>Y z;~d~0|x^*ccA%H}Tg~D%ykuVlx2})mT)jO{xL-%&OWJi=e zq;A!$c+FoQvXz^N+x1dT<+ABLyq7nrt0U?j_k#m+6cE8NkZrK(hKjL)4?cmqz53cG z@KRkSb6+z;iVaRLFt!uS8X4j!4r6r?D_pyG=~^55#aDi#Ty-f@!&(O%Sc{bKAgRb3 z5&nND*PH(LT)FY4+wC$7cw}w!VXiM?$JH%sZG$L6!oEG){BKE|ek%;QV zkEqer+h3go5qww;zsn;09ta>a)T|ejYW~69SLs?qC+CoJ643SPM;5q_Nj%k5g__i0 zP7P-gpT_d|Md1J?))Lqr{AWrwi$Fn9+zieT6ns z%bwqhm$Y-;^3&7uPCxyV4q7~5S%=UZ$qT8fS^2K{$*P6k$fldpRG${c4eJ38&i}W0 zFY<|mLNV3PeVyKD75@#xl@$|jQeRL^c1CM`#n~ee!E;`l+`{%Xd)N88umR-O!51i3 z={N*#_gck||2wYJSUhAEv-@PdX0=|q)eKLaWY;fIM)9Zn`u6uu#dn6n*-^w#w{bZ5Hi%3wvX6qJ%u47W|nD~h-6iH zP|fX~>)K?+p@krI&A308K1Q(vp?Znu=2)v)=ZgOHsV_Rm1dwA`BkE3(dCdn#Y_#p9 zbP<5vO4w+8`Y*zZF1ZMaW!R#|z|Bb$BWc$Uw6%y3b z2Z=a$7$f4R*4^Uul1YzZ6A1)xxp#otP_p#g-Lo+rZ$6fk4vI=rQ7u~r=H@taL)DpRHu_OF-uxMQwYZx!^iH>3_$F?`7j!-m8-_Ry|6%FYxe6#Yja&L1NYklBT2Y(?a|O+J~vdT+(L%6k#upTW6^~|rQB0FOcA^J zZmoaH1;k%(IZ@ZyR1KCVyQhW=^;i#h@NB>g6qAXlKNe4S#Z8KiXUnzGXg0kYOmk3Q z1D7K3!BsvYgBUipxH2bnW~2sRdYBiizsUe&O&|@JW~{I}Y$8*3Os7B03K^}s^IjD? z!^QCl;2)!-)!O6LG72A{?p2@E>$g7gowFPrf5MLNE=R0#V%p7II?x;TK9=;y)xKF1 z6ek!?6xj(iMiB*1W|#~GLQ*bq^5&}x%~zGRQ1;J{j2J^B^M3#Q(8%67_4e~+`}r!; zoEjcE@4S%_H9T_PUImuw6!H8$#PgFnlUxK2OC~8XV$I9l?Du8BhH(GN13s;5%T~8( zyuprLN44}D7Xp5tbtq}64}9yLv^#Pr5qTHoDsGvzl811bp7g(vR!-;zbsK=N)Pv32 zRPz+5sgw%()((E=h~P+k+>^F1ykA(NbaY|G8LwS*ULKy@jxv1U;)!6ic^|nwEe#gn z!CB6_>Z}!-GX_J}EIRfe9b$a*A@uLytmTaC^zWAKsO@JL)M}oL+!9!%zQER_fq;ML z$Jn~L%ikINE#?yox?s>AWgcv#*YMs8q&)+$tcBEJg+qvosPcRwVxq|M0M2%Dz_^$m zQ_(;notfS^I{LA7siI%DC@0{=QkkQpqkpyzj7{_D4}3uVEYsiLng5k_se&**DEU>Y zy$Q1&b~Zb}u2)^v9@p2?rq}B#hAA1>6djrzm`qS=W`b8pDNHqV;>>@BxqtsP^1pdt z|Ni~|L*Dbrt9MGhBICbuhrGIol5xyY`zQN3Zp!Qjx?=iLncj&2R#`89>aU#UXQJxC z+W)M5GT;1W*BAf1{^vWJpHjy+pZfHiN^G8=-8%YT*Ee6Ceqj2$&4G^Bn#IkV?|I?W zsTZXEq9=LdzyeWJVr{)w&@3%2Zem=cOC?&Kt%xnoI-mnW;?k3csKPvC=E_5Ihka5_ zPd{c@Q{`*wU{nVNeG;v0Jsed4D3;aG&LVc>*fhhO$M^3Y8ln2Zo||?R3seg$lJIR6 zUCS<7m~;N2ksXz1t2;(?P7xofOS>yOch3m@1;r}{E%?%$_;_eM?hu+vT7z+nz4li` zr}FvGcoE78YtT?b!}splGk4yHi``Patowh#OP!9zaO%zWKU=wMco@oe|IqMd{m=Ga zHpByP>MR#Gr+T0g(s;XqFOMSVk+PtT;lW+R^Iy?EgPD(WHppK`g{~|HZn>*gp@t%$kcl;@~ zjORYozBUOaiAY1P_IbAuWnWy4Ew7r0rs@EHld@5!RAZf30%k*QY?al9XUYWeX#Grn zDjpK?ONx`Os3yhl>%o;pifKq4+9jvdQcXKF+c-k+TakNJ*{*-s{x0i2GRlO+c{yx{ zQgAIeiF_pMu1PiWogl@9MdwY93H`E5c>@OwBS{XFKdc$#_?ICHqZ)SW) zD%zFLW|R4NOqldBFbrQX=rhDq7tBQc{#0_NcK&w;G*Qa{jH3R)uS()-7xy~oyN7$7 z=AC}=8E*{vb0n!UJp4K8E~yQEP*lhjv^o+$Ob~nFwWPI#{H8frj1LWs4t5n3WpttW z_Z55Ac2c_CAFOrv_oh(UBjwp_HV_&MotMQJ3_7INgaARBki$U!58<@i)y2q$!r!sG zKL90!aJ5VSUm zM@I7M^fEHwLuZ8lDw{S&{dBInOtCaI@084yowmBB_~&KgcA|GdlN`)uM7SR4?H~F= zcJuuwPcn4%IlgFIrJCf04Dh*?^At==nO2cJVrMdjy!3vN_1dCQ(b*x$IcA5xVGXXi zad3@wmjIjYvUW~3c1G@ORU)OzJvlSr-_>}Tf8)?cjxQ{Xd-X;+m+HuoGjl#UBIJU} zP3SAPRu_^_T8N8Q0L0U@HP}J|3*vRwbmhiOX8q{K*#lFlWY8pznc22ApbGbx#4O)S zW*qw(#G;QzbkeZ%-f)P)V=`2g7S1d=Y>0WQ)q~phFXA#?RNqy9F zfj74=>2sa1)qUzQT3d`hz;|#j_0mlm3zA72+c>go ztu)Rey_TbHe=n_!ED_9c)s>N=8+nWz4C!yNeGJ#oDFKxFAIaKUbT{$OaXyg>F;wF^M(FuqN~_VifBBXJ+hcvJ7fh8m-Y-_ zx@T-tU?kO3?DnZ$X1rR;q@!fHRr~RD6TB^#OFjAXXMg1;6^p5gFL>VQvopcDI{j~8 z+N}0Jwe_El#3Xf5(Q~pBy$RKy=zaCoSMzFX^LhC*&MW`mAO7keeLraaoiRAl{Fat+ zf5EjTG`?+yBO)l;z{<4gU-^Wvg6I_uMGz+v)z?-POR%7j(J6cB4E2dLa}R$hJnzl# zwBD2XY}ZAv2pZ$Flv*Kg#>V>`H0tv^$*~9y)_`b1Hxn`)d0Kh<&MT3^!Qhnz)#c)G zLU1FZ`;KqhhCH=i``@qqZ*a6<0*{dEINI?@$M1H0yyNR?joPZNXEY3q3-&E7u?4d% z*ORSh#BHn>V|^#(ZgK%l$wB+v{)Ts2mLV31)(=G{ zdk^%Ix)kBi`-|qoL!3l%5VRBub=O#HS^Qa)N-WNXl6PtLOM?lwQP6TT=VPVE$uT#=LW@oHpm3;%bfg5;#7I`E_&Oao zNaf>1Dibrh3w}z^#w?%X3#Ai&G$no&AgeZ!8%ZYC?(7d66dm-B4VZ!OINV76K`U86 zB8T#QiEvh$5b*Wo44dLUev-99aAa6UO7-?9{5?zpv%4?FRV5sCE8cv|3}?e-oBBXe zlMb@OW~|iP9nHG&Sn~unpQjZYiB#HU5y4kP<3rJ6ECpoC=%=4hQltlX=zpqtw3F-~ zsvY6ctr`aLBxv+lN&MMhm@@n?myDJ~!p+z6oud>B zbu*LoP2-aG6^5ki&zywZKSN+nFnC54^@x0kc`-OMKX`-5X?A6$LOfJuBRl+IasI~*i0EQ$)YsWa47i1t${dkv_^>LuS~B zI7YBy<`UKLXkVh+Fv|EA84(`{N{8s9Nh*o-n}W3lJr+e@I4L}xAdJ7FLUgY|+!DM7 znF%e!t-m#G$gYsNE;CCMc+u(mWuDY0t5_c*AO?bc>>;njT4aW>pJ;#3BB~$z;T0ZbCBdNcD84*`9-g#4)G$#({Oz^P?j(r7iD2usF3pU5Hn{I26zC zKad|9X%t3=#&h;Qu2t4F?|Qo=??4xaVgAZ`hIEuw41EwG$>JYimJ^C-2}8+`7dus= zl^(K~ixjPmM@ufW#e;0qx`Q@h5w^0MF;&_36jtk&nWMsNBhq8nnDseR&8$_#<5Tn+}s2W~VpWWRP z{Lro4-D}2Xcb81{pk%li!u}Wo{NhhBuWish}zMqJwSQA!|=?=F& zb+Kg5_=08x7%!2Qh@Gr-qD`#g5Qq}ZzO-X6BcpXibOi2RE?%cVEvwO#x=eOOtUB*VvP$O2#zG})YFkYjYQ7|8Uo1T#wXI~i(22; z>xlM&F@Izs#-?pd8qO$zyi4J!2^G>0va)|6QVAB*={4#}AJsE|gG@HxyKN@xF`3*^ zsT%Vh2PnA}j{QM6iKxnVO*D^!f3&Ha`{SrT5E(E&+0~g-1O-SrIrUY)@1!GCq22Ql z0i(w={MtdA_WXE)V|=OO?>qjbbu}%Ept|YP%!3r@UGd-vFjE@aFT-9oXzwapCL4wg zwIMcBskvDa=RTf}-4p|q`KDM}QExbQV+@=V&%_uXg)gx=t4kOle?)r!AN>6v{PgFY z_Ln`R{yk4-&roxN+C{E%tockVo&MbyVi7AHe}QY&I8lQNiH{pQH8%mV&=vMI9}{9T zO1f6MBn;fL1_d`L+t#6DhzA!n6Ga}JjrV3kg|?34+1XkLx}6Lz%-FeH8r8r)P#76$ zq#Gk6g#*+UOj7`0b_-?n9QGP57n1SOvTv#myFq?@>!~|)&gT#DBgb}g=_g0>{2O^P zJqpcJFn#Fr45DYCmMQ0-@m?73E7#Cq-b*M)Eah^l)h6PDt1bhFkhWi2mmyssJGQfbKQ)})ThO=Ij1ND4i%Z>I*=#$<;_+=D?)HLo9N(MtC%3ge zLzUFnn>Lcw8>=;=TD@^w^(kuerODGT=8QKV&G-t@{nzq)pL=Tz@F%CUom*WW^(wF3 z&yzoMl-OqI{CSkdU**tOr~C;HeM!QX+B;!c6MIv>#3h_6;Y(lL{2(Q@@c?e87U*#p z1cYaxb?+==A90PCR8C0IU$SDNWz%1X%4s!;v|*u<;btO`^bR7EG;)X@^d1x*Z<%S| zUKm`nW5+Gs#lz>F_n3iN9fiy*L@gF1Il-QIEfDJGp@ezU9Ug% zx_!pJ%KZHHn|AIDRrc(;<>1E`M2M7CIgap2_$Xy*T4K7a$P+9b3@u(WMXYHSQMLY)v1l`TIQK|6+ zD(lD5qEU51ABRZmO~4K%;n^ka**yWDtaz+?zKpvMO`Ce1;+9{f<3v5qAMuVNQgky+ z@dl)`vixL`K1^BM5bJ|1*D`(eegp$0%IkSQD4iz@Gpj&#K(FTF0pZ3V#`GfAm>dMIkt1 zmtYc{qkus5-k1=N&ad-H#NW4WIucn_l;id-YVXH3rQDo`S`H2vzKex0BC@z9s5-fR zE7bgl;F?8oyIgGetAo5oa;~urr-|1u8+9IcK_XX4N!}KXPCUzwl;zO69=B>zD>W0M z+Kn*;DFfe_>|>!PT@h_CI(^`d+#RFqryU}}(+6(P-LZcCbkH>S8MhoVE5(9!p`Gul z_U3ZtdDc|-T%|!h&S?N@?OpZH)~}ai%-(kYRsPOgWw57|N|*a8)oI_a{6TnWyQi1m z29EF=xMrjR;8h(5LAu_FWRZHa11;-Wj8&f~T-sHk4QfnU>e7nQFV-zaxHoMYBYO6T zYRbi=8f-UY)*y?}=HL~6j_pqZeH1nr^jqT>hW{f)V) z4gLLlE}9>A!k`+kSA4!LYuCDBuo!{4czyPU;ybOI7B61E-XEBny7=PtJ$(xln+#e3 ziX!;aYlr5XxX(9R+}2+yl(tm*>C$xO-b3x_~Cz;|u? z!)Egf$yBv}^wO&?aw287FF>e8^~4j?5}Py92gWwX{dXQ9sdu0@y1v+LhHC1arjt%h z%~yawB%RsO(WnoKq~`Mr0H|hXOIEm8#D<2Xjrbw_b#4Z-xj{N6F zRz{(|N8E4Vxdt1+j+QYpi~;T^j~;U38KBxhBez$;SHLj&9jz3P4Zb_akVEP%4Xl#g z36y}YLU%odbvb(R#d~Zn+g?0xZf%wYV7$}4p1smqT)RX}l z$sq8(Q#b?jrBXc|a>}Lj^a4&Y{I=88bciff)SU5>KbbE~4-VGS^9x1PW0;fRM8~ps zaiUo>)Qkluw$Q-ihFzqc#pLO{_6q&^bs`pVk6Vs97a|3j#Rx*9H`C7spClUfiq&WA zo~q^VZPuoY-KU;1cJHrEoqB4j_AjM1)A!vsz2^M8?)uHU?oz$ewNj}@ZSGb2v*ZCu zu8o$GIt;g}Dg@yfjeTK`dXQ<6F34VOXPzq&=;_;n!P{V_4ux*^Jk;{Cidc8Fl@zQ# zb~hOLH-{)f8d*RX%A&Af#nIUQx9TVM@%vcwqq?f`@s8hO#JWK^rjZNSY%DmUV7By5 zaR$m-1Z;$UVHaA5oEKki40k50hKLtNk8I{sPzn~Y1jur-S@p~B7@-_H3qLjQz3t0q zk)5(*`j@=Z64%>HpMG*ej>E6A?tcyxI(tlp56C>9lgjy!;XbR6y4dfGh)XGgcgc+8 ziYB5XQ4RX6mz+@8A7wB#GzB=kXVx&11AmL*>%|l03p7kBTdRBdVJB1CDI4Zz;jRoD zW|B=7!Le{E?tRETv=H!Fo1M7d@~7<~5la4KT_24|Q!z*Z1_aDo;7`q<0h-Pp>rRZq zwIOr|f3BKMSytBSjabeo4z6GbJ4;~Le&sJh;~GVD?ZxWiUX`l39@Fpd$GJPh>)s1f zmTOnR6h|Y8sO7_xN5+(|HMRsxDPxPgs3ht_8x{#Ixj6V)xRL!Ht)qeSY)pLuxemd|WeUunhUUhB9$7`z>qbo?d_FS-fXy83Uc>XWnrb-(#$nL!LLYeAF@ zJ*o&^c=n>SNpiKuz(k6M)+;U&N%HI^VJjudm!v{^XYX21*E-kL^o316`jy-tuG|ZMNMS4y*y7R< z87r%=7Sa+PX^iF8SlB`v`7L6(g>00VMM3g;IXnqR*mu$nk16tF}${&n8%- z@Y>{dPh4_jVS?)5*88r~RNV2!$d2w@j`&Ti;0Nfu0TBP%K=h49uxl{Tg+DhPkNJ(h zL}COI#yI6I{*%L6I=M|%OB|1*4mXZ$-?%>wIxT&v#I_GK0SLeAmK{n0!E5@?I*8&%6OeGsu}7u{!z?arqc4w;s*7Ks*I!)%$cab zVr#T=OXN*f${K2dlB}y!u*A;%?_cOlCgHs7{K6N=BIWf77CDVxOmX1OnsOisl~ zwM(PxU^YZ!?HQQcxs@pbtkZ!0tM zq&6OWSlQy%9(6-w!9I-O)8{O}j$bZ^vER$+VX@Gwlol>ry7Y(0o`LEwOl-6XyGj8) z9B4^-+peqki*g*Vy@KpwsjNqiyRNH8jlHm!>&|*k?W(JcX^=+|wO_fDnjnP^GJC0G{ighi(8r@gMD3fLIPUDLQ*FW|}W4iv1P&K2RBhvxp zpFYz3vD+VtrSc{-z>S&tR7|}U2s6yaX?0@HOi?ZFDb5tPfz$|WQ^h^h7Zp?FL5!H; zRQ}UIv;8~$=_s0_)XEXgs0j984dmhiInmdUWu>)8+9ktfEGuJ%W=qdXe!zqXQADT= zybKGfHx9kM$D}ZJd((j23Nb6iF<_#`$ewb9O={AM{E9gz8~g4~rpD2hJ2&@KJM*a& zxSu@5Q#bRMN_FO|YBPUq`v4oNo$CGUq(5&i@w-YgIljCHWG}Nql=;EdQ4~Ot%)9?FNpPQ&jFIM3@tpB0-gM{rd|d5L=FZA;&o^H%jJLwHVh2I+ZWrJU*F5K4(u9fe0HWWA$k({00rVuv1vQtq2uzAwB2oe8 z2B88kT3}{Jv&`1=0LBB!ixP2Y$W0T}2#Y+uuNh~~yK8=+rk+jZ_ja2^f6c-C0&LP| zG&V5xy7rbt-}Hv_uDi&WqISJ9@aYp1%shRmQiE&zD{8PuZJFMlzG(OEkz%Lp!NKwNH-vlwKb$L;t=9yby?oepB~RV^VxK!t#_&!0(J3 zVFJ@h-MIJY_U-S!X>nxKsE=>o`~8#kT4V3R=LJVqZ*gC$yE?A5tC&5g}C*Z6V?S!;bm(=^NF=y16x@gf;SlJxr~(bJeF z5_Um6sInV@PCM588Hkw3V|MaATpgDbcuygj4+Y4A!j&|G-W)KUOs)agBKQI4t@uOZ zZ*?Xn-rblmrv29hN`Y$tuQj6Pw2#6Ez~H7MZh37s;f{@&1TCeyebDM$+nXP*re){m z@4Rg^7#w|Dr<;K>Th^tWT-V)1A2S*yJ?871^o?b;H%bP-%%{l|Ta|J2*`uTP-@fG| zGcF-oY(Lk%|GuO5s#lwPZ&KqYLvDJ8O=-S>pzeE~kEhLfmTz;O^=8NLuTEroTf}Fi zm#qhYExczRZ9WkCgmn`AKDcXVaGUl1_ottIu0?$IgGK*E7b&&BGc$AR$nf7SbD!~3 zY9jS9-teGmiI&uPgU&egguaY& zEd_-=!OOp3ARuMdAzjW~gHjwPd7HdP1Ki<%DJBFHi5@9IP&px?+$kWJoAkWXR= zdXDnruXO-|+pvbp#P7>6Fq~K>S@89wGw0Qlo!#jSxeP~t=cr2Bk-WXtd@4) ziQST74qZwWv>VU8mPoW$caH8n93^yAJHCtYg<$uhzH}b9o34{`OuFmDW#;vlN6NXn z_vpMc7b0~Sx`%>`Ze-x#H5Te5Z9_(oG^VG2=P20}>2wiH;e65c=aZj7_oeR)7($U9 zCCS`z5G7Nnzj^#3(3n@|E5WlDus@19gMi2qemC3WFFLhiCY}gyTDzA1D`&bhX{Thk zW!-(rKDsYY{k3pk3U9s*nF{q!v$)B<{#(%@!+5pN!`4~G1^BtRZj}XQD`QGi4hzgk zhpfb2)s9qLrs7AI&E^28VS2fZ2&@VruJLX8 zu9c`i9;3W%7b`;Zet*a&EFPMgLY)||+!qQyJT+~R4QNf-&U6LhQtrFK-+j!}?X9d4 zSr5F{WhYxxlm-%rWqs9NdaW+XH?+`GtK{lTV|T5}iD1ViriLo}VX}6rwVSpd5+0mT zt$KuS)ZSfF)vCdcyV6Oa1|#Uaw58%ClgHwjcT=4Z44&czGxYjBa(5C zyS*J8K&DT~Vkwq1s!TTBf>qHpaoqFBqx7S4b|O+$IsMT$Dk794{pB< zfBR>i*k4iiKJf&(3zZ-7QmH&Q!$0+zJiTx9^;GA3(QhS=(X26 zcF?DHqG6`V|GosSy>E5=UB{2;Q*)rsrDfYCNLk=#m9I*xJr6GO8AS%~d?u?m%o+$P zp^29Z(`Ghb(kazRbA$59Iv_4!0CHZb$DpKr5eZ$D#uLZvt?;M8JVL%>w z77Goh2MNTT%-SGr;}7{q5h77}MR7uPm3@HY$=9tjNaa-eJDX|fEv`A1B`<|6mj)m@ zqCDoQZo}vJ11AJWg(jt@HkkHQr*B{&7fM@6&~SLvsG^2P?c#wjNxV`=6+HtFpS|vg zAEo}sYn)b;@Ma-H5!4h({d8=ykufPt!n_P0)x*ek66hBB?$~{az=L~mraIB zh)5&&a18&y3O^>(06dJ~>jZwc2FfVIFeg>rbg=I^oARX-!Om1nh^Nu}LR3+Z*ho+n zIy;4;?LS$*=tZ$!cW#2nhy`1op>8E9`6UawPg|D8CPQs_0-_dETO@x_8dR{jIYqsGqkpnOt~2nC#v7=++rB#J9Z`)iGk+Be=O~_ zjx807f}|{r#l|CDoZJo%);FvVC;BkpxFNZotGfoWzMx?mmkidIhKB3W<4a41@44gk zJ%elOgB1!ol)Ad+YR$J4x06+}KuN{&+6@DYFe9q`>F0WigS~l0#$#eC+C8wg_&~Ay zf|)H7>#bB@G-CvPVfwWT2DpI=aVsR4_%=MdvIMvN?vC4-_agjd?%-Aj6%`bMV;$L% zo{+FO)160Ff;tkZr8p}*pTucnN-Ut37-Z5`2PQph1~z7y{sS_*^{f^hn?UYlwq@{e zJj2bE(MkMUr)OMfr=168pn#`{VIJ5~A)b8Z#ysYK$qzB-NUe~jHml>*;`gf>5g953 z$S=#=3e)^F9>0J3_ININ?19_@mato(G%sM3X?_u}Ik~huZ=6qnG@a^BY}iQt+@SN; zjcaQ7(leX@wadNd#?CH0Ki##_-r|UV+s2txP1^G=6q;f$vo+NfNf&0&_|Rn@n7J*{ zxiIiRXEM~4q^xhbFce(mur)||vRQXtuNz*C!5p?|o$-0M=+8tT{75dX8Bnr;{^)0o z3P>LkkC2Eb)GKru{R}9luOc3H2^ixFGli~&imvjt3}J0{4Tu+4hPt-Rboa`lMEs2y zhn9%ir8b#JEhO! zSO^gqMqGfMRZ@wL;-|#SnSD-@pHQk4X@!xh$p6^8#!wQ zfVjFGUe4kVY23jImQ-pUuE$4mA^aaCC#H197MOx=NKv5aS?dMC=t|LgBw{on{VE@{ zdvzk=ita4~cYMGV$csl6;mS-9a~6?MZky>W<0pnn-zlZb?qc~n+fJY;6SlBi2ZThc z?n(0@l;#hYqC~mEa;uQ!cWJ(A*pQVo&iTs*;z*!h?S?+>qp)cTdxytw#d=n#hC%o#957QUDj5+a^ z>#Q2BeQJ9bH3e8z3l@R`>fu6ylcJ-XzP(SEKVT#_P`z8b^|RXwERUa8m-q50AL(Sc z{#Nbf{kZR9^+^vya>50Tb3y=mQ>GcIdkF~g@*ntoi2m+(;X@u=WZAe6^EJ+$*!PWd0`wn#Bf(_$jN)B z_1#N26_&qq^jG?Kuz&~^O?y{ZXhgqmW7i^*iIrrwd)i@nz(cPwKQ(;q|0V5h;M+RO z`)}Px($U+|v8;E?vMkH8q{xb5%d+Gsj^nzn<2tShsY%^5O+!f2w3HJ1Mpi;8rL?7k zQo1g@j&&XDpzFH+yAHb14d_@ujJF3^$KDu!#>2z-Gsd&=XN*6i;`v_pk(0EP5Bq!` zCz6iNo6fn+k~z?RVW-@aT_e$oEV>Hlxn(T)TTc|0 z$$F2II$F}ewFeFt3ecn$3WcsM__=5#qYiYyu4Ta5U5^KCu62EULNY$$v)zXsoE_IG zMyk!c`HbW=;R8gNkmDFZ_{%c$Adk$kS6b@p`2&slg_Zk0``Pc$L#r$Jybex(Q$O089_7VANbuZRKuO(uszBSKQG@Iv zPsZoVcoiJ8(RZagS(vfH7AMPEuL%@JN~Ksl5Lj4^3mJ+$1EP)kd%*tS6EyH>9ZcmG8LkJP({w=8vbENp8Z9~n^ttVPIhKCzp(GydO=rIOK= z?OLMeF!E)V(DQ{@CLlpmZFif>ma&0>e@bRmHu;T#fp6l)$R>aC`Okmu;isQA?)Cfk z`b+8VH|c!){QiBE4@s*W2=L&_@^bfm3twB{w?y`C(2rivY&Q+MNjTOo#NWaF;QDI& zG~ok1Tr{$YR8nedvV<7YSJRupkQ-dl#8h+2J5Bh(Ig*PT<03`nz=lt#x?${FU;jZe zax@-43Ig3QWqx^ zMRPu|8ld_6qBk+4>4j7Mu$t8X5rR>y`TFesQ?i#bFCV!aaLI5!|IyOXk!$%JR!n@vq`TknNn+jEdD0|; z9EHtL*yV9A>R1*R+=%-yq#28iRLq$dF~cP8=!Dn3VpfYkO5Y%JAx>-YsbhUf;?ihg zdP*jcFU`(X8kIuln?^EP^31%5`r=lp>b39WsZ#TO>n(uAwZ(WHl!R5kGp*vg#|n?l zs-0KHlB%NGKSzS`g@J*W1(LB{-Jg}lsNhzu4G!)KnZ9jq-#Ak29DTOHeVs21O4>>< zm8I7)d!v(T2fLpAd?g=nrm2QIi3AbAQ>!OcOvH+gWyzyK=_+kPAVeS<8;_ql_F(3E zGo8#A8^$pay!k^5%h~ip!AEaC^}T43*@U8^nIyzf7UgU+$>5K2Ku)O`SZmb_(MTPe zjOrtg-*R{&N3?2eSrrP~wvCJ|Y*WXL{_}5qush?kV?1%6Sdqx9G@U$V~6+;dFFA}-@;mi3*86p=gEcXu{UzEcD2#9-E~L0%m_kEvdoLwchIQFwH> zl)j7=-h=*fvV!mHl{8V1AgLT_5G3)U%%JMnCZEPh6Lq|p%^25ECeJ7qp!YVG^XU(; zU1Ke}-_!K_=<%5Xu`QXa(ovP~4~Bx7fkue?Ou@>6S2d=_Hq&))Z=mH54whCS_?x7) zsoD2x6`6lVz!;hI=N6Li^^eq#Hwpx!Bj}m5iPY?p80dZY%9jP#CWW_nl!9^A;G%65 zSr?GAPgHK*Or^HBB@?k8y`q^TDK*GNq?OkDSV7*AI4Cr-gneZvnIr|pq(k&tp=`Fl z2-{CC*AT9As8a!_9;4J@p$5Leiu-|}Vq^Q&yp{83qYL#Dqfn;e+TN zDZm5)F$zTCSr0Z%Zq^j7QfrN+`a;yWY{0g&1Itk$Z^uHGJL@e5W4np>7s8}?VQ`1P z?DvPa4(7KljFGn!UX>CtE1*`QW63_tUk~?1YPdF{-a)t53|&RiO|btk@yS85%r`=ljh1}O*4#49#k`_rx!m|p1p zc}I_?tv;Ajm*o6|&t*?mVTO9H*s-=GGVqc0QCGD4Hs>>Jy>U~qRhQ_H7Wm7Jjf`QO zytz=V7H;;Jl8?-2RePrQ@d&jYuisRwMcYQH-joLtznCBnet~d<$3(vv5*vQ=>a`i5 zFWy-)WGcdAfFvVTlMcd7kM@eei{NgSJ#j6;xjzQPKS78ZDr5&kavw?OHuOg(UJbPh z+|gjbx##Y89c3N$UbVPBJ|PbzLxp`xfJftbZY=dkTNMAc^ZrPxV|zXv_Kr!FPB%ziCJPN9z`Ajub42UZ3*${vj9&N00c)15_s| zJrf9wJN2r^qhvvy^anD5Bhj!1vO0bSCr2WSmcWd21`pK~bAqPa)HYG(Xx&~sN&GM( zx2aRDMVg*C*;%H_-o&HVpGl~A7*+=BrbqD7`Q6s9AN7|o7{ZtT3TC{r$wS30wR+J- zozNEQGpWeYU*9{IAam661}{8zY?tp$%0>4_!GPsk8goaneci)5Juia@(BJO&#sjvY zs6RPsUe00BKqu-;T9gP&1cGB&qOf|Bd$UIFjc`@CAuJf_Ge)OlW#VzWj45O73G3nR z*V1dz4}aMDfXZanB2O6icAt)XC-R=?BWh89@))VO=W_i&U@89vy*Y&p+eYo0C3^2w zt~a@U)%Bq3_gqi8{+zy?(sORP-9(x<5-DF?fCxzNbC!LA1we>9>z(Ckju0@uv;Quo zcPSU({wcK?7J}WNi)=Hn@lBb(;^C?S`VntBFxJu_F>)$vwoRIXf+!y@5WM*o` zV|V|z#qmC3((WpL1z?);W@I@;HmKt}=RKbJot~2CRr6l&{Hr`E?=8E$-d(qN54cB0 z-13SW1gVYbmJxE#&jBu<_j=BoCt5v!p69sXeR!u_iQC8x|BhT<#PGbgMQVe`?8 zLfu4Ef!SO-Z&Jj9NDvY5$tfe@e7fb<;*(e>Fi4R z2{F{=4D!!MRE&$3v+0xQ#u1B|IiX2Y^C1_@ZIKi->HJcO+vT^~B@@Owc5SwtX7>p+ z$9W{}(jpMx60UKAW&q5CW->ER(N{lN1BOvBK{gmfV51gT7*ENv{b_no5>`zTbO;cD zZ%-RW&R?qMa)u|8qZYgoonSo3>2Ug^U$Y~O+|Ca~@h7BzbIOy2OsbA@ci5A~-9GYpuTKOPNA zb`mV$24zGkj=`w}Ef1(?0q%RQ!_=JMawQZ@h*}aej6}Kz{LxI@qBm8J!hf=Z1a4z{O14=>U76VuX^25_^m4<t z7NCL^i}n$eA>0}cMEU?6xt|UL#EA_=EpI5~^8{#*zOdnr4tQ+0cNjluBH$s)3!>K_ zi+Jp4IGjz`cz3;)C)}S*_y%c)lt^6US`=0(l4AOKqQD1&in^A{3~&g6qDJQJwn%W&$@^%3g@`>lbX;-_Peoe(T1&bO}kia#>F6RlOh67$PYLC_A`1=C4hx z|Jf!?V4>2k;?dglO|)XEGX@@(hi1%0r4{o`e+ZnYl}h454ypU_8@~~Z&rkRqQ0{8> z-XYc50#o|XQ0KOCIWTC&J>@bfJ~`qPdwO5>#~xVGpzpS4wZk~5o*@nBRvf`cv-jpI z-KOSN7sm4L-M8PKv8~&0N91Ae*+0of_`=&yV0IUIEdA&I-@Q7shUD%#^DB4iI8w!` z{qNoDQ=LwbO4o!}14~QffWX2X39t_M4zbD$E(m(UR$t#Qz1Ig;Rz!|7Iavn|a0(^_ z!&+UnL_F(Nd0C@vv2&j7E_{S8o+I8E@FW_$BetSc4JJp-HTc$2cxjPq-H3t90gHc2l1Ksb}}) z;)%DN00|Iz-CSc&pU)qd^VxmA=y|@d{olE}JFB=CY$|h{dPrEIZ0jg9>_M?7k#D_w z8zyqOKs@c$u2V0*KdteLxD(O#i=JLm%Pf?q-rgoAfcBVduJBFMWAz#uLRM-C+H9Yx zB_{f%Sbb-kWDoJ4Ne1v9UO)f5Z?g492_DH#jC%R#eeL(y;r0_Q!K{+YWvjLYf?{*K%o{K4H*>mH z!Ap(>$sl;qaL`krRO{$X4m)~EJ@cI-0hmX6@szX8C9=-vKhUYZaA2rf#16LyotqzQ zz^S|SA^|Y<5_c_TqwXO?+P-yWNU83?%qPyLw)!D=u_@Mh;74D4 zuWtm|c^a|5zwGu(pXXGFv$;_XQpCYV$_UA!`aqyBG5f=^9MgpxUHPbjoULPNj0hl&z=G~M7N zb;?=w61Vtsa&C5F!h!=RxJqD}H&W%REZWv8axWibW6qNBlJ+zC$PfR7)TP8SD`W1U zlwyC030BrbY+~*J#NyJ$WD?vL<_|#-2iFR+v05Vaxlo8y3k3pXa7ff^ON)(8A#dzo znJ*Ha!QGN+S#~X%>2%aJ`+{oUh0D=sJXqRVzxh>1ZhG|E*X&z-Rc`0(>dTIe;ptl$9ni#(cIkB3>DmR_?wrkxdIEwB>AnTRz3$xBU_ zeYCs;o_y_TpRsCL-S69W_xsG0z)q|a2fCjuxg{6~wX79RdcF(T;1;Ge*&ut!!J8g{-UAb< zE2mG&={I*2?34ao_BRHK{e&R$!`0e1Ufx$49wt}7%Hw^hY?)N1k*O6cTb4T%MO4}0 zP-t6F^+g6U!^4ZiTT)`+33Lp%OL?s5ciY49zU+mMsXy8}=dCp3fwjJTzR!c!9}XA$ zFj0Iy!rPSlNN0^=IiFpM#1e@R>9^Esg=|RJs4%idrw8CeJC%U0U`qy|h#E+bjg1!5 z9&<`y_>d%%m*>uO%Atz?_evAn5|9#&FG5T2CMWv74_lScxUmiPaD!NAVazcXIeKiEucPxi}dMq*K}s z*sK%3i)h1M7!$5SvQ3snxAy@hq3QLUwoQih=Hv#N5jPq$ryk+MGVPFGle)z?~hWa09`+3fowkt>?byCa~OdZDF{$mT=S z&0ln;7oFd}_}bT07alqP3b~pe%gH0}gKaZ==)6bId#sLy2#+9VcI3x-*iFAC$X(HU z?d+1RN!AgDcw z*&VBw-*Ly~duDeeDP?BEnCHpvec6@T1ibQtLm-Dlj>$ZH7e2EK@zstX%fy1ak}DDf zF;^r5OrDKc6FRqEU!JHr<;^`9T0ge~+sDWW)2a|Nx2U(`XXClDO3W3p3|mv`le4pt zOg556pxEh1E4oTy2(Up>)XURs%4VX;EW{({Y${kmb*ek3Q>fK5j)np74Z4;&0*iU| zAKiaW$06Ad5@{TSn>lF47P0;y7-!Ii{$O)!?Ikw;BUDn)IpGL2f?%j5lv&RSua>F} zi!fF23{8{o^nTY7dNy;DxDp#v4$wD=4BrI4$P}y6dQ5%qj zZTi~nkgW`Vm^Am%zO3m3Xzp=GU`hgY;rAgV08<4(1L2Js=z|3~Y{iZBSF{cuynW@i z8dd4$^M!r+DEbbd^}sZ8z}y{c5^KliOi zHf}-w3)(U{m5^3xCsXYtym-R%f&Y_@G$ik)Xv;Vgwf#T>P$Lzkhl%>F!?c1w@UdCu zTS;@10}FbAQ)&^yS@a1IDe@D%a|C;pO?A-9E_G%JQTvmPmF{<`<-_e-W;STpA2Kuc zQm0dl2km%snYY5tOZdx{8|pBueZ@{^$Dvr-3tu>ElEyz0KpqmuH!e}Ry3dUya?%yT* zLbDev?u7a(kS~`;-ZkXWo2_Uhwq3m@mlwc^}=6 ze(&P-_4S)>{_wimBj*ZHdzXo1BoK{#?&bKxUT!8^+3cXz-xnUtW?M<$URLfkQ?0?F zK?`d^ujIL&#ZXva<}1WTuW-HIbsA-Zhbm4dY2+lRF74Xsp$n1vXHgWma{v+gN}HlD zWgFlMcz!y}tVe{53TBUX5?7Ya|7lN)e|ppx7qVNe{c>~xBJb%opX}Y-X^{6Yi6zDi zo@fjix;H$8Hy0U!Z>=Kr7s<9b^+GhpzvYa%!_@o4vutH4Ge_EVZ32%n3|@$sv`Hx^ zA-zmnxx?m?_-(P}dGmMVfZYWrVRyCh9{ef^|^=cQ{Hy~Ll+n8m3SAG zf&+#K4VUOKUS7b}n)c+Bap_PdtY!Mm$n*m|7hw~<95nc^5(i1>J}&AIUB3620IN8( zn=&epMpQAH_gZ;SRkn<#8rg5oN2pTV+>4GBa!3rYS1VY=1ykf(F|^8*aAqx0|tW( zGV-~6?m&k+q?ugW`ZU}eG`-HJ@t8*pGrfW$Qma|k4=SZ<(Sz62pUZmco`ofx^JI(v z!xm3!0A44{GXT{{E@*E_C1(dx{xl2(@#bJ90Bf(|>3&NWlu>=b2z|--csx<9ChjTm zjJ?0g56VMu)TQ!Y;8%B-R4yrdghJgP#)@0s=oxnx%e#$<*WuLVQG)Y#{Iw3A+zlEG zOk4j*|43}wt2wMpA1w#j6$!Dzbdy!ZYwLv^wIs z?(0j=*S~NNV~+YW#8oeKPcz~=E*B<+JSUzRFKsuOWi!Sci^gD!|4W{pRCEN^!avsQ z{dpX%SEzK@Hu@$fUzNya+gm!rJDt4aS2D%25savj|HS{*_OrS~Z zC3B+BH1_)7iz<$Wl5h)qeNT>#KIwy_C`%F@YBsJm(o@L6F#L9CDFxNF2* z4C4-?7>^cLb8Hi|E1?A@Ie)HHD)N*O$Jn%nWiQr>C)O7h_U&80+PvduQr>&ag(i;z2jkQ~B3TZLHa@AbxgWMExDu4)n_0^R~rebzUmV1=E5XYX`f&_KN7&T6mfu~&; zT@C>Xng_v%0|T$6M*g4&535nSD`}Zbf=o%G3QEt|*mB*@Q;(ygpE`6=7^=&@aA&t@ z=ZDTKhJC)+o27WL^;0ro{Hvs?hXU(j#2B+%>PlzjwgR~fVY7-t?O!N{`=b%-%~8KE zd<>)JI>HH|h~g0I79P_Ju3h+xegQMqOVRJV1nmxoYhQ=Mr2(Eb!rkmJz%?M~iPMbe zpiXa{6OYkkNP1DnZp7^g(-#6tA97|L^LU{g4)@Q`N7EFXizZYp86{O;ugSpqP1yp+ zLCqdkIMbi(K9_KI-CV)`#wA7BMmSBKK5d21eEHP(z}2ymRq0QC>g@9OK4t0qDKefP z#o}?rB#@-Bssi#u0`-rIiGnYUJJX~3pAUXJmd(cMnRqO0%X?PUuef`0(Regl%67>> zgds=$L>98~d+t7TXlao)lYt_24{v9TYypM2&vnT4M!J+#eWUl#7$fu(+HiElk#=Q% zTx?oL2o!v0mT_E=G0p)Z2RUFIRxsvTv7v~Ujp+GVrvM{gbkt1m!}#FxIjQXB{A3D1 z)qF6W?9?rlcTjZQZ&>wgE}0I_M}qh0Tns>CUnNMb?JKfbJ9XJ4X&UpvItO;Yq4P2F z)@`I;NcH95iJv;#f6AG&xq9%J>~KteCYk;~J~kq}uQlB$sm{f|u; z7^T+o13Dxzkk1e3G8h9JfWbIXJ~;0jD`$}{oURY+8Q(E-feL2EN0?u;*sLJx$HX1L zKZYt`2xP*P%!59&J&M8LPK^4bK}2a0zY(H42^ok;4(6WzW{NgqieW6r1*lx6vGwef zYO$*_%7c^yVrs#F@(jHy9GtI(p8fU2Ka9NY;1+*0OOl0%7kp{n?CZ#!r$l1Jh#gbZ zrcFZ@9S+B@E)NYAuuFgEW&Ug`Rhhsg4*_^m5-q*nk)4IXme=@7S(Q}!D@*vApbaO^ zkM8HIWwH1BazkYmk|?^uQxvmQc!Wyk`C5N;V{DMJ%Cv{PoZQ^4d|^h?=8U*g=-eVD zfrrS%gNjTbHO0j0%s_M&^|#H^t%h-Hso5-*R$8r6adT0xUqQ<8r|vKAq9TGh2lV=y zRW(+c4w}21Wj2JSS6N*u_2j0L??21vl3tF@Fa2B(E+mC#Ghf|TlDUp4RP=k2YUINa zsgBD3bD8^Jf|@v;zAjyIwD)4>x<-M;MlqMZ{(5j4FF_^qrR4^Mmw}ywP?$mAl-Ut1 zvSPUr-!&H>pv~~b_u4HE_x^6$js}A=xFBS~O=yC#4`q#p#7aAI1JZu9ELAAmz0e!C zfiD$(OV%*pj7*D374V5C-UJ8Ig6`M2`w*2z?R$?MU0z;ZI##WCn4RyD5UOy?1}Q7559LGdEnBX&|>Y z*OE`BI)NUDp`+)r=|m5VaCQx17!|Y2QOP$*%ktPll8&fdc?BT<(Fq(6~;GV`g)iI!8cgvez_ZD z1L~cAznboI=Bv8voI_0S)$CLzL=2jg_3^WdR`=bOU-dbVhwi`gc}GLgS&fxav4K~@ zZs0QVU>MsAg~CEMnD+#a(^V~g3A@$wuL%gExBQs1APlL>UUGg&2 z#b1vk^8?g$2?qPrZFbxpFw=Q~ZVLihL!M8R_88YCBP9|bPf+t#Cd#GRR%K!dUqLjo zG*M~IE{W%ohjdaGX)P6>e%g^m#F{tASq$KfZ3sG8R7tM6T|Beo$aS^GEK3Jva|Nbh`Rk8#CgFhHfyW7jsVU&wlo^zvjIE1>eW0 zwm${IuLU;_7SUgjE>n#d4}sq7@Wzf-N#PgAKo3hG;=U|iQ4wP7C5i!(UOpHPX4%cb z3%`*v(;so0Liot2&IDH@ft&hMX`p}{=244}hWq-`52ux9cq(8gg70u=em9-7Um1*t zgUxQ`6_>gDz_+!+AM&W%R;`9vjeWJUW_$SOt{Jx04#>HXMM!HXB?6iX5g(h@-jfZs(MugFPzSgC$ah;?Mbcn$x0R~h! z0zoJ~I;}E)A}0&30bb^cEm*QOH0a3Z!RN=MU(37 z^%qvetFFM>l2B9k<)i6=NIF9DH)|TBYHqZl(gUO2&taXtj#UxfBi}9QCD>+J%X>t> zJ@Z3Z>b=RHECTFoMXc@z>^@Gej&fMH#_7~$vTOHu_%6Syj*e0^wEF?dhAQ=I;MrIi zIwZSLsZl^oX0rAk&`denFrh7VY>kkB z^d8X0(#ymTgT-QM2_TUlR!s$n6a+eZ_B?#L6YvX&bMn0T-Mi<{Q|SkHNI3@;SiS1l zMN$SU9ei1|zfq7p_qu>)A{ud$=hDt^JFOtO8cM(uhV1qdor@0IQ9g3%^q^QuV5B`J(W_==$mKM%~q;cFGYu;m_oTFLljW0cQ)E)Pvz8} z9J&m1yXc@iXNdY8ZPbh>^#M8`zPC<0a~wTZtF4=-k@etB0K9anVCncc7|(&4z_vx$ zM&dsaNh_jt2I;DoWvz%}P#E#Z!@adfWmB$dA9B6}o)ZZ!v{lK?BUxwsIGd|J|KT%$ zJC15NLR~((|5inq%l8ifk$cuB1e}!^YFN`q@;QFl^U>)=Z-V-u-w1P#Knd*p| z`NDsH5Fx016U4(zH`GakIleLz$IJ|Gt-`o4@d%|$@B>g%_0;zG=+lrjwE|~*V zB=Dq;25|lPMvaJ@;n;vg3m+#YJAXl`Ra!lA0>>a;zC}h55Nv?WOO~V1~^TlJn-N3!*um3&S34(Q@;0Bg%G7~L$wB0$uxOtGCn8flNr%jTCjf4^&B~iqw zAQu=GIK5+|B^`)jg}(8r1Pct;~3qNowlwrN6zhVodd$%}RNC zx-&aDSxAJlgT?bt6vu8%CQ4(C#*K4}N4x*$#v3o$*!b-|Dm{1O(Xp{);s#Y5J8^z- zFl!|W6O%hT)6?bhV8$O!9P2);Zj>=AzK~mKvwc`513KGw4ZT~?9xznVZ0&O)tfGoh zeb$Fz0nQPvY>F=$_9m?;Mk~0$&G8Fmr&uur3mdHz&W=7MwHH$AyHI4pE_8i1*|ku4 zKt-Sjb(a_F6;H&7ET-ed`!dzcpA^7$(S$_qKyRScRZ4L{YoPDVXtq##ppcK4b2ZbT zH0o_7Ke#8qabNfTB>tYHx(+VH?zbMgF1bQoDC^#b9wHB!K1Jujsao*oAXmXPOEy6< zn9Dw7osOFsi3I3&xENh3hITNjrPt-iuIpXD?fOI4U%I~L`mXCg;LfvE2GeD$I$!No zR81>xn()Zlq7Jc;rUaKM@fPtjqG1)9sma9TkTI?%rYB2NJB{tCJ(1du4Kg`3Jz1EZ z98F9L|7Psmrq(Vf4?+(^Runi|H3psnQRr)u(#Kb+xG^>B#*saRT9)9q5>t|Bf*b4H zRqfG)6MEIBN=&tza=Hdy2F}Gn;*OxRl>tD(2|NuDoL~@vqhx!E7?JGLE}M*ylKwqW z(E&^Lj+QNQek5zM&8au{!KRYc`e0TQ0_4Qh8ZA%LZP1K~BgUsEQxom&n7flcT$NMP zsmXR?((y1zv&ns{A7hA65`lEnC#58`btg$6x3Iv-w{9UcaOQ9I+|Fd%&wsa8ovjsS zW{TC>2WDnkho}zcA%{ZJGLS8jrlCJ3gvUj?h2Imbrb)-}_|s{+3POd*gGq)1-6R^% zigqNqC;r(W`vwV5Z~#Qx4Es6wHLQ&3F9bmobLyJkOlKsYg<6wmF3(vo*Jo=*uBq0k zeSydT-X+ToxhR$~)vIBs(MyA3CZF@i5Kvcl?@#35Z&25P1+@FFIa#fy>X?-2Zg>3c zwej6cw?M_p;Uza$AO~P|_fgsokqht5neQdd5Ej4@<_QIaMa)g>23hiQYpBsa!ZhA~ zvDNx5Pb`HA<@ZY=%A7agDM^w`oInij5ReS4cjr6-uQ$u_C1*Q{Zz=K)sS6kI+yQD{ zy%|S>1n7EycSxcSz@*&C_4Kxt3+w5s$R9EM9r@!$W{+!zf>pSKf5ml&>u%QruHR&P z96FdOT>L$JilatOd8J#WrZkE`vtprD7o;a?dOdoa(8wd7bj(M(lN0hONvNkiO_!Fw z%&bVllingLq~p??#qEU+1dWk%5WQA9uvdzt@?UgX1SDfyF05hXh`r!oJ=+JLjd+sr z3|ULkXXr7r6Oxm0GFl84qse_hG~#gr9rkjvib;b}o{t>0>7Uu8lc>%aJS%UbN~9t%W%v*Ol&%D)GnlgaF@BV`1TwkCsX@Nz_gk()?Rp znV48voyb=Azy0{}T<-Mg(}xb7K3>JVrzBFZUj~^Q^32=2(Xn3ddZ+7mT~E56L9>wQ zP20;2uv5r-CUWLNrpQEGFZ|rh>4lS`knowPvD1>>I@Oq@Beh2h38cBmO8RJ4vetL0 zCO*Hi>@LAN(RYOvJ7LB}19n!+qMSvmYv-ItI#rQlOKSQKV#z10x9HRfdtUY?*#_ zjKmB?ZGr1DZ3qTnfX#aDJg1ZA9?E*I@kmJ!h6e;}q~8he>4N9jVa^KODEDJS3Y#;p zmmNL1-i|PJ%buKe!BaGhYdvODeu$pWJC9s!nBH?YVILWVQ{VuYyQ{%P-HJ4lT7{yX zl^xfL=r<&rzDO{|9LN}xa3eJ>6E%;7rx&N$6Iu=ty@EoUj=S&E?B9?0P z62B2MBB`akIPX$nS2SvZHE1kAX9>iK4{=%p0ZP+5RJ?dkVNR^zXtPjIbsvD#SNJej zpo@I|t3Ju!j;brVKjrq!t?HA}H1u<`JB*93ZHA-p@RHjatZr#V7pMG?CZ2CbeR7EU zLpj`Mbbp1^)2T&oH!21+eZ_O;y2rTgIbme|1y}x}>mG*3L)>qOg_y`p?t%VcLJP{A zqet)53+`hJ`pCsEx{W`2E~Cw75wN$^y!qdys)oL&7vEBPVX8l9o%f z1P~w&@v{4mtjuo>hJv>_vE%1|=ERh5Q*X{H>Me9XHc(Po<6&&cjAY27g;~~Z-40@= zkWtTSzlak%k=Qx?z=Z|NFlr#=&Iy2wC4?Lg6<4d@%4h-v2k508J|Vng zTlGOTC*VKWs+7;cDKvUlE23F0i-+ihYs5g{fjZyWhCHV`;{fBPaEO>f!OXIH+n)eP z&^~OqzzN9YN48Ckj(6rZHs-cfLI7w(Dw$87hI*$qXIuypLC0wIWsbqyQ>kp6+Q9u9 z>N|w1JQ*3goD!4lEItI`q1m7oM@no{7#Vqf;)xWGnnaM$l6a^-*l6LW)nxgMFen}+ zT)PXNCG{>W%f-U$Lz3U|Gz?#%(BHkIb+4(ae)ApE_YRgD^-wlIVX0x`1_d+Dr0fb~ z%F~)6EcDHLr|&g=<0c=2YS?E41KHrVhSPQzf#5w+|Qqddw5qMYY`g&AvboN?Y5sshKVrcK>?AbnesS`2rS*biY>_ z4NNVg>WX(X9r5^yVoJBxx=lp)ZQ*Ndx*l?UPI@>^AweJU$MJZyua-4Ba-_N6+Ee0m zd%-F}Ksx;o@P(r=NaR2QMe^uDTTNmXBH|}Sbm{JZ^kS`EC%gii>&nyHm8{&Z{7^O*L-x+UAH)o1cr;Ba7KA)O;)8}SkcRpx;6ux&8X)|!gwzMp0|5|{ z-cW!5p#1rRgXvhD2(O%k>Kl&&9?=6o79T6&B?`KWD@D>7SY*M&3Zpa@6Y`erWQZs8 za8SA<;qASz@QiJKwfo#K)bO?MH_kiH5hQ0m8>3fPXu!gHEZ6Cc@&(h~_rh;t^Z*U; zMy)GgYSQPhx_^1S15JruPwFj@L1SRRAX(h!=98}q!6zN$m5iC!;wOMV5xboRJp&n` z=|u--9LEx8x`}iN3ExghC`@H- z%iPEy(|9MGFs&wTuyG2TA`K@;Cy6nOz0*K7W$GNI>oNPtsA46ZImH1}lWa%#)T|Kn zK(V2;Ma95#zNzQ0i7xJ=qEuK7Br*JO>MgIWtx)7e8L5<^!jKHBy%(s+)iVn$1`BMFBWPHQr!WKo z@zE^2K1DnANk#iHNuiJk0|;aXcSE<(|AaY^SpZ-`uNk#hO6(8WF3dgRTGgl?y}%be z_3ECp3(0_+WVW!pws+4k49I|SApiDy>`Z2Iw+DvqxRo>aj*d>h)^~wtGDVq~)LgW! z?%lVg5_2P=;4~*qhG2_jk2Y#!Daj}KHtaa@^^5i$ARHdgk_;6e>%J2B^?XDT5LXiwWks zw(aLO8SB*VJKS{LZ*57Y7USsq;t;}Fo5`7Tsxa2D8Dz9^WPqWVb6f60zGSPB{EnHS z9IJif*=nI0hgQ_K!`7hB8Cwq`6DJs3IhnEPGg>)AC&a7gfa7Qc=_;&Bc^m~OuI~Fx zYt5)sTA!I&Tf46_yYDmmIJqk5-@<+0F82KEt7^vtyrp?&zos9>*i>LdP9;!nBV5CU*sBN6>%L>3hSWjniAc zh$uxZ?tMeT$Pj5GOtpp&?U|OlrLtFy6=#IVR(vDnHU*%Hg{c2vBtC&BS(i3pOUBhgdH){rf_T!u`_cw zE|zBMV2wZG9UW~<7DtyF+l!^ULR)8@ukOhqpGgE=1&Xs6<^iAYXR%DSqGItGiUs@e z@{u`7icxrLX^7Q!Uux?W18Xp1z%Kl=9%uVBIcux1wjXibps@) zZCF)cur(N(xF6X)72@bt&EsIV%&1 z#9(A@dK3NZ-#)9rE4bR<&mu}3?pZT)f>0~ly_dC*iOwdH>jppjijH#UNF`T z?l(UTq{IJd-O1E5>>9MAnZtLl&C8+{XR%V6KL90?iD#+SGFmgMk`AE1%(RZePysZa zZxVO<*;B@bI}Nh0$=JFGPw($?*WxGyq zE?>;&YZFr1!svd@T%RvhY7>P<;e)}i0a-Vj&zhbOpD;aL@)d&F#YNm;>9w`)vlDk7 zvGEn*r!lQKt{f(rq9kM_=L_}>t_07KWG0PwEuCz{aV&w1V4Wv=O)l43;?^q6J@5|z zxDm{ad4F8&^^XUHIs9gx7zBR7)Wns)1{=S;#P-I97PTLKea%i>#lLy%pvdeeM3^!Pa$4px2g^UCd79;h#8zN9AofZy z8uwz2(oA}$DeDH4`|j83xO^4=i$>9Xb!n;r`aaz#3gXYkHi;pab$y{7i}Y@+US0Cv^wtk3j!Z{6K!oO8{V z&Ny+LKR~Lul9(f;MdQIu<7+2X{T9iyxTX7*OAq`CSJ!Cl=AH67*Nz$wJaNk#F1=K# z$y@ec(ydH2?wxEfR+nm}E3?8Od=?9AkYPogd8$t6_7Dl!i#ebIs!=z=236}^ua3U3 zKGDXlkKTInG)c&Rt6DEAKh#j~?7r@nTXYQAvFlc02VZv`b{*56-xIDIiAUY;y3=(p zKH&GdJ^&*1!><3~`k3oaT%T}#foqW`fX_q(_NYd8;~;=sPu{e8Ct^r+1m33FlL7@3 z0Vh3n3PX{X^m7R!@WEV%?>9Nwo<=#uvnlIYF-e~NG-c&eZ35|K)D4Ngm)m?VO-~}Y zMoC^8CG2W)6mgXTho;yo0bvCD`G|z!P9|JNJci#z(Ev_tjJ7A()^3sx*yQ*4srHny z0*`?`tNi8+8SS?BCXn*H*+DhKFjuqT@QwhkRg<~Pd!skv(VKQsbi?Srbz)*tO|(7U z8MRY++ElEZP!GI%sq{r_AiV#;#w%lY`Bui>blEk=yb<#xU-`{%G|m=vMFBVy6xp?${VYEatsJsYWTu-s&WS+s1E=U3`Q$ z2Bgefg!%bKya7H-J8}#x;x(`jvZA-~I6D$PdwO56)if54bv#GVj;=8tU4x~rG`}x% z-O5M5VxzZLB}Hd|&s| z-ES$NRq@=t_dcS2{8!!Q|Frv$I--*`=2E0I~TZ*)hiM_dI`Zi};v&`OH4mZLR(h`hGV4}6^@Zn2l@7s3ir8k)N+poTQ>zE$z@8iCwVVWJ&Rp4UG@g*kXm<*eiV%YOV zUid7Wb*%4q>$Qj+x8zdFp2$P&w9^r5wlOg`yOggt7x3-6N~O-sLan+u(atov~_ zo~mw9sqSBgA>qj9DHx^ghWokxIoh;A6zLLeH*h702%nZ&jQ{qg6zHim-gBO25ALSp z09vP&CoIO4UPDX}cWh6~byjWe)H_ghsQ|dx=so~Q33^P!z{buct&N$5L*1ts1zDLD zdH0y>438Y6f{D=d@7G^s&e!YK*`DFm`%t$8^ZCl;B9qT#VQ9z>g+@~8cx&;{LgLYD zOpiC{<()tCjgXJv`rwoK^#l6k^3ImOVK=sT`Q(p?j?0C~Yy1gM+(*>45A=;>6Alx5 zE7KddfvIh4l=%5XU@rojbjo#`#s<8@bw4@n?{j?+-|WM#M_iAQCGb%s@}Idr?fQ(% z1)l@5F$Gahs!#EWEhXRevTP&ih$x%$l1TIBOV-J<0Iy=a1YbUtaH`nL)Ef7dX?Crd zAm1l7ya_*u}yneuPhu3>}{kR^jMeE(&$jz{sD~uC0H-$kpa+?+r)8US7p$I6B1Vh8+u!upHubam-Kv6w``l8exLo2Xtup|*xtGo zV7%xGZ=p|Jgho;!^2YouKx#Ba2||fxA|41-E5{x0a?}(F!HX#=5f@_yr6(8&KmQ&5 zY28Y#^?wWm!ri}GNb$E&SK}lFE!2(GsNKC8B{FKMdo*&xuGjhOKAcQ0q|^06UiPXl za0y%!_KuMj<{homp%Vyku@+-URL8_{_>Y`^#!56lQGB)OB5xSL00YF<)80vOG>8vQ zmn9TENb3}c7>VMDCuzQ(#}AOKRG>e|<|^5Y;8C*KN^UNLpIwHd5y??@b9Q~-TwyMq zuEwJj*`<=1j7?l}=(+qe<|dNSXj1m~7iVWy=u5f0D%R&no=Y?u@kBVBNMwg{y3Vas z*rWP(AAM%^15O^+zM=?FlHV5E>LG-Tfo>C_xqxK`NV^gVF_rKpWs}DK{Z5CsBLmk zUp057)bS;KkT+F4=XmEt(iYN>owm5Z$!f>Dl}sToN9w6F`=wf%?==xk2ud zdoyl|_FX$5CyMLyEy@Y`I&kevw~ubB=f91iB(2o9orczBLzPXg#s6_#ZX7mlKr508 ztJ>m-iIATnxItcAnSc*MS*N{WVA4R(9y_*e{j~r8`qG#F=JdMyWAdQFwy*o|ec`wG z`&8Nv+-@74Yp=~8nEAHK9k{#u99LG0M4zy%CkPlwe*0y_Aa7tEY6$ZZY~^P}2Tvj) z-H;wB1}G0i-1H?#gJcx$AYw{-$Mi@nDTbMhM)}8(X2k0~Z9|SgqY{HwG%URn`+f#g z^_?WNHYn&=hi2NodJx94{%Zg5@L=X@AUpNGzIdbXxipbZ|qR_i-UtuLYi*N%J_Yh!W)eHg+V$#7=u*6=B&P$-y9qaJ7d=2K;D7X zv>{Ogi51CBGXiCd(lZfCK3ZUNz=~V6446flN_wU4na(j{HtrN6G6t+xczVq@`)eeHc_uvyDc|2Xpek0a@3t%*R{Ya9Es*@+@<@Zf#`cAa}>^TZ0X zU}JET~?5z z{UqZ1kwp4vw#QK_eL7Ogm^u^k%1Fw9!xX?dW!J zY(u&Ln%t;JauG|iGclgB^eSnem~52@t|*6q#b{Kg8+l>3k}jn863GDny>=gquc}qr zbg-KpU{}BrK-b`qusY3ie93l}7~6tpW9~rII-HJH4@SsrWsZ0fm{fzfStMg-&bW`i zHRsP4YL45vw&0&LbMbVM2wOZ?!oQHFNOwFv<_iRfHw6M$oa0m;OrRx4Vd|aR$XU_; z@zo(LHT=oIg^~g$(U251vFTE_s)Jd_1wFH+KVHbN3zcBxCwel`;cxMwAzr~6g7Jc- zkUpke%i~mspqYhQ*>Rk-TW&&~PAk&`X-TIoWdg=W=!{Hx9!_gI?I}C4Gij_RHK<}~ zHCH1k(6Ezs-G;2gz>}L?ZRTX6jOJIqzDzwF{&LNr?TK5n#kd7#rLynl8`n$OLc~fI zX9?ZlUNVkr;Kj#ldCJ0sZlZd-eN(b;W;m6kTA)pEhbpU~Kq3(cG2JrWY_ThCBNPjT zq6yf|L#b3y7I>QA*igWGajL6`fn0~?jH)rljnM&6awX)9)<7LEq*Q_CKtKr)U-}Vi z1Xw7ZC2my`jOCW4F?>{Yu%7dq#~`G)I{reSVfgdWHw3)Tg-dGs{ic!i^+){^v%Xl= zH|93q=r)6UXDg-h5K^X8uFT>CR5v^e_e(VQ=1AXBPk&qmz0X=|z}t#MUU_Gv|9}ap zt#9X{kdLZ!eSJd!%7PQycKRgv7$m3B8AE67feAE$?bv|lF`m$hr$s&HC2F&%%3iTl zMUXNUaNdq2CACiOKE>^f$sU_8t(IRnH#c|J+$(n8HK)$AyzbOoY46Kkd#ssBn(Ez@ zFLoQ@K)B$E#uMFfwd=0AyLMW0>XwWcxu|W$#$Ue ziMHfMiGu3H4c!vNmpFY{9+zosJlQ>X;DkXfXtH52>rnL==|-jyPv#2MV6<`|(?qk2 z3Rwi$y(IkjwZqp}XS*MSRt5(y5GViqz1L5~J(gAL#DnSC<&PfQd+=7^@Rps7mp~4a z(S-c)R5JKRoAcR)C~Bd^3J@2b_zaZ?*RI{Sv{+CTP9=~-L{0a{r`D@;@o3$MWEWN- zfiPTmxlXDt8yi@9Fd>l7snzWmup(48Va`VAOEgFZG%+9TG;6hK61IGL4yK*`%LtID zm5Y*)<}7terNfKVmRwa|m+f=i{}@43uubF;OC!O0eRlD%nw(giWnMz3I^a63y2SH_ zoH(URON9W8{-W&PE1_Dj}A@deciv%7tT+gx&H%<(iQGsk2Znm=ut;{t}{L2u#;Y( zCyUMNkw(D@PT!f@Y!+!99O3%4q>mAM?CZk|$*kS!0yl&>u1 z<|>s+9xElTugqAXtU<6)2pT?r7^<^ia;#XL+Xezf!hg`oL*30$&{;;2hG~DjzN@;N zVn6Hc`qrgQU&nL(XP)aUqm(<-ZK{3Onh8kXi`*^wDcOS*RL&bDTjTPG|LXti+kdisXPO^z_!DM@RV{T?kV(e81nx(P9OeVv- zF`H%6)qQ{o#!_SBGu5gel~0by@n!{~(2^TW``2gYHj0U&`Pr4G8qBP4IL~U zGthvC;ji=Oh`s<^f_AoYq%xnwsTn+gCx%CvUC0%SGbkYPWHfBr-uyCCEaoJ}1|?K9 z2fo{{i0qXpc*lDwV{CBr5Ksr6CgHE4q4^ zV!G!@bk*_%p_wbG6+JA*XAcH{ktq4gq^LCGAY+q5iM$pq!4WD-Aa?@%A$YI_10%p9 z^gQ6qXE}UYWgXddG!;NaKQC|SQYi$qBNrhZlGYH#uL}%*k9Ms57G>pzm zOR!Mb-ukgk7f@qEuDGl_4?*x*YnId6Ue{!C9-oobf_GM2h5?^aOjM9$;Ycx zi$}!A<0j|%Gz`rfplLPg7YpF*6^qR+sM^gK(V2Nh>+o9bFP-fG>fYl#KQ0j#D4tW) zpUz|_Chne?IK0@bW+V+ZYNCBx){*Xq9Z|lqDev-$vrNxTpV8M08;2lUFrCF#(SwfBH?Ba*C^9<5VrjLVDOyiPBEs8e=v}pXqDFvW zd1igo&M6^ikrui3vI2m-+#U)@R~Z@;S@Tdb zdf>LS(w>;cb!7EMbphkD~WVkJAELi;;Kr zWQTuSea@M==MDz)dUhGghW5Z|vnQ0raU&Cl>u0*1<2x%`CMNHmoY=Q>T1&|3={}2H z*=0}2>T5PxDYH`Z?3^#-06@`Mou{Ykyp)b3+Re}FHE+;5%^O~%&xlU-=jc?@4#b&2 z#B1px64Ge{Zd7gPTP)FYsCK$|ctU+y-^Q2pJsiGZ5#YBZzc_YPki3^cB-JEy`O9@) zxv*`SX9|ItzETXIg=niu^iNS?OFIq0X=r^WWtN?dY)+J9-h2_oRGVidrmUXgzs`Wn z1o!RtXEQ6cYPDFLE$powt-#OH%rt|ZdaatSANweoMr5v#xOO6F<}zupOqI@o7qZ0O z`uMGL^N-KZ%^74Wq$|-Ry#2XgFhp6~x$a-Ztl^P-zW;)^B!c15(aQ7%ZubXQ+oVT= z>|MJdZH4>$neQggv(?bgk-R6?Beh7dD=+EcoAFcQQ|c1Hj6L$5lZQmOIr#l`ji{LfueQ~BZi?&X`_f6#dJ*umT9W;*qHHhVA`FBJAx z4=ybVbV@&mZOF~vBn~23BQvhQb$uV7e3GBmJyY=J>L#rdS_*+8%CJesbD`j7!bA`3im8ne(?>Vy=i*D_q+U(UzITlL`8gkhjUC zK1Mrn(Zm?}ZCNFK3OXizBRFPpkuip)O>vY9d4Zfz{_*qb?i>keC`pD?TnqZecK)dV z-N=b7NaCd!L;r>+Cj#!m^GR8-)I;`yRYjAk?j=o%Kb&h=@9e-LP&UAn7(kwx)pjlh8*3OxQQ37;7U{>t9ZmB|lC7ed znk{9Sg0(uRPUAHclqLkOD@IaG(hc{mIMO*S8DK#;7q}gD7k8}fGm`}?@`;hce5DL9 z2j*jJG-hxj{KAa~K_1!2N?`?X^L_oa2(wNw>@a}P%iH^o;C)u7%g%t>649fAXbvwFO!ryV0g$+=kGGm7OB?X=IL{OPrnTLZR|i4BpULx9SEM8*nZ@n`?U zSowdYstHD%mg#gQZC2=BB~DiHmD5S}#3elxu}B}HlS?v=1c@ELniOl*;4=Y%$xc9Q z=C6O)j^IeF&*pP^8=g426}V)1F8tvHOd64iQa)=W=eFb;i-4fk2~nE|6y zcam)e4e~-7f`8HiBDwVF7dfJ3iXMAO)jgmde}h_G_>F4iu~WC)a%|Q9$7jO|7T-c>Waj+YoXP}1zWL%5t<_~oJ)U@NENJ%my_VOQJ#g|3j}^DPcj;ws zcuYP2KbM!UI=XVd1zU}Cxfqw2Pt7atrVYw_1(0Lg_29})XRx!wqCqbTjruY z>Y3r1P+D~7hT*nSHwYV#@b-*pnx5{7bGE})es+7E?Xdf#jn~%lD|qpo_gApiajR&O zpTDUMuMTro&c8Zbd%;F=y~sVD)t4ozaXy-Y_CScfNO$(}$iz+2yIZoT|3BW|2EMJk zzW4XZY!fx*-iEO-l%&bR}yGEunP% z_jXz73M-*wtb@WWrF77B4;Q+@pxd~;?BTMm>)6BH#s+M#U0#fFw~jwi@B8~Za*{%~ zb@#qr*AJ4;qt5xA-|zeTK778PFMwF-reZovUzMk+l{NPFckRw<<=`@5Rl8Sh`7L!-28bqKJ?Pxtz-Mu(K^#|!yyUw;n)C-FEEcG5bTywW>GHRcuF1=CnAA6T+> z1;2e_;*$N#M_^CtJSc^cpAr*vbW}7h6tt~dg?aG&8rky7_n;P`N|3D=?!LJuF30gK z4E|l4tt5CD>Oglx#pkUL?O7gy6kjyr*pxf#R;F+`J%w5XFUNC!wq=T}qH?T^y$NHUiURXrX8ba5Ii}*$qY9sWzr6mHEaz z)27vmMpm9!i9}oCwV0zMWd*DO^TtLzLnCw^!yNujs}fJPm_~mccGAwr8Y})Ce!%6s zcZZ1s2X^?&<%YUyx-xv{J2kjaUc+|he^y%YL?V&x*La%EduV|K*)Mrbul7D19-MH0 zy1De`u%?~TE8TnR;jUaeyMnb@)|zQ|#lL%>+31OQR%mKYaF@y<;fPQAwolOnaq7Ba zimH1-&^I(KW_+c$eeNASJsI)^-pDLi3B52_EVkE^HE@2D@UudDCiQ`efWD6D3cnO~+i021OwVXD`!NJj|-2nD08 z*R!0U!dhCJ6=$kmg+`DP&630LJ@D#UGi?GyGcC>m7gBe^Oc6S9CLK|lWsMxg?Us^$ z`A$}`f>+dDUIj6(r`(DtuZU*w%I?{Vm`+U8)rwEPO9mL1ueD$_XzoUi2kD7g+;aW? zI>|X*DFIX$J%w-ODmmUip;c$jCH0uhVo5trovL0dyUdVihYloH#Jxb|13=nsDqcl5 z(qF7U=u5>QkXETy^cg0d7FX(C5-a2y{l4=jp!RiZhFj7H;1}p#IhQ3n0@LOKJY&i) zt%uBak2g6x>AWB_xC>Fg*q~cSj0e376P&Ayx#w+h?d&1PRa(ZC22R>cBxC;9_nT;& znSQbZm5++OKw2Q|BGri^#xX108}$TB0yPU!RM~^BiEf>&i-PNzOd(Lx#={YNsJ~Dj zj*mXJzn`+kVhV`b88xZ(9`D@(BHzR82th>%#n(Ym^%fwQjKTiw@r1p8R#?h!s4Fsl z_w-V+9f($)U}8JX4-{G#n0Cf4w-S zaYdO0%3^XxZV7E3IN{6y{wC@Nm4lRfF{~P}onSI?J+N5{S_lx9h7S0*_#%4`G*(A# zuP+#+@Nuu7*dh44z(96Gk?hutJtM8|{rJKAl@Ch3EVGJDRi zhRLH&s-C`rmuDk92z}A$Sw$!TZ=>yJvi^Lyk|e^$h5G$rKf1I(>@&eTq>0b0VSfDLqTGqrUye$jI@+x#Y*IQQb+>s2C+0k=+UuwWw_Vp@dSzPlg9?} zt*<|p@&v5Xo^+L#AgD^-1%_IrTusCjtV^VzQsfzwVlW;F#;E5E0~5{c@sq|(Ckk;4 z>N&~i@mN4MC?HKfWmlqJ(wpmsDwJU?NJIt#W{}Ow8;HfLK`$ksXx+LQD;9jd%%J+% zSYarW9xDzx52GXoZ4k>8?`BG)P2(}K-+Ij&r4Y-eS8a>Mps5P_lBoc-yuE7!k=Ce> zmQVwf%Qkv3?i3G_q~cc$^c7+-i_ubI4tk9nN9+){ zY6fCuGm*=xfnM$s>y5J-)7e-x4U3H@7E1u`QY6^^^q?IF5fJa(MX6nUrL+nCDct+t z%2~)-B6iFdiu6)VyB9)zo|Vay^LqBEf(`vTnfrbS21X5fKW*&`n=ll*y2k^?5n}

a0}gl5$qr?YAHsYgW-VD2pMPQZo-@baxM$B#SWakcAU6gVeW+A|W}&2p>|p14!Z>zN zjRx(`^S%(W(D#JH9;s|Bmi?$OdsCV2(_g>h3bl5{Ti&w9oAHJ{dtP`*?b-W6Xegwt zp;E0@(jPcuso44Q6K?p8H~YyCfw%gQZy^(|ghG{YhUUzwWnC2G$rn3sx?=6*Th`Xp z6>D#K%au9~@;JI}1#8aMIikW>3G5~2MMWvKh9{_5*P5xClDX68R%I-J5byeLF94!{7J9igGw_b-Tb7ileD6`w=-2COJMiBR? zq4PweqRv)GIufV+rv1p&a?XbIQ8q*Ub>}9(l%kMnlL{6qH5#RlLOgr)o_qeEUC++W|N4J&J%YS= z747r=XJ6gbh~4{t{H$K(wLEn6)m@8m!L`5+0E01O6U)H0fhrILv~<$<4|SaBE6?{9 ze`lak`k@ZDwT$;XzEXXA(D~&Db=(1(itP=X_H;r6Q9Q; zi&lr{IIqA4;Q?};2iSsQ^$im2k-9->bEu${)WN+A&%W4)uE#<6Nh;Ngz2!{rp`G)G zBAK!`pXuE?uiBYdte9!%2e(4e&F088J9ZrIWpg1N(VL^OVp=vwGQGw(8wGTnm1U;( zLZi&EUL5^IG~OtFVzgLbx+}}(!15AP&$-PMCfnQ`*ZfMZUuXzC$pYBJo&=6>ge|34 zkhr)MVy?@iSRK+L8D9xfCkB)lQfe};yKa>(ZcL^n9Aiib@s6=l`_(Gb@q{X5U_}0@ zSYNuxw2$+yFV=YzOR;GDHNkA3rQROw>kD@7AqV)3&LkGT`7^_VqkCi$iOP~;%h8EM zQI7poESqMYO^{rl?t^iPV}DPdry1IDJFW4R59{3TGHN9FVhdp(o?9+GF%~tK_{@_h?E1mO|DN)ht-L@ zK(M-Js?H=!5P&j|H@h5HWWBf`cI|Lz4oMV6^XAJGC+oJNs-w~cM3eD(w-&Pr>c@Y^ zpN~WH5wc?7%gTM{SH+UDW&>?hG=3tHTR&qt>ELIqbb3-0L%qK9$GppeY53HwfyjcK zt&D~oLws}IynFt#VsUHQ`V2*=tSz#87)P}k?tGg9Px2|Ea-iL%@{H)esF{5}G<-C2 zF4^B#gm_3U20b{@+v`8#&nI5CE-$P4y4T6o4rQz(!M=3pNazgba4+8%V>>njixhqh zM`Ouy2I$3g{zz{^kdd6foQX$!%~C0tP6w}plSedmt|=_X{Ix6u+|OJ-T%Vu{rBz7I z6?x~{?n#Meb-gJi5qmmANyL!qHAH{euH1qzXR?*f^E&coR7TfFZR?=%phV1`uVl~Q zK@eJrZ0E|6{UbZB4(gg7=f5K^)pU`mWMYU+l`c0KBfZ*l?z^;bO~o`1e(3-JHgfya zC=M3ey0iPOW%Y!7`)%2>aV6T#m1s9_MC}m$=Il4R7tp8l6$MItZ|%E)-?$IXmnJge zO+D{K98PcdOl-F%wj0u0by&VcXzW4;Uc|oRD-pK>x!eV7GjLGO#HQt!0X2m+U1cQD zOX>EE6A8)DXd*$mGl{i{(}}T&c%?0$!G?MH57B+_$VR<>;^l;kH_Rap@yS}bLIk2d z(p$t$i%>L-r{VW#MdM{&vsnS@#Bd904Hzh-4@`^0y@n_1dO`_B7(F( z&du$%iBx9Mvvd^R1vrR6nMuAH zUN0!)0wP0ISvz&d`r-9k=GyBBp7rJMfFzwk~f?Zp%;_IINU|1vmwl1+Q|=n}>z zfrD+BE1mDL=dbZWpHdF}9>!WinX(tBC-R`%p1g!x$xFDJ?6@ZW+)Fl5MIzlta0n2W z)+nimXHh=%PLR!=zE1UzSp&6?N>b8g=kSfBB65@XNoX z-_FFSeEvrL@vY8qWzW4!qZ>&M7$$ zdMC9CuBM*L1U;8{3(`-USfT+5`yJ}sqxKIjir2kiL^FkYq#El+ymSQA-N%pb)}Pcz zMvosKRijd)rp~5gvgHQqBD-Z1BJpD@tT-meP}<<^fqB_|K7K)4j}w0YVHE8SA>Ca! zul3((ZgjRG(SM=8B88HH+52i5`a?m#8Vm&9ai{7XRGmi#jb{o_A4*FfS-$hs(haZB z(r3R9mcY96PIX7UmCsKJKjQyw8>b1u>i+TS+W0nUv(EFcu8B|1kDfSDU%>C)ZDXlV zG>$i7QMd7S^&jXExF_5TRk}+{x1eOjzuPVDaj#d6%DeFt1uFjSt`UuPulej_@y-6B zK*#SjdZ@?9%$%Suv^I3A(_(yxcSK^?c-&o;Ts$jihYULZ7%T&H=rmX)8IN>+i6_cC z94~rr0K{>j<5>c*3M0YXH+e z8ZB0`7Ue$RR?635_^vsISx*AFcL0eL^lov7w8;qQ4ItKlIKX{~<1r#BSy0RqYh8)# zmSAh3EPTE3NUj+*VayS_ko$lZz?gd*Q-3n)tkffwEZ(WOy~61+kjm7_P3BL+>Jq)n z-Sa(UF4ZzjB?1c;m!JW2a(4;nu#o#oA1=|p)3oo_9>OiSm!yr5aPFItoY2q!9S6j~ zBQPt?DNV_%%qcp&t{YBUN;-=~=O1qOh$b}MK(I(N%F~j)XQtt}xNyY|%DPC~rqp~L z26FBO&Srp0Cw8OdShuWQo2<8!peUHeX=3i)iPD57<+mf0`bPD+cIhxK#&*4i!6++a zkMo~kYN1{4s(EQ0LF?q7@fv$ipxUfm>rj2y_!Vli7{FTW<7ebqT4!h>PV-N3Gr;++ zsQ20>qh4zppJTNZ*r)f|nAZ#41IqLWmZdFYJ$D(qj5(^R-;5L=uHw;qR=6) zZuP$j@r@>o+JHAW&>OXzxnIZmtx^Lcp{?YB7-@QN@c2LqhT{RJ0k8-6)l-n@Lig{F zMuK#Yy3>R@KhIK?6rA-U->lDv!gn?~EW=}ouQ z@;B-^qqpZWV~=q!In1|lhjfl}`Bf4Cl!q%$7k9w9ea8($N*paBz8N01={i~PfBUKL z&KkKh_cM1bJ&m0yK`sFxvEf-E0_^;X>c<1Q*=%2+81eOG2C@Yei{*NI%^l%G+lF7a z_lC5`TW+Tl+pLhCjUO|>0U??QlgSL|+2%p}^b-lWf_l%+B}ACKR`~k)%ZID;!5u^p zq{rk$Vv!i{8N~dh-xwt_NQ4R7W7LspR7AREH3!S0StIS-qlfM z;7PyEqCY>K7|bN1QS%(c0Cdtw$%O8Ba+FRD5!P46J$;cbiwX4dtzV#e7Kd3I69~y%%#Aips9&aS*3zgYP-jqcf`$FwHWjcm2=}L~}9Z02CXXYLpb-oH48%$Qw1&n@Vr+H&G5*;hvEY$m6B9$19 zAQNOHNA2VpE$0?$`4ezl!DW??-#oi&)XO(zaybe{#Qy{{^*4_T@zrsTz&>Y)Z!ShQ zKd>IV`y$3b9In+mnKV-0^zNSb@tkzmm)S?=AZNhC^O2z}4d@Pm?noi$t)(9gvXI?n z;ufUnpvc!5-T-&n4{r$QAAPLXTl%=RtW%{UCKnuUiAe>~(27Q@(Xllj` zEng1-nWV)=5i!xwC~J|x8^SBijZJfRA&AdnD^MzFxx;qjZpwz_=Pf(xt>=sJeS2H2 z6MM6j+($^(!2*b6XP0vE_Zvq807=cK03A*_*D`NK%nurrpXbp9qGfrzljkZ^s-6=? zEFrJ52CTd}BC8Ku9y{?+f-ugZlul2Vo9{J|Nh6CT?Rd#_c&kP;<8W z&Vvue{GMp=+Zz3J=7epZaIMO3Q;3$pq{q!8eohW~j%&n4)x|mr-@C8`{ws{{+CfF1 z!r^<)S$+-#N6w7K_Aq6<66yP|M#DE$b2(M75hV{${aE^pkNPMM5}0Hq}-!hPZUwsll;fm%%N^9VLdV^KT zO~K%oPs+*%?|h;@y0o-<$CH)H^78t^O~vxc^08yfE4x?J`;(cLlh4GhxFo}4hL)X% zLzNnLZ3DzaEys#4ed5%C<>hka$vgHfQK#+fpU<`1%W{U@M~<%S*8R)%E7tK%2!1Y= za-yG}d?xV=G+HU-8GS*Ak0c4nvK2HQ=(~YyAPgUNRnh^wiX$r7X0C1}WSD zNvpU1&2M^^J3Wp9w@}m!_=tJ(};lq)f@gTcwY`nP9dCzMO zv&%JyBl-G6?|t7-zvh|&y+k4kW2@^skg?T|h0sG%ObLI+5I&VjfgQS^iLptz+Oy9d{Wh;hYe(-h9%Q9^kCB%iG6;un`I0W-7;ONy*UEZ_uI#YPsdH6 zR!tP&a5|pO;MGh9jtmaJadsjin)0wew{`2-_~=L?QK9f)Z*QdI-22Sw)6c}v5cBE4Q;s&wo$koH0fp?WkwY?txR71DMeS(Uwl7zp>7X1d^{|3OZ2 z?>9J@6E!$dsVlSOc?v#zT#tJuI+3jsl9Bm|Qda37N{Z2_Wu z<;h?W(AT&jzGs>YM~tS&Hw?TQ1?S5zPl!?8g9{6zU@;5ceAB4`Nq3O_0SA|HAQ}xs zNe7QFEKp}Ez7TKZ90rAB__c#X3HATGekc#-z{0@=HCQ-U_0XkhYb2dJZwqoWy35yfRU#L?5FSL_2Ct;?HrjWwgiD^t*CE zIz#st=$h+WXQpzSf!X0nFY6B7u(h0WCg2j)8LsqkxjzW;i59SV#A;DpJys=EY zy>%!QjTt8k>0iEM<0`dr)!TpBiA6gP4USA_BGE8HyD>x{4$i3{hXNo1=%Wa%Mx2?E z!H|H@<^NG|3w5~1sE%O*TQ5~bl2QE0y-=YSz($Lw1zo4Fn-%ixh_WH6Su>}m+eF`3 z+bdagPC5Zm$8_4*C`a##+N<6baSb>J9m{dz4@L9ljTF~{b}bjM>UT?8Z-6Q|qykeR zwnZLBIX>&96sU2tH)r2wfF2s|yiob&!0D1wlfOrp&548+tW+kM(ojW5j;4w_d zc5FT|*3haaNgrV~@D~3fwJub!*A8=&5+inHwgEmPPv((~)T?2=xwYrV(cC_yBaB}l z8|kaGgMS7<3Xf78%08Y@3PlR5c6v&RR+Or&5f{u(N>ph#fWKNqD;8yIy5eW!q$pnE zIAw34;6)ga@hXcz2F1AHu#!pZQK&#q1e@QW57Kx>ajWqa33l!7!P(KsH@}GW`tbg>eZ%yapv?5^f1=_Knd<0Q#k8BZ=~M1-XNq9z>pdHs#$s-R(c|{C(;t+@k~|C`bF5#`ppNWNRCDD@SGq z5IAL>goM`bHIItR#Dw3HcPD_W%1V;iWO_yaN1JWpB=SN)i(Y9wj-DwQRoBW9`rq(A z!6$9z2Ri>mew9fi$f620F{$oJ<8tB)&!o?H&-3>^zplSopC@oYPRymseBkPJA|pe1 z@ioSt$P43zN9Z5pvGDjO#dGaf0C)Vj_gZ2x^mJ!{+FkMGdM0!5#s?`Y-h9gW#3`zA zf4{Y69jwpKFT+C7`Rv?*xw!-C*ySsKS*iy<(EE6~RA1UUIe*6|4E4;?^arK~2e;HZ z-;JjQiC-tHA}3W zY&g87CL1YO2GbJ`pBoH;(&h(0rQImg;pc@z(*vrJN*Y(GC+~Rkl~*PJG6v(ZXg^dP zqq8&V$ub$ZA-ZiiQi)JB(o0>F{3uegzc)70Zf^%-NbmAfbjkf0-r1iE_a{U+vSFyG z0L6t8ijpIsY_-UAU;dSk-AXXsleuqnUn+T;-aDRLSvihrZ>%k4aDq-XmTE-+y79U8 zO2$bR@^L(YXl!)XI9`Ri(=1F))icpLetdjX*hEDPG5iE{OFA%4RNGFX)8W{<@W)-0 zw7r-8khcdHiXrxp{LdLjse?4YtlfhfE&_O)U;3n;v9$Lo&C}D_uR8cE9aDBO)$PrZ z(RSI)4Hn17rY@S<|CXTd)+?`k@^<4#_RqA34-8K&s>P|{k&((y2XEMkRBGwq;cKh) zzRd7mrF>T%c=5%}QibuFCJzlmMN2noOLxa-MD*Qo1 z5_6^_PD*-am5!)w3F)S$z^&)$1Z3xmcgWqZGBe4vQ#5BVy>W8*i$-fS+_@8-x>|GI zHE{aC+Hh^SJUCd+rxvf-v6lYeYiAD6#~?X9d$!MK;sweL6!yRVAB~mq#>xwqPshr+ zg8K3m>-D){FcKNQ{7@WduE!YNQaN0??aKZ`*PSx^;t?k`*ywy~vNBvTO}{_Z{PXdJ zg(n90kCt*}rE?ctEQ?3W0sJ*Xu_15)g3jBFuhQ;mS$0FTQ>{7m7iYgl&-@F(AK-rb zIz!ZGyG^~`wu13+=cln9ja=tDDgw{~*hS|%F2U46VQ0V!)z8_*3}uK#X}k>0q@9ay z^tYQ2C(4S@ZI@c;r?joi>;R#(5MY|0CbcpabFLw?5(x9feep!p0HSP0Gs=nWxYYcR zcV|6|f)TUvOh@WFiys1qJT{Z*8?N+G0A77I7P8X=1M{^lcr`N7&LRh{+*(?R1k;gx zejkQ^crX}VD9%;o`M>niOMh-0HvSIonwzMK`Y4g>t_YH646ugm1Zgs^SHll2(D5=ivcD$qKu7G5Ouz7mFw~^FE2u*fEUS7+wY&4 zo7=Jfz>YK?mQ)&WN^s&MS5=GI5I?%aDQ?Q^JUUvH1iQ76oD;_w!a6wC4E+~YfT?7(6NP;4t) zD85YkOA|FKG&p$UJ=3i@zO*u|p0~&`0B2N#U@%w68Yv<^9V1u>&S$euxqR2wh4+e!JwQKmyLNz}?2!5b4Dn~Wt>=sFzb!8V2dwmL)E^Ymo;srO`V^Lh_; z{&oxrYB%QAs0&a&VMLR;h@l?+v(ac|D)Iypxj2@LE-gY97nmy~i|v4VeDy`CoNTpb z5!cpt&DF8hl}u(Kl22xfO%CXsXqnNk6AYN|{2F`kW2(Phj*{ZM+>Xx8IU29m1h?=o z5z1Y7X$izDoB$FY(LD=atYmrXUrAEMZlY_VIf_rvUqS8GB90OeU?@4dt$?rwDz6oIq~-VQ%JMxleUhr@ncc_kGU2 zug~dgGd?S~_3zx?i<|d$r+XuEZ-Tmd`7;FS{(pKeF5pck+lmDzm=L!;1OXs@A^9qA z?#}snjP7h;VcyCnExkZ3k@*E7nzR06_xk4?MURk^VAWfkQJ$f-upnRXgZIAo|Ki@e zRW0e+?%nb*U*+9idxk4KAlGBf-^nc||6_Of#WR+*?%vh>DY;1*m*QV=YfcP_tk<1W zW>~@>^ivIm5d6^&LniGC*kJopIQTvVA73=?bTSS#a&6;ALI_VDVJ_QEf_EVL)I&Ig zaFJX)OG!)HqTf`(Oikc_3-uH<^B(8YPANS63GH)|8KfIkk)Gg*iQX%e*?f0x@7@!~ z-~av>_I^s7+?KU+1Cewq0ApMw2{&N05s#{8Us&Dy(1{c8UsZMJf&7ppQ_*J-S zj|*Mip(Ygx?104Jm*CGE=(MFSVpM(CiFVoncct~Iz0X9QzZKYzz1O%!qp{6xNPM&H zbE20;?NH|*SEG(^yD#c%`&6akbp8t8k{yb^#nroS=UVrlW2A>|0Td%zl+IHZz#tbU z-N+Z4i6vsySb8SrH&(6aCj!>z9<}AMnDXK5w@*EL=Gi;$FfQ{)I*-K6i#?u&1b08-KhpW~xZ2WrRMjUsf7IY(L${S+EU(~`EqJ$Kz912!dkCctr66Ql;~J=;_H6NP z+liii_RQUU>5pww?`cC>@Ke*iD2fz$g8Sw=Zl`D(haVu_?DcjPq zROupVhpxEUZ+~l|^@h`@pF6GUsNGgyD)SR*&#ctN#XYz<+gHgCz^-AD--je2A5x~t z59oqkpzrRN5RH`Mx^1)A*YC$~-hJuKH(%NwPdNFU-5Z;&ly_c!{r&e}fBmjqDwT*u z$mPUrbx3UsV*CE0)bIkF9}SHZbUm*SQ?6UqOSdgva^vUm=l2ZbF^^5Ae6f?|<32_n|vF_v!tPqSN1mm$*laG?`!cE&8iMtm7&#qNw0xV9B`3d&}GQPYqA_ z`})i+xo`^(cY8THkbvqeI_&l2DyglvU!%Ue@zBq`?w8WbDpw9QGX=Dw*Z)!}Uy5Yg zg@KF_e78@`+za9}9?2&VqieW2Q=&eC&eneHz=0PJ9JoUgwLkJtCr|#L(C6V(i#HiH$Po%?x43f%B`Q^^63sI54BMTjL+6J)fB_m|!LIfHVfIaT5v z))f+#2ZXYBK$&_UKBhUqWW!{V8n@K0$KRUbMNYtKav!N!Dz=Qjn5rB8B0>37aYWTY z?$*^vK$fd|8IOBiRqF=&r4URqSSr(1e2UZ6>2X8cx3ab}#p@(1xDm8Oy6jX1NDnV^ z7`iDjs>#aqoGRhR#g{Al$oeT>SprJHUsYb@ak;-DuDZV>(#0XeuV)&)y(mdb@;-pF zer_48IHC=iEAC9~Z@?u!Esn4X=$O>Goi`6U|E|xB`}q`l++= ztFsq)U8E0-14oob-J$gxHduE_)-B)e?t(ta&h&ff`W_$14#S7P(%_$@Th_5z&Sbpx zQh9fO_<*lRR(F5p+qx&;+)3U=rBzsQr0Oy}W%sEa1BJnXxoOi3rQ&8#uD#4{l=KHU zg?ve0KRMn}fv5N-I_r-Hfl6e3Wv~4A`(l|&qp!a;rP2e9N=BXX?)0Afd+74l0+k{S zn(x!sBX=R!L3XVq@A4z9qA!*Y?naRrdM{}Q_a0aw>wMHKc0aj?x!Ye)My&gjx~{u* zbA@gzq>&u0|L~CNuVE1bM9#tq`C&=7t$d5VP;n8<0xvk}cpiG$2)y=k+K${|Ru~}+ z8GeST4Hq8vdV`6y+4v|1dczZ448Mig+ot;KdDmVsoSKlk9X=E?r56 ze6J}2{(p_vPF9F>Uf`$o;1ko{@?611ToGAA>rdr5JaMu;;=W~M1NRn%r` zE5XXjG~62{bWXin0%r4S$i1ob_-bC*<`xV-0Dq%pB+u`a23EQ35(iVg(lbK*JGwmZJjV$s#tTpUA&F10StAW*J1>9XDv+bDS$OvUX?1iACZ0u ziC%K!+OlZrD5lTlVVCB>fraFnkpMs1!Tl=-W{<*CWZSTcNc}+UI06vKh53VvbNC}D ze&}^_m1E1xjj_eWmN{B3s(X_8*_C2$GzUX{JlmRGXu(sCMQ9w`sxZ-)U=G?oQl}I- zmN3p2hFK~HnUNYAoP*V@bKm6TWInaN|HRh9kg6Kd*6f=H`zQS>k{B6j4wbf-h>i7; zaBqfmA8~VCEI1a2Kz{0M0dVtjZ$4K`MRQ6E`65#x?zRek`OS~W`b8-|c=oYm+-SNb z2yYQvcadm|Wi~DI9{u4S(^#v~=)kVN_^ebDeD-cwmT@0~=Fo344~zc175(DF=okGU zONgrCb;A%RpxEuCt|>?3QxOiA3EGr&SfT2p3wERDMiyq^h+`LTtgr08_O8Q+4jsDt z;L7so-~Z-nc3*S##v4};&+e|=vV3xlpOd@i=her_+?>7rvj-<94;}ikyRJDjHh$&l z`>G=ib>qV~?i-z3B!T>IuUH!%=K4fenBW?Jj;nQRI)O2YRTEN!$ybdfhCM^-tIbb+ z@8t7^CpwQVwAH~UIxnc(3!N8Es?R=s&(s(8)l|Ln;J(f`-1`;2#ZQp8_12#MPwv+r zW8%ci!|ft|VxoLNC_An5=DY8DnLgMyn8c+$w8@^5cF;pIEg}m=mqD3od%)y&kHfQ} z&!dl@9G;%?mzb}U@=Wz-j^eYiW~#6EMryU*$lsVHQ;nHLQ*G6s7>;U;uP7*^oWjB$~#E;e&WdTFr#6!HF5l z2v_e6hZFnvC;kDP4RD;){K&iK_CpA*9;?`qgGDzA`{YYKqw}5T59aeSZdJnAP@f^v zF15`hcL|;(rb5vN@ypIk`uv~-NkE=S`O_)blcp!1Etpn$wrrV&`C_0ruUh+-mi7hK zmX_9Te&Pw0xIg*GBgy+8f8>!jx66%2x$VA&2IYC9=)d&8urK}ud36!rrl&1*ME94G zSn*e|_+@0syaeG6TSS0h+5&14#1)UVIwhNCDy?*DvGU+elLv>($wZ&&xx8K9c>P5; zZk;UW4V5d-&Zyt*4+M+#eed|#J2S7HnY!-nD-#n*Lyb?1tfI!f#i?;ZlEnY~EvNx##BY z1$#0uZuFEzuIbs?BdHwX|8~SVK228Ug^TJjc|KT%-_zBXaRh|UoclB5X){YA<3Xvgw2E$0~R->@8 z>x=g*UUqeAu95oU0Zl6yy&L90CgDI(dA_)7<$NbOPP`1&DXL$em zt+(!9f9$rE9e$vaac62O88YTmrE+~`B^3fT*4NkAvd}*@W#xVsPCDO3d)Qs=U%&0v z#|qw%w=y`&nYGVO<~Ns%F2G1`2rgB7)1}|}MNn*d$R&U%-aGs$h)8F1`V}?F(G#&a zNSKvhc%oS@Hy5DDK7d-byVZFNZoOnYcNZ>ZnM2~%ui!Se(TmWOw=67_o6VyO^BWuU z3vlCgzA?R5L8_f=`q2 z9JIdd^hR>&FH@{4l6*QS^(C#&U%<%XKPoRj+I>Ij_t~0%L$Br8$oLTd*88YM0Yhp$ zPthpQNi!||fzB%f7I&BQ~2pUyRdc*KZGa|$Yr&HPm{>9OC@>*8fb+>1p$VQ?0I23*6i6^*6`e7HtDfQ6G^hBQPbZk03 z$>cL<7+^-PuaAlNRBRdR7X1S*au(>>* z8GypXrQL#da<|Pim7%zQ{n5CzWB1nbz3RKXD%H7ZU|_w?|A2a;y`?Una>jheCX|`P ze=KkIdM@9t*YmktXKlURW+@L&=*6C8z)`2g0?;`+l(*wM#yurmNISu0@++b!#U!p5 zBxw;HXf@tzZ+ZLtFigkx@cbRBmW!(^ygv9Dh|zgx{$fTHL$U=tKF<~EBjXbQd#)K9 z@c9PDu2K0TsvvByL=a zK+Bk>AM2Q?pcC~~F+uT5b>GS9l5g5%GiGU(1*4Vq7{%qS)nz8?6hOXmeh^?M7`nX2 zJ6f%_+jpNN*DU4rbhfryD$~AbaauL*d)FWSp^8(GWUf}s=i^jLbDXJMF4Jta4%aH= ztXC?HMyu7{{dB>>z$=Vq?%gfkQEHuU;De4ML#5K|7`f~%UFQiFNe1YqIWIh^R+>)qmZ^7hmV^o~ zn$6#8f1vx``Ppvmb602VmpLHT%zLEeQ)xknmP`yT_pbs{tm^{Q`j?DBooy< zK6QKr)G|cZ#cRC_jS#2FqK>_9rHJ)VcgX5w_3^ z=KLUeIx8pudLU_yrV>%wb*aNL^cbDqD7?LSZ37UOnVH6CPoLsOaK}=wL=-T=7GY?1 zHJz{ps=|sC20cSw@tTvxMBbP&;7t;yHhnl}3WJ!pi1tt@JbrY1wL)=f)Wpc&Z|Xts z_E|~CXNJvo(7ZmBgvG=cIzR=<1Bh5MHbU2%!8Tiot0x&xCV9BwNFtfTOTrDJ)4cRm zFb982@7n3kd=Xr@JKYi-g5cuXu~@3yh>P?Q_<)Y;aL2uTPCFHblE_cGAz>F_rg8@D z*x(a;8CNBYhU0j8ccgc2FZj%2d3d}%(w<)Wk%i0bXm2PaMa6E&g*q8w~tua{@HE2)^=zs>*;1cbh=x#R(7kmqQBUclF(K)=*eW}?{(X#7d3r)=1u}-cSeWriPnZ#*C5y{V^l+oVU=-1%r@qd*p7Gb*No_+kgKB#C<1ty(2d5Q^QcU@K$SI10OByFZU zR40+@G7Vu$?j)4jtqU$81)e6ZNKt=8iPz34*DaNdf66SFWT!J^DNAr5V3Mefw|eiW zbCS?+yUsM2tGBV-rwUl)`D8&{R-LEBTcuWUTs;_xoDpO&vMiaDtTWD28J#7Inxb@d z4i5y1(MUZnx1@a%uDzl40(3DEB8U~;?V9Scvk?_O3qMHE^ITx(igF%umZtgeTw>kX6sE2CP*{`4Kztc#M3AaqisSHusK(m5=;L zG-~F&cDVQWk=N~7-a`Jn@!$t<5>w8;dSNHWedSy@@ybkeY__*m8cD1l`TR5rn1E;}Wl71=Ych91I?Q&Hzjkqp!eOcPV79s4M zTl>RDRnFZDwmJ8rjd1N#q#NK=rb&9aIeI?o}td~U}t zU9b}Psb~#Ca~r?Axmn3H_E>XsB?#3I%aO4nd;E9d-NFTB`*!IgG<>x$R_^kD1-!lT zrE&TCZLhrRk8EC~@^O{1STi1r5!c}aP?N#wrLR(dm-^bdbKQQPN^IA;yZEo&FGc-~ zoZEBrO7uz>U8`^J`*4MB)@l9dh4;MlvP0ePi8L=b@^-lo!cDxq{JURa-(UE_>jbac z7k|YIrO!(uf#{F#Lwgjw!Lgo`J?|0wXJ!JF2og|!^(5sId(e4G(-RuODGPZ7uHl6ChVo8m zcj(iiPzM8cwWUag1$e_}d_Eyb$JaLaEj*ut;MIi#fpXZIYO?#r!->EkiS+G8BwSa6 zOuv3{L5o{SW@x4`RhsdmOQVx@-#ARBHBKRZF4Rr!a2BQeO*2+W; zYxP=c_1KZ!#iVIE845;5X;s`qX2xcMGx4ot0!!33w%5!IJ{L7+IEUrH!0KT+(Avv^ zUh*9>>`Lo8(WFiCHfdGl-J0D4Sq<)W>&WE+gR?DUJv?zw3L4#vZH5xklnDy=m?1lq z3Wp8qS_B5N9}E$j%5+YQ?7Q%wWT*)I)K4@Vz$tJQjF9S@<^Om$rEoBY>C$BAWeqBtO)>jlE;wudIgj z&d#Yb^i0P-W5MAvJ5{dGSpQbXu5ipNbX{Y89KOun(749eaMBRXc1ABKr#RGn6}|Q_ zE%u5%Q`lg;4^oOWH)li7p$BjQ1GWN#^iCMXSQ7@+r( z>gTo%JyiEay`G-QuRwW_F)g(w#+^6rfQgI1dl6M;CEKaz;*^Y1FW~b#5P|T9(MwtZ zNt(nY;N&~FSgXv<2CO1n@|2At1QY-?SSgGZi*ETU_8KjkbyNLwD3chj#QljxdT6K+ zF)!|H>6gH9zxt#8N+QwuJ6}2t-k88Hfp8{^;7C2QK0Q4*(^j5K6CsIFB}tt0`tkgv zhHAjzXn#flCv3mr|GHUd2JLB(Dc+s)btVN+_n` zu>*pHId*vb$btU;rOURQ2~h-08JejCcg>I1QW1Z^4rXR&w`Cot%r$umcQIV`n4PCR zAH?U;1_}QYv?&viUtIP~C;W*t6pw*~+hl^FFR?rU%*UOxh9%ZJ;d*cZR-{J^Wa2z( zD?4gW0}{|B*3hgC#G|!P)m~kCrd~u5Mp(XV(*#c8s-rmEXUl})N_#C`5-P9gRmt#HS(~wL@ICtVdkws{SsLwF5jA3`I0EJC&*njA7D&I z?FZN+VE&4%{gv};AHK0=d)1#E7+cGk*20a2v4C;da_HpN!!i_X^A09HuEM@|qpj0? zm!@FnnbW%f|F*`!quORO%ehDMV`D9Ar8R|OO^q_r{B0&%JK!#g#EBLIU?9ne6(|KnYHVO1t6T6U0@MGVmTbbfY7yW~4kM`*a^_vxNrDZgR& z{_C#Dk3qAZnY_+V$pMVHvoDb9hVSN=*2x!TKK2Y`(sYY*U#4CgAOFv4J=52D#x4LZ zyl$;M;5DvX+qO5imGJQ<`oF1Ph)zTe}mcm6T# z|CiLxKi<^cd91*rMr_ z7_`%sgtP&-MyHx#jOz)&9jodsLknB7eG>x%F~cYhUvlD&my8tc&|GVJ=hiK~o_uBX z_<==Gm_^9)RrbBUE2dlOo{}+CAQS9{Vo)UyPR62kZzhd!*}-|}%QQY@@C8*BAKeDCVhhmG0UeRXwD<6cTzwcAN^Y|*B!ZH>qX zDejtUusa_n@C&@2`xjp#aSdd&L}7GpndAe@n5t4{MP|3sq$_!<2rfO_@#OtH`0j86 zwd%?wWSKq^)oxSfA*N_c_BS@NnRBTQnx(e0TwhwO7bz1MjRy+F27Y^^kgX-fD26Ad zmd&!#i5nKK(sBizFz_8GQ%J&tW;#TDvXF2TW^GU~xTdefMmbM!o9P@LA1_ZdN+D0G zzd2NF-`p50?~YwGZzYibrE-72?JpEY8|6|U5wmjrwd(lTe{lve!1GbQ-W#-HeX*#& z-tV`H$Rp#W|G(!VV#Pn%^J6_<1GTEXAkzEKNp@Lq`?ySn;s@WndR(qjk0^V#&*@Wlse207u`L}w807J$6!LH=p zYdlr=i75z3$h!&swh1RS{dp{y;p)WQk`*G-T6n4-7=D@OX1# zEas044nQIRy3XTE#qi8f*oCQ+`GM3h#|vVRG%u=Rs2CaEzFf=~#2F7JuoO?%rzS_z z@v_WL%JRl?;3Z8z@i$LEzQ_o8QlnC_MMa0>(QMrkub}dI;-L_8s3%HgmMj@yRG7(a zSzg+bL*k0I?x8r0*V{{-k2**}<&A_w^}gO1-Xw3JKb!Ilmxub2Fp`H-{aKQ;e5CvQ zMJf*6n~!gz)`*w=L75 z^#hUFdI~?Io!YX^4l92}5{%QEwr`9S4Wu6fWYq_4_?Gcws9q2{OpYQNjZaF__0^dm_2sNFfrSvK+Epu$VZE0#-3Cp@91wL(@d|I)ksi!nRX+H#4wQ}I)W?Oim{ZeR2CQa+4gOZ zB}sL+sQJ0PbVD?--l8V^9R0_%S_|+DE>IE-<(Ns;o5>am$v_eoIn+C-mZ9OY7xyht zM~x@vohz4H)Ig5ja5^qTUEXJCASv1x2|R&sO@gPWep9V|7cbSecpg&fA>Su%YfX{$ zITJ^zd6Cf3If$YRY{*CMw)qydS zxzG;z$wzg9Bm4w+xn zq|@>R0#1fRGv93HxdlFBF-tHS$}$BKOEcHKkW9csbge+=-Ly7*^#h$pfFi*Rs;;w2SUC~&< zjr0CwI7u1XmHf=&_4lj!kbTAa`rm^(x%JY;*K}?_b$YUO{mKgaK4Qdu$9{D8=twQo zs20=%N3U5{_{gra@TWy|y%Z-KVkgD>9li23JqY zX!Tr+*5tHgf@}^CIC2o$rmqjwFyzz???3&zYoGb?dtZ0Wwky|8w%co$&#G;pM)p3X zpq5D%<98f6diwMijvk)7<+1i$YwEFm%VYC!_ql#HwnBjK6Z>Kax33GhXoTi}{9Q!@gm8S9(F}FJf8?m}|;bg=oYqWOFrO z!OQEBz{X+2IJ^;vtS={>`5GZKGm?*Z^Z86|J`fZHb*`q%<=u2A3pl>kWw}m|}S?>*O95O~ak9_iz>hLE&^PvxQe*HrqQosG) z&hzhmuNp;4AAaq<>f)u(>N#zcIqf5O@29opL5??SxXw0BiIFUt>M+C(u29;12VBGi zHKE-R)yed5YzR;a?DR9v+rDRgyEdE4%|@Fm<+8eABhv!VE%}q;WMPoh7DwxLAY0C@ zFRH1|Us>jN7XoX>)qSm6=YLjn{n_QFN;He5J&X5`)DQLb<@y;+ao9ZT#wGswLadxv zI=J-vpX%HcwbU&;VA#@iNL=}D;eEZK=WVbAJ=F72syDvS18g_W4TuMx4(elu<(C8j z?PJA-D!rEfivECdU3CPSK-ZWzP#3jG)-$wpYwb~G9+tV-(FPhA52?LTxSG&lZ!|Ak-V#c+JhmrG6LFPUNUM z=p>V4V|gP9TFWNZmqhTQ_#63hEe|#(Gg@4r6uH;I=_A;71Z&cZLOvP^B%#(cB5||D zX(GvdhZMddW728_90XJ@TP_#9U|Z)Fnq&c^C*TEYGx>}8oQz!fsk_xQ59W@x*Nz9u zqwxQ68D(4ka6Vye!7kC5sx__+6th{vbQy#?r7Hu>+R;ZUhaAx&RVCuY^p6uw=cxBQ z6i6*p5~aR@{Cr)-aE{_d8Zw6wV<|AL|&p&pB70cdR42QGDZ1|@KE5+5pLNb-^ zwQ;ZHzk_0c#(LnKsrH47*cUu!MCZU4Z)_LbJrV#2+k#NhbYqs_|j$cLD~!nTth zDj=g=+@knXg2+a|yuzX9Izba!L#vXc(tWbhr$lCp5-0eVX`!_vVgOn}ki37iP^}s7 zTK6^z)mE!o$^Z_U-xwWL>-G8wKf^wArl4Hue9b+IK^IftQ_gD5TJ z1Bossr3AHQiWN#Rz5p%UKf#;V9owSeH)p*1N$bJRuBr#i8t6|l?-T+VXsu+#k(bPX zLOIGXQ)^D#l|nL`O*%$qp*A~J%atq8dq7BT=i`BW-arQ19gJHN%pMrsLcpeEvmM9D zRIVfqBU77YC>Ub_vzRScvWuLOAKn118|HGv+qs*;imrmv=T(1?mdAIB!8On@qfYoX zl^XK*5xDc90HQOipr1T9sd40!O4hpu<0_tPpj-aj!?g8?!>0T{PZtJ5-A-v1Z=~%>%gKEGBSNSMze_{ zh7vLXR6<&qyhh>N+$7+U*@$M}^XXXHi9P)lC-(J0dGt~!eei2B^}(6b;qd91k6spj zJYDJhjnpU^RDHvl$HNzl%LraJVO0{j%){b4rp65q&uIv@68cH88ketpnSHR6zWQzN z7vqii7royyzH33T@@R2%w9u|ZzQr@ibw;z`{J&+q=Hni3^wHklN26ZP$5rRM&jpqB z+`TZm{!ZxeWU=#y{b1P=IWNT{zVBEO<3p`bn zN|HV=K3cJbN)_GBCHl@3M6pN_9|FGSK$nz599eGaJoxhqw(e8MhSHfvq4N;D=jqJP z*GZQTd^>>CqkdaDv&g!1aVVqSMOG!=Q63ThCKYmRv$VO&cr2YB>J)}3d^n{3awwhd zJk;Joyw(oZa|1uU$Qjadp7nhajO4{M-;49}a=izypFF=_+Q84h+XgY7!UXvVms2}a z;xW*@X)OpZ9kVgjp>(0fm$yq?;}hIq7PwwF&X0RrTm7z*@#@+|eX8@2R*uv$vA#PG zyu6+MX|bW)=6T(|^G&86-E5OrYNj`lSXSV!0h|ZbUk2>$KiF)aAH)364W3>&--60_ zzJdOYhLf20CI(0<-py%-#veujNr(>xnx5mD(VJaIhe}CO6O&kPBwR(_QFl@ItP2+_ zrI#UtZYpMoTs@0OgY*7qJUJUr*0Q;;!kvReyc?P;i`VV~-iiwr;1Yg0N~rVQOr|W{ z;Ui;IZES#%e1S!?bS z$%ddmZ32)>De*&TO-_#)t?o=u=)NK`V1C_fx|x=G58?T|(~cGijOFu{(QNkjV2bE0 z6qvx&=L(MVaLq=upDLCk0i#x1o~Le!6(y~;fqSQHSefS3*g^H{waPFMb1S-1-!_;B zWpOpLuAX3@ky2xwUsR=*0r#9z{kg_KVegij$7thD@og#ekKkSjLwTNwR_t&@(tC8= zF@_J}*TGF@V1nu9GWlI`(VW>#^pnZMGo*`=n0}Y`T>x0p9O`|A!O^XQgYyUT|2)~; zwLIB8x@-9(>JNfPF1r1qBYW;Ua{G1nfiaGq{TB%BzJ9P!F!F`bvH61c{w6>7AMJc| z;lP27qo?mX0#+sCUQ;)RK{#g@z^+Lw)Qw$|o#>8i^pfs`z~o02R+cWDEoA@;{>+W? z5Mb^apO^qu^#EyuN2#Ud4n_5VR{iXbO<{!xz$3Qnott?3-qEQQV98eJdG=c|^11bP zE>BXxC$c!mAUMPAdiF8*6vhUp$ky3jKl@m{4Ic8@l_~eEQ!6Ld^EuK6BwN6p=UjO$ zIfd?QFW5Y{zN^S6VVKhGIz4l4s&_|li#vBGdsqC0t7OKpPuh;Dw)N$~E1yMYRU$s{?+9WC)}wwY$8 z5RHBz8AtA+e&ulJAsPX2ui)I2TxD|wv5ow;ycb|r1>@gfo|nucZkgGKN5nk{?+=+n zKP0Ysn41#&f3x;3V2)kYov-%M(K&h?9UZ-no~2T$RFYb)R;yGhRdu<#x?Ei@xBKOC zyWMU##xERWOw$-+I*zd!;~3*Ogb>Fxj{)K#;BXxW9B>jKBq13lLteyT_!zE32+qw% z7?R8I5t0BG%lEgos_Zr}xigbn>el1D&pvyvy&nJdU%3~FXYuU6NIuH~qcI{*T|;E9 z)q9_{q9fe`+Y)Nh+ia?)t`>OV?~+Z`ZeV8LobrapWC|AMh1`RxC`*K zZ#?h2j4gxzvy81@B1iB7iJ?hYL5Ix51`^-KwyGjhaJV2?hlV(PBzbC~%celkWoCl2 z)uaYZZ)!K5r^_zgyt&o7YvarZ%H`ct(^zKj%O5y;)abNcj|GpDU0wRvhdBjkER#J}Ie_0Ay)ifHFI z5nrJqw`iO){F*fXI1VD$lu7627JOXXnkdph1d54AG)`om-cD-OjE!90IR-Crp(7&4 zLATxFFTqFe8Vh_887g(Y1+gu2fPSjOm#tq+*9mzO3x-N0rVDZGl{cvyg4k?E3ftGq zvlh@?0th8M)&Qe{fne5|#E>FkGig&R5oa+*7`2E(oDCBeOSb62lY~iT{!YyUp0Q9# z*hJ9d7q2HdoNFX6yy2F0CxW|O&8)wCuGMUoz&VWGrGCYL;49awr&E3&-VA%9oRsi= z5CB&!$w5ic#^R2LO8I;_7Q+M!SvJ0&%H-5iDwS|U_>`&lQOo<`-)Od)gPZryKJ@GNLm7I3>k znY^}U@+Z`9iixAc zX`X!IyJdEl)--oy7Q+N5Low%=xCKH6vq>CwTACOSK@=}LGZ@CLQkDC;mlwFkvS?`d zKLT2%=W<1w;TPa(qoPUWWzo?fDb~uE9_`|Q3(3&e9RiwCJs`4_YxdRVfquDSblP{E zKse_|-(6b%&{=Z`DcRv654oBz9-!h-Q3D_;9b|lFP#=8>|44ti-9EnDZ`9kWRWGg_ zUtT_YV)P~A8ylw}D?5Dp}vS}zs{b!vn~)m@slY;+%d89#h4>;J}k(Nos{!mZ%) z`?uW5x<;6fKBe#EhwtUz^ju`Lax)V$r2i+M3*7bprn`9xUl!4#r^Yw)|6?D+C=hk; zf8}2Ot$pljCxxcrT>azjWeFK9G13@8dvH*%7Xhf$ivfx2j=2guV2d`G&94o- zBJf(NDX6bnT<3bwPHHdR{CM~Z6qhwkoJi=`qVP+y4t;2BhuPXyyJemY&E-Wf%7FGo-9+L9*FcCJ-K9#y%{VG=II{t7U497Opz!FrQ-P0Qzeb!0^lAYCeM{i|gpv$-Q*J~+U zfq5RKoa|Fz+nlgb*{r3U{OFtG%>}Bxv2{}aRt^1@6&qEYkos(Q3V)$r-IO;D@Ay*a zRaR}!3*ytBm8`sUR;#>YWl@?$TeGw?jW|U3YrHdUB>Z}`F=l*lig_F}S3E*|6@7}b zne(@*KhW^yXTPHX(BzrJHsaNb6!$WschX>#NA$xa8(PtWhEt~rMql9Kq77r|^BRgQ zFy_xU2BoB(izUKNEOIBVOON8|$z+Ns?dZ3NBkdNvIfsR2&)Z$YA-`>VoW%C1VkKS@ zxJ)d?@$9cHKx9b{q?$Z_5tPJ?W;M)bOHUGqhMx5F2BM-sU(F;aU^dxh+$+@MOcERG zfACVO`eqX%xH$pdp#*k_sBxclTr|?az-}b&+KYfB4M>j%2vbfUetaLtC?GILN z*jRt?hULMaTI#&EIW5a3xlxp~`dnko$%&OU67m57Tx- zbR(J1$E#&oCA1Mzsp~E}dR2`AjYP;Rv;Dn4|ACN^EMIcqmcwT#YINBr_usd&G6mNA z=*r%(HCa6{eZd7g_ZA9He7JD6d1X11OrM&&=mhQ=V+o@y^nqWxXz68pmXta=XR2GD zee`>~;^stUSTp{!+PClQl?M;j(nhed^T^@jKd}dOcHAGwyy+Dxx&_j5KSVO9YJ&1^ zYq+US*o6jfeu)2Z%VgV2fZvK>L!mlRdts~kwHUF0=0aih2Nb+Ec2eaz21=<@J@<^P z!Mps-IWnBz`wVL>%YKIQqbsSy@Tc4dKg8JM_54^U8&$!RKKoUf@zi|`M4{9`SiKMz znjm8i*{bj_LK!3iQ!X2ykryz$DgoB-^Regy`S$$L&aFE-2bJa*#-@Bn zlW30hKpF38vY?;$2X7m-5)k$o1MpyL9en{GI(-Buk8pj9EkTT=**Kwrhc5sT-+3M> z?-rr1@aw`~y8?UK50&^S{$?f~kL=qQg|9lQb9QgF7K1I8TUwa%A z_h4%+;tyMef#Q$pcL*$IL5XFJ^Dr6~srcj&`Ibb!(da7*wmE;U5)|!UUhwm1K_EfE z?O-MhL}QsK3~PkP08;Su8HXYzWOFP5zR4_rr%yIP+s1mB6@eo50@t90i+<-}Fe`)Z zo%4}Qk}|1Rk5A8LjV7CEV@?lsEt1sBkfglg&4eBPA_^!Cx9vC0$GS3M`SE1HptHCPu}i8BC>!)1)GaaK=qQniWZh%w*j1 z0Op6>xQ!UVvk(JfJTX}bVb_F6q)C@B$gGgnrQo1D4dl|KGvR}<s#O>MV!L1id=rp%lP?51ALRj>qye$)1++X8o()CiVBDeoQ6fcXo@$3`o&ue`oeVA)&})X14;#igV>5=9L{T)Ik7ZD^O9U5 zFK9wjO+ukvQ=WZu-dwP!yTL60oAwY*P%4S+l>Uk~5k+ZQn8QjJ6P)>zE%~Nd&M?-; z|Kz~%D1=Af8a)+-Ee8pwv0$W^F@-o5DZU`S)VW8T8kRHdMS~Ck2!D~M(5?XlMU#-2 zD;v|IE&hqAj{S@29W6@J{RFVp;FWquuG%A~z(Buov1!7+vcp^-3MG2-d zi3C;4N&TT+@rnQr0qA0po8jl^J90U}AoxQ&k%+x6^BT&Lp+1LzUk26F%QP~4(V;3y z^Ernm)H>{#KO_jx&<^-;t^m*UhQKc%$%Kb%fx>t5_H>i?IRWue3tRM5R1(38ZVirR zmQhLUjpl=CHU}>??WMO8{5X`i<1Iz&CGSmdC{9+5Nug#HN7KPoyEZp9P5URMwWn|& zAV?X)pnAq(jOHD^-c|9vJ5uFTdxcJ|uA8285ngS0ab?TVNTU?}1E z4b3yTV?lxMvOsKhbJL4CFfBPT#1X;u%G=NrAooll%N@rk?d zzVpscga|mB4}C(06I4PMW*tD!jO=&a5wwyQGjdMVYo|e~?6hraFodff6bRrYY<^`(1}o8HvO|tP%m2=OgprKH{Ul zK<>izbbGKFndw>ZoYM3!2&fuag0pb@)^s1%LT}vprEl{hU_Jh_&<9N*&+qw{JrCvr z*oRi3@wOo=%t*?EdDHgN#agu#v|5ly)4vLZ`qYFEH&mRGt#m;<0zb%1*ezx9g{&V8 zwUkQPC3mJ)DTfn9CldURwOaTkFG=OpeMT41VbQ5p%Xt@p>89{uF&M&*kkfg7v4Tw% z1)hMrj+&g|C(j=ijFNVYC%&f zTtF2f-zNHOU%Itxfz%pGEXqHJ^ymPqjx};i88a{!Gr%ByAI2b)T zJa}-Z{BorSxJe@#5Qvy4Wz?QkBqm?U`+=c^3VLVAQN!hC!STY~z~PCq3~)7CET*a} z(Dh|Ve|>mnW`6X+!NG&`>eT$f(aGMKl5K}b+QO`lkmv5LluOXagOFe>*GX$m*iN~k z4tR06E~r}FlO2>Dq7)RyiR-N_rttSg6VhGIYoAvJ?hd?>kt`2a988+eQOrgpAWbIr zBMRRSf1*il8%X*KhSK&Y_9&xRVjw^Ki8ZPXkF9}?OIsIlXTlW?^K)xbu5V3r(MsO$ zihkNX|GiTc6_u(#Y?JpYot|vbJO8~?VTG{!``%YIul-kzJ9h6DOpn6{Tkl3W+S*@^ zG1*}$I?UF}@g|)g*}}UYD^8QaJwvYU%rno>e(JeVAOY_6_X8i|7Y#K*uaLF^v!@3V z>WMI+NIH;K-E?Vs1wdjbqw4%+W8W^F5iCi@YNGLoH(4}1!Fh;R83hQig$}k!Mz4%o zMyq@<^`Ig)U$l%-JjqHK%XI5`aRQ)6@^IB8JZBiqXr@Q5nh3_6cpLz9-zmD_*ZVt> zl4daPyyDcUS0D_jw-RsnnIf@;K)_wU|tRu z>vK#-O8kYRU3Jyg(VU$eC5ZRe>65S^M+=rtakOG&GHU!j$6J{cE&Iq#{ad!Kq+PZx z4r`ZVK}TO}c`#Sr+BG&|b0n0JiJjw%b#9q^`4K8=sL13BSH|)7RmaNsk(bZCf@|Z} zc201Ij#IQIomd{T(+xn}Xqt&6u495&6>Rr%33hl9<{sf<=D~X731O8 zH3x%*mpGdh-S|t;{Bj*Rf?GhmzN}UqVLy_7Z(87W8%h8PBr|LrY(b9_P0P9kLsE z3z;7v;fH`hO?0k0RTKE-@4lXL}B-o7e&b~J$rKxpAz6lWz=VS`#T zf&*)OxFg_`nN`WJBOQxOGu##FPF^He>XHB0%{F1I=bjCQHl3+3|G z4Mr}f3`$njyhu3YhFy=OC!t^qI*B;*3WYg1ldZyTJeP_Eb9sdhL`(`NMkGu^bg@WM z0krk4pb1$|IN=eJN=0L2YRLPOG4j4l-h#%72&OdmYxu!9)KuJo<@~J^i&7QJfe2B3 z2JMt=4c@KR8d#1fJpEZh}-~dtZ za<*M7Ojr};jbiJ#HIvV&e7ZifY`3~Ml1LR#-|AL5HoM*Lhh>-$na z7*)pHyH_f7#;j&52$?*l^KjmbDkpRzk_3B-suv1gzjc$!*usXE(A9neX%c~d2QHe3 z3e7}tGg6d9+q}(%2!wz4kDgJl8XZtafw~wMrBg?*xMK8bHF;FMNmW1pH=~b@KE?&^ zn;d=JEfnLsjvpW0s;Uq-8i7f;1NXokxI`V=K$?J>j&|p9e z4R9@$Vy^|kV|4MBKKKagr+2$2`~5EE0z2(itJQATYwN96-Os<_UbEfyqOD#J%D3XN zA(><3in>OT)P_c@%vX<+>&ThFbN_{B@hpU#B6^?$2>RL>b9 zBV$Y$yJ$;ffEE`rT=!}Gi`f5QCm8V}Kjb6Z5WvgA*d5u(;b~>#?a?l&voiIwogVj1 zbjrzbKzM<5(xO2;gLE_<1xK{aK`}g*Pg{azdzRt+x$zV1%IS5uT>K>4k9BLi0W<=# zb~j;VZIcm3N0613WLr`7lK&_RoKVD+{6K}7WI*v^?#N1q8BcL|C#g?7jyyh}TfxsE z`T^ni@vbC^k!;a`|62~g@pRT0&dnJepU5r92}qLG9u|pq17W5Jfj$dIl5^>ckp4)# zT!2sw-6=V|$a(Mp`V52SY*X*fvJ6$9r0FH%n=lrHDuG|3VR9^9S%9irtGUNaPM(L{ zUxK#6%fl^ok~Y@>R>$kFn7wK<;Xc$blFL_uD&+``woM`{K{5V8U;`eI(}@! zxocq6Cu@NGQ4r>uUdD0o21uG1)Lbr=SGAqr#rBL=D*h7=DuGoY@*+Fowh;#a+omia z3e<9yKQ^##9Av6xq{-8u11*>2M~ehBYz%b@r%J|hR%!u9B1{!%@Z~WCMUz zAWA_i#)G0Sf@3iNQ&AAvQs0>5h;lcRYKbq$sF6KwT0<}cjw{{>M7&`-^){oo4ir2? zfgJv@W7tZnAT!z6QwGT(?jm6 zTy@<{%G$&@;%el4z(rbR%s#)xPl~UzwdsD`HOqj;S<;5tgUq`yqCM=n97Ad;b1Yhr zpi-tAx6_`tU2Km zsY*1QS^rF(=xO;=6}&RatYq-#oZ&8N)fWDdl(YI}XdNuS?fZvuYZ=UCz+!>(grn*& z5)?&;@gk4X$sbMu6)V~#)#WW_PMiaFw(7)zMF=fMDjoJyxcEI5@Jvx@am!#`Cv0|( zJJl?L!ho6>Rs*K~MEvr~L@FDGpX9ydS;uW0U|}=#2m*AewvxX%JUJP@IKPrh0<(~r zuQk!$gULdIpn>zRoGgli!wkm!99L+22{#o9ao1)zsYoy}LWxo+-iMvMYbYMRYjjiP z3ey_<;41QB%A9pAGFK9&E%*qEL>Zw-G7jN~5zOT<|2cZ9m@G>NRwhQ%zIsJH6Wzf) z%@yHRA$@QP$4NeBafA$h6a@|swqNd@?>or5Ru>my=nbTDX3}Bme2>2CHQJX_K`I$c zQ&#i9hEfODW5+^C@;@(aH_^H9e`lge$4rOvU25mXJUf_AM}nbftVa%|kq5*P1DlEK zhkl6L#!@}#md$WFPr2Zj@5iZ8Y1?MTjHO~!vqY%~eyv+gsZh+Q)y?%&WwCpX+*F8B zE7i%bIurE%mlh@~_KcTgWThg7 z7WpIFv53Qr3#(ZE0tx_2Wxa@R*#L5yP@OB*FwI^n}BVgk+pfQ0*z3p;#1`LFTXebRoRHd-qf=T3Wp3+R+zw zeDH%iim*hX8x{~Mu{brUQMh;%#$+@UOqj?(`i{6XdF;X6xKEuBsJ?By0W_1iyrpw8=GX$kMNu*@6fTl-Z$%4fqeYB!$4n!WHSnT) zxa3rvQ-y;#M3HcKwL%;=m8Rl6gE!$N(y=hgs^KNQd@G{f{M6@HR<5Xexib`+2&$K- z#LESRN8z=dUvN??9C3cWn^S*-g847m5cd@+Cv1*rptra|1^~lgGS-SUB8Uw=4mfAz zCmCDF(?o?>fJ7jjXfkYiZk{qq81BibOsQZdXb00~KG+k&*G7VwWD^6a3R5iAi6*E3 z6%EIl-(N7Z$j>UiXxPlA6Gh7wwgr;X%7`P|^}z(k5}CM%5uD*@UO?NY)+AQid@ieM1=M>p0g1%5594R8h=({c(| z&5G66<11MKC=6pQYfHDLP8y2y7`2(n5-%DLQ&FX~^P9(z*Oa#A=&;$XRf~B;J-`(0 z;n-wmVoLQ%HD;EeJ%|G^&&d4E1a}WP+oG?>ppgJP;DgXFD@W=K;Ekx*H_{A>!mpy9|c z)HpoZok)WnSrZu?#zacszoTQz34qa&rY?Pvi9DP>d-)<|&Y2VRpFV~p%aPt_r&85o z!G_5=WWkpR0Kz5(;{p5H@#)SNR4CtLI+LD z526v8*hF^Fn`YT`dn@$>nO>w`=6olfQ);T3O1tWfI9DSq>=bilC!Qwj)S0VQ8@9~~ z*|<~mOK!Z*Vp&kd*7f6#@$vd(wcBx-2a)_L<)_oV8jEr{mQ|qa35OF2H_<7NUYpJ| zNCep0yz0uTimVwgaTEOJe&wFWHsXpzi&02zq9WX-khE&8cDMkUf-KOs90GpJR2y@0 z$n-K6zXELmK}f7pxIB^K>VhvMljRoMFSe9Xzx?uKxiljLnyFNMFW`@h7I$A5^b#Es zCllFdcy;Q&g9GY{94r-!>iy@U2BokB+-y0;l@-S|H{CW+m{ca;@;0N_tZwxBwbiIa z*%+5VKlNf(JBtV3k9WMtUjsDM7}GNLTg9jyc6s2X5-Y~t{W-r??Rvh#N}4XuNzprHTH1zH@(pk0=uBZyKu)Z%7v zpajE!gbtVSnO?$Yg|NYD3!JG^Sy^niHkU@9TH4%P8h-KIxi6kOY#dwL|GVq^@4xQa z{iD!d;&O+SMz|kvqX93mqi!|>vvxRTzcXU^%81@91I0kYOStfCS?WDIT6;#ny=QZC zkGg2jrh4{E=T5(p1B2byamo$j1~~Ft5>Xqcs7-3_!JPQC!~?9KH5uHxam3h|Zb#iz z!yBCV=5fH*t;OTtIxaz3XXUXwSC&s4Ul~%hC!-!pIgesO43D2!Jb3Wj@WctWaGd2k zA6s5t8lrgP$Nr~)$@uzHyloOAwdgx|mB&L#9>#z`vUD99T%;GyDdgzZKtt1zZ*%pz zVU`3qK^CN!eHN;{ zKn~wwN%K5h1#jlh1-=~kwhAzte)mUHTIbrbQlx2Sih$J8IH?;AOzN^EtFDllTS z(bKp=drGDUUSkn5){VrhmWB8W2ZW5zzw>bmFwy9_LmvSpOq-GwBd0BDIZ_{>zzceo zR(mDNr;ozP@BaSSn*{?g3tQ=HVvI4K+Uy?G?QL|em8bc>ZAEG zQE3}AWN9l}E>^ax7&fR0U=Ny)%xY4tiqptpdDe6*I+U2abg8+myOsN8O7lb03shK= z`{y_a9DNM%)nZ@kV>6?n_Km$8xdlsiO{+~o$1QDZAF?!8-ik5@RmGd^#oLF0S zJ+toCZgSQ7g<#>SXDGFrl@l8Z~s~=-H8^A zbQBIn>g<7#MBxdCM(?iIrsB|@GKa&JWx@Gm3QM}osT|~Ifqt09VhQBD95m!bIvJQ! zvwjVpf{7Y=^VMp$GF^j*1IuKO6^umM$)Fogacl;conKnXU75wcBxTyM%aL4Gr$wjo zu;y_dZllg&3oR7MSh$G&%83<`*b)^mt#CaY!RMKcr$7qe>AX*TqSRi2?7;i;Z=iV_ zi%Fu9o|@l`sSCNlNSp(5)xk6w;1SrhY`;{Ah+=@{PJ?f(*l{&W+3-kuTL)h!hB1sB7_F?I%xgqy)E;K?cEb};mj zAjuj=B)fx4g$;-+!T+xOpb#0+-%XX+X?b9f!kB5eK3Ecr#>0mgFcZm=14hov?#)h1 zFB{kw}eP$j+$I8VyG>k=P6X3^NpWCM3!Ys}avA6titCKgLF=J0Znj=oBGb zLtfBn&Qx)?bCYIW{gzjj{t}4|jb)BY3<66jYmmtP3GnaPf z2S%ER2+nOtmY_F_G-KdC@YjT75XjwHDxFgBYK{U+#J=86JfIu6a+@#KHAJ3?;Kry( zgFG8gRY*`~8r-*A4qA|y+DAGEy=GU>WjWagS<1&2G){D8WaUCdO%RpVhm<*<%0?Uw zSEx(~>W|kO4fDiX9$DWwj6;2W{qXSz7=fMkN~`5Nf^Oysneekj*Uo;!zvR3O;EiZNa-m7P?pzbvhO=&h|8b86~>%dbx*p_iy9 z+#rJ$x;(5PFknf*0T+s`TsGnbtPZpeWUHo+P!xfU?>Ns+4H7d2qN}TT18dP_#!X2w zW0oDK*a8C)En3XEZMrI4_2((ty6pGHVnsmn-TZRP_wR2HQmK{;%^YxWw^JMvi2&9m zY%+|uZdpq2-uLO>tK&i_56DPu&rD^~Nn%Pi^mO_1u57kC)o@7+WSW3#X6d}^O_K{K zmVkgm#~GV1@N#m^8hfFAHZpSwG#9nv|KkpR)c78~o156ap(n}*|JB?1QNw%$+gN-1 z_8?RFSMN^aJ}*M={MkSmKBptZs?G-PlUk(`*x)9Z@@3+c&dCHW_a-Kd4!WQjqYg+* zuymnGM;|od-;~LkpaoO-aG}Y*VgdPe5E*(yo5yL3X29d*NH&TYN{9QrHYt8%w7ayApR=T0goh&>j5575L>z<^E*dFou8)S<175H68=UD2^WEi*I&~e6hy* z3MwlBT35ZhOYSFR<_8zAUhEVX4;)?U8L2m2HByN#`=>R zMCjyAL@emzsl(ez&-|zDZ`Z z6Qx)vU`Z+>85@T=Tv3kI2}5plIyxL~tRIH}f4IKdZavt}tgK|(*mXu@QQMxE@?73X zkGlkGWUO$}&Ik<|3$&m{>g_aW{Cx^jEhzqtS#f*tsI-%iO+{l9RjtMo6dcR!BQ-q7 zUKMT0?;N}RwqpZKeMn=X=Wv{R{iS2ao~Av|0gZA8lxAA0dSE3b7-+Hi*Vx+2sDG}t zSwOalx7<0lIly(Fc?4Mlx~ji4`ZlaC@@1*omWhmWy|C4}u}%Hln2&o#DkY{RwloGd z(IYUd1#HaQ*a{skjFC%edV?jPZZQmY1JrI4?nX&g}Dx70O*Di%*qms#4i=6LxpI8yeqGZ{8bzS% zKkhoyBAkV810N$IN_z%1uC=)>;sVdTjS4 zdlmU;w_!Ek4Uh4g18+B)bgF3@6XL*+xF*j z4E@X;g$*-{Jjp%DR{g7dcA(X{rLr> z=5^OyAKkIo+Vg7JVR6S_|J=pbzxpTC%J6+(SlF@HzyA8`Zn=KPB0$soEo1c_)4czF zl<2pj*%<5Vs5jqTyhpyT>3@8IR(t5>tKar(&joG;PmCG@dGF`}YqPz$y1aaA_0+8@ zdZwB`Q@v?vIQ;nHnS51`m*+laTpOGquN@zQ?h4Gtj2f5+<;l~1nVoc3%_irJgPGLd z#nLI~@6cvS=c@h#Ii`%<1E*G3-~NMs<~y$YolL%Hr~`P4^TWLBt*)LLeO$&R&vAq2 z_#nQ~00Tk`WZcj?J$}nKh(H@V3T4b{$vtg!-<^qs6Z3noxZ=(`Ph7FrsS$O&;#-fY z<5zt1ieVz1j$pX`LOPuoE~`5qyK^sHE0uJvc*O_b)c8|XUF+x&hrA+tw?lX0k7drpwET#f>A?&55KH*6DRD64+ED1wW+)L-UWmY$d|}n=MsM6TS*=d( zQg`oKtyVvO$^2k2IJh=D8zbyqNCczDrsuRAmzuV(l{&?O=-uuSkd)9kBsd^Tg$5Os zNy}LApsH6-!32}Zl*W`h-=N?w=36-u?LmC=SN%-7{8`qwN}nw^NS2_!ZXdmbq>TQw zCSjG_r?=8amq9!2LeC2%0jE;}kOrQSXk=EO8r_UJjx+)}H5K$k)xe3Aot`02K;kUT zc`Otm)E|2wN&mwFqI+Fkbq8edE}=^FH-Pnc-7eVhjefgY3s=jdM^E)yEXg+{a)L6E zcZS9(fi=v3r%$bfbgsL@Art1*M*k&gVAbJN`Bb=@%Z5JR-zb%KTy;u)zPoBi++%oQ z3St#v{h99G_q<80i?HT~k@@@WV6849JM(5*RlqFV1TdQC-^WX~nO3+Bt;&jbOv``n zf*uA;R1;gE%}b$Ufu4-#{@i%75XTWsf`buvJ}%8gM||+c17HRITnzr8|?gTyMHv z2oVXI77G2^WIksV+RzyJ)03T2xtWBxI82T!Rd$$Pm<{zuEcPymM`1GuIhU{UMAPN* z>v=p*JN-xcK$bR2+LY2wHj^{yWG>mWo4w>hGH0AT@x?EmP@VRPd+s^WhCk}jzB+Z+ zUHaqkXFsb>^+%5$Jg7gmIB)_ta?H~lb3d9YJu5x0or*N~LO(10heo6sd66-Pbtg;a zwwCo~_W_*lW&7g7+}^CYkSnR+R4|?6+tVE}Rf!e<145tfLpBe8U{G!wtUWFoCQIlA ztUOviOcf1GV}KNF5nh4f^4z)67tWpgT+3{!)@m2mg*Z0Gvlm_{lDlfR^)LDrSuXA+ zrH&L233~*8dhG?yysD0VF!}+W6!W_~jHd2uV}481|JZ|HB{t{u4?lxeTMb61_2h?`h+S;=QMM?v~YArMw=x>=WO; z;kMOw(I0dNSKn(GxAzxM-Fw>#!)NOm8npMHG1rK$s_la2n2b{lHC~)Y6Sin8THLqN z;#N>bw0Mn?nN;fX{A#LF%db}|>r7`EW;DN=-|Q7h7Y40&s=H}G8CbU7)`Ep1vt0fU zjmpksS(QqLs-!x*_wL_!@mza$GUWyBeZ8yJJ6TXWiD7pMzs-El$JZ_WO*-8nuJujG zxmn35Ruvnsy7<)jz>$x$k12pFOfBdoBr43#4Uj(5C^wAX-uw$GO{!uRNlU2Iy5(vY zv~$_4I}e^Pjry>Kv*ewNl|iGPQJY|Ygd9X{f6CZU}__u}aPM~qm!2u*Sx$g|zOLY6!1D^cD0*x z!ST8Qx7(C8*=bZgvV_imJO4YYc2ef6xlD!^2UtMcn-$~lMQ`YP=P$s}wrOUZ?KT%R zC!h0NfnDPmmYvIzjYM6|9Onj}-sD2;>G=hFE^Fte=W|ZO`KX}Rm>i$1sP9Lq5yqk? zgyG#W+y`85^hI!_`AoE9xP-+)Tgj$frxjgpf7UNX>lOFG2Rm0A-ZHKH#evCKIyJ_z5M7O&Qw!(dYg^#m)tvgr+ata-Z|5|(>eWz?%Cd% zp1L{KjP3-tp}>uFCkM@Fx?tf!?QmHL3r6=}Pfpr}O!U`7af08!G5VrO{iB%io9wo% zE-d6?^+`AP-k*KR=&{5~;w@I%dzn39C-x?u`Z;J7-+Xl;XIJbG@;h7(|IAzXoK+W} znM~f{ZZ_>t{#5T(vv)kR>(%``6R-Nui95Qdd)s4SY-8Hw2tcR#g4AFL6JI4nsx=#t zlsyJ10>swBQ_s6%q=*RB(g6Wdr?`s9Jfqe~)m*4w51f4D)|ED-4#Re;EqFqdqOmM_ z_@>K3R-xpSW2J(Yd?6LxQGCt&9@vd1we99OOuC)UXXas63q1E7#_N}1zl!6T%Y*-) z28FRp&4awSRGp-s4++d!3z;Db!1Qot8gD2O1ADj-$~ESFsQVb$Gh%cRx3L=w_&evp zAZ2U`=P|@lina3;iDc>8K3z3i0gOa6ZGp&{F-y#B*jUIl5DtjZA;-)%q%EwT%+l;K z#Pv5IG$rngq2C8Z3I#XQb{~i@U%J8hhBeK|$TqCzg4M8l3zl75fCj(m8VLnFq=`Jt z(BLu&u?w5Zo{~;%H|80ca;QcV-N0wL#kXE_L6R6mZZec}z{Hv>#y-h0fYE#b?@E?C zn1# z?(LLEMm|;3aJ>KuQ3J`Y>wv_Q{%wUKoauaJ_38s>i#XY4mGI4 z#?6~}KIs8SLLvz$0>E3?U6vpdnH~AYAGre>eZntirRCzP6||?}`Q>Q17WJa}XbNYW zX?6S>-rQPVz?DWyROI)aW+c{dElU!tD?Vj%|5#4p7rGq?*f4p(g7##vNjLS$xLwPL zM0Tm$B3Kl+1{B@#PgL7$GO1giqoNC6qQ(Q#srf4segSsQ)vmijI&Qfs_4fo{tn3j) zPB0kxAhY%8qpezX<{~E@iJLK|xbh87jdD|VgWCfk2#5Gq$|WAiEs^|BYP1(B!e&*%o$|-g(#*-;d_Y* z`in(;d(e*TJeYQfNd?LMCu2Ko5~U|PLLwl+4kPJgVqsDnB1Xdt&n$-~YN^-%RYk`W z$r*`Kn*^MKD)5x-8SV<`4VcSZ!i@VWk&et%<|C0-O!;fXXF@@NiODkza#5%;j_syj z+6zxlIB_)~BqPo76j2wzc%k3{Ty~Q6U`2w^gQ;MWDg&2N9l{Cv>LhD!-A?M}wquY1`oL+k3lddzq*ck!W% zC)?Lvvf|;L;vwbAlLcUU)oE&XUwj;;X#aCR2z(G(vJ*?OO*EyCwz5Qh-!-^*WEMRZ zI1xA%xQ48vo2d7D2H(e7X4W?_x85IkkW8b80_Uih^S;3Q1CKJ>emL;az;6aV8Tj46 z9|ZmoR)Wt3J`Y#_(}Ax9{wDCXz&8Tl417EA&w=j;Ml=IKE21eW<%2h@kloaQOWVLG~k6kX? zbH4xG{r-24sa+OQonSiKpF?w{y@+nr26G5RylA|D$*RS@laQ|AnlLG{P&1oT;ZXj< z=6^W-`gs*fhvxUb{*pf?uts2&08$W;NRaO#vT;O9=O4dhF~;=#c)^R84cUIYsXmB} zoEotGk1QL2c^fa@K2vC3GVcFpma#7<-8!oN9vu8O1_L-t306x?U-_|Sk0?Ma7WXcA zNkl!dg39jZ8}KTWYh($8yT)}lTrKO8Q0Uij+`2CFZu?6TH;@y~yK z;~!eP^umEV9Qh3|KGa(X_3=-nI|9`4Z_2l=CBd+n&+D-^BXOOPcfR(4J*!6r^QmYU z3=LjP@63}}aI&nc1Op~788>lEp{vW~PBjno5l$lOA|84299X!^>94c6j+k!ZX_+DmEP{byoyJJTU zDacF&f^Zf_9Ki@txBEjphrPk9X7mD%Wl^{ikm{fz_kP#c3_yLi)E80AiZJV!>-FB6 zvDR&`njOif?oc(gY!Lfd()ZOY|F^s5ch^Iq-zn8*@_7FHtG({(1?^p65Q_ODUNM`s zj94-lk6Dq%!g+B>2WbkIhSnjUzj6)g)sIOKH2}pVNWp9CiQ(Nq(UHd{CMsH`psBcS z?l0RzHv0Gs^?u`O6GFj)8KOhn+%#>22K2%`_AIMW8+N)yu&yMb)K4GGtSrJ+=s8~M zaGx}lR%0oJYe(4b$G2{-w!5?ib&AVC5DCti!{-~}-&0wQEc+e1(%JN$@U# zJKOU+clCD8UzSf==1s#U6J|V^j2TuoTl9|Pi?NtlOt&w%a93}&uWF@2y;k}i%bXtT z+t2;?z^ZW*zIB^<4!>-=Pj_X43+YezW`NcaXQU~_b|*$m%L(b{=#&S!VsSTmUyV5Evp4sHN)0^%PCc@0YttAM-2cCH z8khg7LoR0irAL2#qdzm1iY}B^tY*FvDVf%5FHI(b!7J|%#Z$RL!B0hc6AL@s*sjH? z&A)h?9eMm@_oo%Bci27};bMUs634*;8u9Q&w!Sv(*VtD`S_b zF3nc+u~Mp-n(X3Q8JI;B!Cy|zymPm=%iVQ&?I)t)Y^sqyx~DuevvEICnVEkruq5;D zK{PGtGayD(tJL3UOidWJch}E1I`6D!;fvaF*-R$wN3WQ&OY2q6&LphVgGq&xd4m zB&TK=7&{e{u+T5)XcifPIozTAq+xBL?jXt{-W?o)3=SQigq>^qlMwmwI}fP#H7D*I z{jSPfvwqDF%3krhwXgb>FN+tj+BNf))<-MFa<`m$Umic9*Z1=%L$M&5psY`snTf4tjoKR+=-1?XQo~x>|e|J2Ya$fn$@%t2{*dpss zabIV#;7Uk)aJ|WpIHi)}TsEfhQpgR>P3Z`TjU!%eP{IWw{Rinoe)_~+8{YcaO*J@s?But9Sw_P^*j=v;s+K zrP}U#eyYpeR`c&n6^*mTZO2BB-FE!8`bQtF-n)5PZET+I9AExcs(51g175NG4~?>K zmh-iHs+~-xQ@#0S2_25#@5q#^KCTzxt_nT(E_mw}@Ij`z>*>HwYEv9!jOi47%)M#s zyD`(=bYnc;`@^lz?cYI0l?Zu0v`D~Q8$0jBEo{~PTNd(gQUu?Uru0Oqlxr61P^?^? zujO*J{n?33X5vpuje`d}%bj}ZiVuJ1@t?Zz=dQo*!M#^}Sp7wX{W_IK8GhYX`Mt7R zX&0dMYN0!kWzW$qrCckS%au-F`_rHNR}wXR3Eu8o0;kcSUr&vj0K*;Qn;;k26cX?vKNdyTAI^)`J7!DS zjn8MnUI1%}e1VFMwAtMB-1HpJz6~<)0=1+T>}IZ+qavyRPz7zn_PoX$k9S;{l}(y@ z?c8`v@kNTtfb>F~p(Y@o)T45=)CeIoU0z|vjYy$UDt-RbCp84gY< zH+=V7$YO2<6Oy>^#zPj463gl~`Llu~^H@eAjt@z;G1$gpL(|&5ORra~vLM$m=aw(s zd7^aby`~@fcZYVq^0Eu9w1m&jo5O{hA%WaU&H;a#OHyPgJDr?XA9`YR7ynjn`@$EV zKuLM_L+YnTcN-_47@gEuoo!!xihf>ad@lr6>E}7T_x3byJD%JEpSgwHls%nek>;9M zn4>C8=!K1@7VxakO{z5f6Rc|5AAe}A-KcrP#)*e&txYd=YhzPUxwzrghMNyOyxx*^ zt+6;4FZ$)t(t2e=UG&En?4P*qu^*`Y z`^z_6w6V4Fu_bj;`8tJ1{etz0in>U+yuTm#Gy1pU?&9>|cLjc*R_YQ3gRi^UAJj5) zp;>`Y>3K}|uOYG*uZwo96Dk|(y2rDko{pXDLncd^7THX?AwAqcZxtl7_S2xsvO+p) ze_<|@1-ZeVvTw7&2XnG`LNN*DBxt;uTy{phHZqeY6!A^FM+_e4RIMq9HG8@z7>HSk zclNTB-9c;0*amLiL^hF)`LWSo&JZP!?#M6a-N~tH+|6VOQDT4KABYD5KLQzz7c-MJ z7KgjlUcm{4-NKr=^JHgw@4C9O4#*N4J6JAE4Wep3U&s-u;CG06VzFeVgr-j}T1U{3 zsp(#nijP1fV=6O|0|p=6BYpwBy+&C|^<4hmrMNgFkp=ksp)~l);*1&FU0OEHbh;H( zxIzTstH=-1U{=FV<+$p2H&ZH^W+OqJ=Dj<0D8R^5i`B5~PSi*%b1G|;6+9DQb>ZCR zLQLCpYoeWVZP^{9e8#7k%>Pq#GOI5y`bXl=5P~$|y1a?$Wn#P&&JG0J=SI(c9jwdW zBio(~Jgc}P9zqX4=o7KdprKte2ys3fh4Ozjg4Gw?n z#RJ7u$7G3Lv2F~^bDsoY$6W_Vy1e8l`lWH{7D^QVn=be`$>u~jHpIn` zYjQ!#jW_U#T72Rq6gkL3NgQqHy#|fpEc*hIYczXMV$u!mhMmha#j?&cxe<$w`TTzt z%JF&g^$C3LOpGnE_4&`P)WcyIXrv^wH1{J08w&os#L4;EfG^Chp~F{bH%*UF6LnHX zksPTu*9g@Z6#Y50#Ma~RqJ<7=95&@3+`9Zg*KAlhix7uI zy?!|z!>j1I!Pu1JRv}BH28cy9Wt?4ENS?~!R6GosFDxWr+m{7;tvaomKP>bx&(_;R#Z;y{Wd@c-g7tydlJ3*&qz^AuDmV)Y~;(-#I85 zcXWoz*jPUojUFu`IOIf>A+TV$QBuT3Z3TZY-Y3fWx zjrIqPN;W}qv>!FUY&7Nua9;QReR)Tg6w;|($#gJok6sxgl`fHAa}u$1^CKanyjL02 z@mTB`U&nU=E*ov!NYD0Y6qNuMjW>fDu}&}=Gkk|cb1xBxCx(LA>G@tHv3O|GZFT1D zO1#~6C#+$onV3AZn27WS87pq3I4>L>3ECTB5HXyHl?lZuKIhPoIU|~w*%h6w%(W*o z_#6S{b0Q`~;OMRq^r2h{#v@3lgsvhU5wQ>sM#)B}iJ{J+tT)*EC|60SC=$m#NpCRR z2;g!Lza`I=)Bqy1`CNOhG8^m6Bw{L0unDrsaQyeC5&+8!Ub+U=#P00!9$c zdy7YvliJvqNgAn*$+m#I+fx@OQ|SvgQcmyC#YSRb875+HWtgxkdwS_Jvr|EHs@t6k z8B@E<#;(G8!Xo3cyau&SD7;jjPCL#%zx$9uf+2!@N8CxGWd;J*FlW66+}2y+9s51J zkzWdY6>g+&Ynz-2K!&53)!26~Q4PcZBUs)u%LLK?ghc27{~4dyB~+1jc%&0ff-@qpF?6Hi4$a>}(dv&oPVM@AEG1=+70 zZMHYh*M*@3mVhzNjd`d!xoCO|!!*U~Ihag*fR&J`3&SO5v)cRu^_1rN^8?@%+*@uI z(9SHL5K@?M2=quD1(t_fT+$8k;`5B~KOx$~9=t#nh#X2RG(6%|Qn%2964W3LfeOgX z#k*{hF9MUh26j<$>7uK`(LsI3OrD4VL*DRCRN7u^XhrWkb=?P|CQu$&E(i`pD~?w+ zfL0Ry@QpfW_N)g4N&)?8(Q;~1$DAXW<|A@KYH|r$fQ)P)?O&0ClyW&Q{N4J*T_+Ek zFdR_CFsNebm{APEu#mJuX~P$*R)X<}Hsp8)nQ75$_2arDSo^^itKUOA}3O<4(&o!b~Y01Z}FZ zfD??_tBb_9^%l$qGBMF%YpQ$46Nd5lcb_yLze~bQ+)db#$djpKK@z<%y`mZJc$qwP zt%)AHgHEwhr6z3Maf@DbIpaYiBJRrxqb|8_(J@ANUc&&r=|B&wU;U}Oo(w(y zy^k5kNdc0_tf+F9netAmSR@-PtPHAT3&r5*HF9>9jC;~z!tDa%Cp;C)PPjN8cTstg zG#V-}8un5+*9eRFRO-#)l5#`l1mb2U1pS5}HP6@E?Z8PauJb&oqKnFS62p?u}lc~vXDMz34z zw){Lv7Y!ebwxn~A@!er>6Hu&*Z&eD(o*+O!0jPx z%c;7aDRy_}(<FBODz8w%P?+E8Rx zW_GJF#q&sGiCElfOxh6bn>Iv}&2gA10T5143HETIx7Aqh|Hg+t^o>VHUlid$Jb`u~ zoeQcM0;a`U!^^-IPxag7cFQ7yNlOu2h2SdVH>iY{_gl1cukny$sWUX#J#^)<8~T?X z{rg8B{rf`#1*EHhR9hnE0F9aDB`e8zH16gWTZLkZrX$E6b@z_jGXZFxN!^b}RVpVg zQyT6lLXpOu5f z-Ey=cZNW=glXek#PV2}hAFH*Z*~$zu-55KC<-5E@wUa?D>LlH6YgUqYI%-@a>*p4b z{Wb|UG;xlv9A35up>Lz0%*niB!^X!+c_bWxFVcV6xJF@Vo-7Y0Lqwl1x$HPkO0G~& zggB9_k|#dqlG4`^B%2q@j>Gm*fH@+y5fCi0nRqj8-3xMP${d1)+Be0`Td2n4jbf2h%vTNV}P%rH zP9M7o6Uz!h#X_noX>bH}AzQfwtw(65?UyobAv3FfTDb(*;vuiugc&Pe1Wz{O;dGI4fX!3LGR$6z?^5WfBQ8^b%C+DjJTRCaJSf znj!%)7z-DOg-x09WOz6H0}&Kx9Ch^doV3G~GMK>K%#fb<>g7F;M0$MHP$)Tti2Pg;% zazd2^K@f|;wrF!Sj9dIw24DzaMP`l`BK4iLVw(pjv^Ox3Q?^P{=oSgsC(@FGNTQ-0 zjh7~h`!B9GYiT=Q$xg*{m2@%;R~1l#aCk?tl7rf+HMv-uDAtolt*~3HQ2D~}lRGQc z>jl7o0%8OUAP)>gYB?JX0_-5W(TW3MNQ7sS@mjQ%FD0@46HPC%NFA579gL-cGT5qR&RMOj<$xvj72~}a!H@Egx4{!AQ8~w>>G)Z=I|Ef|t8wapAbDx@B&Bu2{C)2h! zJ*7rDz1f?)*EtadUEoEpD9)(LMKEK`84s|3f1?dfCE9C4Hne*9t{ZM&?KfbiKDd?{ zeMP1E8-u~d!zVLFt7>^CSHqUxgB#HIwvFFR;Q8+oN!u?ueLp-?HMu*YXWRo|$^lBX z2ot$WYQ1oq+Y=gsO2jUBA%yL4YnI!ZgB}^STEo`+mT#hvrsSac8!fct4?D%OD1KHo zni<`xHz}4Ynd1Y$$drEgOH!1*VLS{@^oj4^!2YdaZ5h7LXsu47Rm!-b>~2^XP#-oDw&~68|xUkN{I+E>uSuBObYVkxT)R}sHB|4sKh2~Bp(;?;%r+x;cmxxCZx*~cx zE?d6H6KB_4pw)B*(Ih1(DW{MQgU}UmuY?6*dw*HS0mR3r7xEm~p_jp=kt^Wn;*Btw ziI@oC=3)t)joc3Q6}RSF+@Kg=dWk*$qA_SjD^)h~sZ0^JywO+k^|E|lhsiF}bsIDy z;LoBI3_xi@4@Kdw)*S#tu;WpS30{)hdgv4Ig9}ln{iS0qEh2p6jjloW~iPAy^@tH2 z;y^Rth9=*@%|l&|aRYaGw2v+qK1yNd@Gw>3Zg?~D>H!W53rxlE{{hFG2cC@gs@kt| zX@btss;0|NrHiF>vYc1*BznBA5mQL2ay%_gK{Oh>DQsA_atbIcsm$)|QYhGpG-A{7 za1a)ryh6|kj7XF})0&)dg0`EO4#z^qjA>5Zye9$SYXtw2Ln?&KP*4t=R*?*H*!yXj zl3y+zVK7re!gD5y7>!JWZx1GMW@}bhVw28wId1Cb>rdN zM<00LK)!Q$aj;UYox0-yI1qK(DKB-FjxRQD+Gq@lR%LN0sdL)jKfqV;9|hu6qahh;xrhJZqjB4>0g*v3E2 zXc6=wQDU*p=>1x8VT_0X9=k6YBQh2kE?9oXtT;t+MP@ML0afbYm#UU;Iour@;kDM8 zmE!56ouO$AyGK9ODf>$Zl0xpCJU?}C~4tzy9(sXRaArL1b`ovMX8-rOY z&LGiz^^1pZE|f}lzvD7K3%Tp}DYucm=uNl$5%S(o+l8gn)D(!m9C{9f3qeqi$$CtM zk|+eJ37m|{INk&!?sqEtchF5rt@Q+%87TuomZ?O@p}L1M)2A%eQxg*$D;VHd8S&*=u9)4bGo z(2j6vNSeJTeKTmoLtAT%ClxKt#oD0J$J)1+^H#by+@haFc=JN4>&J?!9o(Bb94HGgiU@?FiR#bo2J{IB^l{G-Llf*rGLUG ztbAe?5}T4x1FG`CCI}SJ=QGmeji&T+Lncd_f1fd!W%i$=UHRb5@-fL# zm_zxHIEem`$_7%gt0w9Yv2>ltVq0=`Iv`ANZrU!ZS#0#}wPI(;C=!*4JHtQ35L7ed zK7(H6xkb!ijt}Nd2qNg;B~)Z0xn=6D(26D8zDYF~_J;7*P!XmC|0rto3{GR)a)VJf zR*%QC?J^vCe#;IQ8mR1M9LC2`aAMYoGlSr3XlBglbTScx5}b%|sEv|r+0CfK#FX4% z#xm4y$Wl!yB}LK%z%qiDg@W{N7BCK#ztQe?pVj@hDZU%ITb1?MM9!k;cT$=!CWe5o1iy_O+so| zPX!g636%~r&$)SLFC7)nABnfIRAd52B{I^2$sNuVm4ud-7K3m_tg0x?r;$W3S0X%U zSqb=8F(d5(WU`jE$H`;JUgQvsQM0PREt%5Li~%e)vB>xk9>EHeIdnoL2xv*U{%s?c zh{bTBh7uSQF`S-7YTO{f%owF_fD{)>_%;eotayuM!iIw#g#9_r4ZVwb?l^4T)h&DB zQlvo>uF+v{6223^^qv9Dm0)*EiPJjkQ(7SX(m`&cJ*4z5#ojW!!u3z2@i}_uhB!y>GcURY|R};=Yd# zP8`31zvCwc1EbUJcFwG~+c>6+KA#-u_y(VrTYM1i62mxteEZ+2<4(qDv*~ffoX*+& zDEC*<@pkcmXpK}pwPX@DDxaamhm2X|Rzo6fyxL$Wo@exup@*52ft?nmzwA}q@M^hb zMKe{TPa^|13K0~hvQ7`@xa;Jr)FkIo8CC;7mQ(f{c^?NUpr(`=Dx&3xUi92E_?o_nRQd}3B)I_;i=kZM z+;B|TB?4o7S8|tf#oQ0dIP>e4RECF4Cz9zqY-$0eb$ZLL5jqg*k2qoF*cf2Juz|-; zKJ`-h91sOzJ&+sOl#}2mZH$*SiP;iMZ8T|O>LhV~N&Dc3d=q(w;|m=KA!f*=p{dcv zi?s7$w?B z1uE^D-=D`NZy7lv*y$XRBV6xpIb1Ot&Cc$M7xSyd^)~*H(ErQWyMV`amiN9|-&(WQ z%$k`s_cf!@Xf*d3jb&*x8qLVEEX%T@$g-m-j^hX?D8@LB1ZO#_59 z1)5TJNJC0fplnJh&Ed&`-NNYwD7)oQ4u?%Chs~yJ4!egUHU{YCfGWAoj>=Oj+ZVqm!JL zTjYjAr70i-==VM=T1)wH>oV<&y#(ahvNvu~D4+1h2Z<;uWwFs^WBB@ZvM{2Pcu$u`cS2{G?E% zVPcRuer`BjBA-M4 zAxUY#-37$0_nAdTM&^JxT(U~YLM7x(8VoC?GQ#C>5R9BY3^6+s-54Faswm{JsG&lp z1?y5Zm6H{ZWt3bHdBc)7bu<+jZJ0(9jH@>H>b>wm$wgQZg_M~c0x@^?%A&S%JQ4;@ z&)Mi{IROJEcj(^3=VJqeJbMmqQV$#IkOtK@AQF&ISpr% zqa@u1(l6otlGBSx8Dvd0STuDr!gu*5Wj{14wmX<)UlvU{BfM!q@us5=0e)(*NX!{$ zV<7l?alDO>WT)c}mmA3vhL(%qjDyOVa&y5Ev;ptB(g1wPcn({n-tbS62*4ka@vHov zW*pwCeOLQO?O%*rj9)T-!}zfAS>tbw9~du^-EhJ8uxeSQ5R-5S;kyzz=7GXkld&oy7?8L3u3HjCl0iBsTSXR~H=;{0jWSYq zrVBn3iL8k0%L_8>e8q)ilblRW$vm7vwd;_;*O4k$=#G3VL1Ni2uZSshWj+!6VoR?x z2vx{MIvg$Q4DTmZr^`N<_VTVtT)NhAiH$+0Cb@VB{=6oP2=$tG0TvfsPBw^~!IF@} zSX-oO9C85nKhKe-29dWGb8_Z9YZ0*pG+*!CU={0ig^p6LE4e_t<9j|}7VktD00@-^ zk1x09xdHipu>47}2|}M~*TW4_V?#Dev$Ba*j;0t;x$z07+N7e5OA@=QS#?hRdvtT=Zyu+lq!HCSIgWZx8_ZU7PnkaqB?N5+&LFx2dgFe z!_FrrNWCT|3VX7Gv^la~+u4B;fUJgRgq~yd!L#UfD7P;L54V^eTy-XmrNtl^lfl&n zT<;+yguspyu@~?_&Q8R0x-H{ES}aW|B}u8`DP8F^%H|5(*uv7I*PuzMiPh_MD|-m- zkEl^Z(HNcFx>td?D_l>~!P2ANfa6f67(FMCCxz|?KR9=%xnb#6j*%a>FJe#5xa{H0 zQu+eBk~7GD?Chy$)q8jmN`xWjE2YInJ)9t#EHz6Wvyn^&ysV& zl{tgAo{O7Te&o5l{*#Ld4b}`cDI1b-!zd!i4*W-5gyxJZn`vDB42T!S(<3ud4wRvb zz+pZKDzYjbXa4hFy{!b#>My(KqJ|GMo?&%0r1 zQy!<>27)d_gPZd%3?zN<2wXpfS-)S#lGkcg&;hPV|A;`NIoiN_svdnd2l&NDoG6gmRKVg?I9_i|T@anszOATm&eD6Q5+~ zUOQP%);rvCJJn(y%XvDUI#1pVJ_(UM-jv{3u+6;NmB=$~TLVhW4N4n$ZAG8fJ09#_ zgh&~I)^U@9E^!6V%g-#6&y_k$GQU&3PM26w8H^L(fz}0v%ky^VOrB1LyVMAl4sSD6 zxTLZ;LfSKJ2`>;{i&@$`ji-Y(36Oe^lyMOxb(u^(rY_znP9VTgSwtD|9hzGjoLdnL zu{Q@iPUCdjlxGy=yElZ9hX94;8k|N(2J)AmQcqR_)?Qq$xL0L(^8CH7V3A8SrPnWm zp26iTr=RI?FN2GUQJWHVlN+b=JpzjqKly8ZEIGBh2`C1yX(yznHREz>uHVw1ty=&I@UWj9AU@?1K^H>7SqN7&9!d~^bi|LRiQr8Pq)Gr#l*A;2)HX~V7@T`t&Gu1m&Q#O{A#@vX`~bFaf>5(N zM6LjV05c0H(MlQMz0gnt1bGB~h(nrsCZaFmJ~FY)xjhPZuz`XmD3lmZ_+)qj`9)3D z*^lSs+McQ_VGwx;*#R$;=+L~yL=t6|oda;PgHqB7aq!eO`Yct6!7&Q!GsWyA`vBxB zM7%T`T(`t&_#?Wmc*3|K7vZKzX61a!B&3gdmZza9=@1}*#Wuc?%0fQk7HHXVsSM2F zSPz^w!e&u@C7i=Gz>{%tPL2CZSeB(vqzQO@Lpvy-EKNJdSvbNN0jL(n^_9kBLa-T# z0<9F~2u?+tk-aB}^N73$=tcKoeXtv+0?mf=B}V)5rDxMfThK?`nLma7W0ow-YagZ8 zITvp&67A)NX-By!TwVhEMgJFcD=sRjvCce z#OS?LelVxDauxPa)Rbs$N5$cmZhwa;rWGp%$m|5Hb?(G01&VV&!tn=K47BF~h28RqE8qo*SIWvj&p#ixDt;vj`=nS5J>3X^_ zK)cu!P@VR8o?>T+tK zm0-{lC}p-GMaknC9K$JOT9CzJ_!+af5dcKWU>39UEpmF=7!#6Kkf&VaD^3rDif#h| z@k8uCoEADY{@AS3d%lqGNshtj<;gfRGe@Dkqo$Ua=C~UqW+Y?kDLKjsQiX?4 zww1F%Y@2bibA(t)#tgs=3`V&zh5?O37ji#B-N4BaE#&@)t>_B?%%Vi5JiW*Y;swyB z#CRMy7`R*A%=q6$8}O~%hB*zwlV<~ysg8K#od;uFXzEtxsMl-|CVSJ3C(zz*@ic)D zGfw&Jt}TIAm?}cd1R&Lukw9?I}u8Fo3cO# zj%6m9*FH3*v@%^4F#ben5NItM_IY}f77^LR(fgSaf*yT4PgrFWUGm#T*d${glq!M; z(lEYY($H#QW)00rW4v8XjgiH{YJo?jbvgm^PMGMHk5Hb>CXU_^R4#}~Ee;Id&nygn zKn|3zCV48#jcG>#VlwJ9?SougVkV4EX>#__PH^jN;imL4M)_cfFet9%SO!8!jnfto z>hrWx49@@S97Jb|KnBLCRq$Oftb++4xsZa%^yjqK(F$@-`7a$R0~ksh`G=fALeh~m zNnJWLNGC`OdS#qsw)_gC!!ON1SBpgDa6FhISf%$lvu>T0m4aEIeT6&W8qzxCC&;Ms ztN!ocZKTVXWUsS`L$HW&4#P~!3l8)Jo{JTN7d#r=4OiwAoR^FHjEXcNb24M_&bwEhDabEy2=eKBIolv1}r#Z+57{=KmA>jJdLDF36Uy(ha!r-37_0Mo6 z?m?>=gw%(_qf9huV*G-{Cy0*lG*rQoRYm#$(S{hJNr(#akSz0pQ}QVI<)L%PZ?F_J zZ!m7r{eDSiVuCP=nW79&bO0R^SuGTiCNll0u;zg2#m9xOkuodn3;_bNgS9;zh%)!- zi;(W%^ChOlO2RBAY9yURV3kY|&7#PG(nlbjXEal-fn^lQ7Q`(pSCDf-gRZMEvka*u za|qUb)*TohffQR@&oWRYBre6cfkQ?{0Hc=&^nl?3o|{$9q(Haykvucsfb3$}#mRx7 z3v4G~!+Ou1%IH%LC^kQJr*WFeGQy2VBRoH0uQHYRG$&;+jZ{SBF8~wv%BIj+Y$7?t zY#IKHBSt<$nbCj-0V*--55}^@$2gkj#vc~2QhuB6^Z{bgcoOn2L`);*xIce3173rX zz^OO^PQ5G>k^T!r04pj;NoCbGsW^p1<*DppQgNt1AY3WcPAvjo(&r3Is7I6a6037oc{U`o#aEB>TmI%kNwlgMDfe_&|=pq?d26)J{ zpEc98#vETMBH=@je8_y3DTS1la&=q>ybXGQpQ2h!KSrFArI#3-?JdM~JzGg=q0{AI z{Ax_b8&|a>-n?c7m9xlXMB($ipfo~K9zfcKS;A9ND9#gzoYh9yN$C-)Z-9TH-~ms} zqzA%D!iPCr%=68AJvVaC+H? z0?j*m+RjsJnn~s|!L(QyxF*AzvSmnl=$Wk`b4as!4x$Xn9mm2SZDm+OePjqBPH~UZ^xhy8 z#Q?nxwbSE$qg| zFRC7OoF#TFYbFEDlv1qnD4w{J#mEP^mO(0_3K7mD7(iup3$4-{JhYK_Ub!Pi3*cg| zKx=YCQrv@OpKr7f_8Xd)h&$>oYE}kG$L#RbUs((pbp+igz~Ime>~9bsWAKn^GcdPM zXL$-S8f1NE{gVxJJFjK{dNI!Gj{)+fO=N-e5l})Hrow6%oEjl%sX{9&D8+I}X{XzP zB$IxVl8PYQCqgOd^nV*1FaN0GLWo`ZB0xh)i#0_XVSFRxy|o?nTsIaZ35D^?xfqNL ztZ5L8@L!L*PGa$hhOO^^cmtojV(A8na7A40~897?bSl)D_qZqubBu0i-p{2Q4 z%#OPYYvTqLmq0Y6YcI6$?!=6SJra(q36vDMmV z`d{ASf!3OLt}HEnRr5XH|KgU=|8(9yJvZ`IX=jex;SRNiY!J9vSSfbHf+{%b!!T#x z?A6(LWau~9jiOhAoJm;eefa&SXZPUdw#e9@C80kxGp3PX-kXA>EltEF-J7+#rP=9v zihZWx8r{#=776Kt-BP{eel=@ByE{8&rp6Q;@-26|KIZGyfr&)OOJ{#0LLG9x+^6l= zr}!|YdS355na@+~^T?5>H#d(QQO3GDT63~$eGT#O^u|U*Rn|i8U25G}bJqFtKG3KO z7gVVNFCdCQ1u;UWqCqu|9HFwG6E}bpt{e8cs#T0qW1bEyD5Ij(da0q*Km6c2hf01@<#dkH_ps8NB|VD5`Nuyc0t>lFCJBSw$+sGdi%Y=W;6=p;YW+Di`|Q3y4~OARgJs#AC@}gdC|)WujPcA7c|oh8td@`4@{wvIgY-rBL$%`L_OhP{X z+5E=b+=hDBM=qY+I5<6j{6hZV+za2@qkZ&ECpRzS^BeLHZ1#GaJr6s312~;uO|C`CK3MJ<{{mFw(_86T3@w!t~?g>hpXY!h`$$QIyp5_ZxRd?=Wslo>bSn8|uh8gx=34wFe(J{r4H?{q~lz=!6RDUQ$xmqVZ@l>V`6Q z&U~={+}hT~{+Fp127t&GSuWgC1Dtbj=ygMHfkETf*&>c@8M}yU2AMd|k=rJ+ixDbA z(zLwx=dFYwWHb|cAf{kS;nKl=9Chg&@Q3KT?4lQ$$%^@}maLw2}ck2eH+PL-BjRJqyPMum~_w`e!o@_2O zn+xi(ka$$mb2g<{2MqHpK{`o7P2>JB9|K+)UGGPMG;*rP(^(vhrDbY=%CDA8k z0-`+ zSXvg{G3jQyN6iyB1dLTXM5;wi2;Iqfc-Sb=?zXW)-jr$A6xjz0Ej72IHA5SnY}Qpx zjLLX?k|PX7Qr#+xCv7{>wC=#dx|Xu+Ycp}p*rl{s7(+VzUDv?hH9@|^0t}V1 zVt8_>EZk!rIQiupL`ZqUhuR=}wXVC9cBOXy4(^3&U>}luf6}=tKJ~;LB{AW zAs?>52Dlt1F?iy%^d6SVJsP5@JZ<&L_4Kr8p;o${s#D3OOo0eC^V8Z78_UjPsgXyM zX_pFjnmHtcGX4~aFZ?Q07Hi{<$ka&C#F941zZP6rgj3z|xwnj&jW%S)9b zBrKtB>?An>FTJi8=NF0WF%gLp$sm!9Wm9f|D8Fn#EOTlpgy&Ykbh(}-CP96xZq|An zR2QkNt`6-EQV!O~{}E%?7>08&qPNDN2Pb@L`5i!|G3_|c7Tv&=gq2hK`gO;^6DKDF z=3F)#jzty{Sml-xo{QopOv1E=H5?lmVFddV&B)CqB1u}L5OhY$b_ovd;LNLzP1<>) zs!6<>_5KTmDH6~Uqf@xSQvQw;2u30hVnl|cIt;=1J9J;v7rrkTF+vf?!Ok_`0h0{T zb=F`gGW0aS0i~>10+wq}niI_Y4<&1Ie7-c;I1;KT?= zTtG<~&0oYL;A;fN;wd~5I2PQ?vE763x;D#-IB8wB>0UkTsPNGawK+ZvLMkhoqz@tTt6`Q;rVag|I-jmU80gIcpGavOkH4yp=_b!4S^BWW_?}3m5{-U*2d7l z?>mn;35d{i7v#*|W8XT?vd`X&KpyWsfKCu+7A1(hAR1$e#U1yy!Y+u}HaW zr&WmWt@tO1-ye_O?Tk>mk`~wWy5jX-e9?{G8| z8Fq%LAN*77#8+V_23b{?==q_9SYoE-O>Aioju%i&y2X-FV+R=l^)8y9 zw=)^_Wq~Xr8)SUUqGban2qljXC)R^WFd%yu&aRHD#x*zJbn5W#_G&hJMSczlMS^tM z`baD}7Me8|i>0H7A6`sZ(FtZ{vj1Hzc=dtujkTZ|N*QX`waa_U>aBrrH$z&cnH*hAB-;mH=!T=g0)ETPt^;S& zj*$-K5+uR}#-fQT*1l(x&XfE0IPYfA=B|d-WN28Mp`S1o7_ayN5LJSllr@hD*i=$U z#1d>6h*#i(#Z;wS*S!K8q;j&7f)!n$HX(AaOU*HwCPj4`PS%CFKPN!e(xF2nF*U_y zZ1~&xkFSnQ`h1b>Yon2wiR5kdj~fZ%8)TvpwT$(D-_SRl`G|cWl7_b9oVNGBuPN>3 z;{Untob8_u`MT${nUaEKaPozxw8{Qg6j|a6Nwt~HseCqW#+U6i)c;&^MG9=FO+?>T z#h>>Z1*}x4s~Y}{KYLGOU3H>&7S=P58yWcMI%+)^ALw0os#lXQnZq*JLNW|haTj1@ z2@8wh$QT+l3NL1fr6N&6C{HZM{=#9uMt$J_o;bnUKeQn82{B%AvShEXAIjItFv0>_q# zH_2IdE9dj`lkM-j{+wYSiC0MOunkO|N3&7oQs&uCUI;bF4e+f!v1e{39D3aq=g)?k zc+&r3^T6cIlV-*UFU9&hD2)&BFFB8guZ zIc4evUvvMFJ;{3xPH(xxmzS^Hw|UFIQ)lim)omz&hO=?{+}Sluk>mHBFxNx*#b{#* zUm$#>l6U+ha^@Trz~4IbE7YDCViBe(y%ZB!%)Qx4hYS|)Zn`UTTo8ABSHme-v*a64 zeI!x|f|Cs*(SeG~S>&5~%^Xa50Ed8(MYj|*HA;nG4mm^Dx1#~ddl((X&ED$@dAoFT z9;1Ag=a+jCn-J0A_RtR*7n1X=Y5!rV9?2MqYSs!Z>_70~BZprtaY8K=HrtEi*WHwu z?!vY#x5stamaS6>sz935 zq0Fe3h=$54UYez7NirT?u!F_^w<tDNY}N^P?Qrg!g!cnQUv!Sz_JpD$ zSB;vxv*}$55|V6N3wK$XgZ5eVYbXkCWMzDE_R4opcM{dgJC6p_qt^CZA(4tsCeb^r zR3lMZ7$tBOfb9v^I9cRLA2lPfnO&nX;zHrM8!o%-iu1wH-o5*OcTGae`+`OwrNyVU zVi*r`D-!*6V^1<=Wz$ntFrtlB-M6RFSn6ogsT6kFRKxF!AMnFJ6UjTNc(5E99v(|4 z?2@vIBLT8g;Wo@O78RV#0p$E2Bi&9iHb}XZZk5tnNpyC4S~_&VcO*UHsTC*|0On;L zQv^&>cSQq8xu^mt1-c9g5*zkuo+=={sI+ly#F%(0uv=nLzT|F5B8)t+A2jRMTy%j_ zI-SzSTNZS^7JEy{Dv#L2{G*EzBZGwFUm$P;5p+m=qWhzU8v@j!+5Xs)<;x`1r+oVG z4Q8qye=2U*^I<22e*nUqFokx_KsjlltObki?)5_b2L}`Op``8xA0rrA#;Eeg>~p@6 zNZdE4fxN@{QVu|X6ARwrqtt@Wt{Qp-k^^enl4tl|Xrup1R`?RN3f_os@&RhOe1s}4 zvMMGSU+E6=oLQVyDQq3A92w2t2o^B!;0>I_2Qj-d3lB_6a zg4Y0HC&$gw9elw%UU?^8_jHPnbdqa=HcqSYF$oGFbI&%IKzp6*Of#7EUuk!b+aON8LhP2ex zj!xe%1yY-EpPC~-9s#`-Ec;YUfUd{>2H4l0ubIPo|DVUfGloo(`l6(J0bD6&LS@q& zHT^kXB>+c8)+D{j95(8q?C3HS+8r~a`hxaDJqxl)|XN6RK^sE^iH%Cx~k?G{e??*>?bm)09H$iF%r<1L8uI7DP#A?*aNFGtBi2I~SpOtPK5n`$6<`5x&h2a}os z1;$HAUo~ZEf6FvZHpXqrtCfn8>SS2O z&4>lU2{e*Ku6;s%Yx~F3Rs4$4awH4V0e%w;R0JXFS|X{Bq~_fw_KR6F(WzW@c_kZ9 z!WvR z;Y(2W%SmT#BNhO=;shhbUBgsvNI8i-4+W+Ma8e~X%IY5*o*d5>)6h)dTrwKT`tlw# z9rrceYPkVohobT2+-{#g8*T(5Ry+n?O&=W#g_`AZf&B95m^~S*LW}M57o8Qt9X>Z& z%;m-t&Io#yZH!dH(G=F4Q;v^LX==JOjAa*7?%({eX1**&dm4sl_(33Wyi{3I`e=62 zB(6#&IBTbkKIJ6?+C zOgHDxJZ+Pmg>ENH4z!W51PIcYPYNnCj8ORi+oI@0V!g5>7P9Pb_)pwpKRI7%!DrgY zyKX+C9t-YCv~#oV%dToC!z9n9ja_XOn5!kCV}f51L<6{hfO5fcV4dL7qna2XY9bVZ zsP#cA$C+g>4+kF)BxWq6iu)s1t97dvaJL0B?${``|q8qRVF z$1)bZ`KOn!S|9f&F5#U^-fdb3ehM*2#hRPeF*Wb$`v_)s~TY89AKh-4o}C2^5V`dBe$+S=b` z$5S3I-wr0+k?5KQsMnaH>ba$?1SmQ!O5AcPHd>g-K%A}xlamGev$0|LT*pgRHfep& zo{Ep~C3H!4YI6T{23?0`6{B?2IV3a_oU9_KzeE@_g0#(utCi#N^4zEk{EEHROtxAL z1Aa+FBV@n+}?chRS_I~kb+jfYjUjMiGOF_Fw#8R;rive+#( zBsDsXN7sW<>zhG;&7-plQRI#y%e14@83V}PGSbz1lb#Vz7-HJX)|@rVI73(y<_Rt^ zR%EHOH?oIDG8EpqJW}X6pZD$r2>8HX_#OrLSDmL3T<({5%s zmaN&4z~L(aCt6wz!Xq$WnO&AM)vabzzDQ9kUf#`x>Pl+ZuXN0UD&1#qPDDGo!iIYe z<}iZvS));K7drWnV^%Ksvz?Xb{Mk|^RGDj0Rz92QC@A3MFNBMr)J&H}gRq!C3DU(M zEhS-2so@jD;sp7E;0gH&0V{LPK83_Fa|)YmfMuA&$MtTicgie$V(1TszDU2Z?g=nQ zx((A?<`-E~q62vqn(0Sb`6S0lY$$%pDOc!T+R}xpH!VBpP&H5+1Wk({rY*0YMmsC> z7w6+_9ldr+BQ25~Mc;IftR}I1>QbSWK!0AFN$1V9WK7}ul8VKiO=O8ehnSY)x#UaY z6v(R-?+4z|uGWMam`9G=d7iZZI~tZ7rGNWBiMI-N$SqOloz8M>z(l59noGLt86y*q zh9F+6>4`{sgpb+730e>b{KBf zky!v%5pZ#)qp=wJ*nLEq8Hkd>&?;44U#qHXZ#fK9FQCE;aY!w~=@8{U!1RaX3z${F ztCe>An!c3wRb2aa>`@sMlUA5z(q$@fv!6&ay@@;+Wo z^(gv;{1aW`gN;44+MYAI=gYDLAELeZKZdSl{l6Pz6Wkh}lFO4tgb7c&h#&7s zi_GR;_w`)%ylC2F&A58^^=%NU8Zht4<7F>buggTo~2GW`=@)7 z^@$iub@_glo*YOj9j(h| z#0)1?ahdu8R)NaXd}w=R9&w(Tk7rblts&cySDd`Vn&{bL~m((-1$ z6fJNiO77*7g#Pdnkj()oD_L$#X}DNOz7u@(_PrGp2W`AupVCoLP#pcf>)zs|9k)U- zIVFr%GHim72&31a7=^N%2eeq})E)vNe$py{$2A*;qjTxfDYE;={`?_^MK{;!*HZztH#ZdImE%d@SP@xJWr9?73$O4)i zhIkDCgjJ^7lE5PP$VS}wyz+kle;9n^m7@l)>?VT)%%nh32S>d8OWyOp&O}zn)?t6w zKs2aXrGw^~G2jPT$AzMIlmfXhtN2b!Yx*I>xZFUmRv;7El_WN*b9BMVDZQpmuTGO3 z1Yo>FJs@TjH_?=H1ll}TVR1kl(7T84Y+Dt$p2Jz)QuP8Jz$$((+%kNo;F z70xajx&m&Ea3ZCdOuWc@O9b~0bV9a!urJwv2QYEzFNiLN zU$vLeQ#ap%#Mc6+7u zTs8@*)hTwIuk}BFYIXJ0%Cq;MI(7d^_2mPSgGKjQYPed3_cJ*@->ao+QzOIi*ZtNn z{^FGryXey?N-Vp+6k@{Lt65VeNH8FX7C3po$;?l_FJ?7no^x zc5&0PZMIWR*94B~DS|BROfsrEV_Nitzo3TZEq-Vw9bRUR(rS|$yJ5`%nW;CyI&p$d zdwQl-^eluH9-BI~NMNQA|2HIvC89wTRR9^(N(;dndItKf(BsIBa*KnFc=xyu6iS@% z$aC*nLM*}o@CkUJjixru=TefT#bqnj3!lYc?WQ}d3N?_DU3nhSk2wdZ7AzRkm6=4y zhHs^Y>MUe6f_!HMlhf|h!Tpx;sA+!P|8>K7%)Z}PrFaG8g5Y$ef`#Wl2%(^&&E}|w zPMs6%Y3RWH*R!bOSwQI|SH=LI#j63Jk&5cD)KN^m|1DWma1qH~M8>HCPiBu06t_?# zh)m+9WrYB@1s5Lbtb&|b_C<@uZjcW~blqeXKzqbh!3)V!{Ew5x2CxV(26jEEM0_t- z;27|~9BmpBtmkkRwZT6Q=GNqdvWc4)Ze)4KnUjOPI1>bjaxK|7K#`sG(I~#1m#_Oy zY2hGw)}*XkF|ywPi;&L+9h6j;hAPq@HNsLaNTcpK*@A$@CF6t=fJkKFmZ#aseSsYx zea{$^oGeMh(ycl9o;zf_77hd*7DmciNV*+omRqKf8a1UjDyNM{utlgaMmpFVB>6*V z63II8k!uL0y*3Rv#+NqDFla%Yp)Nw24#FkIP~dU^AxK~`QnC>9h1`f_+5n6&kf8}?e`FWB?W|apq^~8lJVHyg5E^8-qjchzSH{oPf7AWguJD6Q@3ZzD( zcHG5B3bnPv21pXAI%F@bWbH4;is*uJSwMx|%-lU$2iu{wWqekggYQS#*u!*12N4cxd%wGewnO*xH`_ z)khchEce?Z2Rnhx`T^a&>X05gcC{~j4cFg17Sj)1_G&=Xt?I&}&lTY5d)rz)`E`T5*`D5e!dI&srl7B{YV*8#4`#-YtgfNu9 zG%?{sOEs}tO0C6i&QbAfAsZ^JbSm^*1;g48<@Vx4vj4MWQtnaKc0@21A}9KA0^sUoM$X zVn+z|qzqUA@5(pKiGjKWk_YA|lvM|BNUdWIRIZK&F3#2xBgy0mC%AHa#0e!A77vy- zMzUAqvn1IoFhJVAR zc*0(ej5xTLMv_3ku%SkC_>&c@(r|o^7-8jSg?foXobsULS87p_%(=2;l zm)yHqYi!hNn;RRo=8;Bi1BqW)D$R$wZoyT)C$!(>fB#S4$3I2hYc3hR(n%zw)Py$< zXVppip@!FSsOl*mUPK2eBMm4`O9x=6ftKMt-d@+#p)ZC9OWvYEmg?H|+GP)QwziJ{ zbZd53NTtFxf}qxDdEuFbz57ZhTERHASt2+2wLlKelE0uyNBmjqK&aW-`pMR{YOC|h zm*YAl;t`y>uDr0Y_k;V2c}NZHS~x}2G(*)wE%28dIpP=FR(vB@(l+-ZtKUur*E9Io zsHlMUp?g70UBv2OXrPZXv*b~f)iS5OafKY^hka&2tq`8D$dhw>@|?XE6qhgo@qH4T zc(51J6V(LSirdALnQeDE<*UxJE1tQ*i$~z+u}N983_}s(AO#maix*#BiMs(S#(?zh z3^Bb`l5`>EpJ1-Wp?0S#nw`t$YEkuck}7U2^Psv(Gm)IU5VewR(078UO;+**Kjyno zzQ>boGLI0GVB(WoXUXe|H=F*+kkdv?PRwObvEKLpy8qXJOI(ohr~H%oP@|Eh(oMJ3 z{VuDbQYCQtfccK{)*sJML!qE;yQVqOkrH1{s15A}ngD5!ETk$N0DqJRKoz4-K26CtH|Wn_2ifH?Pe-uR zFM>+!+(pL2qu3wd)eLJ^SHW~{pNg!bY0KKl6M-}?GH9$Hh6zVPfiBe~yM#2|4O9Vx~?~HL%ykT4Qz+>?lRM56I51EQG=6#X| zdSqa8uLX~VcJKZZZhjjGNZf_=iyR+)*qe|P@#4T}fO*i&l9@ekd_IBBM zv``LOYg)BXUfK=QBxsmMCLBxKv8C%@`{@2X*Hj1fbSjMfXVE-OtWXF3ZL-2$>WCMfXTFGzd=NYTSMhyN>74k#$T_PcqOmT~1Wa&Z zN%F3YX!HULurA{FKwWSx)~vernP_HgES`NX74yxVR8@^K2%GzLbz{DqHmvFmdo}H& zpG`rCVpnx&P6CDLY7&l%Vr4F)JsV5M^1pXtTC>Z;>P;8n z4$-N08nN`OojP&dPqCUfS zkG6&UhESDPlxkT=P@*R(aw|F6-pXLsk@3iVei$FxF-)-Zc<5t)o*Z*`4eQY5=CYao z|E|UUj(p~XlX&-YMkGJmo*a!v^oAQ54QsztENP?JiG}@zgwVN z#Wxiq@|^r0;5pw;#`7rn=OI`wh23(XED!^da6lPQBYj1ZFO$K`^XU!Z1oR!*p`G>n zj(_N`l?%;E<;?tO;rxdUm0c zX|~?+rAJ#$x3h5TCqAj2J^T2%g-m1P_RU6S!RrHFHo3RA3@w4{dy;#jmBks1KZ4dC zj3#M#2~A4l4>mDx#k8Tp=?;Eqe4mUL$G zfP?2E?B-gFu);Xu>U4P)vvwx8FC1*N%#@wZO&^G0hKCDN#ST8|(cw_5S*Txq4t3Nl z>)O`7B3UK2VZo1J`0kikmP&Z63Z{Q$_Z^Vk#QoSS`gRpB>=<+&MqUu3sbB_c1_~2X z%L0_}Q?&$r0gtJ-mUijeceCz2P0!L3GH<|Ir_!l39n0P;d@ zr^md|Ri`}bQlOy6-wrt27z43XU!zbdk2fM${#H1WN;lSt z9r@IRc6F%eHy5hZw@s7CauBw(8+53AAX?MO8p&3nL4rGk`YhI{=+zd#1DoR%*xNgX zE`S+)Xy`FCDlfx~=>=#!ughF)p~7@w&}IJ2l7R!xr%REOl(6{X1Ehc|vry)g&>m0f zxaH^~W;71K8cHxTkqO3R<5{K&H?TcD-Ez>|yCxNqLIZ;C(aj?BT-`znTigjMxF#ha_vlG!lk8 z;xiI}v*?O&4B%NH4kebIO^5R%kXyxLJ{?zM6=fC@F^LcZouRrSJc$rvW{v&hzG9tp zfS_eg7)75Rb1gr~L7HBfpqfU6?9Y$}a3+=3e_H0N`h6P**;Om}m&^N8mE(pPKd`#%q=g0bqBYA5TTz6qO}G2i zCn~_vvfq{0T>ql>bTpfZ_fJGK87+7F(WAE?{nYmI^7hId`3cOqY&474Dg^06zSL@| zcbM~%H_FsEjYYq?%|X#^go7hRYLN)%bKY6K*W27^|Ho06O59ZYDsbMTx6iL^udHlW zDp@yEqbPc%wc4W1r0oW|aXIl^3$*kgWAydhjBg%d+$empL;0k^{wyYT=yGGTCglk%3KH&BgPQ zt+3#S9!42$bAc>Tm5a_%$k%OTv(#?OX4*--bPJ(|t>)%H(1hlNPNAL2I1Oaz@@nDs z`&OgQ^>>vrnNs#XdCjQD=U@?;^zWyVJn5{nnw!zA;R3ZV!eOnHF*B~}QVlN}R{H|L zS$f7^GgOYuV@JCa*^y*6F)}=n@uy;YBS2U7J^-ZX^}lp^@s6cEt8W@E4PW|CqtT9+ zGyZ-Vn{B9yttW~R>yhQn8HR~WCT(+hp)s+bmR674`Qf`Se)Nuwe;z*ESlBy$Rq~^W z-#mShpwx};OL~1G>)(4A)irN4|0}YAb&p7?hti;#Wr317538V{bGlXwPZk$qxvCS6 z=h`f}M;8{3E`WtJx3;z}Ui|2mX?9F=`MzyN+OpyAY%Zx2E0fP}FK;XLo`tLT?!9`% z=ezc&uiDZ+eD|BLHNgn`mS4SnpLTHhxdT44bF_EOWj6)C)7t&&@7QNAqnzEqhjPjG zP2fiv$5ML90G19!as1Cww0*qh({vDD`6S6y}c=8?Tip1=H`X}7=O zou9nGA+k!T&KI-lS~^zO->W@#d;d1=(I>L^_D|mXgi?R=!h3F4XJ7Z;{>j|`s%1Xc zzx93EZ^`qB-g^k!r;y*3Po-wHk6e7y?_=khx@BwSEUUp-Ssyucb8j(E z_#?FM`0;(+T~?y#oSh=cR%iyPcwq&6*X|!K7LJ=|!r|Ad2U^VZf}tJRzWCAKe^aBz zT4N8VCnrlSOW9lPvHJY+y3b!icUV2WHs;QTr)E}3;UJ_!E~tX?)Aw8JnNsn!M{N6u zw1LQlL7xU0(W7Km4^_PfOL-D+HYI7(W$!~hC0`hWNHx4KXC8US>8%SFww6wuSZc4V zw6nEZ|5IKMzy2M6{z&DnXWw*PRXcIdiOOZKS^a~z)MjeWdHg|xIkZgwJu-BL4;U4+ zu#1K@kg*mkxn)`sVUVP4F`zDqUs`|AE$HNfkU1+9jz?T-%!)}wkDTeH-RTlh5YZ5{ z5?VArnRsp0$+*!D^(=8|Q?oN4H{j!-sJuf?di2%{c?x|t+6&P&H}BR^6)5Cs;2=}+ zd}xW>_EJT5E0uC);Z#1fNx<%H=uP-As?~Wdl}{ChmvYrz)6v9%*+^PTMGsQzChx8; zhT>6YI3G+odv1@ospwj%7zpRa?OM7}wDTFCJu_FRI;k;MqN9)8bTK^Yt=EEidK&wD zl~%G4)M=}pvSMa8h0KLod@$WmhS6ySe}Sk5lz~3$$!R`<+CWUp>W3SsSLdU)tsXxA zjz?~NNy(w46v}&)O?r9SrTh1IemNEr*>9}e( zKdwEue4_vUX7gF4ZteeNaPd9LUYuVH{<_}oJQI3Co0-vMEX(gZIsbk=A8oX=!_Dsek(a>*FgP{Ycy?P@FeZa3%in)}PZO6xb(Al)=cRA!?DdK^d*R3O1fNcZzTrJYJk)>k1I&9lK>OhkND!Z3Lw-4_GxN7Ke6(20&Rb?B+qMc#Tj;Oi7}An;=~670=m!_}mdS z*W3_W3dA&b=&wM%MaL0`x*aqFAc}7Qs<_R3#Uow6-kn&n?*~>PW?t7$hR%}U$YD;r z@V+~h`56C4_srMki$b|2cBdXCablaB9sY23nR$ zI0G1h1Qb~#_zI#9L7wBnK_m8hBV(Ds9#cOsLWH zXOnibX(zLOPMrJxORe-$iy?=IL%pnxL~gf{Lc;cWl68>X^ml zt{AW{ZzaN)FSU&K{^yMCm+$|I)*B4QPfHt|e@TiXL5`W`+TA$B9MykDn#$Yb)BpC} z&JeE1)|bEc_I+hz4w@+$Iw`}A7Z^v(wdD}BBQnT#M%YOdJN_?1gUtV>!5^B_v(>;N zX#azZm?83{P|9Ea<0<$wOd7qT-m%1x8z=aE}VASR%0nw>dZ0Y?Ay?N;>Vi&iZ-_$R%X$fR2gJ7IOJQXJM|r(27<{WNFVY zEgU(rr2P*!Rtiyy)(AlP9iSlk-pPqh)d~17(_*_;_jK1%(NQbtkQ}8_q$5TS%uMYc zPnu@26r0tq+P8ScK)3jN?3nLklZ|1^V8;O1?ht4vZDU$O?Zm4Dzb%13-wfXcaFw9_ zNUR%e&@_?|I{Ppmdd)vZ^UHQn-?udO zbFJw78?VA2La>En-neNkaLnUYzYm;W%fQwbpTDpPtuNpe8H9){dXZF**-^w{&=Iqg{ZHUHb^VxPEw|I|$HO}nT6o%ZSdxntX(a&8k} zkm9$8UiBNqm(Y_F0M!R<3`sO(WUk;IdmdklGzO^09kgUJ<>f$mg91OJZXx#M@@o@kV6Sj}4ogm<;ufc(Kimni{a!=szIK2vDa7F6daba#B!iC5I)rIAoP z``C%-{}Qk6@mcL^^!@SSVJn}pO3?``6&VhV87ZQVjj`0xK-@Kr(%7VKbZQ@Xp}z3n zwf(tKJwHm6%zLJRO_uSZF#t)$y2115#WXwzOC4Ga)>SE)E^ZexeK35=T0?6gm7~i! z%o!@Mn9=o2!_G&$@&2Dav)F1Fb|zV|v#!WFhwO$z`_I&4FFaGtP$S%L$C%3jw;V6r zS#g_zGW(W`VK*5{>XDH|FB=(g#{9xmIB+O#sV{-UiD5BL3JQdn5&ppfu^?C85ER0# z?kSBp?R(-D5qrA2^Bp^RaNUkJ@!`AMXZznc*S@>+qvP%6Pc9REY2N$Edz_}PnR7F%s0%(x?8 z%jat}rB~Bid@PR*m4<$Q==q^<4toP3NayZ?Il|&Vnc8Pv?P!R z0K0@cKz?una>p?DNI`8v<>FxUWQjDrhnmGFzy^5LTtbBOh;*3e8W0(>W1lj_Tb@Lj z0WiW=>W;Rk9@w4%P1{ONcFr`BuaadAyAwW2iJ>dC^#B{_ni#=!SLZ_5qHnF(fb zdtHf;l(ec^I=eU-4^qT_WNPoVoy%@rY!Z3F+Z;;mp5LCcLpHAJc+9(D`1qOx0b&5^-j;p^aoM-*`GXsv9ZF(OV4@ zJ27JCtO9rpr8!Y6OG+x?1S&iMz}y`TxFKqB`{LR#*m{n~8$m>0oh@eP$tm?khqchG z^3`qs2(_>^Be@u}h?1Ndnb8YINu$ESW2N@uVuvh0r`ecmwMuSjer08zjIHE+XPJCZ z!M_UMBwYGJH;2z1zA}lpu)WC$4gol%4zPW!v)IkYR~wTh@z7J(yP1{vX+G{&a5F>M zS6L$AH%U4%No8_M$@>tXi+6hPCMq<++2#M8@yfjg%09!SRBJkh>p=Mj;G~<3<_q6$ z=0av(QaimhXqEBzkl4Bj$}m>RU5HufR25R_IubGVKUsSp__pf%-rK(;Svop8l8^pa zmStI%Wm$F{#jzb*avWnE6O2hraE)=&G)>bqgf!%a5YjZTz$j#erJ-e9$k;|HYq<<4 z?RaR{b&S!%D7T}mx9g>>x3}w3Zr4%T%R{-@*0s&yd4GRLN*r3c=k>fEaHOMij*iax z{l35NpU?MSH8}E<8=s_P&GeX>ENpRqaL3pGRUMmjU(QY$d+wU}cE;@o?s1>Z2R5fa zI{o#e`mEo5R@sHXj9edmw&8cU{swS@IR4uLt8o;|Wu{?{EYR%@yZO~d9A7P+1HsOo zVr|vc;n_2*uv4GH8Q374Ta^uh$h|dMhsx{Us(*g#@tah7-5ulODm(4I_F?rMoLy0? zoJ}UP$)i%OG2(@H|@Uq;hT&bkE-}O_lFY`cdT0{C)*iOAFYkq6gb3?{^F!m zddyDguN&))L%a7}|H>D+tQFmpk`pF%9Y|##mIL24zVpiAy?YK8xRgFePD|#J$y}U! zNMy`nnWr2FHzA1=xO=h_?yINbww;cjil=Rx?8*3T`r~c5s-7QTb2;Oak2be1>un^b z2M;Q-im}GXrgvTUfVyn{x_51|1BrMh*~E8Z{@!J+&4fpcmM&l8HbiVE25=sZJVSth z(w~HuWK6z?F7XC@eWg_O#3h1qmfMxa{C<-iE+m`tohw&PNoMurz=lGfngXNk?CadH zvNO-Ysg?bmopR6$H#wvpxm>us za#HOHj~BT-KT;eI@9E61)aUe1vBfEKdAXD=U*^)O6xVat@R{LGg|&Xs4$t@;oC07! zCS=;lQ!;DfauA}fP3NjX?f8P8wf}(u^u~f6j8u1zC)LT6l>rl!QDmdHZgRP@+Jj~~R#J)#wf2}W{Gm1mRW)GVzTGQNZWz5|~G~hPh(ASZp zC{E<}B6OWGL(u~fJLbL`;#@ld^@c*xNGQ~iTRt@OW+WbuG`u+!3WYMED?_0x&1i&p zK+j+3=~C@f0zZrGpabZIimPAGwz&R;&LypegdGVWST#c7@n#*;4@fg2)yw2xGco?^ zUSc+$7^}=Wq%%9}kdrF8kEyxYlPC8-=^mTi|AhPVqW(|a{{5!ZhSAXt%p!42IO;ZR zaQ}1z|6TL_4W*L$c&Wr2f7g^s8XMiiyzGLDmqn-Io@B@?Bozo_0WM_V^@;*H3Cfs{ zbPL!N>>_=s8sp>`8Vg+H{^`E*y8BV`9Q&bSIxRgCQklXd>`=~7;pj(uw-kCmisLL} z%-GK881rDehin{;CXx8^$$V;|IApkw{nC9crRLIUeQ!SQ?FH-$sSc;(aDa7c{EkRP zXonk;Tym5jw&+x#Ii%(n#No)o(x(SmSEA9-+|*k-9@FIs)Q6;J%4Z^Be5h0^v#g9| zDf>bAn$5mg>z%y9(?4Sb1~yi!Jw0;e8M1fpwyEMmC9~i8Cu}u(2nBj4svA{rPj%u@b0kW~kK|X>yGLtR@M76T&+X-z zAHuE@PO??-3ZWCv%O|lZ(2!?FR!4X$7QiZaAIHV1DhEa9tyB>W0D_E=K=XXi9z)oO zun?d3!Lus;a2LI|FxJ;M#zKzA^+rCIjQ?^E5x?dBDTD2?1rFL#0*U&p*YKeE~~_}FDT{38oz>>lLKRR6y(+5PYFXyjt5DO^QX za*k_-C>0w`x?9*}9%MVo$jQ5>*GSCR?Reku0ip!+v~UldN9IN8Xu-(SQUj!xt%6n1 zFX@BYFwlCnh*1%)LbiGbHcbi~l`Cn7>USPkH$8V?3!%cvRGk0t+n71pRG20O0-Vxp zG1DuXa810&S>jD8Y-R(p5R^|4hTo*{-#mFyTMx_`xA*oQo8NJ72bn)XHJ0wCr=lNj zP1%^j%Fbe0ylrL>`ihZ{TP_y*myJ0NwMe2wy##`E-jGh96m7|dhN7c1h*^aWJq8kZM zPlrPm8CA^$(oXK!F1Y zV--tJl7@tgRYD6y2}4135)D((Ve#Zc8$BtIB#bxi`;A0TZ{pQpBAInpW_vLV24KeA zUWl$qBDPg3Z|o=*-PtIaOv&DCJgTU?4JbxDzr2~R<&iFq7#*Vjc)c%{H>}0uLzYZJ zOA-;zqQ`MFEILo@k03JO)m?SLZf24jd`*b}6ug8YNT&!xikT{`t(;?;qb*U-~l%PL(U|M%0W|!<})G}-7p6*}S z7|F3etIJuzSg$CVcXY+!|wVe zAB+p+S_eA^R7+ak&TN09vo$?X;FsjUwM##!XTk@=Xa3y3vbl2o4|)+SgmUpPwa93hPn0J%v9BT0NXW?*&J0WUhS=H!s{fUf< z(&Fov2|{tAk<&j72Io&kl8MM2!QiJQcj~{YgF*Mjp{}mh)}iTeG*XiDOOgGVq`J%d zPQu-rh(^>`1Mc47kI4%C7>JF#EBC13`-WOGJ*3jD(?h#U(MX1?Mz8=HWd7g$Ha5V| z;2`gy8q$G=o5=gQPvT4yG48BImVr#ZJRXdirBOF=&}4-kI0C6JhcM(^6far7l~r8@ zd=f${-agIX#n=-Hs-4(_UZl4*dGRe`DD-jfJDApRf6q#kOZvQn@L8=^6Qeppig#f{ zAg<8fEwkL3DXMg__0Ei9s}++V1(fLfJ%8i-#S98lvR#{2C+xp$Ee`XQ8=6wBnGD8O zYyEh*?d&FPPQsUR1#Nb4wM?tFt>hwHSszGI9yx3c4MkcBFh2bZ4fsF|!;P6CV*=Yb z^LyzYcYzHnoKHp6qXFNY*sS`tuzcK!;o{xAr<}Vv<=?~*Y2pXMi!dh=ytpggn&DL( z3BP2A5#3EqVcY$zD92bQ;eGq}*KD}=LXTGyC9o37I_qg(o!+7pZaM9+l7NO? zU5m3xU|AE97eg0-X0*LjSLv(LHU!redZ8vg&_^H`Ayn?UFZZ=v(rs>jp}9SmJe@kv zciLweFZg_}&;K<`-B17?h&gGcKJ-F+U-RkaTsvnrpH8*=Im7pY6gG5y7NB*+PRAUr z3wYz3YUr)=M1Eb!xGp0~BMDjU3@~eff#aUKO4;iR@q!WfWws>jp3$4~#_5-ZB$bF| zcrs-_jP)*p#W`tmYU@Bg%UJZgFV6z1h(Y|QA>q6P{&3a zE?VOk0Kh{%uv8vhKR^~gxFV9sfAf|tQgQHuH7?TrQBz@CaI943rHh<{Q{I<2u+AIu%PZ)zz(#`qb7eMcFhHM_kv^vh`WltSa}er z9b8xlrXBMZ(+-Dj3E8CLheMZL7NVCZA!(so5Vqc&aZk!c$L-@5J^QYQ%m>Z)P_bZl z-U7n}V3fqV(>jj&vNbFc$RXz_gn7wEou>xfP*H<9*e4>xG@^wfDZoxoN!6Tz`k?yY88ByN_^U(!g6HHrJwRtEnA4i!AUoU_ zHS7YjYjV_wHU0v#v)t=F9>;!T@hqIvF+8Jk$x#7xz=S+RM+F4(slz$ptrll=uxphD zaRex;!$x7ZTll7Cvb8blhJHQ`{hUX1^deLQeXk)lj&TwJMfnRYmwFf{(d}h)7(}sO z^)SIEeOi4+F=fpaaVDT}q%leTVtC6tkr|@% z6Tsfo*8~ z%zkasfre{wqtAp-%hB4o#zirTGlk8ELZOGuaO3GO3ptw)he8jV5cud$m4DxxY3dR< z=71ItY{>@}o7t=1<)c1AHc8z5GK=SaD`nnqx(}#H5jXdv^4`z-Ro0W+wmmrtY>ZXH zi@B8zeoQ|8Bq{qCW+1q2-UhGs4t=sdN5<@|T#8aPZW()O1W^;1hM4wej4wey#dN`6 zRS2qe{gif)=yb=qUhMRmjg_96*|}?a=A*lI&Zq&7x5VVEmY7;NYg2vj`HL=6GZ#Jo zQ8iP)hj)@s-UpfhS{o-H0Ww77Fz{k3a}ON?wCnApjI>a(;0B(5PF5`ejy-}sV-9LY z&e4^Up{a#u7am@j?M9hsk^fp9czt(al@Yp4dehP8n~N@+n7H`h!sQVrkBIsUFWh#T zB9-ede9!nQlzjN%?_%Qu12mGF5ezIle`4m~BQ`Ch$?-48`T-8&PQT+ATPp*rjK+|h zO)1kx)?BqCuP(Xd02qVqD9745dHydO zjgdT^PA!?IW@-gVj$V!D3yXt@y(dal>QhA)TT3dg=Sgeg%$j-#Nno4nMI{N0?x%;e zX*^V$vt!I(T4rq8(6gsbAR;!HVQ$x~UM-R$oUNI|bG^Opmt^8Dy5b6%L{C1GKU52#HZCC5D3DN`w(}g7l^9QJJDO`-sr) z^;zgTaL+vfF&A@3tf>9SYhXl*5y1Vs?@ zN-srP$_kBpvFZ}sq4iu&7?e0WP5-rHhyeIJ+`MOy3)B=#QXGdsIqJ(-O+8>1z%e*2u5GbsD#&`(BmrEX33{CHKkSQ56TMX>Cpr%VZHN~>CLBGrA< zoA%7&8Q8OD!vuCDoeTB*&`YUER zNwu(vKsgTrnk28-Pgg&qkSf}g$Rs3!@;_84Cb-PuDGj53o{gKDHeYAXGcuH0rp9sY zyq9(&GVpfo8!8ruXtgPAw6SCEZuo}!YitJT2n9>R+aoJc>~C*jqAdk!;%x~Okbr(rX78uq{ipio)^dvx3^ga%V4;TMvv z4$6X)wJ%DUkearssh8*NghLYf#y3ba*4DMAG5HE=Z5J|AAX*_}Q5Lz`&#V|$Dw`c> zrm6rc7mx*EaFesDP#EV15~ap&5^jy|fa-}ir;}^C3f-ki%fti-S_!@oi6jTwvub#S zuT)B9+ES&GaeK#((KQ4iMN+9&^`Jl}6mhWvy|-=Luy(R9YNuD;PC)``&Kv-0+UC&Rq@4sC*;dtOAQ zKn7o3h=oboZq`m_ZEK*Ql3Nkn(j?eEfv3tk0k6fW6ScOID=mDJ z+pfvH<=8D7vF>*0>Z5h6O{Sx6`Z6o}Pdr4h3c87EE)t}Q2?~W~M9dn`$9Is7Iz+=$ zXRA!QK4qj^khiKJm)+V1;uGXT*9`(n(&)9x{BA0NMUA50*y1-1lFvPvEFO*~HPm%ne|Qn8xeyLr>i^Mr*uFGV*keh@_q1K)~nyI>tP zTB1!U_nF?Dgy%5#;ybZe+s}~+DY+L73CTb4peN|jv)|7EQ&rD)qxiYTQpF$;a>n(B zjX);PJT0OhwgFJVEj51XZYmOL7zzP$ZkG6rl!IR$>~#3|f8V&sA9PDV)87gDt(K+~ zFsEArx*RU5?+j%cQ%x-&U@4yv6Z-_v<%tbiNAzs$cKj=KFMVx+VP$&wu7@=e8RMDV zT^g!^{=EDw&juCt1q;F*5XI-+bZuDKvc<>=gil}}qe%fc_utGSZ@4b!pz&gEIiC5k*)W-=YO~7Me90 z5Y&{A{>*`eVh`%y5@+4OG7Q z^v8&|x+Ze^>1b15Ry9TYnj}}FVL5B@zfcvZ%vzkq0{Kr3HzI(cSFCbjB|-pHc!lw< z8p46$&Aw*PA~eMi*C3Ne8akJ`f~eJ`7p?f$o*-=6qX>LY!@mVZZ^gm9 zHS9lvW!>#<{uV&^5jpZwGk)@9L|!fHE-Msmju5Y4H%CKzQbY>HBl4=O(0|4`&dyMr z6D$s4cd>_q76GyMUk@*@h+Dcs*~9Do?#BA|5iCZI9Va#^N`V&QN&ETdeX7)U(t!M} zd*u|)6P>7`;W*>Ej?6@KqGYh9VlW7@!q9|`sg&)W5Jl(#TrN@jHr%KVJ9CzM7d;L> zDK?fRJH<@Zn81g*-gJIx#d6EmDdS?*+vYyqR)XlyZ|ik$WNhBJm7LC7*J9z=ALDn$SNMK@_e%WS zSW5zbqJQgp#A-Zgrfk?i)8*)=l5pxOeYHO4G}jUf=Mj z`YHLI=$Ub?ws`Ccg5sfp{A4JCfnz{u;*YrxEF)#@V`c6))o#%mx$0@F%`u7!opj9mxXArD z%~R%n7zi}Aul4}?m*oNWs}|T02i+g-*ZMMdP3BT@$IRH}?9N`>%5FJK{c@#Yi@7e(`ej7KdeThHJK2yHt-h;_N8 zZ5wZGM5!j1cxRHI&B8eY;gB@m_@m7VljzR|9id%UOo;nv zS;{fHJ3RoD!AQ{6SHpI{WW;2vJ;F*fpU+Vc*VE%l0;stNnAw9y`*&ON{VZDh^) zmbG#Tb{m09^~0ymKzS0;bPlLa;VV&;w2~;qBlNX2fN2T1{?shBlmq^4Vm33DOCpw* zpzA~XJAw(gQ7ITd%J_yPpW4t3Aewe6A)BSgx5ELK^nMaQOum5$-lMTD@!R$eI7$6H_Tf-qn zT@*a6G-7#(_Tq7#1e^%mN$ZhX7w}@D`1zuS$>0s5aA2tm5GA^OqZssOAWe`=Ejl?t z!n;K+Avs1{`Jz{+)Qt9_#F8qRXlqL(l1E`~J!Lf?g6*5;1s9m^ec;;{To4r0*berT zFAJ&nl*r!HI-#y=bC-d189ofX|H z)yi(1w~i&ph5`RPx4wL`a~c>sZL^6sr4_C-Z(8iaSs4M)Vg9Gfn6MqKWa)8{ zz#X9|&1eJz_AGpfXAP>#Bje+T7l{)#qZ!%>+F6sHg6oNdcp@+kGc=#FCQ-V}vLeeR z+D{sp)C84g%H=2WDe;7-EaR^6^B%cA&}C-Bp@f;W&4gKM+Yk;tkx5;C-kqroXm9YZ zCPT&w2yzAE(Zh&rKC-!7euo6BOAHC?{6xby)wAkNVs0Da5{ag#SR*;2KFY(vQF}@! zU=h#h=rW)q%|HN&)c@_6U-`KH^nH=#{Ki*IGGppCkHk8ho82#RE5^E)!R%QY3f|mZ z^Y3whQtqNf&@w_tgD0rzPC2;dZeqkarvEkaS+f0S)uE-4;na9Ru-eZ4Qqf7R*P-Dj zPMp~9zE}$n4-_R*+}P*-={4uXiGvh5-^b0%dy@*f?;}E7l~0`D?F6CX1dEqS-6g%2 zu@#;&-swvawKXIw4G|;@N{E8Rtkv||m@$yD@R0lZ43SVWm}=__Nzw(AFGz~a+0AIw zeNp{PA8}22GhY7NEa6qruP3tEghabUqko&s5;%Ptp~QZ@NAtRy;Vm1VwI#3#C-N2mQN=DZW++`ROeN$6?6Mp@6 zyquRW}|Mc9t3iWvWMi@hv^< zH4|UPmOjy%f;|t>lo+o>%^cqD^hX^FaUQoywu4x_S(~e9;5GNHSh`fnr&7%##pk8R zgf$OCpxV#AQsx`PIPVab>X>YoCclBKohKOS8~7y_btr2o`}J&TjDRa=5iWvkFc;

A}EXY#feG?Nr*;RqYRIkR)v5>7St$3v|SCG)uhF<=z{w(Tg^$e zPOmxlNwTlgU)2JA%6&rbQ`1xYKDz>(y$8iN9NNzfht0Kmd9D>7<1a$+$&j~W65v!g zr9Kma*8D(lWUSJ9wdL22z;}p8;brrYrRQKhzco6q^6iK8pz~T%Zg1vc1VO3o;Y_cm zAKZ$px)`Zk)O?|V3D#kNbyWv;srd~UPF$2Th&0(EhN>40IMjkOu-O>$0`N}%A66`h z9)#op7pV>VW@qX!&E4Y!gS_eg3Y)t^eacSaM( z8vU5sMh{i24^6oLqKuZy@TjfD1MaJwM-rEDV~SHJl!*Zkt6!*9&eBny~tlVt63E) zWhDAlqsb*{2xOzts^E$B+5K{8u<*N)|u9;T8*Jf8GV9^ zNoFQ)rqg@V1rk=JmP^z+Zl0JZ?=6?fZ=t_>W^cO4vk120;hJ51V7b-> zA-R28W7LqPJelxfgp67qOR0Zw(kN;FAc|Tz{Jj{9Hyrz3%D5{P`(9e2Ryl#VJ$*(# zY=4h#tuk=euqNL_=54!J6b?GNEJ1DZ33=&HwH4Y!K}tP5VmWav88KQQ{iJ>RM-c!< z?-QvHr+*X;wVXX9@Rc!;CBGvZ|7%I5kW7kD=o92ukjX)kMM%%xf8jos!@DGgkzZl> zWeti_tV1aHJ&`};h_2X+9wFf*4}f9e2Q{b#&k<%ErXaJMIvJn^Fhn zgB&kBh}HIh>=9YSF;A=nsElfJD#bYXs$o3SD($-coO5mA){i!5} zfA-GJkKJ(OySLr8eY>3So~@PHY#aR|Gg7o${76^w+k03GIW&-pjsO#>zH}b+w1`ns zo0r-&iAsb$rs*F&DjBQ_r?0Js5*sxYirIZZ?bQ?M-lf6D$lHEQCO=e+L^APMhRF0t zff)6o9clG;vBS9R?4-VAg(CFuvuJo>y(DuFyg6w{3S=lnNCK9xbCEx?Be8f!*^zh* zQ&_OL!#wY1s>fu&;kGp(5aXIA&ml?1JM$-+U!?-qg4E%1ABBvtAnPBfUM(L) z_{cHq5du-kU$f$Al37USGU8@M=x46RSL0D>aS@-xRdap5+4dsF?Un^^|9 zX`zQ3j)Xv$xNT}t-OW8(45Br73_|7-#e(On=v<{GdkyyD#cxikf`GE8M5Xv8nuK-A z+(CVBDv*;o8pu-?!8uU>R44=}VSTHICfCuCwH`D=kg-Fj+f$7`(?J~i5~Wk61eGD) zxzK2yeJDo6P+B|(d#=Lw9dq-+_iB709CPa9#0jrbeVg@Lh1xm-Mo$NU)ZBKBfb~F(cM`NxciZ=ZDqb8`N5>Q~>jNE9cyaT)CW6&ycLZ zKKFU|d#Fz2({A4`I<@#~eu^IXkJzj|qNgQfoIIDvTl_X_2uV2`Q!foKiDhY5JIBTr z77p4=TsK8q-HYQ!95}>Q>{^eGv}Ww!!p`BM`7^4Mv6xKlip* zHJ=^0E}t-NxN%i@ncTY(sZFK6$qxN{;YIgVeN(FD;(7a9qv2JJ_lg6jMrWQrA>&9S z;D2yG9tT9VkfJg-4dL_ASeP$@bpPrz1vfZ#VgA5O6<_z zsb{eHva*&KRL?G5u00B(N_Z+=X#_{EhyC39tU$(K$Alp&9Wn&(cus6f^DFnU=?GI7 ze?S(R#5-Q3Jq?m{$Nh4Lf;f2b51q&(oz5w1fkxMzbUySH zEx3;k31+Z$HhS%A=r;P9^epHr(Xr=75uKsPjqQEZqi9!`wf9nTfj)F0%l!;}*uP+A z%#BFyh`IXy5H-xt|D1RJ=MeEIsP-IZ>bH=w-5mkIAQT8k^4Hp%oBP_`uX#t+2vp== z_qZ9_NDW?d^~XhG)1E+1MudMVjdly_%9Zr<^D+)Uy$fzSLUqQy4Z`K6=>z}Q5;TTK zWcdqS(2GNc#6x~j-(;LTD5g*qbDgh@bl0rr(qeIJqSTXuG|I4a2TDaU^2kqn%$R!!+9m(oF^k+r4_JGj73g8J7>>{&fN@d{-*5Pg`U`xBq#$d&v~I$AR=~?F z3w)mUX}8|7W2TW1cb>Q-x#_TZ{3AFD4Ju#0SN$`XPztH4rI%iE9&J%A9sSM=ct*(T ztj}uz)c;SLEMm*N{dRhEI%>+g#!Q;mgp4vkAl@ngoB{_A0-~!gTJA@;n&wt@z|#7; zC%q|-xWnYq&^_u{D8;&)Q5<9dsE^CL>)60wF+;JqQ`rx#3MQx=FxKl2r81K zVLz&0E7rd*B7pc@;Y-8%^l5z+IKx?AzzVFIOPGA0r`Y{k$A3DJYyLEDLsj7!SBq|w8;AQ4|&XT|(MvPG88>}dENQ~eu}5-s}v>p|~5!-G1BL!PLH9P0>bhCqZ0JOHh=Wr&8v#5k}6y1a}+3}imv@yA{S*dG%arfv&M-V}-5?qRaX2h_X2WZR9tnMbWGU2q?r_8Yr&=$Gvt z4u?M}A)B9+WOL3}w{;HmhreX|E_#$GvuNluGjx&n=;>DO^I~EJB~R)MzF1#Tb$5}- z5|5HRr~VnAzVL-w#)c?kl~u%&^O!sc3Cxqh%fH_u$ygdr9DA2w0rH^pyphYYo#?RzWm8a z(iV-zaA++XvPTUDL))yt#Y&RG6wz%@sh5nH;1F@35bs$aAXyA`$AplI47)e#N5!pl z_%L@zI~XmRnw>#j2+m@?!CU3Xp3NeB7N=q_Ea5jbmJ zq*y(LL;Swv7?&o4zFZJ|JPcA~B6&F#kIJHQO^->S7d&RIM;9NfS`|9$w zYH?)dBK@ol4R}#~FkB8+*CUehzWkizrfH$wf&excV7uS+R{}2sK>K*BEq{U(_ezU40 z-}Fw|1HaLBvzC=2dUZ^4sv2z3u5>B(0XJgs!AQN3^i|a!BV7$8#Xh2X@jej9BGue)orx zi<9%`DzaWAZvR55ANL2`7p;>ba?R*T()c7poWGhJYSGva!;+96$5LP*w5d=NEzB*kuGNtq zFBw#i(Qq|hb0H*y51IDKdT5xp@#Q=2`05>Z?ANiOX0hfjFplfsF}nZhU^JVJ{U3Y& zWBif0N!SK2;gI`X?Ig%sS`YB(^Qwm5YPgkoViB>HhKPOFD^c?{xmU6y&vI^T9l=1g zopXk6g_V!M#l4vo!j(x7{eUqS2_)Z_bvi7;)l7?&LKUT37j#FfpwNu0&s?8QRd2S~a_%In6>~o(J*==F@bF8d^-x`@sRt_*}qPlqX%B6_yk5 zuaBmUQr0wb#0vD5_RX^M(c36LTc+Ix1mqj4Pv1D))LTBmXZ#Xzp@2{Y)oM|#>#``eCvd$m-Wt=^8L9}U_9 zC)h#BDOTS$7L4og5KiD9{;h^TZum^Y7aN{wcn+#)PWHeL#5u!&O8?)HlCW{Yh_nr< zJu&2!GM=!)x{e|t&&`!pBSSsHB_VblORe9BIfe?$NVn9EL0X!x40}8^CFalhtcF!V zIYC->iI&R@@QdC#a`mKmJ?M~l<|mlERa8zQAS6Wv>x!-eDvWu!Wwq)$WH_1i>!_kC za6ZM43h|_LW-`?Gk|~n@U>JNR*NAYmm*EpeSw3WWJ5FK{O@B++xLGN`D(uAn0*OOb ziB`Ra!(O=(ef@~^qGU2$OFcpc3G;+$Oua)`M!S-ypjP`OSrtX3?~WO+AtArMz`^o8Y(vklM%j z$BNJaHTzj1qZZM(+pO)ytQsb84;abWHErJ=1|L8F4x; zdcWSZoARH@NPIpl48$jefAxEAO57w3LtNS4^9f|n9C3JUWZ@LPl^>p^70>( z;u^=z{bTJketR79_)jPtEXlGz0k^X8iwVtsQ`anM!Y?MZY$Z>JY0&c{D8NXuUgBf8 zXNeVzB$G07QuJa;i6He&>{Np9?HB9z?%ukq|4GRVd04`0udfMct7g;cA|0fD$@myh z%eXOwO&AvKyeJPZIt2!kkF~@Q)UDRefF2b!J=}{AB(y(d8jYu`m3ym|$#5a%?o1WJ zljHe}Xe=3ZWaDV1QkmPo!%C(KMm`<4c6iV3#Wdx~0lSP$I-cFj9~a`RS$8FoRETo@ znZ(JudR1d!gr&mxT0lNoqaOaLSF<$YKr2J?d*zK;)}F@ZMN5c_&GZThXkKyvHxW6h zrR=FpX~Hon*k)P9qVO6iMJ`4apHg}kDHYaHO}R&@Q#u89fcZWDtY&b}?)vD=^e%6k zE5(yu38qDqg{o7CW{!2|;ZwR*acrXL-8(^E2J7PVf=GzLGe)b+zWJ;AVLcY8~L za7lHA?L>h7j=Db!PpZEiEt!Otn$@{WBmtq+(>m7YlM)d(`vX)xS8uqll>|w~-pm)! z5Vslr9qZ{+>KFm{lTVE$o$cyS9}C+y$M$X9EXva6N~!ns$rAm3QG2r>fJ@e)=&n%x zf2g@aeOj^B1JPA_=xtQipYvdN`b6fOvPEJ2gc&)ju-c)kJ%#mOYe+s&r9k=E6Gs~M zssCy0(Dlz*ex4|0z`Zf`4f6XBsbD-4Kq>_8xC19FTs~s#$i&@Qe7*jI2T=#q=i@d` z1i9XR6ogmQw>92LsE+Ut2o?K8U-Bjf>wcXn0cjjRW&*^?fN8xNO8AK2o#$MGJRF#j z=<_TA4>nidmSho~582nk-A@dUre`llYZ>+J-lHqraQmLd(INm@ePx5o2sS8czcyVVV@eOmlj<9VvL%&E ze7;`(CsQO#g3>=NhL?>X$UDjQQguQ%>wq_^tFf$?mpeLCdn`V>jNS~zEO80T$y41$ z7dWgg-gf!?VYKLu_9ADD#^UYic%Kw6C7w)*ld9YC6zR{FalhZ1CMxrFD??X}Q93>3 zhpg9`@)^s&i#EN6dvkqjw^2KDh!aP9^XUvHrVX`+20MfYp^BO=X)^LD1LqZt{J$dy zPBTyEQA=Z+&K)Oam*;jwRW1b!JSrN?NDG~b#la#fH9KU`?WIyTMM$4eHe{n?^{R_6XIK@KV0N(GW80#-brHnraFs6Ho?P&cezXYP#oGZYPo zh0>v}CU}NF5=o_GP+w&h;@5G*q00Ch(5 zixT$uBlyHNk}o7WFS@G`hvzib8ZUBFYrJCBhzRN7IY)d#Cz^1Cg&0d|st1}P|1TJT z=m^$cEazU&r;em>q`!#c44q4rtwZ^;@kKgxVSDqGJpVxd6o(|`PX3rks7h_N4jeJI z;h<05(A??%9vewWhZ?z+a>t=C*t^h@`}yS>rH?MZpnv6MVgCUt^!To&1oUMp+phlj zTI&XlEqgMtOjRtwWO+o9zh_l@(GEZsSau##BM++ex0IX}TzO^&l|7I{glq`L&*J5N(W$g0qS?Dg z#CkQY9#`}#guuJ$ z5{+e9H+bYyvT~|>NnlqnihQpd#X1@ zU5kK|j_V+lXrXU7>F>)GjRRP>rrp~=78oe@Q|#PYnC#8x{Yi7UxUQRHYg@wecL+W#ddVPhMi+wToP!hVNzn7f9P}{K z^k$ZMkx#2+Kf4-b0(3i=>WJ)@<4eJ0kP~UtRW{{49xa=ryUc-snSeRGZx@Z2t?8iw zb;ukRKyZ3sz~tC8_Ze6UIsfePnU++lW#;nHGaDDL9&HXrH~rE3HU%Te(b1dVw+S4^ zNUk1T&;O&zP4}?PmY>Pgid5ed~-O_M7t5RCCdd4o;wzo{Y^d)&hnVHr8=G9978MW8J+7A6* zdl{to<J{;+}FPL6~e`T z)cD-wbB*c+(`r8>zCSR4r5S}nrXlC%S$S+2K_QPOt)}l&n?JsKuR5k z$8BZF0Oi$-+MZjN)&04-;CZqPJZ@4i%>Zv*nA{J&I!#ekdYb9HcS;jLdYXPH5 zzQ9*&F}@44@L*xwID;Zb5WisXVzhYhj&>lqX>m)s|iSFnd}yUb#9OO;%z<}PDJ zj0jdce%h6=*qAD5| z`}Z?%s$qk=T>Zj}cNZT8f*TqV*rg;lr(`WVwtLK0yOstP33lV*SShkFrR(Q=8m?}* zN$y!JJ#7R?_ef9s3+6KE(uWD5cynuwt>F3eEh;hUer?$ZnQg=_D8=c^Ns?>J= zrt$__m-NOJdeuGTH@_G7 zs(6&C8UFK0%bGmy^%fw8;?38g*OO$vo+q+aGUhxX!`-op(0;vXOsPbQo3AFkD2jIF zqwcMSfPLetOQ??TkSzT z`%q!U=f>YisTq?btTf3MW7w&i4i#8)kkC@fX? zRAiswIpe(w1zPmzf_2_l%4f`Ab*(=oHE7$~C}J#s#Sh+h z-v?JLTh?k(4>6nZ8R7Jba$jGevn^W)QBCyp2gk=Zt<2#V=>!|->yKx~E=;Fe+p^8g zK`I4yq&qefY$Cdr=f}trA1$5W#Mbd#5oc^29SiR9Ip1KRr`anL0-1D+>LpY!{^}r3 zBdv_NTge)`{!GDds&L1X+xiN!?h3tzyU!};)m*-8J#KBajGJjXGl2E_Wl%q)-(;pV zz?OS&>H#eC2U1U%0}@I-U>TzWn0#7y@_HUk>NrOsLhb=TMMt4)8%x6S&lbv+q2E?!+i+y2c|%OQZSBo@_FQGa$L(;aLmv?$`^ZEY+y8 zdouZ-6a)4l(>!DcaFJ8mFXvYWh){V>f>ccFxzgxR1_xImW$>)hgo9OZ0>gsC*-VKp z@&01QEt|N&%*XU=nJyNSCeJ$5u+J!gg>~pCaRFdN=y)pP8APmZe2H}`LxHsE)|5N1 z{+6&R|MI0s8M*5i^XA@viD&Gf>38427BIHCN3e!0e{uU+0PVx0oCcDTi9gSgm*qp< z{`YDodmZ8>r>~_EJRVn}aO{GZ`Y;V{Ml3`L0T8rQ04BLNE%wASjDDt}62faJzzI`? ztxJ_rm2Zp^yiYyk?GwWnC&OVnLlXKM3$0n!aTu$m@mM09aqMft0ETUm*d?*p+}ECe z{_CR_3G-&i*lQTq({(aX-aVX?##Gd-O*+n81+U`7glT8`Jpb4JzKm@y7A1rwvt`Rx z_lboCEIkS2mY6xRV~oSd`QK?c=J9)vG(44oqOCk=PYZ?S2b+a&if~`421f=NbLn7( zPTC{=we)%Nz}h)O*Ayr%$hQgYl5Y=cM&W(AtN!I$g>-?>Yib4c0@2Lr-pY%bDaM@v z!yqRH@^j`4npojvE%X^=i?dpcje&S{!0;Ehd2~u>D8;QH$pLzqZ^R!P2TO4Zz5Y^x z(>Z@mly%cyFpPn?Qv~`p&3)BEj+)*5tTsZv`qkx1Z3ji(}m^waq5wqa-f!i_QF z0D>yg)M!W2Q`FT|5>S>4Icg@CTU!c+N;(R@adb^|z#nPK4ehtrnaf%-j%p=PSlNC+ zDconOjjK~6wEMh7v9;9=`J;_3sc^e9YVRmS8UwjzGg^#xM~E~;e7tL<*(zA>KM`Eo zMoh<>|El{K-%Wj)tOP({`sn(NjrAZD7<6im2i+Er<@1`dHVmwqCh2_z*s{(Rw4 zyc!m0IfdPI;FEQ44h!AgJ35-H(62tK?xMxokbBRmoBY!%Iqg@^9hdlK351r8i|Y8l z3=9tKTv-TOI#a|7UaA)Ewt`n*9hB)|e(Ju?2wUWC;efu`<^BdbJjO)Z}F10s$OO<{2(zZLveU*}TzbrRo#HT^u=BfMDpu2^(NRDII zpztVf@xX~ZDG<yjMJ6a8cO z^Wyf-Y3d?H^HV$0X;L3arpRRX&Gn|U*>vyxcjo$l9doI^x$n#qx8UTacI;S}lTNp} zshvBfa*q0T4nU7GNT8CLMLcKzJK3Zt(z9DrnJlG#$b2*|S*sycNU_E(EREY;s8;nDMv3~!Pl-=?Nw7%KO*!?+P z_Th#LG`3e`Ql8D{g?iu>fuWzTC<#}PSX4qH;7+I%8o)$b(5zfrhvE$PYIaK=ehbJu zS)3XzyXWj#a$DDz{IY_1NWqp$$&lM58ShT-Qwuz;=1kkn8xJIGT>2pwXE04ts}RT zq#==I4LsjBbOi5mXv4!Af*#T?>r5xrC7M}g67ka2Q?ny*xQ(mGrit@PD=HJ`ZF0ZR zT2S%$WvZ!rmxij*3ANEFyvD$9Ya zkKQE?dh?w61#8dtYS{Y_exnUiEzhjp?YS_yH}Oe$`8ox#Yxz}delJzYr>S1pQB8|X zK=@yke31*ini)4dP4m>0rI^%|CKInvvZF#AR!5())LMp;x>cP{$jGt);kQ=p+ z`Pe~TZm*`e%cx>nulk|YGjs=Ht3?FpQP9ktWu^xrCBgVwZAFVi3bG^v=nwkl_z36M zA_0bkb&MLj?0)HQaepkW($9xN?>8e6bKD9BaHZK+&jKHB`L3ioFMSa%$&T6^NRIpC z!^Vzu>=SaOPsGyhL!q>_n{gbs=v+cIIu+td(DFDdl)tZf$;^_+{8gRJ%x6NLcOO11 z&oA`ojrDnW*6(ESYh~Txru^x`3|hnDg+Cz!QDEgoC;~k~s}kP3#@m;i9Tc9-pT4BL zi{iTEeBG8x%D&gG8lZ)PR*=t7nh;t_UD;(>efe}tW6+>Vs!C)?OlxdO=a+}guC~c+ zAsAVnZ)rg%3uF=;q?~{-BX;>T6AO(QD@;x0CS~S}VdhY_2>kbgGP-T7&ZIEuHe~*^Yc$ z*RTKiNRWGL>oUX3y*m%ICf9QLfd27Joa;A*`Eh-30e@2~_tx4}JFI`6dy`vF`tW9P z=jtoBo92{WD=QA`Tax(`o2%~g$&lr;(6C+l7@h0!IkzGli?~Iq_iIgfu(p`R=IGM) zigv~l1Ugs^Lbj3>r9}&@v$mnB90y@fX{kqO2@9CPH--P0Do>dd{%7&mNzkXbxJrFx zF+~tZ#8}dP+@cietF*b2Sg8AmwSK#@b3a1Uqe^P9F)XFkBp5^yFc4@pTEbC9F?-Xw zUi!c3=GT+@jp`>?HBkbF@sWSt7>zX?Zg{-muUOwY$YTj<%JRndB((~DGnrTMlZmOu zp9Tly{XZaciPW!Axz}6+6#xo{ulp>0?@Q_aD`^Z7DaGn;D>9P)M@Y@-poHC#a;z2K`QuMix+C^Cp z67^7D4>;hWeVOJm*8le^X`1x-^thBEtj z#E^+H?WEkO8@*08k`Ok{!W8j$*Qh`X24WELH?DKmbnaKLTBo^)d3RMWVS3^youdjL ze)HduL;pkfdc}+7d2r+xYV`+bo>#X%M8KS`Hw&tp*D2hR%U^NM_fc z*}qMy)^zyDtp=%DEw{E5+-d3RY0TQEzYGq114&%J?K=|wF#MzW%|9?M@KqZu5NwG+ zU5g*1!LOZxIv>{1%fBx4gALvh%>;rVHnkI5QZ>mHC@rQS+beH8C5N3$9CqobvwoKfn{Wc5xter2VnJKI*FhtGJnt*5)KO=Ynk z+uQ^7{cXOUo{Ij^mUZ9XLwC3OX|JC-1s1Tx&J*9#kk-Al^>((F!O}X|s6E<)$Wqn9 zUO)0%suv{BRCu`kX(_66xz2Gv|6$t2Cx0cnbVIFf!6%=_pSY;=+Ry(qp#ebeTIYE; z^M5U#j)u6_>_ssYOiXLBD1x1yg;^Jo$k89gLpQ6|#qsl!ndGu%YutannVSD}QHWSi zSk@CE^I|p&;bFPn;dG7TSEOXCxWc`Vl6h&pp&%8mXEMBf{2xj6k)}Ql3i(ZEM(dJ;u zAP2qKY}dc_VSGgE@y@P=>ST$mF)D~)Ol!|%1uT%Dg(^M)jX@z>XyT0CE5BXR&=#dm zi59}nY2L7U>>WytZEu-ezFZ9qUPNKV%4}cfY7!8v)@YNW1yp%uXMS=3wc3cztWay_ zl{%{4v3g8Rt_rRkm{b=H4$f9o&!p1?+$5=n^oefkD0k)uR!)(>U@jY0^K0m6j|QWlODaV0Sr47I98xdl<~3SFH7jST8ILVWTg zJoCW0Pu)Y^FQ@*1#JB=t1X|BNPPUa4ADW{T|6WS|E&9}?x`d=KN=b#S3mU_<;YiPz zgm#`C693OFW7p)6**`F8O!OnmFi&!Q15*U$n7zY>O%?+w%Jcy+7ya&+H_Blc_`2Cj z@1)}&?wc{~C+U=9NFI{(bj_82o}omz=+B#2Ki4t03skiS@79Qq_r#(cXuwxym)MFH zFvb8=&H&;F(^i25XUeu0ELy3eD`+TKa034Ktc}JRLJ8`m8;FlL5` zaXL7@!;&UF=Fahh!viPG!p?lb*g3k{EDp%C+GZsk9R@J6Oeu5Shi;b4rKd9iJ4yv4 z%NkatB(z-YH%2G(!-O!U&0KM4s8}{G?jLGx&-Y#N!SiMUjg05TTAJj5)RWl6>(oS$79SJW_By+7sIv9z7y3xSKKL1#$GoOsdyVQ7Y zqA_I#b467wYyHgQK~ghwQb!G9@#(M$FVU3YtHEh7=qe?Hq(C9)34jScdaQd%z18Gc zGfGyag!0aoSl4k5I@baJ?PTEA3pFw(OEQ#6BaNE*mxm|&!kE6*#0yn(uX(*~@H6ao_L}_WN!BmY2 z*Po@9hRnk(R4TO!Y&@(yFAr(VdyOe{z5ai++~vS?-?BblyMF?e8nIt^0-lfTXq}|& zJt7L1)I^cz@?w{o@fWTGPo>)ZIa49n9CZCFGbXlkLNgT6jm7Yj_GaRdgPZh7k9!Fk zMr#(0xB$SsL|^}wNxwNh zHTA?%^>_N&f*W9#aFgn&8BUB=LzsFRm|*VcLH*B@m(9O&*}S@J{sTKVZmp$-ht$Zr z{RGdB2mO=peD~DUQ65$E1Mm40c#Y|n1UOX-llHU-isvPL9zgKchg?ZiPE5BV^PChs zXunc7-7GrfsMMn=QpA+nzrXrS+cxglc64fL+h%#HcxJzP=oXVi2Fle0i&slXn)}$V zdw{Kz>gPwFSUaVkVCC}jAi}fuq@y*0)kG7KtqcUBOCxFjp#ZEBD#{v_&suvLsfw$Y zT`;;X9dTFN_AiCNwX2J%^$-)uhtah?==wZMlXiT&o})KD2`k~BZuJZ{zBC8vY*Q8M zH808N8cnOZp~_!+d%j}*rNy87N1s^xLCRFK#DRdq%IOg2d;DM@R#3 zouck(WS^%+8E@1TbJ*gHrQ5T6ylP+GoBF_2lISTf?o;7CVgA%&_^L2}##80o=~t-u zRn8e{{l+I;*L*0iKm7_O7d;Yc@1B0*>4OP6Vl*U>1)hYcmt&zH##`{E?|xHEHQRdC zG+&kYXG@K}fw6>r^oG;|QMd^}6-)nG*C7LN@+-eQkJDHY1u7=K4?n2 z-Ilh{%XZneOSxR=pMP#|OS^2_rF*xOWxL(Bp8UVRb4GrI(8t}+|K=f$Mx&W?e&=_7 z@5gaPMu_rp#XQN&>ps18IF>+<<5-MMi!4c=D%p5>A1}UJ9^RUWvqZeB7#FxW1m5~V zg`5u-rsY9tAvmjo@4LDB++q)4>h0!uIo zvd|Ie2>nH%6Zb0=8HpJPZ_vdCIL_$~oNQLIoVI51GpuHnJM%zJNukYHuzs+iLoDG0 z_J?HW0zHRS)q0jwMIwS$D2m`CWuoo zL81*3ngqJt&5}h8x2>AEn=xl(Y}Kk&&=bSidKwaeBVEsi|Ji9WdHqukyVF}NUFj+n z5$tMnOu<8MqAm#bK0MZK??V7J9nlH$NV7JKL{2M~T)dVIwJ}GiIa&f$hWzKYzz6MA zlMEG&5alB=i(7HXep{(6)NE&M!CWn#v!KnuX=b&fwTNmzE!)!QV`NX;zU1!Ap$fTU zoezd6kH>6k@@2CQ6#ve33YsC-vBxkCpU#cglh6(LUyMd5JOS*71fTu)21LgEv ztSXYkIG4bZV>Qf{EDpdVcrQ=BdiZ*7$wVG(OzMEk0!|APx!@J05^&Q3#G;F#ub?nK z(p&+DH!U7xd$AU7%bjM)nhIW&o+?K784{XSIAxD0#f2qG`ge|y0OL78Q4Cj;z&@K^_+c&kK4P9D|Hx5!em zSc0Kqi_Gs3f%y%@_wkISAo+{9T9)9BJ7UK85j1cJ-$C-qzy@R?n<^{N924utVqrNP zk(}OA+35xa9L+~kxv*5|u?PBlBB&~ChTh;;ow6Mln$>V@Y@OL%E~3DQeFIS4+!M>p zjMYlfM7ccHAA<|kPHt3^IV0$S8-mdeeB*gbiOgw=vPSq&+H zOY+=jBZOL>@Qxz=5$c3urzG=`5Zn~F@=;j)30_&8O55X;-%AoKcq998ONL6Ta$CVt zK@OJA^M3885X)iiWJy)~DGV&EnViS-a`rUpzTJrGJ@CdNoTxF-?p`nx&Pc)fFNgsX zI6yQRo^Fm)LJtx7Z6u|lHJ}LJ!S+U3IQ_0Z(n~O1f{Gq2CwM4vD-d=3>WxF#v{>H~ z!r8FYZhJ|8%Y;k#2B#KZfODl10SlpU`UNjRK6(;j`@^`6+fJ|O_I~J)bc8pL!wnPtj;_eGbXmDQl2Y`$&}~K!zNzs}Gul%CA})J`7=dDY1dn)_ z;-w|{%m^1Kwgk4qxz5$3lmRDbgK^0af;$3n$+Cg%C~6E6$`HBCBEOBqVgXg`ORf}D zdr(kzm8wqKy$7t0&!dvB7bOHgxyMsVlu`eW>IuR#hU$WL6abWsgZFZe7ige*?;t8S z{S}H_+q4(q=H7IbRh=P6+6?_{k0%itq*{a>_(a|>E8Bu=hwdfMn+Yky__Yi!hN*FU z5%FErzn-X#0d1VIO%7Wh8@N|-{qk(e1dDaG6gGbo^hUWnu4Bdh?z zzJoi#wwEx!M0h|V>T`JIY0qaTaO!9xgg#W*9%!Hv4kffF7kn-!PL_BK;Xw#g2ucPX zXiuVG<#u8TVsBy1^j!vv2~M*-zS@I=pd0XxJ+v1!L7STsd&Q>>$?_V`>R&=^7*0`y z*g{*Gha&PRItDTqsnb|fs=iLZKl{jcK9-|Kx^lKw>xc9CC& zzkx0FMOu76_u*el#P_Pt$6^wy^}mXI)K~d|k?0NWT@n9Hc7e;Of2**HbNLTY=B_D% zFhY?@{UGd`M?y=GHm3*^Aw5N36_OfpmUL3FEQGKmB+?giIlHvBO-M7pu*C*w(Oip- zd*9q$gOX(W+HR#%`n>g|1*sEPUS?tDezx{4k#c6xT*(*+2Owe80jDo-;Vxu1pNQI zc$02wlZXcbc_dB~h!Fgj;G(_Yl~8ocuE@~@Y9wM)|5rfc?K4YGGw@VGP`Mw*E(NwH zX+aMZ6v0Mychck%y*$f{1gU$uE;fUrj1zqkmgnl*8#wMmB$^IiAq%v@i!x|L@ z6Ks?MsCB9jfs2zo6ncWKV1X1saZY5(;|a1Lej=C&J5(>pj2+ov(10yT64?0cIBFbl zBFCfH8iz;Fgk(-s@cPk#60!n%k(_-C;UXg?A?*`iWN8pU9D^)|+&I1-9a$SfL^GVK z!woqC1^g~1b|9RN%SEC#I(d|~f;!UX5RqtP`Xxz}zyM)^jJZK1hwHxgEWQH0K|TbP zm8Hu_N8nqFD}AI*&?O*Ja0H8lwy>;I2{;K=^>HOofcrTbzEgOy7W+=Y z5(5JajnX-rKngI{mWPS&8xqVc_q z<{^+v(J~3`%Fr_@;}0Whzc=Hw2QpyWXkvw0q$np6fLGy=ve@-oFnc`#v~v7aDzEfjUYkK}&(SZ+n&G{Xmk1BaUu%@z+8`CkaT+?(d0tRW|Brw3ocZVuoZ-$l1wZb)Enq&icNwJaVcyHv#dOe zNXi6BT6j_SDvL&VKhX7wpxcvn2Qq2Z%Ha1gX|HWljd6%w_^-mdw`i;-#9zK?tdNwj zl6Zy42O|}YZW#~i;`=#i#B#%5iM_VO-xTOZc+uhoPmPomr(E-@F-h(3amy$Y*Mpww z3e+F_(=z$1-B6Z`Zh7(0OIDZB-6I=qMsK+v^*3Xxw+1b>v_f{GuJ{{fGm3~?-JP)E zDJ~PieBqj--r{12OF&zf#8Mm>vm+rn6s!^eZ3>m80`j*R07dJ)a*%4T%hX`#9ntQ*1&>H~1QN%xzE zq{j*dF>0~>v2oC!olGUP)rZ(1nOnGe!yd>W6!~TR&wOLyU>^fLjiF9LR2_u97=NBX zIu8QD2GuAkD#QYyvMBNqU@zruetZv8US6A7G>LrB?^7JDfhJ48$pp(3nnD7z`^|x- zs6)ww@^JQXSkJ}R#3)ZwXcDxo-W*>;5KclSA-#`YxsiiQd8E*h)s^p5yj(o^#(1kN z?_e&gI*R{(=P1f7;~2JhzjLMk;t@GtmgQUIPs3I}ivKSEN*65lu9Xadiu?nw;h%%f z{V=S^qwvI2mV%z9qI**sHT*$zML`wBnsF(LYcg=9HO!RQo>0q$z=86d5c_n(jk;xt ztfdOKau!PX9i%_sp;z%A%K2sHwR@~a^Hs&J;jVQ)cP$5f(&{jocA&I9n>Lvd_`q_t zXQujFTc@I}t=+j$xGNOwYLO1usE|L3^@uY5NyUQQ>NK(M4|jE;l4fdc>F?l}LxtWX zV@U)}pqS&|l|I*>Z^vC)H?;oLe6z=D_1w(yQ}}JX@Y^h>3e!9xJkC{7eHpV0GTmtz z=Q@(i>E*&8K}$#`8>!)+;=Z3OVf09>=~z&2Ix>N1si&wryy=>VcRA7%K&Q}c291=c zOnZHY-|>_<`IJMI4#Ta3vNSPmH+SqLxI2g4k34A54CgSfN>j&f_1n?9#OarYo!Vza zVIiJOOa=&{?*d`pTv3J#!Hdhoz;TvYSo#GH>D$8@+-7k+QKM!Tb|;}UBGok%YSu&cZc_j3-%B15)S%$Fz{}#{(#D@Jr`oJweoHFPHq5G|g z!Sr5E2=?yfG~oA80PW{|`-^=~>xgloZ~P`H%=?dlNBBg(0KBd|88FEGu$)985+a+S zB6@t8F)|A*tn*D#+=@zmw}zPrjg=08b!_E}ycNx_@PW+s#3#;ju0o%Xh>FkpS2P}C zt|A}UhNy*6WR@Mq8PZaqxnRk_E3l+u9jP^juK$s<7=zTyp2A$y1geA`X`y%07pdox zuM($G?t_Jq1jazEb5FegQStQ`ko;Mu$??t43rp|~~z6_w7hS5@xGz8wZ>a%kL$^}Lk# z##n*~fwjnKG^9a~X;+|NFCZzDX@G@HTYS@i#`kgpM!=;7rlJt~SClEFf4Sg0s&B&) z0pBuICzp-KsO|&0K%fqUc54%nFM7EL9h91Q+EtU&x#8~j7Or`+*qO!5I6s3N)Wt8*8zOMjYh0k8qYF5Wkv2!B zSC%#^q6!8L7T{pl)5MUB7I1p4>fJa1WYD$7DL?{yG5-z%r}b{26`%t6(3ksg9Y4Ye zRa(d4VtYS_Cc#Df-?$o`7QM)FQ#$#2wuk^1s2I7_AL#HGLyf{}P2YO)ZxL|*VkO=zCHxST=PpwJ{7vwK8X zH&MTsr?44N6ckmyJ#4s%{Np-Rpb~m~>tkC~sT5VEN2cu|X020R1j$!3b3wX9P!>cN z2~me;PjN?88PYzvRJoSo1sKTf%}-=g94O*==_C~xY)!GgT&^{eY6U*Ce-8WSs}rhg z{9&~{uh)}pZ%59u%c11kdDkm)N#ye?)6Ve9guE(Y3LzPyP$AwIlq$TZFW1)Gto}$X zx8?d+Yb4iJ#)nXIEcbc8{exAd6z(*-2MBZZV+UhsJP!^Xuu4zq~)!F*efuQ zW1W6XNP7|3O3_KgeMcr+BN5H?2VvG0E4a{%x(NmtI*Q>ydTTJwzTC=h9BI!**w6kT zcwR2V+-|!6C;35)xv&-IbhQs5Mt+0g7Emk5+0fca9fl)Q$0*VE;?JU@3rJS<7qqo3*s5+{3MnJZi) zA>Ats;~a|BsfX2GSOLu1;OOW#?|{7zR(6zLSEa{(y(t$8J$5XI#!uj0b~JE^&G<*l znP>mc0`F%yrQP)6Tsw`DtyJ+>*|TU~bSF=jX7PB_a{_KWgplczb{X0poA z8H^UM(=xuF^;E{kD`>|KPa|4tKvPa80rz=5el6;f>b^KjccV@jSJKF}qaRq3$l;-N zpp;lh6U3ebm-`9 z*iL@O-j=xwRIB}ikuxpQ-I8jxnXbM8cX7ywI*WK8r5ARTe5a~IK6I2SQt%_Rc@kgV zfJbXLKKdx(7i9nQ=OGvTchvGQ_{dluC;5jC$h!b(2&KcsK~HZ1Uhaorf<#iOKdf!# zN78d)?|IyYPR`y&uPmzlnBJu$-Z0k(gl+*zJ@aLYu5Qp+XcX9lCPn!^PYN_7{)s4yT-H5#&KdOG+w%_z8vtTUB;TKgZV zs3(!|M6oA2z22xh!IJJ_>6_Gp+cvbcT#h3gO18(l%S#9OIh!qNw+$|xK@lH1UoJ02 zPfKbMy=Evg60(Okh3$c4A~!ggO(uf&aG?;km!a=+xj@L@ZeU86VU4KOD>@4-Fj}Wc z{4X;2Gr15*+83aqYX+#p1Xz)6V}VExbQ3iXf=@q4#X>#l7e8j5lZodr<4fPy$kO^w_ESrdh9`a&uBBzO{pZS8dw z?M7rP+e_gthajQbmEDk-aWhgtZgJb4FbzUMQQ1dx7byaCCKQW>5Cj402DL`Q!_{pR z^Fca_z;!q51RdxLvkEv5Txoccpo|2X(!zXFA?&9nbQTZhN0uuWL)edS@$*9Jy0}FC z0!UYA^VXOV=?}B7qW<_Rer&U2s`_zk2kC1Y&{QN481x7F>@cx{2qVc|en=GWgLa;Q zrUi9Cdd2HL#3HH$)gy72Bz=vArC6a5Lq@*e9{^s##>jsyc+V@+X7(@0TB2?ekd$fA z!lFaOE(<~@C>)7|^cNOnA>?JjBWUEDt$^vULNQS7?9FDOZ1fg;!}*RdK4!A(D#hO5 zrgl#*Lh-ASoc}-Dka!ymL|b#7_6$mAoy@sWLIi16S(c_22>5Vd9ZS2{rR*)3aKzCb z2(+PRPK!O2a6}AnGaCA&t*B4$1;<M;cFx$(k)>=p~5yP_D47PIzM z{aX)IP<#*fB$}ai73l_lWwAOH6#vJqRdcq*^bQlo03Hj2X9PoX{SaR(xfT;P4Mt*P zhioWZm9|)MYi5rHtWN6+JRCgO=H_EjEHBf;Oif;o--K~GRg67EPr_kWm+HivOlXm7 z!gRFHqgfrC1Y~N)?J#6MiT9Xnu>f}{MzR{S_<-<0m24!kPFkRC5Qzfaf(+X$Kr}ej%1<_#YnlKLUaX0`XyK8sae3& zMK9z-!&^|g@Oqpyboc@gCw1!A@%w#GXErYs(--;m`O(F*IWA?j$^d+5_`G`1tA0vcOQzk=L{kb4jd>&6)b zCo9Sz0(m=XwGQoCdS!nT@oCrkA`u_E-4{Vquhl6T`_-+a)3AWK<I8gccc{6wIE?Re?YUCO-VQ54iWP_Za7oyMAZV+STNO|@mxI8+=C)FQbXcln za1$6@+(C~+@%mURa$6VZIB~?*@_Z@c;RNpnHxh_OeqqR}6@4v8xxsbB+R0lz?MKS{ zmcITiTW;DpISK!&>NLyw+{{TQ+E=06`{)L@JJHiqn;9MLMOwZTo4n-hH(s%2>C(+I z`c0~m>*P#6hl)0~rVXoBwda{sjI^v;HB*CWj>dSoVHND_?}J~k9Xy;Cnk+7m8cB$x z@nOJ38eo|Q3)Zm#Q9FUtumD>3!3wya8hR_I(aQS_!?s6*MeQCmZ}G|E7Et@~LU znH#kq?YDYS9O^V8GB1PKkk_u|FuGM5mUSD<-4B8q1771uyIE|V~uo&)RQ9KzY zLhZ-&Ry8$B%8;RjJZ$f52NU4i!@qsNNjI-C!SF*q?MvdJ!5n^s7>TmvI^ z+J%C{T>q_j8qflOjEh%i#c3-C#C~p|%@*~D{Qil`Pk+Q{YPF~7QA79%c&;J4rw_E%86$7c87K6d++GcxK= z808sq(=6a2Hq=r8{~}G5Zv;#$<)3S!jLCRK4uP&yJctIH7?}1myt1boO_CoP84Zcf zM-X&&kFpaK7aVf;3hy~}Gt$2PEr=|ucI|>ZGbVVppzHLZNze?SLad%>JBG@}kRS^uo3i^E?kjp`HzW?&g?4jkYd6pr+S?3$2TJ_R z4EN085=5>_*FCdKL6tu1F4WILo-JM|v1r%d!*vL0L@?903D7za>01-LXM2>4ONbuK{83`gjbwN0ntS9CE{h6O~chgiYO%$knV|S zQ9EkTaPdj|4HAqR>;^2sf=GA-&udTd?1I%Q0^unj{+*4yD6-@%Cl-z65bJ*ao6=^Z ziuwsV$u?-fXn?6eYV^mRBi3B4-~<2$=Rts%he==uaM&9&y2L&m~Y9IE6(A_PhUF zf6sUn2Oi+Q1e%BhU!y$)X=SIP#>UEtC@Bj8I~v}j;JX>I8zDcOYtVwc>K429ujUk# z97WB6 zPehJjD|$h6@Lnu}4e-heWP{=d+`R^I1OX3Jz$I8U!D>{=QW-t5KplWOpiBfC7ZKt& z`G4Yed)-ebxDW6wZwB$mOtsJ+Hw|WO|n`{ZAR+a+F+{*}M0*CTZ7q_k6vGpW>P>Ue{?mT#nnYDeN|V zUYn8oDCRW*YVs${t5Fb8?B_=6D6i(l^{ie@&Ex*tIG1CR@J?&FSK%w~+sauA1n_{ym+v%2M*5i33GvF5o z&`SxnUgWrP7LIbkl-pL#~n$RwWmX>cclflTPIACe43YtBuAf)3Ir z@Fa@g#i-`Kgn=Ffe|p)kim`Z5`)xLx?W^W~WsUgNU)84857cVt5piTA%WJ=B&ZK); zn7*?93ZYtF)Kv~jHI!Y~ev>_v%Vz(>>W^4|RjbwhihhF{F8EDLZ#s>i;ER7Z!>vd^ zAvh6p*@H3fg*EF^!wx`-`v4(hkujvz2sTNse^@&}0&oD_=Ji`4jq#{4Y=Fgwgyh%@ zLRbf;TX0Cu1d`Ip{k3W1v3v(hMN4TAckOO~&X~^+lWkKnbebd-4ROKRufN62UUQq# zRA_CTjJB=>MR#C<>D9_!7~I&=F_@|Qy=m38Dvz$X6f$I!#`=~v`{S|9hDxi^9F&bt zD!AxGBeMBJcux}+OTs9Bz$CX;a)<A(382QRqIeT*3VGx3nFf5`0WaTbUd^AtvV=4>GY5(=4mO-5 z9DBGp?}z)f5zfER8_%URZX`D8FyZOnELV<2p=pxowvZpJ=5`CQzoA*tKEd*uQCyQ-3&k#>_0MJw9em(mA-Cax z?03(;hOBw{z=ljHz~TE= zyUvn;Hrri(i%NNi9+c$=VVgp=wS}#buA8rrIWkSX$EIN_e3I0T3&ybQ_l^ObwdR;x z!z{t68-x>GxO6$N6+4nn~qT@oVeRtmFFwtTcWVr_`--^;Shq{ysbgVaRZz~ zLoVj385vectecbL;t3P~iuNs6nBcDAo0=jWxSa_riX&lTLANv!!^1rci1i}DuAs7; zIEE2lR<-X5RD`7VfT;gKa|ml4jl|Jmy~N2<$lpJuF$3kAF_nloewIXzSKanM<1@o6 z)?j{4PS}d5^UFAJO_#FC>p~eD813mom;w$&-7m;ciN<_{@agFPdTbR@5a2j(05Lo46^<5U)HRI4+ zIz?>d!XXM~!NqO(&&2Xn;}zt&S||&)$)lenlh5MjeITirvjqlWeX+iQp%9n{RgK4K zDQ}>CpZ0?%P8>x>2_`tz4|lapwfd>YorHwP`KmNDKa^%+$zi_6M~|u}PN>=ta`Ny^ zrhjToHSR(ORO2qln`5D7>VT>5*%0P6gn8{S9EB(1wBd881Nkk(Im4@lUt#qc#uh$& zHn(jOdd&-3LGtaBRL{{*uo7~IaiVCNpS@7KE_PxeJ_tTTI73%9Zi6d0|KaE9MOfqL z$>fvL9||5944An$Ph8Ned-nL%W_(F|Md)`uR9a%u55>jehkXDV0G^5TizVq-zkHbR z#7?h@@~i$x23O!%?I!?hd-?i^Q&No6UvY=omvIGO)w!QYF}f`+3qtAmW3>Ah-W;j` ze-xhoQMWxs`z&R@k6vg1Df=*_Xz_&7{FTVW+Dca}dL!5Uu%GB_ zNbI%@`T6Nh`M@@Q8GrpmLq*hWe4F79bHO%XU`DJ7VGarPkVGi*Uxao^8(vnMT>&Fr z;dIu()`+XlAgI`;kZ*XjB`2du zFK+Un+$cvWPJ&42<@hKl5_Wewh@3q9Ob?!d<%rU=h5JibvGILxf1bg;3x>s8Dr!%< zQTzI9A_Vtq5N+)4#)n)q%I+T-g)Rs4z{m)h1=P`zxsR|F*rk>2{oG&!i4IZU%o%cN z|ArNUgA{fa#EPI~acgV78^0#Qj@`O)r3xbfz0G|Vu_A&mirC{N@QI`96rccu0N)8T zhh?x7LcsO(RsjTo{9LHRgms!+N$WhZ6?G{12GX}1#6i;4@$**3r;oUJ$Yq$j-R}1v zq_AYPUk%4;H6l(n* zHk>d#X!wlb319(Gslj4I{3j?gnRA59M%FV-jH|*tg(sP)NCYBI)+o-7cVi_K;1q-G z@CHF<=9FpNFQwB#LASEhZX7qJA8{&)oFy17xaERye3?Yqi&c1LL9@hq@a5>Kru5O0 zj^0y698!S#UAN^-xLeTN*J=4-yOEQs3*ED z!))xY1Fkjvr?EiVWz&8uZWX}&Z0f?}ZiI5eB0*J{T>&$a7?8YxsO;kiCZ-C)QjiZL z7O=6M0c0QQg~MlTXu@uH*}vs*eB5E|HR7LxT^DdW5Cf0aVvcmciS}FQJKp;~m!0jR z$mBJM{0O)*JkSH8f54_~;&;Q5jlC#4?KVcGJzye%tGB)13|sEw^ecSrT7#}!jXU5N zD?9IZq+IwKMKp+gPJ$HeXs+pqTzH-VvA9ZJ5(_xT5y-f~J>8^lmnmHtfeeUhn5&Bi z8`*fHF5a_(29xlIhG-~9f`;`vJAPn69lV38_5cj_jVgFE>SfymMI@0>u|DSt@MiXW z9`msoon+VJE;AB>i1(6E1W^LBS#Sas#(=l@3Rf5x9A6NNu_!QO7=mC!Af$IDZQ~&r z+Yo`lyz|Fig~CP@?FI1;P%nUW0I*&G4;e}NL`n$H=OT?!w<#q~i{u8r4G5Ka`7@6D zx)jKNlN7NyoFZXgU~}>9LI!`^ei2c;AMq1R>cAP45F#!j*805N5zv??) zC+dsQIcB>OL21m#FQo8c6<6s$q|U~4Yh1y`@e1SGmAE~*6s$3)mp=ffZ15n=@hkB($Wk(88{aW}LywW`wDxzl*Ifp0{eKG}nLDSQ= zL})sgy{bB{MAJNfTY<;k;YPSSw=B@^#^q z*#e#wP?tC_f3d6!J>bJ4Z8{oKg3t z47eBnDXOsGm`>ZhbYD%z9q8he_nf#_%KK6oXXws6=78or-}?g=Pi_e3s3nk#(2KGP zF-fS_z(vrp`JNwLycIP*orqb{rC}Df!Ho+`SCKv<*<_0MFEjSbC$6nNZ%HM<%&!mQM-F<$3 zj`?uO3Cy3fcuMg{z26Etw7}$!AtR25FJG|Nq^pySQVArJG~%(Ud|d+&yIB2cM7oN` zV3wz`EcmldGQmoO8pZ1z7K`?8=+mY+tQM&a@34!N`j3S}H}@~;%az_~G+tGf-Zx}P zG@VfWh>cL}MvwJ`g$*(4vgIbeBsI&7?e`))0+CkQb=+rfPFz}1)#~OoGuK?RVcGZ+ z#=2HsxOUtB57*8D85_vh5VFaF%WEPFIU8nX0TvRp|D+`?_w*p|z>A1696+2gnjLCS z5B!+OYQY(c1^EJwKYpnnKp|BpvT&Wa2@cQ|4)0j`F#ilkAN&MRI_CL?gL^5Eoz|$h ziQz64g`;8T@x&AGNW$#Xf$%U%+5+M2-h8)yrRM`w%D@WNoj0$|T>f=`F z+ZWnx*w3^Om8S(B&X2{3DC7*q2ymZ#Q@1EImFXcT2!x9{yOW+L>fzP8K;9qNBB8W1 z(g?Rm_s^LsbcbQ$EFZ}h$@(~V82{u#BT8c=8r4jgw-eeimOMs6P3CBy(k>vGpfM0$ zI(1>jYVtF(Q8K-T_$c{^*{q$TbkwIPB2yb8*+68Y+Sm!%gi_2V`FgXN4dM$uS(UE- zj!myJzi=EBPld>U-(#;tv3oLigP?F<2lzAG&y%_a5&W8{oxx#ytEJ3-f;g%eJC z3#;YkXZ1?K&sy9z;p+ih8n)BOh4t29T1WU8fFn54f=cUblOlP;C~E-4%DK3WP$zs0 zUgf)}#BPN%fY$$h(4t=Md8f`%L|ut*3l>QN3~_GGJfPH6(r;sO%5T z4EH&meZw;$znO{@&3~3|nLF=Zbe-%LpT%A~|E#ph$ROJ-qpbLb?atyO2M>@M;NZ$G z*iQxSM2_RSTu?P4+Z`f;lm+gQ^okZ6#D%Eq8u>Stp?FI1)`0ye z6>mO4WblL;X4OHza%#)SRIl0GGxp_NoeDcD^&Has{Hj;|8d_Q)*)57t_f*0kIGibZ zWoIdcq-G;4m)G8Mv*OaeYm`0Ea=XB6j4b3aNoPJZB5Oke;&H zZgCHLZdKJ=J+ZiF9Ip3cH%QVAAMwZ^VC)0nJTAZW4s=YpL-kwl_nPj&1$UTmwh3o# zI7w6IKBY0t{Z{h%7=SJf1|9)%0k$;C7y`X|D!j}S3XHOFN}V`E7NMgNFCrB0yAKhb z=s0i;4E4-}bgSq7X7X7(tVhnk1ObzfadOfKD;J5MXO6(y<(8W77c^YJy#oA3Tq@!; zX*CJAJ7A_lEh949=_4Ywp3oeFAo~x5Uld>=8<0f#0B~b+@&|H)xD=v`zmFEgh&<{-K%nU4_ zlz_&!pyr=VmU?$rHb#(UYqxshvG#ST=16Nr(@6hT9a4}4Cad!wudPu~oEH^xFIl_V zg)^#!txc5&+q+n-1s-U>)nl`_1!Ap%pq;`9F%wGO{ZYAvJlQA&>$OWLK3tn*U8)CP zo6udS!T&70!w>b@nKW!OTxq!8a2wU9fl5twNfF_Rl``nT2$&-0T873R(s^{1`)KEl zIub_+&do@9mFL(Q|DrZQH2Muaio)pI3W(0)^iq6MZc2R&vDeWxT=Q zNgs&bOTSrH*6D?|q?uKgqoW_TyVI)7*Q@ls({Lj70mXRt}>=6P<1N9D}9g3&`T z$7jhOkX0OPh6YaFuq?Q&z_A;!pEtl3U%>Vz&7a%3A)*3VI4b~$0(#NrKx8Rtot$R* zEz%}4wlp%8K>xK@5&B>@pF{=^jN9yillXu-182=X@n)f6VQnoa zsYb*T>j$RQQ$31prmqKfWSGss>IL>gD}t3%&-Tme1LSX(`zdq}xSg3-P$0BdKLsvqh%BFOPCRAc`hD~|&r7|#1ZU5MUkL1YTz9p^2Qx>M6b(RsvX z;!W^I3@{v%iFu)T{RT?_Q-1J-3Rm8|n-9%uliCY#^Yy{O*Qfn2D=YM!P>(K@^Zkh6 zSw=7;a{$L@1Puum0~4H4XEFdLL5GtEz=y}j={sl${oTR%gJ_)nq{|a`*O7>-b=w?q zcUWm=pS;P0!q#t>1(99_6olHjiff3bwX)^o-AlWE(bkiaZdaoR?XigR0~yf_=!EKJ zG3}&ezY7SCe|rz$6_Fta_R=RsIb@c%|6{8PgOP`$k5*|;<>&i z`~d4?iF3<;Ab136zL`iFHCK>H8db`XOd?fA;n@u8ULhRWD`GdaBizM>0@i-?os%Ko zq|gKxn^-x0vCa^p_K{r|iI|Kg zWlh zY!{y;nMcY(JUP@C4VQh2$L>BcSZ9y-b$A`j`Euv8acHOnT(LW zK~33UZ{Y>RK6+asrOwu99HGZ?_)X0-U;2{IZSx0g4tO`X|8EjBg&0`My|re1<(K1!tghzd)Kftk{K_ z^#lFo4#n;Yc*3#qAEN^m_zGVa(f6xD^^m|&T0w0{S`(QPoGxLHV*?U@5pH|(dsIA2 zzY8iumckf_k#RIUij4`JP0NkLAW!N(QO6F-{e`GLhhW8zXtTkeDhY( z*VrJO1nW}%Lh{}SxBd?Hst9&Mv$2bZS8MN};Kz&6-CHumImhx2)WtUMYDk1A%bG93u_Pfhh_5!f0OFh7hMXz1%l z`g*e5+>Ams&QB;)1N~E8#e)@;ZOzT2XlsGfe*-NP|2=44d)Xiyca>yC`zAcInk2w`C3|0 zIrH9J_yg*nfe8GWs(r?K!fHLCF3cfqLj7@M!Tb1{2rCU=B_hOhSlQK*fV2e<73k^V`FE=#v$K> zjicuF_&B&Y!r7JaF%;B*y--qd3JYqNYWZMr^7c#LeR)0}PL(aeN$NpH(v1)Yapng_N~%%5EKB&Fk=Unj!izyW!#gQDp?Tq@P7=EoU@B@)gC(r zCR)VG_8Sz&uZexVrv z$*49o5n67H%aT(SsHZD$SQ-9RPn9YYk-B;ZB-xE5hi-u6gpq9E3dct5oS#ii4Q}ON zSGKO3IgB1(;S*mzapKGD5NdX@4ZwZ3eS_$1uz`yz8?3Bz3eCGNK^b=18E->FuUDt` z({D~J*cWa{;Y)yDbHl|@NyW5454h-H4HO!T!9M(BF~lDeo*+gY@+4xS+-w)lIg}IEfXiI-{NE!83UN)8sN#N zsTkJRCk;k)K{i4{Vg}j7-<$$ChWtWHOatwvG<%-#sZ$ zGO5kxS*#-Ub(Z_fvDQfPZ+%Elgz>=#{Drqe%1h@kY#Zj>U$1)L9bglv7J^c$(jJ4! zM1V5%tu-JWV!OqNZM&4MGZ-9pY8j88p-{3%u{L+0Ux_c7O^2#pDWJjF8) zpSiF6LYZwHyl>gZrrEx)+ZyBl^l91u+&UDnCSc z->$M@ZGAl18VVwt9w{Vpxsc1E4uWw4(z!*FEqhETkDw3GOz}9|A^C~{cC@1*aJb3m z^|)QQqa$v$20OZ;3v+T#U^geT-JT?NY;V<5M4%~TdLn>8{;CIH*FUa#ed~c*WpL%; zw|~1<+r7tu67eC&p0Bqh5^Z1K-|X`>@BezXP{>N>W;U+ar)jGpG|#9Xbg*ar~{+*|K%3;DdLFv%tsOiJdHLg^$i zsbG`aNs!0Sl(=PXLKI-|=D8r(JiF$9Uit2KU->zVd`)w~=PNX?`G?lFwpQufb-T15 z?79vkoxK)5(EW-s`?27vPL}9gMTsL4#lcBljL!y3N2OlI8Ca!^dr;#6`;H@o86_!9 zfVauC)C7cZVPJFn&}wY~tm92_{eK#OzKnfUdyy&HuUUt7uvU}K<+L9n4>5-^;O<-W zwI_IV*Gu#~gl+AinKuy7WRkaA@X)2Qj(>oHm3BQM;1)cM0I{Xjy0yuJ*+>%x342j8-()})0+Vbu?J*dQY=;5r6m0;*4h7U_ z$gqwX^6kyo)_$)G#!SU*h%nSsqrJ_e(h13uyo!p4WJeDO63{K{aWdFw0wyYLoMeSP zH{7si-}U*O8&MRzSWHd6eDswFTHN_t+iL1{yIAk8>#p0ieur!JCYOt~<{sR2-6hgw zXjM`BR&iAb@1T%?5@Z^5MG@-+O362k%@)7?Z+oBYs+ z*q83U`#){}FeHJvW@-u7}jLIMbGxr!kj<-t~N#9z9y3I|a z{ixBn)Ckleir{qM*LIH=*rRe>1!eGcTYO1l(nFwN-A2orQ~m$gefld89-r8a?5xS* zKW~@LX`g26U(*6?yLOuI9d;iQDQF#L@RGrpOhC%^dWMiiY!l*C(smQ}@lpv7hahFf zMJ9BKvxbNsVTaJ}m^sDD+Frue*>xQ3m}gnPryp>S&^%p;W;6rRBH10s##3elPrIF@{)&7 zVQFtGzaMw_SnTpTLz0qvMz5^l3K(oy9& zO#(DID#`fUAORFOMg8fx_?q#}eXwwDqhDQhvgP?5Q~e`LI<6XA{hq6~UYWmqyjm}J z99%we%R6^pR~hKOs&^>awq)s0VuITO~!z_w#< zoYNb(o55K5Zdt(QEyU*aZA+WvpFYpt_#F0zbQZ*7ouK0a7tUd41`OqTm&c5hS6~1M z5400>5@BkP2%i_h*%p&*K>F6)`gar6L?450LIEJFAMNt?+;A#Y+_*D;^p#o+D=aCq z>s>q6_%fZ;Q))YVt|_m>0AQmmsN&mO_Eoj8I#;P*HHzTdl+J}(#aoFT8EtP5ai1Wm6PlfIuk|M9z2 zm(l1|@9KJXckS`vFN0@%Py2Epui6R-h0|7QKg#_FyIY&a{AEKgXoFiS!Tw9@S~i?r z^H^wdQ{59|lH6772%(5`fk7LXXu04Vs^m><78kc0AP9m8lKz0^w#pvR5P1jo!}7Ig zg$nH0fy4|>4qNI=-uhbLk!d^NzI5%JqCq5dbGkVOD=IazTs@Bt7~5GEsa)B%-k3S=vwRzIEEzHRFMk%6VFjd|nV zJ@35!lzZ~_+W1JO@Z`!%@AtSo12uKa+BKK=jf}7CAD`a7MSI`+j&hk@GPq84Us};V zIX-mA_-{tfOR;hAJA&gHPGir(dr8^adBaBqXq@>}SONN4n!&Rr0CB+y$Sw^CCNXVY zq5)Gk?f^GgzSfGM28d%!X~3@IVpnmp1DdvUEqay!)VlPxxeiD%Lo^ad24Pn4kvSP5 zQ3el#Fu;YlEXhP34lHsB6NB~%H33k>8Cbue8G{WStWLO3opMi9*IjXi_BXZKFRWhJ zo~=XU<9F1+ic0xO$PB;Bmkw-w^oj#zNZUwFV?Tx=aQxBL8w2grk9MsBrUTyzMh@Uw zvmtI+RUc^~sWj}7beR-UU8b81*yASoc!QfR7ZRztK}r`$qs^?@A|`@S&a)!$QKGBe zLKLNGu&#YK+^}!=k^GMJUFme!`W^WrB!j9~Pk(sF)mQIWx7DeYomZ@zzIrYDSYSoR zhdYL8J&9*Jus1JU&vYv0Qn8-##(K`5c+2%LNWK6-Ud1x5)0gy?TJ7^#$05F=BaxVT;EG4L9w_CR zJe!%!m-u3CT>a?yMoH45k`!QH^RMc9bQjl z2-7o?>;^U41T`DccmfcZ-5j0*MO#~%v8mB$n@^~THR)Q0J|UDKZK5@;b~_nN2qY^} zX9^&um`{KeN&nk-gZ6Z$ynY57`i8H4D&1Aid=J=p-mqY)xBNe@jjOLXz|5j=j#DoV@}E)SPOm9U{JOr(@I&YfCL1Z zNCYKCEs6g&YqSIA8LR^a3WG5(`4>}F{PbQlQ;29V)OGHBN1sRKM=iCa%ffd zgnzW_Q4xnsHU~G>&+=8DleKjUXss+VK80k9ojrJJEpJ1|BOJ_BDo92MdI3wH<@zxQ5Pj+Z_VeXtiMU zN4?2?^S^t`t2fuvp^(GQ3?zt!;-Pq~E!s*tlh0!hI?xo}U}IFAlSjS@GD<253HdZx zf50g8XK2sFAlN|rk|pi*KiJX|#Q%T%{QWHdaqZWb`n&U}hD`sHaMc9Sbtp7DO_;4o zIlR&Q*PNeVU)ATIf-U*|Ura|p8rXz@LkF^uU|d`b2eQ5BZ~$erY`4J%xy%BbZErwf z{#S2t?dE!1z@R-BN`;aHftE${xBs5`vx+co@cPp59smY!zW@f>`Hw{cUuA1|Z{2!P zF#PUQIkR*kH~Y%wUG>Z+_6Cqp==WvdsnGAi4N1S3E~4KHl$E4`KU&AHzDdWgesA#4 z|MKBIV}zx>BR4~L&@TP$XSMe+qc$rrG~WgK*U*<#$ihqNMbx8&2?Qws(CtAR_{K3n z%Qqn12G$`cHPG`RQm9NNwI)t>A(&do&_W6g+rMJvZ5lUDv5Kt(Ai2j zZ`i^04(t*5O)bW08>}!~^Jo#b%hE**7ZLyEKOhotk<068$X1OD4d^#?@#{8&`WXy` zj(mG68EwVjBc3K-D(SI9J%*j5iAz&Zu7m)}ZDC3Nip>L#Wo*1AU3XY|+B1Esd1+^F z{bVYCb1Kh9Yq7|4<(A+%U{Pi`*-m?DbU?dQf=xK5T@DjiPrG(`j=d+j#G<9xd*Ve^ z%h1kh;1kL5g6+vuVLN;zcw0| z89Be!89C?I4P3qW)tl=uxf=|mh9fJj&DVxudD2N}0nHtd6~$Ts1ZFVptf#t21F#Uu z=S}Ls?1Tb9lH>d46oAJ-P$0n69+%ERT)c8C7aq0WJuei1%b);Ueg=+$UM@8X9;nMS z7s4iu@}TISpu;8t*x-y4_UQ{?)7YZ~8!Gl>`2Dcql#67Ui(Y+E*!a>(f{h9LcCj3j zZU`}4nhp|dJX}#?@1BRvDeb3o0`(Il!qj4qGnp$#Td#zwG@E(;atPFy34xjehkcFf zNVJbpKngD<;7&85m9F~&Tmc}#0)3JOas|qUn_%SyN#-&gm;%_P!2&_lVp&RTv7>Pn z=vhOL1ohM5u=wiDb?9Xz4d7|bz9d8*5?xyxqH6;+lDaTJgdLOa+`j!6u6ozHv3zA{ zVBp9PU`Yp;AIo+e*qTg^Z-mtIBxm^Z`X1RG2kL!841wwsuspIgZ((=@I$zxI7zIUL zYYnFFaIy0fPlJ#s|w(g4cY`9~{*5RmS+RAq8 za93%yBWtUsT6-Mo2(6~E9fki3O~)WSl#oB^-zKp#m_ZNRb zDutAJ=j;dB3)+nd5qC8S-A$1)7~4hdmlzLOu>WNHW#{hePNmwXw&$1cB4pU*r%)GT76JY)QcFd}g{3dV@W#Qju$^Ns?o<08l$|EnHJ#h~!jceZ-``>Ko z*T4Rc+E<@>h65Gr2wG0-NHtp^FZ$e8GyDmFC|SZu=E5_v7l28eZy5|teq8JH`r~F| zK9H=Dt<0^b473(5GPrAeQR$M7u4TUHs~`LG`-<8xLmPS@H@Vf14xd!~zQ=P*Iz}X~ z_LuC6*}v!=`cHcy#P(@_?JZG{*`=a&=Yu9$JVy&a??8RJOD{$Io#`8oxkB{^Ctf2$lMhw`I zv^Tl7Ur9ER`kzFo20wu>DrtNj$A1Js@b|}Gd%RZTFYKY$YPHvD+SVG|Thn6nD%~?M z@c1vjP^*367t5B>zw2pVYgf=K9*@f5gCJ+VVgg6tdqRdurHI344 zi0gtt+LJMf^Axpep#*t4XVK$xGL|ON_AqX$JA}-R#3tw@df%1dmPHZMl*5HEVJ!bGQe^ zWM79lZ$_68ANPtHd>6S_nj;!sUMr7|qG)+}_`t9hs~=>DI{<3ZshLsjg+y`Zpl% zw_iJireV)Ta=D0BisYVZYeu0Ln={bd7H5S#UC@7pR*Yn`5%xS@#oWZRjhI^;vaunJ z_=yUyz%<`Jz{sQUDU6&N5WyV5v$Fz{Un{Za=t=rh4@N?nSYIp?im<}H2u7|KiZ`<7 zS7ame57kD4pi4;YaCt+`ALFGE!2}5g`vK$K*hMbD7^@YuWUIk!kgrpB(Aa>uRA3!{ ze`R6lOIx*nSaE1Ye}8%P*zU1aY`Wvy2RerQZySs+jT>1N=kSl;SIo~1nn<$~Nmx7z z7se%6FdH|nA{f>mmCA!srKbqY=-U=eL<;$Oz7R=7r+YI!Jrg}WncBgPg~G;z*B;tX zoV?@Co?=VTN0qgGp>St~J=(LTQd!fprEu9hu6xI2ot>AxW8l*FBUnPfS@cJwh^H9O z@mW+A*d)KAAyT`k`wa?PA zex8|2lU;0E*QE3zwmsfA4Hx3 z=|of;5|#!siYCeB2O*mqo`N7jBDB#Y0y>+p7KoDUtqOefo0+fN-KwOUiI_B}l~KFH z5klRNzI10fmS)=3=~$^V-QM57eqeyzUoMvek&fm07MQu5&Y)w)=I}SSmCLb^-(f2c ztf$Kste00*?q@nC4j>erL{4b!D7mO_WPLn*bWKu3i-l6D&=LH>yY}lusWeh5eNVe@ zZW*O}k|FKB=G2iR$uQd+O0F!9bajmswXe5C0zM=II?%UQ;NnT(;xLa1Ly9U@1LTM= zl2M3h1RGm`9nY0}6FK&HKGs{-ww!yYP_J*Q*Vz)gGtd&RR^yni{b03Pt#7I0AHdFG zPqFIjU>k@+zgP;a1ZX*Ad89A}0XG@3?oNrz*(g(i+L#rQ2$Rhi(Q*d0U;zzuQFut( zia1}VH=HWew)W+m%KlVey=V{j#L%)M5|fS~qE7V&VwrU@ForPB*1jLGj?Vhh^s*y?dU9aE=5+d8KD&c?y}9i<@8IQwoVSTFldUv{%He}N-w_e& zY3QKtQ#}@_FqiBo^7zloWwfC1I9#fYHT&9}wjaeh=vULe z?nt@paJ!lu?q}uLy8n;0w*hSHD({DVu4T!VZCTd0Wm%T>ZCR0JNtP5vRun~XUB`7D zH+5adbxknEq$V|Knz|*FQk;EKaiU+TrA ze^R_{=g3=r!GEG}On7>5O?ad7@s5o6xgRD1lik7Inz#JoQ0s~M4XA@?mqgPmLA`9W zLoclD#yrU?=i|edd74;8J6y{68PKn=>RSU?q5L)|l>_m`pNzad-dE!lLGy@yl$38 zfUM<_@Q|*SbH4!SFO2LjV%O=m_(pB6*mc*%5K%eV*7og=?gm$rCAeY3vx(c1bxrJ% zzPQ^q>KoPdP4^{zNadUKF>iO!Yg1Wd-Q(S&H))O7!Qf)qDuqAkahAisz^))QSF9a7 zLZhODYI`M;eJ-O(_FJt3Nlhv7&OzSc?F%b^irJ?4mN{2bdrxp81o28Gwj?| z&tODfttOB`sfb-;Oy>vQDO=fy_I+K~sc%4XLZLoWq zr!&=;!T~vO_>FLqh=+Abmv{Xg>(}40cREwsq-qY}?&j_8RBy`757b7YVbWaGVTBLF zKLfJ|d==;x#fiXTpIcFQ%wlQzS^BkwmK>u3xQj3oIX)nq|H6(^23AV?C(H|i9C5#u zW^ortn^KLXX2NaLX%Gol5RaUh9~qe+NrHJohSu*%JQVwfTBWW|2YE_Y7fiw%^l&(z zK?ue=ty&8|{rqpqHETw;baibJ)_|pw7%Lo0V6TQu4rs{=oLeLylw$xSqK3hU<#}i3 zFJjyRo2L_*?dkOP2d2~MX*2P4eG%c%64wUi&A)gqJ^hh8)~&naBh%@NX!vyzsv9u9 z{4(Nqlwo&C-n<(qvV=B@g)C%@x}yYHSfFEdjv8o*10M&^OauHEJ#Or#k@i`R*gBG@ z178s5&+c|wb%XI5Ur$6X571?uj$gK0HMs2U#btR0 zUQ3y**OED%-P+A+Ch!7NF1%sYU!SPZUM+wo+TL2FmF**q?bZeVpyYfnU0(eCb# zR~hszb-osl=<-+=)~{c%c-G@3{)Sbr-vi!#kHtgt{_+pdZyD&i9o%9Dpdg(xnHa;W z0jnR)b)NeWS|{|D=zNs+x^e}+kaYk+L$R@8b;w;e-H^|)N}K<6zYX5FHm|Z$=ePCP z{D>fpGdAdVdxK`=Lo;u72N#bAy@O_CK0{VbuRr2%-ng;ZUmmaaKRmi78@s-FmEX3h zGt)Ktu)kXT{hCk2yNn$-58ZJ6{!VX4a`Wb7hqrV8^*0QS1P!V9Cx9*(N6BXioG^?e zkw6oX`$56rjbt~*T(Ju54uqaMrrw8eTKgWXajuG$sp>@00d1voL%-k>cEb)m+qwunG3wWTa=8=tpLuGpgI^NnHVly&@THu3bzjnd?s zL-HMptFjNf6r>b~Eq@zmK$#ZnYX$xl#f04`k)*J+04T!xAQni3nT*NxMkM6`oxo}t zV87gDpJDrLGxq(d$y91`Hyu*;bkJ-LrtN_Nzki_DH>%kwKJWLM1tH{3^qI}6Z7GB= zbWcopCy;M8!x9Fzi#g(xj0))gHqKcwDD)FCov?sqTD)Jj+Opu%`0V@*ot3bIB zVHSgc71fm+FKgjyC>`2&Gofs>NA10-CdpjUgNgP2Oc^&ec$8RHxTehxr=P#3hRzlndJBA!%mJ(^8M6kk}$b-1Hbp zu;N1JjBXD+wR7AiYzvW0JX)SV7s7S=WScQ4J`u$-*{AX~M9doPOYnDl(Ta5Dviiy< zpD)qYHgV0f(Su64ozH14r>6x0%@POW6Mn41Aq_vYURB{fhL3S>OL)OEB0% z|IBZ+y+68%_JT;_TZ#5H0={3x+-}55L>4>HqLqO!gKwchk3r;ZYLQx2kL|t!`@@3h zj7%V77+U%-NFP1d4;s@V1F< zBhlHAI^nkYCMK-zgb#ZR3pFs|YmQWV){8Gg{t{>kPfT>&xYp@hdt=AMMA*`f(B`al zy{9_T>`P?OXtWb;q`mejz*!5rs|SS9N)nEC5Trm!^Iu)MSTw+}*LB+!XgV0-W@yk9 zE$9XN8hIJls8r(X^acM+7nH$@A3fWj2+3dpAOzEcazttxOk)G7R~6oe*^sOX{s+Sr z^G&dslvT)Xbllh1x7#I+zeGEUBMKsuLb5E2ye>m%VZ;-rowq?+t0h(ql#JYeo9xYvs(P8K!E_yp`RJ!-`($pvQq^RNtyyJicq_JM%}<* zwQc`FSK5E63Ol3X7pRyUZ_JHNHOA(7;J=^v80E}$}Hrg>V(za9r16MWw#~vC8jd67t}U`Chi;eMKnIO8!>Hc8lCX` z2Ako7>Iv(0ZELrC+28lKebZw3W*fVny<7c3eT(=Nt#+iY?u$CB!C=)9enYQ6Ec`R} z-fKZUXfI@UOR`S~-x7lUMPn%}Ge$V&Lr6t@VFzy0(-#9GLzm-61oA-mo2cMy(l*;o zS%j&m);1fOTXZ&?-o%6^(_o;nqopBL*Vxe9*lsatoq|c*q*e;rH+88-nZ7mIB&${4 z(57t^n&4fk5}LKEI=VKjzc%6vX=_Zd=Mic&UbUe;7VIb1iINs4q@qA9J2KlMYo#S71Hobpti|n7P+S6RfPqv{XGTEQ z-JOW^hosA_9)U~vm{A~<4!T7_5CHbhBU1(9cr$^HCe57FB+2*L>n7*oIi{A$Og(X% zs!~Q7DSQz_RAoS<3(Xn!`fHXNIuYDDr9p?Fi5j~P3UI_^Pml*X4z~Ok&EsN*;LygJpGpXFZ{)h-MO?EFv!R=LCSa zOJmUkiQ;l!Lazdj704Af%Efjw6fY~l2_Jduaat{eLMD|;g;WdQOZE2N*V~)+1_J$l z|MNofwv^Won=xw$R8dHbCHtKglP%(Y<*XUe5AcrmKQu7#P`@uRp1}KrHxL9>gd;2h zVIf_mI}mWE5C%?X#|eg&?}Pse_!)-TWEm>wtRc226on8diSZ%Cr1T=tUIxWO!S1-v z5C0XN$)4!(I=xY*?bxuP!@piGuWWA9bm*HqR;^c7t)sHRrRHR`6w^~$og!s%P^mQN z6r@mAL8lVz0U?qSuvfy?!eCqrC&qGYm`GSqhgxGEMGQM92LgsDVxT}C5F%`wIa`8V zCNyvm}W2hK=eH2&pso;B<4SQogV z<&7QI7O@%61~&8W7mcIsANSv)Z#I6)YCXok%r!OfHA|wqb+q?mxeYfEovWtGAq1g# zAr#I8Bv=n|AZ&24Opp{@ffTnfNx+8CKDZ(nL_Y;DWoL05R{AX(v(4ZQ!30UAQ)?_v zv!*iOG$0`8Lta%?9o*eitql!2y~tQ4CZi^B(cel1@Z3WS4TU7M!x$ibJ3EDfB337h`S`Fi!x-E;5Kb-x~d&E2Fc$luR zBf_EfBXn(hJ3s#f9gm1|y2kNy34XMnh81|sScR}=MyBZfVN^UTo{jzxfM3o2Zzlyu zW04n^_g@>Xr$=JO*N@DO(gUNjc;NFN9ijV2K1%Sy`d^@dM$}SF^R(y$c&jVO*xbkr zM!a;ZET-mWDDJ`%Udu6mowS!C#w=W3Trd&Sf@ls#7$|SZ5Y^m5Hfwdq#{Q#*6HeXpo5tQbsG7`E- z^PFTtTnnfz;P4eF+?hjR#Vf(NUFWmU2M=Y>?_w%C&e4TKEZaV}{%3cy+V;7-f3{xy zFFMX0qf6LZFX1lDLy%QOZ8aj&tC)BpLf991f&B%r7-;K{{t)fD>itg=<}&~2ESm=s z)BU5fxW5?wgtvu-8hBQLS=j056o!|UUNVK@D9R?+NJcNDKJni;y=HFY9wJstn@7~UdyRc@5QV}KS-t|@ITjdKw^a`?lbl>{1A6c-vR5ItZK zFHAgJT0=5N^f0B_B%$WvWtA;~MjC?>{K?gcyir%9doO{q{V4RpL$7*B4LrSpd5wd{E8xrfFxm0>5N{QV>hBAyh?DwrQke) zzKACPPj*`T5B3Gxub14*O?$yXu-xxrVut-AXAVS235)K<`V8k7a4=PXy@zcoP_`ud zM=Z~TdeZV-^bF`Co}owZ#7u#{Yf<2N(NFsH)_4%p`54((_#j~aLVS?xN(ktPq zR3}oZUky+FPfUF5-R#WOD4kIEr&s7w*a1&VV26F%a=4Ao%`Jo4MZQEA!7PWXF39@| z@TcggGN#Nk{_M zHwa9~wwq-A(8l=f@n}yp>b&=)hPEPd&v{v1?*@v%O#W zAQG&uS_J|&(uJIINGA900|&lyAozLB-UjBA8c76LV_4Z+TKgP?^HAG zSg{EM4CuT5s4W>V`}_PX8SLo^UM_=Oj`fWNMl)Jdhg~+b7`{i|FOA_Xq4s40BPk|H+^^*G*X=;>j60mKX zH=nk6cZRYTkYJ5$H$#~*v&qva7|hI*}9P*>2cL^z^`sK!rmO z&JIW)-CyiZb&sYI?fq*?QzZok?o*nC_Ex%uUDNaHR@QTk*L%%1YzSwqbXok(hOP~_ zuB&XQ66cl5b(JQ1MB)wiV@$dMA=&{N&`MY~mxp6vW7uA<#l{Fyqp(L2zQti*_pUYi zcj;HN@hR3XKDFiW=o3$DVN=_;KPmnax*d(UBbAyvae`nCdyJc5kD=xkPkIQ;K~rE^ zL2}*{tDsoHu*K|D7&}R%0u1}qr#9{16znu7C)w(#dCg=OT^L|O&-AAbPvfVd-dIPx zYjRCG7LImJCOEZ z-l9pz$3m%X_isyuz7{+ePY>=px^HlB-{67s1X~ymT9XS#5Xl=6@(sAJN^dkXyckTHAY_An78OVp^hQ**qt-J z=brP;uyf)W7Qlb+y>xzW@@y(4o=K5SCC#gkp^R%`b0^U)p0y?~a#DD(#m6Qe+kJQ{ z?K7$N?Ngc93|c>K9~sHL@wDOl-#0Yr*_ggb{ElN}B>$Gme=o{^U%{FRRLK}~6c`0i zFETggwru73@npl@ySj&V>>P@YY#)h6N22Mdw|lsIXLt8bl|5j`TX?Ym!xxi8s#-%RVkKp!3&5~nk)Y&lOt9u#4Iyb zNL%npUtmdogiWsekFg-()OOUfwWJ;!x1xvq>1s6rs9XV|cX2`p78YJdlB%}?+jz3f z?VJdOdXZ|gw|A@A+{eF*!y&6~f*sUZLlffk!~|G5H@_m%)@_CVF}f#2w@ie@$0zs~ zehK_h=JFB2P#&kO+cC1yf|3D&ce%3d$`ecoQW-^KxC_EdK2LP8qJ?mt1ewv;iYE>- z{<_Vely%!8CRM@~@Llm$F00WfEmozjMrn%Jx@DFA00iwj27Y2UIJY92Ikdr+ zKnf@Q{V0vkEotB0h8W}0x{YywvOm8#@+CUIR2LRb+yh+>frr9b6M*DG9O<=doK89} zUVySxWw$RKp;4e;&-)T8Wx#5K#w)?D0m)j>A%#h!ZlUPwM55KKukWU8FQUP*tL>MmZ+6Ck$l- z#uIAFb{2(6S_%wLEDA)x-1HWqbz9QqHMM%ZY^}e+&?Vk! z4+OG-K-pz`pnRg{Bj5J_=R@u5n62DvZdTs^VVz80ompF>ujsy2=yZL`(AM@YWfe@N zL+fu{pA5iTUgb|#CpQH*1Ogj^L3_3G-LjuB-!b*Nt(q97g~QbnYZ)6G8y`=Pk2A|-Rl4S6BtrTi!$s_Hv&a8rdF;>VFH^FeR}{FczkgPF36}j|EpL(;{&acZWB;4u z%T7OYMRB0Td7R_;LcYKM?eZ?||6eUnu#a9@9$JMtk-?mxc}ezC6t54GDD4%!j=I_C z7Q8-BSZ#E}+w6-*x6p!NHi^M8!4KRvFD5ORJ;L`)G+CDVu7yR~iZc$f6>WXEXx@Dp zso}*p#-1HrKKT|+h)XegnP>^|jvGPG_JG@x%7uYlIoCau&O%{$=-|+i;E5p5=nXS| z1DpM>_{KSe8HyX~#f@rM53;YSF^@T2&X-w5R?eUgDAfaKV7wsmxT53(n@{}or<%Z% z%L_li)~vpw_@eR&4|w@2mkie`)XS_WyQJYJbcMliU|HGUrT&z(pY)(o`>$vcq4Eb?}Pv3+?Y*5i)Xub|9E1B@{4gD_=K%kv0*C0hQj3^n*c#( zay!i;Ut{{2K|IB#g&!BMF{7j6Lt|r7dxwGJGdaC>zC<2EP0E`ThCQj?LAq{cSL<}@ zcL>YExTD-LmVIA0K>kQH8t1$~L#7phu^r+&`pyxHhAEieWqafc( zZgnBGvPG}Ot^lZreL;A6{{#C+_wUD4Uj~7|*h3GE?cbjtw>%ukvO8Zx2^`3F8kKOx zVa0NIu&wYy!+Y`dD}f^Z3YLe1gN>(vA9*@$0AEJ-*w_*vR|;jir`;i<&~tkSLdYvg zBYak$^})kYK2`}AOg*me<7aen$5=WjjJnIO})C7Rjj@-OjqpH z%h$w5zmT z;s+hfC%SiI~eET39{9|ofp$%89jju6Mxpg!KaQ>D0 zwCagKTKxBs4RUO5sw)4ROAc7Eb0QKY)g!OtPs{!E%he*xF&kxwfnaIv=ii zAfm|G3JOhvy=VnKV2-t9!E4Op3;B=XhCXOwY?t-W_ z4rwdwP?7BLA^PFTl1swgQ=d!w#f`BTyD$|qG=J`&Kd0`F(lc>yn;JQDb?Ta_PNR)o z<6Z6XtoF9Sle|u^LVrjm`Ol!kzr#$xd3{TH3&r7%QrfH?kY6uk$lAOd9eEGQIxZ4*fqp@4B*}#$ZX;+6 zKy_5|^|vGSm;ok(1FyUqkF)dfbmgl@4K}v6gWUW(wyTY5ya)e2W|I1Mu z79gS_lH8i}UfdTSB%?q!;5Ur<3M?k!Q+Bimfao1LisM1MJ+sjNK|?i7ziPt=`xoFU z=YcVuv?fXR?@HKAg4(;_`iv6E0StDiZu%!nD7gY%gypzF2=|MdRvY)ivVG+Gwf1&< zgXwlt%boUgzcqd$#XuZ@r>Z3+;V=e_#90^8J$brqvv0dDIAwuvk=J zsow;%XMjuJ0_wsITXTIa2T_1+DB}4&J2sXYAOEr0ogGdyw=y&wQLBct&QZ5nZ9 zwi^3Vyx9j`4b|GaHl9kgG`B=<3Y9zhc0#i1T0Gw9s;gC#Z8q6lNOOqBtp)NoDUQO5 zW5*QmUkbw=AC~Yj55nu)L{qdc36VguZy%1V((QD{1B*Y3yX|g&;2Ddh^Jw}#^;K}g zHB@OP(nqI^Hk*if4QuAe-3_>gY6)}t0T6AA30>7U6`7}du8;1m*~yc zWnkz*@#T&nuT`A;#+AXQja(rxJ9Us4lJ}S#7UkT0pYIT$LFkM=b=&m#@V0DpaA?;= zcV)bHG!#wlND2>K63&cGkMu{!)PicPcWAr7x`*UF{?SZa+-*-pb`dTTy?GP#;x*J~ z<8s#+;wKW}L`@{|LiG^3a%KwM>dgAb#$LDi16DC@4S1P%db)3VT6j%-8?-|1w=N#H z1OmWqi(h7!K7SLaV+u4$&sX&fWrD%#DGAm*1)CMjE|ShbtOg73Af>y5 zi!}m51Yp2)`S_V}5}fuLN2grlP>!)AEHebNb0a46)q z(~nuYZ3=onr`ZIzQ~KqsJ>E?};SdT8B2DsGjmDq~-FMWR5Kmrl%hyb9v)N59T!7yK ze0nR%LbQPyU7aq3XsAEIz9>G>x9iRF%EhKzetq)(`RHB&%aVlalHU*#>p+X;q8Ud? zT*{@W5?u_UZ-5>=UznI4Hw_B|`0x zxGQ3IDX=K5imu!>NB$?$C%`6>d%ciIk3Ba+*5A@$@!TAp(El7M0!Ge|{}kKfXc#d$ z9Hx;52d=*4Xz0Qj+^b-_w`I$(N1ErEze|FR#C!KbHhXi~c-ebFjdWZptI+c)0ONPE z{|D`XJ_TGUd0Qg+F(j7?PAp@<67C!g#|`9MB^L&)6R-+bSOu2>w9{S)I)h^28)LxT zl+Xp>ko8AYY9SercL(Kg6gL=pd^Pf5wla_u)T(HoOz`*k3<0;o?za!vZJUuD)MPW6YGhug|4F-F<_!G4Mi%KQFGn%gDg$W*kMr1C+(P-*k#oR)|x<%QyhO&T=LllR|$a_BQV zbV6mkFFqdacf0RT7y_Aq)#>Zq)=RJ}zr0v>7uvA}9Xaf>$ z>fr%ngtGu-{MZsjK%1cTM*9$^hivcZDgg(S7{2()T3vZn|1axI@_O|>uc#}vPW4@k zDQZ>^Zf*0fu7;aPh1+tnsw?Q$=w)hWM>OoHuRvqNwxAHWCRiR6w$$nsYXxuWtB{&_oQ4}P1>zCG^ku%hJ*5>%_?`h-=)*KR;}`?n%%8kt5$V^kQ9%hhime= zWSvM0CnC}cLVF2tW&kK<58*StuyKOkjtmy8nwojD9T6SuX1I_bn2nlQBnMpKkh-?3 zR(+;cvrZYXpd^o_y=tAN_6)x)+Q>=QtmbQ`giGY_;-pc|NA{rMg(V(&D@e`?u&)45 zgIG5Hyeb->!Le?))xySXgZ|JczM93)*an3|n;ty+;3j?uxw~)a@Na5C#7L`HlRFVV z+h{G~X^6tMaNks}oIyQgtU)4p_%Okkz5*@=MuZZ;h{D$(9Alc-3{ivJW|I8;UwxIG z7ftNEOm0b-Wiq=waV&A{;ny)C<^M`Njo1gq_`;@RipJHA6}1(1Md)*hW5l=0v4#&~ z4Hv-MkY$gevmWjj5OsRU%rsUXhUNDQH{Ep8zlgtE^-t@VAd2h$X%(yb$IlFZnH?M+ z8bY$Y$IoO$yfSCS&#=k`&Lc^CGpWo*TCH>CdJtZOJDj5j9#<|7BD~Ba9(HXim3s8= zZ4bA9;~VV{+y4IJ3?V97JYn{eKDGLl)P2l~-~a9phufchw*BG7zdQI9f7ijT*1^Af zSHGv2&r7@HT$zlG|4^-Cv2l{BrCo?jIjZU3Z=Mz5f13;jOFg{Uqz_ z?df?O-c5LyDetMxV#LG%}UkfU#g>0vV!wilIl7#{2r#@Ei(MvL< z7y=)V7>V8YzynWO_xp|?_wBb@!Al{b9A7`NcwTtmBcDI_pzn#}z6bw(#|Ku6i>r6A z(8$O=;*on`zJ&U~hAgw2CQrT;vOUu(y0z@~vYllgD%)H3@vl@pK$ znUSt#r4R9v^q>wu;t4!kNzWr0J3h`y&$A&qMZ#RFN~gOZT@?|w0L5yiq|;&POjYv1 zUbc7}8@-kfH+q_yJdFo5jrH}78dfV^757lrNV)0B&U#YJa4C; z_nY2Wwz+H=o{ihe?gVwpk7Z%J3ttL@TDU@+Z6x-Q3}Xsz;a8$eIa##i?<*9e$X{W7 zk|(vQji^Sm3x+;E3%v69M}TA$3(_xy4@)fk?C^>qaONl9PprMvI4daZcxv9>lfwOYlGtY_Cr5AKnQnZs55 zR)+n+m2jnbEWvYk*`BfkWrxc?Q}(xIUoC@dy)b(U!m7fT!n`b8smRa5!k2PmZnj_v zH&Pf~aE#EhN%zsU804OL5|D>)0pf)(g&`^oT4CHFtdPc2pZi8`kcAOfmrRN2lF5{t zC+r8(J>p~1{C#^y$!Cr*tTtflCL5N+$q#c_nDL5bEGtcG1nQ+3S31WoN;8*j%N2M+ zn!=HQQ|TczVWpbHjlWu5UM>A_`l&kBiW91*m75kYIT z>^)`M%kD0_zwE)4>3UH}uabZx1squ-qxpd={8Sj_!aYkr<&osdD{KJZI@ZPp$<1JX0yf?_|{3l3zj`vI@-B>v<-S5YvD8MhB%}c-CES>#OdSFtjU`DzV z)0NxHOYums&TF}NmG+s z;>~^rHrofy-eaNAF<5a=BgR?A13y}ERS~~m34X*1SWx!QFsL=laok*=fmWACJc`b6 zG6|y>xSz7u#Un6Fqe!xl8T9qe2~FY_gk2FVQj}RK#w<+qRt0`d@FxE1e(c!>z~xg^ z5s9M<>!6T>ECOOGM?QX6p*{$@S@*a2>s5)bXXh!3*QHBrm*Cy*8}qVmaQvU4Yi!(P z6DQd?hm};1lSiy@BcL#8y%3uMAvDl4YzN7+8xjV5SQ!SyT~5?f!82&Ss@x{yGTk$ z=IDeUTz>T*falM7Oe8*3t_qA20>TX1;kv>6Vc|l^xj1ET{zC0$$=<{CJ7DCHCNg7+A>ALHvz?Mv~#S z#3L@1mG_sI@(P3zuVxLjb=U!FNor1v9X|8E^cDC{DA0+2lB#1n$n7-g6Z$LImB48i z|MU!9%i_g#OW19`NGD=2|1F)(?n|fl@uT<_u2!bgvzg2+KQbBOGcsjn&-x6$AUf9i z421Cr;FwuhkG~ANZoT+4J|(#4`cy^hFckHW8;}G64pREC(63YuDy_=yS^KQ`*en8i zT5+!2FzcXGg72RN6M_SYS+PCjHWvg3vgRU~&~Mat!W=k)aCi_5XcJ5K6HF)ufuPG~ zXYocT?Med4;xG7E)kx)Anm0oT_r z{+!OM*Nf8_IwD9*O(fW zkQOhonl!5sFX3#KE@4!~X?)LQ7U(qB{%@nzf?oVhh9YlL(-Ap;0Ru}fG+1gjqz-@9 zSP;x9mIJkk#)1CnoZ3g%NPeIHjjodpqxe4RBRfcqoTUT3X8C*Z7uoDy0G?n^qanS7 zO*ya=4vMSLenP@ka87<27Z#5L8)FN9ZE1B%8VA0I)AO;J1!G}o?y=H+^dx0>%0 zwU=N{!jJqvU8D9>y9w9mpS~CW)4g;L!GJ#LU+N=zCLx&kRvz)F$8^R=k52HyaN?Eg zeWA-3F3dd|Ec6?_U7wqVG#MqFq^pt+V+rq;`pjtwx90|(B3cDG3#Sj%`UN0*I=w*o z7IIVJEGG(R=7R)Mc4qPCfbwrJ98|}jjUxnu{P@!+Wz)*X0wEaY;YzS4_~r4WfJYo8 zAWH-v9O%6SGy)g_kb?|U6`$+}ga;LKC#3~*nfVwkbV(VOCUSH(1$;>z(E zN}?}n6@5}``H1q#O6{YuMSH{@998r5B+I8Kkqdfp7*;PH7xWmd{{j4@xg^agf=!;@ z@s{LTrN?I;j?`NEjoL@o@@)jBNzju>5rdXo{f+oZh1&fFY58PWKFY^_t8E1YlS(L&AsxoijRbJEsqhHR8n7v z=H+QOp~WhRg76;kj&Q0-I6?YPt^w*r zf&jPKVnc{TaI@#&8{6Isvt4PW9*ZbZ~n#eTN>=fFvf|pm!AAT+u=P8F&DOVe}ZRMml1i z4$^!eJeU#OJASWYY@aXg!#mg=w8d5Gs4bX;GQH?wj zs;rT#Wr>7Lt&@i$a*algtxcBJR!jQ^J2X+*_UEc6*T!_qELJ;S{8DWpZlyo+TUvF??TXt=O6AIkB zk$$JVq+G|JDp^b1sbYol)u;WBqK} z@2Bp$=g+Q-!j(Xt|7X@Ua+t@aVdz_aE|$(h=Fi3H*d>J$5DvkeJ@=hHFj2}z@T>*8 zTdZ0L_(OrvxW6Gef?piy&JGS{H*8A2|HeSz#`g<{ysZy@?*H+6bETkORyI?XWa7%t zp9%PHx$CZ5{DE96ghRE~zgqY!YwgnWgj-VE>$s&BY3HHUgXs!a`$602Q8@GpSQH=y zO(){dIGS6-;nrqHTd&X8dt&#^QqHKGci;3~m1bb9Ut8zv9qRS{?n5`-^r2x~y=nK& z9Dk)cXy0ENO?xdY!iuY4eqJz&K$V79ZXd|_GUH;gMh%Z?m_Dd2Dw@MQD{1z zz4TaRvWOm4VeKhHBwLUrt;oqqf?6Bi<;7LEg?r!6Tz$b=BiP=5W*Y7*#?02ZL*U7#0&a!s{DH ziY!Q+2Y0H6t0`2aGdxn;HnT4k9WY1DgVB`Fylp_%*C!j;W}Uou(vmx2lN(>Z_9p>L zSLddRicOtemO!sT?do%?^?l*4u5h1T?d)@@v0pDEdnhTVgn;iviz$C2^patOR;%|I zuOP|wXnG9)lpT!)`j3duv)3=qaf=&?I*%X(n|NeSnCwf6_p-fbD9+=(Bv4~}O-}LN znHlSuGjm*5Nb__n*4XX9NQzhpi4{dtfDBMdk_WMivEB&U(FuKgt%cZ|m3dwYvgq*Y^Q=isML;M6p{f&zo&Qs+hCi z(isa?wG_TZJ&<9!ZLs(fYA6FDWjX2|@>?WSYK5n^|ZI7}u7x2r2F`wR4Yea^N;5hn9>^2v_D zC%ZG;0;>cF^2n43uJ`cVhT-lYVmVNV##G|A#Gn|=pCu;}gWIRrKfT}I*QWI%d;G*2 zeA9RwEb*Q-Q&ZBKK?X&i#_qTUd<^ABfCSh>Oh^>gB3N;`ptX~%m*9wrQH25vu~wmi zkt`JG8=W(2jYa1L%OOD%i(hQ_khdG;BOoh&9zW6qWL2}KE;zDW{u3UNP62v@$_K`munD!0zY9Z zf{Re3SBn0@{1$Ib9A?nod8gezZnrz_L8n!N$fGKa)frSBPapRsyirY0R+G?l_h_Qt zgrFiKv2`m#Lwdz|CmzGU?h&YmRFCKo#WtJph0I<}Pmfx_LF2ZBdFM4#s6>z?eLLNdmwDwlSp*uP^} zXtwFuHAY(uFVPT#-S#y{ z-@mMGDKFX|shdL0f|ll6uu|>WnO>`ZRQzPF4J+3FFZc9XaL-xZie-30QF17XC_1|W z09uG4*XL#Sge_ANrbxkwY!C(?O;1eV4SW$lDGZn3OE&w;L}p?lvm7@G;(r7;5z#WH z<3f1YFRh58;?aRY`yk!}&VhjyF*PtS;1mW2o%F`$knlA>Hx!uH*kuvdLeXHaHbWGE zI-9<5;phreWK?{L^)p#!VueX^K8w1F=OWdI-J;$>-g{T8ZSS#T?7#{&vHizqSEvM4 zaNTL1KQ7avu|^7U`dy|FgR9w#*9(XG#rDN~^hc^1zaxQ>eqt}w-6P9}KYdG--V z)XpR7tU-Jhg78N!FeE2g+J{x*WGP1LYB6{{`?&afVasZ<9VU7ofWg<&I!ZZLCCfEq zXNv}h z5U3b=&fx!9vl(;2)> zPDDN4&??@;S;CLCZtyIglLCUXRZ>zg>tT~)&Ecej_vdcF>SkDp(;i3)9J`irHJY?6 z)8fHipSgH(205L1i3ld{yf{9NHVmE@#v0}dg~55`~HhM_6296(p)G0t;rsDve)iR zsr$dOgWY1nLLup{y3p>wgw34=+;j(z7Eeizr9-la}-kEX&R4?SfhS}!5_7vdTPPopd0_fE-3t$RQ*XYW$?w5xRbXOdqsX9jiVJd zn+e!#)&g7Hu*~j2TUuy$AnD%aNM&Byu!7l`7VH&f9`;I}ZEV(Q3;KF|L7S7!io30W zfR)YS__{3+NCyJjza<|1*0*-<6fTI{YzFYmH8nce@}3LW7SG`hn_#g8#P89a>3|qS znwI{ZJ4ru!`3dlVt(fU#OX?{LP}`P`QGQrr#PmfFe3C4m_4Qm|7xVOSUA&F!YId*!dQsW*bu^X`UItA3|&*kF`K^IgJYk^{kyi*iNtUA%`9YVcIi2x*7?z0twB zEElwY%TW!sFiFFVJ0edDz#wNT|2@mh>=z!_^}mWyLW!u zw)x3GDIkB+*Z00{eSO=0y&P^do>D9y+OuJC)Y3k_nGx;r7-{PaDPN3aeB=y)J*yS@ ztaF5ESgA8rp4B)*Y9Hc2BbAIVpKJgTQZt|yA-i3WA+k{A2~EhUIgOh_$V~5_nvv2H zQ1oaa31bSp(G1MLyw5zvq&LIL2s>GBbA`=d%&0}SbJ*WN@K~V$md6ZQMJFZFAPx)>cm(iFkuN)?)UCweNU>kX6(;AgX_<*)81&*JL>g+kxgrk+su0-iG?qYn{~&d z;?9%LKfCyj6Yle}lhg)UuWtdJyc45Kat@+Su@+RE6K@pc9MF)EuR$FvtUh^ZM`wLD z#I^^6IvZ?G&EjqYjD)OKwqI^mi=Wh(VkNQ zJ`fxWM^+=XOR`rYT`1rAY4tpRA?^G+72w=lV1xON09*s@KtYs;2aisj;yw=D@pv>E z6`wsS3=E17u=@rP6HvVPDqW1yPtLXz3Z~u>{=Xk*GJIiyGjM=$aFsM<78doFItx>9LYT&?SJ*l&pR7zN-tE?g~ptfz5ntN_6w}XU{e?o zYGOX>Yt6UmXdlwIX=>?qVJ#@}sW->j{d-LA0I|63!Im9r7?VUt7AI@LAb;B-Qr%G{g9J>5$U)YQr= zpHtO$$jW71&W5_$jsGr=O6~h0LI+d(+JW<*g>;K7LP=5yffe83fmD>|K?5=-i6&h+ z*g=&;>`XCOSzF@fn-e1=GXx_vq#nFx5YYSw!Thi4CdHkRJAZiJ*5vJ8g6xEN9FTo# z7!EE;@lj_Gku06kaa&Dgnu*1Bt=lqr%9T@ z1?WNNlgMm>>&WVD)hGo)eA8^3BUSH3$pe;lQWS@C7h-=5d{-%CY<~X z;2Y#L1=4niDL^T6tD^@>S3OVwp;p4==*vyBkccg@Ig!}yHJiPxpL~pkpg0XpJ1%Zc zw3xknJ&pW;qGA7WJ`3CRpL(Ew4GXb>{uvzG$h!C-g5Vz6zeUvP+u zzr<>{w6Cw^9$eB^D`ZgEX;E!KdZ$vZ5vk`=!^z}u3LXaH7*ol`UvQjw+>G#KZT?j1 zrc~Dt#W&gKI`mukUQ9=*&HHvI@Z=Ww*y*4T0+&^@Kkz-2DT%}!^c$Y<_OIpfx7);kzr?~s`@Vt1T6g*_ll)pBSZT3PIt=X*$}l% z4LaJ{5u0(-CUKS|YP*d#+S`;#ZJ;R74(x0|tyZY4BHtY5YSCkJ5q9M-NbRGL5KDD0 zE=Y|-*3j93d(B5g!%{1STS{7RD%Z-vRgE))gT+lP8VlMH=3={mfgxrFYB8e%qJx$k z{yK6LAmWZE67fWQD86&&ka*e_v>#v#HR`yUbtUL^@Wv+-t5@GB{_T*l#cmj4H|gra zVU?bb#fLB!H{>G8+(xS&ww?}JuVL;@ALKJi9*PKAiX2ps^^uH|_NRyiinM_EfRT7z zVWMLbFJTWNY)Tr7!KKKg=fOxq?dxrE#@Z{DGKEa0lhq=pTtd+)YghRjQfnSt z(`ELn+GUZ-1gpevIvMU#RtDlO+ee{_gPX*2(#P#dz1&czGuMIKTdJxoSfA?5x;ld# zUaVe=PmR1|HlMdrqf}{>)=Hh#Y>rwi7Hh<8w(2UaN`%nVRC;}O%mua2;vH5~THV}x z#7mAfCMSI4)J_vQ%K>Mg!OZ!(mV+mkq@qC4V!;6u#SwN)9I=H$Hg*hJjEvBC0v6IW zh{)g+F2Sgrms3{uKEVCG*!M$6iogPtWGZKuLRQU?rWs>N_Bx3XAa!E?W4^KEn2#mq z=H^UxJF?F`?i&>^FvBRf5veZQ0={Jte9OvK$7LK(aw3kLq|HqMWhi$p*km5wAcjxK zk5~N89@CjlIuULDyfMh>;NjX0Pgq&MaOy zkDKud2KXyTFRTbT><_D9oq6S$lG;t z+sM=64_HL}0ZEP+stk1Z_dn9t_h^6r3+%;5ARd^bUxaP8z&qnPM`5D35>G>MS4f9L zduwT!^A0(jx;udTP)otXyAv7(^q-KE{&~9Mi(sK>ox!K{LOPQXO6If|QUA`GoO7e2 zum!+6?Mx*Sll}nZIS=?J6UkH}#qk0*^TGjXzX-KAA-mDxX@Ru}nc9_euXzk_XSo7W z_Tfk0e_imd4Nc-j+ch6iRM(Zi$Eq@x-|*nn9sQXztA(4p9$Wi%D)lzyfUT~mt^Ms| zUE)ta^dXGr<;w*b6=kS^bkl`hIt6toN8o#-1FIY|sJdg2mBsWb2FWam6cF~oC}+>C zZ?IN;tYX7wd+zR$?UnbwQ?t{`xtk5U!}VH_^Kwchz+T+9 zcszOZ`THY}J^$s*EGzqkcpG@0eayP!$5!#;4)F(X;Bj7tBrAo)AM-Q3^alkS_#`lq z^f$u!C1j&RD!O~;q~|1A9kj{x4A7bWTC%gV`)0vj9TJ~j*t=(;v<__Up-+Ok6Z{M{ zmK~+$9bgx!sciaHYS>#a{Sx~a`bRuxULIIW6q(hN%$A|20inD;CB&GjZ+Cb1?tM&E z2~c(K>P1S##p8<2v!9;5K_R}`v+G*%l=y4KwRiXA+wlP4)lVEk6>0Mrq~a4NL;Km3 zV8xfC5>(9aB*lE>>yGlXfHdYi=7mNx_c9X7X|TmC4wpt`j3bzU(^(XyHdjXPj!fXi}Y3$)kUPR!?Qt9q{@Va}3 zj`*D?oKjqVyX*#G40^9RKy6iy>&Ffn@>?#$Lgy5ESPN8tU<9} z+iA3F92qfWh-$M6{d$?vU|nz5uwhug;e7*ZEr-clV6|)1!Ms|Z{%IC))f)u%qpCKu zBN%j;+p79yGVxz)JIo$^qo*DssP)PE$7?ICPA9v>%ZzoMmYy#wyG=+7@5?=pv|+J!dfp?XbGJc=g2$5I5mqfLP* zuV0Jc1D>^b-V-x*F(zK_I=!Zg;^cIlzVdNu`weLOA?eu|r7WYm6`uFv83bke&UbR3 zH{{Al=04F;JbO}D#r}Y2kynP&k-j(AQ}&0`r+H7QeXQ&wWw)`v=j{XcLUpjer{4jA z&*dJF?t2*by)4}aQ6Bp7Fn*?{7jC0E&!W9rsuR|1xF=udSrke47R@u#=(*4U;uIYE z3O#A$C0Px``kherbdt}UM*(LT*hHvcIfTPJbSv}p1xb0KTkzu`99oln@9kZt3v(oT zn7d%=y8XRLv3bsFMUq?)3`x!gIgju#<^n|}ChImtg>&&}YryW92iB=*Easfu7&W>* z4*b(@*JC6Rw+pT-1(~4`j+MJDO+H6MllVjw0XfA7uX&n{$)@XN^}kU08X{(m_9ghx zzG!tGXm0hb@%hqGv(q2<3RX58N1#sjqoJ|N-D<-_HnM2coKd1a>xesli^}>vHd=0x5VllzbLbZ|GTVl!Jd^}bTiAD&z z{WYOO;u%U|{#ODH^Ghwz5bPJ0H$w;l2&h&(yC6Q5WnW&YZd#Wl z_>dhA=1U>3Zw@S1frkJ8Bkf(_+bYjAaeqg$B+Ig_nGBjnWx4*W_rYXa) zOgE)$OKFD&hGqEmPY(a*{XWT-Y=<(tx}0-#Bz^bGdwt%MTMv$&x=j5iPa&LX&t)sT zFi)X)o$ZRtPZnqN9)0`m+-2&{p5!wO zs!u-dKe?aF;e!pyK%RR2!OUPL=#pnbI1cR@wm7Z6bpKFa#)EJ6TAdvUQ!3KC?Z~#? zNXnGxa9UlK^ibMz0a`OZbk48P*8wk}DJXi|24hfXPlGU>3Sd=#R;i z4r3O5hWM0Z!Q|oAvu5FL=mpCFt6RxNHn@mqI2Sp(BOkA_4Ki%RZtXs3eQYs~tMA^8 z6pQx3$NKzRrfIx>{1(>axANM8rDUs<&#_=X#XXadFOTnte3OAVh*mt4%{Anm8P05n zxCFuVa1N6r5pa$P?^8E!?;n6x=ExKv2j0q#@5Rry?;X!}g}aBk!;UZjk-Nj0-I-8y zM81DCH+tXz0~0UySE0kuLCRkbnNKs>gft)oIUbs0D0@ibe8ROPDzrBWN`f!oz&5G z{q3Xe?W4C}-o?Pc8vv6NpEnQ*9^GFJ#9unX$b%jKfh1Fsd+r>kiq&=`lyY z^j{-W>67g@W^R}qU%7I8@`lX1Pkb z{AuN#E1Q;&h&Cx1U*v)}zYyF?ym)jmhIwJumaJ!U1(?3_%24l>AsnxSsWGpckh4^B?c7{- zDChzj6;?J}!42{@Z*hZ-nR^(K2Q-27u!*8vT_ic40J!V9a|S(N)9B=ax*HnH_A9S! zx^e@RZ^M=Qy$~hWdfQD^=_(UHz?hVUYq5|Qx3?Po3#(BCiAjQ}#@Isx@B#Gn(@%f+ z^waP2Uc`7oM@kQT_b=bYYkz6q&5ac`XgI7qv#CLGul5Gw$=Nmys70!;zi{v%UePUE z3a>)iYYv`0c<}7<=IgF&{_JP@k@ugl-Le5UZ5569I7I2-1`3u+)K+Lo&@+qPZ=5%F z+554Mj+jY53ba8303_dP?dWK=7`Eyya52(bVIn>!ieq0kjvBcU(gALdRPt#Cf+(PA z5xSN$z~{2C8vtugc4Xit2rm~R@djaW$KKS9o3W|(G){t;=FQ;Uk}4A|_2Y5oOBRQo)g3lsk1)xOrdy%h^npPOqYa9rR=#I^(* zFSH@odX`F1r#~)(J+fb^&4!{~20&1qEEO=m3tRMHY+Wq8GR(d?C-)=3Ha_-6Jyd+H z60oU@R)jq{IoUIMU|~hrhP&<>9qnFF5vqqsn^U#L^>85&1Fs3BIt!bOy(XUtrqe-_ zt~=t-_z8H;x-i>w?N_xmt$^;mswvy_lLfhpb>$xHYgd4awP0jI4uScK*$P}n$Yjy$ zaG@!u0sz#PjIVi_h`xk03bKH+Gw)L=x^u8ar{Umhb;(=U1WJ;K_?;e6GAnep&JOnd z8I@o+Cp? zuENDiNZK>@8UdpD&?b>?or#(aVZ&n`D5G6IPsYY+zkMi?8HJ zHII03aC9{OCEqtX))>QWxCC;;f|DrT`K1KvCK_yvtaL;fuS%(#UBS+ySIRHYg$f0O7l=k_9 z9{CtHc{oAfhV+9~&%E&T>OlPKPk%ig$e(cQnc}{zCbWb3s{-~8&O6e^EX*Xie;H(B zJg^;NCz0(&D<&y>nQB5k&C+g|s9SN!cEsF7>CF3FvWjTQ=GxkvTl?8Hb628V-^bpz z1ic5&1j;8gB?2acLSz$%4~M6xUpjm^G(G+6Lx*q-@guE46|>`?FcP$o^$?c77yCdv z<}Eq{%qJKr5Sj4+0M%h$4P22~E*g8Jx;4IB@>eTr>LvJ%D*|!#>ENL~i8m&@-q_PQ zI+++urBd(b831qryCmgP8qHHm31>;Gd{U`&2jRmO4_N8XIe;Fl3RO zm)?||(2lq}W7Dxtvga61vu@bNo{x2Q#)f%p6>1Y2n~iA8Z*$~RNSa|=7yrSw3;I z*u*G`R>b3ivqSVCY%h7XCcgnT5q!Woy@B&E!XNF~omySmST!uvi~>{kW(=;md2SbV zy=;1r&~eW*7_%1yaSO9}G2-j-hbIK|)x!KP*4F`$+EiEnE?H?e`-Ch*tnU=rY-t&c zk1k(=nk30^q0fN4AJYCBSndj0|H6V8HopuT-LZ>de~&Lh?EoK}h2{CXYp*3ua(lj5 z=L)4NZ5NKMd)ZQ%G3E#;YGE11p@T{r^z+)Bbx%)EtOPy5DLKb6q5>i=mf#Lkn{`_iocqdNEy!$5j2Ns+C0@ z#RN_+k`?d9iId}@?Cymb=DY9D?8JCe_Re|v!utwvGE7t>Jg&n!{SJZw z5Rd>nMuF2ka6q2go&pr|GjcDY4fO*Bz(iO8@;lc0>npx_)m6+SzmsHy3^1=vK~Y_{ zP4hWlrlyyz;=H<{k^fo_py@DDh~$p9Tqd`3Eg#%spS-2lGWJ zsc(JRiahO46i)#ji2Hw#|2IJac-25^^r&oJh?u|xfE|UKDXzhIfjb~Rkeen>z+PCV z-T5rZm9R8jczN^m2f>(h=p_SS+x1$jB@HlaN3=IBJs_6nVSr!XJZlz$m8!j=p-NZn zFsrL<)~af?)@`ZxznI6Jn`^UA(O#tAFG!^>(_W8rd0d!F$u8SsEL!%r$ot_J`x*B}mI@j9yDeo3&v$C6xZp9W?kuM*qw!LARcOT|cSLc7TP zyZ&w09i?I<`Tv-fAnY$R>T_*K{v=CCo4HC-&w^YkiZL)tv>Zpb{A^1CniM-mbzU)b zyD(y-2x$562IqeE*`M`Q+p6(m#?m4n7TVoAv)p13RpsR<(1~R4?Z)bjy?y}~1{QTW ze8#MB7=zyu%_A|N=*aX(<%z*jjb`i6QQnakfWokuqw1f4tIlTfY1*o_YqugllIsXr z6Y;1n*hv6!f+02$)L-+Yo8<*6!wd>A3C{*$XaH;A7D?CL-90Mn;G$_^@8c-n2eC>v z6na)Z@3aQpDG!8AKnG_(tBpY_@?DsAKVGwBNevsRS+X8dFuWjAwwVo;8cn6aY`Y8A zv7+CFo~d9Xw}|a~fR_^VkYtxn!U682)8}`vVTa#80Sp^BAMWX4r!%mA?sWQmPIlVi z+v~>%cDi_tRdO$bddQS8wg8JaYo;*k$EzTIi5ehDj)Gjw1aoAyA2JS3_rkvz<}OU0 zPM?#{3-_nfg8H+I)1bC%E2ww7y{pS^2OYn)OWS#FSh{0+Fl-5_~AP3x=!u7t?Sk`*V@;e!xSUBMYM~7WBtrhy<`v^$BG75C(wo^av*RQ zHO%>IyWekT0QdRzF1w!_zLZo&5HiW&vmu1 z<{(>VtXnO!^ylKbep2Cdz^VYgn~R#2q$MkiXM|0M%jb6n9hcsAKuRQ89Uxvx=f95d z3rmpXO5;1QBl0xsL8xu=kej3+6@rCjKie-y+OBGcv{R~?<-w24oA(ZqTQkTH%>}n* zGr27n0-v_1xfdCj3^pxad|vpGJ-Nf3$4)wtqNcUG*}L1f%kPNz$n5WS~x1yj}B6_=0TB^5~yZ$JD@A@^@1CAWgi~J>z4|vqz~%`q-;t5 z{XFCUulRiKsx@n3kZ{em8VR@N@}u|#WEn(dR8e%yXjtzR)fZLzl z`F=W_#%un9ee~#r-_168hMHmd%f?o&T-M(Ho6==dzBUXwKw;k_?z9#33B|oBo71}z zrxx%Nj$P@|JByVvdjSwW!9wv1Z!`M1xivBS^;{@IB~X8rIfF(+Z=XS{8h}s)e)~Pb zJ^hUER);?}j~?|n;*G(XUwWYb;E989q3?ItD;0_ci&o*WXv){%Jt`ct_X`(wk8oD+ z;35-?YgF9L_piX=A-(A)ME8NeW2tD40EU>+YgISH*^IUaTBGAwq13Qg_2L8JNW;;Y zRf=6ZA%b08yW=AkdUUd!24%zLpjIvevJeGywOLbNJOcT943uQia^%k z?{R4~O2q0hX$)bdN~1R=OnQ|{QYsOdNq!@o7*R??#TYotPKPtOIx>mXevJWHH z1TT+@bq7#u=X|O;5lZX!-1;=z%R)4Seas(E!eEzM@dE9Unj?v3P}#7%ao0UK_1UbX zSV<TYm{1Psnvq;ux53gt}d&MwbYe2HvV1nI==Wf zH#u>3Htjr1!H^Igi676+y5r&EoIB;lE9j19d@6m&qt!@=ZEkXV93Gw0VD&ildY9W` zQtE-p?Xp<4CP}OFgbW&AChE3$T0MBB4W4kct1BAz7#KNx5DzQHo$x8i%54b01Km>(>;$fA~ z(@(;PvlFEs9OeI!AEzJD=b0Izf#~qhFe?@QX0*2pTAuK~%0NA1D?kKjlmP{VNiUU> z)cPk9JK&tm42c~lP|??3`(M~;;>45h*bz_uPis94Lg&`#LcPmSKT%Qg*XQ*^MTwsS zz&uYM?IBsFrgA~&6m$|4G=;7J^^Z>=)AvIMgLog%#oz+5H1_Xb6X5j77a@n-h|vO_ z|6(4BL;_%sncG-?1p8TpjC#fqM8K$CvCpIK`B*}iPX|$UM9dxn#{@(s+KOWKoZ`Nt zLvy~Pq75&fj!w>&L_@j__!5-zk<4)e)UVCadt50_6=KHOLh7@No9V zBa*q;&;wFrO?o8Nni@%K<}Ux#IuwfyjnRQ!nZS4IR7#DX&0WG2=<2bnTlj(Uo|7GE zu$Kc>1~Wr!P{iE-)nYJE-`OE(_vXrQnd1B^drcOvgL6f>Y^i8$3VR6^=)bb0!UkED z0(xhnk05)_<(|9s*5`5%`|d=1;Fo_3n7^5slQ4NB%#jAso+4(gS@_YY%dwy~k|j#A z5i4-HRgLK0wxo2mLH;+5RV{yLG%^h?ScQ?vzxv5fUOH#d-mhZn`?Z*0vzIrs9XH=h zZARmLE`2VoM0$(o!JsE7hjRMzdC42Wul$dh%V#OSwd;+Y7cT64gYu>|<{`|172v2U zz)cvzO>tCxIP8O=2tX>|hzW-9^*F;!AJ<$ne*D>IpL=d}bgO*!+3~S4rW})Z@9piC zR^0gW@$sK8ORZQDXl?C>!P{=U8e3Y%T48`sdF@4BeV`tR8Yp-)mzgm(LHc7`ukt)?@#ryV|}mTip?B6`23+m&p+SK47gEvP~E8C z>yRJC{RP${lnf1xW->#7m%3RhlZW-}g-h?}BybbGcE6Nk|8k(?((&4chFWP0{h!8i z;s0i?xkL(JsECUs@Lou;EvmUF<@ppZgxVY?_@lc_jyCzplGJ5gTgbJ{<8Ns2dm>9h zZBk-3JLL5-Ec6u`ZVgQ~p3q_e3Lb4DR#LPBT7urtR=_ox6A4X>CO6G6_>T0ZM}|iZ zjo>vr(!C=pA35z$B>bnLGxQ@6@1EAFEvBv4UVH6luIL1;Q|M);g7u012#{HgDjPm~Y zVbniKo*IY?h;*Ak@&UM<;thfv=CV0a295$}wM7Z&+^R-&3_>ZWVMn@m>Idz^A9PE~ z@0`;mGiHoH9^>KfG1E09lXs^z41Iy9bZ%eW&Pj zEEL)sekD8@8e*^h29NdK>+`4X2fMp}(}M$_8~Htpd%wXQP2|D{8FKNERSayK5$Xz; z7+`F>{D)0=41W9D>}>X?RjY2w{)nAjH8ce1!AZb3@7+5%nBBf_JS$JK@ZjVS>O_5d z5`7xt?FN=RSpxtTyvg8(l$;3s$Tgtxqo65fW^%hawv9YKGI|uYHCpC=w2tBTO2(?b?ZJZxib!qDV>KoL#ZXm_koxpK$fInH$VVy#`+9Xwz*8)BLv`Gu+R@p0*!m(JGK*Vjs!HF7n3SKhdP|8d-=^&;OUYOI5xIS6$Q$^}74 z#UZL0I@Ogqy{VL+0=}9| z@`T=GLGaJluFGaK%$Zm^5=f;2Bf(_GtRKN2a4=^Uz55L##a~9HsSd(kN|c{g0>BlZ z^l*&0OxcULP3p%IUz}<1OD>b;+$e>mg1^(~()RYH5OZ``U~LE_vr)a}2@yqDtk?g5 zwljh^g6?^ia%hBRn2e6d(ST4ptu|%_APn%9*l_slxNBQmVoOGw()Hfn**)oJ%Z1P3 ze>}TvP4kN8fp|s7jVrIn>&^1m=NgJpTwV~3A;f2^nw;$dEbK$@($-ehz>67*8JT%; zZOghAyqJFFnmBzHO~l8_a~Rup&c_v{WhB=-facC7^H_5-BOR$o{h# z`4tw*oMo@^_7>P$m7pz}1a_5}?=)f{zn!!DRSSdqcykRHxoR@BkCQQFI|JwdePE|o zU3VQ`Kg`{l%iVhL*0pPI{lQwCbMEwKEloN4oU6AbaKTa|nd`30upf9Zh3uJMC%f zOnE%1&Nk2U9=h;skqRYBp+rhvBC$7%HIq=3z%I>6Pq1p0Q@dc5S($G<4BV2>u$n&9 z-+$;hnNG|5#Kqy`gs0I0bj&&e9x>1*~(BYYt2Q zmCN|*Axl!%K!*g26q04w5QsuJ&af%_gC>L?P{=4qFf6HBWZONY{Tk$8l zOJ$_B?W8oU2*3h`c!C75?SS=@SS2xp232ufKMWx%sV$BgV0_u&6a06^hKlPqeqNtYvp#&QP=;?C*?rC8()ikoUd-wt9&D zPW}aSWNzqe3Vd@hMLZXe0lKRB^0IQs%OGC3Y$OJv&oNB+8(5SDGboq=O@W!!$RBoi zvXGXGQ#N}dd!nP%9f3nN?B7qZ;_w(PIpxPv*%0bBf%O1ANYM!kQWZcdB4-Yi3oROf zXb~zW7Hj+SiB}UG#;chb!T8Ik5oDvT4goe;r`1hsOaT+M&<+dgO_3mJg4V(b&)Pf4ncu4T=hB7rXroqA_EQ z2Qc0D*^x_c16CamHd_vG3}%pZH82V$$3U~!%B&;LJ^r}-HXWtO)2HP#Z=F8Pa-6Rb z^OVvTKBI(xR>o+q;$<@<E_~^t$`rI)5n$w7S64cDc$7Z$+U27A?}emY^UzXb=F}^9K6FhJhVvX+xEaJL+qSmC-^P z$NBB`38hpQiaUGp2_2U&?pZNd^3D3G3Vl)xr6=-zO!9{LZJRDz`)Nu(+vT$t<^LB| znAh;mPtpEQh$`d<%Df7pJ`ymfgzpr``GNcsdl$L;SRkWe%}|dp7177BB*h=Q;S24C zs)xoV<@YLTH8?O0)8h&Uwq*VAM3srHzoCLv*vExs)qQEPG%jd}vb}!ir;2^&@4KiBHcf##D464$> zHGg2>)X;3ePE*j9=4KKa(?Uio7}Q41U_?{#ErC5zNAJ|v_xJWrZMb^Rc zVe?bqw6Ugg#q4%@7l$0aPj8)?vhK7LE^?FoOibY! zQ}qlrJkYK${V{)wf8zJ4Ttq(=>`usYuOL$_P*5w-MtNe$mfr+vBP?KQVDezUT!^g! z7(TLIxj;i0agXSLA)9}Y5gLDB7=x4pN(r9%JNz1UPjm~wCE>ptEA%CEn#9>L zHhaOs&1-U>U9+aSZe19Kmpk7-Hum$+fBxr}IYOp5Hnt7#vC+{{ zI?**Mjr_%YC2v+(fgunj4QUm5wPSsK&fn4M3()b_}0Wg6q`e_ zfzhjCMKqp>Q|gWDnXo2Ox0G71KmqywjBjgK*S0RtS$C1T?D$y^>%P9LYb$_Gi&q$) zwy*^vAJ($Qh=kwGqBx@sQ-)#w~wIOwe34pLx0*)e(7GX35w-RUDSljEbyIqp} zru=62zCOLl{%peIpG*PFIvjEPoUQsyu(i9pN55sND&NgeHvhzlAgb5@_yG%SG>n-2o^;;JU0p2=Xf~SE>(P*^ja= zZph_yTK>eI3j#@dv0_Q11Q6qM%3V&MHN=MdRfdp;C>ZRDwPf_?lv6 zTh1fAK{5$uf;UCM459(MV`H)fek3hwF4>~(l0=OtFydg+nPg~aJo3DhhFq>Qx%Aeb z>LV_Tv(=<1$!VfK5nx3^ahPm zr&pQu@Y6aNiM#_ferF6(o4^?(%BD#d8;Af}w_``X4r6HBv7&iU1{B-?i697Ep#jRX za-5Hfhn&Hgg>m3ll4gr|$QMRNwr(96ncTW{3$+dLbtc$SJP-K~bpDX_0JDJ@eYkRx zQUFdAJXj@aEI9obOnQ@vmW0i!;5r2e6#36!1p)C88JNIyA|Q2ES2y=_L_30+GdSjAMwW;*M^rKdhB2@RGw{UWh&!x zUzH9?Kn+n@ZnSBQ22&)^ZqU{kl$y$Nw@O=X23AI8Lxr);(@ zs_}u4J6}JckI`^%p#lY(LVrpMpn4!~0o5Jwqr92{-W1Cr%fZL9Jf=Co z*mEJDYbclU!%ziryRA-lC^l_(+C3(_q|^FvFXXhsq65B0Cgq^iBto1IBj}cYbxlQs z(^8>#dfm%BVY^eItTZ~kai_C7p{uc0>tS$a&?+?TeMM^zNpayKMQ?hN(K1|s@up`W zDFHQj{Nu9ma0oV+-0m{8o$-&EFo3j}d1-i@u^U675P}FdW%08c<&STqOL}8871lUH zF@OrIk#sPe_a&uF-Z4qE6~R|veF2dIwf7uABzs-uHn|M?>9o!S#yHpS`BU4LleIdKlvaD;6$GTn?U?0dgxd$RE<6o>$ z57&;gRYz*rPpa(Rbd_=Cs@v-7u3XjB_jv-I$%LQ=C{uj=Z;1JD4Y26Uu##Jie)I=0 z#$fD+F~^Ou0xEwX2Du@ON?~?{FCad|6oL;Rm#X2O7@rwFEY*G$tMsV!nksW@>GJmG zh}NpsSFin>24lIdGIHzH)kagzy+eqW;r0IaWw-D0*H$3tj>EhxXpFm^lEZ)H6+^=h zG1j=OrgrI2m)>YI1$6dGtD>>?_iBy0c6rmXwrlq2oYyDPiT1e1>{;sc2A#D=ol;S* zTk0QQwti`lvCoS&L+p#>j|U{!hH{9MAlLt`)OP9bIZg9`eAU$hXac^z?8dq^2&oRF zL9h?OGR5LJ)HDKk^3thS_b{b6${+37%{nK$k1{KCjYqqWVm&JPKm5|LvDuQf&@z5&8$~~{Xx<~$q&b#*8iu$JZXTa>LD`WljfLzq>>t^v(C0O2DH zF9-zG%}vN*{f8{bnCs$2ii<$a1`Ca#C1}LBXFBC!Q5J zRD@X@8QA&b_DH1t$94W%vE<_@zsIfnxt+h{gu;ZcBpk*zT*MF7Vs&dS%b*o4PFSy%mZM>5&* zZc%x|n|A(_tG21yYOQXnbzy9g&Ry)SwUDDO1I>pu&Saih@_=dOoTf^`(0;BO{*C_4+cx|A8(AjW)HlBKhK)_pjAY2%a3=vm-FZVse%Aqq zAj#oz4BqX_nuFRZDTsM>&-xvyQ98V3cOTLo10RT_SWpCy%;1vcKd zGn<~*_Q#wQEyj7y>2n|w@X?Z<0NU|t;S+N6>e7}s7@baUU7bms{=WtNAjUf(s#Dn^ z|3qWYZPD|_xL`n3$=R}FO$5I^hrf&>x6KXmCk5g2ClS)cb#Xp&_N6!H207D<;SW(a zE*y`vL;0fmST1XjJ|jI2E&j%`>&nKTE( zm57zaPuMZ}C%-M$4&n@!WX)v9t9D707=Go)l<*)i7w%%xVBpaeB>M@3tE0Uan56{Q z>j9aYOfXYLy~SEtU12mC0IDvjjnxcM))fYQx!z!|N2u^Suh02ydZj|8w;GJP`f77U zxn8YtnEePmTcMJebgv{yo=`>H;|Z!`GxZVGGLNT4p;+e8NK6mUbB94;{70QpGCIx7 zsQ=$8efiQ&OJPo4p{~@Kn(k~e>MB*z-(b70^CKdv#_Vv{+R8PGYNfF?1-JWpv%bO- zbT%(Z)!V8Zx=Mw=!BC-Kj=CjAUAa_Y)%$dk>R-xJT@gija@}%CTHcvZD4M;ENku|o zsWmEUY7M{~HcO`3nq!gzfVi;fW>UE(Yzl{s%T+`M{(I-ZtYx*jFpgk9KNrjG6Xw8+ zCMS*l`^8L12ea0&Hk^uRLzWH#{JzW-SXt+#Ij~Gjfrnl8u+ds$3fpNZDq2g)6D>%T zZ0QUD6^L014j#)8{1o}h1ECd+A}|aKU(TNdGg`?L^J%mWw^MdO2s?byO4k~Gd;T<# z-_sij>l>Sp(Rd&niG)|S;|ibnT@(oA6qtV~vbl!D6-10c=LA|r*eQ|8Zyd#npXl%B z!S?zQlN*;O`lXI!0#~nX+?d<}Grj(s64-PFeI(LU5egZhm;}5lq3Hgk#9w&zK#EeO zXnwO9uy4GUyyqVl%YGuZ1bocAmv32ea|UkI?+^MmrK!6IIQWUHVx7KudO!Y#e$ z$xzoq_YLmc^C!2sE#FK_#A^jAp6cSNI`$+ z+veL2S!|~%CO^L26f6f?`e_xWx#wV2sjlRUY@Xx#Bo5zST$EnpdJ&^TY; z&Ip8)fWP4453a(ZnvK$iFtGA5KpFY$e(?G(o$0lHe30)Gqyea4|h7`>87wa>)py8)Qzd&SZw+ zVfi9^G3=BF=sWh5D};O$W#f>Qy~AZ?WF1OlEKX4cXi(K+rTS>gdu(dUi!UltFTNO+ zPqCqwUXmwBy)5WCA-f?tJ19?hkq{0JmDC#mNsCf4z}Kx_J-Ygy)#Kk_N1DEVkNj^T z>BQ9Nfdg+Jmz|-<9%CM+LqTXUDae7`+!}}1l4`n$BnYUq4eEc7GzbzO_MGceh=kf= zTqHD^`O`v~kODd&EqJq+z!`kD?0VD}d>0H&NXpR+{-3yD+G5Cqh5+aI24$f=i3hkue*CpiszmG(WoivmI#wAL|~RtMPDP^2TA(7<=Zq|@}8pf!*H z!lc!!bb6D)EhQw4#$a-%oK~b^a{6Lzy^r>Vov|ak`1t)-jH~POGFXgXqZe_zCPYVS(85Fo6W{VQs3)n@0?FbbncQfE77V??s$&=AR z`FYkss>=QF+9Owkyl3!8^Ak@jzq+s{6xKYfqzq#d>s>i#EvQ3a0*!17EQd6-Q8J;vQAR+&oO}OL`#@x?$ z4w`E^qf7N|-f127us60N0f)V>wRd=zrA>=6QoD#gu7K?Xt;XsAz%8-OhZ#AuMu8a57w(XVgU*GV*;65n! zF_E?c92>9+Nv7%dR5J*8Y}n3Vp9f)AqV-EzR+W9eS6ipOAsdOvuYR3{qLJ(k+Aq@m z?_H_Yjm_#+I_ka(qGJGo&x<1AWw&oWp|;0By4*$;DX4B!@9DRF)a=D%71| z>pE`j>gh>C@#=TzbOZX%u3J0$4omlghwI)upglL(k;HPTyn(`O+LrVcb557KA=P)D){!jm=^u zlGmEIN49~)CYe(;Q~6hcECxx8ui-E?aHuyH)<{-en^qNyaCp+KL)xIBQ>jypAQ&9K z)@g7lJ+OZNRjY0esVd`DdR3i5s_HrLxBJ&$xYwxG#TAMx)YUqEsaE3>#p3N!=-+}q z3v-u{0to__ES?IefspjZ@ie!XjTC@03>zOPrY^k+SvJgjpe3AWZzmWFabzdB){3l3 zNpmIvJ!iKRkZ#7@%~BiWXKp+O@fxkn#GVov2sRsQGR-EEa3gF7)@px%m~RsO(%Me* zD#60=O|(EV;jri|7Pr=-jSQ#oF{Cv_GzNz<65`)j-B?#6Lv4C}FsL;|RR)I?X3%u& z@w%Ybg>W;Xfk$sR9JE_0yu8Ms&;MMfr-UHJ4cd`~)upu{Au?&_{rL#`Gl47c+RWHk zzKpR}2A3!1lV6t-^5`${Kuycagl<6CO%X*yKC!FuAF&pauLDK%f;oJ_03lGgSa=7} zW~6ZzmQPG}L7jC15zPSEgRX#H!VcAhIQ5o%lC!|^gw~avJ1V;_`V+&$?;Sl#zqXr( z7duUdT^FH6Xu>-2O+0^Fe8?sDhcF1y|7_DLzFPUrVHhNpp;>ep+Pk|WcW z+M8<2q!9;ATu9E_+uG!d#%gDs!6=S1I-8>E-df-Au&?&sDuumL{wU~YfglCcSW?f@ z)K?$BhraqXuHYX92`7eL!6qVZ46weJw%sgB%ZneM?|Cy6;=4s z$b}0uJC5=78xe7&uVFUY$vPZH;e00%C2a>y&7D*TvezpOJ#r&kw(>@~#^GzMeb*5i zj8+?;bARhwzj*k@$jTepHxRhgZ1;sew<#ul?FW%>VGLq_D5^ulBIO4!jwKI0R=}8> zUkP?d+tV8CFooK((f9qJ?@Q|dSomLqRywfQ0Hj04Ii?LPuT*zWnl0rs*5o zzP-3FFQk4kA%D=nefwC^oYZi8Z9&6%RLm%VLpWIqCn>1&5f%?BB2sgy&t$h`@nVl& zC=43ACachq$Q?$v{c_ z?bzNcf7m-Vul@SRakp=r)1?9fkjkIr@d;>a5Zgl`z$d}K!h40tZWt95mXbJPmy_k} z+=9Xo@l@}y8=f=Z(B`wawmRhlG^S_VN@ch^=m^bto_mfB#XPZE{cXm&TEneI2RM(Rj@70&sqZkdVweWC6jV_o|neC_2n!^?q>Q^Zb#2^PNO?7)c= z=Pph|)o~2W`xbERPhk;#$UV%S+Sr%s z+OXN>GEbUaODwBc>K1h1oJ}^Zi)2+8$@}m?0s+{P`86mlvo{9rkBZL)X++h78}prk zu;i_hGT-jDZb=2L?lW$OG_u+5Il2@6+9`JYmY&8_MWy|TC}bl}ZrismtWPx-&1Eh2 zg8<<}kv$wZKk|zxUHTN{vqBObZZ1T7Pe*sJ!9qkNK&1<7*EE1E`qTG$LN5KTm)XdK zR%3`6ENpM_mSoUQvVMch?`ZuKmftzvi!_;ySRZ-*WTrvJoe)?Ri;r5&=urr-yl)Kn zf+m;bH2MAawQ;NNy!ql|y)K`}$yQVuYCrEZ!2FW^vUop1i2KGEcJQJ#|MLFy^ZomO z%d}4vCsvrFf<9VwuZ9gSxG|febZe5|I(l^HmXi4+55i4z7qifgR7!6wzEi8QPb0#{ z{GIyDPWeL^@|IE;m!{qr7L(Ohfl z@zRoK5c017V{oJNrs+@on%GbCwqZP7Y|(fvAO?<8e4f5kYc`r~P5Fv<)W7_N_5KBq zQi1?!&)J={7t*gCJRWX<8$p~1xA!->J6R^&x? z;$f`8C%E^m@T!QB6dt5%L7<8u32qnC$hwu4@dOcDXl(i zg4*0+k>7&~ioL|`K}jwOJ5p)Phe@UNAt;%g(L)GpVHZr!yjiLIUWPwJxojxc574Ux zzS9Qo2s0RY<=@4YteCtg09HtH9>&l?fs7pD3@B&vVYmk4!EWuAU*Q*_ZjjqOzkx^a z1%3pQ1Rj@0*5d(vm&m_BGm%$LJ#4gtl)n)+JP=%=;$CApjs%}-^X7#CK+!`qI&srj z69`IC|IR-nP~i!xyjT8ZU?zV4#p*HLNviY^dp@lC`1Y zp(^S7bE$q`e&xaL2UjEAhpLP}dQ&9(<}1(td_8kuKa;=@3je4|k|%Pk=saMfqNb3M zw) z=Eo?MBs)h5Mfu=CSerkwW(}bFvF}5UEo@wBu;*_qyP@pc=vxwKkWh<@H8AZU`%tUO zA-n`Pogn)oA^jjAD7DH=zlODe5NvXqhJ;{TP6jauo1`RieEf?Yxj~D-) z`wIIoH<6@-AuZ?GaDj>-u7xQjXhbA}Vvy#Ry;H7ezPfpIuw1WFs5bA2f3`&hgCp6Y zs!*24*7yD3k!A&})R%{IT~BtdT~!gkONv07!{cusY+u?ITzzv#=WeHoS*3ElPO7yx+_Q207q8&o zEp2ewVm_5xp^-i()moP;6jgc{sn#j<<=XE+UE9^TlwG+FT3<<-_4-+(XSGVcNoi|b zlId^0Dhk_90RO3$t_cKk!R~~^thbg|X)~_cp0K7utM+7TYzj$Jt(6pOD;w%O!_7%V_jxEeZ|V9@s(+nu3W9ku35RfbJMzsu0UH`fPlI~85Q%P)t75(@3Gc;8kg985w)sPrK#4} zwrUM(NwS&2xLZ_Oi=#SnD6I?Ues#U3+)$;H$|DoW@R!$xte#-9Tcb4?BFRVASJZgq z_iD-k>Sfn9yX?#AqD$RNB2_gGC|VORoFiH%CT)=(!#-JFb~E;nXdt?RqMih-wi>E3 z)jS^c3cCR)Xkee2fV!?;VYT5)lIfwcu%PkM$fhw5i&cgSmqDv^MB#6zR{}pxf-YausH|?SQl&KY^*fxBMpEiq-5RY5*k2Bn#;Uid zd_IF;3)d4B(AG>yNUyW&k$%UnP8}rCL|X`K&*el*H$s*f;MMhF>Z0~uVa|);030(K zEd0rFK&Vl`edn3du(j)Ui%O+;nu1oH4xnMypvejAR()Scq)UmXn=t^ zc~)TSj?>m!0Dr+wpQkNskZO&d1tTu zwscC~(cjnG+e?Tzy?y-A+sozr)V?BrfpbBiP=SUxptcT!6l!~Mm|RMTooylku+dYM>1CA1DoX9VnJR7 z=vHpflK)}QXdPVNRNlyQ@Ze*=odC)7BW(+JMC>|3g)ErMaSti91zVLshk2{)6-_qxIY0G8nZ+ zrq=}2Fx%Eue5FFiukBTOj7KYc$~(9Y5&RzM5Gz1}Tzjn)mcObs@@dpm%aKo# zwg9*U5c4hI&x~fTnLX|EsnXlh)=_Kv(y5Wx_Uw_$cI|pv{{5;|7$jeof6wk% zfNiYw->~|@<`p?M)Bst-21+yuLrv3t_sNezqPua~)8k*fe;GhEYI`7}-xPl4OY+%& z`cKP1_ZR%Y1sy?lr0@?QYJy>MKyNAL_VGhf`0(LN=g|ct%z6kkbdad*-~EnRH-EH+ z$+E;A2Oz5>2*v@tM4rwNR5Tpg@)WGG5#iVnf4D(W69`F>rad#P>2o(e!ETdpVPE}R zw{%75(l49typyf@*OMnb9rF1uGV4XVrqHf#v@0avOi{%YjgtG2{5aG0F(41f&%1vo zpL(v0Y=-kZ64k{3%9Z>m$#1&}IxZ0ls;m*So%|=uy&Nnr-p~j-gcwTBS%A8>SSbV& z6ijeD!3A2NMl1>Vz>bhNk~|HtJ0h`2!b&%Ar^A07C~CRjo7wD?)89dlAFW|muGvrV z+14OJ(aaizfJV>?_De(n0(doICxMHmdqpuzL?6_F^7n%B=NQY-PC$%LfUIOkQ!KMa z`EVaxfY(f=Ch-SV<3LBpfov8YrogwAr-?9NJrJE8M=5twS%Iv9M;fKrkMe={{ytZm zUkSjzQ&eJk8Hxuls}4R+1wTT*FeFDP&K@jB!5SK)EzTe>S^{&Q))8`-}+E* zIXMc)&0f7p-f1avD?WP_ybR6ynT98xfa7EJ3_hX%XzU0%BK2UVtP^90_FGVjfb0=6 zG&O{=u_PBttz@_)d@c|xID(GFk>pZ-cs>*5sApzEKLUXYP}Tl}uX$pzTnyn-JPr#k ztaeY#VYNbZ$Uj;fo|w~Ob-Y5qJ=Dh%IP`yc<6mNHqtUgoZ+M#ZDo=AWtm>oQ+Mu>F zh<{hBkfKLrU@?zvX{9zOZ$UiSjbG+#(;b+X*Umn3(jl0=zY61?N-i|M&M&beUdAsI}LbL2A|MVy#f zJ8hn$SVs!wC8=nsjHn%YU(S9;ZIY8pF08+&)30q!Z{16<2J(3>5*>4R(&r{7_VRud z=_xV3^<{3PNq`JCfN9wvnzyOV3u~~YYjC*d$jQ(nn)l#3(erk371-IM2jA${WwJ;6 z4zTV|D8G`d4FDIHv@OhG_`rDgxT`qXbJGWh7fX-&;PdFe8?c5fC!2Nn)^dyVc4p(U z35+#80_wp)0N!)ZCJH1e5@66gh*<+-9Ja7FS+;sS)~DLuw0iteU&e1RF_&HcsNQPT zM>A2qwTsM?zu~d7tL+UdJoc;W8`~RH`oS zTN~Q7h6*yjc)-19FkQ@-rv(>$UKGo0VNk!>V47dNS9ha4K3*~_N@=&UYdk1T-)sTf zAii%OXI%!X)u3n9RJe6DJeFnE^?GPyc=<%%lkO0feY7sw78$W)6B9>EdSiNcV)*E} z`JGGk6&P8B;EO%3c<2-2#_U=y`DbEBIk@~0968)7I}52d!K%vV2}SiUHA`Ud2VhmC zNqsERr7=Ts-LPfO8#N`#e`nWFX3(){7HrAUTY7H6VzWp_bNNvDNjE@4WX{O}L#n)> zbRaR3Hs`9p_@2kO&IyAl*DdiZleglerb)D36*l z{MXa17p`g$GO7b5>B^Z*D4P|pd5Qm`a39~6w1biBV@pepmWDkI3LYq3#{8FC#`roW z_COOfr5q^`P>_iva3CR#@^X^;O)4hvw{+SUU$L;c=6Ko&98%j@S{L9T672EY+mj9QB<=V&Zm1~dx7&n`Z8c_3P>W|-t zoM9Al28t&~vsmB(m6=IO0+E?sK_WETrQvP~5jnkA(Rc>1SJI60)bd>`Hr>@yqhI}* zTiS48)vtQIs<$ds)vJG4*Q;yLZK!&)vR8LwRbQo~U)E7&X`UQdv1{{cadFFL{PsUo zZO|(!H|Ty?*;lnz->YL9{86l9B#XQQ);&q`T*a6WR69Y&K}`*dKpG=zXs4~ck1m< zos_%%w8nveca3#*jSg15dPhg3Ht4U>)w?Q8-umP|ot7CLreW~x%{u1l*s)sPJv@x| z1SMZYs|$Qu#BHl-AbU@B(V48q53pYOnFFO)0GaOKwhbL?kksYVt3g`DPho{lPzpuw z|A(}Q51_OP=TBR%#p*djiOf)Hb64}y!(Q_78|dqIz~NNWUPAf^B8*}Fgkuvc7lbgl z1x^>U@gM)Vp{3=`Cw$SU?+Lad5Z^lj&gsymFRZ@liD+jt`#+#;*Eu&W9ohHM`*#kl zx*lywb64OulkFxf!?6Ki07KaV%?~DUa{sk`%-$J4d+A*0_ZvUg`ooa4OEr?p?HLWd z^}_BmWM0nqR)JwizJ!p<)1nCJ8`mV0g>xg)!Sqn8EHEjAU4EifvS>6W*cwAyY|vX| z-(!!r$*)BFp3>`|(}(oW8JJS5wOipn4?6&p+iLGTe%uF(&fcf=A;Yru z&&#G?{&F1~Xzpv3uYsspjGsxQ(~oq}^Cjt!=LB^&h*7`-3QORY+!TQ0flP!5zm~^M zWG&FQqc?bbM(Rh&!!t9%R_jxyHgK}3-rk-5r{?DoD9r=HSx&CxHyl)g^TlWp@TNQ` zb_6K(z^e!MK7~gvSjdQ-2V~DQedl&h<)$duFft?htxz8;X|GCZgw%mrhqi|VQJqi! z{ZprMZg*~=knX9Dx8LqK_4dRBpIe2rFj0zAqW*)W0H4LgO(0S7J1wvlg`y*Aio6Lf zJC`GmV`8@p`LOf3sotHvRD3|Q@fyx6Kaa;cv8^BAQ5cEL(b>6f9dGBt|L5n=cj)|oZ`->! z_Py`T{`s~q-WB`q_wxAzcvxz~80JxHN@@U69Tq~o1&RzA4+;aqq?f)Bk@Hx%Q}Oi}{G#jIqG>l8lL}!|VtS(o09>oxmG8a+Jmi zt=Bi>_n*ZqBPtH{q)OpWT;8Q_f$9Zo5V*$=*%tYD;eBh@sI;xSdu+6e^`zcvW4^Yw zZQJD6w{4>|X$`*>X>R6eQhW^ZbR{ccgyi6{Lxda&9y#Iy=u#U1{le^?UWwU+sdk8=&e`sH&?fLxk7P@AS4GmG_ zH5a_e&4rFcW&5T6#|``TbznvVI`Aeh!>Mzcnbs3{m-91P2)#N<(E8b5@gugwAZYHPpFlYPD*mLRV2;WvVsJJo~5Pf4R;5Tx0f;}LsS?q zTrP8n;dEBL&hJ2!b!5(-f8>z}eN5=+=T_LLokW7y17$%mI=Q!BhlKG%gKk z3~J0;ixqhLGO&x}^Xt2N*30KtUUSVo5AN)~h5h)4>@j&Od#wAK-9w@s^Y+R-Eefd~ z$Cgx@*0E#9VBdZaQ4+dgfi*Pr)XoQv?(AloGwe}$ls(!##FOIX`rjzmA2DmN_S3rG zNCJDza9W%BnT9VItZ?TYxf`#Zyn1_X!ZA3|Igw*S@~OX6Y{j!Bj1v-A`qQU){I2_W22;gf;Kr%{}r|A49O3OngIoNM>>pt%R)CC2V*N)XImpGZ6#$Xl4@@kbycftkP{X(elrhEiMFrU5X8FHf{xw_?SX6?xf1J}!aK5H`?iKpc}G ze97{ei#u_L@h#feKq`AsfZlHpB9@ehDCL14JB65{cX$8~M<|4#6jP)Ry0pg^3x%ZD zUVZh_9yS=-%k~YTjG%S$`Bre61iXA&-e~qVQFhPPIsl zEyz(u{;=y>itH4YnCI13J+Vtc%8T-5`(7Cskk9YkTap)Hh6_9+Pyw^P<3(AKc>tfj z@w*51@?cr{jHsgWR_2lvTOvhZwP`SDhc-Zql=2lWdkB#uOA;t0?n zqI!O{cN1D<)7^J(dgX5U+^;rC4{W;o6@ED|@TS~ z{o^Z}m~qqIU;Sz?d-at~NT0^w$G^oo_Ak)fmN7rJ4x~haHZ1c=l1P%#IsA7ZAH*j$ z{6>H3OG&!j`z)#*U7;>(hbH9kr>s+lbod6@17n$c;dw7 z1JlFo$DjHCNqZacwyHB-)N4zYWLcKC{$*K~Wm%SFS&?N~mK0f56k8~caU92(5R99K z)C4!1Qci|RO$a}wIUSl(hG{v}O&Nw#N)2rp9xkOb)Xxm32hy~|&Ga&%W#$IT zv?&J|CMBEuerrj#>=@efTwA|e(%x&Yz1FwBpZ9yei6>q?!M=Ir(I+Nu`zD*elFQG3 zz&X@nFM@TN#wRa20kb{WY6MP@=QLxkl(d=Fo+b8Murvv$<2*1;!x7y4Ij7s6_wzS0 z2qcop7tBtl&*{vY5qNdFq}q;4uN>}Zay585hOfM|V;lU{xQ#hm8X8)hWAsfQ;zwMc z!d#ZV1OKLhqy5YIh+v=VuI_@TmGX2cD9jfPirJKS=_o`BU603#drSfLzHGL7tk$!q zPczq%(6G~&^qXl*1PqX#)1C;MNhXJq68o;ziwsWd6Qj2UhV`9IfgY{$2iazmztJ34 zn!_EQ3xCJtCjvb^0d{48>-+bkeF=^;5H$lgU~bcZq&q>3FydF;1${^9J7h`1i?HH; zI>|{l@Q^^)5&s6g#8$L%Um}4=+@!?Oefv_%4^vBjY*T9AzN0A8wXgg~zKncdnAa&5 z)KU=)6yrcDI=qiKMMo0D96nAe(?RwT|2&bhBDWk~{RE6dA*H)(SaaB>cj{1dM)xqN zy=@?2uyxcpO}em+-qzGSq~}kzuyO{QC6}{R`MJMgAM>^Yn1k;-^$+Rw{JY^ACO6bX zXjhIJr|xfPS2fNWW)CZ`(nmlUG&MD}avkXeuj?dgN0lxUrXU|)J>4j#QMy=S2J)Qr zV|&S}n3}m8K)v5<6!mlS$l0U~Y}D7Xp7fpuF?dzv;;* zKi1Rpv6+wc3~Zg*iW`kV(n0?o=V7SwQpGJeoyrH$Ag6oP$pG87G`iSN?`F=?d%Y7y z4y!9n;(*!sK2*n^Di)<@MwHi&-Phf_X`ehsz`U{gPj5n&&AT1k?B|th0FqhZ2H;V*+3}d^^N(5 z1+#gaN$x=L1&w&W+Qh9OJI2&(d+ z=q|sYJPi_dQr2r%hV5R1>~(I}#C%r2UN##1R$olB-RYGT{j<-qg=c3#=I4~&GmqH_WIEzf$+6=eEOw?;M_O(?Q%GUgcb zcY&y>Rz0Gzwwt@1rnvc>$#f1z)9+2}FWI9Bb5MVx#$DgwZ*|o->Hd38qX(~IcdLqx z*xF@vyurle-}7(d2i?5y1$Ltb^K2cWxf!6G`eBhdf~ighNu))>DR;mMJrvkuYChax zZ~<^3L?(W4sjsmT^K3Rev$u2R^q|{4n3T6GC#@c@nZ0fGgfpRH=r|}ooNg9z+XFsu z(1ww2$o!8!>Y`Z4U2VlqO@F_pvzTwTu$@*j9ov|lJy(+1}?{0;E>XwX1{O+&^ex>MwXAm;>@c5DNZDbN!D02^DWc5*6- z4^dPQvk_-V9%wsR;+#>DSmv&q)aw#%S*^ix0YtOLEbApRymD$IvevyC2?d{JyVE}k z>J1Ros5Rb*H)quwCawc7o%97Tvt~bWzlYUm!1=xZbIx-C`4+tG3tL!m*jAo4lJ5(dn8`&z!Ixn`# znjxKfUaeE5j~1rWfpj*UdnoEPf`kpJe=<@PB%RS4J&_M*(}B#MLS!tH8LN;XD#XDF z%L1Lgtp$E^6KVITEJ_v;1$%pfJt~K(^(-^MpL@*f^(s-{A+s~&p7Qm>QoMd@s=uY> z!W%94>+IFFSYHQzv86@X+Q~>4TkZq$*P;)EHji^tj!isG;9OPVuDj@aljy7W(N}#` zkI&LV_0vfKH{1gwC)u@+oZ3RY9(v!aGgWd$h5k|aC1y;s1CP$)n~3& znPjQj;`^#MTy0RtJX<{7D4J{4IJAlHU{bi$_PQ;#7FNe%j*As{gRD0c&DEDb-{XB;!b$61s~&SU@{ z&)ir-r&C_hNFJk6~l}__fNQeE{zMCgA^}-q0|uYW;H_||D?|Bbw`c4WWjC? zM3VV0#pB^(#BSF)Ww>X7!>~JLPt+BS`U2Dkw6+OO4$_`rSL2LJ78#9^E|4J6KX)IJ zB&HJu>9sVboL$uAlEc}lTy|-^kd>d*JL>eG zq+$3;L#QVkr|;J z;_ z7m9NjxY0;1w>_Jknw*}VyxVLJ9KLrBwVUoe959%cgSdqdN|4C#E9DC4a*bCTiL7!>B?0| z;5Hi#dE_O5P->TWmlID+J5kS?ZMs(ygM*1zbhc)B;&;8xy|~qx@vFK-ouzK+mcRyV zrgI@XNYpYi;%u4`nduVMgL$?JdGF|yk|<+9ClQ1bfS;I_U0j>&;&VaKfWX2raY7zf z))Rm(jB|p8a~(q(-iMxyG#XI!frSa9^8|=p=KP6eo&QTMYU05q{@p*GvSxntMJo!nMwH_o6ty-mIlajpAZ6t zvLZOk;4)&Z8ez*;lrpxaq~e>_g!N6c`Au^YPs*v2Cr=K+3CF(j8?*U07TRWh(~|m+ zmrkB!w;f?e`M#HHqao7G;HN~6!BR@ca&0t_lpKSqzN#kL^Ur@+J+yu_osaENjD=f} zMbiN5{;H}^R9#<%(zI~p5P=aWN5E0OB>YgRgBBf-+Np@)h~S~ZS^&*g>ARpUwP9|z zRj!s=%xsz*oO-H4;3RpZ+5y|{K-frzAO(KU4FB{uGhH(5tln2 za;uMFKImW88=YRim*U4>BxF;e0_ETJW}{ArIIm1k^4BsCq@kr9mh}a--R+Ntyz<;m zo!M!Xb?hH?AjB>m&S}+6(vh61J%9c8# zY_m9CLe-bcT%-1FUF(~hn{P5vsv_@uffK1m9E*IS@u~uy{jwCGu$hWZ0d{t^P*{8c zZTSVKDW@g(mWz8+Qr@iMK01=E8_2=qi#Dh@Xw ztdt&8it@nua52#fl5gUfTCVC2g2l&y8xgLEw&R6Qk`lh8ve)W8m53zSgWyJpCU(!z zLt8)Fm-JfMar^FMB;m0uJMrBadOb5Uqm28Q$M>A? zxgA!#dtkeLhT6ZZj}tEpArfIL5F!ckmxow+QY(f5!4t3%pgS1eTzJ5TUy3aCbi3XA z*vJm%P+BVc`4>a`my5Q$H*k)E~K@1Pp zl|Z!6xAC@V*Lqu<&zAH~{^iC#OhBpPn3w)3M=g7_G_74ou;|2czP50T7sy^@JCMMTVEJc zSyWz!zu6S1R+-h;98`rp>%A6pwO&)LHd%ccEHb1+eFbaIde|LqoU6dsmAy>R0gy?F zqFGu5T5S^i24=$%b-&s!AC}$5n^9*zuDmtDP9V_MdfZUwHviaE_m_4Mhkso8{qKK| zU2|@p8?k0yiF_HLEEq&vw-8^D@J+0mifuq)gWCoyM&zyts2l*%MEd$%ev~k&la&iv zjRs^WZoOPxty2_Vdmj<-Njq}jdjf5~*^qcnVPx>M`AU<1e{!!myN`*>AX*)Gx&^d-C!t^na&{()N8dqLQhWTW0SkTw#@NIB(6i* z>4VdmF{4LATpSbLiDYJP_Gzovj@lr~V^*Kt?z2AjW_pqPlLYrZB7PKeBIkQAz?CI> zAHc$?6fgz>x`$}4GvTSZ+}>OE=H{ltnX#kNH@DqB_C|Xzs~yOFDwmttfY4uW`y0rZ z7UQby*XTgZmFtt-a>YTgK=%-fHI0C78(X#B-EDRzCuephobqHILB%{&iDf?12OQ?F z^Uz}Q>n7)|1IevhlgML#dj*9Y^t2Do;@Y2upQ@ClMJBU2FoN+o9e%Qqlci=^FuHln z56?Wbw(3luEG*`q@0ZRZFZ_*ghUp8r8JusfpuC$2zk!Vxswk(vK#Mny{a-ltKjX+B z+NU-MZLZZ^)UR`A7kSVA^Tj>eGSJ)3MyPYi4=D0$qtHORO?2VV{?fU?8AsA53$IFhZfkBJ|Ffh_*}>FA#T};375~~@-2A6 zdA)K!hBnzmHk{wzfkih=Q4kY&=fR|axB@y5c_-aeY7MN=S_gaqyd_xKOJfMJA4lGt z3_SJn!KV@Cw@-lLl7a5Rb7ZU}&_O8XL`a`mi6`46l)V8w(a16%@+ zs8wcnR90GNYA33~fdJDUG8zLY1`=?MR8SzC1P{bIn^g36Mgj>-y=?Aji*z<~pU|@H zX@^_^$gM3%Sl?1OmY*L#F``|l6g3WlSx4xoiSj{{A=e0K1i@8Nu1C#Y{L#fnWlvX5 zq5%}NJBhxfJ`nv|Pf?{6J&bf+X9JPY`kGrC#>9XJ&s@?&OH)$Y{Kxr}a-B zXWN&$I&|{*eWkTX9Lq&nu3((T8N)#@LeSmICry+?yvNBkN((Cro6@Dg#lVb$7kv5(1k{-RB9UEzoXaakh98ooF<&|y4M#HpB+g{; zBAoWI!z+eEXnB~ROVBS4;Lc!S_xrnL=YqZOm_#XIl( z*o|8^88%tFqX<)}?^J7TbuKwqm$DBI^^V>-bc_Ek)dT9G;)|2cfZy!$+hfBXD2R5T zi4zBQs7Euyw+!()C}b;XULW2WOL?vvszncYV>v_m?BXP8Cx@$ zP8{Z1txCdsgUQ~?;?9P4yGg5>1)*C_ZH-nJvo=@^nmR51jMWCS%hsu@(HeAMr{iN| z8gh9W@w%!M)*`G&HCUz2%^sg1;O+zn_s=m|Id_iR6dwqDld+UtU1ft`rMt~WvJIAu zjYxawP9|a|%d${-b@!s%-8~^Z!YmOiP$xnWQ{-*Ki zKpTDte@zvuMktd02|@hynWv>6zN&0s)yf~(kMK2ai#OxD-$e_2$e|vp+Fi9Dzv35$ z%OP>G9QJB4u@R-^a!=dFFCt(iLI{co?H&o`$wbj>KZOtBiUA@)Wtk*ZUxa)K$YWs%bJ+X$m_N_rL_4o4H%45X< zs=}Ox0)c^Y5uNSZb4TZJtE_X*+HSq|$gQ`&Ub$p(pQn(ElnF(sZsK}_olIUjC@8Ru zX+V+PuA=dXI~|r-lyGFAlf^SRHDx0e6ET?2%_8`KKXBThya@P8$Q3c0C4~BoH=62{ zzT?NGriI>KR2os5L344As4fU&j=5gKdRwb-!laXx6cJR6!apxTD1f0H2nwz9_HA3% z?}+%K>pS!Kc-!rrSBzhA1z_HzN5`j*O<$MsCyRxtvFQhojy?<=I6Y6IB3fN2LS8gUDFbCMG5MVE#n-{Tz4?Bhuu|1J4^_$gJE ze=pC%5>B2zLIK)ZC95c%Tab1X-X=xmER<;)BLWv!%d3oG_RjBALZSlLXN$j_MR^!+u48jgz&!I`N;`wAR5$MwO3kf&$Q$Aop#T2L^=JO2QT@S3;9#5 z*4E^`cmIlYOCFrmY{Y87mJ6@ADteSGQ=Ol<1*lT!c#d1B$Vi3(kcP$keh;Q@i&Yg_s+Vev3~ zh1Cl3e$msyScc%>{}N~kFc1rQ3d?bE$H+e$_U#vlpJP}e`SYKUWann-t4upLnyASY;kx~taVp@SLynTV`?bBt4)Q1H0ZHa zBTKTL#ozKs4gERNmEUFhMdGK6a(+7W7Li2w^VV z42V#1D-{vSOlCZjd1g*zwHHE)mA?e3-`pH~fj%40AR`P_<=C+Sswy`?uNUbB*Av9~ zEFYhcrscgu^orxPm0Lh0g1k*j!M3HCKFIiRNPckk;v9Gg@D9W1tN>FdO9D+z2WBUE z8+dar{Dxk?E`ZgG!E_Ke>Kl@mBBn^3Ww^Ei<3LP?Jf)Gl1xWZ|c|jw!M(Dawa>@IK zo?@q!r$gE7SSFr}Su>~z7w}_>+YQr&1j--f{E+di;LG^>PxfAx$%GSIjjpD^27g^g zzT+qPD^i{6P=5g5@vZlD!GeWcscM3({2pHEu^LxVA|41@K_7x10(m{G6i&cciteB! zCY#PG-Xk-6j?ya2=RSeLC>=4&=J)PJ005+Qll+5u4hp07MC7Yzuz#LO+QN448HpU6 z$B}D~UhDnFX?&$(j*D^s(WCyu2mIP2y)w2Sa*|wF@dL2S;)LXYatFiR0XJh%lY+|E zs^QFV1d(ZLwIi5^?b_~SbvG;yI}`((9kjFXo+LlDX<}o~;}e@AiCy7LO`rDe#Bfi~ za6%w!b+v zHH6zfokpW`ZjZTK8eqob+nvtsaoMQXxLmRAghbT2*8Z>GM)iao4tLVQiz-QdQ#q zG)Yv+9_3w7&1ISvn(V}^axY50uz6+j_t*sFw{mZT-+ye|r@st8( zX@SrS3%<`4@|5Ojc}>uA#x&@{&|xb41_Z?(A|<%eQ2=x``*BwJ*#a{z`vq?NG{K~~ zo>bna%=Pdp%6hj5yc#rNXp+lr3GANpm>O|_4~2;B00an!yXnI*VM>l*EEVem)z6La zOeZh^;hLatMQUJ9gW=cJqNKzIQzPT#n;IA03FXByZs?U2Le#XRFj7 zyjxYoT)qR=4@sb2j2t*Z0e}R;UfV)G4MfGcCxO7Puv0g{vyhX}9ola2mj$%2OBo

}0tGgrDP*`7g>8EqS4fnH49O_Trj(SZ&2P$qkI`amYSu6KKr z&D)z%Hk#G8hD)Q}6g&9f-48BEpOAirm4kdiUF7J13Ix?O2#G^(Hk<_9YAh1n<{j|0 zeErm^pQqbH>m#4Oet$zS|vKjJaUY=}SE zoysJSO}SnX#milTlRF355JMrsi3Rk*y%b0DQl6XPUX9m|nw>6}pO-oJyN}B9UbJy} zUK-E`0ko1@hDK2;b!#=AyKT6br8oQ&{)Tx*63OAD(V&cufKp4m8cy;}(mhx|dbUW& zu&euG&lc958m5=WQnZyd>*dmMg}z=yt>eRVTn%}h5Y#1PF_0I491=nu(*?m^xT>f} zD4U~Mg6Kzwkw2W=!N7@;KN27@xZ+C@eSl?z3mZd{Pe}|*C?^5blj2@28j|EIwc2TA z!ASzj#a@UsI~(g8b&{pdB3nFeTYaror&1fVk_t`@dviww1*7Vlv<#FFvZVKQZ3r4Y+*n8Yw(@<%pFTG$u!5P^-5$BEoW2 z$9mS|37PBgv8~3~(AHR^s!^%6HPx!RY6ENUZMPblv?`n4*x1&fRf8&n=};N6PK(br zc5l8k(VRBb=-Ybq9i3g{U8?%N*5)pQTBq;W)DaJA)M|7~qrt2(u5-6%S%&6%$xqNo z%n&w=MedB~!QufA1p@iF(=&3nITsYJ0F6+}_-4|&Z%3HafxpXL=F2S&{Gl-Z$o5+v zeK;I`_|aRoKQb;wtWIaZDRMW;`jU=fy_Ti1OzI#<6mj7Iy%{y-q3=h$-ox^E0uFQB z665kDiph6*qh8$hb@oMuuDmqT*EusoVHiHIgsn~-r!mM~vW-ENLLQb@k~bJ85Hh6q zAjZ4=(OMrLj}IGRtWNEdN1{aV03uW{>sa|#Z=o<1Ua?(zBDD_5Zjm&&A*MXR=H{SB zc{ds5`ESuAZNwIA=W|M|*(Dya03m?%Kf^(S1h@m=FF z-9JK^2Ossq>{Szm8h3o4wQIbybG)mu;qDT$y9%DDvj5;>Oc9}ANPhE)0#4V`Gn&y& ztcZB-mFNvpIq41Vl>keERxyS28pJ>VMmtAPV-7YhZDB^?KHzvGlv6qm1?V`+N*%|4 z>CN#cVV6WI<6qFNto^} zz{}JySoK78^4cId$%|dru+RP5Cc@Ieq~iScz4*{*+FEOJ#H4SNfW8f1>Zpcr3m7N~NDg*hd0mD0n^{h-XIOm+c|@h-0le^eT}e z7^wsIVEGxs&?dlGNYxDjG}cM@D{Sn=Lcz}aw=0j?eFpY2it~AJ&-pU5>>%I`@Q84FAmA=Id5L77WnfViND zzpMx2nAm)|0=bCyNrI z&SHk*!Yc{Q6Y^#R=gIjahf#v!?}=dCFFqxk}t{mt9LAjKm%m0 zZ4f?O(S_zlNI@0uG^RMOw?}zv)jbBtXlU*0 z?Q3m-&&bc;RK6A;wDwLYKNDe+7516~mb9n?DB9i4VT_{fyk%Olt1-Gi%c=GM}dF2;LSK5_c-MhD^ zQjL|3Po+{bjd;Kx%?Gk^gsssa`nU}|F0Dv>%fU(orkfiaRO};_M0g%`F6mw(-qd11 zXnn-G8E-`&W6^UP3~?V4m=EmmCiKV;=-k z&2puMeYH-x*2?a+pSW9pjq^=rx=Nabj&?&b8K0e;WPi`+zo-MnVCv8Vr0g=Sm1#Zsd{b@io2G z?hQrKvRkj#-D^w)!f~@4LW~);xa6=gfSe7p>@(VRdaLY5IhP9$?RFs1Asl}0S*u)A zU2k)F!+xL5WYXxs(C2J&*u(u+lTll%);ndNh_k;48A_U+6}}80<%Aks25XN>7((#6!`X@@FWFn7EW(Q= z7GBIxOF4ckAxARq|Aj$!IPO183}asl#3q56M%s$+on4Mtr+qaJ^_y4`?AzBj(*oPJSAPy=SV;2@R)3#b@jZ#%Z>2g%u+06K< z?O`@QuADxk$G`57{uc3!onJ6)->w>Zcx*e7#*JeRV=`1#=#L0XcT>Rt5PY_zpw%uu z{BU@h9ar{FOIA?M?Reyo&~$naenaa&xJ0FILzDFK>=}`_gE8cQFOS9?rg{o<8$cS` z5=;_HBYC#qS1CIaABy$&$55%MU`&JM-|u%l;CDs`^$ATn47`pe@$(TfNhe~M-KcktB}Iks4@JkyepkpRw*P?g zRFoA_oGNyfdog)UEs)+TKkQ_iZhZa1Z+PTO1Oc&k>Z>r$`2?;=E#$@qWL`NeL2Y## zMCZFnvYH?&fkR}G#5}D-k0Ba~Ue;Cv%7C9^wN|Ctv;YzY zwSmB)UCfvdO}`Rj#(S;{i~{7o?;qV2^SZ4DWXBo9 zfmp;F2-^)K8C0{94Hz6)uReGNd`o5?d8d9CF-g9(BR_A)Oe9sLk^MNtI zsouxm6m1u>+K6*{u4JEhk)aMB66*!C&7(*QN>7BkrT?ywrAz9Q^n7f>?ag&cv>MU%(wR^_GoYBabZxFdv7vzx z-+o^-g{Z^XVZPkmvS(&*}lH23ar&itCd#1m4FOb z>*WkDR`Hqu6J>BpKmTJd=IL)0KH4xa@U8y-6DVN}j#lvsm$5?cAuJC0*~<0&gwjKj z52bJ}0+XQ#HV^Kx`3a&k@;L3FB3%jq`lTij&sVmB%IA znjhDiJ2-o|!n_)}wv41uD1R+G>!~=DqANG$$n0$2jW@njd7vA4GsJi;`G@V0@fcac zFTNzhDdrkws->_6M$+xu3Vlv9lPr$D!nWIg<}`oX0@e(UBO5v#ngRu*c`9^x2>BfE zpS0TTRuYZWpB2Y}7epY|G}?UifK#HJ0v@l5WDGQXm%FFI|#sj#yKa6u!ov~z=i`~g5ZGMU=VHK zF!4kJkx*fQb)8VWsr#yfslpTptll8kZ_TfeR8x~7|ITzap~=DiLdWt~n>OfuFt zWwyDmZ({BmmZ@p9)_N`*Z@%8+bY{oLy|MN{ebcr~(+!Q=W@>9aozskG&od$h3y%Kqe*NZX`GH6s%gOa8dIu<8mSn%@NVcU zV@-B@W^`L~G}Kz}9!a^!x(sH$V}tiplfxml`|I6X((dUal0@5qm_xbEhldR!-Y}-k8^0oLnjX zF8txKXuiSHro4W_jC8mY?9!G_ueY;Bd4f3q*m+U| zw;Vx__c^W8Z8E8w5bv!W95%3@hBw>wDsV;Vy_a3qT7xR+j=@L`(^%w&I=xQSv^#st z$7Sr(VAmPyRP5*KdQ)A!O0L(+)t+Xxd}i06vqf*Sge;pRw#jVWbCmED{MXI5nHcIx=zD0frp=QKd-(8BM zQ2|^nt+ z%LTv-!DWW9&kO>^yu$lZLgok<1i(33g2I+e1{S#(p+of_fd+DO1!s144TKI#+!BG} zmv8F5=_bVM$Zq}MP0ZQXxDCfSyiu|m&QcMbv{9H6ejZpCT9#(sHI_W2eOZJiQpfY77GzFP^O zBfKJO?!68E*3{a^V8bXeRgg6NNOz6mNJCL)EGv#=KL3OBG{?!_71yf7%ggf!;A;RV zm`7R}2FOxe{Y+*$o7B4=Nj$92jpg=avwL#+i5-V0CZv0Muk9P#Q1iEmzjfF2^j>?@ zwY`^2{Kb`5{>8+qV_=~x<@BvO2KkInf;KAbG%ujCaJtATq;lt^d(yksZ%Q>RWS@{5 z+S9wP-<3u_#EN!fEU&%KC4&ny^x}QHMJ>^b_m6T(bmQ0gHjJaq@W?b!b~*IJR1cg~ zfLuZyt#nsGIYVe#XzB4}w10fOKbmC49A#G@_f9-f%) z&o{9_2sg|I&V;e_yGxVI2cDgS&1>r^Rd}3Z|tL#~k8L zNV43pVaJ9Ir0RDDHpbG?rJNCVC^wPAjU697`r!1~RH2w$${MMN&l%v+3y`;Xt(gy( zD`E1=5}f04Dq285(6!{if&G*+zdr-oLcp2Kv3@hyf9zmaw>pjH{;19jwq~yrzp*>Lcp2*#`i+>&IZ{fWfzb78(@cY94{T<3XzOKgEbZ&3H>x!0{hBIGfjp09QaP?l6-_n!p zXzxyZI?R69Rctsob7_9>hCs_+Xw;Q!KOy-MM<@NFoQTU6xJtQD0yI*Ol*|@^`KHnY zERvhf_}pR4 z9N3e&M^FPRE@5-|a)`?N&CaOP8F88Y2A>@yE0u9I4eTl}JY^Vx$Z%lz2N;R`;KKRM z6*NK$k-xX(Az$MYX-7&4ZDubgH%B*YnAo^60v^d`t3{cMY|LK;fF=kMnnC+>&yz|1 zwbX^D^6TiU(an*Kr>*j4d`=IW`3C+`#a7YBRo{brX@Z{INcsGPsHa>q%EcfjM;p9E z5Q~`pNKu4*0nkK>Tu@|}OO_Dku*$9Uq4K8e8sAqe?t8Xae0JBa zUAx8n7rX)0h_wYs3Y1ggLDe40hCANR9+L`BqIBs)%s{np`ui6b2L=|I zUc{E@_c!4DC($Cvq!d_$wLu#e9$K1h@c!Y2O>5yB78Z^l_jo)Dk9+T(z1QP8bqa4h z|KXqh!WCD1+id=wb$Z(R))kwsxYca_)=jKvGWlhhsTzW?2U}F%U}DpN#05@(UuUHdQCA5jaC1A1SMKt)j zDL@0H1=5{|v`PVD5k>&R5Y|?rAxCY|$Du1Ic=e zKVl|e!az+j;!qw@1C{d(0tQG$rJ zK0ziz>3Bjn1DzM+C=RN6L=zQUV_v6!mdyhNL8yoezn(375XE&Bza!iakRSxuBFw#I z#XbZM>*Vr|*pUSk!hrc;l)pBm!18cVc>Y`Y6!Q< zKEJV{iUuB`NJAg|t`%2@#?bOL#eC*}?I_+5XFY z*{$K;t9w;dLrFzR4ufP?N)9Q9h7OMz=H?8bzz&aQz3JTmdeEE_F`{Zn}z zRAd^v2gFeC(&Hh~E24*Bom&v|z63FEfh`L0wzOW<7)sxvq^sT3ON(ft%10pEn>)=n+`rsz9(s zqZK+sBJjY*oyw0s{ykrN=RoJqjoaGWxA~$wKfklR#baQp+G8e%y%hn7_jcy|x@Q9tbv+O(v)P?pu2?VYknqeEf+R(tcR~v~#rNgJt z$X4WC!cyaq}Bc_UB6HHh0l#L*_j>p z`Me=FBKVPhqg4~tRnGM?)|4ZKC@YhZ*N~pw%4_1zvgKD;A%Cs>19M}`uUQk2$re#VL-n~+Qmni%ik}{)?SRkFXPDY zdQ)T-qyuD>@F*CxR^&7BI2~PsQrxWMl$=L2i~~23vUKt!s4m2lMIqdFriGHD4pC@y(P2l6UTc2;pBXWaQr^5x_+c=0|fCQ%gV zDPS*?Nq{g}(eCAacR9}Gb9lvLs%=;}A>nB<)7fDBU=#@hv70JNkOgLw0$|kT$e-i! z#rSc808Pa`R`%R)pz=mM*7H_R9Dm{kT}WVo#5@o>waDK_@N>!6!sB@4bXj`AS`dDM zVL*5pKCDiQY`?o;X~LkOCq%0LjplW5(|a~$Yr=_gX#cQCEgy`8}MQ+Wumbc56;bG-b#;*q~k;S z9NZP7X+_cdT@vqq&zDScj+JmP^ z9{?*t#{N&NuPR7=QAH5h;Vso=&n5{8I5C)RXtqfCFJpH+aMvir!6+DyW>u1I{FdP} z>hT5^77DOOjFV?J~)r-`U_sC(M{`iNk&q61Nh*Bt;i5Fk&r~Pmo{ht`BEzh z!*>726N8@{ym?@~<~8lNnkU%R@~fKuy&HZb4Uyyv`9gy?56&T#L!r3x)Lb<3 z3LDl9-Oyh;m#SJE_aD%L8nI^eco^t&Q#K@`A)+lj3l(byPxtJDYYmBiuuU?<%HzYC z#o-LH;YZT_K3~5Zv|*FOk<2g~k$ey8cV;q^h6f+YOd9>PkUs=4h%e-N2o!SQH1iuL zGgH(K4esmEj&H#F7T)3@s%@3~fOi4!2GCM^kU$(vT5KROM)NQLC|jInZF#XEI{Ap1 z5=;|?`1#pHVPVAkt6jTh69G>|zsGY&F`o5!vPe&s3WzL+BB=3H2>A?SiOKAj^y51Z zj`)-_>RrEuQ_t&~cF)8HJzk%4SBBe6H=>PKay%RAN4J*mLY)vJpPeazcPKT6gT6_g zBcX@?Aua!2f`zkrOeUPOz@#B_6_^sLp~kDgh_oYCv*|VeuYc`-ZPUNuDe!CQ+sgUF z8xGHHxK;Ttru{sGxGDK_v!R7O=7^Siv0lU}e-@TZmG zRAt?#QoYG!Z|YN}=Za(1L2g$qgGb_PfJfM4Q$(HPbKB>pDwmcQz7I%dq097xTURVF zq(_!*3BD$*+WV^WqDqyOM_9(kuov0dhY&1%%j;Mj&qYVSP!L)S^PpgQN5}(A?l4@e zPJ|e95l=?AYYzzSHzZe|sD~(6=Q;7xMfu#UY6|x8+gNMJ&NY?y-GdM}1Z@Cp75hf# zpea0P9@!6Z1pA-H!TIN!x_%6vbR3`(cbvqYJJEO)P;^J9Q1gO|I*ab<}g zxIcg@cHT|-XWEL%}=nvrhNF{L~eX`v4XToRa77NlnVda!goI?7UFnf6J(L9~U za+_A1JKJAsN5zSstUPZT|9}CMdyC+fs3-jPV!6ZSBzdmfWs6ggjc7MN78@*`KRmid ziC{O$R9TS)Wu8|Caee^xx=JM%)pmc_t&@FLcc4Jsuzv)*qIp=VwFu3o4F&_GH-!)3 z=fW!80>Y!Q%{LZDZ-3zS(YyC5(x~#ZZu~DcZ@Xjb*4xKEHE%gVz*HJn8zCFMh?qn> z^t`g?y{&RzSeiv%DnjbCUl=DtA_Rccr(OGZCwC8@^T%rC?!diYdA9H+>d)o5Y=D;qu_mfgF8Tp$WXT*|7E$ClBufM+RI+e* zjZEfQp3zfOEpuk%0bU}LKd==Xwm`8`)y%CG$0fWXY{52Iq6D}`m|2C|lmW7FsGcyP z8ajwT_^L}$a;(M%^?st3RML!Ymq^AhiDJ^T;>%JIGE#7QQT76|9CPzGZ(>?yGi{_z++UtUfk{uECjp(-~QuA_wGG< z97SX4`hbVIgxM9JgB88 z9?W+_1Y_vPKw}fv0{)@;Amh=2Ix6IH#@73HgG*78oL28XuK|@*&OL)t8XD9FbcddI z(kCu+dI$eRdh1zyq|StZ;+G(0hJoWA0BqWY8KUHKl(sTlt*w25Q! z$jaxE3|9|cdU1InX^CD47rat$fgyP2xYKWxQC>;kj_gNPH*Lt!KH0I*21z=F7v zc#G6Ue25J|P$9`t+X@U7HXueUf;l`F5|ft(1%XB=Q3qAFeMD)C9rED-xt&VV7aVj5 z3jG=l?@?Wcyxjf)v#ZdH!fY8w}9SOh^F{)*QF2R#Y2^9Ct4zGr@(8Ho=v%cg5Tzu<3B zKGx9M)Qkl8st>+-uJ6h#`@j^rd>kuU-ijz2s+AM#>xzR}RvsyP^2N$Sd6o{ez`pU4 zr{Y-bdrJpGN0Iy%`Y832@Fic=Q&cy!8uvB&N{J!*v8ub2Qv(CHB3wx4@guCo^>`&} zPhl!*ai{%(5?hHC;FF0QVJF$9{>1@M#*5zwd~Y@8HY$X0q?QRa`Zzy4xB3y*;(mZu zD9hw?6`qXpR(J>CNMdIw36(rbPCu12IR^qK{svDcQEKKC2+t`+8D!^FGr$_j;*0c- z>?O2&`5F+%HLk(xRjrgOS%O4~EZG${2QBP*{*YgVUx!7oNJ9$`h-y{Fzy%i>RbXBd zw}(iGjfb0CNu9ilaWrIYp^qwBue@J4T0rlB z0c@GvP+7-D287Nn=BSlt7c6QZSQ_-G3y*2FE93Oad^t6Z`Skd21O;Kh{Ks+7kU)AsEhvhLyy}%id$|D_ueMt`HOr0K5|IL>7a;iU)=f2RO;bmgOO_08{+w!&XlVjBfg?*K6%jvS-u`Md}cxK#PW(I_TqsL0A;>VIpTkGWbw$6m7<~Id}yx1 z%d=KLa>>9o+>7SxYlLN(TWi7|IYL5g`C1BIA<|O0QB0%fPrQhb+Ej(z{xDYw_U(gGaBh`ESf=v*JOyL;=;FG;hY08uV_n6$YAE*fAuX$3WBp|YWcYFI zfJRz~`B#hTO(ZP&c;nr3k+fcx4fTYRTdk=z!sTY`R;^IZFwWqetX%xC)@>LwOs?EY%z19(#ftrtU zk}H=qQh;y*7j;j?T&d^W_q498@-u@CQzX)t*BUX9N~|ixR|07ZMs~VPV(5}qCxrU) zi;FWg*9F~W$-eyR$iN~W(-aFS+a6lTrFOy0Nn?kOM#~(H?4|W@MVtQk7^hJ#)PKRZ=9u)v#jHyt8s@uI!g( zIrSmOv8*8tmZ#Gpl2ZVna23XT*N0B4r&2v$Tgu@jaRu{5`Qe9LvWj`IET{etTE>P~ z^u!~prXRa~WnUl?y;7U6I6h&AiIoS@12}oONhc7*z^TD`0Q~@(P1_n*hM0P!9pyR5 zc@co3gf4>oq-7C035#>vvKbM4jVqiOHp@bE05g#MqhkIE8#h&zM~f<2K>1LsooCe; z;0~_ItQnkeH;&1i!I_*M~-$nMRYYYTJOBNM-Dh1UuIltEYj1RT z8&lq&i{*DkACg@T(x5-qVq&;jtHqMF)O9PxsB*6tr0ZV7%y@V21{pK1E7bMHRaX-b zecu$Us9>Yd74r4NMu3l_s>JtD1KY`6CAbmDKQB-h6i99%!HY{QP->^tFt&+YN~q6jF13D+3S?tRQ`*2!V{jyvQiyql8o zu|2t%!K|E#p{Q}85XtG|C&QF$P@@0Pv!{N7vkAsYdD#0S5Hzv@@;zfd<~Zq`!)Y%1Q#olGX= zCzGZ}>967flHWGo-HamFD)@RknF-m~(hj%lbd9dgR{I65-fH;a9kShM?61+uc8ld~ zjmcE4KV4@vYU6tCU;njMFHI^gS5Vg{X{$%oa!s9?JsYoXHX&g^*IEs4GMl#eYd>EN zPpsNtu`6}#-)m~6br-%Al?=EP;CB9?ln-AIyjc!4imDj(J$aAOM5;^F2JKt841g9% zQ6{(%+)_A|viGQ*u8vWd(gxdr6Xra=zCcoHL$0sB&ePshr#C8}o2sp^uXV=joZ1K3 zHoaPJ(I+Og&bn7^9*?c7p|-B>|D)~Q1KTLid||(%t7U1dyJT6GW!VD(v&7{NNJj-!LU7So6;1rl#f!HvXpXIO4+Wr<*+nO zDcj|+EbVp!%UMzm-H*fK;rl)BNVXgTJ^ROJOEaU|i((jjP ztc{vw8bDvzRT{0u=n&}$(a~uAzG!dk6!q66R91^h)%p#+=&`M{c{&^I;$7>mOa=Rw zX+)bQrfGzSlK1riJdY#L&yuLwZKxaBffo$@u=7_{ajaq32d9nP;=1sR2zCd1dfUQI z3LW4!dcI$?xEZ$b7K%q%HQn>)`oVMYpYRqDVqT@N``V09CYS0~e zg(G&ObPmi}u0RM`(L>w;r8nB8dy^o+_j}>RtnXxeb|j3(-B@eQiDUOPt2U!igVGtb03~-6xv}2vU{(t z+klJ6m;_9QoG2CyU&(A|K>?O_%1DpIYpvjlj4Qy!Lvd4-ros;Lr)*dSuUaq@M~ZrM zR`z>m)MGaLVlL@1Zzkdt-4VOqs@MCXal1F4@IBs7Q(CrMKSMBKnMW{6u6A ziZ0z5NfJFqc0wnJP9M_IYprJXHLEY0jQOmtNXF}ohuk2OL}ZC*52XiOPNhyg;8WTo zZc%z?DyP+%y%D=Pkk@HUyLnFasyx@$Bv=vBN)k{xzdV=!|HH3@Y`wxw;0!{(N2W2+ zBg!DGk|ztn>|(KDw6{8vVNHl_-H^Q^xoKeauHwMW>xIjjI|9+~vBpeExT#%Qr3$ZT zix23t^#k{oJ1!NrI{=vq`azn2yx<7$&w^v0#S%rMy}Xf!&yAL?MuaO_2du`#n3oNE z$E0@?dExEZkrVI&=lDiGIqH)h@qosl6c1ZXk?_%P-L_%FZQnW?ju>s>cxj!@7!Dh4 zPlWycu=K);X3w2>-kEb_DV>Y>{S|qn5`!<-hj{h+>W2PHwW*YzM?(?T!;ud2VA@R3 z3I-0`fA9l+WW|z|Y9uPb{Cc7j1I>Wm6$-iZ|5ue;N%cX1D*+Q@L&30WS+-pj2nGYH z_H0xgu8|4VkijZ8r!GI(S5hkKReUC77dwG>Au|Syw9*OmE}-*CohAudHarCTBR6u(>Am_E$0bqlqe+UU!faTzN1XD_f0Q#2Y9r&x{4KxshWkQPJ zxpuM$o1yT8G$tz~dCX)fg$k&QWA+f3iB7^)1JZSnf$;Uav0`zeSbR0kS7UZTueAzB zaIu^B?log&6s%fN5bWLkgNFwD-wRmsdCPs?<=%x?xj2EqNc@_XXXEi;v?-}>^TpQ1 z*iARF*x+)%SDkE%27!xdMso*-rbdsH^(LUZ!)+=KEUxG-knR8qbP$}WpFQh^>hpV} ztfUy@MmsxhH%kL^bHWB+)YK$x;cnHFO{NuQv*ejvdVU?D)hr;uRD`)moCV=00d9F5 zLj`i%?`FrnzkhW1kv)?!qf^>t$3^4^hb#D`Eq~S5_s=-@ikfTH)Pdp_a1HK-uj*cv z@~coUhdeS10~c2y$}9FWx~#Ca=G0V;PTym=D2*Yi_ocdZ!h~>`dkw?f-co0Y6VEYT z6o7>n9(~$I5C9(@c`s83J8fANyt}F{`40QaG12HeV|s+mXzaQ{t?Fi#>VQf+pmV5=>?@}F1Nf*le_i{tCpW*j z^~YQO`l`z{n(YsK$}=U;zty~|Rc>kMC?Cw#N^EXzfJ`amve`Z)&+5vbl%yN~cGWZ6 zFgyKX?$Rk&{Wk=!5A2qHy!+K%ue`GB)f(Ninlp|>xYmt|S<$Yk#Ai7XbxFym8=2!1vEJq;0K44pPiU7<(brL&ir2mrCqS8uKMhNf7ceC-Ivk>sJoQ z;gnj^t^tV>q~bVp03^mClsuLdV^Wyw3KZDNcPA-nb2*Rf)RAtVN6X1X)NWrcd z{h$;{j!)5|pf!gAM!a9r20}(L5HjzlT%ty#d)2y;-8$mN20jXIqi}W5Z0QcSq;#z< zeb@Kl)zYd6NHU8~#Os_W?T>f(cjX05@XrJHGK5k)tT zXQw^Q0G{Gj;O)izc^D&c9cV3=;R(p%!ZP+7tN0k(THaME?SgaFXcdl^Za92HAD1(Z z;Ws7B9MCf^nJe+x{>}Sg!FV0sbRMk0&cl^Hv0?uy7wacKIfW~Dacz?8vRx2tGG1rVzuhXXYzP)$v+n|u>>{RILrPaE60b8s=%YIa^TQB|4=VNPp zbPMTvh`YX0co{P&WV~#~h*&9OD+?KkMGQkQ(E=Nx(Ie^+&1wsvvUf$JSNHZRnO;Bt z4~7OMHbtEfHZ-vO36{L$4(YiQ(finz`;=y#&aAvoy7#owsMixPkM5a_DI>OD)D3*_ zR-}qat`st9B$d%1a||9c#68#xSZvSDF0Bi%{pW9X(}sKho~b=n>+W;A?Sgf;Fm6}6 zHb1f1rG&QR+WhzyY~-yYCr7M&L3Ja$jQorOyax?H-VmpNC?FYR zR#GDqdq{lctkGpY`?X?X!Zi^ufOQQY&8OwnHrPL0`00|Bu*=~vSyJIf5y&Ah6atJm z)f5mLLurfYxO6uK=CG+N{QLL&uh>Vw#_9M{y4&nBnOx?HB`dl&Y=Og;yf(N2vRy;I z8MIA)W*N!G8($@q(!^evynSnNEN>6E3Wc%4}(*D zNk~sVb`+`32M@A4f0SLHWjDU}6tk`U{9T`4i+WI-lH)sQeCGKU2x&o-E7GpHxd!3! z`F`Q?rLu;G;u|O{2#-`>$cYZ36E?%c(Jo4E_J=p$eDlmA0+wesTlDkNb)6gqjJW_O zwSnITs5?PM*)JK95ygEbe-YX~U)otL?!0wZvABz_^CtV&(ku0>y8iR@<>#+oMbAxv zx7?=XED>nS+;Eq*P`X+Cv(wy!_X^z9RRf-MnVdmW0)ODrayLRIBAiW1fj1F2_=(WL zU$Gn>FTF~hs)U1-Q4K5>+9_;^;Y3C%H)P# zZE~cbR2D{(+TIPxFE<2Mmu$W@s~Q?st?}7Ps{_&_wswme1E@l+R@55=r7hKDu^KEE zoxvA0IGv5*R(*q|NyI(m?Qk{5(J#SfG1N~TI2g}u5Z?@tDk>@rT0lcpBA(_%3Ps^LB^;CH-y$W6F=&S z@4s2A9n!g^2U%vn^enXt>IZpT{{*6(Fe7rSEAb@~*)oEWhjpxeSl6uUy=DH*TiC8! z1Q8$B>vZ{Br1Q718*Zs-SA^##IeF>0m{MVgX8epWRwI{5jZ2UnQmdm%quSRmyR^Pq)=c|{tKf+(&UR{c*PPK5ah?5x(NOHO?Iw9F1Z@*7XCzc-j z87_GVc-b%gtJ_d4RpV1XU;T6Wx>sUey$PP;R_OTPrGswU!m7@Uip!DIc~bWYT*%}7 zvb@@e8cDH9PgHL->W|YR<~BRW5aguO0wku@mUX+NXSTCEY#l9)M*VKR*<{$QH#WAk zyPf97MpKhE{pqyUSzpp#B|Y%1p^KRlUC5 zJp+0fP=L(QIY|(a$23SF78rT58T5G>IwI$fB6%M&s>80C4(#q96s_Gw5pIIr&z~GK z8~2D-~E#ox|h zPsxRl!RQ5WyIjy#U&t6QV8FtDvY}A-qG@63OrpdN?S!-(+TLq2AZPplv0qd@9 zn_BRGkT;YV4P|0_c>`_WPuu`@ybOgdnmbg6f(Mx*@L|t|O~r?n_vNAxz57;f|AB=+ zlr?Kb8y*VU#|_kk8rdEZLWn$u%Fh6XL5vU8=0LZc%#gLs#Shyp8a%vszJ*30@=^@! zsBH*Cokp)2P?%z z1%g{=p}^FB1@~@W+~-c06V&=n)8fN!lCaTe4+QK+#6~22MyohO2hWIB>EMSpVw81J zz9x_CVwNhzLvh&GMSZssS}5<@q%ae-gq+&7YoU8dH<2$*y*>9F68+81P1Y>`_Xm3U zTDkvQ*f+r>)K+=(XL=jP*)`BO$Ri6&8&s-_hmu-&FEnJN`lNPF&dM~3h>02oEr4}L zmNxK!n3>KP10LS^rNN^QIcIl`&j$X`-QxAObXQurMQvPfV&?TmwZ+YQ0c$<_-KN=E(H6Es>dm2lmFr;P!OV^xhL$M%>dCLj;nl%~VUOanLAZL+$Oz#S0Uta?5?V2u z3oETa=v=)~((jQp^%Buz6bX2%nxS#6^WY-#~ zy8`jSH}GrALdk-9O=RDdIfy)g3l=ZRNQ}OVj*AgxK?mmwB#%(@!H^DHA(_F@-xV0P zse9x2a43krPusA{hC?senw#6*Ew>|4Y}v{*oI{T0zz)kYokilXmK(@p=fa{@E{kt;R$C1YkGw|os+AB z>(PyHlY3|_ky?E`Jj1`J3aFdz`C7+P2x+8v}-p4x)_E+Hino8KCEi%qdTn>I#PpBEJNUPOXL<6}*88xSJbgYtdH;R);{|_1 zZCfXAL)%gn2V4TFF#RK&82)Q%YF^LJPEX*UFJ_lg)kun-ebYDHG`+8;OwfNR-3upA zm3`KZ5H&d2PRm6s3hU!i1veHukj)Cgf@rO9tJiowLm-pYoQuV3BJ{V9YqdT&`R!&a z>~6@Z9m(`(3ZZ}=nTO&2cY{6sVIpDb3>5zmX{GlnKie$~Wm5d&xMRVw-vO`_DX!+<_w2*#8q9~f<-6 zeg%c>OhAeV_-gAhnsbit?nvZmG935UufI4S;xI>*+Ox`F|5^ zg*9@Ud;c|zxBp5lsfhvbBm90|$qwMFCG)F=T6pkM7&;T^DK3H!N{^ksIGW&o=|2wB zITzcjKsK_h$+3iz=mMZ&GGjx9ZueDY_#)h;oJn_i<%usX+n?qm%36^-Y0)HATzZAQ zXU;4!Tra(rG(5wORPM#+aC0`G283$Hy$U*Dl%qicpzq1a(~|^KeC;&~3S(#ay*q*9 z^RQj$i3zZYwGl1?qK^syPYuHMvrPLOJCKuJ+V<`pg~+xiguL{H9;V&<@Mpd{sJdfi z`?Wv9b;-6RbEa2)HFX3OLhKv@C~f>7$v^OzFH|Y_&i3^5`~fK{<=@Kr2j$Dw4pW|FvoQtfZurHZV6pF+o1{E5{(KIzYGIOtVlsPBk6BF_A z@ff|N7;_4lLgD5@!O3^XyG5K>0XyA6%)KKhAz8%hEHcq4xa`6q%==+NKZRhc0%as3 zjWHKB3PGA_S27!BR6Ad*|2chmp`#GD)Hi(m#=j61R$t?_&CN}|fr3e=F&STw{=sK7 zS$wxo8dQ!pL#J+77|}J`3wxvXKl7>;qA1Ro|^?eKo~)T{l0x4 zWDBEbEpt#ca4Ry6s*6p=Peess9C$$i-?iR71%Xj`CJFcf+41DyAYRhFm*RcRCq@#9 zk6S+BFSW=XG^!#y131j`%`|r zD&v6z_5C3ql|LZ!QA(1b+AJgNDdC4P@BAN;@~c&7Xk9)etz=3 zb?P}*{>;?gy;J{#t;SkdAw9b97r*!g8^p3^ObFr0V-Cp@_&XHl5|)iSO!=a7aZ>@6 zOQV3^fn`cwTT-)SXhB*b6G#N`VCmT==#^0dI2qM?0zR#J^ru=MaF>Cxyr9tNje^qB z)MUB%J^x;lPKjB-0EDu%g8i*tY&1wc@_2m(>bMV@5Uk2887xg7$Qev2gZ&^aPh}_V z`}Nb_{rdgZg8fl@zVc}r9_2@^1<#|NEB5t1+Pe>b@`~+v^ijD@$TD#w=MS&rWP~+J z1ujYS;PQp(Qv40&0;Vr~zBfJP&O{GVUO3SB4IZ44j^Y~70p6E+0Ts9gMJi)XptLEL zkGxuy5|-UFG?csag$D)(?j9OStrL!;05?tb_DgVlmM!IeSmF4P)3-QKmT<}eIVlUu1XCDB;RCoWB>3oLbQTm1^tCP3rRV=#5G=!0Ul8f@YY`9 ziq9(HL!4IY)DZym^;#vwZjvozpBMRnjNGdSdDgLjt%6`gA*(W57eQG;h6BtJ=1M{k zY`bt_LfRBcPlK8|E$p41m0<;EXV0WVXQrpm5KM{VqvSq7xfiS0S!jlUNzf36$(p=r zM7;!z5?chn5hV_}M`^;$Y5+8IbZKl%s=yv_Rq1XJ8nPMV3AI%{D~hvNoiLsmA0K~y zV&cMt&?1-Srd0UMzI`Z*)MTz7QL9Jl&0jZZ2SF+`SZ|C(5{WM-uS#5bW#XzzS!G$P zdOv*d1l5t8{}K0u2(?lA6u=By05h>SXj7LGgvPledTtgTWzw z_mnSfIO6mxUI!p`bE z3U{R}SX>gMH~&U^6O9{9CNiymVp)@Y8KO>HO-2!p?8kh`&efnWL^io#i|3N~z2saU zRE^0#Ym0djLEj_RHh1L{ptE>I{c(R=vQ2IWGKVS6bX~BnmXQ6r4#p`arf>b}Ai{-l1Lw`nbGkJcFg)%*iL6u{6l);j@&UnMO;+ zF_=iCg9Nz~mU;Y5KWOrM3`V2DBQND0@m_Ll_QpJ(K&Ri|8R+%25WpR6M3xoE4_WmL zgM&vl!$a%p!kl066vHTwbH~jN=K8xb;-^u-} z10N{Z1p(i(H;9J`a-%0iVY;K}Vbt4r33(F&K-g#B9nD4e*nLrNJnoJ9>^tJc_zv(s zx??f+nHwFxWi89_@;Uf^M_bgpJk}O%bKHnu(e=q@D_@_+TLT~SNe=Ep%x*6sz9GKyFc!T`V=reU3{QD``jk|r&mV-Ew+I00Zd6&%ILV-C9FNom*Q zB)rif+9M=p@hAN+`2_2*nrvFP?iQSMGwlKy-7VOa{O;u3WqG07&xE|{P5H<5mAO&5Qku!z^35z z3(F{7#6idsy`s7SN$;XPDhF?w(2VF**{~@KGbhdgtN>03wS&G#H{;)fJl_PqTmCiw z_U7b(S-4#=4{RG4NC!M_x7U{*z=xWhZe*CDooRO@)Ey;zJFOTT710d9{qjm0_X3LO z(R$RPD0sbsD5~*6Z$!M-R(YS6AHa8MJ@mD3Vhye+2(A9qz?x63F?+^Z%nTc}SD~ov zHMNX+%-ETYWZT=b5$PMzY$TG6vX3wQ>^Cd*T7_9}QW>;@ndQua)}S&Q%!>L3rMYb8 zdqw#eX^)L|idGz9;`8{`kWFrcR6)F8++&VD#dTn`w<`Sv-NH(rqsA)dy{O?qKUga5 zF^jIGQ?y%+lcM>2x|B?o(%^8eiGavV0zHvTnj2@xb%R8qbC+L!KLk&N9)*Fwr=X)n zU8oT@3k?3ySZXnpDHVYw$btt_dnBEN<)#7`Iz!R5Y-n=h#xfh4e*^L_5Q1gl2jS-G z`CXCH+`4tZ?jgjs#C};b{`KKHwN4;tm9`~q zdjD=VU&&Wd^=lGqn@rA#Ih02JBUWc7a6XdBM9#Zh=g%v;UDo$r4|I12gt}1XajQ#u zVhMJ%5%S_{xxHI87EIrM3k{ceMnDi~u*nT_7)QCVM*2M_<_aUL022uT_o3kPzy-v3 zi<^r>!-dVF&z0=gx}v-}M%}uB1Pt)ekTX+&U4(4=g>HK&THM9H?RVMC(tpAnqcYo? z0zGRw?e;avRh^@W#AxTL3Wu7a++d7Aeo+98;CHRkc)G?1Cc$mDbwD~WIa>0DE`)sL z(Mk5OY;BS5T7Fk!<6X;HY|~x-(~Ug=f4=dw|E^6nHd(SGeuNeABP@p>VKU_HOO{dS z{196{!cK`tQt=Fv6X-)79Z1N6gy9?eBa!}(xbmIt<;%`Bh`O;L_E1T@N$CDO>~;QN1A7jyg4Y4)Vo z)!o#V9DufiAL0F<_}#B4)0_#J>ncBjzzP<~oorASbx~FoS5zlG%BFUVI6d+Hgx9%I z{_Wy5A(J?8O$q^p&@qNfvWKOS4_tD|^_Zrs`hyhx9J~rUrAHU9$Oe~Ok?M$09rieR zS@`vMU;vLm3Rh3G5hZ2L#dApKyFKKLkoF1cUI{wEnj4gWNm1o)IjveMEGf^4%X*<^NR$x0v;C$u0U)padd zy&-Kv`DpIOEkXWxHE^fo$#D39fOG_**pPIG90S1I$QtM}CM;Xdq+fj_cB6Fe>#23Y z*2$HdK8_US!RF2E%OK%CxqQza_UD7CV2|;^zxa!ng6SYXzuX5J;mNy%m)!x6UK^Jo z(Gjf3ccV1AoaXuWkPGqLJqhU*z@61BfVg>KtbqIqDKCYu)qZ-d zZw}O@a$B#CJ=NSy@+=^XZ}`&5FKyrpHZ^iPG6;W@KGyou8!=vW$a+*A#FPaqU7S%$ zL86?X=OHT_G$_!!D(%&NBBKHO)ZXhy;~Q?f_e&c(J|=y3gUN1b?C4nD{&yq%&*X4C zOdD8BXF=z)eDr!yd80fV@;gWW+-VLs+Jy}pHvC;Q9FB(VrfE}Cbh@$*S7g2-@a4zR zu3J%N$YQ|m%UsWBK8SNhfm>M?ju6~kmB`N6@_(!orF zAbsvmyI0%I9ygzH2b^Ibpn(U)kQqTGUC__qG5E=bM_ZY;t%u*#ef$W?h5f>R)(blzYdE5xE*4N8E;s5xSQ`lHmRlHWFwj*e!sO{#jw^XtK%Ni&dfE%5f!rQGh56uG=#_OQIlz`22GIWD`6nkP zIt_B!!iNE9HXcfOx}4q|in;rv#bhF;)lU?-2NCxbfJK^gM|j1^F@z?FXA4-LYGKQ#Mjl}Kwr9~w z36@wD-&t(@Yq?C~;Oz$!nf%wJ*SlT)BmJ)K(BzKEuffb!MDFSHNXKNPg(9#jpXp4e zJ2O3{*Rsu?7I!w(-Yy-CuUx)-W&FI&Bz0m)G_k)o0YoX!k8(RyAdUuYF$hbKs!I;x zwgNi@b7n0Vh2{h>>8M4e)+Qft0xnV1#2uo=EkOw5#;v$-{>U2~Eoyy-LJfOJ0jC(*Ws0 z{QG2-g7q|P0%WACEgTVyk17`G1dW*>d2(=5zM3*+WHE zr0qiWKFDQLW5lQU6y){8^aFwF;zAC2%jw51E+|vZwfPSB)fSif`1^lATl**Zd^nFB zv5U^l(-{(8lce$|oRw(T#Z;TE-{LtVeor7ekHJA%;gIAX<-C&7CzH!t=6#O(R zg2w^a8T6n~*kLD_D$P0BkYb^>7|I;gnTM5Hm^W9-`B_`8)Z(hQ>TJN5nzZ&+0b84O zotSB;H-Sz{Y+~PPU)|omdgJOyWOaKmlUWC`yW8a{<-7s>-0RX(UI@LrEc(=Xk6u9h zXPF|hwIZ8{lt;_R0X15Vkk<;YTEC6#N2_3#C@K;LOvD2&u3>cs$Io8;y-6O>3xKiw z)84)Lz5Dh_cgqWQ?LN9MG=9mlp8;A}3JgC*V65vb7@~N@KG~*`Y&s=NFo5B33C9od zfYcxu20Is!zY7~QzL6?4dBAPI8D>#Q52GkDyYXaild~S{&31P|tyb&R>djc`5R2s+ zyjgI(3p*&Rpznemsm1m#ZDYaN6SX>x28Z!wQ`6jczsuXi*U%<1*n*FfsZ7kIVrh^t zJ}bS%;10h>nq>DpN6-Cz9H+=&%K}SIT@Z7f1(CrNfM3!4)fm5O^6PZMxWleJlE2L> z%--$x=eF+sIHsd$$A;TZ-L|14I{P=hz9WS%GV@(`d4`uEBWcgpT=cT5BiFCoc-!Td z-?p)LSNrTUyg$O1SILiEeO`!lg?F;@20E&ZY2il2pY#spM?7~oo5pK){%zq6JQo4{ z6o@Jprun==Gwd?vfKwA=uR@K1H46_@G6NE@l!Lt|m<_jUFR%ZK!2;xqwQ;Utcf(JN zRwkWPU#Sr`iQ=|xW}Or=x*mAIWqjrcLH@`_SyMiL9WeeXOsFbN)((_eQFmq z-orpi3=kU=(Hv!zJA}<-Bqt2)$F{Jc>*`GVpgZ2vG2DSMZT@FVKg&9a0&VDjU{s+D z>AuR?0yn%`VhjdGtA^@R zT^?^&SN)Ji7~k{2={v*&_uVWGX-99p`{3yOg|vD|>$zj3l#cx-UEG-FW0CA9+93F)Z1waDkRnjAXL_}ONaD4u3rS^F;6*#%QfP2=Yw9t>&=HCFZpkfx+9!`W7pA9C zJJhkblUWz)FWmw1-nVc!gu#jZdnXd3Nw*vI%q_hGXK}M!c&xQ!Ct=waecljXs-ldI zZ~EZYXvOdebB}DeCFmhh+fo7|@+;F@0Jdpt)0ofY85kUNcIR_;!R_7VH5SX#nT0qD zX}VnA!(T$G*%t`-n%!=9#_nvgHMh0>)nPD4A13=e7O>dkkI#$p{0+H)`H^b23-R44 z#L~(OGD49jm(vT?_uS7)|Av~B0Wfx+K(mQ$&6Cwq9q$QQr# z?U`2(UAOJwYX?6!K=&16NaY$Narl6@`v6`GURhZw3)|>Y6gNm)0^dSvk%bW9otPye z9#20~Zk5rUOZ&GZ$~zui8lEEUl8ImL??Z1!j>*G)$<3cF?R<0x%0Y64TwiE8xOHTw zzto#0BOVwDJ+KrmU8na--tVU(Es^&Amj3qk*2+OxuW9Y?yh(zK8FNjYoU=>|bYTZ< zg)4F4>WHYI=hc-U11v(oI2k2IYZAhMZV77?Bpk!(7_O{2Q4T({Gfobb8}%0QMXP5# z9w}SBTDPb)D(}f>5-0TCF!Cc64fIm|>{;5L7Se>jO8TVDhw_iUn%@+N7a1^H=EO5`ul7K+WEm7LGgg3*p6fxy(KLA)%~e+_Vv024dl+NeIS1$jpU z^$;vkTa(GH<{iUB+pSyp*3j??Fh&HN&i!U5ycEtSE<`Q}+qNgSZcT1C4h@@kB)4u! zZZ{7PZFTvaPM_-;ys|Wk8y61$H zhz~`}g&l>-d}ImL{YiG$~17b%MIYjyc)H3SienbOj zGf&4NQFU&*u(NzY7{5^7S(wggBhhFyQ_L4LCuk}W^?UZ{nL8Fu7Ym+&o5%F|Err6C zyngKF0Z##AIZmL>=XH@=(c09RjGB)r@)$*P7d!(ON94d61Wm>PHw5vy)pl>D%na`^ z_HP@OUS-dd|8V|wqU06q@ERfm_NMOPIntTrddoaYYG|Bw%s}znfYQT%jp?53nCr)K{9KknZ7sZZ^^R&L)tn9uKoo3BihJa0koQbD%sz$v7-N zlMX8|#R2W=*EoK(@-j_Gefi;G<283mzdXs7OaH5(wc%s~)3JDiS9h|Z;rQYa`&w`4 zUw>dNyT-+qe^WZk*5a^l;&ACKHcn!LHMj1PkKl4@4`jGIq3ywz18fZ%94?r}_ypuW zVz#NdvH#g*dcSV@wfUZ&>8TilQes?XYRaF@33r+#DK@n)m+Qs;I$PXSGOf!0g4_8k zV;#^?LGqAseOu10Ec+qJU`A6a(d2;6*lK4pdh-RnIS+`|U?`o(*pLoM=R#>V=$i%^ z&C_Os^jBDs4xKktZR`?KPRvFGL)268jr4;mogS&=?@Oni$_e#vm zLB~v*rN6;fqynXC7REi0oB4B=_x+l3kpWmKLY|j^Ho>PEF_-Q-~ z5!#zbJ`hG`@+4wgxwEMY6sy3wdsq@N7oTNfXaD?Po_X_()YmL@txL1aI(8y=X5e;k zQ0H>4p|rq#uOut{x$tqJcj26xAeo4RG@&`NL1@JCNre%c^v(QR%iHHqKK|Q-*7@K4 znb*Cx_7?5@-ux5nmw$l&5_Vrpb+!x=)QAE^ z(xFojJ&>7~O}+RVw6Y>w-%;-DEO(rG>M7~pPsNM!{oMx5W;;fNHk<>2B@j?$8>Wh| z{1~o**^#qTI#Ajb-N91$JKyoA1ednW*tSL6Z2H85$-vy!YmItDIwJHWQjFx1yNx=n zI47DP{Jk$dm(T`q8+duw;r<@RwY(Q!s{-eeFNA0YU?z*j*g*8jCnFhlJ`r$z{mJgg zOUJBkH?HEAeuuA$nc0_JfhXUKbid>d!F@yaj3~Hw?gMTW!fDV>Xd|d~kp1xhA>|Rl zRj{^(!kDVn^>zQb<@sNJ&)vQ{Y4Og#y(TfzdHe0ld$+qn+ix#MnfqMS^B>MPSV4Lk zu_OJ^KdBN$A|7;PNUX>ZJF%-EqMwCL{HpM7vhHCECVX zq~Bx*&V1HhuUD_q*qk9vy+YaH{+>5F0U43X_WpmOY`;R;Y~-6j*<^FAqPF6yu)hnX zOI1oobO{8eKb{XH2umeiK3u?@?bQRODDE^(mJ16@FmN!Cl3i@_B@aj zF@#)glpacsrH6`BPaX}}U86$Go7b6>ffo{`Tlq72ADkM(ulc>IV<{2TxjfR990!hq z&m(u8&GovLB^5u31eqaW80|PS_o$iC{ zrbkAm*Bx}T-N{d!(Iko5Oena;} zi%iw-;w~)MCUF2E@5qi(yY~6YRsncQkWbAOe_CS4&0+x1K-#`f1RDXTl9_*_b|swX z^ATLh$CV!}B)w>M(;=>sGa=ki~tGyT22$4a5;p0*V!$d#WEi z4{bqM#|SA1bqW>4HfBq{0U6y-bO{7@2iOr4B%vqZ+)r_UJoXZ&1b*UE&&|!1*f7Ks z9o6L!E!+_-q<4UVER~>&mCF(KMmh33u+*L@muFCDehhmS$r6W4eeqEAnIb<~x#woSgVSL5ildv%_>M=dM7Kfhl!IbK^_(sVH zoyh^3R6@RueU(2v0r?Lqqx@R(kq`uxwq(Hgv6v-+vSCy)5(`n`DZ)ggDsal$mSd?l zERsS#*n+b7Swu*LHuT!1zs}p)zZy)vH}#(BIn$fR`!0i#{2oGcuY?qkSoQV_*M;Z* zKD^PMXC-@n+GJ?0A|RwTI@F|Z&7YxNHz7{6XCK98Y8UEJ24$Po}~fGs>T| zD^OhC{5iCVT({JYs)$)?_pm8UK+Qy)8fBrxC#k@Qj| z@BA9HjjB1eVk-HQpV2y~C(v7A1Ddz;_6c@^LeIZ0T0w$$>FqOK{&$G_V@de6RXhx4 z1uU%6A1k;+fDffV@?HE(cDzseex<2Xs-u$hALztnFF1g4b|bVt*;( zh0bgG&W$UiSM6>szfo^`5Owqw*cB_J z-&+4q?zi3DzolyOc0Po99;&o+e{JpLDlN2gKE7jI#~A*>_AWEB35PCj@spF~$;toP zb;zp0fvcME2d=YsG(I*KALYvrTZy0TLa!LsN45Zw^lsG+WBBTF#0vm zu~Jjs9sy0Sv{Xk5B2{(Fs`Rqzm_$8|-cURs7;zB^fO86Ze}!5a?_VNq4?TT>dfo*g zW1u< z-rhg(uK0`mL}98?ytXi*@QwI$nmYJm-mgnTkG}`KbO`-%!Oaab0<;Y|o*3=2LP@8o z!cTy&0UIw|C?r&`Bu4RyOFRqM0!8N|1ewK_gW!GT${#XTR0@g$)2r6ITn+W=o7MFV zF4uZ>16!#Ol&ct9g|Nw$tUTzcB1g*a3Q!P^K%4Ri>3F)2VMl&~?CBf*tsg{o?Tb1*9;0Nl2>IaiuP2wCmK$ zElRb{YR>7DakVxf2nn^4zA{^vex*(d-8GJS={;DEK?Q>B-1?AOcbQJ<5VZw(?o|b? z=up&Orc;Luw(3_#^+jLlSzE1f@U?Jv7%w#K8rvkroN-b(yX=Nx>Fx`&Jy%`TGlBEdyuaZ8hAo@` zPXNl;gz@wDZXIzK9y!SNy>{5KbJMXaEQwd>z<9d+(ysqg3vwE-TkujsAv|Cx+xYcsuPd6u;DtQ*G0R# zM=)@qY!!I}y_~6Pl%J~FBmBBn-GMH3S(4cvxNP1d1wsPj*8|Lvr^GH~<4089MFWQGNU z6gfjw6@&{$mZcDnn70sjl~6aCa&Ruk%*FW7rlDAA!9T+?O&z^$M06D&im~;%Xf!to z-ofQVaSELv(_|%I3+d5vS=6v9LSu&(N}2*JtyTLPdF^^C+zvLD1Q$&#nw!f#x!~Jy zmtwejTzXr0=Uw3o{93hFk*_OVcHa!HMLu~s22{i2&?({(2x;=klYs}Fh@A3m*aXAj zVh~>CYdVBjNeFb0K-Yw&~w8FhooqRog0=;KAm|6Y><1`KR3i)ST9Apu>AX< z{G{t?RD;_(5_pa$Q7h;ZuvFn6?2>%Nek$eIPeDIUOX1|y=+yDYw~bDbzYy)Jl7ok5 z=Z4WV4SykgVkDK3$(yCx;28`1*%SBRZ{x;7E*6vCKD34DHcI6~qlMfSVfUdKVP5+9e++_?NKByhA+9CJcCC!PD`Cy9OL zlT;V-{m9RSI2dG&s173o9|>qQ2*N<^&nD!Uaa1xZjMI~tW|C+3*qPBY<9O=>)52cq z+y(sQJ)^tN&|hG5n$AzMu{`!x_1n5G)Rt;YR6G{EiH8RiS+vYgPJ)dGxL08uzoYv# z1e?+k+-Dcs3c!=uG&y(R&j@3f#vJ7l0CHh}c_9fm!9eeTDG1h5x1X~8m%j?}O z!A-1uDEO%$d&wJrG4|q%_%e7^sHM3+);G`^Nw^5sqvlUu%m-SfdwVrGF`^#o#A+?N;g?W_wF5FS@-7YCA+a>*V z2P>JJ;ntxw9lDm*@WAz!F_?q_C=KA=Wp|&uL>Qr~xUZ<|}F4SG%HNQj|@4Gb+ zcyah#?A*B+i>l4$8TX`T(mmLOt$}R;_TqZ^h<2?hW&UEzWaWPbJdqFw zC_cDiN3L2~#Y6r@BQjxg$ZXmD_FXjVEmJ2Z$6ia)ZQy@mGqGPY=hsH6S>V--?V)mpFF2%YPRh0DZP z`4#EN5c_?t<(lrD+~)LTn+=B5Byo2k*e}ZzB+O`-kO~`J(qB5;T5kvnsopl{zpQ4T z$cHVg&B3l{-4&ewIeXjDR+hd&WurDCb7%zlh(!Z4d;}PiP(HF<)U0`2Y^v)w-KU(M z?o*jl-T24SYd_U3On+;m*S_J@sSVY)-MjHyI5&;OGJhiRR6(0yrg}y!Lnh2J(mT?7 zLkK#0PuMyCHd8Y-fHZpAy2S6A7=B0O01SXx<&g9+@V6iMmE5+feG;b$;y%|4?5%Cv zB$1t##_<&m7mQp0ydBmYOKc++W||ygrxy;JKfUBQJF%`qFhu%20f{~00tcnR7l~9( zMDPR|3k_ICK|`#fogqJQp@RFA;_xZd5=X$V!ZFTv_PAgGy1Z0m5k(``0)gG1{!wHUN!gFf`*RkwgnsL}PwHcw1VNmwq|aP3K!GGXJE9c=WmtAeX-VSK(PFL z7N%o3ABEjk;nsv{Sw$fmy;X2LveQ;Vy({|Nk%fVtSIBEVAn)Kpxh3tO*5n;J*1ZevEe53WrEW z!2qY$_`$V=H4Sta0NRQ%?RwGXXfz8>v#-e#F*upS5Vkh? zY&Hh6e!IP~!36w#z0T`Etc$wdZqcapFhVrcV~Lr!UTIM2bZUd59v_%Or>$2jnX*Ay zZ)Wu>g|=R!Q8BI3sl?Z6r&1%R99o6iP_Jn1Fk2Bdqczuyjd}%sqmH+l8tqMDg9S(l zXR|1_#+3^EpkC1^>TsXc%ume#h$EWy_*U3jgNC%y>bCe?{<3CB5qBC4AseA8Y$1c_h%1IPWxva3 zaa)yXL$KAhf@H~x45op-ftbgLrz?v(5FiUhg1HkQErRqw?`dX8rnB&h_$uF45Q6g2O8{+x3;rSL`MzntvxzjPiwnjG}V&iCZ`T^`pBh%3UVQ?UTG0DS?a>A#FShTo`i@du4ipNP;J1weRd%@CCCNa=)E}u8gP~ zyzqFq?$?O%|HqK>R5+tWo@pE=JOb!@7D)HuR0r!sJVKU>xUgZ`&h6Z>V`sz19UG=5 zw~t=G&TcY3d-C`n{@XW%jXQTrv7I~bnSikR@bST7>BZ>pgkt<fdFv`xC;hmr)ifCVR-uV?U%y^Zj`w$e%iG@W$AJk#Pa|3Gk&nq$sKzlTo;L)GlK@Z8oP9qD$=#KpFu}zN_YAz^!!C5iX@S zl#9Z(2%ieOmDXnS3-U_%K`z>wZfNpZ)7?(Tij>XQ)R1na46bcRI~Z`RNZQ+6l|4Al z)n-q2I|Hq{R9iGx0<)F5#VRkQLpgH_j`UD%EykCT_H~hOf6Jd;d8t`=XkMe zHv23fqjy`RUGf@r;$Je;b;pif2V#{sbt(B9dbaQX2=Oa6Xbg+7ch!eN6)7P34JQs< zAl1*}vB5A&+5b3m28(3}2X_t*W)Z34%U>3yn3a$B1d_>tRO&yajlNXM#~#9xP0>+E zIdD3+H6I<$`w;rFH77g_iU7PulfL;8$~7W9>`U@C=f=H013Q`|BQAbX@|Gwp%qp9M>!xSa#0j2sTNZi)?GK zD-?p}A@}u9pq$rXB<1|c@Z69{5LA#28Mbo@TBVVxlZ^Y}PKsF-ATT0=6tX*|9E2X8 zwX;|#?X)xBefpSlxW5o37K)HpXLf0$aS(nWVNF!)GHSgcV<7Uc>5wzp@Bm0Xo7qex z(75WlRh?J(>cMr_zH{I8A6pI!_|Eovb5p(Viq7TH!T{HgWM82QPnjazG-PHCVva{p zmjbktLi~;G?O$bf$=%ztqUS{R&fd0D?C2YxZa=|nE57;7KVzSj4v+I^BJ0}}*U<^T zY8}}RC`B8F04}cb!5E#qvX4u!P?Hyq@i4_A^$v3Dy;R;lIjFO$b-K}=(<3^y-l7uheQE+M`t-TgpDpZfmdC*cCd5MbV_yb*LR?t)3!`uy-EY;R*-2$gAiJyFtYC~^6~JzeVBhL^PwEG;((Q}opc=Xtik4m z$nT(uoFbMs;zC*I2Mfd4-CpnA;F%kWO~=>?eDF$l55@MzrxF7o5$aD?cxv7B{SbS4 zf8~H_fX1-R^mNeHfjrSOq#;`H`z+%O$o|IJEXfXPfe?umw>V~!DhG*e=Un$9jl@Z$ z+}Lqo%4`l8(@bgqjoo$RAKl+-8zZQDOOc96e^Y+N!FDP-@3iTd3+#>%kL+AY)4)_BmxrI*?tIQxnNTZkA=Eyv*Lon)K(tp@QKhYrUZpn zXR>*NHu7dn^y*D!CjfGgw%294eirNk;5E&DV$fL|t&O6gw->{5ldWE->UB0+Ek=ab9#d(KTtQFLavO>S;(l6#+X z?m5qS{{EiivG-Z7^O-Ncc;=;iq3}v}8{AWgpC{M~MOMzdRVbiK(cj;}wJs;SIJ%Yp z!~eto+2+YDlW%O9oD?pfoV@L-E#IAlaZUY=Y6pj1vgl`lZ zTsPI*`^Q%sx8GTNHMtlkXxpq&N+nSp#Jg4WB2ViC<_VA3;o&S zxyu5pSD(16=AeA$1!V63?e?GXbEtGs&Ay5z-o&ravd%rWEpa|UpDg^|6*WkkHD2+( znKY5CrP36_nnxBpjDB7_l<*Ehun6#Ico+&em@4dbkoiJ+p;7`&e+x?y0=XP&QU^Ui zqe~i_mX)Ekvz-%zmJQmNCzx0z#EQjbon6SSd_X&}%@6j00?y93&6bE6SP{!)EFazK zjeGH!M%kXbvJm$)wFWd77nd(s5EI75V()DiD|4&OfhMiVU~5fStN_ z7x($lq#0`makP5wX@(e&XkY+9BS``-PhFc8k`vM?*z~MrJ^dREBZfj0AV$N+?Ni&0 z!xPa0j%-}J>G0uC4jm-0NzG564r5GN!UNbm5B zef9kHC^U;@?VEY_^K}A#e)6_iaeln)8XCHXWtHQ~+g~~Tj4`SwjeR;spb7k% z4~9IHbrK>GqK{{mA}s{qB4mg|+=f}T9k-Ew&J>jI4K})zcl?X$LS~nLN3gv;i1?G{ zRB*eTQg+X3sosjim-)NI1%Og>XWkd22kuz#&_fFle0zfRE#T+51w3&n z{62O__!Y3}k{KCHky0eF_K~3H-g7$pl+R>I1OkGdgt-b zV?@~my?Gl*oMDr%MD!iixgrd(ep=zI@Y*3vSdDPuhEpEvf<2OE$+D{AB}2GGBmiR5 z)CnFa@1&`H&@!hpFdaA{u)lJ90FFC>oE(c0Tb{c+qMYIhzQsz+YN;2?cTUC&f(<$4}x zfnKbn6`4qf8U5TFE7ozYR`6n>T(t6j_Qeg8db`1pi1&`;YcE#x=&Oi0?;!OI4-WBve`bKk`PZjGDOT5>J~R zTvm(tfludndi^cXv|()3Ia_>}dS-_kx~iC_8^9j4*4&1%wFF#<;uMfehY{5Ta}LIo zFue7H4+t&e{rA}mcZ?Osioo(H(r?cGJAU(@>TiHaPt^si#KIiuM;`g!;P<|F`Ibi> z5#E0oNn$Y|uf>#;4?nEVhh_NP%@qMILshhsl#~FwAX7FOub~c;(F6(!nZ!dRKtYN^ z{!}|W?zE66((VvM*Zd0epjWV}IlUq{X#9VYpilzL;6JB|@S1Ug1y=Pz4 zt$xY`6>aP(56r6ut%ppu*o@R@8)z3BW-~T?WVlYQt~To@SbY3%%{Z(zOikBnpfOZl z56h8&-w<)D#>uF2W)77i(0pzguhy04ZwuTYotO#Mrs2~lEqiD-L-(t_5YQ}&|tV> zc|5NC(*c%F#Fwu%2z|;wcuzJMaJaRVrT;?tIcrTUTWf&ximzE`Ul5j7YM`ru3lVbR zIb|0xFlG)=LIwwcifp9@5r>Kdxr4AIsgOT zzwX{2uA6u67_LR~Mwxd~#0m5svQi;+D$Ok#z$u``B}6$4O;~a$R)?E6s00lIMl!gL!JOB^b^GvZ=rK_WPbnPYwx9ycLora&rj_AfT;)RfonobGBC;QxfS27w6pZQ_{Ii-X2 z-pO1ReI(c)J@dwkkzf+wal21m;=Ux(7HeCuWbU=H|FQ-Bb63fObZ|~vv+^#`<&5@$ zs1UlO+u%r6Rq;8i`u^%@RbgK;d!Q~oEX;yeaXMi{X7ABfaWe5WVY%0#Y(;ey2ixrM zDwnX$Ye>E<`4LH{BjkM>q@Z%t%ve+JV!*$9)ZgZ-9dMPZV|mw zP%FWg@|B4WP%IBwsWVRRYncolFjxx}uQ7|)naLw?; z(_RI>s`P_thnKzo;2My9dzzWjij-!XvGqD0Oev?+X^0>yUsuOWSw|tSD7U*{rQ+co zu<@Z0v~+Updc4le)ODXIoKWJ}2scrXS{X%n8;UU80qpKO?oh8$)-}`!7+Q}@i=od< zXQvrmi6`2O3y}hY&Zt19yYp;ChSu~G>xZ&KcnEj+97@XJ6SBX$>83|-x`|zJ(@p<4 zG?W<{`nv0s?OUi~7-&Z+!gex>!*uvsU{uyEoj6M|Y&$I0Vc5+~GUdz<=)vUwm=6=i=EtJ($xZ`<86Dz)emGaB_-p$E z6VOg089a#N)YEGfj-@dkW)_76-s;2@m8rlV>S0j64sC^P04B~8t?W5h5Y8a}m#3l? zduW5d(<8i}9!5XO)4Km3bdNv^AO0EEMSd#fC^4e#sqM;9Y+l0*7i6zp`A}-~+L=Xa zTr+^byJ+)ldSH4!t9?RsPAJZ-8FNjY%1|EA?CB>Zt`U!+wgW4mH0uZp3KkwO@|Dnj z{GWM;Hy@4PLxIY0;7^g6=wzP%om88@X(YRBSr+$$)_8TU&%8dxxv7z;(^t2*Q8Wah z>{D)F2z0fV=H&0aKC;XM^(WO-uF~~y9YF#WGT`|2$I=1?d^;7^|1qLFQ|yxrB1*wU?ctg(en2WP*12hGrS*E z9aZ&n5{4AlZoXn-e_z=OFXfD-=4Y%cjb-L2UuL=-UbF*x(Aihfj?b~DBdLV+Btq>f zTlLBYd%>f)**lMI-wyaVat*M1u)R&NpSjZ~9Lq+|9HN85a0EApf+*FsnXp?Ou;bA9 zpo-03Sr6eNb^vV^kuX3*07faC$tZ$s3#AE&kdOVhuq_@xep*YV0C5|aK2n`Q9d@CUp6QB+`AKf zcQN;n2QdTGs&0_I)C_yL`=^sK02)H&gUj8iD<_aNr`0gT@=5mjo@YKlQo^-Ca*Kr+SMN?&iKZkokz zu~>dc{X>1Sr{1#M^Ur4U{)R`utI&zEtIra*?6Fv0vbgrR{1(6WB~!w(-}4xk+tmAE zMhrb<003Zo=|)tMEIh452wh*gAIitd$0w2Bu-fA0_v_};eQ{b#_vJsC__FfxZ|db) zvt)o4sdIJaHThiqeb=R_jOA4KP1kn^U9QQl~toY!B-EaKK`n!K|=Du>wPevIWKoWeYq4N*0$^a15W|b8t@_!zcL}pnoE4UHQCW z!$3~m+1Q`UWd`(_jD8@49YZ#27#Kn#5-?(g-Fd^!OXe-PxduPDc>p_x{HAQS`m)Tt z%w^T(o$tex1B1>C+Z*ZOcJifJ(>~zvl(cY2Y^plW5#T@@CQ}`Qfr+p+f$RbI745Z~ zI}>beJZ|%PB5s!gkUe+A<6%4CtsOiu0JnMI zZ52-_pYpV9o}A4n*Xvv#R%88vv;s{R93&lp8Mh=&s$M;t7Lif#_&M701pjebIv^c9 zNE`P4nbRhl%_NwxRo?AfS1hbAYVZP3uOj>3>Gb7;>GYs-3g0l3VgAf->g+-jTd@9) z^+ka#`1UpwoZw>%de<=Yt`g8D;ZIK3$kKRSPVZGIdAjGw5waSvd?0CauY7kmNOSy=8E)GduKi$%An5{&;TO zQ`l>8MU4jOxlR7@X90yyPz1^wqA0@qz`RH(bc*7w)#hrC&*#zE>Wpr~oqz0c-*rRN zPFHm_lIoflzjpML6Z-3omu%c59Er}4;&Ge93Q)$Ncj{%^L3)}E)O#&jA&#UiXeB;%bs*YqmdL;=ucA(uo+RkVY}*Up6& zTFXg_P_MxS7k&k2>Hz*;r425oJk2K0zuua)sr2jV^bLIMECS!Yi*q1al~kuIdK-RW zhnDNkd10CbP5bQF&-)5;G*=iN$tT0%+|G@ia`&k6Vlb<&Y;l_n+%e&>y>=ju&I;{;>JW6ACkx<0-tFb;J@)j*tn}jr-l9le!l6UT z>GQ6#h$*X9t$INye)-(2;!a?SHVO+VmjqejC=W>WB~YPa)x+B!eRR{N+$v$=3oksc z9RH662hW>FHgIEP^ne1CY=G7-G7M1)Bf*B8&m4Bo!>E!h2O}gCLTW4=&t&4^v9)92 zL?)AntYl+;PdFBhc)e#1dA;FSEQ|slNhRSAzA#kC6^6(*&Rko(lO)986LvOG zf3GtTaNb)Vc)2)c%;$|`MY4$RxNU8~c`JQ#D=k*%Y($&_9=`zQKYd|h7@?Ah9-x@# zQy{a?$l2jiLSj%b3PedzE#(#N{mv{ zdoWJZZLA$x03ArcAkhhL?a06aZ^a^Ta+HOEKLP2`9p1KId6jK@;LMvEmq`d}T{#xI zO4$^07w-^;X{-F(Rcu@3ng7dNUnK<0e2pf4uI6a?ASotk>{6#*(7a9dd5V{SOVdYu zLMA)6Uk4-i0Ali7UT2bTQ;5+zbI9#|WzCvr*%U?cDZL)2m%%X6-cBNLX*)20cdri& zusKkKzNq{3Q^1}}UeE)NWd*bp;m^2dwH^{u6kI-mwGeBzl}{2?)T?qJNvQ0pgpi~< z^xAY)5CCBmO-s784&HdMc`*9@C?*)8Kux=pR$I5B3Nbr5NI1HW29*L-Gj zX$Li4=c8_;=dj7k60FN)de&gbNS;ZJ#$xbHiB4wXLx=N{^0{a6{7l&4(Kt9OFhIaI zN>i5t!=dxQE~QJe_t(BAc}<5sM)#vmuVxTJ(r2Ibf9Rc{D=9}=7slslr#OYWV){w1 zEn_e|D_T;|WbT2Dg7}7dJ;FqxjITK?oup(I)j>kS7~;`^<&7d*!_#e$)Ha+($3A#aGniB+2et=xpbMH*fQ)=su(^=i+`EwR{^v4cTCQIbAO zi-D@>JAg6oRJ~;ap**D>-skEy-B^{|&R6>nKwJAxDU5fx|RZR^tTsg)ThqlKh^8$8U2n)An+@x~qKUG6})GHjAjopJ=g3 zyC|nU14)VN1u9)M=WEF70ltA5u0ET-wmZODddOD-90c*Joe^XwbI;@d;Fmjsf}4Ob z2;Q{-ybJ5M)lun4SEi*SJKlS5$C1j+QAK#~J*FH5ZRd1?-&<$i5re+~v8LcT-%!1& z(^(8|@sBR+ayq}EdedLcn)T#lpx(J~`Es>?3>YiN!4FkSJ@>^-+XJkKYK1685q?lg z65LTjrXey4vS?v-KEHYkZ61z0ow4wWB+#P=wximIUwNfa*otbgh1IvM$>-PHwz|L$ zw7TrAjlm^%J%|DxcU{)D;>i>5FDTukmp}tL3pSS(71z<|K{6lZz$227U~UOwSOiX| z8c;(}!VbzmsVsdAJY0dt++lhQv6MmJq-53~~SNo;yV4jXMogEo#>dD$x&jTV#9CRz*{n@ul@`nV|hqaLU6%%R?d zo?R??t$Mw^!7<;_XwmB}Ui+2MU>XwscvGvVR`j$6fLrxTcy!dRqJ&|qm+-A3>uEB10+v`QGdzNT78HJ*?F`ke3ElhdbFw0_gm~@t4o7dd}yJ&4fxJUEXbtvAmy z`2u>gqt4ypLA45VW2~_b)*3DsnlZNi4zpi^)yPAk9qdLV?dg0jxB1wy&Cwv>v%8{6#QM6U zF~RGJ-Z*dUmR9Bec-a3N9_kwGy?t@ZrQy?e&;Qoz^IMu5e0XNBy}7Nq>+<;0AS8G2 zsWQ(X{{i{UV5c|h9MCN(OB~?>mFae09Qu)67XobGkt1hL9XY~Y#B<$|Bg#D^$3{mh zGs^o%k0|dk=aHkz#v?}#u$@N^9O&|oj;gWus(f69_14Fci(?f9j40H$Kz2K4%;XKl zk_bJjq{CY6Z8F)QOSW)W{;FssVYsyM!2+FXJlZ3z0G{jtXVC3Mb;)Rt=P6n?cG@PU zrr3e0(_2jPQ*cVB!cw>x_9P=VxyZ%`BLF7)(}43Qp2c&rSIuo~2-LH`Kt;AqBXe4~ z>H3FBS!0Pw_f-5gV^>1hvB*#uoWr}9Al zXfE!_xq*N!YrlL2WmDlOg4{Y9;Z4$tk#$_iq9_;$T!>Mh86iX1D=-q2{vjVjDx>%$#9gW14)G|6J<*_74myE>WRy%! zr!1L}YN^qnhOkB>X!IuNaZV92?Rvc=%l=@*?}QIPZwi_Wc$NHs!;2cEu+111Es~t{ z+YCm%NklZf!6J=G76VpV2-QZt5;Ss6YZ%@R{v*rNsGZqWXbRgoegm>It|(|0wfg7!@lClnyRs$y%dvXN z?VG!Bu79?_9(6mcW(cMfr{cg`^)x(EW{jzB&{gI?)68vp2eTj27^LcwJP+(mD6P|* zvS81@1B+NxHL!Zmdtt_P@xnUEq`YEst}DdVhttF&CJD#m1@>wb6}md2$5i9$QMJMd zTN0`52cU)BZVI*a*GAeet&OxTF-GY?wD!_uMC{}1ZWY?{Pdwv>aPkw>n(62_BxJy| z2+1ExSxBC4CgFP^T+CisZa0f=?;1rM++feHo*o_wryN%U z6owbi+wA>;GVlxU#*RK#h;?3l`Tom?=2x|6l~c&|2MoafRtDH(yV>di*)0_F`J%=h z98mVex(%JS!9iQ0#~>pSCnZ1k3g=sD{Yyf_fy9E5$b%uFH&LJ$ELeerF3^@vQ4}AP z{d4t!p_m;wDCD;Hyok)*q(;=dC}g3joTAm2D%UD|bGa9BIE6xeFVUE%@ul(-f%`fA zq#L$bf6oQs;66=j6junpdd+#8*joXYa*BM68StOLjagg}zyCE98B zk?aa77N#ouX^&^|_366n7q|4)S2y?P{r>!tsK@h&@%le)^@SE+KS%b>?;q-)@6)|B zV~r@+axAT>qynR}WtfdACX)J{Y@`rL`TMfX)Ginmj#ti}Ls1^(RhwxoIb_y~$eotN zbp-smPLvQu?om1#qtQn8_lF+4#8yh=<`AI(b8?>*1tWr&Ba=|+k``Q#KHpWY*LZgYixXSv;YzB{By!` z2Zs%vw0*`o1$UQvdO9i5a4l%~7OlwbJ_hiYQ>%~!PBKyXIN}z7@5HQ#EG9fB<$kM@O6rO@{0%0_Qw(|yMM*~OZk|pn?3V3zS@~FMf=xh|M`e3+t!Ol& z24qcLRbB^EL6byqaxcI9GU!8F&JqsQ7qEpm(M3G{ff6(jGeB+zvI|qh8T+fu(@$p} zd2L|H>#xraha+AfB*odEz4D_Uz5IRgAOBHQX5ShP-x?>-ZY&q-xK`ymYB$BT{r6jL zMgpZDMIr|L9N`lk?!^aoJpX=+aeKYICI&NJ1x6+QPW z!y!H$B9X>*r&k7yWzJ2?@Om6%ubsVwD!(Y);!JH)PCvw`Qk_`!SgP@mZ~(^x$eg8Ym^LbKL28fG)FWKiM5V6#?*8K zJ+u!slpYb2)0Z6>cxKI-0|%bz_3XPF2Ox(>Pr*P4uPc=Y-{gJjrGPSpL_>C@{yfT3mijiOO< zNgKn^fSCku#|+wn90lUbw1F={Y7Vu1g*+WGsjs0=l3*y3gqbwDP{^bc@b_A z^t#R`G-C5uEFLNRC0bE$TzCeW7tO{5)`378{toi*0xyNDwjq0seD1TOOo7R;=H>gGoYvd`H9o!N)&-XXZV;WncR^~DyKH@nH+m7v2tt#*-Juh z52C@nlS+OwB#Tky=-AK@o8W8S2DEV*x74F3URq1}%TRh?VkPho2ZRc2DLDYlkX}kE zReK0Q*j^dg$&p|t-lOT+7BhLAZdWD@+n~{y4;K-*GPG*VU~eQM1YwTUI-_=ds5=RW zf`u7(vE5uJL>Cw|l@R2TES-*DcIoAHF6wtQw-g&l*^p&i^)%&fQ1stg}S%_PfC zQ>c#J!?>>=aA~qBAPC719!RtWs$juNz|ljU*7n`+u3&$c{oD~)!Cv2d6?|Lf8{QP+19&Nmw?{KXXm6<1<*s+MWh02`9jk}i_YPc{E2@dRuo zAhHlisd7jQX2LCrI=Fwq{DAg>K?P$rL_!$z;f8K1n^S~gWP@&8I}|PDhQ2GhVQ6)m z40)%`74+LAP1qTQn4gP8a(Ib4!y3sZdtJ7Er^T5tSp=IN>xjj97zSjwTPwPi)1oAK z02(nqBdIic`MNHhuHI9pulIapXom05>Cn&4h0`ym!yTdOdZ*UZY*;-jRvYtY>*6MN zi#aAnuhn_#^>vsxxEHhQOII8UDeWj6z&J^gE&_wcNWIQlbnO#>KKJ3sR7fR#C{)q z9lQXh@=0beTeNs=$|nQcg(v&JzeM?roUuM1N%p`*-O;bMTRoqaYisaj`M@~7{=|Ko zZR{Cob03;<{snGYwzy|`@xoWZFhd`!^~#Y|0hwACGW$X)SZrwYuw-^sbe!o|7YF+` zIXgWMuouID>y^(}XV}OhX>?=h{&>;u$H7q$2~p~Isz^f4Hq=11@o2$H@KiQ-p@QXr z&(vS2U^zc`0RF9Z__qj4paRzE5KQilG_qBM_9aJ-EMe8kZ|PO}t?=%^(W3*(XNov* z1U2i#LJguY6K+F*18uRzuh`LxKZ29q5jePAI9wUJOlDgQdC zyKRKcfTcdhtO%k^YvCKgLCJ=AChS^C!9(CSy4}GJX;$h5k4w|H?SXB5ecSq7PDx`j z$(FUQgs?SiT4yuPj%b{T;^QE6`n`?WO_$iIigkkb2}1!u@2k6lZhm9NkAVhh5@EuXBmOFoz=+Rh`N3($MIJKGn`1pFMf`ZFtxlQkP^J z9Erefj)u(QwA(QmNJNC_!-K5<;fIyShm8@JoJoPR8i)PKEygI`Wn@GpZb<|OAEtX* ziKoivD5eNb2rhT4#x*h-1ga2!-URQW52I_w;VjRc$&#R|9H+!*_9!-3V_23_T!h^y zvU=R%_d6KAiBC?SS$6JR`h>_)^H|jO65l9SC8)5XmoFIciyK2Z zN*J<;kAXC1#~5zM@WpY;W1!cQiGEuyZ|P4=CHpM-yrnORDV3W_xsyqEYAWMSrQD;c zYJZYcT704H$z-3kgMRX4;!;~~UQUPaq@PUFSMjm|MQQE@q8Qy9j2z*+Jl+eQ1r|8Z zT+55WQ(&vQ++h6&mBMh|bI(xkmY$w1y~Dd;Q^;#wtMl2hEbw~rt6drP{J?dKZ`-q_ z=i0$dx!k7Ag6zthugMnY9+}C5D7Rmxky#oI7=`EVJ(w&X7pieVHFYIufM9U8^Kr4h zJPbCdqhpuTzy8r(yN+iu5Oz5cf2iJ#o65ssJ%-47pYv|~DL=c(??Agr_fqc@kKu>4 z3b7UtLL4aoh#=V&?_k*oga9CK?F`meT`y)C%L?;aiX%68JU3laeZ9WM z?5b~aYOZe##TPiQH&k04|KN`yvDr^nt7(7OEa;0w^@17wcWxwuDvF~crmiyhugoo& zZQ#Bpiv&hqK<(13I>^zJ*-X}*p`M(cY>!f^;Ms~Hce!IrWByT}GmF9RzWltoclTV> z51s2Cn%e-9xoocXv#S4-ESNyW6}t1&WR^&!yAFzcHqdu&IA9Kx?tK%E5`Y;|oXuv2 zvPfKXDmy{>iRl5cfsX)X&=1mx+_`hJ_@f#6=;fD>jXhc(5+E4^VeVXqf9~9Gq!WAt zA}}aYS4Y}{wkEvzlIY|a90g!FFatpqs=`r<5U>+7L01lT}HYMzy`puKs?2{*_u8$Sh&&xH;YrN#T@F?LU;!$pQg+fnyL;%w+{@j{4>Ib2dt|6#F1rc*?gzvU z<}!Bq<$QpiP&otT9rj?2+{Q3OCpE{l|Ju_m|^Nm2dP(Y2$i~tMwZt^tA{6 zpOWc)+tkUYa=E8YPUW-tS3o1bl{40&dWux|#x;>M^9wG5k1EF>Ei>rzR=!7+pFK*~ zDAh=*f^QU+6G-f>JXc%gy{+-VH{vJC1y+8#t!3!-7FIK}%nDzF)ciNfK_vNx@*oKr ztPRnvrRWOP6GTbrGz%!yO@}9;;TYdCNs@^+u|%Rbapn`+CZ1-aK+{mRlW&Jj)Je+z z-zE0!Iq|y_d$qVQz#CD0&R(9Xblr^LrrtQslu(h~% z=hpc;P>if0*fcn$@L8b?%sS4iSvWl8q)JX~vtGX{JZUpN&sGY%!$W3K`Fqi}v#k!J*jiUA{zw}45~t`G zHn5ye?}K#CU;ha7UxGdIDOSKDIhzU*aG)X9q5M5tvHHxR)vNyq$&o4bS^i!5{`23J ze}hOXA24js976dP?&qpio@9&pa}#^+tJjVfTp>0Mflg`5TnIyrk4#HFsDYx8Rh%cHNhH zlFkVGnY5DoYF8(Ks?%b)^cKUY()faxwnPWrEfJeWpbD8Ef&1ZVj zIdS)t&5u9+@)J+I{P^Rip1_}Q$tnCPDYy?`emQUoB=Y_`|D2pg!lIz?bUNoLwiUls zmX-#BdIB1GK9y*f05*d@1s8#f>)E31NzMQT&e9#?|ol-&qhY+ zHjlzy^-^iiVo@^FyFw@C>Q@J6^ov+>rUWU$rc)rK29*?A3%OlFPr=vG}hm86ge%ijsO6# zu$sY?(AIuZ#dLa3eNhg2Pz9Jc3qjv_V8T)MdQP8IyeHY;s5ztR_Vkse+9?9VnW{Bi zdF7R?4s}IuojG?&)1wNKu>69PQA)8D<;cn7f!-(H#yJ})RVd01LsnBI0lhUa9N|WK zPBZl$f;VhBo(_P_@icRr2FB$$hdq}* z&}szJ;41HUaDx4{RRh3oBFRu)(T6n>abfq8q zR)t{6=KbzQzZ3rKEX2&k)EFJ$&Ey%kGgk4{ro_Lo+8}<%k>a1|90(hw#R9@&faQ{7 zkyw1=hG;alUU@7G)gI0Vwn?&>!pb|DSS;A@j=H*xD>@4(AGvMM=qJLI&)Xcd1e==y zzZZT=u0J!Ysje=;P;I#sJg1$y}pq!g8jOQb^Z z^?e<=PSg417RG{OMDND@)F+e5uHR4d{Q1{{=K1prlUSpG!R0|sro)IkFr&UBsI7y^ zKaG$&^;PSKq6_;wUmB_OAx1OoxmW?pYYyWZ~c*_zTWa9i_2p*;M6=@ z)1DV_MJsH2<~)Oa4Or)FUH7tO-Nn_p+-g%SC`Xn2wu1+SoeQP!+`rkr&@{Md=cYmB zgJ`!!`PAHf&xwZw=^>o1A`E+ToZFi#tiU-mv+#egM&*}+q#RJ*tb9Oulk?|F(C`b) z2a=Na_T)(!k=4H=w3E}`6386 zbuD@B zlk$@KDyv6(Wg)rb$-1c5+l;T{i%UJi-+2p53xIC+#=K?|!x3DY2e2?4I1u57bH(l!G%wVVdT*1fcMNRL2K!+X6W2YWZK>>c-n5pe}bYqqC% zm&vB-e&c@knGI}Y+bL#xZsJ(95Q`O}yf0Kai4b0JVHjL^0um3TLlgu;eM;geNf$g# zmlhWxgK6H)dDankPw$-K(&Bc@Zui67|H$xB&<%I#7cRN*#ba*S%L(-axt~jGc{vu1qPh3xw~=SRJ#nxs%RKVC`7y&T}GB=m^cY1SyhjSxH6O?U3db2bm_mC zQl9K!7YCfmll1}E0`|bEznH?=`CL)^Nk#poI0y6+1^|EZZh{ty_#(1B(OtSge~h4# z#E9A%$Svp@K}>w$QlTA77ha`Ge~E7ccIc4extuAl|5Y_CB~S&Uilvl(wzRDM@13b&65 z!kDnXsL>P!<&&&v$_(`yOu$o_%=%L%;Q*i?a^pq4*J8|(X3NA@15!goU2OnsxJ;tQWO0ondMoAix?El_GLO+U#0N`07s^Mguudm|!G4b9 z#TMq{!RL+42S0ajZhX^tHj7P8Fy@m%}r3Z620)j35tqRV`}$+|-yiGW zS4fT|5+liCBBt>wo>(#&^C(_TEWx(-NAJHs+P^O`JU*O^#57Mm6&#-!4?gvjCLU4S zrs4+iYns~KXhgAcY`c930?TAoZUPc2Nvt9-25 z*OE@R_>|xJs^Tej*I>(m11*COwJ%?@ygk}l^~^K!+Rba_XP&8Q<@s9-efm87ScFMZ zQHA!w(Fe(y@=)oY@@?RJ-q9bEi*ZOwnRqc6@86Ld*xA>;vTtQ)S0>Y4T+zR>yKm~~bwtVymky4}<5K-(tYSUadZhKL=M z3#GDY$>7`S%ZxUPWMzjO%6o|xD)d_wV0Iz@!)B*q7;q7rD50=j`T)uzXY=IcV2WOA zF`AH)f(fS}FwqZpM$Q>T6cVWfz>2jPrvMkL>_t>_gF!D@XIT-&oS0)bUC-)}s?ta- zq!B;|s;1DPd=#k9sD6BkCF|q7}neYfB)d-RV z*e^*+LEA_w)|U{(SfLO@H90xiqZdv7Sj^8>N?z~7!F8B_TBZnlD--~l>;ROc`w zLr>ifph?uem{4d2@Ig~Pcu~BnB_P&5XmZxoK^Es*zHX>E3*<54Xf;;exfkegm44#c z=e059r?9T_ctszm0~aAW>JD$#S8s}o2zTLL%xqii9vpz+bB{%mf=<`6Qb=cOoudwS zEZ-FGQ12MtLk7ZaYq}^=#c^R__>sqsTRD))tg>}}@y(Q@DR>t z47pieqwmaVm43WrHSC3<&e0;bld}zARD#!jb-S}u)@s|jTNjKj2rP|+;?)by4YECM zbNg%D@tbQjO#_x1(b{j*KRipCGv8HL@0c^+^G3F1!Gacl+;6To(LKa-1pTl9nod1r zWGL8H)cgbzLW~#v!vgp;y zWi|eh!B~kmFXIii>YM3LlG8IVAjyU*hYhe7^QWh2b7N~=Rh3<;(mU%MUR4(@^O^$Z zseE#s&uKXS_@*g2yMdWLEDp10pJ|g4~g|X38n(7dq5K>L?-oyYfqZ2w;OiVeH&M_J;aEx{QUaq^gE~TRWp68rpi_` z&s1rYkfN&xwxEdqcn-AeX@LpZ9C84y^{1&iCWT}% z9d55Rp+l%vWeD0ei?&=EkM~`5X-mtcEzx=NhI6^-WwRrZ@V~J?_D1x%oIdPl|B%o)=0O9jc<+gxRt#|cTYrl zX~IO)dWNr;ED>{HL8Yj(i*RR=_D?N9#00GrTt0BjSmJq>fO@zMiSC%%R)-ALoZ6*p zq9%DJ!kq(MVJhwg%|T_M5CaJ$#u20F@rNNuV3F(fc>A_`&3;~tr8am$42nLg<9gf zAjOqw+#s|8>8x5n;z)_FG=Xir5Um?V4PaB<-3A1`EHg-K=}giuK&vt`TJ5w{Uwknt zQRznseu>k5F~-rISRtvx-G86<^7J8*7YI22Q`$!&oe@0LZkJQZFpI7-8cY2gEI5@n zN2%IYcemc;(vOmA%xwUwe(ZpLybwK3!lXL)VZO#2)sPeb1}OFWxdVJuwNOSBw;2L(GI?b zdw?H8M)~PkaBjh#!)$yJZ(!`gZJ4l$BN=Zl=CZkv_Ae`&kl8>ruTUU@ro!snFj!#O zKZS$*DUG?v<5K)*y3nDAFWePVL!Dv>B5jB&75OY zskG~05w*i2>cuKe){41^Agw^mI08uFh2Uu+A;h~;Kqv){YAbn+XeEyqMO|PXJ!&OW z1xyr3WeBO(4d8;nuqv>}G=g@OUVp#aG%OVpJMnI(rYCIKV0i%VBhJ;s7H6awGYI-I zjbSTR!;B5PN40TY(CGL<+K=6PIbh@^ws=m0Ht}5 zhLCL))4RT0<%r89XFmqU$(vjz@l!ncmw0X&dFS!e8=G6Y+lJcOhE`qP)^>SYyl~M~7hUv3W3;vyTfb?2^MYCyZ4}<@nz(0USJ%dS zCc1hOL#u|8No*3mg%t%n&O97NZrg+$jmi^9L5%YCQuS+lurh!?isHp!QY*+4|0H7a zY#zf-YI>Dm(RjD1*XGxx^lAdFKB@Iey{74cX&bu|ewWMks$WC;smA{*Y>wVUSB`)b z;z3njJ9pg_G@w8D+7y>bF$^I9T-kN)Ja|ftjY5nH1rU8RX)hq?8GoLWG|WeGo)O`j zX`MRV>!tb;xtOOH7C~ol&&WiM^OP+3;U0KFnqX_I;4#ktK7|L7z=TkDo&(WfeTB#X zfg*(EN(bJ}88@WSbeDfYAJjbHXdFe0-@r9`@SJu%kXp2Z5$Id&al|ibwBbU!eTaPN%e|ZZ+Med zC)tM}E3~s>AMR}e(g&d+A`<{*e33Mt z2FwW_q%M>K+%ZMl=uy=cVj4@oCElOx|I7p2C6C2D7|Se6rIuyjSP`PK98D^NSvLwx zCVus+U;R1${E_tX80z4z)Pl1X3ztKu;7B1v~^9 zn^(G+8!yV?uC7rC&;fT3KHx9=?CcGwGA@5L}0J z?{5HY*Fd8*lfR$|35!&rm|U`ImWqzvz`H~VE77s&y6D)zeT77F%g!yyL}Bk>YCMwY zJXlOdSFPQOYE|o!@nRU&O^Wg4!JxO8NEE%er~EqWaGe#fvvJELBB1EBm=5JFdZLmX z)0j$hEg+si1;b7-7_pe*HfP@JN_yq4L}aWu5`1=OpqNN@PNw38Jp(r5a3Ye3tP)lP z!p7QSU0q(ZUF4|ks%-qDE3XW&UwDeOk=aBL8#a0_Y9zxS`Fs8ke5n5g%BaFgJ)~@2 ziz}@flM)go#ZABQaXbkGW@Gjf15@`fL&!2hnqnhkZ)7qW8)O=nZG9%ARriz+b47q+ znIuswgrlVN(q18#h@y0;9@UMFn(!M(IuSYs2w&y1^4|NR0o6qfyZ5QDZyn$7GywfU z1B8|Rn4X~hAo?;wdI2(T;KAUm6$IP;TB3!jx+7z4#`{$19eNd?TPdFniwX~BU|W0r zVT-%p`0{eM)Z(Zxd14)C6%1=+Em-9=(v##KrZ%YBWs9qHU%7;8ea} z&TpEuMWNRkUAJ!tkBXa(78nhY4IBf22>wjQ4aU_T2EM8h1!FMwP66ceHmLFuMN`35 z69P168u6IOD7Le2{d)ed%MUjGVgA>@&VTsp`5%5bpT-enjA6(a6!|ravC$(WpllhIqi`1C=h~ zNvMWx_F1u^*r#6htgsuwQ$JO9FiOp$HZV8F&=gU1E)s~j_m*X$GMzkzPNlTnSA`5p zHMZ)TsU@nS@}>-&j&>jVc=ArY%hCukCJE4 z^(d!yBTeVby~_N1*-wATqKkj{%U@DEGbdBF`$nD1J`o(c-DnQdN;bZdZ53(u!5ML&>xi zjwhfb)UisK7~}wU128^GjRFdUmJZAzKvJ@6lTnJsu%v5bG|w2fL}8jCIgijn04Io~ zO{>Z#RhAi%HW&NZ<61%QS>{HFjn?V5bZW7TyTh4Lk5-HL8<)uvTwjcj1QCy;*BCU? z!~H@eDhGk5)0yqF2=8Rq4aUx8ZsvNo_4aPNZ);!QRyN+=t~}=5ytLL*>$-;7Dp`#I zIZhfw4Xa%9Fq2B})A@jRmQ@r{47jQ5-!x)1+mJ0T+UWaLYxL*m*YG{_WZ%|5-FnF- z*!0oJDb<}bfD1ulM&t(LP!^cM+}c#hov7`^bzp$v8z1Giw{k}jL_mbZuqdP*VYq+C zyThA?59tkIqY25(0B6$Z*@S?Z7m;jXz2V*2owFA&4lkVjR>$x#(k=|TZ;$G$YpssP zCXJ@L*5VSYDmx?g>d|lONRcGkzJ+mdEgu(H8yH3|dHt~%Lc7($TSL{oAnH)GsgOBy zf}U@@!CrF{o{GCLIa%n;X1Wwv7^4*5Nu#Mt6bmax3)yYpwy1CSUlkqD7w*HF2tJmA z3<>ukgeORgsQyM`xNzy`R(s#N#KwUMr!5@1w&n9`yFPCa9{Fv{s!OeojZ1D$tc@UV z;PdM0yq@gvaD$ya3!49h$4OIcFxAH(8!@QI(1HiN?3t&USd?XrY2ve%#k6U+f`hu3 zV6;?dQ@$9Mk=eMH8aO&-*EzkO1`mOJ=7k!GN(KkqlI#b3l;md7&%{h33!4-&7WQ&g zbKKt?#!VaaQE=5d~`L{>UCP)c1sqc!CePjv0kj zrw#Tx_@#-yItEIyQzf_a_q1;Ef0(e6vaYmb;S24M%K3_g$wXo-@{3^OB@qjNl5~vz zw`zp$k-;v(s6kr1Uvk;Hqwq0k+3gxpvN@x&%_(^-ve9Ie!;wFU#GKv;VkqKRo#6Sl zfH~QmE&=#xDX;=y{i>N*$|Hq1r7DGBimpR%}#8~`o=p1~=TZp}s>NzEti6nB)%XqEON{vu;VNMx>`F8;QQd-r3C<)Jm>cI2%4X=H zGW%3M`t2En)`;odf3A|KZ#CD|RJ)W-z7lmpzpT`Rj+IGlT6o#bQK=5pUEkLkX{uq{ ztHNcv5HnCQg?ZyH@qc990Kea-!*({)A^tb#=`|_$TY5Y>_LB0Hmf@=-%Ev$aArs;5 zQrD0Oet!_FfC=_8KW22B4skQUYNu?3c3>b_!P|MR6_i0^7JfvCFwVu~Ru(U=Ij8H*CLf`vH_h zRWScY?H62#hc>ZU7wiDy%POvuijfcbsWQ|QqB7!5X*;TWu&&IS42zB*J*uocIzBFZ z%cy9Lza3xl^wXEEdV0zDDkNu}lN;PTVzk_I?Qo9)?|{}=ZoA=OGEHCURrXr42R1y7 z1^|KawJTDo71+20gD5L6T0AK8?jFny3``6RvdrS^U?+5i#A;y{OI>y2Rq6CqH@29n z>nd+|hiAboz{wYV%YAHtN%_QT; z;$b7Sc_Sjj=OK20j~?{>y~Hid8@245%C9u{)o%vx(~M6mEGN&A^>Y~ zM{)E8tfmRzl%Bt`{z=q7vTQgQaTU9Z7W%d}WM60DF0O&fOLH07=-%do8HfOCc|7-w#3g1#`3 zL$NtZ@WY>Sinc@p$=-hszS+uUtQwNwNy@^BeU!7*1c3;!07J^d<>x!^2+`=zw?qfo zGucP8?_|59C$>a~z_riSMpb3_bD2?uL{kC6c{MyTEYO+hb>_1P*Cef^2^T+f=vDqu z`a3(f6^q*ng{_^Pc%1ow=acYU7X_=uuZr|{0%Jq{qrDT`ww2peuGL!7DJWKxTE_pe zb6!5l@J|;!m0fEn*dJJJc17A15?>ZHytq07_% zOzK%Mu58ei@g{c2+Xo*LGMiG~EuPGCQ2XqitnZq1DwQ6XKReNxxl6ut@Hyq_fq^@3 zxdqpxdvUFBweT%Skq(Rqs_sw)Gb8A zt!ZDFDZR6Osl*pyHaliA-I;7^N=8FYSCinR?+h1|(=Y_M{3(=tbQ+CJA6plWIkQv< zaYr&5Sv?*h{!x-+MUHq9f*Y2jfeT3)rEt`^GrLf6>Qp2a8(OlU*g|?z!waY6BKPM>u427yl!M|bRXUsMz;F@=Uw^^KIZ*U z{tjin(z1bqFJo(f*sx?q&auSYx^u z&>_{(XBh%*i2Djv)Q|@<02A%Wu+BtyaDD&C&K<%Va*B>ATVuVJ%)kH&$-eg<+N7>` zRNJ8v+D05a5q{A$1$k+8P&0`alc1O)1Q;0H)Fx4Mgcbnx?N|(1{OSJXztvaQX)ATg zDML*SFyOC954HbmapRyRW|=jy_@Wyxx~!9Fax2sQ-#>WNa@A8tlSQkXsun8is(*Av zTB`d^`s$9#&dcz<#S^pqjh4$d7MFY%3GTa+WN9up}p7A&0<9 zN(vNvOoQ?=iYc4fAS;N9#h$r$WE->FnC&R~Ue{P&+*D zh@sg{lB>xy6XG zyHm5VW?^Ks;of}7>O$GuG)m}MRaT$~lNkSH9-m;JprD{lF=ERKR4Dc_<(S(mJE1R; z>g4uDB86yFxVX`(?6-Lut!&ihSzKSA;E$F18k5ygU+=J*YV^nF6z1Ro+DLwQ8oboO zt6PPk2V`)c(QkBP>EFR8v7HYf68WKMl03>OBV`CWEzt9!&62H|y#}C60d*)$Zg03# zb{jQ4s;Y*%8NGtWV3ge5sCp(DjG$Hd{~7xh@V2TeUGF1Vl4V(z^|m6*dP|WNS(f#R zEh~zmI7Si1F^OZ0aY8V`q-k*75KMTKh9u3T8Jf~yC{2M&(~tt~Figr&CS@qYP~Vm^ zosf3gUWNk0FlmOifsbL@UVL)@wU1=WfihQ*qodb(?6ddU>+!FDy*)eopRt&_0VI}< z@C-B?TDA3WINRtSn+=`zSgb+UXll^CEO++1xb*sY2JQ6<)medd9wE4ES3Reo-(7zEpO<`LI ztRQqwCN+{7vdk!S%>9#)S2%SK{CN59uXMHbv$J~r!x=W9Z;~&4R(Hl9*6h7g;i?}0 z-EMT~Xyf>Lr$jYEAD)lc{;vTl_{NIST+{}J` z^UY!py*ba83A;eMoyoMkM=4-45(_uYwhKBh*$p^Rp5aW;ekFMZ$}5y6MX_>9bM*jb znqgrOqSKO$cYsd4R?hVO3R~8F6L9HgP|UNcIWkFVy%bC!kD5D`D?> z?I^S)MfI57_5md-v|e`E_ia8yLu|Nn#oVD-*lS~duz6pNMqfoa-Z$m(VSO%F-nKM1 z%HRt?M5-y}qcKK)4Y<;H_8NaN(m5oWkay#U*`>sapPf5!Kzuyp57|*0!`|lzdr=#4 z*jr44{#$K!hvMF0n?2+eronM}%P;HHCh;@1b%Iu>R-1IqElgF*?$XtZUv98Au}O1X z9q)537;k?A?>YL&C!A-M_Vh95`>!iDZCbJE>z!d=Gy7w+@74D9SAEUmo3i*u!`N7E z(Kot0zS_9GM>%e(njG@^kV#E2|8i~{zi9AE1<1!*4ThZ;l#o@Dfrv{kS^bEo zN-M~7SV%M^9gR|mr!(L~SI}bIpG;Emfh3ZqO7Y}5UbfXPO4UGxw(eG4!@HD!_-=!) zwY$5urA||a$FjuQH~<6EGGg;BS>m%vOG#cy^Q;d2gk&i?DdMWa`~X8twHmTC9}KIK z{8b_9%mV8iJegfcM#xR>;d5?mFd7})vOXHcgB0TVu=SC}uE}mb5c!bIMAvV*JQ}?m z|LR$Te{5OP4UhmHQva5Y+e)@giZUb1JsiF@?tw>z1cgTi*<*o{MrQYEB%9OFkz8j_ zO(OP+BE+F`q2WwZ!-!Nd0VyY_pKwDRd!y~r%jg%EUD`&u)1;e8xX*f6hGFvY@EUcJ zr+F;(9%LBazFu492h@>R%E*gQ7~@e^u4LQXn}CNL?E~EkvL_odG!M177x_ zw@W-?cFUP49_wN=X16}9cw*;qvzf&n6)vyzpdqz#ZP#*;bv@c_2tW22)BeXE!~Uqh zNb^KJ^%uTB9=i(2YE#&sjG^R!zpcq6zG8OEma$VB@wSX0i-~UvW5KzX{UMFR%#QeX zcZpGE$F``gqL7hCV9O>r?h85(4U0}F%}5ngf``rlM=0{o3 zatA|tIOPtTEdWfuCzorTMtf4HHD)t{WsXM7JF)IH+DGkrJr+jcz`{Cq!^gqDqy7F9QF;^2+^I^iz(ryV!VIGgY2$>B zfDRJs^s*suY;JB_&y`npUvWh@EnjK-c^mvb8A6N;^3xd<561&_sR%|x#|WD^56y&( zEgo42k03#wZ+{8mD&OVUML*`14KzC|Yqc!kBSj{h{)o)GH__i6fv18%%dnGk82t*r*f#TV+;?e}FF>g+r9Au8E01`^|68?ss=~ z_QqmvtY5a+N!27W_T1}C;|_;y2kz)QyF|-=&;V-s6%FrXrl#`->$~rsKko?X zG>!W3%4PaSRI>)evPEyuqU;t@afBoIZD-TFO?co%*NvZl#&2u1)v4|JC4T=BJ#d)L z=D=R#5`$rhajdBskrVius%(9->Eh6-K4Q;N?JB?qATP?7pK8z08}ecLiAVyLm69+~ ze9DOX3#il?4B9L1!>1i6BZE2s3KbX-tVXNg&{0`un^uoFQOKx^A!MqsI`u~3NVR8i zm5Ac5Gxf^G`UbT^fr2o4%SM}4CR3=a_Gqu)rjoJS1Pw6%dRsGP@JjMjx(+IgU(8}< zFQcq_`kXJI0>LwQ@S#JPj+wnYB}}h7`0&AXd_mhIdAb_%;ERZ8P?VvD`7neQhY%B% z6nW@`jCdYS9i61$=)#Bx@*8{O(MRiSO_j15O*Zjc@7{aw$UQ`v&*i@)2h`lhgCd6I z%8K(C268xIdKb@BG$*R&hzdkt=Q;%klG|n$zr#nqCivD{!SXR9S|j`we137BdDj6A zfzRg9hRT$=Qd$+JZ8Cc}3pfTmY=woIGyp#tOr1h@f3ReAqY#|l=rD#I-jL&0jxgJv zOcs;Eh>kuqiu?Nx7X|Yd{3UgJi$9?h|1Xt~`9^CJmvy_B%nf4Q#I`LHJsvqJhG$riSCbjQ0EbB{swNwLRYBq_^KpivG>j zYnZ=!xOq3QOo17%N*7VWek8pNx&VB_L|;{AMnducHMYwF`y+u8#j3r@1OB<6>ojas zqkU-Z9shl~0hF%>h~n_=nUw~K$-Ev0r@1*89~+QCdRA)iLuke|+vwt18y+D#_# zPU4)n0qATfbB7vxmJy8j`$?hXEqmsc0%$)@wgt~rQ=0{gTG~0Sn)eMekW{MR$6AT zZEaB1Y5rG8sctsnz2E8dU#Mwn)_+rr*8ZlxxoNdlUElEFYBjmz`8+JiBbw(We?06} z-e&^vlEM0ik($6AD*e>%k{Qh>0~kHz zM61YO%(RmGmbl|(+$%-1g^Rrq&Z@nBbuJhy6gC$CTQ!^Ixy_)|c*qMoH5x<3R{lCg z1WPZ-&6<3##w--s1j{6Xjg3LV;jf6+F&VONvHDN3zS#VO*&@uQsgq-q_4UsJA8?_j z4afdXFgX)09aDm-!wBzgdFUphgxn2KhOZLHZ@5r85KM%%6~lNYGC^_y+xtIXigvJo zojqX>I9HCZUNtbXRv%m6QA`v9Tay}7|HP{0{q~*Nbbh?o8!=lQ zF}tH+vx^_d)w>7QuLo5v+LP=K4UX#tXei{>pcai0%?&hKGGzJACEN-i={N`iTj#L&->HG*_cz)6K7=>fO1N4!tzbp@ z7OOuO>I;YaLOH)xe8J`oZ5@ukij<9DPJD}sU&Z~7+~&TD5J~6UyUnP(zj&(fpNc+b8 zqJ62TSNo_~7v@+cOurTu;QLHLfvTYVI@#nfZF4w!;>1qu64ua9u}ew)IKMH!vHg)p z*ee11*Ya10kt_0FtL%}t{Ytd`m*8pCVSKvK_5pC{akmBFwkRZu)db@nG}4I^5Wxcc z>T4}mUTIm|IJQRNz)k#~)1A2V((R?a>^oz(7R{rh=Hjhmy<44*9nLK47fx0gyu z*0%@eMq_9j_PMpZPY*?zK6bB&(IS6?mk;y=vI-1rCe@7>tP5Ny(J&f1BwM-vp!=OSrAGd+z$GC{enOkzvPfo>dn zB}ER}!M6+L-BNMi&FjqYee@T*RI04PtZ?|X$?2q8;dbIpR;B7HmL9O$txltvJxBfs zhdCa#hPpBXU`R)Kj5uP)LrzCp`Z1E2bp1L(->=XLfV%PxrX9}llF?>^D71}_qrL&e zq!DD1w}VR;55Jelki68Ebe>XdM6&77mk2nHQOTdR7`dRfrK&#C^aLvvaOw$3OBC;m zkHmE&Bf4~de|p;3aEymflqNF_7;XXpC?eT1*kQnf z*_Eh1(!#>Nj?Ecc-t=)C-V3Rjt_=@zhxxtxlWCWOG>>t##gICR43y zHE$Ow&oIUN*aS4DD0MBQI&(BR+MI;d{2LSEXt)C{4V8e3cabB6nB6!!2=bJ7MoTUI zMk=&P?vRWBz|nI;)E0C@Qij#*wYr(O-yTt~*XV6Yr`~Qh+jRw9Ld}}w4@tA1WXMG0S6L@ zALR4<3jq2=N|9s7LS2Q=t=b1%$t(d(03et+S0thS#`GF4YWy z$B^%ud`?Z0XSRpyJY-VA7U1T+^ob`yx)4X{!WW{~p%TfK=`Eb)XBL1;9m+^ivLrnV zQQ^A=yPH#V~gH}XH&;2x`rfgGVt*n0nXJ1FFaRu7Y#Q6CH&+NAigPR;XO=PKleC2*$3jbU|Lw8o_njyFWznocCmYRv*ufv zV|mc&3@#U)t-@Dg)MPlM9}d^UJ@?ZdfPgzP$WAd%x>2 zyIXV~PM^Q%_rPdSkt47M1;qP#y1b;(_p@(}r zI1fA;9;g_lM>N`Xs$P{23tKqTA1xH3xe2&dx8-PcN6~KFw#!oLZ|zVPD&m zy3P4ssN%i3ZCU(|ul8>nGuq}hACv5jO5IVOYXD=nHqex^_~IbiYsWkhV9y^uEZ#LR zatBjP&%C`SnPjJTe!7U-B98I%VB(ErUNy!UA`Dg7D--%o0FnBYlou=6c4nSeD5>GG z&Z=M+#+wwqvtVY!sl%ngA!Hx-lh?CbGhx5E7!GUFThbc2dDp|R?~uxi7v%Knj!-ac zebiyg8U3N?`t8z}dnNp~FpRH4eYW1P*5SZvyik;oveL2?Dhw8aDu3FT2a*?y9v`yvsfZpA9m906wT~5zMYEy5AhU6WlS(Lr2y1J zz3dd$h2Xt~-`;%h+>1Bg%i8ZP2uJR{`L~7p#5W7~wPUSvER}7*KZ=xF*fTW1>F?N_ z^6aje=#c`u<46H(nN>6GGdKN)4Pdcqrt<%*A+K(LWYOUmQpgZ>RgF^i=dIqWu@-CQ7hVF-oE&~Xspdf# zV?K*ISp&$XLUvGD;o*7)X%_Q1hWQn)h|uq3l^=IjR^|f?5J{5aH2+D(FMgp0IcK?W z#IfjwJ&d=&GCePq9e>UtCA&y37itz2Bi|yyq>x#+B8 zQ~m?*2j#f5kzWNG2XNa|rSKr|jEr3arUgDY(Df0)!sQ36aXIOrU=Kzd>^U5u^YyW@ zQ(m1l==BccHs{+=fFFF zn)7`7sLO@Br52)|JwMeqd4!5SvsG-Dc<|oh+O>RKm-|`ye2{jDp%XyXD`X1)<9(BT zQ!_J_KW~BQ!fw3x-h0*-NibZrKO7kD0fJ`nzwzDuB_&GUdrzr^-;>{CL9R-*JW#QK zMk{%8Dzg!0bm>x3yYl%9($mGB2XBE++`dig$c!MbL5CMOGBXY>JB>^#R4*C1zR}@m zynaNmw_w@bjrT3$dmtW^^kj;O%OJsA#LY$)4fKo!l+7YU1qKb`8s1)#KcRJD^z%w5XfA3aNF3<+6e8iVZ$dsLxkTnFH@A4p(>`PrN9ZJE z73~QdkkqJoed_jT6tNsfG-}pr9dLLU9d5}t*WOVUMgI*`C5Z^ZX64CQf#9LNx5$+xiv&6 z+Oj@LiVZz6D`Ds$;RwAP{R-ezk`d)qVIph{RYAuL zP)#ue;w1I)#G-e?k#4ayBeZl=qTloPw6;z+I^MXqrDeL2wdxY3&dySz)e{3%rH5%H zkXVbi!vkWO8jg2c2_MXt;F;3{k>Y{&N8B+rP2lB1uY{8fr5epzp`BG;W%La`_my9l zGeaxoRn#KpqX-BdK_)2bG>TgB8|(ziY&JAtRmD!=V@-oneuxESLPMQQCN{GGK2p^R z>-Hn3PrUX36Y%CPv8GnhP+P|Y8T+kxb8W4rL6FH1_lgU&N02Hr~`ZVF1e30gF7A2s_n=J`A!z7hnf=dyu3GPUax`?I2`St7b z;WX>bZp~)5?xsb~Ju>3u4>v#%@eQV=W#`?WwI)p)n5pNw-PiT-h4_!2k&()yNeV>B zxv_l6?GC}=8+4{e^Fh1X;m2oTui70IUjTy2X@z;iU)TgdSBSa-bO{I!vXyfAh__3_ z(%Q6_5Lj4$G2}4PSMVT5{25gy*mVSWEwkGwXh1cGM+uHoYy;PhWN8TF^f>xrlIM35 z8VmB90*e+xokFb8n3e8OQ@I}mC!E6drK$NNCpWLpY+KgjcW6d?hBQgnvYwu0o}^}V zXPev7+8XE?UJ-0<4X$WwgoH9dg76o1BfT1p!trd_oz(11dsU8LZa5RP%Z(6W!K^y% zCTb>cQvJF*=?!Q5=+}Up52G?HoGy3^;2E73*SV#+iF_H2h^5hZt4Ux&lwm?cwPV~p zCK;dV5v_wRh-?&^{ynp^Qe~Cg{{8#&4BFq`!rr}wAHdypIG>;UPpFx*>@Y3&A#Vz= z$p4(HxeU0JJE76^)@*}?A@OU%y@)`QQbG7EG#7cXh?WsrpQ?7|0 zx;EOGegdDRCF%2L1^NylKg7W!_#Xv&kp@iEeb}BQi#<*t+?Tfs#(>76S#hbg zLHIUnhy)s}kznm@iXR6uEp^LQ``sy>U*j_cbL!53)zW;K(&}QKs7HW{(Jo$StP8I$ zW*Qshjef*V8;iXyx`rj1t7MwSP{h(`(3{p+?sB%)wyj>l}Zm=3!|6bm{YHgQ8F8406=&dq&wA3S)sT%I~w!38RW@E#4^<~~mG7fdb?aVJR z>z5gPt&XC{(WJP)))=v9!^<@4+RvJ4j=bEcT@Zk1R>At=`sC&X|!?zCOAsz@8f~67`;?K!qE%LeeChX@5>_=bb zZ-Mk6-Zbb526(!7uB0i2&O#axJ()IH1btX?M7%G$e)Ib1dF}xsFVK7Jc@T>MNh}`D zIFoL7(uwRanp}877|9SRe_hhc2*(1o4BD&#nXBlA6kAI{=VbeH_aDte8=4W%Kr;hG zh7>AuG9UB?K5eO8mTd^Z@6_v0$WQ zATZWhHZgh#?ny(ro4LpYA$Q+&v~QY{?V_0sM;K3YlyN45oIN&1DR(xU;q-Z6Rgkeq z^Ce(wV9JWSg(JNkJv|)+Fur-smNjeW%^IxWO|R%A9%t{#o4dW3C7XL#81Fd<8E?=q zi0S?rPQf$dh-Lq5*0&bdTtxynHr z$ikC)CmE2HCwpJiNDg$#c|Kk!NRKV~yl_O+xK=$S9=aFuW~dMnlC zL`<{T1)PTi%n>ooOev_>XBT?h6y73!OJ`uU!}wu+JsU>hhGBJh*y{d0=7jnEn)rS(t5by(NFeOF zvue+%qyfLAg$^p& zx&?vABtcHFsRLv zl{e&+`m}YZL(^zz%t?AxWnaz2DX?g7i*g7M@A|}D=gBE5WeU9h=MSR07LQ7y3d|=f#>o(?I!-a@)wGjgcSXr@yy;w2|oe zZb1LI8eT#t>GjNL;x=ahXj?x(2uVwVqN!!NI8>n_LOtTI#{BL9=0+<>UPV9qT{x?^ zs|3HjOA!xc5W4o;GK$lY{;{w=>d|B%taF zsg$Ylaqx%;sBW&&Img%k;)v6zQOh3{_KI(f?*uuDMm>8DJX>z})Xb=0$;H&HtWT|2DrBPHd8b;eMQ&Wb6S|ti%;rf`XW>5V*0!F zA`sQpz60{bxuNq)Q9qjV=3Qz4moD}sB;pAub38Ty-54GUsNfE(^|f4%==N#L9VIJx*^eBP`cd^1J&0?$FoPNpD!Gb(hL)W9|g2>iiY!P zKUGn~fgE3)GE^Mlhp}hU8HdWh9+a6d0Fdss_&EMPD(!vM@^mYe%WN%3hfIBiY=i|} zx}I>jWPj7VN9MMSmV`L%gyxJ|oU^lq7he?rkbhA)vTuC<_&!$u$SQUN=3p8h(sn2l z5FRlAJvkOWMP4TI4UrY!Y5Gp?@sj%mckiD2O6=g~?ATbA{kOP!)20VsJd)kC2@h;% zA%6hdA^#yX9?6Fd_db+)4=fe-R?>UQo9xewG4p7qpS^!hJm*cPy+TcXvpzmL8rN^G zvLDqPuZwvO1aQ=^P+$#!Htte|$;#fh>7Kj&Ih`(~7vFr|r~!7=8+AL(&kINN&*Jk= z-BSH;UofdH_4*Evv(@+yI7Xpn1o_S)&v%AVf+650Op;ia@Rd^G=Wmgdd6zpL z?~TXPjzT08R|ybzs;u9t63k(vwl~Hh(;?({0fmx==GH?^BCnU;2!yPazy>Ty=bVe5&_TS0=>u1YTRbKj?b@!~P&D zNCc6|{%7|)w0sDUPu};?P?{(4kpEkX^Kt1^)skHKRd%Kbio$+r*4;mIe`8~*@poU> zv8HS8HS5CK2ZSA3e5woUirVLo;$;i6;&ey(n3ZH+1N>vuH%V4`TuO?zQGgfcz}*gl zol+^q(P^*sG*XL3MtDLp@+PN+7OUr`k)9De_*km3Lk6706+sNkK*)5icP2r`1hJ=3 zMtLll`({#Z3oqUjn2qO$!lg)jP(Q>pMRRs!?wyfPbn*qk=GZy4%V84&BZ|!{Bc*U^ zSw26I%;)_RT_cB&h4nwq|40XGtJ>F3xpc%nvIcwS?JouFU`JL*aXiErK<7r+rxVd$ z{#(4GPiaZ!Qu*7&uk7|gn{AK>etRj(IQKgL;91ryK6Ajn-Hyi~?sy1C?1M{|4BEee z*!uT)Y<-QznWB%DED^s4qJb~i*4Ywvdjceliz<}?CJP6rbb*-JmfGx^w87(1BHi@!V%wrJ?cM@ zdxEde+S3!O_hf}@{d2$eb<5>yg-l&1gVd>O5ag!LW`nW8U{E)B%=Jtuk6qS! zlS?ko4#ZSF>tcUd?_HfYx!0_$uV1;wZOX6qN_|l3)12FvG)IYT4r&rw6UhmUI1xmS z15kEhAHu}}nAFfiKb;~(RJO|qR^%yfQLE4!wNEh(X3)mZ{PdwAeIp7M7z_$+(fgUc zOSGnRR%;lq*zT46p)>wZ`=iO9`WE%EKf7NB>}O$o{FC=RKE7(4DbkMn#V9dV(Ms6%Wny<4tmv*{b%_t+XEV9Pvif~!dgX191VbX&o90G!E zc3)?oaXR_j3uik#g(C7nf2jA#h8$NgY zzcPFFpC4e~E^Cl<%n}bK*JrB_PKNE0It%6O57I$pv!Y6TR!{&ppBoc<$Bwf5fv2xJ z@Bja8B>4X4&VGN6{V^-12*?a!-C`~JXr2*soMP|bS(?D{@@sWL1kqX@W`co^axOTL zlnEt87VqduuxrhHcH5OBPc*Iswk(BGT7|SZ@0N_dF1L zEXRDReST8qYn%l6^e|%JVFfIv{4CoZBy=Ep$m*wAUIsPy^%5{wxB+s78_!|42PeIN zUN}#k5{{InN`CmG3As=#&LJOm@b0+ zqKg~#pTCRkR9_>m(=Fc8;-2w|-NO2j9aMFS8NxiuYgVDQtO>ewJ&sw@Ai-cvYCdIM zpv}m5H7Y>JJGuvz+i0eb#nt0+)osy+T=XRBL>?jEbN9U%^5i=f7 z({~};*+UY4q!h=xm?@1gtlS15*+!#@p76cXHJpF4A3d?{36|~co#^Y^*4KBsw|o$nEm}D6^cjiy9vTn=&+T z^4W7WkQ@URAFN>H$bm+UY!jM)U6?Q>(+bo>KXUKvaw|~Y>_wC{cbaXwBC2Q01#>nz zptCB*8omQP=rlSBc8z~Mn-04&Yu^$M&?dTL&NPxY6K~|3+G#l z-qS?3Ia-vExk^g*PVr@}(t`xA&Wr%K4|w@@XS2JrncbPpZf4B#(EgFRw=!>BfBp3b z@O)z%yZ-t`+a(?}?#rOMiV6?te~JD(vh%=kTDhG z!d)Vtmpo?p8Z(>O!p-}NP0Qo4G+u<^2aMva0Bbqe^G-@8_S(!kJ+fpRUOn;53pS)- z1JR*TtMte!E_$utv{j?Dpiyr&+Vz3}vMU`xv&gXV>UCzDe={=m>}KO#TBF%+G-~h5 z0wIbmM;u#F*iEh1Y7~04Dw>2p!mUvVHn~Qn#`Y*(0lUCmVFR<4)(VG3JjUN^zz>1H zPFX1^Yn7HH$I7x*;-G`WV!>>HL^=wB_8UA+nDbd8dWMOq^-7z{0p=4bKl90TfJFtbnAZko~eHSt#@n8^4Fex z>2`6ywsFm+S8P$&uB?-Hbtigc^8E=6weo|GM~S%f z)v!lyKrGD;y_Isc))8+6a^Rqy!zT-0fdWVpX-SD%?JSP|2IW@z2zXF@=mTXiLOjrI zfdp-3oNNJq3v^ltz)oCt#0O+y&#mb-gzM_UdM5Z~vJM7H21TiZ35jYQ*2v zD-J2}sAraX)j_4$%anT#-w5LMOJ%Z~JmcGZs516xncTC_bCXPVDgJrm;l27h@7&Mc z+`Zdb(rQaZp&-cD%jJVqb6L1wp*Sks|DIZ1dAxV_B|$EK+4|HAFP>7X-+udLxmV$tm`mBg0|GcyG|Un+kf99iq3RgaQ? zjIS>7c-F4yphtBDLCggAvT33gbxXsaA@`wl3rQtrl( zQ^?~uafR8b5bT1mM`yFTt=5-gL&^Rwr&YqJf9U=duszo2?dDopM8+D_GOtXi^)@sJ zky;tVK&=o(G_MY#OAcqaMh@~iL8^c_eQzCaTPf~Abp~Joa7kZQ z^^x0YlCmlmL?VElg1WyyiAPf0%pStiDZXxYfcoYkSk&*u`}^blPbHIEABf|lF8bmr zv@c!51^b6QePjXAtg>K_(XO}^WIS3ZTV3po_$2FJYzpPimACf;jMqkNnMaYCrKwS9 zvJl^la#s*9JW~krOc@9Xk zYzxhu#&0ymV#DgNZK+W=Ua!_!?IE24HR1S2weW}XelGc+2%lkxCIVfwtX=?jjMPCK zMOEsC53{zxgY-efPuTqc)Pbi*o7-x&ZoOl|Y@W!uBhegKPWO+!cDvWD*L4Mj4NdkY zJT{@cb}v2KBl!p(?czT1-`K5}`9i@wDZn_EG&t9faBY|z;4y}<5T;8<*|#EOv&jt| zO#EGp8O&YooIPS~vMp8A)m-TDrp-*>A->bTzCCAG>D2as3%)ddZjv3_$h~Xr*v+E( z30D!ljfx{ce}x{)XhFTjRrzoc&+${LlVJVdsuzE>UZ+t_v)89p8vP*m>$P&;v^T6C z@xGHMkun4bNrRp(qowp7hr|1OrRHgdXVQ>E=%ZC#(fdhg@M*IRm@FxnNW`2JAxL#b zc>&^D9(;h$se@FG%^z3AH5Z}U&@{HIN=6%v2L>?|jRodFb}h=(BS@!XJr@^jy&?zB z8fR5qWvc4hi{ixLB|cxG9q@Xq8JUVShOfc+*$&-ndCjLFD;6D=kD~bjl7OF7xil3; zJuYy@LO_y?1RSCQQ~TIfK)liDO}3fEb5b>SWjs+nqf8s!>`UZ#uSGgTxD z)(oR2qm$Kt4~3}zOlj&~tIE`f6!}GclVZzDNxJ|g@@=`{vV zJ7!qCaP8lRs#_}1W(;IN`&$s{;bXMCKND;M@@^pd_mTY}b?VRW5H{8)>~NK9 z(Hw)xGUXw$Woq?JmvUte14<05sQZc8N11@AIl=&;T2f2eB z$#A*JFsvzM0^>gbJt3}i1uQOD9v%?FK~=N3k}0K&oUtW$-}*u>IEEyzF>lA`y~d{H;$gXs6+jI1E4|*2r%pVj)2G>_Ts$DWRt)C*(x?nJf=Oax#OpPO zLogoQg!_5%BZ^k4Ju13~Cp|Sj^0kw>W*IUrFwC#M&y(PnR$(RdEEXlD1d^$*Xv#l#aN; z7X-A8T`os0Rd*yU9tY%q!XKY|ixnY*quxx$%aFqB0FeMyYrzXWW&fMXZ&2fim~1ieS7;Oo%1>?wuIytdu-EQkjmn2*OT0_e z&0Tug63-I#Un`mF2rzKX?3!k`Tilz^@7R9>e85NhA|abXrHA&W6&xW!r9k;fm|>Kk zuY*=SVrOlzjz_r4Gz((p3Uc99O&HHIZCUwJ_48 z*@s+HLa+Fq-g?^V)iEugB&YSFj#I?iSpOY&n8R7K*=)>(*^R8RiFvHASPkNPO--*f z#f~-yY_>r2AMvAX*krMo!r5|Pl5)+713y$jb@4Dh?;+6HI$?;?2%gXDa8(33LQ~+y zI560k&BJ9>$n*^!_&ESSC}qODxROb~e_L!^`0l_L*R9*ps`Ql z3Hzczy_T0&A;`W92M|Cv!$hq7$DZ{)4Ti?{U}h;u6P6Z+yT^B5+kHiW-IB{~a@m)G zB;VZD-Q89XhA+5p5Y{)lT;`BrSF!uLZaj*+458Ld*{mjPj__+F*+qo3=Pd1pi%lTt zrUZ9JzCXDn;SQCC9N`zSN>dp07WAU=D#M5jrEwBgzYE8O9O_ByG&X$>l@#sqp`7s4 zB0C9Y(>d{ORtowBOf7CRs#2pwoJ#Ar`om`n1%8Z=q96IWJhMQ1AfKX#C*WNqB~fA> zO_WaWK(_nK;xllYX;?3o;*W$vtS}__k$Zb9JsUOnwy}}EZ4|$^v1{W_X&&2%{Sa=K zSN}j=%v1m#K1>f3k4Ly_&z?P@(b3!S4DH!_b|QF~>4fP$dxN7R!QjYfaPQW$+k$s9 zBpZ|dA>}AiehsXYMf%60ig`YQ1Mz|^CV0zk?;6i!#&;3tL?&Dcg{YotxFo)viS~|- z^+q#7zU$gufAZ^Sn=rS&(??9wmSudnWF6mxTu-x=mz zz(du=P{|baJQ24>oD=X5Ts=aaE5Wruot#@n5NnBNvI7dgV*TEJwPN$2Mn2}|?+5pz z^t*9pW;PbXE0()kCwoh`U&1!AKd?=1>5cgC406wASvVG(#Y!y3{qB;Eumrm1d@eD1 z7IqJ1VczD(IKXH0B+Hv7VTu$|?1udRU~@(3woz_{9RvF!-6-o&ybqx@c&7Q1J)eOZ zA^nc9?(~~8s0RawFuc}|lO&r+UP@z8%IR|O_%JRtEJJ85hy@T25*+m0LhON$DS^UH z5bCC;0ANYruTJ1#=6>P>{SAA`B;Nhm0i8zq!^i6C_518Suied#TU_aW^_5p|5)vR# z?}Ur`QudY0ZqYP7{&e-S%UR@>*TU%OW`e z{5Y9@xKn~j3T*~z!vIt)YNjS&2|H6%Nh?JnH728P&)uhqS%VsF5+#gva`ADmofW)J zy8|qCgI24cVwq>3-4U0E)U$^NnDVQ#2DQOqxJsoAEpaeRl;VwUrv^LvT(ecC5?7}f z*6$k}q;^}-R~mSvkYBkJQV-xZ_sc+7i1C8xhGb7qGh8F@sZzhOcf{`6o%=Ts z^s@=FpxfI=dQ^iORB*>vT@T6!BVITpj3UM*F-v4o_T%H&wrO0#g;~p&0UDu7*iA|o zOh$=@dyt}v(CinYiCO2uO?+!%-T6R#y`IJO>&yE7vJE$Mqaw(n4AC3F`sZwQ;nwQh z%$LLi=xn{Jt386lUFcJE4sM(UUAs>>2N^$n5;BMg!T;g{_VLdhx0?<%cM8v(^L8An z_|hjHYJ~qh$AA70-4QxGe(j`OiYCbV8Wn1*BMe z#aG#bbGr{7gx6K5iCs7Xw{sd=6PXQ`z4(ph#2Pj&csTV$0SWYzg z;8XMyGy7TLvgO6F{qpf;-OK!uVt(`1k=9GD=;>cM^yz4~5DP^1ZoX>Z&C*Is^Jn_k z+FE*q*`+MD(QdRmeX&a;{mpHwu8g-a`SR7Vp*iH;5=h`3O=tgR*{$)TYeI4APrMPG(My2-XAdoILr?FThcWSRj{M zk}R!M389#=4_jI!9q4>Z2#?jN#^DbZFxXE`f z?U$?^E%_8MV>eN;bi{8vQ6tIcvOsA9Hx{1gDQI-BH@*FXqcGRfxB;ft|In+yusyr~ zS+fI0mpm!46w~#4YC&fBRQ6Gk?VlzMQ0!Navv8nR8UH8kahN%!WV;WR94KX`>bZ!!1JR*R5X~ zSKjRtI(PX@>FvLIBc0BC-8?ij{&kJ!E55lO&wkzHotpYT?9vzw2i`u782dkf=7X`( z1bq=+R+x>9jFiWi@EA}>&kYTUgM>n20AoqVQ}G*EiCKl=WO%*d6kH>uRC4Q%%0gAe zWm^z`C1aK>2jp91C_ml~innZ7Yqr|Va_fHag^J{|J5d;R$Qfk&k(e6ugVQR6gtu_^ zFhV7GY<6QNB7^)P(3y^y`$B21w@JR+7>~O_Z{vapGb=7Bt}@ZHLtUDWTu4;y-3(4m zNMIE z?!?A;qh_6^(N4}?J70}&Ot_WJjo{h&+0s-nm|7|=%k9}MTrJ$g^<)np4Jj8iSD^Yp zk6}rmqf%qStO!sx0;%r)?|tukPl<0%Tz4J2+&dPVo(`^QAse`5&7i++c|JBqN$~9b zzkT}Y>#mz%%|8F=&C{bTExzlv2JDWerB1)MWAEPbzIWjIZz*SG));)2TBu9ZToUFk zo+NrYDr<)tv{pdPA0|HrNi!=umCFG%L1Y@={QinZK}Sj!)ZZGtFGEUI&#NkAaG9XX zuEe=j?CSvf!U7c~%?89C$UQkxSS6`wrzMJHmRM4T3y25hj{g4*qjC^GrE6M2*n@J_hn41*QF(|z||hqPk*r-T_S3dw(R zw!7<>Evt98vu~NNULoGdzPMtur4eyHl2NjG4zW7K*??Ry0I-T938b22CRaR>!Vq*t zP3EVc7Q#PLtbnjdtqGP?AM&(f|yaO$gH{mjy(>8l?3%iiFI<8)pMJgfOc z8!^)WRjv%GQttiFVXv`Li&HXCI?sC}lM~pUy z!)839w>iWQ0U5>P+@Elpotc>_xwGbN+sxVC483H$-~zx8xLlGr$myEHz+|;0$_u?a3F57lJ|NlI04>`dGV0vKp@y5N6g=T;eQuUn@ zbEkyY#H{xer@Z0w&9~7XJQxkIo0zGNB~YjZM}3B9;`fRl2%aLX70>OXYe;rW)$e_Y zI%e`&s(=4&c>KjP#s8?rb_!@|LjQNRGgmdy6h^O!Pe}}R=le`|4DtEB5Ya;voVPmJ z&yR$TiRVdXv)j$i9b$hP^m0$qanRV6+DZkTg;x|ZR5n(7@orG<0s2I`ywSzGGP7Hs zg*!vq^1!0~CB;3@K8O7**lLp0SunCm69Qh?0(=N8<@tIBC$??fx@}@{p!25ho+N`A z+ba8Y>!I7B_wfiv7S3GM{%L{A7%<_fge;>cW$lP(B-bvOX7ndcgo?$`i4#WQU#c9u zVA$C;5lZZIQJ$S^XCgGQt3i)_Q5zL;ZTEw3MGGlH`y=2BRarN})etzwz1n^-K zYqy#<27?<-KN^V;rRxrpMGD~b%533f*Q6T)y5)*V1$h@F9T4* zXSa3)PAr(HdDSW)3S#;vtf=GCYqJY}r!i*pXOKARw^e=Ybq3QwJbAP1_eR6f<`{~L zHM{Hvldq@PNz z|2qb*78I0HJzFnQ4QwFOr7q)4EUJLH?ikg8vJR!ctH@uVC zD+#gi)S`5<_+K|-(=2i$n&aYa1LlhHvT)qYMMrD|vpUbQEf-iBVD_Dn7hjC*6yM57 z+msHR)z5GFqGK*+Bg}7`HN~hUkhLcaSNQ5^FHRSO>ePu*xWmIyefWrX;;@$_LZf}my6H0hU82hw7J{FS?((@ z&r^hzZQ%%_>duT#LiKq-@hNG%u6ZlL6%^FS-_^~1ptD-z?75P(DhyX%h1bAka1dYW z*e;!sPh6sv3a|xF(f_=>4J1E38m#hRL6kfy4PF3QtMGyyC|zF9aO;g8}ISf)32GS$% z&d;LaA0!LzN%4%`>UXB8j;`?2%-nVWljmJ$Fggdx+Diw;mr!0xr&ggJlOFmqweN*r zVeEZ?Bg0$>Y!sTcm7yCW*^T!rVYp3Hw0$mpQYQvpVXh93c+%6sPWLfyU!QiOOEj|g zPlzW`rHjvLlCIGRow=NW#r@loyB27Aa9|Pg2mycu#tD4yv1BbdzM;}q3Ab(A6d|iy zubs_njd`12Jo-S;{^nuXdl<=3r0=BecucsL4m4qTL+&%apvNDq%6t+TgsGR zsppn7k3IxUlv-&>U_MBZoedUaGu3XhiF-4CAu4LviLQ{`Z3bI&CX(Ei@xEm@cD-pg z2j$zf!lyIhoz0$1Kd6cUH5zDg?jI0PxSR2?(1V_as1_%@x+g@ z4XN+O@Wze&*s6OYgXbb;hUrJPeinJtezy{qAYSpaEa1U_*=sdUcP!Es&&HxbCjc1g zE@#-8jc22wup`?wmUf`lO3WFGdEItv*xwh`gIfW_SLP*c9cxzhb#=G-9FBC48~K%~ z2IW#~eUDP*(KHI(3>VeZ2X-swJF_onfSwK zclV{u%|k!wb$i<%AwZQdpQEEBo6F#e$~qZhqJSQyJO-3{Id)8Z=HTd|u_unflW=P8 z7@Gn==b>94WxZA7vJo;y$}>aO3zPCBN;iStoKJId{8-Bz78tTd2$B(le_5hM#aI9oMOZbTf#2qTp zzZxHm8xl1L9sz?TlS`miDY1QaM!Lu zc6jTS@p1OmUEkbw?T2s3T0eY)x04jlAiopO-$Gmv`Ib$-2AVGDPOPrN@CI>k1F6U2 zQZ^($T6y}}9`Sbei^m_oV<bh%Ze$P$s?? ztndhVPJ<*g+UK@S+nv4Kvc2ID>|H|eX18qVZn@W#^(`$d#lx31-Rl4oT5ktf_ac$T zw7a7h;|xBnqiFXyBC(J}K8RA>DGtQ}EKqwaB$?2<&_~D@Me_!xSKzp6p?BdcL6-lN5a`=>e$=<(kMN@U+KYaZQMWs=5CMi=J0(Et* zp_OYAsg!-tA5p1vVU5Ak(v?a@U8;uKlF6x+YJRWBvE2%fyPu>aN{i#*NJ}SYHHRG{ zbwP@n!Kp*DDk^84ba!bdgI%b|TME1F8UN;Rc#Ah{2Zww(h~lq(Le}dLU)&n)OGdh~ zU>``PquC%V*<* z-BPEz6{x{mRakpebql^wG5Y=%70o3Vpf|`8&>84jqIWkLwF0^0dH_O@axZywA!b%e zUPUAHqyFsw9qUy1`9NN`sr1rhEhw80#1fZrbs5d1#t4NExH%qm+j+)^%*_kB6lxr953m_v()?PO|QScapdw8E0`xYZ@cC*_a_j*F~ohesBLU$n`gLY9nlHQ zW{2p+aVz1GUuIq!1043UTokzQB^monzB}dGdCf+XA-2^S09aPwdpFhgj>(CEZ+)`o z@{P(@5Wc|vGQ9b-byr`r(Y34F7yEu76~OD<{Wr?FCSzSO_3dwW^z?KzvCoFi{h0Hs zs(!=;35R%cRVj&X;rRm57V0SGKIU*WAV*FF;Xy~jTZEnFst;c(*xzqi){a>7{np64 z{dp&;P7u7w_v|-Z0}|}bHd^_SXraTu&Ga~-H2G6?$H#b870@Py&y%-SJG}ToV=>vm zc~B4_9bw30*9spApy{~7my=((#bDMAUEZQ`#yhY2 zbX=;{Xe>TCzq8%USfkNctzp_~N0%#jV{3J5)8%o|>J{2P{uhQOLwajdO0y3x zLmLVTsRHdw+%AYM8SB`TDeezNE#{!fVn$ejIb`y?{IbO?nMAz-cNb zfl^9uZY-h|%IRTGdZNnCDXUu(e)(m%n!gZblf;5gr6z@hN6CB0`{;eWUU~23m*0=N z#P_Z4DA5yICsn?YyuK-4KnNp=ct{#cSTa<=sa|ReFlb93$$-L*^jH!}nk6+OwA=+b zOc~{oOg1bRCe6k;LMY55Bj?^98DahLlPQ0i&8C8Bp_Y8G#0VMmA|m-@DbvmLp_!Qz za7DXhWMu2cK)P|GpNyp>h^S>;_8kbKj5(BYjbacn|B#X+3X!Wi$aX5)1?`2UduXj{ zxZ=KWZaf$Ev0GM^&~>r8jBGTd{qp8qS0Dv;zH+>&DBqx~>aq+g45B=^4il&%m=CIB zBm5XS1zQq{mSP;{Q$s1)Y+0}f!}}0i=64^n2t%_tC#QzlVZ@t3hns?24QE;5=umR~ zCAEbb{XMPz#P*@j4q3kHZpQ&XTYJg+#CGMoIE&X7SRn8s+FHu--2l1*4Ow87&V;l` zkoCY=fLr2kwr*8rXw{F%1nZ*<5=0eiBmS&G^#g;a76Er* zFp%;IOg!EQ>OB+62MH}HnEwFwL>N;ubBoHExjAS%^C9Ii*y2sN0tO}%Iq_4w(ilT5 zY*Dxh*qtP;qxTxY^?}i;)^fpta8#kYAO~~u@=$vbk3;rWhezWU+)&VXu+w-PMMSR8 zAz1;(XgZMTX?K(}K|9)eG8qK06I2r($@zXa=+z^jR}K8RR6l6h%6@L-qDXnx?0B#6 zUU`{A2O~&cc%;J94Z0uttLQU5+U-)bnyMLyitVaa1dT@8aUJFkkMs4bF{t1}z^#D0 z!nPHB7>N6@^0IM?0rELnRSA!ZxZ-;yK|sP6x1jeS5?q_n3R;uVr`5PM zT8|)j_yK*Rr*8}p(dbZc(1Fk)^=;F zou>LGd;vDspbcoXK~1e$(_K?h*J|h|pqFmPVuXob;a{DIF%q7To3x}tR|6aFQXcsd zMAa~)xU%M-E9gmzLzCg%gTA?kW0|V=BmEJM(D@}aK@5OW&P7#o&z>dq+#GUJpFV9i z&8a*09Gw*I@j7W7Am>-6&cZi6218$@ShD0A^r_IkZY z6KrZP=X{+IGEz{j?urhh+u%W9kL04dd=g}Nc`G@+dDrn&0 zUI7)c4l&gMkdF8b(L;E}F}pwXKIh&$cI=~+=l9)baAD#1m4$#SSCr-G z+Ew~}_o-QRA6B@?jYzIi`^X6D2g$a?1e8FJxG5X`l}v!yB=jT1`>4@}cN+DYphn}# zxHa+YW7*2+!($r1)}(Rww&I&d5tu|{PqmY4C}%LUSGQFsYv4Y?EQFkili=1?=}?4!`!E+NB^enuT9@dN?u ztB7N2BnGm45lWmgi>)9)invR4Se?)1gv-?2nNz^cQNl#q>8+Mujgbf-g9XMR@nAd% zk3@4Wppy(m`YT%GAZh8~Da*mj;b}>(f-nZDL3?Bj`WE}H>zl@UkNqmMzE5wS(66h} z8%=J=Rl3?bpVKt*Pl!R$)fnv_3jDatXcqi4z%h4<9`j){Fi`Ynt4o5RlJc+%M_eyE zjb^>U05!6Rix6PFYE1)t&RT0)B^R=KZF??vse*gP}>OE9_he(mH4df{SUk}*n z$R|e^fIJBI4?98?>=&@ zZ)g5en+Hod$yh3XRL%9GWjPDF19*LwSxy}aiX{_~tvIWuk3wCrH1juXXUEvQn&7c; zmJRyjbIP$fxUkCbGhPJ$bp7=R;d3@LI4!5Y`c<~AyM6HsUs!DKRv71{h&9Bxtg0Hp z7(E1u%7R%IfE6SO-@yK=YpV`c-BNW&)mN&%UiD23__7+KS{2*_S}_^W+ThXwz~C^e z7Xa-6JwhM?ke`@8&=5grt`{)BepQxF_$llHKInFlWP8%9iSReW*o1ly1C(?D7^8rW z2f>Fga5B+IiZ-a>v^A=0x;;@7*`UL9u)iQH2!0lbAg;(tqB!9B@e6o}x;-Jcd&UIh zN{i29(0cTG=P8H7Y3egMMUi%4qgEo^9!YPw*_4n(t9ltwM51o3)KGlKZ_sO=Xy^*2 z8k$`B=B9>JP?j1@9UZ0yNv=HURZl8!w7Kh~R>|aU!-2O|szVmB8ol{To~DK#S*K}! zk=1GR4L5om=AJH{1|(HD|K9m`g-PKjs$_s(=I*W3x=D02WoLn=18$KJ5}=Aj*C8aE zb!A}x@90QJ@|(9>qC49|?v_r^Xy;Q;{dB+{gP&I1)nQKwW8seUpWU14w%gVfYTCT= z=MKnj={x`H`{!;N_^0ty?_DvMxqzv_WrbCCF8H9g>+IFs&h?8udsuwWp0|{rgOT|8 zg=Q|EH$$E8FYL@*KVAO4 zb&WfaF5`l`INp96p7ks5)bsY)v!(i|_cKB(pRCI9*<*)M3qlu}F6~;kK#Lff7y*ic z6h>%HI~OBq6u&=GmMiN5iAD2LO4_WaK$; zIYZKvBs*M@k*J!z3n+M>(c=Ps< z*Bf$d@opH6^qPrYpiRKv{1kNIcc2RaDnEC^L=HyC-$4F=M=Eq;K=elgW4ZBC=wcF~ zOYD!_U7fj5=cjzzw{2&R_RsWmU*6R22-GyzJiD#0=ka=BcW1T}uXFEzbK5Hb`QCP| zykRgF>}l7G{N;^KsHRc69EzJ%o`zc2j6f{*v&O9T@VVJH|qN zTOuKwah*|TfZnsQGqmHj4*Y&cN5@#`OBli&k2;0^{|e{+36DT6g}wAlJR3R9qN?SF z^rA$=d8ufDWH1jFflc{^H^y!rXnuMK*XO%s=3qKR&WW(?*bf#L6(UvOV^37gvqiKe zc^81kDOsyytZIA$g_&Rri%JHWn0`=M4$fCWV}L5-nc%3%$hh=Ng&tW{9^<V}+#A=b{n5-!=cdGof0 zbp58r+;9@qt}8W?Ys{KAHVkgwJlL?&oNL^4S*i>4FL_zcmZ?uEw+>%+*)Z#{`gZ!P zxX!%I7yeix+|dzEd@StSh7;MfzZ$IHXg;-m{m%94G5$iZ*@a=VQ$3qWu}nZz6l6|8 z=SxZ8gz$kYcVBt^_1GLxl+9OOdCT~fY+@^W1*_u{J!<% z_g{iqq2Q<0x9$J@AAkOmRk!Uw(2rN~F1q>hU8|wHSMNztAKc5c62qlz#-_Mu>i=jw~yefLG~|G{(g43xdp z&eR?x|5@Su!`0ubT7(`TgfDEB&+TT@YqiU{1-gH!ABAg5{a9Lod0(zte{mDul}jx{ z?b2WB$q5{m+NNA)-19@*`=TwfMtk$ZYB4}m--TNABU$!1U(pVB0z5JnW2<&OAoSED zvQm?hQ1$eKHlp0kx}}3MH!o;H9-q$>3d-^vWnpwU9LmhE9Ue*iwJ1q6i;%M6_t#4~vFP+)~ zf0B=H0or$4TSTHUPBOjfqev0`8zHemsmboeIDPJ3^3PV8fyU!yD|iz&+*E zmZVj0z|BYr-G96vTRF_-{;+&{*yHzmj?-p%^k_7+;B&yWaY2qQ2nRBmpuuoFlZhLg zW~InIk!%1ab))8Go<%CxlSIARxPqNGCY{`;+Mi=9D z8Y$qltL@qyu&EwvaOGF^({Q;^9n~lH4=^>zCwojo9vSUBG;79AHqQ>B>33Qmqj9EKG@FxOEJAc65R z1dPGK){jnh)Kvn(D95h43WkAF-~WMS!D0Yfk7Yn-|M0S8ayhxLPtN6n+3fEt5S9jc zQ?4VM?Z`o8QfZ4J&nk{D42+HzF7YmVS8;zQTJ`~95oj#WpHhdzf5zb>m8%*Dq8=Ry zpRbY==nUE8c@aR4*a_qCqCu9xIf|Gp9Ta6;#;WKl+4GFLqp`>8pnv^avb#bLidjJa zuso9phIj`0)Ey(9kp3z00R2V{n2cpeD67e1)tUgUYqpkcmT_}lg!sC0Y&|9* zG$GvPNp>(Y>DU@-%H#`z;4zrLGHC62M9?2o#T{6~$m+!gsd1He+=wznh#{vr=YIu$ z@!v5URIE$YXN_-#@drD<6MAqZ3X@8wD)FBPNqgy^V+NJcpDw$#ZNBYR8b{Fgm2|@7 z7wd-HltL|t5Cp1u`789p<(e#ow*thDXF!8o2y>^v7Uc1R@?3=qIj^R`-KFj_@@Q7d zOdp(1dvc@fhuCt_@T(+MR zdJTCNR<+lFA#2dt>c}dH$mr^Jo30B^E!BZ;@Lm)aVb{@gynk*|aWNBiW6b&p`-Sr6 zBma2vq~qktM^4^<|KiuK-x*@r)boR1{k(d>n(zJGK=O-qvR{2U* zUZ(Lx$Zxnm1`$Fph^MxB-+$=ghmX9!{~?6;3D+F?tG{~acfWh++TPz$n=i`(PRQC- z-KsAn#b%LPv<^)VUn(vH*sYM365Ww*Z#K>j$r(v3M&yHXM952#pF709$nkfg=|qS* zT=K88KFK3xgtvm8!(oI&%hD_KELsmpCOSsmn3N%Y9g98r>nA8$?n&X8@*@hBqwA!`j{Lg$L(~fSd5i!-s{-N?}J7Z=?Kw-v*K_ZpYUowS7u;YJ?dHJ-zzI z1eP?9+c3HE&UvzRvT3>*d|JX4@jQ^rR@Mp84~S9hW)T)tUV87f$CQ_pmr$Wq{Zp<- z*{sUcQMV$P>dgIz4@2e5!-nXQtfo|%WgA7QE*!o9&bLcMOP%yd)P>Pqlrxn##vnj- zcxBLU%lAh>)vECZFIVq6=4Ho!{UmwGK9OQ^iVvjrTvea;ia>v=6XQ0)7%9?ez?A}5 zXsE0Vvik9w;|-2;#1F7lHx2OdMx%BGng)imP>=fnca6t{sl#rIYO7doE8>lzRbPSU z1a^<2qkwD%^E}1yt-zBU8PBlccy4x7c_)p2RJKF`@BVOZx zFuwbe$dJ9;f9>Glwf=5#d!&EQSpND;k~@7C_Z3k!&0Ox9ruD8{NBZaTrE%s2y?6}u zg5?JC?uuHG3moDHVs@BPi5GzF)nyHy04{^|C9CN^hry)ZOWx){S9uGZhiO4Gpmmt< zhL5!Q4wpel0c3jWx#!g9oc~9(pZ3F^gVrk%9t;f3fCzq|{uzF26*-{0ARzDjwcP9&M+cen6O=hxt9bxC;;rxCn)yHY^`NuJKDJp6U=E!mj zV8E_!fj~Fm*FvU%&4Q9T!^MphyyZq9DIN_dj92yzy365rK4P|>G8rs`(|)bNsL=%D zPK`mJ>WX90!KrYN)hho{?kn~%b>J1W`Pp{8`-yI2qubYgsZXaz_F3cBaoEGE(SuVv z#IB8dF4-_dCYdE(=N`fdX_r*{u@|C+H_;6_0|)3YB#NN_s1A%4!07p>7>Kv3phnHS zWalICggxW7nncUE#bF+VGnHGWAnTw8reUii10-jwbsW}VvjIsNeJy|+*-42})Uo?U*AUh9_jBhbj|GF#Mdf|2MzE}q*NbQ|?9DVGjv%nmES4|yHx zkwg4%_*$dGkTVI;RI56q1{hdi?7~=c3t9nEqsMB^jgEq89vB;x<-xIjhv*p{%~`GN zL?+|eae3Bm_lRxno!dIuC%OhZeUj+0+q0vi)K*;>_njE`CUAR^Sfd2y&>x7@!r?6Z z#2te0Vv*JdDZGT7!DKQh`wXT-ba2RI$n=Nhd_-o?AmtMN zlsm=@X0u_8X@yy{LGjUtakKsdgK6Age(Q!G96I!a8w-W~YI-JNw!ptCuo09Q>uS~2 zDD$-?c?x(}q?2xk>Xx8M+Es5&8ym_qS2P<}3fX8@=r0^Tdbn`)-o4`+Hf`91*S^9n z1-x)C;$Ku7w4HS84Bpj1{R&h5St!(#F%z{wJW)+Z=Rhvf@fFdIbDVQyuS9&lxrCU5 zuZ_iRj2bh31gkzxp{kK|ycpNMN76WhQ_@_w$ilsHeZABHJZ~7meNFd(&$z1F=777} zr<=eZRPd%wj2elg5lFE>8|NG?+n|pheGrhe?)B~$~&H49Bafj8gwx_BxRXL)S-Uea^(CehOqh43%j*dha zv;ueEK<9H?N6faQ$|G@`3MaIkc(h)$nSWSs{}XFtovq$bU*C!;Ws2&IwkBIk!y)AA z-1l2}R6FYHzY2fl!~^USq>a46TCW^M{u|SG)e0wvZ9jaHA{l8!CKd8KaSW#(AEtONn%>D1QtPuUk?J4*_Vk@F(YqTL|&ws1$ z|DZPf;J3eJp^sY33;LN6rTK5Q;vX_D+4SwVKmAe5s9Dj+mms(8fQVUER$9H4;TcG``|{6Ob~Sju|A<+*XZcHB=M0426TgUb@fi90L4@^=?tF6 z*7m7yP5n8^bZwsg0s=u9zaklavH7Fj}T(Lqva`f(Se(6TJ zeE9C85h1c=!`*jp*aF$L4-zc@ptk+Wa;f+tsN;u}OH(SBFizznKfs&Ne%nz(6-!`8n0i6@ZBjm4E8(ff%RIrrs|u>E^CWV6{PvL9zNow++ZaXY?d z-i3SSpu4HV-2g+-2H$#h_mk0^2wwiBG3>4oat{$)AR3#t^jj)VSwE#B^+1{<9d4QB zpmh~9qPrTb25}jbYNwT!B*$3*gC14S&A z;v2h>r3c&>4W3ezC31bn~(fW2@?!VmM z(-ntD$K{^pW>09KGv2*E%l4oNFf8#_@rS^|66eiT_86T6`%pRtE==DH6HNYnPu>GT~77^WQu)B99D*M@GWKBeMGAoj6l| z;Wqr4Pocb4loy@}jYJFrZ- zeLVq_=VruKk1evJMQG~k9rM`Qdb^sMx-wD=Z2uKwk7x#uLTtngC&~w%A;k>}wvrl` zk9&2TVl)vJ9qK_BjN?8uC)Dp?xq&W8K(=ad<78o2m5g?E%GAm-7$MC<3gq#An6Oq8 zLuRzfTlMYBahEh?&Rv<}b`BnApWVFqv+z9=T=I_3UaxwdVJGvkU!Gq)zGbx^ep$L% z<&Xb7cAK)}YGQr@ z_NbwAe)yzT(<#`T{Roc2DSXBKP_f5(omhkTRO|_3y1uc|ZM7=r{a?A_imw!08#lTN zOGoUHmR6t5Kc4petbA~bMf9~~eH*X3MG6MCwzX{y(3Wkp*!bxpyTj_XSlrgP{H}D` zRk(Y6{O*D)m7=4uqx;Nys`A%zHf8K4HaE zGdNw@e-y)k6^CX!Z~=*gbsw7@*iW#4b25^6!1-A@)7~n}Ak(T$s?zPU*ScyIYJ=|> zzX#n1#u-o!$_Zu%qd^!Gw5Rb&@mu)E-y&`1C_W8;MT+vuaEmbz0*Z?ZnK>ARiMFWE z(sSIyBnCO2l7z(xrYH8o5!|nEm=zXI&oTW6${5|`RmJq`!Xo4H^D@nc6pGn?0p8r2 zICE=4%<;06@$1OvQH=(HQWK;{jSrz{gOBzEZCqdQ_xJk?`uNfjp1NBEu-%w__qI!? zREWDh+tLMdUu$chxscv?DL-l;nV8leb#9p8l}%Wg8-Y}DDQVRh;^^RxPR?dnsF!nn z*fBpj4;v^S5P0m0HNC9j4yXs+8{+3Lu0z#~pbmspOBg6{hFR?Z%-wgZ!reP-_IkSH&0Srdy2eJQ)w*q!Uod&} zzWtpBzf>c)!J~q2Ivb5U;LT9Cqt5cHHGO?){M`zAyA7+ix@LfPf~pUy3TR=#kRct# zE6O-LXT%3mKXgcnJIh|pX*{>KIoK%q$=H=&{qk)~6K=!xD(d*tg3qV?CRG&6tb@xt z?grU}oMRB2D#WvZ(5dhb269Of39X{@X4iNe%Fob%>`BWGhn)6kjQJ39Cn34ZqF4m0 zlRNCRXb0nRpHUMU4B?7gD(ncwhX7dS^1J86anOzBHN$`pz=?$N11q60e&81m6c60| z3&DM$_`ol4aI?B@s=A<7p8XSamah*Sum=edIqV{#G9nLOAeI%Ngj01?YR?hOCF+Lp zNC6hG-46}i(BFTj*k$hDK_!$~D3()z*4sR8}Kb$1(}(7*ab^^E26(1e4()U5Sn0BwRe7XmUDDs2}OC)N!Q;FXV;}20HVk z8et7h3zwq0DN@vG$6ArVA;QO()6JbSN^WHIU37a)*u`($CpczansErThgPOvXWQzH zI%~b%Uf-xUdTh3aIhJ*&qHslzrrg;VRxO4oQzgF%LcDr4tX{&<8)!nNa!Tfmk@!~QQz;dlw1X{Ff%r9Ng0OXUP_6uQ_k~acj z+Q`69jF+SbM0p|R5OX3x(j3+s;1tGefIi@Ctb|-|(C{nB<@2Wn9Bk7e{{4odroD!zI=YHnvjIhr|ipga1^2?KL%AxUOY;-gM$vmm# z5^Vdm*ItVva=v8&b3TnZFY(b6wR0YkPtT?JaXX*{z&8-Ti1-u`Ca?{d#NaAUhh;g; zvqGhpjzW^l?e<{fl1_VE9=8WCmq$ojtvq*BX?Hp_=rlU=g}lS)8Vm*tN=t zkj6o?iJueFl_j)VGlIJ?T5xHC`BAzUo6?EZZO4%@+oh!jgCe2ajDb?asTD|8HXfT_ zYP03mdkbhq04n08dvm$@7FM=iM&m-s+yXDu!iv@-Ijr2L?YvLdY&(0Ix|P~W?NaLG zwOVa{MLQL!hQk%X7s4_2S%bZy zMn?!fh*rZpNf1tC++pudAvZJ=icppw3MuarP@eFZGB72$0Jx#N{z~6B(uZVr|KQX^ ze^#=gy*(Z13HEIMn~n*G2q!DSAz0zv40q_t3MnY zEJS~`Lp{4AG&=gT``E@_5j7iBvn`Micyl3z zIaVI5LU9D~=}I5qwTw^p8j7Nvri>~qvzV2Yo7tS`4$B$k4S1?DmtJob;TJtAXk0HC zkPaBfyKsC~dCNUEo)L~_WaSHT@1v|o&h)fG&z0@$Y8Bb_V(aDAT0gA5&UM-bG0t@D zHqAQb)afm@%L`JogWO2?*imIZtoT6r*V!7|&`NARv#ba8qwd28=do;v&GSLu49 z&Esg(IUb?ffqIj2*e=56tR+}0#2W#(zT3-V_tDhl@IPp3kFepMK)$Gl=&l#n6}JX@ zl)qxTZry%s@AmAtdoEdJr$vAzHhaPKwr~8;)UqVh+)9_iHBgg4?MXn*YX;p`jx~PKPK6CX3&)&lwdC z2hFpVr}X+sjb?Dn>=VaL&)+#Lh4&(%ndE`XuEyka;3h-! z$LEJM{;l^v-2 z{{yXu2-&$4^{1>xT*ja|jw0LJFym>`z_v>kAIy*PkpQy~zVW(ito`UnRdYWU}%khH`M7FzH2? z!ICo@qI&a?@@j?4=kYD<(xD`Qcv{VddJ%cwn{0KRCb1>4eX7z6l;)ugehXXRw}5%L zoKK~cLuF<16bvUm4{t`h4nZ0Z@W?H&*x*C(g5is}OuUFY#|eMsIbzFKUq`6Z*>vj0 zR66^I9I*YFR=2w~6ZHFokM_1gnr!V2`27LptIOxhWmRQ~8jJv1cd>AYQRoNA*NEbn zF^b7I1vH-g>;efLmWd?|C!1H!^dDz%EHXLuW&<2l^!~(%#poUwayaJtW)73gb9koj zf9~GhK|q*w#>S}0$fo}HR+GNlAHDaAty#-GF#B)bcMDxviK$k$0X0It2@=)741zF& z9XyK+zF!SdrR*ju9bA=!v3)Gj`81xCrw!f8fktXGV zrbv#xnF(fZ9vhp<__IGsr_(P&Ipblc9Fd&#+H1H9isfZKcOCSjZFoMst>NPaz&0M! z$T6DAfU@=m${)EnS1jViWQ$Rm0NQ|&oiJJeJ9Ugrvq945;eBE+T<}fGG5UIXjvY}> z!WA04M#&!2$Rp3z(4E!r<#A0No$|`QVE-e*HC1)leSu593ud8GX4aFAlNJNQDM=y; zIB=1iZ@m>dnK=R6EQC_*!G~|Lzfi9DHZp<24WmNd=D%&nPj&d2om??uEcoV|@=5l9 zGImmVJ(D>|cj`I$w@l`#f>-~RVv>_UJ`WJMiI;`xYGsT)aFRIyWHt8ITb=mv52zRy zK9^)}%7>|I#0_lOx89OZWKRBo9>lJpBGY}o#T-3I?MHLAEF&B70oNl165=AEE9FK} z)5#G1o}5pV9pCQ6bHB|Vyx@23C?jl2{D*Bc5m8C}E`;i0&M5EDht88LpVf#qX=vk* zvbRA2kGk=nKqU)X1FJuYhlN)CrW<_#I?Eq~@+t3}km;hi%3q^!G$y-1SH1~dOdRVJ ze9PZ@zns3GMIiJx4`)-(p3Er~L zEJi%xuqWaeFgrvGRuJCj<#Iv}`8}nydn2W?#c;sOrm86^6qyv2YZml3x1nsoM82B} zd&=x|AOpmO#XK(fa|edVWzlSw!V%AqXx@iXnr6*pJ0f23L9}N(=(HNs0XoAF>7}z% z#toGvLD^z8SPRLMjKlDjb;H7Vg#Rh80Z{M|vYtLUJA3?w8%`ZM6tTLTh+`JoS$O^W z2wT5Cm`DWwrP;TBi2i0t$>@ijlw+HywlwmBr1eZtHFaB{wZ#)1}_jdR7d z6Nxi}!Hy0V?C^%yOZ5J0duxZ9vhkio-qGe*dZEZb|1IYlCM-T5^zB`UyrP`zYP+X{C$`Mz)&14f2<4Y*%TfEn37&&I3?n@1l24UYy@2|lEB>&; zd&FHAFKw+y{OfY-qp*o`2kcsEdK^@a7d4vz$${h-N3D(ty{eQSWvr}h;gzj>;XtV< z<%f3n&+r zO^ux+o1F{eH-YwB#Xk}%+0t-?1;y@F{fGeK3Vi(-)b-rka)ql0d*v*O22eyxWWX5F zhcjV)#5fR%3>ua`P*7tjpDmJdWQZ}Ccllg+ji8P!ttzonIB9WfXW9Hdt=n?q1djJ92WPb| zSXg;g)+lf|ic6=bacNX}H;PNu<3+U|s=T+{zMP|6tF&m{kJzYxNNa}6jkls1`MSAW zCQ#mslxWR1D)s6bO;PGQEE!AjGaE6$y0tnOM*yq>dq6T__XnU@pnnegk=%eo9eoY> zrvy2%Yav34_6`1kjXC`jTBE@#?mFc1`QqWZewRlI`@(LYNek?-tVZKX>`4Us=OR(R zJ}8`b`g|d=}B_v|3U|lir{mdyq zWpReA7AejBn~0xKX&zb8uyVtaD^WxWpQ@|rNhf7rTScMSF=t+w3BJ3MP+v$ntm7RW z9{WfIjax<9_`FohLI`%GD*y&|BN93jH?vYZz%N0+r#{2#^`i1Imi^3Ulyl}L8Y1ipjHfn76MLf{$ODvMlfNxS zy+KMOLJpEAORrM7{sesHX0Ageym@uSrp1tV9mlLwnLDz^E%h8vi`17MO)+C0u`RPF zPB8tEBU2`kTwsLF0oQY`0Abp1!F~%upl-FcSS&42G^;!~(Y&3YeiEJs(WwSY0-Pta z$j1X5I)rynoZTkCBq3}L>4Xoa3)AdbtHYde7>yxQRD92BGRdZhHDz>Rd1ZU1cRhaJ z$U5H!Ynv%%9}w&7z6|{FA)Ber}&hi?lM zumE!(8;p*I&BM-tgL~7vQsL2P;f8*BY+q*J#?X)(5>wHTF2;jWB$F-7k0{2}u2j63 zHWc+E^98b>_NBxAV1<3Q4sDy{=(YUOfkYAtt3WlL1ydfG@putzY6Lm72IQuw<9ZG7 zb5L!-21&W)&?I3Lt#EL_IcyS8DtBbeJtW^S2;|KE8wx0LYF8RaVq-a{6!)7W?z<(A zY?Yijl$eT^%|v{DDyXtE=ntp+hVL9k@%6ki$OgpbBcsv2DZ_*z?D8jsVdG;VJjmg5 z%Q!W~*ORIf=sTITlW?eEfe6&%^5Pt;lF!V&a$@lSbIb3{y+Zwrh~y=FRX6mjy;UPs zpFn@3>IlE+j@n@wK;3mnPpHa@gyiL~{_wBc@wlbSu{^aRN*C)`(w>+``ub9ygf<((rE$UGiCB!LL08ypFeFYP^M~Fq`cLg2^yi8*%<>^$zDYu?-e>Xe z9O{dQJR%fK&sux~lHV_-ETPn(*EY3o=nQ(&kz6Q>$@^UY=x~29uN{h;MQu*#3uZ*4 zb;6gj8clsKCS(a?A@bs#6OrNBdFCg9+8A;~uG=--7Y`z#ln@r>Vki;`^^5WT39At% z6Pn}u&mUvIf?m>!)c~HnAZz@eyhYGib||0GYs-BGM2=szN4k0=y>0EVck~Po_lS<~ z4S%eoPdAh>+cld41MG+APMa(kmVLvM`y*o5z>6Z^x%}ijnWH#QbsS?f0^5F~>WZqW zWO;UxuQGunawi<1-y=kal!*|ZF|lGqjOmz*_HY0K&?xs%5@Sf5O}I5c3+rWc%*6$* zcL4@iU&ikkPvobK(LO0HA!#E*Wd)y~@~UHJb(;)E-5FezcZcq<+;A zojn3D&rJ*mNT3=?URd7u_V4!%56?)$!jN>`g@t0$=k|NI4|~1C+r9fa4gD6{wG%B2 z%~d-zS3oiV5Gc|;vr(o|_C9;$K9lMA9VaIzpMCbYDQG%QG@#@UQq3h-@&x%9@dlzj zkQG4X;4VNaT>f7IK;Z)=Y6rGF3_{>oiEBjMMa2Y&$imNw`M4zWN;B~W)J;FjTVNhvlhx`sj52X44ja%}W& zPc?N|9rngxQ!3un>5|N?y}iZWCSNgL-`?BXf`50$?b+h;Uw_9J1}fw=!q#pBeTQA^ z!mJ9_#I`~Q3oUgFz`ZsvUfj=eMP>!ZT!yeG;ByJbOM0!!ub>=*#to)Ee1kvE*Z&HA z@$cN@5_g0)5JG8ntQp#~PyXXiM_>A<-|qhVzXx{K7~OUZDY$;f((2q$aobcKHuzX* zOY!DfQ=#MBPs8kaCAyU~k-`I4eebF#uc~+!rZ&0d@QzS}Q27LJiL8 zlHMc|4InI?c8Ipl1m}XocxR9f!`L^>kFo7DCW6eLH%>fh4fgFc<=?Xg^Sexar>sHY z0J3f`Qa**!E|Xa(&hhtYc(JN{iE3}K6AlSkn@HJ3CK2dA379LO1I|Fne?+x2L?Xph zsu&p`d~9GmGM-9dgToVvo$>h2nTbSVLO8nqN}RcJ{gtT{Hs!~0r zKNsVg3)0h3Z>tKA73VO=Fgj!19M=ejJRfNUVADRv0kue<0d)mG;l>!Hppmzmyxyj_ z9p0X|i{2(=81*@d;I)cdy6{&jPg%AlTUiYJ4;0{ypsK2CK-nSS!#~5R5b8u&+3K@@rp@(`NTqvkL zd{9B?35k}&Yn56DK`(%Af}^>xoqcLuop%2}nO*u(y{1-g)q8gS+0I6JlU`SEW$c^P zpK8^vtC_B^zr5D5POEMC-WR`kpR=K>wMMWyEBHdfA0%0Yye^j=6yXl5%8V$2daxu# z5|Zp_xP%%@45_LRd4g-7Tnu6~>6ccA0w^wDb2BM)mbWx!NG?&w{8Bj(RSm*iDhiL6 zAk8-xNY(NUC761EM;}-&2&+=FZd7jBbkFP#dD%y>$HE`}cw_I zCX)qrY?H?c*Al0Uv;lHHyZ7e3S)bKual=F(@;#Q^I-l|c|FFt5Fk~bN1>4mss6087w zCZZJUSsOsdV9oV!0yS651@bH6lpl^cWhEz;WNsIR)z>S1yiuxYHMZ2cwz*rjyIL-F zyS6v$TWVXio<^Zf<7l-qi}GhZ7Hx~gP^Vew5k0o~o`!0BqsgxP1cBM#Z1OevLanat zE%frY3kMvw!x5jsRr=GnZ#dlO>^Y2ZjQT(QQ?IGsddnZzJDSXz+itTo+s!vE5T!ZV z%vcNmfvPK2c@Y70ZyoH06u}N+2}4{BR#}+x5HaKpB!%%}@$_7APB~aS4HGCc&0)^Z zeXA$)=v=Y2=lT|$>pgwC7hP4co|COpjXbGpR5ec2McrJP(aWk~odim2&6Tlcs~v~=dcE8X*mQf)B^mYA8|8MZg=OWomUg>Kd)ehR&h}g+=5y7x zIQ7*wARXEoOm=-;t3BOfskiCajNZJiw$bhZyoF$q4Q7MIcw>J~GU-iDb13fcTMU5U zkX%7vX=W_eP^2&t_eUhBWR^U7jp&O8Jyyx$^hBIiv(Y3PlmT#IcX_pr%V|6!u7@ANghS(U+rr4yO?9i_c3@B0$3Ix%Uu# z=#T}yKN3}5R22S6@kgUChx5^Bp66jN`BW{@Zt|-{{&@-yBN(P7u)QT+#%ykxIPj8pg+0~1zn4O=-#;&+xYzG^=DLJ?;anntW zO-@S)VYUw`!w)^g9xfzKB?{xB^^{dSPhDH3K^%)3BawsrGE#LFYDvM;NIAv*!EE-D zu7W-^HBuD3nN_|QAWDSpYIbYym95~{qLOBK=c|HI{4awBe}?_8(IJOHaM3Tzue$*l zsbWSFuP}}AJq?Q6$hDY2A_Y8TH?r9xr2w}>p`Y#a0erH0sA}cO5fvzsMdeI{gR)2VzHZYAYu*|IHue|H(t~i0^Vhw z1r`%5Y|DX+ejUuVkhkzo+5rx{Zw|N~;ZeSm_X^YFd($txA^_y8YsbF1&+G_yjeTZr z-vi%WSorQg|1;g2^y=>jSF>Nh!c`B;`w;bXV>cE`d%b`NGTQM^HeFJ;0WMPb2c$cA z4{;L)Iu_aS~>~sTnlh++x?I)>YS6*G%Y4tox>8hJfD19G2$B zPOUx`TtB={FV;8J$m>K=W9Tq@bcR|B=M`^4|8GaTB%!4mMBA(M26ntyH`F>Y^f{mL zc8qiASN*^l+MrT)K(yf>xHddq0fHQue)yOofel|G053$je{%ctd;F5Tzh90F-!T%N zOlJqQMzhIef+`BkoY`W0A>E(Z+m}U-4P^Mp3NEc)qZd8GP<&@1GM3V3vl>I;I@e$b z5?Dd<I=ylCzl%K7I6K%?q4gL=V0!y5g5HS|@#gT9J%8-&pS zIiL}VgqA2Z3apOhr85ZTX$vHOu$z5-_stEWz188^BDS=2!ndtW?(7S%Kf0T~+FhMG zHz|DM%MLf3KOJ9o%PyDfUJPf$cqz)B>FGW6{AJl~InNMLF?h*x_hb0S>hP+@CxT8d zzu6H-Sp5@~IRL%O6AC`kIftz7+0T^&_}sOA{ra$j9eH9xIrDLbPvPrua=-cxQ~j59 zkmPZ~vl*^sizNBKAr?_Z)a%$R`Hv`f(U#3BZ|vOp6#lAHDc?DV4_o1N0OFr>2(K$U zpJYmZzMtv}PsP%@RgO(1Z;c?=23%nOBxfuNCnc>wL(Hl^mt0MjKBUTV^oXWseuUD$ zd?JyU!5`%urM)oc5tRZkd_}g1*de9B7U})leE?yEe@VWyr+f+LzYp9m8;?5%2hYk~ zu0ok{CDjH#j>9~3kHei|9@|U23)E4vylK<;rcLt5?U!A;aa@+d8`tMB;V-*=q-Qd% zH+6P@;*+sZy}suY!f3Xb#p{{jBcoGyP47?p68-t9k?H%643DNKGm7}aj40oU zG0(0~@~fuMXRyhh{}0UnUt)$(Ru3uzLREMX0@b=04ErFwjnqX@mooXr2L#ze=(oZH zPv3C(8w20?M(|ir_@(#UEk=S~Gzwqbpg5j-iv7(!+qT_<`(q-O>;-DJNyMvjpB-d? zRv*HhebM#gl0)xfl&hOR0Wgmb7Ycyv!;3PSDen&||5e6!L|!!fRjwN~JeC@MZ73$R zA<$>Fy~J*OLIH}GvgjD@*kk2=j0T&&sl*7+jfz6>s)55~I4Tcq{Xctj`d|n?;=l zej?%d%I4$Qx;cG(u$}wmo?ervZQ`vF+_XYaTALr8(Y`j8#ORN zRSBSuwDzs6CnOH4BVF*d45QD&J!jF#uIor>2#&Sdbw%VIGiAE|CctHu$855gaR?yDi8;V$+$@<&uee_0L~|ShBT5aX@>TkT~YMu zap#>@x1I`$&{Mttv|9F;u!~AQHhuZcR?*#JZ@lGal{HYZ#f49|pu~bU)O6e1YJJpg zWjn9qD@}m>36e|UF+iq33R$b0^{@s^FSU7>tig>45kts0sSz5^j>*}qJT@lhL!rEU z(iK}f z;1)}B{J${AU&0zd5$i+)VXe_&u_h}en3+J5Yh-|R4N1e!{MA&Tcz^-wH9Fz%?HSy% z{kHAViT12|l-Zr`V9E40+AIH%7Jd@+ZI>r@-}1@7_(ae<#EY#(C-Wjq;{5VKRmc4u>&lG$owMvusW|vNFx$Y;l)9KgD9P7BOxES5CSvm3Dw?bIFL-07CG_nn1cP zQfX5GZNQfxKs}!W>4CAAoM&Oz=qdJm70G9Rqwe8mTFK+L;f`SFaYNdwMmfaM^P8#X zuw^HZr#eH3fpc_A9G_)>3!4q@3ElLgq?kV2)6z@hiWok%tQ0%mhEaw1$JOpbtK&9m zFy1jIG1xKpPFP%|V`b0=VDCag$urKN-=)adGHu@ykP2I<)VC^uW~Iv&2sX1HyZk*I zPlX3nqc|0`x6BiP`&&J_YhXocL~ByO1Bthlig^zp3OuJXr>7V8uEKLtS{d@e{u_Ci zRz8RF5fk49PaTTwSdDJKqQ2ZDqv|TXXypADsjeoInZ|N7&dz@oXyt2HcJK9fH8wk~ zWF)3Oj)T_R3;iYaF_c1NVWACahk#Q`-VPMoLGooAp%?U<+3Jo3qCw58fCB<) z4hwWez7i}QP@hmQW9%~dXnHYY3FijW0O`*ZvT|YP$Q{S;9Nx(mUnmyGbI#d*6_CGw z)|vC)RUAGtGIC_Nco*sgI=Zx$x~e{hr!A?}pQvy zKzN!_n;Hof<1kGlA-2hnSUD>;TBADwW4@pl9X^vuW6~P+rm)|GoS$xkMRT1T^2N0V zx5pnAtwsn`AbeJ%#VPsZ)CH!7S<$XHuB)qEC%H|m8Jhn3)~L%ZnqAHHE|XR;8k@sN z1hLNPw7HrZwAC7`$ql5+YDjubolIM8Y!vHk_H2($r#00#rfs6OTBp$onrfY{UaMu* zbq$yE_Wc;f&TUvhTgbzJB43EQtt5Tq4o%<`$(rsi)-7a1DbQq-@eXW4!$3N5pL>>l zUD@-NiO8SHY}`lR?t{b$A1d?0drzklPt!PUJpVNzU!BBkfnAHi1O)vmtl!YF0&$|$ zdmu=hrgHhfUrktLL{!+VM#0tLS0?-&t~zF}b@w)h*?n((GwjT|Yt2^%lF6ZDQb@Y| zn$K_D`gup#+$tuo>G|~F&PY#BWar?gd#*`}t;%o9*gy2ypPEt1hn zz6;=Zxh!^F6I93d}quTi}@aWa7>EDgxm_H7aJcRi%Mg@cxi|6Omy>a(B}2r zSBy{{sv1Dm)kURZO@SN${M-wdpn2p-d+u-_7ChGvbGakbUMUQ|D!Yyy zD-@0$bHo2e^qeX{8Fhro1?5a@S7F=WHi!@@QGydY&DrH=G*>UX?JnQ^XaSh= zc)+ox`xdsz?rn7If5rV)-qT!pPefyaidUCzq-2jBd*$fTO?U}WMBIY6yJ|OI@~wnz z8qHpINGAv(=r#lOzzu6#5?YrO7EgqRjuY>!nsAQ~$@|YDHtryM0mf4&%&F>5I1n0w z#TWkQl9S0!X()7Ej$8-m5~sPS?kd))4%qIyIX70tpl4OrV+^!zwL2h|@=}4*5N!mf zL*v9oycPX(tYKAbfCHSL#H47FJ-e`AHf0J33pWjB$h?~wG&M(x#f}fFoOnUqlrt1305zR2Zjr+lrzmO7E*ecBsZ!h$#@$3oV~M~}kC>;A-V)3V zNlR-M9g-y;$30+(S@BUhSxOQ_^hup3WghARZIT_@YVs!_M9kFz2Of@xDICBgnBbG( zgu|CPdsdksq~2z!}I zOz(Z7XJ3ez$vl9;D#Mg``z)7@`+#4hT)H()r>n{{@{tO%su1u>E%9B;F}iB}93m|d zla>U>hejcQA*8|8(VKj+C~}uQeE;)1BfC!J@b{x#;hmAl&anRe``Ik^?2^8|hpt|K z^)J6IjDK5s8b|Ce)?dB;OMSn&Sh%2+gmoA0xJ%YTFKq3*daD(^_0S&0j@~ z>oaH1LO+GGtm+uU@`yjzF`;UKRApSAyA9*)W8ki;+KJx`kmH5cYXiM@V+u)d(@h{V zo=(f;ghyH&&d;Qxt|3_-az#@!`Qb%LdOJCI=}_jtHO0*xEq1%;XzAEoyyigW(jf@3 zREO{3{&vt`!Xxgk%9W7u%IYN2xx%-UNUt42I_NLBDX_mKNcDOKuuX1WLE+#+jM8vJ z0;&sQ7EpOhP%JQme&8;_SH3l<`zWYVdVDyAS9^?Ly+i5ZB^#Twz1+Cr; zBk!GBy~Pf#22 z%h1xYuEk(Le}TT9{{_l=9vqkjlm}YqMl6TW4?)@43fw||P}8=OG0`D@*cVTK{p;!Y zz%$QC3FPaFhpxMhjVifiC5w_{&j`14Zwz&$y9Z*izv`CdZe)S~7BsnM2-1?t|37nY z1K&n@=8O6rNh4X7$Fi(1%j5Cr!;-8hvLefpq9}?Y8)J-P9OD?{8soYq4QU!onwm7t z(ku;Wn$1ZmCrz`IvMl64O1W$oT*`7-ek`ZAo8?lLlV({C%VlYoaww;lr5s?pTs)lr z^NwUY2HM`U{r&FB)@U@6=6&a#_v88aKmSLG|8x#@pmC=2*jgd~VwG%45h~t;#>ix= zGIy4w4GwJK%eEE+{8_vIf#KB9;P%0RN0P;2vIG>f-Oi#?EE5Zta($(N9fL#L2TG*} z)MT=h6j2QL=QWT z8C+}na&_@fiM7ulKeP68gRPEzNfayw?FF-BV61lS=dNd&D}H>{k80~|1|b9ejF*Yc zjcDT$Tq))7=xMuz5>W+Zi3PY3BUt% zPBA`}Wcwzz3vuP~!%4ZE_~BzSHzE0^65E{;V(QsL1y$+wPRMd9F%{L`eQNe5tKwun zs}P#bJXa1#&cvS3J|-yvdBCTH0n2s9_lBN2JUC{FI&Xo$c`~)#-6g-ebM;*d_0;taYBv;CIc~bVw|sG1K^%L%=|LP)WcsU}m|nLIx}R$_xE#;&cFR{x<9|KdVElG_TNwsGuFo6PkTIn=f9pHtt>>b*( zHoE(^Ke;{;z3#TTtT`=qTe6KogTdHv!YY`3*~}4 zqF$-GRZ6|BzSAM^|E#uSUl;o0Pvz73F@zJa^m0sUhe>c|xd$VM=VAW0QT zmH@K_$mCATz0*TbFOvQcR7K(Pu(lKaf{RmxX9eFd3FlDv@g?duTtU$BFWeiIEO zmVV<~by8Mv2OAq1it)9qp<>28{5Ku^th^Zg{_FR}%k6hd77_rlc$))b@+9j*oS+H1vY8?W}U=T4Q&7tdR z8|x>6K17uScliDFHYCY0*L&Rc4M>vXYzzO8b2%;dnR@6Kl*hP+U7$=5lNIhp#X1#% zR?E(7b7Vp$?lej&yLa-nSUx|R&%Z^8!xhPRK`P14P5lvlG@3ulbMjX5NsEx~0pDd5 zQ$!hIKw8Pc4$v>V2}aFs+VRlWU$^!yNbDe?NO+@%>OL z6%r1C2NJ>}^pg+n0fs0B`H^Qrh6TihfyCo(bno44EDslGOxuGDa(mvJHN-Z=-v6ng zEwVZ-Hv5|Z4#X1q{ACz}m7>fpKtxeayM2HoAYt^I0pB@LFS0n< zt`H|imMd+No!0NSel7`Z3h^4cCCncPNW(}&rI2g}REIDVz~Xz3l1_)bloAHvXWS09 zbgnnKPc~JvUx*0T!Cwc&0z-d?{sZk3lO6g6@eWcK!B{a-z#)wSa=cUT!9c-S0B2t= z?Q~1G#3Wl3j+op;0;wuhr_<&{u5Y#Ivpe(SbVz}Z$>|%3PpQK0XgGhIA8>o4u>>Mo zEeOJm#%xkbDY|{&5jJ}5mIR$pk}|Prm9KXdKOfxz(uYWg@KkRsny;&gMF3rm7^;0~ zDcpwbd%2P_R!uP_1y(-ev(G*ayhJ<@c#6X&0>VodD#BK#&dV%UfDfA{`B1IQ>8dcBP3YczThXx81%hj5l~YUpqt zke1Qxhy=cHupZW)4e?{0uB@rf_k>sdp+{RZt< zg?iAh|CjnkDvR2{g1P%FS{9=h4q_dgX)rg^(t;@r(-pGr2mzO0U4z^VKNZqQFf&FW!69yvpe_{J+>}v0ocfod6XCuF(OM)Jsl-&8gPmlW5d)xr$5t30 zIdb~Qh;W3Jk7;k`rc%4!-D6Bo=1Qg6-dQzN3aRvZHZT(k%>F1a8wkv@ivi3X{-do- z9=UAsJxh6Z{l9eQ-p+rjY$^5Nb9}@9Bfr0`4Ntuf?7)2?j5tNJuRw_FH;9nI9<1~* z*pQ&K3=GFKp2JM;RRV6Lh4r~rMF)e=(BWM4F(gSvkOElUBnvDhbpNa6z(U!GwAz@` zJXt_}XfDEHZRUXod;zCq+Y{R4Ij7L?3?&23kWIoS5pegjab_pP`GT|Ti-!YAJ08hE zI4+lPezL1n{VzJRF|ov!fc{^`iy(AXUoT+XN0;kbmjb@uZRW#?hLrwnQb1}E%<>>C zIFA7s53V?pMYxjaAtEV&<4&+X9X2-shqP>oSt@XZMppAndBW6mi0_VOb} zQ5L*TF^^A#9U%byQ=zwjf&sq9D@P@3!uB2yd&P#`=guS7ZW!OsE1-5&R=vgL(){qj z^SFP%rrCj)I0kR3!uie6W+-+bH{!4@U zL5(?uI5fIPAHZKC{0g%Hl4B4~pGy)L{w*+?;Wi<a(vGtEQZiQ5uKb0mtqp@=d9E>`pHbcp=EnkQh!9S(5yt#Z zmd4a7Nc#d@q`d0{z44qNmQz+AvR62^1_dnyfY zbEDsFN+a_;C3}j6i=qNr=UiWO@z>G*yu~6bVlm9d`VS1U8vEiIJF6MEv0oUk`%HbU zU6H0^7xk{0mK1w!{b%a5=eB(Lax?o%eBCst5}{07h~`6@(s_U~1;0u@ zHWE5^EHrXP5**Ojs!5t}LNG`pl|Fp0;B~g^3&efOEt!Llz*y2x7zO7=0GO zeRAP5QfFX`Bs8`#K78~vrcK&tZ^Q@XL}0e?ZbBYJ?yzFg;YfPlU3Jjw#o_spkrB3o z=3D*OhfVQNYiGeU*BXkOa;AdzWJ||bM@xGC+xS54+-SO94y_S0=Ji*n=hO7j=vTk` zRWvW}V{x?9Y20NqBwSkSo!tzXqpB+8CFQ;)zl+$xA5; zHwrQBmAhtd)Qf^Oo^0;iC#1(%Z9sI%rI=^0gwOk0)SVi>Ix669(8mh3JQW?J=J&XP zrs||@V30Ne@uiN!Y5Y8#%g3C>5Tn&Gqu)uAO6jD~^39lmBBFjH!*b3D%##QWL-fVQ zV?K-1DPoyV7;|Ja{!Je~EjklkRlLh)3o9ihY@HerkueUx)(=Zoe%LmtA7)=RB!*f# zt?oL}nsl(nq*bhQTRU5Z5(cE{{Y{_MdL0)v<&l}JOuEd>dg`b!r@Yn0v7cPK~5E~;8pN2SyQQi)90L~_2>4PJUT*!1JqHF9f z%9C*c?(iJtfH((kVF?@l27X3`J*g-Q9KwOkDuTL_tvFh;mI^>=zFE-U#i_VGQT>ccs^~GKX=PbU$^Q|G}8jI5kPI|Q$ErSQum*kOZ&I8Ip zN*c1x@=#Ot_|hw12v;aO1fe9~A;kyN>)~?waH(_%bgK(1D97cqrL$TRn<;)_!tI#U zK?fU_*)4MPFg?!FhU!6Uq&{zQ32*g%VNI!^ISK8YJ1jk5s~`_P`)7m+92UHG_)guy&UWBdT#a~7@LMDg< zr?PMF-Zfi-&D!|}>1&S`wtSVKP>lqIYWze63dQHxD=@ykfO{>IzQgOtUC!Kul4Xtl z2;Fhq40EJ|v4Bt$7;gHzo84-?VA1}x8%90V*^q+sGpC&u##K!S3}-Tmo0XiBb_XkE z5V!P%T^3U;Pwh_nr0y%$W7Nos3qilB>M>u6#6URSg|viS#10O|O?Kn06S-cUZ%}&< z+`|E{n@t?)O_h@;ljUUY*J61u;uUCxPQ#{XX?u!MF_)4n@4b_L0X%kmq| zO;KD4R})Dy)D=aJAxEY4PU{KsD{y7I%z~45C2sPGYVWJ*nN%{Zo-GuT>0Du8Rj0Zu zl{yLXx!Hk%vjYROm2!J=&yHbD400Wc;ut738su8M!XwI!Tx9HXdt7AG&B9Eu>N_l+ z9#3UL#ld1IlNtw_848NqITaom2~YX3dgsb>hvv$;;iH1mbw#?p7!DWP(^qsY)&`t3 z7MwxLl~+YZMj}_SA0o`L2O`m24}OOF(VV1@tvX2HLCo13h!LYn2e)!fG2aKnw3IuY*`<2ZUiI_~iZA0;P76qaX3w0~-jL|S+-}7S^25`@ zK3eiVd-vViuUcZ3&wb7kYw7M@+I!)%l~1d$E53zG;IjXJ=CO3djRfos^a$MHR&)`X zx0@P)NzsiA7%#$F-Le+@L!e-^4mP$eKDu^PC>;!>Qh|dS9tRJi0|^HYj^e@BHNA~2 z+_t<1ytA7r8kM&aO#ukLCh?I%1X7u$*`ShiNQdwf>7RbrA?ht5-j=@mgf~PH@sE2Q z!@xq(=0QGeyhF>v*+}nh+&J9m^4uuCgdg;| z>G!S@pXuRtJ|g&%h_(a*Rv6&tA|jJgFpGD0q5~rE-R0@p#Jbyru55P%|H$DY3|lNW zT71$kk$K_9<=uPw#F(+S*BBG~gx>0IFT2Sm*S%OTN%b$+!U|8oH^D|?Y+OM5)eLV4}b_rCYq z32$Ir2iT1Kavl$Avk%^{=@ur1Z=vU7vTn*oOyoKeA(CQ?wnNh)5FFc0$X1JVgoqS} ziia)QlB}p%yu}aP&NptmjRiMb%|)?(i{h#?*bdkXbw1xWD?biDGtu}{Zto=+q*s~Jmlv(=F2bPo>iwLbNdVe!RX5k#5 zteXszE)(cP(2m_)aPTa_YpOfK_(?oqTPc85O(~GPhZS;2e_;bBC-6AA05Ok9*Ys7h z0PH9J`8@X^=3xa=4Q1fdH81i;>9-1~CLnEi$XPmrH54)wfVf2#$y7!yRvEgrSpq^~ z2jZ!V#lxv|e>#2CX&3BvYsd+F5j#L2BWK7W;h6Tr_`vu;Tzl*&@@NP(<4CF@DCvPz zY9L**`qFNPTgP=_C+)KWWgPS2KOXi)MPNnZVOfmACcxLO3DkWat;Ml^#Q8>Ct}F4_ zegp?l;4;vKX4vD9phJ+SGYgq%lIb`STYKbS`hcb$cxGYe&V?O2gbf=IsiYwc3Vb=& zB3w!PCcE~VgFCMs9K3etiuF>0y;H@EN<69Lb;Ps1h};$6y5YBprdK!#Twu3L4PTKlur+k^01! zagAG0vKi|;Sy(XhkPQf7@6;t=8G(csWcmCp`LlcWjE%AT_wF4V`!ah9ASHTUfrGi@ zw9(I3u>~!i595?e*$hcVQC~nYsk74r$rE$^kDNHUr=M*beC$$Y{^mF5<`$nh zd2+6b1JiYzs-Fc@BAMMHSp(`w5##3|N8|q-d{qT@cmmmr@g&!!rqYw&$BLhzat;Up zR2SIeNra*LvEe$TCJ2&4?5H6=s^KFg)??G`$f3jL*Q;gAivS9ASt9 zWTsk%Se^O?AAVDBGg^&}4IQnnMuWx3nryXbQ;Cgz^_!w>vD%HFxS_?|czM0$>$Q$% zY#Mt_rqcY6VbNiKe9+gJNCfNak%w4y)mfbe1ROQGT086wX0yRo&)PiAcAG&ov05W* z^)$%hsiSP0aeD5?a>V# zAzK>ztKQ-(Q`Cn^R?u}WV(&&TG1K%y6gIf$P%t`SQepIh$fk;xCCE05_OqdBs}&Bo zqQ&d5TBdg~nINNigx&)o3&vsXXFF%C7Q4?B;gb0eWo_3lj8GB==cHsQZoy@1bx-)bfopySswjT$c(_YyTIL3F+gcm0m(VXnJ0thCsVz&z7_Y+0cb!bMb$$b8tKlpV0X`Y%E`E?y2rFi|<{h!73}22=%}Z;y(AU0-lft4h=b_w{nZVy-hte%qf&5t)50L)TF`|6k%d;7z9UNBk7X1Oq9V zYGJ7G}wiS7;gXzA=&iMZ&) zU-^2{eG#3N9q;McjQ`DSOZlp@aEg@6+1bB_DP{1lSDy>sFW&x$5!C&3=+>B0DwhHQ z+M~DA#*BH>&M)mOCL?Rt*>Mr}xcbdb+~KeEU9on{+O>m;j?Z+gb2O$=^JYh*dI};N z@29#gh|o0@m5A;`9cq;nQkAC+T}f!NbZySeEnZZ8~qWNhba=NV8- zs2=WdRj;P3FJPDi7h?tJ!i{p6Vh8~fY=_4SW;*nMxJ^Q+3pisA0Bz*mJ!`dUT2A${ z2el!W8;z_CEZEdJw%%4aubv!BhP0<`Aq<$Ga~(lc*={MBY*P=Txzsn(E)fVoij z;fuG89@Y-+s#NeUUY!>{+zxkNemRIB-^lWM-i_Xl>a1v!9!MdV)?9}E!R-P1#HVX& zC{{O5RwhJ9UnG)1&E;LVIyZ8+VWbx^ru0v;Y6~i(&7vG|0POMrd)V!DdsQEJ*^dwdBilh+;c(F?g4!jX^eK|fD7@91o}lB{pgabf z+h4<`V&QSW-SD966mztC;JTn3!Cp^ZZ)!LWKr@q9Bui=A_95~)3I%`fU2{SzW>=x= zcr);G+XbO-=b*qIxae6R993{r zKuf^lNgW1%Pz?OKfUIewnkKxC47iKugaq%8x(|uGN0gPj2N#07DG+dojBA;&8E_3A zEN$kYmK1>BwJvNR0~|mC3D(Xp2=1OPSn0@X11lYSNgf=`Ih{&qHoiTvUAB#Q%PE*K zUkyk@vwi#e9B)kwIEJ?~BlZj1kqCQeJn9V?`}VWFtxc}nz@@Fhdik2fHETchMQ>-% zx^+E!12Nl09iI#qg7s|wOh>t1OyIy9c(3N#MKyq|0WEk#_npSLj-fQc_8H-5T2qrh zMRZ{hBC%wk<7dzTxC;|0R|)e#ky7S$Sn$zfy9o90Ircer{kOHBP5j~)6Q`Qnnn2QK zsx?clIO|l`I;?E1$8$v@d$lOs`~vtTrnTpp5RW&oPzEh@`-UTmWTQ0|dsI<;so@-gJ8qzQ?53Qh?ZL5}9JL$%C=jNndYLT~%;teG`0 zK0{mWzZLD#? z$xsScgFbabj%D%fcZEWyXC2_DblAhi5Vw#EJ|z{kS#Ug*K%{H(CLWU}OzoMR*aH?m zw^s}o2gpPoM)m}s+cCN4K!O;U6DLP9^wkyhBij`5vMtpwoejXt3%d~6Bi+AK&CtmP zZwdr%I(1V3WEdY?FP|ig^!5!8_c<)mN7RYz^iycFJr(;EMGD~_pk`GURJG9{`;nxt z2yk1Y;a0|HA^{w4kwCSn0Kb~OE36*5Z@4(+3!i>Hli8h4@4`L*m(IRU{QpCxrO;e# z?E1-(YkjJBYSZNPS};ow)ak-{Epfo3eRR7TJmwyW6nC^)wN3(D=1sVZl+l`=fRQF~ zqY|N+(@S-^>zF!!yc{h$^_Qby)=Q^%FW2mgD{AxO&6m}-HEoJ+95 zgv+#Jj!Lewl0ZqL{6gquaOjIjK(Eh8e3_$k^h8s$M9lPZ^x0=a$&zG^T5LJH)$Krf zqj(@!a)P%O1aOOIpn}2+{c`S^fpQXoo*@uGhTIa+W0FKUs*`2yRT!qQrdIS`Ai|p< zsBNeuj3RlEWDgRDDrj_QIrKTPX($07Fj-{ETTmqXxpSO}o?a9jB+plKXd~yx2L(Z) z-oZB;Xz?I9^eXh5&p~3Ko*ag9fhErj5?@H{NpqUV7i1$W z=M4*%(FvPzD5)f+xFznjdj;FXw8c1>l2cMbl$jJqYI@LuQG$9QC8)l!!l@Lfsbp`$ z>$MtX=dFdw%6o_VJ!GkmAr~>djPdn)H|jToerwF ziQN0zFEKsYw72>5dvG6vP!aCZ>u$bzw#VPobML)3m&>^96}~O8T0+xCr6J3fBSYm40aMqqh*JrB5jo;;kG-4oi>ZnXt%JW{-xE_HehYq+= zrvYt3j2XPEK4P%Tqzb+aOr)~Xlb{&`qFpWaOrL*zw{l5a5mbt zv%lvnUwz;8Y^>XUr~6J>z&Nsp*mKDQi5UU*NPQ|>+QCw)ANege{s1DsqYk&l;!MOL z0a#;zlo~CRLIPfk?fQ%Mas>=PgoHO-w{7iO{t{n(QR+5#Y{k4v$~RjhP!;#Ru3X z?XMmXWe4#LEbHVA++Ty4o{`+Uf>yL*m?s@{1K1%eG#*ezFEI0IFTxxTiuTeG!Wte) zm&+HL`?NWLfG)q>(QsI5O3m`Q{wtVEFTqSoK5(cpP;GSgvngHS8QTbxnW!RGjOdSb z2k|lO5Z{rbGum6zQQ;D~b3m{|>}zsLme;i&Z<2yRNxwGT4`PSys!flUhR4wi zTnH?;v|2^TRZQ-8EN93Qfb|9|nCN29ZHHiN?3>;1?zP&F?~6TAK=ya_7)bC_-g5;k zYr^dpCK~zHe%3-vm;|+w(i}`}R3(G@p~)xC7TmSZ|I2sjz{YbgL%UayaSt zTa>a$M{_R}^9%IbWqXW|>dd2L2>d}3r(Y!N5Oq32A2+TLF!RJ-&OlVIy(`T2&z53o zNeXz!#`0sxZs+%E*Lwq!)Y{7aaNEJr76UVS{n~%nh7a?YZctz3%OKzJAw=eopQZ+b zEg`@M%O_KezUmtxlfCerFrW+$q`-tGg^Yc>lI8f`U4zbWLJs(xebYPRxze4t?et|z zYAUSE96eEFf9$jQ3R^Dm)vp9gZ9Q!)=3;JmkJst%{n~l`J^SH>Q{uwK zGx#CEDJ#d9%suiS#_Ca~&F&z2C0=M3-cd-P(Elg|$rW4)5<8L%qy|-WF!gLIDksqo zWdhr+9%*~_!0C8)<dWeWI_y@0L?gfmiga2FjNKt^9)U#wJX(8(6yA12vY^)l3&> zMuVpAbVZUF7Buo9XTYgl93L-g=draZ&eT~U=~O`1glFn(O5YVuRK8H8FKc(rVsQWK zdx{gUe6#e1?k|lM-7ZJDA!r6#IU8I6Mu`xnhtQW{sjZ!SgL*F8L3J5c+KnvW#G+QU6~f;LL9iP)>4m$< z0JTUJOyESkZ=h9T>awd zi?E1c-oR)Gx&pMpN9Ya}Ycb6wE+k_w<}-&f`C_4vDd!I6${B!8kQr81Pg*e?l>(Cf z6ci0Cx=}EeC~D!?X7&iI6uG3I$uQCzH|&JP@T3A^50mH zJOR{1cGU}@kO0!+mK{z9&MQajet(cIk8BD|K=e!)D+PiT)dM`byR za3#H8>OS!Z@xTC6Nj#JKpyh^BK8QIF4C+%E(7;}Hd)Q%E0yuh`_!NQRUST9azPXd& zCj`g`Mgl}3od@r6)kv`Lt9_L=Hy{_?kD()HYD$GO&7nIZ=8*p&OI7gV!- zI}61feGCs}kElB7W~Eeab6Yp?5`AcI2f(EV}2q{o96 zO*=nybaeFSkak{=Nk6ZQr_tkX0ILRPr?~N#~Wm4{)BDFha8(Os@?U`_)ipDBQ1viaXy+gp~fU<3c&Er?cO|F54CD_m6d!c5a&5 zIMg}j?~i0dK-2TJO4n^#D)u7y*eds(xZ2SH_>@E14T${_i9{HRWk!i5gV01YHIz#Y zi3dewWfL(TPsD$8Qt6cnVY`g*@^F~VSMn%~zaaI+b3?sp$xgZ1Bs;QNoPJ{q#IXg@4_rY=KV-gvstizC7d-R4+Jpmyx`AoSfG0x4+@qO= z;n{)x1EWWjS;aTKcN#0#LSB`N#WxUo|MEhz-##$lJup<-T^=njEJRZXw#0&2RDdSC_EEWJvS}}6J_mf*@6g4pM@P6OWt!&a+E!MMl5O%6vQ)UqCPevBT|5usmG{V z;IRPHVx`C?Dw2!)l>#G(oAgJ}RnCkiPoGYXo_U>FWk5NjK9uyXEPCB3u*yE1a{5H} z)zQw=r#na4pWh4O@&|p)-qH@xxvTyn&X);$7iC4FKg2--9juej z>W1)5982t8Uhp0+59E^*eN(-C`LSLj;-ky`%kM>tbze9~P99(<7OL456Vs zE;>RM{YWn1b65m^L_4GVpY-{z5@#a8ra*c!BHmXp4o0fWuo-Z$2wb<+&3R`>)f*VQ zaV6cL&PVu)U5ZIwr0?)r0Sos9+)`X(>ujJJ3}mxGpS#|cElm&^;fQ4GaI~gEHmlVZ z>}qv%z|ycRLsNZJ9<@Qb3l=~4e!>`MpyneT9!rf_$-QErT+-{fXOpwF&;>w|Ix><= z-7yk(dwmK&wQFqAV8L5l-~)KRz z_Un$e@YvS2@V1VQZQ-`9W8pUKf7-wai0o92jrC29W(z0r!(AIGlo>Y!0@59;{^nY4 zNg~1r7f>5;*N~`rp)E@oA3HvJ|0}OL689(VZnvFTv1Nz;M*G<-d)O80b2)dTcBviX zgni%c!Kpv){KN+JG3UQ!?7mlDbtLaweSXHy{>JkYzKSeiA9H3Hj&NN}S$%Hr*ezr1 zu05+x{Wo+)zoGvB8|{;0Utd)SogY&`&Fz@u(iG>1h|q9@F0Sa;a#+M!GiDX4NK z_Q4bHXgjuUeJ4@kb5up&C%kh_H>6dDComGfWY5A70LjOtB^ZTUKpU^x2A1PJbk5o( z{~ZauM5IZt?IiZ%X~I6OCA4qAKG{}4c*UQ(k7O13gJ3r&vikMkWP{bEISRo?h84 zD3=o+f^MJ-DuX5m%l8>(^j!EB`xuf1Mz)Db3N z)R|ubYJZmRP=qMJMdx~c*EX%T8)67}y{Rr#XR0sNkJ@vool%8DR3B`rRikQYZ}Wyd z%(ti>Z$!wFsNRFP&)P$JmH6S`rC!wUs7!MH$esovcDZDrLYnIk6cub(LY)n;Kkb-0kM^~#|Vn^JF- zL)ycL-4?~LC_Vf{@rNjyuRY7y#xOK8)ZjNFEip{FZrVgfY(y)59MJL<5R6)~Y)|!` zNT2;UDC40rO%mEGsq)FxS*j1UM^z_H>MLPI;`w-IHHlrwIEoZl1mGqH2lnJ@t(08X zm2l%x@DGoof@M2S@6kt;I-jQ7>s z1dSc}aLIOqJ`IAJZl3-CdoQ1$2ZiaJKxzhTPnxz(dc6S;LIm|~_5SKQPb1nAy=|2= z4?PEdPr~uKFc2iD!;rt0yu>R4^WQ8ea>Dv(p-{F0yo(Th_&4PXLh+%D7Zw6OxMpNE zHIy#U$1=^W)W@zwo8Ex&wgEUYssrreFj#)b)&ZNKZWAF(KIvc|UpMdu27D)17(%Ga zf%Jxu6p9kps~T5ywToAEKHz=J8_GK*Jr{)JfTiGJ9GDNtu-VCh^iaAeDH8tmI{#P1 z-G6`{Nk~JoQ#B?LGP$l2HMw+Sm3Trq_vR5jVFT0RAJjloC&mJ)phti4F;6@c*VQ!F zl;9x+UbVejgggnj0sbLLMqKVJahu^E(IJ}z*uN=SB0^}6Fv-9KMIz=Xdb&OEx`h!` zl#S@7f|OeT_YUx8qXGOoWw%la1x5n+56z74m{bG9sx8)66hwPK3|RV$Hg7s1djV{5 z(9`GZ_x;+Jav&^C21RyEo=Gv2*x+Ga{5K#bCM7tVm;?XL|JZK(uXUG(2K-mGw+VvT z;kef5Y7%Q*lBLDtX!O#v#p10i2pNy-D=wriZ3SdqZ%f@*QHvI!IhTYTK5_sb;vN#9 z*tqw^P#H>4|2eXa+@*)Wuy=^?;(DBR?^$Bp)8DcGXLhz@!-kG~Bl0hR$fu1q2jfWW zW_ovF*?LZE=pHK&5=$Y7=#e_kiq)j1`@`Y>sqItzC9FrDoTvn#r{REUxkaCd{I*H~HDqqjW2fr;QQeZ7s%oZQFztq`~X6E3) zz`;|r(cYh!I666bY+^!t{lj}xx~^u(4cs)K9Ur`DVBn@fwgD!5l zrnWpzZM@d76Y{&G-OGD+b{OYU1 z4eLVp2UDrw{h@W*2gz;gEmvG&S-&kA*&GgUj@%DljIx0Xk?d3~z-=yJ(( zn;-ivWpCTIej7P(jfk-w7p}rwZ-O5`L^j#1r_n6B+YMwFB49sM{M<+yRt-}% z(9{(PMJ}>72|dTn2&J=}mz>P_HIrhu)tz%WwNKjYjot?PMSgGWQzz_9IOAG7!>+J5 z8Lz;%>ulPYMu+hVYy6)Yo9zxyqxK_j;Ga<+3OLezVIL>ASLM(u?)~zbE0#SAWJxE% zrOL}ew)E=rqmKRWen#<+i)Rq{38y~(_%7|}f2-bV!qO+gCFHiBppE{R*m%KX)!Q#1 zezo#IyO0j7&mlafrj|tjYva7Rup9!ZiAWwdJlSlowh(3g57^y~n8WQDobnEqrEw`2 zONZFa+7CL|z#50g(Sb(a6ij!l$4BKsF9oatd%kpj;zH5cRwx?08>kjqv(WD%u*i^^ zi!hhfeT)HWW{3i`fZ_=W7M61tWLX?rB|-w=h-56<8@amx!mRG?&g{lxS1y-(Ap;oX ztS=`UZN`A8y>(CSo}3WwzFYg}7eJeEQ)P$4AMfVdY<5?67rRf+wwO$QWBs@B16+p@ zPhEx~t}V=c}s~4=jCNG%!;MpO=h+p~!3|{qt?MT=)|2W`|?5_tJ32mat{p zFZIw{&n4lUjs4Rl*Yx*abIHa~y1hLe(vF+Ot?)h?jHaEU)s$*eQpP&*Ge(o4%~>}r zS}fwQ)zxM&89zgxDsA-XPJF63ty@L2ux6`mjT%MvbYM8*wyj%jaW$OGW!FX3c->a+ z-`4YB=-i^TdU3u!vkR05h+^s@w=$UoglOsZ5*xhZju-E|^QAlP5Hi{kp}o z7zghYE!3PN#ir|1tfg|AKd+bYCXZ$IiK=O_EbiyQCtFncWw@J3l^t{^E;i zd{uDIe#oVsZmwF81CgBlAO?VTLPk^`_8IhdpJFk>E^E(~#>Y!622zjbNI7CLj!1b< z=sz(BL3RAV_#8sh&LYX*@bl|>C#)(>0hnG1v8ewog^mEAwE7U| z5CfAow}8T}4;eWUJ{b?G;gA<2z~%<4O4w}|jd+L(u(yKIVt0e+TSBad#o`W!1EE;J zD>>~Jd&q9ZD~z%}@95-iui4iS8Bo@_96?tsEV*1#c#SjA1~# zl0Z|(wS}Qfjy;jf4UU(!7t7=9_@i2pJ}AZWxxpOVrGq(kWK#9{)JZ-@b&d;SvyMWZ z%tMpF>2-5{C1H`XiMHN86 zgwwq^>%ArOOq+2D%s%W7L?aO3`6jaU2Q6H~W*B!pl z4Dx`<1-JT@t!QiX`^p*(gdf2ivF;-svw={&Tzya=ui=>6Lw*GM46xU@XbpIy;fz|m zeGu*_F`f$xLNcEjNZS&LRA4raMD{17=B-^(+1+wbdv%Ss+3Iu}5=CQQ+|gid_O7|g z7ID`*|6;N@iSkJf`2_Cw=V6_I%)m_KUFoE>Ivx;RB@(fziG8;gpUVh)7sgX5@2P#- zbe#Dpf~Hz`@;3nFwycN1$*HHq4)72U!p4TX%uYavVC&#oQW{ho*`OJkLq+gL1OXr7 z7l4Z#NwG9{6Xgmn`{ZQmj(vlo1v)ag#E0VhCeEcslF5;o(PROG6p?`|@W>m|sbovb z=Ics4d$2iWzk#j2lu>r^=2~&^hSuch%;m}CarN|MSD2I%cZy?n1mug z!l8drz0K8~_O37tjMaCHJozHhE#n`?8=6!owUWM9@#uLn?4BX#j4wAlJU29C0|^qi zkhFJS%-;pLHKH!uY+!h9x>rWBJDdG^WR$hp<++`9M_wrJP53t)dFQh0hlj7f>~5WH z?C$JV?e8kYW3OK~eDP$>J3vu}mlQ1|d;>FV$Lc~3j})D=hv=F}9{fMi zXQ7*7-k>Pnnnt+VJy34Ue%`?<9&b~U1Y2Bha0v?^;}3QtS*KKQW<-1X&If#NPNz?t z)>+?#Iu?y~bg*a#s4xN}9(7koPfN6Cy2?F8W3~llf1fx^bRYu;49RAg9)o;l(&Gg^ zK@8*Wbr{u<%4qq*Fs1?pmnXTf# z1usarn^HuO-GE?G1P)#RcKrRA|x0QyIJ+O1(b@o;8{SKaK0W zmY+L7X9jy))x)k2tu8;tnhuvYrwQg$bM`EOw9kSo-_5okhq=lzJLdauOaV#$EjmOS z5bm#`zd5dGY#w9JHFB&K^*bGBM*hJFa3w^uP8_W`zb9#ih@bUjVfYM3gz@-j;>P|` z0j&_7N*8v7$3WV@uy23BTCk?sd$H+s-s?ub>To(Sv+rm4jVg^F2pmeh^Z-5r|hS#VrVdgKvB!^ivurRFg;giW<_it z2$~xa8d`ek(wE47q1AMOkLM2PM8t3V2WZjiG@D&!3*(b3t%$l_#MNfdg;kUypc!xn zFxV=DVV)120_cB$EkMpzp&Q$Xjt3+`8x*TFX2v$5`b+jTB^KKl?fAhOvneWCQVmXv z$uwdSERM!5qnULW#WjL}&pMdd*yU)nu-XwM5qC7EEF!+XhH2wXEiGYL{(P&!;4_GR zmx+mKv&rKZ1)ssx(qg0+zsH2sG(b%GMSRK7${ty>VGaJfgQD1PHn{37-3WQ_w$!_r zLFhNbsR`SjrO#*pMUj}bARTztT<!U3MiqP1UnnLy{kHy>_pXZzvv*EM@c*WSuOEfiQ{|3!S)Y z28lQLzaSU1Qwzwxp`9Y@HrwF~EWW~xCFst4{NyoyPNG!ZCheC5bh37TQNRSmIT~p? z7skz_H=nwBRM@(BM&Hx^Azoa&7TF{R2KNsP>_0Mipuhh>8d^Xxjwy%6rG8%GU&UXmkp)f(fY(Q!obP|c) zi$Vx#0cb2M@Bn`?6@LmWL-#a)mYF9!=ArG&s z&1tbZEDp&idKIgPQ`(>q;>0LOlu(`#1zW-C8;*f1K=uh~q(l($ZBmMClF=zzB%{p< zcr?x~xkZN$d{=gxRS-p=QI#AN#zzR>R1@f$Nm@l+i^m={aL+~kZAf#qvVuoDoB2*GlWD*omSGVDWo_w@`aJTK`_d!NN$uB5wR;#hg;N5jcdZqku5B|XB>Uw zkbNnhk+9mF0|cbk1$V?I|E0mBvO!J zW&4_7Z9eQa*GZxfanwo;^_PWBS960Ij=`Zr-#WBq%gw^q zSfgYLwu z;<^*E5}%kJA0D-Z-MkWE+vxE4^ypy!ApS>t*>trMlP6A2q~g=y4joK8ol}WaArYUL zh$j}5N>!HYQIAmovA3BawZu{d+Uu7un%xJlJrxHZzIH1MXfLh2*mJ%B$_V&&A3Jtm z<=kZFpthZWqya~2^$LMDB)tPMpOq_HgNQ=9q=o*`!Q+X<@xjsliHX6P$$^2%*?|dF z7@z#cH$D+kcNdGh{q3xNgW)2 z&=yy=XdxlX@jNz(iBdU{kz;hNabG@GMk)w7?yy)KaXFdne`RIkQUlX7A0JY1{mN)K zUr73TeKs35$)#pqaldOJ?fE~trb`v%m7^wEQKwxq6H`+YGrLBH`iF-52SSoCZd_gHs65uBfj9umkW8>a<$v5cR6&rQ$ zbjRJ=eaG3DJ6@9IT`}iw_c)H6smvMG*k3lw% zR^C)7aG>DO1D+?-QF;GD=kg}GgJ zoA>eLNK)~#FkTQZ=?kmgTWrYfci@1&4W+%_bm+FI955;>)EI6b*W>L7$6sOcMm|m5 z9@%uE2?K%xmOiXEtqhSTm1f6nAS@XiK}U?1yDyC20Ws zNL4YAT97IXODWVHaMfUl^JT>q3}?vr0!QRnIs{!xWlzvHlpakddtd9#rHcWdWb1d! z2;p-`?g3*-?C%$T)wL~sDSSX*B~K8$L5W}5HP+SNo4oYWWUuy0XT%$=uWgcit&L`H zo73J9jlDgf$B?Jd2fhIbh?tVHKrW5bY{b1Au65w{#RU*19$rQI!|gX!T^}F*$bdyL zr~~V9HCasZeA+?~X2n}_*ojCv#5yBhCZM`~;Hz~GGY8CCF6&%n=C-zYdoq|C`T-s9 zkXIkpt_rjS{ms1>x7o~!gZ6?gfg^OLFy)P@sreW9|Na|hE3$`?=K;+hfo!f@sk+Jk zU*UkKV@q&SLCxi!yNfax-<2CWj659g{m>?5kkAo~TQ9%tu-#*~9UtG9qTMI&!J`IR zeO1o1^Zu*j4uKX!H(id(M?Z*QJW~LWA|OI-NwV-)r^KbX5tY;(1xrU(Gn%l}&f$H- zJHx#bGZTGbZLgk_fE68H9}?WZjTf}}FZH97cu{@cm8K~Wnqa0HySZuo`lg%5)=gX# z4qr6!iDpXjQThL@kCJ})^lc2eKVXQ*WddDUjcFiD#)T-Usw`ibX~IEM^*X>a>u;(! zRH@xp;-yw#6}5y;zA}!4ko%Ph`lD#pef*!|1NA6M3Lm6t5MmwVObKcG@Ss3fMd9arMT9g@5MxX=&d6$TA+%%Xt3(Lm6LqXt|8%ANnn2AZ%dcm3kQrq){Jz9gQEl zj=twCuo}%I@{vU*-vkHXhHis zgs1IzQ(t!g&=>B;9Y7xeHUlz1n|w!Y+*#M*Ts?*#5O50T;tLV;*5?JO2|9;A(0DhVelhmkyV@qcW>@lAYF zWL%9^6!2PXh z=M*lqSW(7dh(5x2@p}&)gSBqW-pz$b{-VzL(wF;k;XnA^L%r)ZnED?4v*H?rx6ysj z`w{6*I{x!Ra~hFzE%^v=Yc>%Ki{^~797bf~dD^}XwylbPAW=vc?oSuePay?1_>g0r2de;^oQ4N-g&KZt%83bFwlPB2T$>}+W?zx4MAU;D$+F!x{xj?$)Eya z8j>s6md%_0w6kL^-GJiSXrh>ruRZncja}KS@D1%DW=i^}x)DvgX=kZxI?&mD>h?cK zw{*w%efbO3`*fvn0_>m@Xfa?9Ncqih2VxK$6jy}nWONRC$d ze=+wq@NJdn-LUT?S(0U0*0*F?mi1*xkri2%Wy!H+MUfT7ag1>s#~5KU6AYL%H7Os# zq#?~{2qDmnhXyyzGDcYlDPK)fmxnQymr=&NuA^y4fu()Av}^kY)>4<3@zNF_p8s_p z$+45b*xtRrXSP0$zRtPNeeV0ZuaE!rzl_zPo)ELFsnj!hc}1X6tFKby17lTv%dow| zFS#iX_B^}En0h$W3Wj;MbVW36aHw<&ZB?}+=#Xc_-C+StmrJTDwFYLi z>19k`YitRdH37e=sy-sf62TMfd81vgx5Faf`hj$=?Szq)tjXBwm_(JiQx+ z3lDYkxKQVLCN|{EQce{B&HI^3?B}y0$LGm8#MN>!gz5v1EdCq;ViX?ZsR09HW6}i~ z8*9c_a**OuTO|FL;sXvKS|LASM!{sSMvv2TIVCw0CIp6cQU31 z%a5zmx}D+-a2Iem#N!X>f^BIEhI54i8Jhm~dxxQOh*tt2DhzxnQ#tatLmu~m# z+F&a2aWCZ+l0U+Pb=?cgA<2|fM3vy(7~`m{20CM-wLE}D9U2rbw-yw1!Hl@i?z8B6 zpNfRom+ zPK@_2W7QzMbr~RQUQWp6Hx}bD9q{^N8kj*`4mF>XK^dV)vBjD#`&(}z$IGn>3@%X^6)mc6_TIYp zrGA!j_|=f|VW5D}2qS@Ch|r*zzR?mh7+X7Nj$xvK0EMO*tZS@MxRJ9I;{eVw(%Bo5 z)_vVMA>ZAd&2`%y4o6&gSZ4|%Ol(sKwy|t)8lNIfr6-)V;K^V|tzhvd+qbiq<(vD4 z#|8QL(eYIJt}H7PU&_JRt?`)zd)ovMM8o;EA&12-XBm&n?h9YyvF>ZtZ?PFrJ?jUKYv4iWAm4%^L9*l8jDhFvd9)(fdmprWK1<+U|~j}vMJE)iTFI4ozkX+y!fuc20K=# z4FV!$QyXH2Qw9+L6*7ZvotTV^uJ3izT!h~Mk}kUWz~(5+zW{DxS=-3m*4~MUUSaRt)?gxmX-oE2 zE#~pJ;nS{x6$E>Wj|#qibTS$3Ge8zS2@WF$Fjf|m#n=kWo)BrgrfTKV#N{5==k2R9 zy43f1c30`-ORBWSTkjE8hvr^u{G(9o<%yp%@Gm{tuXY=%?q4l#snRTw>Fe|?JT@k+ zXOdsCw#Zabhh+(i5wU}C)^(am#yUR_(JP1h?uN#`%gF)ik{g=2vbbqy%%1@H&7Qc)r+VYT`FuED*% z58n^k+}%Sz&RVj4wtmaAam?N?FWcDhT=qsYQ&>zlE&GZiUi;OAD?Vw?niuFMCTJ!R zcq4kTN{}u>ZdD1hK(>6E>vF9S6Xa1&lFravdZG6yoAC>CGlU1iR?;{4HeoE-?)K5P zbj+2qk8R}}?T(EOyag9ZD0WwABNz+v&HM?xZMUg|dEoEV!v40=tz)$v^|9s4iW_NB z);78<7+aECa!1=}d$0u?^=!Ppv^}+CYk(o-rtnD(T`w~e>EGJ_}baZJL?Lx}9Ec_L&>a_Xqnp98h4Mp$*~8*j)F@By+GWy-H&Zolwohvri-!h6 zv0Zk*AB|%N?-n1t`!=o7P|f=2Q9SKN1JwpfpMc_lbupJHn38cI&w8Y3Q7R? z*ae6CUb_&oXA1}eUU;bWy~~Uv+xS?PWRaAOauNHW709eArffh)4#}Gmq(t1wHl)Qz zN!*;rkpNi2#&sLshOR_yE<=Bv#1X2{W|SFVP*I334(d?N*Vx%d#O}2$(?2Vmq+f{> z;!BgSNHv2=K7S6s{UiLgi0!8Wab&zS;7(R$g8fQ#q@nIU5zoZL<2hl&sZ-*QGtqP` zmIe-O6PNLn5Ba&`KCo5*7lry8#eGNH?7(KwWgbqawQ`*znwUO#@YQ&nAL|yh`D#e1 z7~!}vNH8`jw4+4i2A*jkS^(LSij2d6fEQg-qA5^7s&mZ3ao#XBSlH>3YYq01-94Fu zhYx1*HoH18K0CfE%z91Q`vG9khT6g!Q^w-4^s%eddW}NkHeT+!_2^Zx*4EgSl}zYb zzWgstTR_Nath!2L^4B&r)cP$c8unO#X}o;;{vFI5$PO&(-*LZxd~yFuvGWD}3+YzW z?LM}P1GTPTDBnHsalIVTsx>|^Jud3z1^rwHE^Znt(KWm?Go` z;76xP8t{{9OiC(OR5_C+#gr%@g0XI9XYIB;AKKk}M&Pe?weP1ho*j>Qg3+09TZo4E z{aTYL+=n5~zOK2F#&zNAx4JGjcz_T_!Oy1j^5x4-Rn`9}jct?Wsw$&FQ>e1|X^^9% z7mV@wUSA+M&dUp_PbV>Vhk<^V*y&0qc7b#VuRXN<^8Ks7y-{8*EI)LBWWsPFcHMJV z{cL-=ULH$)`_Q42i)4Wb5#QLQ#wZrg|JcxUwYxseh;%1zxb#pwKW@m5N4%0>JS#+@ zEb%b|X7c#-^jT@7$Tj8XW#H7=vjb8RJa!R?ig~h{TlIoe@`X~xI3L+X>EPRiSp_$iSC2q^K<_nUWrBi$00+u48(RW1WM_3LcHF}*5C3iJ z(_J&6=Q`?y(CTa!yg%75F#VUr(Z;|1+nH>abtWtxuSegOxXG$v@gp~nJIRor2U-Q% zPU6YRejXL0(GBl*zbg(UUP!QUcI(K9c>jh1HM7vp4v6DeE%|kl>Po1oZXoy(VZNjh zno9<#Y^z5JBL)>Fw>-MB-;qAP^Bf33G8;zy;aIj!*m$>fVr1VH>-N0W-Q69k_nYk% z6pmVC8_}3=A(S4uO1K{hC*DFszi9fwy$7a`i)9ufw?JX=Kwvzh#5u8GJ0p{~whHEJ}hQe!0Bi~QbF z{W1g3GD((Y&@#!cgqmVO>0(}jg$K4vc^>l?5In}@?^OoK0knXFeL0q}09L z*w7JgY|hs-)H$LnS4L~R6okJwd70^|(1@!cdD&%2gtt?TjckY00s1<-8s4g5P-Ez{ zOqGuYU0R1cKbmi&%-y(ey0^{m8VQYDJMLlV02=PEJqh9pCM7z2+)o1-rhap6IjfJ?V=$9`H3XTn4RLmgI=DG_8J&S-hy;{8WGEnv zcxUSCAc*<7xa@$y{H`Iv7y7_fh=X!h?Q7HUecXtB+<*ue^o9mh4l^dK+)T$_xaSP8 zwvEqcH#uFAey{~Tc)idTHW)UspQ8?hMhN#uLMfHh7RjH@^V?`*n%!p561I9TpGC>1 zqnCf}Yr=lmFbov1aNkbP7w@M5!Abas$yw_r4>1Bm2>G(JU@Rz1&K;ek=ie5@ z-%5MEy|g981gFvW4vd!o=lN*k_+EEOn}P3$$hkWqp60it6k*DJoF^fnItQ2|{7#7i zWYZyC32Zgf{LzUwzDIpR4y3rpC+<9-H{h-Lc8%Amt*+LB+L<2t8(--xc$BJOg3w&8;Yu_q9%z|5TmVp7mlHD?t z&J4CW9B?)NpKH$xO#T18Jq`bL{qw=AmuwD~sh{$CVLAFQYtOHaU%EN}r`q%C{{LR> zIkxq`S9@-4|L@hFVdsBEd))tJYXo;JY zKa}RQB1C2O4#%pk;6>F}+n8C`{B}tk4y{P96Cdd4U|+D~PyFMK4w8#n5$Gy>`xULN z{TOB8KAJBM{Gq>B^C)R7JxA%AL+Azk%1kz`F-}j{q|jBW4r9* zp1bbyj7P)aFake5$6Px_yo6Wm{t@wQ`oghIuDf=6HVqGl4-FHZldeyx4;taSNtdlC zTY2d=P$b(#Wr_eXqgJe!+E<`iEd+i&nAW=*n8VR;iM8Dr)^YZ`6~@vs*9f zH*u$Q1sAPsxoFT~*Q&L;pu?{NXw(wTU23p7py!>>BMBgC+YCHqC)nV6ft(luixanD zh)d*RBy_@;EhyY%9#ysiHEb!SJK*o3bvg`UC?EYLg$Ei zJkMbh#P>Y~wJUSj8IQb>jYft2brsFlkTrdI$7P*(j#XmkE!gO|yyNmzO~@Km*A)ud z6)t6kbA?u!t&cSejfwhfmY4-vyoLG|jjgSXE0$^t74CGpp`27Qu76iyPJV|o3jm5t z2F<0+0#I?2MInU~0Oln)Anv4Sg7x99_5sUic%v)W-rwKuibN4)?G^j?Y8}%w=A7yG zGftolf^1@-J?PmG9<}t}I*>*j7PsfbXMA>_ogK6LsE&uv{(;ZVbwuC}BP(4TCD08N(?EC-u^o>RPWcv-FdXgaj&|eL6YZH1MPBcG2sF$d@rm#KO?1^N z{sBJQ8>|z?>w>{L@ks!3L=WJe@Ed&eUF4!GV1X@oRJ)t2Y3QJa2-^M40z;<0+hwOgp(7c>ekyHD`s2?p_D zM<~xWiVx>Q4z|$|3W+au_I6g+*66=usI6JP$rW-5?}VJ2y60xPHzA+cDQtI!#6t-x z)|0U7wi%pu!*+u`VX@g@_w(^0VgCq!Lp}>7lGKW!T3j5WNjCGkUudt=+R$(l9E9~& zcWc9g;!jz9o5v#lRO?U<3Husu59M%HnBTNwlN!Ahw+psK`H zA}&LBFT}RXFir%vWJ!HPO-;jcr$*zf{j&I)&Fi(1sR!o*Og{F#;LRbYXJmsf;{-X6 z%hAn(KKtCy`7+_K`{rI|Kf|RUU+qVK#km>~y#ju(#q1%=4YiG0ezo&g>|g0FGksKc zml$HN-?h+Q)Nx;tlt}{UG~%m9s)=P?l#(AA+>$#K-g6PodFYzyLj!dD^Zpl#fmyhB z6e|ijgk*3CNbzueOKImw>c-zJFUL19I(V~oXnPy>4V65HBWgr}hA1ebXT?Wz}v1=TcM^~jf5eVNy60%*9tghGBXLm(2nJB`V@O$KA zS%)RuGu#`J_ao-+OZnkM$c?jY*@(y9=j$_MH)Lb}m>;((d3VeiH)z8>Vcbjx1nPa+ zkUY{hg!V0NWA`VtQF7yx2LdY_39Jqly{M@GS4wAsXx$}Ry$1;nsOKE%(HMfMRIqox z?Zb)OxQ0$irMlE9*uZq=%lO;EseyLH2yh1e3_pXcAf21t4reJ{&(-Mfdk_t!dH~S1 z8oc1!@dmtBuPo`d(lcJ8I>Y?bo!<~V8x>K-j3TDmnApR*_Z%KpOeluh9IV?h4#Fvo zN_8BS6X2#a>|`coVf8e{1kZxzeZb{fG@fdJ&Ftq z^3^F70YpfoNC>Vrr5QrS0XYV}jelSQ=-&)yq!iaKH<^hj1pm?(B(EEO#&<>(RKo^S zy{{qJ*%fHYjAV4W+PYX!EeKV*ntER(zPv5E#BDK(uh|>?Ee#Fg?^(6Q7wzg>9z$ZT z(c%tRh^FMUy31U7>YXC>di)gT+*_`+ zs>>huA|+`BV}O>KQB1SOQfJc&6`-G}1v#eLVypp$3%L=woe3fX;UHv8i9wa-fu!SD z34TH^yo4`Jv>=#-bdp$t!FR%Ilb}8cqN4EWg+u#YZNBpu9ACRrof*uCuM9ik)j=Jv z;r5hpu#wmi8gKNp)p?t}xYf0J0xd1#hbQTe$A&;=CTzu(p=x5(tKb}D{g4)ZVjeACeM<-=3KzFA~+}8Fbj(@cnRgrH6X4D zk;iZfj6_rHCGI043B<>kbRHV`&Ae0_4H^UhVU$z{8G-;jgcwEPDF+v1);JT8%`C{s zJ>%|LUYoq63g*(xe zaDP73+p(r`f5DY>%T^niJK^qhC0#~ii#LR4y6!X=5m^H#E8%8>WsrWxd6^29ZwkK8 zH&X&9QF&|lj3e;G5^?~LFhu~b-d(X}1#YIA;rdPPi3b{c4;<)id}!_{-iyXOSJ=$_ z^SdV8%W~_m3BIwmY@166gDJbTybDOA? z<3|2zsuIMt)6-68!QpVWx9cd425~4_ z7bJX04Xz$p)6j}ZB}e2iU`8G}I;g0$0|0zU%|5}NvbdJCFa6;g-_zIFeg!Bp+ZoFn z*ZJ2u-LX}xVxV?T1pUGWr)_6Y<%sXz9pC8*deSzRg=H+R7xFQWbHG1f$dBdY!8X6Y z4Q8t}uB3JmV_A&QrXRPeDiQFa^%EsVk;VZvyQs=^FhA&A*&`RX<*)z#d#0gywE_jU z5aby|i!Hyhy#B*C*rOLWW;fI9M1pcqW7}zQIc?&L2vD*OyLU@ts>qYB=a_vMZonO4 zK+}ISik%Vzm^BHl7Dh*aJ(vecg$5{5XV{{P0?slXdfg06D8_}!5W(G9qbfT!U+l$o7!1jdGj))o9(eas@O6g*d7-88bHX#;K}ygfy{ zTosVxh$fM4d|rWM0WRA>F9)OMbSdpoJiUKp%Z8gzo=3B>m&CEDEnCjM`l@t}^ZVqi zYHT5YMGLq=VZDHemLw(v<&%q}>0Io^7sLE%ETF8I+rSRJfU-K+eR1F5R70Ht z(t#~l7s?fZ29}JO8)QZ-2K7iHK%y{W1@AZ_we=e-3D??`oluNY`f!*Jm@=0kQ6U+-Q{{Wdak7^s9vcyOv9h(_bWh zh|#v(-L$sJ@dk}jHkFV09E1KrQ~vsVA_&-9BFHoem*skkBibK{hw&9e&@XCF{2^;!?Zki@M`qUE%WPNJzvd|#H&c9 zMd^+hkQ=L6E1W=-SW*f3F;_U@7tj;pnm$b&g#5Y09!{xL>wZOW}m3T7zr8lwkLE|XBiLXWk`WmvX%us$1 zqo)idcMQ5A75jz9=rE|~Qt6N<4$=c>ToYHItfwPoH|Q*ixHgXLT5a4DPNnRTv@_Ig zv2+iGG(r1pNNv-xN3?cTc-9`&gkT2sF0E#|aN1v|bUW&xBbt^jHQIGmbq=@E*^mz7 zLsw^0jo;<+BcxXotX!R`(pGCSt2Kcda%FN^Bju-4MRC9;32#j5emRCM0fBJJK-r~{ zr9v5MfPWB*6z{N?kWFo|d{p*PnFRpckTZcwb*47Wi-Rv3e6e$es81Ij62=J;oHXNG z=43s#t>$ppShM+W*8h#Z#cMElTl9^CT!(XG%zOhHQ<*WUERQh|c81t-LF@%`TzIBi z{HQF?^3-0$V?X*|`0oD$Efl~2Bgn>=GKSR?Veq-12Pq{)$f4lUyW%V2%lY@;pWD&b zSNvVsxA40#JbgGzV<2IL^n_!;U*3!;F0vJhFPn&29<$X-VZr3D?1h3If+45Tu}vnO zrahbxbn3lotvnu1sdc884BGu#9UFVX>3l+?)s7n+>iCdrKN%JKUBhtc>DuI^HgVnQ zf8zKxut*z$?WWb2k1Mjd0AG-BgP0UN_6U8CJ4Y{w?tL>l&}7!GOXaUw*|DzL935b$ ziyWasO=Mm4{%XtCj%Yp~?bvG8-5*^SsoRn>uNyFTZCSruitp7TzK6ant}{BGJI#d@ z&s!#NGln|9`p^RuQo#!}5~!=a{o$dBty=~ou*G*6d|G6bc%nW_9)r~4iEuWfj+@pm zUAq1z%0PZbuhr_Ko?yta+-zR%XbgCw3)VLsyh2>lT~PO75eQsKY8xjG!#YdrJ)cw; zx&+#}T6-7Ks|vn|2Mw`wn|vI-to2>!D_D?~cgy02QB(P~`slZ1Vc{y_Fvge}{@-gc zD?CbA4gm$GaRPaw+*kvn2N@aYC5u)Fm=pL6FBKR|t)LlM0JL& zJroVa93H{0_1jfCwFYmuKkV=$k3eSvd#_r;I7o6t2CW6m$0+YMzwA-{%UPfbCc$&7 z{&C?Y6ed0*&PE1fPUkE-oW`MqO{wJC1(tlS6eHZea33(23I*Iyuf4b<)?R2I8CkTm z^STpp0@%))F^|^6%YQNMno6qSK$M|)X@||j+17Hq84I-Wx z(pYJl(6G0{X2jB>Oj@D2vbbDcvhmET+O;2U+_f;sJyLCA?TYkCGwhk_uTvc}CUJfYqyv zD+3)AsR=Y-tK5pXp%=0a5W<-oZkQPxn;9RU84C?w>0fgHeYxCyUF?cbgZQSumrX9| zU%xaYy!hnPPd|x!S67_nSKfg?JUzW~<;r+2S4Q~#Vr@t%N1((?Cb6F+5jErd>I+n9 z2so_EbKt;tEwBfu_$qtRiQrL&y(n~x z%h}&N)bm?Qq;775bLmp2@M!(qa_}@sb3?MHh~p(j8G<}&BMAjccrH3wpu+Jm4KalP zA_Zm-@~^;O0X@iShHcmSQd=J(fA+Zs!V(FZR;TC#S?5&vWuhvJ4vrEbnqjlOAnfmJ ztM=B2zpe2)Tq`ENII%(&&vz_!R#(@D@2HJs8;G=f-8F+v9bd@?<9DK&3)W*ZF`SF>*s;W@QzlA5{Uw`$UdmbAbV?P)h z6ZQ+ad`4C!f@D+LV*jtIVqKGXXA|4#5w`_uJ#4q1_vuF;6?GgZFa(G|DR>A9X_i*X zWW{-zNz0)q6jIQPJW_zk2aW98U)L~@ezLFKsbG`es_AssJ1Z3Bj}-VCBRRFM(iEOcIZC5N$bT}O(6(YgWm)W@wFO-yf%L)QtwRYg*n zy2QgT05>fzwQ}?vb5t}uTn-oZEjjll?~uu-+^VrRR|SKeG`2tASZ#JJcpDc zwV-l1v}u)solwgYsgz0~zGHVN&`ES{&bP6(Y}v=R(#S^y#kmpM2*g2EzOcRJ`lS9+ z4ZT89;iw;W)owlCTro9#sfMyq-Yo4Co^5jVo}hq;nxT(y8g~@eB*b=j!`>E_ML-V z`)4V_$=qfu5|0I<8bJvpS-_-(M<|{Iwt?KfXR;fdk?}oyMw~W7q5aH>i3#WEj#zyA zsPL23hb=emx#wzU1PS%W+RC3+YWc%Yzrl=7lX%)( z7o$HGzVl9#6MaPEYhfE8fB%E6fXu_XO*+EA*Pb8SY<(G9I%UiJyDj_1nl<6ok;rO- zvvA+7%7%xETKjhw}_HbQNn6j^Ia0Gar341&k}FbINC z3)=2%^BYtSDas<{JNw$iL+$g5LA%g~#DA?pqYYbZo;HV6^1#vN5nty4mXpQnw=gFV z`hAH{o7eqCf50PiC3~Fib4OR2RAO2^I&{lN$=pTy>hH^<3ea?DK^Ew8>vjq96{TpXcvA$POn0 z3Oq!d!q#4_#mCOSm71JH3Mb;osYPux1D8b%M9t*UzPOFlMA)|%HIZYq|HDlbww`ZK z7^mZk96kR=YLXo;wUF1K{^%DNTmOpIma3^O)=i1`6&k2pzmUZ1leP(I$Am#9%*_oA zJv})15>oz~3N$9L8%JFCgUDsWQ-<`Mrs$m5|%ec^YjXVWZhazS0sql<;Aizj;a1tI0kg~rLe>S*v@K0I>TO8r)-c7x_up>6uvUcy+nfmZ1Bc#z)|12W=(6oBM`oEFm`kQ-nG|U=1=!T z3ppQt8C}!qzwDZUd;5PL>R5uGqJL<;?*K3HLXIr56`L26WWlXL^yf-2v6qv=NkF!w zKY&=7wbg$iOV(W@D;wk4e*i<4I>3StuBadVrg#~cvX&?cjo{C^1X-54EgV!uK#>&> zJ(zZlPLC5)R_4(lQE2^V+K6V&x6TN3PoVXa+PL|A+a~r{AO6Jl9beEgw)5fs;OMi( zJ{(0KQgp!q%QA?}0#wrj3oM+6a@J6D> zC%DD02GKiw8gPcCqr~#Y&>O2H>l_I|XPzv?RRO-6`m<4_mbBA=9Q;6@2km<`f zMzkzhN=rt=iAkvis~K=V^o+}l=mvRpi$RY0gh_XRq#5q>$dCz@!l6*0Xp&CDUKO8r z;3=O#@g)9^LnTK68F5!4VQ*uD_zv=>{#mI|l~?ICYc~3?> zQ;#F)+Yrxh&E>WVH|B54-z2{!c~!#Mwt7kOs#a%R$Q#VxcK>aB%_mvx#PNq zP!EqBVUR3wYZ3{NLMLMia&%S2SVez%f7i9gg`1#uV|) zmcf%w$4uj3oYksyCC(@8FJkuX+dDY8w@*CnYu8z9hUf60ZTFd+V@~0X-7|%+Pns>a zAH8ZO8}r0!47ciP?1tO4HF&YaYKp~72#u0WEuC{E<%>zINlH4^1~f#;f`Z$h&8=Ir zJwFFSXn<&KL+bi)AsnFNt+X=(BvjSW$ z>&iyTt}B};ySZ#T{2C=>lJ`?=aOQH7CsJrqG8b_c7i`S$^Wu+4nGLwH24H$Snb3yp zWv9uqO=|&Xu3;-)If_pv(odd{Fw%&E&lH ziIeI=CX*hy+UPKT!fov1KD)#RU0v?rXO?kS(Zh*iLTlU)7+7-EG(ceua%(5XTZ9MiS{Y`Ft~Qvr(^?twG+} z&0tX(gVWo_4k7E6;IuK11m{PN#$blWwN$y$e10_7E`6$SAj-8^C$v+f>mr>HARHMG zg-GuMg5y#^3KWhnJ2{d`1q-30?Wst6dnDB!1sn(Tf9FF5V_o96X1X5Oo=P=!bT)P3 z*0DezRYM;I+yy0`mZRh?>bnK>3#o&_EmW)^2+8}hqc9nXY%MshZvDEqmkrxh)yrETz%+A(aj%jAt$r+{r z`5v}eulU|fPV65WJIapH!;>>z;+C$NyYHUqVy|`G%@y-(melhsj!SFKofxz0aJHPG z%;@GzFwi8hXQX&XIhRV3G^O|l!4Bf=1(R!BeCBQOti|bMyAG*!TFoJdL;tw2uHMqx zD*j#EX<^GO^?z2a5kIU%_BWGP>f+BnD;-nf8Imx6kc{qDsoE5(XHtGJOi6kckc*7A zkD;NoP5`sc-b9OG*Xm)3&_Dk+QUlnVYkE+&QPMXy;(R9f_sCkC|E}~4={J1ubR_&% znCR*4=|Pe}>GyX0{#m{PbN0og+XNMrCN5=5oAqvjMF!l^TwxW#Yvm`Sp1^3h2C43# zW0xZ+P7Be*=r(o&Tu{3_gDxj)+qKJ;t7U_sFJ8tf?ZH5;_;39n{r;a#z2>&I@}@dB z_-p^|En;nx`ll2dG*e{Ch@E3Kqxci$-Aam3O9NI6s7(?ggt$iM>AFu%pOP4qIBat6 zU0u-Ru}|B4CciGd2T01j0$9k!ZQOjPWZLiffk^k+9sURC6`upr@hQGoOa4vd6O#$Z z@6dI*CWeLt$Oq23^oxyy8+LK4tb&7Alg!7vap3N__~G=ca;b6h{DO8J2B9@5tr4o^ z&j8~6T%*}bE!?YBKU!*^q?1W&DsWz4^2bEr5CB{PtfiAl3QC?qfHTlBI3OOSkLXgt*F=7lNjOiY>A`2CnCxW1?m;BUXTt*%X#+*m z@XGEHPh%^ELc@i^EWSgDM67Hn^!`TZ{T94{V-~5`pdutXP69t-NXV#qqW1Jjd&oZ0 zKiPNkv{u$;pF8oK#csDmBB}nq^m9TMnLpCllKM{v+4fnSiNw4vS=+#O#;N|AfC@|= zzl?|N5ywH?kwC$ulLJc2@!0WXixqF8;8?(ej1ens5$?fHESBITqO#?!3ha)5N2xfE zfgsVmF%%9DjNdvw5DL+g%A`RNECGgt)?h=SDwq(qw9^(6f-XBiBw+7Er7N`sl`^5m zt8^L_u$(BICD*9b3XMAG^0V;;5Q^~nE#e=RjNfwO+Q!DUH{vNAW@(GvXwgJ?1v9cNmt__KqB5%Jx&k@qZe@m=v9r;lkz9FfR~IBVZ9DP(%ooBwoNT(y1K zpV?UY{_xU6;v0?Dug2NsGLtydYDlM(EWz{Os2x{ArrwU(6M%n@sz&6{4vq)FutI7P z1~iYZLw*pYGCV$1KtzJ}5;++rl{C-e0q%w8bBg9VN-A~hdQBdALM2HR@Xop{y}Eo1 zyaHg<_})}u3Z-mOY1c-A1-?kYSnYPxn;tp&C*__u4GxDZmQP8J-09iW^sLVY7JVJ4 zOnl__mDUugAN9Ns@fKl`U?u@l4jK(wrh!KGwnCE+!2jb-z7#LS?Sg~wIKoT%!q#=+}W3eWfmbfm!P~0<_7)i;I%0^`|6i$P}XA9a4KTh{fPNt)3 zq4AD8cA1^BI|{7niq@*GRW1~~FxDws-8Qwda9y-;$7F#aBSpG~akS+jw1r|{Wa&z+ zL5W_dvP!S91+lr0YZ-G6-F)+q%N7w5rh+Lk(k6GggtA*>!)6YWrxYJ1)v?_(eZJ^E$i9Rffh}stKOFJ812dyr&X;SqW+=e5UEXO%nZMTa$~Jz z5ITXXi*R0XR9bAc&NJVjr;s?HL`sMZfeQpMQ2G4lK2KWZah6&kZ!1J^6-Aw0tF`Mu z+CvTB+crY&ZaV<{xqL`h-&469%~|d?I?7uHm$LP@{0lU<8olAy4%3cXZgGfWd;944 zIJJ@dH_|n%z%}H4J0s*rAc=Bd3hSq8>n|gj$;sZd?wz17tMa*uSJEVJA4yDts+ZTS zNI6_|!CBK1R+zk_5UuGe=v;jox}aH~(Wz)1ZeoQyep5yDEeyYNns?m+@)Vjcl3d~Q zr9vRRM2P?igeC$kD0)0SJ2{257Ns)~nwXtEH8nen-_Y+QZYXJ1I1<@(La?$|tWl%YJ+2M?ZQDZ#=yA%*2}%C}6nH%Lya+u*k$v z9yuZy&audDw&^Xw_?YFDd6CyP=<x~bFmea+FELf7@aw~YvXR*nb>uN<=9ILjqkaCWv9dl`{v`1 z-;D^);4zF2*pCfLl#A8}k_-)kk^*2t~fg1M2SV-(FV`z9u4$-{(dG+cL9BlqWT8+c-s!4Omrq-ygXZKU}DhFI`{OK4y z+3kC!SL~Nsqfz@MdA{6Mb)V5uwaZ=!1>nQlAih-lFz(V89{=1CaNx#kd-nk!yc?F& z!LofHz%0}3m= z-x0=>RuLtlx*PnTK|dtCl#Nu`0PmH)1f??WnGD z+3d_vqf;srRR+{0SZ->xgn+>^u2$A4EJ}enmU-L`kGIj<5SF=>4h5^RR;`M(gmnC8 zOKO#Dsnsqx8=2mwXTGW`TyaI6rcx%iR?2mPuExN0T3NN##F$K3>9keGl%~c?b)`wI zms@NVa+peLrL(T0N~pBiP{X+fY4ILMty=lxfZWf@D)j<0)%vS+`kD$kCKBm`(z+{y zR{_|X1_(0pXDpU)oB+cu3xFhq@?m3EGCe8(lp~Ng=UnH7oGZsvy9@$AHX*0a1{iI~ zX~;*Ot;W9sj*n2bp$3qe3)=%pN7&~8d{NLJB&;K5 zD)-oeHAhwi)OZ6D5PD4fKxzrcLOWdVOm6gzj`}uE`f>cXvf0Il7az>uvU26;x^JQ5 zo|myyJ(1^V7d@<~ap6Xmk>n+wcLkH2<$iYZvU53`a>C)yx5P~b2h}y$Fg-1rc!h%! zZk5v_LfTGA)!&epAyt8+^H#v0FaUo7VVvL=kR+~zjUhi50Y_zAjj}RPEVyD|PdI`C zE*`PKj)Zm$?l>xIgSgcAVyMXco-a117J9{Fr%oM}WT&KGNW7Q}>|@$9FkaTAm3oja zBJVo!!6-vstOGeg&cbdb{i&6ns2C_Pp_@aEgQC;G}O(SwWkDRwl?%rt!!`}$PvC5JMg zSr@f;^TC7I`QlwubNj#gRqX%YYb*K|ja{@?@mS=*fyf0NAZnUuf1k3gD7bQA4@iCc zFzxw*U2~;kht%4Czi&yST-@Hxm$+Wym8FaIsrpuS@m_g*`!BI;-rPf_-9tBiyzF1t zH^Ez=!bm7Bl#JN?H~00iUthlYa@_Dy**Vt0wy-BJ_#TEx8_4#b473GslloWk@0c-i z!RON8#)<^j29`HOkQvq-3L;Zvo77fzMtlK@VZCkk;Y7GUu8w9s?dOn#5`6^Z79HzU zkwjo+s5~EYFZ13BxFFYqi({8`fihN{84wp7+qE1A;gWYvW;r>(Sio60kQ{|-&DxIr%fQ~!qk6-H0{A8za^kQc(JXaq$LAk3}3dNL+ z5MZwrUf2L|fk{5+Q(7HI;z=6#vs=`f2nSxL^i>7vYD$;)rV94cLT3RtX&sXC@5wLd z=b6)dm)I@2vZ?Y#s~0(0#Kr{U3d)!poSuk$Bu(V#v}EWneIm2jF_={-vV)GznG+{` zIg9u*c!5)v+%~y*lnu*;!#gtR4BpJOXPmA~doJy9A|1i=uvV9*Ksn}hQGc(1-wRSW zSz3zRR!DagMgonPyEW9}V?$VM=B@xO&=YJ$>OwXY$p9L{o5@ z@A_Hs?5S6gHZ6|woE}R?LN~N`3Lc3oI--vF5>xEwk z$`4wIZ{+!ISz@1}``e2b<}O&z4|H`QD;lNjNT*wnpU2X8#7~vMU}dN2jpt)LArYr^4v~QMMD9FpW*C8AEEg&Sj8WcIa%y5Am^0r%~f8 z8>PyF{4vs_i}Z*u>v|%(Zr0Kn_Bov1P}=GB)pddx$mt0!7o0vH>`$Ffq44QYdPG-g zDA)RG49dSV*7&sLhDx0!W6}B*OzGERtN5`|aX0@+X|VdmbpL&8*WNoYaPL|q1P|!D zqlWH6^D2E)H?9F)TgfgWe*+{wVsfknum&Sh)*#XV%opNu1d1YJo}?94DsTB2=`3cP zZ9V-xC`#pWnELxo4i{TR2f25xc$yzo2s|F>X{)bq>j^wwRb}q)w`eHUj^hqW$0fO2 z3*-tq7JfwnU>fU02vPyJBg``dAf18?ElTo;WGinE0y5F=?@CP@ z&~-<3Jv)O7TNiY;^=^m_48)*Sm0G&iusWh&^#pHj(`tS5s>c_#mbahTl55u{`xBS< zC8a)l0^`a-dI0E?JX{_O~~fPjvei?5`EOTlM(ktAY#Xt42a| zaAX^L4enY5xiHjGtGzfs(3uHLAIg{Z3o-xD5OSsp(Vuj0?|H<4xRuGNIG)LSqPjt? zFyWv3eqd_D!-?nUk^hQk zkda9#Eq&ZyLWbr1#v~h$b|V5U)mxgLhBNP%V1L|*CwTMX9*?j;-~4S*bR%2uD>dHK zs%Ca$bAEaizOZrCZ+tPYH|ASlt5jlKA-2h_YSJr8D=?4u(b@}(<%8U=T`=Xz#wuEd z_jcWVcbE7+Q?ts2cHx3^Q((WO^>Uv(7VcsM5qs=l$i2f1N+<(y^fw#2`GE&+e#&DL zZzfK}nbdg35ZyV}y-`RH{mH)dU;2A`m;H&&tu`zlPqU|CX|obMLZqwa6?~!+F5+2?FMPPL!cK>Ech2dv^&4BNxC^Xc}dxzI{^W}%T5oo zv*Nq-?4$?&4%12`>RiDSHC_wWN_GuK4RA=<=)=ITP(CMJPl&f*LKYR73Q}( zu*u^ZUSXr~G*(A=7a^eVPYII&AqU?1rT(@h5&zW(^1@TG{@ie`zbz5ja3Ckys4b8q ze+F9){UgzKBokD?iy|FKVg0_>Cr+Ey3UN3bKK9vfgu}w2#Os?+TS89%>*3I`%}<3W zO@RA!I`y7>KA%3L~Kb5fMDGkSByN(*z*t_K->RAy;_I ze(}BNkH=9y_Px;^EM%Gr3W3^i`^hUB!(TBsf;D6A2cgg1eA55aK&a_t&lkkwx`$kJ zY+64;IQ9`}JfuOF;XviMFJxc9_~0|$J*=sPB)QIDARy#Pi|@kRD+)_lvFTh<)(Uv`=Q;F|mH z6SWoJ-MNmHKk~9iHf z^5bufJ$BDMNOl*0!7U#=2>UO}sugk?B-FC|+&sH>ySNppwFYZ9@`1ad?yNE!Y~3~* zcj}M6D)h;cxMpZ?xd#?O3jicSpTME2w~AA*-oU=kzArYv$_`!hePawkFE0z|)xs_G zo!i)r|0qj}&0;hA{;Qx8;Nwx!eMxo^@}nrFfFq%t0XLSR`QV6~_0WW4T106^CZ#Ew z5?wy_0()%o+aUB551@2~P{+wlZ-Jw9;raoeYcYZxaqJ!xXo+4y-k~#U=J$n+h_ue~@OhWe| zJWUeweG0R^75MF5aIQ?Chfr6G0v4?(f*gQyCjFDHRuqQT7EW0Q&D@fN3JGK_6p#i8 zD2ONsDg2YSox^dO@f%9Vf{O}zxH904BGbPWiVN0Ric9k(tF<|h- z6;+kChHd$O^c(%S1?VwfWv!}}sdT4}@`_r6Of9SWa;V4N-Cg%bZQ5E(OP5+-t$~}4 z%cW-_m+X+8RR1%9xk9#xNm&Wggn9uiI?#W~`~gE1j2^GW3hfyF5m1_Y;lV47I?(;x zySDice~2>Z`d8dleUqkZFss?3{o)m&Y}HMw8rP<6n_RYvEt+hIC~WS&hxBL3)${uV!O#NAxBODG7v&`xS$u@Q<& zDZ}_jlsajI@kE)z(j@{r09d#g5Sj5NcoT?)O2}1K%C3|dE5z1HwNQ{5Rm^p>x=LGd zGx}A0Qzh4!Ri{<*`;{iW@^+zDS0Qeygg=l?Rcgg2t4&o^rfL;FlPmWtjjD%KLbX}B zL$b5UkMs=2BVnfNxy}iT54H-93u`aNH_A!Pr0^VPtAHW|J}_9`WbY4$BHOn|LhT0+ z+QXiWz7U9$SyW=na$p6(Ar}*l%my* zX$`K0F^eA`jj_ZSFnzI@p?Wug`evY}Zs8<24}b*cJF%H5E`udpcQrg6iTQl31%Lto zdk9oa#Axv3#pxkg5^84df}@;sj&>7<=aply?}(>OnklU*=81Y@gH-g@6|!p$Ce2_j zCq&OTB=EH=ld0 z;x3IYF*k=x0eLP*%xRG87u@et?gsg6B5B0fFcJ}z43bBol);lA1Mn%)f^fMI6jdPg z7E~W=#Rhab@fj61WslHn@fn?t4bbbMvuB|j z-ct4r_6xzqH9QZ3&X@`o$UmAGK+b}#P>q{QdJ^zlS&uuDp4Di1i4#K!e1Vzt7KXh* zne$^`keAD;WNac%oR(CO92f_~#{0jt(RlJ&J=0yg?_c)q+o;!zzqo&+K4#b`?8jUC zuGRhdM%Y65+L!Qli+=sSYxVkT`COXM$0}v$lr6}~YJdP%LbQ`e#}LL~k;3`&sR>3% zDM)NY($i>&c)FCJbuR2r$NHjafB0N9mmAGxV_+r-f}9{YZ1ePnLcK0aVNuRj=lJ2l zwGLesLr&emy2I*~*K~DVv$D(4SXbBR5Pwl?2qY^jlL15Rg18A*ZMdb};2H#UiTzr9 ze}Nsyar@+fr6?76F`Wn5MzrYDDj&dIaFBUZveHBsc1WP56cDAei;o9J+Hvu~EI;OSiY%6*tdji0 z2Ix~IjkN_i)2Q?c9uCByTc9d);lxc!5@CRNayjaT45hqDsOYdfsa0m4PDzaLV93_` zax=M^%q!U=TGY1UBwi3FqA7S;^JO zb+f<4^`Ptu@-Wb~kf`F_a9F`_B||q!+NDV`pRdWL#aWOz;sydn{*2d|486)AIN*s! zbEv~n*|_G)-p0n>E7vrNzs+2k!Rwfe+%bZhw~*} zSMnkg4*}r=xPYe7=LaU940&J`ygW8vv~;6AJ%$6*)3ZG~U60`K*-!uu@P5FcCLI|E ze<1k?8AJBt0q(IO4Fp%T5kA+5KvO-!v;rw+q<%>UwZ`@HNpMT9S&d^iGq&t`55C>xS>|b?-=UdB+iDoRL>Kx*$dixZhbnWpQ)&#dmE1Jfr91L& zOuJ@wv6Fa!#|M~rahfCJk*`$R7S@7t6j;ld8F5&VHzJIEasg_k)#myCZ`Er?D@lTg21i8Dyr0SQ(p5!Yf9}u)g z3W$M3A3h)D{51hj9xQvlx?maLtBZ%dXUk;T#Atgi>ll+D54(hMKlV6oJayklz+QCL@Y1)>Un1ZKz^ z%05$e6V~I~%RXQB1wQ_LBzIG2WJTy!}D9rGZh#I`Z&-ultc~**QS}_{p;L==9u&=RRDA@AbWE9;lhC z`D)GgYJODnGpzrx3s}ql)yMQ+_3P^6|35!VRVuUeneq`e!pEV6CXmF7@+0&pNNqqi z5rF~LVhA_MA2rq)SzK3VNa|F&X@XP~lgPV0b8(Sl-y4H`h>YQQxvtq;?`C=RX@yxP*Lturk(Z4OA_XPun0J|z@ z$>=i)YnL}^N%*>KNnZ+3)}$@z%{0_!*vG|dz4lC_;)tRtXskP=w05^%W?*+{LOOP& z9zzfE*q>^4VfQ$Hv7Nz#+L8i&9cHb_Gqa z=Yx@}B0dRJfOZroP zL^9ulRu}9L`>ZZ;J=;f7Xz!gv|NjC}ZWn8QD; zd7xsn!V{(P? zTftJ$l!UxNt`am_g~6g1!V1BJ)@W>7aq=03+9n7F?G%brB=D|6t=0&?P`2BwGMp4; z`fHiM1SM#8Yqd&QU1NhFtT5E-YX$X9;v2ULwY4(b+E)#0&GsfY8 zx-K=qoq2T|aizCSOtQiFnjSUnJ~{=C;gk$whr()|L62|E2ib zzsZ>6@mmtPEjip1x5VQd`y%Nt3akMVk7^5{_@O;ea0fD4&Mc z979kKJA^QtS@Fa?98b`RpuJ=biMQFac$Y=SbKAD&o(_ek=8xkxm^v^o=%YC&f1BDw zx|0+;poC7N2daeI_#07j3`O&t9Wn@oBqmew^h_rfQQkahM3ScndJ)3EsH~>~fobrB zAx;Cgi=LlaM(5{ETYmn927Q16pmi?z#|Se7hEK3EcaiUuKVX}Onqw{NfIRq`LNLJ9 zJPYgkX9*TC1Ze9T()@4n;9MVB^U6aa_Z1nY< z_YAuj*W4gRgJbZ0%dPM`pSp12xL)1YTyv=kQ27!^bGdwSP?b%==?_r;%mQ_4xbXai zD{)5pN~Bnf6xb^WaQ4|AipEAahdg#RfcQ#u8}ACfcS(Igyq{d>C7m0)gfggrS*j`? zw5n!NDOcD+8kU7?!j2~fOk<%jmnShWkU(a>OgMCU+Ty|8HnMpnZnwQ;LEzrB=g>6U zH<0kRUKPB`blJ9nl`B@Rz@2SyTQhFk(NKH*icVj#$!%j@Hg^WU&j2}2vUnW(-~Bum zJVE+7D`&Lyz=)0&9eXZpdU&MdV3g4yO{h^qs1n=>qE+d)V<5u=>8_k~1wxT&= z>5as_=8dam`MhlPM)&@FDU-{|R(=#9k8p}bD#>S@*K z^4SiXDZ9y7-{aEhzSGl_7e6}Ti%mgESgdO|&p3M72dZmYf$$14kaAp+aOG~^O3usO`^viQDue}8VIsY^j z^G$q~3HkgjJw3cVR`mUMA^A!E_xJ7lGK>+%l5+P~fKnJ=L9~MAoG`Y{9?qwR?J4_6 zDj#xe8)ixpV2Uw?Cwqu z8jQX{ztQ-2Jy(zA?_D)Ewkoi0-RIEl(zTGdC9LH*GiW(5*Kp@&{0K5bf$rSd4= zVu2U)Qc)LV#~^za?GUs)6Plcz7jhxK2=!cDDjh5o4wg!jY)ZUG7+Y2q)Sv`|Q4w{Z zb*9p8E|nU&+5h~w4@x%*oSb_LupmpqJX~n;PQu`!#ib<$J%k2N6-!lRNNv4jECLLA>% z*lOCkEP`VHxd~zDk*x*s@vQ||LM5N0r0*~Cc4m<^xNH}~wu6Dw!swrmAnreav5!Af zpas?#ZVJUS8392iL&G1<4%mGKpFQ9Rfv03k>0k-LYawyA1Op*%zQZnhVn6A%hqi19 zHiO#V4adgYbR}`kr(g^`4Z}dO7xn=h6?>_!Fi({CvE??QB60%5tB~xb9w$ARRz}pF z+bHREn*K@S0b(36qGUcIuM8e4+8Q4v1mo~CDMpN_D08eCuMVGKvVD_ zRO1I-HkT=rN?BZ~xm-H^8nG+R{2T z{(c%3K8nRAu2ifnh%>`#zI2L0L!%WW0nTKKe{bv}voqnL1=A7jpf6%L!Y3r9ND$wZ z5SS;BQBI7Nk)$P3*Mwa`uTI-ujcqctm`p8(+l#=Jo;ulkvX_tP#rOeY5CaSwu1GDo z=KyaaV=Ih=+?hrxGKfPAwlG3mDqxMo+6@NsS2bHp2@oLUeF!38B~R8dMXHJGur>S0;^omzbknX;3Yv#Ex}5c;abBx0S_v7s!Fa4!Qrv*1z=rUhOp1s z^lG)^w&8qUV<6w2Hn-Vg*}Qj?#j+_6*lZqj9y2p`-;~;*8Aonogg7|^l<`M6Z9s6i z-7sEErAnn#q7jqzFEHVOCl@!;Q@1kr*@(}k(UsxJK za%?^t;sEN95rL0aZUf=hpiD1*jVq8|zdlV_B-`4=yDBL&JWaD7Q`hSnbT@-n>_Yi7 zLLQzm!({htR|$IU7{oT8oeaT?^=rjU0Vu(UdZ5ps+CwzBKt*7zzMwRheX!x)$FKQJ z_mZlxZ9MPCl3EL+NRsjL#KdrJS#7fCr~Q!Tv&0Qh;p_zp5!ItAdLfBP3neX#Sayg! z2#%q7=pVQp$DuGo*&rmZP>#)=dle5kG@Fm58jSs)qX+2B08x_{rn3B2&NebUG(7VB z*#{r|;s$;bI?u&62+<8yzpvEmg0;dg&pyvjBK&;Axl9iCSOGxye_zW&wOuNn~ayWG&LjhkfkSPc(p(`m)==^U{ zA|A@~0Mxe7CyIuETH`U%US{%WG(Lj}!`evx z{#L}3n6d59HAB$V@r~QhJ+gh{wqq;|;STv$^v~!`g8sNK6!Q6eC-sAH-^7NrkF(zm z6voC1(6-%Jc+&WF zI(dUoB%5?Ldf6(s-l2@<Jz?wlVVpNAqVagueSpT7vtXbSy|kccu@D2-$o;NY0;qG$r@ zNwUiYv2Q2RwTMWdO%n)finxP6Bxp=arWFD|VfQrgk1Qd<5cr0nuAx>NXtgwV_T{`# zKN>9>*rCkNFqW%lB^$!;5-Zxe*LQEqxEmsU;b>QTu&vb_x=;NPgQYbh^ajuUN8mAC zz1FZIu2X}H(Wj_ubvi7%#%GmUzx#`kc4TyOMLN>g@6KAoEZ?4@!>s>|G-tOQprFtQ>1qa~00N2P;=Iq?{U~l`NQ;540x2erk;Y ztV$)qr<88=29w-W!>3DlCQb#7q+S~Hhyoitlu0=Z&p)GhGCTL&$XrU;h%{3pC^2Ok z^HAJy=8)t0-->6ylbg$=wvX_&^SysX*%V*t<+gjwl=5hokuFR%0XCj^3}BxPK-I(> z!CI0H!Il7#*2>lacHZgr96VM3*;u;!3l^uj)v#toY-5XYRre}(%~~8Emiv&WfKOj3Lf{0x4$YO zRhg}v4>XMDO6`TlCCRA#)_#)->7dr9z20lW|KJKEO;p>yN){@gtreICS1O%0kR z!edf?sHOGLLcbs{AGs(ntWg?8*VHb`q5xSE$rFs^6=8-pd#TK8OzXuNVhv?qX!3N6 zTkd6=zvbDg!r0|`nG;le7ASuts`6Qm<$lh-;BYP0gJisF{3s%h$cq4FnHZQCHP)aq zZUyoI+vd4fN$6o)!E=Y)X%C&sy)i#eIP_NO?fJ-8sC~=Ni(UC5=cOgWz5L8)PaPLe zoOkN(mV{%HoT7Axo=3Os+V=Fj)D z2$;_d;^VLKr(*yg4j&o$cLU7P0x*VT-}(|-5B(ihL8UPWpE^JY@U+7~&7V*az^HTr zy&y>eqcfQ7#5BeZ2k5;FF<)s5dBNG(ch~-%?*@g+FSFUTGT)HG)>NlRPt`XY)qA^F zX|*z~PKM3PAQ)B@T2+cVMT2ISyk7VP_F3)hQ~gh}D?X%<-Ko{8teQK%*iffwYPe~t z-qfPH#oA^x8$%&gy-_QZ3oBi6ht&ig4S4hG^u9(x_c<*l5M9Gnz@9l|D{fj;vTE0MLQ`78p{X(SmT|%Ba2I>mWWAV+szZ>%}j!dp}*T&^Cj` zKNe}nWLVL}T5U!fh%n$^&^NZqV@R}QOv+telRT+2TXY9|^uGN9c`%~97X8>Lh6M}lg|LN7Ses;hJ=b2E|1~94d76jmj z3M%>auo^GWgy2GTzl|y(|7}dF&{vmMxL&u0Dkr<2ikAuJ%4H8!)o&Z>XI8V%P)(>V zHSc`~?o&rpCav?7$=3xb z3&TH9xRHd)zEA5g9MD?iMfo9sM%fwAR9vTOsIz>wp^-h;*rHP(_ZsYt;u~+gae?|X zAi1#TK!$*2pNyWX1PG3C3*lGTp(9W;U1)&#n$!SWz%K4(W8x#i8F9G3-aBtz!CP=$ z?XyO!_1sFd0R2;rKW?TK+)wfw{lTq6LOMNibTOnoCI18}C1vfzAG<;(`*0xF#T&X>f=Rozvvr8cZVIgqw4enak-lGP*dEWd zp+ z3xfB;LAvtM!T}SVv%tOTBeBP02uL;PXPsIp8BqAh@uT5L)M63y7=aGGJ}NyuwB)J$ zrf~K6xG&P4PfcdJyEBu?RqYYq__)R4j>hu&{zA{dK+o#6)7uiQ;+wh_9q#ke(=~Kr zhyI!+Z%T62yXc40kgH6XF#*h(ibx#8mla(FotGClGA(Y)|EXtDxGXK&fEQRRvF6dTJ=NFezq=@a2wKvLm;?uL`+OwD%l zIqC5v2uJRdK0(=}_x)Mz#tMGvb{nQrAEe>svi~po{NK>$mSwFcrUaN}v3-*@vsO~) zs(SsfD;gM({@9we0S!@cU>!iu*HB*J)&Q@|<=>pLIo}g=l2t zzTLZ}HvgIBF0}e0<(hV9-@o8R9b0NIMU_^@*wXecq7s*M!$AzSLL_3Fc1E+uGZFR( zOnHTH#6IncWR7Q}hh}e?l#qB{%y(!*ehF?$5FjqK z8@-L)LJ~p=$w(mGdK?hb;WFV64>5hMP$-os4#;tkA=Z=-HDz4Q-Qp96VEA?fxvbia zYkV(8Iw6h7&WW;&X0NmjK^*Sl)@o8d%i&a117e|uwM(|F4u_!Np3-Y)wR(DT!eJ`W z;lWqz)avKS^u%GKv+OrHaZj$nU}(TYx3`H!ntWcnc)H2kZD?T6g22#ghZC9aGbz;X zKH&GU9Qs!YAitF9SX$}k_f^c;l~ATlI>F6yrg$Wgcy~AvO@#zod_W9EQ})E*GuebK z;bD$H6pfFXzc0REc+~Wn@BY=Cd9#7}*o$ViNxz5Wr;08>=vP9&OS=LF7BU9~!Bi?> z10lWMZ%#8qd@K>N=?`ZPTS8klo{hfv&th$|MnjZ(s>3ybUVtVawXj=LUs&DOn{JL)NtXR{5g<9Fmxr} za(F}d`pqX30wpRRNU8uinTZ(>oiBY$7)u0vww2ezEJ!) zq<$z2L<)916px1r+WzrAeSvj{vWjbLzB>9v9i5;zw$tXNZ+LCjD7vp~_S-+#ZfLd} z+gIz>(l1tYc0vxV(&s2Qc{^opgHN7kEzS!d6_-hIdAOLwbcEHnk){SJjO3lLEJ&?9 zFF$#4A#Fo8oZ1|XTWp!^M8sqP0UDX@ zIrY)m^=#`KxV$caVDNNe9v2^b&wpd=P~IH#Le@IUaI_j_0GEKEettzji4N-%Ka`~7 zij>Lm`IOgzJH+r@@wsxpYu-69(C@T+Hco6rmO;;EMAT(-84WF1B=FHl#*E^7rRZ&W2wqBheRD9{yg`r z#K_Gej_DcOOaRpFaq^Jk4gi?aN2DX`{ z_2@E_lbQa#1n%V60YuwT4JRh^n>OVq3zLQYfGiaD=l4%eKD{rW->WT;fOpX+)Gk9^PW9#%*>oY^6)u;)ujAw0#=_x7$*aefFb`< zz6w->_ok)~Xs>Nw`NB+@|nD^1dg*CfSMU z*hvYvWysiz9Hv1AflB3yA>b(D+dDYxi{$f>s7qCR(ssnQ-FDa_980e7Ldfc&nU`;i zTkQPVf=7E>b)p8)JfI?e^8m0G6or!l|!&<_TbD+ z`Mh^mmG$%Q_xB$jZ@BHY`U$pfK@vRW2olNDDO!hUt(5#3lzWfz!ayjf#_KU|{D9F2 z158oD2oiz^a|Ps5T}gH_yKy7#;xxM(@i%$LR;OGpzH9M#EMLn$Do%fm^=!;++?Zi^ zyKVn~JaxMq4!4zEWpnS`h1=ik+I8VNRActuzYa%2`9dh44;AvEoVc6ahl&&&+g+&0 z+r)zMc=mDehR4OWRjb;1^5H!0?AxBEpDDD4nHGn~%C2kj?4H5x@tK(=eQyK~ASTTO znhP|^=r4&sz!PY8(Eh>Sq0fS(gpyh$jP;z#p6>2GojujF=Xmx+E_Wh(yu16jo=D;K z>~{L7`xNA6db9gPPtS>NXG3EnKBa3ya@0R#jrcFD5LWD5d=>(0Vok%LYXZy_$Zf0v zZ%-7)-`+hmG*VEFghv#4cJj=b=udwtzRE7YmL;DL}I{xH|T##{07?~ego$uTX*$2u~wXa zR*o3rt3_91)tRw0AT`n8VE^FKv)?G%*Sl3U|AxCWU7_yBEXxH9P!5k`B>puQq!BAbhcVARouHjl>ai6TJ1 zeVaY1oXWGMPu?H(72}TBsBp|$2ciNS>lp3y_QoB#wOjf;N>Rh!QhJ4f&83_p-s|lg z#imYUWvdbAHGw#x?fEc-wF`5nPclHC<~DI#R*lKvVp_8#VE!ffd12 zYJDonvNkrJ8}j)k;J`?*pU@U9DtwsKtow?{p{6)`94*(!>T@z%ov`sH= zuN-OE$JJ`_6DAY2`MtNxI$S5k^}}0;h-+>}<(On8Y+hXU#9Q$E6W$38x03zQDbPl` zz=a^Rq%KP^rNyRLQQFYE0!PY@tDVv7u5M5$o50VI@cZL3rOj5$R`iaPLZZ6~qOsR| z3RI#AUw_}=2q`kDTA+ru2$>$B`g+YyZh^2`ADiVSRE*tVW9D{bJPirV52W0{5i$jS-D6*H?B9VZD zmBJay5n428#iv+_IB6E2GlQY%ET2n1M;+cnTnN1L&|Q*VXwJ~0@l4n`r;rygph&Mq zoQS|t4VdxI7l%f(*Wa``J37=`x?C7N^1zWHAsl!qyE*I04TbTP-OSz#9U1Dr9!J@s zBcbr8@Bj3mF#4AdlzK(H+Z`V2@pNy#>H2OyhuTnwuSn~WpAT#52GRi06Bq9c=wC2J z#M73pWI%>FPy0Mfpn@E^dxYVP$C(QSoQ^?<02be;;0D;$c>%)}%693kg` zBXGotbd;GP!|`yIcNXH?kdcKrD;J*MMkY(AMN!P>iwY(WIQn5WcR=jt`}li*1v^a= zGA#Gw!wM})8?HfYk~7E)o=xMY=D)eCG1YyKnrvJu^W|&qwO7 z9c^#FcH^GEyAdnVP%0%$4DTEn**Ppey%{jhp~MXZhdSm9$Y%v#0_L95=84QeDm9R) zvWuu7m-02DswPr`wWxp#h-$SkZl;uYKe`Y$=D~6SJ-kvUgWc}4+YQT7TY56N$?3^W zDW@|URwSHdWaL)6zZtd~=mJYpT#DB^&57pV?cUB#@9q8$p+{zDw6m@4Jx~WIoR`;E zirt~yu#{aIRzB=MREuEcpq9r~a$psfw1B_-5>Q?Ej{O$nVvJq6tsnl*WKe>{}(nu9Lnsm>5@U^agvWWHTAmYNtkPvAG6IHk-$yqI!|s zU76QSKt#ki2Ac1Xw2+dCNisno)x!eH)M%C#V{DvQaS>w3D@fd#<-Kt+8(o}2;XQ)y z3(im|7Y;i!!v<3#0#YHDR^4w<#3CWPD`0Z$6^_9>UX^6-X@te&9t&r~xQl0QY#d5i z^bN|!CgWY~7Kc&C>eRZ@l_Xcb_dCp`-(xhkQzk{iq@nLnBkm2v6oHBbDGiY>-XQG{ z7?V~|L2^HpMP`y%RD-w>xs6eiA#N*02X2UFQxADYbK7^vL$PdZTVLVqU}0XrF%)&= z^Bx;gl0={Gn#`ucp0+FFO{VeQ_RGU7PL@XQxN`qWkKVw#S4Xlh*RLwAa)*SPuKuvK zqt$1zBC>_swaWeNhD=X6yH~?&xV~lt5!^LKzEESywsv8EBmWsEJ3#d%kd-x6i#Ql3 z1M3`#FoX(#(1z%?l#<916ee(xTfixrP9&|~fEBB~0t>%Y@gMcIZH>-=e*H?fjAfX7 zlSp4#?I) zcwxd3kghp^iJw6WyD#@g2jM>k_B1N_z@?m3>L(`OIx7ClK zi|a^>stkcaB-^#XverVBZ{$2iew=gv=s#p#$-Xfp?ympSH+IoHF*)$K>her*b8N@E2UP~RWv-`F44yR>5^-vOAP zHf<7L4cPS#m0m5(`GH?4a*?{0PfpSJ!s+`TfHcW}3{zR54%eqH`L-2YFrU)P|A z5J>%`M%|vr)gs0gETn1PFFewbCVF-6pmVTnVey0!hkPYKA-{GQ2?N;lxkpM9{WuyJ zFGL3?z>hK{zO{Y($?evDl&*@Dh66qYr>#H49umiS1&&1`$3WeB!tTL{P-&Un<`MUe=f}qK7^%|u z__OLDG2M||i1d{2EDIV+u<4>dDb2<=;PxFQ0VlPA|>4WqJ4KIBLTahum^q{i~SbZlb2-4 zaYK8l)V`*#ea)KoKJ)>N!^?!Lg*!MNC&(>RG%2Y-X7(&p0;92u0#<7|c~y#7Qgj%M zX?C^Mz1!*$zsH_~;mWexW8J-*<&|=04jF@LeYLB;(fzn^hsTn|b$AXBENAm%t?r%K z?BB|rSqDPY1M>J|-H*}rAn>oWRt9Sl;1efn{kob_k|qfA0;n#bpC$h(?4%1vk^>cH zge7^s$t41_k++uA5(Mj)MWU|C0XvZxOMpzsf%H`x{fh>TU88kQZ}ZqkqlkF%S^h?S$x6~eb*w@j4yPxjO z@qg{@jTej8bhX5#aUop`u#G~WAUtt;fh0S;v=WgI(554Z+22kni?<8~whcOoyp{Is#rC=1uT1ptrCNydUc8OFHbH7#S{|gcOSh5A z1GpT#$QNxU%8U#;k6*G}m*f1levq1ZGfDYc{ihvGTUAP)_ z8{oTujJ-$ya{MULA0-iui0{#54n@S?}h zTga0@-X`5L61A*KP#qzInMN$YLf~T0(4$yj&(Oawb80N`zypCX_BoI;pXMHnh%+J{ zxp#0K3qSeEiQxV0f#5`?pZiem5nx}O*yTExU1=q>J+f<>gB~cfG|ou>0~5bhNiS+i z-m)^bW@gQrnIku^S#$GKYi>R=v&P-C+1$29xNwAR~4j(=&-tRbU-%f9_Fg@Dedh3U}dS=jQb@k#Ijh5+~n;joZ z+wEzc<{5hP8IA6HhpC^-@fA8qnl#s9=a0U!pCXa+Rt#^%2r9EcU4$KR6|*cEisC#Z zGMCA;NqS;mqhYyE$c^S8FgR^n01I@UdjxhRr!eM>3|L&2h5NZjfG;@{LUwgeG#t1G z{YCr0<>;?Zpmwc%gj!(;_EJ<)I*9=YHjc7t4jUVWW4bmDyNa?Cc8LUtThpD0RoFU? zC^UqgAsWq~nbjEPc`%yzoN!uUP$(3q6?%n=y)cf{(uhn$gj#Fv8eFx8Yi{nLFLt;8 zLZMJLDj1#=jg@)xYxpSNfIU(V>>O4|So|c5WGz>P0E43IC;by<6fYYgr$eCCBeqV^ zr&4p7!z9CQw`WFDsS#$;SsNRzI*@bGEtLl5PCPR=#|(3G+|K?>^ud2)H3YIu%cmll z=ODlU5-p4kAAR8Ha41q3JTaJ$hM4?{Pf^^*RlD|Wm|)j#*tbjS$M=51&!Iz&6R0t+ z99hqZhY}VlWO0Q4;v~=?!qL!=CYW+~{5b`uc%g+Wl<7_3cxE~i52u{Iy>XKUE;JxD z5~k_<9>``*aq$FRmZi+OM?3~XrY>T282(AH(}HyGQ*mH1A4!;S4Lvbo{7 z7cW@u=xqW#bID}DlN9#f2`!Ya`7G)>2Hb~~4MCJOI`tpKw_iA&YPE`2@iNt4JpIDE{IuZFIC${jlf0m3EG{+! zzFTTj#i!fGqt(%&K(d>H=zeZuAsQlXT~mUn8S7VygKpc1=FUhqZL)cE@{0xpiZBMZ zjlmfgvJtxqF8ydE=5%f?jOW!^hs)q}nZ$kM?>($_`9=m}@w+_2N1n+~N;?L6CJQRrSh)Z7>_3zbBJ7rLrdn zFTN*3Go^U|od~HxP9p)$;@*6=YHuFTk%fT1LbzB`MX*u7vA92T`$5&7P_dt3$NHdq zG;N%cZg$bVnxl1d@3&ufcjsU#SzI?M??r{b7$u~uVK5k{q^Zy!mrrI-oOp${>dLk~ zSlP9YfqzCE7+hQyBjP>cJ8;we>G)t(yCvL|#Lr7*ahV|LUat1l5(1K@3On)i(<4Y3 zuc!Z%c#scN8W~~@l%^q@i&VQZBz-;*x5l#RF_VpEpuGhyoTVpgMq511}gd zwRf;C5OI>}1;HQX4V2~f-+%vp*JF>p{O;eky1K^VvHt)k|G!Lr`mXEPHIGIA{&0PK ztn0F*zlr^Klb@fPaEKqp-r^?<3m;3gpU^yn;3L@{+gQ+AEqGY5;>3f=47KAq$4C_B z3WvjG`DNzmz=C~3z1buT3m-+dB7)qgMDwSz?&$9F+>+{{ z07k0~7M2oP;kO9RIWw*q+;koUVRBLGCet+Ql#;Yts>KoWsqj%52oL#EB!#i2)4 zV0nlH=pqC6k@=;?Wp|>c(NX&s7R@N^GrObi?AzkmW=GdpmqGj;u6rM7R9u!To7M#I z^>+Us7b{Hb0Ig#mMW21BMhW`^SS^gW6o83z0kcE{<4obPKF@QWLGiW0L6(2_T_GR> znsNX0&of7!eou0pWZSdBAC3p?Zeai_ysJhL&A zCFoW*lXco{rMN+#Q^kOre40e3+hnV1%?vl$J7R_v(|a z9lbj@Zrpem{>9(wyyi}y*{_N8UR$bap8`mifYiQnEU8hdZ~D({Em-uIwhw@^a^=7F zz73tMZl3UEs_+l-u<--8Q+#hp`v@2EWB6i;iO^3oMrlpP!4Lug2coqZX)DPPx!^77 z0K6t}Bb&y3diutv^wyg};^_Fc-uj<5mtOy!s9C0%-Z?O^b9(S8lR-REP`kch@Yo(S z*i|Enhx8VXLn-r2)xjDMepLunR)Tw9w6rZ-N~JAZfS=ZywyCsg+k;xuFD(wOb}nQR zzP*KRCAjFH$fz7g^iI<~dW))Geq2jFA&l+!fISob3r9SIH%6D2)C`h1A;4k71~%VB zjz`*`0qDp2E{S~rmyF4;xNP|HVPoye%dZ@{ab#uB<>Kp}Xh&~H$NxSn(~aHQbnZ8x zj(=I9Y9BH)%gn%<6uJ63n#j?IYroo>&G})Ig*^UdkZZ*qc*Y7$cF-ShzOb%x;My zlVr5MknZpz2ZOGsVO6lJpUkRXOeX*6in?%@=6f^j(BHx?$Kyo&CM8mk1pTxa!IsLb zwHBoxnM>1+;C2?S(u@D4vM9xO8XK7k2du7 z;=7;xB$FTb^>lSvl;4Bouwc?^yl8psKY#S2Ef*{Azi#~XwD>;@Ih_zj;Kw<6lucj}%WP!AHN_|PbC9)BsJmeF*cneYD`<6MqCJ)%%ou;r1rkCEI(F{pTgSc=}iGcUd{+M~k`iEMd$MIb|i)CLM%x z=)mcH`(GR#JN@xnUmO)`ERTK7^4zohk^6b{_{}p|wJD+m?t1<^5B(6ThLv0UgJ~Fu z+u6s~6sN*bww<0fzIf~2(^qVK@wQuD5X{$W#x^!=xxV4*jSWoq1KZcXZu`Lx%#VH@ zuxr9UN?79tXf-&W42C;XMfoKiWX(amZRb&HcC2s&7O;wbZpFSGe=Pv&rP)xq(|(gMWC znD5TxIj!b9`ymjaBk+GC`sF%EUo~JVaZ6FvU;7$6=(F5+pT)QH?YA8-{St@JV_GoLYk|KW!p26Eo<%t>*9}ICJ zZ4M~0Rs*6SeGQr{%w=(_vO~Z#Or=WbUcof=Olt8ZPc4|P1sOszAXwyb4a5eO8as$a zy)%;<9*;&93PB++>>Td*IMq+70@3`y=%&H2Nyz72P@M177Bn`8OP!bv=xwRZHkU_} zkn4Tw`waF#Bn#%Gl${9~RbDtH2q022L=0M$Lh)ieJ{40aG-|bQO74n=#)ij=1EZND z2$T$pkPR`ss(k@@V5e5$LDE}o$a%~ca@h~K0?zEy2B#-Fr}r34eOnAUt(x~Au2K!~ zcHq>JxFKU4??DkvYj815Fo(fCh<`5}g~3KpIkd`F$x^KXNP~$u*eq+bCWEnLP=?{3 zNE`7ELE)5u=wc!O22i`B_V-HR|C1xIN+F+-vFijjE3chljn^Arc>RTG8B{q=R5 z*(jd2U4Q+rU%37S!N7z=3Ssqrg>VNu1b6e@vObxtS9UJ_NdX6I*zHs4se7jPOtb$K z5AB&oiW{c6HIrd!@!hx5Z?QP2@h?kHrH}5-+#<~*58C%A#>JIr5q4)U<%Td*q&*Fb zPAgq|;_JpA#|Xhdg@FLu8c&0UuUX9am|$<9S_lAk!3~04@x>=$P&JtqM#iH)T!Nf0 zgiO82!{l`J4{r3?={k9FBoV(Sj#~ zU9PZ)_w5so%C`-Vf%tpdLtC?j0|iziK2uVu)LM^8unC#zK|wy&ml<`~>~dE0xojRm zuU6=tF>z-9elFkKfi_%*m5ZVZ2?vR3i$Lmh66y6%h44LV9aV!%lj*b>1 z8P=D-A)mitFFoX9!?D=#Bt5WC#N$ngE6pkE?t6CGQsyg}x#z=sKitC~#OaO=lN&nt z17ABO|3U+|d)IKEHE9k|vk-a~uY&R|@es1Pae}$IY^K@SWyrlnS0VesL#+{j@N^H| zyA-ciy^iebZak3c*C;8U@TZ0PhD%}bG=IV?4ic6g+1AjS z6)V<+q*p7}46j)sp5{+j4@l>d+Dp-19as^%v4(ol?~=W|j1LB)ffP*w-gqUyz6@_9 z0^nVXV-De49t8##t`&>eZ5bzg^iLRU(Shn0gL+>yDxOkh2XgA%DOIjNSHv5>+&7KZ z$Y5KuHPhOLUl}cx7wg(t!>PLLx~$gM-tJ4`yHC`04`kK6&Zl5w75RSbhvgSz9(xI& ztZs}PgesEgP23(ZJy<`$vEU&0caFW1^NE|K1aq_HCq0o&>dUW~=xqXD`PnA#am1w{ zUi*C?(7yz1l=|2N2`d84Hjf>Pa-=|K!A_H~reUOzYEKbF0GD5~@@XqlIbx^6A42eG zvFfDVoH9G&J=(|uff0K+5!m))YSWW}oR~kaO^Q??9L^;`5IH+;(8%-qfo?g;-|&QH z!}5f1EO5n&)y$FGMlBASgF7zT);d-CABx3m?Y+fox9`6Op-egNsmbc9UsK>wu}`x>x)bs=(|92rm%$-qK$KiGw4QIKvBFUaL#1bCoLfE#ZRp|7|R zaN-~vM0jh+fd_CC^YDJK+m@8Vuiz^<1u9#L@MpgOeJyBgr+ZKG*vE7Kh9pi8in9-}X!yXuwuy(r%j|;bLNpS`>TKLLu^ILOjm5B-j`GBXo(C@WTD_g#}Wy=@) z4qdO8wKPjbA2>jLOY&_61Lh;2lz$P2R`!i{V_T=_Pb7&?Vv)Q!8clqWBjFVKyK@7B zV=m`;cr*!%=5nyD^QF?f_@-tlB8~VU{{nsfG0bucM$#G}XKP@Zl2m^qEt$~c2r1bH zy#WN|Kq}WFJh}V_cr3(HB}m;;R*O0ts(lC?0lrw!2dKl#4%L z4D5RE1pB|p??~;gVO=osB8yELB3DugsG~PYei#-x5*6>(ur1LelhJ6D)i?vfa5Q>u zj+G3cFrSQ0OvENaq#%$EB(0HTGsph#2KAhk0`dq@1uG)xmVx3y@Hk?{5k!tSlw3d4j zUl=IVg5c;dmVe6c1?dIecA`5J zRtttCy}?H&Nyj)?&fCy$b7?GKX;mZNj9M-Cm=tQHP|<=x+NS{HwB8YlBBY*1lw6_F z2qul%rdGh@s>Pe82LJaCAVaON%?`DHSg?$~)dEt=m!PUD3a8 zSH4%+l{>t4?crR@j$3ct(IP$WyKC*?M>gGi&z8UV{HLjG{Od5jz7IQksLazKVVk>v zbcr%4G=pDS1;XwY7L-&M;C4`Zyl(PSU?^BgSVW$o9pk8Y;HW^I1Q#wOE z%PH**;0|pvx|DgD6DQLdjW&}_s~69>o{%{$zK?(0Vlr#K1rmnEe6Jc<7F=Bas9t-m zUL@*4#Jw!Z17NIOgbqxSd_YI+vFPO;9Yfb%-rjz>{O+Lv*WK&aZ@g&>!milLEsx%? z@iSLu*UYfbwqJfNzJ`bP_x7f4VfU#S$H7 zUcpf1GP%TyEcsu39FI}4JS!_3BBu~p8dU`2%K~|GitR^o&@p5Qk2Gk_&E5?gyv>$|h6D)Z)h#V`Eo$P} zzzSV+7;~u~^O*S3A{3X?NMaGhXb_ z2C}&4138w97K`IZc7y6-SG5BJ;Ry+1G3?2pvf)6SjU6t(-M|b=x_grzJhmJ zkj=&kx4zh>I@$}3R3QROqdkq@J*Y;xHB>&k0jCo0t127zS|j3a$~8~!VKMr8Xw_%zpEm{CjUoU#t2aJUi#NC%M=Z{0v>o+i~U$y8(qPmci@8 zHHJoX14_Z!aVgF{^5&b!5OtQ*+b$(Bc^A?dNq(BaJo(w;h$|Bn@KLuXzLw6sXRUN~0TCA`*@FZX$JJfz7pd5`U1Lal?r#Jgz zv(nVyWivjnD6*?kHjUw`v3SAKckf;tmDS~IVRw_thn-m>>E#o2&upx3_A+;9VNk#M z=AX1VU%4WS{UyyQ7+<0K5+Fuu1!aFO4@8=vI0+w%bk4o~@!4oUM*QMAAnzKnG~kb4 zd>UA|EKBDEpK+BjMGDg%oRsD(4J&C-iHOQtGOiSGO0h1Zx1R9}+1*WJ1;`UXarpPD z#tS$zA*V0=ftPP_yv)#u#mOJUfWdRTzk2LqZZtFC1f;mXqepA3AsRmGs#S}db&AfPyJl|}~d1@0Oc^BiRTaGFfc5(+IW4G#HJoYHp(9hB_- z0Hy0$)E{*49iLYwHauzMl~;3WC#~kyMZQXfgE|q#p`lC5yFKVQNv(FfPrBWpP~@_p z)StA*!%vHKscK%zmbLjLH{_rhC#%{h=%@)eZ|_NVw`9c$Qo<{ozN$Tx@s!WI%8uY) ze(sa76CFeh`C{+UnJJr5FX~-MtIAJXbzb5XlIAntYtB0>00ifs^w6cxY2ez!d3~K+ zesUU4<-T5CM!BPJzy0KSm0!HZ3w?si$af|9ym(*p5wdi*JMYYce0n)T%P-^~X~1Dz)L)|B z6a~evC6?wicE$^J2QVM!b;yn#4?nzP$MO>|_H!-YJFqNx8_zrC$%D(sa_=SUNKp*Z zK7`d1y-RB-X5jLEIOzx!>EeM8aOsGqg@)C?{yIH6f)}sz!nlT2#cS?hA82Ge{4g7O z_~B(ICEc{LW*P~3gEew-72)!n*}HtEFAQzIRxa(L^4Px6j9)B^_IcnUu$~aymBOw0 zHoLqWjBq}O&RFGE?}`FL-lzV_at^#^hPnT zwQBkNJ}qwIA76i+9?6lhY}i)qS<u` zPyqpptTC7i7d|o8q~+&4dFar|EnAkIv3gucYtcen{COke;6d!&%f|-oCFhL|!p2Fy zWAZ3P2poX$|g@JS5qF&5&0x*Wp(!FP0pwN9#+MwNVxXTssX{@{5lcquX7K31E)Ml zD`CkI#-gLsGgBKQWx^NHH9sFda)fQIVseRGIW5f3w;erNwGI>N02d4KGmB?b!e_H! z1-$U-bA{;xd(0rI6W+P%THg`2Jw-jMD z5Clui(j{@4gecmKN=OL2d*U@IQvXe|;^b(87KN7=QW4*c@cdJgN3$cj+(`E1LEZ-n z*pYq=-=Kjq!Wykkpmsz|f8Eef91X9-~<5zZ# z*R6=G+mBQG!mU1EE3im>pOs=^yNQRIal<>I$T)b6%<~ke#jV=p^S}q>RKtN1X;oTT zCs~s5N70Z$GAF}(Kn#;G;0t30Lo}2PBupx~E98p1!Wym3(I3l1Gd`_GA=euW79<=| z%heje=1N3W23yz_4}mS)`8$KwWSaOj&D1DL(RU~ct9q8X$<6Wl9? z{cTNQfyrcQT`l}yX1%4Zp$_h$c4t$qT%~NNe>2e*u)}7qORfynDQRA__s-U=!1a5W zc2mCs0cIWC{lE{9B@PYdc)2`_%De%h*-ppPWKYjgx zxlXUIGk>~u{m`0tv+x&x_1D*fbWO!(pa0>Wb)Q%_DRJRQI12$tDL*RDgMZ4_8|PeP8?9(=R^_ewBwDzWev@zu$LKJY6W*0s-3@w)L^-Q{r8Zl&`Y0N`=){m5z;;wq8Ei*}j5ECH!jt{$B|o z8I^fEVm&&hU?I$>OJOF(Nt`grs4);0pT^`ApdEuy`W&ggp`$ zRI{dl$}=oD#RvA~?TNdy&N*jxUZce~Ltx^!+q8fJL;|xu6a2i|SlD3MJl7}QGlUQw z@~`Ycy{=lQ7w9!USj`{NxS|*Kuj@af-|j-h*<=Vt%Fp-RMO(TJ1KS$!CrPZ}w9+>QGHp&3XRUEoM095c;Od{X(tYJ(5yW0?YzllZU{ z^lBBYO?cT^eizFSG3iTRMc@kNGGD0j0-UjQGU-QH+2|}*1r>&sPNBpzT;cQuPi1Yx zY2$c<{j13mb4Tkn9R`_Dud&+IT2rm9R^HtD7g3w3PA-=N6JJ6tkB9oJmnJ5bW^0U*T^{lQh6{U)0M$zb)9uEgZE zBLk&L`yst06b)?N9BxntJjJ{-^U2cCxFGbq9m;O6TBcT-d`hDw_P_p~sWoP2+wg{o zbWtWC*jyM>s0KQ#0ID0>_Dw#)lo)X!hCBrCG4H%qcC%X*hA%d#TNk|N8F zqBxE*#+cL?V?uDjO-=CJEKP&MXj*bZ3W1yDQfe5tV+>qiluJ8mD9tiXOBpA(+c+#_ zte5R}l+u1E>w1!&wuf=ZpY#1ak0eWegUPZa%hLaO`#rzs_xkl5OF}iz%|IH#5Mf`r%x*~XD&GvkMRGO+CXN5xzQuE5Xwz0 z8FB1v4h=|Q`99tbzIu9gNWS;<>AAtvBXhU}+9+KEnkeAtg79E+`wv8xMlwp`Igyg` zyE3V<*%A3ZTyTjVM`m}O$c*jE-i6Mde*X07*{W-CKNSuI(#(zM#Oc!*;HC5Oy^2TV z6YNmcXUPLg*{swKwG8i!ryJi9tzd@O9DNsk9zH!Zdm0gd%X3Q^z$HIZ2`G?%A7_)V zVt(mrm2=E5glkrgAO08{nnscZlG@}JN^~xsr zQtyQd+9jUOEzu2=#itK1MzfelraLV~PG5RsZn!jub0c@rY@QgQd0a8RTA@p}mo0&q zD@yrf$Cn96EX<6cp1G0JgP3wO!R4!u{t>+S1K9WIJVo3RcpOE}Q3R8UGcJxQ!hP{p z==UY0RHaiTg@GoM8oy7YQCYQ85J1@YL#dIH{r!6f2BhDrRPA1kbk)71Q&*n4O4|E}s z{Pa1Yb5YF8weaO|oI)d68+gzaz6*d6`aaLWMFat^L#K4ehf=Dd>k!1ni-b1j3?>cU z-TUmWm^OhwUH+5_f9iFvs5Ze~0~l=3;gFH`h-cJNba<0Nr#;Tb9)y^iEB+-vO@9re z9BBDYYxL3oEXGO3DdGW8Y+%`g%5%%lL zF57pk)79kLqtO08r+@+Wl;8Hsz2UsJzU$NDoA&scT%E^cuRyAn1_xDxx%i0RK4j3# zuXvF};PA4VL@++?NW_O6-jR4tk7_Rn>p>rB-Y+2LwTkUV`FGo%c;wDI@3a8t&DEA@GJ4)CpkE|22zx^#vdc?e zJJ4k-YYc&D&@bdWBZULO-h?1{vMUKENu%$j#CTG5K9`%!$-l`ZCzH{By{sQNw7_qO zYP%}_rCdP%H?}1u|6lAY@?o}+ysoPUp~Z>UdwO#e&q%f{(Y}_)t-wz}NP>u{f(Fb` zK{0w2E_>F+n_5H&O#+b3qVA!i^G8*kh`CE_waqeg4 z?T8r+y%D(dw@f?#fYI1y>@--k%t(d3<)1Eo4WuIITjZRIYA_`ZCR9hT;9A(vfU|}r z;>qspU7oscXZkl~`|O+2^+<0&W^*HF{C4Dw&&n52`K$W6WV6JG%xPOW4rirZ)JD_W z{q0~b6U^X_0Gek@?NDp%-8b1R1=aLy32woiMXMSG_?v-P71u|RgDXwooU=pzt0Al) zzD$(kAXZQ8Mq-%VzH@-8a=GXcSXJ=7-#9q<{e|45G=V=SZ{;XelR(D@WWM~Hd8`xB z$rfDy0kkBr=qP^^rWRyJVZEUF;u-2MKxfEAi?G&EDv82f^U2>&zA$-L?r82o*Qon# z?NQ{*#QP%3XkS*xUUB_{>pOqC?@#~NzTti5?pV@UKg{YIv?q@q{fmY+F(zSG6!BKn zo-d9RXmdG+$*kxyvzo#FgI|vAf5z%2yyI~4;L!u@S5H1E|73=pcqp7g#&3{0;o^j?mRQj|CwFXfz*&qq_aAWCUP zgSk``lR1r8hDa=&VRM;qGy)LLq~8zY>e75Jr-wWkoSY20?0P-Zi|SDF3lNsHUN4ZM zwagI2hm%2cldq}Ban!&UhvTnY?2@u_&_~jV(m@-5f4aN6=f%b53v+okEIIA@M<*xe znJl_<)SGex{KsE#Smz0ABuCe$xbD*Rjj*I7h=ZC-z}VpLBEZ`QJRuxW2owte@fedr zFf2iYSE2Eg4RF*@X&OW6#tVs^J8#;#6Ht?67{0Ch+Ei~K%Fq|Y-dVME+IrV#{wWiV zwb}hvR+yihWXDC1mjsOeTL{LZxzVW{y0BLd(NcGmrUY_kI0hCo$@@%xrO$#6Z^r7a zJtu${KxGMmKXjllRlxl~-%KCNDJ6$B$0Fkg53=9Kw{O2;`}W&gldV}}y|>S9J$dz( zEGz+hPQ>-8c14?*lbW?A0I{%q1`ye)Dx-;)Ck<>KYhq*iv97Ey!hjmaq*|JVO-=r- zf8QO9hHO5oUv#4rk#(IO59|K?=f~NMUT<^y$91($^+C73POH(?9c$ILXgAe{zC?Y# zVf)kc;ZCod&SbYB1+bEb8?g5y(3vq+RZ-Lmij}shyii#AVuEn+4hbJ+QZ7YLQ*i3C zaT#X8SG9X4_Gk-$VsaILh*5CG^K(b{=P#fX(*(*g2_W~C5zMm9?DsY%r+k(M=&ajD zxrun&D66IKO!Pg_9BgU|BDR6^|C^-U$Sp8~!YMne#@r{lBA++&-HI7bQo6(wWlebJ-KU5sN*3jG@?diFuCws}?!K9)#~#ZwqW7*;T#wcB^yrG@=2=uMnaI#2;?JeP|Azy`ns?6cIz`+0YH$CHUq z-88m&OXrBk(Wt9eg*v|Lv@5h)N1ap8ZtNTH?H%t+xI5gq6TN8g`#tO-8(tY9k9Hzg zYbUacuO+G}%53FmRv1sY#gY{4?x4p@Shp@R?s0q=VG-o)k~D1M6Od}UlL0GSQ&g6K z2bq#i&7%Hfaxj?)8mv~A)q20fZ*aMtTBoFCDdg@dbt=8vW$>SIha*lm+wFEnf$h%_AbzU_25E$1yxw`A)Y#D%&NR(E5g+u9UpGPW2S8UitOZLPY~uc}w5nGrdg z{srwOQ)6>5*xYE=YU@>|#+G25WXE{0rP0)?QENA;FcEYnlwx{K@VF!}2V$ubR;Y5t zeM05vK#V-qj==4OkBt&*p{Zel*Z>9ePUPq0;oLOT(5Z+%9Pf`?3>rIv%T*>I^Rj=8 zZbLBdR{5oLx+T%lk|>13cjg3>K2 zvc_eYVez;|DZh8uUH{)igXu6cHLz>+rb`#b>g#X(w|^7Y{0gpl8T@=MeT&o2N54aR{|q^=7aW4t2%7+gNo)uFAQz^a=b@z1c)I}w9k3~C)fgxQ zrAG0Q;vZf3pe?Q79|HqPry5miTZ&z7MGn5A*3{ONR{cY)$?sJuSjy36(m+}%+>U}m$JE_NTr<|RdIV%rO7hah@K0WPv^;PNqXXJ6XV4sq2 zJ&U*S=Ja-a9rPe_1HfsG;2D%O0qNg{(kqxPpc$sp-ZUkGVB_I`oB34nv$=6|ka$ny zW@Ge}$m){5#qCceoU|$*6_B)HD(X1mOB8y?@|pP0#iwsy<*uFul~hVU&@7*r+7od|VMmze5I(Ikj%gFxD|0&T4C+D#av}sAC!_H|2QFM67?r^v*);?7sHVM0i*Rc>m8VFM80KsT+crOrlU^9{gbVg@nsUL;Y zbFiD3^hl`#PLfuq(W?;nFZjBM!zk^c6(JZUrJX#!FkE^h%X0KZDd32`21oB}(&r1f zRYt2_dXJ41wsTpavJHxs_?T8`{nl^kUEtcU)7USc5NEt-PXRlDz$<|_n-p|b3eARB zuLyGm3s1sYOPm501E2sRz^B^>Z#FwuDxd7`XBvubx%4YBPz)ByBV#+OO&Os7u*z^=RWpKknd%Ma;OHy7I#I;a|R;4A7b#Vply(NIP?^A+pM z%?oOgB}zDj5W>sbpG8qF$cf+cQ>mrQ9v;h7g!{iO_2txU7hI_*(*07d@IV;%peXCK z$iL!r!jy%=01pzKvKfE{>}E3n&c(-bnTRz!fLe7IM1dzRyIhWaekWe>>&%M=$>K#RkyKRTo0U2Ft|V(wN!C3`WhvR%3+Z21ANJVMeo&F*eQ$7ud~Q5tJ4{A zx!9z|?TR=Z@=$`!#pMIX&)y|H2e-T7to(Z_LFVz$Bh%jL3cJepCl(guk?nLW6HogH z=d$!Z__G6=P_||})p+MNYMd(E_6SCL7Fua_R#rn7o;VxiC)0>DhGc;s|1=uZI@@J6h|l^7Xj zwoFmw`7Wd9LNR! zs77y9Weqx)&cK`|s`v3DrIp^bD`Bl6v}Chv&3*jch!K91gsa?(4k)v4tRGj`(30UpRjqA z&5;A_|FC)MZr%Ci?CIZjHfQf^-Xi^htcw)9P3*c&n;a20kPg0KFdXXHlKp&7^H;OY ze2k)9%6}F-nDCERHw?gU59C?8*YYkP5jqww$S3Vyr89hx9kY71F?s1I%Z#UTsVuu+ zpB+4!J#!mcN2O1lRRh&J%jtY=!aDF4`aK*~e zIRIl#ZfPEH|Cr+Fg$p@Ccqy)>tU-Mfy}-HJ1a z6yBoX*bQ{uDvF_%u3YhRSj45=LS@r$u2^^&KKZS(6CjS_>cdM}Q`wIawQ=l}%ASxq zL6v1Tni0_(SU5MBmST6P2XtF=a?mG=6I!PKRXc~~ziRi;j92ZT;yf#=t^-f$$~{Q6 zwdl9{YC+J+^C$yGeUYI*&piNoQBwn;bhW3N383$5_8#n3uDYCN8af*eq^7PCnZz36huZ=3XNH-hD!PK0&C$!J0M z)?2zlG&!sbC**g2@-S|rE~@7M=a88HN6?=*PIo6+z05rSPn|B}vk>?ett}m5u!NCQ zpi{yjhl5=r&>(Bq+5BLB`h`TnoAt_PAWHdjLHk6ie@1dg!>*u8JDdm>P`oOb%!S#N zmtQ{pjB@8@?-nl!U4=G9XZjlXKiYevObTq?8ur>1$}PdRp2~hTBKnK0alBErh?~Tr zCCrY*l9H*d67OBBMD}5npu!MB>>b@qe`>-GkY_Z-`q8~Y4js%TgASdk5KIhfRY6xc zD!)qoXMd8vCf%tF7lQaOdbfG!4}02zS%t#x4fiDi66zSXe-WMM`qf_n_qP!%iAV{X z!t60`g60Dk8(Qu5b>DHv9c=uLJO1&SYsRj*rXSwknvZIbNBYe8_#1DGk8^q#eonHL zAZM_MSBc&*85Y8OfG+YP|RfmF7)IT~nnc251lE}YsBddAge*86qzZRr@{!8bB zS9L|M+LxKUOn&z2>4(P`HuJv*7qG6x7fS8eAgy(*Zb?M}s5nv~zZcts6_aKeJ*aGX zcmE-O-@YT6L-+O%OT6_6{>~LL;lUNXc=f(pvqx_3^B;Qi)bKgcm$r1F@8&*V1PJxK zPydP;xd{1+B6bneXZDoX35@)Dw9S2#WoJC(N8zjlrc`-`?_z`gJ|GkLy&21_CFA9P zu!kVKIxUu6;z@p-6pIwQ7(|`4psT6L#b4~8k2o#;;%OK3RNVQV6c}qwptW>OzUDH) z5db(NaeF@R8CA6H0&oauo`hYPD0wDDEmj`A1B<}%ToPl;23PhHpy=#WDI$kv0RfYW z0Dc>4M=BF^#&loS#hmm~{(dAJ#+}zJu^ROKfSiDjn#pZD+FH^PTZ^N~Ws9VH((Sf% z=E`)7-QJSEGUKDKL>e1x1_MfFh{_q5XPC2#YfpB42ec`Qj_#}};A{Ym0y-IX6O4-@ zM!RTRQ>KWIrkG6IT?}<3pxXh^q&pPA|A3OILIfUSfnaU}{`yOkIj2dU-Dh&3R6%sc zdcZBJw5o_A*TlJ?oaL*79%31fxP(4lE0q2I&Wh zB^U@`6vZ}z@f7MK0>WvvfRPGODK(U|n^G~W*J91aCgD^BE47<4QA^Nd&BiBVS^4~o zHy3jxBl`>cGC9=r1==B_RG7F9Hw`LCjO4Y2g03&T#(V6PJ)UzXMlEljJIC~JbRmR> z)7WL;vtNOg)CNtD@JMTn92BiP9g_mYX6Y{=SE>}=3Lty4C}^0(3ixme-mTK(8=3DHzR&w9F!&{4*%6{{0EKf=*b_03dI;iNok`oMB0${i0}~E4 ziu&p}mF4qDmwz`H)~JFGz?aa|gZcPtuSByC`ZIQ=CKG%`+IQ(gCTaSDjv!Ew@_sx` z#)mZ1@`Ku;*e|9vk%B**Bl=zDU&JLt2*pxdVL<%a&S_jKOg-Z>-TSvkIm?j2mOKR z1NM+K0v^)9dxs_hZNFrofO2c}u&-QqUGH_*_FQ*e&$ZXKztN5&)R)e6`PsNXap}@E zY+QbdJ+*sx4tIF9ckgDqB9Za&OScoeJ}^Y(G0X$WUV@LK2WE903t@8sA^^p1mms?> zl0ZZ9Y3VbNp_vCCLoE!O0^;3+{L`0yGs40nZx_FF_^|vkzQS#k;(LTcM$(9gox(UE znUYzrC~yE{vSe&v8~u~2JhIK1U&WYQ$^VdQLffhwlZu$9(m!&K4d~s zU5A5tMJ(C|bn-)|zqy$lip!6f+hrTP;K8Drg)rE7gN>yZP{75JK}Yb~#La4`LVERm zed=c5$JCXB=y#ym$y(vC2{;_z-2j4>`0Pg?fVSTNMQ{WjSf!z0!-i$_)iGq!AO>^1 z>-y`vzA4M!B;xz#HwhU-`m!wV*~6r9Stg}kJ~B}?ZWZh(CdBcQOrPYgH&_p0EHrZ; zT)@I3p~~l^G;w4wn;m@S$Ur7DaOB8fDl;ID9~sPK2A_eoI}Ts>4ExfKE$M-89U0uR zWl#X@Dxi*jjDtsKxo%=(VvAMxS~aCY*QQw!jE~oD^>P zHaxP2Uw%n?nO&Itto)X*>EB$N4jicOMk$})H2Hm~$ZPlgL1KD3@fp5vsTP$&iFpT$ zK|~#_>Sgtw?CH?lAXSLgS@iz>g9nCWUNmR_e)j$S`(e9RC?Al&#jd(^L$sCsptWOI z-pYP3jM6$=Tcc~p0m+(e$m;nN+A0ZFW%Cw1ghJFRzk_2)vXlzZQ^+JLEW=%ic)C>| zMKoHJ5P@CD5Cw!RxfUw^s*WSc=5Dl_#%AJ(1hr0Qt3JuTLtpEQ&KMj$ecq|M~SrX#JRtr_ekeDk3H=ACZIQKX-Ms*li@c;Z))03)5qC z7~|x&^yWT2M&L_t>kuO#8YVlCpkd-2-kK=%pMG%vQanPsH2=0T$H0&PPYkd_F26%v z)3e&72*kyyT}(B5-;RI_m;EF~UfAs~uSoTK%DunOWOvWyEw6<$`e2s5qV>A_Z;RL` zvpmp;UETmMtQ9vrv|2UQ`I*ml=at?0Z&(K+)*ZKcz3QH>?6|dd+voE6&vE_&oG9rh z;4T69^=cSSmt|Xiz+*E)0Vh)$n>7APLI~}gs7u+0`40BBK zr4#*H!kONJ(~n1-l8upAQ>l+VKoBSG647<2>k(NlUOgcHN|vd*^@on+WWr#2`&lQ| ztR^5?)UTFq2|6x)0L1&5$!^7>8%RBTzt>!c_PzkV1cV}naC{O>jUMjliG2HC^xw`i zXCB3Zy5+ywinJ+tM<2dcalUVY)d1gHRybfFz@!x~!%m~%J5s7neLFc}&+v<}46p0X z{^rBP^@4%n6S#9WdmzNaXAk=9`wg9M3FA$r(o${QBh`M zr%O4MK7%b22F$1dj(3;SfW(wI#Bl$De4gynWThro&3T$9T2IjjT2CAY@QRe@DzJ9T zu$$5iQAw-YgwF@JrByAhZfAKG;r1l$N?1x!xv4ZlC$G4k=Z_z*(bkEI|8G3DI&Pn> z0p2U%wBdhCuQM{$ZohxB-!d{{VY)RM+^ZQI)8r;%v5Dtb4p8%vj9Qb|N?$}vE@+QI zczip+gUB=02|Elqb$r;azRjRLa?ICSsRB;G7ODk2x*AoU8YBhc8r4V|wFT5TL8Yr* z+Y~xuz0~t!PNA!-(>TOf~h$0#Q(dw)+`E?iVu{- zDT)auaMG^-8Q3-cv+Z>A>lX7AI5~F%xt+@zv_;+|Z_jRe7|KX0m6Sm`)e`-gk0Jd` znZlpS>3J9vbQenR(uZ){J5O)O?;%!2yN5n7gtx^79;N?G@1jrbdP8UMtCS|_YtkV& zZ2$^^O}A+G4;Pz7+xR~-lM= z1|_rZr~M5L2z7%dP=krEYsjtvYbBUWqmd2|HHwph)sO*IZGkb4;;m9P7*yZAYcvwc z#xkcev1}w_V48Q&%KP&}vwM#plAg<^CgeYLqAYAfeKWi1nsoMTB5^0%oRGg`jo5;k zO;;g^g4z}Gp&y!PL_|m1V0<7#fYromBa58~{tO|782K+E)E)uwYJ_$`DFuT-kqrVX zIUe;oUC83dA#Nzj3*`l)-r$Wv{E_qfa|eRMCxgT9Q<8_v72W5gr<|m3Yp&a7_w{Vk zI@)??4$t(q;l^Lg1Low9TXCB-L3L_@7%9$+J1|dIVvZ0;z>-C?9wY%3%~S}+Wr`cO zCTgv27- zn#A6`3Q)rui5^vb(N!zdRLR(T_CDDn!#mX~z4DB+hg*fUfV&6R*PiL4qZ zwhF5*R?nA2U$!Ei6zTDl+MD9XV$^QBXk>Gw9Q=l3Ad zLvFydbQz(bbg7MjTH~3w_P_Pk{xhVOvF$%)S0UfwTbHvR{Pd?Xg1$IbLUH~Z5Y5qq zlR1s3@NF2WU~zO*!Lpa?Lbz@)R7;ssX{bz8UX238AajaOl-{6P%*D@17Q#)CO#TvjO2Wsu9Hl?pf_%wj~6{HIm2LV`(!iqPpRZ3jO>h*EYW5O8@d$bLn-Inp*F z$pL3B=XCY;tu!3S_c(_~dK&ArPG7RUE8uTcD3yu^%e(k6Sb~%D8sU$rc%ksb_U&Tc1kcKIREl&L zu`AMY2&g(#ekmgAsXzn7Zc;Gt(x>KSMBrCp;1=}J76ys9D;>Hk^|aR!c3KSXh*NR~ z@gkOjp&{Z7N8ARGgTs59Uvh?>R)g!f$$<|bT=9OCFnV%NA8PD5{SGNL6vGGcN;$em z!lj%R&A?DfazHehiE4Gmv;z0NY4)wS6JU`UkL*e^{=UxgHgT^sQF zkp2#!dJrgJHAq)#z;h@jk#epe6RjdheBNq z7o5#Lm6GjXy4uV4Huc>8XP2iZIu(u9>vFeTc4U~bYe%-UIXfnIIc>(4EuEKJnynMt z69Y{B41!%{xx+cUrKR(nr6m5wWm@QH>gNdhE772?=8*#g^s%HTT$K^U>)1V~^z& zO@Tl%5M(p|+S}fK__49$=3zep-VUYxcs;r`IHMJd-C#=o{dlDejPAhv7c2fD^ zGtcaO>)W^u?cFO~*3vjVEk8Ov-PqF7$o4e0$mbJ@#N|zR_yF!uvM;V0H^s*iP&JaU zATb8Pxw)E6-eV|2{1@ITUy40s6~ng5dogV5+#HRXy|!!DfyzP4$L#LK)T7D8OlJKt zlPpdCBO0^tED7C*FnxX94Oj&}YIMkl(PGH*1bY%gmM1V|c5i9O)6*X};!2yUgz=MY zgs4Z|g)sU+V>(bG9+>1=^vH+uJ10-F+({@m!C*2NeDKH->Hd@MBS${`@JK$;9Sn8{ zesc08&ekhy?q##=Nn8)v&^Q%^l?9f4RCnUveBs$M>`C#B8@@w9s8Y?ZYVMWlR(%KQ zou%(&mb9hs$iMy$R1T@;nVKAXs{Ea*&X#*v`VRF>=(F#^U-}DtyO!4&t{&*gssXZJ zRE`Z_$G2)~-ox1F`xu)U6H{syUwv4#N?&_Xj81&#S2d+JX+A3EmHntZnd}$kN#yNZ z38bM}X~&8=3_&<5&Y|kr@_gL)ofr9ce#OF4-Ky`{knLOi&aakUEX{}KJLn6|A=-IL zx?hY3E5FPzu;53;fUwGYmdB$I^IrUpp3_VDTSZDKeo;_J@w>DF3~iR={u*=Q6G;3Y zBiwHw$D=7)uaDjUum1pAMixEA$)%z&cb|vkkJ1m}pFpj#LX_t@?ABURe0Ut64Z1lU z0V-+Y@*b`71kx2Q{Z6UsD75YDakcr?T8*+rrK?v+ku5lxuDZ_UlTBB&XmAGX_(H%w ze5Kvl+v#T)29J0(8u@}sCrQJzxtXjJg-i5SQ%dLZTHUHRLN_c9SMI}mN2HTVO@9^z z9`%Exuv8Jf37JYqx>*2Tb1q#{c@6=`B?2Y6(}Smn1=*Y0s0)?c5Rj^gxe$ScS4gFI z8Jvb(V!qka6>e!pC}AQjf48;X$d2ochK81waDvN8%WZM=uj=*$SK?V&My`>gVh@*c zQOXg@VRgIVL=G*&dM!Vn2%kH*RM~P%3pFa=W~^^zmxU9z_V&)B?mg**qJ850F^W(L z5H17)V;U(Uc&V-m0HiQ5fSdx=L`Ft?RhP)3g z@Y}qpp1owMm%qy{3nsflEiHt-C|?h8A=J|3W8dhd{CV^RHmPD9u?Acb=+R|PR*R5c zQFN;wmKz+01aC=PnMcsDDBN^TlZjjUBJ3@!3zBEW~UkV>B+yC zZ?xX}_FeX{JZbwXLHn%{{B2V5-Ilc?uw3F`ZweB-GhrWGmC?FPqUx# zZe3Q`{wnX*cF}Rn4V{%4$OsR@BSkUR+{=kdUKSKGg1NUgU{g@9NxUd z36Y(x^qM{T{3iKr`EC94-)n#t?KFJe)6&zLYt1=5@v)n(j-MBqv3b995+&@o3{dPBKzqr ztt~9>Y|VVyyisJ%@sM2yB2-E9 z6Y*)VzYu9H!9E4VIF$MuhNulo@z;x94g}q>MTFigaGP#Kv{YyAdN>$`z$}SrJ>)Mb=Tkfp*nmYuSoZ?kPUg zeiODkGDmkchOh(q=fDIgf_4#+N`_QwF@vJx7gDJVo>O=)^(g;yZf@?;xjAVQvb)}V zY<4!Co}GOxjsN0?x9DB`(tOexDPl~Npqe<>l6D{yaaYY`%?&l5#jdm=WQKlmNVGB) z0?c602m)IJM+*J{H35}V5l~}GTWv{v#-`{d4H(WOHLsb96@eOoQznEDA#MzFPQUm* zT)PMjQp0CPiRElErq_pqNM?5Ghb<0GVX=VZJB>b>(xJxD;JqlO>biGOhg9EGQvVaZ z#cCOL@6DvFQA=2x8McP?XHwH%?P%oHVV&WmKj=2Oz0bz1aqFY0+f#n`l$-VE?NQ4M z*@H2Yb$4)|MX&SwQ7%a{xR_A75NNWupx5>9)hHcKNflolU^TmdqosK!K4`G$49@Vq z4vo`d(htS6k*qXjH^uE=j?HIdkv;a2yhbx+k}L@aB3-$S;7g#-tMH2AqH8!T67+Az zb#U^5b3gc1h2z_|%fCN+7T+OWQ~4c^HpR%tQPkh*y8*h!Fw@Duh3bySlF%jk|rmPzM=loh61t zFIrig>ac;7LcyHf4?tm4!gLP7AHOjHBITU?n;{WHanK$#?b~MxCQP_V_xtRx+s*QC zjK)D@%pAdxzN_8-BZXE_Gn8lSnOvJ-yl#N4p8xCQY zO5fpMe$Cm0nA`@VEf?lm7iGCkz$viHR{rp{*RUeR?))%X-A+I`SSeYXwaRnNq~f&3S($#;nmCdWcy|Zgwzc@DHmH4S{LX4`MuduSM;+Q6Ly(AA4y$N41ak3uHF|NW12>F~_ z1|fu|ZQU?i;3$S=sKgEegf~F`O^8q;^NtMP;#B~7eYTQB(p7qa8kk5PLyMqFe#rG z^^1=J_(pU4BA~uB!5}>@9+;dI1)9YpU#~gv#2fJn=T0}moXj2}!2hxQ_8j}ItYfsM zH20hFxj%!2YHtO7s>zjw!yn`pf|>!f(?)tIMLp9; zcz_8+2e45<$*A!ej&1@+NHByz3B1XX>_qwb5X};Ej14A(7OeyM_L`Bx;P~i?(Rg%t zU}WgF0k?a9AwF(*SPU+uR%?((v+>~wB3z@fpi||ZwdAJtDj1hz*=RUSNRd)ve6KSI zut_U`B>{RIi%Snj-3i1TnXC@Kclbm&GJ0ZU?+AkUlY{f8vYA3G9F9j_PLoRIa67ZZ z5V*59W=(plGMSkhNGXFTvgq0qQ(COn2k339+-zg8W7tR32%5g>>{O~6~*#nb)(CL(p(SHcRcR=ejoiVvI1Hk(2 z^E=M~;Fo33oOIzsK}=mO;tD3E8>B<0=@`-m?8zzm-vql{#RVY)%+PaAA^671VI2_J3*qfW? zcbFP>bZ@CwFojaBH+ed?o0BFL+qbF9rmX#Dy_p#u7G|hFQG8{pf0hAvn$<;{n%e6W zy4t!rr#qksLQA08~^h9#7& zF6dlA7%5Bul~#hD0fnssWTHia{w|fCld#%oRCX8AFIDj0<6N>z5x=10d%y#Ba9Nh@ zV3a|QUx<;!YuQ8c-qJ5(F=be0Bvqe0*!S?BzC77>KKif*D8$l399asHQaoS_jv{pk zz6Q)JU^&R4tA;lshN|r8Pzvv=)Jz)rpJq$2^H}oc;LV}B&cJ6kzpt@r`s%KeKXPo@ z5;n4{KYw*PY&C8&G3hVy~VjEQ7|0#|wRjBGsMX^FuYn6JTNqNuUB%1fnZ?Id*h~2%SztR@E`QS{rt#$1B zPyM+k(-_F&JkVuyrkk&5#3g!tdevs1w{ur3eJ+*sUy?IdZZ_#KWWKleVJ-Gz1_2a>{^XO@9+e|G9zYb@pudBt>reiLFK=infz^|+XC%T6hPbFj`K~sVk zi_DoQWQUy?4KW=US$O6TM24>J@&K0o4keLb?IF=FX}nJZKre(c+JhQrGI5r&d~`aN z5fuj_5L;tTmo*qg0wp`;cPC;8<=0}~;6TtFgU`kp+1Bo~LJCeG?4jPKKb!qjPtT{a z54OZwaKB8avoy6{e!1J;xJmb=W{pF$iDBLlgF!Oy_dqX%^F=j(yKC~W3eZj|hvnhS z*Gs}62MAJHG&ufMVju)p)adD@<>c}K$Nr`guIbqZYS+!tb)OANF3;*LO|t*MvGN_n~f1hpW@+ z>~wYXnCf$6$IUI&Q%D5JA)N+Mwn^}BR3Gc7drw%SZyO6*1V>4Ef5$f zQr0ZYsg;q+QC4^_IwSAR#s}H$1&3v77vkux%(O2W4#v)BcID%X+To-t97ZIRG}JEt zmtV$aZjSj{3`d3wT8&YAV?(RID>z$QU*E$1YFAI!<=RI#7Y5q4wBgSCSi(p%f{r?P zL|{pDu4Fkx4=~hmN~x+RjA+1+2wYrI{g^hg8|8!n@rK&R;jll!hLirV{G)zTZq(%( z$(f|;GRQxu+`$z!kfY(@F7@D`x@(yFTg+=9Tvzha#z6D1Od~!E*_PbGtAI2IH&tm6 z3Lj3cR=~NzT}+w+n@^4=BJVGn`?+Pmaf( z$^Ia4aFgTm(w<`}>2X2Bvg3{9nMX8M2a6K0>oZtuY{{bUK-iT?vTPPB&XXgst7^f` zsX~AUZkooebWQ3+MhU!xVUuXRnc@@p1V}Y}^h|NY4+w`FNB3 zR8u_f?JWFkJNs2G+;?<*d^Q*C`#azbyaB)}H+$NSf4}n%K5EYt;!i&v2j}MdW?AO- zKz>|RDHI6d##(R*_&UfCOKK^&Vr8{ZRMnK<=an?6VrW&p&~x0z1>l`>(a`PO)+X9C z@Rb5@s!E9A{(RU@NnjdkCI(3yP((5!C2I zJy6sZqgbm_QBYcqiZwUD*HDb#t{Aut6TfD`)|Csf;J1?v0?|B(fLdcU^Nw5xhqa)o03s{DSo0NaQeJz*Wb zrsudvkLjz|rXmv%U96x_+O4o$67;)QSZu?u%lr&+wXiqgZ5? z7geP8CH$85N0?6Ts!8BB4Pm7qLvL}PtXvxG5x}T(`o&IJW1Bn&$lfNG>p2(D&#T64 z19w8cDv5DxjcuEoe9HKYW)?#o+-AB6>0K)ZG+WVwk3(WyB^4Ayk|7yu#R`H zwM|6z-DCZEd1=LRNDX|J0Sk2Y&Q<#Ye%124Q+!eN%p(Z1h^DtDPvW+?HTJ;QXaiu7 zx#ueO9gW3Bl(jq-3gZE+>^kIrj$a-yAREv*W)%crn8j`oE&p9bvw&}zN3v^m_c4Jm^YsEy zqq6UW8(h`*^;rd6{J1SmZa|N`0rpaL!&O{ixoxWP*izB+mO>E2;t;Bwj)^R>dX}l?t00 zw|6g}Zn|T~N{sTtYI-|+C*QI-&kC!Fu99c^R?Hulph}iq&NI7LkzScyuAWZ5t$a=M z^Uqb$pb7p2ig8~(wvAZiJofO%^T*tC^Yg@?H)f8@G`YN&G0Q?sTXQd?7Ax+n$@2Jd zDz>{8VOGxTT6-DC4=>2QYC`EyUM-%t*V-Hu1L$NMzWJ6-_ZhQ4gWT zr$L5Q{U?34vi}=zU%K>$8+dy9fd$}1Z?J)@+NYZJNZc|boqoNkL)GP#vnKy;`&v_0 zA$!-tHp45J`?{<46~u`ZLKyo9BFe=TJ7+~7t=#L6T|(eA>z=*2jm4CUxeaG!d4E!U zZfNo(T~dT14+!CrifeJVvujrAMv+t!mZ`A#FMmmo&QMk1>s9-dve!in37z!f7Yclp zOnVL)yma#;(R}|{Y&k2PtI-$Fox6z5vuYwM$K~abDrMb7goeS2y#AabOpLebJy_jj zrHV*O{MxNo?%L&klx0A~oglG$J-Xwk?JClH;tBcLC!Sc7`YO*2lG!-@0bHHJ{3}N& zPz=`~!-WOb@xTMCX0URV3<#X?~!Poe3#sCA&uP+yKHeH+SG+I}g#S;8WDLA6!rb1qcPY zXkeFvg`^?x_VqyyQ12#L0Yts5K;bXLy|=w zcyDqWt9%uGBGh8SJLQ}Ku@TUr!H=+6S5~SgsYhthM8m7k?vQi4BYd1~f_Z7xB2>&d zwdWR8T&X-)%{OS74|vs~N^JG8&)!SMyp03{jclkNOWhrgu&7E;z}>HVICT?@`C9aCDC%03e4?oN5If$; zc2P<2tHdTwVm&=YN&|^k%st_)bn+PR>Q*Z-&D2F}P4&oE${ZCuWlshDuk1_(H=eBS z7sHHG^DFtQG{TRfV3pdqbI@MwGaY@oJjhr!T6712cS z1-E0bAbXrkRI8iJ*el48Q~u#Es$HhFiGS5txhA?|tRKGxPz#*o*;UO~EC!v+y(X9X zi!iEhxDl4eZ{tzYH9{{gS+=`jzYui4mIT5`@h7QPJUv~_^r2^M4>gM%VtQIj45^UY z$bPxZ&>q>tL9D=ch9PA|gfa`P*WIX-l|uQ!Jopr_S`YUP-VHdEdl?54z7m&aUn zcCX;}FbEL)6Hgo2Omn?OUdW$T^rm8CRMMiFBY1-|!fk_}wdVdTX%?$wl_8v*+hMij&YRw@2J2sw%He)&s5ejCpp*Ui$L z5%SGN8w`|KHRyBeDN5&-m7|q|tXzL;16c$ZS1))!9~Y-Z-}?5Hb=AR&+1;S^N>W_j z3uRj<=#Y+mwJ*K)jwWL4@2AIA6gf8b#1r^s(bd8&&faCZ+=NK98Z#9?6}FVs#K~y~ z>0zrV^nr!TFJE|Icz6XP$K@+%g|5&29Lr;=TC)|qy42Xl)H*!O+eV1XC$djzz?W&1 zw6E15ob@Mj_0FE2MhYRjVvSi`oG0vD$;nkSw@d?cP52$keg4=< zTd_P9^v6D$oJ4yo5ee6(y|P`Pk$i+0(Ap>NF&LzdtvX4#HF@JRSJ(s^u?~=@($)UL zbMSG^uNGps;du4QyF6EAdqAnrRSdS8!qC9#HmW9zH@Cs*yBrVGfb)=K^q!hL5Dy0- zvsoG`$O(w#h~ z#Guu!m7?xKAwFPnYoe}x`P-8)Jd&iv9(DMwb`-8g&L+|&aAU_=$Bsn6>25H!Mmx64 zA9M^Pe66S_)7la1-#_{KT}A4*Aey?6TSv7!m?i8*4Wn{p14NatjN1*0 zc2VWH7ugL{l;t=zRow?GWO|BxE%!k*RM8C{vO=aEbO;G}nD$a9roz-_c#5DsMxDGL z&QbQRe0s6ejk~GIyNg{p)_phijtg zpQ_fcVzthkOPR=hyJ!5M&2!M^-NNML-?AUsJYMTT?>z_Ev@)pFE1g+$dOr9^cR06X6NBH#sykGjzlij${x^dcVh(@!0S6*v90)cQ<+Ltjq4n;MPcf2o&HV$2W-tz4xw{{;enu; zUjpq}&g~K044Jz;TQ{D@YN^*R@h89givQ68?|Nnaw#$$GSMOsxeSCc?+eW<4$F@z3 z4L}8G-?l*qzV02}<==(-sCRVzZv0pNk*mB{;ZF2I@rRZD;gk+RegiW+TZw^pR z!S~)Fa_Gmky{F7Q(+#5j}*2VI&7h6S0T` zMUDNANNjqPYA}aK@dP{IYvHNzsC)dz3HK{Hlifh?nyd&^4!??ziZAU&S!6@lU=N4i z=O3Q9aU8Jay>o5NfgAQs`J3D3Sm^`ebCXR?zHr#LVAQu5>}Tx;fO}ZN^WkscledX) z-SGbC=p)pPN9M!fr^Lr=DDOqg8OatFoW&i4NlDfM(v@gNQd~eFiRXadk%oNGq>%{A^$G6D;C?e8xNz4rP2B2d;Q^vmyedUBtBU9 zp!c)4eYTfB$oo65+H+MWe+ZO2Kjklt8>2y=NhT8guH${)jH({A);EA_A{g6h^HI9a zI*Uv=3EjmtCjc$lup$5ovQl~d%sk155YLjqfEXNK^J8vWj8QDh{mZM0MOYdQW5Mtu zd|`fmbaZri;i4rnh{=QH6=pK6S5wnu^*V;nj`9V?#m*8*oD&Ph_LUd@wmE&pqGBFs z-<`r4o<|fig($^#bODU&)1shd|CQNgW@NfY8C3|o>Fc)(;(%y z_dV0Qoi#UiCXOaLQ4;drO`+I)EU058s$12j$d*6J7)@Gx^p%$8IMTTJ zc_*+4sNemdI??AYUi6hGke2#P86uSRqgEk{iZ(13m>7I_Y1z2Aq^3`>p{U(zwWH2T z9+_3)zP_AJqeJpeES_+Ay{<%DmUFp5or=N)_-#^>fKF8C@B4ONzta&<98Ja@PWgl` z$OmCDdHEPD%z|?~VxrTWekPF-=Q8pABk~w%41}(p1|@#7k#wQA7UYLe`8jMT3<(-t zcbAKO{1A@6rPN8vA1y7NmQbkE^7ad-m!wZJhB=Kzuhc5%bK2nd-A)W&hXae`4iOJb zJb(~)FvS$@06s}TC_bLdLowrghtuAv_~m>6h17Uiz@P}!S+A6{d4UI*QPU7;4@IJO(#(^kQaqS zkuIS{1XMtRLbf64aKM(tyzz35C@`c)+BNi{G~DJF{hNKh&Hf7zevtqtzrg=Yv6ZKZziMl4U_5|L!M{76M{ZZ#FCVQ*7UTx_8 z^7-JV&D{%Kchs4h>ZI#D%xBL&6#01_Gd5}N(b5%+4$VC}tL~mUgF}0d&aAyhYjSA* zsB@puVd`io-0?>6k!&|heYvj5sHvzCL-J=aTZwawu5K^52thv*EDLrb{gBxoiJ#qk z$Nt)Gu=H6CR*T;14niYCT{x6kb+{&64hzmXt1|{FyYx;f=(g(F7srs^)q3@iH{0Ut zu{XB2ex)_h)Y{sVXx)AjvhH5G^klBp=i1`MToXMA`XnE_6S8PcNmGNCUY4yCoETv1 z1VR*vH_qjvyTB|*amsmmBgdX~-IsSyl~Vo%h=F`PN*A_5FlJwo53|p@@7wC0s@NCQ zE@FUIwn_?^C_zHiYDCnY2%cIz79abU_!U z^Op9LM8mZ2OMPf3&F_=;B7kuVwEqoz(g*mj-}sXUf)B3Sn*~A$yC;zNe8+?09CJYb zd7fujQB58|5#cPa7T(3_USb1~ZqQ}a9V*Ng0 zFBL+q|Cqi#e&b!!AJZ%O)RV`KQD0~cOMP*Ye{1cYGzgQqqBL!5^nhA@QcTh6#vgwi zcGh7rF%{#dI*$RO-=e;?cHAP-ZC&gZ&$JHyu{*E`f;o20(Pddko zoMtFy6sHw96WRpXSWEoDQzj21^qv#?VSm(gg0DF_J>(C?xKk*t9`ZHlJ1PyzrWT8( z#f12XO?RR_TKnbpg1k1x#x0_5cNa*s%e+y`53-TG9539seh2R4MgNFG$ht?>x9OgYe$$v>40mXn~(IJ$ABkYLWhKOc*BQV|C&I| zmt`IDJNO}42pPhNLeteGqrf3TkbcB)bEsjvo6e43$R`L1i5&tCQZ~A8HZqI*zUb^c z9Ub4ewbd%$V|BOM*cYs=@;BONXWM6QiR{}KxrNhBx*pNh7a?(T0WP$Ngw^s^boj)T>uda#X}Sb z|8aekf3t7j@PtY=u{b)qaUXws%PrTct##M@IkMOI`7Lx8J!R_zC=(deOgUU|yOJM^ z=Q!eULOQ%Ofx?|AO%8M)l&4Pl&*hjt(jUG+#bi;$9EhFA7tZ0IvKxTs1AK1_yrEJ~ zZxeLf8iI-Y7Bf|0J8a zfT}c*vSA6$6)UtHhcmA@4nda&iU&pB`f{BvGZ+NmpFQ13SFf(SwHrk`QLhtb&1xT? zd|PktNRLaAxqb_Bff zamZ{wI-Rz17#LJsP0*GirG{#;F5_D=fHrXi(-5=f!|@D2*>fZP;dnTaK?renv=Bax zo<#i2ltkq%ypVsL7~azUh3!52uSO=e2QT}ngjHyZ)Vb|*+mhF#TBB2L#YdCZd*#FM zZm!sKgz)+aB|eh1LQo5#?tUC8!&Q@;+?a-4hv(-xZ~i*wC&{Jh04xRo41>}H=oVfS zwY&J(U9QxKlSBY%qEcs9d#clf>gFX`W<`(O6=-@SNO3MmAYvc3VU=jG?CmrzJc#p9r7 z30)8wz2b!#NIxDuN_gx#F`IskVNrzU$Mw^0z)e^0lh-DlUgx{oXeOqO zSPG+gs~u>ltEl*=9UXv4{jt&7Xo}ihF8g2OFC)m7>^h}>v~ar)tR_`Ev}zv#hme40 zM4w>Vp+JdRdRpDDij9>I=dICF4=v~}i>}qj%AL04vPX-Z{R;0YbsrsGK3ml|^Px`& zOPtzM3rB!n5@o4vT^4|sq&STMj|s&g^$ZJ$U71MvgD0Q7H)sVL)S8O1`-Z5??=2*w z$-Fn{I#B9p|8PHhe{gJU&~8X3i_6)QNVU6cR@Twl+F`S|EVegTtqtu+l&Pp2qeH!t z9XRt#W-yu^ux?@o9I^~9CbH`S#sTOUWY~a6U?E_$U|JM=AQT`j%-&!%wYtq#)}D*7 z|3C&#PdFTC2kc9%uHC#nY%(@F^$oUWpHu1EQ6FI7l83+_zJ{3vjPDPukwANUpuN%6 z-u^e#dtJk}HggMKeMKN>QZ#!|;8?AR@7daa1+kdu)%y*=)Ac!>6*N(g8SX_rjw>-9 zGJ>RqWzV7lYA-5&+fr$~3E~7&5usFs0E-3GH3{gq3a{E~D-N}6Pf?df_P8rzHM!j; zs}!9fYW8a!T3)md>`bq*1cCPYeq6ZA8F-2YyhSOS*D5l$sSDuA(R!uD=c}x z)M6u6NNt=WV82s;NALZ$d->)>(a15Aa`_Du?;Sny*gd1Pl2_d``gc?X$=&L~t@Y=z zo^0nU{H2?}&H01yPd33{+rhb~O6)uWumQ<%W(5emR4wNez&PbFQg8~OK1GpNNE5-U zg1h(b4(x1=L3^v$+iDN? zr*}?d_FWaBqUaMl(+Ap(4u|o-IqhM6BcVMx{~P@cUr+@fBg_(EH(4=%+;K>~0|OG9QEOD)b4aL}r0DV;H^ zn5ZDCgF5kxrmJp&m{+;#csESg!T%?TG}I!&LNrOC(Yj9rL(%UZnw^5)!iQ4 zlgR8HjYdcJ?w=WrNN%fAvKC_2q=Sw+$A0lN=k9azTi@aseGA`3G|67KKQcN)U&B*I zDcMmzD^{?dH#q29Ce+FDIvl5{gqO?dcJ*O-`Isg!rg?ZnjMyRV6cJL!9_5rrGfl=Y z-q#Rq_ErW?fpHMRu3A<0=%DOa3~Z1~f3QuyDGuis?QVy|ZBJ!IhqKOocDHHIl))P# z5Wk`1!Rc&v`ruSfX?JOc5A|nm9En6mZp@7Kv!@#zP41>9gLwKsx3oB2&K6gXGw10r zPO%#dF^|D$G(6hUGkxeY+4S|9`W>I!)^^48EuXofjYzkGc8P|lLi0K_1RUP3(7L2U zXFpH}^%pJxBMPrpQ;gX`hyS;GCV>--SA1T9E!ZhtC;d5SsI6=YP#K0dT1!2a7!tngl;dF+wDRQu-%gFVcAmH!WKSk z%XU+i%d%ZEJ>Tayk}Ww-O8N83(#&Wyo_T)n&+GTGOPOYqXm*>dff3eWw;4^&_HKiz zXO$RfbBiXcC^VaaeW<-(aJCpEr$G*Qkv-nD>e^LiyV+)Gw!6A->vr0k%`6?THydJ| zvdzE(ZS79GNw6tW)GnAk{yQv)AqKz|0mqq}dUS+A$MwDD7rY&lCA z0mMNguUp4c-Us`FC;&X)Dh6J{Clu7bs%khFzKH#;XD!)krzAQ3k%*u6wGY1U9V8=C zeXb0BZMldyUwLgIUD7gopIc#B*>f>G$i+*_58-FOtWIOFnvt%$zNH)Mlq!u#Yh3bH zAgit#59t(^>KDEhC~T;|0kGm&@&0>h1?1#{2mW2tJA|#md%2Am8Vq-VrU|4ogP{sj z84z4e3Jzg=z&A`D(46|*eUwxYXW)^hioL6L@_^Nu7$yv9MzyTiPVB- zdLh%w$g5EHorBW8gYepmx4h#Fq#i) zXH*Zet_w4Kci{z(nw?{J^X+c>|JwW4v5^~h+(`G}JFScxHH)5&scg}lo4?XwWlwwC zvvb-W+AdIzF5Hvv^m#mg|AYI(LF?t| zQC;l({ZXrHtM=H6w4k57`77{0lnb1)xawHoq-}0u4a!{jAT9a{P+pCi-#{Fit-5^R z+A(B@#p_;umw2u|{kJwZmKaTpY0vZB*t5^_e!BR4H(IHU$G-CXL5W z;c4iq21y@)`2coNZ;YltFo!fV&~$;-2Y=`g_yflZ&J%Y02-r{ht%E^nuEGn2oPmfZ zg`ywV0R>wTMgvpZ)5GcQQvo2%M#EEimt7Jik6o1QuKZLeD%od3TkT?KOGvbDQ)Ro9 zuLMHFp+F^vtkAzIW?~_~OA?KuGr9E4o=`U@V`|Jk6+bMap=Lu<@r94un_T^ol-;HMp$Zs;%CMtHmkA7Bp8RZ;EXs5fzSlwGg1{@H)~+L8lpes)jCyU-ILpJVJ5-@I1{ zp&qR~UtG;?mn0i?wb2T z7zx3VKHO>sNWb#w8IMa49(hDCS|vr(>{bE&NH9L2ZGR08Pr_>;osY4bu@1Z&rJ!7n z&8RmYMP(USC!;I|mBZx+V8PU$7iP5QzYB2k*Ie#h?B9;ll;Y3{xP*gx7Zx%gDawLCw z9X@k7oFTj2(dq(FvC`r&iyiKc=u>@Umf~g6bpoXGp%tmAaV>(eiPSt6pKjZv`7ERX zz7=Upe}S#`Lh|6j_aaTUS8w8JNPY!2> zrcp{PIrL}}vb~cP zb&%)k#-xR{0R*BX1{{!)6d^>Yw_dFE2-?JVM7baq7J;L5OohVL`~*xty~0ejEGP#R zr5M$WFKDlY{3y@}F9ymqfim%*cOxI!@}g+UL%Trz;evJ^<*AkGAtWwC!F1Vb$^N^B zXIy!EBN9{=@TvFleXDVZNMD%Gz$!;!f_bX}h}dOBa||E}4$MU~2HyN@VaDJ^E0BL$ z7nf7&-A{nK?Ce~$T={B3%(da(-Y|QVw%QbXRGa$8k(+P6>*kwBqP@MN*{s2n4PTfH zXR~49v2b>arcKY?J%{&nZX}x>$?>sw55~a&W<8w)Zt5$0HIl)A6DPdyb(&j)v;iv9h?^bU0%O0AiGW!EmHeD5=Rok@k$Yu8jDWnKNJ5^EiN@%oa%1D*KX-Sd0< zqxq5HxvBXFk569ESg`ccEFzZldG~w540{uD0Ieb$cpre=%q{eTJZBp5;aE+OVR7kv z6(Il@9nfY)YrkS0n$c zJ1)c3Xyx{CJu@3`jE1N4VUIT80uw^Xb)+brrrLw?G~fvmWJ0M#L~vrOJ2*Swtv!zr z$kf6D@2~oEEnHfQ0QnfLjA7cx>qPe}uGPrW^MJ;{Yk*^k=t&ouR)Q--H~>%k^Mv^Y zDX#huv<2zA7SP}NtK%`mW1KOKEwX8N28~E?#JXOF7V5>}$;-!idp}t5d9e0R>*X# zi4-LhdF?)H(8W}L$g?vnYL}Tsk`kRot?aW z^m=KU&5bh{YHM^^;&80ni{L_4r)-~2*)NXn+VykUu1=f| zX?t^KRc0Z?oyqyI_L8t=?@51HCs3C9qk{jrop;+^nTb${-IbR;A<*bj&3Q&DzB+l7 z%k+!#=N~m)jMkJW=HuE7Q3tft5O)6mKU^{5^Yl8v~p#`uv37h8wRe+w$m5rVS-y%Kik)yBSu{?hIaz)j_zkv;j zX?uBqe?yt8NJSrj2In#%_x?dIqHJGAK4)-=AV^K}K>XFbx&65u{&bNIF|gN|Vm z`2`TnKF89IuunC5o}sJMwJ|*xQ6n{tZ*>LJ!}#Dg{sCkFVAnTNRFB}G&n0@D)G!t}cMUJT`bt12xCmQ=y?L5L8egv6moOHvhEl(7 zm>C)h$PsNW+sYi^_;Pp@OMP3%Ff?qAoe^uNU;uyi4 zEXHJBwv5$rbl@Vqiu(5Bqe=%r+jP06tLs;!P88NB~xQTORdmz$;P z>z8EzE>Ip+?2g{(=5dHR*!P7id37^I2sG2t9 zqRLpZ*VgFTfR;xq6VeBC_|)jg8A?02|MC%0O>c4;EF?WXPp6Wz=Q_EU=?|NEE|b@P zADSEIx}~uzgL9$rQa{JJYZFCn5TUlIsh2}Gg6HQLVzek>_$+tz(aMeEXXWw2L0tew zP+wQXSvRy`W49XPqvvFKOPTvX$r}Z}M8cpk|pH-!9KKSaU z+iJff7N%j%YOFn-#B$H%nd^(SEM|+-SAGION%~MHzZQHflu0N3H&JFNeYRj!08~D%X;EgqU)97Tr?fa?9aq9;aiHML{x4$sh6Pgd)aPtTR7To z?#`Bo$ax%w9q_K6VB}TGlAdka*~S{xeXvPqmLcZj?_My#-5aAq*9y6Zx==?W!MQc z?RVzDG1z}QOFC&(zqP?6b7AN!OBJ!@{t@o>?`h1(QInd5>g&D|t%eWVPDnZu3OT>xt z$jk!+Nc6&WXiM`~0s7csvXM9erviQE$B0!E~jRY>TYN4#7=y{iL^{=m|1AGkTvuNvq+Ae5>CvoE_dJ1U0(gJ z+QsjJ=Qqy4{To@yqdxlFs(pfOj`T+Go}F!9KzmaD%6?(Huz>l)2R;8{&UWTi1sHEE z-m(x+3vn}Yy%zdl{p!sZ;4NK<#eLZI#p1;1`0!z4>*upp`}?;{eQ3yL8T;c8-LSDc zx8b|}wvrfskF7ts%5p>Z#v9h>A0HSP5Ece(6SuCP+Aj`@H=URo*|*7J>tDUfHu#>A zts8P*zF{PpU;ogmez9arJoLm9AD|j1T#fZV)J+gHu_xLOdQ2BHM z1+X4Fq>%F;atH>BF}rvOAPGjYvCw?^|6+_fxTZS7wWHoDI%QSkhvcU?LmniMVJIRn zGK|C?LqoCP(9jUG24cXer1U*{+5p6(B4xma4M!2HS(ifqkKyvC{w%WAHnn2K;$k;x z8J9m{ZtlpDx;rCH4YE!xyX6wEOZn`;{Wru&!PAqY9ntI#E#h)Fv#mSCAo9(I1Cnap zagpyE0;VJuV%BX z2R~u+5hN3&&)N7kchHSDwI$6vdYqk=Tjvm?2ID#mRrrwEjXtXg5REutZ;67^ptOA& zka_|l)Sj+}!2!*2_VfZaz_$zI7W%xd-`7yJoxpPdyblmKsFQS}`;lR+3m+g9@dvV_ zr%ywl&Qj4Q7jGXbvH6nFf9@Q)Wxx@{A3aAnfB-SXGia`{qt8DBo3sn^1>v%k5wSs0 zy84RY&ia4?5sRDhm|S`>xgc9E{D?8cM;-QXAnI_LUJiG@9J?*-J)N5| zj`RuI@JBmL{#dtJc!p57ib-wAI=UAb!_Q0Ob7RS}(P*tC#&=rTxL~%sLeaUW?dkNq zUD4ifiGi>P6rrqOwVUC5L~TTC)`_a8-fbu$76v%?W5YkZucDDCB!!B|xiiiR;hO^A zbF`fYAwZ_uvVf7QuMY+KR}`D-0kbYuR;*9Iw}pHV$jc87E~pNrS0M+5cuWYURpdnW zsD6*fA5_F>KutvhLck?jjea;QTh*v)7Dd@_v;qjj7=)(|R%STu?b5aTkIKn_%VU=U zN=yy=RlD8g@h9b=UzB8jK(dR`%;`*2lQr)UEP3jbhkbPRa|gW2t*34Pmg@~N2|9rAz>ubOjJ@I723if$NMn1gV{mRCXP){ADcKeSDC|G_{XDXXHR{=s~q_3 z4QC&w1!8D1uTb6nunw(EJG=zBY)0!5O2BVjt-)Pos=;sQ&p{DtPoc__Z~oH}s=Sdu zons%Io7hUi$C7IH)E0zdCWYYVyDP*zeD=_J6^^0SDk zyYOq`4~5``m*F9oqMYa{McOI(J@UNlPq{oESGvFdTv_}65-+Pizvdr-nO_HI=c*MC zFF!nkGgX=}Jv9(8U|*QX^!`s?Q#$0Jb`;3YhgQaBW^Z12iW50I3EzY~<0m zw5U{97gO!bIQs@widMmv1&5=4yFZi}$p-zHB(oz){zVP=L)noG=1YHcUcyu-!;g>e zSXAFHxuC-HIi*ddf+;IvMKc)y+*vVWh8FOZT0D@p{?ZD}v&CQb(B1qpJErf863v4W z@wjikiGJ`sNTjuTn7gcjZsM#aAw&Es|%g!(x)BRHP1ec`A;3e2gTBy#B!uePV z3BtUO`UwRr_;BV zLp?qJWBmGKv%@jPVo_qlTaR8}uLIRR8!H%zP+O4B0w9T4r}d>*Uw5-g0di3xX3!r? zTUwV9_(aPx{)i+bw?EOJPM6F@Ag;}29^5*XpU%W6oB7z*2Xd-Ckq}i;^ef>YoE4<; z5*&)HvJwc#(pjaHDykm#rBF|%lW5+5UZ>Y+g&8 z_?^K>M|U7>nJuN17V-gnyY_z*IK0I^!WHE!+5fd;=NI0}0RUq4q5}ZYp<}~&IZ6wm z!(p7m<*F7$!{uShcn$)>@kQR~K!oSkk*9P5|qg%wF)j3K2&$P1&<+^%sJ#)AzptMgV%>O z)IhiIWz%vl>`K;dcsHCS;GDwlbwzre$=Z!sZ1%MF1mT3S_*YC^4j#cAaU5JaML1^Q z#Rits4dI*?sdmIbSRy8m1kL?3uZj2k#R!)X?? zsY1ej98BfYiXUo)fGfR^*^T4Tj7yHGifRNV_pDJ>LSfmJjgA}d-xZpkR<{NGQGZyl zl0$EP+>WWih~ch!1W$`4PEkv7OUt@jy-K~JY4Jt~|9}2g2i(Bk$vRbE0`XBU{x8rqSAl?D>{1!U3-vcLtISwF+ zDqbYRyaV%Ij^W<;p%;-U{}KWptzz*4gUN#AwP%x} z^pdP(wLOpm?b(nv1(9$6d}!3@q4NhrY|GiR3t1tUv?`LOWuJay;p`hPs&8o8ygDk$ zip;_XL)xyhFTVjlq9vLP;2KkNgfJYZ_ zN>9uTV+s8sj?F*iuYV_P4V$lUj&8dNxvKM}h zi_a`Pg>UdN398|;XIH6cd=1p9A5)La?ovj^LU)I>2Nn=Hn^m7&KtWK4OXE!>odomd z&?O7l0B^n)a||E?Chbf<{#atC+8A3Ww7<^Y)&1o!v*ga#wT^1!eAQ-IKMv{MWN+#9 z0@vOW&%s}>{_b%d#}&$GlpY45or%XDPcDB}KjQo=d+wzC_H~av-}q3#pnRwr%U@qM zjv?dJBdB%62bl3t&>TDwm!LWJ162Sa4)e*!A5YGoXY)G50VOe|T&CB*tNZaUvE;kz z%T={+Lq12T3LcE=`ezhSn#GbW-MI0Ar7DI23dW8OysP_5kK-9?rI3AsNCkV}0L!2E96Lq)1SPYa!&Pnvt|8rEI>KX+Y2Q;P`h*E6VVvFx$fLkVVhAjUVZI#C?|L}il##^RNh-x zF5VZr`aCF#1)D~*7#pkhk4E#-Y3hoPqxN>b&R%M?n>UoJ+81GgL&}AMkEZB)Ghn0H zXslH2_l?i0Gfyu)_TL*H+Gu;EHiOJ5d<{C65Jp0c1$Gl36E6@bu!U3z5^HCjm?BuJ zJTr4}X6BsiNh366C>9N+J<{+NVP;bJ+RULDytO}0^^6UFWyE9}`O5HEPs)8o@}7H= zSJd-P20k-lT=Uo-EZ_C6hGes+nTaqW*>iO`k=lzDygtazk-{-eImdxO7}xe}U=wFi z46awvaVFf{rxbpB@XAHtKCO1TTP_AT0rjuJQU*&7$_6k4ACw?uJLJ!t8M5xkZrhgK zVI5jLGUu%0v5}G3xHY$U^z9s8Y<~02%5{mvwD0E4SI&8Hbe;E>&Hdx@P)Em*Jl?1X5iMOcC2|6-@C5qN(iseej2c%Sct9R+%GJmgA9GjaLHdN{&400VF&KL7h#3> zjvEp3ZXGq6#go+&W@GgP``yAqY%I2*Uor-zl@w$5@7Yt-zQHPNhuJJEYA6=-_!ad+ z^zHvr?PohNW^Tclabo>|)d{*JT|>F(t8O91WDFuGA32JzvyTe_T|Bl{zZQx;EjKnk zKQ@*RMx(h{%wHM~dXh0fnwMCU*`<9!NXIHg7R;2(nMyhxf+y`Qbou;vC6=TA_^~1* zgv=fi!{Olegc^{g?UhGEnM@@^_7M8${i8nGliQ){#v80oCiFTlJ``n1t_7s64kltj zHW7#+(^Yzh{u+K5FX04||7m;p=({_R*l@Np-1(8t&hW!wu1EPN)XRTzEd@n`GH`{;uKF$@N10$BfAGPx;dCZ63kdK`h*iSrgci#CzYU#0 zR8hvxvdXK5y%>x06lV zF&7YYgzj0+v9dWRFDe3x0x!qog&KjxLyn!zV7 zuWHN@mZo=4l&&vs2Ir5UWd7Fy384CCQ6S7h)z1IcF%BM11KR6Dl@+K$_+Ov?kJ$DW zVmV<(64Fo%2Lo~pacD+K4!Kg&_`;Z+c7-I#h+sE+R1OBzgp!tuLVodTLaQ)JQplB- z$4`t)DOX6QtHl^y98(a%U1V=MR=Yd+X=d+|+X5Y33X%;JSRR-mzOIh8fHP`GK%Y@^ zgxsqg;|rT>*E3=1dPkw)Sh`$bpwWS+I>zroRn@Kilt+|2b0`)9wrma-WgrGVHF?)$ zNeh)Gk0ay)hQB{5Z-%q|;8^*OaF*;EOT3H3GnFjA3yh5f&IGoF6jxp(z3BDU-IbYx zAtWI@)vd)2$l?^e z28}90fUrUXa0#Bw-5csNWm#9h!wxhqnMr^1DjRENOzA`1yi%Z%HjJ zR6hq!pF6-#snsRT;jk>`i4oslmnmn=IdA+{uvT6@JUHGhh~OK0i-|) zfd@eYftAPyWPeNF8gOaQKVUJ6M{wTTfhgKOTn5xm!6IKbuxH>p`I>9^!HnZ-?H{+M zo4eJ#Amj&H)7yl_Z|Z7WdaJ-L3|!}2w@$vUw5NZ@@!$U~UEjZ_ur`=#$!rybtr`E| z+Jaj9(vngOoYtECh7$J z{Of16FS9FQTd4N`8s4-D4=lbaUey1&X|L*ZgD}{>Dn@s8SzZBrTE}1J(A+wE_!gkt z3)vx^Kdz^R&?uIV#FZ&AAvZmkg3A-4J^nE4)|V&b?5VkYGSCkF3KrO0OwCxIJg6bS zE$V;b36{~GV?Q^W)v{_d#>_)!%4bd*%~>^;j|HDB9gGGvuv6^i1KW)uWE_)>31jYw z${9X4>vRx**a6>DtQ4@S!4gf=a&ISO5)fm;{9qygG#{Y^L-PvZR|j?*V1?2XPY?}k z=fTpn_9zHB&(4`8Bd0`rp?s!%Fh7o1MB~iKax}mm4nz-DN^@Hfp*Ui!67%)SnKCBW z+<0yp^#Wbhn?Dw2gdKHKx_V;hoj}Besspqe zu%{34vaF-oA-k;W`pizVY1U>j^-b7X3|8$Y);mA*ovrDuUl8 z-ymB`2*k2Lf#zU_KZNwcb3L+T$!Bub4tw1Hw#sqrF;NIg`;~pNSq!o5Z>v-!Go;Wr zPhwQ6sC$ZnhW?mkE}ILI*dnNSb#y$7t||miiSK<~-bmhrGXtb~rW5R+`o@&7jjai7 z+}OL>8?mnL+^GF%c;E2wzGM5YxMJVeuGlx+n_1)N8s2vW`>#kuv*1LBDNv^G$1s%o2;YQE82+i@aB-wR{Pl1#Y)zJgaDRAPId}-)GD$PO)axLc zvF;~HcGEL6p!Y!Efw+Lifs@JM5=^-BL|Kj zz~<|GA1?3kq(y$o7g8lkn%%Jk|@(MQyB`T?`hiJIRtK7Q}$=!x<1Jp@^K*MrBW zrjEZjb^O7*YF}`a&uIHH`Q&DL8C)2|UNw%-s^P?*jzN#N zL~LG@1$bF`;AMRR>w70gZLw*nX`ExNrZG?fw%3(cI)J$ZYzzTn0_(EC)ecKLh6z{! z1No)^MT^_f!T?r*#|xHw{@dbF!59B(&uDXx89*Gd)`Y3~!~QmNkA3sb;>I+)S^Htu z78tl{ywA2#$`#{=(y?BP%V=rwip(oBt6w;4X;;01CD@_-g{7^-Yp`LH8!#SoP32!{ zO_5ZHhWA_luBF-H zm1whi@#qI4bUJnXKIvt!w!wR|PT;0k+Qwzq=Y{-af%hJAYUoL&x3PTyV)kfvVQW5n z_H1Kjls|6sXy?IsdYJ5K%MKkqI`k201Cld7i2ialdX9slRx$r%3%(^r7Rjy5nA72C z#Fu%pTM}gAqRLd5`N%ew=-aCOXLxmbLpmMyIPEO3<9|jX5B}|g5z!G_-QI4F4sIHZ zM$61_bz>!ZNA!Tb9bwY`PC_xkJK``+tY{R*=?z0tw0uE9+u6u*%!tai)kD!`|S zhyj!^mV6i*3XoHDGA|-&2N41(x$}efe6X|ggPTKUPT>D+q~`#U(PCCNTy@ok4U>Y$ zs}rY>{|%_4KSK@C`U2NcdM5fCv@sSicxi^5@Mf~d)M6lrD@NWa9<@YV06vRBBwp6L z^K+q1{tsP!{S}k{c-87%k97IVgd(CDW*!KR( z?@z=M+855y!g+=+K63`gC1l>h8c8_Z@cE#5SeKg!si3wNHo3thQbYl9>0lH=io2F3 zxQ{XeI;(ykhs(hz{IjD$WcAv)^XofzvY?)pf)YUBGa3zi9X{28=-~=G2siFBJgm#w z(Q^5BmHPfmmLlTT$!P*MbaZ2Qnd)*X`G)d|KHmpnlBOBZQxlXpWG_jQ?6p)mH=9qD z$|+>{Ev0}vFq=cFv1D#*uKZedWMs$aXn=&ua*EC4nj3oQn%*1en(o{UxxrLwFgM$m z8oYI6$Ht92MsDrkBB)N|5>6Dbvl(#03JpRfK{n$YWCr>m+KN7a8=()vJA2t(Wx4bM zd>UYqBv>x^I+oJ1Dwps{#pGN{Ql+x2N@*OkvC_F}B7k|s&qwbj1u4WEeTTLpo^FXA zj&8UzZWY+vLL}QrQ+SamobN^Yiclk>RUTvsGH9vMCCDX-e@U0*(nTm&r>kUDcif4G z#-NUKqd*FQH0Y-4LBeJWHK!RlXLX)$DeW=Z6L|)FjY*$h?tfVchhy0-SwYs$<4|E= z$P6Q;b5gBT(sYneE5d=bVgEZN)&r-CFjCcC=kNR(OKw;bY3q=j?a5^2zf(h*aC?U= zw|93}`&*5+IM=3DX`|e=olu=#g0}p!jMQdMT`;KS8MI2v$usv?=^HZZ1U3uP+P`$P ztw7*wGfE!ruAk^1A}^~5_scg6n)|A!Q0 zz3#Xd|LmoIT|JH0_di6S4D|onn@tGwxbu$bEyRw~++BAcFi^F-5abOsrBDE3VnpUh z7>A)4L-^F0`dlnLO6X^!3^pS6AlN%VHl>XV{Fukc#NbI;psUi_kc(7P`A!HUslH?Bh`TDm9cZAf;AvjSKq%%2|cM{x_ewXjDX z%|50be;L4DBAm{wF6+x|-yM(rR5F;;-Rhn5#QUVx)Pn?15duU!_X<#JqU-Fx1&4W#Xus+z~4WLPBaxs2C0&?+GWOs|N;C zBp!pzZo`!Vg z;_@;4Wcr*1A4O?<8Tu~ijpBXO{irw4=c%U-A7U>&8UU)O3$F2a9b}$EhqPZl_85Cn zi?Xz<=pX9Wp3g4e5BH}&ra!}0_0gzi5qDz@^Zw;DQK~w42J0)W2@XhjPz1t^t|WUS z`^KS1wYjI*fj~mcX0@}&#tx0MyYXaUx<8cAj%C@4;~;=}=KKMijm?~eUjvTjvLHYJ zubcv}{8_X}1?}BeW@HTk&w;g_G{9(td>SBfXq$o$fa+LRtI8on3B}=PRubwkmgo)3@@2e|vi6 zXML18{)CUEnys~pS9EbP$-orjHY5%e!xPFD;Ln3BxhOs+NKB8!vn^$3ZODVDy%+@& z5hh6wvO+|oiW~^ap6HRYrxuSFe-AVY1lmeJD&v2?Z**Td1dUS~nrHkqc06-tK|gMALfU!sr& zFd~;OV?z;n!<`BXp%sdHcj)&hDYe|^I=2%2E0nh--Eqm{)|b@`Bx|mpVThE%l30LN z1DZ)P4RC&t{2aoZheaF=mb1RN6DPQ<7NilZS!^#L6P5X&7iWv*c~9a#7+J+nKXM<8 ztzs;r?U^h;68vUtC>9%lp_Vi zwD{sB$S>#i)={tBIjtAqXVwpQZWYd6q8J13Xnjvy`|`(^O7SV}(GWw25>b|6th;xi zBnl+sHNZX`Yr4K^N7F4$JJH`rEsxqq8mrziTXb?T)L>7+>2l_QJ2u0HXaHBnn+wMU zaK!M9uKDO1=u%jXBYiwg^5VVRxQuSkUP$EgiBQHGi&--v()9z-)&=t!^dY&iav07V z{?OQK(WsaSCGwDPJ)tcUvQ;2^ZlZ{Cv6xUZVk~A3d8(H_g)>DU< z6&5m!zA11R4$e72&4n*n!e8N;mGsC^UuT@FTugnIXN-2ZgWHX?bBRWF0?OSne5FoM!t^uv_4OE{cdq z^T-sKCjQbcyTobP`a4mYwj*TYIoW9b?${VqqkGcnm-K^N)HU)_v8X*O2V%)6#a_fx zQNMinpdw16r)M}XpzFvD7&l})0ngr9fD)5<94NfK$fj-SG<34lliI`-0A&swU@2?> zdyP06HUl8W@q_z0-s0^36B@-?6R*C)J>kbycTeBqJ()^3g);yW7+&(GG(TO7HodKi z^h{RnRYWT}z`>k@clF59wRi;A^Ir1IB6$kVey-wZFgTi*kC){<9Ti>d*~OFPg@tdQ zIKe&+D8YZ}8d+l=8ZxgLdEesEp2Z{Wr|b&tuNM~H;B)3DK+{^#w1h$rZA6U{;x7v1 zD~3I}!V|wVKji8kSJkn8*T?R^KleaBo85VT4mhdz#WwYrueie8v*|~l{Hpc^wnh8N zs{!o|X8zv&D0B$c-X<|yo=AU zFq_jvV=*HQ4l!z?QWyTV_@d8!4vU7Iwl`P(IA=34x40D5UFp>T@^02s+o|jB^)2Y z($E=<`_yJ5<72X>EB02$4m8zJ5yK}8{S-=L1Bs=;wzybh%(@yC!_HEfy)POlk-it3 zgQZ4o@GIK0zb=>SRl>UNO7qGrK$!`W?xgO^NeqBE(=H{d)EJqc)WKH;N4qJz<#debx>(GCuIe_GX zLE(DgFTmCKp#y0mp&CI1rXCt4Fpfl!pR<4vhaPuXP$XjvHYxU>eXVX5)~?93rP->f zjg0+#;75<%pxN$Nz2ll>b8+^aSErhbY2o8yNX-aZIVcCm$DV$9^cCr2S*RPfrAtz3 za{EkKPEGBAdWU1ww}XZ+!!ia3Aff;RPf(z2p}$T(UgNQK0#~Gpq!_b?#&PJxIG9|mZ_a`Kq9u?R8ki->@wAlRh7U(J5ET97^i;)Xt>IhN7fSR@DQ z_o!+z*#1LrFqmvtUrJqo{|eWgox_@{VHL&*0iOyL3RIHF)!-m;fmjngRdo-RWde*M zta&7F0PQ_kt)ZQGj{L+Ey)8E{o{hxO@$N_LoKfZ!trLZhq}oHR#z+W;3F(Q zy>tST3N1yX*rYvqeIO77wx>b{(FPDrF*oxIAPRN0!#av#PB%ark>Q~s0Da&sxa=3s z4zuTmFPs`?FPhD{kl(*Bc>-wlIU}4tF1#?z?pBY6w9|r13J*a(6|>A(Bi};^?D$}v0uVmfz@#xI=CeU z#TB$z`nIb;XY_5HA20rd3+{*}Gh*p?(R^9V++DUuv%w3mm94>Sl)aLT+RN56VyPHS z{ybVN)qa0ZPn)f5pYG|hmu+9M4d$b(61Fwn(Y62GRUEYS{Q00g+SAt7)73m^`>L(9 zwu{Cf=7Gf+?^PUAVkt7-z*PfCa$2t&z?8aNH-IKtt{dQi^gQ(ZrJ>N4lA5pzc3DkG z!?J*EABt72B+YatDGf;!wrLH8hScd254W$O2x#XvbPR3@vAEmkHMU5JcE<)O;Sk-j zRozkn@`2ZAmsY9rdO6{+dU0~PeSL#5S3o)-GXx1HE0(cd zHE?keSBz>urot%ESX?UI5p~7VUMA%I7IlkyiPB3+b+Pc$1}Rxr`0BXVZAO%Hps9;O z=m={ir~4tVxEg}n18)wcWPunyA!N>nlT*mD67y&Mp0IJ;iX0ll!+iUTsom`9{%P}X zzW()pj-(5=*0{UF(cuzXEMc!rv<0lq)+z1ELVjZH)dk+S^t?(&tcnh_f*~7mcM-FW zY~c7~Z%hbJPB2A#Y!92%{P(gXxVn$QU21Af3kcH-d&c&lNPMko!`k{499b}b;64#| zfo`K)YglRc3aYzxU=3aF5@D5-(<-G->@= zja_KK#DO5LORI%t>OTgWNyXC3_9Xj@0L)9I$J6QY+3{3rEFFl&@`=PZw9^!^&Bo!g zpn2Hc2na|Fv(FD))8Bv1fcF2T$8W&J*rWwGX2tPF$j*gVDQH0O2IChZ_$tg$naTE{ z#~;x=NtEg~2`tjkH$Wc_k7Ovn!Nc;!5nmY0KrEH1h-S%eG=>v%A;?Xs&|Ct7p z0W1$#)CxF7%Nl10O}cf*OZjKg$WIx}z}Tpy#z&7U0eeXfs;Su${5CwZs%W=Dg=rQg z5e~khDr;x5QyKHI6ERtt6|#wNT2WHLfMS&F_%&5h1b=BZ1Yc&qV78`0F1sK0z08)3 z6tF6}sGNp_lA-BQ_%}ZS|7OZ~mIviPT!4`SjYrK30|&Hpe7lIpfL|B8<6=Yzdt^;l z*P79HZ_0FaW$3f%-J^8oFtQLueLk1V=K~HJn@sjV$`w(QqjC;h6fqF?Ryf6zOq)}inDJo0bod;fy5;pYDF z&>R3bvJ>n_#00l&3qpnQtw5QKz-hU8d}psEi%_;q-16XXh7DzggFj`v9#L;mAIXjc z*nNTF$qDPxBi4!C6H+QIO&k%Tsc)yk!aE{2-4rR_w|6hL#fWxg=QqFE$sWvZ*pU51 z?(?6|@p^9Qh`URa)AR(2tczp zE|2aQk&&MVQGI$!GOP9?>`vKmcpqR>50D}106PJNBj7zo0L~Hc{2*+kv&Jwx9L+@W zK7U|#fyYPa@{rz-XwLS5<7>kF(HX}Sij)CW6`4MLK-;Igc9bal83HVH#}f*#0CK=f zgSQU64i}WD|9opSdiOh?(Z|1j?*RAMKo^9|jX>QDVm_s*MMs6OX9iD84mtvQYA56xNJXP#SoZ0TNc?E=oZbe6e?ViB zG#V?vzhXf%S;+Fc0=ob7U znj3tJ*Dwuj{XCEmqQK3P!oWmm+@l*JEk@BVx)eKdz6DgjAG1Tq6$*PqtAa0qkS7Gx zEtU$pM0mKm!Uz)cD^}4H#zjI9U(^5+#sObJwEL6g6|VrWjn;im< z5MgCD+2nw=MRa~Zv>*|(h5iRe48PjV2H40%yUmGi!uyKeex%b_1wAv_>T2`kqA?)O z4Lh}1Cn_z9b)uJ@`s~VmKCf1=;X+ zA+g*f+aC1W6B5PLNeSd3Z~VsoZQ{KXcyG{ImRBZ|gg!Gv+pADyxyrJqK|@sF9URx?Whj?Jt+zx;TCP9r#q$#Yf(orH2LvZJCo zXvIqahT8$r7=jUuHV5=G{70gn>_2+Dkd3iEHz)VLcUMbLLtCPNotpScQt3*^5JbtN zl^ajDaS2s>ynfec9_6AZ7e0sZs($13%32`b{|#nW!mdDsf*TVHp4g}ROX$xgU&suU zxEanf@^ko#%W|>P@XkIz3yW(Bu9fgBICoTXrPY+0b^%uX*s+u>Eu>Nll02KH!(%&l z9>W(NCwVjGw0DD#ZYsn{J8ZIasVb9;OjfmD-JJa-D`@}gli5$A`=ai2Urj(TB1p;W z11n}B9EUJzm?%VW@AO|MS@M(JPkt@Q?oX}y>uZH0dw;xZ^!~)yu3ck^`$u>E828Y1 zRWs045zZGRX^ab9n^Dzc=)rlgRb%06XW;yB?*f0G{y2nBdKCFS$>WhSrEJWPE`a<_ z2e$0lyXBjSguj8GP*XP(_R{)1dZ>PuOOlrITYSYFa?b-9A_l^E#a%}HL z;*W_QJwAl!iN6&+7E};H7XSe+M~Gez5FObv;I5+nCz(B{{puO@oBe`EaokJ<+-z66 z)$SBr0Fi9c)veu+8hu~(eXPjqQDGr*>XmQtrIJq-5lyE3`l-~Ns56$=zI}i8 z{$1l$S|`w6ccSh(;MZ{3y0dun+N<4ndA)`FMqY9K%o@~wgGzI*P-(K=V5Vvt9brA% z-~VOLeZ0++f4_!WsG z@Y9?I_LU+OW93+=6f;ln*&VC6GWJ*|Wes_xQSF(4z&t7K$1vc{CC%(pquUDG)~b%p zhsW05Tz>BluUy}jTX$7C?4F#vwue2~eTp5*3_!Nxa}{T5pfYD+%OmN#Iv!J&!uz?lDd~a3h8LU_~XL1b?q$V(MV^xsKSUcPNkDnYBq8l5yfX2RaS81T1`?K6K-;{{c70H9*P#Hl>y~e$U9}^bNwn*p zS!&n(cC_pGVcxDQjtBkOYv7ARoem3lFZ4B>RCKw5FU?F2W-4@n+KA=tkB7|Yjrp5s zJbZA|+PU(3U!17$@zCj>ym>k!JeWGAeYmH;3w1_qJ&krdNFKE`Z({;ObL;appXIe* zVZxsl4(@yDf$Rf#zqD*lq_)0n^TzeN(zMtYxp-Rq!M^F*#5i-QiE(=GPpeboPeCu$ zr@l_hO;xW&vJsOt9aYiBxqAa1&hF=1nmrw~IZ z+wN&kba)HTb;0Iu{lJZu7hrNbK$(`;1x>VWoy3h3pP z=s+IRK7wX~(u>RYK;nw`si4D*VT8#8xu~3d1us(2)ySBeWT{&wh>RKF>rEq11J>ua zMFyv1HQMkYw2TG*h+(t{TuZ2WVUhZbo4 z*}e!pa(T9nb84D$;HA>)(=!2}?Ve}^>CtX%S0{SLL`RF$Wp{|1vJ+~12NF8f)w>%J z-g^96CkL*r0lcXwu@CVoU_LLCwF5}cpa5DYP_PpOq%H|0^!i1Vlt2hEPuJEUs0gpA z5mt!TlOAhp;L$5hl=&B~@Zjs0h5i#`j|L(aG%)F*MV2ub8fI4Qx7*lm?c>7CaD6Z@ zyttnk8sc>^i?-hnj+Jn{C<=sYCcs74r7nawBiH9qqyr`#-8pPAR7D7G&z~-CBZ-Iu z9Y88Sn7<=`@H|hRIW>|Bd6J5^#r=;y!gX`Du zP1ma32Y0V(>$+*@_9)-9@e}OoH|FN>ran%3(MI~qB+vX|C4h^bF3MQKG$!9hIRI~$ zBh>(Q**~B(_(yL$xm$A`^9b7GIJ~shp&Xcyz?bLAV-@udkSj{uisdH@uOfLHthX6&B}O(dhSSScBfCSrd2f6uIdi6?!XS)9R|XHWhR5wDw%CAyGOB`YzFvjnDsM3$qiWa8$Iw}HsU-p z8jJ?fBzYCljT1%_FkWqd4WDCfxh-TjSPb}I(PTFIfE4Kp!@=FcTn@>~%y#eX#oW}I zb<8axge%Uj*n8XiMq1&ZA&+ZDUwNd)0%=26T>fNDrq{Mi*r z@kEn~3n3OrD?XMoLt_H9xCmr-k7BgT!3jDg0dvD+xB6uxB_AJ4;Y?7!MnnpBd}+AK zY=@o6ssyKZPK^}Llq3T7l}cxdBUAG;L61m7jn8BKXy1D|%#W$wj;3fCK1S4Lmlm^v^IwI%N%dZX78i<5H*W@5AvmO=RD8|a=r)y~k^Z4iGz zf%epx)#t}!=T(lp-Ni^F7isTYe!=eDRUs)7@>?2tP=)(acEaK$< zS_NB#$XXCV)8bRTqGWMfGSeL{i_v7W`z-M5wX1kgcBivhG#f2`pRvW&F`cov@b5~y zBH3D9M!TY%6g6WkN18;m zRsoDRMphbw$78`jq^1Sii=T)MMp~hGjHZ}8SapkHf_gpH1wj?=X>b5AcOj32xAzQz zOxw}rWDzepkaM|QavsnRF1sYy?Xf_P36P>L8;+7snKMPx@Sfs(B4uLR02wlH(B z6sTCWT{AQ6QBm^bJPupi^i(`@b2Py^+B!C=Z5@TS={Ek8w7zf_bG&^du ztX^%g*(`r@r>(igawj`xu`y}(!oN6NqRZIo?6@uMt?dEuww-6};|Xx7G1+C^vZr`3V7+0E-hC6^@Z4P#|Wn6Uz{HD323+tGnZ{t-At8 zCju`LWO?kVQ0hdPmi_Wj@i;S<2#|5+%+9u>R|meI3bFm6)caDZ_P@*XADAz7v8kEc zXYi)B!>1E{`HNWnYj#ioLt%}Cde29O2dFLkNTZ1vA&d1RZiyHW*RGS$Svz3%fm`?Y zYllkjPFNy-Hb=3DLf}VoyXF14_kZv3)le|^L?X-y9tx^D;fuE(IB;ue;3u0~C^;ym zeqdfa*Zw_b*P{4+@qG#UutI}F>UvxBjovzNpkEt$8}tqQKIHNGTZj7lAK-lL&|zf2 zXJEh@Y8A6sLtSK0e4^)5K1nwwjV zrhwUMaLba?5@nIrkV*8LCD%tk`H7>gZcnpGFniqdduMOlx3e?2$<*o){EmGe+B(&t zv>L?T%1wW}bxqj1(dv-{8~$oThp*M>2~0k5b*sx@7#5wP>El+HN4?N`mI!eZ4nWZD(16Vr0HIN{fUS78AzdiqPz2Z)b=Q2B00fRX;Zg!()Sd_= z5X4ygCZXaaJf46(CMEsJ3{HJKyKOWU8{Iayop#%^jX2EgFFjIo-rwHl@dkRX%ceXn zcEEsCzdaP&wC(1b=-+O-dE2J{!`iz5wppHM!+u`Nk}S)zPL^a@mS3G^S&$Y@GkN*T=Uh1lPN=F#W@K&g7svsp3Jzkqnge@5%HwW}XO0}n z#JgX3!JQ1>9gc^#Z9{crr}Qeg1)5nHr5g5qv3C`VBv9ikljv@5|3)GlPJ}>WhM##K zJ!ffh4WC5F|vT`fZ|I4 zr(g=SGAMRA0Y#Z~0#C$%z88Rd0P{E%_du*R7H_2q0sS4DXgqmBp->_y300V#SQwF( zCXp`XaQnSZr%`!t#0`A{8k!g`1VhD>a61|WHm2+|nUYDJW7^c$7xeOmpf^gbb+ znHGUy^n;v4)Ky<6D$*a1mG90kR{o|bEXF-tJy6xF$8v=`|p z;r^`K9J7bL(fnSx+QZ(=z~1%7*rWyjKwSCs$oD20$6ke+j|Kz$KsM{IxA- z4kJ$&5LaluDcTGJ;A6&~?kn$_U}p|gLHi{O^XSo|*{nbNU_5@%5B2OQI3^>}Vl*1U zo6;G)H4K>h{mK0ufy_Vtg%IfQBbg%A*42jF4>|%JxCPFTm$0H@1LoC6=sDHIiU6i{ zgn^Kxo3d76qQFO3H9ihR?Xf2c(t(~Hwq?UOdrVsQyH74_cyvYc6U{5wmvIPwoEjYG z2mCk)ZTnPw9l}senYa_mBn*E-YGS{Ve)WZJ$Fr+_f8*_c_EX#XdRM>r;$PEh1A2rsKSJSA(M>!Gcd+@Z94*JHaZ z7KKg!vQc*sHN2D)sMuo@)QWv}VKn{4TyrSYocm%r*w!YEEC0-3tvhJdFdHix?RMk0 zn9vCjG%z9Oe}%sJcOdSuVw>cqn&F+GKnTE8Btr+YR`Pge6Q@5#L=!vKX}jMRf6Zw0 z+oiYd=F_6qsM!~acg2Fy4F|@f!g7<%X8N0|b!un*^LC$5|4onf8s<3YZEyD;w5)Dh zdF!n!+W@hi_mLB`V2h0DyKvX2!f1nY?ZUK;dh}I09QK&Ca0s0pEEHgQq%u^<()AaQ-XpHAlq&p|BI+Dj!*hb*KqXW?9J$zyRJ6=-XY>630d$Y~if$xtD>?t@yZi*XTM0@T zRI?N!X6e3k6kKi^vqO)XbNQrb(d)EkGuW{6C>vr^>KzJ&L$4GgVsVn~J#XzXb zAAP^DwNTi)dvme4i4_XHLk~Uu&~R`5!P$MgyEA5eCOz5}3L!Bjw?!y)Pd#*RclW&y zO?4A8p|q|Nmc|YbL>M@+Tm>@v=PWZ&*U2W@oF#%wLYK;HnR{n0t!VDcb1%*~Lr9Me zPeYB$BT^tgvB&WY&L$X>{0YHG{6*iv(=+mau!%5nH-*0_KS{5JmxXa-A^Exdcj@EO z)5G$II4#osm;$(um!SzzB%L!%5Q3C6926!6=oRX{C*f|diV`;ma!Sb>L}^g+Y!R47 zMN@d#Y2F_93Mee1)5i)zQR*+Es%9}3du`h`vnZNDy>pk#?40TB>{2)AT!zk>>#m!b zX{sMLI}dSRIISg1F*p7Md9j2nAT(>DJ<6M>Rv?Zw73B(umCBz%xkBb077;F$OcR^n zjKb`fq9cr4D!Xw))Mm4L!ggaiJo<`wR7;ds;qZpHL9*k@_BSN0a^V0dR3B#2E?scMAIdS?R{-+|AlmI~EaK*xL0xi!M;EV?N zV{SwUj%+r1gR}9*fwjFid`jIK3D&llIs(!c7rB=x-Gb4$_TR*|Hl$jyv$M~!Cp2+4 zN;>@Hy%A)M?7_4$7sQD6S&b&>e%$C#=-FGe2N$8F$$QWQ`f37uq88ge{64^K`5+vH zRHau(*ip)WMQ!>C>Fn9FNMC)A?_1^n0c*$H|CFPuv>0QXAh+e*A?^l96Q$-Sr>WF^ z=~!-C&gRYJzzdzb;Fv%nRs)LYLSAlZ@L+ML1->*&JQSLvBB-MyY!9!&4hC(T*KP(~ z8<$cavAHw3YzEY9VNkQtd6EuMmf4Iw?n0?$rkHq=AX0N8KZ7D!2suLPIeFh38F>$f z9vR{LRrz=_^6J7PVl6IrM+yf8u5j6q#fP@zjb` z`0f5=(wI#i+T~1c@(vH1jRQvI=#X*q?#(}p9ezIE^Esaw263@&Wf?4k(Z7pHwy({ z&iA{NX#E|YQ*G|w{mv8F`*EahP@l=iuR;c+lcTWsageleVM9om<{K?~E>7^tdbS=1 z-YlJ+Z}6?7kz$PL-mo79^yB`Ir>L=Vqtg9ok{XV9+7LviG5%rC3**OAf9ZK0-<-VM zX`MQn`uOF~iy!C1oY!U~=U?fxdU4Vp;FLdrHt~Ts=a+VUfXq?%2OmV-5u6wHl@d-< z$9XQ~jCkrxfJ}KvB!a9Pt{v9{IU)BXW*laT3mXbmNJd~-aM--T;<;&rg<1HlbJ`z2 zJ(;C!d|^0P3`x%bgQ>&UKy9QWa6eT#js@dHjXs%`&wU5h$+hTZ$`KSXYS4wUMUQGw z4E8*6nvhNmsy04DM?fI}81d|{aeNl0V;@H2(;&dlvKM761MA@->rko1p6N-P>;K*P zVo68<;eWOB#i`)u>gS6Ugw7XZX^unANuF(nG)GKhSOf4#08$Fq9BGN<#%RJbeJn%g z*D>Jx7F3AN@A?s&|* zQ}394W#>*%DWMDaSYC<#{tUDv(j|ZyrzwO}B;Pu6f00q?qIHFk2}m7nH@E_9bL=Ov zXDr~=7aZP0(o0MsonxU^1RON!Bzr3B?y1jF290nAO1R?^@)*|s)WxK&#(g_B-}c`M#CXd z+@D^TiS|YO-kcYOHr+OiF(jq)2(h?=wGV9X*NPmRBn+#&3 z8B#DU}m|>vgf&u9Hr)Qce{_`QT~DbyGdAM)=SUmjg?^a?a`aZov5K> zb$03v27RZ~%3iiQXA15D-H^vRj^Dypk+3?BH{1mzt_tV>Q1J;|m-Se!F%nE*X2Gzd zr5eTWFdR5Xiyx+P6`dO30ZO5|Yx(UgV)Im1{=Rj2;R~y8T{qa$%KS~n|LsVBt%-f= zV{2CXtTvs$t`O>WEK65acQ*GeF*a?;u7FcZkFhW3XsWq>F8A(o?0u^c>m5WT+jYo3 z+E}p}qq6LRhhk1v1){Og;4loxSfU6l1_C*_(Us8W%rt^&imI?|2I3TClUbo-*k@XW zM6w;`Nj8%RcZ4g|HDTB0G}0+)FN)xrJ&uTLBkh1b_}!34oMNeJD7xg{r?T+a zYY{3{1(eiBDf(N8-|Za?YO@h(i(iOIXWTiP-)N>FpK~z0ZQGGh(3tcGb#}X7AKB4R zuUw*VvIG9vm)Un3ZGjEZ*8IaMw|8voc0+6DBN@?<(bfmBb@4s9%nM zwXSPpHaF3QXgn(Sj%LsFWV1c8ZYjqglHB$Tl>DDmDo3e;tq;vRfR=UWAW&<-bf&l9 zSx_xwF`zxM`J($&}Iu zunmNTn}mvFl0$%fW1X`7)YeD7woYkY6b#*b$0ID-P_tyk(&K}-BF8RMT>9j7x4yOR z(XFTA3buLOqmg_jxDID!KlH<{Tt>uGF^924y7huJgRYvKMQBoD)KC$7T*LrY1m1JB zf5cKy2{M_%Oy=EztvgSUL6cwSi1dz95^f|GVlUHYgBj`A&5q`O`7G+z&upK#B@~NL z*`U$hMGkqtlCNQzYZ@4OldHTZ@(q)F#pF#>HgBl>5fw5e6(uX9=MIe=%HmFA^fZ3h z8F~~Bg1qr(HqTwzZ+$C!7vjQ;Y@Uw0?vj3X7k=0xaMPMG%*UzmlminJsc_?TJc zI~gx@mrX7bkM^5{he#AiYYJRN{&au;-huc4p72wC#dHI&54^$NCSuIT2lmDH4LpvQ zLd}5uvv(l5M*ew#zwy_iRr<1397uiUGpPa5%5JfWI2FV%%K0D^BO<#%-c_OZP-UZ% z`-KNG%72)UFvf9_DF2j5ky-+v1GEDa;6N>?qlYGtj|fu8gNI;)(u>2}l3lrQL^>P} z<+_sWF=&=-$HNa#J3Nhz9>?_DEB2zv(Jj5zx-?Q(7s-W~v)f^kzCAsSS~Q@zgiXPm)Fp8+ZI@ZFm-tANEQTiQ*K5! z(N(f2)F+opK`d2Vk}k7j_ML(F4D!9~!I_|a#va_ARce%ba0i!YvG}P@p=g%ANz#l5 z8pj(O$DgpbwAh)ZZBdox^OQODd1dvYHbOv>%_U;p{1$XK19T$FpfAtCxePV1F5x%f z&k0TeB@KY^sS^Ug)amedPVlpTTHMujOV^6U2$RPU9^b93s#Vog2ZuI}7xn%dZd>dZ zE%miiA@(av*Q#aBst6vPN~Z7nNEdEd3au~p^r)1^2Dc}+>H2`aIDXqu043fuHJ=Kx z=WMFxWvjqC>0EYg7s-4675Ibbic;(hIvv9>qTm7DRW8PUAsuH!^8G$q)hjE8hEB*g z=~WuDbk3i}Ij@*MhOew(;5lFj2*de2SmJkrEB?)Q&e6}9)ct1Ze=ly|N*aFYo^rAK z%8j$3`(}?Jdw+Pi)H;LvirSXP0?l|n76?0KCI2#V+~E`eO-m~yNH3|7Snr^0dZ3Y_ zx-A@W+so>#^#6v*e3{I8kyYKA2cJ)mgdI#g2g{+@#hBiI0psrX*gm|J2o%2 zYEh%8>C@EfjCxQL*TYh?_&R#eAPdPpid>I}LF;d|;@|@%|0Ky;-A@=wK4yLc|s&zLl3p88m)Pa`e zHGgl6+b!#?OIU-$Xl2ZzP#LVDJ6qB%xUtCx93E?fc_qr*Ej9kArmn_jxl561S-wQ2 zP>Cs%G>!Uy*49YGivJZ@@BI$?uNL$vtwS=WTogKe4*L8W=$jwG=pfJ^FlJbDNJwu2=e&aC!dK=|k3|Q0kIN zol;RqNBj=6{xs$odQ*?$;ox)Bqgp3w$U1`I^ix1$gbib0DmqPIBm+kqlf zYTz$bNb0aoA!HSr?*nWB>_I`$X#t}QMRXQaRjKrOL+~FxO2l>e%f-!SY3kTcF%}cq6Yf~-eQ4a>(df(4 z$y|I>EI&0kI3=BA{l|_S6W*Gdih5_)d1EoJ@R&PxItCYYF(#b^{h-BS1C_+_SxsmP zrZas0CEZ}5Y-F*0NcpS_<)cc2e1|yzTZ@qQoY3R@a`Nos()+Q{U@#_(7mHB%nRf5) z-L#Sxg@fbc3+X(*iW!QV^nt6X-e7=2a_yekW3F-6J2NwTU~(;x*$O*&p^Zs0!`cR8 z`+wW7v@!BNC9?Oqo$^kAG!G$B^i5Nyu zcT9S!G%}8bc7}!C<9x2mn0>;^5K^YBbGV?k8emAepzZQd* z(&ueb>x6&Yxl^MR^d^HvXShXMbB$In{f))l+`yI@YOb-c4v}?^bgHfC^~PF@!K4=` z#KwKya!z11dKOwS#pl7pPT_gfV6b8XfD>yDm9&(-!88T`?%n=^^a1OVZ0zl{Xp_Lg zCE}$`WD`aIr}r>_=jclI$rY(@lJ7$TA%$r9{U+k!^-dWwC*}g+#t=MK5?aX znPVg~I+|f`UAA#*+lTq}By_?BZ39<~D+WgiuH04Ho(ks+;R0^?aN$eLjac9bxQCq5 zAWN#fn@7zkGdMbWhGOQW?+KbC2sRZI8tL`Xc#v&5AO>H59U{ON8p3`W!G22mX&sP! zh?BrGm0++psI+3e3XUoj)}95=?BFYGF%f$u#^Uo2h2!4Jd%qO(dQW&`Gl#qr z4{mVAXAXKN_D?wCKjd@un>gnt?rlS^59v4X%s`L9szNGz2j_~x*?Om)g?FzK?kxFh(bZ5P}@LW7Y*4F zv-Kl&QF=j+56NrWDd^-z?yusC1NU)r%L?|59APlXCJt0XTKzoiz)UPZghK#h0&_iP z0V={Vlz;Brp`rXCLY^G5*x7r8UXZppE$hh}y*@w0ea-SbCSNmgBmfaKXR)Lb2qr)^ zi=e_L%z3ENR=^g>?Jfh$k$sEWejsF~Xcfgl00Cv;U^?BOPCo`>r=UOY4`qU0B`9y? zyp6H+w9R`6d2zw6fnv}SPO{IX*Q9Yf6KES;>|gHh4=ibI@Qz5|B5jOKGFdY!wIM;4^>1%o&PoIrmt6N1a?83^kv3x1Z8`VheRp7bp?feOLi1}Z}Vfmbyx z9&AG(GT6E#;QcX)TNd4yNUVwjzyq5FYv*kkXSZSnv4Q6bJgD+Gf>#LW2|1I7h8tN2 z}2cTe6t{( zVIsZY@1QTpKl>E=!d*VDiB=bRjVV3;^Zxze?|cW3t-Yd6x7rLdy$<60sv#IP>30I!kxrR;|RcmalqaZlls_F zW8EH|$ynz$j2qnaV&Pw0W|>3Ff)#@E-1(rClH2k^{l!m8?S)?#7PX%q^OTpag&g8Cgn%o{-rG^_6NuQuZR1lBCSX zWGdEf!17MYEHqsc{L86!zo64aZ8;F$8Iio_Eu_`T$94YW0#Y znpw12fcWz39#^WO0}{^y4&u`=zJ)xw6t~k{)%qyy`kWe&u+Y8X6U?!?N!-W=X+UQ4h8$3jlxcgC`N8fF+Ye zET$ge3R)@J`DUe(mtmMuSm4+JVl&#@w=Jqkr)`lThi(7U`)$s_h%KG=_Rffoj8mg7 zC=^EXBoQ=nmc|I1NUmPJY4z$sn{KAvchxbcm z2k@d^nlI#sX+{5k1xP0+`k(L_2vtBArw|^wV94E#&2r8OW-2=h<%kunbmb^WJC#Li zhs^=ggK5RMdSkL5JLg7COoXdCgrSYd-?KF2Cp1PuE81gfgk*|*ud^wc z+3)C2ipUCg`mrMx%nsCpFtgKs#}kgAMk8v~b~~_0_{;zH6HjQ30w{2~4j{+Z1=?o} z%w=K*CP~5wldwfly`fQd6ekD!;}Pu93BE_mAjV`0xsli}4X!x0Xbzm`unMT&QACb=f<7zKUwa{0ZDT$BPa#_Accs^(Z zaJz%MWGT{yftmyLa2a9;&>1G3C*eZrMLswJNPNI0=U+>tkc@*}4|WR5Jn_AC41i)~ z*yaFsQ?rgX+Xs>AsWU4dWE0b<6B#TzB7=^MIc?V{jpnq*>Gp=w{lX59{fiAqHn3S# znx^V%Zv*~1tAbQ|hKIvcfa?2R=wa5{x-_SOM=L*EkiMIP5UFLSdB+!OEO z==XL6{H+U=pt-<2{5d?hqKbo<7-OCFzw!zK|KT%0`BE;)OxODL53XO|70v4p+XwWA zE$(QZz5bK*87T)8q!W0$+8e4d*ONM+)p6N{`KQs)JXoZLImyTgkLTYWOj^w z>3MitCrk3^58IrP;#P=$#Lnls26O!-AR?@YZy~B$+QR^~gO}Bn!tMY#JfMtL*nwD} z$Rex*_%g-!soh;aWV$@6-9MC{aX_~Kl-T+HtR>1xxiH)StR{yb#?Ot18r^J zJqO2$eZPI;si&SdHkwS0#<3OYba!_;z2e7h#B1M{w$)#Iqw%Tl`WhrvgRe;lJw-Co z+PqLka9zw<;Fpz9?nWq>3q-t%e7~7^^U-FpB%S37qP4OAd~|1}wk#WgAxSQoCyi`7 zv0@QMHCeW}mkKsfQ35zBV0Xzo35vtO%8<7=Y;|mk@^IdW562^e_V4q+Tl#g2Xm`E< zwOM>VcW>!1U z9XT*#%InmJk;)$SOMS=H@!|LWd+}J`^me-+9mD0B*M)#9%#`RaEo zQyJ-9;0f6^7FSA?_nl9p%~d=DsKSK$hP0uV2M2kRmN6A({kAN7%WZopeVi9}J!W<) z3X{@9VYY?+`L9@`&9%gBl}^}PHq&o^bsX28dW&!`-4W0kDZd}bZU+GE`EsMp!^znfb>>Y8bRRc3Fl_P zqA_dy2ty!&POVpJ^={C9Dit`MM!CgF-`Wof^er}LNXw?2A!oF759cobHs8Bt95K}; z!tA7(=;QswtaP>K4UYs-KCvDSdk&9qlrO;4HZMCgy&ctw^rvko+&fKRUt9~)3Cj3n z4R+BodYFQ*hyjs5zKrgE2ADt~17*}ywr+J~(isPvIp7>hNBxcup4`9x$rHc2gKE}Z|M{&$L*jtE#~&3w zQW?jrzYdkEc2@ie_7cqY)MAts#eMIsFm=zW+Cra;n`dBtzPEo(L`#LN})*sr6s#Fz1(x-H8)=CZn9QaKUE``thFl8SC|}r zYfUv%)YTiT)lH5%V6v)ffm0F+du!{=jnFM?YXyaAX*%p{)YMsOP)EJmU~Tq>qlRjq zFSTfS5OoOZ6|VO1uuZ9{3KmiwF)fZO+*cKAa0%AB2CM7$AMIc64_7yJG)HR z8XWxgJuBP|Oku3^)qyT?Eq`8TE5J^IYbNpgkC} z42}0iqkZE;7N+T4AMHJ-&=rDiFzBY;!Gcb)^PCt8=R+Yks*9m+*y&Z_G^a>PhYvNZ ziWz(n_mbig_aeU`)|yA5>elgE8yK@|`I;x|$O?FmZCrc8ehd^$Ea~&m{!$OqEim`W z&<^PV_XMaAk02H*|2aM$$}nwlVDG^AvGKimuB#ka>0bEM=(FE$^b$plnxFd>AAig=8aWp zZHK0tVlMtI6UdJd*|pNs+j(VD|Mt3YygwHWu1gl~jtvB(MXwl*33=zb(Clf}RTLx1 z@9WKx(0H`iy+Jr=G$uk->zu5xcyY70vn@CfyStFMCD4}ZZx7!b5+dE5(d(s?RR#Sm zZ7%ps_?|8E7OJtT*l^8Z5zYB6x&8}+{j&aRDk*?|;O3wNQr;YV6e!&RCJN|gDRwHh zV#WB16)}r(Qw@vU(I(Q1jrDcCb#=EI&CSgpJ)-~Km?v1-T-U0%Jp2(oY{EiuysK-x z7}RXi+r&tpJEGlWWJh$psQR*Ap`AFQdvTquCu}x~Na$aWHy7G(G(ri{1A8Z+LS)>7 zNCDJkgbV5sp;B2>SVY=^OF;T6g6&WfJ#^WH;X$=G8_Yzr@oY2`%zD*>7r*g(IG+yp zhS{~rY+Hvv<5l4so{YbvEz95NkpHEF-q@R86z+xMEU&SfF?ZHOn{MXbNHWdm%ySuE z4O7xKxF zYf={%h*1SH`G5+UxhaZi$#ASwNYp;XLuk5zf*rV{!hro8qHE8wdl5c+4mx2nN%~Hg zMLe~5bu6}e@fzwET32LWfP!K?WMLS59xF0*%l8GIyDjX51U~J_EcV{go#=@;F&sO3 zmW}if=6wd*!EI`H4-W?HlT9YwK>R9!j^Y z2(U_(#!%m^*4ETD)@f_vbQrsFk7XUIj+dtswyWy z0ySBJdee^L4?x>_R+}5hYo7(>KCUJrO49T4wSHEcAIQTxcH0ku_ab=6?w%%=wzzu) zFH3LYx|8iQfVy5&7||j}*i>*xC{n7SN|5G2O9R#_zH(K=59TpJB$|Qqni!Dh(9F1( zr(ReF4iQ#cRaL7{GSoMjY`LeY<@Qggt(s2t?0c+Xll0E*+gq20bai#QhY%KR9d;no zl zhojKBs1vsW9@#mPOsAG5Q|osI@%>4J+PgsB{Tz!-N~giwQH&G{5&lShMt&SQuAtzV zx*=YL4I@3Vz^GM0+hCM`dF7$c9};b(6WbWmXbS4B()Ty9wDfccsoMBCfF&k0 zWXEtnX_saj*w@wZO-W3Q=jiILBUcNN+jVn>cosH!?0AMH2{}^W)3< zn+h5*U2o#&rr4JXdAubbK_!$7q&*`ZW1QsH7N4$Ee|HV(= z!5;Wt@QnQvjqI=P+Im;(n#OCVi`CVsJC-OLC4b<14{Uwl1;2E<@e@e7mHS9;m->k8 z#*6!C!7#t5ug=gGHpYIBLDgMdE%(>WllR@6yBRkeoBFJ*D^n)7c!fUWDOshdbcMc? zPRMP2+adjvgZ(cwwv@MeD|O(_|2fwrzvjfJ_%PNJ9r{r|p9lg*{F(=R@r82)C)A^{ zYchAw{_$QmJ}Etev0c6i71j2do@%D)xJUXw_pph3CfSPOq7}s`rcALLr?%ky$d@CZ z-@G@620qe{6G+5f&?I|Tr^!rWRP<H05A^r*yd7EZP@#qs<((u9=V?LDSOz z)5HQzXN%N4&Di3K1+fGR?R?l^;Cbin4%+w-6GMb7z>wa7osSY?$cCj)gvjja;E|r^ z)`L+-mq{9RUGT$A%)YKO#$#c6T~J!(Orw`jNN%zZt(c6|v<5K=`<&;>2XUnqv+;{P#M_xQK2xJGGGFYTx`n`@8U zziZXC=32I`*38Ddv6iCru_{ZTmaYrt{rQuK?TEPktrgc}Pk}PM=7#5sZ7125D1w7XSP6K>^0y_wND2<=or>tvpwb=}cRJ^}7 z=4)T1PP=l7k){Z3boJ(mTF7w63|U} zJc}6K196zR@2UdyHej}M+((rW7UO^{Oby~Ze`a>todafwGzHM;$8;J z3;byTlL}T4ccyVH51eZ9Gjk*EsjRnx=m)*+Azk*l=)TC?<-7DM_8hf#-}C!W|5anz zIr`v(0*tYJV&u>sacpc1a60UP0|lr$3(GR&?vGHX4u^3q-fk(&dKcx?nvdv>QALPGPQOy{aA> zrSD=E_Uvn~vGB#*>&I_xa@=|!jz_wKytYy9y$5SZEn;JVE3>LklOOc8*CwyXrOw{j zb>FRyCRTSL*WE?j>5B8S=l@N(QTS)fS&EFoD`KKGONlj0NWtMqq|dVN5(^P2sj`m| zxXkkVwBEu6k(>qRvbTVEf}npKw7g7jw7Wb@ZKg^^iv37Yt!r?_d@7ahoWgAD0MNmp zM>X!pDwnXW0f$R#3)G83chDAd8NGps%~`F>MPk8^OJCFJ;nX(jP#o#I?ct^RYKOh8 z1y!jQTZ5|2rR#vTR}j&INZ%x!2}kji6jNcCG7D!<4i1I}hX8X94Go^m-hBN~Xb89K z@dggT`#y(bJj9QIVaAW5B6A8zARNg@M7l7WC@c?eKNXOmZI0(0dffB@GOgsMB)=sT zGV_}y%!c#**`qPH(*ifXWoIN4O&;&dJ5i8sJeM87T7d8JTi7m!Vq*VBn?nnVJ1~wR zi2+<~U8oYIcJg)gW03EoT)t+C;&2JM#RvTxA~M$k*8(ARN$#>lyd7C4HciFBV0j_| z6DDY1vU}afvTIsfNQ#!$`qoyq2kCR~HF&{Mth0HfZ-1n7e0RBz7x%6(QLjRmA;9x0Xfi4?TY)t2=t#h%bt_V*)c7My_9d$??N_s6!3g>`P@BlWf$Y=9>* z>HJ>~4gDp%eo1%t66s0rZFh|FFGcL^ptb(K`|7Ry`kg;lkw(9K5i7cl;v&GO!CP2W zGL$ZDll}cz>t{X_l3r|Il@yyb(N%qgW{s_OQ>`&;VC&a~_U#Mp_z$9g_>YF3)%XZs za2Z*nv36vnmTaL*+Cyvbv|XjWn?s-37ryUu&23%>QCgQ?r8(YS5a)Lk{YqZR3d;6C zo(wkwFFiZqhX496>8nfnQeLs9{o3ogL`{Qki`JAku?KSJh~Mj6sStKxqm* zxYaDAnn5MvBQhw2$+%0H7A~qqkzxfZ-ly+BmG&o}3mUz{>yy$ZuTxt{Tg2Et|K35P zH=PvSJKaK)8wrF^T$8E43N9KSW>vrTG^J9-^k)Kl2czzT15+OKZUs1VhryYveNQssN$FK8A$W6QFu^`cD=<4QNeob5>DB3V^hz2WUbu%=6Ni(D zp=u@J)B?WxKvW3E9z3x>w2vLR7v{kmv3*-kp5Es_2e;*dn1~uO(ADPkI4EP6dz`H* z7d*Oj>4}akC0`xT&*KGQi99aKX&{!T?CH~>N}8Tz6C+tdG~qUK`ZS1$`1`1`ORt2r z9Uj}yIv$?v{{Xc}{0;V>cl-?b#k0T0r+DGb(wcMrN0`&JbJLaK!9VDrGVVame*y0h zY4Z4$%cVf;$1e-}{jp%q8S3A6bYFkSnG44JenIW^N8Dav>#=PJfq4CuRiVWl9XBq$ zv1j$Z>#p0k`kK+DH+FO^zOzadj<4*xwsqhW+t-BpR(8eVMdEwK2(Hg|^r!_p1*|0O zRz$7|n?wanV_at2v|B#ItjlXEMzBu1shSUP*0iT`?nv5U>+!2B@!N5GE|7px z33LaA*#VI$!-S= zOG9&b<>JgO=~7zsWTVe+_ch9olX9vwt;3WjDaTGO%&DXG3RC&QUA(G%7KnUfz);2? zUeTQAcbY4Le`b7!he_VYqqH9nL8o(a#xLeX@5~|ob21tgqN`S+!0F@sn`8A&pF|~I zl;fRgu;{hgIxCN$phD_G`3T=n_+2Ni6C&%TOJ(6Ri)I(@l$K8`!NsQl|4}>1cZpCa zz$$5H=0*PiByiunP^uX&78{F6kKdiHV#`?D6vSmYuJCtfg;o;RgK3=UhR~H0uwHO-e11i|g z1_fx?QEFMI)I!}yl@6uG;f$g(I>6&-UWr;JDBJCJ=R~zesk93MLM&#b@Fg|)V3fOd z!2zS(vj-(njsl0G*tHXnD9xdSlV4COsN{qK1w-{(xbx8_e(=6p1IryRY$)xbQ?K({ zj3DaJfSn_v(At2BQ9ux-#t&Xi{EI+tR9X*9SV)=S0Um#7@+ExAg|m%vvakXMst~Kh z6my~Kl=HANlt;mLV)Y)D&Ky46iy!P_C%wI>`@Y#vI86U=P8z2d>`S>}zyDBAPtS9` zy_v`ZvvSN-5+c7yb_jN_r( zGdA~j#cF5;#(p^@E3bqm z;^H*W1C=GWR`KbJq66gaOL2l$&~JF!gb1bNsGxq}n){lWhYbR;6|~#Oh}Y|QSFvX+ z12wt@MQkP!$Qp1))Y@K@UeToUU`0Y5W#z63b|#;e4&)X4guRZS12^e~pRkFzWIVH8 zd{t1QJo|)3ePFB)0db>ZyF#rr>Onu6et84-R<57?C(h#+91}(I*Bb&Vz$DvILY`g& zpO<6@9Kqkb9dzubwCtj^)i10eVD0$0V6g}H@DyzJpAJkPZZDVe!pRQ}&!1`jFr*Hq zuve5@m?vC|hy<_MzcS1A6Ddv9?j{}R5V!84oaWHr(vdoa+*e&z^}V1b)ErA4eydK$E{ zoj^d-56Mb)@LKfY4$S%p#_VNk)ge(4K5=4&q2bxCA}S@PfXz*CjAW;?BV{y#SNcON z7&hC<*mFeH$&rzqCf?hhwJEiOLWX!d32%>R*#xrQ?skTCNOW`CM@E8KyAh%Lc#-5G z`=u;TBQ%Q3N>r|%S9xX0E>}P=J$d%S3pmP9u?B@DFC!+!7t8q4=F+IEFr{2n;DM5^ z>xdRa&PQ-@3xcu@2$)EBQgo2a-zSPnyIy+8Xj66>^=?!nJ7Cm#bw&x1OtwFtKe~4> zJHBVnF+F}}r1vQ*QY_LV(_$px2QpyKD)9gl(=xBl>?3nsRcdr8gGi{#CTEhuMFryv zN<8TgfMAoXR-r|@{Z8L4t#!3cT0L_;;FAi*2C%o zC-BpLYR$j^M5KJ1iaQ|Z&G2`CcOM=y>kodgb`x7Na>q++Z)2IY_?+g5T&u5&=5{s0 zNJvpcDv>ZOZFwfLm#v$99f!D4+VX50{qa1e*1R3AhaHZ!4{5CPg-nQxgVugDSGGI0 zZyAh42DgloJv;-L-J_w4eZZ2qv;!YJ#<5j&?PWi(9#`H)2!#t;xS*P20M<5nRZ^(r zd|@$^47YD~ZOP}i!0U_xteMdG%q1<){yM+qzT1~`E9Ox4DSYSeNC=WazQ$_E;Hkg_ zp4;1Etog;5XKSpe%t5?TV!U1+cOLyv`Sji);1fu9)KHTjWQ4?MZZlz-6K z7m1H#)H&ibJu9g5#h6`@Rd_>Bp+=rr`IH69XhwtbY@q?8R;|fq+=80zGfU0|={K zAwltq^uzNNmFZbYTF)NE=`OggN^bQavV&8rS24b|%`fX#EaPt%$7hPt9~P9Hcd%Ff zW)C<#*w2tD8KDdjcG?l>lp^djj!omNd`;nuyWo1704PL57hgXSkg$>IOGe7K@49Px zp{z7UymWOIL?5gRGaf+h3I7xhf5kAty;$o}7Ja2<0ayX`zD?7bj*h zMK{Ru!=hP#`E;z_=V6)T!Wx*x3&&v{#&}6hb(hBMxw$zSwa=E zC{lx1$8h+6bdm9Yubnu>oMT|bjU$L z0Vf<<57VCJC+&v|&-seydwIz(C&_~KQpE0q-5ZHi3|q`%C7dwG&jy5%iiN^&LpS8u zkA<1yLFrsXuZC10<5C#?YA0L}@GziGr&6f!|K{&o@f9Y`wpCSERe~c(gRgc9z=EPw zXRVUWNbmlJw|fixNn5z@v;u?4j|Kqy_6JlT{{bfrE?r<;(6hQHk36YwHCUM0&}!_( z-#d=nGHwVPo;-3wFX*gH!dt!gd&d!U4?iw({GG%r4Ve&?43?L*z4C=ETOX684N2yX zP5hB*SWtSMJu$llh=c?5f7HM794Ob^nD@fXxjbQO$;-psJDb6iGLp~#22Y^TLop3{ zdMCo)WIxZZ&Exjh^o^0cv`c>eYx!NYNB+qR+m!2ke5jVW4~-0pIUp<+Ww|8C)r5M; zhGHM0_^SNGHh?w=e_mbGz4Vo^cnX+_xf?|PpUDrvx-9LS{FUW*t|ot27Put8rF0rs z?dhZ}^b7J?uqpW&@~f}V|0}Wjm9O-im~)qW?j1O9YV zT=3U1dC-*3uY5sDvj0vVIw@In={pzv`GGv3N?-k-UYAS9)!gY_?Ydkzu8w_}>vG|+ zDqS9k|34d7Rpn7MHy!2%*wy5hPL@P2&4}^@`7k5vg7F3U=l9bptU-09%uF+xVko+r z3b?=+k*EU5GoB#t#OaX{>F%SzDd|T?QT=R$xc`NN?C9FHU-{{`MsB=uv-aVVv;Q>dT*> zZF&;bC9ZUi9WX$+4Ki;>edzPV*uFxavYl6H@UH)x>zBG>TUWk*;H18A{t$|I!Th0- zeewLn{K3eU-di|5OY^5AJF;MQ()=O)OdjWY88ds4t*BIi-zEXwxE%^6H|_!7MM*fs zuG=k_n2m!w&CJ`k;n4|gF8qOIT{be{@VdvP*APloTw+6h^jhg3O!p74@S<-0A5xv6 zfNN3wx65zO)70a-%@A~=d!gGCL(p=JB^a(&xFTgDBiIc*T2E?xk|!4dg;w6($OVD$ zUOc%V(FUf*oA$6-J7g2}+7IF%X!W9PNQ(lj7L;EL0n%^N=}w|@x!$JNOUGqm!VluY z-Kf_kT9R7*zs_?G@x~jp)}1G(&>y%jT?Ef9Ktfd6 z0S*x8>Z$h2zC?isUVIrKUns6F3jLMbuAY^hCrI*bP z^)hXnvo@sGx*Qtm(2YG`R-)FttvXn7zBU_JymIB@mJaQYRx3M{0b7f;bKPnKPQqpr ze!pU|GbYBo?g+hbM@ui9F~2)Iv_`h`XVi=-J-f>hA4b|H@YB8yfUKWUcxJn?d?H8|BYO8R&Jb2I>AgnyNL*X7dNv ztnJ!PRZ2y28)CBRy$;D4&La+tduMdZYsaImS~-pV$O6acPy ziSb4J~{2@bkcf1!MX-_;ee| zpX3W5S%s2b3FC+;b(GxA5djzktDzp{FX%&|w@-RDIvN@c+5A!e`uMu;k&yIiush=n zJ^G&8k$wK|NM9f8j^G=y-8&;ee|9vKcBZ>S#rR{aaQMBRC$gvRjq;d^92ckoE={h~ z+JcBh2e2U(25X7w3?L?x0s9EuVBYh1B!z3qbw*1h>Zt@!{SDz4L@~f)3a1_U;{lVi zu>K*hq>MVF{-~pOkK+&NG#f%O&2)Ny8n9xwEyF6z`lMTWAa9xYOUV6*w z8uGF~N?Vx4vDmk`X-U(Q_@5#CT9;YeP10Kirz**uOWd1?X>y?rT!;R{S`=8ss#uD$ zhJCQw&yG-CCZ?0#b83Rpd(rP_vrZH%klwN=MTdCWzhIrFdc@=<#QH}g3EO7-!egNV z6X)rizVLu3E7x)3jUCOWfBIADpR6j;(freLtgf{FmyWxTk@JG%F67`mA^nD#nOXV` zN&B1VJK^Qa=>~?*<+)$H_L}rYgWA>9{2E%IbC)^DG?)PxxeT!++EReesY0xqymUNl zLBZ~_D+cMtw}`AO)Rx;Q{aI*(kZ3d3o!ZkXeZi=EKxY!Z)fSSz<64)@Z(LRgZBW-` zZf(9+XZm!j)ujX9jf?Lca+~!Sts!3Jw2Wiom|TK1T}A-xE{O;;T_{GIwYw#AFiN0zyK%NfZ+4L(ez608d)$1co7maoNPwE1PO z;Ul!p_oT7kzC9$^DW4B}g4WZ1C%-d5+3Jz{f_VzUHYpDlpK}&BD2QLMxGipWZ%^FUd_&*{^EDfLmb5Hs!R?c;LaB7710k##;G^!y05?>S_7t_)fiY7_;fF?#00;Y&Gb4OT`PRQ%36n>w7|5jG;D#`7lFkes&1k>E}Q zJks-!Gnssoua0;@KNOv}In(U9fu!9go(cv};d{HyZnxQy95~gV9!U20CsEiWZO3Yg zXc!+ClNf`;7=s2LD{#@8K;;7g)ZmysVh5)Jg21LiJh}tB5k>@07zRc!z1}VDb+6A) z8aGT&PEJp500N_b-@x?rn$Pxkw6(UjNr!ht!av1N7#aXyf8B)BvrS<>SxEe8nSQa@gM_ z(!a8Xy85oA!r#4ma{vC5lCi744jE`mzDLL^j~@--cfL=HFk zq?c!342L-wZr*6jcRUi?-QI)C$k)I-Hk!nYL4-waP zXxi--U=^)RKpP9c%nvY9~j1m z_)Mvu`%Gs)3u;ynA~0R0LdD;{PGG>KHe{<%4o};_56EZ_^{Ns!_KtI`?8mW~xSSscz5e_JRjd{(He zV!rn6fAU*pgEbsTEzZU|+M@1eX^p`Y3Zxe$99~VW(e4Q)pv}Twco(|ZTGaWfgDu_x z=@tXh%bP|`0TSo3lC}w@Q=rIES!nipOP#vb*m3K>hHEC$W8F7gUg}C$Fm}_5j+SPV zuBy@>4YdV=PKU6j^15p_cTKV1Y|S^ElY&l$m@{T#Z?%u zGPjnUvPet`!gql1TL9rVioJ2_Z)`*!gn^XtZPrMV&R!v@$^$bJM-1omLUI;5-?SeOB* z8SG%cULV|EeER8=#qEA$MBn%Q?ZNHB!PSOEhTyi&li&EpitRxI)A#Mz;fM7|<6qXv zv=ty>SjsqK7cN0FtEYhiu&&BlLg^!g*&m?G!#{0bTIzVZSoIcutw;uby;RC@I@!Ow zFP#ocr?g&YSVYKK_FDT4I?wO9|E}L363`&5Fl|I&lV5Vc$cD5s0AX+k z3BIJ1j>>L$ISBr6I2}cji|Mk%1(!eA)ynK(LUzGcCnF!IFDyDN#UO$)MakiE9og@a zk;Kwx@df;f-{^CvqM2|Q9=AqB$whhn#?U_p;b}UDHiNy9JiBnP3tGLvDbPU2xXLR|KM4E;Ct7%Wi~gi9qPEh;AQEeX~WdxYI!y&|XN7RnOt_2(lcxESeuK*7HhL;yo9YtPgK+sUqL!fk5x37 znnjoF*9GLR&M2H{8NAx3qHQ`~D3}Z-J?)Vde#yBi*#6rz4?nKUEN1NOh-CxcT3_>d z?~?+GgU*sB1HeFh&S_yB+63j`ApL?N+?N^d%c#F^&|3_aK)lmzY_{Ao*A{4xN^P;u zLht6@fsn#dfxfm@7VE3^;SmDhN{iF6n;h|XJDj!_OGsz1IfL=ic(JeD>-A-em3~TwfX`HsjJjPaXZU$d1;u8i+TN^F`}RV zdcwfKpK-jBMwsGth*51^r&lMg@5A5yi;o~u*eHu{_W{gkpZdmr`U~KjI91=kEB&$3 zKH}eqzxo{7t&v}>iI`y8?c*5u&p!JTc7uBGC&KjYKf&KK&uHt~((glpr=1#p;31^= z14ZN!HvblT1$0!IU#O`g?8(Z$XQ@aO#pfOE>wktb*zb_`1_s`C2CtjXv$osSQ}^BZ z+rP(lv-R_n!l?QL8>Qb6jT%ovF+=coZiUPWwWiR4m4>>JawgP8C}K7>;2s{$hDdPK zWniycoGAv&X`kkqsa~HQ9?lYE5IY10#d>vly26gmr~+`PMSXtQm#zc@qL3TUjcgq$ zW6wpFlCe~|oD$Vjo6BWdbBXV5=!z-VJp5gj`6`*HLF)gfJ1oJ2K)tu|JY5z1rSi(b zmE~pk*CI>k{sb8%XagAqKsqj<2pZm8CP3s)-GlBOCcadjAr(sbsBkw#g28Jq?5PLl ze5riTXMS`P>Fv4vu>yT@59g`Eklo;$3w2civ2lgEYgB(0*?mYiNg!#MH~nb=yp*;A zkdsY+%#*>l2iTL!!KgZNAbN1m@Sb5jfW+x4&gAnm#i6TRW$WnGtZ7rKluQO>*KYNR zUD9FUXlh4l$ByK7$MBxp_tZ*4e)IOt`SGFhOiq3NKHwsil8*cDI64%ad<1PxbDZLi zZwJ*q@D?HO^7B9~vizX-T43*j4o;((RB*s*CQv8k$!Jio2UP#8@mIYtf(8fXyCm3!Byefc3ZB$Rcvv0hS|gGD=RL_ zv?Z;py81rb)fz8#{U#gh8Oh zjT;qydfZ z0KrgHX8#LMGKon~KB>N~zWt;SW)e>BAVfF%&7w`1;*hmiyvAOLfd;OVgd# zt>pCCVs&R#C=2kCEsa&B0KQKmme1w-fE(l#(JHgm*RF0eb`I{mFcq?w zfyw6bIn{6H6hLJ%+{9<-q(vcYXNA$+AU?x4n7kIZ*t!<=rTM1G-ER0zD$wiXk^xLyqUV~*FBCL|lp6$Bhq-6w=Qx5l8)#NG;cO*l78Zc~M&!hyYa?hS-fsc>)) zKVdsXx7+V_AJtxJVr`-(s&_dEhs(v@s=scFl`N~yAFo(Sqow9m8Ua3EaX$*Pr>6*7ZWG(sPi#PVviH9ln6OTI3|uU+&yD-X}4#0;O2h!Lz7cO zY{x^FhJ)Ju`Mq_lSN)Im>sibE+lQzS;=`Llhne0#|qdwwS6n}7X;(1>pFqSOM7NPw7?1d}4 zBbTQy_g?s07Y_BV>BU2xSA2rSr~G3k^N)(}`L9iv&Y9&caHbM{;B0j5 z7A7Z#4)_w!6M5_qh>M<$EVfqtuXXE~Vg7@JtPx1WIZpAh_a(Gf8DlztU4tT^npg-1 zdXG~J0fFX-w1GKg0rs;H&-5dAuJ%Myl>6n;lIVEXWo4s;LQ>O0uJ@$VsnJv_O;4f2 zuj}tp-*egm0h{wjk-q5FS|qi7CI8d>vHY+}KUvr3CAgj*v5h1P88G7N^g!vXV0a+A z4fQ51jU3Yj+ZMg@sAbGU;Q~j_qki3ONv?1>kiycz&Tn(5ad$^YqN8KqSZe*c@zmJx zSoavBc!q|AFSLn{KQ|Uq>fbsYp^(GLyw5sv>OXWUfq>FE8}@~}g1%rPdsm$AGibP0;d)5(h*N@W%}DAC4y%&WMnT3cs#Dq^*i}=8 ztHa9hP)(_2j?V0z5%zdQ+aCd?r7;-hAGc-H|D%nD=?A~pe2_ii#6*R#8&FBf36v ziTQ-+U{yJ*9+EP01~kL}`hmnq@`=Pqf}VlO?7sc8!a=Fu_LTY`PO-C7bh3^_UjMXc zpMUWOBD4MA9e=#NJ?_6m?v#Vx5RRSl3tu5OAii%j<`&uEyC4-nGCce20t*VyktL(! zm(H=BGg2A}syM{KFP~`Yx4vt$1y7r8|8M%A&`Ds={{N@{pZXGSL+H`@-uwTe|67qW z03`pn`hRx+zW;Xjt3LGqSF|;s)`%0(s1x;Vt8aGBhD%I|$X9 zg)g(AckR$8hpt}Lz3Hw^!&iM1NH+KTlhH8Sy4`PB57YE3!Sxq&rM=$Jj?>S zega-+iLS)JIg=pi(Fi|rL9kkI>|VG6c5eRRmk_3lT$A@}FVAQ%K+t)k%&ww@lIsWl zHz1bs>-*JH{paU$=hGsN^8NyJwGjUUk`RG{+%*_^UTA*{WU{Ay6EYrzKCUJia2GOh zBbaARXHvA@0OhVDjSMAv0D2l{1@bOtf z1`(9cX7v`SGw5OVwR-)HHW*@4sP7W_bTQvc6CAyOG6ay33U2eVmoX~sa%+%J6naoCfedRLwRMSgPE;;i0k_o*YU<^)E zKa`iwLWF?F5Tp%wFdagN@EU*{#B zwyVc|KH=_r?on6WbI(2OyZ7wsi$vybz4h`)H>b`e9B9ZJ5<=H zS|POrun*<9Zc0Nt*G%68Bo4#~uBQXY6jzdBvxIoj-|*kmvbF&dz2C#bv$9-{B9Iz4 zW%pLCzKMzCWH1^80uot1My>dRIy?J9l&Kw_lb#NK$e#Se*mc*%@ORx&j{MILv9TB$ zhIlGXuG6&6wBPqai?#-B#;5XfJ3S>!fXFw1@V&-vzc7cq9OaN3I3O><858ONo|YWs zvIU}jk3A+=@Ta~LOeQJpPD|!-EFdYtVpu_zg48==Hk}oPb(&0wqyzxlffL!5wj0-{ zQf;Z!jrH^%lmtW)|F*;Hv|3=vbV`9p)?&9KJV+a-je5zb6KOC{tIq;55F(B_loYpA zdEioEg5id)cr&Jm(Y>q=>K#Eu10|DBsHgl=0u)DO|12_NW?^n}WwX(wWjWpJHCokE zZQfQ#i`m@bX!WkoW|fMsudNKQdLJBPXuoaH+KRE#gMF*k1Qqw`6q99Jhh+mXRWK(* zU1Wq6CH_C`h%rvAxk3B){@dN5{wc`sYXjhZ884Nczp_^#kA3_u*2vefk2uL1155{~ zk7*}i00V$C@&Hsuu*t)4M(EFRg$5J)0Q<2vB}j`;^M;nG$s-Tk4m=W;oW6dVec2%u za{#4Hx_v$b+8NEcqB|^Upfhg!XkxglYdFE~i>;cTUiDLtD|VejCmNbfEdZW3*{_Sa zJh(>r7h?{%zmQJv)1dQWNRTF2x4Jl1Biw$Fd70KqH=^gr_Xn;TQ2t+GL%dtgDdn=&^%7JD>^b#`>~K!myVvT1 z`C(Lj@90qqg_yx!RCb6Y%YOU{X!-yY5sC`*@nB>Mos2pA4Ry$jLdY492-DrFvHP>d z6Og@r#6o=$^+cp^ijDo#73`%E79AN8x0O`P$A{Gu;cPa{{0BMD9LBwWAFBabiYe!L z7j{=;8mh!q$4l9aOPeidu!d!Ve2QRnQ(m?1)FBZYzi?qi;aX0L-hLJE$$wsGO4 zY)JPrDlqO_e9PZ(neEO8?(<_kn!*JnF2quMSaay*3#^Y z+KT6!IuilY`73NJ+Gep@Epkk>wGMjN$lQo$(DAr8tZ(lK40ZcjEjC|-T=KpAi>o&4 zBRvuQ%xa5Gj(X{GRJOIa+PjAW9qszaU4R_2?6+F?BaefuxZJX$j3Yan+f{avTfC#< zkYL*%SCll;9~=oN*^!Z~5;$VLGXO}Kktxlz!#98H?SD?s;97n1qqFdT%`2Rzz1vRYh%Kzslfch z9D?gP6$Z6u)FVfqdFCkRp+~Sb9LB0hSQ=m%kW3S^&p`b^8h{Y#1K{-mb`r{RH)JY! z_<2I?JJU*bm!iJ@Atlgc-|;D_Tu}Ya2Z{6p4?F-TuQTJQ;K0sPx?v+krV@#{;X+F0R6JTXv=l-aAKP#)x zzo(>q9}rjqd(s~T9=`hg_bV0BQv0Unl2Jchjru?E>9;~9O?ytGEV3Gh!L#tvnAW~p zEgR(_u^RpJ+*LpooBjx47PuQKIr5s`g)*ZvL;x!%!tdRGKT2g!qa>I9HFYE$&`RD{ ztwfDdrCP72wti?{)})OjPLxZ>1O30MzU*n_Nvdqwa{oCh&59hF6%}9AzHzQQ*3O=y z4*#G{M-|5()xA+Z`4y60Zy5!@MjJGUP!Ii*hNx4*{uHG<4X>$d!vT$&eO2_ivET*>csN}fP7mLGjMdaEdi8VF_6x5}VIDl+t|;vv`E+xb0B3EJrIh?SZL*XY^$0`xFjZIHFgl2y%|sll zCBwfsc5Ep{>`f5iGQ6plBLR)5n^v!m7`-$rwf52MCZy}{=X~`!wEeJ_oaU4c9ZZ-c z2&1WhnaU27CZ*Zb)?lJEF;NPpGnI5&eWhZ|@;sKv8x!@<! z7H=||a2?q<@oN&F=t=~i<1~gBN;5*&z2FFVhELprz6`&|cwQni8*SUb4u#WPtK^MK z1*n%Oc_21+{u#wq#)VLPJgY>Ms5RjC^oEQ^9WX1S18u>uI}~BaMut4E4Dc16b}=No zLq59`(uH1ZK`t4|)zRs6K+OXDPiHIps<~$(z4-!z({$nGeKWmAolf6zURozuZ2GPn z?x;#@kI(c@^fnvKM%{)|$DG}DvHjcSE6c$^TdMoK-8IQ2*`308V*b_m1+3jWoQT@p z@pbJUUo*3|7%hRe;Km*V#>KO>tn9LR^wws*C){3IA6y}Y& zrw8R*4RY&c2!Bg4fRLt{N7jk@=2&F4-ezKk!Bs||H>mq!&-p1MAWcn$3s{Hxj>S0L zv#~V0qFHvV-m%7$uu08i-sW>)Gxo0CeD9)loqNd_!e00W!Hes(*GXaW*eP~Uz2U$a zC-2-9uD*Xao_7VST)+D9o4D`4;J!v^)tU&GrCn&Lqj3(>? zn~-_ZrM|-s&Ofw&zcACFOCw_I#AmS3b?l_oVYjK@vpOGDuib68`5ANE90^%%j&_O*^@vD17IcS|zoKxCzxw*u zK|Jjbnx4-NIf-O-&TWyqV?#Kl=p<0Y?KEfR=F{-nf{1MZT$}m|;yw@oay`@L3sljb z^%Ta27g{&+4#`qH6EGbYI0?uCTKNmQz=9?NkrXFlu50dO9!(a4^0)vrw0^kA&_Zxj z16XDVDwcw7cS)3`pd{tflW9DZsw`KP^h72zk=7E%26L{AD;Lz>uy1NVmO3Ro)@v_+ z$dkvmx3#tNlPu333-{4>ep2siL=p&p2rhsyUlDS_`k=9GxQ}9#a$EyMS7Rt@@uV28 z&+TQOi5P}BD>3<9BYC^067^HG<}9dM@t(PZG2K#Cz8Z8R^aFCaGhmA`Y)M{Ys7 zRT;DNb|?cT^}ie*kK@74q}rM64$S{4b9_q~7*N>7%J=_LUH7eTxzQLwH^_xnWs!IB zf?MsyyjqL3{W9cOhJ~R{EhZ5_5H-qij_B{Ro+ILL;rh~Z=aTEKOU@CQxbS`UGWAeU zIw%JuDIhZ=4mh2EPrH1;9d_e!Nc&Vf9@IWkKhQp7zew68k0WXKdi!3ndnLy!c1haS zMb~hU>aU?LL}J-|*Vy>%sE)CU~0Sp9C-xnMtj~ zUc+%0;Th6%W(IKcjU=UPn=ee|LE6Us1w1vmz<|}JE_)%!9j+U|KQRr&onALQn&a4M zxjY7}r2;!S8P05vj+xDYV7Lrm2;;s7;1+JSJaXcJvFT`Ldx|}3Hmk2#1zCEnqJBBS z(W)vyjb_hVg%W4VNvE(_?t<)9FBx7iMiVe^F)+Mwz=4w_NF^Jbh@n|h`m`eLok8h( zv)TIai3il&%<}SI3BMpkfi73zIa(*KYjkmieOzZyhMN0cb zhd*4gINX5xa+pPj`awQ5%HTXPvpM~2K0Wf8YLq#fJ-g#MqzHL3T4kf|fxbZ5X^UEV z{mpi>!P;uKy2cAr>mTizyyTLpZ{tjpXEdK1Gx|*Ps=)k>LAIIY)(Fy;=fLppA zQ04)b>mQTjNI~qE0^`X*zSX~}FPt7rrN+|XzD<5tA&|dd{944ihpZ1uM;Jkb4o z&($zSUEHG@^MLcHU_J?a7sCM57Qj|^AmrW~&y!nW0aZ{0DLOoSytc&`6!ixmO};M& zD_57V_cI|HsE*GHTcY!CDJ?(w5*)9<3LQ zaLseltgCb7pQ zJ}Wx*4ev+SgKd~q(wV(O>4`u}Dg}#4AqB7i(RExF0&XFln13<(=}i=T&Ni~Sfov+# z9Sij&d-sJqdn7sB)8_w*Q@rIkd=ja7Fz*{V%80wse54QuLGc?)LPud0Bi3(`!_d{W z^aN-?+WH5Sd|qJ^Wuw{5|F+QI)0;OVyEBfuVlg@|M{yM1Qu4UEc{9@1sc&IHrtfL( zRgZJAaw<~fO~TuYXV{?T;wC#%m8N^kHj&jie6A>*S0O7(yyrM(k4cyyB z0gN*x2!Vc7M8pfgVGwQxRyz&h4sR*~*;Y*aGad@9!=j0OYW#_waP}A>m+2P z+vS)IS0;>#dGg?AIc3Qp=4zUEgEY!J^Zipu0>jq(?a&u9>MQ5nuzbzo<@xMcnB`oxIzzOe1L+~5F&sFMAd>P@NPOF_-p0ju-@hK zOH!?d=djx+`=dr-+AL*~$ys`&#-hHUFEN+ELk|0*Y>>?`^=p&AIX5k>D&0T!n*ool z%`bU6=-J-l84QJA^h(HX$-Hgo0)wg5&pPmMAs-` z^6pHnHe0KGpI(5LZOjf0;VnBfG&?*zJH&EBTZiyahv?JUnzp}cIPnd9MDplvDl|Oi z;M%J#_-9^eJ>xrvixV5Jo7k|TJ&`CT64$KQfOiwc4*u>z2s%6YyCgoln?AX2!~df1 z6%*%exOQUVTD&8$fyDgRF4#3OvFm~#Y9DI#e*pcMK}(n*TY$rYT!Sb1FObAZSkvsz z`tx7c{A}oFYpDORkks*CH2Jp)4!khacxjv)NGQRR7_jjpQ&UIA)f42dBmC{5lQVy? z*CT!U;Y&^q0T5mrM+^7SGGH{3kAo?V`@{^4Zim#qxHI9`(@lkG?UpP>x364Xee132 zc0b*o-L`P^Lx<-7#W{D|$nkC4j*r|n$DZSb5x;W>>N*7KNn+Qcz{t}jRDg81bn&Aq z&>9E09F8}~-c}E?8vu9#!Llx1Za;SH*-898d+gX>uwg)d6Wj$N^oPB{YYrdI`)|E< z5}i#8uI39*B`&caAk-1kqvpdyRs=g6Xb6ml|L!mqLoxb?pA~>Du0ADo77Fk`S&I<; z18nVs*Ze(h%lFS)pko?^ZLxx$)5a}9%Y=bp4s8$FfxP`_K8k<>|d0zj9pKy3jR@tsy_^FWO&zA7- zmmZS*>IZ(HYfxWVFh2eo5_SOmFd|gpMzUmNtYqGtGX_H&ENJj3?qqrGgq>PS!om56 zGucCjbD8R+4+GX`JK%@5%`rVv`NEI%o3u-R>JVc)UhU0BquJg{D)r@Fg~fUmnUoKt z1JP*EfgcNV?`1HyvD2wAfwZ$xa;JKNZC`ATg9jyb=q%J+r2YqMS+k6uTR`CdIwwuj z!Y6ugF;)CEgKc^WkgE>R4AO zpP9@Q!h73-sj6dhs(Rgz6RZoix?6LxSS}TpeKFy}h^mWRBiaguP`lS^YZ1MB;n&&| zZ0oP44A(WMuT7-ACHc1eZMWsRyRW*ci?^E=TU>!$KGAeBIB}F7$0l^z0ZaraBIqBi zC*a1s*nk=bY+aa@6t))6FC;KnP%$i=2x)!Vr+C7x1D-x#e|t*jOr^Ud{|di*U1FoD zxI$+>-+8{Zr4}5KJAGNdKG|RF3H8KdPW67LuPrLe16HTA&F}; zmR`^B^5R=d$rL_`@|O`X|27*RTJyCO5xOd+{-;jY*#p(Bww7shHS*Ck#juu<{gYVw z#l;@E4xt{R1MRtj8wGFI2w6;sqrN-@!S_;jt@;IFdRh69$9sN;zcbo_qi~`}&MXQg zQ5GHsHphz+391c3_ZbOzD8UUXi`+If;gieS99OB@>L0T^*Q~ka3QoH(BFrVbm&^W%8jH~vIs3S&`HXQd$1 zrz!!Xxs*_bft*-MXNI#vdL$#H#>WTn_`UH920A76q^Gmf!wheCuZzZkaS{lGx}$^P zo1$rc^c5D zS-%jS%G`G-yG@-1;1_!U#H#m7(nvH>qQZlzXbFisQ>md;>M^R(c%JK&A^)rE2eRPKy&UIuJ7|P+h>o1xu6yF}sk%yFvhn6CQZQuwzeH)i>1F#V4L7 zPpp9WI2W?avc=)^C;e{G2+#<8G#z{ zVBZQhwthulrZhHIf*UbX&e=@z+JMOu-jOq!%tog7mOH$|F{kKp`r`(@$>MFlAa1l< zKW7n4widn5Ve^P>9=lTlT!h8m&Urk|mxyQG*5c9O&V$;ZD$vky1-?$x?rREvEiPRV zrF3pCnacyS3XdUj0X{(PQoKeDg!WFs+797fNdU8lp zx+(slS`{c?3Td_!U#(U>#JQ#2TQixhPwa-0%Tb-X*DVeq)x(;2JI^EKOHeAQrEgBU z?1#kGY#aVv_Cc|=ExQ?q`a0C8&l==B*ziB75wCfpQk<7Y4X6Q7nFv|R&Rv(e-E%|4 z`%U6-EQd^_a|biOv>w^ERuS~`>a1CFa-+GejnCVQFb_V1RnE^NZEPFx<`2Ei+6-B9xR-(~LS{-HE&W}g> zUHupLm-`^gK;8&?A8M~{RVwT08|y1dLCar6dXhzYqMGLTmr`VaG8CgnS>}!R%P3P1 z1pKc)Bz))BAuyg8Za?1qyNhIQFBEv2%|Slej`i394HNt>8SLa<3 zpAs4DC`u=p<{p&20{jX2dM#@Cz^g;ApXHep4JaMO5e2l}u&|IAO!RhRHSp+8 z$Y-Xw2SFgqcKCh(CJ=t$fD^fA@y9*-chV7h0JVZ0R?XgcWA?_M!qNW}dGV76k7} z_vR4>jUsQnQ9bqHjW_Z-)zCk;hr22d)N~X_$9*ILxE;;z~I%#E?p=S?Z1TLvl92@6pc5QC~%Zj&A ztLp2oTST-C>SR@@LiEQ@)o#*Cy;LSuNW;a&M!;>8ztrQCjf*p*VM ziBe)~vXr=9?{`Zui$opiU|=`^km#k3m#-CHFh~9FF?~4@E@!r<dK{Rsd8!?o(GHpNfzPA>UO1-;8;)r>C18&tyenSQ_QfcGg|H2oo(Ch_it~@{!~BZ z?&!mhnA7LJfvtjyvkIq?CeAZ-U`%}zvm}JsSl=3u3D|>}bZpdcJeFb$EF7|XZ{fZ==*ln`h%blFv3Bz%_r?VA4iwlY-+Z&AbG4avwXnmB_doLb zbt|s>aS^$N%%8N_zWA6{z+=b1a9`zvnNjlXl~C)$5=6?axs+hBaErzuhH_Z{A(obu68hk4T#n{`tFv z9ex<6H6C26ixV;f;gJ#K6daPl2@+T;W~hz;R*Vq}mx*vhHk9QywqiCLO<2N0V8#_e zD9*o8Or|!EG2_^l^xtI_G2lqZZb?cw0%A0W*!5`fKt7dm_!3N?kR55LIm*fH<(WI9 z(YvP0+tue}hhCo?N+OZ84_U)lDv=17gK{z{2g!CrvQ2}|PH-e^&qgU!y+jN-&4V-+ z;a+!nLb-<>f&>U?QO~T)X|$`;8ikppMlj3&Q)x(F$rtw*^JQaA8k#+$Zl~3S(;VRR ztM>>Jv7MIg1bqFkg!+M zbRqt9ZZ)ay69l$t{?s&kTvchTEd18SBXi(wr|W0VNGrUI3X3;k-#}pEshcj`f6-U( z`Dy)Lr{+(wP3$rC;a&H!vM)}`BF~F)&xtzgyZ(XtZ)4iG zDv+n?fB8H9tzH2TW^iZl!gYoU#bQt|sPQ8JgK=SGVf=Q=NIzfKu-%_i7N49rCLTKWdxFc@BMD;!i`i{-a5X3#ey3q5YWMC)09B03bUvAsCFTRT#F zq{i2&D8~Pzut!PYoXJ1u3|eS$AX*UW3PQXEq@;`=Q^e65M*r^X?5nP+PfU8G*6@l8 z=C6OCa18gMxpfWd@*9vHIhWH)YYK=5(SVQP5(f-XUR*qx&Emn{OJcM7-uJd{6@KG# z_0;8;v()8-$T*Q4WFO!?(FUHlK3^B@!B`~#p+~GDdWRG%#GDOqbxVJY`iX=>q-KZ3 z3$9GqxJQM_tH;OH*K0_Hjz8o=XD=Q+$luZVzh3a08`%1t7yRrNctfz4*2Mj{oLqAY z-pv0ConxhJ&|rsrqvf_C9U#^u2m&S~dE~fhCMcBh@Rc!!ejTb#l{ROxV`fW2Nn&|Q zKb$P;D--3C`p!9s+%~WwVKI+o`!4YZSkG8~aB`)-I8{0a$((012{XX}wu57Wj2$J3IVM71;*@(+2cYpTrJUV-ep!1!dHnkX*X5M8S`7F2hqHP`Yhjc(xM zM{7RJHY8^n+E%{yogIVQhBltrc-g34X*8c(msNBMZ$CvB&DL8mMyJuRtI-1+6IG~w z;i59$gOc>Z!IeAC>+U{p$IA2Sjp*92*octDa zT8RNhXpf}ruZ1kI$tj~MrRZGPBe5ZJN5R|@@WK?dwWV!U^Vn7n+>nN6Qs$EU+BF$ps;=WLSVliC?`}jv@$q8!?-N$ohIPHM7_4 zLv-Y8h}=fV>t@dV-3!EY`c_1}6sWD=N_9Roc--Ctp5LxsB1g+hct2X5AuDSA!C8+! zjnAMV?*$*I!x{>m_-z}`Uoo8ur&sh=v1V+zEipAUrE^alp4xin)w@d3JU|$ywv8bo z_z}L{JWNs?>ihA>bw1I(;BAV%=kAI_X)m2~sD%2E@b+t915&J@#)R{30V zY;4S94avZWrQXW)jushG z1%c)xleO%4GVJ#UQ{&kh-cFV$%iFHsR+`T5uGPZ%u^}a=Sj>{&;;xD2ti>^=vu!xC z;nD+_URjI<0)Cpp zO0MHk#?RKpe{$uOm2KN9{CKv0J+y6G`RXg^D_2|%Mz5*qx3KPA$mduD3m!Ow0XRc? zv6O*fff|&cNh*RcU9IfczoSwW#tx0UMYoa#fTA>UXiT`UdQBCN3l2}}0=~FC5Do_% zN_&TH@~}2e>M}d|pK*&VWv3#$fWd z2_}P_OG%p=De{asK_SRJ$PoDvl#WS(pu0$Ch_nLW%K7kBW8d5Xx3U8q)M%eKxFhH} zPNtsY(CZ)PV_lOgi3YM6G}O-sGFoa(?&x*Tm@R~OMz$QOca%Q9jXWqE4z zWg7a^s?OUSLeyE?{T0NQ<+d->epx3|%WvQQ;PQIQhzMV-_v!shsy)qyt4WO6{8{>% z!Gu%XacnzP{2V1emG=e<0}rCwnDR@;xDHa9pL?rd=)yOoZf7~8#*MC^?Mxf=Y`9oN zhB-?Aw0y8@1AWI1n3UMf`5&Kcw5tb#UQQ4n^~>ACPWG#XaloKJ1IFTMJ|v9+&xWbi zOgzi5Q{Vmjfq}n2ZNM$cf3(&)U|S%sP1Jl~Y3*T?)24Hy(prTP9YT}+^Z`iiu-FoK zCn0YI4Mj`{$>ov)?=Dh@_BdYHUT+cg-JrKIB7>eTmsfUnd4s1>e0pC6>z+kOWmxa4 zP`y833`a|8B%f}OWBWki(^_BQoG(W-Sc11Nq3!9yK%KH65Nv}ODzq9c8^APnmbRg` z6O;6c20Xpc1uGyz<-q`A;GiqPtYbWDE!m)$xqJv-fx9hVEVnnvL~^lw9(mA^Rt%ZL zCMV&5^K^UrD@!Nsjyl2H3;BGZP?)?1XmL`zH`tD0uF*-kbac=l5C@cp=QkRy6%7V{ zM)CIZm=NkzxJf{4)jV|bh>!F1(>z4JR&uBWcESu>r~b)_PC4?W$c-l=a%bP#;XWM7 zl-U^yT6U-{5?}+09D&YtZ<(o-6?I0Atjz}chKKv2Z8#sC`QH&)$qP}hGQijOZtUs5 zkFm~o+|~dY#k~^ZQHUJGiXxXL{2M?8SV|M3syvVdJ$s|OhDSwrv5Md$ao39vY;rl^ zrr|P*%th|k`-gW$M@6GcaEW_F*QN(v1Xee|Sc-0O*U->GxJVK2@-Ha&O`M^9T5U|{ zWZPL#eQi6ghMsy-7??M*8zJw{H_Zr_2zxZmOH4;G6o~eKVi^*w&d8&IY2Lu%Dg<0} z2p^nt;Y>g{lgqCsH&lo%zinJA%!KMP zHJ}C&oxl93i2F2m=-jig=O6Y6rfM#A^H$J|u3{>-VU+aq4 z3Y+q_NaDGq-=BOg5p&hfFMQq|@PHmL^ZZ4t$D`<(D577{JC=W*svPM2$=nc}v`9-BRsmdYd7AARhxt?W_Bh)g-b+~bcUm(tMo+N4V!d;GD{ zIcg`2hbGO|PWNv@#BP9|gpG{+FX3sMhdLZ#bY25LH((OMu~sse_(kAV79=glAnY|ziM!#9ULJlvm2(eg z)hhy)vLzuXWmi#BgXy%p=z3K@T=8d$#yiU=#wU}L!o|iwzhc~%aF#sTiFDCCQhKaa zZ_oC~#aH74!}h{c9eJ4rPLwxx!{LeAT5BJ|dq=D*!ds!dfK(MPFo-E0laM=_^3UF$ zwNBSwQ-tiU$?v7gcPFR)rs0vvBfYOG^WT4FVOQ#Go4^h~x$3wUJ~(%-lX3NF7zb><{{;vZ?P)CX$scNaOix_qtUVu3fA5PxsuT zwz<56S@W)w8x!5DNZ~;1=vIuu9emAb2EPDx3%_#E`U~~(u`yBhUIZ9!`qqQnQ9p@=kb+8$P?=Z+p_cU*BrnW9y`176|Y`G=SOhHxJ68!}e4 zGN&$Hn45c?J$%L8cLNZWV}&C6X4`f|pz-k?L_0hVTQZ@pEQpgT98~5I2737*jH%_yKM-I&>(LnayMz&p&@~Xb7Zo znekH4`bjQL6_A*+0H+Q@t&W>IdFEz_Dqa%|(nKmbWKkF_%wx!96=7HBpY(4Z^6ku< zcb4Y1mUmckJAH`oc{m#tP@btA=wUy z2Yt)zm+Jj{m2?uZ0LtD(n&FU1r4_{MW)gdsTQF7Kr{gT$omP9}pH|Z9A1P^uOn2Xk z_jacdp}I^b|0`^(2)HJy08oi7+2o;Jq=1bPG4=3RTN?k)ZL8|zsRT&eMg*pooGz!1 z?5p4I#aDWI@a^6!7f(SO&38>cCT=Un{b5!C!IW(4kp}022qWHp2>qh{iq_ixMgZHA zlln(G$kgPTPTn0J+Qt2Qqw-!kx|j5Sh}~C%qC=qcD%(Ye3m*52FZ`-iy>|vxz5d;I zk!)v%;EC=9@M9F55Weid&(1iq^h+;QDtG$>K|VHF9+-z;hTaU?6Yd5;A|A~Dc)cGsk6?T&*l9GJe8lu=@EYV%hkd1=D}TXq z(nf>LU(h5xmr?gjK0Tfl#B{Zq&f`*U6tVK*bQ%E8;EwZ2eKu>G1JLz>q52|x$nne@>7+tF8D;5gSbO`?`w zax)AgCyXfu<#gNx*%m5Wt;={k6}=%X0&;I?G}7lL?V83g6DvrF)KGenYL2BwqNCww zgnj;~nVrfTqy90MRXrsFZ;z#{E~HKX)FwZu_acpgNFS*00gclk&d>)lK&cl2zL^-F ztR>1hVb7H|TiPO5lwG@GRqub+juG-oA$ywbMdb8pvq2yk;R|37eQx? zxjfml1+_I2pdri07>o{U#_JEKE$-f-HEH%qXrPcZQ4r2ASZrpOcoEf8 z{k$9s$sxCVpC1|v?)y)FfqLC2>j!|Zd6g#wXFds|$3YfImum0~_3 z)Gl4qH6{6r_;Umi_vs+V{GFdC)g;B zC(+_Ah7bw0scCc5R@j1e(s(BUC{7OjXcO4_FgB@|sn*cqAxpj15Tql9(uLZl8{ab# z6mBQUrT8%h2DkCR;O12d;ACL&2Z>&zL5X`!d4mL~;(`%Nd%vj=5d={T`YqXu6pWZQ+fIEa=l;shh{I1)j-{fZ% zy}4F4suOrA>DA#(X4+L|9R`C^lXF|W&gN`9IUQbeS&cEH*=L0NemET_M7WZ@&4F~N zrZ#xtv+TOQM}z*>UXK!RS^+olq(!f6bRq#HEOQUHOWoCWyWGaQD;*DRIsPeXQ(6bl zY|~v$2hgerb)z&k1inQL7Uvr60?AKkFi0+huuGx~HMJK;AgHfdzs%;r6Q8O<#I(32BFS;GW zlMZFvfmW7llyo)dK4&X4z26}_{D?AlNZFCBEc%2o?8<`u0Rq752BOrkSQ$M76=Yn#WEL!q?%nAxo00)&p1u&NAwG+DuYi!`kqxMl=RA zMC3xYU@}5n19t_rH=;;jlOQPN0wQ*}RS!K3)=y-2oH?$kKd5ugG9An?y)LbX zjQakyS-n2KrY%1!Ih*@1QzGaehFRe=VO9i#9qwLFJm9kSc3A$zVo;`9Tg280xA_m+ zJ>9E2?6R-B+MzyZHtSk?%py<&dc!8G(-gMo><%-trYv@Sv$-c^w7LvoD@;H2d8754 zCLejhLu_dJV$)YKZ_YN((bUjDU>U-i)JKygrl7&&Sf61)1t=}%nq(^A1uc%5M82VD z@ie$gMEAh|>5QHRYeHF};j)Cj?&ItHFBvP#mp69BIlF-!2_ynOEAWlYqWS{z!luH& zW-te>4j0nqifN08prCZnY;_rfRz0%h;+omPcAYT*TrSvfk%<~nMD8W4A3u({J1o+p0%YSQ1mvfi@26ktR5p z#4HxgDNI4|u9hI5mMOFG->j{AM~~U-FsD`maKmj~>Cjm{9>LjTmL1J>&D7dbaq3#0 zZtsh`v*pzKv{1dIYL^{Buy(OZY;~W3_0{BN$!>1Vsvnz8%+}p(1G;*5r^)It23vHZ z-7HuauCW%UfiCj>3Zl30r;wN_yIToj(84^KnRb50)+}mAW@1HYQH7JAz&2QpubM{mx`!L-KbKza_ZRI#4lt+T13Y4$1Je>kDUMNxKN1uxrRh(R1f5E3Dl4$QB0|1L#%i~VCSsdvHpcP;=6;bE} zC>yd-)4GEu#AdMyklffVXwOi>NU{kn1NbI9ncERKFR1gDlY*OBj4nH{uDflDt>tA~ zOnd}yUT(45llEvuRl6BmKO5S5*=3IHrgi5v{3_$s!vHWF&nsq?JvmVkHWv?H4oRmSqNEh_$j$n2+DY__CL zc}-{X>P-fl!>$MLdspoDoa{fo{x@H5Q9n*LeN1)SvL!St?6W&f76wktqg63#@3Jw` zatinP12HDzUW&C_{JdzF^>(LCk9_3Kg3Woq^4&-O=F!oQo4Q%k+q0dY_{3$Mvsj-R zxkt^gy1<@kp#2-6j||x|`;it7`BHI04t`*+^8M_Xf2>#}*uXoAic(}RJXuuUejX{n z$9=_-QfYKkv?LrUMp;eC-#))bmP!z^NWVrn|Bqp=g`v>_zASDH_Y=A!xMN~Run7S` zj>?3>&$&M#2alM2h%$9MX;qcGl#ykxxu?Ffg{{}$?F#og! zXV>T8>wy%euw+4wK3YD34@MzSBPInYP>~Q?L3UI1iKzUNj6yJAKK`hwO}I>WhVp0> zxK}S&Aq)wK1n?RI`%6A2*t@+Fu50f|fS~vMV-hvM=h7&`HR5IM5ZjDv0xoo<(-`(T zTrJ%IAJJP@hF2syFHRa-+N^GCbLW9b0O}}<*le>%*kx^2udl^sGRON@cI7SR=$1ok zHwsaA#Mj*!?M=Bm;8ZKPbjA)jDw@0PHf)JTn;-;T1HDesWN{kI%%C$nMW@3A5LjJv zOBmQl;y|_V)%~M`tgQtaf+hpzxrly!4l8IER;N6V9))0u4n~+3XEC|&T>UH`cY>+Z z(H=&t*MjzgfME+xH#8-X5P)DwoF@sWXahn}c=uDewE!iuc3PeP=CB29t^gYz_{h}` zM=sxg;U(VY^O3jIiGZs`uP^mX^sF0-ORM@ef2x12Fyiu$z|qu~r&TTxpkv;bgpBTY zsTI0I<8k8NJ;J1kM)OUDl*gIrrrszk^OhoL37P@D7F@#J>Sqs@PEX(2ql30wS zQgiClWC3J1NWmRsYGqGvR}ZF#dwYk|?3=I#9^{}uYmXmS-$A@TUt_g0NzdNMGmlc2 z)`x22HPP0^MQYTToE~`5`xcAK19B)c_N+$6$@kwEj8wirctG_+)u-4E>p$6hUN0UG zZlA1^utd*Ee%OSho8UTT&1CzlNGUR;pO=F`JbIe=A9jNrENYZMD^<&6o`3&+_HXI| z*k^^%f;Dt4NZB{GD^u(3tz{m(rlFT1p3n=v1Hc2w1{H_x3wa|TCvyinFAQG;F)vJG zo__cfVPuirpqYUK0*TarTVD^K3olg`1q*%_GvzZJOjf* z^MD=%ISs(UNz)4VQyG_Ge~Djpm$`_zHkWv;YPvg zeZKZ#{marCSjf}H0G$W^X(yl^0skHxFc5Ingfq@RDJ1g2 znqP>&A7^dOU~81O-DnC?p^>kc+FxA+QU!=!SM#YwJjz^ItOAUcF4f= zNu$je98%vN`tIrt4ka9FmjUt+6GQ`Cv|Ej>(mkI~M!kOEu>TvW*m|Ja4BKC;VC+tqiFYYHy`*VMKtmvHyQkq19FG4Z(v zk4&6sQ`*~=HtndsmswHjU9#R$UP|&w&Yo8CGJK3y&irBV<>8973d51k6oO#6gpMVE z8Hr^i-H@Adv7BpaDN*xpRCnHV?dsLn-n6sI#0By|_ridm;hOa zf;`A=1|d3_;1uma^N)rQ1`TI0u&gphbN1t*0xr6Hs#O;g@rGR7#Q9%MjyTN*OfKVu#3X#RaEV`<7LWnJ2_E~Q-; z7-fv%!~1>Ck$i~*>pq{!(vfs@e17-m_gufvXDRvvU^Ns90@w^hg~-tsM}TVcy8{PU z4V^t8J$(R}n3&5ITX7{$r6S`fX!5f4=l7~Nnm~v?^dibt`AqAf^7&)x-__N1ptEy- zsU*F({L{xY#(;kUY%k%0tW}Q68d=)!N?U%ve*YiT^Aqdzzfcd5e3~G@DZ1!*pTa=n z@v*fyg&v`KsHrl3bcE{$&!ynVi&g8eRkDaAZ4EC5^5W-*xqjv!)JMpEieg zODep|tB=7-z^k&}RJOUsk>Ep_)@Y7yunt*>k&C$76QLVOzv@fHSMIt}@OFKv(A*qv zHdQCr_m`UeK{SB)4H3L#7VWBJ4j^Gf_PY?nFsz4lVE|cYVGF`}1j3YAugVAZVl<8X z1)h?J!G&?%?n?^m{xY^8DCZ8(yf114a*{;rX z*TlN8rq#MK>9y9a%}f8zd#;Fnn(c}XH}J`g>;3*Vo_O`e`xV*UNjgBS;gY53#;^n^ zyuBXwL_c%|7%)FJ1uX$)x7Pk zU;XO7`yiq<(*5BXyrhrFuL}MOOZrGfVWwFqXXSTtS#v_}Xixs2h({1U zR(Y<_I||ugVOyVj+kM9$-Qm9J?dkMqKKGe49U?cqvkfQrDs}i4`l=EA)THe0z{8w} z2_?sH5T(W9VgN3SPTFAzAjYr6!gH}X$?Wl%f#>D%%>9N;kQ@iiyH<+k^ErC5#7I7$ zKjE@MEr$!G-?j7S>wxDkqUdrC$s;XMe;JYWQt+9FQ z0wn8@kBhzI`2KCiqz`38g`{EI{^Jw(+%s|fuMac@^F#Sy(}BAlyX&sUlzY7gzl7Jx z6OM(+IZ(b05b-b_$wiPG*>$TSmWdf|9Ud-!V3W5DyZt`T@SAw^yN6L94zJ36C@Sh= zcM4au6S(E5q0nE{j}8x)KfDOrRb24Voy9~##GU206@JQlO3lts<`dsCj_nw!9Y~*dpNv?OdGf@0! zCKB0fHa<`0KpbY3{457^{W&}jL;PgjB%j`Vv-IuR%)u~i8R0KTXN+}qMiw(zEFD&- zGvIQch-9;u=4iRgvbi!|ZgA=?$T`w2Bg(-n4h0>w4T?)JB5*;u@WqLa0yP4Of<_kz z8bq_efGL7eB_-l~XNJOlBD07*9GUz7nBWDb%gK((U$Z8&;jY-QnC3hhzTTtBuGcq+ zsk)kzHFYCU+-5YxW~Z~s<(6Jbu|INnQ)66C;LSQYfaMedOb!LNYRFetS*4>N$cQrYG-O*&*whiqBBU_%A@J?hFg_yC}CSsw< zu}o&9={mfW{s49Y@c`xM9#~|`S3mN_f!51+&M(wWD|cQFF;)IQ7K3b0_g5%pNBKWC zl`qDv<+-Tb-$=Th5XAZ-az_A;n5pLJEKEEoZT;>nf5YLsH+Ak@BUe)?czV;_hbQ^$ z?%p*!J2}2gEtE=79a8K7_aNau0MeL)p9TmKwC`&^^`&*=yLOGQ`_iY@u*sg!UhcAc zzxp>{ZL~Wt-&d*oS=61{Op<81{@8!m*;xA(a`Bt4XpgbUn>G!5U33t z+k*cEhm1)>R8Hq04v59#F)DND$xk=*+{YcQ^*;1BU-i1<`@i`oo9X|i7y7xLESpMS z2O#oJe?pP8r;1o>k7KR*DH4eMH{_5?yje29)>4FNmX`NZik5ROd}Ke2$H#yZ**5n5 z{@G0%nOBs0oE`N}r!DZ;PAm?WEx`WW`{N(+-XG81zH{P7R}BrU&4uF9PrmFH%wB6l za#iJn()P++fw!$3*@;Zm6%v<*k0GRyF#FGIPE1dqxMq5~{LX&c3ldGjx@b&S^PwJRNTn!>076F;~~FI z-+C*P*mUs0?*tzE0SoO8?iTRvkN;YD6yK%;(+`Tfp*$s8Y~se@2d*NCl)OAyAdKK? z_ziH1BNge0;bKDw4ajq>_>F<+z#KsY5=x~P8l%z1*haz9dDT$I6=E7NO{=enUV-Oo zKsKetE3Ulbiec`BxjqKPcxG@E9-93z{E`w!Sc1-u;G^g%j*i|wO5?aNr%1MoqxDn; z+7RZYb6U{|10YXy!pj8JgVI`uZJn&KT!SkVObULF@+Q5Qy(%4F-L8%`)fPi*$G>pI z_orX$+{x|pcLakS{`1Nk^JK5eh6UI!*0giM*6}slA6~WLlJ6f_y|atzq^`6{hEU_@>ip zVAqd9i*JrMm}~vb`_tY==XIU6`cAgGWmU_jjq>Hc?fO@2ALZRZtj^GZsyhG(6rEbHhABHJd7VMZm4@ z7&wT@fSvUDh5MVi{;B@{T$f13Em0^JP@Ws`jRbwuU~T%!>l}7U9YfDz45$IXK+n!Y zW3%o1zrS|v2W_m`y@F4)doI7e_?K`)c@#SgxALS~ey- z{<6(RKW4(8+(+ORlqN0eBk5hGEz3ITH%e1zE^+hyL^>$wGv_-A^rbS@S*+YSr5UAL zSPvjw3}l(D3!8+`j&?irXOfw*t;}#5$~z_;oJ|jJh~0rwtvxp zo|+J-j^(jrJ!KiZitt*>^7p)GI=>vx*@9-hHxhJ+9(h0q9x2yZ?FdGBy;-pFVu|WL z)qkK;b2R*;|N7`p5r5r+RZc#U@KK@(2<|Hjlq2@Nv4cAIYD9~9vZD3K^n3TSsH$a0 zQ*f=QZth;!ylKv$Iw0@!Z-FQMCGGQ=x1@pgPr#oYzUllAegKk&TUSkgbc~&qFS$1L}Oh9UoU%XlBHC+K8GjnQS*pi&%N61aK(YWl}PZpx%X8MqqwE*hD8bjGBo}p zTcukj&>JV@mM_STluN=*dS6o5)h|M|CjSM}o?8GpQDzzydm&O6batLY&Z$HN6i_;{ zztqW$P}k8J9N0^z*hb96aF}POaU5Sufc^9pS#H9hFJ#+Nc&keJV9Y3!MS6*)33>(W zI?$PeidQ1d2vw5yYZ+%72-lTLM5Jjb+)h=hfO>pZ29Q~(hSbXXNqH#Ofzs_LxYyWI z%C^IDCQNog9Vk~K)eMmsofQbjm=77UzeBGDlt#pJ#pcG3vFHr7uWTbx?2%+itD?Ll z^e;-5Xsp_H}}8c;X33dg60tkXlJtz`uh9j0r5E0hmnoK_4&qQqWn6wibG-0HK1tunhE+K~{~e}?%72yLv5O!A3hB=X zh#89GxmQY1z#i-@%^e58P)Um8ixi`ebH^im`7%C2FqN{t6$d_i7j(#Y;MheE{TVBGZ%?=NAVOr(qX_3kHHdZ9f*q=o7NNY`LxO4gS260fZ7_L?9%pb8?<>h z$HwBw1ziN^C-Z`eZj$n`ApV^pwvy1@zVc|p??-e5`DLNn9YtV_04`@obG6l7EnLyw8ZGwFe88?)j*TJDf(rUt5p@N50N6E_ zRwj#stTmvJ3PnXFQYs_DIZ@zQ(y|=~)C6asG{JwdOm|U>F7XJ{$Z!RdoD9t9b#0Mp zN?}@lFcZNgj*cD}_3@)|mk}=YoNGf73u*YGHl}_V|;^-L}dg6b#zV(>Dh%^Il z2rstZr@k*lJ3A}S-=ogbyRpvBSZ9%r=uvs?DSj1|%uN+*xdOwE*+I534fdG|Scpa+C>BiVPF*fl@ktCMEY}blHtnz z**R#TW@X=urT1o+Y@%DkUvRGKa@fIdgWiF#Z6WxOf=?uO2qorso{86l$zhC?F$kCf zDFI$0K61oXK~3*)Lcq!32xnO~XBTUuEoxsA%dJlV;Hp-3Qk1?INUt`hStpY3`8iu` z=gMk>Hodl8(=60`TP#MqQEfDA_)@A`FCz2?k(89PE0k2FdpmBkxRII0($F3;uQW>k zZ)2j~*0ItNZB}tY3nGp(+K8{Y-cf5u0E#M?Wej16RkECWDc0)e@Dk7@5Y!t5Sno7+Myf;gQ&Pw}pN)5@S+2@-5&UXfp3me(4 z=j)e2?v7cP52gnCha!BFXH71B(cyb!c2BvQsAHMOBmSfjdp6Kk6^{lmm;wTRfO7>U z2DlAnDH3su`TFjB*%yN|7~A#o{$8+t+j@JUfqdB;gLwF23|ZwKn9GY|%*!RcF=;D8 zl!)(p2V?WIMLbYtrPIw9TylWH4Sfn;Dx9XDWOVR87Nv5)Tt4?4Q$P3IvpvUpWd>6& zvr<&=+{;{Y?qxPOg$LGs#Xpqr5V14L_IA0qF)J1r4Wi9uIx{~BC@JPHN`VF%S!!NHPWv;s^ zdb~bEx*+%f&_PiWk?e`Bf--NxP6%5Ab-Utd0!R7Jn;dzU|4o;lvabJu(Q2tZ^dF(Q zABK8N+S*1-qZ8h9g0qp^Yhr$9qu~4$;(74QOVa@^9qKU#d^YJL!IjIognO|nD(g;* z&%}*-WLIkQ3kI-G25ZFg|W#|*cYHRvD-Q7wYm-w^hpe}3#1?wm;?D_6S0G3i_s*qpsM{C1_QIm#|skY>Wt ze|6uM_Dp>7^OvsP*6DP$wYg3?3$eez|F^-Qqu2`+9)x5N${<0$14Jv*7Rx+%K(D1XA4Z zHF`jOO~C0+mKvZ&Aw6gUo&w~P4~h?NGG+hxihd6&V4wh*^;U<7xD|7(EB?tI(!Y7jmp;@w6QqqfnbIKnPO_6w4%xu=XL?pyD1M7%Q zDof|L<(2gC(wVW>>)qQaiu;Y!4y#~Pn|Za`6)~xeR%)w4cMoB|>BdNr|D?HC- zz>e7sK2enItH^jo@T^E$Lxx90HTlUy0^Sk`h|@a7vWDF63|HLRz!)l&i9Oj-d~Uv3BivX>FTq_VwS}QBzZU`xaA^-w2$^ zAn!7nn1*wDHAVw(XtMlOX}pBzlduruDYy9vv^fOIcnR7Jmmu=kM39T@+Acfa$lmR; z>pz9yWwA$G=k)H*^}!a9V5tt&C75K8=$Gwo2m`oe4%L+c@8!nE-mH$z>o3?a`u;-D*ua# zkrHk}0r!Z@0n8+u(H8f>1;NG(K9|en&;s@~;X<9QUf;_uhY^1!C@paXPI$}zB46P# z13Mosee;ULr?i@CeT^Eap3N-|tQ$>@sz$9h)zrltCi92*QCov32>jaSs55Id27L{O zU(GQm_`5|qMvC2}*@)eUkfH;~nrFjKuOnVW$sXqbPa;RhW|319eqr;a_Z zS=7D}=e4#V&|rR<@JtkWUJbLYIyu;-EoimYfuQt(NATeJnw4jd6(?8ylXqj$9lHal z%Hlug^DB#*8qpP5XY7bNjX`Jqh`FJ`@9`AeR$6+HuRf?+fw_1;G_h?m@_Q(5Nt`t;4RtG&&3y(6r$vU*VyZL?+{uC{pe)l9Fhw&=GA`f6`LqZiz@h6cVC5vpRf z%UNrxuQTY3PTruluuWXGwJz9dKGfPh?r!*LgCP*8t^GzcQ14bTEAkOG3N`BzAyq`J zOSc-DYsGA1wtjQ9%UZ3r)WVd<4L87@tbuQ^)`jZqmTIeAYq8^_wV{rDT1mbqAGJS) zmenWgyDA)<4pJUqXfdTRsR5ybo~3O`%)+b~pb%p$S+M@udUhrW!~x6zPiD-eEt&v$ zUbu6-l%Mg$^?h2~)Gg+&h|93q+m-N{i(6g0xIu)eAZX$k!WKA>7>qg|4W6{_iK-p0 zGge-ZUKA5*Pr+=`b{7~JYk42}=vCD519+%F2v+>!6?zXyZW=eDByuPk=o_{-9u zw_^ZthGO0o+{)>?x`5MXuX7vqVM=JgboyGA!D8_EY8~};?t14*SC8PWt20>~zQB3- zIQmZQX>GY_^!CHeUL))^2rxC8YAm%jzpJS}*ul45-t23#*<9@&m%(ARnJsO;W*<0F zSx%3m&W|9=)2gcLt8T|Ug?E4rDk3;uQaUwqzg&V-l%nrTfr<$K2Y*gr7(u3>Ke^ef zVY5QBNEf-#ZbX68SHR?zjT*QbvE3Llf?eP)g?JgO7ODl4*yeY8-0r3}u{vM~7-FGN z3~vFW*w*C64^8n9RKmhPwj~m6(l1Rlyw%C7t7~g&s{OheRkfCKJ{a}bCoHVaXsA3kEw58Fa6%D zhU=t4gDT~PN!L&*5xj#8AtbA{L5MCa78Sy_3-i2E`ujEY1wyW#zG0OLⅇmU|cgC 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%0Dl%q3}GxlU$E<@J{osE`&nVcm1 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

7l)Z3?(-{?4pRn4qtc{-? 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

  • 5eLq{RGpc423)llI@4x&J-zd7O}B z?BDnS?r%Rv_DNxu(eP2Ku~yuzU9d>hS~W@dN5{&XmD-t|{;XD)Iv= z@&hXJyMaEZK6k14fj8g>n?b)D@bmh?rqJ&O{G7DAsquqNqTdbpIr**$an3Ydd^h0d zpf};7$15fS*$i@Bsz-0R{R21^V59pV#jO{2U4J!6wuXDAEro(hn%o?*{yw z_W`~e@N?2G75f2o`rUw^lkZZ2-wpUVX_pH8Zotp$cLRQo1o&>i&q=#f;0Ie-KiJCp z0TuhfR@M)w*bk`K52)Dh2K=0Q06w5%KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHei zpkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCu zVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_ zKcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KcHeipkhCuVn3i_KX3y4 zARgck1>+y;Zan>=&iqSmonhGA^#tMseh??{J8^=T#DABA^#|evemgYlzf0YXh#wHY z-y#0^HvcXM=)hs{I}Srinp+;9<{Sye#AXfr%ofwZl^FpTzjI*ZN`MWVc0X|1{lIDW z11G`n25X(~+--*+Y%}~|o8brB41ZW;4#x;PG}=0;i;Dm@8h)@*@H-oYv4R4KI5AZg|m= zz#2GiN1(p=Hg0`xc+n{b_-=U7Ndx@wuprl~0!G11u~ zIJDt@0s;qq5IFF=0XwhX4cIvn^f7Q?{BEet@olXfNzrL~yI5y06sRc#%={2A<3m7% zDa6_2WxUxf%I)J&VDUqNr4I!bJ``BIP_U9hL4BcMC53`|L%~W41uH2O%$`s%3qrvx z2nDks6!c*z=)+Jq^yv+CLza$o87>s`Kq%;eP|yRRpa(+TV52t_^gyT^Z1mcIS#7|q zHegm8Fslui)dtLJ17@||BQ)oGcPyRX-wO1j4Vcvi%xVK>wE?r*fLU$8tTtd)8!)R4 znAHaTYy)PsL4VtTS#8koHegog_lI13z^pc4RvR#@4Vcvi%xVK>wE?r*fLU$8tTtd) z8!)R4nAHZ%Y6E7q0khhGS#7|qHegm8Fslui)dtLJ17@`Wv)X`JZNRKHU{)J2s|}dd z2J_4Y%xVK>wE?r*fLU$8tTtd)8!)R4nAHZ%Y6E7q0khhGS#7|qHegm8Fslui)dtLJ z17@`Wv)X`JZNRKHU{)J2s|}dd2Fz*$X0-vc+JISYz^pc4RvR#@4Vcvi%xVK>wE?r* zfLU$8tTtd)8!)R4nAHZ%Y6E7q0khhGS#7|qHegm8Fslui)dtLJ17@`Wv)X`JZNRKH zum?7<2R5(=Hn0aaum?7<2R2|<8!)R4nAHZ%Y6E7q0khhGS#7|qHegm8Fslui)dtLJ z17@`|nAKq~8${r3z^pc4RvSd%Z4iOCK?L3g%xVMsXoCp64V-ElaH|cRYTI^=x^27M zY6EVyK`_n+!8jWP<7^O&vq3P<2KLbg&bbZP)duWp19r6myV`(VZNRQJu&Xw(t2VH! zHgMu?;KbX2TW#RP+rWvpffH{7C*B55ybYXq8#wVcaN=#i%{Fl2ZQ#V)z=^lPxrFT= z#d>Y`sL+vaki~Y73Z1kY`4mRLR+dV3D%H5r% z4UQme_o&coyGMnNboVm0dsOJ8-QArHjw)=xyEfom8}P0Tc-IEJYXjc3-J?RM9-u!6 zsoG#iVuO&X9SO!i65zYP28yGtAJxBZ*H-NQns9PnQx&_B}M`Ph+Q{Y3)& zNT7eDyZ*xfpN0Xu9R}8Q7+BZk!2X~d;Qw+~NS=R1n%cCGqqi8OumfVR3}Q5)-pND zi8==$Gk(L+O=iz1j_MrM)vYorE~TY&hTt3oB{)Z(ZQ+d4z!^+pRD8?8LrQvbMu;g; z;>5dRQ~tXoM{>O0+KF>Tx6A81WdtKyCZ;E}j!ntsBvYKgSyEzr*MiCMv3hiRN{Vy( z;;0^9vgV(<^Qm6NAgB>wkaJG9@-9JuxOK zF)aY-e*B++bjH{JqlN!`nlDhlbJ`v2_MJ1f4&Lu{VxZ=~lhGYoCd4_Xw+?Wiy?+-Z z{+%Bfm*luEu};J?Hl}69Y;}H-v1MvPRD66um;X=M|0C>8n;hA3bj?p)U3;C{*RFfJ z``)oJ8%wj3YgK)mp1$=rWG=}id1!GRxfBt~Uq8?L0;IbXk$EgFL(ZK9K@bE$uvXw{ zc$sP5t^Y$^do`sN{zh4lO3t3J5|!-JwM`>x)}JZshNXyvc0UKnCZSn>ISav!&AWEp z-_6r)lmK^d1&;U8c(!U5th2xzRS>ZQxX+p#4A%1rY3k>`Th7k?afV*_-0wYMuO-xe z|5ZILh(9hU7O^cI{!Pg*mRm{v$*O7JcrIAB{zfKEKY!@&e%a*5s(f6I-#7`pM5*6@ z?)$?pBBDD$$S(6;8}-olX0iE^(~ynsf2J>4styZ|r!FG}?;ayYXv=S$I)-N(mi@2q zBQdf4dBoA!V%HDtj~(oh!k*pKx$k#F`8sc$jPUk^hEh47-Y?v{r)DQY>Wq&asnHa@ z6G2Sc5q;N6{;6BZ)QH}6r);rV^wHvQK}`NDXH9xAJ6(3|$sjx<-Zlt^i@SbVx^Jh; z{5tDhrSrNai0BDTK;yt3c{G^A`@Hnu_N5~L(ROc*C%ZQCb_X=zpEJ-S1*iQe$UF&R zmt|z6tEax-mjJgmHm!THzYgE+9DUF(a9H-gRKrJf-{*5H3f`Z7;F!+&kKO0bjfZkX zqo1>&&$FkPuPaIuZ6uMY?}q;1IXL!51mXv`#rM#$Jw}z6T~6%rdS*cy;V|AgH90Yp zh#)6!N+u0`g8{)~VBo0%8i%!q&u+AvS&ZSbsKZ$>t%dgP3ls?)Z9P-E84w@LjcZ;J z)1HnboIQxuu0I~Hp3PO?pPk@(SJq)Hxsb9yI_DZQhv#egY)@AYa1BlkF0k%qU0WpVR23rG1BfN{SR_`Qu zY@UJ)Me27KZqZCipS4xHV$$10E=;g@yUzXM^XOqOKtgJEx4l{nngxPYE-fuKQDwhc zwX->_TrB%V-yLH3+Bc%8h+2GM*%W|ZFy4iVx<%G>Ap5doIeWI2hsH%XhV4wUK2xuon4~F~tu#Ahn!jdjnjnWEu|i$AEBFl#w$DdcM~_fS zty#BM*p0Fw1SUZ6gJi%#fO1_Rz`Qx|&pGD}woIC(dAl?~=k4Khdk8WejT@r#uHQ7D zK`>(jTcNs@tNSJ@*0p@`xKOjz~}bV7ld4F zcbI6+`ht+B)74WHxI6FQ;bXF&5ox;+Hx8JQ)rqxlY7D+Ew(UWD#(LucuF=S8!lhUE$j#b%%@Q_-!w(GCZjqA9~_ib}_>3x4e%M4PxgOFXQpNDtk>d(ei@^$*d z69w3@-z*zy(bjUEtuMoQcr8IFbp6%K62F*6t@`yh)9|M0cE6oQ>~t0oQUA>}R`U%v z^n8=mk!tm(M#cVmS{7JC8it!p11!)@1A{31cGv#trsU;tVC#moEt=u{%NI$1yonJ9 z1V*^A8~B{LbjI;V+t0o>I)&zaq#^n9QhDV3NeKeMpO$YyuXd|Ku8y=ot!AkZt2HR5 zPEdBfCJIWmvI3zx1s+csa2>*Qusq&-cowibwmUvym5h*bL{xT;ww5uV+qo`i~{FfQw5ZFGkF8X zyMa$ZSaBZPkfFN_wLt@pQ_j=avxpKy*$$h!9wHX|-vSy()Owd3GvGsN_m&;TA>xr; zx6k`^M7L?RE2{>BnZu^-&UM1mKuC+Hwv=(N)TSe0B_quaYv7@hf&e$fq}H7Sys10m z>U@qp^=Y)$rkNB2Gt}C2=NP$^u&nl!bJ3}T$14ycjA83vN^o*kgjEsq(Vt#TEJCc> z*ra4_3~GBoK2>pG>^fYUdtZ@%npB6Rp3j~*G}OU6WaYa?Ey`ehl{gk>FR z+S%^tqipUn<=@H#PilK5wf1bfPVXqCdofM_&sXZ!D5iPp*oPj=@mUN1e;nExySp65 z*ovDHS@fs6>vD>!K;0nf#PaSi!kigc*Xi&=tE*8xMr5}2xq4YM$;xnKNy_r6O>pBq zgeH~TY%cq5$-(T$b-+!njKgZbtaCZx)xD68@ThXFoLzO z16KaVfIF&YL!p8WCa$)76ibod1ag%yCDI716 zC+DQxPp1oh8Pjf)Utrp8@(WD6O@4uCx5+Os?Kb&SCAZ#lD>bMyR`;sPGUSe@eW+5- zk??r;s`S;Nx-L~0l8v?&bDIc@E+`+)vv0o;|Mm;<@4gWK{tNLRz7YTM3-O=65dXI? z#Q*&Z@&Bmw`F6Z-zx`6e+b<=&tJ5V|`Y>_JD00#1(CoX)Ny#{E1CmbI9H>cKN#|pa zkDNnar$`G_oMz3S2w2TJqi9>YL)|^B9D$@Z2w0lsBjW4RwK9juccof73F9iy5XX#+ zt@~4D3`+k0D4Vq@hPKcbwQ?p#Umf91j#o!`ljGG9-sE_7gf}@}9pO!m zS0?jjJ9rHpT*0^{e1Dc#vG=x?SF!gt%d6OXo8?vPz0LBeF6ug^@K?WFaALwVV%6jO z>ohwY_kXyJS$AjD7&3zR&20h~GgjUDE|T1v%lucjIVHjW*-g|>AV=Ms;e6$0((4|+hw-K;V1I94?}!B?|0G8yhoZ_>Oj|$9XvmE z>mO(9i{tT!k+nG0Q_m@*bmEoC{WSH**^`Xn~&W-2f5qFfZAR6+?{@r zWl=^iBt?l1El$$1?h-vN;{Vl96g zbco(G!#*=y(6+|syy4zj`TSfzL8D_7nh%K{3mtWjn`2C*LV-4DJ{DV)9lv)!N@#Xr zRgusxBbSe67!Tx-cl`qc{bdxvrV4?v{R{-!$jS;Mjpl^bF0<^GtBdaAMW?`n-$p{f zZq{PDv|P5!tls*YBaR?giHj^UJjRqRE-`|o?BbncIggk#vZ>!hOnXGAXCy-JcZ{i6 zqDjQbL}ZArquxhC5*Yt0C&Wb0ri-nWjZLD#z$BdmBCTXw?PVV!aXs^9Xk!2ht@`Ka z){0Ac86D$_x`G_l?_DzwSc#~`nu~$2`*$(FYYf&BtK>oeTMze`Z|F`m!1rhYQy^qnaM`fLt#a*qoba^tfCm2|6xU8P%S4KR1Anh?siB z-$}5K-4P@?e2Y%x}2G{mURn*M-@yBJl1-AV80 z>FJzXm<9UlfQ7b2jXn{Y8=4eJL>y3xpGy}W*ID}$%F!r`Z~;ah2*tQrtj3<;NRO8TMg*)&RM)gBJ*u5cPyChQRyp?5x(32;wtH#VKZ$21*?A#6AUq)*nb53{T)C@2uhquPO%i& z#m?G#k1jPdtLD_X$1L#o27^9~hK?RMj0D<<=l7Sn@?WXi@emaXcCivAizF{KWdpNWs&fn`3b{$e;v>MF%ds zeRLa;bc4Yux6i1c8KBVvl=En`{vgmv3KrgQTnA^D{=L5ztfk(F2QP~mJGNcwGA9*E~OAH3q3LJLnIF)Ao2kZ(}V%g5Mo#+$vg9b-zf5ytx zlPqG$l4muZJZBT+GF5kT*RFGKMLc@oVl>>IX#4=NbiP1hQ2=q`?%clr49nTLWMQk_ zJf>ryVU`%A-8w~YrEf_*UbI)PT|}#PkhBOwhzmJLM*xYlN`G))kT%$8Ir?I3%_$9* z)bnLZfLDq2#zCvTP#m6Gle96&zQy?>*55+Rt9t=}xZ_dQJy2^FF$H`s`bXoFjxtd< z?9UEgS&Nuh_MYLA6hqEOdV?Oz#Ac5;kDV>R!tp$pW@=Cq=qNvj-`PFFRO+hBE*bo~~;tzRNAe@y(wszY@D}`;Lu+kU=y#vKSV!OThf@AtpU{ zP;9lKo&l>19`(zfJo5YQ<<-1M7u$%13~r6}jEQed-}{G=@mX{BH^@c32964`AuLft zlnFz?(dUHGf`l1SK-Q?IM?50SOE5rnvOcuuqL*eLJNC}J?>(epDfa{39KN=3~ zlt>q_bO=JAn_{54r=4$(>-5KkEjdu_oO1V(-m!`fEHKad1}2Bw6i<=)vW_(bpKv}q z9YMnG@{EDI>cGm=-hDDK^!r2C7<>;+i-j`Ns7pLferWdIV?CS)&S`9gZsY;2VSXel z`_P_klsp6v)Sh)j%niw17Gr^B$odfFID*Fqw>J!Qix~5Z{Vtlkzzil3w(t8mCvD#k z=Cik-4E${)&sPR0(n~2*PIEQhhwN_9#Sqa&hg-R&NO zHQFI2;S!EB^lP9#Y>fNJYTa!v6}EAJgcsE>!|j9 zb8UX-5BaIr?LufCOaoNYuwstc8s_ArWbO7ao9@A(d+uY_bZ(@dQI2n98rv?m)dQEhmQgdJFMAa+O>H*WPi=)s{eq5CdUWuvma1nJ_NKDpNKp1LhBIy}CK z#dm7v2$1&Q89F*tbMrF4rD=!_PVCjjgxZW&J^oq%;-~|M5xJq`=A-MD(g)rgVqC&Y z!FXVIfsf z4qh)fdyan+RvG1VcBq@v2~zIbMuDws<0Qk;#Q7zhVD^L2=QSSIzHG=3ZfaPD9Asee z9PpE8Fc0u#Q46c;bTtkP66Nf47f~>h=o*8F8sPBR1?zz7?aVb%XX2%!ZDePt=v|`! z7-rhI(KF@11J9wT(jME)@7Qr-Kynkv3PI=RL@nCr6vv4}`Q*U5jy@mD`TuwY+EK-K zJC-qG(GWuD_zy3tTUNn>4tb=9sGNiS(^|fY$BGWoI+U!7gA@l3_6;eVVoXS0>ggxs z)G?wbHtD1;2ry{NSj3v%Ns`E7_IP+eXLAQrxEy1M0$+%@)4Uqwq~S0+D!X(2i{P zvV0fJp$rN`RGx#3o#E^}NEEQTfEE3(deA?s5c0!S*Dl#FCDi9?B;rUUSDqx&f{tPv z&Uk{38XT9WVcnSmJpSD+JT|bGhhV%UwRf&Z>6wiL%mgRDh=h-OcK<`J%cOJ*H-`*6 z4yXD^+ON;V6n|!Q9FuSus{TI?yq=W;C^Q2PA#mbLxWTmm4$YD80!FXm^#2G5f|{a5id5J)r@^TF3fpuq7Cd-8Nv>_$=eDLGMID zlEiUO@*3O-x7!0dd3FpzTWSi86i6SsXP0pesFWo`NycH$acAdj^Y-yN!2+%k?t`YV zlOWW&q@aau1*XF#5VS0|_QGrs`e1@!(tug?^FBoz?CU8u)tQ+)u`aA{_&sEWMj|kj zw|m^dCC>r**yLJuiBlKgJY!40A{BVDL|KvYizV0XFa#F_buQK}+RA0>8)zn^*U%FW zr^B@2tP7d$=1Q!aXPMI`$HT+9$bK!F!ba2WqSjis53!$zqT7ArwKj41A?s)5hV07~ zb2ey#%~(UUP?W1Xd4S_^7so(gIZy5$B7Ow%$>|Ov&klxjBXoZB(8P$~dOpt!58SKO zNzJWoo82;i$5-dMb_cgm@QV734@p%VP*a%A=?VEWJ#}u`WD1`>A#m{PWV2l#WdrUz z=HOjyF#ATjA5SNIKb=7$6$iu5FWqyk9Y|~w`y2dk&x25bTyWRE?&~%c=;I)R z?iYzM+Gj5dM4)l@7yrx-AB%-;CO+VUJ%A(faq(=f4CfVHs<@8(cb-Ocv`q2Za{(n4 zFQyYwruENz+#ISsbhd8yJF!Tv42)ve^k6u22M6G40N&yZ%5k`gjCKw0(!RUu4xZZQ zptW3Lfr`W`bE~ZJ1r)&`G(U~P_59iG=%s;0w|j^Qvt||_#7J7z>qR<*uIhNm_7OJP(9tgF&L|(LFYD+3bNo zwk>->$1;wId=%McqlUUb6K?R46f$~|FPKdOr z@J+K^{!G6%R>kk){D%s`(4j@mj~T0zL+@`CW)aS&>aNTr!P{)xUI*8CZm?J)Gb;-| z=U4iSi9ro!XVFd#=PN&VDwjsEVd0^NpD5_vfUQU0X^QF+DRy%S1P*d+;yhBG;S|Je zx7YTUuEWx6nK$5G(_I&G@&M)|rZr-@TMtwgEdG#DhCgIL!J`ZGLOwbiCHKs(0&x@K zf}?M`?fPcvUa`Dn7o#GNd*_#6?WYP$Xo_=)!S#trzJ8-39!g}gCfOHwetVzO7 zsmBLMkRScl`NXYDXZrsrA3CPXdNNEcF0dJ%9e*JgInXh4`ai!f@Bex=gV={jEr0xC zrvH331$JRl+B5T_zhWs=cz){I6&KOl46(3uE#0%08bL2@hHEHr#zP_3oD5Bs!&dGv zcxlJNmEoQ1VuK8a1;!OZkFd0!w3`S`br6lr;mI;Clrp#uQddLqtn1xF>y?xd#R14o zTspLgZdzlFk$^dCuiJ3)71ai@vKOsNy>OTSioyZKP;`z(QM!w=&=tJ6xJ&Ab5~3Zk za+N+s<&L@_p+WrR672Dj0w>#WV^F1IwDOSS_XK_y8R5#giX|5D;^zRoAh41K&%*hF zvPr<{uIR%(_B08DbZB(HV)8});jLr!N0jRBG55hf*mW7H?E}t$h)e<-Z1E(A!-jU` zU^73;^;i;P0asdJTXPLcp4t&8MRpyo?fx;Kb;~Ic9;Gp4tb7u_Q0r;zDK~s*pi+p!1|sZ3R3$nF?njCcjHhRV2<|0= zJ_V(9kF^fHr{_aZT#^d&_DDrm>b@R&-C<>T!6WJsGIs*Yl3was4_eU2RV7;LHddtM zAxMav^N8r1=fHz+#fr}LORky z?Y9Gsx^^=LKZQKqknrKEk_03^Ob*5q!7xbxgmlbRoX{XX8~;S7;I25}vsK8nlGY-w ze&P-+Vi^lml+DGx7XM4wz|;9cldj{DHyeNh)&{lb5r`c6b`^;FIcVB; z%+r)%@EHM80KdW_Rt?Lq&4R;R|Yt zbr`c0EVKmg@-UXq>v&~hghFIlzEQo5qd4#znA$wu@iBxBXl0B|1{-@H3`pIV;K%Je zFS=18q@X$km?vyGv{0rX)3V4&cLDdzClWtB0k94*GX*)K`}G8XOzEZ^j}k4WeUNlp zkJn7&kUJ22zD}ze4x*`CBViVhec6YV$F5`hAfJvIdS(Ye?r$8mlo`vWQ*4+Vvi5T{ zoxFbNY8<@8mSrO-Pi%3H>K*DfMqH*lRr8q5G^*67%h78kWzI&M3n$Y=hRZ>x(~R90 zN;LBN?pa~{OTc@+$M?9;J<;PM1mhqAR)WYDb+5rI9;$>pa2mcMDtV>R6e1DJ9bi!efC1IHn0Xl(5Ao3yn&x~;Rx36aW^Oy<-FSZt6CS=V1rTg7D&C$~$K`8uUDf9Z#3g0j25Lv6q z@FmW3^aZx&kD{J@&DAmyF~vsW(gfVB%tn(N)j=a&3R|{3sAV0qs7%s7r)#IydUaisA;^Xxmhga za?RD~U3)+M)W^kQ3tV>4)yv$AVg zU>ob(_6>3dEm@-}eo)yNCRG@F9<=Yrb_zWUsw@Fc%&^1Sa5L-{p|9ZaWHJD7oc7By z$@7YriACrBG7IP$B>cu8QCMcS&H@3aVAhNX*02)4pyPaOJ7`>u>OQbmXvE;fL7%VD zR|b(Http}+Y+mDH&xmR;CIUO&Fa|4N?pt@%N&!Q!$bV*@+MrF$H~v!~tB6ak2B=VA zjGDpf`#Aq18mjA+C4P7+BD7~tWTAow6lT`UVX$floWZzVX$2y)Gv^rTkUZqFRw(IQ zQZtws%@8GV!dn^;V=TBB@prjVqvEjUVDLbBEGC;R_A${lg4VFx4M>zsP{_-(TdCQ` zyGcRfOI8VYjX5=ETEuI7HI75^RPHo9H6i$69}1Zlkc1Q0A=1?ct<3o~zC5vbJvRXz z(QqwH{d&5&G=?_)Y@7qVsm|CKpLK<1FpfzDO(fzs;6WLEE4SfM!javWWJ7ajj?)JA z#H;fca6nRurK#Tw{BSWNL<|RF;1(l_vFXwTWCn7qR8H4Yv$!+I4whTmxF{YPiV8eh6q6af3Fxvl=Uoy_w}CT5+ac#+ ziYWVXPNV^zCx|jpP(_1}nc*|GB=l?WAmJ5A)x45sKEn8(iPi|Zi1GF&R>t1#$*{VK ze_%DC<272{B)E33n`!j4VmSgYeVkTY;$4IJy{v(4_k0;B;#tf{ZB9fPRv8t2ZG+Q* zX~jg#po&Y*?o*KK$vhi9B5aU^Y&9vO*teIl;>E3)TK{QaupitJMV+CtF zL@o<2(eIEp{f9>KVm*e)Jr7joab9GRjv_O77D6)vEB5*GHF%F~%WK;-3mNUwI1lwc z;gB>ZlI{8&oR;3tmeGke+toBsnZ4GC`O|Bru#YP%5y* zkY|h2;)brf>rh>^*;X<{RtYzO9r8HKon48g&KY44dqg2zF__puHDkp|jcbluXNi-M zY_`a4-4#HV3W;%Bh`TJwp202M)a|Da+T~4gI2Up85@M%x5o7wbi;ZG33ug_aJP?Eq zEqq}(zVrqw{zpVw(#(07Aqg=f>~%ctTX0h^qs>+YJnz{tz1R{fZgKR~kCNd4Kwx}q zK|#WFcjPsyXBwtNAGiu}&)vZE6XKJnm@+#29fLx;z%|^=%BYx^a^ntbseQSmz%a<@GFSwq+=6i z0C7nkVclEP%NpgirFS;`j)PjCU%K7W5Pqc}mfr=%yTBNR%nhCh(rH=&f5>|$%%bx+ zcgn%6LNJuIyhUbUNRk~X+*P7&P$bT%Fg56^xUFUUwE#1w411tB)M)p8wpVZyEyK_q z@dDMNj3y=Hi<5k=iecO3UM6w5)is8pNE!STcC2MnF+NSAA%1HfV971VGcrkK?X3`J zpM%RC6O0v!C|=sJ!4z)Y86mOmZOAcF3Sjz=JQCxBr6)^#gQU?OCTBi`2FODkl9Nqq zmSb%Py<%(?%e}@%d{vE{3YC4BqFWi5mdK94^iU?zrPCSx{OsXqUCa@`v zTwG#zMd)Sh(0n#sAk(fvH{{C7EC&$W9bs&twX5b$5xz_t1tltFAoa`3NDWU>0t z#RH4neG<{r2>Iv-ml1e(gMeJk^YaKZXgieW?&=2`MXPbuEH zL0QFa^;Uhss-Ah7M^=OgI!LA7$Dn7dIb zdc>@ayCmu~o0GJXM?Ko`2J?6n)SL@?J@i7*7V;s65yT@8U7DHsau7-=7MJF5dH=@V zhIqnVS8%YBRwW3saS5a^zY?NGQH$W-ligIEd6Lk7I4K9ze|MF?e!j%Du`A-~{!PfZ zMV6Fbq0?S(I=sO*0?u~Sjlg^xLkVmWjG)z|V|YGL*g|GJ{)rP*B^aszq-THPB!Al+ z)e!k*xs3skD>-A#Hj5oB!t&;i&KTWagk`%;CowH?ZxDrHU_w0>JFw2{Tt|eOST|h0 zu-8^+RE?6uA_Zu9kl~H)aCt9A;@*OqaI6m!yO4}M4>Lc;6Mm> zdxu63`Me3sDpm6+lf?Mgx4m%W@$ksQ4R69MX!Zn52P#ySr_Fw$_jTSd)8SNM(l0%6 zpsKH&#@pxL*Dnz^-{NBaG07udTpP}V8a-L@h8GoTSgrH2gGMRKI|che?|LxV9JG~P z>NT(d4Vzy^;W?y1?*YBhU3HH_cDn+DjE@<*dW4Zb`1+rGiE#NKIFr1uIEdB`7-uWh zV0r!j=A$Mn?^qH$V4fB7u~C&nHW{7@Zm{`@Sq8Ho^#Tak!u?GHKfY$}qpx6Vez5HQ zjAR2yXr={;8led*K7mxzwm)HrEa)K&*109tpDYS=aUJm}$i#=rl}I(gH|V1jL67VE zATMSzgwbU7aP(-7u1>cfrmK0Jgy0j?bZdBs_+!6|@Cc$y_ zkRLsKCfb2Hog#|S4*DJ*glTq)luhpp-WNB-v3xbq1>_m(FldR%Lv`@gmUN0bj!_c* z|ACkkf2lK&Sw5UOfBZrb%_{dJdvp#B{Q^aogoj#z*z8u6tmo*u8P5%0Nbg4*?rn8cd zV(vsh_HbL?SHldJkQ|y@7d^=(@Y6qKZv06gr7&44kjjstmqRRYvB7f7bcL@sZm;T-_5`lEO~o8(%BHjcnb9+j-l(;~=YRA8FQ!TNKG zL@mZ-JS)=?^9L{J79?+Lk9*(b9wR|=D zxct*=EgYp%I=|Wk3~cxOYF$I~m)GhVfS-W>?_W!t$=$-M?OBv!6ut+Vo--1h*+$Gh z=r}FQ3ZihYBX3$}0{z6O{Z^8|Lbo!Xt8?Cx#04Q@Z??j+k?Dvj)#N#j+E78UfoqZ- zW2!fXbdV59aGFd3)CmV*(`zq~=AhanVClkr!?5LnDN9#$fnr zqE~xukOS8E-I+G2&|nJ%BfPzw!v=wmOtJ_QyUgNr*^Bb)u{gA_dQj>pr)CQksgazz z>9JaVV6&LH5_O9ko=Z&Vu|n31XKz^WwY-;a^4i+eaL;hitYPP=w-t3?3vm{_yDR{p zzd|k9y0gncP+<;a;neGOF*ss~A5u@YI{C0!3M=m8*hX+%Mgl??xVe)FHCwo8q{d>S z8BVEboGLm&px4uoume2F=xt3o$Iwg=6m5YhaYhWv%4V&xvV`er*j8#>9G#w=L65E} zLa(f;7y3n%_BaV}$w71F6b>Hsd+1Ez9B=D|n!*ih^&_69736VNz?)@O%D52)bqZ82 zKeuK+AiYSaJ8Z;8kaYti!3}A_$|S4xaFFLP!)y_dNbLjD@XQqoQ206MI9HKTJu6T0 zsRP^Yse>CkE&qrd;{@?b5mDRpzm)LdO9>ypl<-N@Ad4UzrpDF<8{!W*u9FCnE#tLeNdLRk za)_AGWN6G)M7cr&j*)QpLKPjspZv<>$w3w+vJK8SX6=V9AXPj&D*K`N7j?jP&R(!E z*lGgRju}W@7;TrX3F@e;wJSg9$O`Ls?3XUA7fMwqS;6tiQ|^O^4HGhX2WCT#L!g8( zT!~hK)ao;NOmGKzHu~h|xBU73}`$LPUW@iEvPBCPIW3&)l~8fXt$_7DiC7Bu8%=vegt$YO=~0_8C$qzXw+ zvNbIqNyFogA=-ZqT#Y$)k9f(WrB}_PDToxb(z>!ynrJ|dwNv0LjZ->@i5&u5Q}6Hx zgA_uC)1~s5JC>pprs?cFVrD|urNf`P@j*sl<4m?oNQj43aEF= zD+@NxE2auf;K>34$3*j&qe%{YwrB$hn3Zs@j2_kZOe4==_T8Yt8;ayA9*fvBXcnhm zku{C?W|q`__FDv^-2LSEqAq3FmsT2Yq8T%Ejfbl`x%`b2ViRMxN!UW38h{-{0IF_h zc8&&c3&NAznAsqo@|wvp-r7G49L6|yKjutK&V3vQI~G+PuDYTl+I^IB-L`|cZGCCQ z!;N)DoGwSvoc72UNn&(wM^;#0n)azlzf~ioxo1F2iv-JB62Vd=PE<9WddSB*lGqZU zN(Tw{)Cz86XJ;v#Yz>hyEeC(e%E5On)(4@paYVr0Vun!rr@$@b9itw{!Q^L@_YjeT zt~V8m4!NLlSM^3z0Ol^Asxy~4If`N;!;Mr}N_9-e$%u#dM`4iEV?~mx37Lj<_!i-n z5p#%FBxALBV=q%?#D{fk`*y<{+#F$Q7v)g_n9MNiAGEh}Jdk48sp$=ykRxOvVc7jbrpk)9c zENnM2IVS5EkH)Spr=dZr?>9taE)*8NY7E8kg7D-~y9-Ay3kN6x_<3{B<4U(!dJIL6k+(L>XtwIuoIidDr0S)V)0+!|;= z+>}&Ef;Lw!ip}L>(nCAihYS)UFw4E$%QjDAC!M`#r)wgX_j0b^V|S*?__k z-XY}&hs6P#q5-ogDrA0myHPM1Y_Trf6%ws zbKGTWA{<1mrPrPvkj7dS!bYET*cL?-gRh=(0R_YcLoTQC7M5a9%@Z4&-O8v-?7F=c zw;Xt*Rm_uq`jaA_J5RO&)a@1rF^~!qIBjBOeS(%K%XuTx??b=A563!I7VA^nqgoiB zG*`R0Ix^SHi|)cKMIB*q%uV4mJQ!u;RKG%|<=2!$_AQhMA$Twxo@g$Mn-5_ZXPX*# zv0*#FW}DsCth0TuRvf%cMI%BYCCLYXv1$%^1Q(&V7YnsNZ@SGz2{4XWa3fH`)J(nP z#Drv4{RU>i1BsQI%LT4#h9d%NAgl6buWYb7MlZ=DAU3(@3+FRN=3|ofXh4Rin#CI$ zHuB6b*ZDQ8w~s$dk*Qp1+vNkTrYXZZ@Ov+{0dX2`W-C6E^!V&)_G%E9?Sln|^M+|u ze|7rQ92;35I7aEJB=*h7^HgBlaA8e=*h;$82qPhHI59eT+bjKKTjBb(8e`D-Ub23H zoB2q9|AokYFUc#^WWAA1f0+qRm{-tQ?dUCH<2b|;$^kZ@Uf^_o)WCum37>a$C)MUZ zjlX5ylS$U9O@gHEb4-f}A*u)b9e_D#&zBi0re0cHKEfsVB!+pBRF;GKJs@c?@Ut(l z?_4v;OT^lWjNG&>lTW|mCaftKzeFoxJr>ugdD0#J!^pYOEv4n`iiZ(}Ic;d<5V9t) zAL#&`HS|&w^VoqqX2y_Sv%$@tH949nMl(YZV|tutcwTFOIMw0%q@s{sxR*@juoTfl zv!}6vj-B42*R^kMQ0g5Olc&(iUJlO6tHH`4O(HS{Z2{)=ka|gY4kf-qos<)^KXu9{ z@#VX3g)8y>$*KKXgMn`02utKy?7H8a_j$m%Avb6vgKI>;HC!d3kSJFMP9{X=mlwmM zx~U0ANHBOP_Ia%aSO74y>ImtVZ5I%g!9qB?)L;^MHt5y@IYGl?FNlC-gV}lulhM6* zd+A+yO=_{#Ol?lrM_deYYFV4sAw2U;lqa}Vd-`^xz1+SKl7|{g(rpbr+s8h^R}Y8@ z4DkM|vt`g>Z8LG+G2)HkZaz$Q3Jk?**fK z^#O_mG?d_M4v4LZt(DtKLO1mWRhfpwK8+dE1un!(r^xeSKht}lni-jBOYjC5QCR7&zdT_ESR+ji?oz$Kd;`Qukz`T{xY2tvW@ zo!ZI`N)QJJa#4QRK(wTRPWhhHlffP2rEeFn-iW>EH|FJOMlMvmxu6@g<$~%g->hOB zrVwFWDCCM2cK62%_E&s+P?SbtsS9>pqtjOB`v( z`SpoS3N~xB#!%gRL`c>gXo7nKLD9LH1_)Wu(eQ36`gE=hI|#`T65F1jTXeW3^s4Q+ z_1bGxl0KYZ4&oapR&aLSneig3ICfOYX|8IO3%6)4g)V#Uzi=GX1nUZ;`9brDp}?zg z8sOB2ziMISL-ABMdy*thdsQ>Ap>Se4n|{}TZn|&O;J_A^dRjO#e@}?ju%!pwlTt=> z&B1-=`ohMEB+-nUh?(xW;%!GocGAfSdWCHo_MuM9a{~7iOrWU8eIbmXTqDq%yPRRX zw!))|On?Nx0ZOMC0AQF>h$O2i+@C=i&C`!UJg#VQeb6*uAsa)DPMPDXf>8Bxw1olA zto^I!K77y|wY!#@`8>k4A$$o^$Sg)GUo|-0(1Nxi@Qu~8;nDC`N9Eh?Bufaoqb68n zd%{H)?WuZ+!U2E_F3c4#zF0BbuB}!}7Ev%!*7*gg+exGM_K0*>>hBd`<$9uG@w%&n z76Qn#>B3FVoI^gsbk({D@Q^aL5LkxNSJ{X6y5uC8k9Xu4Z8MAv{Gyrh!Ea6spDw3B2naI8+%7@HO+p zT=6<~0Rde>Qiz>^1=09`GQaQuN$@}RRAC1kWWsyQNf&bjaJkuH_*^}6^Cj+lQ9XsU zIYI~60wD@szF-F68j-KanFmo>0pe4gB8AonGc+}5AP$!9g{hhpKjvL61PGqd+8{Mb z7Ir2$E$ex7G#OQVF%LGA`8+dET4rWOSeQP^!3GcAlxR@;%cK2r zu3kWuxS9tvVdQXtL=4VLJ1=$-TASeItqb(oR~sK7+gN#zmsA3Z;H?Lx7*}XmKKy8^ zp);tqP0(eagllGvLH0~m8>v?{5IQ5F3fGBo9-$M^y?tR!g^F?5Ef#@7I8Emy>MaJl zIR2@T2A@_>_l7}+RM^YiemLPjwPDo zJsahy6tMNTV7b@j1LX{bvL>dSD`&xWYlk&SXUla)NujK<*1A@T@KM_VVgb*tPMv4d zM8)JOz{66DJ|Y=;sF@Y46SV5JS)zG@=*rATZ9%}-+k7{LfJJRPH7f$pj-%-T0#vAq;DXl3(gU6YPV97RNS<&_A#PYHE%ESeFWWAv-Tmwt5)QlHUi zsDk2QODHMdMYdiMz?g1H4m`V3MtBm+0gnTpMY5<4Rx9qDkw2Mk^*yd*8<07R7prN? z9BQyCf=3`uik@ESBvAaX#WZ^r1u>m~0HI7(BAO$^S^=Eflui zK0QF>5)nG&(vUhp6h_FD4yx$i$%f3F^aKYHYM(}Ptd`%$y}DV?dJ>3gP=gduEvC}~ z)`;Vn=M$T-QH~r{l*1p%@EH>eG77Hah*hhr!m+Q4Az#>->CR!n z2XebiN#UtX`LX*2MZD3NWDBf?K&bXYXam_Z#W__vA*ezHW~zSDkiBVW>R{xHM>C-u z-e6Qg5*|Tx!(|LZ1Ih1BN=nt_E0(>>>kb@3cn+01mioA1O?xaQfo>94NW~=Ta=go< zSrO*s3LaOf7SK(k@kym`VlU=tZ=%Z5wF4^kKhA*~o_wMV|HenbF}A2#^Td4vS@K%< zr2^0m=2x>`t$)>>mjqhJ-)c;56W*v;-OMIRvgXl4@Yd##_j(-)yo?sOp5y+Azn7dw zIC_ZKN$J6hhi8dN_FmZX8BUBkiX&dWgyyyn(K$_yKh<;8SQdMkPSgO$8q+HxLUkop z%alx*ED%|gr4M9pA?L)s{J?FjFqGn)jdV~ASPZGP?QI6eQyq#y3#qtcqN9q@n>~5P z`&7hgd!F@X;{o@02TK(qr{=*XBs4KooY(~=B*Gk_lvg3kF(GF-11DsKkNaYA3t|sT zQ<^|* zxJlti#FNF;V$VjZQm}B~V$O~WO42>4p~57qf0Yd3^OYa~GL6`wCO2lsNtjjKrn zXFj+ViWpQya~bj;BtdXAYN+T{1xVE4VV+~ryYK&+3b2E*c=7l~o{({>^I~yLl`Xps zGA44;@G`b42Bl{Ew0r_>dtWh9lSQYj!HB3B=!m?A=CTO+J?Am5^6pH?y?dKC^oWW% zM2wGGLt^10SZMxIEMXi-%Y-6P5j62p%?TIPLKuwAdHaIvJeU&LAFsL>h+~meertc% z#LYXdaETRCMOGyaBa14{;t&*2c{BN9GoB0xY#ObDE?Fy@a3NMv298C>f-32cS1T+; zFd{s8(MV=%91`Nbk>c~R*-gArIL{gChc8doeniM9tO>+cYk|FqaWsto)Ns&PVT*5S zsg~Gc3I!{Cfyhz$hDV4a5_N{n8k)eZ<*2UScI7@!r45tnm(_>kqypkHhnkY{vTl^j zd`z-l!2Gqp%=gLK&b>z%j!a4;W~O1x8XxL(meK6E^K>~({;J`FD=Rv{5Hbl%VLXp2 zrP6i}ElA*<3Sy}S3g@by=jYHL_wp@C%Cax^{Ls2ep@3_6u1S1!Dbz&|-*t8Mg|2(kt7%x1=2oeN|c7fCn+sE9X`NKC@RdXNb+Uy>fuFM-Jm5>1LJiDf2(00o}s0Z z@&p@Niq6jq&6=pN+Nso7!1C7B@X$gtYX+OZPhuce3y(?LgYD1F4oNPERSTCGRmMbm z5~V^lE*)wspQhP$mpElKQ0yp!=`p|}Ab_cRaw@}R%AC!yFDP0z8q+f%QZfBzCe2SN zCY;gy$U+H2T@P5C|4bfw^a_I7$GjbR2vRYj6|ziH zL@BHnr@dp-B{Q>&VY}U!nx&AQc&fvOUz?>uozEhaxiH`t)Nt1(`;F2W)T!daD<(u z#E>U5;1+-6(l<|HGrMBT=YebMo16>^rzdQx*KXBeovgdK=6ldZX|96!8sLowSMpsO zOxFcoKkm#qLWP5;)ff9Ahdq;pU~D47?65Jdz3>LaMCih66kwub)hE66v*?hGYspBx zpsFU9wT?D-pG0I2;{9s%-~lD%u9z43#UM@Zir0=hbgEbli{8e-V&HC6t|sT0~GJiVf@RSPih8r_)(uKf!u zr5tFkxcy6KDs)aWl#Cgi8-)!~O> zWj-5%G#@zAo`CBYVDY5IXXahAgmNq9i-7eA!4RVl34>Kr;@+0KAE)w8E8kl-* zaF`*mmR0b(?}Q!%p}>N>yp<@%UQ5jSae~H+XUwa4*E-QwJwO9SnsLE)6#;R#Tl&B^gu?BUzC( zF+_1%1kM}55HU|9>K1=!rN~uf(GjUvCp&H7X*^$k;!8+Sgr!mdve7j@5pv$8CL~ES z3rUKPjF>#VF)Oec#F`Pc=zw*Pf)sl6xaGyJp+mId010m$l@B=<=tN-JAvBu+pxuEIJIv7hri;ILESc-&kmX=QFt*U}%Ca5#3>zDRXefR+@A zzXhKX&OGWviLzA0Ga&7F-luY>I^89MCs)%U6bYkpZ66sLMcC4%&7uLDQ>I*WW_HgxcuUhV3V|ky99@M#<8WL{ zV@IetY$F{KRq%vIebF^)fW_=C?lKn1t}ZwVKeU%s5TICN<3wEGJ=r_s8pVy7U5!Nq zzge<%^gd>HQ@%$~d&cqcqu-^9}} zq6!i>tm0-Pn0sop%DkSi#HpV2)yeats?eRh#uCks-+p_v0|CrwIHEH^Bz4LXZc{X; zRj^@3yVo(NM#b6PoKubSioD6?<9cW}I0E4XG%i#k4u#dSbWTTK%*oj?gnddd7r;l* zykX$vp_xnRs*aDvJmB+Z<%v^*O_jN~1ooUe%Qe^!MnwZ;QTSHJsv3hghhlcEIihyC zw!zOtV^id8uytL_<|)pF$4C-xWBu9_a5}15VS?n%Y_{Rl?TxKNB?WoTe`9_iR4n4^S~>)EJfOg{m#(ZT4(E++M-L$2s<>x{$0aPe%Z|_hFOM6elrFI9`)`OXv3 z18{HRtaYh!q~lTluCf%@j9N|AVf!hVOcX42mla+L^^4xEP+K@@7)STIoQ$hef}4og zH((fH>Qxz+%Or8Y2TAYiE7Nc+&qr~|nhSpfN_*QLQF;;#VocYm7Pe2rcB+rsxX+n4 ztWDLHu5>i&;#J4g0CD=s7j3mHpxDSxbQMG3*Ew}nc}(!LNl}SP z%Wp3$%aSk=mw~+}BQrr|c*UJ+r{UBrgZ2W4$QPh^)Gx1x`Z`vJX`cE;bi3mnbw0&> z%ScmDw&)vKf%#n72qXO$&Zz&EvxmR(pcC**ez`>`l6dIL{Q|@uCO9OA6+^>YknF;> zi+Ra$SHqSXxEni84v%r&PLJZ)@*GB-(#RiLIm@(;_MvA3)^5o|t^Cck$#c5|5Sb&n*H={M46rBhnuRjJb(#4I zj(!rH**3+jb9kMSAtRJo2o|wef@Yk0#IaYip%#1{QO6F!G{@m0%ICzm(5}Or@`r^S zJgnw;cMa!=2y>JjC9W34wev#iu2>q31v^nr9X(Z}J z-WtH=Co-E%;jDHU198TQGOR_+@Zk`znKf=5{3cQ(0BzQ0(*7(XW24Lb9zmboa|Sq( z^Y0^T4VNmikOtm0KaWg%7K5%7XY~X@ojwPT566DUj5-O(_Wf5;Zfg9W^}<0w*R!I5 z3x3?u%C2$7x4BrGU8~{JwI4;T=gV_e7B=z;i3pUuWj4zD(b+-CZ`q@VGI1D+l*;Cp z<+^LL=4A`-QaYwnWAg~#or#!cV?0%0jgW*Dl=ZIJ!ro9MV6D`sZ} zlQLQ0f+5LjkrRQfB_Jk#_+`QoeDHe$b>!Onj@KLo*Q*gEL{@B&ml^$;yLyN0m&iN% z%ykC05PR;&9!kduqE5iuX?Bc}kq z@R}LFlQ5P`K~d}svr}-Ea|cAL-4%=hL%2|busyQMzSLjY#+=JDlPTo3JOpf)^+HPe zAq(OlG74r7*xYgDP*x434)cU)LT{AWGBum3M_kdZ|Grm~~Z!_-Ota^RkW_7z~ z_{wN__x#;CKe1XYh=3(Ki>=@_bDe*^> zDf{DN7GU*oipo(y03=wF!=%gzqmctH4@GAJD=&$o4sbd~bFvr`rr({jLOr3;THw>> z8l1$)J=)7yj+Bd+vAT@^hlJZ$Cks-%=*#Q?bW=Bm+Jz_99vgI26WSLHFbi}M9G1Dm zu_!E1!dvQpNZdee@_1TSs8fxfuYY;{Xa|d@)sn(&omUtEX8#Nn`%4qiR z=`%)vr;eKBFYXWSnPizL?-kG#1K%VXRr-R$v) z4qR@(7*7~kB49>y0(GIxBq%Mey9jp?BgM|z?N~$P?yw<^23W3oB3_9;?HFrxg%=V% zZPgW?YlrbRR*xe1uS9O-;NrY_LULTrEO@T1d9QBLBMsqBU^2JC$BkN)Xxs3RpW0|3GgvE)1r>VTA9ckr# zRhKO$PX?d6UW~J2HG~qn3B$5JDX+sOit!+_hf`j&PQoFT#|V6= z0_Ut)qSB_x6w4j5@=z%19z)gppwpvL(SXQDMGS}nH)Fb|yTBI1{hWsJ8S`m`4K@@} zkr~q{g_Himtj0v1NEA2NZSb2U+)MK(Wd6F>An8%~zBQiIC z%O594yBH_8OR$1YJ<#_skbm2s7+L>3;H?M!hOESks6Tx7xlu+8s9g^6+#_YPZ$H8Oi*4YF-oSNJ1>Pl2_LGGF! z^qg#`LD3Y4n3@|rF5*1abdSmA!csjS|?3D?QkQtycRlJuc(y4HdV?}Y_C)x!a zWA_?^mK{e$O4W{LAec5)>SN6Ni=cKFFNScWmrm3x-m%CW%W~DBr^CK z9ly-L3@#M!!H+zH3&HZCr6D8N`hsxwYmZL`j3y?U138VCADw>h?vyAbTwZ!5Y?fc^Qm`w+#?w$Yw+OF&IlE5=G~vvl);>NFd0-%_fICYkpKsogxVO8 zSICWO`Hh+#-}FtOUx~|o+OtyP%6q8>C|0NH7~(Zf*6yyk?{Iz_opQuZYd7Y=;ZlhQ zq?ps$J=Tux9_PIYIYf3t8D;|ZP3(2H`HD1KbW4VdaL}CyOZ=eaQC++~qi#$ycysnN zXNhMIwLF@rXOwtOqV+_T$hd+U4WsvC?13%rzuuhkLeht)ENZvn8G~#giw&u@+eA;` zlX#!dd81OyLCGSWHC8?@V53SeJ5Uez>y88oT_{7Tb%-ip$v7*B_9r>O&<^V`Zem;qSSNz>=usk0>EoQdzmy>+KJ^pGM(@S-9 zQ#aI9IV5Mn9$xkd_ua86%daQ3l$SLB{7PKu*dJa?)7gF6odnBtsPM7V9I#(vYZGw3 zsi8`yqYU<98WXamX&G-)^r%N{d%nqP3CEAr*`-`Ixa|&4b+FEUvkVhHCE~{i3tTqW zpG3&}lUvBWN({Kd(hG-QMjk&`UUZdv4^SULgxvuL3nYJ9a;h3P=wuBwDw$vQ@xkmx zWNDj$vF!VeF;w)N2yv=0QLbol&c*o@`zRQ3IjZ=h^4=uK z-w|6P1rcwuJ|Cy2vh6LOy|y#z~s6ZK;L63mxnI={V-v|wb6ExRj=-xCo6 z6tTlzd81?$oAbpsyG|3zK|3(ZG5`Nw+qq9EEAu~I$+2mlg)1e?UG=i7e!cohN+~;b zH+X~F0ZC3W=1>U#LpK9*+^Yk+Pbn>q0~&LDaX`*8>GlY(`;=0>7q8*(DH~_k!RY>< zDoi7C(*Ln{FOo_N|M^0L}tD zLy7vJ95Ive{g2xD+xXJ-|9p{tH?o_GCw;%EcoJVK_L}2`Vrcu}{4Z+dY|829j3otA zNNf=|s`2~e(ea)iywtO&RNtZ2aZLmf(zZ{|_h>iECs7l*xpYk|^YCh?>{|2|g$Pgz z$frV>97UnSRwO7L7Kuvbr=9~lh+Gnuuf_P{(T%CR^-3*#LQ3G(5J&WAcL1< z3oWFQIk}bT2(^X3Rvd*e{KakY%VCQF*+Dy_9n0$j+3K(r0{9~w0|-)+U|A4?ene+K z++8ZgNhkus*!_*2xEU}`-AD7HBXw9np6pC~M^WQF!c}kRHJ}|;G|@S|y=F^BK4r)7 zvOPw-=f<&Gl=h$GSWahJMYg1qyAd2QV?nAa>m8>bIMln*;$=1hd56{6ZQYFJd86v` z44V$h42pPOYNj^W|64CGxXY!v4C?{XWKOxol1L(mEPbX+4sNcP27A&=U}iI1!=OgN zKk7+xFNhimOts;UHpQrpWnVko#v&j(3&_)m z8O3kEb@M?1#oX^&W40pfIUIx6DFbR+DRG|mni`15E=mDYvPlK*3}MNLO$zgSWOVDn z)Ku8>Q1T?AluoG*<5t1d(*2rXu$R)o_Xj@N10|eOlyE2oUml7h;IMecbPP{KYGWko ze2kh6)^KYnu3!?B)5{pA>tqDVA5d|OchX6CIA5_}8XI8$jZrwa4r5}yO~K>2RHHi2 zCAtU#0B)ZKPh52?E?=Jj^{LMYRHMZCNi$+#*Vx$W+%+zYBl3 z3xB)|f4U3*Ejx>~k=xUYx~6Y(1{@!}8{{!x)&?vxE*YJ}V!)ysy@+A14v}fls?l?hPz*9vtISl(xY% z0C2d_km#-RbqKHnoDL%WJ6|!)h!vP+k)EBj<4uC4rtF^j5T*(-^{z`E`Fxhtz0a#| zObCInx{v1TLnu*)PyC|Tt#OWQ+_=EmeH6h`Gms5SrikI1!MG{vI-CiYmZ2UWLI?^S z(e|#Z9Z?i@L!@rR>_n^F)i3xXZnx+KljK@4Q`*T&5-*T3^(>qc*yuuoLDr=PPTq@I~lnBagCbpujM_Y?2Mi_D%TXr}DUBoUt zwHbx9*JFc`0`xvgK>H^cgSHpe&}_H4eVnLvU_eF(8568^axSo13d5qB4eT z)S>6&SU4Vzj4D9;fVZ}xyBUZhwN5avCX~6+arrJoVn_5eThTVwTIx_UN7UqO{d!7i z$V8@eI?HBDw@K35$eX?&s?zyztoJ6VR4hr}%Pi4?PN!c=E9GN887I;r(d`^JEFBs? zo?1hS?AvWf!kRYs)q5xXtZN%EaO}9z%=hVYSSdhECStEad1=F}Qh zYbDwoZd>x?co1YdUOigvQ)P0Z=Zav{^U$3tr>!PQ4t0ky8|`|%IzggSOERtE&PihMWV`l1ApIa~Oup>dQjS^~&6xC4JlExqo|va)-` z-L)GKic!y#m>AXlyFQLqHxAKFw*QndWpvsnb+4 zt0?<+Nt^aAk;a&x*)0ahc<+!U{)8(Hgjk1l%x!cS?Q+JJ>ZeT?i`tSF6Bi|en=C0t z$ZSb;W7?zeVi+JuC~JD_C*BGI_ENc*3L_Pb?5;I}Lh8$0z?OEqXppO;%n^1xiSrr0 z1bIWguH=U}#*?#ThHMgjKjEH{NxI~ErL6Z1x#?325}xbkgO{fQx~xF%W9yMC zMjC&vOk7BGi}gvV6XaH(MXA8lrmMtX4bRc`+pTE&Xu&3QJev))WYP=XUAw zU!s$UFa7pU)No>%FL+z#ytoPD*X<^}p2yaE$^6~nHvOuXPagDAc%iX|WTqtq;I!^P=g(o@flw)#vM2l+2C|oGtX5vmoJ zG>NyO!!n5`Ln%0r5QVaXgz%MNw2>stLlo*Hd_U^LQ;~L@{d_xyL!Nu(Q7CTQ<&h z+@rRtnprQ?W=73!jgM!O1#o0729GY4xzE`wyh3wMaFjKiN$CYdXAiQcQc@ZC_pB6PpEK0Dey1;uq zTA+T|A=Tv({Va&;PV80KEo(RR&sJ|fvrj@C2gi`OWx>=rp>$l~N7kZgj~JYpiL=u{ z%$YDtwXj{&)xzPZj&y<4g;6vEIV~s$WkyiT+BCD~H5bfHvH>RdFNzVIf&+W-? zT2Rb)PR~Az?8T=avq%JlTtYlL0XLNJ<*N)eGb<+8%IxtNQF2bo<}Mx(mjfW5kfJle zU8YB#h#EHj<$)O2p|=&yau+!+`Yim}1kDjiaJVQhCbYxxGNg26)=}7RQbz+=OR;*T{57OFd@F2Gr@@LhwxboiGVTi- zneajF+A-MxuxV~(tcjR%Fg4ahR62yPs|Yt8(IaX{xDfGZWaiVm=)UJ7vWQKYv{g{v z6Pr1Te8{!yfR)viyk#~fgUET9w4+VmK#5968Fy9|=VMPjK21C={E8CdTET4+%Gon* z!yk_fumULY%^ZT$+_G=XDy%Y#4vt)Nik#TTa#)t4t{iHV_gB}B8!MD@A5nW_JSwTcf=QQa`M7k?6 zm2O*R?BLVemr?ItM!kO-_2FgI$Cpu`wC`u{X5a7(~(?X}oA)lQb0^Pc63 zU^2H6$%!X4xF+6mU1<&_EcZk>crw>Q{MD(0T`p9~gx4`9Dv_q^3>tETqFN_2{b5RP zOs^q~!8>yztINU195tPe|CKX8%RC6W>t@hR2%U-4IlY;!j{9Nx_`qL{IuXtwXDb+S zJWq}h3JQvuu3%=G#6s?hUrSf2yECFcdcUbaKx`TpV1&{ZXB4C2JSY0ThM+_qc{0%# z+aAvCcHAJ;E*C*wp>WMklZjPm86)w0VY5@RCZRNJASpY~&Z-)nJN#iE4~pq~E(i#H zazj)9EKWCIoXYNxw|$>)N+t_#2Z_gSV-PUy_t?2}HDJ&_b(aca!#=f3t**NyJwSdG z8kTqol5Fa#jqpXJwtvGSdRVvN%;?kHB;6pIj7T;c^Q$OQ9EiiBDECaE(|GWccW6si zvua&g@eD=F+Eq22;O;T3z@1#->L*||mT;iC0ktMZI(K6y3qiXoo~111_ACh|MsB}1 zJmW06fEX>@d_>{=d8=W>i^TE;T~!Q<9-T=-Y2yaE@Qi4MYXb5U**=%GCt>DKLnJv)3I0&E!hsqnc$_uK zy!zB{s%cEvO{I%7LpjrPvU(W%%fa=!Awk#S>#Ft{!d-gW7^nUvor zpS^thEP0^FcC?{VeP*T%pgcQMyqCN65@{WtMV%Od2}!(U_g&T3h+g0j%mBJ@htoaL z2TKtT=mwF46OyFNmHYGuOco~UBB~igGN;zYP+ZUxa3d~&D|DWQ3r*F25b^hXrw-ha z66Y4_I6*`n+dj7N-MN)av)CHH^RM}*cGwuFpe(!v00j* zyU8lnO|=HZj|f4kgH(|-dmWQlAMK1)JP(-l@%F25^FdFD z>o+~P3#qp4I(}?Et4n(b2%rV(hC-%;Dx`o&o3KaUaavFZ6`Gs^2ztBFj#$2Z{<0;m z`dDKTubYgF5mF=y`)UkSK`W((@pXBLl~<#<2PSaW@MJY^@p!6bfPb;r*!@w!sevQr z*BJOIwi-GzDQJh|wht^BIHgH6qyCV=&l1cQy3=RIWfC>K&q^YXAF|PO*DMb_^Be9! zHP{+`+?cqJ;VX||9YW^>$}O-Sfd{}TyVYxhhCDsv-jf9?*y z7W}$9B~ZHKrX3k@a1}jLR8I{aIWFE4xbw6%KZgMCXrU5L?kqrM`XLc&D86R6pUnX8 zR0x)e=QCEi+A9%-knvzxT(owfx7@)-jD7JD~Qk-3#Q|Ax>rST?|luP1tKdf&qg>DL(rf)(Y`lpK53QvU3>h@fj)^k0T@4 z&Yq?jyv1nkWZ{AuM*A!?s-mYQb$#?Y&E^QyOV4J+N_`58EKI|tk!f{ij6J+g>QX3^ zw?J=54rvzMTum?47zxJM!WrIW&gCSoVp8d3kr~jcM#kY0z#34V0ktkXbr~D$-e6_H z74-EeC*jgPkJ9mJ<>I;GeFqppEq0va>9bI^uqdGBtp*C>)Ertv!dr5L@g!q_m*y))hHksq6iHU5@x_ zU6JFJx<06`DKs2Wz%&KqN9Fu#Ba!2kMw~FMD;g>LR%vYt`%m{{bi`Mij~uTw|F`?P z9P!nD|G2Nq5nrtt?wi;}ixWL5U3xrFg z8WF&{shgK?L$MiJ&UUyQfudv@gfxlfD3z!4;wuhh+?(LAdhngw@?FT3$gsV8 zRoig)@5w|Z9khs=S6?l#MWUr89P*+PnryLmQR$jT@Jshlf=zznjRAM$^t6TDzFiR;fY2r4C&sQf5v8A+6CR!OPuNp3 z%lJ_AO!!Od$K9==QdT$;xvdSH6agRI{dmv92!~>vJ>`gn5Kz#*f_heaj2JbkNJ02$0f_hLPA$f15YhR@6LWv%tQgA`?Tx{;;xz?cdj!Mem}x;Sq|y@~o>2br8lBumjv^Ym zw9s8@QXcn2+#L7B@mn!86a&fAE$u$NtILqIuz5Z1r0_U-Cmdhp5M|$6UqgC#X5aG!b2p|vhi*`2(?TCFW&FJRWRngXOkf&N4g^}( zM@eJi`y^rs2ZXlRQoSURR1CjG*oM%iC03qzj=ASJQ z`SpSG%Qb>BoD`eyppY(2-Y|a#g{087p+ddL`}Wn1<6-w|!$+A!>SBhuj9=1!Sw_%5 zp1Nc9b!#j$K_CiKpfY^}ojJ65cdyl6<@4Q_FUD`@mTiN#s)-izwu%JEMJp&QO1ak@f;e4VpXtbkPn34fN>B9hPt`oZfJ<7=BiZ ziZ=UZ^=3;{Ys{!ui}mvl>8S}pcHGlyIK9!OjO6AXYmON+pl{~*Om0G%Tf~v!Exz&5 z&hd6OsZ;PH8$0U1A~p+iOuZ`+OwO7;?E+dT+2F3V-Sq~bMgu3{4BiA%Z;6X`@)gJg zjmUHE3^i9_;rB(XT&qN=j~&3Gl7dDhOt7AYyoky6iCDjj{CmE98wsXGbUDz|Gi!Lg z0y5<1`5mP-uUb%`) zHVLfYQMZ)io*D@|NaW&p@C0{Qw#NLNw>DeUzc>Y%EE1aW_$jGrWfs$s1u?-Rpp*OO zP=jG60y%SmgRt1sNv2NYuRI~`Vey){=ZhbDa6q0oq72UBS}}g;p37Ac$D;K?iX+Xn zH*EYQ$IFnH6k7#%>$yyM?|qgf3nrhsc^?ssNeE?W`PhfG471K z2?3QDn;&~JfM?oR21DaGTJEPPlw|d2KnI{2h^`-Bjc{V4EOB5hAPwqgc`{tgSP2k}QoPqX zEv?=+4dWYk?VGMnx6;TAyvs~k_j;rAwBd-K@&Y@c6BAg{ zx*kGqP+Yf|+9)HY|H+gsl3bBLZ;CVMFbgK`5oh579^HXv^^E8XJJ~SHR`E+`s$4&| zYtSD{jC{wKnNwBfFh-%yHK_$q;pS)@>LYZcs(3$2u+!nm8N5jyW%z zovakx`OV?56}P0r7^FeqWZUnF(kTBO-@l{1#%l2Vsu!c4y^<3IeDb^rDixT2%GgGT z;?6%SLaD;uh_AbooMAE*`gv0y*v290_&B~rmSx-i-WOJ`aHS)zD8 z(2|3R+I30!!{g?!Ln`kH74!+4? zNQXJHL4D!g1^8>hSR| zx}Nf8j*i;nK{;yIj*{>DktybGpJuA^cO{N-(jgB|@r3`cR)}ua4XUfJPe#O=%tfQMtQy9i3 zGZu;9`rLONb$2pt(A5Ad$jOHSCsdbC$&Q$7Z)^AhV6MX>qco42_=E)UTp+_K`8QUu z5F{sb_N*B&)YSmgpsg1&&Xi7|^+Ip4?0Tkb^mQ<|5A|r8#RosX%{I7~%(byf28Ec6 ztuzESleTp8JulS+)Y@@Z-pQ+-0_uLnc5j&gZ3CU0?rkIsX(PoWWMQ(I z&qS+D*Y|2F%!AW(8+Gf(`m^|@hk730u-pb`6SUvp5}}p0OqM{AZ`r(4(Mn~&2`|9ma9P`Gx*(5n zpHNAK9dd}?N}Ijl(P}r6wH)9%*w9sq&{WckMeU$|%MfqA_?UytiuEePyTCKxayZ!c zy_JBAw$suK@u}sR&WHb!CBep76yqI8Sd$UD0yIvxGuB1E%to7Z1^VG0wB1NBExQ z%-`Xlk(v-`D(rOHjg-$3=02>Q&GSpeuON#cqNN>-i|Gd55RCd!DXG-=ui6#(_QrB*O7~ z@8Y#57a*Ea>{q!@GK#S}bEH`(=qy*DSNMyxE4XtQrZThu%XIMWURUO$O)*NHjk#Om zYnRqUR(*>gK5lawyj-tJFu@#d@73U09x5pHW;PJll<((lMF5Z%;ALP~qdrb2tRYo0NgV!u?9Od8OD3^}M7d zaS1G=4oLL%QWibg5dZBGacA-^A)gKLdP}oTVAt2_k`AB@f~DTvHD?W+Wqb}T!1AvY zMZTG1he<}Ws7e+DB4R$0=E@`-gay0yft;UK;?H39IT9lj9zTjkdYTO2+}Dn+4A9A^ z3AME2($)gGDF6MBC91C5VKKwbAS?Tyo0UyPsy3f`4he|T+y@go@X429&BI!5wz_R$ zm&)c(H-$xV%x+0ZEHekc_kqHg-{Lfm?0QhlyB}jD793FuI}Spt)_shhz`aB@##9Kt1Cf{eZ5QOMhSOBUqreLGf4PNhkJ) zDIOV2R@Vu>pRzf^`Sp*T+@yB~Lo>jug(M-D9`26=ra zp7|F66eX8scoj=^gc~TaziA^>pR@=pNo84!5MX9mbn)(o+VqOp0?m&`FgLcZl96m& zBPOF8YfRhggTu@{>zLA$mSGYgz290E$@IxK!JxBVdv}!jel9b-g4SVaBno2$7))b} zuDQ&H8q;1RD)@&uAK%gYO{_Z&=lIhi8BeSbdr=!Kd|%@=-&zA0kb4Op>=`VeJlhon zlf_SILxYJ2ynGlFh%{WcnBLr|?a0U-MBg2tF-(S7Z3Q!vc2{a938*@POcGe65;9s~ z;E^z4L&l-iB9pD5c-aW})iT6VO8?RF=s@b_sbdgqBX~@SFG=rHrAsmCYSvqEP;KYY zA9MKGtSPPZH3)PS=){cr0>;3Y;=|=-V{&L*(k8GWiNjbyopc7L&G6-3N>ShCjl0ID zVwnFO#dy(rb~??m{^biUZGCyZni-EvYzoGe7`IySz=>hp?GPZ1|I&zqK}36SM5W8C z6bzx-S?PuPyHqN(H6aVS1E#nT`rZm8sVDtkjG5y;;AdyeS}l=Jpm3%u5WCi1IfXN< z?*yolOrH2DhyF@!x3p#ATteAi{1-g6`Ev)KRZyE1>Nc8@hLr%9B0IY70pW5CUwnlc z+&c$wsZ0U_a}0#O2P6#M1OgQTB;iYeoy12s&JjYJ7!1$!iMm>X&af3iFt#?sNh08d zSq7sN>7-zRK;|((UBSVE$559t5rl&i<<)vT7-NDI4+J35lxO6I{b$)!cT_90YgtC7 z;sjiUJ9%0u#!txK{$)?w|E&z>u&##jER(v~v0++VHAa>)`-^lB>^VsL{wT$&*~O6H z@szW*3I#d{!rW6eW_CXOT$MAK`yLOr{VB&n17kKI)6z~;p2Gn1%v93D?%R+Z}w zp$-$s?FGT*?^jle6^B?dX%q?Krz4(qjaKw|wM30+>&Nu5!!WBY!$bOSX)nt#U2$Pp zC4QlTR~vgAE)E!EXAbRZ>N5gKd=aJz-`94R9bp74+niX=5vrvX25`~p>>rK#Kb7+RlD^n4luK4L<$cd zCLkwl7<96Ts#y~CeX8!!xKP~D1q03s6DM4hYz2r%SCB&YE2*5CdIN_t&_sq`vW2p~ zV7&ji@a1$&?$$8Q3lQjx*VhejVOy^#PuH=c2AV6Hz*P~m9_`ejymKU~C5);N*KWb9 zF0%;vdW*_OOrH3_$GhJCR4tH&D_~W@1`*>WV=wlTMX6*>;M1#TV?Y-LMBOe{PFThqlQKz z$OP-3>`~}-L+yG6-b-;EHs@1m=^MbSgxTxN8a}(lCp2Owaz6!4a@aDPc|w(g7ZS0D z9Qm>VXxus^!=tNDcN>gJTL(JMR>-7zgCTn_uMilK(b}lw-2rY}qk_Y3iS4!HQz~`x zg!A!4Oaq&yg(&Jtb!fZVqd<&Ccg00e<4TS;;H2D)q|KSO&@cgcuU7y>e8U{ELe zTEDXp6Wu_jRrLYkx_r{><3_|%q-*TBKj;3UX?6Vx5Ttc;Cc#Xo-^^ShgWPGt2_Y|x zr4smJht%^09>OIZ$(bl5arpWKMZ}>6OxL_K=&hd_PxLmED!Rl_2T2;@!JhagGaOeJ zY8Qgg(^jO+xP#H7)m5#6anyIUg*E+Dt@|Y(3^%~cJ@v+s)Jl6+LEi;D;xPs=-;L(P z=_M0LwUCRcq$_3g6Et47@NE>=nGB{SEUeLMF`Y6d(~3xEfLca;8%VhXJE$|AA){We z@^e=#H^6Y|VriVpMmaTpVKbWzLIA*2iD%oiJK#8F!5zaEmTW|f%26Aq zw|L@5tekxJp;8YIZ(l*Gpg-%Q#35#PNEV;T;tfy0DEA-AzTNy6;9N?ZGIutjgv-pWs7%K!2@ z=f9jnA5z~VGE5)5eY35R3}yU)N8V-A-?h3B296vJnl4?%fduRMxr-FxSZU|fNt19U z9D@~3Kp_*jCu9FtUCsm%!b-`A3+mf|K$J!9^vb8K&eoTmgnp*z@v^bgPx4&m-6C4& zN*Cilv_EVKkXj4wu9htM1v@Od{m?r^v9~ZRRxI{>{RTX7e#f+Y&Oz*|cK zT*0aVJuecjaH4m2@_ocPo~^5-RN+(?=jSK8Pa$S7o!|Gbub3~C2Dn%(Go#fPACh@( zKPp&E-*1@z(yd;hjAK}%)te1vA`*U=R#rbH*0Fiwxp+Kv5EDyife!N`d-I4!5`8yQ z9x8vI|M4I4Km9}g=YPom?H}@g|A+iP{vrR*f5`vWub2$HKR;&P(Ez_+WKenCZ{Hpi z$iz%Vd!sq?*(Uvs*3#O5a60*P3P4=S=&mlpj4u)PBg}KMF7`z#;ZecqOaL|4$D`dO z`5$(&zUguj79W0FZ@`qkH-x<~y>`}C=8q44PP|`ON;Oe8)Zm;h3{*GQAfT-FtdvdJ zCwlO7+?hMhGX>%geSEt7kn`EMm(5u^pz{j{Y8(}@MX1{`^7(e3Z>S$v6Uc|Dz`DS^yTK~}dU~FBq18|146{Z0Z3YNBB6;MPIB=aX&Y2V~q zHu3F$j)rm)67+%^rqa|RQv9IL9=D2mK{{-2#RSV2k_C_S@zI(DDZfl~1E|{tQ!?Br zn;DNGofL}KH*M>XB#tcCqO2eg2;B%v6(@xpbDUc2B1iNv$k*o=G)d6;NN*3XQeNwz zm#5zf$~%IEfC~Dc-h+)}#`Ai=1%pS}*$H}WrC;;ND7KK<{d!TvJeE{<_HZ;b*v(7S zGtM0uSJ<|%!f;4)r5Ga&x*%~fk7Ux`Kh&1|avZ&djI_voo!Hv0Lu&#{zx#$4Uq~&* zkoBw-Q~FmlJBcOr4S2A+JQ18r?2E9KGliwnv(I8J^t2VYDZ=f5Hmp(oM(G5Dgq}r6 zB3-&Q(v}TtP#$f)6l`xGcxmB2$cl>ge23dH)n>{b4?S1rGG@vmS41XsFOife>)jG5 z2^xw#0AdYVB0|qtdg+QIK-IsIf)yUR&(f!BM#2lWGW-DZt&FM->`}1J&=-q=M^oaV z6>omO4ymHjFF&mqXjbY9ZjsObhQ;rPk5zRr=&+RF81xYVS{Kgijs4jCBG~3)w+Zei zIl>uS{jPfG4lpSmFtc(T|1n+VOe=BVE4ogzse2hNtLkNn+CNkuH1V8-vL|mw| zu8~A50G35cYC~tiJs6SL47!$neg4ar6bqIJ>JXf|CPeXfL{I4NGn^-ZcF@LBUr=mR zqNIWXGcio&7Y!_8;7j<>tBuD96}kC_9vcG2@m! zWlblTq05g48_gwg&mb~lWMz!->O*YGffDG}B20<58KO!5b*2c#m^^dgGHSDfl<&+e z`C+VBcY|zRU7XkqkMTH|3b8?SI58>2kvZ#7e6Y|_W&?4^fj>*aXRz$!Q^8|70-hhmj2 z(zAAw?q7rQ6g%oOnHd)?iwIP!gI)%-o+b6rL=)x50n>%H7x%UzG>2sV2%B zj0`w=?!#^gZGZM1+LF*vPgjO}5yjCh-2kH$EHHDG)mZ6N@S#!c=dw{|uo*02{xK6o zQBP?}a||Y*skq2}4%(RU;-r=G7_`BrD-Lp};(0A?K01(8f~`1QS^GrtBbyi|fR-<- zA1jDISQGIdi_p?yle2dh`&%MK-<@?J`<%CI5xYgW9XGZEj7?6p72NS`1TsX%CkmNQ zxLk2I-om05tM9(X$yj7%A;X2Ee8f_5LRrb5*fBu}2%3{~214dVE!;9@KX)H)0YBaX zequG2pJ&a#kad1`i8+);tt|+p(e;oTl>z?COaASd)rXE8DhKYTwo1)-XmlCZV3Y_i z%XvgEG(${Zx!d&6W~dqMq(pWyHd#B%m=M$6z{8UiVv5Z`gd1=NY@mkAeP$~q4nYB_ z;}Laddq;cLoz!i3-1c_i1eG_l+aYO+VT87|r^m{j1bZzF@mT6wMuw|ZJtJL?7G-r* zRyletyE>T@#gz;yqF^nif|usg6g-#pq`Avcfq$9BI7QC?TW}QhUm~9{Wgg1%cjbZ_OhY32dq@i_l1VD2RHm+2& zAWGzg@-ww_gqULIOv<{|g@sHI3b=bKpH8cLDG?agXdqKN0VblyrIW}fPck}`2AGJ7 z7(@6<#H73_N^9gGOWs|L+civ1#6MhxhNz~YKe9G-MKK%&40#k({CP_%F zNkwTQMOYcCnRrD~dj=QipG|Q+m=!SVL(&2GkSa%5xVt8gz+&UyJnSuwmIbJz@G^t# zeO<@L>pF6)ncJJ%`)Ez?bse9s>&VS_UB{<)>iB$J$FLpev3zzN;N%R?JMl0BwSW24 zebcvrA(%fF@_72EPXsJHy6#_A&17sK8* z*vJUPj;Ja?^!h@`Dbo@fl{v5kLYcqC>k5%P-oGj4Mb9=r>hH_V7u}n$l|uh;7738I zMSD!$y|Y{AC=XBqvE^)i{g!$X*JVl1ai0*qU>eUwt6|OK&>Vgbj?HOpu*tJ zY?;{F;I_rpo6&0k@O~~Lw4MQCs@zulMwWsH2U@p@fwd-7!-|`g3^HT(F1E!dJt9h+v|p3ULRyB38jbOyu%0qA|1D@istn|&zk-vB+m&HLMjy? z2l%d!e&P{i#10A`2IJ8$`Z=a+Q*qQ%8@fuyR=*LVnJ}LMW&I05m;hrfNMC5-{8h+a z(X_uB0reGqN{+IdHmP0u^q7Itn3vRoKW^PaeD<{W@7{EmOVwlgPD*vZtVRJ@xd8cY4v$G8 zvVukMz}XtpNRm-f4ZmYZG~H8G9we235Z-`7P2Kvlk)&Q-?I7&^_HF$`5t(&!e)sA3 z-ykXV)=%5$E}jnnHK2tXH$qIKPDKz1_6i}iJup8KF9HjwxFw1l!PACLL+st~NNDAw zHXHIa3at#bTUCJeMNYU#saGYL8|Ek`5n9w!rH*<%t}#q<=1I|HP%~T0F+*4>`YofF zC{vq{W*abWDZtFXwydZeDAniO`_P!Y&SIHTe>NQKta3tWj^6h|&J;6=u11@Ysg(*_ ze%JApd33fDofKLis!35iZTc$q>paHvRAO>tn z>Jf*_kc|KGmX@}Tx}4e_4^MRXO%I7|EMpRrPo1D&`Ll49QNPKcJl+7|kb0Aut$HJ! zA>n$SwI4Hr0AIH_Y~C~umV7y&J!D#f_w^2<+DO)>ks0MqyI2Z0c4kCgkr1iVhJ{jC zA0CxJa0pf;Rd80gVbEOtnN5&dK!!4vm2=oL#Rt<$h40+6GX^RK-mnq?affX zd5COX(YCL$9I7FI2LqR|>dII?muf0suqqF|sJd#6Y~+6htS^|r%Jc&HmUxC#Sr0jg zRT$YZqp6#dvNudbgXuGK43RC1gIH<$%er4fs||M8oa=FbwKu@^l{=D`eUKNY>)uY! zm@>+=XGrV=EmK#F-$)Pl#}wAl(u6N)nIl8tni2;?FpV_EFng-HWGW3M7L_d+jV7P? zpiq0dvdrGlKbbzfzP6`p6T+(@S%xv;PYH|1Q|jgthjf*LVkh^AccSbt_4tAam}v6Z zj~!oS%8k^S92ZYK50CzZAt!?=wD%x0sVD$C=Jb|Q1SSjyjsOZwUE|A25leTjfYn!+ zpcg&&X?3-KXcJ4~)Vr$8szgym2&6al0n<{@;3+v*%+<+^E12w_lA|Hn@MC&yK%18y z+K<;8CnuJc42&H!AV@g~PTB;>gHALlU#!ICC-Q}>PQI*JDnP|v^~`Zxp<@>!e(o-8 z6Rn!lEbexoNzNG>gBS?9Q?KuS{KuWjq}RhLPOi2v0E`q#h9=zY2k z5z*g1{NE|_J(r)l%H*)XrdXKsLNj`vhJ_TSY>#XTMK=iJTAzGJTSMKi^yaTsl=5t6 zp(lWx!9l?prUApFDPGg&QD>8`2@qyLhz^2;xwcj)R0%UIq#M>$22jDDySYl#9D%o# z$f>5Oc1n61LADyiw>;sqF`cKxLG?*cM=k(80wBXfe_w2`Ea-L5auBl{rW%C$N*$@o z4e9C;Xwgkh%pH$?wF;wdJ{U}$I4APNcnKGhGit9px@@ZG<))j zWr^^7$C0VvT`$|I_%Er5&Mmh%@JF|*djtA z>5zBSl?fJE?2-xmv_07vZ8Fw~P>)uN28r!kGe2uc1e4 zF+V3;wMe)YvjIb^>k4#Hb(%E`Cgjxf>d_N;mQ1C-(HWaJfjB`66vA*7FVe_b(ebDa z0ojYKkORX`F2#%>uj7Av^3l}ah7q6ha%ZN(t?rNEv#o$NvM_~@V&*Jri$w!H>URwl z6pZt!c*;lxePrK=QIT(Pp(CAX^O1?O-u7PA^6>-UMV7M55;Amq`19or7R#* z3PpK$R~UIg)ynJEG4m7hwz{0A-pZor$pz|;0=Jy-YfcMx15(*Yi&gNf$Kz%DBpl)7 zy@uu|%(SlM#VLxOKwxot6X^q?WojS3A~or3@DB7nY@)i)I~^<|o%9h0%$p_)(nZ_z z>48DL)RIuP7}8`Mu}yMtVZg4T$PAmvg#(pZX;5N-GtvE^=026N!nHN}tE1FzXwuE( z!AB8-^Z7Q33U%;5%brWte>OpoZ1?a&Bh+5fn_@z4?mk>W9JX^R^XaP0=PSr>SCHSY zAb(sz{shCD39Y0_pWwv9lWCd;tc3}N&jRG&0Z%RT0 zD?H6P5cC@4r{d>QpRP-Nz6Skv4f-7t?7A`T&!tCL`l?hRK8?y|l2+2(kK;>|F5XNVF{H_`(H z_o1^)fi*Ai0%9J|U~cH$JFIGE_|DU7jEY(nAF%bVfb|8$;{0PT1#s#|O zjfvmK#2;hg&oS{YbhEN+l1d2*jp&M_BZpZ1mOZY{SkA++m6TtG;+7E67o0{9KxAgg z<<#pWzI+xo^)3oE3EwTXtK1bA!o7 zRgwELhwh}EKI%e+5P%;@h+bdBG`q@z*o5N11I?5}zpYV`c7WrOJl)MyR>=>{5|;j~ zDF0g|SQE4nz?_<(ErHbomU^n9GNRK%-EHz6u6?TSCK04WP6^B9Mi7r$A4k=$N2GWq zV1rcfganeGnaL6ikG>6L-=2;C3IF4f;TEPI|>A9Fp>&DJkWym|z*R z2;g%Eo;Z@#ama2iqWV)e32{N{r5&L4jR&ik+Qh@2Lxg zl!K#a1xw4pNH<@&Ga1$-Q=bNG*f4-oI+l4NwT6Ovz_vHk+&QP$dWmun8dmzc;@?Bq>pwA9fqr%^D_bG2pHjQp*lQpzD8oCPYs(>aws$~#*ar8e^-HcyJOj=2$^7;fv zMfh1Trrm*1iG<0jwM2CT>@l$3^=5J>K$T?fUL!(3nGjZ8vmZ@N4_rjr&nisGt&nTjNVk9#Xhx7LE zm58;rojkwFEm~Ivn|l@^!h0^P>}!QDX=Fd|A<_SPQgsP`la94k(C#14&%(3|&ek ze(pkMv0f8k#Pxd|RfBQH(CZ0MC7qGa<%W?&Hp+5ibSKq})xwOU(&MQGj_5u?-UB+_ z+^^GClsR4?yU2t7_-OQwYi}Jh)iN`mz+gt0dAv!wFAOK*w^fAF=WV&B)p1cjGFP=F z2ZmjyH6L~H#KFcGi+t(a?5?R}#x&!sWql!3t43_+muzS8A*o8wS+lKNmMGt=%o^() zrh$2_rk0dZ!5b6>+8;{SrXB6~49EIpL%+JSrl9)B)RY1t4i5<345_kFGgVl-P~cvL z;__J{>Qxk^%JwR(ktlGl;^C@_f>haFg|!$3?p3U>swha6?NwOwQQ%%h9i)9A1*x*V z3TsOW+^bMblf_&Vq{{XxtYIl|uR=Bniz*6IWqTFY$`rU)p_{rz6$PoXy$Wk`3f!yM zUR6<$D%-2D_NTzTiZ54H6r{@bDy%UoaId1C$?GdpkSg1&u$HO7y$aFz#atAm%JwR( znJRFvVt-XdL8@%8!rH6?_bNpA7QHA)mF-nn16JT(#qp|&f>haFg|%h{?p2iLrcY-< zs%)>qnzjP>D*n3aMM0`;ufp270{1E;9xUdfAXT+N0! zmQ_W-^awQz-3t*~ryy@c^{^fTHdSS$)v!~5B?h-6PcK=(Ia@!qr7>lYMbKB<0eie? zC>y_(>`#1PD}iRZ?2ehiOWw<~Fam16tq*DeoQnU-s;x5bnc)qF*SBeKZ9yjml2 z1+8y9AuYH3SG$ehXyn0m>N#FKvVCpPs%YS9A$ldBFfK6KbVaY0(E7&n<0wN5X4RNA z2W_cu5DdcEQ4fLXCKv`bH8Os2w#p$3ppW5^UKXo^WaQl&gyn#OgS z16c^$)})mMP(47T-^i>XLg8801a;yQP%kGUpOR6+$WVT1acqX z%W^2-fl67?Z8r{%{Ji>!a@Qo#TfnNPMfWV*sm*%JRwR~C4~_>js`Lw99cCM(%PD>l zX|EvXHU+(6XI|$?JbZFgy6Y_4xigS%jalt51zWi`f@sam<5|HeMS__K1p<4Nu1b@J zluw)us{$yFy8=2)G{O*A_M?p0B#a!-?Y9ga+HXbopc0#=<1-B+$Dz8IG}g3%LMuHa ztLyLp4IKIdy47y$lHp(`m$0g0EdSv~`GVal|M5oog54_r=|=g2-75e2M)`u>D*xM! z@&&t9{`VW@3wEpgA2-Su>{j_dZ!j$QFw{lR%`2DztNb@^kK(m}yw1+(6Yb)$~jD%Fd*TG7ZQ1xXw( zRf>mM5lCbK#|zUe?!CgPNhi5_vS4BSm6Be8(YFkRClnQ)AEQt3c1TvmjIc|CIdm4` z3RqvT2+GuTi|#F?%8tO)?x5~8HhyL$O{K%T0TlI32X6M_hI>zQcFf5)sUasY4$NC} zju9h2Wx~1~GGKu%fO?%>psQgpaPExp9zAoJhhS})YYD6`AQa&SLID1iOhR?jEbn;t z(e5ELyuM?+?J}7M%0bBn2$`7PG*I2svx2&-)w}dW<93|txS7p6K3~4V+3ch-up2bG)Qe-_V<+B!%e&5U##XHg8cfY0@j>F+=Oq7irl7t!)_G#00Ft%}q$8 z;k&c`7rg>0aG;W-qptK7;>(Uf&Fp%2^mEXW7GajTkMQtpDw<4zCp{+|y~ho3%`%2( z?kx)<(dC=xt0kByCbXiRlpYC0GVirHF${?(mSMyyDE`QK10j~Y?T4C0$qwP+#c6mA zEz5%T&0bPHC7xKX$h4Ni&?~HGnOy8T%S!j55xWVO70-}~R>d8SLC}g#U6WAIa z3$=!S=&c&weu^zQHQcin4YwA4E{2xrd1yc1Z=q)`T43F*)AVYB4WZ$*PTh=y6`oEO zPP2iU_SRBzK>S`-(w~5oBKKLloZ0EBUHLW;3mK#Y_;9*tp8YO^wsaNMSu5HjlNwPC zd!JIYfZ}f)j22kdHYhxRYA=N6V;YE=eUbTs@?<-s9bn-A^b(|0zi_K&Q#$BkcTtz| zXqhFa;s9rsXhDrRV%F>GhfHvyzv`rkBrecWSejoL{H~gFXU>{c&ay0&8ipMwy`6R` zOSIN|O%WB5lvQ04&kiSgNbF!(h;35ufb= zGVr{%_k#W*S}+UG+j=s==dBKXdC+`dYYgd+i}a^OdbLR3FVcRuV5rYd7%wY53bEc& zG@rn>1P75E)3q<+MD}F49S{R zR@z`iw}@y+jE=Uhq4f>;<6Mc2kn#Fm`HV3II`2Cse@s_7)+*uS#qA@qN%YN;H^gxY&Ww#9J!$wiv5k5YE%FeJC1XSRQ!gGf!@n9PV z9`kUB#Vq}YrkP0QC4t}QrjT}oU4ANPWbt{Gh9U-a)m=+Xg-N+0{67$WKHj3Cu7g}r z*>!q)Ue7A6SS-xf{RqhYRz|76edn z9pWW3LoTnRAu`D1doV_4ns+4%l@VCv5h}{G+{%l`e#aam2Si{5vgYl~T|9&la_(PS0|>Y9xTaxMl~Ob-7fim{Y_rg|BK43 zzFD4^UKD}0an$pUFPz^pRo`1#>LySf`PIsI4g08G&&AfeFdyq znZhnMNnm(pp=L;xW&YD4Nsr>m7RK7nI9dZxCFzssi}b(`_95nXu9wbRMXOz39_-r% z`o?Vtrrb<^q@>H+@N!qUSJ@n;fl|$Gf1;Z?)e8s?dVjwKb6$OerAOxR3F#lB8r`MI z&H8=559zAa=liIW#m|p9p0u|B>kE+52U?6R(W*hiaeqL@*0ok-GWw>YuI^P_L8@K} zMlB-s5K>Ylm~)nbTzp5Z{%cQ~NMOP4$oKJaK>D#0i)Fcazz#j3r`NVdGBiUPkF)^8 zBhlajoa1D67def4TEN3OqJYp6W}wnE17cR%wM+mM!^~tW0l>Y!hEf|?J(tZsGf8uX z8?)G%lN8iDWb-O|@l(X&4bGwdlO$@^_30!!$_zUI7F)&sCv1WaaSN=WK|*4Vg|Jw7 zlxob{Pr3KqpaJfd2UzM!d;ytXVPjp_Od z{z^}LzHJ|U%UmzXNkqD=OHt{0hsyWZjLYzgc$NKq2^y!1D~a!WbHWU z{bRks^d(HhcDF`mh>Y^;64=gT?k^0%-(=sY!k<+g(4V=At87=n&WdKFyMZJ^$|it| zu~>@jvac0~)lmpaUe%2te=7%f)<2BWg-zQDCoWb)u(2ldg*2xz}6o=Y4G~aQ_{X0 zN7;Zi^9Z@is=9KGMQfZD7m>j~W%TLsX3{04;|`fbv=PRT7^5hJ6-hw$as3@aCOq=w zI_w}1uL`eiHqKu(C$`-7!E;d;_IYk9H0kT(C1crywFGZNN@8#cBta1nIi9Y3H)>r) zDT7c5)@->qqo&AXu$JQrI(}1iJsiI&=pugFZnuIx6PR0*(KI=ho@avVj;EEJ}h>d1Dl@QjVnLRZW? zaf513kFqnQYMsjZD4xn1Qe~NjRtv{8STg~tBm-<2ae}iQ7NDD@W6w>c^Nb$w-Arfj z9tovIc}+_h@8b<(I^2!VIu!zJaHjd2U_!Yr2a~NEI%)28c_4>&tSQ&+&07a*C|)WQ zGfdVDsX;M<%4zIG$VtJyov|Jp^=~Xi+N%yPR#%k)A*U3JnI+~(e<)DFekQ6<8BDSArwLR%0=u(mVE+Lo9t&+J7i+| zn5nm~;7&_Wt8?SV?~|hjp4qx$6vMo2pdXB6q$kxHy*_XJR5g1eHRw$#H>T?o25%NZ zPyI+&ZMHOUbtfBeU;AGFc^ z1)6r)e3M8e9bcdsJEMcZFm^^+Uh4(AVW?xyhj(+d_22pC)4Mq$5bu2R+q*fxznk;N zyE%WpoAa+JhgGOKNVD{@gUqQOG-}Vh1sCikXIqa#1K1;bo_HX_KWZtNdBSd!mU{}yUd3d^<*nM7nPkIEa z#2dZ?sA`2Ky#09He3P4D*m~i9LXVe%It{WW1(%PHo$e}qVB)cafv*eco+GldGsDYs z5Mdpg$UICi>|wU}hEY$tgDh`20ap)>++JS=SS0l8489x=d6mx;RcV>D9ad{U!)ysT zLXARGhGfka<3}+sk;oQ2!CUk+ya#82%fLBq{J@BkQh>y36oh^*ipTn)FBc~zWrQps zwFEZA?hg-b4{>WLQwob)qc++&U~%gTS{*i%GUvAaz_zh*wBq)LGLhZ*a8Vo|A+K4U z{9UzKOrx|6y=0Vlc!FD&nXm(Q%9chiC;3(-f7WNgGlVxHwp4LL)LiNesj}c>oIrY~ z%&QV9omjgyWOGPjg0TIm(S^J?=Ab3Tz&NT?$Y%>Jj1T211}2Qp=jw3v#B42L)iDMk zvnZKZ6@=P!J+*zil<}vZx(NdTws9(0(_$cr4#y;Kx%o5Bn`Se**G&%kovI&#=QraR zgr4VK?>3?;zU%9$Dhx_Dt!zA9=W{V_a>~9__z4>AkFv}W+o}5*uD^wLbSt2`7zZz% z&}rRDFkAz5$gz3-`V=1k*hkb}9Rd>Rlw)gjX(`P8|XnHq_N0hxNj+Q3a1F_*| zSkP!%W8n){2>dvLD{?)y?@=>HG9|LZjjAY zTmp{`AN_>c45=w#u#WSk?WOS(42s}Wk4H(xHvAPGl^2-6iPmfyUn4-h)6Ck|8tkhS zVnu}+n6B5u^glEr3`{#`BkM=se8=-i3}A$wl7?4u zuBB;0g(gg~-RwDF8!?FyGQd(mYgQvf;O*g6N0+ZiNq2@d1v0afL;D*x(nNt!EC_KE!uYTDN3bd&RFcffkgVa;EdpF}trLeqPgNO) zH7Xb^Mzim(fb|8qK4u24n>QJB5&^Amz#t+6C~ha4B2)rMP!Xw^b+T64S|d$GQx7p) ze*NX{ELFAK&L5sRzOB`%(Qa0**RN5Dnk41FsM;)6}i0rzwgyyZlPG6q3d%s zmn$cx)`|MoN&@T^Pu4JmS^x&@ZngfRfXR>ptl3H(M|nK^4rf36ryGM%v|59}#_bS2 zQ3X2rQo;J36jPYBD_|`HRcLmf^&;BaMyA=pk&FO#pLrI5GFh~fk3S(nE`6@o|7eI_ zRN4~+(5%%_6x0UOKFC_CIzuz}p`{LgEfSc7R{?f%!Ki}Y$*v@230hE4FuPxLu72`t zmo~!j)%$?UOT7u$!nRO*!T2ru^mdd1K%8dcjB-LF?Z*Ud9%9;5-L9^J_85xkeuv9u z477_pFTnk@3ZE!WQHgb%mAw{d&IXGx(0xjzJPdl9IC9K07 z{V~3TF}ww@@0bFNUA4#Uh|Hd6shQx!7oDklKf6X=zT==%%81bU4faw`@okgY*wF7} zRX3QAp-A){e7^$L7bE`@S`xZ95L9MlNVeYi;20>ZNIJB1EXw*`lV_e1T9zan@v@uIMY5f|RM>o}0vSI)gIjO;>gsIcICyArzv9_}-Drdx=bDen3Ta6puE%n9)jx zIb5vxj$fQsOjD)eriXzQq;tvCyFh0jVP2S~wab0OA=UME32YM#?R`JD2I9qCR$Q4( z9oJt>FU$J6Z6T1M3rar8@?U6+G)>?G(3t;K0cc;-G@@eVGYJyP9S%$zIwzOaoqTOI zfu3-pVwV4H4i_F$St6-@cszbq?^lP!f>t##vdxhryWw$$8pbjcowN#NwRL*yl7jiv$`nSgsW`V z_vkB~f7E_%DL)>XyKn}O<#-clO&bgMdY zvJ$gf@MqU7x~rL4^wwlB2(i^0aJ08HQ%1d|QmYQOk&6 z3TMnCkXT$iLt61en!~Mar*JEGYXwq*<_sVWK$45LaD55hKgwwm<{O)daAHo#R;RCx zpd&2??sa1&(3q|)+w1rokR)e z6d^XfVYP;2b(L>IWARPonWgBdu?)<*a7orGlW<5mM7^5aKnFB4X6b*^|bz)H@`rXQs5my}NI6&J`bjIzmAh zxBYVsU6jeD*&9J^B;#uAR?kd;YJ&sa8NwJ&)cRfd-n=PQXI&wOhM=9GD(${SY1QYx zwN#a1u#a-vmp9gGkPuAJ3S434Qi;YZ-BqSlu@5({jUN`16i#5PI6524PYf)&8Yadw|Y}d9P zpf%z@NXL!7YxU}9Cw>@WGxBOgDj8y_71x{bxwO-Wtv8yNi^p|y^3ul z4Me00n8cRb$YZn>en643mnh6)p1T}lA%CIfv z=t#(JtbiegPGZUH@5!?fZz~C3d9)#ade9?{F+G{=Qnu$R$ems3+;M4#c3f&F>yEys z($y*NqV`-#LA_moj=ENFEr2tlLT6JI#$o7Eu`PWzCe0Xj>p%$+p7PrPTD|azsQ}Qc zC*}$<+e2dwN)t2ok0FNvKscQ;r;5*rzk`S&9q6fQ!iP{RqmgkLfH*c34PbrYdSJ*L z)uEv5vEe4r?lNq}5hg|MF9Ka2eJ`nh^)VeS=d?hco~kmiYHe%rd~#)2_R7FpC2dz8 zYf&F5CRl+%pw(`Rb7t_yRIbOcbkgPxcb!n^7H?+MmyA(b>SvoGMrEuOmdz634^Pf- zah}axK;V0bE`zEz`qA&MYmIY56_eHFbPG={QWiF(md7SYRZT~*7eo@2#u$+!I2nOt z55SGqMlZVq_wniQyjumfGI3a#3MXH|Jcim?%CL>5fc{T_YMm9147hessHdt7sMs#G zzW- z72fVWS>H3=xSxuiX4FK95SY>nSrVd-qI{XmadHy)pDN8 z=6AnhJ#2`uKIzh(T6(JLjxrM5b$fF1)o(pATzpoQL?|4Tkr_k6m`$7NT{!Va~_g0rkO(ce3hhpYKD+UGuRz!mVMt0k7{M z&W(p6#Uz#`r;UDR=~)4WNrXrkicU zGeOo*(BZ@OI~udY<-70CrW>KP?^Gwyqp#E^(3d&1s83%o_auQ+r*6B-M1toSngEFO z1~56Y6Hxcfl=)Xp97{aj>_+ctqo%$HnKu6@n0q3Jy;&2?RPwnlo!>NR63Pz|sbol3 z<6z_yGKdIAQ#sBQmdnX1&Jk#>sm{yY9YcPLcZGEab2zLRCYqEKJU46kZ7|?qab&}E z;rs!^W=KpDLs`I)<$Ts`WzR+sAr?M8x+4}T)t8HRg!^PqOaG&zund`ds>Z?e1T^N< z?1sO|IZi@|pdj6zRG}N2YAymSW_TfPD{kjhd-O@N?A!Cbv>wl9Bw9*GlOC35l;))r zwZ;z#_Tud^M{oOL11^&GWegytK=zd}r3|TP<=Y3wG^VQ@OFqHD7l_amu)Y98r%b>1 zMQ^U5^$m;JMAvYLf(NEk3$VFi7biX_H2U1UJs1BtFtEg!g-Q3VeB13~dA91%h=GNs==RsCjc z0i}vwW~|UBiIAYaVR-&#S?Kl1b-yGz#hs#eW4bueRm&tAXi1rl_0(7fTeWb1 zgGu^vd|L5;C*LJD&q1;86fBSy99`FRECnTOTA`Bz0i%8|(o~-ACSlh{wtiYX(>~=rg1jEigOcLAt_-5J;4T%0bNe z>tuCmU`K_R8`;@E4)3D0rWnw2!Ea{()HO zr|v8aOIDL9MHdu#z`Mv9k;kj%hNa@HqCN`@Or-1GC@joM`$(rv(|e(EPsgDbz2C1` zD>iBY@tAj=1Fhh)_|l&S#G#RUuj zpiPKS6-$+5MkP8&{EZo`K^E&#aXDwAzkJ8I_^rs z_OtV06I4?K&gsHXhnTJgQBoq!`C42r!K^pZkA*u#dnF*OQ*eBm-OYnw-s_rm3HaRntaKq?D6w)yM^iEw;$M%s`UboY)gr-}vC{wKdiOe*Cz*qog#Wyq?@lf%Z|z1;-^-1vnU$gH_O1GCw8Gu!E+4OsF%N*6 zb4tpErTa{$BwsVBlj_NFEo`>$ zqdg0NbGF7NHtxE`2BlNoNIT22^c^@7P)3`gvZ+b4do@b?LLq2SvhAJ(9R%h{&{r`& zm=`}3IE0ZlzKe+P>VS;o>}nMTAdxQqo^oI1*rAJOyK5o&$K@GhCZ?DD0><@J%_3#O zKDl_)o~km9&7m5m$E*U0D#4(_r}Zqe9&HtCS^Um4S^47h+cUa-6Hv*ycW=)MT^#!W zWJ!gyX)nka2m1&eTeH5SXb4MvIp6Ez{S?mEwus>nrh3ivMV^LARRt`K?&8tOVC`LC z#)%6Fnxcp@TZt;cT&G!sYvsroDuOgl@s)owl5W6{J6|%Ydd2QL>U!LFJ$%sY>5UN} z+6<|-nbQ4MK~PR8IZEJYGLq-5$}$q)L4&ERSW8q11MTxBgDWntDe2i7fo3_FE!V!u zqQQcBVXdjpi*K03?v)vvmqO`S6#%x&1gH+VBt9z+Y4z~v1u#Mvfb+@JxxIVBgWfuH zqCZxs-p;BvXnentR^d@G)TQUQLB4|inX)f3a^w4q#G0l@jiaY^OJij<)lPu1y*VR^ zfOj3Ph1R2j1+lYhHNmrX53xJihI33;18rx*OSPRj2CSh3s$i=;8BB9vdpW*|ZDY|I zNW2l&9kA(|>$vNUmzk8L`naCZprw8}-|4!VpwjOiM{P|o{hC^zlSp0D%^&mL;x?c`-hYl51$S!4yZX`@<9u$tuNm4KVG2 zlRZ^sSk!<Q!5~b-#D4k80AojAdIK4fv3^*O3o0hUicCl<}EHHdt z^v>wa*C`XsT%V>98Z%EMiR{?$MXpNrrcc`Rede;Hyu`u~OIk%5tRd26kEM}s_SOuk zvL;E5?Ay@~>}_A(8C0biZObqHM#r5~4B<~y#S zRTBs~e{*@YJ;3xu*A#gF<~_e!_x|n4s+Hx$WK9y*?h#Cjz~|6SvYZ0#sLhGMFB8|L^jN~` zV}>~7v4`0Q3s99dk5o++kbT+9v+=>X8B%4Lq@L61!V-47d@$tmZ~|84A@pJh?Igkf zV1GPAq(F2q!CCtvSWXqeaw0kgDp^>M%dcv~qeF&w;65o9TEG`pG(NCQl?V!21vCN7 zIl>=jn%v|Gz{;F2K-C=m4aJz4yo@6fmRP!5XYPw%5ASiaYDu$+$!wM`)3EGMXtMMr zE!LL}9#xpZT7E)ZKJqu;#Y@|OlHrbz)bD}K03~19%c$6 zT^Lggi(p9>RZO^ zvB-^l<2Q_Ys>;xP-5KGppW-w9Ob9oX1!j^H9Ll3C?g_IJXq1du=BJ$^D)b;!-58Rn z*BSuo8$TSb-*lrtB3_s`oXQwgK#>QK^{%YU0Hat94OAMkT)gsVuMX(AvSOlVNR?$8 z&9HTuz&CTF(hF2e9>@|qvo)rxF6IRr4+Y0VImQ%V?TlIw#elRi`xU_L(eEGGxa;_^ zWt;3|o+HIp_;5k@CO|b1_&eREYI@C0&UdVW);A0=LX0x;)X-B^hIy80ik_%yfrbh* z=!>(O;(9=h5@CYdV|nPyHMH6R`{rD)n|ZXnb&jg0<%E#8hg*Z6F;P%|`<4m2$pyl2 zmR8#fgz=$Ud9XDjGKGRGN#f$eY1=P9^!wXYD@ZrgI;;tZvRCj6J>#H@t|LVE3*koe zIM#;siug<54FhV3dyJs?*)K5Z{vuOz`SKV;cbf~Z_Q8(-qCACYGY|K&RoEgP-L{(i z^ur`xK%eDKDD0R|L5f#nSYbQNC_}sg))2vt8<`O@_hv?YNsncZ-6UTSGi>zpnWiqW8#?Q-l)paOVR61+lu*KA5*+zvCwgGsF7P&xv(u?lR``8k3>+PvKKg9FK~ z>Izknp&)I7L&gg=I8noi_?O`EVx<1L+K+)vh4Nbai|vC-b>@ z7BtH_UFAAb)F#eS15&vU@-NjSDB$eD?DJs04uPoZz|2vM?7IY7#7S+tP-vj{{|Kl$ zSg>cAC~FD*%8%Jcn=2GT z_g^qtJ*}i;W6&$7pQZEJe4|$@J)kCoctTCcw@SyF9~La=n~d{}=;SxQrz%|DHQcGA$lrrrQmwS9w=2f^x0d%NA4>?H<2v*KfAbY`vFp>yx5bfJ&&L zLn84iwp7h`D`R5U%1opW^5c4R1IIY(ch$kxHB3Rk&cne%pKrnIyVka)lGb*}D2WfP zj4C?$dd@XERrRnchBh_|te+uOw$rdE}t=kzm386Wgqq`Z#GEjOk;#>Y!Yyk%);luuu_{E!#qxd66vh zboA?5^=y@bp%BwE3o-l9Yu{p^iGWafe40~Q^5C;D<4Zdk_63VHxv7J@c`*s$Tb)G@ zU`X;j!QZtUT&sOLc^0MDRX|kdpRu7>^UMoCeKeNzMjA^_J8LXy6dX%VILTsFV>w)g zUm!4*i5}C{9gwTwfp#F*45_kAVIAh$?U3{#S*1o+W$~0I6{Ld;OGO1kvMQiU!S)tg zN0(;ESQgJV(e1qc_Bvw-75CnJif$NwQEZ~sc%4UVIrEO2KAP5qX_ZFiQ3ibCqYn1E zFay#VZI;cUr0V>HLdsjhLW-x*KHFPHz;AQ<2VE2nqS z=luou?Fb{sS%)&h@|2GcXYR!?|OLxNkCu}?^7qHLQwGbg61gVovduCrQ;WLOA8Cg3f&!&R`79-bh((- zXUP5#Z~w630BgDuMZ}D=$ik=bkKs9GY2Cc!3~Hrh^^Z$(trFFw?j|ecE<2ch+Kj8` z+(Hx%04Ij=R+9SCW%DU%hs z4Q{zSK;@jI3mF*$jtHi}k7BLauJueWt2n0XYgSPv(Bg{=!c6<>EL5}RMCI*SFLhq$JRG-loF3JPVi zz1OpZA!37^V>x$_QH;QNU@jmb#`M;VGD8ylf`7=;$EV&?UvH#sqfuWc>&cIFMPUh2 z9e1dwSL=hScdJNxuRG%t^p+*d^vbw;0Qp!5ojE3s`dKEm&cY}->>;oM8$=#6DlSghrfHj0ocHVpxr29SG4uLf9jgJm0l*AzbJ|q zgkDywav$8m9Qh6CR14k8%ALkahfY=%y4`qWsUM+qQ1NY>As}OA*?b3j>&l6F3adMd z>dfYltf>I24EBhbuAZtgt)`fPR@1yL0ZuRS-ftQZj!E%OkD(5_;S*hpd-Kgx!_)jZ zHfm6CCVa@F5`4(=g{?up3l$bz3s6i;0hmj6EuiF@+N4Y_>f{xtKl7`nCu0p2F~uV z@Z*r+yxML)6>+FRsw`bR?~jh6iIhc4tM7VwD~=mtNw9WS-P7T~B;7^0uZ-7O(M=Y% zm8=$6SOfh-l3{TU6?QG zQuOylU1xF+VOJgp`H;u(-^&^-d>3tLI_jfETb`D8@;p72x9A7cR9TD0G+mWrUT-;V?_|dG zRVM3M4lu#D8-deXMobaQ8>pD_o)FnrL^jv$u&U7LFuqJ83g)?3z^XjkTwHEi5z#oz zZ3=28>pfZDu&F48^cL;K@5*PRl~w}N9X9-!u5zGcgU3*q{spK?voq&lSw#wv;B7WY zktH>c3(IS0RcopT6UYsS)$K0pR5kD@*0>2xB*cAvRctWF)nExn*yYtkRi&U#W|j2Y zYv{I==qDW?`q6_sTZHtaEkb(o(=Te}ba|p`^p%QFwxPCf+n@LZ$ee&2J;xwRijTGz zc{mcvQ4;vqFwaM1{@NL*Ho!#$Irk9sicH04|tr{xVMu1 zgVn&k0YnQUNrPI)bbaNMv>sQ%sRMwROGFC!PRe10H4bMW0>RXGD60&W0H>Exbh({G z9u$s@4F5DhjEd5560Nt}h`wF6Im<+XIE|5^}b(A4CO!nrc8C1`S`mg ztDJf^O*b9SWdKj6t_ZH|t8oUn2EdVV{Z({)n&ND!IzoqURbBZiKCSQZ5Or2>7wz^; zeYlv^DX;oH;m25c{r=zczXWN|QW=YK zN^)xYEN^m6q<@Zqv8RmrlLw&`|^xY1RH*-RF&Z{-~dkv zXRxn|=ukugJm~h5GK_SFdYTyN436odUrV?z&1iGZfOovEz3GZm_@xgP+d?*W;1#MVTD}vdyS>QbzFZ-^7)CeA#NUaD+T-a3p#lf5rC=!#Dllj)y7jivP4oUd8yon8ZzV|kSj6ccR`M%we7Ep~*Rag17|WPV8`0u2eQ?5X+! z{K2_Hx)Z;6K-!mrx=ZAyggSg9YM6-bUzhOx6skvSzusaT+aTy>tXU5J_+h zW;xBDd~}9ma&qr>`cj|`_6cpyVA`A^)g}wn9Ha;dz>-XWDhW9XeN{dRwRJqXtTv|J z*K$AhQcW`XX6r*-0_lfj)!9pVYI-RruScUbfU-rpv5cbcgw3 z<$9_<^=iAmATI3ZC>7}{$35KnAoolTLgXYVQGNTC^mHsIyR3M>UdXFEkP(o~^3GP47j?g<*qP=ry#yVUS!-I zQ`C1$Bev5Xatln&1g%AyfKfk7iE+0iO=&!=JROog)~IfTxea9H5m*FdghdO>k}zW4 zvKKMWNgUYQZ%&K!@}6#Gu$NCFDz<}&pr*(fwcTaLpqJ9E4DVt*vuHDz9wV|M5F$;@ zS=~g24H0=hUz=48jQ=fot-0wE_Bf%f?G@6|;lrL$U;1>nQId3m#^*{@39v`kNH!9R z8@0*-d-f=H6bM9DET{&m}c zX6-U&y+_Qvjp-_f&P+zKx`8zlqPmvp4zjM! zrtvsJ7My@Q6giy5TLz0L?}ImtX9A6sM~_mFhFK;nja zvKsQPB!X#DUA_t?RfovMf}&NyGPqiqvvKO>NQ5n#$E;u2y7jF|OVn0|LEzaR8^(_a zhUR==PS=V9hDTv>vD5?+&N@aOH^^zme=CXdP+&`zqMmyy2`N&XLww% zEMZli;pBBBRw6W0Nn-ecX_dx(JJ%VSQDBM{oCxS~GcSfu(uVxa6pBOF3l2tCrT$|o z6~0P0iv4#h7NI5L$&6bSqAZGLv*dd%n>N}yOwKPinsg+e?(1@^2<%(51L8jpaW(al4a>7j=@FMbFS2G*+`~3t8bPVcJj-x1KnyTZ!CMZE(8XsbDCErT`G#g zRNl_1-uOrq&x8l2Js3C@$^*`TD(P)0B4cCUiyug>a!9ixt1ryo5>}tHZOVIgEWduERv&K_6ExtFa1z)VI>IZRjTG3DgFj>J$G!C;ST62gW zQPi(TjM}$My`ME|kgClSEBSni(W%bK+ma~j)i`KHGyH_)Yiw*uztBJi5e|M=Om zK@l-_XJ63y2TudV)3A}uF;LG%@yccP1!t5$3sG2Homui&z)@lcW)8_36TIgA_T(^c z(k{sIL{78To;h{aqjB;$@CjjK>5Sj)^NJQ+ipMcGc8Mt?Y`vf+5kx%N2S%85T$h|N z=^)h-Rvn@#=Y8}0QTc_v<@$462_3(&m18JgbMdJuxLSuhOenOX>5^t|33Dym{S0Jg z&jKzaL4!JyS@~nt&FkR!T>ayqbeMJb4`k)i60YaXcW!!*SSL5r`5?RR(@NWRYesfR zR$U+=2&XT_^~m{;%JZlYN6nynsy+fGWnTBjL!;v^Y)oVA!ii~ghw?Q|4Id1ua>H!U zzDyMII-B-;YHT0$#8{jX;dJ>R{T{Y?%q_j@&nXB1(dvNOwaQ?BR-h}X1ErUI#Ii0` z>7oJ>N)T8%m7U6OO*g~@fUNcGD2OQGe1cV<&45G%SJ@6~@-*9ajm@yG9T*71G5Aha zRmqsHi)c(pO*b>@ORmdq6bJ-_hGk}s6%?Bx(MOK*TkvXzwOQn=ciwz46T>>xH>}6< zo9GuC+wTu^qy2TsOChd6u|~3%OHWp44*zl;E3jgp-BZt*j#lyDfo#ezKX@6pcJq?8! zT(ALEWl(HU@-Gq(`EUw8`TMWTh}=mvV|Ty*$_T>(5``jteO&Fgx(w4rf9zq-J1h0& z6U_8B#j@vwWtkz>2`0DYz>b5K6QD}c$CeS(!r&I5D(y9Cx(QlokqYIh5F$#8VC6ni zS$7GZXb+$FtfU7Mpqlm4wtAzN?CV~5UeLLGm|M-|16K7Lxmx|!?&hB8EfloAVMZ6Z zQ7Ie!W=4I8`3ury03k0Tj}Q<-z=(Nt zx;w8ZqmDWPi z>%?c(I*ej3Dj{%0IXJ(=$@)!>g&`5^HwADh(-GcCf<`gP;YGNdRJ~=(*I=URiG_qM zP#Y>`pkG-_YhW=n$VSU5(U3}rVf`*h!>l4d>`1du)@3o&8~KO>E(N<@1-ceXyOV~v zw8VxnD=x#uB@L9U3=V*ql68KUm<1G=!%G3C04^m96R-QDrIDpL%p5YI!y;WDuCKs) zY)=nIHFB9YInrCTvDih9)V69}JHMmD#N3Tsg-McN359qUtiIZzg(kvypcFr;D z>ApH$i1M;!uG0Qexi(};V#NJ4RL8%#~Raxizg_cB;?X0tp(qvW3{}C zmP3QR>&1>*f{h`Uh6U2hkTH`;?WTr-L?ckCy*N#(F4=ApjY(x^D@&pzS2}eH z5v7%+W*t*nX^7*UEi#GGDrJkzhq?4r9f|W*hm|Nm&Cg2of-Wm%uo;iF=%}4V(ok$> z@<22ktQRkp*b=c2QUKWzCAR`qQxUTz5@*xV$Tjk8wD?&V3N;SM zA*2|OHq;o8)CF}ylDocD0=8+zIaOXU->#*^nb|_(#_A7g$&ECw?yik^yb60tvC)Yk zPVO8u3w0iW?^}k8w{pp0vBJoXcZ(eRZjs}XNUrsyX^KL~0-&|C(kH_(;Yzc3)ej53 zaoDl%rIQ+>U9#y?ZG`f7@HO)JbrN#8D0mBHy--oTpi9O2uwbnqYGDfCQhK~et$Vzs zS|l~wB5-xg_L~QCSXsF?%F2pm+rXDL5mx{ISrBWr(ZqKVPYc^e(lktit3EOn2<~Cj4yoF`x;^$V_ zJ7QU2hBzn2V4r4Ltp9E- z*LpdJ_VPHe%az9!XBc^9kZFq7x)m8q#=$`nav0fK98?cwCLx!GEkL1K2DV~9?9wH* z;rLE!!$Dlygf2Nwc=P$Ee(U%LuK}&~#&8mJm}s@|A|FnGFufcS(I6WtKjGswO%$AN z!pXP%Y`YX(9>}3&lfk8}OS*7&LC)L80cQYYQwc~Y8v1dMkc@<>tk~vWsqdrks>EcF zP96YRvDO|{1;^we59D}YQ}Cl$g~Xl@bLlC<^|+`~-m1W1f2?J9EXuK}@}T39%a~x1(G$y<2XdGxy(DVmT5{`$T{<=v9Kz$#46MD! zcW6-@{eUqTTeFT!8^?;1Q5IWTe+ld=2=xo2lLb0+dc7QDOON%ZjQ*^a+E%YXd5&a%hD0L{;eG!C-|$@K&4qdI)uSF4O#JU z)L0H_Vc0#!iJ`t_B$WcVlv*{s{|aYav4P08wF)yDC=-?-W0@ zO)uWE;k$}(ogEu~KFsmqmyRvaFP+~BrqW^BmP&`P!>4@~ZtkJIqN>Oz2lgr#sbi{2 z0nlYOW3F8uA>h%cJ#phEa+Rf*RE9um2;;N@!_6GMa`mJpmO+%B2UQ!x)E-cht38TiaB5Xerw@^Y)E33- zXz`I++rMzAHU_)y7^6ltR`0JWuLJ_VL6 zYJ0sn`vI4Vz^3OJU&=fw*T$3_v?o<01@h6p*N+4`ztCwJCF0zOmr?TcB?cAnj--Mo z(HBYUxapOP)NG*?Yf{mcjNnZ4#9{P=YH3J9X^e7w(#}~a<>cuo++BrxFWm_V(&-i3i>NG@QLqfFg>Yt}7UPGqaqD^YUFED>kIgeArr z^mpjl@ln|MFvkm-OZJD+3$Y?o0GE=zf=oK`kuJH?=d1NRBpaL`c6nI&&OobD^Nc#@ zIE7G`hb2hI>eGVxFqd9R5I-tq=K?NqYBb=djK{eyWon$u^0^2%F7?BXHrs}SCnL=? z#HE!^Q0`HZK@BxnuT@HIp-SH-hf3=;J9(V zvQj2;!oz*aDh*lA`?*KuEEB9XcV2!e9~j{S2QiD3gtU8kq8PX3$rf=M!eJ}ZN$(yX z$)^6}+@E`Uk{u!&h=RD+ER}&njkvfOsdNbe8yIoeNr?isZys@QKmpsJYvTkwDKkNvk%g8k+b`MDz<+5-qEmlGjV;P`%DgZj{ly4H*)4LI$qw_OE zEG6OkMSjR~>{y3`qS9}vwOvvqvW}%evdha2u^E7Gp5y`y%Puu3KSmFy7D64dez4hc zvM71^TophCDBi*aw4NTCw*KIb9?e)myv5sZUXLbi_p$O)EgcQ^J;zR`eUF+4mW#H{VHfREE~R{lOLL?E`AWP0=K%6Jbzsls%h^E+{=YK;$S)S3l*GJ z)@#(Twglt08uxFqN#pYb7j)Tavarr4clk>jaS@c7@Ye%kylg_(H3fuCuvI$vv`s+x zMn8Odlilw}c28U#*`mu$iP z{*Xp*Hx+I*K5Zd+JR*yam%zB5(88U7OXNj2e9?&yCHmxQVduAZV3V4vavzknb44Fs z^&vGeu{{{RGQj(uaYo<1*~NPf*>ht%k&*n6K|UuZU-Bx;rX{%BlZpvNUWurp0s)!>7t7W1v?FTA&!G)jk5n^u=u@G7>?IJ9I*2#Mv z9v=WWyGFt`#@$B3tHG((X)p}~WyKo}-A%~UV5))-6TKx%K5*k&3QBH};hBA6m#diM z)&_htC0}Z?M=69lmEq8I>Cz3GC?3+Zw}r@Uf%0^t*hE<##Eki*T z-V3@^Y-tMC@t#;=!KGoBP88MJd^epVUDq?DN5h3shli~*9gF#%HA~b0U0Gkzw-$|g z-O?qr6Fvx+Y_99ZZGpJ8VkOL4evU1@`uQ2Zh;y}$6`J+lvPN;MGy-^SL6VRTi1MX4h?k)I+u8TT=&(3i{K3W6QyVn`kqx+C{)`d^r z)~#RBBcB9wlgJI%q;e6~i7Qd#5>xD@;Wh{vTBjf~AxJ}5d#u(t7nb|UK^*2BN+jpd zs-a6^5uHipqNb&Cse+_Hy1q=6jfuI1W#Ym_6d&UA({*(H?B!Abrv^-kg;sp7f&&ao zSM|!r`f{h`GFp~(a!;fmb{ScK_}2eUT$8e#wjd30X-Q-$PPk&P71j<_EKFkpkB@;- zP=1bxzC>(yKG30H6-yts6!(lWdmL~nNW?yKjP(FKgD3-oC0C%{<>C-xke+~>N@AS( zIOj6#zuNvtMgrb#E1kU?yX8_=b_5%+iOZn{tOItZq#kSo<=cpu%gBmV8ss>Wy0%d| z%<~6z3UO&!3ilBm^mN%84o;J!HmJ-cTyaTuzG&Rycx?_|tXL~d$nf4{Z!#d%mPV+a zhPG`|tBGK4CZl&ra$A64p_$;UFHWYoT`xQG-J@MWmG1&9mK8UVOlaV84z%hn`EWQz z+(yK`{7D7$^HVq$Vv70-P_T1(c3=^a}-(}CL zr$Xuij>}(2Jsp2+>YA>g>?tsH8Q+@9t+Z;BIQHmTgDLR}8Q=G8#2p~K)t=fUjTAcx zoO{Sw*A&2U!q(vSL-3?Y-x|4TAF|lM+U`Hb<&~9xo_uHX)>H53GiZ_RSYK9_*wOl7 zm)lFXo=-h_=_KsZvE{3Iq*2k&72<^$FX+-IsiezbO=_ytl9HE--H4Y;#ssz^q+nR8 z!)Qj&d09-!$#C{z3S?))Mw^5jM^aM3qWzDQ)C;?G2@}#OIdH;+9VICR1YC-QEc-48 zO~|B2I0-x2izVsOyQWk(CFQy{DoYyTXwfKh!N6%9lUH%GtN4)PfqDbHV!x(EVVZw5b)cnYjV$ z8J+97V=1=VB$3qg80ND20E?`l$w1V z4kLB@CBZoN44j+Zx`iu0>@biS-qY*ufnjgX6~i^M6%~Ia3r%HF{4k3|dF8_#W@>FZ zE?GzPbV&#=mBZA^x<(qp!gEfB)zQB7t5>XFk2O2J-E9%(891tU zj7a@HoTABF#uvS&E$R>M#L-W@TZ)(bG|~1EcwM>nx(9DPTc8dnMNE0F*{t z!5lh4k)&rWvuS$C{fd{ym890O1}n!)pB{d(TXF|QJD1>nXWFb3z~`i|do$($9D0aU zS(pT*h-q-wZtTROnVc`9!0m+@x$!b|TG5SzFc`SVTCj|$Xu@S-Aq{qfnF|V-x{Vff z$Xxw^T`m&Vl>y9?Id8{ELLTVkFBMuU`U;p`3^`~QmRdjK*dMIH8K32RCs8iTOG1q2 zOlR#CXkL0PiuE!^<_Bvr?(8Ox_2MI3dV3w@V3n4`69|%*%Zq)K9Uoc#T`$uZ?$@yZ zx^ai>G<|uGUVFPnx~PWkO0KX>LQWQflZ)xBZ73^V3HIi8u}Q%D-ss?Yu8Df&?5EB^ z+yPR%co72~BG$$dbXr(>i{CAg+Y#5Tz@2|`A+|<4yW>T2RHfqz|C&3Vz~N$0a`#?; zu_^lU9iL65n;Q-Z4QGl(I@)1j)6!&Y(XxBuFeF##6-2q*Y{yCNGzIPm9xKk}r;hNG zy45i3EO|VUm#^>pi*PyF5V2$43)#oZ?&KyP=F(FkcvwWXA;d!+6?;f111>35#-`97 zO-v|;BQkCjL^$lE-?QVR0&HDgv1lFce3vycEVe?$X%ggSpk(_P9Wbs^#?E1UM4vP{ z_vt^zaYI$XJbfJ7ynd@6BC-Weh!Z;655) z)00OH(_n|27HKIqJ$hwK6E}8i0NB68Ff~_f1bHBbi+sjW)&Nn@@?kDL%b>I!M0zN` zn!zCiEiqrorj9A|w&vIpQUI5oMpYv?%;N|k3Ar>Rv2MwgP_C{u=!iILUnUk!fqK=f z0Eung8tg%KFB&@`V&Ux4P;A~#?x`EujN)x@ekN1FO$SBs??GA*8qzyddwmg^j{GN;d= z>r!}pidGvmMwz@@n|JY0*meU(0X`MIwOrvG$oXNHj@2MnV&Q8lEbZI57EwvWMLizIYk=PpbEIB176KL7X6#0{54G?bZXgLsex2osDzI(k!(0id@)8%fMAk?e;?j~Gds5q(L>VHhNp~QZ znmXpjw;Y>OhJM(kqZk}q)=8L{L+Jvb%Rz;A+l{I_?v!F7)X9Y^(TBH@p);r{HV1b- zCxR3z28pZu>nfo!IKi&>4AJl(Bc95`QNuB!wNk~(=HV9=piJ^}5~Gen(+nvp)|X5S zxacGr!Lq1r7A0pT@%%l%X|!DrvGp^fv~p0rmaa6>ehIq#Y+9XmFi-T-S<1OVNk$#W z1G${6sU*s22*(zMP?v{B#+`+c63J-I9T-(L)lrC;BP{=6EQF~JiX(lVYGa}oGAqjm zI${MmXqXCeh_$l9^fX>+NTirex%JYgltejt6o_p?np-kbAcatu$7^<)M~_sdGT8MY zDsq2thpK@2aBuPVK$nO$y*}k~@uX!udEoP95O^F#6_?>)Nj~% z+Dq@Ub#W{MU!BM2bl8`o;nQ(ghg=Gs$dC*rA(xw&-E1Bkr1A=_i=&>nxb;i%t*^X6 zo`$%zYGkp@y)M-Vl7p@gJv(|aqKov~E>;JNykX5U(F*zC%k_S=X#GYo7mWhCTs)w= z9y@cXi}uMh-}p*iWtF}F;}5Q!l7&v|cdSzfu_lF!ZoTyh%B29vc`bTamet0&6$>h8 z9>^vZem3^5f*xZ}05AN=ckl68j16nL60^ZhJC2dJUpu>(;XI60Z8DmU#*R7VQ~-22 zDBX0VMMZT*VK(9sA~gh((g!#cRGX!1FrL#dvF*f;4T{qUTGX{0iAK+iGoFIH?CewUgCg5z|skj=L@M>Vlb?7JHMY8L;WruftHC}9B?V99aw|p zvXO09tcYHW;@HU7y2e1>w1q)`WEj&&O=3ZlQHg*Y;&f`vr*lyOsG|@xwh%O~5H!9J zG@%eQu@E$=5HvZW4D{tHxAnr-l!mxsQT!SMlgA2*11<$i8IP%TMUvIDb_EOoq(}rZ zd!mgdLv#eXv>0RJXX44SI3Y(4_*XnjEKLueIPzXI{ z9vO5O-91 zi_9X)TO4qRsJFN~LeD0rcT!n>@p6RjB(Oy!Ag^NBGc$sZ7+@)p?5tmdClhd*k!KpM zsbZn}0Xtq~fP(=!CsO!uca;oqys%3rrQ+fV6-P?t0xpH{31Gsj<$zhaXDl;YW{m?b zD-Dro2s?f*01#IS;8L=X5@E$=NeI^DM2knt1Iqp>E%yej0%3nbyt*ty@1`}q7)Hw_ zH`eQj61yJg_M}e*D*(D2w6pTwCg$`j)=3B*tX2%0g)9kaHQ64?L9s=?ez`mg#QvI^ z!n7XL?Uj-#Hx}XPN_lXC4JG-sFn_kg?Sf;+I^Ib$Kb4)VaJqDiD3_aMm6PV8D6D!3 zam>z2m1T;2zBn82H^L#MaJ&ST8y2<@>he%iBsM-KEmL1Mhkn4v&Lvt~m`lLN&Lsw_ zFjvZM#ifclq~VH7m4Z4-Y@TWM)pW@;l4FE8m%?2>R*U2l4r0nFery^!AEbBmA%_h) zJhV?1>J*Xsk_U3BWvHXmYnlz|VqBcmj~|!pQ(#MY<7!>U(NuBJWfoQ?6-6e+i9;?8 zEt_IeQHbayRa!Jm#~}?&D4N`gUgFlNrJKhjA%~l$mxCFsW8+gPd0S3`Yw<3a^vg-e zj?ZZ>3V_Z=lQoINc9A~{XTcJ<8*Ec1{7MxgTQH0}31D+KFX^NWL-(|%t9uJ;$$A~f z?AhgILu)ZP7+}da-~js-vf8~!UQG4E9eMF%^TOlu!m@#nRUfzbDNTfQJ(wsQ2N533 z4(>b%D^=`Uf=ug-1xwb_gg_c3_+>K6t$0~+19}h26g8_ z3^sGlsprioh^8)P2H z<)uRTQQGE`GOU(ekE9G5cDa)>h?tWyq|Atyiq{o+sq$|xQch$`CrKqiM=>cYR}B*G zWevew@vxYzEl5HRj|?!Rmb_&qO=bZuWg?5jYPf{Bt}k8)N;u=KGYMx5Ib41k{Z3Rd z`DbFhGti zljGIp^~=Sd6;Man2CQEY&{2VB4{iPq%|BtRL`a|`H$wv1W&9bd31*L%K*h4ob=_K; zu@%c=EMseyrKMnVbqLzA)yu#Z##Gq35iHr2{28az#!i$#&B`=}aa!*2Ub*3qDUMgR z#!9)z$K^(nxZLBjtBH9+b~Aq_R&0(1II(7Pn%Kmu&FM

    N)KxkzawTJ3t$X$aF)5jmNVRpJp+1m19tx%;# zWe^?)u^j0OCw4V|yk?s)@r~Zx&#S0}j-?9ba{`-`F?1U&904Ph4NvlRIX!5Q#04Hya1xSvptlFUi z)!$ZvMA#Q4X_3rPP5Ub7hegYV1-v7P8il`$5FQz7`OEtKV!MD19&V9wdy|JVQ{iL* zzjhg%xc5R4)5h+KAjzBPtrjqiKJSQa+rSb%K~~jV5qt5~ ztQ>*P)fMVLl1*Z#`=M;HT!Ewe^KIE28>@wja$c+GQ_jzm{@9EV3?y<4RiLij60j5N zU=r97+-_ZjL?{>RPOiu9V*{|Uj;rKo#(4uZy*XHHT2*F)5zL1rAEjhyS()5L{R4pD zY2A?vVozbt@*GK%Dop)-6fs?#acojp+=rQ7r$qrYYevxUsoX=V>L&A1Gog!sXPTex zqVY6C5L)ALsFw2nbTII%X&UCku;uAu7?-X+he*X@Ko}A963IP!!NZ5A%zrrrg8cTV zL`Aytv|1RhYma&JqT9xBLzCz5_*nOZ}- zgZ~aZNhNDC0u=W*r(U~@^93tx;{v_AM2>&f((UxQCw-Tia%9ezBe`qAr(%*;3a&8H zE~?U*#C%vjS3Kn#P^Iy@#BgY-6seB~XFDhHuBK(XHJ9+JQoFqh?YR%-f*^NcX#%R} zQHVLJo$u>M%CQR4_V)JZz^a^F@BjV-5jqV`dR@qlegF`JMNW*z2yCP zecJc|6<;;bH?Y{B~4WLl%{ud+GST)@a z?jVf**1rbgcS&?ZC@*R;#M(A}W5yH!F7gZ$whveV<&Y;dW18bFV#?c10VH*XBi$7K zu1`6{lQ4_i-!4#eEbB_)h4c19gtBxV4O>crp;{aBzsRaRqR@XJ!Ky&g!TRU zOoza$%7aF(hWX^)7p;V7`=quv-(k&9I25M-N1hS}V>VwO7SkS46P>5IDzzmlwenZr z?V7tfxF!!NK08$$O28o?xn+0SIR+-+NqPkTejc6&PGW$c-HUMEEDdYy)G3}6-Ar|!yToTR zVKK)6sE=9B9}I)qKNTeGxWf5zowb8@{L3VT$2&jjN#QGV*`Ka@bw-&3djN6^WW2-n zoa|L#KC7q(lSSAV1ifL@ujYFUPE6P>*|CM4Ckpb#F$GIsdk|K1p<{lt&$#XkdPZbky9idEm!Jqb zVR{ay2mqR&yjch%DES9Rbo@PSz&laaPxYX0{4SRQXGGg&Vt}D^7MZ;k2Yz{ zBn~RtXViBO+H&|?eJ`7BF$%9L9PX0xO>MyvyC}C-34B$uATMBj-}n^3DhJvW6#+t+ zk$|=P+~o=-wy28bxiCqsd~Ly)>-LzFMW-(vum`((O%~~+lnrxNa0ZdKS$xT+n^}wZ z#h`1Ui*qe^ijL|=!?)_1YE{ptm5y+(q}BqQN&Sb!sl%12jcOpsw*Ueb7YoLAs&}Tb zx2UApD_*&e$Q7ba>O*;SIL06s^bQz!_N1%Agg`vf%qm?kX#aw+s$(#5dB(vyKSm-Z z7@MJYN&uxwt3?Eo@TnM{Z^jfWOHf*EZORvAv->3tY5Pj^0`+DF$Lm{AmtGhK40L38 zHl}T3RRIMof6N%?vS=tppXx>iQ<5?1{%a6qd#_ETGsdJ|Pg&E{S&f9+<5<*V1w7vK zlD!^<{f-5E-&oRj6ZlyX+D>#WZi6yHGC+; z$c+)k9)q9jQny?I1R_-40JSjjTh5J@29EAHVgjQIDMR2r3w!1i`})UAVS+7CR+LNBB_?CO(m8dZNG&

    -wVuW1mGa_TS>QmtUCrSM7T;QWG3uE54cZ{7=- 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

    wpzIwS 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

    oHKBhg2e_mK{3)JZ^h^i%=3?G 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%0Dm$=2O?UC1Y4|L(H$8n<-sO?-v}655MC* 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

    {Z$-W_Oh)%ucFZ#S2CH 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 diff --git a/assets/fonts/JetBrainsMonoNerdFontMono.tar.xz b/assets/fonts/JetBrainsMonoNerdFontMono.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..e827dd803d5580b454feeefa15613f560dd77938 GIT binary patch literal 1958564 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

  • V`*D85ttBQRRrt(2xW_ByT>UO&fDROn)*R9 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∨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%0DvS1D^IFZd!32P5^ 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

    RQ%%)L* zvTLE`SB1T9&)$`td<9+bNmu)02Xn}@!gR~u$qBgE{v@01H>PHET4B!9(I6!2cnbMA zx7F6smmXak2$w0oo2m4kYG-eJ6kwP`PfQ8X&J?r16;4z^74lrIEAO`FmGO|kDh$Q>v(`hw?Jj~d|LP~; zCKow}QgzNyZg^B2eR8}{@S(`;mbR2<_F-9bd;*)0IrpXiv5iO7UdKpVvtJRo!s@$b zp~dQ+y0(9id6gl+&OPbo#c0(B(Qsr4!g?!BB0K^hi}5e|W22EQ;h{pXBT_86GH2mF zBg;5d7t-OdLvrdb_4AE`OXRJov|{a}zTG-E^cKlq_cX;v9Rf+7i0nB5B$~q7BFtf* zT@H)3^2_f=AN<(Qc(|FZfWu9t`5M1lH1|;k z-j|X&SAr%tW|hZe_F0cDLR7$~um>3mj9#x<2Q%eWmB;W`?Mf@{kulm|B!|doBX*W4l^#M>Ad)g|{JrOKp3AaM69j18LLXi|QUQ z(PL30;=ES81osKa4XM%3kibbLJG^dD!Xxt{Je+p0tLIAht)55QrhON8f1F@CP;qvvud zR2AhBde_fHyS!E5Yn=@@TE##N2}3Dil*MYoeZCa3D0m|M~g;wOG9DOwIm~YFh*U%CB!-r~8V#4_ju*AK|N^Lr?;eUe;1H0c- z!1nY0+0XlJxJ-17F$Q7>Zw5fTc81I_pHmW=Kmj>B-$ZwZPsWK21FVO`%3^X-aDbziYU)vU1~mE>_ZJJW zDbbP8r_w@BA?vOeME9pf(l?tqe*~jfcX%w$-^NK)L4!IoA?Ads>ho-W=hF_gB4srHQhbkv->WWR7hu-o&3{zhR&FJTmnCethP7jcjQdR8@1Y>xIF8M3ovc7 zt0`+C2T61Mc<%W+37g=B9}&BC$?2#nLECT5~6OY!bW9?e99p z8CKsZPCtx_g=yQky^|eGfQb5vV@txV{w_|6J*!c=(9VMbuH+7)4eHACa>sE1@a#e% zg?IDN?R*oW1=di*AbfhV&N$10vSz@<4HzM}ag*4cTqM@CEp62Q%-oVe2!(#j@|=Vh zbNsl~4UP02kBzYu0J>2NY4J~TYZ8TSdq4sdFqT4NDq^Bgub&9xuFnYludypD=iLWO zR*(QO$du92!}Dw3Kw~t3O)X@3I(wjjrvMS1qjP<^o(8a=e9!&h1<}FxJz8xZdPPXI zPDlU3yDWEg+NYQ##zrOLdLG9td4wc=ztJ%Up_;zq^#rekaqAz*^EFUn(A1pFVm;Jy z4X%3;DYa{fPqo~uIX-o-rIqrx9!k7w^>ef&H{o{^YB7jPR;2ahs0Gt|;q)sb@W143A5e^x}ujTz!{5 z=1KG!QzJ=D;ZS+~rbFjJp?<)bQM_}{4q6%450?4Nn2uPzPvp}ZE=R*-_v%LJ$|yQz z{%4SzY6EX+&kS~b!eO-?sw+cEhy-Ie973yIxn4*zxtjDa0TVps_k*JeHBmf?F0Dx7*#&PE7>=WN;QM3has~!#w*0!?v1VYv7e&}dyO+HR$&j;jaBi=c) zLdm%#xl*&@tIy>RnWAC0&k6}tb1o52 z=;?yZY_;1Di?K1niU!qrgbSts0WOLB3{;s&@;p7BporS3*UrV*MGPFEESgU`_@-BWnBqOkrf6QMum-pZ8|0O#^bB*fmAAO5> z;Um=L#~pZC&uNYm#h$Mnl8B9ftSZJM@^`r8&ceeP%;7p+`Z+r@Ro(7miF^B zH$?p%=@N-f#2a;dE2{dS6#_w|g`eo~>;tGZ^^?uW?96x z!L@0oun$27{baKf;SCF{_%f>qS5oGZ=ruED%f7G!zEQt18kWRfeUM~wP#i%lOUcTO z~BbsB-$9-=pUMS7-DRxwqaxt@`t3V^=dDVB9 z7;4*{@KB)H_>*Kz{_@XEVn`r-9Ketyz}{2^G#Cwn`AehCnM54UwlqEDoMa6N8M4{% z!(m3zGd`Ri>EEmPT+EJeqhh-sGjy5;k!GOQ;+cue^9)aOYfy$oX{^eIf}+Sp{^xSk zG>V%hln82u{$d?uYmJ(0D>Hn6S@)iWt()p}{D|Jd-&H8c<>U4yRwRwx?*(E+6SH24 z#hF1@OHTgpUXT96wSk({x5^ZCDM3wB;(#UmSANy7Qj&L1l=uadC0spW=Y2Iu>)o5Q zF%q`?cA8m8aBuk&5Kl7Clu!Y}KsBWX%qvxW>h#!l+bqA^HwcpJJqy8afq4ln8NBm6Qp$WT3Y3M^D#(!D)<3lyG z?iPbU|I+ksEI#qM^BS;VA*P3|-CIFcM3Y8W)WG;l?bM;wf*bVmHPU&dFTNX+3 z*xL~t0REi-DnQl0)4_e8u;Q3IcQ6!`R|=p!hL)_Y{5o;wJLB;l*4{c5BdNUsY@2LF z@}-fuRPg<}a(bF&OM`YlrJ^q&pm!Jg!)L^&Z2()DYl1e;&4)k-s2C7LpLg^{+&K6| zQSql(9#+tch-D{4)FnMb$H$6g)eh^}WD+kLT%h=}Q|$Xv4y9@%C^HA#&jcv6Q)7qf zd9OP2>%kM!Q1{c}KsTR^d=qNWC`+KG96_EtOq!ihylZ@%j*(w!JW=VRd}R|luZ=fT zZ&F3F-Txg;m`Ks7;@$vr}DO%E8FGIuEDJ7yOIA)tWL<`R)N`t}VlplIQ zh=Hq*w4cvn0?&{^T1*`v>U4V=6af@U?)`qxNFi|8Ch`C&2%N`k@dH4PapJb&En4gN zztL%7S@69j^$BM9*GEJu+;RjQ^+^L8gTdYAf(LPz2hJj(+zCF{ip6v~iQJca?JIoF zPJ-?Ua>G$X;QYm&rzm18v>F0U#r7&l1e9NyD739pEg+!<%-8mcd9$UpLaT!GHjDJC zY#HJFzYdF53!^SGzAjcInRx4m5&_sW> zgRpmN+{g{Qd{@)~cYr2=7V4_GPZ{vfMCK|xZWqcwFE_hf-coybN&<~z68OwdgEX^& zvCdQ-g6=R!zO!)_GFVbj;)D;o{(y%I@~{N|HA@$Lx49kz@cviZ*|9&&2oiORO}u&| z_%0I~zufkLJfw)tQ+(EqT;s1wW(#CTS6`X!gU~r*rNL^D+Vu6sbu=T~)0XXj zo;=9pe~HvyUxDnbJEal(wHowt??#M5g#-k;*>vP173yWeIURDd0I~~k4*n$$>bLeB zfv$chx*6RI3MX*(`IXFr8^Mc!&2};u3gM@OzX#&Nm^7tokX1kM8kM6k#Y+^j{N(o8 zHME&RFIr?wR||AUO5oEwB-r0(uVURB{pZpB%(4~qAodDa2B;R_{ zZKNG6PA$co!So!*s(@v|?1{uFGje@-THU`MJvOM6898nf#bbEUWe;3aJ@oyUijGmx zyV}{Ji|UBgl?a?aRv7CbmxV8HyixNFu^3@=)e;d~A})6(^MVNRK^#**a;xHgl35=N z`R$%Jr7QH5BUiZW=(Yf-W?nRq2SEoyaD{Uyn%pa~04;Xw=U3-mKOqU6L9~URs0}et zNl3yr>05F%=%oVAB=TZPkkTo83=|&0>?1J3n7|jgWsL~#y(o-#P%CHCn6i=ib5X4< zx>)7IZKvK6gr!MIu{>{pn$H_P749U@>HD(e@(~l*bDeIG7pobzr$W;JEG75 z9%y5#c;%DZmc}^_HD0Nnz5pS4U1CYswF6p%f;-96DJ;D1Tr;Dhz7R<0(H3KSGb#uH zu@xrP83~!1?SJ(WkByq}V5H|Y5WrBqh(dN*;fg0Tu^1rzaZ1?OC~W|IZyVlUg>Rur zo@eleh_s}Gvi#r6n>4tJH)F(=eCrMD7B;U(+ON07m(x8+1o8JG=J9_` z+8vdQXtm^ZS`PBvt}N)>r9m|Q4-ZM!vrCWP9W<+mlt48&Y_(x%pz|YzwwkN~O&WKP zAjYHx?R^HR0*LuFWx6nxvSYeX{(Iv9oas6P1!ZRj37RjR)UjhxfQradBz49mnPhDY zDA({Q8|fy5BM*piv|>C7e!-=*@Iy}b)Q*0@;Y)}&bEIJX8O!$TB#_G@<|#Vl?s8_% zwXM3USfpl;e2?))^ZL&Fqr73j9atec)l5Tx#=A+w!d$Y3l0^dP^3OFCjpP*~-OG|6 zeDkG^llyRvHKUP7`4uFk#~5-IVm5_6)NUjbqD!51?i;H4F1ZlHVw9ahf2+@rejI zc$PIfs(UCXBTF(ijPZ07g`KoN$zUo1YL9r39^#P3?wV7#J!MXz>h<#qU^UiFkF$1{N=(>DdZcGXv!fPp)Ub2PV^ObaLv@6J570sZ{i%R zcLugH;^oPMBESOJtZGhJ8F!{e`7QkWjZ1VmswkADW>)!#u-Hll<6ZSu4~dnASU2}+ zfvLp%#rwgN$}avn@oZDJKgL)4@IlxJnx1gJloxcgL=o;_Hm+pjbfnxYExrc-=W{p7 zE+85r22%U863F4ct529r^dr%l)Cx<2lCvAR(++X+cZ268zPR6O!FCn0)7iWF`25JE z({L@6pOAGksB?bqgZ>kEBdl>PwnYIfO`+k+!8ddjC?Ew1-iTNKNrwnAQFzal7ls_! zrlzb)uA0}67YRcGK;3nU$(4L3VKNk_HW^iEGpOM($!fM%tnxDITa>Ji{*n)Xe0rll z@3e~A6ymW;OVViBw+z;RFKoSd2x-9Ie5IK3;pcg|D>PaAlyMy}5o1@U`29S8Geg^5pq3mT2_aVV_ofYk)A3 ztR(S{l`nwy8^goye1#3oQUJmPRe`CLB3d!PA*loEdyt=yJGcvS=ydWqHJT)GypX

    @2c<483U9$IRA+Lxe19@YnTp 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%0Aoje=S(+^-G_Fg)v;!jp+Yh{um-@YdM0Z)@Xkmq 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

    KHfF`kK@voOI;#Z>)s~TTIQ;2U*J> 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 z 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

    tSm+NE+c~6NWg`sJA3UWy zdZ<#BG4}o9slK~ub46@#z7RT_Sr~kZ51d%(=r$=CG06XYLczc$km<321b?5trE6Kc zFisycr~K;5z>d2u|GyOmb#xrN>{^>m1wZK1k4NGsxv^AarrYxT_ z4k$`QiVgfp3E&mt&m!PY}!_s)@7UYP-1# zZ>)hhMrb6vq%~RDC@&#{9eJ60a#OUS0YBNgc5OCV7{@F-EE0$FD2?|0pXUe!*B>8R zas5uQ0hmVI@FS=`$ofJ%@6S2CM@%_m_ZOZZ`LEi*B2Dsw)|wp&KVMW*K?1UzoCprr ztUfra@V-M#d?VolNNzgwDhLXx;Fd^h1d>;ZFh?!(JNX67O-uB><#-;X9Y0kuy446w ztB{mx^MtM+;K+!LQ5?u>yP@x0Syv-J1%q2P~c9(@NG!|GGcotgPIuS%z!$?Wg; zJ5)(UcOr#nS>arvsu^eU?;8bZ`~1|7A#M-ZxiT(_nk^SC)F7^>C)}jImwkm5qcEBff#?SCPGZzRQZ^F>J z{AOf5CtkIZEjz-jFo^ioehi2RNL@i$Zk{1zTg>`$`AvCwKNi?9+>LL__56tH%#Bn` zAge~a{U$;l#Ht6m9tS5Q?^u#hjV@EZ;K$EC`>VONs0|}%X2B&N{_ri_s@pG*wFgP7fi-Q^v#09PXP9DH!(Q3cxt|>iR09WV{Rf9IW@2h?sfx+V9oB23%;t6d3nnkSl zOLnG}AM{n6!@UJ3&+m5FVR$)jAn})u!bnCZTVYJ}>a&DD4sLpN^M$hN4Cq^pC~X^w zAPu|lXX%QCqYmq5ELgFqjWQRO))L2I;Y$qz)Wuc{TeungpFGmdXkFBWSq1BqT&os6 zZ4Jn=u<#2aBo#5~qZ#P`Ka3AJ#%hUh?rRTBA$EE4?t0sCZ?I8fTp>{wZagfGS#iL3 z%fS8$8PT;~S~%W{5A`^;Qu%+nb$W4Q*7ClS_pK7y$}X+f6f3B622u0=P4Ugu=plHA zxAk@*<ckaQVVj3`k@kK6@R;6$niWG}e$hQs+ml z2d^h~SYvTugh{nCwp0)_>Q8|u^rXc7=n=H0ZB3$(|L)=*0x%?$+Bw}mr>B!s-Q=-U=Zrzd21m(B?OLK)W+M@>REbkXI87zNU8{t0cx>f=iy5m zbP&v`{`Tw<_2mS1^~~VHKBO$X!lSI)wPd-S>|3=*PygQ2>kEuqvID|#a-|$ZTcc6f zko|>{;qtr8A7{E+83BBPj8zuZ^&{f|^M2>5Y}wBR^j^|M~?! z|DTsTqDeG0coK_LP0ddZ3()r_GmZoZEc=nMfEq#f%udhDOySzj7C4>1kSEbPfE3np ztQzBxwIV%c1hjzHwcD#r0%J;x!7r3BYq%V%M)+Z=gvv|-veQkD7ZzG)e-5@+BGE|% zQMLS%YCkcPWcX|xA$K%9f*7mVw3_KZ+mJ5Za4L)Bm3+5Fy%A}R=2#v9NH^%PtPkE$ zv~%)XQV*%1A;4n}|`50GI|q%(xNaE|`0$j!-K zR^}YR!liqJf2YoEwJ@qFElr=eJ~=2121N#u!QZREbx?0 z6Z(xudar5cG`dKT>rvNL+ZhK9Z#Y+IwXQ1z%<~y+3>8>wP&9qKAT&^K{PB4-xDsY=nRzVpYL#HnJ*;MfPR5&xp1r5dlRUtkPFXDH%%UE{s<; zZN@{aO3_24v@wo%T4xttzNkX77#LQhcLiN{<7vxiV&7mdLN_F_HfSqf^`OZiO_?+CHSo^@=W{9{?AJ3~>EUjETYe&NeT~3TS ze$35H2wSSAXAIUsvmiJ5D#95=seQi z7SkG@uUo31R1~vZ1#%qEWTwbTDn&?+#1_4d_o(X~$AQQwx#SNs-#QHsQqhFtIY4)q z5qNCFS6oqb`lS&ZeB_IZnIBS(1GP&h`ijo|)LkmkY&NR2ed)5X!i$h3T6`%A{Yk(5 zmsR?;Ng#3(Cb{FO$+mMt@hn=d^dnsmf`)3OUpM6afU-~K|6&&ngM|(vr1bBxqa39L zVNYHH#N5E~fAei#N59&Hq3(HR0ny7Ul zr7d(N4w``dfi9P0T}`Q}xqY3CTg$8+&9`}3bPh>ilUPzvDl4v+3W}G}*o5jt*%hSS zsuNH;GaP!mB>Z!;b^AiCSkbm1lX1^8A2o{~7Ep~}8YO3y-iT5A1I;9uk4>S3ZN#e! zreh#Ru5`i{nYk)!)@oqmYFhqKWKaVh<)GJ((~6o#hr}s5Km_CH!~L#%8zXLK8i)xC zKSHLB1l~YxG2;0}FAJC_Ujjs7)@k`EHeq#ZnnIsq(BtptUv<51~ zyut-Y{DoDF?UZJQfXT86gS?P2)imodFTThJj*4mLbT}w{S)GLLki30b7%^35rqfSN zHN3?7e$LyoJJ|nl>{7dC#R`2Z{dc#;!q*7x#kJDu8tC0X{aX9LM+t8v{3C)_H6=3G z!cIX$29dIIGdSJqN8t$u11gKLhFdU5-&rt_M4I0406Pqnh%}8WA0HruMm=ai75#|l z5~gsUzWT<155mT7T8OvUtH?c~C5?|tjJe}h(6IK9wS%IOJ5M!7MzC~Ue}bW%%h_T1 z_EF@(rD0HYRpaxj)U)?Cs~6x1mSo&)6ak&ixNRC;##PNwsIO0tf2P5oe_?WQ^EX$3 zDa8gKfPPOP-6GRjetz~fawJ%V0VmIT4#WAxK8KKkg*_>=?@#K=ck2vr63mK#*-Xa`Gk0D+I1E zZNB7dEjICjnT#X&dn;`*aLe`<--oC^_3WiV5hxkeX9^3+vpIRxT5RyOEbJpW>vois zF65uVD_w4$ZE896drdZ%MYi+glhB@|^!xDas{gaVsD`=-xnK84j}}+DbI~qcI2s&{ zmlBJC@u>_k4l$p~jtxEq-2+0|@_mb1rFMJrw}6rzjv5xnrJxJWFK#BOAcepZCaM8!iE$ z;B1Tkd=||Bx#4}zdub%FxV{|#ug2F@U4y+abGpq3Sk8Uc)9g8RtdqpxPS_V>QQ`T=XJJ@%y5B<8Q zkarV958qv7j0pN2)KHW2X1(q~_P$ea&{b`!j6LL}l%{1hu?f{v&&pU$)SP!Sn~3P* z!q3JZD9-UfP?!iIC=-PJyvdEv_F0HtJ(k)k${d%+aIM18vCr4q$EWD=xnIQ{D| zxwDy5QMk+Y6;0fz!XcbZ6U+w0$dujIHh<;sV5Kf%h2}8AVA=B8j1cDvh;pPzEDbfu zy9CHcAKS%GJA7;{K4So#N({zRb?+p$j+BN&xf2XV>e2`q*KBUsj^W0&h~IAqpunyo zH$oPDP|3&*Ky36;FwV*ForutDy3Q+B$qiWc08f5fb<_cl&Dn{p7-37eR!FpwDJyj} zfL02eG$_8pw>R1AL88l2$_b{Vc4&rAt^zl|zvy-6;vVAf1cbplhl4kS37{)PAJffB zisGi+)v6-JBqpS}FBe%Y{5@SH;QO0qjb~pqJ{ETp*MF0pG^$_6h|*+IAP7s(!*mKx zOAIKT5WvNyera=W>eFT!C!Z^G zw@mL0CK2Be*o_W~+Yw`o2huhujRqSmYKzt85`5-Vg%Et0NM_&c0YVBXW} z5Q9GiOsj`132-HQvQ-FS&V7MQ*-wLnC5y0kECuU#Cr>@6@+#=AAUzOf4yof5Vb?@X z{GZ<~XEkYdF75LSlud5yti8w=8YVJyuv+s%cE{ zw6*DMeXGGWM9k^DqbgJl98W_Ns-AKR)T~>aJr)zitymm{XAe|Efz_R14O_W#$%FCV z$BPAWf5ZZjTVB@ZqzyjGbJH35kyBD?0c^Q7Sz?Ez*59t9<&RkdX^eq%ndWrP|CG z4Vp)%sU|;s`$Es71f>#NDn{f@Bx=3O$UPf*o}0{*Rig)Z`ixzAhczF(PFMSEwGrZ% z1v?xdEvlp4?@NV=U^<={Yzo+r9S(F@SCtYE7;Q3bBHTeeK}f0fNiA+HJ6jgI$0NLdNSfcX`S3 z$5LiC!6q8Ek>FgbFH3Wq>1aO60!gISu(IY5E==83l;G5r=nAlpNV|z$lN&HvMmgy# zHLFTd#*k&~G>yc5fSP|4WvQoB1deFd?C2{vK;y`zu&5E2a~I zPi50Uhm9ycz_Nzx2Ibj?0aI07NUvN!jCcj`wGKu4x|)jvuPPhHRuI|6<>?0&d%M{n zrnUJ3(0wL{!A19|PFKyj1=oz#Fz+z-YX1i~f+XXkLwV(XXxCH=Ii&DqxPYTj?O>7p z!v~!WBpruycWYSzW+P~ckAFc@I%6DEZSjM9|%2b2?yd&v0Guy@%r$WH^lxne5 zkeBk1#rXZCZ>mGvggSDVY7DQ9 z(|3e*hHxq)!|Lak;#yxco7ifdfKksbAqqeBi{R=)ko&YPo0EV<-=(gF^pWp|uxfd? z(}@4udFw2#du>U;M*Z4#{R{NKWlr_r{D1ZHL%6Nb z{nqPDoPfK@9`7)^>fi!YCTVLlNFR~%Xr7AYzK}F0#jVL5N<<1G%7BDNa)a^TF4v>K z5f>l+*EQPDHHJ!;PqMca)QfM2B1q``>f?2UO)!JC8$Ao(*hz5}N6Wl?ocUKh4IFY0 z8m9NmxC#!5k&M`txP>#bZNaw5Oh`%8UWkxtK4fW{;1zQU@)h+YM@dI6)okn~BUGTz zNqtjsVLyt6zA1AJmq1d|wz%SO#qSB~^YEG&k{lGzqt10Q1V@X1hc=-`HB&pwn;?}6P8J?yv<2_E)Mh{4ml zPoA-edR7GW;#{H>@yr%M;}%-F)wLknVM#aBC2)V;IfhXerdGxxp66@-In}W{E4^VU z4U5n**aExYPrx~^tLe_fIR?CCf~}jYv2en&?e_1Sc(X>v`8s~8`>CD-=jUd%M#5PSoFlAJDNx>S7A_(%0wsl9=4vY z7@5kS6e)PH;b&^T`-M?946v*l3;BxgU=L=+MyIXWY*wEUPKRB=A&HrhmwR<~1vMJ~_St`LGRb5NitQt_hicvEtM1E9e8qCxEBA6Kc(K9ztOP?#?8t9M^FD?jMW0w=X$dFC?V|Wl;UJ;EYGjM51-Li)9Zg zbW`qW(b+X=w~y`Zu)yg}1K}R{Ky_R6w*z-;h~KMoyqvf=Jg6CyE{f5Ssb=zTFEwKd z`(^o&bk#&`M@sb`^Q#eebN_nuY0JsG6O@Ml;wr8IQ}G@6XV>RJ^swPobdyh>LD%f$ z$VXuIZZ4V9>m+MjS7ZJ)1GuKPkoTnI$cuE@K4N%g=`o?heFo@Fed9;~K^$@EJ>x-j zBU7KSv8mMdk*fNn(_QBP{9+2INtWJLr#3n4zK`#e)kwCLp}}CZSKgi_UkuqC{s~RL zA3?xYGZdQ;G74tDQu{O3b_N~th<35 zsHwNuNDh>}TFu}hsi`o$nirD;@aWLL_+T07@m*~1#e#!~ZEcy^?QFE#X9idE(Dlg5W=eGYc&0p=yJP+JsdbJ8S! zzk=wO*@iA`&Nn+ImSNBXV}V@APOPS~3PN{t`_5QVzYDO#?r|eB#N!B3^Hy5gQ?@C0 z9waN-+bzm$cnFjsu6A)sBb_4qki>ky(-$?&Yq;4(VcotWxJQ@#_fPSgQEQrWu8{bZ%{ekm5!rZ(y$B9y9_7I5KGfpwY&DhL&Ag0=X!iSSoP+ z+A2nJ%r2G^)x%A2`b5%Y=o7uoN*Jk(6X9uR3yKG{FRecymFNs&^}0D za~`tnnStUeWUxId-8Gtq24vmhfRHo&@O*m*!EnDcmo4D!>XyoYfZ%D1>_M={bm0R9 zyQUY*lhMRpIs#ARX>7InatO#H4h;yzpIRyHu(jVfk02{6)APiv4K=?0D|OPW3TlH< zqH2y9nIj>Zdjaq}hbh-#;e4vu+m#h)#irVQtzvN$Uwe6EYYX|dL#7|Y`|bszdS_Xe z?fwEYoc@<_s}~&jp$$Xa`)g)$D|EotHvupnIiY%{c#YcDu*qea-xIqS$Be~}&4G|b zB-gEj|AZb;Y^%0l(@aW?B88o?spUIkPdVX*DL^GkMkWkTK$3vU>fG^kK?lWTz}aN0 zhkkB~et=~`HL7;o{Mo--H}jkdV>@Be@qnVUpE7PO74-vQ6v0(|5w4vHv#PT->RD!> z(H0xO>EfJDrGS1({l5X&3&K;lcGj`!gi5b}q^Az-Ay4&LC;hi@9r6LE3Dic}vpfV; zbyTEG6YT-Tk7T1g2+C^B$FCmwnUI6X3pii)wqns(4J?d}$xMfOb#b9_Xq* zQ5oEXtJIWDzV8KNJML6-fjy9ajL4qfsmtoh??BH^k>{>Kj^FY0Djb152WTn(gOoHC zq+Qg+xu0;t9a>RZibL_pfn>95@9VKlKr}ZpM~t}|1SAGr-lYLiT{*m#iD!klId$-6lD)Yd zUju|NOWi0I%f2>;*NpeP3)ze?Yrd+z=-wd(S^rC-S0{+7XAb!n<}S-Iks8sRdrQl; zL=JP{iw?dDG|BjU9B%Tm@3GUs_F%f#e;S~qC2s*1Gs8CgZyro_lBwNQmEI8 zJ3`=u9;+`}gZA4{EYx$6{WJ*6q>o}cXZI@rLk|ZVD&F>U-HqM?4qabMDgMnPXXdKm zCKv(BH(8H&q%NQK1iFBP@Fn^^*sN0L#A})$5;N_#N(!=YrH`RPZ`} zuqf5+no(_~itd${h`Ef^#Hm(3-a#ZrPDm4FqzCWkUr5W(L7d3H_>mY-%7wP+v8OU> z+;@UCerrv*mRSm6GqQF_o}-Boa^GWEV!v3AQ*ft7;WYbGhX@Tz$r_=)-S>Nao7{76 z6&R+kc!Qnn26N`isp#^@{p9j;5+|isaGJ|2?fM)4FRfuW+;NLyd~;@WOa|Z2m;(Fd zk@7412-34|&c1~KR6;xi_3%iG-7bTUGlHiN{Sdcdkg~@_+B>I=!?nDzjXda!;Lbr! z?WEWFp3B@zarmhrR56c41*cghlMb_jZ>xlQc)wySYUWYk&{WkuT(I0f8HHgvLyGb~ zCCl!$-q~dK<&2S(N@Y8h0oJ~CDo_b5B*(HMOhhM`W?+~JIm0rmaPs<_MvYBl`FvD`t#jD8;M6P?LDitg62D}I{ky?O zNLL}lhkGTTC5MVBu&F?uqxNd?7FZbkHInN{K;r>Y8~8_{gBj~Z`8A)PD=7r(NTHX7 z>7xC_8Mn$qd3lWlSWtoDWQ*g!7Tju@_XG12eXLjJK{*rveaT$DiiJ3?AY_ULBn!LB z&`%J+)e;!Vz*2~VW8`v_lywCs?NQ47VEdkb#@sM`nw;R@eEy+yGJ107+){v>poR?K zH$OtutlU?7K>S@ELl}vZ%hMzScZ=Ko``VrJY}SY-@V|W6i+YMSjbGP`gL)!n+QmQp z9$0|0NYpp1%In;Jyu<=LbFJ?@u@bnd$>~S~FAvV#>S{n4At^hnl(@0-tvF;_)r)YP z2Hdd(9$yTQZxZ$JuS^>LsL<}~!&+ESwL&pa1W zgDnTs7$iU%ZWrNv(;wP0H&76M8AyW3{oK1`pSg4#rN%y95ha-gju zRF<*!!p!eJ65R9dajV;K2CUhkSRc|Uziq$bfXD;ZonkJ^{MzKsd^*S^eT|iN_{CU9 z2;W@}NX`%IaruuPVoF$a%vO0H9Z@rq`2JCT?6wnLjhImVqpcCLF$dksxePSt$p`>* zD4kn84R3fZokw&t2xVOT0u_j0G>DMdOawBm{F&dL5Ued=WQFnu+(|8hYKa|J89lgq;GGclxqZXIUy$ZTFaynPO@BwrsRqi}K%8Nij{$4P*7#uUnO)an`wk)jJ*CRf_- z7hI~yU$FX{>Z} z)Ub)!4=_ZPe>>U1TQOu4f3)Gc@48rTFsV1P&Yq;UJUgevbZ$dRGoN(+*W)X}7YFjZ;>AdQC|SF$;g;I%=T^L98HlI=vI-U(p$s4T zVbxAqkqs1c2dX$ZGt~P9ecJVB;RYAztzH5QzQT6I;)5 zjGa<+D?ZdyFFScqoZqGYBcj15V z7Ke~|?u^MBn>-hHD<$<-Yg(ZH1i8K^nE#1uK3|z7g9B{KeQe@fUAW3iY30Q= zT+VOQhDXdJlPw|Gx$003;$*s82~P%Zg`Me%N*E4*W38m0Q zi%(<VMU~&0z1CET`mjLu>R09&HT5z3hB5u)GoulqqbDJvp2GEpfrRqGCU5C^b-E zYiEh?D*i1Z;d+&1^}J*A)EJUEdg;&b>*iN2m}K%827fu_a|2lj2OTwOv>4+F>QBN0wKvuMpw%l<6_PixhE?TxM4z0gE zpHP*!w6)NlOpP+YL^6@m;CYsdKxw3mwuP*4<^boMTPW%*wT^LpAkb>DCMu#3Nl~yl9C@8%- z@;$N?#PEDvidbCAl)%@CYYukFYQudz!BniuVqne!ds=GW^#(~JwN`tjrzAqFU(bqj za6j+M#pCdLC}bnscc+eYccsRENW!)V?XyPVs)HV49#J>_YnRgwxPHa1mAosm6gO|f zeJgXLrV9LCb3P%>JIGU$*i&Yy^=642+7wr)cJmV_a z?(xvLO>Mc`>}*u$B#h6^kPjQ8cmVbIo@dV$TZ?1P+dsE*@?qcVMO*0di&u#pemiA? zYzW7Le>&AI#k>KRNAJR#oJ+iq(8O&Ws6jL=wuj5V;jXqOVCYJ>jO5WcRaQzkeZUb0PN_bnz75Y_;{Ne11d9N zM7-}AzonYmR4b&IgW-)=5|O~7T%9C8U{Ea=Y5?aVj{w{qUKaMaA*V zH6sM`fO4}ko0pAl!z$c|GzxZk9cH;GAr?S_<5kw%i+BB#`Ji~Vva4O)IS%16gT3`u zRnvgWvskhxOV(j*(1ZgNHP7HbY%8Z~{*%h2{^w77^IY^0(9)YrY@EzS$`$x{^!t7w zWH_od9+1KAaBKt!r6eL6&Fc3ovU`3dQNPxJ7WPp6$U6ngpqDBQ2#qz3Lkyf6o$(~* zHsU1PfxB|;n_s)M3poJ^L~ytiv!=V&*)B@gr20rLj%WlKSYhq@0%Ob&saJz7fqAJh z-@~v%NlV+rd$M*rj5IxhRHy;|OYDXsAkMu}+d@x5kb8-uvrmP9RolF`WxhE$QABSR zTd4?~OtisG5eWO{CQ3SD5RbKo%4g{Jv9(&-;wVlx>FjG2CrZSYN7uRKd}4c23{OAx zUChIHg>~yR@b@0Wc3a3{kQUx|H96L`vd6G?%W>gdIn+_;R8Iu8JbKI?dkv)-%AJ|! z{TOORYD+c>tO)n>))>)v39YVqEFl=2hK9X@8oYckTe`?a-?{FRI_#SX^E$cO;G0Da z!+b3C;w}*&;)VQ=dY&*Rt(`kM7NsI+sXA zV}iQU^M$cifN|pZ_xw;NwHk(~3l;UWQ-2Z&e&QYLx>89n3o<-oR64+i-Z(SkNbMDD z()3k>@-v*51VEJX+(cQKA2*w<0+;NsAWorRlkKM1{f}C{pm>)EcJ6n`+p|hm0e&IB zI!K(3$`WPW2YRbrTJ)X4aXyU`gXW{YiF1lsio_*u;S}?Mw+=^rv^5$8Pml#TAZCnu zHF-F09>I{dwn4DCII7>~s1(2;#@xhPqr~B?ZV!O|>IZMCfiAPl+Jd6>4xlzL z+A0tnM7`XI@n_+mWBM@}I)AAZjC)YK5{OR8=((p?**??V>GE|p9s>HBC&0fs$ptD@tPSbG)-*jv^H*e+(Rf+?hT1h7 z&cL%%mDnBYDH+NV{EMUGXwGalF4 zd!G37K#S_d-e*wOuX^0Xe}x~}#MGMHTD#7&Obn|cSl&qSw*44(epX;=#KMe$@=hoi zLRAY>)OV?l8(|V)rB#}drcb|J-^B5*^5hyg^3e^l?1h9K-x&@#1E7qr0nwmzPnzn@ zL;I=vnbJ5np5u@dN{&$&SAm{p^pCnv;tjv6&Gut@>q6jc4)SiL<(#}&ow2e;JXOFN zI3QO?AibBkcxsFIW%oe|=z(WpyrJj&i?rg;5s+-O5jd?gs{jmOXRRK0)1>~nz411( zxA&M~jE&pRtTSv+8nxI7r!QQs^SKOmFK;%U9}7>b0%F+|cVDc@l|(xOvauS^t?H|8 zw}Bx_FQ^$)iUk~I@(x*-pyqkJZa?Z+UTtANL)`hDqI}ol0IXMIaF9L>Y0(|)^i6VS zh3Rkj0G&o}PapPh;|gK(d8tGxW4nK310m0D_$KrjhF<^owCM%BKRI%abWPNS&Sr2u zTi^oq)+`(%K#xdfpd5?=h)I!~>zR{h zbucK2sguoZd;o<=0rAhRBiC}{M71M98_U4v7~V19SGS}@3aE9q_sujUPKRrdEk1|w4f}IBA!H@N#bfGUIgL%d zt1W+ky>i;SSfEAU)!uzM)HXZCF!vuw_hUM)CQUft{Z72kgZ`N5#If>`HVgKe-u82t zK<6m@EXg$TZ?Ii*z)0Ie%3U`W`lasITmKEg_P!wRrBC_auq^gjbM2<(yHthCsi2xMi+=O3OFA&gz4>vO)(q$AjCBCoru4jBA{#^d|{ z6;Cf4;i-sCx1)G3XnY<&%PM3V(vT6J1|uhn-Q_MjUMcYt-lL{TvI^z5z594%xvH#T z8Y1Q{6zwWy(2Y5(+yD~f!rmg#4f4>l!{~|77b{5Iitk}o>X`usMC?(k=?}}z6wjVL zq<*Ue-ceG_)e}8;!Ng{)3ZDi2R4y3waSokD0pc{xT>~;=evilmk>*S&-pN^?&6wX# z-6rsWi8lSXiW(L*bo%HN%9LO0>2V21uX%a3_X5Uh`c=_QEN)&D?EZV9488xI&skRz z-Xl0?`{pweyE1+EnhvCc0V9)g-KTxOu*8_ZK6!~Lm7^n_ngt$=cO{}Vqk(lDNyXvZ zNsY>qF}rjh`HEsW)Z{y4A?pwI#JPgp0}0>W=@g8n_>^O20(&XZ$wibakd>wUw&yFc zo1hkRDh*sL$0jS@gHpPUDlu0I!@WeTpRHVwcTex-+1jm+xwqyF3D zu6_-vCoi%l#_U1O3t14E(nUHqcXlPlGY`@1Qcz6Qpit9H8}E0deUox!Yu}#kN?iCR zn<^>I+f+`+SL1Q#^D#1RQ6P8xpetUPpjCq+VakLRwR&mfc(J7ui<+A#SgNtKnB9g7 z&PhtvttN|Mh3K~Xi2I&ET$9vQh0Aq(cc+SRt}Pq9$0SvDq#)6*bBR_ELzc;v&Gd8$ zez4!MFxHO20CMrlXTOCkJ!6F~Nhne_=YiWYc%GFTA#W1{hF#?hAw0 z$S!z3MQDFK`1d#4*e)!jue+5oWx)z$@5dZ>2gOma&l1Gi{_gE(=V59AM84^7Rw@)y z@{4laDErsHXmzVd&+AH9f~2vzFp;&&)GZU#Nk4y%Q8IPX@^!VOFgu$#`0(@G42LyohO2n{swJiWp z`Cc{7n2$_k|)+L_&+hP-M?{f+Q5?_$o-7;FV1{kGXibhF_E)Z!F&Bgk=B(5@AJM%~`bZ zqvq_GjKhepPTda!!Hr*=@bZ~vV|`)bB>R?&i6ViG`*QC9L)&vg4B<_m(i))1Jk~F> zyb$was@SI7((j!LKLxclPl19(AOO<BFZWNia~0SUwE#4M)f zNdj%`DnCy*vzj~SO#~76&MSM~k~IsNNR|de2ZB(w|E&LBde6aai;3?VTu{>0UnmL_ zZCQo)mYBiyrO6Axx2@OPgNZtmmMpr#|6vtEVhT#*@7%CBuli!st0S_`)1qJIrD#V@ zF;X@d3JZC(3)N>6mZNkC-x#pEZKsmf9@wDVt)kKFOd&>vhY``10eO6rpe)p=CNS`O zJMMnJVLr6HbWh7qv2b%ml^|Fft#)Vd!-a{@p|cH0bQ9)gaNYO`-5nebZJz~_d&Yis zGfB*$pPS>rBPu;yy5Os@RZ)M|2M7ymuSSceC&YITWuABBjWp`5Kzl9njcEIiGwZVJ zxZasLNU$3_x@9CO0TfPjH~6~^<<(y6u;6)^T+0Xg6{Q0<1o;INf)Jr=NjrgeK(Wv{ zMTX*xU`3c(Q+)vs`?yR^3Zo~B!cDmFdx?7S;oNj8#jq+;Q}nF_;-uCgf=^m+13C>^+LQ6>b~1~kIvfjGObb8diP$3lFy&(~9v# z7_LapUop(AS{ins1TBJ7eOx#Q915kvt?%AQNmdO_P0Qr@K^@!E0dMT%yW5%1Li?`XD@j;9w5QB4B7vg^yB?x)q1;g7=mMT$JG zfdr_5sxE$L*Nsg6GIES(WFvF1KI?Q1NkDggJFH$}cBFrG##2$yp|NKV@jD$J{~WX? z&9dbSzQ?@?CxuntNqm7xvAlg@+D00&TSS3ikGM=AA|@HD#R_jUtR+s4CZGD+<dx9n(AqH-9(iHH zPStW@gtOfPE*6xYLIIh|KH#h9&i9=9L!QH-k6&u#a{r7eQ~fLDr;VR*#eG{IiGwu% z)dOiH^|0CZqo74uAb-s=k&Q_Lb`rHf)Lu*w43!))qv<3WCyT~#7YP7B`$1N_kX?JX z4261~AYXN&-)95;?8xVkY|yHk-LvgKc<{Ud*NNe0!6pB#=g-!?Vfq=D1yDZFBj($g zTFN_5wDa9vUOA7J7f+TW=kFhVmb*-A5LohDO>OiH{F9Fs91w$Xd#hZF^Z43a8&4kX z{BZ8zG(f>QC1uTSc!T4g)(y~I@xfuj90w)Gw4=3nS^;kZ1%GCxE~m3`96upOE!GZy zrX{C>ft4K`Gsqn7s#>K_z#NL5>`fskLMQM2TsK=xpF1?`hi!ABGLEim?O63?n4bMN zgSV$IQ1;A)CN!A_FIgUFg>Pcl6HB7o&xf#W+FqJ~@BvNB98doVGR(1ZRVT$mxu5g3 zUw8hJ$EkZY$2530#TxbW8)!zYiOAJbU*tRO4A0^mb`F@;)w;m<($c*S>MPrf&IofD zxAE>1WB#>`nZaH?(CPqkD93IsBTNscO$N$2(Ux$m01!F9os^EPFSVhm0P= zCpluS)Y%QBX2Rdx&qEVusxGgxm?D?Bq2J-;SF!MPD-%)hEX#jk-*##m7M*C@>iHhH z2*-2a4=ImksQz$_3L?V$>x{!h!SUxT2;pToPuNa-5WNpF45MffrL&Lux&1>zIkL5r z4T4#7)iq(FvKP#dG9C#U7X8zgqQxp>dk3p-v}PH9pphcR8@jvo1J^v$6*Dvt~*KN0<^wTY;Uqf{ag2-OYEXa`>qfg8$cQc zCH63n2^Ow!{e&sH-Vmr;k$vBMe0`Z6pX$Oxs{o|RS z23K8{J+}1tqz9^y)0j|bhDNzF@Znn#@{)}UJuwvC4Y}CgHiR|XXhTf}=yZD?mM*Zt zaXQUE8gkK)G;KwP4VDBKc8d`v_fL&g6UC>J3H7J6`BJ51ZvZHb=3iqo(%u+%y{cw? zx_0C+AL0D!s8XhLp$r2pGnJ$SxCWhm3Yx|(%6I)OMasY5yhxi#qHrxNT6~R@0Ui+d za@4tBtWr!GpwsbV+n`y4j@3pqf|~(w1MDf<*eX0oOC7a@|5(uNtPdPH`rU%?f(KvU zt&5&Vw%ox;e|_hR3p1QqG5^&M&Q)z5t_03fgV_k-RwUgVt+SjeUcFUQWL0L;b?x+R zvP{q$MT$N)Q2HEC<9^exzJRsBrlJS(@8+$B`5maQT~s}2vp;f|xA~Fa26v#;`9ege zT3OL!k`-WEpl1~k!#%8PQXKWDG8)#Sru4E*R|hlNXcMS6nvS#z++<+ie4T34W99lc zP(7)h=*{BelZ<_HTX7Q`BsLDc7y%i*JG_Q^dZs&zxJZh#cIjhg7G7aSF=NoRJ!6tL zdRjn`{ctLTg`9~ZdK>q*@-6UzS>=p6Em@mxp*+6lG7QlTTW6bZUiD0USaPW50k(H_ z!^%DSQTMhZKnM*vJDR$z7Cn@*-~-gdBno5^??~|E)&k_mxdsVy_DQGjUQMJK;qMt8 z*s}{E+>S7NRp5*?MfYr`%Fy<6ES|Uiqek_JXU&!c$Yu@rW*a-X_XCOi&KV3`IS?W9 zur%%6a!?0^vcSqh3Y>Cv#^Va^5k1Ee{@O678K!Hzo2{*TqTTq30lKD>K0%Hu6&xowvf!j`{Ait|WWnY2sx1UOubF{Gzf zD)5)E!iH1V^=fDzFaNQYq{_IhYwk4^IRDs0L2+RSejV&NQ1#p*2j?5wAxQ;4oYQ$( zm+u7V^|QItK|;xB`rsGs3|K}8c9M@Iu8h>UPKu%A3YhgO=l`LRj9it|^ED$Cb0 zZ86xNFGrhkeWj-3pg86fbaJ`*d;w;yqPvC=rrv2h*LT-TAx8{(2;VQ|_vk?}H~1EI z)BE2-|LHGrI7JZ#MW5M56yid%4J}h-%PPF-AQlOkR&`r2RW}#p8V!wS2of@hTC5%b zS;0-H15#zO3;Id|^O@MDmT8!vtW_y4){3(#S(J5(zndhi&Wh#gZM88?8;7tm)wqUQ+XiGJH)1Zu^8*-5WGJjgL3=FQSz}{Jy2k{HXE-pw2A?9XXWdQ zOGzA`Q$^0DMu{to?gC<}%HG6MydgsRt3hO#L6gEoobx$Y5DPgy?RN!rL|vB~p15dO zHmt{uzLIJVo6dJW-ffq-NQL&j<2o6=8h{~*kws^CkZQbhrG*WU zUPiq6#|-N!;(V(}QpgRf5qsOnn{ynSc+4tEE!g^sclR7<{#&QNNIC_*w20rd8b-=-pF*xUiufRcW!kJroxlwY#KHb77;dUrfq(3Fky7V)CqN z#3LxV@N>*0lPx`RvS^2?=D-K;#>GJO8}3xk0^8${i4zeMLFfb=8v6?kO^w{U^kE>J z&y%wfU2N+ZXVJ_P6SvehMO^CyRvJ%{5+=hVi~O96F@nbY@&-4-xE6{?k1zt461SI? z%5csBRc$VY2)|w)1u;-lf^``7NLBLD*N>{UsFBU4ZzM~;$CF3O46TZA!0nppbAD4( zf$|y~WQ3Y^k^l9hj%`I*>F(IqvWo8Hx27X*LnrmGe_<<3dW-CaMnwJhsEnWlP{!4b z{%t&+fklUnO;EIJ-S(#Pr15NtUbt_3gHhLGSMuK087~EjYlimifwS_Xa9lLeIMQrtU)be(VCsQHRLdr&T`Rx! zR4Oskwxdc6|EAYA2OR`@oTt=t!IoyiNg@acR>T)WVLce)08T&E)vudMGSaESu~;y| z1!u7PJf5C{a;)nXwP(uBnTQng0>6&HL8lteu5EF81PyX%*1AAy-diT8zVDYZCBb7; z01yb9Tyl|G3FP9HVK2J{KCO_a0(I0N0Rh5h%aM4?0Sta;441IBO?oSy!|=Frog^k) z$%ix&SmrYLjqK2yF}!5$Idn#|WpKo$cqzct?u&}Enshg;{SPrR`jetcx&riI?RZJt zfC|8#8POnnd|DR%Uw|!z+WaJJIoW^O>wGMAV#%u6wih(WTG3z_kn{AQw1w73{k#ED zdw^;nwdkII7^Tw0@8*3?s?L!YMI_lR4|FfGApP2AdEdWazKf0Iy(B-)TEBG)uW45 zR@0w4U~~K7O&p!Xx)4*YrZ?cD1m#gIk}a1Nx}eiYDVU5gn%gifmZYPE164_kD^MJh za(`?izOT;9AT+;8O@l|AgI|21f8@} z{fzdyF1>_H7%Zm&7>gy`3sJiMvPyCF0jzP5f&TwZyFa@-INnYpLJ{7SkS~xDiaI$- zua_8aD_thZsiU&y;^yyNQZCE7Mn0?FCAP@-$_X$QFjg&B*jdiJ%&JwpAdIMxo_C6y%4kR2pc0Kk_$W7E!%T+<}Q@b zrOe``t$u+gJcu59Hpc|hd0^{J!`jO*>254pZAjGT(?||4TVg^vOcCAtkp-)=Wc5!V z$08u+r*=T>lkNL_OE{!Y#z=hU)OpgKK1GS>(;j%auQ^xCbA3+9po26FTEKC{LCgqZ3k@_vL$*)bUBE-929*q}wn`J*AmG9o8(6Q`Z$HKii2 zgv$oVE7maNyPLLD8Uu8L{qK{dfB>0rWcg-dCk57t@2N@h zG&-`A_HkRfAe$HDC-ng5hnXGU9S03L5pqin7-FwrI<>*FU;x-WRMs>(>$D86CPhGzqNJ$<(0t zM1wnyf7kNoJ`BXE)5aFEvswoscY=uF5SFf)2;~<)EeO#M@hx8rLH4MBlCgA(yZbKOjU9XE8ai{+qzHa<{+SM=55WuO{*| zK9zc_&p^NDw!#@&FfRJDB9^gC<+GaGlbP$#DKG>CU6$Kw0%j@kU1q(9vVsW4V2k;u zT;_b6{OOQsHM7$EXQFZ9u6oRx%336uATYSmqn-nC?4DXNZob27>`|nCFG58fLn-2b zsme@6frLt#=RPtcKR_!?4I1|2;FiBPE?uz@Z0FQzp5o(x8FMW5!Ee4sY2pUV>FMew zG6m61-zh|M#1QH_m*CJATS5Qx3?oH%nCn>h9Ols6Ew%h@H@GxB;YZXTS~lQn%M)AT ze?^+T{uAtaX#@+lc*ocwxg`nf+S3AcD#cC)$Y&OLQbA=o*;%`FuL51e^AooJ{RXt0 zJ6!Zi)ZU4e&^7*{BP1zGExYJv2u@GuTJ4y4$M|hrJ!`Hkrf_*f8D0c_6SQI+zfrQ$ zC1K7`3c-EQBaW8{OgFGwOiCKh5qR55u50;*(YJ1ZQ`Y9lq3WGo4kCv-aHY~oYRX-4 zXi2ukUZ?gs;ayOkUSVRX$w&&AUnK<|h)o~qbFueqaz z?SV$j@>JBhFJuqy5WEZ8Xc4Afb>9r={~m;k&`5#BIz|*fp^7~euB`zw^^OnLsx~}_ zk{!_j>prlBwW^n$cAF>C7PpBaEMdg|1;KWl+j_NAd;wnjylNC?{Ezilz+W*fb3`F! z1Yl1oe5|bjKQBORjt zBxsiT6}^MYIr*Vu9U!aGnJv=DaQ4;vlH+TLobR}PM~Nhd>5g;JL z+OflsAM6RoZ6Ng%0#|E&0&6B9@{JPuvj8A-#7YVLZ3m3xTS7LPsqg4nZ>w$cA*FpD z(nyX_$q@1ed%YB&Y$A%0$`wOpFBm%YIIBdZNG%l(iv|b;WkD81ulV@n6j-xd(CtZN z*%zYM%>Q!<95x^1Ie_GW<@WnJXbi<>GAQgpp@}@oCa_8$OV_U7ESq~u0ErrW?FwR7 z17GPnSb~bk;ITrIj3C#z6nI5j+F||`{5zG>C;7dCD4{R;fxPA14*!z0&SJ*$9d5U- zfwv`Gv;G*#7OONSe{{|-Q)!)Ql_)Odj%Ov_vgr$4oimhG#C@a7Qh)W1-KRg64l;!i^D#Q6vD+xR7If z^He?LTn~`GaqL>TC}Dh=<*GQh)q~t)&v}Eo>JYG!UO_+_e47VXvymn^)mxI}Y>ySc(m71AsEKCyI@5fFl|wlf>6GC> zYLT2O;in^oxL7P2M1hPWHAII2oKjCX#u2ezkxOx&f+2$@gXic!}hZ=z~q~INp&o-yMz4s4SFziS)lvqGJJP-o58Khrm=5dTyO> zcM(on!b8SEyc_H3B1;m?z}%o-Epilhx*SsoYi4bP&aKKaiC`&XkF=c44nRa#clIj! zX%VVweGF;VsRZ`C*@qF!>6doQwEbwQ&Er$6K#ia1t6!zkHLzT+-I!JJ0f<>tnf0-( zu^8?`H!18D1V;IM>-_5$-auOQqS{(g@h%~%UD*t%>mBZp7mmNE@-cVXre3GnqelKH zLhR!y(~9I>?+#*_O7kNbh#x>f%?LahWD@NAicP4CI96f{RmZIi(jw?{-jAvyyu#^& zNbuDW`?Kg?7jic3#B->a?M$KS=38ZqZa~X?*rN=(ob+A4;OEkkD@GuCr%kfygJ`rn zDsq^{>b|-EeG9!&do}6rIW-TWL1cfelyWjq&m3NB!l7i@SEkXp};P56;5#duYD#!Ufy?3C0hmq-Jzh zF~dBPT7{(@#t8T%%{ ziEajJYbvGl5u|RWnr;>BPVRP{f!l7-l@X(O#B=rx0*V6H(IYi;eI}mvl@oC@IDOlW zB?wnx)vHM$zu#po)0D@hrL_G z*WXYUE;HH0l#Sx!`xB1pXexTdCiCfQhqRrBDgxELnMQZdqg)8poa}2)(M_m^sWujA>B z(s-aqg~;G;R(FRA{hppn%(|2M(bnT;IIR3Z(gnNkAs-J7I!eykVp7Eu>R#&4^(%0t ziz=fEe^Qxb9{P{2Ucn=vMN6-N*F4$(Ev=xy1gIa5LXw`Im3V1%+v6sgz7(?O)bsX0 zm3!V(Q{~>aOr&wJwLzQ!ih7xZy|bsulQPo5Nvdf}V98avFW~Y=d@1o$>yk3id`4Hk zD~)_7eJ)E%BvyabAnU{^q;+3TOXjt$hsc;LOk{VlP0Z-2|pkK5@yfPrSXlb)S z|1h4We4EvB0zWs*t!G_D$%2H!;Qy-1?|ChPQs{Dr9)zeQ!?+Uja91*ieL=?erc~?C zDN8h&ZBn;uI;g(P+x_2?1OdS^Sb)6wWW-ifYC-(0!e1ix*&cLd1B3B9{oq~Wq&o0KMolJishKmBzs7gwCF}DL>_$Ff|!Cfmb9nydi zV-Og(JpQJ|F<@_KMw)1cyHv7-aGY0NW9HZIToaFUA&~JS%jan&G5uGdxPcqM*WVQG zGg(}6wD|)Xs0^)xd63bG47R68=LCJiFeMzmW0vs`u0_Cr%he~HrR#U+X0-{t?@{Ya zASUzuBQT|+#;io2bDr=(zti_&M)cqHF(SkqZt0yo@YB@;({GdTRa8YiGxqA5aZ6LD z&o$kC7{(Juwn37ak(^<)TOBOO zhvH~6MX+pqgVD$3UasD$!P;UEF8FDBeL&E{+? z-gX_vV}d+8M#fppnUJ0Db;|HA{6_$th+_C>esis=fnw0y3#d8apTivTo66!kJFw$} z5diD_kD0y^WwGy+dZ!KW(E6wgG`3in*#N@z^>JZGYax<^!@vx z@9@;w<%k)W>JSOz`{iS}se^<`m@e2x+MG6?42HeA4Wgl9U^h=%`T@N{3d?!(>R3-o z0W0v?(p98mU5NZ3HzzlgZ(f6r+1rK;N>b-TfX>$GRp@ z^@pijaP-;+OK<4NC5*EZ@Q2rq*ImY@~i0O~V^Ws;T9HSJ{G2EQ zzuh@Gv`bdHZBJj)B3`rLH&PfR_Am-RMs4qSAOuMh5(ZH*fA-&#pdwPqln3hmy$2B> z0u}_s2>!Lp5?s63klGSJnLJVW2+-;3UB;b}j(@qHyA+(at%`}`CSg)PsO?q@n82a? zcm_N>jsDJlCuF}s$plkg*37O(?ySsAyp~}I*tfTp5hD^PB^79mx^dixX3#Ag>M#c- z=o{zO*BnP&Gd&RtQMQCAXO)R$Uo{C6O)O}gldL|->zw6TZ+=UD=`9@Q;^{dNDB$Ik=V62)S3E7A%!RxTdUV*z+pbHExkLcFC2jF64z~WY$)qV0}|mw#e;W7id(*$u7nM5 zH9;CfqxQdklWV>MYW87H=WXS0A`DU8HiUtab>c z{Kn?j=B~6v!2GYrjav+<>MCu@!!203?wCE_)SGRH>HJ#OOd~S?jCutB zf5s=jv?l#;D#Z_aG1(3@$?d=&h31|Tcqg#vcpSB6-Eo-#HNNv<{jSUL7en(R;r_qQbT+ z+TKJiKVU_rlsy{ydf;e?dK8zuMT!FP6hskt;-A!Awg$^GWuD{WWoytn8z3qldiHD# zXc9ghk6QM>RSTnlXFgD%@!jt|eL>W1fNQ+g-BPr0@7$TnycTNc10vWT(Tk&7`Dd5$w1+&^l;?> z6i_;is4i!8D(~uZWC!{pC9?58rJhUPuT?{JuS!xd^^V`_2tj3P`-rg9 zXBt{&j@pCRN$q@`qs(=H*1nE>hk#-XCkX=GH2?X1&^2SNm|I$|qi3*ufdjTt>@^IN zuHCMi=@>5hFw2lI6#*EC5 zcu%~cGwFudw8v3=>i36b&3g$IpnU40edn1FdQ9%Uot|fQ~*r!b;KWwUpQ{u8R z1U+r=G7A74`rvki_2oKK?bnqI(z;a^MvTZE7MHKqig;p7q2Q*|_NSac2KKGScqs&= zmP%nWp*nB(++lIK0W-|*(F}s3l0Ri4mO`hoVS$C|1= z^y(vu{rOpZJqq9bDe$KTE9wzLiKM9|i318(;p?FV0%z28^$)+AYhp3qzp~+;`RCDo zr$^4e*`I#K6V9_f`{ut=k)evsSP59ji*W_68@jwgalqgk&OTy#D5sS9 zhhObVqReQem-|SoYm5&CG<^res5g4SWI~?2uHu4HhkjT564o6VuR=$qn|{@EcUHj5 zrh4%F`(66tqe0%aXlw+n)B_QF0;=cicg2m3sM$eQ<9*aBZ za-C;Jvb(A5-YA9q&52&(C9ZPrNlrd+KhD_q0ouBHUGp`)$oW-Je#gZ4eHVVeIKhf9 z%%Kv2|E$}vfo=pudUsm&PXJB9wHqnl)KCK3Sg{ltu$}c5hjYt$L`&Pd+)-al%LjVE z2?=T-nSo&yQ5-e-J4>Z={Y}=9V@+?lf6s5|?(S}9QK(;`xFEg~vV%*NRr#A~vTWlI z-Y@yh5W+xB0{+Z5SZv6?7D#=Cm2b`ER5Z%Tq_MO=;o->BVm1R&Le}?DC@Sao7f?X4 z&?$&_9)orLR@*}GE9v!hozv&clL*Rff@9tu_kfwTIR%O<@#Hx7BkS=ghV|Yc58bR6 z!pqH=gViUURQ2f81JB3+%e{&}xr!u!Dd`Qyg_{8Ivoz7Dx_d^T_D+Zx+W-H2pco9z1gS+8f-!{*#Mb z0j`L)wiqu~FkF!vDtzTVdyE!(0vOZ{^SNS-V0(kzkL@Zh#Kxe@eR&)fxV@-fU9Blf z+uP*o)JrKe(pk52sJ2y;OG1rHNyeQ!r-RXl-d|wNmBxwm&(tDZ#j}JvKzA3B{jlC` zzC^8{DIv8$yAymXpSv)F8dq4H%T&&ayALaGEe0T;1g7Q-u~b)J{6r@wJt03+(9Q*% zyfAFI5;UjCeb8HhGc01qct_GCTxZH!er-U{&=V7AHnE$15DZ$m0NXKa1uYy!5Yhd0 zU*gkdOcmFMWb_!zCQQSq%;-k68#lr=n`eJDriU%J+Ye-33Ww05#7c;@`0j``I+Rav zVW5|<)hiARcj~&^1HZq(5AKU%7(Tmq|FrTyu;g>prR>%EDf0u+~dMA|BhKe2ln{9W98;$My&{uv!u^E|_anw*|w853M zLwfl{P{wygV-`VfFP!)R_kStR8vMTm1e3!n3x&WM7!Uo!waJ6_f{j^OellHBMl9cPpzzGN3^GO3R1MGeH73Y9G>6xhJ= z_O=C$pw``TI=DR?bolYpdMEc2HUf4L-n5WI6Lg-28r5+6APmLrz@qkG(Xi$nF!woS zLaviI-Pcp}$Oz5VcRRIL3k{8yv|x@0^bn)5LgbIh^WIh-ZN)mQI3R#Rtn_T@SOa{Y zRitd_jY-bFrMS{}4CN!sf_jB9icRJQPzEV{g7+5#Y-wcmClZtX^?AV^-h{$d{BHvy zN1HSgEAA_>-P9WZzWlSHPEmJ{jP(D#j7L39spb0}Jj#ED+1^17OGSOPr_#$iylD;@ z4pdpMKfoGKT_jXx;qVk+U_@rgilm(AxH*L#ALSzu_IMIPsdC$zfFJEafa1$=4(>67 z#0$RWZ!%TbX>NiTeU(VZeueV*j8e0P`~aYEDb1-l$Fp+m>^CZezm4F!1oOIY!8=z@ zburT7|M9h_{_v1Dwmh%SspIV8B6(Ek`0DVER(r%O4dKpQd5T&FOc4&C%8enu zJ$zh-5)|@wtnxpm?*e``$TQ5$>Q{?VuK@RVhIVP?uCl|x?Z4(}(56oNfzpqPjN-*t z&=_j3<=x%lwt`%F^T%_*dFb4u6>SoR4U_HpiVHjvk<;0DifE%NE5FqbSDn~SV9c`mf>>lQUnev)MMh3d zRvSwFM`&U)F2>$4`W}L2i-+Jod_6rUFqxPZM7nEC={jf)OE!2u39&svBdYheCGpqS`Q#mXR=B zFP?w&9UB8r@@+4OtT|QMZApn}Ib<*o!J?5q>;hr1F10l*AEX=ak#bR|D|#mB`AwXx z{v+auXWCc~^`U9{`m=^c5ygIdS@4pP4gwX^eJo_ZxJj5#W07C_}ECk384SsLL^pMc{t(7w`{-<^Ije4vrBpug4 zRZSCSheRx^kL-TOL&5;iz5*?#UyRtvY|K@dP_m@v(^p9XM}%GhadIOXmQ-kX{t;tm z>qVCeWcYV7$P1KJ@PkhN-_mp6Prb@2N1pi4-8-$#U zNQk%_aG?t{D~}W&U#IPkK#?(8o_7IPp3p7=0 zqDtwVb{)2r%q`sv>v$!Bv zBR<>yGA$^ey_H_xPIOS$=@*=PK=Sc35Uj&j^EU7y504SfdrV zO4z#RQHwM^ABkd)vv^d!eleC{w0<0sU`3aAoTo^LftO>DQi@5zqiD`d^r`%*Y%RK-PL13QEElh@&c|LohbN<*viY#JT7N7ahekH=irrA~fj1=Pxfy zNY0JsXANal%bP{fQCQXq6vZ2>SJKQo4lBlxGBy#WJ-!?c`6>uT1IPo@3Z1{8bf30HESgapQ8%(0%6ywyS(PsJ3u*I|RuDQLm zmAAc~v-*To32KD>@kUCU+;wll?W)AN)w7jYg9$)~SaPd6Zxelq1I2dv@xrC9((Lmh zn(>eI5vHJ&-W0opD&rlzW|gu(I^2LAR*P*HMu9w@y&O( z2BfW6FjN4}ybh5!#8+$rBr)_O=}Ylu&RzLTP}X`Do?v^VO`6yVaZ3u^Llk~}IKo5z zNk}xKLR6ZwD?MlX=mabNH>ZiicjZzM3xw0C+bv|3yR9iJNEqJn) znmUWwk4iGuWkd6YbrxZ2pn{nk86l0O7$K;~*owDvFJT|OC@97%P2Z$QnQr=*$tOr{ zAj64S{C#@U<$f8cHV_>XF;XzJ{2E3js|^}H`bZEfHb^ID&0^$LniAIBWfIqxySP{F z=J(CTlq7VldpRV@18{7xwe{T_hG&N!(k&F9hr(`*_f$A6RMe6yxRi`XKZGstS0 zt+vtkCMV)bzpE*_G=BM>-;ogHl)J8!&0m)g&)~SuDWi4!WpEO?Wn>1{!BriB%po|h zh4hBl-rz+G;#g0KeBS$jz^XfmvqKeX=}jjKXwTIx=VB4n7NM)#K4CNwzBfa#v13db zZAgTRkgpc?_;apXs^pvQWv_ybWAo65-_Lj$A2OCyL%4i=X8=)0Y7Edzmh~7a>AL&H z;d6-JN8uxdhD|oQ1p5yy?Ji7$VoD}90baKDD=Iyp(W;-7DTnD>kgD}AB6bYbH*C(;=4ruknOK-D^g<$Un zolPgbIvcH_PEE2bmEu4Z1d%E1K*D_G*Pfk73{?`0-@b?mU4;eeTQ!PCf{WoXw(ctUgbi%;hnbR2>u@Ni3udUd^zgy8W`U^_cGj%mSkC1W_i1&O>6 z(^IZU_}mhTDlUj33C^fVRCu+AgT=FAaW5r3nrKI_+78Klf=LZ5D?=X;mU^n(e~)WV zOBR1k>NHQ8vp>9?3-*hE=DVoT3u3Yu$S+nn@xVsYq_VTacDoEC#UHL5if;j!9Fk9R($0kk{|jc7B?4hUhLp2!7% zSGo>QTD-~B+C}=L&o*gEfR*Tg`=^@pYhAM%a4xCS$U243yq6E^1-|S@Q~HMGtd$^| zv`aXrY=5}z)A8|`a8rH0_pATx{A_G0U3P(j^E9uN#RptW=m= z;{~<^bpf;qsvtbNf+>Y;;Q)cA zFdV=xY0OB14IC4HfG0GOY+36{98*jcWHDftelJ(PZ~cP^{I+NX{jIQwr?TQ=!hEx}3+9>NGor$ki?@ht4pPv06%S0zo~_0;4sf;9AB68pnYJM*jvzMO~u zwJtC#?X&i))jqvu#L=Ap*kEAAO)BP5IR}7rE-r5Sb}6$=XPGXcj5gPQnD8e|->QU5 z^TCPaQi!lzY=PP^|3;nQ0!KD&!R}M0K9vZvTU24l5*FbDfze>Ax_u5p`1juW7`vsX z1Jig1xhU2nIR_$g8f1Dkw6eo-M6x;%$OGQ##}tQyRaWec;{yy@-ZcMA^qZUwVEnHD*1M$S3)44Dx6F6(^b0as{$7f2Lt zoX$N;^eY*lV>MWXGJj=k>yDV<-;zv8Pf%_vUUZsXK)jmX33S;kDhB56A3E~p)ObFy zEVX43HTQ9MP^YhiXNDS>g_A8|de1+p^h4>IGPUgC)->fN$qOGTS~j zR8K<3Dt1WEATG$O_Y@@^5i3!W#ml6?B!yyD$9)-+_H+dYJyZ*A=Nn2Y8TPbuw^wd# z6jA;yFxICd4%AOmhsDZBEj*g3k~+`ohdLj=1a)VI1J*Q%sNDi15{JHfq1)!}6CGMa zU+SF#bn>yQo0`0XE;#aNcm3okSniyKZrs`@G8>3u|>GfmvZSo zlaPKk0P4lF5STAdq#=pDPW%o0-?QP7+J2Mw{b0_A4q(+}TAhJ&+hV4ZFeAc#aAO40$<>)#L zrhw1Z1HpJD9QF|}?pv0Sxwz+{l{5?&(E7q^l`D+IH*pp^xjl}0+6t(!jNL*rMoDkv!0kOoOX2qc+J3dSSa47w64(3Rc?6+9ba3fveTD1u zXyUw3#=C~dpw(@wnqX*z@j6OP-7Y{qT58d%Rw7ETLIyn#kTbxda;Z>vRMk3f_x`xb z1WOdfw`2*(Z2mQOiCP3pVg9@rUDdDqpV1|zSODp|5ej4O$jc6RJ1Fld74<_Rm&1E5 z(}q~UMCd8wk;6v3kjNfF@JodYg@zN z!sy(JZvOKqq8Gg+_fbNO$lgFGJB%>%hDjA5D2l8jjA48rY@qC@zJ|go8Vg!Z{qopF280%*qCPK?R8XbgquWey;$$h0)RdD+If}F{$mt=&a|-ui7F-vC9ux^`UnqaZceujku)B6E zN+}4%WxiA`HkJx_J6I!o_q{IB-AVr1Xr0<^<|`WVX_XF{MIXb9Yby)wPDT!EUdFBo zFk+jwUIv?i9gcnZn(cZ$6{Jy@)O~TM^CW7;F_(@JUCA`l`VpIT@5+72UB`C5FVnba zzCw*J4pG8D&@Ex6otqLWZw4YG^?+H8_b}=#d-qE9O>V1S;c-1kKvX@XdWO0g35pxM z+?}SB45x4zw8g$pkfB7GNH<1g{{F*;9YW^TmlThEcl<;EXpiAf9CpYmipTjc;Ie`8 z_P{4uUghN75Rr=Zm9Aa8sJBFFR)QtLPuI#~tBTb*nYDd{TNz)J;bc~5PFn@um@@SM z;rkTNE59WhsQ+AcU-+@~`iFv@~A8 zz_WdJATwvagX9;Z0N{Y!=dAU?+}gXciJ& zTJmQ`mTk#R%3(mlb7gD*vWII?5{`u(gM}79UZjC(X3^t?J$0ei+UpXlg)Zijl|dGv zGxJ2FZI5nOxM_hVy691McfH@Xy9C}}gUF;b8r`~j=k#}OU70%L2w0tm{8-iAXj+@8 zg{U127WlQ#`?+vs(pW{>m|rtf`WqQ>+?Z9F;^mmod-DUy*WOm)V+=@rZyAHa81ERv z#Q+Z@N+_3z1ZoI!WF_Y^kU+t>Q`QIcTgxB4z>Fci`Bqpm*1UeQv-oy7;2&MdNfT*I z-*pk#Nyr~z$5;5jxt?#&b~+21edCm_wWP^lK`)txMjew310ZS&wu`!EX_u??v)>2k zs{K^DL`p=v32%MV=L;gDrOWNbL@c1Sf)hNqGgf#Q>)6DX1@kv=ysrjx07(N+>7*A@ zl^97HT{eVNp1^r~5cJs-E&$d9H4ugRl?8ePR}c{A8aQiFX6ESdwBAkkdG>m9xAwC# zXV;#A+?2-h@d}G?t5WHvR-$?~*D}W6i+^duvaIf&ZY@)M6)#}09slpJX1uI*egq-A zyV`687hM#yz{z>aN3YECbf1T6sgyi1bIAT;HGZpg>lBTuULf;-+dyZCJwkN@B2V{I z0`h7-99_q~|8GQfPgK5F;ZPZfG+0#Y52=H@Ztp+aeoi^y%V z6+?%1j4lw}6z$UI81!4HIS~{6U?s0QvOd6FKFHa~ZBKaG3dB`uwtZtmf5~KJ-Y%HqQ&Kfdk%Va-HS34g@@lpk@0 zCBc|RII%Q>zNb^1(N1cbAEm{JJ~w|LbwGO=O5Ov|X+6<4O!9Ei+2*%&+H>M#78Lo< z`XF!Jk@vD4SrLe;tNct-Y$Pn+2{x+FjCO2h8KQ)7h{YlZ#;p=?Uae-GYlg1#kk~2p zXfG*PlFQ&dA?>`Ce=9)G6=<9+{Lqs;k|m;b~kY_1LV-E+F#4 z)Z~aMeu(pLBSs=`BowUxH(V{wY+R1lnX+?*T~jwkn=1hR%FU{usn(N=m2j)HeMAH8$Lk$h%bX&eFKLJC8XTAXV84y*yvlFNKd{40W zH!S3?@nQaL`A#x3acVBj&Ls)QndpsBZ$e*IAFZ-`;GVoLC{?=gW?_B{79~ZK|kkhvep8?R>7}H@6?BCo|Io&w<6X#UxA{+cB%WM}`>kjiLeR}7q3}@t+5{>W* zp6hyd0>)-5thltL4mVGiZ_VldFtg6oh!IOPz2F5)p9bIJd)iwMb@_h7>1Nkda@9*m z2hA{f6%eac<%fT^^160=B{ABkUia@mv8bkLmvJl1K02@6g)QYI=v;F zo(oU)m)@Oe;pzqLxwQC0>uM)VO%MSlleeB?ryjt$bf9-xylAby<(5}Cq(*9Rl}r-2 zM#SWQqZ1)`QUG=N-22YhUw(YnM*sBa)vrbn6&Sg$K+oueh`I*XZ3Om?2)t|jA#coH zm&d#BFY=F`?ih7^Y#Sf`HZ+ao9y_*ryJg8}q`eYw;uivjpux*Q&aj8NTN+WBeTT*4kZ+0mIc6=Cj{& zN}c3Ca@iKTYH}3jV+$gdH*3la8YK$z3Vy1IPwKU!S_XkSQ8|Yurdf`+B~at2sc)sg z#F>zkAtq{5SWP7FYtyPJoVe&v#MyCp({VRqSO+{v=08@uD)JV8335W>eIbVAPj}e# zvs(XW6t)}|rHV?y98KB*maC>d?AYfxQ!@NZUf}%S*pYWQ-q>0OT;kczDVO9lAHb3x z*au#1s1TFR0FEc;0UKA)1$n7`>;SkY6O!K{YuMWvg7$&d z1hC8EZGxJJ&_f+~*MGVKL^GqJ*Fi(G9Kz^xT-MkEkJYDJGq!B1fFtxS{mU^CEVc6}mE*H!Wg~)S3hdtU#b|ei|+Yjqdz&ECw$oL-s!v@ev zlkwZSqVUjNjtTQ@rdzZYf(bb9{s1*}@{~h829e~58gGnr>blI#|VTN)3*Q+;!Ke7<1~Ri^hA=6L{I@TkVRXhhVV-fuo$Dtfm+v&0Vp@Wls8m| zz_5s>boXgOoQ3{LYh&fHy~lkO)Goyj97se^tRvI$7DdP1(ZYwx0=yUv?v<3t!3?E4 zy3rJlz+#bvvsVP6$(|n3uzQim%RB8Um9d@-)KL!YlCdbLde{u~>=mjjo~h4dyxcC` z`Ms|&l#Sx91b!Qd?%w3Qo}7F_(XR3#OQ+W!f4fGpJz^jJ!A@u+seDm&sBad8PS(P9QMYA>J|acvu@csu@q%K4^4=W`xD&EqLi z&vu67YQ)0xQ2bc{X33ucpsE;vDZ@;6Qs7gDugoE+{FqC3fbDWg=wa|@`)h1kwq5p0 zT4>yk-K}-7Ye%RJ00H=GO|O}>5%H3JIQeJ+?Mc8pKj}bz zL^7xQA{1M|QgwOPY1huj3Uo%50tv=o8KgjWnc$0Z1g+1bk8$7IH#3|Tsqc6sV^rEt zqtkE(8SY4mRV6iqpo_KNZczCS+^rd6!Sufg>m6-je*NnZWm2JRuF?@!2fR#KA%sO9 zqChQKH<sY zq%J{PqLtr_J}~M&RZS?z3#)N`04W>iw;G?m@hQUJQP$P}{VU4>cF0&XZM=1nlv-U^ z?F0u-xb(CBt(HuLriW{q7}nCbRT)_pV&~wnNydkmo_H zA-K|+$I*ZmmfiC#x${KGe@=HoQCqO+Kf-z}_iV2{Gjj-Tq4mH>&%F`oFZAn|NW5-= z>e(NBBvPDfb&;^Mry&waxEXY#mbq)8vMSMT;1!uyFyrn+tZd+G(bJVcR}FBZ%&imA zdlEGjJTO$sB{{0yJx;&~<_szzBnqW8Yw`6Xo}fE}Wli=X9&Szg`L~jC8)MNmO}NE@ zSgo|?t`B-I{bmcW#DhsN&vzL>ef>dbH*tzmz1YFa1ALMn~UFQR<&>{X`#dFIDu0?@jwtn4wrqC6C0i2^sj_=Rz8-$8z5h2PB);-wJEsw^Gr z8!AiN#!*9qfhzEt(0J7`J0hT09y&cye>$XypeHu+c_3UciO+EXVo{(rDc&ZTMLr9^ zmthL{oovt}T4Ww91(05TLIn{cu^+0WOr_k7TOkkQF$$nnai78=30LvR&Cm+rP?zq!A22-(YhP zv%pV8Ua&{kdZRKUS1W9qV>Y+&19cb&#o*jd}ybG=z?V zv_apUsogAge`&0v{%M51PjkK*j>c#l5vT)8;WN%bI?8lfTD0vd=Au+ToutyEH>!6c zo6F9NlFL>u#v|plY<3gvUkY1OAZdhZDogf4RQh9;JlRM^?keZk2c_|Lw!KnvaN{a- zr#iQhT7^bc{i^?!`SH^#Ob2MKSUpg+N6gy-F9thiurl|gu><*TLLG$AYRmlZY!Kg7 zA{sn#emPU#Z}A_9Xdy@)A9PHa{e~i%LE@3?NiV6ba+Zpj9`?-wqsQF7C`fCXOPn`o z*U{TbPF)ja3rw| zm?|6B)+J=w`9f76OWLv^NG2&AN3e3OB_w~RZ>*i?)fdCwt54qPAt4%VzSjWt7N3&u zXriwK0N*eZN8Ny>%&`*0-CNtGO#zl ztVh|#MeX_LGwp8t2Bglv{+~73|K~7)AQ369x9nsixo0qVm64P%$>Og8$t>s&!N8L} zUvh;;E5;txk0SvWxiFq>ec%(!OilqrwmK-7po{@tSj_W{?ZZ9gaMt6PFdQ5w1k;Ja zlVX5f5EcBU_B?vw3>d`vfzVx18v}uh756Ebrrt_F;?vM)j=+s%zUvX^=2Rf!8ro>B z8Y$5qdsgLVA0mP*X$wY2mDAGiGU1#bvcE)-l)#teky6zJ(Q4_`bz`NE$WShyt65>j^zVKfVV5pIJ_PkZ|0 zX0hY{IhIO*vsp2bWXzeqY&?#Bbp|7`W;lCLZD_92(}~HP7vdeM6VhvZq^~yqQz$!C zuW_lKUElxQ^s2*g&`@R2>fGTS2&Ms&hwV@QgwXo&z%dip_p-xX5X2q$_V7f5MErhG z!qsw6>tUgBuOLLz`$q0$7{Or+wR7YXq?~^=?*>Y)jiPd$06Rx4O@{COom|4q7W0Yj zgO5x?KEy@5{}7fe-w3q$kKt2Bh2Zth{Q?}R2wR%T%&wY)vsa@hxgnTIEqO%I1tp;( zMKkya&9ew%1~S$0eXs2sJg4DnG-YSEU2zC#$%?{K57O9hPwp}d_sG^;A6=utf2Q5} zC;v*uB1g1=sOppYOc94C8-L*@iY%?SDu#SC!x?JBY96@7wYt5pFtq>;*3rHs@@E~> z-qw9rMqh(d%j8N9-~j5(^=JDcDL}P(*Djjkgvk}c^u3*+zlEs_)jq9msC;j3Xf3(9 ztH<9Fh*rIKNuv2F`Wx@KPz4<=!l6oo42e9N^~UCvX9h1^7S3&^dCc9Fc2DjT`0tSY z8UC{7d5>z}r?^mjlX=`>&`H6;hAD4$faZq3nTt-^9#w%ggYa>XpLM^0zL_%Le$PxT zIYW2%B8y>Lx;DIa)B+@5tTF#2Ut!c-6R(ZVk?J-kco!9T4+hKfgXb7EZ~z4YHzNX3 zKK7)!`4~J#C$Bg2!^+9)9wYuZLSVIRleh7IPk^XUe= zA%5Q6p4=-MHh)?^7syZn>e8bpiZOQZVGfade+G2zFAIh??&=Q=i2gzdZ8prl)R9m2 zgk7WC=rouNYyaaMl2g<1m458g=s z&jx#wc%lh|fMtb7bLm)0jF=KrZtFV+>QMRaqFI-&_X0x0r0Ieg2Dgum`Su5{D=uw3 zqdHKbu`V|a5~ygLwK{D<{-vnqkm6`$no4l>si$SULSLopNJJ>SB>t#@?v6cRq3Rpu zsKxl|(fEI4vi;4Ih)0<~^u%|ks*B9hE}bNZ+9Hrx(a&Kz=KgkvR$o7a9&z7d(dckKQccByK|@@^CYQPuyAz{D zprHh^**MfuM&g1{_oN2TxKur;v5$gRd~fXfVSV|dUP2tECq~|$^N%Dsq^nC7NRNk5 zcj94lB~$BWV7%)-+?3^~3-ix)7mF1pyxWwA#|T>LG4TuzR~1Pr8!AN&gnc1xMj;XO zNmD5FD=7w5K}6aDDPF2f!`&JY&}kJO>?A=%w71glL@ij$`GW}1*;ik)dNa#&WaC4c z#zp8uS>*l>7-( z?5d={&QK*%&|@l-o`3y|1rOiFuFkuXUa=U zKLw9yOP`eP)d*HH9GuHLdWn8F>Krc1mM&?*q|pBO0C?bK#7YY=?0j+)GDziYb6EF- zyDd`B*i}zNny&R9>jii(dJ9fF1AkT`ZeNS<=Y3u* zOxaZ62*10;=x%xV{e=CE9o;t5C$7R*)C)ma0S^r>==}54DoN>tZyIgW9TP@e|ups?PEeYJp5f!F3{yh~q*{=Yy^U`hvvl@sAE0+Vmc1Ti7w_l!r zr9IYzAlR8~Fm!ksIPjiUem_E@Xi$Tvbg?vXuS8EcoA!s`?1o|6Iwvp41}I|?OetvD z^0qB^m0tdf{@9JMJ)Fk+&@kW)3R<61gn-P)HyDFMN1P$&c|eye_)6Oh(|)k%c^a)r z+CC!Y&dFiBXC?F8{X#r)1t5UAaa114AqmDv-ai}+rGcl*{cDLYI&(QID4z=#+mXL5 zX*MJ@v#-74++1@sxSZUzTUk#7dfgaO)Gp;|9#L5zV(_jt#bGbDLPlE5A|hUds?n zUa-QOeq3IsGq#X6v7f{(Ny|=0G8D~)Dg75aK|M^W&CW9`L5e9>)sKk}aDGo&-@1mD z=|c)q6=9lEg)3Lxj5%{EY8a|NG*i{H z__bOt!&-^*J*E=}?!IbHci-bh&vZ0q{Z1Us<&jGAAk0Zl6)5w_G4 zO2~bQ-ii`Idk3e1xJ1N==cpcmGbitE#CT0anx2}R^;EQWZ=`%%qI3n2`3{B<1QL%N z8=zb0KJu-Hgb(fv|*%+7;0JMzt2ZP9`L{E4H%23@KQ-(D|7eS8R+)=)Yf%UZlJb9T zzM0W+=Dqf8jepnj-2sS?BjLs|_0CTeMAM+K()utM5`J`kd}Tk57YiStQ^Kq-g{Ki? zbrSVQ5%njE`P2L7-o>|Yuqs)<1Va{I(85ie&GJ)5;wYw$?>+6O;e@R!LGYJKgQ}G_ z(%k-wpkZKlqd};C7Ay3?8B-Y6sZkXB4EOCe`YKYHM?J$KyhdyKndzi zbAY_NZbM6ioLg330V?rS=)0eVbTWe|&%J>P0~7X^Z;FytLznouFNk37dzbv)W*;XN z0is7p2qDnBpB*dmA`X4>&UvhM@wr3fjqTU%Y6-}-@rt=IHZjk?h4e%bm~co;TBv;M zKIstUm!_a0+3wLcIg`g;usr&CG9V?IJ6wZpp{7;m7`_6Co?avpu~G9>xI~(!v&N~O z#CgXsZ$c+;2f5OmJ2>Dtu^*w^`v&oax`|CW>Rr3aBo+NrC-H=Yy39%w__9(%K4?s@ zI3J0wzENyns`(}X#8}q~@(ypJY!sECBF_<@O+W`gD;lG%IRCxYMgV@(265T&fWEw8 zU+0*ak{oDUMxleyd)EJAj<-SH z5;y=KXcd~H5w$(*C}p$GL8ptvJ!Hvtz|vpZc2XM9ovpbVe%l9dLHEK+JX$;+5Hl6pJm1z0z>WbXFBkEbHQ~%euLwLX%_yre8+ra=+7_`K5AdhB0h9-#(KVtp2D=09?JgUYuV3Q1(MJZ6)Qo#HI>C`tPsw&Kx+^N>kijIhPYWobS79k1bv&$O20DSYCb1ekg8RY`h6 zcJR7COP<;#+kS_UwuIbkoN*kqe_{FWCa!AspzR7-`u<&~B)349ynF)q%b z6z>@>pDF#X0MDz8in;d}vXICI*|CL1>GT?)VpcM2)qk-pX_Y)y(iIV-xBy}gHYpPd zu&8L0Yk+7+gngh4HGN-7?zb7>PXKK=O27rX0hmoNIi=m-dr-u4Q&3??Io0rS(6C*n zVf+|6SK%5_$d!tm;#?w#Tl0o&i~Y$x*+VnwM_oPc2bORbf#PWiD}+1rNOwN3xe-A# z+;n>gPEH}`l#2#I1tY_P=(fA5?ClGUUVc@^y8~uej=DOg-CvtMlZ2x{_l!hIsd^pd zKkfRi0wD*GpS#Kdn1T06SD``YC0x@uH|&GrdVoA3IhN7>jw_J!qpi-9@fAu}yexDv zz-Ufex^E#s#vyCCvwDBknSkH&K~Arlw$=+m)&wq!azK@@2x=BjP+A-Qw0^cO{;^JV zx?`r`N8t~OTBbKm4GP*<9?j3l>;Og1T^Efg5tvTP4EW&rROB7&tk_($VeM8Y(*2G; z=7^E*es!x#1J-dI*6{5)3NC;MaGqCJZUV2J&b}ZRTfD>pquXp)<2|0={kTV)D*&wz zEA5(nF_9yEXo?~QJ&);H8nU0Ws}N%H$%fQIlXf%=p7SEfZf3fHrlwQz|JE-f4QsK| zniJAKnQY>&>MvCCTe~eEbN$mr77rfVj^WNpG;c2%5&x4O>kRuW)d!HKUjYvLlHoW; z7~CoGYaFWO-7-ZNJUsa%Co8j))u~u!u!7m+&m6egLPKAu_6X@Bya&^qW4QbOy^->L zXH=hI{+@#e;R0iXaI+hdPwANILktfp+Xh?hIa_Nq05HJ>`WNZci)`^6X?yVY-l)sH z*9ZT?$?Ou@HK23~8P)t76r`-8kWDvQiUml*tSfyoJ7dcj>#V72A75w~K@MLP6Wr=* zO2~T1>a7ndfZ*>8upA!QIGE57vgB1RZEt&k;>I*a}t6c zSXx9nip3$ImqXNu29;eQQb6qpca-(*zMjKX2MW1m?jhpnU6iF684dzpEA~tm#9}{^ z`B{%sy^yeywVs)cTFr>*DM)IRghQ8&lQf8e;Nz6$L-*ql8y6#hbF;i?oo`rq_J%%x zT8i=sHE31}pb=w_UxT6?HlmK`>*V-Y2XBaD7SOb)8pZhG6BIfWX*1}_QMZ^0ocA`R|Wh|ai* zrQep19p)&bMd3jFeMU6YJlt;r6*2$2gye$eI-gweR1YVh8~ny$ZP!TfzySgdK%YZG z#Mj>(U+M$>G{x`iwHmF~$6NuUopR-7jJb2(Gk27Up|5FL?6zw5=|kc(RA4a{fFA`B zENkG)n>VUB&dm}raG#4hHlL_72t+TGJTf1Yw^QI1PpW z0f8aHP^s_hSFXP#t~S$;jH0?c6%eZ`Qc_BPau={C0wpK3j8_!&btKkIDWKH+gLkw3 zP;9$D9hc%j?kAHXwZCDLX3)97TlHWTV5 zsy${7zDC-oZ-I8^#uCuqr*l5@#q*%?6;;=835G?j1*hi1+MO2Qgd zQh1DXQ7`lCCK5qNKWlJ}UPcH5;1!yWnM;v9YGx}sc26p z3om!}sYMoRKc$`=rI(FBxAWW7#ahLvkv7FNdF`7L<;`eNJylOV%qEq6?$_9NWXN+W zZ5r921sQ@n=J}S@5#Uf&$wZ0g^PNPJtt6}*0xO!hEk<966r<^EmVyc9a5fU8BVGPk zySFt*jY66YrhM4qK_D{uphnrdwUc}XIgi1Z!prWw z?rR^cK%wzj?Yj!VkiHez+6)%{2dZm#&(Ke&v)*~BM+I}`d7vhYYLFXOXhX(a&-x_D zE0&BYTt@c5i+~Tbv?>7_vS_+xeWT3A`ut$kIHS5?hq{Fk+zIiecEMOz7hOcrKiX+> zlD4TTu)iY_nIr&RbHSe}4;Kl4<-Q@rY00_{eM7AC>fH=Zx zn$p0zaQwI>(`dwUecL#}>*%Xh-H)5>8*YGDYmk&p579BZ$o%W5T&WA3fc6DQ&`dT^ z*UnGLXF7k2%+cDw&i}!lmA<72e=l{10^wOxN#~3l`$!ehFw1ED`DEzUbTfgLpdVH z5fcm6VzCEwU6PxHIqpD&7~|$NL^lCKk4LXeR??I zXdASAo~JB zY%YSPQ$uC+DuLeR@Ssr@5P0XuUBhd;Ty*w;0*$2vwsbOBtsfLcJ*Ka-);LwiwRF2(HUg5+9BAC72~8_oB@dRm3pl{4Bkj(+ftWyh$hZ%kG~|UJThD zK5e1{OS9Pq+mM7<*%{s-U;CT^5^zSvp$vSyU^nJE~Y+I*p=c8B)js~*?q>)#c(cP^!uuxYS!agDBqad*G) zR(uzR3?e|lZ?4n#k5U3fDitDPQu#m{&PXK=qkzD}Gi=Hf93~ErNT<7Bdv<1Si9@Bd zJAd3IgzD+OO0g1?E`Zk9LgH&DyDJW8EjUu!MSL@WF!sYnFZKA-(E@9H$RfJhNP@je ze_}z0CtPVMnTlL&-f~i=Qg9&wesB$<`LR-e1(%(U|zEU*GH>f zf91Qhu4V|9de!sY-`Lj!1B|lXZs3!D{bS0GK+;rED!{#^qhVvH2v`xl&(>;VG9lBMXI?%C6ta2jnZGujLWK*u@_u%DH1e!zU$7fR`AN}0ox1h5cT z1AJ;*bk%cG0RGlyn9FSMlOyOS0JvR7h6M!GjK7?_GGhKS3O>-tr;!8uc?H0J<&q;X z+hkM_NyaWJ>;1+#K5ZW+JY{)$Ju;HQYkvfts6RTX!K4+`zXRHo?VtUG5~ous7+eMr zO$|A>?6#DKTFU+qc$N@B#X}Xi>gW3nZ9YBU)22`>&%N4WYz^)n%YqcbY>4%{Fe-mf ziLQm{?*2TgUb@BTy635bq-&pkXJyr^KZbcsSAzgOsyw%fFF8v61inhdth#I3!u^9F?|paegHY`Udr=Kq{Wb zX))y|GiN|W5k*jz^(8tDT7A4#J{N`*Zp*{NODS7k%6E~_6P1!Un$W3DRXHC~C|8h6 zy6#OPz6sCIiJKNbcKC#gvMgD>W8ToIk0EhKl*Wp2#NHLNguT!XTYoCV`chqMY)*Jo zMM4)EAGA}L9%d#va4eYz9Z%YRD7GN}Zoe0oR-q`12b+Qcad9K{Xh@kx;Oqr-gOyFt zy`cSIaEY}Rz?KfqAWkD76Qg3TPkc^fiA$5C#Wvw(k342=F1ZE-XZ*@Mh(cRiuJ;MI zZ2`-o6z3A7Dv?vOX)Bk=+QnP_wAl-&IhKi$r75S^%Ly)E7y;Z$bUfE4FLMp~tY&4NtmVU_j$J10*C&Vv2&3PO>mcv9&`+0xY)v;_gAn`bW8SR)9_uv`4S)}a?-8`0|W;&>EL(}I`Xz&0?`(DvFpWLNB+*a{n zD9Uk*4vO-atC4pfmY%FAF8BfH@97i5ekygTMx()Uev_=(OCL8Uy@(uIF|HYOjy~Ge zVqT$Uuc=_gc+i59EoUKkgRUd4mc1GO@}9v`BB|r2-SHFBLUbNR1Kz0jFMw=lyrCJ| z-d$GGK5W4$kckmt2{*uymYAj`{B=vpC2G|cjvt+Fz6Q{;WAYbXb`4JRHxdB;mnz_b z&hj+e;)sC~&D}lZPX{tTm9WLy+VfLvQ%HYNr)-K)45&rzWm3RLXLa#LYzhR0+%?cR zG(P5yS&YoonW95DUr~7ao=@U;^0ioDavSFtXMS1W5Do@=V~G2&^!dM(E8SD(?iGk; z#7a~LvAJALT9Nn`;u$^XWRL=%rLMPH;HrVC*G>#VkAQ=cHUM>E4t#Thq!Szkndrhf zg77i>xg#>pD0DgyX8nrlnp4@0u7dXd1XI48^Pw=cIDSD^G8Oi(JJ6=$I(jXGWxXGw z0kt}ye+ji~h@^lp85En2d9r>FTSLWW;Wp#`cR;F~xNss<@fP?Wto%$?Qpj%iUf}Q+GbHj`z#aq-S;HEQH`72LueGDtztH z$J~ql8pu0@Bj#qqMVvF8l*P&}p`J1{jW)-;Q^Yg^R8-HyFhJ=sBFCE`k{*VDn=tf{ zGCRZQk#ySIIr7j$-cE1LXT4Sm+2RtP&^F&N|H;VU!45pOU5|@2r=PoPq!PTTc-{$4 zq3wBlt}y#K0-jf+GL5h<^qrZ(6Rs5W-$`@Q?UQcAZ`9onRO;Oh)G;81{t6|N{h17k3E@2^ z{*)YDOtJB2vcqMoWe^Fu5^?xVM41x*1b`?p0{!Y@le2lnOU6zG?DNw04j2YGC*NfA zb3EhSjN-3oQb}w};I@Y@TH2bhn${S>0yJEbxnHzK`3-(j^l7D@;RoG1R>p{ewuDJ2 z!`!Q#T5`2WFEH*cmH#E;8NQ%0C5EGwf` z-|N5St#heKVdwhGltZP5WP)ngdCq>?!T`a)dvWj8r^wXht3&q7l2U|4Fi7W;wlc~N zLai7!s2f@X#c{D&`Pa|RDJ2kvS~cxGufRWpwSC96TzT|wQgHFb_S2ao9@|G}nYob4 znql9ET7FZs5L~lKr3{2s)UcuUN>fCBl{fNuib?y;DQFpqcln=wCwtzs-#;YWPie=ujZKfr5E2G3KkRv!1 zT4Vb10j(alr_OJOKKkj(Jp3-Po z=vzhVlKa7aW2MxgEkB}0kuC)Qv&d+4-kSKh&ZHv%Zlf0~c6DF>=%nKQx^WXYbDM)B z4vnLb%SfN0eH9UI7(mhX^tqNRW#DlaqeF9G$bzOs{K8(=AF;Xyb9&xKe?xE1Z53 zE>ZyWiS-yORX~o~4os4ksNIrZ!Nup~d^@M@NMMnJ@W=TCh4X@mI8Wkg2fBZ|CUEFB zabw*w7}CJK!%6kuON3|FFK}k=kUSx*L9^wzb%t z+;?6We9-KU?cB6v0W(%E?m>w?ZT?c;zP`Op>s&sH5f!B*5(kL*)E%;f2aZ`HP&n-V z8Biap-5uOamjJYyd&vg)dCal$0oCfGS%3uEI7eLzs#EOJ#RnwVuFRdMn1zqZXv=~O zC#f&S2H;R)Q-7z70yYsJabT|uE%|!WL+?H;Y$pCU^5{Vt=lUIvZUR{!9nyVTnS6nu zpv2GpotJ-y9Aw%I6+^EPSfnW1HN$<&3or$_v^e=s*_(Yrx1iJpW-#72fi>Uz?%t*N zOh2rMj5%N}UjKK*o*z)L;gUXoa^5UZm|Z|4$Bz9p<>rg*qM-XY+|kpZcIkYY6)8~` z_sJIL%(mILRcbY8Ep@AD_%-sYrD}o2AZsC;Ek4*mx})riClq<)p!H#H;A_4)SF^g- z2i?*f4JDo!7p1W^Aw|&a(>ygY%EC5E;wriQJX#6G{EInxpKB*qZPzV2qBgdI=dc$h zGK`3Zfoj$2y2dh|R7%zPk#{$z!g*z38%DUUSW1d*(nmk&vELBJlRAFGct3<^)CvaO zxIP+fWNL&ZF$z7)Ci;3X9NJxK2|2|+N@kP*qMJ3rIG<9|a^jd^Z1mN<3yB9up&PPd zR4wAD6s)3qE3@bW%@Z(<$GrZ1mFY=f4>v-C!z~KxBjze+Ok8QYrA-WdU7v zmBJOFlGtWN-Veov(FR6AynNPT5bTSK)AybY<9V+$o`wR&(J(!Juues!ovFK%crEDy zXiF|K2pRz*o95}sM>9(0a^+8VsrtmU*t)KIyFM9MMpgzc5V72G!6{}FYa&$#_^-ez z_p!xwXkcB#Ey#%rO*Rp{r(Yf8`m4+6KX+St>kBmj4BouO6?9-ej&&6!(o9W{oocg) z*r2t-`StIjwW8@y%vE7b^~^T16frH8>wHtlj|odqInqYekdLOkM>aPQwqKQ(=<0FE zeL(-$nO>X-(x6GXk?wPJ!0oiaFGkz9`oFi0O7Td%<$*yR(qut!iRy9WS|JN;fhxG0lv z*GVXD)K1ZrecOPt0~PvbN&9!b8%<+wCb^1UwNet^(Syf{(X7b`ziGA5#`h22fc%0O zPlS)kbwyYMKCztXGJaWjk#~vdV zp))@$ko*4s)h{2yvWM9_Yy$;^%>awdG%tx&a(6j57mMw5<+y01iu@RuQ=ylo@A=4P zE_Xuy2l0l?bT%;|1DSijxCcp^qeohnS2kSxe(c~<-KU_WPu!$2uq+mpS<%4Fm>-Zc z)ta&28ys&9=8!!2w})G0}z)KN0%fJ0|zWpemVy*#|80w0QDZq`zwZ#9E-!tVqCanu&EfKmM72XGYfDcuj z3mlsh6d!6js@v8o=PSv*0TDGE3u`kFL-tQs-D!>Mg-jO7=mCj`YmCe2A3NA+VmVRJ zU+>O82)@Px;lI3kiyXPX20mG;i0jo!aw1vgAdtma*`leMy748lZjooN z?JQG+WVn=ExKCQ1=CtMv8~D>f20%mkz|l!7A-vT*%1%d<-~=I((^WQi1U7-kRgvit zhQsovRZx}w@dn1;wnL5$=Z|HmytmIQ-*^_}X1`YEL^+cN^|n#kWJ@`}3FO?~#&%j8 ze9Sj#`6H*VaM)CqE%+05{vVSva8=3lU}q-~;YV{uz7H^~5@MCdsno{H6=1%}63O45 z#w1!F{qa@rt-Bxhuy&Ap!t7p zl1>G^3k!$5SR-z5EK7#Ph$c8gm(eS1!1#>9O@89;h}9_ih!m^n6Wxb}@#vE=@k>6g z#t5ln5aUh`J>8MH>VY+qCr!XxtYofUXa;5fX<3^f3FShEy4M2X6R^-2bRXbS=zjhG zVJyEn69?4 zH-ydMODVw(L$;My9x#~GWNQRa$B~{ACOmu&Bq1QKAb}NPgkdnq=RJ4rK|aruBQ?SV zc33t6_cX2mUpl$41SwzKM@?NC^%^MZ+ryV9S{;t=_bUY^^xUJJzb1yU$n zQP6ijS9l0yNs$LXOZwf3Ziu1u0`|#3sLLawCkhn7+e}}TtHpWEmiow6ZuWf_N?Df| zURDr{;ZmlpI&fBe&E@GduIU_L_TIB))|S4g;* zyNX*k^u$v_IxslPQ(rCV; z57v5%raw?#blgP#@c44EEwikei4fyc$RaS-p?EvT6u4>fbfp|N_}$=UK`g5$(jJ!; zW8v)K%1{g5oP~~Gu`Os~llBZ=m(6=Bn`2s(hX|<+NC*OTdRhjQ$i&m$Uu_|r!eQxS zn$c;rKBC}0j7e=mHA}(OoR)$?6kadrRc;JjQOlHw^1sdl20+`7p9s-oR>(vdU=GW! z%F=H1oSCuJxcihMPX+>;2S1>6 zBay4ils-Z|@@oc4w!-$fXwPTn*QB*Wv7~3Ut3)>S!^_Eld@G%~BHd`eA+bJ?!93yq zFm>otpW<{wxh$CQingf;_?8q^qI~=EuR{fd&vO`ll(>Crh~S8-EMo~gy)W4UsET3L zmr_O#{r(~h#b5pwMb6kZ7FM&xi*j?aoo}td+fL!MuxUyp@n*0Yl z`Wm-ZB2i`!Jm16yx+kK>1u;{p8NW+_8^_c;R_+^ira}c!sTyy6_K@K$Q=v{^rE~a+ z!ivE9_P;xmB4YavD5Q@VdhoxO%9oLTU!+cizhdnW5bN!fLPRIofj$~7g z`CQ5LdlzD$P=Xc+zk5z-efyqcVR_hx=GC06f+eM7DC>fylBv&$;RuardQOq0mpvK> z2VO3m1gX^Pn~dI*E4R2(4gdl=PeakLaJ*`oxQ^Rg-ZJ~^Q>)N#;V3lHcZvw`+#BT< zcLC*y@?syZ@XJWMqfp#z(ndI*)ZG}Aj>nOwHZZ|9fru=qIQKd}L2BiCCOP5vnD4*@ zd%WLo8zhoTAfl7;W+?zDxKP~SaCuSMd{S2>EGxp;Jt#zG0-ymeH@gk|BN7(e6nl}L z?;a{R$lD6;4&k}SvWFO#XCr4uXXb<>n@lm1LdcD(+Q~J5)EmxFksGM^>r@kwRoc11b(>7l?u( zi%-5{c13J!ja_epZxEXMmHH?YS*5QXi&abzY0=mWl;vp%4iIf8710j%nT@S4mM@x# zCnpNyf7owlHpN*pC~B0eq`<_!mR$YT{9KK^{EmCS`l&!!KvL~@v{2Fio%gAvM*Qsd z!~|Gy^CgF(HdqFFL`HWW;IJ`p=7z!_E>(IYtj825q(>hy5q|}Kkh!kK^C72^CD)i< z-0%@$xRC;UKBh{%x>1P%kujMI#0venuBmt1u>W`KBy=U`TD-*w^pm=h89hh#UF-OP zmo8(CX}5)!deq>0XdtJkZ19UL0|U_~Q{h?to9!)m3YW>80D)Lw5F38BtRUhtoF&Vp z;GzH+hEK0(Pm6RrO@`vb^mWAB6A1{J`ijB>37kv6d`t^V77=^ z4?}b4r!$3QJ1E@u%3o%C;ck2QApkE3brX-VMBi;i5cSAE$Ob&I!z$TmcmlT?HLfZlJ906(yzpidL~sHYpxufZ3GFtCRyCMMr?2`=4& z9_Z+-V?JvKlBPGP%18XZQb90wM)`=7+L-HOAo1~JhkdU;11de0fItEc=KtlRq{-Nc z<7jjc6%Cbu+0H8p3#^lrXtP2AIfebI1Ewiir0p7dI4GFs9o^OO%!+V=L98R(-)t+e z+N!9(w;S;ea8%aYV~=p;4B!=pc)=*er71h<;S32WL%cGRK+qt4`%RSV-2UNIdl(<* z(+ADNF<6k6&IZNQlKD3`q6aI*ms#s|Tw5qgGf4?hFK=-lI3|_i;9;%wZBmxePfO2d z=}m$N+}--cs6xpzIbnizE&FuDmN`{$L%p7Jz)P7xt^P(#I&APyIwoh;_L6RhVCder z=}DGd^Wab?4m;^AT3JxLwp5*@Zbxv8OoK%kEx!Gteuwf&U$T0qQuqJmh;VyK*NXr+ z&H?wtVv9Tx;Jv1g0EE4wi5*XP!pXz9u<+s(xD-78qVV6Ez9|)*r-oWRVeL4VWidPRtUNn~O5(#=RPlMZaiNxvuHqJ2$8StVg3wZon$?BWB3F9&8;3vtQ$bgu9b*E)DGx^cNB^w`lK`&?BI>nnqln$rN7QO(2d=spzCpFOM?r}#sIE5p=OtK9`NYG zIB7$ig`YJd(1e>&&!A~4qy@#u`#h=yKp$yp^j!FG;Ckjk2yvq|`Ag$Yw{P+1AlixF zS!S%LDhKm!G0)e)4&qs=rFTtJ0L58=1JxH~!hvE5wB>nK3_$S_jUV;;NLuMIb`jZ! zNd!ItK}xHAH7`|kxV!E)tHaFtUU9Vv*}yGi%$rp2*^4i&zcFdj5O+Z4&!r%3>>Lz5 zPZ+BT5Zx_X`BJgk1gGzcyTGT}>2kVT>_`v4lz1Eo*4R5K3brwD>av__9o~(Sg3T;Y z$eEKF^Lh7W{JLVhvTA$a*xUH8L&L^le%=zlPqNdbq=aiYGiLVJhq^{QvV-nXBX~t*J(U#;bceH3oKR>6rCYL??<=ellD6mSmQsqr%SKyF~d#`%2Sx z+C}|tlmblwHIts0(|X-(I$mSf3sYjijrvWlGt)<$#sStWtTA>-Kh|BWMrL#%AJu&} zz<8ld3h3hn2MknmibzL~=6VxLsX?jB7YE~T9e9AVW@Pk9Ts%J_$@f8b831vOpY;TAjGci9i8o6?}Fe4vGyKf>!~itQ<2?LczKtY?>JJMkg;Ry`~&}fXc6LYwSY$) zF=WMfib?N(bqynjYqWfy1%1c%OM%f)z*HfmjL`xv9}+)B9y6UZLIk*)|v@c z(E(oSr~c;z&?5g1>e&)h^%5hecu~At8;&PJMT{7Xu5#mYd)7fnYBHsw`H=@XQ{58% z6OSSx8oV4IvL9s11klzphy9g;WtH;E1_e z!;^}uryOB#O*>0KS-OrlW!5?3yRrzV-Dl$PGPVEY>G4ZDn~y9B*WDBM?P^VMZx6%3 ze@W%)Dw$&ZP6kfS{>amgK@<6;#Bk{KX%=qbN26S@ z3WhcO+f4H%ZSOx&`_ru8?BKnfX~9c^5qRJOB^MWHe=z2FUQNmkaoT0N3frk_?RV;q zv4ehppI$@fIcYvqU4|zzM!?qvJ>Y!7zY5V5mE+`)o(c_%>Pm0CD**p%zqiD`v%_KB z+B~K6hWvW=w*BT*XoNKdOofgplW=T^pn%a{ za*w%tWIgfgciuP+b4i}J2izB<+%Z_AKzvDPY9qCROe30yAgewA{RWTJxv5*R~ zQQ`fGN!z%6+IZG9lT!Ix>S#f^!Aax}JQ0w{C+ZNb=m!f1;BR)L`BIh(l(53?y8~&; zU=K&pMCvM|&4jrCEP*q#ObMBFF-rgzVyU6r+$_dS!Djc?qm;ACZpCQpL`)wU>!APO zHCSaSH^p_8e(v9@p=XdnwsK{-e#W3&$M~i)%*11v zhRUxbOE>&b_Ey|U>3KqwJ{6p=if{gW`?jz4N|WMdrF%smsL;J@-W0$e=o@z<6(Oxm)Y8SloiTfFqu>yMKDOtw5<;y;)NSXRDn@aht^|h@Q%< zl)1uHM>II#9*WOUV5J>6uXyC+iT3Qk(_<}G0(Q{}K&N=4KdUZ8IX{ytn06R&BrV99 z>q_VB?6BK8^Ok#L72&7o@?Arq`7ufl%y?BIbyZlZk1jmTS*~B7Ki6#@6NY4;Y ztWAST_FjiI3iPtw5-=fLt?0!Ja?^WQsd=(Llz)F7_Z*%bE$KqqQ7I2e6P`rw8ro>e z>c|KW?Df_tk({mP?Rt<1Au}GF8SB?S8~7fajb#q$z59t4_y0$$;d|z@s6+Rj_qQVYDAk#P83rAxzhH^rcVb3z-(Be zR?K%0Q&Bilve^9_+V5l_`!Al`laVn9y3$jMaW$u+Wt+XpY~q#k(H@1%QK5Z0&zG#~ zs|wMG1w_jHVta~!;#S~ZWJZ7k6v=m=n%2xbo)DbaIU6-%@jr03JABX z!UR+Snz)^EY5daQX0a`TdN5+A#IBA81UUZUJ(i-inl6}jqXGcBpk^Y``n2w(g=23Hj>5NQDw$&t_5SzLGgW*#$HjRW`XBS)9DS4%k(q0F=yOR zdvy6~#NP|3js z67Z(m>gvrN*V6PY*@A5gdN>~O!pN?}Dr%zx3} zj{J@a2J2kj>n_`{c2{dp0ooW9DJic~k`KFdcT_+|cnrThBN%Yw%F@N8F(7V|B#tR; z0ky@P=?w`-J-Tlx=ijSewZ8EO4fq}ay3*S0Ul_5cTY>^Mhq$ciWHF1E@$3Y49bHZW zSAvJo;Mly+tE9_!M$TeKZOt1n2MFfAA@nvw_^B~y(GlLDP*(#~z7g8o0tML~!jSxJ zsCt#i0^U3H!>rZ#O{RSGvjq2^Iq9_4GvbM*0qM^$YL2pToE9UL(=S2IfmVvm0Ec z-bOYF>JWKVEPoU!=bQPiXG+sndt5<89+9bqMZ&rg8XOq)fZ;;I(2FD@;Xc~Xee7kA z8P!uNylQ3^cU5mPm15?^|7+^CL@I3+D1-HUExmPb8VBN>j{V?$dm7tht9Iojj?ZVX z&eNf3sDUP8WMBB!6>gG9n%wXRiOg zAU6w<5T&BCcR9y~L973YWBg?W$X%zZaFuWb1-=?Tn1Vbe&!sEfuKv>>f>NOaTod7( z_>gvc%9kqnE}zg_A4j0%&STpmrD%b=s;{W&iL}z#48XNxMAv z|36_Ma=Ph71|*Zo00y?<^u^Z^oYmO&MLwUukKkhn3#gos;jUrafFgx>>3JfG2OZ%z z)o}~kN}K?agTgT!kS`hfC}I|LxHe$5g}H{(tRv}Z1o!e!kYJiug`2hSmk;sIvO+dY;H*pv%R~_y#Vlyq*;^i| zt777u988aYq5OCUgN=??K()JU6V!P2TVIgt4`f4U5-gWWa`;4EQ(ww4i`&#t=;1y+ z5VJ?W+%^C-ZlP$&P?Z#~TyNwc4?y{RBz#Rz$1#PPx_;GW8)$fiewx{pErsUu8n!!w zFfB1dQuVMBB|-DMkkv;{(j)sE(CWjG-bRaW%A)%E>>|t*T(!YgfQYKh{ZJ~pGF!?Z zdRNH~9`}vGwONZpN$AZ-Y1rS8Skh%?>AY7Cosc9R6|F5yZ)|taXg}Z%oW}(9 zYEAQP|L9-eIJx({SON(|{)Y_szcDS7stU4(n+iIdsF~I-d4|P<;jgB*N`EU_ObtR;MSAHbsO#kPeuwOWDz@~$s<;CrG7-^7*eDeT< z&QShFjR3(*u$JA4cy)L35ZkPXxcK(5Kk4L~SQFTHt)T41(A^ASXbHgiN%p#<5HZK{- z*3>M=;QkG*57|&AJunmaQV=H6Q?=JK{i`;2C?iwM9!hZ^dnR!*@V6wDRz31@efQCF zyW22D!zrJW>SE7zOYQ{nb?Pp}5nnOy{kihn3`)`W-aiAv3Y#Ccgu2w=3je5~;Q!Ud zN9_HdSMu^^H#662gp1IPb6^p@y#tk|y3D&-eK+)~oZ2;3+e7J?}TY_(p@8!%{a zymi+w5Z==1n7mvaqHDzHe!}`_yA9-N!Ba{STVlaL#fBfpyhG+2vak6UT=JoLCn>hQ z{L?}TQ%b>Bv^dMyZ+n$9vqRfhS?T~!y|E!w@uYW^L(ClJn{0j+>5r5OJ`01zhKWyB zQm+Q=I9|6G|FSZVmnUSD6quW**?@M#c9sl{m$P5BdpHO&^EtSdnX=k3baoj}mL`E` zdp!5Im&7}~;yNxv^+mYXxWXsE9Rl~;)Zv{iqQ&50TQHt5gkkf!>Sg^Hb*F$fswJ5gp3lxW%BYm8LqtHD5Us2bX!wbp{yH<6j{Er*yNTK^fJoa%gl@^(;U#Cx=CA z$X5!mXlcuiC(k0OJp8HMu+nXK3;=MIKHQR;-i$xk{+Vc=!Y`A_5~5kkpucz`3WgI1 zAPcvd{;5VjXbxojR#1uT^F}>V#CgHhe_tC+64?gxt_VGk z0|1LG`>vW)@Sp>Q;EE&2MwJV%U}nz#kVNO*i>6X$p8U8Pa- z4Cp8Jdo`1k1({*j$awY|hO{P0;KT9vc9cYuL@Z`F)08&EgW6q(D_b*BVc8uhWQj-c z9QmiN{6t_;KUa3Xs@PWsyJ4bf7{T&8^6mKNq(#ubCtX8hXRY@sQi&8#ZBLA|3^wcA z1?G@>Z?E~llx3`Ta!H+L;kNEg{Bt;90b9+@>NHgF!-S4G>CV=0^Jc|~wiG;1u*N*2 z8;(6EVfRl8qQx{|Ka|LoXJ2-S9IQp_)SXVi)q3+%c;IwI>yv(V;XEhZZR7xkS}^6F zkAa6*?l3MvY8x334qu*b#JYT(V1<^!mN}q}gkSLaoC)b~HK^+cI#Yp44=v2MM(&V5 zu6+sspMptTGa|XF$o3|q25NR?@Y$P)d2&-}+K|1!`h~K}-_=INx zbk@~vvEfR6XrMgIvczv2pB?{$$70~0MNyXp4!{3ncHWQMBrFxiZl2Fz+XFGHG_0Rz z36b1hq~iJ~2S9Jo`}GYZ_Yv@BN2N}tl^NknyqbH!d*qfSR8h;3*m!cQeg~&ksuH2( zsH9~mi9rcQ?KpCACLt&T}A-T{=IQMXG>lkuL_*Ak}oX>Lh<^M9f22lz-Ar(#$iM;?t9yP|~;X?!bi)ajTto zmN39yo!v0!G@iXQTj+EQ&RuX~RHbO`t5IA0KxsC=Xd?Vl zJ(SQ|)UDuWE_yq*m)#D!fIg=8XW;gwF*6tzNsBC~Uz@Af`RDIT&bhW|N|0zS5;n>M zx|{bKld1@y)rEH7@Z`Q*879W_Q=^BC;byKd$DczHhQ+m0AbDnCV60BtQzqSTqB4C# zABx|3B#u?rX#5{#ouRA|?!(v}c)gbOvo8a=u^(IM-$zeiPnC}`{il@fC8IX4hf z3tRzQ`aVh^hiYNNAY@5zLv!LkF!1cH$=>As=V1}HYPZ!`cSseipweUaM?eYZES8t>V{MDY zb%Q6?zCuZdS3Pu(B130j62z1cgGJ+BcVl7sn(JuUS1$I(GfN6Ak?oz3D9^0m>PAH# z1UHZ$6c|5cdfT|abX)!>pmh|#?nsB~c^hG|h|i^Lp$Irr=uuSriq556YKPn=O|#&N zX=bdr&A!2ttVPV%E>giZfO}0EI!d$B&|uOIafckRbzrfpV4#>t{*Cs7X0fDw(A(J; z86fw|HH~0Jnvw1qq7ma1IXfGIfK6kuqXzhL4jiJ4qz1SV15%ocfGii7kZ;`Ml70JB zqU-S!OHA7IsbH1&fIzABkmlXGuVxEaZ0cxH9?XrxuI9XYTv$5}2k;de$OuAj9q|_T zw=p(Ucks3`J83XB9Gk}b-~vnwq_KdyD4uCtjwt;Vb(|K9yIQT*#NKpT066^@m0(6o zCU7!LE3aDl6B%V@ucU;UAF8&+jk6)t-U8pNX^^@>3_D-nhO*VRQQ7doSoyKGSbs~0 zXbQLAP!8tqaiRZK$IawYq5&8*c06^H%bL~a!2I}L{A7@NC1sJwc%h7+JT{`%vVBMcHhU64pkg^nWVc(KF-(iDWIL9 zt+~H+c!EVn;d#8>&Npq@BsoE!?sot#);L*Tvcm`t+EjDIZH%6tyCR0{v)ahuSxw-&{V{4~pQwyACWIeogLME7? z+bGOoVc*LJ%YCjc_88J6PmuciDuBfQCkCg|+&#l+2kI||_T1qK;@lH8Yl&xJP$?|_ zo?^3QuM0R2_8t+1+Z9B*ZNLf*X-{=5^ip}xYnd|ow6wCHBq9N%M?7K-@BgA%#EXl^ zv}w-;TWt;}DyX)fXP(Ae*7oW~On(VL2cQXyTHY0(XS4%0pUifiB1h)ufSPAMPg1*{ z;+aDkaOck2?Z0w|Otx{mjv?R4~UDqzcEgBJ)1H)6kwm6vjHlvJygD??0E zO@cJDrKIL$UghS-keqi@dcUmFPHq&EA!*HEaIetvhH_=`>r!bOm`8as(Oa-W^!$1U z)cx-1?#yIQs(xbaH@-c_P7_Ray%hX@%FN{Tx9tdp&E3QiO=;~uHifXCa#L=SUPaVp z3MxfiS>&+1X@nX4ZHqb+V-nHh20`uqY?u2hXD%omshoGMz{RW5FH{>4xCU~xgaASJ zv7sEe^n$hOpa0=Au0R6PEP{%N?sL*`w^T>=i?YkwSqYeRyh#lei#Ha*Z>3t_?#Nl0 zcGfeb!l1x#m^~^n0>=rvcc;p>5<=$-`XP3gZGwdojgWlmMxVveEDeaGt{4BpNi?y1 zHyTI_x`*)QHNJ#4qI4Bz6P^44$VpyA5A1hhD1^=#p5_BI-i+u8mj} ze8$w^tU%PtY&c2y*Kj$64j13ShgxelmJbsr6mq54aPi?{^4u)wD_{it zVEL3|QNAT#w>*x;mXyiK?Fz%o^h`@GQfAWu4Jzl|<3pW`K#0-IdhsIIv&MV25J<#7K~W z<0Qc4&KqwB>`o-wzP{NTW&zXbQMAZ&-DU*kz=rnIt0pCr{uZ1y$A1S^i2iOWjuYR< zAJgpkglBM%&P^F8$cec{uPPv6MivLdDsy~$Kczjk*#i(E3uA;LmVh`<(!lfOZ72_m zDv&iW4Z1!RZxapTL8CjxZlNrp`f)Ot)$;D78 z2rLw&ID?zm*glt-w%YH-tmFV;^G_|mU#S=97oJiOJD&Qwh_2YM0xW8k4-Vk<@ER4oMQ(5$GtNy77tR$QTR(k5kWrGxQ#*W4?%mGtv8l%L{EQfL= z>d2y+K{!aP(i|EWk;Sy!*TM9kaWKk%O_4+6qO87tUFrt#sxj3l!m4uQE*TtfJV>F2 zymHwYDxPZjjPDhu2HaeL8B$G|uA0VP7N*~1xT|;d5gB`f9?Z_96**QHf1SS9eS5by zSt$5K=H;j{Sb^ud%^=671NW!=t6aQ&9G|edzdt3Vhk~QboPg^v8Wi%jY}dS#dTt3M z0kcxi!%AtC5Zf^`Cj=<0q1^BtQ-bn*`+2wvSo56fDcr4#fZ>=fUUZ@YZudaA`aPA4 zhZMR-OZKoj7>z#L7M_O%Vsvhv$e-Ih!%}YyP=(6rI+Y9AA2m6wfdWBkRuHE`r{ikmGoH>5H`nnUd zSn*m~p-_8S?CvAk5!*=Vs32XrCR#KER&7zn>h-Joy9bmKaR!wfF2-ZW$by$wyufSu z!XsLX>^yY4oik;5JqI*h)i4N$zhI52?6i&Y!nr)m{=w##RO2V^!8ZwS56eiuEL%0V z|7aM=9F;pAi6?g4xz^&!_?nuF`J9E2xOQln=b>!2b5Z&^;d&`8tC#&0<6DUBvzqxI z)vLW>?b}qQ=}6}Q4=)-O*RL&?t-BS(y0`(%TakgAj)pI4Z|!rz>R|~mV~_fETP>;R zHCL3)EFUtIQF2^O&=gMPeb;YxNME@HZ~M9;F^2F8JiA3GVA|=OJWxd<+crWDj6kT^ zycVu@@eP@mxEYTUCPtc|NbSE%SwgE< zU&Fl>mIm7}?2D)DCzpN}YFwfrBnu*;>L=BmzD%_Ar#cfwM*2TNyMIqW8qwe*$D5zp zH)r_S;d%ykVxCz@#IVp|ayYaYG*(tguy6^VHR9(*ElxcYN2$1zzOPzLoMr5Pqr2l{ zkY_vipN~pdDo{5G+@bYGtAD2_@w(D<+BmyI?wci|xipVqCrjDwrG;Dj3J993=FK)d zd+7KlhIa8t-H)6u#^iJ?d)+}Uz->QnqyvvO7%fM-Dx)X9WayWuJd)Y{A{NNSqxM|5 z-i&A72p}`d2E0wIp^an)02$ZQjnKi!zg!AeT$lGEPcCtKnG4GI#LYnSKQyvmV{bwMmG$N_F!N%#fr!jTjRZ~QPq zpzeNrF$pCR-5p40se(EeiK2*-Nal}wPQE%<>t%fXnK}YdbR5I3hE;QWCSqfSFNCg4 z($;RL@_Sz|5Pu8(c>D%&@D^$1Zptz;nHc}Nr@D7M7&_s55Ylp+ZCkxdfsXbJ@9kyjMJCZ?7*wW6yo-x?}X7lX+V?ouefZ zA}-#`1HP3dih$B#Pl)f#n~MMFIp#|sIcJi)Pzvy5Nr(ANj4veuXrO(!wHQRZq3kRU zT|q%El()^vacH3hRnPmqQqW2k?Qj~A5Zp3)bP9jhMlT z*3Dqn-gj#Ry}g6!mYT=Sa+Y-&10k98sj_QZP^cN#Bt3uxI7hz58sqU{&Cq$Y;$vOI znIk}y+tP|7jW%R^9OoNQ450brg~hI$k?79Uq=zU$Bfo&^MZNywiebY%n1`sww+c~v z95g11uMs+OAdC*SP+fGBl}80Ckz~Y|es(_BM;8Y-q|QO%Nk(Hr3x59dT5;o>>Xu&z zaT?9&$W)hWR-f8 zJcfcNEAPMv{X6kJ0Il@ZqcbL@AgQ@KyfmwAlw}7^ej|T@%uc!4Em>;f#i3r2+Gd@C zJA7lBUSFD zQe^O9cN}=+=<2wUwj63z1#`>aM!1xZE}&4b#hG{!KN~=w;6`}cUdA-*XK6HuVA23B zG87JH1Y@pa@gX#_e0ZNZb>f>UEY{5*h-eOd+~8?9(i3FidFx-OV~zW9m;^-_?22Ag>Da;BeJ_ltxsd5$X9a!8k1XjtcS`kpJtD(aG{OPY`bH^RKVjfzCF=*BaNpq1 zT3^sHyUWT4z>X3|2>|6HS#QeQb<36Wn)kAivB7d8mjnErPJe4f>Z+43C51% zG+P-McwB+LF52Dz6K!0LFK)O^Epw)i#mEaw?&6wZZ-T*VArMc zs(UvJUF|(+k!_5L!**V0MkP0DIbfN|u2`mH6UWC^MnGd19TeKck>pgk z{Av`w`~xPJRNU?yed9pm$YCy5-W}$G$T<7~6O9dEPUImcVXSU1!MH+VZbvn0tRu+n zQ>T=p;jP%zOXX;=&A-qvGz5-6b%0Gp%K{vY$aE(6#Ne$Ur_uZ~HEithB!xuH@eT7A zBx5qUBy2C7jZdI`1-9|78J)ASKX>o!I*-vz?xGSBB>7s_^ zjZf7DU23x}S5t6jX9$zEp;yV;#@E^(9BRl7yw_0;iY}6HX;i-B3$UtV8Kg34Vl<;J z>2(f!?UdE&uIb>_jm42`!>fn&iz8WhwL82Z8%cyob{AEU`4Cvdzw2?}{-#o;B@T^y zL39V)7(!$bXExdsQX>LDa8}kFQVCy4bey)csg0hb!|TD(q3l`jaO9x;m~O)C{;5mE zOju!=^*|z--G8;1gV1N!cy$Zv_2+-mV4g68@2ZJs2meG}6~H|SMOtL149DqYkr81h zU7@XmXE8Y=PpdI5H4+n>EoK0Zw}p~1_znJ}^tg#+_UzG*9PP@aZkj@JNU%AzsK^3P zuo{cq06EG@8|K=<7jtRHH6_s8g8!TDh*5=-`(f9ns0pp4Rj44ee`ZDr?oS5KG-N7k z28=ZjCbmT?(n%b>i#nzm9YHe;00KHPPFloL7}Uf9fXiL#>1ZG8xL>%OjY!0If;3V6 zw`mI)XE@1ziX*buVg?^8k10`h=k`yf19uZ=TujpHJ5ZDkD6&>9qa+RhFfT1I&!vq| z_p-Ih>uaS-2?NBfV?cU|=ZE55Q$!jI=P4S;`yC*N>!4AL*9`C%8R~df#3ONA_-UyHVRE@uKH zB!fS?KX0hc?Odsk!XF)>bHC0{ejdS<%ojDm3;ZjW++IzUjL+E`qgX8e1(27EpI{Cpb@?k<@IC3~XJz1J90 z6_Y2CWEDI=($kg2F*nXGvajv+yN@;R>>~{t-dO^@3f=qSWZOimm$%W&(xJcJPCK;y zwV?k_1);A^YDv#UVGd)~an~7-ZI+##Wyslo>YpVfWx?z(huFzDJ+N|fBmr%1_*3nj zLa}2Nm1}jmd2j7NSF~X8#mAl#{jsRhy^==e2uu?J^2Bk1&!op$a2z;mS6!paE49xf z@wthraA`Kg(dmqbHtQMgLKsg<{<2t`8p3MCTC(StwZ?^^Ynk1#>s zI*0r}?&R$DL1qUjmfcEsm4fYgLeuo`}n;=!HGpX)jsp zY3aFInjVEbrG*}r`z9HaE)$YYs)MAR1C5TCk3(VdxCSmh%|Gw5UVzO51sy1Jv`CXQ zhZG($8#NE~G^$~s$uyiUWYG4rP~6D2@|cs(0Mm=EN=uMwFzDi!ypu`_WSV$J)|_$) zNxVIUA{%lqd!P)1%Ri`2PK~cs8Y%@}`0o$6V0taNq6KBPQO1?(*P=E4&34 zd;TL#6p{N_U%_V-T2FujbSy0&Yp1V&1x$3zSTrP8L>-rKN~`Cfw}jd^e(sw5v;Z(^yKzX4ld z=9{pmMMIvajL^BK_aS7s3jsnkW-IA`Tw57+8Hqhhjuf6Pc%oxC?y`eoNKgS&4!T1A zkIo061F4{Sp(_}?6h;=ld~Qwl62{Q92NMWb4Y~e9W_kctdflt)+_Une^46op`+d$u zW=6~jJn6|$YIYJK#*>KB-bum`kxf)!K{~RP2tbRoq?&UpAKwR9(6qz18OZ?i6$Nr1Q^Lnr>nH8d1hnA`z?VrP-4w*AKUE^?>q)CXJb8O7|HR=mGKc z4aemB?)+ixIr?2tzYN1k&1shjMX$xcPC&~PKC-b-*`B%4*93#j9^A1t#*ns|lXMyl zGY*eW9LUcomMVQe8;`j8x)Mc0@db$q2zBh2XvLAEbU&%)?UJGVT%9L-n_-3GWR%=` z)elNdsH|=Y>Uhm~IFzjUCXq7XIYI>q19wQjFOzDh2d6LU7;3JxLTqP>-T)L|;8!XAz`R+#ZBHR1>!->1aNmi>-V(pTmM< zlN>arrB(yP^d3%Y-+3jM0jC;KB#X^K8SgQTj+5$Fj2<;)K+vHauR5?Lm9sooMEXxS zyOo^=&>dvnHlIc+gmZe-gU_Atpuxo1)4r9@r!ZLOQyGY#`o;|`J^?P6%Me4S*`LjO z#kdd_CNt<`VbyI7#0hlKVD}s42s&^x9F7=2q}U^7?pz(PJe1z*?Vh1{0NOR&`D_B) z1p8Pegs)3#0@dM1K;u^f!WPkWEn|p_iZ+%W1^b%TfiyrY=iX>qD;B4}*hcASw75nA z-oRR1Cv1`tycqI$TdT@Hsqg^xzX5ddul&FLGlm@0+!4dwpq+odateW7NyD=z+sM^> z0vaZkn{47$2qaYofG$CngtdMKuh$LZdDNm#kn8xqUM%B1QOkn;-a?TYx@Iu#) ze(yHq&n_%`;Z+7+bjxXcr$r{ z-XE#rWfCd0Y6#=XMG<@wZ)iR#6|sVht(G!<+QQd_ zWAN&=Gokon>|F!{-SN&G8o;SBG?~#<`j=XBk3JA`)8`NZE@ozocZd0Z-VATuw#y&p zq|1ICYtS3$RL3F{34?d!*cz+O->Vo{tdQkNE=e*lzi&Rl`5=GdL*p6%o1p2%z2g$= zgMREHQ5<5kzxN*K|B%g$D7ov_{?t(dH#u)bL}Ytqk#!Pkv5uU|8qZj}8^xQrFC&U~ zQA(Kp@M!=jud$;&{AWQtQ@s7yCWknvY(El!$&^Ut(g-O|E?gH7&`7gZCNB2>4rOOl zc1s9#K?*$#zFrE!+wK4U1ddo<-9IVzdJ9vrt!oX?`y~v5h-qe#7yiWSAZ7yXd2c9F zezD*|&fE8ocVRAxUZhwwcHD~sHNz~3-R#pd>c~q%3dlyc)lh6Z3*pKCh6Oo;5TS=kLN5%DN)(@}1*s*FJ(W*D_p%(GH5F`Y_?K?5ST5%-uE(hY|I3Eg%G!w2wnkKpJw7W`fk2r zLzw5%?#!)9=OhUz;&|w|DbBUV4H!;a+Gw2lXZ_(gKJ&O_W+XtN@L-49eqL0;Av>xru__1$I1e|r2J8^E@6B*{RwYiQ{J7D&+#3=*s0w1xxWXO<1^(G z>%5+L@iR0}|Du zha;BZXGhRq_R~A8@|9v$QGA3=#nNeFJ?hFZg3lfEN~G9+o_&cd&)hv>*ja$elZHy; z5C+!LsteXpc41vkR6CWYxN5t8ntfDp zMLBs=h*$4ugT{ssC-G~ocvB5a1elcGm{f%2_e}XVnJXF@h>+Ol49Xh5)RVw7rUsJ* zNbYmn<0#tmf;(BvdNyz6yDEYVUH-v~E|NKsTv;*dSL>al?taU#bYQ&*VdZ~0ozCI= zP~ZX92ggK@cFQ*9m=e0)ag2hs5aO4qoXhAKue4=uovBNV0B$O*mMW!C><=SgobYSU6QQ!G1VO_+kRh*%F#b|$CC7PP|I3W2_k(kvq zgc~czcO&3Y>e0_+Bd}Tu0D5mIuE(^7x+zo8B{E3Mb@#6`%9hLk8$)jM#lC*f_LKX(;2}iG%EyoLu(Va`QV1Q@mnt3XtI$+m= zub=cf&B6Z5-^-W|JU?Uy9WAvZ_`sDy;P&W6WwT&O)gllNHh&CxyPaxJ z5Z>P+&2Af(tPs>Wa#u)bu$0ajPnbi?$?Q_JEPtD&sS_R+`broVHu&Y4v!v7S%IIs& zD)eUT6@aEg9+xl^Xwm)%IYwswEbrl82kj}AycsED{d~)2l4ChFWff;MduPN}v$v?N z=&i?5>qz;WQqiM#w$O{oE6l`>#l>xZV+gXT5BwA)NjlnWHeaj<8Q2CxnPUQ;fLvd@ zDZjy7EVp>)>WTww*2*>jOJ;I}$6N})T0|ObqwEs6frrU4^agwhx#{_2y)0u6s`?L? zg(MHepEJOZE4QJ|1)6=gRBmn|s#wKPO{%x!UsMBs%0LC}3s^GaqaQ4T-!W%@Czi*q zNR z_0hNbF}GJvpqeSf{ha;=)%6LX{s|n~sJ$hncoHfamX1!hi zzD8%vaC+Az%rP+(1MZqeSOR!#Wk+^Q%RZUG`~kJ}p>Qx7Y|7v%l_A-Mp$r*(qUb7gtwyJ)}w<*Sxm1JU2=v4o<7^GLtDH&*;)=d(oOzboNBpPbaqBy zZ`Jh?;s1XOJpJ`oZ9sav1Wct@}nGDm(g z!;e{NSd(J?lF&0S_J=Zu-VI}0iv*{A}Nl_ed#vA$jJrzTTg84!3{E?c(|b0Ky(MD&6XDn^zTL+mr2Cs z3N@T-rQjDU4zFb%ZmC_*BTKk3s|Fdy3}mJ{F|i(leiz(TKGPO-n0c&P&Pk#>e;kI$ZvOu%=gztZ*b0F#+ld#S7Kg(f+sETDRMCNNfobN(9yA}x|t{Q`z(w8anR;P zwehXX5~`yjngfia3l{XTcXCgnJW8vAYYp^8PTmk@UDI9;@8S#dmAomtt4xOG%=C-3g?UpucnZO6r8}pC`yCaR}$Oq{HhxU#8Ue$}ll| z%Zi3rCJj+RV5dBSXXj2!4j4^%NxumdfpWx7r+l=o=IfD1ad3@+%#@g7B1xRE7#(#` zji@>rj^qJeyKv?#%1uFmI7nMCH~s!wucO~}bVX_4$t~22h*keJIi4>X3wb_|ViZr_ z;-&pyXn@rP(|9QBWeLC7H?ibzt#{n*7H|0Drz z8VA)%R~T$tis7mFb*NZ1S&`=q>QD&RpRhw{s40&TK-oZb+M2jHSxg)hZ1z$4${S-{ zcR#0;g0it@X3iO{nex}9*Q2YI95uI*{pCe{$4vee6BnCh~2(maUJ(*vsF&OZ`3j)KO#+@;f54PggQJxy@$3i%zv!qQ!}NH zNfN%)uzk?L`y&2CVGCvMskBQM?ZP~bHr{Ps3)@{m zDQC=sn8**V@wh3}t00KBWu!#wG;DVdyRqQ<0YK)bNEX$UozJyA#P(R?_+=!??MlR_ z=y|}yKRp29d)FMcXF}!KAaXLX@*kh>AKE(f7e#7eV_z*-$?2#T$6zi<3O-h|3$|!G zSs_Z>)8*9LPa0@K%6bpPk7U5+)nA~nl9m#xfjM+2Wn3W)_9wKDabZP?@V#Y`&%02t z0(gaMgc%P>cd+`pajbl1qym@#D}M(@#x|3qWJkwH^Gsk^6JUr=u1v*iW}D;|kt%8d z>wj#VTcN%!4_*G1o%t|$xk#ycGArQ~)|h!K66>Q-*oG8l;#B;jU4@2gRFmu^bC6f8 zxU=VH>9nmR;K+?N|4p_#7MI>%gyPv&+{0 z7i`n$BClXGCnnyc+x-x_#>EC6BjS##41xTG86f&9o*xP{c5f%=`HYeZt5=32mfS$j z`;ch^fk=SFoJC05Xe%i}-Bf|QbeM}l$?jK+0;v-N?mgu3An@6mq-oksp&XuU3_)jw zOVz^(7V-76&Oj+{7VRU2CJuuEzvYa!693rxE0s>zps+FXC#EE8c-N|*Gp3uy!r-F2 zU0v;FD=Smjn?uZ8Ski*r&PD_*1+q*3V%!kZ+&D*3j1c0 zrm=mOQf>d9j6hJG!XT8wxV)h>6fW!61Oi?_OaS49>$_~`VMs3{ayc;@WCDT}F*s8? zm-4S*XO2&58n=Af6JEOI)Y;q%AN;cZww5O!u`6g(LjBZ^S^L#st&9hh9!7rb=1|(8 z+Y_qLEGNwba0sA8&=*qM$E?n*uH|f^(O5bjq_A4C62#=YVx}=b-gE#eVhcG6?0kYF zzg^1PBG%<rrL>>!ON*}jJ|t{t1zkk=Mi@J3m#NotEhtEz*z#& z=|4dk|BqN`7Q_4C_6YDn?3FmtM*{$+)JcHVoNmySi}ExZHd9JuLL)Amc#}RStI=Q# z-+sQBGK0;1D0sQkrx2e$<)(V_i(nO|pyO<(uK;o)q$XD|1}YJ%yf%nOxza(nJwp2X znJu1zQc8PyeA73P-U@(k%bVT|CHi*T&R$iUqPx3{B+%TLb1+w7s zU#E3lgH}X~ceeGJKjQ?f&dwkcVMkkCCTmJVOD{#jsi+OQJ)5-XFNy2n?a~fZ<;4() zg}M9cS|6M79>p)#*GIgwdo??2PqLGGM)gEKC75)Hyztk6i3fN|VR<>jiEvvLCb4 zwIln;H#}$lM0LCyrODX+rRe$yD)V+6?yHMrrtv+xPQ|@dR0(KF<<7FIN(Xa^biJ7a zwFY+^ou^04OqLrGOHjfg=I1M{Ds&m@+yp~I{2(U`JEU0!U$V!I;9%=Ww)S4$gg}Gt zISy4D;k%79VQDSv%f0dUX|mOWY4f^0>**jRTJXYoRNp5b0q$T=?xN!?B`NSUQOqx` zLdlM9WYLX00bxiKoNW2g)LBfcn4gh+;~T2v9$L;?yI`q!v8}eV3Q<5dAw4%*Do~%H zwUfbsoY0M;G;sdI;^Z@w?`P&inDkGynpeXD-)%Eo$3j3I962Hj{Q~{RPh|2RWgZSC zr8Tl8Tyh%JMEVd*)bns1AyS9Kss~SK5VYQq1<}2xN4|B3MU} z{b;ZWi5p@*@%)I_5eUs$spCLT9qQ7H&)$WlDke?m#lx#^u|^?9M{uRGIf@_aAeo@MS3C@#sR;2oX6aP)K8gmaM$lVP)l-j;gHS zVIV0@1o>aJ>=}#IbK6%$%1t7zf?*yxDpXN!?^{KH7 zqpDiLoH)vJ0YTBxGOb27B29UB_H<|9X?@3wFdCFy151d)r9=+xS923H@Ab|d>L-g4 zYXm%J;WyGHy|;lQ8hvINfWGL3bn=!J0VF&rv05N~C*_WzXd`&w*R%=QNB)LCAKRQ3 zcT#u>H$esJc-WDAaR&uDd_toWlo+gHfhgj$L2=sIN0$MC5b#yRYbhU|0cIh`;Kj`c z*2|V~QGwa8@t_H0rAGPAnx_Crc^?xXOqiP`Hj7VNc0XtFfZCZ(Hd~!9 zy@;;?neHV9^W&9z10OMxO!FEvlwtgk$!~BOvjf?cy!G_hdykz4OYA zI3(w>IKXBW1s=sU+kj&A>?#Agm^20L0ybUvnux`CBS-{&UIt|b_Ava{-Ew*;SVIA< zU(G4lQ7DEG3%~#vH-|jjnlgurm#q^uV4!_xEs2sGddoIr;9V5jaSW~~$}}v28s+=y z>Eu+_4lfrZIH&KmC1Bk3*8_Td+mxgzsq2F>Uf z;_w6Tvbhio)n!%VpJ+;o5X>;*O!-#C>v!ycHK@)Fq55lOR%dL=5(bEE_K< z;gaQbu4GSbhwMUa;fxS%!PqV?e+Lj@Kha~oacJ*sE&#J;yais3T;ZXjiVCAZogjHi z?>=|*U)2r#?K}cwy8qNq%W#Eb!!NV}7^N(zPP2_}cO>I*RUmVXwH)yd7=hdf3>+>p zAt?Se%Hr#Vs995L;A7s3imdNXMXL8_b2Y-h)4(uem>IOy^Gn?KP#f~p|2-8GZ%*7=E0<%=OluQhs5Ly+L6 zIGDeND_Bmk2zkkj){jEMXQioSsM=tsYix$D-v)P3$T=2~Iv7IGqQi=k@b#!tf}fz; zm`CQEnbwceNbY;FyN}fHyA2*K)oPmz?u+Ov-oO<6{f0^B1%2nQsQjN20~6WE_AXK| z*;`b9KKeDyxF<{bds1F;O^4&wB8JU&FCd$KL_0xn+#FqV8LpUt+Tv~^t6{9k9v@v# zg4hO(z^4Uaj5QpLu#fUFsQG3C;&>Xwl(btWXVR z`gDdEyK&(CR?_^|@%->o{~TzWJ`~j$m?`7zA2+@p@7BTiID05&mnIfqV&kpNq#2*$4V&cDl9d)agjZsy}>66ZVM3xGy{Vvbibg<}S z$%C}fB_t}*p&z;fg0vFCl={!pSczJ9^LF-ORst5f`%N;Zad`UGA7O8mwBzszdHT`6 z)QB5&e%r14V3&afgW;(LuEc*O8IRyxfMuGo1x{O`C_E(5)Zb2!x^~`jeIMwN-`Pb; zq6BJPr}L~frvB{$43vxJ7J>{U%XNyWvhoJ$*%9wg8`z6O$28?{U+`l3QAKNf=qJu2 z5i~PA?9MrzH8_xzpd620Wf^bVG@_UmFYA9pvQW*tYG7;lqDjG;8MA{&mJKk2k9UOd zqOVZp-H)_a0XISX7f~q752t|8R0p>Bb*dPhSmDULN=D9Q@|D_Ny17%4F8?_IiEk<9 z!#7?4SmV4?EjpgpousdcIG-wMkYq31+1C~(*;`N@V3hw5(K{C8aal09Ai2*xMC7*G zW_9B+#M$Y1=f-joR!JA#hH7=Kv()ZUYHFaV^ajuF5Sif^b=nR~4*Bf6L zyWC+9NLYc7t8a?pv57^K>)oEa+KuiBOl_FU1_`^MbX~%hb%)H}6jOP>DbjXa-$NZh zvo*(GmBqENZ;Rt3*BRn=aH86PSEgklTRYBsba}Q>3wW5YP~A3tGdE|D72u(ljCjnJ zaaOBKLV6uY-t1%iy{j5zyz3A20Ca)t&<-v%{5#xxvdp~o}ZHh0ls zy3EXUmFz7V5ySS{OCUMKUu+8L2F7D!#(?W?+oixdao)y7ES(O2&S!9bb-RY4Vo7_+ z=9J?sl=xDrh~~`h?p~sF8ae4%!U5VHE-JE&2`>$Wqmj;x;hLc#c3lO1b0{TV-y%-@ zr%dNyNfdN^?avG`4w91VfP+WNlP4D*|; zhE3AJH*HJe1K#Pip9ti1K;#6KV36>`kP`$O=DV{;6+33(Iu)p^`f@qE1F&oa?BeobS6VWjs3X;L$q zDcv#$F9;ye@jpm3rcf+RNYiItgYCTfh6rC@1J7=PVhSp^L%ih*jLvnP>#abpuy?0x zNrDf6q~*z80``c2@2?_AZS8e zaOGg>hX3udB~+L8+dSa#I!|e(k1tJ!BdZ`RR#S2&fI5v1#t{e^8gKMX>Z0_V_?UgXVy{Ykb=rMdl%(?pcE~*`<(n3&u&T#*mlEY;ELPP z24)g-0bw1(`tmQ%)TN1-nTdZ2#;>@Uv zy-e-XA)eF|nc}1;RDcCP%&q3wu(-RKzurD=W;X<0q?X(Q5W-|iuv7mX_emlxoN?%X z+|A)eIum1VY+O%@&mm}y!B5r1y2Hh>*X@BvloCI^`!jh!gF|fMX92Z=yezDy{F*Rl zVVIA%xQWWu7DmIBYT2AMJiO*tS{d9@^(oP-DpxC!iqu6U|L8U^VzOaitMi7wA9c(b zqSSe2D5F~c2~+`I7(9WzV{_)&R_B5E#@WYh$%t|SjG;n(PjKK0T?>^31bo;hik zUWyS^viB@rm*BEDtR~``o0??na=LoH6tc#b`E|*yVz&Vw?iMg1x%FjI`{vI4xq-HJ z8h&f*HNZ-I>nL2{PA#rXBp^&w=YWDRWQBKNfmit+v-Hyq*2*FT^*m74;W6~~oV8$+ z&aw(pR|TZ%0@YlsLw`L~JavMFWzKxN_e~!_lXbz){>HD>VsxwroJISkh6hjbHU-NN z8_T|R77|BBt3WCLH06{GN=++of(7Y$1LFTPxs%uV z0cjYCDk<{UF5|E;uJ~uM4!y*kdGdH)1z8E-HJ>Lz((y$Tv)L&Y^e&GBw&D$_>Nj8f zu+&<_&il53w8E;Rke+leRFqB-`_prHWsy*Sd#>aQrtEUk_>0BUTew8P`W$QBOgM^!(R5-K)3rM?oKImn~V3Or@QJSLS-R0nGp+x%6trH9uVZK2#(#<Q9bQ7xyk`TBN_tn}YFl`AL>RvPiZ8>xfPsma z&3lw|45;*~xx>K%$VHiS6UF#BcGe0fN9l6&S9DT%Q2-xBBJuWf<5zKGR$mB82SX4# zPz9Fz7|6LpH{yNmmeCZh$k0o(5`z{*3=1SvQ?itAdcvhOvUjf|trI?#^WYN(S43Es zEr)A1 zimDX6CF#7Db=VH+*C2JKIP7#0z*cipBNP(mwd&DSw-@B)#z09YvV|8;m$UNSN&0~2!H^?sX zc!CIenJhuR`CL}hHhLQryJ>t%gRq|xoas-=V5ic;BLrgdN3+CFL(xCD>%$17-8mQy zT}`cwn~SAMk$b$yx^moTKEOL-x+iq!io^C58{nrZ{f5eF6wz*)MC)SNnKft_$jOdC z70cOvfxqby-kOFWth_36EVNX04|6Tsu}cgu27*egW7B{xB4{cF%W?kSS!ZfH9_F~I z50Y5OOLgtlhZyHO&?Avnrlo%W8Nw-G;lK`8aG!E_zM-BGkE7|n6PZ{~x}Y;Hp+h5? zqZc|LHmM|i65xa^$`5qC@UNPI^GTP2-^^-~W6Tx(BVE~mqZuZ|22+c->X@4L7VU5Q z6l8z`|M)Z!RxCZnCdNJCq-CDL+#@rSx$WO)+J1n>5ji}z4$eo~-f#)y_IJv9QiiW0 z(O(bVaG66d7LS?zx@KJ~ZB9l6S~k0>x~Wv-p@m3+@+igOu7nBS>8FEfl!i|yb+Is# zO4+$;`TG6YCSu5^^Nf{-0_j{I!{23dD)1~4-M0VSx1otogJCQN@XenhC`$ z6nj`l5qEorrcC)6@brHN4fB#N0zVvyI0oV{F-5_RZ8>aJ`khJ)h>Jj*7|lG}EAs3c zGbW9#blo}Vl2-yj%pb>XNvb?Xf&EL%HSjjT2O|*nO+!sn zVhVeEx=bB z)5dxkSGM5`Y|og05=d`DC50Yb$qNWb*1 zoa|_U6T=+IN6TY zs1G&VdUAs)nZaur)|ho_sGju4hA~kW%RQ-aRxm0ja2~ za;SEgrXVCDTwl55lg1@1Lu}uGEC2KWRjW=@m>^YVux`k_1l;isZ&J>CA(UTH9;PgP z=LfccTumg7EL?w1Gp@Ece^w8EuVnC}8T6NdTmx|6@)LW;B;P?#jxXyWt!lIBo3*9JV~uo5g#eC!w;b^DJ*WXX>$ zO{Bw~m&!s2>rL)7#3!AKn}NF;lHE8Kc^D3=NIi&;Rcx8|=DaxadfK_tOWBTbcu9J_ zqGe8JLctpR@YlJAVFThiCOXke0sD*v1UpKFk{qWl4%zX2YrAU_lE<*vWLGfM8J6L9 z$H?cVWSw>X^%+;Ji4$PRPce#>iN_nJ=P)VIcFbNOuf+9dv+b5js;=QL_Dg}tCP5kn zouce>5_6cLXjF`1*E8G7s@Tcf{hSt&-QKNIVlijEiwy8y(px8sK`X7)IO^xFiu&l|@4b$! z>e_SHrYtgr{zv=TVP!1a?xjV#TNB%QD{A{XDjJFCpXSrCQqc)IZ-{{arsLB9@dM{R z@RF#f`ZS%SS25o)<%?&|DZr!x<`p{gYxCHzM_4RmPKgM!J_ciuJ05d<`kHW~NvTnBEQUY zs`~>CDFoMtuyL~aKOUelV*5LVGWkO3#DP*UdNZcP)^Qj!GrPa-(<+gpIv13*r_HUi zFvW=Oa=?Ipye;#G*o496eI3U<|nx`+VO<{5m;_xH2O#eJ|eoaMXKzw8Gs8{;u<6&_k z*$PV}#UjU)9;pemD(kiVsyG1%z^;Bd=fh2sPVPi!q=&Jmy8Ir^)Z8g1f zW|TjZxsYkaGnmzqLbO?WQ{14!>8q>L6~Quq^k!_b=t0j`M5;_iF3-?}N-_+UZ8g{3 z9expn98c>l{A+M<|5r};W)rg)Nva}RVI3+uT@~@>#;YnHwhrnweLRYGr>t^1G?_pj z!(jSp6VEfSrCG#Ir9Ml@q2#tn?+8T7)o}huqG~UIMr80(zQSCm1k9~mE-!z=2bNU%4j8oD z)AnAbh-3Fc+EyiruxB<*&@0Hobayz#U%_{H-!>ArYDN4e(I?GZ(ZQP%M(<{~Gdcjy zyrzm58)xF;tI%ztfKUx2i7b4F9ITQuAhBoRD;ugz#}Bq-B_wJQ!|sRYyu5I|OTh|) zv)PsrFN(#=K*O<)d-og^j8Gnyl2CcpxI~jU|1`83hGe0z&Irpxgn%yePNmG^ zh3_ZJ1-A=vGr97 zEX!ggN5@3PQ=?c&PA(<=P>YYUoiql=UZbtCQF{2{*3?uow<}(Q*ZhgWxut zjd_#wVm<4O+G@BV{NXXcq3Oa;a3jJK)z7PfNvuhTa70nZcqw`i11<@pLWY7w-jp!7`QF3hS3sHN|Ed+H<>80(kJav$x%SR0Z4oi~KJ9 z>jlz9dPV3hFuRo*_~oxtz1%tp$$CW&dSx#;^4l+v#V|&WVa;}n(WiSakNzdyJnY`i zM(%w2-XJ1j{asC_zRo{|T==K1xOsFG`CQ0IfgSFpoE*dGi7me@e~-5? zEo=dRFfeJg{{^*IXNE@1>Tk-pN-F6ipVA_EIiK=azbR=RqBN0^)`uVPcV>$7xc^xJ?3-XKfTei}!9#C(eTTvU!bWo6gf(O3t3tCxlQ5$O zJGXg8$ROiw1GNJ_dl}P|zdY5tlL+Sv5{pX(tO!FCE3cbS8h4V=;)D>pTct(Q$G}UM zD&?RQ8@dni$QXZ!WNFZp7K3rVceP*!Ej{?S3+r{+T6O!)7iq$Het#Sq#1wl;I`O=~ zaaPO4pDH3x6P^3*k@XW(bha%u0am6(f=PGE_NroKt#P3wC(hLkWW&nLW3Q&|&nEk$)77k+=3RO&y{o|81_fo) z-WDW)oa@l=a3%Qqgbzi>*s;??8-CMFGhB?gQ3g^lj@WW_hu%s|orjk;>M?>;JM^x9 z%MTv}I6F3?qQSiK+GRJ#|0?=IW>q7#&njpS&ZCX>NA-;ggual zm)ZON`tBbp!ZSd=xgT_D`qp*`RTZw10uzG0#smJ`v-EVHAiMUu>=z_-%tuJ&G?iDb zK>LI$;#<%7aV`&$%14w4D40~d6}XPoFaK^1M+}LDd|a&4?neYpHKeKFfB^rrHN+5{ z{x?tuYQ)Mq(+SqTx8N=e4rBJ^U*apF8gI5w8k0*$XVc^e|4FEqNpTUrN>*Hn`DP|5H3WK#7JEYkJbe`Nr>3%`Y4lcdNxTheHxXe z^*r_}ojzr2{d;ENGHCD6Eq2omsdCd5h(ph?gZ$)aS47Xf>l9)VVvzj;$TUpO82_)) zmJ^L6fayPk>KB1&cgW^(9G(nr6PRH4A3;+=DzGTqjTH}Si?7)Q!-L7#=kC7O1x&u_ zB4!Rz$(6=3LNa#M8%=_b^MtxfuWGQ^Pr4x!Y#dj4+8!G#r{o*x&)RjWshC;;o;blu zO+*bvMlg32mx!p(< zBdAP#7;Zqd4sN}cL7n5moAleD=Vw=l(_F+tEJON8?M|HKTrR#TE(L_?>p*!zWt3%f z)cOV3d3-SW_EZlhXzP8LGVOGQexF)KQXytKRN^iT=3_|U_s?r|ccH8=Y(dL9Rx8hi z3f@)+&96TXyYb@hj{&&EHkdl$^tKjE_8*#n&oUExdovl29G=<}6f_8pm^o}>O$2$>8QGJ#P|Pt$5S2;`6Ax!TOZWZ@#Vo*~J9g(+uQNmMJ5?0r zFFvscA8iVH@Q;T;u!iD)P!vQu*kPjqB#t0Vi^UAi@fgY5NY7QYp7A9WR;q{(<>?1q zAC&X*x|g8b!Yjy8jHvyI@S`bg#@m0NWhj0UYL`=kohl;w5lK^$T~Sg7z4pBoGkNg_ zS!Kv`+$pb9_-MoleCeR}-g7+MF{dggLdeOQM6*Pwy+~k&L{f1$vaps)t`TjLg@jBV z<;t;rdH0vKt8WZy+{ja1tUvbqmU9eI{C}T4vSl7+OtE{I#BPc7qo`g7SuT_h-6qx3 z7bXYh6O8idevJmXggbB4h?p z9B{Z)?T={bljZ_w7uCm+NRUy9Y(-C!1Wc@|A8}JFo9xiZpP+*6tmPY4@_9!9s@dn8Cgb23t$d2-rsh*7n#)*3DMaw-q!aP`!u-p2R0vRsmzk6t z96w{l%p;=D-E}lN_EQ^89zQ8)_rtqBu5h->sE+Y9`o4S9wHlITtx zwYR?%KtkgjwcUiE)x8|Kze%ylrKOtWwg&XtS*-Z0tl zvsNMrB)X=geZ9$ENf=XxzT_O4dEr(QXkfS7fax9yVW0B9FF&`kv-#AGkVh(Z9_OvK z|62?9acNqvFVA{fTqg*;xsJflApC-(oF&i{q6W%y#~l2UTuz0C?D^(2T4HP_I+rcn zv?_gv<{F?DX=V$jw`^elpWCCcxHIy~bFmd0%a0x$Q#Kz6Lq~`F_VDIuB zm=ba~?T?ixfBOWQgA&N*v%0aD6@}B+UoV;p~ zpTHOW^40R>`9snw>_s}X%Z)}tS#0%;kbElNUG61nQ?rVpt2ypcqtbL}>dh$~ns zhgSwK`;)U|T`F*84DbnjhmSi%nLf!=g7rr}$xsA8Wtu8h3BwlhCka5tV1q59^pNYU zsOJOZnEh-2WIp{HUqtA{yA1;XV~!6^^{N~ugS7}1??hZn!Ip4ub_`3(My-q>Gn3-T z4Oa>~|H>JgCMvfl{0s>I;11Vu?q}Ow+K81GBF!5m7Qy81!~9>R`jW3TawXF&u-j z$Qx`Csp6cUwJwCu%C0G-m&IkU_AkYCl4kvT+p#u$cPZ0QNK~2<6*v<)>IT-pi@oc} zHR&B9XiUGX3Rk5y_H~ptE};;_$GbNI)2X#Vu#Bhj2<_Dk?#Cs2;Qxcr96cB7EQ3-| zt$6zHH1R&2lvKy5jx4^lQ##~J+LMf4_iwDL^Kn?&EplUEg;I{hlF8@xY3w7pG1zq| z&a7-N24c~|5E*x;vz(Jowp1i46_Q~|RO{jJQ*yA;VRyLD;DZx1o9*qmi8%&kE=Qk} z8E$?e!Mb+ZlpC+fClQi1mB!U#I1s)wEfqTT#?NBl8=y{&s)sd$wo~~hp-lUCU3y#0 zEJG&nvVQ7T_Hm3yxcyALl)>|z7|DdeYj$TD^?3Vu*#cW51UY8=-Pyv)W?QAJsC6QX zrwaYsH^_j(?~08;<;=5Ip>o)09DNc^S=8v>gbll>#gn*yG#kf;9!^dU@=05z;NCJZ zkShgy8$OEeHw=pRz@oT$G1w_Pusk(59q{0*1-y=F&xK^S&r?D0f+Ql2m+ae zys@}fhp*EnJy}NqTFENvcV3a7b2fyew_hZ|$8ajIn4Otk$vHEnP+Miab!In5$rkfT z24Rh5r&h-8x$Ofea+cJkhdxatWF~Zs=A~)^1Ihpu3Zyu$Jqcly2nOI_x6w1VjbJ7! zV&AR9-rxx%y<`gS6UF9;&UOTL<_>&8A7jRjIQ70fnzngLV~E|Gu}F86;C6k=J55~% zg%VbQmJN$DNLq(=AaTFyKS8oj*EHjwj})hJGxeb(LO%Hs>8Z?Tk09qPYFKk|c$p$7 zsrT41R&rtGyhCm&Z$wQ^dV89G48|-G`M0}vWs`qLTpocd~Yp>CMI zh0Nu~R8mOujJ0M&C(@j3^;d(WF&yj^w|p4`?$U}s2_J65>7?D<%l0W z+70i1U~|F4-L>4-60uOd(;ZZWZzBQH4QFat%L9>un7ogXhISy~MW2z30AQCwv)U0} zZr=YYf~vjs0hU;RA)49dJlq5`7F?iN*79EnvUE^EG#}~>tshhKB*Y;8^*VW314}Q? z>A%8E++oZMCWYf#<$L>rNrS&DQ!o^k?LZVVBLHM^HdPPu;RYJFU`VhPs+LOAyET(_ z&fN&V3MMbt?^)?G3ZcC1FU$J`1>@_*K`)$a)USVl`2g z?U5k5RIQ=JVp=YS8l>9mey7~3+VdHSoK+-^w#H6uI98jDlhXr?aiMxDTDNvaZbh{f zq`0--8cY{i6=!fV@H8uqQB47Y2+lg%OQ@r6Y=Q&ceOx8up@Gc)DP%*L=O_n3g^^vQ zHFkiB7$6#FMf94|BwnhW)2tl22=~yiDs~qtS@*VAMJ{CwodxhmKDzU}zd$mf z*!B#|AeU?T(TqDDHo6%)m@_i26wHl`XM1BQogQatZc)$ZVwv4bl<{Q#!Ni=&>w2N#H9Wfko<%A2EF;(Y6Kz#R*`Isz+#bi=338 zS-uFJKU)_K^6s4V^y@6kaVFGLpMyk4yz7-HbN)w!5Vddvu!o3=$HB3xPy^yyeMd~o ztaJ3W@4K>1W!o;pUWAV|;umvx0S>2PmV32T^;kIN>P4o&Laxf#aWQN9_Vf@EWJXzM z0!b+3@^9}}G@R~id~RC6SA_G$tbUq_pSI*vbZSWr9|I9IhNFwKUdpyS8FkFDB>Fr$gsV$wBNkK%rIXXH{VG0Z?unNO zQ3eY5OiCCQ*%4#-Kv&Rjmx+Esf$s8M9k5Hflr3j98sv`{^30=z)cfB~8%$g^#@~^$ zZti^g#~Qh5R@^Vi%EJujEOTD=$Ok5ZE6 zW;wchah~Zuijc!^=^}LzX<;8P!ePDWLO&^8HcDJ!PwnQa%d5txsf&8K2Nxbcg;7M|00eNUoHLV znPfR>?$fareK#A6fD7U<4g_(vGawJHQIYEyq9;7XPVg|>@9jSR%)}YTnDsC&#h`;U zas+>i<_qQKrK8a<54WCLjHpa7`>N8#FgxU(Q@r}keZQ6yP|8Bdkx-BmIwYBPpodHL z&M&Ko{A-Icl5YbB!oDG0+Y7}I+PWNKVhVZzB*fwNG;URQP`2K8!$|b34j1~1{7w?z z#l$ecFU%yAdgRl$A<-+qqZbV$&>VB>J5I|HvhL{fK9@Us{Uw z_>eIaF>3ohb?~G^uEYfK!EoC=?e8?7W6X%i2`}D_MfC>~>bA}pYL9-O{6$X2U?6jy zk!PCm=mS_`ANVC85bnHZ0o#%NVF7k=T_zHO6J@=hW7&n$lamVi0K`ac-H#2}dXYr@ zVQP|cLfYh-t2FJ*_!hhTy|2Ae1Mfasgcy^{XvG~~2W)r^)))sv$UHG&%)=~|k54@v zxUh*b8q;uU4Je?&#el=Q6O}E$K60tp)1mVU}j z%=O&ypmtMf!Xy48g9ttOivmr{y5a)9Ns7W+3(7)pvvny4L81CX7BI;jQtHd-A#j z{U%!u4d3O$6X$RlBtWD();-_k2#nAM4JI0G^aj%P5jAgOPDs?FbOJa$-SVxCu-~5i zfwh+=l4=62DPov7h#Gz_+V~2$f08olLr2_Gqq<)cBS*j>V(&=kr2ORy;T3K_;>7V= z8q1+rMY zm3Gq)PDbfjM-+1O5?!Y*$)Mu@6vpCCvGT~LLE5!&eWyARx+O%^X^w;|fo$RzmUY|= z0fh-O)Dh|wC5j13W4Q_Jr16t^Wk-w0I&oWvSFQy1x_Nt%z3yPZhTT2~Pkf1s8tf-Y zN@G)ULfT78S#F8x0fR}c-Qr2g9c8G}GgSd7u;%5n$3V*iuf%rpB)f->{a~I%O%%+j zs2kX$8>2b@4H2XfirkV(+aw_+DoDSF3VK*cjn<5k@ahEcSThaa<EuKl+48?TbrmRp#N?g_{Z!@0Gg z(Q+(T=~PZVZjkB;(?GL@k)x2O#lg@rsYLB@8DB(#&rR0-<_EQ2 zmsBK{Beq8i`^rc3@9r9?8iT)>$9EEvnZ;w4HWmVFYP(@tJoe2pYMfe|9 z^CxlbxGx?%a3o`I7`bydR+-7r@VxDuhC6Vyc*wRHB@WfE2px8!yE*wYUEo1AF$PH9 zLFVM9WlxTmI$|&a^_ES)maS}F?6s@K<5(diZ8UnI ziUTr0v5FH1;v=!K>Sxjl`bI(aFU3B3dy|>5|1JXhl(|J)DNIDgzj`P|6>XaWuZ$h*>au}$u`HOCN%{E>v zLqZL(H6Z_lbGtgk?5Fa*jLGqc&s2)|#hnDkQZ8jW*6$c~w2!lqYKj+|U8?i1NIYVj z++~%17q4n!u~AcQ<2nJ(9lDQ*m142vjmR{XLv|mx5|S7%pu?V zNh%f?&7mjb)bi1GdwmA08p)^+tlsIYFigx1NV3npuy`E-HN}M z#0lbWO0NoL##myY|H{B6j$B;9NJB{88fn*}KIp1EU-?76#Rg8qSbJfb;=DNw7r<fU6DpD2be=_K_i*V3N09YLw!4RrLs<;a|mD zmJ|?81`CD7f#J@h`|U_Sv5oML_uVDX@X={pK_Db;$<_=!jQu&d04OQf2?yk~jabv3Pu?@u1-qq(q+DT2c z*OECGOy#T7+n$8wbq$rFtqr6CZai~D$^^J-%H zIGhavA~*FcQ$X&M+f$kI$wv9e+45n7#qsYO+;5cE3W4da>sD+znu))kTBMGO0nJx| zzz<>uX#GIks(r^GC+&8~Gk=+**SEt1L#1++OxDKY4@B`f;%}Ud74x)-1K_6Z-2jS$442zDU3wBOHiI)Vqw}xJyYuy! z?Y_Gf@6;jS*s7Q=PjfeK(jkn{OSu)xKhU3>R9C&FKP%t(GKf+Yb!z4yL?eql?sej&JJ?pR{xZ{f{fboT2%nMge@F**9LMjZiu}%84 zr8L1fe<$j7y~jQh@PUCiketTGFJGEmrfL_|nn)dlv~bE3zP?Nx8|*nY7uVF|1RkNUxRUZOI=S(Hte#!8 zX1jcVg#~j+sB-RzZHWUPN1%&3dnQoY;&a=%yZYm8jd zlQj)TDhJ=Ivx7)*B)@Z*H@T1Ap&N zs_B%a+o`1XPwcRDW$S7Mg6b`KGi8oiZSZdQ90AY@SyK@>CxCyMj=|Ajt}7C!$!>P&nnx^^ zdYFvQ%iFB!T_#F2=1|~*MUC=+)}YmjmG8b|JXhn2?v3w{CXs!z&&De~wldWB_wPyM zL0xOQp~d-31aN%$5o|t^u_Fj7(>?!xLQ+BB2zIpI!_2Yki@s@0_BtEL{M`jKccLp4 zM5`QhfP*fqAfxf3yqqvuz5~`W5@8OBT!uhK`lJ>iS$?<+#OLa^IGEt=@=H_fl=&kl z!g7Wcie3Gc@uO0Ro}mb|5Aj4iB>`>h0J& zfmjNFk82i0I%&s{zu%{bYV?z}g4WlCoUX{fI6;y;^XAI|$hfPr#@QH^fHk@QyU(S= zQ1GHtR->oAI2Dv3G9zhNqh*uMaAhM+y zd!R|P2_2nu;M2uz*sFBe!c$UB@L+G$kWwh}+ickYiz;gW+mE1UI}=qZ`!Mfo;?8tS zBE(Eenje1JG^4@!B!cla=N6$oKittcZx#!qY=}Py^b4^>k&Fg90cg6r5(Ttp9X+`v-ZbwU6{+hTqm*1LpUrGt zq=UxR?)ws0rL<;-aA@ia-oBs|BgXWXn8h0#O-giEDd2ssb?O;zkyo8}eXu)CR+BXp z0QQXm=drCB?&w*iM|576S_%0=mi^k*QP#q^4#~|uwiv8STC69sw7vk&rG7$$Q(N|^ zzNhZq!N;S_$S$5MExYXkt7s801Z1coxQff)T8CdDr39C;tg^ITjGA=BhR?211mzdzyvqI z1xc|tZ-Pib3tDZVx;t(SnyEuMux~ZyE3GqwKfBU<*P#0eVkq2LhO|LtSIg1Zt{3Fc zvQOk@mVb)$w}Vk*SnWJ`G9OJNcgBOr@2QDbu4nyRIc_l8`d@d$iV=sF)p?@_rxQ|9 zn(Z|)EqT9!m-Tg4_Kk>=cD{c-;G}<4+M7PibFwI_&NzFD?NyYnbcOMG2GBNnZgu&z z;&oET4YKKa6~Pl%K7pBH}2f-C*I#E_Y0(mM^ zIYAN%a$fllI_5}RTlaYs#VxqJA z^3f~2Nh0rASZ8LEO@n_XMEyaW2mRyY)=rHGTI*TB!;Qao#9rvP)6coKxxUNs4wx}+ z6TS`7)|IBa6TE2QBG}F6d6wqV${WymU`v&qz4ztK?brzYo$Dj$#8c92gd*VtkGjY7ed13~5-^uAB4_i@RJ9&pM{g%PmXA~|p z*t)1V4!=UFra0*5BH&FZ8x^0Yq7UaZ*L*?0<*0YyqpGGIAvZUJfQ4E_Pst`QV7SGd z3eY!@787l&#w{Jxw)&|)!6%it7+Q@zk>4Rn$2f-jT)PwZ%A3rTwi;t*@=+~C+9G<6 zC5(4r)x(obx#@Ni3TVY^jlBpDXojcHRxoMSyEu^#g^l zuxAh_=(%IPE$v!1YXe;^r*uIs?p*Ia1N0UJAS3Yaa^pKy9redad)Hd`Ok7sJ^`bX8lu-{xXZ3bN%p^PlWK6S^ zLuLHVy~cI)p}I;2H6k)D3}G|dp8$|+D^hb*PbZ${Sz{(TO(V$`mXvE0zN^PllQP8n zwA#sOXb5EyIKi>Kn_BN)&Cs^+yO@_Mgw zJo!l74i%9oE^RZ1I^)=LE0;uX_q=H$R<4_Q49E4Y|0G=X6LVY|zqeANb}<-R%s>VH zPJ@;92t1I?u*5S}kv;@C_M{Hrez!wwIeMc229<<6hs?K!dZ$@#nDt%=-%LvjOV1?s z!^?*~wm&P+J z4u^%SG=!b))5WHFeV^GhI3jnx`f2r1K|EP_=ykVXUswM+)|f$mt3rWBe~~t^u!VOe zqDTMgj=fqHM_)%K(X5Qk?O1%1F9)^i=mnFnlrsU3;bsKQ^)mCJcRqDXr*SiT3ukK^ zMv==F@;EhUGxusJ{(V7=RBTz(Gyc6_%nw$iiUuX+Oc0I^%G;g+SE?0WZBscS!g1G^ zyhh$E@Gu0etAO1RxQ_gmyO^8$*_fg{FI@uF(i6KGz8pzX^`9mJ^l@4$GGCwlWtwDn zUO{-`eT$F{$@P@-m=o3f#YPUR0?7AhCrrL%Bai2h)hM014oc9)Z)&Z0Su9vouC(eM zN0q;t(PCCwcql1s1E2w2Pq+WzHCRj?h_!hrHg6%yKH?j;?6S3bB=@F${007;(=JovZ-ed%(pbv>0^fJKSA+bZJF#WxG*ygB)KNuD+$wod zTeM&hfXV!Y4VPfZNk6{WhlQjVpbD;M1DoZkSCHz?Sm7Tlv54+a542mqOToc@2jJ47 zwThE*1`+c7-SWYV{!e#2fW#X0VxX}?c!dLz7~gtfB;{yN9xjNFp`RIpk%zlPN1~Zfi$7!6 zDa^U!TW4w?+HN)*9Od#DB-E%I@OB%3%O#RAW~>2A9Ua%BrBJkj6b2&R20gG|W^ZsI z$*$`?Uj|#svUe_1h^TenrOB;hZPCjft8d5Pc>_<)?!=mW`?RRQPv|G~LLptl)TNxG>R5avkNWckwS;I6ZS(oWKotIddrKTRd; zg%9**b1mIxLk)?Uj~ zNr<$VA*|}s2e7(RnGWC96$3HX|R|fB@;Z&kAM?O#r6bHki(IAlxf<7ZaJ8~UibxDcx50XU_tB?FzvtW%T z5B9zqe-Wb`Z;;F>Ov@CtcXUb8axSp*|?BQM5ghg5=2FLU}{xka_q;ogm`Bo zL`m79GFJ$Lmh>k%xzngHc&EwJo#M>o)jGa;^!C;iG2`2~g>hjjEFB5iqZElNrf2lYlUUxd* zJWbvC28i9UJb2w3Sn@=lYVS+2kHRe6v;Di*8FAl~N%%4@^ophqJmTyO`sL#a-Boo@nMw-()@cS40=HziVeo} zBD;qZ(OE3fRp?`wjVFsjA)}YW{wPawLmtGROw+#UI zn$}ID0;mB{w7!{*G58EftjIYfeE!)Zu=RshPf9VU`#iJ(HwVS~T0_ZI1($B`>dmlF zLcUPkqvq+O1&LvB?i?|c&9R$cuS;vX(i59HL?=HthXdd<9vL)3WD!REQ&3zc?k_qo z7car^twnhH3tH4yzQSgs7noSmL@_uPclJ{vmvB5%>b2LGQc_H$ZbThEJljPaeOQ?C z-GT>Zj~FQg$WA?W2olJ@yZYwQjrJKDJlk7C&{GUO8wd#>Q?v$^{chmGM-GTab=6YA z)I}_H;5ln{=g=D9(_i?EEU|8T&eo$f8JBW z8QZICISrAP`0b!M*oIiBximybzP@yibu3Z zxf=1VvU`^nI=U2NKZhuxtMZ%5AQ7>GJZ-^GrZy)sfxwV_k<4JOvBb4IcPOCBWk3(B z{zZldIjl}ynF7qTz^!RxwdmGxB>|!uvt6WB12WccX;Fu6Fz8cDH<1&78KCi2W7C4< zh@6D%P8|PmSFXsmnj}X+ZPDuumg?+|ii-GghBMS7<`HeghXsN#y#LE$KyL!&#?FT{ zuv?{D#13A;eUQ4n(*mrS4MS2Rhj!bRb|B%Fz&8jv{@WN?{H)M?nyd{T9t&QXT|fmt zpM{dF&@#}+>!xyqgag|*eP}^{rsw+Uz&5}5{e9A^rxGa2Rg$m-{G68SM2tTP7s;* z2&Q)y#aO{DuK0ZaGt!!fOyAQDu%k&9To`$7juvsH32vttrZPfhI{)}2C5Fo&+aQSL zXN@x`F0OibessO(9ZLgoCP!+=e>)B2pe27dBeB2^=X2^w$rmgNgmOYn!xP_ zfQViI86U#?!M3mbqG?S=XAEDHV&iwR!$DrxT5brNY}nqOpk2-*!w~#x;XCLjuP$Z6 z;VjA{tMXol(+fQLg^Y+KHDndvFZLgF+Xd^|-V0B- zYDo(_hC#Fidj0W;@rIYwHM1)T+nrdY#f%OCk2^CsD{agk3Wx*V;(&n@qx)>!K#=~1 zM;4}=9?h%L36{8OZ}L8jJTv0J#a=}Pv51NRoXBr@<53(E%44VE*$`XqM#l^W6!GDu z{5POP*yl&!x2oJZ?k5Ior zktOwb{{xHyH;xwhC@ z(=RrW9|WaG5d=0I=u5ULpNb6HCTn?1I`W1N0mV124L-Pr8Dk@4hEITE z(PLtV5+J;%;xX7dZmMSdY9{!dPyspNgCY5&+mzkda}v)g4YH#()IQ3wkSk*^jrY~s z!+`ecp47nK1CZKlkhgqxSY}M5mX9zS$Ei!$6~in{B|C^FP*vrMfAy0WrW%q*`3DlC z03zM=5H(Sq>_Fr=4u{6mnKyC5R1cch&9A(sh8(c>GFqI?>=iX{UF-$?>IN#-++*3e zYDcy3j>%ba-UOk1YgHgX+pJABhxfpm>2yP7s%@aPeaX;}ycAZpC>p);w1-`Ra^)3Y zANGl@guB16JRu@YhM?+qsC&}~u?QB(>h(AH!FFy800BhbjjPqfv`zE2HP7Ws8SkEXPnZVxt!l!KJfT+z znc*mHcbris9*@Deos{MLgw^|!W+&>?lC6%N=3XAI@`)$aAF%NRCz=x0rO#HZf8wvS zWmu0!Hei&OGjIw@=sD?nGMEKy*ki`ZyM$@bZrB+!q7NatjP|k!&=*hGJMnWEUjDUJ(?mtvSJ~U zXNAnB4XIL@cq${9j9O*S=4q~i!tNd?%Sn^aqomk#OWaO#6;>ZuJ0C?pdpsm^$~yjY z2DveRW3AUh(~BW5lk>1gs`-Y2L|-SOGEkETT2<+cm7^mz0E0Cjwluf5EGnAT)E1k8!z3mTx;gK|( zKd-HGSPCliF=-iUfS#VrjqhPD8WW{+08C3$lew)*XNF)KLk zy;Q`g3OT^t;+V@GJF>A&9lyC~r z$RGhR4!n^PqxxS!@Dc1KDSFhxmoOD=>3^Ji6|p5H&%z+>;{$ARkJS4Vit=?62j_@(2@V|yPJnjK=KvShv7SSr zZl>PaJTh7ck|HW|ZE88H8UW$n)AY!telN05;WUzupYUoNfBoY1`<_VvtP*xSNWA7C zBk{cIBe3w`k+sl+_8ov9jApiJMOXV<9{u98kkNng9b4nt!}J46>?P4XV+_R~jBBoE zh2WXsl!x+CWD{-W=W!2#DSYIU2 zYFJg<*MDabr6Vg8V$EH|LIF`n+K%hag z!)khE#W3%1S?_Z@#qBTg(-tjfHDdcmPKzKR|K4Mtm`7U93cQ#I$#5Tx-b$b zW$i6v!u5wLD{xritptKCNzW>t{7aul0oRCYY(&zR+I}BIGZ(G=K-DHj>uM68c>-qbVYs=g<`y|b8^ZXI@KW03!7x;b0-XW9X5UJv^y^QODath`10m5lugU5Itc2sw-)qp+@K*2T#S?Uv+1N5tQz zwT?Qy+VQg-Ke;04^(~vM@q%9MJyBVi#MSxXb-m4R&Qmg(+4@wUz-nEB;5GpBw^4Ha z5GpkT8lDqD@TZkd8oAWBs)klxcJHhw? z1j75AEOuB-EiRM!^=`!$(L*Z4o=DY|xP4e~BRBbX6@Lu^L2!Sz9(&8Kq{Ig4mLdbd zAmKOO{UP;!rQIH7BT^;xT)KNb8i!FV!H8(a5yBL%ACG8^kh^d1(;t1IPpP+DwIUC;f4D)(2lF-a%!==I0m3Lsd{ zuj!|3=IN%VSw*7!M0W>(<=N#>WrlAy0>;-++PTFA#1iT-_mC@R#jWYVL~fk--_~o& zR77HZ?P-6Ss;0aP5&&9LFhk*=c-60Agf)#F9MWYCR=j#hxMWQe>zv$ksBz_`K7B%C zTzKgHiarPeKtW>3!dDS#Q(%obR{M?CBbpRZ`L{Ypry!8(z>^5Wb zBDn6JG0^wEZ$>=s8R^MizXKCNRCsJ9g#~G4f6FNqldk{9fY=@!epD1C}Dn((N#~eQ6CRP)}+}bdV`6I#Xn@%2HFs z>TkvYUx%1qe6iyks-W=snl!uhU4@zO(x4R>C)8>>07giFS2wV#`o!wATXP%sfo zsBBr;g(_f&T!&iMmO&r=C;~jbiy+SpWbZJGv#Qp65~xR*8!&^n!s@25`6&nH4}C!z z&uAcO;&9CSnSCN7+eeqt{i#r90@pl8IZ#tcLwrl7wqj5PISFQ+TEF%S6}tw|!7{^B zsE0Bxp+C?*^DUSv*|x8ZTciSR1V4%X#%MJRy4surlTbE=#LPFszBV z&yvT3=XkthKXg0iK>4Zy9<+5`{(gcCUs?{E9jL!mQ#Uq-=Mv(x-gC}!)az6iB-34a zoFs4~;h2;JBX!*sJ^t3hg=L$>eTJa2bi(Nq^|5N)MPFxtaB|kr*v3wp+%Ub@wS<}x z0N-DHRWKkv+AJOUDGIzaS{fnqO;`O_o{g69*^Xbaw8GGegzCXr`N5Wy7j#QYSNw?k zcR5^;5pc&RgN3d|6egorNJ%~4xl=Pdhc}E`1+E5+YGoQu8y+3U6~+!DS{y^{Rl=e3 zU$m`n1|hS2#v35JC>6I}-LfVprCYiOz`o;X zyqd?n7Wj2mXaIi<+?V{LA#7(0jFq?&f))XghX)3QXL@?Lt-Pi~Cba_mj({B zbA1}DMtlU=i`}SENWT-B1T?SJt;<-v^P_!`@|*(jShR z%xnzaM{_$OpFmgOarJ%hbN!QepDKlp4PMd~5oglbM+(o-kP{L3Q=SE~MkyxpGxFJ| zEyA9!FGXZbZm~_t2gNQwVT$%?D}ThPg=d-@h;C$-zbnNsjB7K2wuP=1=BC&H%RNX* z_U6k^VC#7*q2w2!TW|}5`Yi2vfX|pfkPz@RKywa=QGPdYhHYb92=ZP4uC-cKz=}zF z8eptDH6g<=a&UqU7g%H}My3Z#%KOCAFS)-zf)Td(G66cwN{ufsuOsLFp)Xl%buL8F zGx4bj_y!*FouYRPyFi##C^p(t(E?lEA1RiUdHpG#t#mwr6JwD{5*Sj|3f~1vf53$XNx<=^$;~0HrIPD&oR7fZ z(t(#;agypMa-(9*6ZX@}BsoAE@6&*6$`l9gkdS1d zlnKFd!t{tevK65nofrEem)!*nk|lr&^LO*Dj7lIKd){IIV9bUSHYKsB{+%I2zKjIM zvHA`exJpo<7_5iiH=D*UoD)&%ztKH1Gy{AeSIo@gyv#mcVb?=Zd zr4jj?=pDDLrUbv3oKm%b%}wGuF*-cEWBlomwE*Fiu9P`%-{rTyB2csvKaJ0QI(o^> zMD0O*$LTBf@J+c{4%Xq^y7xHh$XpMiBG)V8aKNCG?Iox!AS;e-$rDtDKd$FV@WQBR zQpY0BsmY%65=L3(ueVgGB2i+_lp_}2n3Qvxas=#~y-4wF;zr?l(uDH4hzwGZFbh5n za}zL{udiV&8ca3xY238LkKoXIcf?*+JCn3Pv<479xS5NEo=y4Q6elLjib%8yN+^z` ztS(FmNrKSVo3h1#A`nTW6ABH)A7@PKK7K4(9&Hps&LhvB_CXnDpLF;2#?f#5B~2xRWvNj*l@pL3VIwdNyC z%$xx2<+#ON-^O3@BS>+#{hgLk-7zVcT&fS|s;q!Y0JOA!*qknWJne! z#I&=J-wvilfV;|pADsgJBdm%%q5130^E(h|@07>IvgV-t&Z++ZrhMlLm;3S%_>d?5 z=^V@=Zu~ieEG>~h*V5*$5G&)sdAC#&DX#b00h?X=6uP9cE$qE9mTC%?7WbbSsYUKR zfy@17t>L7bAJf!UqQ%6so`^%s4bsr&#MGirF3Zzx|D6tEE(2xbs=Tglb;EDGkh8Kx zFn>b)+3AD_l(^2ALx1EFT~edbE$|`WpL)`NDs0Y)IAo!TNx)TGHJP8BrUhuD1x6lG zi4E8)|NA9KMSX|tWm7kkO+6_^r)~wJs+4)%w(|(L1BDc1j@*}ZE7iu1mQgNC9*-;v zK2apeYHpta{u#hwW{Ji6Tb@pILeUWa|CK;`(QW_M15|ZH#vjga=go~GhGAn09G;Yy zE9)WsTJf^s*<=V@tw~xw$)~Qkmte}^Wi~S$dh{a( zyMv^C)N(8(sfV@YW``&I`AhUeP_Le@L$@jRYNHkb`OnxgHj~@;oR>mowfx>O6}81! zJZxHNL=q}`&~g``_Xmml`2LW;poEOrc6kCn zrdDAu&s;=s;el!dRlpJ5!vGkY@4BCpB1r6QPft-_4Ho|;LCE6OEp!$d<at(#ejfVZHDGpC&5=SH=9ey^b7k=-MW_ zcR(!GA%dZJ`=ZzVcMlU8FJ=8J2^G12v3e5z*|dy>@|BH&^C)jroE;e{QNHh%vGY!% zo$pCWR1biu(`XZhAVKrBNdiHHm`57=3+(P6rj#F64-&2{5}VK|bgB_x4U;aodS4s`1i?2WwrJT5EU@B!0xocn=uY^~ z3xk|dCKE*~)}?rwXi~#yY<*x>1(`UM;PZNco>-lk+VOXj;Gj8+3-xk*HT2+ht~`l| zCKio{%php#v8l{Xe`UR9O_u8NIeX&Sv1_gPJkGN-W8Pt9x5;I>+QVM z#U*d^0eZ{RWgG;`^&0*7EVygpDZ5+38wvWPPtS&nmdZ#n+0h9IWjo{QEK$+~E{ z5!~FdpmF>s7goXf;i~!OgECZLH_}F4j#eTueR2Nb$h%2Jz=?@+uGze}XqUo+3A^nZf$OnbWk zMB+A(TXXg*zA-VVv{c)|g-U^b{8#bl_q*0b=FBsUkT9-9(Zh#Z>(l!W%Qp^RVCy5V zFK;6!Eg`Nrd!o577f73}Y!+}xu&;Y0Z^x>C*i0_XK{;{32b{Vmz5P$RUef&1+KJPS z*s4lLdL|dYl;`{9KT>(1T-UpV!{g?S?Q#e7UhMJu8qT_15JFE%QH(9X_IR`NZuw)t zA1!%gQbWh&3tLg1ALEwGd3p1wU#JEI}Xo{!*nkt$~Di?pEbX0&&GsW{~Cj1VCXnEXmTp({c_+tE503Gjo zeV=$fESlN_KROV+GGLdCvg-9YQy(Ui#+}8qG8PimuHu15xTVOTfvrNt;So(A5cXos zX9PWutM>p9&pT|~rDcDz3ezN;?`dVAodmo(&G0qU4AKbqB*%_COabbdFCo?`WU3^_ z$)8PyPFcKB9EA3u8HoT_RMZo9gvu3`M#by^$?lmQqh7RdN<9Rf8}87Lk3TGPjjCi7 zYSI~KRb>tM^Z?kEHE?NiWz-WE&M^;XiAHTIA8&vFVES#;Upl5$Av|X)Xj7|DIN~o2 z4VR(X8aA)Jjkd+%qKl<^JK8}-!U5!!Ls=qi~K(| zO)2sqOc&4PRvorlEn$$^f7<$&u17%pxnu4#VFxn8ymbTE%HY&qb568sMIg)Hm%$Fx zME3G^Wv(GNp`ZFSA>UTskYB2#j4xYTsGrLV0) zt^M@osJA%P=GGym`k^;%>rMd}Xshir{9<~pZ;RQ>A4OF;bJsr(##ah-q8@92V-)ji zum1Dfjbh2~9Y>T)w!9c^Rz1#maW4f?L-ueuIA z2)>7S_D0RWy~oiUHc+Aj*#%=6j5Da3;HPde zTt$ekMFottbNXxh9l(S%IoPNyF0UUsa4Ap{OLb#+H@U?3g3#XLdSD=P+yp=ZjD~L+ zW-QvDgkEh$>UL zZ*h*nHYV$u+m`{6_~RgkT6WZd&(0$MB=lNE|Fv1a`oQYlF5)LZX=Cm^CNaM9kuC}5 z39vf5GI7&BQH|KY2A7M=*K-Z)wyzh1xn+sqy04aZphBg$i0#K>E?|Jw=e`sa3pjru zC@MQ$AK#vhvQq?pkS@7IRa2@nk?KmlSEPL{Yjdt7k`Q+rzlgb~OZ!u3SY&T)S(_;@pSl-mN+3cB@om+{ zBi*t>_q6m^`y8@)+Z2{ z#J^kIWrWbXcH!yYZfRivK|%0?A+uix=&_3~NXFfhKGu~22A!B_fc#4JCBcb3q$vC% zE9Z!p0EvM)(`({s56;c8Fcd)E=T98+C17{c96t$5$-LR);|wsnM=;^pG-0ax z`dUi80E0(ub0)(;VZGb@63q&fCDT5^D&gokK8T)xveOx?3>^^&b?61q($7x^l`SD& zj51VS+OpR!+U3vioS{9#Us<$DPH3LxX{Iq7NEHr$2GCtOAoD-#DQNwZZZ>p2GKkHp zMpt&SWotG!{Y&gIO*}r3lBCSMaDa)DQlpGtOg8uEm=C##taK`+qY2#_uWOscN8j86 z3th%XR^9@TR}IK92S*UpIIljz2e6zb?rgx1amwdmoqmw{!1sZ636AKYQ>btqMU&an zTJE<_s*Dk5b^-^->9?EB<13_mMxAT{`QOgZw5P-%xXYozY8SKAbXHuX8 zBg8OCFu3tZ6ua)sWdi$KUhiz+1_OE+qi3`pQ!HaCry9b!POVk8R~0UB-3L12%f|Bs zcC>a^H#W_jZ=_~xHd3RuG`}<%SkI_%?8cBtjgRU*3n91C3dOD4OrIru_T@&C;krC% zy>J(uYfciPmN2L!c8|0FHIC-VN(q$Q_Jm`F3IM16C~AKRVXp105|pIi0t$S=|44iy zY~92#6Y_(0Tq1DzY^Ufb*)6=Btl+l#u@E3bAjc;9gmk3 z%T;Ee3kGwTag-)D2G1km^SD}y z2%;+@=~j*UUt1lZ11{sKXpB_p+!EDlP0OIxyz}zOEC8VP#Z(<42{{1#F_pBYS=S?*ug4Xr{B#C!GL~S$m+TRc6n5XW3ob;Ee`HzzUuEA_c zU%6C4AfZsM{w8$8e&Glmjd01r3dfy0xrN=r=6=2(mEQBT4v*-;9-c}oyPDf>X;*w> zf>xm`K-9kdWOGAnt z-nQp>K#zlEn%Fq*TfeG_b05t@m6+VxjXzos`{8D3Tt6X%ax*!;gO7(?rrq=p=hK_u zpOS`~dlWI4DK(>NgJeDW`Ey`}5RN;-1e2sf-G{NFPXlSC&a$}6aHsr&@WZqtayU5x zJoSk_02aR=W%&BMPJ+RHH zou@DWO`Sn=sgumR_laGq$7U!_xvt$ty(*R?)xYH89qbA+gN3?o$9pZGpesH+-9iuj z(XtOMF?JXP2Mc*J3O2V}V!gu@)-mp1xeKf!AbGRCMbL|^b7i~`zYpTen{d|MWa|IA zclA_JV-g{*lgF$MGxt7=enN+n@ImX>GkLz~swLUAq{kl9dMl#P(^^_w>vBX)>ovWG ziaf||NOZnOW;LfzY#X9q$q`>w&;mV)odt0p6pjYaIEnY}3a_&9X`5r5BZH2G91Zaw z_XYE&JU&lPj`zuXn_==}#5udkdL7nUqRy* zLtAwuH4h1QJsko&Yvhv122%%{NvR+*!`dA9dQ3(EFn~hM&s0tG2i!0AC%}HC*Rs##Rrqcxqdgu3A{FMX$m= zt4g*2^7{5hfTcp&6dB;i1_q;j(%UX47!37A zn#2#*pMDdJ$e}jD31te;k*Xrluajv;3RV;Vs#vF_YrXQDKuz~^Bbn_N8#H+M`LgTg zl=-R_A=9MCo=^kUyP3*%#A^ZU-vEoZ`sJDAH1IY5M|k|(pLPd#`SO#dog>P!S9`;v zq7<2RJO#Lu{6iQ9DL!G#k>$Avly2=EOILGbBNY8TeFL_J+&r4173Co+#^payh-2!yeapoXk<^szM=RWUSdF46gm4oxwI#iDeHBJ6^++N}Xo{8^ z{X=bES%q(pnICh5(bsUlYC|SbwlRYef&7R@DzkbFVvGb&Xzmv61G#LVbDc0)B%2V7*WUE$ju_|GM*s;16nT6K#X84qR`uPWkK&eETJ=Ls* zS-^Aye<0S|Tg9xAJ4OBGGbm6Nz0cm%6DWYfZA^DZB$C#M(miI-l5~I5;pk_oetxV) z6{VOKH2rkJ1gL>$BtLn)_-gUdz-Vq7yNwdvQ#8pw0066_s5~p9+sH=(MxC{Y+Gfug z`CaoDS@u0Zoe;aza1kT-Yp6MgqhzwR2Q=PGI`JN+@x!FXV}O@z^DLpixboGy#;hd> zm+eA!VJg95CFXlp?w1_Di3Fz3rn)(Q3h$ovpBUg#x)?r>Hs@XL_ zCNdx$yikXgYC+fD19#inLvo|$HB_sv4YaniTirBMunJexhBfC!t3oU{Y#mS7$ql70 zE9UzKXK2U!;zJmd2U)n57U6CoVtc@NGeRj-Ucc?v_-GyMradTar@P=m5p~iIg=`Bq^yHWy?5V` z6^__Mlq$Vc_!>1zS?asVhG9KpCwmO5rc;-=i=2zP6+OYBkY-IRuIM)pBny?5HU_uC z3bgq$$t(&EhEb=4C)*>;ZBvW?o)?rzpp2akhckQ&^db)VTAR=mRr|$RP@&OXWi~3` zvF%~-%=JbFWmML-z)nhz7cVB)Mf<$L_$#M>{@N}iU8Yl%=dKMN1h>Bo@rSiQLO{uY z`c&784(PWD(;Dp}qYQi`lLMn;xxt$MY-#fIWgE|zssMsBp#nx8xg#lorQEo4Ps%+J z|J?oRqBd5pFf8Qkeu3^~WM)bs4WB>#mui2N z2lMnLv2-8#ac6|g)%*@~Vio!4y@owV_O@#;OMi6pq8pbGBCT?n-(%S`Sl$b04*~WY zL;GgTLdLH9f?1m~a?P=*#fs-_wnfR@$3;?Ca)=%MNw0~HOpIDl@FRZO`n&M?zb>zC zXP%Gh)`^TW!y86HTpu%&Glx4ZWe0hK$Ch-2o@_0$W>43lx{LkuBiROw9yBAZwj z!~>ZJxrt{D&3v?J#u`-WrVd5$7c8wM?#@nSdcSOb7k@`11OQzv2e4ExluuaiWvu5A zOJ8Cd;qTIKRcvDDa#St|oepW3h(6?vi&Hh$^g=-0N#t0gc9r*GKy!u6v?Q4`?0rF@ zsKP>#52GNrp6-)&Nxs)2wUt8-eV|&u(^#L?QB;)bkyrHrM9EzN(qNZvo+`>=y1!Us zDx}939d?`b>gg+cJ98QySbn7%)mu8PXc8OxU@3XgerdCk7MUn-d(EsC8$zB&z)_7z zO*PelU~xTb8%443d#*tA)JeXfc!mRpDQw7v<*IXhR}9WrEuS47q1fM367N0ND7 zJQzhV!+0!eTk+HCsj_G2Bs=~kOUs^^X6ew2_PJIr;vtTKcKG`Wk<=b+A7zjfId(#t z1!$VW%KYcboPZRp@)wr>Q9fHFLiJ?>pIZAYvPsc$N*t>vqjOl8Lm=#dWQ@k0A~BZ5 zkz2Bu8`ItocL!}Q9xM{nt2gcb6?At#LBeo9rfx2sw7YZP+(oiL4FAc7zW7?^N#eD0 zH;%-~rDqT5u8b<=E%Y%|m_3s*uQp}!&iBz_i(9=Kq^%}6=6Q(*?c zn*ax(G4F|FPXBFY1RPk{(X=7dLv$Zu&Z+wujUf?gCspk`#890(KE#Z(x75rC#%`7- zH0-nkq72kD_8pm2s)Yyvl!z5zr}usr{Xt^79;iNS$RxTZ+o}b2GeU(k2qg4NittTC z=HZYL{T7@$n(_`^t;q>9+JxOJ2TOo#*vr@FfYF+2spVK#8pB%8vI0N-4Kr z_GH&3BejKa$lVn6(kbX)90`Q6-jOSYY29yu3Y1KDIEG|B%L%HRNoyN;*rDSkzL(ZC zCSpaUdC_?Z`g6Wc5V->3yv~V_$>c)i1K)mO%AP%c1K&O=i8o zyNvkKBsY(r7X<`<06ot6atF>W^Dk%|72M-Z(v2K#a5>^E~n&aDz6ieR~Gsn(zGv(5ldj&?xcbfEdDT&;QHiBi^cGX*7gatXWLLa!*q|OD8 z*3<7e(4a{=(Sp-so~?H0@Y5u?_@_4Xn#X5V0k4MhyIl?qo_x_(Vnl0%5H?a55|yu=ZpNPwol zmv4LAIkP+oKP(XD(667Q^8E{M85^>p7dY+Ynsh!G08u&CGo=q%;D2HEFVW27-zzSv z_I=*Glu9H;TsiQ=iT|H@jZWC|{fQ?;rCsWw}`uZ zY^pYuZ(gcBe zM+0+@O8n5Th8U-VTAJz+G{2^jb25Fm9rm=OjWl$Qw zXG)aFACn%W;t+v2uR#A=Z#T_{+&YH1UVhEl?k5>=VYhE81om1b0fHcS)U($mrG|kn z01|fximE&O5DU$_G6V#6)t>}zH!@YOhg6&-g-;mSv% z&_cRQ!Z1MUQmO=xm&imJV_SeRW7x{ZS23AdkQAESia#tGX3{wQTjv{xb(F`_!YI2Q zSxxN^_J7Aqu$NQO;T=t%pOGjAAx^m8$5K+oyK+e{+5l1g5O~?BXKYf&S&Cr8VsTo~ z;YF|47E@~d1-Sc^dAEA=b-06lC~nD+M)!RZRtwx$JWK9nO2>UrX8M@iqD2O|_&Bh4k)dCcHz=CS2cld-C4ug-oer*Uc1( z9gSL!+tw+9l5jwldW(G7+$ATN0mH7p-C>P&(id6-eMXMaVgJ89 zYR;e%Ec|K*Uelc}|EZ_!e-= z@slks?%L1&F*4f2;4CDTZsz+H>t6EUg*BjqcIUhWD zQDc93N#jo~Z@+>^kzB!pE&VONd&6}43?QGy2LLIz48MYcVF~jK!2P(p{RXizcuIi{ zH*Rz-#9f47Oa4}@IaU*k_WI&TblkA3dvHZvW(~yb0j9ieTEukh09z_QZOvmUyI*X% z%C9@#B^EL@II^Za6y)TRfbRfebRe~OknQ$^I=;a|I?iqp_y~IR1T&hLc5#02ZHj?- z2~()?RiQ6bcjh`2lyVdV+e3WOxrG*__{C5l?&2Lml$4*|*8vl)cRz#n`og7co3Z`v zQ!PUo%VFVH!7nqV9bU-W)5_=mWFT%f9cG-_KkAIr6?cmf&U7CM;BMp!_7778>TLF)t{-zb#$AQDuY*>i_G6sz z+kfIIhSkONDig&J`F%ML>DPr_-88eJLP0$TB$E!@yv)QC=VtQ(nG(ZLKk$io7I+8M zzK^-kxg$G?fm8t8fb#K-x}{VkpD!b%(K5l$Blr$WUk^{urtHrRk0mL0S97l>)!8ea zIR*K3^5gVB$`rEr;x=ik&z!dsVEKO)lT}htaZKa~G8Z$aE`DV$bf?AXu?&<4P(+hF znlDJ*OsUH>@WcCyucsK6rp5yB|D*%xsi2lUflUJq^adSeSDYqATKhZjxfG^-QZ5;p?%h4N)+ z%`+W{0F@GtiMS>`fu<0;{(ERF|ItjmbdYw^3hGy3?8%mZG+`R*&E2*sx>MYcX%fN_ z*NcDIf|r&x<>af3O5fdZ39GOXrw4vLMl0iD{3zmFUL+BJ=ICDRqoa_$nf7WSb;LPs zqQp2lOc|fIwW&aEHUo)ngCX`IYew=tr{c7*bcr2pIaK@U3QF~$8NNl~8vwWkrPmAG z0|W+%dep*{0{d2|w)BzM?hiQFy2;X9n9OJv2T^c0IzW>I9!Ljd3g}C>YH5%R0eZ?? zk+VMdCg~Y5-v#9zLa~JZ8+0Q}NMi=~yf(g=NT9-(6e@?nXabiWI~LLS#U=dm{;@?t z!8D8vkV|hME~XB*P>CoCS2=_Grd;&{sA5V~bnGJNRJ+POZ(b`ejhlvd|LMoEobBv=_K4YYyb=a8CBy*NV06)^?i2}Z^^*m$_f;*r+P#^p-rOUtO|{b!>E0n!?!tCr z{@hHM6n!*=GJW`mUNe5=bm*!n5K|BsK$p>=2b*9A61UB?4F=upDb@o!g1;d9!z(Yx zh+I9Ur_3|PvAVMI8s9U$D0MjicvEt|{r?@1ud^UpQhhs(DYxA2T!?%S{0rT=0vpd! z>Hlf@WU{@}OspklfY?n#k4Toy4_B83MOh_krD`Y!6@Fvg^SNbkNIC#>h9z9G9P@Bj z{Jo7qD%0;BRpb*^4&NaYjb>a}fNkSyas<9+DomJD<2t7V2W^IC$5RFf)CF!UvM^0Z z%d9Kc$9YKg%C(Vyy4{rbX>r0RJuu#qcZ5TUv_F)ICU6`$TC-XaQQSRogMpJ%XH>Kv zLvJ^?Fe#3~_kqblV1y2x$`qD>_WOSI1%*+Hgx3jHKcTKDL0za=5Dc!dk?S_3^JN3I zcj-DdoA}`kwY6dZs}+{8b|_{@K&%8g>kpw?f~(U+c+AoerUud8OP^0a%y zZUD~wo0d2qAl1u#Ra?I-(jq3J?!bE=5xB+?;hrR~8#4j6OCmeg?)(1z)!ZDyaerBj znHNc$$>tK#iY4SN?>z(F>qo6?u0FZUbctHOuGIwIS6*aA-2>P`{^Yx70^#Eh2j(WJ&KfwBnH2}3% z{v5KpJ8nTOrJXs$1c!ZrkCgR9{8-#t_3>cHbLa2+yyRJpJ(-w#WW$ zBMg>RKifJ4ytK6YutR_$(|m_RqK4QTqIOx6<-Eu!#<(4H-z5lGAT4x7)$^D}BTB=Y zhgm$EJ+AZC9*A+sNg=A&ba%QLY*F-(0I&hKXK_4TU_BG~FlbxOc<7g9CV9%Y`+9ERkM;47wq1z4O;wLLFDRop;~cw?~ui)*8XLh-7H|# zI{JRA(b>jO+{SiPW2fY|zLZSLun}juVm8|j;{xa)gW3})kD^heVn1vurfAF)jtd+Y zxty4-SnMJd@+ip!ye?tQS`nypaAhm3oef|-xW;ti(wFJOU^z;&7AMg>wm{oCraZBD zbnapHZhr3S`~(B@nPvr7Ny}wzjOB*%fR3)JojWlBM}mq$1}3ogDN1s5hiOe9NGFiL zy7xGJo;||;&AAAFgHLDSA1-nal9VgV`gJG?1k&JZd@%3zd?N#`05`_q8?~tzj1tBG z2oAq(0QK@)G2gdOR>s)udTbwxX2+RZ2$6NdY(IZB$$2=HMX_4;ASppAwwhR@z%otZ zUO5z(J78ph!R+@%8xS00$4&DPiYqVP;~xQIM3B?Sw>_iIvg(gXoeeEB+$&0;oIGjG+;mTnUNp%MKQ zpH*~Tfpf^9D~ZwG;4m*};xR~^4bC+?^oTNBIw{|dz0mRxY8MG!`uD<7X*Yd&tt`RC zrKof};{qn{wa5FK^aK!2s7D#f&anW6`u)~4vHfr2XS{vj!6CYslI`7sIRL2u{YwOJ zva0oG!Dytl31?$=kXJ784PT-Px84%DX3a54^Bs1qh5LTkq49D5-N$-HZY@>|DgYML zXp0MuG8W1o4gHY86F-Vhdt5Y=JoYu-o-g!oKd>p=zEhi^we(j``s!{hRhUb6zN+L^ z-4;MZxRJx10t7gvRBWj>q-UA_$2uY1-agQX{W+SY>V=}6;udx!4V+jitZ*(1{~teL z?w_GxX*L$H;bst2P-z%R6|?Y-)b~%cfsmQ zZEE?+&OtPdBM+2)I*u^>4+qcD)zed&K_Gnq9-rK&icJH#D&BOdkv-7^&9yEh?S-^ zO3;OX`Ezm+@ZLQIqKHb~Rc@1(y6sfsb4d@(-Qtii#p-=D6=#|}gObFNMw{DZ<5@gw zwyz}^wwyZFF8lk2v_8BlwQChW?^oZff{pAnI$zTjrwWn@>+Ja3sh^`dDHG>R85A!D(E8^2ehZVY_V{a+#rdaN*vnu6$3Sb(1E#cn#8nJmcGdwDv zf=XuUC)UuJa}_x7TE9^Weahz*ugp+)tXO!AjqSNW2_s^I)@Oo#K!E+71WDsQ;o&?q zb|LGJtTjC2Bo%Ywh!{~0bbHrL7GVwyfcYD~6erLXOaIjzzNewiEzjBF$zhAjdbrRH$fNgm`d@ zlK)L~9lht>dc5=H<3=x4jLc`(_Tut(B2P=!fNuJJ&*{vtOn)IUq}M2yrT(F?j>|&A z)*=<-Ap94ugYvJfoGk#aTW&HbybH(otCHt<%&5CC&- zT1l|{(z@D{zqruJ76y@vDf{YSG6XzUPkqhWWWK$s|bKRZ*ZYdqpo>89csG&_nipo+ zn5=_1L>Qz0uM;s=*V^?!*BBCd&n+)Q%cG29vkiHZ7d4H1^RRthzW94LB0rybj7S?V zf@j-c)2Mq%RO?c;>krPnlrPZH6kF7C5VrmFGj)`cU_IB9-UQpZX;TSLDnXC*AowTr z#3seouz!ZWsR4uODXJQiZS$bg%AGncxO3DWLHY~b2S^47Ur&I=sVUXcjLkJ+q}!y$ zY|hYCZ5{G!%MArcX53xsDMPh#X2Y__Bs33lBVo@n^S82JGcLDism^*X6CII~3%&aj z+f{a|m+NRl4R~^+!f`zbzAVTGJ2<)=A&l|;hPD}WAGVkmMj0pq9CCF5XVuhXiCFqP z>)hTcabHyel;$5S`@r5@8nMV=9l^J(vt!{6M@@3U@nhfGLs%LzkM4a=fI((cz%dn;DU743PK&d}v`?C@SfZ1sXTiK*cht6SQ4 z$!~0sdmOfRSD0J?2)szqTfSI#(HJZ0VI(`74WUyDP9CXcWo(doM|4sQjmgc&Y>};b zcfQR!fnktF*-R91s6MZo^P+E_9H<)y1MjmOLCrh~9tSV1zBV6XAyT^t2%@aYPQ zSAmTZUeYvkr;eP{jM{hB^nG7R%5!F0SvB6sBl_yH;oX`$Z_Tp-(Of(N)pafnG2yEb z@op<+B~ho~^!7#S5JkB69~GxpJxjDUI&Md@iQaq;0^$hOXZR+}Et(=uts`wn5Tqw?=nS4A_8`C_pv z1)=1W)rT@#X36%XvWQlmv|8p8_drW1u2^lb>M#Xm#G;Q3H^D_ z@-7+C)Crfrw#DZ?{;Y%SKW`oa?ZA~lav(pa6?9t0Z( z&DefX!J2vzutWq;&KgN%=;9L>ej_2xx95~)A>TFVe!N}olz4^8);$&pys7{x?F*B zN!1WH$uA5k)ZY{wKT{%-VFi~L4GOg%eLU!q1VAzD9@u@cj&do&U())MIuz(5qp*9> zy}yVyA)Fo*-qZhO{bz;1=K12}YF zGl(IIt8`1DCQ1$67S6?pGAV9N6ti2*(_qMqb2~;6Jx07C)~;Xv;K9c`_yqn8o8|!}pLszhTYNOzEo^P>8Nxi&19I#>8Asr(J*v zGHx{0QNX{Np2iur!eGz^hV#SBP<8%G%`#Qne^=DYRxNK`fd0 zTsh4!ELoS3CLNe9pVu!en^F3Z)l>9-o~vsrsoM(>Ntz@Fpq!z=6vv8I?)Vd zwS*2$Gyeoh`VhP&6HQP9mUTD1NkSNU#sv`whIsUz22WsV?u2-0GJzD|Yli_n@9k9Y zPCEO6P3JYdN~UwrjFlV0PDE2oGI=1+=!zpSo^qxjvi_VE>qVTwtbj398Ud(RWi-p5 zss6dEtp>>N;(i>o3mzH@l`~$mY;Ct~AZWa*q4b{FTJQeI*E6Y6td}EsHy?yO*5kA$ zM?iQp`dC>$XFVCTlhct+8RYN?A%_#ht&VHN)^m+7(cGhJ; z6T29FY?e~f12hAgW0}Jc9VNe~9wWrQ+S?8q3RhBt9*kl*TjFLR*!`dv%_9%#s1mKo zM1TrUnx}yWJX-vpK3Mjc!*g=j*oUOcne`MtAaW%odV%txW2LW|V^&*!#?%hZnEC#w z(w3z(O98CpDjqkji~qkYA*ovf)!vN&K3_KyBpwSdo+%z>>&+=6$UtU|AeZLA#O+zQ z2>Sq^0Jep)0{4lpShY_Mzae5=;uDy&ZG5-q5phB5P#@*v+O$cKCG?dHZ!@Yf2v#TY z1}Bl4GF_~$0LP&URo9fyflS+T`sXb8eSfV6ObIV1@I17yiG+HIM{O_`Ntex1#8;;b z7+idqn&kLL>NmMrm0CPwn~5IWK{EmNC*&KUU&L$RrsWvWM`TEnf41||`IUX-Obz|w z``1}~MTE@VdC&OT5V@RSOA^o(x-;6QQOaF;ip9Joo;dI?V0w?`So&U;)MaIB1cz-V z6;T*IdOln~#DD-Ou9!_OwOh{kOBF1DA90`B0Z7J}!xuI)?*j1qh7nKc*;m-wIogv- z6X&{oDNv`Ee01+T(q-Ltxii~VqA_VBZbhf3#CnT7v?bJhLZW1&wKx(lz$pL*5HNrP z7T>F`vj4@rJmgyqT`1*`jfF#i3dGX1w+Wbr=cdgdvzKJ0^5ClL07sk+X11`6i}rVe zImsNc(!J;;`a_%49C0qpB67{wGU}aOZPnN+35rCwrUsI)8JPrM5|Lv*Gr50};YGd3 zO4GkD0oe~TV@~i>YYKf%;?zUK`b;a?6+fhgOUALG54NTqriQIUy@i$JUc+b;h8wkX z1cHYbmu2obKA)~u?mT@Lj4M)4JAlA%lKj-3SY>ue2E~J8TphFbVV6tUeP+_JCUYge zkM*0jsqOB}_b*jd^u%;k@l@z$ctj$Sko|(p7Pau_u)X2?Q>=*qi_(&+Gf6ol2uaWu z`!D4j3J$r^Y$p*`ZzzSwh;YA%mT+XX7cPa{@oA5S6y;FjQU}q%eTygXKBWR{qLSLt z`Ai_MjI`C4z77>q@S8r3nAf*$$9$9LU}&N@pb+;FwSn^h64)ES0b(Uv<5z^_fTKk= zZ3!q5l-vOiA50bUN-!#;B&2Nde-WVni2 z!GBvwdJVt(^yc|%ZUGEDc=v$}?^sTsb3?M z-d@#BMqyQLL=Qm=E=no@z_^;jheOV+dTrb8@YhNwQA_sR&n6ydXE-%>k3AM89p|{^ z1R?(@5XeVKif&e{ZeP8I^>y!;XjuUgm3$!I3Z0Z-q~PE#0P&_o1Kofg>l zGuesT`n2#jHRBI6_NcI3zFPE6nOE29LR;$2EE=l-4qn!wa9x`8W$^|@mZ$KcH7NAn zt~<+mvDnUF3&7Q-QKP&G-7%%*sTzTTeKq!^0i|opV!E$ALon^hG^H1ZunAT3yL>V5 z__k`Snuz#&3&(z`-SN1^iCRnM#rk_QxV0kJx;Nh1M1L{=>IoqvwM zWzWY54?|PuA`*wQ3)4&y$L|LYh*QT%yHyh|e43wQ4BrDsIHUG#7VkcfzCRoNohnGo z;GEB4Yih|Q;4O{}WiLo3tMqoY`8*h=N6v2#nw+MrMg&?5_fxV(t9E2>R>N z_vasHZKywS>m$W;Q|w4)fVn%sr9@KzoeBIEH2VvXrg^p~3u#)$ z*jTm_lt(WHVn{y75!iib7+~Bm?bOy3;~HNTZSy{ zz2yK8()>F4L<{|9Hx<2Ggcv8muawHmm-yNLY^svXXM#w4PWLlh4Jr3Kr+LEumUTFY z8~X0^l@Sz-K?9tg|@WK`3iP>_(?CKRaL;9uLV72!5k9Bb!|}w1*j?7;05>4B!UjTxv8F>8^f2PR-~cS z{8>AZMo;>zo=kjF`zP8+D>k)POG*-St)%x7$V(b9)bKRoPaaC{i8&CbP%zuK^;*AHZ`oaFvGo6KjCa+9 zWuTSt8#e|`&<_9lfaMvP9E-K z27@g3c%EwC?onX5)HW)s+@=~n51BsrDN42lji5R9+EGI3-=yt_4SN&H*z@xy=Z-7bsI(bO{wspi#tXBUnsf%-&l zFSQd~LwaF=*G6pntKUaC!iMX&2A{bPUrDXwllaeVP+_H?j0u7{uGa3_P3g8U=_Tcw z-~w)ysZ+Igv=9vB=XQ$r8KAhH9j+jtOak!KmhEu*HK|b7U!T-P2M4iO4U4Y`uc^hWxV& zdT2ymfHY(-jB@tukEqm~#wq%;vWp9L>EnCuRqo)V&bQio&j4At|M{sx#<&>0L*3>{ z3n42J&~0#Idzlu}8=u=V=f*f9UwE?2ZkbAAu_hF#><7=n0C7Y9!v^0Ybs9@584@Gz z@1SZse%~6_AOKe=XjGP4*nXjX$V(kVXL(I%RNn?~y2x`vjxDbC0xS(l7zz=!RytJ4 z5{qqzzf!DBa4%8`A8(9O9h{N7dch!W2xp+b!U7BGG1NC3zbKPq-s||BZ$l)EI*h`@ zqMPjpCkW7|9Ot~neWBnX8I%M!kq+_;OMcN5YUTw|v0yZfETe;Jqc2vcP=IWip^usc zEX7w+vGz%~j;FUJzIeqEX&|pjB0#nV#1JLvFbbqzeWy|vd~p#3xPbj7PF)0++p~a?g9V7`&2goZx2~FC+Kjr@U!|rP&qD4(b(uKORNJ5W=l~;Y z4PlQpFSnO$0KYNPx--oUr8BJ$ zA?10D;x=}hUgn3(A)V*QqYR`%_W8Ay)!=3+lw%1%93x?N=!zU8TnWb~&__zdSg@z+ zCc0|$$Qm0e?|G_+ajrr`v{tE>Jxc4x_}p%ekEe zursxW+XC{@QwJ{^Azd;qD;vfV*l{!zUbAhZqtRSa0PdYc=07w?+rQMA7Y0O0D;h#U z!lK=7sC&D3xr+-{2az7b!fuxZ8RrDOw)d%firgMCbZ#m!QLDolu|Yo{Ly#M?|3Ogl zb8Hio$MtFI4d4%_dd~=d!W`yvK;SR_7X!g?lK0>JQJCKd(u;kGH0UGXR}ZSgqN31G zR|aG88l*7JvkBdV3TyWWyw)r9-@1?gGE9;+iZ5H1)3=$ZJ~$VtQ_vp1zkj14zwz6$ ze<##sh?z#Ytk;ZP)*`-tO@u@3fs%ELys9hG8yj^TsF&+8=oihyTjA^2OvB4cD}(f> z6$PM-{fpAsG&<(xdrDfs99vnUHKj5}6RR{vUTtXY==U=dtgy5c8Bd0}h-Do2j}*ls z96q|Ice_Jn)DdVGbha%Cr=i2==0bXc>aA+nCU42qG6oZ&#>?T5XaVy*K%A@Bxz)^N zd<(GPfS-CmG?*YDh~M!U+V@)wzMgD&)-18dC*Vt5PUZ?N##moJ-qHX4%*uHDlTr2e zr)(!^_}`Ebs}gt|v8Ffe?N7p7AhQbHX@l^J%|r6)jeAMOnY2$JXmxB>5cfVZ;k@9ojf2@}908ygNx3%EyQ(qe$KjRRR zz~eGI`!D>+=eYVYEd7=x6^V@Qvls?in)RBpM4Ej7QH3ln$&#s8M<`U1Pch8`z4~9M z2}!*7rum;f)FJSZ|Nl-vRovM*dy0*$@B}wtUs__v7hSC)+qOdGZiSl$xrzX)$JCB$ zj-XQdzxN^$t(G$W*qq+T@)sX>icWZ`LoQ`&>CKoI3W?i82CgB06vh4}n36a>{baJ1 zRcV_Nm~7K80Ojy#hM?Pc`Zgj@m6lqir<=F|~{|~w^qK;O~T3dB0 z!`5203p!wR%v7i?JRon&Y6t%LTLAn=6%HcBc{d!~U(Q4=PtpVU8D;F*=y3o)^_wfV zF_{bszSn!E_L1y%5Tpy!214GwF=j7CKvBZH<&Sl;$&S~nzAiE5HyG5;K9q`jD>b+NGy9T`qy~Ud&xEwQt8Vi6 zvk?-%&9Tts0k+T7-!>PjT!(oE4D+Qq~E0+wUxQ$oaFR)S4j-O}E296I6pX~#J z$_@SOTacgVV>J7Zw~cfBe_G-Q&QS#~D&5!ofZZ){cc6gT-ztmI&(D|gU~UJiMtcsT ztu#+$*cFJlOTBqjgspG9$LK$@;k~eS!e|cpRBLfLcAlS(!*M%wy6aILu=j2d@0Et}65FI|Cz}yCSR({C|&6s`PFPtL3$2+0E!t5QNmZC+LWsux1Ur;}P}W zZ(QLT<286IJW+mMFFoQ*V%!(ShoD83S-HP1+cIVBCwc`O?B3=C30kQBTkCPpDJ3m|iCizAC-_-?`Qs0PPovS`yUy>A|Jie@E zzeeq4_j5AI#FCGO8I|^czSJ#!hc>9naRC1AjiH#nHa9OHW*1E^VlTFxo*R9k-ikX7 z{>U}NNk*7wrSd7-QaZV5z|`OhRW5!7O_Sn+MVgb+e(q?WK_4hOzR50~qrtZjmdrU_ z1?lK8xqT3ze6rEJQm?sK!k;eAgmbE|s;MbocsOhjlsjuI|{!U|N zNnlGFm31~8-x{qU|Duhj4wLe~*3>qD9q6c&19i(B@{0~N^;2D6#yS=*)#(#d^~?*! zXS3g^t?HVDk9?;pcpBt+g)_Sd(8+?&>pT}MdLpF>I6NhT>VAr>?DU9tkVx>We$Lg% zw(rKBt`00z0g3G!??cV}GHu_)tL7xy_BiT$NtGR6fh!vb=d)PVIy$0p;ZhXl@RtN& zz}>mz7b1|RLwv9k63lTt7{m8gN;E_xw7`bR@R8UScd+ExO=E8SUBvopVaqLH5NgBygp)}^2ckBg zGKLdwUP4LOSOh0CKMvKn4pi$8GPK5FBjazB?S6t^!$kI*~Gnh0u-c@`C1{wW(OKqV>%rKqJz(lACg>L4oC#~QAP-LxuRPQU!J zYN*&((5J^PmA<~g+o(|DCA3JkqPfXQ zM05cj>B?!{*b4bMNbfxe;SZV`<7t`m7{m#(3i+-!NM_NxxP~y#%8dEChOH+Lwhi>& zv>4$2HH9m!5U@G|u}Ry7f5}1^?G;)*h}jYo zCxeH)mK3~8si$?-@pwF{agb#!eG#;aqsY&?b4c3JC)YJ`iM|@C%O{!iiRy=0PPu?@ z)s&{4*1~LEn|q&*ZL#tj;)4=JC$wx9HX*=o6(K-2G=MJ&b;yFg$S!uD{^^=DKMfd5LOAo>rbeYoI z2R5tH$VwqI>;JL+US`imlXB1{QLT*OJYqA3?|-n)XR@R; z;m;9pFz+ADvAQ{vWO%2Wo;pSugXfnl%b9W`eKJ{0796{zmSQ?71oSy~#%Hddz@UFl z%=?9!%fJDQ9(-!8Wcy^|?A^o-OSzL#q}DZ5JaA=Q`z(K;mm*x{C(m9pRxPUDPyq&} zc_Bo`^k7TOH+UW@zxN2Gzz{fF+j8ou)C!kZZ;_o&Yn)Lzn1{ z7H<~gpfg2~Phz_wO#Za)K3>_t&@`SLY3u{L?MPV!U)=AXN($%TK_kZI259UC2mugM zyyQloTUp~H?D7R&5hWD%#6?7DDqGTwHMdXeUyhWu^pArRaMKU1^<|J_wfdLc=sN#f z9vlAq`9^2APGbR{;Ncp~?N&s`nl`IV+G`ub96=Nr1qjCThhIr6fu!y1o%RvKgZEwG z4c8tSUYAE=yAbT~1SP(|w!LkjT!#C4u*Owu0=5dm8ZsfNv5=by-jN>|X0WQD zv5c>^632FjD`lm>Qpe}4CtO}&7SdwgWy)=l;K~$e8zC|67ihUgY$T!+mHo*-Xi*|9 z_mw=qhUy*5@#;)7eF&T|p{;Mhwk=wuCa4V99`03E$#p}nO9$n4x>0C%9YYLo-ys-Je?)hC+Dd#J`saksmlHaJ=`0ha;YSl5-RB7}hAm$a_QwyH z3gZ~VhyF-I9wop!>19U-bC4Sq?->XK>_UrrC7vBFn~{RSr=Xv^W!0&H#;Eq(-C6Tc z@f`{fg;V5gpj-)vkCLvn4JJO;6l;@#_-cUh?ZKUvYoS@QLpKj6>z#QZQ2Kbv9dYkn zsh=EiEtZGXT3UvzRH}1WHH?ESty@x%%TSU9uaa(c8bfGe<(8uHG=jlLC70O z0&R9dDW*U`y_jx9x+P}{g$QknHw)ly)Br0eu&2dCBG?7s^9j7oZoYOc>p=YbWwW1y ze-PP#R%a;t1k0z7&67KMb*%NH!M=?|V8kjEeSM?C$^Z?qf{xOY{bybS}R`!_ymf!Xal zUKm>XU}S++qrlxW@Temp^ie)MXldq4Qp@!Ez4`ozs!>8@v~QuvGE1jByZr9GPs*@~ zd?3(weK#l5AXro*ILIm`reb>n=uLtg2}ijC_@eZ)mz;gQdibSFavYX%*OMzOfyG4p zxqjh*=A44Ewkiz4wCn9;u7cX_Zpn?WYuh-i6tX1EyGHxpRs_7d2x-a9u3P_92GX^R ziB+du-BfdwMzEBQhu}UdW`~Z($_!Iyc#>nRmJrNuZx z84EgxVTRSO4|f+1Ei)Phs#R8Mc?WSX{;cH&e8@Bc=_@YhQpJRJq?$X5D%FWe00}R@ zZ^V2m!&cUpZAffp6@}*vBcFk=8Mr1ze$$E^yn(k38>t;nD9$9gJq$x1`Q`|Ctf7hn zHuZ6^N%_&vO3PS;g?p@cg&YO93e2t5?751@+-m+^SD~k9RlwO%Te#=iksv)U`AflB z-EP!P(8AL5a0j$y=;8|v9Bhi!5cr`vTS$nq$g4lwCsb5?f8`vr9@79i2qPmwAB@3c|F}=uP*F7|}u8sZo-(6c<_$$FAmE) z+Bs)}nc|>Q?U^b*d1WJhB1N=LDqZ*d4O#877P0AP)NWktp@>@=ZE`Y_Tsrk)xm9|r^ zoW;cA6>!*g6Bn9z%Led@lOw^+<^d@`uuxH0JV7c#H8H+4zNYu8TywggWoYPuUz8=8 z+bZ-5p$~~&-@@;DyI?IeCOyj-Rd|anKlkUPv;J~;ANXbX{7W-^Ct+r?_gtyt;jxF9m6VY{VNc!V8U*MKf?Y9Y?X$fvsyl3CU_|g&YqY~!0 zc<)k822jM~zwd5J(!Lip>VA&+Be8WuVuQz!M{ z_TJF2`P>i4Y>(0 zI7(5TMLD{r9j-3J+<-)1Cvq$xTtONFQvNH0W=`X_4Wo%y*0<-^(!2E0J+`8LWr7X5 z)#&fSgkB;Mdu~vDMCW6S2FpH;o}Hd=b(F`huoRa z&`S;mu+R>_x(YLQ^Mb;8GVCNy;!hpLd*rf$scHUCpuqoROwGMS*{DJnymb!b05XwK z=-;&qQKL^oOBGNBRLYP{;xLAUkmgKs`3n(Bor{A2I;&{1n0}mRodhc)hEiS%IRhVm z14`}7R7c?eY*e8M!%_n6##w`+`ZC|_WSI?}Yr1+6_=lMwkf13wR=Upz>Mat(=|f`m zHfE6=Oce^m&`K(d*ylPp;XcR^f5gLLBvB@r3zYeCE}TR!V0@KEY&6&sQ~Z?vCrlBh~SJS@B%v;*&7tX-X?>c zSf87609)%d6ukHA7FsJpwnAffJgoPYi?eOA#0j6L350If5tJENhDfJPzS8dFZb&2d z&6Va5QItLvZoDP!jYQ0PI7N}<-3f>X(;1@VG3MPcg9Wn!D^!ZN?(`e%KiQ?}M8^CE z05%?qKa_Q+_XDJbRA8}}TWhw=fw#GM-_^Z1pVAAdrkUo#@1l1;SznJk@s+~S4>&@W zakJl4+Zd#CEQh4nxC98Q3kp1!JC7|1G2Ci~SW0rcQ#ix=Tiwx}nt9X(8?K7>Veh+y zlu8BK5NJ~%THg>yT2}DsSQD_(j2KM$exM>dUQU|%1P~;AGaDR`G^~&ConZof3&Y6pnlbwS-RQG{Q126loEUx?N@qyOi>Tz8S)RZ* zHJDr?K2i>i{R=`rQx4vvE0@!TFna@~&wqUWD&1%ZxjUYy0_KeedX5QyM#q0!BV?_ddPl zOt=B7U90^Zj3q%mMmrl1UM_Ogxg^k75wPO7Pum5vX#K%a916 z*8uUM|>OjJ)geAOMz z#^3**HKK#AhycVSQuE^}YZV@AYBO2%++?BT)&RED`I*ayC&~@+0C1-X}j4Yksa_6y#6o$ukaf+Np6Sg0(~ zW~AT<$|aOO9d|T@)N}6T!5V*2&6~=FmDM`g3x%T6+T77W<5`asTg;q6Jkev+KxW2a zL!!OxB;HP2q1^0CRKTyEi{{eQ68^D^tiVA9s%|48-@HVV$arTdSqyd|1LN?%Eh-+^ zs3aS}vEIeRixlbLShjXv>tDHGRbkireUZfL#AR!pg$dL+u)MxTsz+MR6-4atyZg79 z@)n=b{8QT+I0tG9bTgm=jt|Vi!9iY!HiAs|?*ZG*r6u}#?8V*|`OwF?mAPCa5R_|Me zSxI5?Kk5Z@SdQ{uz%XsQu{{x5X(=kot2LitAq0VoCY%-G{1gQNh_20W1fsJ&3qad$ zYFm8#2L?mjs=2hAd)mPQ0(e(LGuX-(1$N1~yB<*Z)bHii)T)^M`(VEb1xs3r;foK+ zzE{K8z(pBp@sYU}=4z*Hj_^%AlEVfE!pP9AI{cROyn%&@X-QWOvrw^_!mrN?C%1m+ zE#&NyHlc(@Ug-cTzKFLb`oOR7L~jG0WNl`lbihR^%w9#fX{0-{hb7YI8b{IqDLLY$ zO>}%IO^mA~`H=vH9UiSD`0JI@=--$X*hI?|A=9mGESrXXRe~?R$@2GLXl@Rn=M^uG}cFj3nO&u;N5fVqMgVyOCqax03?>F`Eqdw>wd9n>~8TlB$pccRA zp>zieNT1Ze1dz#e$YuxsKAt-i6sAO*VBQT%8<)!PZl)BzA0(Zf8F&{07hPc+pSPqL zeTznD)g&dO_maL{JKXkQgpD81F?6ED&<;V%ov6NwKX4>Hz~b!bb=j?oESuI76dQmN z_6bP2?kFaoRY~Pqx2zyH!0&>oRQT980fDbNK?S|97}$NPXTHBV6IT+_scg3`0Wa5( z;_0p#5GIPm%DehOu!y_!lW!)}?jhGAmH@xd8>PCPSekdpSr!8Hcdm%8_ETF#8+^Ud zVWjw1-e|iPMxyOoILY1Ll7`{^_IM;t(HdVEc}0dr<~uA?$_PQR$b3~h8|aE|<*WM` z??at1iDW-Y?8QXiv+I9D{)Fw*seWk19Ooe4*p2Jm<`fkX64I8eZkWnhu|R)bzd0OI z^e@?+4F(<94s@~+EU{2rh(7*REkJ3i0=A=4DQ`hk1^LNcRx0Ddl}0w^ZJ1sP=pmCB zn3o>ffNX@ee6r3*Im+Ss7jace%>o;oWc-#QLlO2D?-KpLuv&FQ3rDeb$?8*mnuFi0 z>L;$RONXml0o}H0+N8lJa!v`VGICczSB=nEJMpplhM5+*tKCw7&YQ!GFb=4bZvg2*T@(-=Pf*rDzuiLkXjD5?1laI3=k7A=>meM zfxW_I9hF>e-!CIhb<;G}3dV9V2A9o$-&PBChYkuC^VxdY-_y2issOD$x!GU#_`_=C zwe;(vKYY4bX<{WMIbJ?TKuL)~%~i@`dNsB9tUc)f%j#v}xp?ooBW<_bMaKqau)yML z+dIvUy|ePiB#Sa-P?P)!Kq5N6uTRnc*3s81kVK!?`hxFwst~CZ)3GNxnBXF~n$FJa zfkeU<^zYfNyM&Z~EE^&DZU9eY?dA-niAtCk1c!vmt?%LjRj*PCKl`92cQ&ibtEOtn z$eyfbih#JhFI0Z(+C5WhO7ZP`&1eEDVBnY^yZ3A^&VTw?WjoxKXhZ}fc5Q5{cE#XE zq2B0*FaSS2U)pt_vFzh2cbimYneVC`YYLwi;~F=0$3#k}7@$nOC~dAG zfaK?uSlGuPGVWw$d6l(i=H=WG>&SKg1DK?Y<;VkU_;YXgANa||F2v}iA^G??Hbhtx zdu%iRvs*XQ5KDf#7^Yf3Lzd^Sd$`%Hr9fYpRw6GSnXtMDEhpCl04JO4&j_oWg$x?; z4#g6;N}-!+mQTAvLL3?@xa`UiByn1mY3raHh}q+_25MLjZ$XAP(tONO#}E8u2~~@0RM~f8 zo@l?gW#6}9`@#$UV~h>f!tDmUmz)rj?3Ze$3gUXCk}>(0^}MqyK=>mfM!?cy?+ZKL zRdA-#@a~|6*LPuGy383yER<_45mR$xb66XuUQeuanMr*1FAVAYA@k0OJ z#Q20z0lSn4Ds(yhNd@BgpO~eFZn{}ecm~Ebd~*{()_{Hxl&eqEv}nfESY|5*lAYO) z=l!wr1A+CaJN5J^&HO(Uf`st=W*Q7C516oREiT&QClu;Y&h(#m3rw$6dfnjbITFkd zkFl9UnTz{{obhx`8Ja#Ww-n(tZJEad&MlH9`kFz72T}W0&o0Y*{If2aVfc==s|e?l zBK>FEeWFP4Ip5X{z_qMd>ts%wUe-P_=%nqifHe zM5P{gNxq*oY)uKVK8Tkq&5@L1)SFKIXzAsl<+`Ks4r(`>?zZAKy}N6ePkX}_V2@Jb z`vp7zh5V`*;J$z!Ay1y0kFRGy^gu38*FC2%;b68a2VEgCpf8OIf%e_(EF@LuH~hNz`TsxFyo0HxA633iZJ0vz8&^jf zUJT!pi4lxo>=P;x`zdF_Vlg0#GUTuiIHT2an37`Zfg*BOz$@3Bw*LlK7camWA;x{g zuh=&eob```JoFPpk2&S>)Ab%OpFhEULBmiT z`NM^5E(5+)SW%}WG5-#5b$`B{)}1r)(@_v17)sTA9+MY`?`E|;DR&t>H2+~O4Km_Z z8h6|=)^M|mZFvJwYl|;KD(o*X$r;3>k@)^Qh~1{zUmq|973>DKwj zE>Sh5Fm}pv81HN!vDDtiEW%O?Fv{bv{dfwZ*};Cn9}7CuMLP1xUmh&i<1~Mm7uC-G zZJd`a^=0*UH7pp*oiROpm;)c@^aQ)beN40(3m}H4DGBZR^HV?AJj6T&G((7$Yn2$( z52%Ag+hC*kW~6s=8AK<8-OnZ$F}@TOUHPV{1RT@|vkQ=_^L|D^Fqn}zElOP+VwD_@ z7F6s}A4H_lX#4fN_yJU^`&H9Tsd80;I0&G}_5AnLMGUJMHm)0G9#-3zeCcAr+SG-s z9V(yNZ#PsftbZTuaFpYBFeMgr*Rjo6Nk&og z)0Hevx@C5v2e50rL%?Jh8ci*4C958UBsRZJKukDJae^*+p}GIMwXbvb|H_nMIHVTz zFEb}i;5wmP^C5xp3_25y(GjOev4UkVxTXca$JQh>;Hffx#NZRtNYBo@`YRGi1nGtv zqm@WGX3H}5nD5>r^?O=3pWAxhw%sxXd6PL+MS!^Fs3?3&r2+s)cYvp;Qjjo58Glt*C#N#H^ZC!Z7a35t1u(ZZtG z%im#@7sW6PxEkv^0-MasTVZR~Z%PxeZdcqA`6?V9W=NhTk^+YmVJGu|u%tQr z;@crpM~nM<+!wGGC5bOjTSCkrLVT--`rv8#J0ukX#ZR**idG;1meLZK%{crFk2??$ z!NaPe2`rF-t#{ch9Eq>XbumOA&rpvK@6>2JVUM5b>Fxj`X-xtXt4%&mm@1;QTW72% zptAQ===Czce3@+#w(Zs;e3NyYA&*$I%$vWI*yz<1i?{9~Cz0AtC4{#iPp z)XCc9SA1<&2TmDiwPpqR0wM2t>8^NBDt(|;nrQN# z`)F3ci35IW=4+&YDqcekO~cgAkMTv9N9L`FhJ5^=wUdCA5!>0&uN0CS9&OuEL!fI+ z35k{F8Gl7{)-63AlYBJ&mxLbMe&^&?UeMUID&m3kEizv>`F$4SGpEHwr;e1WV7U(~!eY&L>F z>p>=1J|_RTm+G*X~{lxojiS?1Iy2u``Q{F5Y{@qNYbY(~E6=7iH(XsADV5Re(`RsIAc+ z-!_opq>&v?Kh|90!{L9 zfxRVuVEUPdrhCb-xW;J94Y2jWUw;^sK9%QhV z&-{>Vbt3oUD5R)ejPkXeCI{cAbE61gdvE^6;&mmPS-0H8Bln$l-x{f58Uk*y3D?i+ zbZt^e&x9|LUA@@?Lm!$ZqeW>ueL~yq5MdgB4~Y+!-#A2?0Aoyy*L_a5DRTpE%-31i z=<9A1(7GLDn1I2i!j=?Lq{?<8u3y>xOzmWYiIERqmF?dP9;N?Je}naO{OyDQijzjk z`&ug5|42;LN4XTRSvOfK7!Q^f?hZ{;8>XZvw5n?%eTeLx(UkC%zzqC~b*0K&LD||m zupm)7fPsX8GYf>hMHiCS3={0xom(lt@nji-W$$HEwROS-X)-#T?@e5Kd*g@jekva zI$$a|bytZimynWL{-$H-mbeA^2N1I7eXC2?`8fUS2*_G)B3Y3lS!VNk>c^nuhI>YW z`vxt`L6w0SLO&`}Q0`L^)vScN{p{X9_T&DLUI05l#J^ci$$;v*&HqCgj4yRxUUOMv z5?^FmUiU30zNV?E=ey@HV~dGP1TAEmyCCmE&2=jUGx0j?xnw*a71iwjEcjo_zgtQd zvpkQqw2TlBWxKH@U=ux&#XiNz(7qgkcGZhUTbP3hZNFs6BSyN!O1>&@JYLBl>XiNq z8r>ZQO=00|`4Bg95fuz5%f_MBvlj^?iM>)I+&KKIB$yLmwPF24`8=1f$gAcud!h=% zBC#w-AT@d7R>jj#(?IW34jfBZYwTTV6NhbCDXetBEVS_kd%A>`+2w^vze2csd*wWq z8vnC!N@RA&o^_Y34I^_4_l$-s>yD2z6Cd|h^>~5Gob>FExG={@kAdx;M@O;ZB zm?NvUPh?3ZMN{ zU4&LKn;yo22INo{Z4}K9Y2D)bG1m%na#4_{=RVAdm#xkPC+T9rsgF0`O3{J-=VOCl z)TIp<-kzj**z4WY+UjSK8xOFE%;G?h{pEa%ps>JuW=bIoSpH0e(1n)wyn#pXD3u#t z{Z+rz^88QzMaOHra+Du7``-My{xwB|l*hh4o%HGm8Z2o?&#mOX;ph^nepb&r#vP=Q z?}%27R_HJ#A$L)8)T$$fA@@%5xvSATqqQCCqKu9X)~xobhQKEbBFHoE6)|!}2t)n@ zvbW1Zm*;P|{1nobVDDu7>nudMZc1tZ{};6m{Gc$Z$pF5l(sx1|i31eaadmx*`gWX> z8+E|D%X^1w6;bw3;qqz1BhcXm^d}IX`XM$?-w3cV1>Io^9o+4jVe7#i`<|9!0XJlD zPQrZAlol@}2bcw&-{sbjuO>6{q(e7`?6N4iNCa;=Rj&Om!62YL4>|nV9l1muTI{68A~Nsi`GQPqgC-vto}_C4b{x(bDKHy0N`v5$yQ0DD5pm zy5|hR0Lxz!D}v{`HtaA8!EtYkry7)=x`_*n(>FRR8t1<0^y!~qYNjQeZ4CxHSk7|uWwc~ zoS=p$=4pp_66lm>ry}65YP%aLcck3Y6B^>g$sdDqZZox>-`BvM`|gsX>f# zJTDzjRf_)c`Q6@ce8~VGyR~i3pD?7Ny~Irp2InZyW52#7bJ3!O(P} zL>ST0cq@9cX+>g08LYxlgV)0TqB&mPVgCD^2$TI~jnk@wlr`(?R$Ukv`n$2WT(L)u zhYL17W@s%)u%=Ewu?*b(Trj^Z#ZVVrt2D}M`)k{A{J0Fq(OOzL=ZgYYvqkmf#1cIH zR+NYFtWJRZAP*Qi6T$c&{~0iX*9?R#e%`Xr3GsDosPj-kTD)bqUk|_~RS$W#cGzoU zR@VVRnj${ds{o;$NfSdFN3b`0YscuBTNK7{P{-nCTOO8^T=p_%bdCTKh&w+z%)3)N zgU^ZArbI{Dzrnm@`~Vzx3*@;buZBbD;WtzYrZAf>B62wtFxt*}U=5$dpL$Q!LgAT= zcqTKbzXe~S1junB1b|T*uFj=RN?Bz00LXe1=G8~k!J)Ewbd>KI(g(oF(hhd%1%%(O zE3G1mzxdPmAV!$<^kibwTe&%(2`vZ&O-M+K?E(XLF!p_VO~vZBCP2oCs+Fak{@v1c zWuLX^2zr(lP~?lJm*OBhzHI^zUY}ge%Ux`jENLK!ls|2WYwHZP;pG=;5crk`MSg2OEw?G?&dM7U8ms=Oy_l;HG>>UyijQ|XL{`BnUIh5;u`N<1R~Hw zFo_k^4=CQ)uxI^IOikgEE5!t7%It=ZDgK#99b-(n0zos(C4FLk8KS-S{+`%0c>b~_oV}6{$}RM?Bd_LyaY7c$ne7a*KQ8(cnePW z0VE%7cpelB9YJPY)@ls?td(-=U1YnmFw>l#bBr}e3`Y-_id5G3s3cX9Z!}2!G`Mke zLlR)QpW_+)*f~?Cy0`cKu&8yqac4fcX6AqxlbJEr5*d+~y^RK3juCMJMvB5>JJU*8 zA5s=6?(be;kV|{<=_%CW=14L0kgTAneq8d(aaxD?RfA3p_*-Vnv5I_jckCJ&h<1Tu zGiv9Fc!DY#q-0Nqn8VK`prvZhKnw}YJx5|gqtm>ix2UeW>>8(zetqtS+d@%<`6`}_ z#c{)Bwp~!|i0yaPJ4M&#k))I6o^q!tj%`<$6agbk+6cY!d_{Fq<|1Rn zZfHmJUzuV>>bAtXS8(E!|LI_RVDqayl=8I+J&Yn2s;P){gIMtS!#53>agJy*Csr#H z)Qj(|re>*iTmvg>&S*oDCgIRhR6;X5Agg)mT#S?p$_ATsl^V^KBUXX2olaNc!)@E| zKJnFP+R_0@vOT931rQhnM==y@^DrR314N$!D}JdsFwKir7qhdOkS$@7a&w}cpXb*z z2I@`azWoO)ll%`}<0D?2Ip}|UOxEV7SDWGxQV)N-^{73p8di{H@%i;k+moG}sm$ z*EsftI1t8s+&rh@q%x?dNIu9FKF9_XMpXJk{hiDpVk`jFk4$JM)?*e`O|VMd)VdhA z!vIDSUv2fcLhk0g(DmZwR1~4gyF;Se)P>^7T7k)bc$4NZ_X$=O8UK8Y*+NOTTIk1j z*(pCivnen*433hkF*a#In=vMbA^yYFfsk(7c{S>kwzThdd&gesZEQQupn-+CS{lBL zNBnB1PARPtC_mVb`y}sM0<&t66bZZk=D`cd69nx15p=N|pd5v0bG0>^sdfA?ivtNc zY5vAV7CyE2X9>Iyw;>t3${%Udp6@h@JtW;<+dM*<=G7L$%*!$n?cV@xCsVDYm;TvV zJnLN35ONm;MGu+;Jg>CnLSI0Po+)I;qKKzq#WI@kWBYuBnI~mOxW8FND=b|RHALY8 zRoq`g+a*5D$c(9V?6)rX&+}_7z~6s){|H~>Qxxsr0X7!vvNOZ6o&(>g?4WWcIEz;R zJJjE#a$s?c!%-HNVjW6Cf*&L0g7?Rb{CSm&cWJ8u=R#G?iR{znu(tiMs_;BvjrPZL$w^TtGe_!`OSd#rk3sB?}(FaaD?B=|K>UrH5 z4Bg-ONcvi#yT0&yME+s$jvveXa2k2sjgVuPs) z{_l|YTsrRj6c2Hy+^+K`Ff+0xM;=KD5nv&*13rH13yEK7Fix`CBXk6gkuFR}ea%Ry zwj?{tWvnlRZxJJQU0i82ubRczr!^pDKxQYXri68liCB(Y6-!6x(wACna>1aZ0{ zHLXK&kn4yEcp#fl<>$BaG`VH^k-0tvDCOXFpdNW&c|j!W8G(W^Mm{_!@Tb4Cyv80exRo4 z$sfAi5p=R_P>8y)Xz6n%J2>Awd+@+B+CmT0GyyElLmz)b z@NAVx7Nyy$iRU`{7MUY%!13*W{-a4@KEMQ}M6@gN_r> zCKj?LBFrEh*@NB)xr$L?x1XcM@z8eXfA#FPn`xR~4jP1PYEhY212@vzd(m)#aq`QD zUt5Dbkb9Ddj1W!i5+Wh5&=|W)?A$Xp65p^v^yA^Q5e<%G$a0j&o{5JmI@qjm#aTBp+?PX37IFzEn3W{Ark!7U z2t~=0a*r=jV<~#hHt9A#BaV`RHtBulEG=r3*`{yU zpqEU{4?89-*n#JnTB0*ijz+%tP;^BT4sY)(Y}QeNKmoy$keA{?kLGnES=o(N>XtEg zdx!<2*n7d8a^nx*O$U8E1?gLK&K0Ahr6eTZ#t?X9*~OZcfJ1!Q>1HRMoFb}5GBGd; zvUO>%XH`e0IDNiWm1aoQ>dLT(*_9@lsOn1)4LHfx#uu>@;o9po3H+u~A2#?Qxkv0L zEXEx1)~xwkl+FK0pLYaFV;lTmj*~Gb45rDY!Yi*?QWohra!Tk&Hs3Ll2n9s##{I&B z+JmA}-Kv8hJSJ@MKnoa`_gse%?rTy}J@~%uLdzt!pd)Kw;kpKudUqxY1C6mu6L(>k zkVZ|1MYIFu%}C@)IrhyUVY;5WQh~b;xhHHS%ae_dk%eb!Vv)|OD&M6^?yBwS3Z?$= zWyg%lMbYu0E~5x}?3B}Nrm8Li#Lt=4cg~S%o_T2S;x8D<`b;cAEqwY(ZvrVj16{ac z+z8CzlD-A$+m52@EwEj9Xm9kL;J}Ou`K%&;8=;+^Z8K`nH=j=AcyLMD1CDKttFz z1%aFi;MivD=?igHqzI4wHKSNnqd1Zath|`Zim{I49c4d8mq7|cJl=2^|MlrDsF$b* zO$=7OI>E1IUMvXq{R{7&2kCw*`m%5}PkC=XDj+Cj`J^3B6q0%AT_W6I-@RjAW5#A8 zGGv|l|56lf8ds63IGr-qc>Z56{Jl$JL-JnNX{LEa_ewW(ktuF9_WNXXH1`(5l!L`f z@_C?a!6JLOOT&dT%AyX^ z?za+DeXLO$fC`+QXwzev!5Eob4+-#^BFq0y9mXPvp^ZJnZ#D{!!0R#a#c472!|YNum`KiN>U zrwOBOp|V2_Bx=tVAMVz?RtUNF<#Uoz*zH} z1S;t7cqPNz_RzApIBC9|;be-%dMtD-OH1#R6X~e_p;-#O(yuoAW*6&0JM(E7z5Iqy zE!Gg8*gO*dY1dZ^f2Y8wn)EbC3*kX#qtvG}8gNOq^~e8_!2)Pt3wQw6)S6F-EA7hy zb}-s@kVQ26X41=kW^t*5fk#dX)bV3Psd;Ckfd#6|{pjQj&;~y%5C;HAe2uH0dH+hL z0{g6wz!pRKj3AHOHhF zG-3(oi)i7Xdy6f246&c)t+pF%pyMPY0BTk|ypKM}xJg;~TZPGmPG?~MvP`ZJLX}|< zJhQ9dRlS51L6S%P^N30-iE$p;OhH13}L zBL!FIZ~k^Hi=xduXLs))@U8}qqTRU9>s|p38v!M9bCHN|Fp9I*RLH>rYZ}&3#zkgC z*4j#~{y6f5!7c*Po7hSpO_s_Ig8$WnK+5$kg{|)dm9Tq@c4EA@uNRKoGj-=xFTl|M zV^68L6ygy(Lt7T7mx1rp~j<2s&!B?Jau5aDxtUKD7N)Q&UK@bS87*gdMpN4n0s^SoZUH!J^;2hY(?re{i zguV*HpfFj$&*FC$4O~CfM(`dIRj%0_6zT*~LnBFd7^wl4;UWSGU|w&gzt4@cDrE2L#_K*GtsEpi)_Q;*B; zs3FB^%jBJcnm7M~Am+3qK!B0~p!$deU}{cTFxwXGoT zOzU)60$$P1k%yZ9z^AgBEMOxpOyq<3^HdRTx{eM{DWd<&SBdt>0V{(s5dOs`WU~YK zB{ZaJgTQY*Vc~Oin9*9`u>Filo2&EczH-98vcb3q_wkKA{Td|+c{0Ivs?)X$O1m~WIp_%`Y2!z}&`ZQByvD<=j}kpqyf$`CqTtxq zStB?NolGrTdH$BWhEt7JIks*kHd=+z7W#AviB>sZKY=vm7a51>I) zKf@(^-15D!89PyK7f#QYBV^9UqP_VNE6gHMM_HhT4oD?YBWG$#9)Ccsa*6~Vo=0%@uq0PbKuL*U($I18d*1#o^aX*$%^IbxJhl_7w2op##Qv6Mfh&P_UJQ&xF=-O#|xFCY5&r*Ex{EH;8ab7wPSHL2o4({@{F)T~Xm2m16=CdvcprUB$RWu8aA^{6rDp zp)t75Ea*?B;ug+Mo+uU5>=+GRil#ytj}Nqa@5vS8)RE%GCUFnIN*|14;Q-+rYvPy9 zAFSl1Crn)-NQ-smO4)Cp3YCl`a1UI4WMLHc9wpi?BoGrout*QMvX~+`KiQXk~9 zA%CD{+qfHXGBXV%V|jv-MNMv$Upn!_vX!g^%enHVjnCY4yp)tyo#yO+4F*!WeHTxO z(-mINPo^N>ODQRIVFttIGfZgQZKWa%_Ldgtk8xg6FE@PWrdQGblUE^)STZt5CL$G6 zGMSQAqO_fc=l`38$DrQ)i+}Z|HJ90*#L%BkyUU_$gjI*~i`q^^i&u$V(vU(WD@witCZp3b+{)m~$0rqb`lNtg&M=zyJ!2N@F5;l!hE=pQl|Yd`2QdBrM`b zpA?t^;eC#>H|TQ$Zo)2kAT}`Jia<2E4#Mc;)~7Yw`nBDbF%E18WN!PFLf@od)sg#p z{q9xg2gEu&632pb8s>N5)1^xqCnVR}CF0Yj#3k#rcA~r|H+J!XxSmD3%a6YFTN3HG zK;)YOR)koBI!y)s8edCE&XCN;G|f@cDn;}bxdCKKYn9tH%=2+ z?!$FRsAd|%pe%3-)jis>I-jy<-j0Gu zY6#-xTeh!EotWRDYwSqB#6zFWT9QpIf9Sq6OiB$`KnO{`IPA$qdrEd+eDW8{;?Ko~ z5TJyPama2~661Sqha^-Yp@4_8XoBQ#;EORzU-Xg#^e?)9 z+HVvrx39kjP<3CwG7Uu4YuE|$+G-F8`Liu{t)bb#M&MdbhD`DdN2wTO*OPjv*u6lm z<24cJu5_*s32=|`h904WI{V~P7PV-g2(U+j+$$XF12xZNz9sls#5~rsi3FzDIeo1e9W{TvO4=KonyPABNX0VjQysfjAF3_F{Q3Px<> zY75kaKdO0aY}^LpNYC?9Yyd5`nj!OZqg7Ml!o4`pC2Y}-!@rm4J)NI&bBcP88&8Km zbs4);390JzE-dMGI&WJDY`vN*!Egs>*9zI!kd#6|;V?xS^+Of#)1f~!LSMbEbq0FK zk;A(lUxH)H?IhDGD{-vv5ih(z`!|L{@hl0$>?f)2ft8G+7pdPzM-0z>Hwyt!d&|!E zC!qh8`-In$*^-kip&!?8{?$?k|F<}BFX^bg1Y7bSE>*%7wa`{E{o;EoxzmU|)vz!W z92`8WT|)WS9=wSRE)i6}`qyaP#1trje?YVS_dUgfF9VQ$&Ev1Oy zEJjYxZt4QOIYz%Sah>`hixuG6%Y4FtmYsH5?(lp^Y3lX z9%F5v?K(TefotBH#K91@djr&wY;ZL)PIy^gaI_`^#P8K%%oCF%u<48ytXJEBJQ|)X zpbyKiKZp3s`&SzB2-Cma2Jf*c<4?*=8mt6vJ{Evj^LY!GxDRL)G|hvK$Fw8kYVq42 zeJ`pW#blqW81%8mGR0XuVPgr&m|lC%uJ$m(8)S6DCV`V+j2xE6$RTmkZxSzEuG|n^h0(`fg3d-9VIQz4 zAWS8~vYYMy3H=mgnt=_>O@q&VCac#B2tpf6Q?PF1lj9qR@i5my!QV{mK)R;PNR(mC zrrvJuCor(&yZjRnCw`LY6^kjt)6(Z-wF$M>-LUnaStb4FeHhO-8`js78W72)H-ad- zXXELKBYnem4>t!@i@kVRKWlk^6$4UQmzuEzw$ccZoCCGkF_l~ zLLAEjG<YZu-(;gBC;NE%aNR?B;Gwi*c zAR`1$ifcuPafPq-ykOP_s=6=!Dw_?o-gsr!kTtjO{rD3XMY%+26$ff5S0R&%5ve`{&nArDbw6nx+x!eTeJ>#y4mfqm9lkKA^HRzhznpML;jzCo zxA?O;lHm7Z5h1T$BPcSOKA0Q#h}x6~VdDG*sozKg8({Li#$!fd~vV5S-6{uCAkNkrSw zLNeO;iT*i!j6Nhs77r5rwk4#f{B6-{?HXk&7F<+}6{;)X6)gKwMD&Z$gl*hi@dR6_ zZC9=2d?&T0xXM)&ekk&n(RmQ?9-!gZ=b+@|av&VB3ICS3)R7=$3{^~l)RN6QbP_pV zNAC-5;hHr6mv*c@`Qrd^-yM=0gGglbZ-UoX>v^lRie!sQ*q=(v6X8;0!qio_HVFvo z@P3lPJ)|TnzDdEi-XtCpJsyyz|MPp+DrZ9)bNd4lOh0*AVoQ&CLt@&ZfQ37iK<9C0 zzvLC_3-5?*G9h<5)ADk1)pN$VY!)F^LyRnNp+i!;Z!y@KawykG^68Q%cEC$`;*#bd){ z70%;B^M6;)ZDakLZ9%9Vn(rMTxB*dQG1TvPJ}w59cz8184U-#Oh}`jiP~%m)DBg;< zv7_gR(Y6R5TD#WbheSGwR6;CCHYn3Fqx(aIMhFU>0qb3!g<&)w3bn~Ux)Hr9!zK&= z_W{xK4Y@$C&2U z!5^ElSG^_B0nG9cGh#`5v2XR%GQ^WWG(LtaW)hVc@CnlzUL$m}tNcMWGQ-99Irj-X zDtz#NqX8ykq@a#87gpCT1nv0E0fVQCEbb?5Cd@J8-JJ4K(t?orrm=~JMZEARo-6K< z612yeSCwwY^J01jUdqlzXu~elMuYi+-?BxDSe=+Gqf5>z$*X7my}`qaC)5lp#uZI* zd~*m|lDov#Dxr)TDwXx9DG=L&YFH@PutN#-h;+_kQZ-iZG09PPyo?S$d+Y(zKUW~f zeF?;F-_(Z@j@byVo#J8_esFx@yefB;z1HvZAgpwN*fC64Rz9z^m?JlXbVDv?)4+dQ zccXdv(@h}zVv2)!!xJCTgs@dFP<>bzGJYSq^z;C-!$foCIz1kP3kkU8g+w0KBsBzl zhlC$jymXtRthcK>$~w|xkQZ#&_ICWy^SMfsBfPyA$vq{dW7_GEn~Wjz$dM_BiXxNS zWUxGii7_&$`41=P0fIHxiwBiaK$BhCs=^8EU0Awm*Pzva1-4rMjtyfw3n~lLgBoTe z!9m#RKYJ!-jN}4SYh5bKU_V=f1z>C8>4(`8eKij|&rBt&ey1RzC2`e@WAOb09Y=i? zJh|0I$aPY_ro}N^Bi#pUF#2MqHi~UzbXHgl79`iMcX8Dp#4X!-(;8a9rkB9!qB@%V- z!wn1koix{ZToN$x`NogoWOgZ|@2ihE5N}gPJ%S|le`wC#>Lh46QIRT0C`H6=cw*_V z8+A+T>(usQ2yX2jdMb#Ze!LfU*}3%X_yX@zu{pE3){Ijo`+-Js?N_TLPFybo?5UUb z;&5=ZWY5B#A8sb8v!_Or#ZvlG#Clr`h3>g^LZn1?_2i`M=PjH->ThLaxRD5sb3qId zJ`f(#HHT^kdTwvsKK1+khy~}&$qY{&ZyTPnYo%XKX%%Fa(^Cr77W97KZ;7c&lQzgt z9dH~9h5)Gj>uqL|}Xha4xa>8;ZD94efG|Jf$fLGh261r|^jxz1t2jep9W^%PMIE;twdQDfU)N z<7Xs|oklMVf}3?35{zsUeN~^9^sqU`UJsLEcM*n4$t$B^^6jNJfrL0yHJDw!<14fu z%ZZ;G8BxGlv1@tq&vRyeOV|q&g$WxwE!iel>&p+*3jBquhjR&!!8*ZTGP;qSJ9W-U zqZ1cXx8%P%5{{gtDahXmBb^Qc`fjHvb;B2e_i`jn}?UI2O&o0;mH23BG z8lw`i?p{z?ZS!^2_6vb-Cl}Z-C@z102XK&`06?4RM02yD|8lw2u+)*}~W&9iUDMm5JV;ewZIZmLAe z_Stc3>D-@`0H3M7Fai>Wg*qN)KF(?2C;XT!O%DGe3%$yg!|+n!)uLA_=^ayqUM-J_ zxy#A!fRshL_>q0DK2Fs=^&8C0As1*xXJ7&jv^&vz_ILyBCs;Ob0$7Co$hfMQD**jWoWVqtmmeaBo#y%Xk4 zPee>qO=HBtl>~zL?}pYVG73VaLfA8C$aCqjX0#9)K;Y4;LG9r#Zw~+-j5u*35g@5ms0d%0&Y6?YS$K{WC7@)0>+|A>k==o zWMfT?v?@7O)aRrQR?yo8?(=g5M}^Ba;|IT;w57zfP*kIj!&cuM34}ProwqPH!_o=l zSGJgznx!#CZzKGd|B=SWlI-C}qg6KEp!ckv;W}ThhiFkEo{zWs=vxoP7;85xdX{5I zxbkEwsFq@5Om?n}LvC}YZRQj4;S-C7hS|Ta4KV^fnm$#;rV}>(<(=7Nu(YZz!Xf4X z<4W*}-J2Vm-iQZ(Pwyw5;@ZVf|7;QV%XLlcpSi2*m+Q&%)D(df_136v+x?AkV`Vq% zgKA^NaF4Ud*`lgzE#N~)%}MvI(P5?=RjTBCj4 zYX(9FTs`j%3|an}H1YX)uVcncvnIowU7Lf%(!vK>qI+7_79EWn%~zc_BP%feulH4z zONKxRVHp-5u`|ZP%a^fzS;`lcs?RP%-liPPU{a-Z3~zIG}DQtE5?()mV!nn3r5|#VZ&+h zbaUs%!2n+`r7b~~{$4HF>k6<;3V+c0S{C}eD{)8?+h2vgdqF7PQnn}BVg zi<14oVrHHkUh;$faazo0yCkuvR>1n58ft?}+Ze}z+OAY{X!OWNdpBlno@|WN8@ZCH zDJnRmV(0*SIf`WG8GiIKN{3g6iAY6Q2+Iv6WApML?Onmy>~Gv_h2svPhy_M*pnm&C zeGD?_cLRCgpi9?zd^@$t>eGoE^(NxT+dhkcPR#d0L9hj?hm-+mZc^>s0>1Vtc5JKnt@bJgLhsReS~<;daq-V!2Ul6(NAqAFF| zv6$c44UZgUAthUmR_@p}(hT)zGo0X}(DzT>PmkYw6wh~W`@m{zzoaEgdj<*H=y69o zs9wUCVL8Q=O`{5$q7jthBh#>(Kr7y`?7S~_yRYD)R$sByfDQM;-Y6%;Vq52*-M+;t zh-=h?x1o}A5cx3~#}((Klwx(UTKyYmAS#c5)h8o7zCgGp9~Y&NftkXUL8-xyt~P%IrE?dMIL>F9NnuZ%0c^PX%{ ziZ?JC(v*9Ih`)yk`NR=3@nBwHlu7)s?w$I*AiL{agbtBr01udJ<8t z*X2nrF^^e5Q((g-$m{4NQ!!N%PSj>?dqu7W=O<_UN(VjyrHro)%2S|PmlsxZVd3>} z&HwocZpES=-0B}?HIpG2x)r0-Ix&n0m0dR4c-`^n1U!*NKLGNjQGM_)8wz7n)5<^u zFp3IC&#}z;YUh%ucTZGaB}_i$F_Vam=T9$8odJ`b4Rb^%($*QRut%CjA3&x`i!*(Q@l-b-*=S?YA1TD2THPn(WZ6m$OMUuvl<5wsa- z@9pi|p<2L1#rwwhc|XwYrI{zK8{#69Y>tZIeU}y=6EppGrc*u;ruc(G!zn<{ZP;ifYzZHvblmxe9ShUFz=BH)CF@Su zd%{X*M1v@qlc%0Wf@s8lT!o6BL?|e<|KrT>mC^W6?#8B20M=bD6|R?wR~P(j5^{QM4%_>bF#%*n$6ZlN_*@9Hl$w$fRW-w00VS zifg#M6%Uw!nA3Q{wm9m6-G2@b^D!YtG*A1k#PJK%S}w1=Ll@Wb+Hn~Lrb0PW+f3b{ zldAn(x}yZ1ITt7MJ!uAtUe{=q9T%q^yb06slZZ)VO3gA9m%RI{cxyu^V6P#?6p|gB z!K7&rL~0Fz*nW}b#hoo-*W)Cysb*|tT> zo+<{5^w2k&*w0{{|8A}KyeZu}L@{BY1S$Dd?Mfydsm*(Jd)b0)Y90}yy`04Euao5O43EuBT>Qy-UN(JaqT0&Ey#0p zX?HM)`pp!C_Wk-DW`B`BJyx2M?UK{g7QO$LcX;g~YJ0pr(7@!-(}K0>dL_uALk&E` z!uny)+ed z|A>PRPIvFfv%aIajea3@L}-=s-HhzK$q7kqmb!NLMB;#S9z5n;Q{v7bwtAHUC-v(W zh?aEJuHbNl#S(jC;Y>y4RNCZQ915mxzELY0n>+%xai@y~+_Mq^TI%m0pKQD)UX$`6 zD7*r3IX^RCi^DbvV?{P?>`$0<%&gV3$40XTI_>Zxq;JB(b|60NE3`KQZ1`&ijH<;i zPQkr3*HTQFQ6ax~K2@9cwA>hzZB9}&sfv|HIi~Gn4tcERYMPms3(K}My_!1eAqhORsEgq$GZ-!NT#NvNFwb`J31e%r{RaoQb zRJ}8tXOd0O7<_pDzW$@mxgM7EaoN&G{VAgR^O(HSd4;83>>dADbnen4&V#n(6e9ko z(Jjl=nNF^A?CKk5fcSaVr3?OE4R9DNd~UXJ^`x50DVt)S4HTy2ApNE%k>ff6r-iqn5$KA#i_5{lBAL%ZD>ON#AZ?K3Z0PirP) zzrwyP95jd3CG_7SEt2jb$Nt{PO7!;q=M` zCPA+FP=~e)?PO6DVaWLv*4v56DpX41w4W52UDDn^Pkc}pSERPI%796UPImB^Vyd6@ zAiWO0CZrUd$xA#c=vIA~UfxYG>0jxp@7EPIE(Ii?Vyz(lPdosD$*>Ww zqIYS|3I8?DaAF95%IIch*Ws@lX+o(n9(p)Y1v@N4XLUo{dXte^hmJWAG76Pq7;1ub zy&}UBN{|>OJ9!E^*mXIl@tIM{PVyP1d^{s48%2}m9W6%|U*CmE9(sZ%>&N8bp%N#> zfaUsn>Ln6#1^aDqp#zLdU2YK#!0k&@!{r=P>SzFEWT^(%-gTCJcMG(|Lm9fOmF$wY zi2d|jO4V{0s$9b#H*V28(J2kbn}UOE$l}dmqenFXJY=l9f;nZ7;M+2}&^U_%P}%y~ z)ZQ{^%Xjl%n-H_4n$iFOJ?9P>8Dw)7!w_G8EDT(Hs*|j8@E5$oHhRn%uh5(fotY#_ zYx?MS?pK_T5{<3qy|BDfaa6PD)}45FjxC3eP}_Ck^)COqKmsPEFfQNXG2;sgZDrOZ zjzHwa;{$`#BiLC7DO8x%%Y5=0jz=2$70Te1wKeZ_>4n>9dB{F68iG)M4#d2R2tFs6 ze~XZ+Ic5!Yse-nxTTHI;X9LF-P#i?L@cy7 z{np%8@6i&`J4&eDpCb?9M;1*w0#J9~<2E1s&dw0F^lJFN=f82uFV(T;3;d~;i{U)+ zr6T(TpT-Z#NCgp(N8&^DA1gH&UVc2Hh-Kcojtqs$ccfF zKt!@zUG_;Vg8eZ+z29>&hJWV$0t8jf7-F6^1wfDv0=4CUFh*^1L(Iqo{WZRDU9}i6 z2uKs1C?z8IcxK6n8LIyJBv+kiSievB0YuDpB#pIFHes+oV(!JXwtCm$P%e7mdcPq`#A6&4AW6qAP50}GDjU-|(x9JQafnbR zCd@z{nEY|#eoq8{DCAs^y$kTfXs}JxKkP)p82;4I!5AC3q^^U7SFlCOV<5BwPtreo7xGTDCIxbY{qQ_~@1`HxPmHlk z7sUA}CYxh2uqdJn6Bi|Iey8v#p{1h{$gMh5kInhloZ7f?!{hs}%aoy05J@g?lz6Rt z8+|`;q9ip%)LhhFS)wmJXXHJpFq2!rK={0>2h;3`1;C&=joAuOh3!Ig+5&Hkz|Xz~ z_}o=UMSij(B+DujcG#tp=)`;U^wsr}IldPLC@Rsbm?p_RaVnjG_%3k5u=G<_QQG;4 z$*tZhU++-;5!t9X0KnU19ehsV~*7r23 zoX_B1Lw=@hU3j5>FLXE0xgsTgiK+%v(hT_Qzr?8aNuca1hxyTvVctI4w4S=HKwX0D z`azJ-5dHuYE|y(aVTeLQ*PrryUWds*aR)pwLA6+zXw@h|Pz>pN<2ZAwBd{K3*eSoB zoIQ4qb3zW2D3gZK5Vr=I=Z+sbHCEuOXis*W^8YD2I%xaM>i~o^8@$u9j)41)%X(_~ zde{9P@!&iT9t!cl%twJ+Yh`!|K{ZHUwlnz`4qoRL7eqERcQ~$8mRTV51BKQG67htoQE;^pXp3X;+H+ zf9FsZs39KUd}Za#&A^SyGZuT+d?&MmUbKj{+6g|qFy0=BxNCZ)W7nmr{Zb8aF;ROE z$nLJpG5ypha{1_L>t*aVS#r!ziT;|4Znh4tL)=Mp#rNKXn$Q`LgrSB<#HbBa|~xC!+;wVp=Q|4r$(TnNd3dUa!%t#rza`{B$APFaIk1Pnxe>|hH33O(VnL~){Kwo zb4!&o0rAcz1yVN%jJ^bx@gM)cOT-q?!m2RqUMf>3^Tu&q{*Qi{3NM$BZ0r+rLaX=U zI;;Sk0iF412f-qrmVqNB8K2rs%!eBr>Us)3)IvE?t(yL{#-xB9jbG9)+NntZdm5Mz zse(0^rgzYWGoR{8Jr{x(Ig&1jyw`0Kk#l5^3Hk7>S zto=bZd?L%0cznR@=jfii|$)3L;oS$NeU2yL#;k zeqRA}!4S54X^Uc7);3>6SAmK~siWYxhu;?va&EXvn08$2w%={9heJ$o6c&mrlCGZ1 zP)e|?kXV5wD4t~XSN8#K!qQ9^uLiFFKYCv=H+^H+;X= zHg!k^a}vC4>?LMaXu@1P!g4hsM+-HbQz2_D@P7U4&9( zFU9Vdw00j2O0-&&h9wcgTEvM@y%3t0SGYMB2{2&jFPDB+4G!rCrzDhI(5wFmhW9wP zhjkEI!8nwHi8afg^Yjk0a~{Ycg4o258#;6^0_4+WGQN!F*GExoPI{8gD?y?Au)L;=9J)eG|+1?0KFj3SBI%5As(b>A0H_vBdAlq|-oP=f!sk7H*E! zn$sKfh&f^nEe;j*@Fz~W^k#;}tERI_V9qq>ghJX~U=6V;f#d36QuQV9TNUU3G;XH5 z-N{^pAY}OGjO)G9DgK3km2sI+-;wVpEs(#zuIV@y?SED0|#VGlRdkqAwW~o zGaF!{VUW2>;>;X##cp>cp!#Jz{J=uJqGR9OKC+e|huQYnV!WJU57=(|4pgh5W_z{3?dCu; zA{l1$=wx(0nmxX4CYY&*SMCsr+YcP6>Up(=$kjGOnUAWSru4(O|W9DDl{-pP)YKTeI5Yt21c6)zRy+K{$<5QU(V(z zIMD^ik&Lu~#WWtYr6$Fy+JCK%g&~NqZWs0If>Q%Y&uoJ99FSSvq zA}Uxlnsj?HMhNZ_Bs;HJp6xq{gyVNVK!;vB(QlX= zX+H1Kf`hhXviBI-0Vv1=3Z;T*k<*q$F`d@2%>&f7jD@x1~~=y%*kNxoGE+c$?zXjqNi?ZgeM7?jpzq zF4y<6S1;EWm$f290>A&b3t%0j1OG!N#^P9`Z^q-30TS01NyteM~J0XkC<89XTNB|ER(0u^lj}= zD&J!Tip4fa*_WOy0$6O`rrKyi?hQ5H-+p5_h;ZisLDU8)k&$tkZg+K&KJJ{g04?+u zJ!HX#44}oI%f~M4)2qkfkao)lxUX=kgz}k3e|!Dce0Y6WWr8BYte=T*u_{OejP(^p z!RkH@8BZ`RM}awS24c?!eRQ9n#3ARv>>z1DysIxAys_=a7JkH19BD1o$NFBztdaAZ zHH^8MJ90{IUNrSum1gh?A&X6R5Av=#Je8Z5Yy2jSA+dF#vF-PKhul%0XOTI0AP=N- zl-zw#X9Xm}(GQ@-BkeLx(mTNKxvS|H6hl-^QCv~4k%`frq9`ZP>zQk>c%zPG(L-JuGsx&RYUbDS@x08vYwil zUSB*!!GU7}Qr_${6=Dx7|11?m_H|oIx-1;BGtkQO@DBr5RNy;we$JwBSC2`bJ+IQmw98>VgEB91lT)I^b5v2MUG zA<$Py>n9r<70#-M)$YKxzrk9LC2X1XGh?qFWfJ6xmi_-xs#K%+#3Bv7?ST{zJwT>^#G$H0O@)y;&Y z3(Qt?iciTg^MHXcc$vXKZpGzD2wkkL!7@L^@rh)ermMTN36blig}(Gofp~_f(7?~qmdGL-rt$v67yj5vsC4eb8 z&7g@j%rpNeE}|6+E)BY;b%s$TKJ6|oH7?lv>FabyEHF_}S-59yly+b}YFJ+4C;g?n z{rE?AIPJOX7ifE5Im4=}maB1TT_qL@s*pQeQmukD@224E0G>#iUy701N)?WoF;(xV zrjSfFKG0p-`?FGo+`wCQfL~A*FJJCo5vx*RJWk@pjFNf>FW5#4$e}@eihTJxXc=We z-oBVBnJHfw3rg)!%qFBO6gB(Wc@z(cdQhJ(4}nvJpIZLpCuMw9T^T-U5OQ09_$kPd zJ*y#mezIa>6&8Ucn&L$}!C|J})-a9r@g9e3DNmM;aaVt!IrYg=l(6DUg_f`7z&yeR zZoH<))FD4o<6M5ck#igMjGZWk%L;(qjim>(&h!PHCE?F0(6|0kvj0Iu;!`GtJ6#gH z>-h|2A6P1x#j!@C@CBWcaW-#d{@+Eps*j^0|1(tVO4pBUmCg^@j-i&k@)3*SaCsyX ziz%8-l=x9vf`o1fbQ_w@^7vk1966RsrWliRsON$7!$5IV=}#!C6wYK-FNqJ2%Mxi* zUX%y?x0r`s;~`W{GkFo@(yZ)1j%3*pP}`VT;7lNc?moJ6`ZXS`yV9b3+K9X|Qblo< zmaxZEM59QzA|D^x=a|ydEEbttB*+8ps3)nHrQc3zg$FvZAa|E*bfH)bKP`K%$|}Ju zOGc)GdZ~?MrnkT=#w8uI`(Hf{CXe`OU^?P1dt8we86tmzA|`cqYVfyh&s=k!W^L1` z4piKH!g6#NmFqla;UxcBgN*s|6P`i&*REz5c%II5vAcuSZx+$Q5%Jpc0Os6uCE#0sqbzApp8Rg(v+l(C{3$3s{b*@R6ZmyzSb5(v($c*B)P{=ez z1C|f6b*rvIM1>?E%}Dt{@+A7e#qFUUx9`lS2N|Xn*tYL^Fu|Rm?++73_JX%HmFy!Z zGm-N=Mt${7QK)|QpY1%)Ik2^4vR~Rx#?)a$M9RvBnt<^=uy%1;7JW{NV$29g5pF)d zp<8Pj{4=H>!ltZ8LNY(jqFxPVDMMht7fM*n`8lml1QzK6W(wUZs;}vE%L&?aZF?Qq zWO`sMXLHx=!u+2l0gVN>zG1{Q^qtZ5E1o{gc9K}IS zWDm6D3k8gO|85EkwTI+3GvS7|H3hrzzPR~KNAwOUB_fP=#PDcLkb-nu!MLc#vla-_ zF$9QHT4gBf;a60hIveEbt6ZDIY6{FIUM{CyCE8X4&6cP3I0$8KV1`f-V_@Mu3)z~< z(=!lW#{JGdG*@6rB%R%!kN?jMSQiKA4orFD2l(#R;Zu;FzaXR5dTq}E9Qe4d`^sB=~FNiSV$5Ex!np={l=0i-~w?e{Ti*h0=};mPDo^bjA4N*ydp zT7+=kN~0k9iE^5D9Q}NSz$EhNuEj>KI^g+U90Zd7H~~cia~mC4B#z*t`l)W-FJ?P$ zJUL%_`&^;>f;_aBJ>#;P2;_}k%u^FE3X=ijYA7|-yH?k-YQ#+*E5N`VTYv9q4D8e0 z{EH8DV5gl?DEGT>wp1`CNij=ekYOn5(HUsu0A81OIeBVFPRVo+Y8)5^|A~w*8LP*v zRBky$*3?K~d8``HdWMzc1Qp6zhn~aeKmQu)S1rS*A=iXQ@-`VovGkEW!VIJ)fj2cz z+RxRv_@3xU5>0_BB%4U{J}tbEVFi<_pd>-&J%R4GiD6FzDU4lM08cv2TjL;{zGFBq z5}o3a7>wwqh|YKFWZV8Mh#R}lI$1Yx7~)fowk)4d(j(D@xq(Q_XJrh0?olTXId>-Y znc=RYxCM~<7O1qMZ(PQ4j`RwWWOAinH}?6ba3e&qA)}_6kCyFuRwZKx3Xn}dClbm# zOW(7_eUy|!lq3vJTK&(yF4})^?$KBUM;EG-P0ORAV-SV}PlDHKPH`Xc zD9Xb*unxKWjVU9PXcE)<-S9~rIn&A%4k>^#Q3K}2qF$RUWVi?VDHEz8>*>ro&Oq07 zSoHl1TuR`4yIJ{W&9k<+`Nj{AZruv{&EM}a1k1j;h8jv4URcDmD%0xX77VsLxIcJX zlb5mCPnzbVa%&#^;Ciq>M>7an_gMeCNzBcp)O>?o-VxU#;YNza*lvY1&F?2}jz6W`|KG}l`YXt^u0O6^`A8VkpWRP4K3j*uff;z8M_wd^pd&QteSFP`oE zH+ZZj;r+Mn#ckRxdZ2^(lM=|A4VPW4_#&@PZ^6(~L}>?p36DhIxf;%Ov;S=ZFG=sF zk~>EBQGIt1f}xwoZxjY=A$2&jJInI4ssSqKVJ~I3=3{;OA&ZM9uxWQvtz42lTp z^%5@d_HF>r={l_FvDbBrK3Ygu+LeL7Cm}H>ps2Z?&GXaeSFHGR1@r4>T}(8Ina0(-UL?A-CxN*n%82X_uElNbtPkxs?=Y;eOEp8=Ty z-djk+Pj>{dUWsu?T2RVnH!E&Iu)-CoNnGMYtp{NumQKBc7DXKha0R4#p)<%maqT|L zms~mE9X+T<6#3*QNJX)pz5Mt-*Nb7yO1R_!O zp_wh($VOq~WA6)hTuuwL#Bx&p0c{MWnB5P*JK+1wXg<0qY36Y0zPTVN-Ao5T3)m~2 zrT`-RK;IuSna`NXuV^?(fM~IbMc}+rIN%)$zNWu7)TolpIo_SeuH*3z>4As4)y8*TAQ1wbc-*hu828c=ll=uHZLfbn6Uzm^Q2B!Kyr3A z?;#|P_AkpnGC1pJZ6$wCMT%^fV1?O3FUx$-!I^k2_n{9b=8!Fr_ac-LaAVL$h?Eg| zKaw5oF*6wq+FTjjp+}*43R@>X+A+E=urQ3!njZ3H4{!eN;CZ6qF@l72U$cV`wANSW zA%iK_H+wIIb|69J3()8`K8FRpy36|RnKczdfkToFv?N0;LGP2{^%GpDY`IvuIq`^1>txkI>fqs|D746ZcIn@`~Dfug*ObuG88fuzwW5cD>5lOOYWQS}3W^B6;6kVoUj13|3<3 z5o_M;A*4oC@MM~G_*8`aiYR^34`~}z@a(Y@n_o!v#QLaWir!v&y1mO4@m`xCjjltg zXr66cq!?_;(q61EXbLvVp>j#c%>n>tJcAv4!6cEWrz+mW z7{ySm4MYuqf)3zU1Y3Bx<>_9KKjrc8C`Z7~Uy8-geS$X5>xckg{-H7+i`p%x^D)9H zvgox^7k8r~T~AIfO!y*>^+ekR*Gl9?;pD#WmrUIYU`Df)Xph>>CG}eA5YpMFICRGS z*-T7$K{=C5PY5U!ftepE{$#=I&aTKLhVH8KU=Y$pVZ=06WdO&#SSkNJ9rf?Q5FfO3 z2a9*X!H;UBhgF25>?BZkkA6a6`KEXqXSO#yr-{2OrL>SoiwLHdMKk7o0kx31muffS z#mQOXGA2DJQJF!{^{2CU#x6rR{g3&1jCCO6IIj#X>nNnUb}{mnvmvwGs##Tb46?&9 zJ4;Wz8J-XmB>uw(l4S%DOq{?&3Iemf|B&~4Lo8z&xp9jiFQ^%)9zoLAxwfTv4Wnut zyW@?F&rV>ct1F_mXnCJFT}*qu1v*beA~b>dO2aJ>`ZK4C+7N7Y&wE@6fY$zFTW7j~ zliD9e%w75QIuJDo#XX@fVTKXkdLFFkacF#rG`|QOiS5=kQHiMbN<+NTJWAFobAI#x z(GQ?(--G@s9>Ju6Ic~2xKF6TV3!82((8OxG&}Kb|IC_K2@Th6ikb|j{ zdyH=5YYjgi9V^dvr%hD{8BFz=(El_|Zsvo;Lhx~;kPz43Y1U=_5gfu52nOMLDF_$@ zM9ZMrCTp*&p@-$@?&4$kjqh}$e7VYAg2f&tfQAw#ORgmGEm}iS7eSR8oq`{ff6JK$rnZ zJ$`~C=mUl%?4W@EaONst8gGX^kGnTuG3;4Fa_j6hro0LtrqqtLzG&>3mU!A6a)iSrs|7XA*yOw9@CiMNj*eFPXvO3SX!5u~x zYm?q3e~=X(XTZ?}ZYw!giQ*Tim3fg23UKkL17DnhU?TXM(9zJ#{>D&|Gf$uR`Ek1d zBi8cbJJrs%05aq8>UIVS-u;P+Ed8^oAqN^{N^UE+dlg*nD52E0%SK)EZrxB92TDrl z9n-lUR=wE)dJfOcKa*(pxujrg=M16ij@!C2M9cG0)Yvumb)L(|)x0-FJOP5P74t|& z`K$-$RK=ke!7GCN`#Wr-r`v$p_WDYx?R>l2t;UDdQpnL{u4f<*&mc3%fa0#JPx0LpXr%mib1(o;vop8G5A}A~W~7XxUTi=Mrs= zwYvSKQjG|v(g>%W-^WNI^ug5(WTV=KtY^jl+Nrr*@~BNTv(gVSGS=Rm4$qGKMe@mF z!^`vagHYkRCEspK#?TgCnK!P?Pc=esW(YnQi7fyv%c1*0x-le%=aQ~$Md0dvj<8Z|j?_kPs;jkhvd2^Q^CDks}(ErH;K?gt{7aUCV zYKzFW+&QWr?nzu04mHte0B@`t?t;~WxhMj!2I3fvJ1=^OhWJe0BfCJp7tR>4V0jtjf|&qL)EVWtkGg7BoeuT{7XCqZk@peIYKGXK5xb3XsvLNIbR3(y0IVOnAmZ*rv90U z0t4OaWQ#FYJmKJyPb*+iKLYY_Ipiyb=Z+asySbVN*Jd+XuR?#Na|t?K%Jn)0w-u++ zx;YKcUd_}Z%Ct#M1SiT&<)ZUx^l=|F%!{+4-2qu zL0c$Q>$^MHrl_*Z3Kkw5*d5t6p-YRT z(r-0woCqQzBxOVWB!e65e-FS&%{2%uLFWQc4eLyPyV z$y8iZ)LQ|}a##F&V^r@w*O%foyJk}N=?mY7QNQWfzd5=4O_Wcd+C7B*_dFBbV}#bI z5ZH&j}vV(H7j2THNK)-ji*=Fq+nw|&hV>%rRl58K<2%m z0)UVz>x9@B7$>QyajMdh8|Dm!GeJKSL4{`Ooa?zq zbRqH7)z492i>sno(6DcURVL8Af%ZUABT?`I*}d#>2b_9ud$k}uja4)4O<+SmCS^qw zJ7i(U<)-i?7^bjIl;g!;>1yj673}T~4yQAm%B@%kUAOc>)Qwq4Y6+wy*a~(Nq>H|g zb*sQ<3YHAg=2g4Vs<){+N^{ZHhbst<2a6BPc|%O`Na`0zel5~{3vX^tCnI&%-^OxN!}MYdVqQ2^LYUa(yAtX!#*g)v zIbV|m|H?-+Y2?C zdwWYStmss;C|Cm9%eHP%!bO1@yJMy8Z1%oVO5O*;Irv8YoRY`x`r*9nhP zSB8QdLZzt!s080v)NpQ5g}C$l`f-)Q(h({Jp5=T}%<3%!Yk(F+<4jV^caMp1?wpl; z_!^^2d{Qg|Z={iFM@eBVt*Yh(YHzd*BFppb`^^_*fj{i`p(@WuV(r z!M3_eoKsolZ~p#+k~3BVExz-WJ(L_`FSugq30t)i(J&w^UBfF@hxyG>Z z`WmCS;$pB(&ccW;qm)FUtv@pGMV-&+J*`X~A9*@{@Y|M0AK?F%wJjEp7;{!FT{5UQ zJ^#`Z}9^Hm9+Q6KDfui_{^0(DW4b7mKSE! zlRIk-aM2KdhLgdd09=v8zoBhq+9in`^La{gZ?FR6b8hzVc#>^4kB?BjVr*zlHKbXR zQ-r4-HDE??`(%2U&=u(*?h7xlwQ07|n+h+$&^+JIPEf8&)RxD(HC@BcWJlST2!TmO zd|6W=g}qPH%Y|N08Dj-2@G&mcqOB@=k*~DE!73f`xrsOFO=JvfJRSaG-dH4Y$BwgC zg`&4g|BW0et0wrPH~S>O6cr?Z`k}*{nPYrRADIyyYaU~~*h*1HNa^7AEk#ghA6+(F z3bslu4>-SjK^z^o?GSC~tRv@#Sobf7bA+9?xW&|(;+Qu$<2eCVEw;G+NI31@!bQQS zv&kmBR#l;V0VHDie+k)!1TY`0*>wD-QBJIEOjm#MuNgi|DMK^Zy6Ci`48B=A3d@5L zKYFe+;ZGp$DWM_=6CX;gedpnjhwuRM0gR8qSKK zt4v@3tD+UyvGp(Ebz=x5RRVZxufV4k+$}q6R`w~)gyI6>03hRitoo{r6R+BE_zJ27 zu8wU(R3MrAPSj9G*wXyylk~N|5JfBdj#x97&BtsSz z1l7Hy#QMRe%1Hv2im)1y;@P>i0+H@UW5a1?>%GDCkbF>PG4=?Zn7PrI6)g?NweJM5 zaHxepRZoEw$$pFkAXDb}+JqZjPxu+CY>nB@K4rSI9~@Jitq>F`F=g)ORSXcLeIZP8 zK^D^XxztY|uABuE%7lF&p4Ws0KScvlGOOPJVhimj#!l{aI$vTdmWCnc@XgTjE=K(L`3J`~-Tah8 z8>AP=H>rh(V2cpActq=@`yh;teQ>F{O{L;;#^iP8;U{$Gc7{j`x;|+`2eoT%GaIrT z+=tM7pdazU#IA6YpU9e4E8+6B=(qv-?-5FbmqVPJ$pTdlgy>FAzE(cJwg-SXEBoI8 zAaVj?B7|CW)5_$Ipu%Bpye9~`hR*BZLRKPIEZEH+tm`Hz`$4|NU1LYgme4DRa?#t%o3M=A-8 zA6d?kpme504W*`?ah;Pn?~hDYo{u#6ADdRaPEJ-KGF>j~wVvvdfNiA~gkSB5dw0@Z zs}+mkfXW5}|EB450_?7B#Ik42YNd=CV9pSpmvuknr9Q`36;7XTV6<+DAl>!OSw8kE zRnVCaR*uY_g)HXxcXp^dZ@-O5KE8p9UYeJ2$@`N!fo9#dp}z{D2( z`}%gp-6Sk$OWixC_dpHHx9T8|;p|`&10P4@R>^{MgAlde(0SB%s@q4BCb{ru#k3*# z@8fg|r_t4F4bWBij9NUFpjQ`OZ(2#guTsO)=bJx9s;yTGApfdT7#tzbMrNTcf_}Y$ z0K~dPsG~nBi=eXy;!_Paj$V@pIVpzt<3r#a;bMn{mZovDAB4Aji-3&v`-X-Zr{c;= zb5Lv;f`e7>I)iE_P-i^)to4yfR$d$uvgz_n2$mF;*PkrbfZt$tJ>q{0?^bGgEpQc` zBb}G?PY|Kd%c3{w>aK%j(_=X(N2#N=gjEA8V#IzN{WN|!QTM!q*2|lW#$Ty)ASAMkIhK;aRADQGubZCk8(zdOal$qhwQa`W zn0o_SUby&&R1BrtYr<&^?O3AkV0 z+t6hf&F?VD^=v+0uR&6^rXDN>&Dn=Q6-j8bkx9^=kS{z1$TS&GOmV&(MMX(volwBerTMCf!5v1arV_O8L9gR*!L)4BjI^s4`~b9=CbUm+Q23t)nR^kEPJQ0 zrfhzMJ2C2D5Z$(AJkPD3er|qjNb(u)1^ggS^w4SL;gqmJ^Mkv5wq)jm_c8fj&!fV! zKw%w}a@OfnGAoB>GqHQg2<2Z#N}l@dC0CW6F1R`9d6lV80bfrtkZUbvC91KMjz3JA zzMxb03E=o4Lm-jHs@RuH*d)BAY)ft&3PEqr3JwW0720<&B(}zH}CIYw(lQ(uN(s^ip`Y;ZAgIuOA54{@*lXgZCnUbX?-+CI7qP zBpf))xx$L|F31Zaal#hqojsKEwQ57$M@pAfW{6IDuB*Gpch4 z@u#aQCr*f-Z*&=CHPPO7fRD+)0mS1gtzjG{@Ch2Ud zJRz!5Mg)N2aQng344*6st$5;AMo6Hc&sI=S)&fE==g0G=m4mb%$u2n_)%F3Ed8NB; zy!sF?ajQ_le*cFpp^Pjs+;|y0XiJ_m{{=@lZd^r%q5(c0^UlF4Q>Cwvfd_<3d%ru- zkELAF7Z+`ArE5($37(?OH3Fi`6S|)fZnio-rKc$;YCKg^$Ut)UX{GX*y5BDBbLe0dE zUX&K86Pj)pD~}B>y~q&hoS zt!<{YH#y%bgP=rFA!RXGEL8eOFsd}R)+ld zdXdG|?%09dyGA*Cb|`~S4}d+=;`SzJD`#vBJcx!WRjzvfAT3&JT6kOB-rxmnOCtQ9 z<(t`ALYt6NM1&=9(l}4C{BG+u`OH`DmKe9&7afL2ml6uoISJzhqj^ zU&x0uLP1>VgnU!R2||(fkGyfV-B)7bs3T7XMON<>l4JH2%Ca+HjNiL!h8=@y3PfNA83kq&@2j2Q1`))-B354Tvd!c+4fZFkUWSy%@zv^V zjNB>t*2huad+Ux3sK6*Yan~s1Y_%_s^7-v@O;#$iU8(KXh8fnyg0lAweRwl?_0ReX z!7yTPVO=)-3r$6-E=-OA)EBw(-V}oP+IN;YYH}_6(I&AC$_ajZg*r_3ZPm6247k+*Wk@AWk??6@#=3|Z@d~osjeZ2>x z$XwehadIX1#n6e>({cF};~Nw|GD z=)RA+i2=o)2(#G72<`=1N--|BGN*7A6}?!|CZftEu)>{Zg`aD3$w0kX`eKLx;5PM zYU@T+iEDWYC3hjn;9%4xBlqxeQ}U(e8nz{xJ9_3>0@(IN7F z`A)@y1hYK9*@CT5L8!uD_jxz0Fu=27_gDj{XVXXslV*xn^B01P={#UwI?NTX<^N*n z%7;CFlPvN~dv)w`9R4)6zJ!1^5|p2Ho&6sqkTco~iQlW1KP&&{U?IW(3AxUqit<&wMR7OEPyu^{nh3*W|gHk|aGn#mY7|WId z#OS*UD#7~*J68A2>$L8h2;G*l$23$^+9{gw#A3xGOIJO*8 zF;P^79(+3W8*m0{`$JlOI*HQ-qyg_unZr56AaE;K-fMBqwH7{4daB+5e=yQ30vZDM z*SC5>&WG;XXN;JR07pGzPY#ruEp*YwL~Z?Nn^pK*Q|XReN$0l}I&Bk%61WRxrrP?6 zx6PG*CqJ%WqWse-q?XhJ#Why0q;lcSO?Q#f`~`}@Lg7x+l)@LUI5GjPb1bjL1+}`V z(06L`QBdzCgO zY5AD;XP(s%vG3cj^AAd6x$xoMBOeA7m%%Y`?~8)Fs-~C#JjN_T-U`eCg0ihs!N3Fl zM|$XsS@RESL6Fayj&HaF(!IGrh9fI3j>bWFLQ|F!c+tTV72Z(HWmw-)51UjJ#4PlzX^NvFUZ(~F)}zqq~W*)>$6*CT$NPfTYA!QO967$bFO2DR(teF zj$nWR7L51+vsllrD{_YzBYlp|asFL3aB`SBItkX`Dlkt8mzF7u&$x2{11ObF-oFSxPgW(I=2%);;k{wK-Xj+`SedN#e45;m1Vg;s5x8JswzJze+Qd5^& zw>0&buT8b1$XqzZP)`9U=kA|jxYTK6_oN3hf9QlIfj{pTcgawM$N`v(_`5ZE%8Vi0 zGQkD>SI4E9QsnS9a~%t;2UyC+TykKIb`~#qscDi&x;t7((^OF;=N`c)5R9mT>>*wr zL6`?ys%hlq+q2{pgu=XDYDaYNBto_Mk!+&R{wvL7d&=#F$Qi@;! z?E=&y;+Eod6%kr9P~M8CV}->0F%@jw@AylIB%>oCG>bc-YG}*cc%SW11~VJ+iXdBq zE=tATq#6{hlRY+0aFFv@F`eMM&hOGv<@Ek0F`2X!ByV*J8_PN@Sx_CQ&{$VzH%fQu zBRql<)RvNlC8_j!ra$MG$aQ*mI2L=GhxbtF=7h(R$ggYlY1v>OA6QSu<&=w*y22ym zf_*m=$1G(&MCh#tUbLK&1-t(Qqb6)D7LZ~X4>Xf%NLfFdAp01{>Ui2|vL*$}sWl7* z_n$oHgQC!DA4~i8^5=C=A!j`-G$P>Zt-sV2QZvDl0!wkct)`giY-4I0zV_s~79*w-hv-$~O6yn=BWK0ZncrPCF|I#S1E{JK%!2u^2h9%g%ys&R zP^o+AA0KCBw#68*`zvj1Nn7pSxh7&Jb%ui`h2GR3|X)6CTt@Fgi1z^W{z5)$+C z${0#Z??{xGV8BB5;DeD_YrX1ng4_=m=B%l0(j2(Jl4o$Ie8HYid0@t z41rr0h!CK5!JPRsrE)|D&|X39}S3S@i3vD{;$qvLW-EJaX z)~5bsFi|;&NjyTXP>%#M>&uQ0NK$)$>Xrn|&d&CCm^J|UuCKA&L_*50{+rrF#=C1J zc^O|GeN=cjHA8X$B3ph1$tb|$MC`5uu$p~ab-R}#o1eHnwqqoGjy1#e?G|<&KbZ#n zoE1(D-n)wZ>Zp`1=FX{!2 zJ{uE*I06rU#Dlh7xEgZjl6Qw)?$;Dl>($eVaU#HlvM;Y({gXH}G%d zd}fHK&aY9Li#97xIJdG=pF>;EVkFN6){`JYrVxAZ?fH_#6sI*zy`{G+_)47a2D>{T z)e^+CTTzV+0%W3}oLgOYL0dWb?s%T(B)OOz^{1&P_0Y6x(9v6cBoJnMCjREEro{D% zwuc)`3Ius+Qn^h4UFU&$dxbP=Fc~~Sd_}2*&Mwh(V2ZfQ6poBX=qFJt) zsZX~rI>TeHVTU*VnTy~Q^XM+s8XqPXEXnyN-T$q5=+T(uUVSeBJptKZQXrJXfn%_! zgw+a%%=$g-HzgaUjTLoPA--}jtWfO57nPu0q7f2v$xFjqvG`Nz0pvvegvy4sr*Kp0 zG6T4n4yQA`yRUd~x(FQOOwK2GtEr;Pikfk@+u8}(5_@0WhnBanQTC~{vZiZesW^-C ze5~u0(~MSD;{d&5^KsTS4&9X@#)UNsN5Q$A*n&mQMr#OhPj`T{xg|C_Qgrr|-xiNt zq*jzf=Xxc!uzI@pQ?nX`0$YiBHZD?&y3An}^gt;3YJp9M8FNhGzhPa|b z)reo>N~O}$w=XFuWq2(r*XIuD`>uZy7_RFkQna}fjALIW1PYDzAOUtxdF{j%-?}z7L?e>#XmCutY!!Mp`{8|^)4`d zRA)>n7VZ;Nmk;Ld6BgbK*d}_|ol@Lppp7R#Gfj3vWd`hbyS~zW-)pqTqKx%N=n zM`|^Y(>M*THwmg97bk412sw+H*^I$JGwptDOE~p;tz&DJiOpT|T2}O^3g-i%!d4m! zkQ^=6j?_hyIH0hU^*DLd$OKzVnYT^Y1aFdATC5Dl574Dmu@MRVF(EE98*vM7HP%^M z;DF6iGblKOL~HbfhQ)xVi)RFEsoksC>UyTZVrlr4YGQ*j!7J>jcR8*E`65Crcz<4pV+TU4sm3Yx20vk9_xH>$J z%#)TWDO#j)HHIOdF0N_#?dPa7XhfxX_ZI~q6+iXm zZwqCfOFFed-qyZ^LzM6S0MCe)ysdlk{`=mLF!Xwqvcv`z6WkS5Fm~Qx`%^S>gB;-| zjxAl)e4uvcV8WOY<;AI|sOla&Pr%#wFjd|EH| z>@h#_4;$XOrfLE$z$xIm?-3~mhnK5_R!9@RFb-qOF|JHem`BpRB67REXDjhPj7+t_ zh!yrA%m zj{ZX-t#w)iaUTiW%^C}op3He#!!@l6k>vzLcwc^um6`dN({BMPl`wd z(ov}+=6$%LBq+>NZl01*>vTB&<~$B2-z3chje6R8AiP%(qDe|WX3`S7C^kA5#m6BP zp9M=@WLFo-WcDHq>RPLYv!dGCo=kK7txMap@VW60v&G}Y&W#oT_Rj807j~VwPp?c{ zKF1yJW1i>)&pw8)!PL|vWrOe%CTZJnLeSR)iq&@DrCN;|=w;raLh-Bs{Oj|RIn_i} zN|)VfW$nn>6(!=U(eb8tTN(PQ(Jgjfep8EW2)VSUM&U?dQ;@BX>lKz;=N+w?V=($Z zcHcg{YTGNN0<|%EP{Cex$fBI?9*h!ST$6>CW*W9rRivXqUwNUp_ zWH%a2Gb2o;wA@%B|H(RcPU&cXd+-KUS>z*9I|h}EIdYHC3%%0mUrm7OwNf6Le0!eKdw0E{`+RKlbdz)5LgGYMaJM%^*gEedh}yH6pPJReqh0g)L-Ng;Oyc_}wSJex}Eh^}A1cJ{`BEo9S7zs9i|g`>a7Icb7f zwsiNL<93pq|!*py2qF5Z~Ru9EX)1?!>>p)LU zIyvJBUx7Xb)=y>7gH-2$0SJ|0UQx(SybH{m$wDd8ShAhhuQ!|}woc$wD|z~eCacNh za?_J@MVezAE3052Z12bGHHco$?2DkC{9Kd@%2dROwuDZ|{LbwW+D9IFy_do+o$BOY zmHc|z7j!d#XzXKh-XY+ikYr~tw}}dCS9fMK-son7ff$=N>ko1^A;r1v`>v1nrdPuy zjB^tqY{gT~659zQRU)Mu^DRH=j=dN<<^pBZkc6tLai63C|9bav@TQ11*rd!?67_jF zgdy30D8V8g?@OQul*~p}05v9%&|I5Iq23Ey=+Dn*FDa;d72=94w$ckN3^*)#b$j4k z?$Vb@(TH&330Tw5?vK$n+*J|h$5Su~*&R)fc2?KHeo;=sNo#Wun|v2Ks-*CVOoWU} zZZ_R}G%6dMh5@_ND|oYs4Ref1x&q>~9CWV+p$&isZ(!waE?c|C)?c`s8@D!@fl>vDLUS-0H`-V%rq2KB=C^ad<4j-}gUXSsy zj!#|^7&4aqj;j5&3AaDE67f_4w;Pt@p$xdAO_1pocU#QmGc+unZ>j zB~}{^T^QG*XqaYo+rbkw6+O+0!W{jG!|(!; zR9IOHJ7@FL5xxk))xD?xQl;VixJdv*CVXcZH65AHhv(l-bxQ}(p1$ZGq2)icVxmop zlmiWM<>|yo&MM;C#2zzD<%&b*4q%f3MUgiQ?sQPbAnqFL!4^16oXoUi>=TzNmBCJxXaFOen`Rs=g$P#p@?2 zNY#=S62iZ7hgj^ z2d=+SwQIkIGU5)7@+@^TuYccWIw$EH-Jg6E(iU+dKDao-O3k5d77R~N-=j^(-;fq2 z-PC7INdPD#XRiua9WOLdNfv!Dc{1-hov%LjI2`DFoNqxBT+16{W*g@>7wwIQuu`)`#OM?k9dpnkFvC zkCWH|M)Qn_VAPX}b~N#JBh%R1))9(oVf`zzHuNoPo^S1YSqky-M+@mk7u7JtM2$(I z{bk9NU?=KTJjz9W{fTxgX4%5h)5T4`b39=bFb4=)V$@qG$?%w}R!QZrF`g`6xAPEb!#eOVUAO)>}h!`{;W@$U~-lu8@};xS{%58aw}TA3Z zkR~M=C$)!#7~tgx-p4v6qOsUyfklA)M!|%&TJpnU+94P@K73LuX3DuR%r}TxB-HlY zW2{_CIHe9@I5#iFKa`NIr)s~R#VH4ZkYJoa1e$K4p+z*hGnb)TSN(-nM<`jkq2A8dhgkUG5n636w$l2Mabvs2I2!_5{_;O8;;)2}8uYr!1ATEMZ;JyEt96 z;8Yjf24H_VsR96Fkipfo(B6f?N&Kyeg-sQX02Bl9$?DoMf~!5apJ*FqS5R5Q3mquA zO&vH+70e&B+RXyGJD1Z1{RU{D_S41{uP1F)T#52x!;sQ9YQT|H(u*D=!r72MU~?Th zo=L}Ee3qrfY7uz00k*dr^>K}!rj(x)?wf1Vxm}9?8|sW$!MaNz5PSbXxVffdO5ZiR zA{?a2ub56r;*OYfKF>;@%Qx`{KDEw$$CA2J9$@MxtheS*O7NzmY@+to$ly=unGhxB zS}Jh5TLP^Qodzqon%Xf+7E(A!hkdy6a^Ons8F*ubj&q17i6_(L|H7;@hiQTka7W1^ zEH+9zw#^LmFm>;Nq>QHd1HxAWR#4WbsI0=+_IWU)^|*q6{)u%~{D+ ztM0a>TGoh`dElNu+QfAP#!1v9sw}v7_rj==SdfD!4}3!Eqqnlfl`7j>{6>JbR^!59^sYk+P39h^!yrjI6SAkeCenAt2Yr1_ovpuz&)zY~C}U7R>p zO4LS>XbzAR28Dqp6?crMpk>gbxBbW76+~rE+jL~0(;SH$$w`m6L58|egy9;(e> z-Ow;8z`%UKvyCPGVKNv2>AwLs^86aITk{&bTq9$?T(@MjQ`XVkI@WEnEbKhR5#S&r$D#R(R94pZk7l_`7K*>m- ztYDyUk^awxR}XELFIEr{#gc-yG?c_o>~m!rzQcvjH7s(}loH?`{u|+%ol`B0n0%o? zrYIKto~}ZxM`l=+*>reu+(no_30H6VX^xQrR7(O@K96M+UlMqlTw6M8J3LFzpN1n~ z8zntgF!$&rJBnuK@U8(`b42E4Cq(~U3U&D%EM(8*?i-pcjpyXAnYMe;fg_*&>jn(Z z;n1ItsuiS|NI@(M(e)&q8nGSFz^}OaRtV_TjC>BTe;%Ml0}DXmIekT0mPT=hg7Esf zhT24~o)AxW+4=uS{ywu;c&1cOG`dV47ECfcm$p$rKf}K@o*hM_ZV+@LNloO#lY&C6 zXg-RiVGD6B$y{n;g?ZiWq9pTEmj6N`mT zJxtb#6;LWIXzNj3{*vn40~l$%pL)nRMV>eS{{PqS*9`aB#=4O(%)Q8b+F1z5rnEfj z1wSR!8G$!K?m$A*QlKsEi!o6;uZQJs#99LRL&h*X45p=-)g_ytFFmygaU4$yJ6@7Z zXRzdafFGX9dWpQ@t3Gwq!gCTT|IXYU+wCjhdlWmG?1_0ODq-Z;sB4 zYCD;;d)Nl7!9#AVg*{THHqTYx8f}cR>l#bV01*{{14%*4!R2-**K&52J#1~~Y;Vb& z0}+3(dYYR&p~OR$N<7@~=M_82kNu5TXf;Ql1=rBzZ0}pn9y#(zZtbxb-ONpGpTm2| z9U}Gnt*vSa0Pe(lTzR(daHj>rr$f9itEYl zi4AuYKxP^z)z>K{eyr;nB`kWV)(HP3iKSh3c;Xx`BG0Or<2=ZmqdV|bN6IStn@%iH z*@dJH8IWeA)W=i{nfgK4e+bDQ(Kk>aN}_SsEP>8^JwWI?7XKy$Fd#nYI4$)LecIXGzP2 z1*H7C|P3Qdl9@$rddW4%~DJ(+Y6@NEsNO*+zmR^HN`PE=B z3|oq}DI2LGa{>nkpXOgmV}f8x^jLX3TYKk}Tg>b55!l-GPIsY)|3NL|@uLxQchX6z zca>9J(e{#vMBuP>YJR)JSuB)3nR(Vr_nL$-EV(aR{J6 znOCtFw_X67;vi4+ub{GotTJqOq}~+kpt*zjBU_%fb{J=cA$vAdHRBD9d&%;zW3{!I zI6|qzQJ^iF*F8-tGz<~hEE@vC!%*M48m>8$s;eTDsFP7b)UT%01z}P=%cwf<0$U^( z5TAZ@b0FT@^X{&4TL0=IBcNSTx4Kii9RJs<#Z|QRBfXJR7BIWJD9H_wdCcT6`6c!0 zOKf1aykR;J<2?@{BJ3NXM#s|Ty*!-QQPFt1Zwmg=kV;5@Ww3I@3u)j2yXHRzm!9!EqX~h8wxYI1 z+du;}O(0H$KA}L4huNx~J;v%G2JZ~XwZw~?@wy~pKOXR*WOUwG=mcLNF=z?b_|;{P zd6=RH%525PcyV3hgDR}5g6GxR-;h!`qmBBv>~{-1hzJ@?T3XgcwH&C^o@FgQ=w_{P|W zVmTYoPoXBNGmHbKgzbU{i0%q2OpvT`C{nn}TCLr9ROTI<5j1X&PbIl~l~DOB3o&yOY(SrxN_^))OH10%B zpDz^N!UZe_i6ly@h3)tJP-`zc|2Vzm*ySjz2CSVq0eWL)?Z)mC2;z&BT0EcF^YJ+Wky83zachg`abMo2gyJ zz|N?R72~1?74+3l%{m*QH)Xh?az8?YX7E;*lWkr+W#DM_pC+HjaR?A;i(bAtN}zk- z_p@^@BPUy->dB(5-x>U74!Nvzv3!a)a5 zo6?GQ0o87zjM8vZJtO>*w&j^W2cTb4#=jru(P{jm9R%AO2#N*aVLoj^6Cte-N=T}E zhF^j8h#1fpF_FN`MV+R9x%ySPsTZ(k*1Ka)VaE0>=DE|i;|_s90kOSR4Qf1*; z+J|+lBu10i=Y57FG`{T2M>tefBD$m_&+_s5Fo*%ugo*Y4MLQ0a$-(PEfC4}sO?bhg zBHboi4bQac7+7F=Y=E&!J~yD58emDyyZCxas^Y(gMu39e#=oPmBYOaLJlP&jOPiC= z=g2YsaF${%4y^%v0k82}4y(54DBd7U50NY*L|H?}erF}NhkB*N4lHYA$_8@fuUH@g zcOVjPQ1le-Kh=2GK6KnRqAA6$K_xVz!Dsz!r^20BR&Im_Y&tg1a~u4GCKEt~i>#NG zrSsnZjiFaGMe$I%yF7%1;9;Lf5{(*8zri6ht2b^sw};qY-QMC^4CSl^!zW^m%cB@# zb-5kurSfsNeHT@bNgPbt7(lJ55A#iM36Ib(WK~9ez$S1+?~aNB45Je3X|>h$j6#k- zeU2O~Y84n8udNs-Tc*4AJbR`3 zbb;b4KqpT!0e*MV8EwNb;>T%PWEYZLfnUk{gsEEXk^`43Y5&&JP)DK|IqKjT8>5+&R9q?GTl6;@3q>Vi7$ebj=RuQCgb#UpDJ=AOp+sr_4- zVt-a+Uu~&V!Q!{|y$$xzx(2wFc$L&K5ZGN9g-_ZPxAg^yB6rb=Qs?_DShtnFAWnqU zynL(XfL@^vlJJ*QEsEJ@Z_}-1qe49NfwQHq+5}@}Lv$nX02jwhv#PT6H23q36JPSD z#VAjHLUSIk@)~_MyBm+HN#(K>PYaYk9jT@Q8D|q0F7M^;GEeB6(6i-1fN}k3$XhSo zb3m9NzLFg2%%-&;6`AO}y$XBReNw9OK#!Y$^iEnpj2NYqJ8YTCKrp1#34wqdI!C1v z-Ms>U;x@n7OQ;@fj7yR)A2$mcr)5g`9ly`cSGsJ&P_n&8ESxqm{%}a0`*RmS>&!u zLK?=R1#s|tsXV76e$w73ty{GYyGfz?6d7hy`N#8v$mkTj{FU!=wM#cBj|k$nF!rj3e#4!V_D z=*~I{?7oaunoR*ZlRk%M0MNTm?3!yvZsMnDRg4fdW~X?Me`^t9#P*ON#wu?q?euce zE5me?qp2A3t_o0|VW7lShU-k*@P__96Y1r0z_kKS7z;EuZj24viWe>R5g1iZ6rM=l z9A!rnI4HaN73wF^R=yqp_L6&<;9wNarTMo#C7 z)Pv$sh8-BON|%j2G7`AorJbhNsY|;;(p4~!n(AE|(Bl$)7g5F1Y}lW%RJVTF@kAAA z?E{v-e@szY`{M`oglMpZ?jFI~tIyy;`dErx@)?x##bTsl30(H)0`vssFmnCl?eEE- zzdUEk$d)HYGdizMT}TPv&UvKwlBc608k%b66~JeWtoaYN@B?j@$uHf|nBA$SEiSJ_ z^R#|Ba@Y%)a`O~o7^jyOn8P3jv=95}Er%DivAhHX(n-MMF}b=`y>C7^qpCN$gmN0k z3`0@FBQ}O&phdkx-4Nl4RwvryD`p+Bk!r4SI}|`%dU|}@dNNI9qzzorHU8_gze$8! zyB~B3UkDPShXcw{GRsUf*cw#m?ETQf8W0OOH3A~r7!bP_t3^}C>;X9= zrO-aM!{Q+td-e6(dP^~l>lei<7)us2Z}Dumct4|?S!a)j>d@?=uXpW|OkTS&;%}d4=B&>{9 z7-K;Ycd_$oAr0XlIj0&_SMet_#;GO?l^* zybSLJus{T&v|nhpX&wY}-#@^pj~lzk=7~@xrs+L~)cvv?OweX4;T|^Z932_i(_&Bmc5^7$tJC=&ZJ^Adf^%wO-8T@Sh2bHdo=-i9@gDkNKM zpMoFVHVxQ2yZBuzz4pFEiqr^p;*;{Pjs-Ft82+vZwG)vmCUwmV8}yE=i2dW6Q?jsopPLQ@NqY*%~kH2+!Pj9w-Bsp}rAc=&H!&u}MiXg;aM2 zY-*nQ#v-?8oExdoGFINL%=oC2p*W>V!_$lh1oWE9)Zlghk%&UAlukWMm@mXQ4uqR; zVv*%|C`!iq$DbE7N3x0I%!<9;LJE4|({qdDg(MlZH|lZ&2%cK4iNH}Kk{V3#FXNr5 z#GVOW|JTv7hepVHV~o{Ou|IypbzO&Wfh=GVHJOc0O~>ikJUjg%rKF}R&1%=ijN5_Q z@3Uv?M$K0Je!j@(zp5W81!OR+gq1tDx*VpM#F-WVuUMrd3FCZSbbU#05q#=whqfVU zbh|*>^d{R2s*}uy6{W>cIgome;>>G7_+WAQ{p*MMt%?dtQZ2`Tj>X!L!uNdI2ea9sW7E217q>DMqZYSf9YNE)a%aLZom%6b<^Z@kYJ z^q$%oswY2R1=H8iMWEiygyN#J_t;nYL~YT6w^^=%={nK=!)023(RJdx6$YVLeuxa| zOGx=?=37^bILnYh=1fo1vfo~0854EoR^%1T;xb0|AaIlJuPqb7R~h|TL{G5Y`e;O} z-e%-Y1tL#MXhoVz3C*kbV{bN))~53-`N!`ihS{*1KFM4zj(d`HYqhBIpTOgj!V?0B zLLdG3fRbY9A{6_XyMYJ4%LYnxwL!)(iK+kn)ZnCckqY(erTCwDq#VN^n_!868C{6t z(?Fytfa{sOpued~mVE3+dVz5V15|Vuizv76;fLGJ^UhOAYZcsT5V&$E0BOyS9oi$e ze(spINH+!nVg}Nowc?uws=_5;M8ydX4L}*9y2H`CewLz=&&3v2GA{w{aB;k;t-eX| zBQ3mRQs9w!Pkpch=8ntv zz%!QBm!hY6(p};CJY)3_i%V#lCx_Viwy9r%VlQqjE*-@dh}okR9m;FChr2Ve8j#{z z!^fAYK;oC&AZ}BeUt|URU%2+rMXH~B9@_D2;PST9lt<+K5RbkAq2BjWB?#7J%HuSt zuT@i;^P1tiAtO`7pucS_vpMtt6rj?tb9>x%J%TF$P}=m#i2)@jorX{)rf7U5+&PBN z|1v3vuYig=irRURR_i*c?)2Po^K56}l2Ak;*|R>Kdpd<^p&H+UNwtLvMZ!$h`ODU~ zwQil`rPuT?Y<+=>#wRSq?PqSpWKteKY~i#sd%nU&|JC2!5)Glrx02-O!u3QWCbX^mIl9w@`JO)mw;=RK-;8xmGcRAb&z|M%s!oy!0Y9J z&WE2h?BIP=1e?3$ z4Eyom#JJM@(Xh?y%`2eZ*Gxae+WCNq

    #wn^ruf<$1lua#nxKxjg+C;z61+>T~EqmiBhMX-}g@ydHMx&dh}@ihH}22!wghq zu`wCA)}a33e)B{dElzKZ$)fTV9nD~DuUO~TqJ?FHZ5zzMVOzPlxiozxQKC04j2gth zY*&=%4QaG96w|`0rU;j-lwruV*WV6Lx11f7TF&t^kN8XvhPDb9)T^P%^yC)c8XHpW zxS;d-81mVZfZ3aU-=8%IWLCz2UDaC{H!h=I=sO+{LPZepM&_!yfC4iwG=>(MBOtMk zzCseL4rxjaG`3Y5#kjDOgzcUSa74-U1EBKhee&FZ{*l|dDYFs(Gmv9WB^NIA%d-am zh6=ptI_vN5P_OWlW_&m97OZiy%V0 z6Tyz&D@aUn52Q}9Fr((qL8EHj*rJZAeeTDN zT?i7=afPV-gdO@@WW$kucYB(*O?d6v`7c5=C~yN zg+r?*^(hr~xMK)B0ZyRdM@3GBE|!6u!t?lyO7#;v#*mTEaM66O^)&$lK_k3&zhQ3%%|MKILsf4gmP}_pvJ|cai7Z%jX;<(gWc_a}GLTcMlgpIlG z8ppXfqVznuK)=o6gb_6BYWcrMrwM2X`N{e>H}71W?lju)TdtHxI5zwADK0^C>+Pr* zLBKa~UANuO=57F&b4Qe@pP~5@9tKSJqFK}L$uVzS*)WVD^9nDJRaOANr6R6uEXSu2 zMFA(n5WHkyoL0H!ObFMWN{MN?L53T9Tlkz$)I|qUs|L)SmvHfXsQ$PXfBe#V<5Yf< z-8vcaOPLP~1eR>-$gl8<;EeL+WJH| zAt{x6S6&4eq40K@6p%;mBqelFHDy*#qYFJ2yogPYUg611H>3AsW2(L8ld)S?&1BH< zQ=Hq#%yzg$;_$3`_AdQm1yllCCiMU}a4S*?U;4Bal84}JGL9%)Qv1Y` zQ|-2?Sk5t0#F%5t>19FnKn6rSESCzU&$X2`5lBD$`_pEY1JvhQ_udxA{wQZ^)?S~<4m}pn9XeGF4nqTq^xaX zgnG)&UDUEf&S2ywHjq#&Um!y}=~VP3$u$tJ<=3c(ows?g@**>g#Nxamr_yiI(BIKx zaovNCGQOUnmaYfKFW}ORhjVlf0~>s>IK~su>Mg!VpC{Q(s)J3^@+um{|t1aV{@b8mc= z#e&u#r-SHfH^BLM4cOin=Q7^N1~vk|g<@gGV6dSKN(a{7F8_M2D5 z*_S+90mJ72q?`CZon#I;xY%3Mk+aFjsNNCoFmaKWljvfh_uje{#{s zfLZ;%Q1p7josZyC;ntVD^B*23r?7oX+i7XxE$!1vRIjl4C#JL$do`=dQpoZc~+ds zB1Gh2qOg7;_GHvcpSYg9R=__3->RK z&xo%}{)f4MG0|j!T;YQFBEh&#gN;-;^l)>#&@1o~IGnfxVqO+0TEt`5=>YuNH&6mb z`!9_mCMh2~S!3^bM&RS#m#PVQ7XZsKZ~(4v_Zq`yl_b%6I*A{BCS>X>xv6?Y_L}CBIhlABvdxJ)CtN8hoqWGlUl`eRq2^$fK9du#f2P0TVrDNvQ4|Ewgv7uX6{|9RsJ zG)7@&tkVMQbxc~6WIG_~ZZ|Y4A7)CRdh>Q`z1iiFpAur!+!OMoNi}rN$NS@ak1;~1 zenC!I4v)L&_GC3*tIX_)IL9zGfSiA;!(LuAtVGsh?;NbVR5+E9aTc5-$kJ)r20B8lIF zsp4hn{vFKki%@@T*$z75Qj;(!pN{ng5KMw)5 zY#U#KeBM28lL(XzeeG^iJU<6nDk%^p(6?gq&>u9zSS&<%4J@Pa*p8R-WEbc<=v!3X z>z>CM!H8J>K7di`pe-g01iO`EZL+lnql#*a&zrOb_cUXliLaVbd{-Lk809Vzg9BIY!&54Wl}7^R6i1NRJ49HtC+_5}>DUm?l8=S{SK z*ud=*>1JS6Ubx{Flr^H+Mt0z%h^Nakgh&4z2bx>lmoREd;Fj5!u@fM|7m$o-?j-K; zw9p*&I~?K5M)Ac*iWXeHUbUU2h0HRrq_3VK>?U+t-)p^Y*yzF0<=vTOZsH{%DA%~i zh$8;n<2_0?TRDLh+W<^CQ}0xuwBJ3uVK zWxZobze4ek~IaZ_dZP%K%CxklpYr3S%8+K4y7 zNYdOE2I9SfhL~nx(#!_JHf8IvCF(ZN4tJ*ar8|Wu4%-Zm4CrP5dqOzz-8Y23y(UAc zDA|{g1erNXGU(~hi|Cd&ogdl`dI!sgYS*e{*71*{CwQ0L$^!hE@(Kpd^Rw&sCmQ27 zJ9<;ri{x-UT8jVP)(On#?xI0ol)UPtwmUAF&H7*puhl5WmRTxWnt~B`XoB;NpwCk@ zW=;?A787Q`Zr4ISXRC@l*K&5ItlZwlc>3cUvh2n$TL-knuRX zd&?fk>{~WlN->#e4I|Q@yW?QuHX&ju&{Mhp zHrTCSzas4d2eyQ(8+?c%oP|DpH~_Cf>KQp*{QEh-O_H2*CqiN{DWVu^mRc@SfZjS^ zbRj2;@r1k>yr8+O3TG#rJavNW{ zHy}e?meC{)=apIo<5pdM6!4?1P$sPW@8vd2Mb> zS~9)G*~SHzj$P+Rd6b|HT3w6hPZ2$cij`(7>Q}kLz+nYny|Ys0xl>>F?D)bW;Lqv3SOvX;yAsXEuTf** z0MVkA)z=}`GrUZQ>UJH%RB8FI;Zb7p%bvG>iIEEIA#mcs478rIwxbz;+kC-y)^OeR zRnvmoq&v7cVi0Nx;ROlzy8B+md+L6Y(Pbir=-CI1m=hV+O7#W{cd53ZjyzD70Bm*n zR4OL*wNtSQ^PAF=__8&N;V?Cm~ylz!itl!bwSE~T0s1cWWqgau8JKU#7nVWth4c?K^yfV z0^P4Re@NZt&h=wIJ$K1n+8JWH2}Vdqs33swyDz3*vkEVOH>Eux z?t$+plDA2KC#`oJGCwr5>07L0>|F@v@-f;wdGb72LeQ3I)+kgAMCdvIlLYM7L+qf5 z!rf^}hNH93X=dX!XaPf5cLLMeuM2f)!wW-XL~#f-NX42AO@3|I$TM7ueImRfOLBJ3 z)Cs@0v-Ai-^21h!IwRgJm7nfONN>Ew#B`z+^8yAr#t@Q-R3LgA7PnPuMpPdo{&rm@ z3KgfQrMe!6vfMZhurxn3f!meMi4$*h^+ehwBY!RQ+eZ7WB>7sWpUOV>8-EVWr`;6% zC*T^WyYd;>qW3Ddbt+Cvc6(bP>pEnkveLViUeDyj?a~HxC?9=jw)<8pyXl_YHh>GM zf>_jZ`OV$;$Nv7^Fjvd~B@zWsFz2kci4(*o^Kp=-WY{nLs>T2G58oloXg_y5*~2=6 z$#yI@QKQ$9g-i3EmlU`dq66>QMm*IMF7$wNI8sj*HR5m`jkfaj*Lr2wD2qQpo(s{H zNmU@nTfOV6yRCRNIfSV%#S~@i#|$(C2~sbtF*&4e5Wat3%?aG?ZcrIqi(8Ao2Z)>! zHyeyilB*Rbmm1O~w_~Cvm(caL-!~bk$MsU}*Rfb5fYXS-ZACia5ZfrLnnM)pbtl{( zLpE=Nn_DU+xo-@)HkK4;eFwF3^ig&y zX4=AIwmviqDj$t0L1=6djZLD6c_a>)Y zA%e8tA%X`~3nnU8ZsO4Nv*k8;F!@1Ax+_=U8mwZw=Xfi{K7s=a6x=WXk`b(=$iqjb z4~DN&VZogV0{_CDB~*p-m-8dDwEfwU|E^8Rkgw~ZbPnr(*$jX!7ulG(F`wGGGWK)o z&VcvTC$K!R)B8@ziY^mU`d(YU?pqL&KfAKhmcWaMm;GbOQSqNN6|iyHoJZ(1J(=)| zEXe0S$d*m+^}Yv?%UZr7{%cw7>~lP=u5b`D#U#K@-xivn_&MqDjCI`p&80{;cMAJc zoo+rKYvogdND}cuWY`Q|2OdSS#%Y?FD~Lur3aW+VWggfL6rq3So_Dof0xi#prrtG0WNgO_ssgG_JhL&3HHMvfwHCAbUDdaYpHb`CitubrJ=ePFoFZ2wVf z08>>sO4|Y}JO2r^61C&1|Z-k4r13Y3u;iG+bOIDY4wO z7qqD|^S2k7@oB1uJ|5hbkja*lkps9@b9%Lc8;O(B5di5V%lN}pD2Lv-uVG-Z%Xhndr{_4By0E|<#yb396cU3 zzdwvq|5=HogPM~7pv3OR^(}sss?V%90+zdq%)0(SE9x;yZ<7&^y!5E1=VrUWivzI0 z+=pnZRchUm14=GzImkMZE5M&ms0HwJlpwD`h;eObo$Q9pZmOzVF^Jhrk6B(@_eYa+LMz z*PD*VSRB<_-PO@=O^O}!D5@FMhLPo+!Dx}SI1sjt5OGhnlmkD4$(gH175#Lm zfi&ZtUwyFt%e3Yc!B1#`FhS6OlEku*l{&RHeR2m&U3`;we-Iry1p+Ks)174@R0$b# zhoR?cy9HRWZ{=^qQ+*6_8j2$?ke#Y5VE-{GQprq<*ZX(nAv^+&*}V$-QNcJWkMne) zBZYgEe_iN;tz%|)U<9D1pR{lFjn@(Rqm2qRYC*#(gfa3ZvUVt9&S)hr*cI?=)PVC7 z+p5&a^qSl^jMe`TseeFrQ8>(*;u`Q2@cqulLX7nP_-8AW^z_khR%uLQZc=9RwVPiL zb`xn)+UBCKW8gmS66#ER!$Z zDm20aR-szR57u2OP_V*p@@SQuWtFAsuxi2%6hULQZf<<&DXmvI$@R-X0}{iw08kgW zLSe5hB6Rb7DhO;xeT)g*4d24F9-W;Pr9M@3Lkptp;h@P4y@@O#&(AvHgT`N>5)|Dj zB)^28`T*`h)tDk;mGyrK(-~*f2Cg(oRMO7I*$Mm%=u3(l~|1~vin#u^qkd(CRGe6aWeg0;k@gNL0yDq z4*_35^POCtESdyoUYE8`w|jd6(>!#DJrPrqEVH)P_jPJUxY}yj&S?)LDnoBVhJ*{R ziP*VY@QTc4Ad?=^XR2uX-Y9{;4Ykyz^zMrBJU~10+EdtpufF*l|-WmaFo`r(6oy!Nsg&S0rNu&VxzZ#B-d?hc;-^X^{2oOpFFZff4#G4bSx zGa{Px%8!0ZJ~Csfm_hp;^8y}^mg4^THxf=_*Xq(e&B3$ixR?Kas5{s)t(Xf+z;55~1j;cMkZ{m(tEhOQf(-QowE zuHC@1aoUj%28b54koSw3m^(tY(1`A2?4WT_JRM0z9XnM%r((Ck6(P4<-vqC$n$pmK zE$vya*M?I)xwbp;9atx?;%1T3Bur(xqGS%J?44Ld5o2D= zW;9t_Uu`dpWjW!knK%{GSN*pa=fpuQzlUiD#&qZ?C!LS(|L;Gi8_l$tEr-qDMHVi} zKB;~qKSJU?l@s=|k@h7@MT>YLr+bF2P_z2JcdB|9OVvT6htA`K81_hz>HtnZ`9Q!l zFce$KKMZxfv~TvT@fwwu#f4aCc04r3G~i~1P4KC60pNn>wLLy*(T@8~SX6gsrG zj_`btV4KHo(;H!jhQU(=OWWoBRcv%q+3Cg^V6aGVj1z8LHs3{mo6?ZUt`ucnx<)I4 zO5@GVAcL>9M(eOEA5tqXuyd!6orMH*D=+`n4&efMJ;$YC?KHmxtSTz-#v2xoj=*)N zM;&H`^zTF-T5joAiw+G~N7-<`2^PQ{b0Jy*z)(YQ$Uuswd^G4h_!*&_n66fERrgvk zjQ23DgUAdSJA7!&ZGW`c{T*a458{Of)=rlvZX!6{TcNe<^LPcf5eGF9Uf zUm}UWg+%wF-PSs$(C&@-=_4KWw| zn+M?`J+h(PA@9@(jcQttQu|i>xWAze`<)(!ryj^qfx~BMDMjnPiA1Fy0f4I1X5XES zGoqc(ZQ*}4?gANJuVY)GYSPgZiB{~l=I}=Cq3pu$#y=1atWsIi z7wvAGQ5~ z8c^SEt(&P~WPgi44i`78=K$8|DF4n5sw8)*nN?vt=$n*%N4r=lG6_@laF<>qVD3L+ zM#67X5ON}N1qkr1a3qeC=gFCsovC+JKEtVJn-+kEd40Mwr4J0-qW_J z>VD^njcvV&nh4gTxt{8H3qEiE6~((!DiuOAjle8a4Pl@qK(~|2tVRgTEoU9 z{bDN_(Q$CQaVYJCl6<-j-E6-qc7Es<7I`?zbUyygO_K69lZX(IWE+Rvpws3ayIGNR zb~(kwkCi=dwT=fi=*zK8q`gn=w5{#qzh8r2`8AR;T7!guC(w|QqMG*Jm#+I(nLC7S8zTq!^T;&!(+J6 zs_KFPB11l`WYt~l>4blK+Jp~TL5uo{LB(o?Hug5ysNNGQ1Cc(+ORj<^aL6D zXNxH4DF#DCF{?KJrFKkAtoga<^jYwni7x*y^0*#xOFnx}&|9F^6=rE8DFh{0Gb$uM zFu?h<5fdfIN9{&(t4wLn1h@UPvp^e;<(&UJ3tg0rWm-5N@77>MIxHJJa}YnCRrPS$ zkmcmsq&+BobtJ3yq4>A;l*V~?xVjEn&775lb#m8>hXB{4_Qp&QsCufPr3ZQz{*ODC zy!MsDD*d2W0Sc~|vqzWy2KkG?1-;-@7c1Mh!bzH}gp=(}24zDcHdf-*`wkqmW`8>p zq(t`mJ3qYuDQIhevt&KU%-eTrG0~zlEWdJVP7S@0z5B*o; z(EVzudrB%8wyHZDizlE?jzB>7;5o~CQ}C@(jwXu@#^M}GG71>S;m?k*>wfB5{Mw*1 z1Yv{eYU7hYT?z@}7oM!?j>Z^@YIbHa43l8@L)bZw)6IT`GY0++>`)kyj(bMoKZcL9 z{q`MTUHxInwY&$|UEboM3p%4TT1t>vk=n@)N|5LA2<+^vZRkQO>EIm6ZC4g1ZcU_n zVbc@4`)&dIt;}kSTQBW`X-8gAgx)Dklj@q`3}qk(6JEMQ1&2flYC1nhOU~<-?M_ff zbirT|C;9m^-F>`ayMX}OOu2Xf$g~-}jWX{krBCrzy%Z=gUh$EYGUoF69NHnn&5nnO zz$8X`g?a*!;2UCVJ@#ytq6_Xd-bADHP=Hf@y2u-=q9plqk}M#& z0k={HCY=$boXx_JEkBKbX++AUT43_^{vHIbdR*Dwpzym<+TA0nK~e{1AWqcgyY@UU(D$ z^@Rc^>I%w5snXpDSCzR6__$iU$8V+a)_(Mi@_JOM`$^j7RzDBj-rL(guYJYDWQ%i@ zgpknGMTq0{PU)rOn*CODMRjpvX(LBmbUj<=uG@Zi#O{ zgTV`s5Ey-**nT44*HGg8^orYV(G=?yy$@_#D8$67}8Tt@tcTM zqYdxixl zxnU52=$Dhu>=LhtKzp4Kqh>#wi;W!kWQzv|0Wel2B7U6RnwEdX`L124^pn6qaQAdQ=X9K~X zVVZ)1Sdf#~7iWcwODtNcZ7K#RKP?D<{lBD62JBXXfl{Xl`TQBm{0u+N5r=-HRGv4q z;*3MPtw42BNh*w&v;8K=XbqgR{N-E}g)r-UqBpm1nC(VP7*GwFz4Y;Ugaa#Q_?0R4 zkG?c3Hz3*eH4`l~u*xxL2qOrK2#n^Pt{LiD^nT(O9?uxkoN$VOrXl`}2$ zKZXc-S&)-Q-sGQsYW?ZO8|1Rw#{vNkI08GjlkCX$;yAD9<=W{(UPeuGa%s&|H2Onq zh~&h-nY9ynrC>;>*AcfWFrLBw@T${yR_Qk_7Ap~^RG*Lq0<#5vt6nt8Mud7?VMx=U z@ZPuC`4uBGA4K9yJozhNpQ52=g(&e4wykSk@BL8t!|nZtKF`^oy0z%Y&?teE=)Y;m zU6Z+(k+TlwYR#NYw%12RR%k-;Z$%Nop{y-BsuRpWi+G8ek)n0D|R#cNH0OgZnAB z7&^{t?r@a7Y=mcCpp;3d3;hTG^@QGGJB)0hrFv7x3)dzCidkI64v-@;`wTAEfw-~3 zvYckoLdCM7&`MBL04r+YTWED9MrZaSiHQ+s!3oq>G@k3)&MJO4{~n_OTP%rQH5S6oU8o^pN)oCjXlSzY~n+xVKIxR#NN;F*g~-o!cW;`@_@4*8Y*qc z{@RZ5|FPB{hJ$4Ewd2Li|E1UCbJpxf2!Mbc&$(0!;CX{yHmK?;Lr}*a!gctRA!Fp( zy>|VW#nL;M4JFCeR4JtF3mc{ii8a)}IpDsfG1DXto#k~Kr!-^YG`uXtS^Ph3zsjG& z`GIl0xlV|I>6W=Lsm0}UhArAqT~CU{_?)-bJz8j(9_Y4YjzUGA2GomjmR|L_=L7p^ zwRI)3;c75c6pyQ(wj>o=J61m5E_r8K6ezkm@xsZl4qd;vTLwfajes*JZPU7W7$GTi z;Byz8%$Qd)?pU?pQGLj>5`K7*DlPu1x<7PE)p{;LTaXn#fm*!HtfKLo-){=4G#+PFI)gR!olTKLh2UiynM6jqGFAIzV@C~}V z669IbZ+i7#o|_bGjMOz{#ZCyOs0>nwlX87~uUPvI+VioPQKM2K>7AF8XA`*aV(!uu0U){0>tDn&-=4uPM9YK%> zro$w0pldG`lyEA;&WZ>w*(3y(&&=2&At(&UU{YuIaN=|TCxz6WKk|kI-T*U6S=C8g zH(V+9uTDRJO6sAYbs01EpcC*admeWB5dsNL6pCIW91YYj97l+TSBikTRD)9`TIS$f>Zd1Z5BBErDAMZ zpO|noST4jSM$4w*>DBv!XdBcecFJqH-0HuWduCB)PH^a(vlSOZ6H3=j1ru2Xkny3Y z-uNG}QOqAt*qBy#jbh>r8lYC*(-|LM)Dkx-xq*+iSo4MKnBIXCdDH49?-UE@Ue()L z_E{+VN>VZ2tGp9rMYeE#>ajs9`i-q`bW9yEG1g%Q$8oDNJ%x7SsZUyXu?4s0My%Ei zQhO8rAUk{bC*W}yTSZeVgX@i=qt@%=MXI|&Gt1=PFq?)1Icm0wJkD4G*gdivPu1Q^ z%h;z6F{>`9qWEE3>Pd+2*TypDr_|oIkboK1oz3d#2BcM)*I9|^b$4tg1AK=A=k61u376|-W#noq~lao0GY^LKOW6vfjdk57LhS~e7gb9A!hF)To(V2?jXsc;e z&!D!?+&%IYCq2!$E}xHI*paLlB?#Y}5_`bacL%jkhvr$WDB)+j3CJyL=mK)j1H<8e z_vCvI410b~{IWKN&sYxqD$#?b+Hk8po3=P&`&-Ui@QHF0Y?EL>=6Q{6xv|DOjqK4-wfsdF5vdD*#I2K2Bo^FWMJw#=2dsz%{~v3<@FEk?VoC0GfD z8(+-vBcx}oYXC{8On%ww=*)lq69!$%F4mHp%=hn)P@roVD4Fa6hz>B>~GD(>c z8dnN%ZOtRyao&)UuaEQ&F>T1+%c!}pj}I6(|#ukwfP%5n zWpX_rX%G2S&_p2BaD(O`QHlQ@mLL17YJYI%c$xpmHLTxVMd$4Hg z_ep7t=3Jhs@J3J=hLyDm8IVmP7wX_UwV#eQt6vvL{5b_DJ7-&&&2Jqxd3!tZ>{Wyo z>6ZnJeek7FM8uWA-qV=Fj&&+-p zmkI#HF90zrU|Fu&bNORroI_Zs)-i#gD6!pog!>Xtalx@)exqF~huU~6GXV5N(x zi`VodRLxGuaQ<8BSR@S!7eXW2zZ8a*9v$Mn6D9G6~Oz1d7ru9}!K9Q2dm$}TQmkY*XnnU&tUa0HpdS6SD3B@^TV@%5Y zEFd_GmF|$FzcW3JX`BP^PSBuw^N352yv(T$SNTGc>3@H1rtg^&@?+`Z*v(`&P;P|z zuGCZ8mL5j!_V07S>(mUP_$#IxDtzqCgi`SeT2$+sZ8xXQwYbDBVgGB&b<-xYWDDO2 zDh#g~vgCX@=pQTt^FRzi?FE1m?eCj_@^0oD=~2vsEK1}!_%8qad#rY z&>WS-e76Q%O+QXaRM`5aWXo2%9R zEPlzXmglRReSIE(VgLm2U#-9($29uUTL!$%{qEulj((T!!Ge+pg7870ovR{=}hCANZWwIjcG zD6n{ZD*5j-gF7;F4MVg_lk8(6t)?JuRsN0gt`4#Tbvv+()1eJQj{2 zZ<1f}KzBc=>LN+Mp@8{v81HiP?a)4l?TD=c(y?t}00S=M1?n0hZIQafFb-6o#y|xn?Iobj)-<;FIuR3c%>d~pUoV#>2XnXvjw|F4`W593>4f;*Uqx2aE@oRN1^ zcyg@8qS5vg)Ey18tth|#M#Lq;laH+86wszu1M;>U-j$^0=0uoG+S;N$fpyogS$kD7O zOf=&&O3K;vh!!x~>E|EJ%btp0Pt)v9;}K{R1*M{4jH$kU}#%*HV&Zod-)i% zzVtzEVDyiYG`x8RXpMHX&FrOdwC~*dj3F&3q-TVtCx8%{R_lPc8-Xr7_1iQ`AE?Ya}y^X5+^W>8*_ zf}{+md}#jn5h3A%t}jmzWOVq>$A0hYQ!-Vg5&nXGykBj?B?IdJ<0=J;#l_qs{DqG( ziC9$S`bwG&fM3xQMCa$c`Ct~PGBJgX$g&&=&9UhLs7U?1{Rc)ICr@?wr zUxEe)bUG;fX&@suoqJG{YB4ADYK(%?uw9s68t7e$;<52@%7!2j#c)N^w7ok)P_D*! zWC_L5S6fs$a8VN{EGP|{ zBXIFHaW>eh4^=c$0@lYJdphrt z;CPs|gI77?2WXjVN1&kt#kBYQ$HJj_uGtQD3Q_kqM&Sz7c|@MV8~2bfG-wGTr!|{? zOHG?3Wf-kkb)RJUmBWf4saH(PS10}Q>}-3o1P?SaD5RymwYYoZYg4d!H zgVvWs9oDwoH~PYG682e^0|6i%6i_G_9}y$jF$7Xq63V(QLcALvf^71zZ9?W?Ve7}M zmo6xKzJ&_*&f@yQI7OjxmZEU_LC1^A=$tfA4Dmn+4!NQf(uAh;kT6u3GFmk^ACSC% zo_|#xgmyDaP<+u&A8eEiqcr=Cz0R6BlMA-DXKQtPSxCT zl1ff_o3;4al3aSXjsIdM-*|aA$Z)uKt50E$2+si%Rw225a7wjmSB91<`G|DM5ZpId z0iI^^4lr9H7f}fm*S@<`<{0I^+sOSFu6Lh+g4%+z9p<1_oY5(2G73ek*uUBui1z~# z3B5NG9;uZD5>&JbY!PJ>oXy3_M+lVurfFxP@nOxx3JMRN)}v#-yYP*i6r2bR-kYaw z!iF6q5xl`;U+RsE7>~d3`}j^g&M+0%RQ{YRLf%M((I|06yucbc|NAWRPc=veznRMt zXLqhZJH+^%f?qciHBUIW#d0j^f92=?32?&Q9;7^=hH!s%qJui}jQ)5(Zd{91X2qwk zFs9YpwhgCY1H>|jkddD~*@H#TVyyXI*3L|3$UvD#7ji!ca4!VCh1zYP52DhOI_>Pi zau+MK!@&MST0$N(SIo;#1(i&ahVJWNX!M`iP@o{OsvHmKD|SP5fVaNYPPfBG=iRRj zrni&x+=d>KzreE0Sk%O|QbRMQtWl6fZkUmTP+yU%b%AOsNeZ}$z}*VYEJ~WwGpRq{ zWZdx+xxMWVoj1hWOb?v>{d4b8j)Qp2RFEXi!goSiksg@8^u7bKGz$tjee_&bCUW?y zNuT|bU&X^hB=Hr5t$gN9l%7!A;)_bg09G8cbhRvPcohzcP`U)eX;Hm_2Zd335LyE< z9GEA|PN}vq5B<^qEd~LD3Ns7CAk>m!LS~ZdN$i0swuPvHp8}F9 zZ6Tq5Pmov{63E?B~_6TPrH~`I%M8zOGU4OtOi=OUkJlVx+quQ_<*a8len@(=T$i-wwg;OtzCsMbmCLl3rm<*aZ5 z=*+L}-mPpIbxbZ}CSr})RKdMaN zpVzK3M(Xzzl|ViZW256k{63F`Ixq7S$*_+}R`a#>o`~W698Nq7xzduHixY$r_3Bzp zc|$al%y1uZK&wUPg$mgZl}5#b=bK&G*Q?5(Y4Os6Rfy!vjb$(Ty)KEFdb|FNlI=Yl z5p!22_d15+nJw@tv|)b>A=z})SphL>L*{hZBw*#vu1iq+6rS}k`y(XL2(+g@P9?oK zM?3_LxH^iK!lo1HX@G8OJg^RV3lV1u$a=Ad`}sYmN2^CAX}y1rdDflpWFMw5{Uwx zESdS@dI%msEH7`(b=8(kVfYnbwi^<@nq6@XnhjxHUsiRs&;gD4AGHV_7laKS9}p!0 zR+Zu{^0I$)+(7}9=FqFKBQr>w3&-pDcL-H_18Q~U5yE0~pcJ)2nwE3PcqaEmTys`xH6PBXvpvh2FGi#6@Cl%doIkNv^huHRy$A=Wmg%90q+py5N73_g@~FD(U8k_ss4F=(Vp=Whv>90QSh&W zmvWxe#|Z)%u1@Wj{OnmobMI-fI4xV`hih|^u8fZ+E#DzffDUJ}uK?7j$rWZ}yNwwq z?guGM7%dBhcJ$*Ie@Sn4LIMEN%~SD}42%5f&Sc*k`OZR)W#ERFjtLo35wO`|3aazA z0oU}H^~}YJ%lw?nU{>_-q??Hv6tERzNGsgRw4`RumQVXl!3h{}ul^-666!H% zdtf*~ZWORsS_=NV3RW(e-itZ#hm)U>LNa*j=5` z8_i{(b5`2XL@0@;o5gL~*63!_lufMx9Eb9xxu67)c)OP%A9kJr)))>;A$Jy=TFL-|}5LAKexugINmP6U*wdHdY&$tGfW;17jGtvH^xB$S= zX1je|U}O~z5hA!%Kb@Jslpp%>Poo6MNvCN@7+&jSI&h(&XR@^C%#LSbN$I}VUA#mo zzuF)%aQxt5us;`2$-bqKPzer$5|w=Z{=$rVF+4bDJ<1pyp3uY z6OWGSd`sea?JuFfJ;9z14Fa99^frJxGaUMsuuQ&hF#6njv82ge?j)*Dd4Cwg1m_Cg zn5hPzlSj79^n8YNjaTGtu|6}`u(s}Oyn&7-SDN^;#p76S0N>ilrtuT7tFeMzSOZ+P zz3}a)nA9jZ$BL|AvMdLE*cqT}YO>y@ON#|6n8t^zcHlDrmzR%=_pZEDH8+K&!pYij zomN(&cMdnrf5gZMKJmji4D7)HCUz7#P*I8U3 zVg`YM^r!TFB!F6)f5NXffFd0ffu54y!65O7oen~l^@lWMut8fq4W6G<@DvaDB6PBk zFDUFNKoXFwUSWXxQqhuyaR@EBE9-12l=jMMFN8iZlf!C2A{n!V16%lwz)2D^_t^ z?DG0^^`7k!AIGIuANwyBX=SBa9GC2a8{#!?D=NqeRF(j(ehWn!ydgNsmDk+%UPZwC z&-ZkYXlN)uWKX=2I_G>JINw`y*I5+--$PW~&<@I(Qro(DNxsBmc52LhuryNW2kPyg z`2Zr<(}#?Ex9ks$cEDmhQAwA^r~5u?se8oh>8)GJl1vgGz|r7%Q&C38oFZS{cOxbsU)Z zU&oQI);!QCU%i6OGZRZ3c?W90>l1O@2c_XMrqgPY`&=>UCQX=0S~<#1e{lFBNc}+~ z`5W!!L1z4;#7kf64LOx5c6Eb}2c>5NhO@`6<&{ilBHWLIYOW$GIBX?a2b^!wg2c+b z*+k(sw`*>M9HP0h)=3IWw>&CyJy%x;#j7B(WSX|C1QRHNW~Mku>>+^JgZ`2?*KT+l z8EwBSL;@pv6yZ<;AG{zcK$MLvzzSNebS{91^!$T{I)>$c^Y;PVKf}$9gAvW?Q07Uf zSo)mLbe=#|UwWuxapwgKUkKP{3~q9yQS2YA_hFdeHS)F3S+hReJ5muj|A~T5Dr$hN zC7zm|57J<_v;Rk-?|L@X9`>UzTSdY*)HT!R4&X@I;P8g+!D(>w$f5V8e7_IFRyO8n zSM4f600m(A{flq|u9O<=^XY*2q9%6U_Esu4v|2CDQIZ=PL#BNqB69cbG^6flzED)C<%=ykR@M7lTH+=W*7!%2e<+{gD|1K z?tTC(KGz*a+-s77tgLBcj{=%)q`i@ZbiMt8WQ^@Xe#mgSIg6-nBtzUcr_i*Z3*+7j6rCeL(2qR*hE`d+5G@SCbw*a-K{gqR~1!J0*M`qK+N;r{!B zgCkesC&M?Ua8l^Xbu01QSMTLBVDcCIqknQTC%3lZg(Sf9i9KHHiY4eJUg=$X#fT6y zvbds_Xl^dalJBX7xGrUMty9vB5A1F3H*kbamnEw0Zcs9U&c)ei%aO2SB(?AzdP5EEq7)hc_xq^nT>fV##h}Kf!I#i9x`RO zF^-KN&vT=!q6`zHMfWjew2qH8~53+QH)~fwIT4jsg&t1HD zu^Cvx;|ALGV2a4E$r%fpjBBJ(n|vA#!=F~CxtkvN!uB57!=ni~QZAV?Y0Jsn;oYiS zqi#iq3s1FnTc^s(zZglY04f;nwgwPUVJFZ3*$E(zYJfm8SoDzfD|i(J9s7a4bN`g?HRy4U%9>Lx$dKhQ%}1heLft8bCb5!bhq-u(er$s zx`F6?nc0AJY=)!+(~i(N?lJ|g80oxx&WITBQqQQ{4kNqxjRQIT>u%tC?c{a$E-s|H zww_!?%5?;z<3oX)yhvwB&?4X|(Bjgg0Q_qcou#!zXzXsA+T6cCY zU154c!ZpI&iO^&&DKBPAOg*PJv)ym)AG1v{ca)?0kyvygAzRc2x<)t>YQXIST{qnV z<%M$}F6m$`0IwnBW_K)$C{86MuyE_EiuKY3NRy%t)AN@Ze2va5Hmg$+ZG~CF_0))9 zr}R5EVS(hyU`j_xD9Dl;7FZ)|Z!{m|PkjQ3Y%RERpAMCjLdyx`{M~d#_fg{fMSAV4 z+J;AuyWE4m?Rgwo)%xf&U$*wNMS$p+ciC7qz{5e=u{Ng4GJ^&UnXRdPS={={>$7&T zQ}my7GXueXZ%NS=WB>`n>YxWe1lkiG@c1EQLJU{@=*XWkzH$%*1l$ntDU9i|6BgZZ zaJ6)>U7jf}AcbEaB|M0nzxEb~Nb;imf4Ch=p=~SPfd7sxZ1Lo|qaA|GFH<#KZIU?# z;Of&(j^&iTer1myxCcthF#6s2wFzy;|2kmI(d*)tM8pRy*y3`?<6>ZskrguoC)R2z zJq<7pr2u+i$FP{d@i{1#kmFl8k8xK8yGguV>aY3;zNmZ%FZ#+@ zz8%BuKEf9D56m;b5h=yXWhJ$@8q{)6Hj4N}ja|dG^U|R*z?4Bi`GlhP=Ybyl|?^OV~pM9cp!lss3 zeH2zXuKLFD-NLV?=caB{WTuNcXLfKZW{4`2{zlR1`}kJ-#_7ff_iIxMl*-=Huq5Jk zcnFCtR~F1QO0wmnwE&bB8%}9SL)YnS<5jUPWyQSQ=c*iRsxQ5!y8$<+1)NwIqANdX zM%0c}wb6@A&k)JD5M>Q-kl?Zgl$h_7Ftn*7QK(9D*AXv)6}W;{{ZnUd+E?hI2||$3 zOhh8|%c%;-BURCnH7$WxtAK_z)2YJL6m;G2cg0pmte0!&DTbt?bXU=7)x?*{7$K4^ zS-Q_yO+9V?Z|&(a#)K!16Eu?;72Te|2DXmenM6GMdQ@B+JNpHk#0dXC1$_mS&R7bY z)Rls4PN}7eqLEy>pSZuqCe3EL?<7sr|8{7y7%({#7#A2y&O=`c=)hY^+IS@$e6u!_ zY<8XR!K#~vAj~MGYQNZo)eKedFVtPkRJOn!x4@UKiC$~xk6Bc&q}{K`+4j_3zbAw&xTcbW6s^IyfZzqIUct2ob=neWh zyEdw;u(q9UzxG9InS*C8AcAd6w1KiJf*XzwBNicR;bLRZC{s~PxBfMDQ``{8p!vSiFLK=XTxf8=@J8RypB?C=9-JssAZ|Lz*HJW6+afAVNUMPh`a_x8a7op#W(^7RI_!LPmFXuz>&!?UWBR6n`VBj=AxH+|=bw+QfM%mk?9GCQ;bLfKjiV*+6<^1ug8%x~ zO&_iLo2Qnrz$IF<0Rs#Y1@ypA}yujEzVv2#p6Kuv0Xwb=9A;=HpGm{-k2T|lo3@IdqcLltN8)r zyJch|1{BuNE?DBjiwc**Njl z5GoZy+By>;usBxU+1LPJttm#oQZ)j-Y9UMN!aKO(TS}a0p#RBn3U}ze!E7#l7O+_sx5l*VnB7EG%E)n%mF_jbldk64&E1f2 z_GN=2vED0{fq5-+!D)Z51^cnKXv~~T^~QZxei5zWHfdD^$7EK0)wU1jn$!m%VY?!{ zR0nu5=8MsMi!5(o)W!_Ebl?+8L*Xciw$(32{J^qG2S^oj)VICPhtl_kxj*=_d4d?B z56FrH{UMaS&7VaL;zr!W;N!uyV;0!(JnZR_(F-joB;}{@JTHxz!t1I81t@~Vnpp)i z^At`EB?D8m0}p}WUkUJUvTxD^FQ2;nhSys*$y`E8-YgL57&|ygP1h~^AmO_#Zn=x=PT|9a^!1hRoqnP7pK@=wFzby@qOnTl zt=Sk9d#tXsB2&CUwB%dh$#V4%f3rQ-B|wQ|SqVtMjc-(=b~{;M8{PxQ=;W~)=3uqw zGF?L-5v`fW2kA@+en{#`IGs4^fu;sTbZ!6wa0Bg&_W?TgyF`Ry+iHrAw7hg^cUOEO zcr;(o6BH1b7G+AL(~vy$u;EV9B#FiSw|Xsyvt*w5Y{*qk)y9-8%kv`j4Oo*dA;b!r zd}-=c2LLM!10?udN2iDG_WSpuLChFNMY;Stn5EIbq(KEp6^mI;yd#u8+A*d;Kjr2z zs*R~l(Ml8mFR2$k@(LL*`&pkl=`7&iyLo7cib~+f6}dp|xS}wO`MyY34(Y4!bC>-P zK&Pk1Rl5dylBWm`q~@N^Fh6)q=z#i@qmKIXNSDi3J?wtExS@2LTvwbe%hlf;k;_$+Lj?-c0S23r@M*&Nc;8GOBfXCh!!5gZ_nHd|KtX~l zc|p>F%mPTk?tFinnzY;p|! zE%FB4q6{T3J~cOHnO z)jhjZ;k4xRRiG7XPJouw^V+H9GQoVq_m~W1aZJFq-)CUjYsz@g`ZsR z@p6$2u=KRXCYzQHrWIO|Rj}b&sA&rA7uJN+A5re9f(hVwW400b3X|y@oER^{SI&t+nc5=27T$AK){IvWV zTG>97))m6sXkPsfziwO+DAsIp}b`((DErF4`TrKS!Se!+Vm8WYYmgx9xk zAh(Vw>!UFUJT!YuMJ7Rb3Yf?J;q6Q7E%pnP)2_ua`B$Vmyr(r=b!QV2 zz#2A?STOeW+5O$}v?y88AjO!XqYN{_ZsGB(E)x@qJL-0~NBX@zbPP z)6u4{1_!pE(=)(f=;g?q&S5tnjjie_4D29%m_DSA8jcx;iMa!?Aj%IDM@DNGk67^XHq>(DoxJ$lsQzh z*MG)lzk=5riTyi`$Nz6kIe(svSktTV&rvDO81!@k#>VRG9KR(1bYIT*XF|H?uv1nX z(5UgUP)9UnYQYFx^q?s=jMQa0{uMuA6#+b6df0o&Hv>4AUkb=jl`M|jU)74%rBh?Y-QC^CdTtT#&?iHRFkCy z#4y8IQw`V9#YEJ}k#y6^KI6y%G;dK{!=klwI<4G&yVZ2uoWD!oH3o~~#>MOV<7To?|j7N1!&wsj2 zf{cMwduKr=Z?H%(*bMORbYBy?ifKbv-4rC3c2-1XE%Sh2?g3q*JbQ*JyO03|m->x; za=)CEp1KuwvvN6P5njM>Z{Gfm$pT3@3a4CZ02x>^?=tZr5K;PEdbxLx263?O75muJ zckb(F#IShfbJBAK&*1$O0b4z}swlhgR1r2@sg}>dp6Wb;olqa^! z#=JO{ymCHY4dr%zl2WrdQ-AoLn@_u!sP>r*_$q;2>q1SgwZ2s(#3k=O*a`_~Uf1ck z9f+@gKHVdfsQ{D;sy`Pp@q0;RP=d&Wfh*^{u$#gI4nA8W0rNqsh`{#wLH5 zwF(@PHX_oioK*|0zAQp%w)^$7+Mc0OH2H^dO)J=PUZeY=+dPUwz}J#~8E_Ul9e?d_ z*?y5^SnewHBs1P3ci>{clz4FGvs51ciNxaTil>0%vHf|>9sB5Hqh)56;2`Yr?5`d&0(cW!h^5R_s2nZO8>B-}R7bMP>! zX*3)ufKiiMb_~t4N=_$8UVPqV&Ok3|id1(%wpa8QbqvRv&xEhgfk&2dJ`Y$jU2=pX zoMYl zVO(9Ckq~YYF3_Tw^GqS;qxi_P`-$X3-Sm-km!04u#?YB>`z3$Rc?z7>#MeD4vrJIuBA~yqbxxC!D7%$8 z_KddX$>upVW0=U{2Ew~<6-&X-2S(fw6r!!6Z8@`}9CwXtSihwpv#qaitO zj%TJc&%YU?q@NAm(y}p}Zoy?ngM!cLNUjj?n00GKj&t8j3A6MfwW<%y)5LQy3_oVn zn>d6C^EIO?dE~sI7s_gWhlJG1rrC&D``EP^zxoLd0w{X0yaEX=EF=7(_~r(vKK!!- zW<88C(K)Vw-tI~~aQfF+aRtCcRN@B|Pgq90+z~byz~K5$0>(Hlox2niFXupQrE!BD zl?;)6l9z+fzm0I@L1P+MKwBsFA|$nVUvZLAA;Rq8SJ?PA+^M(0&G5|}jM>;}BiuFo zq{H}K8~%87!RPNo6j!%s`BLP(`kM%DaGZr$$YS9uW{fG%(leMZxP0IRVlMRr{@f!E z1yIkfQl-Ue*!pinD*U=ED=c5ku0ntPExH!Grn)^i(pneTIJfcTj%M5%pUy@YZwP0{ z-NWA97d<`O5W0NZuZ`x1L}y-P%+m1KP?QIBGa{DtH$?ll$gISIdh3zxaPt1W0j5V2T8i|O~=uR9S!LV*HG%uV%IY)Oe}cz~_h`>Ag3#5mCRNA;a$1Nyq=;i& zbDBg*0HQ{U(oe7a-6tI4BmF?0y1GO|qO1$hP!a4NZhxuh1;TsnCuwpDPz7{xVZP-m z6iRIl^Oj~DatZ0iz=5+h>_7m=z5oX3h3~Q$m^w0L4wTo$KdylzH+6VQ;WngxnAq+_?FtVjvb_kdZHGku@eRK3QYn~`4EZ^` zqSrV}w3roFiE9YJ3B&6eHUAxh;KB$^RA|^Qx_Zv9-z?^F$kW@nzhVo@v ziu*5yR&J~@G5+8~Sb$31GRp`PtM=(hZlmSsSJt9m4eRvy4BLO^#{tCIsSf(C#r@m! z#l>?BsuSXyR0d~v)1P7TG=>Cr_@B9`v*^n2z= z;nCDRC-rJ4QgPA>|7ASAbDqCqUA22U=fgBsXk z!CU3?)QQEl+m;N~Ds+;O4{nm>avZ^UAFwh-|L5CELi=3LA+FN;w(7brFV9pvPoB)l z3L-oGg5IGT5DRcmHz#37aqZ1+E{i#^Bb|oTk3TIq_!)=T7?+upSAo%(<<$H*YOL$G z&d@gJmX}IAx5`(g*vc6)O=L+?jWV=gg*ajVotP*Z`R%8+vI;Bxs_r`X zvDs-TwR(dF9}I760UD9K__?7#_RL8sx|~8hNb!z^Kck&}m1dz`kIAD$k*~nppy}k9DXdbmyE4!vn5-hxVy=i1P<4je4Q@_+af5ZMZ;( zt=+18yd>9^80(6Li*)<70iq{d$?3f24xk7SS--XU265szT51Y73#oANb#2fOAb1`0 zRp;^dQ9KQ4r@7+?_pF5<3w9%LbwSNYdJ!ZJn*AC?+5K{6-H^aRen4fD)$lmRar}Y? zNge<+BHO#x_3=TsGb8VyRxEuEqYleB0;4?AN8&{eNDq?AH9UJkH|0qgaA@~-pK45f z{n|GYe-xE8h8X&MU88*^c4vNkWzV8^yH4~7U_TiSO^?7UtBm(=RJFd1xe=uvgeXLa!AMVba2_ZiG1)-l#Z!B(R7)URYq6PdY>fB-pLM@?RR;Kv3 zsu2&Z^8`%VHa4H1(bVAMqVm>-2)MG*RF&Vs;M`RkP6z3H*=wbyCGp2}6m|!B`7!%Q4 zS=L@G%4ZU@q4d?WMb_-65|JAdl#VLlNn6!sapX$C(@GcbsB zYWBX))jn%LwhSr#okF$sK$c@=S6|=es?Nz5+7q z!*^%_B!TRDD&(*j3s74P_?cS=LWVVkTMKp;x6@W>x+sChRQkR#6TOYFvPTHFTyR z6z!TlJd^K|C6&x9Pr$GVG$pv#8$2r;{pJM?u&D=(1&R>IqHK+AT##VIC! zYXjKMQJGjU#X7a9^h-~LzBh{wdkz>We1%b)o)>-73uWJt7|B^<<e!Tl~TsA;sS!k6C=U9_Up0QA;L|s`)ZK9_XF~kH_Y8zh5H*dY0iA zZVlQ*X~Fw4P4x8faT}oy!L$uIdN8ZRN`2wIzOZB6@#FTY8_ zugDjZ*>v~a2}7}gkx4Ziy}@tcJ|SU?Q>UB^L+HFytzFnN{OB(=NJ5yNTB%|Od1R-R zC$T75XNmBRZ5JmEDO7{`6{yF@#LPyqbm(cndTvSP2L)huY0Rt zn+o=1`LQlosH7t2pNjIHnTU6LuS^gU+dC*+ zTd7x}De&sgkY@%o55d@Vc5zrR)^x;TeG)RKUF?-?NF-LI1~GSsUhou-2IDN;v|Z9$ zpGHRlgn^AKTe+`QV_)Jb33rsi@Gs!>!qNK14zg@Az3k3QCVelqF8%0+B8HWDWK2)} zo!~I!X&4?@9@aYTRQ)wT>z>fAym_4mP6lf4SsHLkG2^o zs-0~5B&SFkY&k4KuWg}ZyU4ziudPBu8E+g3{LtF-fx7x4#y}obtACJ6pa8d-e??E* z$~EMV8$<}f@wXQ{J_avGkF^15_#xZ|{=X(;?=NuBS)`XH+lz-Uks^Z9Hm5x?RZO-I>A6||R@4WY!ye{%^1OJVPFPu@}w z__?Iuz{HQZ5!{9ceJ8XCYw3Wr+ zQ9)NQ08#3HJbx4+^gt9!(>d;kOnN2Oji-EG5`UTH_$C!ippl!2wPjl@UAl&WKmgx$ z(&Z_GK)mMbutAsTS-TJ5)8`YWebC3L)v#;xz#Rbg!3*Y4)8Jy5X@`}K_T*6CWxBVP zf=A!;3`ye7+^SW~Sxth8tzBTJ%?J`BxV}HNN^tuX!>D&0Cd!os? z9eE0F%E0k*jPqyz*#9o~Wk2Sv5FI$k)DU_KX6klNDk^`O%U z0Q;$F^0WQP7`0!#yWi$Q0;{gVw z{S6%GwCintD?V2Z#C#Y52-7PLCh(C=iw%wqs4ay<=dgPlsGsh(b4nDhI=^gA#HvDx z{q=hlzT)n+1Fw93_=>e|$a6IGu+EHg@myPsnHv$VANV59o1RS5et^J> zl%zG}au6q6Ch4HFG*G;bixZ2UkwOPh;FdBW-#Vhb$e-2f=fWGUhSD@u+AnY3RstH; z)snIpp8AWd%DE&sIEyytsw9Xn(!6m8p&*=^W+P|2dl;4h(O3vrajn2i#^*Gsf?j1w ztzTSP0WVoAVATy5PP@IAv?jB9+NH;Nc=G|=i1#Q~xR6+8MfOdN$(u(WxeiVI>Ff`E)RFj`L5GnPe zF`B~$NGo0?MN9ayg-;b`TXus1jVD56O8=3-Up^wOY2_Ji?Uh5Ie#}j5+b?1N0QHQi z3k)LPc?dTuSG1}uEDy!A=UJWQ{r7fair0dBZ9by?ANNP$e>#|_clL0@zmkO_rGzgK z;}H5>ssORCSqRcT8oV-4%={5mKjeaDQH7{J`Ix$D+{v9eI!CvvEF4<>(fg?jy57KD z4UykK&{XXoQi6PgbO~z%uNhEwT?{43~qRPOL zVC}%_l#<^eAikG?*A%QB(G&t_Bf*wW6%#ZO)fou{vNfx`J&RQ)d?1-wdKS9D<9Y;g z_R3SKb4-e--#(ovb9tJRT)hAyq&0t46i^k;QHy4jN?r|OKZzi3^nLQ=4GX49~4Cs?4@Kl?JHa1(=rO75Gt=MA$JSx>^Bd)w6k8m@+J;3rK% zargRQsGnYcWW$9^o?EXQt1vuqZh-t~4^IAt5;qxYN%pJL6@mG-{80i)qH$Jyv%5JJ zUL*h&USCKiF!Wm$Gt2qZQ>WbGi}&Y)U+b*#de(dgbjFTqF>Q6|o-ApIA^Eekw_aqX zjozCzKaw4#Bl?rnrNu5uC@P_9{vU~2?MwMbCCBzv2 z4!&ZZngW_^m{|m*B;x~Auo%E(_bKszm3#PN7a)rL%4MlDICPY*`EiD%vnO?hOpFz&09V_ zGq6~15fA1|i$TLW&Cr^>v|^@q1aLXv%3274N4TFZHJU-F-zF$?%*?gbndXo+t#YK9Jd zl>gzs=h>^!!YCtf4Y+4XRE3;^6*pvDQ2A2763I@g+E}*aAQT&>=ktDW@CL@taFhQ# z_#Lk=tZW8-n7dGVG*H}U4)~>+pjf!A9Qai7KbuG{2DWnaJ>* z=Rtt2s2qsA9Y}FgqfAX_)Kt3aVBi~~$jkNj#6r5G?B)W*0?}JDu5c(tuMCht9|F^e zi{}k|pUUm7D(>zpS2GzerDsc7h2@s+y+wj*MOO^Hg$-`!Bn=c~Oy1%;r%@Lv?@_0G z9q;rjWsD#W(D$RSj|Uj)H!ONEDr}-wbO7nN^Mb>Tcg%?!kuGo|0)W8OAzsM2)wlV8 zMz@wCx`w?NJfx^c#HT zno9=`h>g`Ev!8Yv1Ev?EiD5YJEZAHL^|>XAWcx8VS8f1!1Mwl5Wy6uV8EBy{1zT`6 z9^aqinSTfTosJn97VAf7i=7T%$DY|+T9oTG%+17wYPEY5&?6ytY}!qaL^NC!y;^W< z*+X|}8}kUKKpk}_Dh1uqM?t1VTEOfeXSDi=4Vc!37|wc?htwm3Ibr&TF2?6t1G1AO5Kh)MVF&9O;!5bpnNG7SeM>Q)3iPbhCl4obiHRK!r!VnuW1IN(iPTak1 zEg$r7zZbz?qVfy=3O5h1c`XJ3yG1#%ow7Ql_4j~r5UKfx)_lZ#WfDR}gs)$ewua(k z&!w#Z8eG9&>c_$|-j>ZW>%_6f9kf_?u6sJup%|ViHRC0?FYMLA`?}koFvjOTkQdqf zcb*IaejPCBp=SM)+dABrwAc5ObD?dUx(4N`Ak(W7CJVfZfpQ+mpG%!Wd;8+qEEd>c zMTvLNzta-2aGwMjb5>01S(^38z5UhWem;J^W`8qE8=2vY1kV-Y`#cgm1T_rntucjE zWwd|xHvxF{wD`6T+ZEIaanJfL4v)8-Fb1`3Ch3o@6!?ZWrL9KrJ;P8_!5^j$>hNL<%A}{!e~vEdt%OOSD{M zCxW+|+@eZ%6Ad>MUGXA|W>v`L*kHBB6n!st}DAhvHSa9w=AXk_C^h zd6YQx&He&D_N#xSvIMcl%@VT9gquBRK4%8iHTo=5D~@adZuhVFS3n!{!WgFmyWBZy zYVyLYhXMUn%x#mxfvsRZiG)YkC+W00F!j2(@veGcVA zZKufu!dw(#R)G%{?T33w0`4$ZY|u<+DP-P3wNl5Zm%f)MZL8Nbtdz_---GQnbl6hv z&z1k~OEsx%wG-$%MWm%}7&$(p8R0$b4)-7e%``oFa>dEkNl_ZnZ&4oW8b>z%CGt4R zw5-Rx2M6vOO-j;yFr5^ z`<=<(42PoYfEr`GZr7?R{fMeXlIt!#m-0`bLb*_|)P^gfq@+eeR$6W%p8BXt>JHLV zl;hryXEWz4-w+hAzwrI3P1grN^ngmitl^2kG20viRXw-YhYf4ZYnLQ=EiBFd3RL5y_}#ZuJ3Y;|+M`$b&+`3SJKN6;N7GWXQ(4G(F_694JdMvGVN{IT^>ev$h< z&$kcDc!ea6-b<@J)vaOL41TjJPT;l;RnM(oW;vvCEG;Oq&wz-X2& zlZr<~VBr>@;5baDi=FP}j+g=FCBFpc5E(~UZ7rl($QOF#dYdID(>#Y|BoC+*(kb46 zI=qU*rh*K;u`s6`82*Y+DF_Y7c2912@W$N=pQgroEY;sF8fC)YNzNV|gz2;GJy zwSy*QjMx*p;|H@M7)?#&gw9!o{$)_eGe)3~Dz00b=1;^siIvQ$YmFydDcURfdLNFRy3bz6S^|Wg zw`aX?$k27U1ULFSX!>5iG8u7`1g7YO2{YcCWe!e%%sj zhpDR2Mg<5#(kILy@}Tep&uMaswrBB!-yZMLmvWu}7bwqg3J(lKziAS})rYU**Yr8o zKy!H_(rP{D( ztqjF}mQ_|2VS1ApwvKg?lByPOXfJVsZ!@!6sK-DOpCejCGeKMmEDTuRCdmYP|9Jt|6kmO}Q2A)`V1nwXg z;&p|+!n{DC>r#jJA!)UJJNBnBW0C{{8}&VE`oN>d7CzZb+F~@xQO$#aM47~p`XnXT z_pWa?!N#}EMV#vCp3=uLAIp~=4^hRy#Q|q+X*SK*qJ-qpU+VibUiFsWWkUD42e0a@)=nORF&uz zs>$~Msr1Ac35DCqtBr6=r8wy;w|j{KCMir+uNATn?IUr)B9RdaY#TA}YAW({6F5k@ zOGASbJZSK^T>;UUbc=yrF84YBk>}5~!>XHS8aoP!8KnxUc~RRx2C%*Sp&Gd?SX>*F zw)*2B7aW{+-1bj#V^ygnopb*oTL?9QB4`aUWAn4|SV59Yx4&DLtJ(Sty}qf^Mk)bk zPU}04r7P-A0pH;f>OA(vERVV7eLXGMNOM z#LUAV3gst?k*IW%D+krlZvaIOONfAdui-ygzA=H=AKY)i1=d<`Y9AH`UEb?VdxlC! zIoz7g%eK1oKQOa!ZZhqA7oW7~h;0?;!VR78zx%I?JeX9+VSB_o5h7TLe4*ShLL};3)DegbSO$8$=E+(`dpip9 zo5j(uIv=l2v@z*JiZHH9S=~!5PSb^99)^n?}wtgtL5(HN`v~_%qtu_W^Bt}11o*Tx)H1|iT%R>^Ra z7$~jzDtzH2VPDnvUoQ`Du$Jvl?T}O7TMfhq_77;;R;NywiJTVmumBp%x6yQ|Mzn<% z-~bm&mZ!tkq9l4|yU2D;10oo?KrZmU^d$Bull*6Gyg^3HV%68JsLQ9R*lJF?XM)*% zDkvPhP@TQ1bnkAVbwVLK_tPc^CP)mQ*_{CHnkbRb|s&6p?dVZEIZpz!E4KL>RmG#y9Q!=0Pd$aO)PDP6yJ zxuivnt%@(d*s{W*zWMOk$lEN3j3Q-)bBShB6~xq^9yEiyDZk)q?3JXqMP^UfS4oe1 zC525wK@x3^$Q)tbp-mDFIZ3C*w1s6E*X(2?v9#?03CAH|l~vcRit(rZOa%L`XH0eG zVRXD$eQ~h4){WJSm)``+a7F5_pTjI=p2%|rvLvz1Y~)fYPRJPmLS&0lrjjmfjr7Gl zJ|K;{F>wOd+#`u!hOme%X-rZU(6`*r{4x7yWBQM z3-lI5(9NPq>`0kV`EM>Jx$Sc^^8z>G*?&}vtR`WByXgS+jPv`;uto8{E$(UaQ)+LO zCJ#2L0^#AKxTgpko+;`0f~5{?l!sW;>4^@xWR%cGJPK~6mV1>V^Z564fmqLD;m_vX8K)a!H z;!s1F8`94I&ykMYf5v*bqFN+XVbgU7ptYvk23*k{ZBKw^0XG=1vM7LWx&gQA!-UV{ z3DSq&diD{$7x7i%K&%LSgHwPh)C{m^FRuVUvzj=6ELk=1&c*aMR(Xs-a(|GF2sW|% zlxbJqZ=9)Q5+w{e&wTw#?xW1d7rm%0I=nq`b}4=gf}yx}a=1B(0m}ur%r*WcQHJWU zsT#!DnYi2#u-a}7&J|2FhWm0ik2P0SLi8o$Ya+x^sNCQv;g-}?;ObUU*=%n?|O1LG?e zf_?SD#ERRyDVZ;mphc?e^99B9!z6xN%EB$#bCI0p+-BVd}pjqcU1w=Bjx}ivNi38>xh;An%|9M0sqLLl2vYZYC`N^+x0;j z%+8{;sPo-;d+5flyEA;`2(?%7wGrFAlgEwkF!o`-OQTsJJTGA1U~Dpz@gQB{tGCIe zQWoT%+sZV>iqr`*qEdBcU0EA`3(7-&;wG#s{)IJxHm*qN{r*qdrvW3x1|yPXBG<^K zz5_f8M*r(n(@6}Imf*P2jA37VoPsF?C-H2PW-^_2Kwo%7{b2(E?5wc_}v=iU$TYMAP5V%1d!T$jt(wBDKkexXNN!Cr8uS> z-E#L3$-j@GW0q(jgM-=ZKvsLoMR5N^Bh>H}y47yH0{@v$FhQ*ZzuWygi*FaoG4W$~ zT+Z;Ihy`6}FuD4xEt+3hDZqgnX%QH~9yC{Kj!u(<&|{xP+C0lUXkF>SsZtWL^{mJT z=dqR?4aK?ljr&r!T3Cc2sO-^z{<;+ko)>RwKKScinhi+JPGoHw*aP zK0BhO$K%*fd&ITDza?)0hV}*l3QDQ&q2}bep9i+HlGubWPmRwnHL?zYKY{oOWUk0i zlDlTvrUn;2jT0T72Z*DVWslz znf;hl^0^2lYUXR4!Tb~A_IKB-O+?5*>)*T7vig>8-}KlxGQp%Ha~afB*8Bv;ai^$o zi0+aA-C&o(j z?0mYpETe!L@4!zR7W238me_6o(|I!`w>>kn5tx#9SUat-aK-jDFUyrRJ4ciUMQT|m zq%v#A>#@n+R5?I9wesPg0iDHnz~`ui`nuv_i+(cT{Wjsf1KQ_${A|I+XwQ{dkpkV3 zIo)UInA^SvdnQj>ADy^c%8%T&d25|WXALDg|H=4PH|%K5q7?eMyKt`JRrO*ufDSY> zmbAuSWCa&xpup{wF=D&vE8ey2^!oJurplfhag)KqmFE)T7hL-BL$-^+-^ zQ1Te89{K<-;js&!*d9m|=Z($DJ1-gs_2jk0iY+GVbBDNmF+KDB>1GP;_Rg@noyY%F zohW074R!m-zXWL`ToHl}>T18z!uKcP2Cm}g?Cij^KAquZ%s!<<=JbSwx7>?VS`}*O zYS}QuIr(Crg%@EeDBtzE5*Z^T+|qsdb-D+l!;G5n*}|a!r?Id_o&EAr#TpFKi(j;^ zY!t?G`V$A!3y&aZsD2~KU4pkX_+3Dx8H@6oW#BNi7EJ1){6^k>9j=#RV?PR6gFw8m zlPc3#y(GWxZ=;45de|rMktNLiqEP+9M2#e;*JLjmW>~7o2do;-D*K$-b{^MAaGLIE z{(;^NKg;oQLC-=&8%mS!@C1X5d657Xv~k(jMoiIRwQ>3EGLKE{ii7TmG)k2>MFpiy z3dOtClBdM~@F!7cM)n#ZNdAiLLEHaH;SWRo%tVbRb=Pny9x`xPn%9JD{zajq7A_ID z4}aV$buvK0C`2i2>TviYaUcG8)N?@m#=kHJ@)4})9mn;M%Ell72R9#=ZQc+bLmJ(k za+AWIhv9dog=-qg8h8)rRa#-$E;q116{fftll^}2o>egPEPxsNo%gv>u!5^01C5Sw zn;W~QpL3(P6<~U(u%y=_jVb$AlvME0r8tDs;&I}9p>qKHtA@+-Y<&QD_UJB{!NF0 z1$BT!zX?!Lpb(_>LBGYXL_*2m2o*DpSAwoOtmr}CnEsdi9I2`H0lKjhpdNF~n~=X* zIal1slv-8=ch3tnHTlyBVOG=!Sp@y7-UpH244AP`0Nk_W8rT) zPYReQsNIf@I1~BWg!_6N)@D^Z>FmI@0_flG?s9Ou_8{ zg{VR|J>{YNKH*UY3?&973Y{({26<1IIx}hlwji{JR<$_Q`|6_2NOxx)<8!(Ig@&=} zS<9oMh|D9g__{&moZ~=jAX8L&b#hLGzF7CNB0MN}X4(f9_qVS5)qv)x`Jf@&c<*Ba{DPl`TWDL|O`meSCsj%8-g z@!(-c2h!?WRc(&vnPyP6h4<XY^J-cXw=wrK;QoXI-Lh@&;f|kq0*^YHpae%NxjQ^zAe_}QIY4!30qo#k&fB=e~rpbaCpe( zQ%v|D3%f7gDN&wsuV$JH`b=trK2Z&cf;!aq8b>YS1fN7^A1{*elHUMh9s;1yic(Ec6X@@A#RCKnZ#J|uV^&y_IG*yyAiMH1q*@1S{< zv>RZe;D#`5J_tvdKAjPG|7lr>KJR?WlPKlWI|pb zw;ER1f-PQ++xS8RbikL#)sr+sig>*+J9@Gv9#`w-h_sNt@mwm@dai@UJ?wl?*X|VS zR>VPbL<;sf`V54fywes_hC)y)QQr>Tc2w1X@LQQ60(@% z*x_*FY4eIM+8#Q=F?VM`%5N!bXt_Jxhns=aJE~^5C98ONV#I^x7phK_*W{g+J_1AQtmRf=)c zNryoo7k(g7ViM_tPZ?=Zey=UhRcl(QXC8U7-OAsKB9HR=PMgv?wu_|c4nFC&JlxIh zMBFL1Y~0+^?p>I#<+z1=$$OP9XJL==nI=u=bw2agkzIh!p7ZTemcO)2DrR-q@9}Qj z;=%PyC}Ih68P)2gQFPG6hxwXTL_#be$1WFGpnytcjfI>5I*U7EPK-%eODzDe1ktX$`&@i5#nIoE80o9sC!m8;>S~NbkKb`RF9* zUG8_#h6zqa9`7p-Ce@|QeoTS!e(gUrf%_c@43KQss>XNlB@@?ET;jJ>0mBiD8_qR3d8T3@!$f4r#TNvLK6 z{Vh$2b@})@<>_xK zt+17=DF&Ik--JP98q*wb_={P7?$2)}5baC2`90D5hoMFVpujU-YzC@G3H21X3~V$c z`jMed(9bfRr1{tb_K!*?x%UQx{_^xr%5Ntj_P`GJ$6XL$^2))Ps9<;VQXw`yRU(rE z`?Lq?z=zm)Msuh1!AJ*=bc6O5^bwltoP3TC7=FA5LY59@!2qe3@|4R$6;rEi$g(BL*a?yE@@{ z;*03s3~`AVsiO#60yW6B;10yF$rR|4)zvJbkm(;5%)`CKn^-O-px4GK1hrq3gv zfS{bshn(B5_FLM~jP&a4MiM7dOVko@tG>KQJQY7Oio?*9=Gz>40cr>RRU$n~+ncCk zv0fcYi}~B4lXG6WRACW2!$2AYP6LKQei~%TA3;9f%b8Cpo3N~{kl>o^d3bjx;i%y; zhZR<`5n@I2nJK?!5^wFLT_JY6{)VMY1(BH;^R#4rlFzc}rQiKT`3%o`*;EebR+7lZU@Z*ofObUBQGkoO~jdo!8lct<7$RhsT{d@PJan+BV(IelRoJ{xTy?IN?9+ zh%YgwjRDjSltq6C?n!VUgzOq-)~>0)hRyR`?`PwS$jU`MJe7(sby$6D} zXY6#4b^;SQg1j|r8W<(bL({BnjkR=612-+jVlL9vj!q+|al6+hEfIr~fzgmCnZFo- zj^yweXSSy0&Aqjy!?s)Rysxj5v+dzfYAS)_tPLYG(+n?mJa1JvAqe7Flt|E=w`2-Z zu_UHE0|x?xk(X^3+gjocNA;vmkstH{BshZf5l@q1Mh@)Ufczh@X;PYDrx<(1kAi_n z}7R0@&UKA~yc?gEdM;UB{%ol22tcoCiYg#up zi4z8UF7J}QuOeVgy@d~-3_g1+Xl4a|8j)DxpnCM;BruL!@rnFfz>*RG>~ns?DKrxn z1n+|q2;eFDDQ_v2+$SxKt!OY(Qb{z?)wIEjm!h$j^*XLLH%9(7*)l>gj$s|o!|WDY zTQ4<6>&2W@mf>#mZN-L{C4Jbk+jx>7lwj{O@MuEc;24QQ>I3I`$*cZ4tU22{s4CK( z>708WKriJ6NKO3)hD$9_x3?RwIH&jD)qf?|^A#>3WD3WZthG-IrTnB0L`$VGW*=DJ z1{u>_@_i?tki|bj!~;5i{b6aR|IdDXx=}Y&wX6W_nlOQ0=jZi18l#`QuTdF3)z{N< z{ugogUdg}+mOpSbSHWhRsYyH9q<3$U8+_~z%GMw|>_;voRwk;&YYrF;JojFREobd% zY-=!G|N8$Y!?+)X0!o647)IiL!lYzy38x4ewz7!Q)lcqi18 zz>NHHnNk<&6;MGw2x}G6LF%BnT@jPW)0_PU?NY}M>aZIiHpA4lVNEy<8(O3PoUSGL z#(wygV#J<|b|l1UGq^ndXOT$ky(m+n7>fu1%u@cV204)G&2X{;@SYJ;T+lAE_O3}1kE}92a#^c{VNA z#Er%-go|)h5rt+m+26do)ge3uD|=jP0a5BKW^13CB4s~A1Yw<8Yd4CZN^QNo6|h;l&q7Ot{%l*lAqESUBO%HowDPMGw}J)b~#Kgt|! zq`0{G%wQk~`F%%h948PDAT`92wQlsEe~bH}KOd)ecr5WiAzw7F(sf3qhhgja)~FiH z=RWlDreJryO93nClaN{3O3EjtJqv2LHmt^hO?IhH6Kv)rGX>lEWVRIwoUKuCEbJ|l zxjZd=2>zpnLy~>EI!K_-Fw(*}?;1;RsNegLURjX^USw7H;UjsANJap5jmaYo^XjaR zD>zJn>zlL&niVz^iAPu9+rwGEkyS7zJ$4$uv!&a6(68N!^lmdk(Vh(|qe`E-p88Fy zvgK?5Sn!vhV+;3#EF)3RShv1}Y_@W9{#^@U4(+5gZG%`N&}^- zC@cZQfNDw#MpxF$44l;Z{p(g3TSlMCo+!5=WZyYOCaW`uq7+x4`uDZ@m!paI@L{Fn zjbh49lp-&v+#>{QxU}DW8y&Ls+aJ}phV0iR-sSXH-sXG|%4)rR!P>1Nbcv3x2=bRk z^J_3AO1{7NH`tnNhXomVI8PCeE!L-!PoblkZP;?-@cn(eJJ2{fhZu5`g<9r+|3g-9 z$N%Ltw`{ThsWFmO57<+KXc?4jE*4@4ie5%Q!r{j^T8h+;J6*ho1zN8%5kNYtHJhnl z*LGXL#AB?N3rnx8;&A98(!_YqWylAcwdBl_P~frBuSRNkJ*_;JXoRHUYX9>oqw8bL zhR^Q240fVhOd6^(o|Embj5hyp50g&5xuNTTpk1NppE&otb*V-zBE9bwW9yu& zr!|j#9&uba!A>VsQYm(fWpe#Uev!2OGr_|XkUR`ppS{Kn@h_a%qFkaMNf@d}8LI(6 zG+`*I#|cH0hO1^~V?F^z0L^KHOLBA>F4m2Xf=<@N__}L&6i;?6$hp3N`I%d)@wS5h zLY^=;({}%n!^eQlgi(V`cB)xkc49FWEV5H^ zgGjzK_B2IzK0fD!#DGkX+87`?Lwp7F8)-)ogb_nEiP?cUQ)jb^yQaUqlUb)&)xT2{ z5X%ZFs@~V{Ge)QM-C9F9uQ`Q=`NQc)kgBKat8ng;rH4L!3&b?@x)C+R>C;NUg+UcD zh-CE?)b>Q+P3?z2y7=$|1P$!n;KTnyu1w-+vzL2v*gRq?b=gd}lX?6`LF*3Bn#uuj zauCo`nTa!^ou_;@ce|tN6YO)+DcAP_3*?EGW{C=Y zmDRgo;M8yoFZZf}v{8|$hE4?#)yfB68nhc5^h0aI^^LJlw*wUr>k2)b>O#u zaQH_W$xBR*KHm9efw{{!eV3y~gCaT54GjQCNiG z0qHjqN(JB29GAq~ZXW%A8fQb!gkIpXOqCMMJ&)0C(^9O=-ua6md%TH36ksmzsxvBe z>tWLN2O!?wbSy0tybPgu_KeqtdBxhEWZwa}ZAeVx-Vg_d*x?N9)N#MOnO&S;bGf)h zZN1+aj-svC;uw2Aa^gDtOxymM0aZeR{*bf!`k zrPD9)Rg^7)@jN&LzS9H>q9^N)4R!N{z+`3&YSQ?S=2uv&z9m-&4+YX(cURxDyM~|C zhV<2R4L~x}kArWBt!;t2QE)Z7pJ^5!L4J|yHIPrApNcwg`Vnfww`cQ$^ge1&+qlUK z9RD8libdAhJQ)pAisu}oamCMRM^oYXkFGmT*YANY*$UhWdMrp@gxTNXCs7$PQ($<` zkQzc7By$69)iY}PC@ViU1fqcE{vS(M7Pja0Ab@V^3;lk1M6 z2`4J8%prcg>LdqZY-zJc5SuEm(%0t0F7+eOJtjEGTHFrl|4cSSyp=C`nH2^+LJOO2 zs;w4~$_+g}`E&;May(v=KELmIBvMy*vwBXu0~&Ac^PDX!&ufL;d`v+mXXm7%1$g+p zn|$8ekjOr7=oZPRMngI=qh4L)#18e$U?Y7J%G4wHn`NLhKYqyilzv{Zk<>_E{?bqv zgAyi#+yrSpL;)f(@YO?j;!`E6Ai^=|+7Y)RYq8w|0j`*Vjjid8HD(T~-PiRH9HHzk ztJayw4QqZ@NiATgZ)<4~G{r}i7m21eK(BJ3S$n&TrC$lsVbk^zCOb%Cj-atQLJ;@g ztTCK3D2yiP{YgjXd)H`Rc>m^zpRUc5&x9Vez-f2>Gs#{ z1|SUEU@*<8FBocG6S2XlpZn_-F6I81Qd_8?xu)zwU6F@4r8FPmujlz>VS@oz$w+{H zeJ6`?=T!17eR06LW-~~Fkfmv|^_%gX9kwW*Hoz|c;EpXT>j1>)*+uRpAYrV(*#wYl z1!!XO`?3u^6>sM|2odgy)()yjlFZ2b18X84(a;v0PEwwoKgO7D^I@b9OKs6qZDEaQ z=Kt};OJvo~9}5H{(;uJOPwpHAfy59%QaP(CDme!|ny%Dgcsi6R4M#4ngBVG!n>tT3;9&Pmi>n zkfe+?xGkJ+2e%us5$&RrRK?QA5!e!jejYGDR`zSP$N#(DLK6Z<&G z&E)_d(43W{-|e4S@h`)LSg{>l5Q0TvB60qs&Z9EqbO*$F_EwK?*|US;i>S9B*jq;vywbxzkuwHh3rBwjdP)bxd=2||`^}qrxIm}q)&VJ{{7YB*MzY6(5Jl7l}g!K});Cr+mFh5G} za!se?0VZQF?0>-E;E*O@U!9R@1)%xJEr5hUtR4v=t`}@vyA%L>$k(uMUI0G)F3A#FEN&IaJ zq?Doe{2TDHVM);pr{*71@8!sHpoMGomHj0ZsCA14`PvgJpzcv)`R2!l2pAptgcWdI zrEUS#coNnZFsY0u7(Kk2e}PEFWzQ;qGu;V|+eg8*Z;nx15jRDoNl^RF6o}<~nP83Q zDnOkubc*dDqc-^ON04p4W#Oxj3`yJsWyn1-A~tWd@iJ-nG{lTU6v2Q zgjV)-=WDno}E9+3RikaY)&_i4hag5urP$soh(nk@G8j*Gw(_$C>2DNp2aI?k78+)tNdmDYhHI5D69i?MZD1>jFiv zPPL0)ajVsO9V9qp^XQ-hPR2Wl>sJzwAA#Jx@|nf0q9v3b$fu?}5+L~vcJgBZOEXxY z|H&lVhFAP|^@Bzu7v`kuDe`WMbyIDQcN6yeV^!lvk9YD0=iNg8zXtL`qe+XOVLxh7 zOcXE=Eys9;Fihy<>2td|bxm+{J&Bkgbtu?#pkY&Tx!e1-4|nLi-gUB3JyM-MiciM8 z)3J;wq5059yLE@&B@Jxxh*HN02iNE_%k7&LhCX3*AjqU<>84@4fYQ3M&%dl;mQMAv zTX`k?9!+J)#~CmN@((cE_diMBe&|8I{Q78an z48=vz;#u`7;u*h>?0{Gv)rF11iKy|d;5_XLVV!fNPsjDgMmbk+JE2hsa^>=M2_^L<(1&r9r$8`q-3TA2d?_;AEx)+?2i1VGXpEBed8ZYXUu$P8cNnH)y|q>EC~gJe zjVYx%?3d(bFd$yR0sh=X`*{?5u23IyT z0*#JsqZ*dl;8XcoNLoLaohss9M25*Fce$DDa;gmqVcho{;6`p&CU`U(AO2&RCm;tp z5XDOzRhOfUVKccLUf>+~-DzfJU^21RPK6aPO+x5BCNh6er;O19mhh|# z{s!dxRY-E)m!T^aCiD?&7!I!cBN+dpBew)B%|Z6~gJ*cat@U;J11sPbfZBNSbJMYL7y*b?Jli7sa5A6JTm^r1IQSjDq9owRzks=|`KOuKu$%u|N|L7TH zslSwUWJQEqDcgWpikJFo#joA$v(hhla>X^3G3Bf1D;QP+s=VxQ4-%?7;Gfw-=0)O; zD+8=}fPzkGV}9r^TcD1Ez;satQF=!L^n@m(g$lRaMHWPaC#=X*_=OOfwhi#d(`8D6 zGHw^Uxt})j^TZ=v7il;G!z2%p3YubrH{iFNzC?Ba*_dP53+Av}HU&2K$>O7T2H?Z( zc$uyUqjo6^DFEV{d%rWc#tr{_jKrJ%lmfYTt4|Z&W{=;D5%u-Rdw4tgQ{oeJ$rN?x zK~!;4(3=X-sl^Zx&ft0aYa}2m_*>ZRC&|nrC9j~DezV;2wQfCFoo@@M^`vyb1gr?~ z@qWjaI3JpuLp#D2TO_hsy~dzFf#m3h?Jx5)V32&06T+@JB(#e0;!UBCY~D8lE@im` z%dlYC`vENB-T1|KzVYxV7T*Lzhc%mTkz~_FHAyjAZV>V>zv64sDFIJh=^fq3>SV%T zub0Rq)if=e!Uc{4r5QwnZYER!NfUQXs6uOHmynm<$`w*L`Gz7xes6$6R$E5g{%xpfb%F6&6R1x8 zV4G{J%h8;XuQY@ZcMl`1!d7T@+@9lfd~WUa8D`l1+l$de^x}=Lj5CoI_R1OvKhBn| zApvDC0%1#xBTY*o%TVMvC#F`NAu3Ss#AX~|_vnD2Ot>XG6my)SAm#MKO!W&*)lyOJ zE_+_2Q|jud$+$%25MLF1TERLA_!l$EYT=avcB63&vC)(f>L2WV99ft=4oG8K<8p1>u;J13W;UH`wa}vWQL}oeIVgWCOor#C)NSrFH7|EUR)GcC zUkNZ5_VJV#uXNZ!`IrI}9u8%27&hWJVAy_4F%{1Tbogd-vT@?bRe6hOfpLYV5UZ5- z+~&NARJg0%A88#Xz$Y(v;GNqh5NrbCMb)yED*swIdd}mkg)|*!zW!3!vn9H)RAZG% z9Ll={1w6ynpr@FHEO1*d%*g*FYL<&~z;^qs@wez+|D|p;l8H zYY!w#FyL^Q3JJDajf4g3|C=>4ZtolrkUrt1anOy;qb-7mSMgLVLdeU;!76U%nfJV` zPiR!vnOAF1q#aU}_Zc)CG@8vR z+t)|+)s>7*OI5VKP#-2)zFKWOFHJ6U$ED@F$ovU&UdIa{V~C zenB<%zrR14>fBvTbYoqz^OD-TwEYZEZ^5t`gJ~teoI=Kt?>se zGQx!4sKY{l$qZ#>l?jG@wD2rTOmepP#R*Gg>zng)iG2LGlSeR246nqBaJ76CR5!<>PYDivA$ICVU&dd8#2M702BuT=#8C z?1&0jx!!%ar{it~p>H_fG|**jGf?cL`-AZxJ_8ukX$YVP_cyS57Lod{r**_(YfiESSyo z;CLt~mw{Rl?rl`7iX(G4lS%J=#j;hYjikC!Qq-*h)<(6JxQlYG)9k2tL_!DcR*lu7 z;cV5Fk@AsK;@A2x?a1Ltm+jr5h50Sq?bT*?=vHCXQy`M+T^f3Yzod+=WwJs^fv2}l z2uaI!SY7mbhTl%^T|&8sBbhA1dY0;~tZn<7js_Y0EOu1-`{v}@DdF_#2I z&SWO_+Mb0b^)`EKt8&%wOY*`fb^n>|qperW#qCE% z!@U^glm;U((wJ%D3CEX})@ym@qU}iNg{C44vSZi`WwozSh&}yPBXs>jR}+8h@*5ln zN>!Ka44Wahr8_j>lC@#ZR)b6Pp!~&33GkpQ>L&80d^k9NPEnBWcMnR}7sW@9qRW6w z5=AUG0mHk4tZnLW>>_31I|(CLACZ8KJ{un3{`QFmR?W66)o#Mgt*o ze0!kJN^Pgnr1@acWypqb4gYk5S=%~W4T7rh%{Ai_!Hm#0Oxo{KUSpi2-J#o!erPf-9%TNu6%Xade^(vvNiobA9xT!%3e2b5;xBMsBSkRD?# z;GM3Lu$#O3g`8!7&r7R_IfemM$Jg2Nw;Or$0 zps9Sjz#f=opMm>fjro>tv_1sLopz#hfz;r{^rtIEBonphX@{GdL;JYKu2CkIJ|Q;! zXg5lf4~3%|XOpEMd)Bz2GZ*e#aFdv2SB}M~N#@T+R7(2k+L@wEr+Xme#`5~cj##1U zBWgnO$LtI9`kq|V)MdkK6~Z!JLJL7?pvV{@AON>0VP0T}ycil3kK|{o=rts7L@uwI zlj`vi$)LtNl5JP*-|J@d9Na!Ke9YJb+o2_W9lZq8R|lm-jxtgI{T3I&dA4lH7>Da2 zIcLkFby2Ch_$fyo&4#<`^SV=BuUTR2=Hy(lK_XH#i zY|?3uyrjN33(~fIT-rR(*FGM?)CjRo5#R;D7D7(6sz(+He^iC8>IFRr0I8j z=#m~*C}p)l4g1K)#ZjYq0Fuky=NLQlg2#iVrFj&N9TX*340wfWWNb`8puG-egfMtB zO*7T6Sf;iL(%HQRt(u+<=9FIng~& zf;B9^+?5Z=_@GBGCGqhROn^=erBjdY*Avb#`v6>FhdzoudRQre5v!x?%}D{XG#@dDrK^U;cV06s2}B7~MLu|$|RPX|Zv79k0gVq%_8 z!!*SrBd*{Fom{@mE#a6>@Wj$|sL`pFw*!UiAeOjlkkvI}DuE%Crc^MCyPBsdvy}!Yw1eK$j9p(5TdF$3AO^)35m%qcp9@%+?CnE z&kRWT9S=gCI6)f)Q3jlID!JQO$HQtZI@~+UeV`qd)#HNRASyCKT2Ic%`*nZ0&4oWs z;Mu^%7zimm&X3K40ndB#hNb#xrs>mEzIviTV!aea7CKo#Z&g#m1SK@U5o`8M zeZYl8eoenn5DCQ>)<+F3i9i$Pm3dZ)bx;n1uhW+isjmr?!?p09$BViREJ z338RylxLv5DdOvmPCC-29H%5aOZa!+F=~j85?-GQ>%zGoivhtYEw#3uF}HtP!o6o> zrY$GnrvQG=c>!Ax%7>JCY81@>LeC67{P*ebgJ*6|8-4=zUGg3iiJu7l-1g)R4oz2P zuLfGDpE(31ofPYMZ5DxJBaryWU zg)xxa1QBJf;!klpDEhaY1By^!h)I{}31V&MV|ZZcEM^3wDWUDu#UznIV)oW!`#U4L zQ$?Jw=*XYWL-R%+uJm{66RvTuLf!wQnWOzoEQ;Aj{uk}M0NMbzaV5E1ENPt%;XFk` z*FBio3_oBq;`HGMmaD*@a{DQAb1m1c`;Ki&ZS=!)8uh9j73=x^muJSYi?V?eVySLU z4$2MIH-t_|YSp|4R*YKQ=05XHq3Cdx_E>B(I1*TD@JZ9?O5k-I`Jzl6@~*q3d%2v! zo=9g7ptV6W99EkH25zSI`epC9c6Gsh@Ffbs6k?pwb!~}>?sm7z2OSOw9};tXFtx=b zbRMMA87o9FAn=iB290~LYCOl_jnpTDvme$K9p4M00b+ABHXPz6YN`xSg5mLpBu>{Z%yYoc1J01e)nSI*qbWHsBn3pq(Q1^kIAI8jqK`r_A zyi7$Y)@=y&I8=Ry$&q%qvU_Cljv~Qn$OfPljCFX5&A6KBPfDdUcx8P3kV+arnBrf^ zsw#@F*CqIFRDSU$sXNt&%y?^-EUdoG(v|JXxnRKjBP?DFXk=hwiXakZ*B!}7v`U_$ z62F)m(=*RxOZSeEuzdPACQv8|rVw$kH^B*&aRGVfa7H*FH3o+>X~`Fl#;?l*G_0Ib zw3UpKjYk+6CvT=z&9s0i8py0cq<-I!!=A*m?K6|*0l|1>Q8C$BUU(R`3bxCE6sSmF zUE}AOB^L#()~vT1eAYO`Y^) z2LwP%*E!O9T;JD78YG{OL-*KxoFOWZxbK4~39m*Ww>Re3^e8gkOG)4+SUOLkkB)fZ zujIYva59Mr{d~9;Bp>+Q-+F)JS^*9JuOo@=994+42G8?k@(*&!e2d)7*I=SC5Z z>MtJnVR(;kzjLy61_^N%t%Rvwdm%X{5XW3g%e%UA;N5Gtql&>59DDdL=XeHRAL9Vi zU9j{g#p5i3O2oYJ+1i>>-8(itQ(_-Tk2oN}lfJ#Oo&HfSYQ`e5Lgk`IBeInu0v*%$ zM~r8#3!JMGGCR@Csn>~p%x)c0v+7})dv+^5rMv2*{rsUZl}?%?S;8hPn>-uu4y6vW zqR~&o*sS5F|Gh;Evtg@ocLC5qhy;W;H4*^Z(XRzLWN+eRH=@{L}MVpnx4oLO#mu!9q zEouMDZF~Fx;un34l^VldR{kXDP`pa)oqNVmC~#wd!1>x=Ijac>WtGy!hRAejjGGNq z7K(V`AUBSd+eOkuks1bPJm$#wJ`S0SCm@@lbF6`D{Tu4f0sbzpGqt+KrptmhGkU*H zrh#manPmF7&UAfVTnwspmpl z;bI^b5wGycU;9VidlCKlDHQK0`E?-*brD$c42myMm(0@$7SGPUf?c@T*lf5u{MhBL(ttgdQMjrS%_z-K5pV&6v`9opfhKHARWL!=tlkn( zCot%Opb+O}Ge`C3t@8%#GHp%|l=AXx*_c5i{U*!YvF^niqi28h+fBdK5;jibx=oV; z2m4Jz?11EtUso~BKkP!YbL~9N-s08nurUF}rj_n8QG)&+IPe0`aHJS|u6>ugSTUfY zXq$j~?af?!l$temf=A>bt9boXDu7=nLwo)cSSy`urlZntlb&aJGZnOhk1oydD2I(I8YNy_9fS+D^9#E%iWKgz7)|GY zk!RVo=YJXj#99CjI{lMZmOvfcqT8$OoXwKF>IBn%#^RB%hB3NT9#BA0M3b z`TS&$io*)zH(8BaSLe5O?(0Pla>57)Ji>LrC?hWf+Z?}p_p{62b?SmcS z%E8PLuq{uZosj`wPA1Rewhcgl))Q|!no)CW#-&=y1ZzUjJ1}+hvZu5pfvt&Fg=|ZvnP994JlTBvh<$s*_Aaaby9u?4u3yp@ zG`xv&w*5MLyR^serssPxx`9tM^`1WEIgK2x3a?UfZ@kSGUOFU-GF%#$LY)maj_q?K z@1ao&S!*HnP>K@42Lp5~@w`v2(K_Z=)CAdJZ_GBW62VP&=V|-rP=EDl?HJT#@2}~n z9wEaus=@d=`>l47hsWkd{mLy)!us^g5HDCTvx;8gPw1D{0k|ovm9PwLz<5UEh?4+p zQeu0Fjq1C@gsw|mZU%h-h1zN4u~G|-OvAy7n?QQTo0aPWej!mn$&5R9^>m@E_-!n$i3zxkj$2QHh)DUG0`3a##kMBRcT<0WgkMhFvs*~|u z#SP@;Lkq3NC%p{2^5)}a)FZh)U%=$3EcQmmu4}N-ATl@u#^H~D_A^nl4$uT8-~0#W z&YV8kTt)RYr`+S05CY`67uRxLB-ertWA|KUSwgu9+bm7QT8u*z6hW=TUB`^*gmhI_ zu}s!M9F2a%gabJDWBb9%X{-Uebxgglr4FKY4-G%SpKOXD7eq* zmBUK!%uFgJJJmNGIZ0*oRK14Sg=$03n3op%GF-a(VM)z+$7V7vv?oRwAInidnDb-_=S0# z2!l3SW>cZXT+K&Iqk-9S>ytY3*~>$JSRC8`wPxNbFb>{`UOcNAH9+T;D3wYIQNr#0Kok0eJwE=t1gdzLte` zSFgA$7^qM5X3pm3s%oYXMpXqhT*xXokrA?uqak2eGW;U5Oft9(C zgp0WpkZY3q&ZyHNG|ZBzo$wc}Dpj9_lHvk5@Abgh#6X>@e;({G5ovC7`KC%$XV<#BZ&sQjnmQj~R3cr+T$uG)w`bPi1RRwr`)qC7;}k#m>l9xco~|Uwlp^F5{*a z-29Ls?SJI6sd})rLr(_s-G)}1>X=n9TrjCc;h)8gDi1k41+MRbc;{pwV78b z37!NkIlWWtFR!m+DMSKv5BQBN5DkpvdxXWW^Hnz4(`?-AYs!A}B3HhUvtFS>w7784 zdYsD9E)h}&1>Q=iu5Ku30?~ma4`P>jliV{2vAW_$%?2sc`<1MyHIyt4ab@ghK4+MPTE16F&6rJy@H@ofj?I|I}mL z%bzUqVtA!Fcj7-3Dg%12++4O>#{cNAzpEb)R;h($gn(tL-^W62%_u_20L8M@AkFHs z<*$C4D6mw#obcS8E(Jf6TullvAUkGB1#LkAhiw=}BqGVd17rU+T`im&PST~#4uRjB z(OudGO&8hmCXLO+L{M7DEuj5e$-R;<3Lq;%YtZ}V3}sLpUSy@nvr>S;^2zwZ)#!-v zBKA^h;DhrIHrt&S=r#k@SY$F70wj#$?&r#Br%(d^MiQI$W6kKf&eYLR=_(hemvB+S z4C$_SaF$UL_d%gCkfvez!KJ*rFW zfm&2^B6h5nR+}Z8r4VImH|dhbqdM?7|8|(HyCoR4Lh*p{ZK?KHJ6K1Uc{?o;7E7Mo zKorNNyO0A2&CP}w0v4m^>f$nFDDcdg^0K)RvfW@k8b=`Uj|NApil%CuNViA8<_Xk9 zKk@&XH7E1PMPfcXo(CpGrc)d+}ZqeZXY8-(aG?`QG+aDkjd&hn{ zIfX*n#x*=7b>877+I~BL)W-Z&UR2GZ!J3?$GSNAX6LKd*-z%j=StVH;QF7tOeE77I=c8UZdqc-!X%j{m~J!t1P|+X;8bPmV|){070%Z=GN& zy+qQb=ny>=_|1f$|KoMA0N`?r?S4`BY3%G+tSFcufe=45Kt>WBW#N`O*W7`RA@h0C zP_#PFOOwQ<~SPKk0ZW_(W5;)ARZyw9!jEwtb-0XV|7jG`Uaewvd%?uNt--I?E} zkc0CrYr`M<52G?DKrI2K2@L1>!-+zSA%1fxvdNy_V)GDi0I6qr=ohQ2>wdPYySG?U zK**o*@#q>_%3N%rU5YIVo}i_rXttml zdM3l1u+V1DUVmGuo`zAo)QTz7p3M@RMyMCUGooJ}!NsRtnG6xJM)bfDmgZ> zG5nc+o+7n7o$=IeKub!K*jwB$Z@4oD0MsC$P8ZzOzCe7d4e)LNO`5srpzo=yiblYf zUjB)nsZjXRol;!`0^bm^`lpjhJsy_5u#Z_zFIpsHD1j?@$S7N9(39jUngjuVl5CY% zg7Qg^MDmw}?ltYwb48g4R-hUBI-Ifs6siF;h&V@`{BSlj=k(wBh+^Yxs)AnR3cKEv zLr3kv{jqVuF;XTINvJFZ^CQ%MZWJ%me5rL-?Fn8h!3Dm-8L43OHPSsDuEmIoN#+Oz zx}t)SZ&Nyyxbt1oqh`dr0$iy)T}K)^_cmtqe2QhG5|^$u)iCd&{ZqCYbdTKA0>7~-#M=%6)Y|_5&c3dPgS{T&~d*0pK3aU3Q~imy?{VZb@FvG>M&V1%gTcwiXp3h?^iS-9eoA3i8u1-?^Rlba)P8Lm}wbjY%S|)AFRhrT;~ZV z)QW~s`yyH0lg06#7B-W?!lZ=GBnFkHWol1vnC3g1><*mNsA)eRTpaM zBZOqR7w{x}g;vVTs{RxI>H78N`d2&c1`M&-g;(6s14arBW4^2Md(}2514WIsqEt`1 zc+>f*B^yw#7tts#HlJjI5A~?u;t@}h%$BQ%Zkn7hp+L`KDiEk`YP*Ng-YJM8|4t6n z=>}#(%nQdCm?SAG=*=s>@Ecz8gGx^#9vpFTT3(4B<5bl>?zs^ZzjVVs_^~Qbz%kOc zAq}7AnzarXrSHtEXh18wnuEfAA5Z4><(ViK!5LbisdSclP~^?vZ|U%L`zy0NrXj>aOzmexX_ zz66?G_qVASmB4C3hOiGV?kILC)UY3Gg~AMad!RoM$@nd2&wGnrg_QFDF6(!suRaZ= z^PTc2EGg5T%+wgJ>W^a8RmbZVWj0Adsm{~Swq5i?ivPDo2#niM*T4VeZa>>{H6#)U zNGhN^=`=r&J*rcJ1kHA|=?zTK~N>wA}OZ@iag8k#hFZXZfgb(urMwBFa93r*mn1_DLSQ+dFDLo9we_#MFgaZEqO zWQ~Z_X}?bJ;D0AfXQ*J-JYvn$)K9Hm1BLE~2HJ<q=Mq9eMcW; z+*Cq)xVtn3B?f<;OoBJng!EZYu`}YxtPO%ER#bDk^7BhsjlCfpyX-`>dksflPQn&l z@^#2^h5hX-cY*N&Up*09<}iPNTbWlq1_dQVgS`2Yc1(}N7LS%Q$H0_QHg(-JgWj%j zm4@LP^jgk08*;W#{6d_~^1Q3aTzoVUt%6P^z^yDtq&+#VDuI)ssvWWktI9h&XG9TP zjD&Pv{cwTuMa9}6y|#LkXW#?1Dt0Op7~-CQ5gk=zN-Wb?&A*6$gNrRWraSZQ>L!}2 ztObciA2EJvABCcx_$API``E*(#32H67@E6*KNwFXek{y}LK>@1{8)y*T2_d4qP4E* zQ+6#f5ni5aNF%Ryx*n zro^E#00?3KjiYNK;kw;FV$jeoXVeuVn^8S-rs!4+51I)BtQczTnWVdM=5xxxlo^XGoo04D0is{k@-B;k_m#9S9yfQlQ3y)%`JtIQerxR#&=UWXHVkDD6TIpm4sV4-Gf zpZ1qN1Om_jkn5b<^8uHZu!7ETZ2bObqy+gFhP3oCzp;-_PQaXCstQR__HZv1B;*tk zuA{T{SQG=2)OELV*>$v)J5H8B2P>1J4|uis-A*wewi*FD?D3_EMWk{5DTTUHVcLDy zw0+^!BAy^yH+~o^B38IMDv1I+wgA%YxsJd{a`+dzX%tS;BkP;EE3KWwqHE)p$- z5Mpe7WE!gj|D-&CG@oC=DKQd9BC_l8jQRM9p9W^PXr{7#2qr2YtnrW4uP^05f|>Q3 zv2Q1%luB2I_@PQ28YQce9tr{d@*l$Xs7a1F44Pv6{;+tGnnmMXg0_2p2n85Ti_?CX zt_TJUVX%Sx$NT`->KCZeumu}}7}mS=pGMVVH20Fm2Mz@OQOdKbB^toVBONYWeTg|< zHO$8G+1Kj@;1?!=j*1tN4W$c3ZA$(1t=NZ@t^$$oY#LFh9VD1FsEnqb`sN`Eu()dI zY9FX6c~gCCr=Qfh^Dd3d&WdZpbYur#`1yieK?$# zqFn1F?qHxwaZExVWdIwNruA+JH84^SFiC@%N+s|&+*nLEQD^0Ysbtyi)PL1eE{21f z52(ciY*~6NIm|;zOpSD}Sr$Gh(dRUw@tVcIx0h$Rz|K%@@rrKL^PDtHg}X@x7*F^4MUr^<^_#y$98}uJB#kaY&ZB`(=Jw` zd_F5Dm5kG_kp1@IP8-Fj^{D|?<5N={{lI;A#%dIW4cl!Nv1-F}VN#zUhl>Nog9^iJ z^=pnAR*6}nK(Pkm#jr-KpR`?cQYyv`v@U8Q z2#`_3z((+EP?XMMy2lE3_Ags2(A4s}5>nAJyrB4i*B;;YO&JH1>8CpzrN72fRsxKkn_0XORddtUjv&V|@+aDzBDRSt~9>)F79*+vTmauHrc z91xNc+wkV@S2JhCv#PTFE2fs1T5Ds*i?bAm?s`SG21-Y>A0SKGHkO7Vyflw3PkC%A z>(k6%F&|$Iih^DhL7VmrzOG+uq(_`j2ra=}!jev1J)$3?xGQrj$K9@XoP{MP1YBoK_N>ipa9pE{@bs5`e2m=B3L)7SII@t59o ztVjhaP01yvNRlLKxgsLtyr;>|rsvIe3z$ym*=JXrEieXfwr}>!E?URYC`(GW$00~us`nrSSEo=7h z`H5VW{j&X@erxYNI2xo~>^X9^lVaB#FQk=3L3N({XP6A3u|T~CCXUAF^QeGr$B`yC zRGsj(nM}oUZxP<)7@#%l?t=#-5SukeI5Lh*YvsQ?l4I!2>>geCw1UBWTQw{##|7bZ zj*^_MT=r} zBDGh{Kgg_296?rk4I&>1!t&7h(i#X4v$hIBtefLV5pvv-#sN^l;< zTma#Yha^U(8Yw?q#%fdXn??g1uphPQVwjq&&k*oD4jle*o{PhON{mz8ETZHu$!Be} zWRWGBymX!}8OxF%3)h+meN&Fq!70_w*|93B#IxhYd=>$tR0meH{sK>4!F*yKjjbz- zr#&Fm3k*n9mR{`DS^i{&9D0Oq=O_p;x7|g?=Bcq1Jm{r&3E^9hb-%{QJcfofin+nu zE~G2DxyO#xe5;VE)Tlv@?(sjhM!<9&7c<6^`QqFU^Lq^?2qQi(l~NcJ^{oF<=SvZT+vUO63h>KCBsWWLCb4vr)W zSmUs|f;Rp&SFqJUi_k^EsiaBeF=BS1cuWv#@RDDsM{5mSs){DbTi=vdeb=8cOW?y; zJ{o4_#wNg97VVf@H_^KLcXDy{-Yn@5SQ$?|F7ZUHocax+qlm4ft7@gQm|}WJUHk2k zMp<-PV|6crYU0oA%&n*FRrst3*xwEz`0Z+w$jZdm~@izfB;ZcT{)_;KpRa*Pw=?|g#tc}9!Bw#br~S+_)`AOyVbG7 zOiaCaj-;*ZDD73t-Z9miNiWIIS$_09H&d#=w1IHuG1Ni9Sr2*5Yn{8IVY-)*5#G?# zyut-O3;OPNoE-u92M_30QsFQv>H`z}I5px@BR6M29+jGa5P`lLKoIcgCM$7lfqpQb z6x1J!u(g{6GAg#gU>&%zz$u`+nI5AZ%;Ug&y4=28j{8Ol)jt~5zk@n{n-<-}*Hk~t zSTG30N;@{#rfNAaJ8^(@J63&mTB&m@2@Os;2LZQKL_k!WJ#s{4Q{C_xY@6Dk+~)7n zs{{nyabG7OR|N*#LAK?!TR2Po@8DZ9(Xm#n_LAK2PfDv#L$Nr^VnhHsSJy0TJ7Mfl zzNd?Z-07T#1nJE$vna38zTDDb4|H1+3n=_kmHh zQI^4hpe-gEHo94p0x*D%Ve&WWOTX&fOY(2`0kGlMz7SKxgt=Bk0vw*3L#);175QGx zmDr2HV>5)yG_nyA)Klo%6AdCwCMV9z)V_FA9L?CA<*wy@W(Att9X}m7IUx0#YRw+I z+-l8vU8!cI*0&U}bJ5!*p)|JNE!rVgRMdQIScaa*>1Rfm|i z)hdRN6;fPLO@heLdEOBX?GSgj3n5|dFy7+mw7Zq|?@!}s@MjUZjr*e?)SD=ON~TI5 z!WNz*TF(oETZk$jj_!g5GcwR)ZilglS^#fDA7gFek^^#=VjDh=ciUIcy`nqpt zSds2+%fZkLX$=Coutmk6CL&n&A(e*Lb1-s$kefWh)F6}>xKoY6kKp-lygqk56F(r_ zPFV99c{HIyeqY#@i=_oh+(kGZ1eC}%j?REVj12&)Oy_HdU-U~VUV@!4Lj%I0y5Ytf zcP0|dlG^*VvRmu;ts~hj%o&)_5pM#OheV*I2LG13nkFB*Lsm~&q{rHpejP7ac&|k* zK*s~hqkAK;GF z0&2I8I+#CFW$xdZ&qcjT2VZ1e(fd(dnFvQ#N(yAq+-;HnT}1}VG-hU6?c!-IoSEJ?-0|?}^~VxPZF|Mr&Bi zxA6bPN-qm#G-P|j8_DZf4@FDAF-p$RNqlRRynLOEpGSo|E6uyurRc*q<1}i<&WY=9H9;CzT-^^Lds4 z>Zs>xg4iNAB=HnI$}N16*vTcFWGC0EGl5N{^QXRJ^t9Mz)Nx%M5m2*x zza@7)l02%}fK=&o5*2_$(`G&pLFo4Ku9ITPU7LpXIOdAubzUt&M1r-<<6st7d=DWBui`Mq^jmyC9g>Kv{*1f7MNuO{g z6Cudv-4SkAzFXmFFmlW=ZHS7jj@7$IzNPHB5 zIsyWCr1IZe?VYQ_*IAyWvhOpHk({qKQMU27Jl<2=5{0^xXe2(bsv3|N#WRF}^ME>! zb!`)tWpN%X^sM-s`1-g&^sC(dy^Xpo4=)o$I|{Ix5E3G}OiB;TT~-!7Xat zMKatQ_o~wlp#*g$7xf1D0Z*lnx14XD#{Z);M`lCyg1Q?ITqq~=g zrx?Mk9&3>Od+NTK=DYf!Rc4#u*(&{3Qc{oQx+QbP*iWp}G2;z1FM(19n(CQXj~<=8YFT6l z-_xgX^a?e$pa+#NhRe$ikS^V2OFSLa7`dFZ2vhZsuW;=7cCklrc-!SST2b}f1kA?+ zXr$|HPteergr3V+6p9JBYfGpr^#DhiCm9pTw)0Q6j#t8Ra&?78>Wfnfqn0JcZ5X|9 zp$k?<1+DzIfNJ$U3USE~Exf8nS$J3gHQOmIm9 zl|ep~tXdzVwBlRUyYCb<>$UXjYBJDkddUl6vkQ(LbL^nSr0r9Lcnk8m8~e9{^H{{WY>B0%^_r<-mWzT-F206}%eZseldneA6AhEXxNIYJC8=ZJIsyI^b}G!K4VWwiq(!pfCV<<)~P{pPZ76V1+YU#5tb;+egx! zWrAJC{N|nwg?U1TO*$zHkL5`NJ}p)|=jQ;;kbgJng#Cb3P4Jz`)GQ6P+@rx671HrB=X zowNTk!`T$%0pbDNpzb?$kIz&BU`NUX;rjl^x%z<1u~nkDBfvNAfU(NspG^GL+K4AZZc_2Oi*dcUm8+=Xx5g8=0>$=OkB#HCwUSS~VBjo#QE%ZA z=}|YsmWs}{?nKTU$v<(-L6D?9MujB5frRw2!V$m?`t-1gqSuG8C*z= zgbIVQALH|l`CA3&PUl!&msZc0Uq==$vDsEt)+C#f!3|@b$G&JAxRw(09G5xXhzP(?IJmI^ou9GTElcDjaqG(qlr9#EeA5Cb! zBKcvAFZkm&{>@zdb8bIHkjaKFi=ldJ44{ z__m@?wrH(TM&C%6G9|!WM~8;sgCZ;N(v3y{bA&MtP=+|`vrPPzL(+GQka!u!PtlF8 zmr`{A9Yxv-u@Y*T8C*Ukt!6YN`xCmH1gH#yrIH$trYY4`G(n3C4|fIhFVC-Mt@uU6 zyfgq-0u1ifEX1;GRoRqS;5+NO|I_A#{ZWO$K=J*ERBBn@;&8JoPSuBZFY^q?OIk8= zvCs`gN$OGrh1rPcvw*SYM>^-QIaG`FeS>>Q`}g)qnK1(fYYV4J{ud9Vy=M0`6o~*K z&~{Hj_f%GFAl@8bnIT{<4|d<^t=@p~vjdFsY0JKKSLG%6lM}$Fn?JrZuT=9*ZG!x0 zMqNAm0zD#RJAWf@-m}bX!8tu&QRbAl-)CHNI)ZP|LN7mjq$xUHH2a zf>wquk+fX&Tz;f&coXYNbD5o&0orDXY|Bpe&~AGwPaA2VkM=wBl?JCRT((RS8p0O_ z^AdRSoh*b6Q^nnd{6T}!D-c}ucDP3)x8T?kG#pFW(|06Lhx_|?;bvGNVdEqfqAW+ezLNsCBG*dFJ-rt`Z&6Yz09 zA`3px{9PwZ{c)wsvlOXvsfTj82l$p7>w3WGzAB7bk@t4n1%3ca#4USN^V}Q@e;~Pc zrN`lnDE?1V$Z9=4&u%EcP+x=PgiWOQB@)TELj)d%X6j@e?9<7lmOMEe*(?2D7^M)x z^EgTELs7%_l1P$wahz;FPp8Mi89JA4E;#Id*~LsyQc+oxn7A0chz6~LX~{eU4boz-#xO&gd{DZxJkgq z4xWqXmQAF>Nx$BTLSGT0B-ierspUw7JI?8TgIhS5?}Yf_1ZZ>L>H+psPd{xp_rCyt z0K*LNnO!()hDBWjanscE6Gx%Qjc_{!_hi-qGrBv0BOnV(=Th~s+FNaBi0rjOY+z#` zYSlR$BrOk8&ry?;+YfPY005)h_uz_m+Tiiqjc2fhjf+jO)5`1(JVy87M^gq! zXn*lQ$lNr77O4(%S%-hZoRG?dU5&z=40Iw3paLA@J_5-$`mpvGWlyWdCwdxO%Su5x zRh20@$6P9kXfPLdLBo*>UULCB_?7DmUdWEJ)p3g9HzQI zFcks3FnW?}`CTo$V`j<3?qD`aSRyOaim^{yZ!LDmcpWyUmpkd+&#Dsu z{-3D&*Z2E9R3>)C0&Kua&?~y%;{M#ZoLDk*uF2M`3Q$%Vn4DiRIE)8X2e=!!oI{C0 z2pfj4V+Sp^wloDkB$;dOC%UK_Ojk41gDXY~j>C*7W8`?z6czIzH6XmU1`nY5x)Fc5 z%8D7!AZI%TF9s{Pj9q6NGO3Qj@!fwqJ%TS=M`nt86AFr|lw3xHXX4}3qrnnNxMKiQ zHbC7iHZ2<|TrN4NDri+ZDW9 zx1m#rr@;vk9a$%SQqL*~^=Z;GH&%4yi@Ocu1m8R=-8i@5n>>CDQpIV3_i!v$4 zdxFsj?i{6^Hq?@`o*T>=h~-V}eop*oMvPBQ#2ii- z)&8qbc9F6-?h+h_tqr33+*(yOI_@$92h?of=iK7s?rNF#FiQDgVi8}M%sLflEs?3 z6JD<#nlCl*bA32Y7MhcXYsACCwQd$_kWWrJH_w3>r!_;Ah>>s4WIXQSS}^`Q*Q=Sf zdjB$$G~YXxbQ2w~IrUEx{$pB)2|e z0ab-r@E9ENbF0ke2R+PmQ3ZvoJ(fWIPNg37oqEAzuBn)$K7Z2AaKax-pPk(Ux&1KL z?HQ9t2MOGsw)mp9etOsAOlaWo#s!wIiS__8}H!_RzTFOUg4 zYjVOb6qET}^rLcsRUY#C!bI=`%Bv!=SDmgHhq94dGW$U(KGRCeA%!@S3QV8pHw_hE zq1!jwmfDP{@TPOeE#D!mn!m$_v zF@&tSqflQrVeIiKWIl(&eHz8A%SKN@xY}bQC|XMeyV{TKDE3YHYb=3-F{c{$3D=#N zppfSv-$m^_=8ZN_rUgTj2H~H*xZ+gUA{sPBq0biyf#0K&qnK<)Ylp!10V+rsLccwi z=YNZYWwDvhucV}6v^Yv4A=T0i^u}|DoEofE~Y053*QV*G#`5{9( zuAUvO*QSjenM4k0iWEV^fi&w?(lVgaz@l`m6HV`05sFtS#uQH8d7MY%l0E2D_u!P@8%Ok{zHWKlgr!qAe)cy^jX zpMgs`93#a8G&PGW9Ujd$BKhs4S8sY9Sn;i;wi*wu5>azIE{Zj^A_xQfuB%WFd#96B zYgos_>)`Q-OV|y3M3wS%|KpmfImxr}EJ7H=ySjMVoK#JP>ncW0Fm=%`Zy=P^Iy&X` z{zov*_^8RxTlX zz16Iy=#t8NKNN0$=-SX@n9oL?9(zxo9k(U3shyK#A9J*8@QG&AA8{8~POVrQM%)sH z_{^9Vk6H1gKYqU^1AN5I&J>egl^#_=4umwy_3ZeX2PZRi@^%k@F{eD}s`!4X(#D}h z7Ww+&zMtL6#6#0Z9lw#ZPmGj^j>IpD-ddAe?JVbHWKZmaOF=~o8 zT>Ry(wO0yi{u;Ma#ce41f!7b*m`{4}fVDxoptm>J_qzO|o8 z^*=vD__+RMNmB#hLhaT;GA1Zibf@tReR;Li(kn?%u3Sk9_=a&kfz%9B8OAjEhLO_d zM3D@?DB38A`oxg4%beMv9+QVMo0b<7a`ljiFUIR1+^h`(a13fB3du0Cn@iiv^r6ML zxqJcTr9S9tTn?~*L$DZ)(St~)P_<7EiJguu-RCiH)~^Awj>56ZS6x3s(v;1Wm3vzw z1q25t$GRa$z1i zC>JOn4%2G`#>Sm4su#=CNQaINsE)fSP?B)K8A)EFzR0Di|!w{{Msde%#_N z*3|&C&JoN{rS>FHCWh|5WR;8)s%RVy;31SCunaIteUTB-E#EoTV9?tiUW7mf(>6Zz zinzEPY_Y~Al7J9SQTEDrv+U-}FaFVRgBp*A*vQAXwqZ<{V>~>_up%MFY z7LD&z9+}WBN;GiRIjYBo7>ZNxmpGlhHY6CCs}YFThvPDtLiMi??MQz>cY|I!))GaHh~U}Zjb`f_^sFO z^C;)5c48uBha?{dH8{73TaS5Q6YRa598q_e9&0WFX+Zh!ZAwfLxyzh{qTMcQC0M5$ zhmpPV6{Al(I_#MVmKBI z=Nv&&)~Y2z*NElHH87a8>|fwMRT4$YgdxCU zz0#Vk_VqC;FmPXh#ZGeo!BGbOu^g|-O(@qUjdWn^9GrL)4l`%Xeh~QveJM;3R%npI zSv{zkU+WgimN8h`DG#M9une4q+7zMUM0|(^r@9Jwjj|s+oN1NFzEKx`hjN37TBYS-S=bBa(}eyDx>hTd5BFjz=q(90K8_#* z0S=>_ykUS9_}F*JSwLJQK=bkZy;4YR`>JWW=)!?A8?VIJk?>3E)esrphbws%rW2q@ z6QMj>U^u~D5Z3kGbqT---quiPgoO}9)D8++td2csbK$D)U6b=M7p;X%)UyZp1mtIP z-v>CHl8Hdv*SF9#**JI+Kw_qs8GBOVta73kMKlCTFeDv;53onrB9s{)@ZIUIOgL0N z>9*$CmvZl3^Fc%TKu*Y@kjdWS3)M=*^_Tv!GBxz=ARMe#0}+QaPViSsj?4(Qb#b;G z5$Xmx&U6grJ8WDSQ%UaVAP9Go)|&RE6-VcCbhVbGNjq(s?u@(GQ5ZV7GAl51e~QyT z9=yH|F{0J>LGuM=)U{aIp-RnLoNftGR?Kc(Jc+HH?JKo4_2t*mf-vl0A37aZ#9r5~XT8vE)6y zrXOXPotR~}{!s1pvOxRid37+yjOZQcTTH;We(hD2#!|TTaL2%(fEKeZs1j}&$flCY zrvyvI!p1x_?3&cKB+yLxOHOK~-}RwlTR&>~bDSo6@d?V4P42$4eg|I1;Tn^!!~aJ_ zeD(-2CM#o&|EHkIV>*VX6eIy1@2$gB8{R7P5`HKG1?%=JDH*@3Z8go>h%VE~*Oq}? z4b3HZZ_v?yex5+Fdb$V}%-nbf%gED;1u-}lx1~4Y&Z3U>A|y{|tq&L{yco;+KC zB}i3**I3~@ZB8A2V4>_`!;&k>bzef}F@ISBYGUwRMesi% z6e`$}k8%#23ozD8ChSl}*So+`hIm-i(o|~}9fKGI@`;zHkc-qF8;|)mSYb@EL*nUpROC6i}bq@P zG5kK?X2IgQP(#^%Hhjcb2RMz=6dAtJ7st3Vz3&M{DG<{|*BmbE(x9c7a19;)>zr?} zBC}f5QB$doE=}Qr{k~Fx=Gk8|@6$^O;ODc}(<8c8-lba==yH*(5_!G`UQWdgPO+Y$ z8bk+GiGige>PL_#DM^FkZ$dvUt&d7l8g+sRuI6=A@!>Hjj3dg(3B?}@Pt8mL5^t{8lsoFn>xH$+r-!Dpu&oc_ zvCDh4{%PT0Q0{%_hR2t|Scm@vh8d*tgsk(L7PtTA!gm%_4vMC7VPF-4nP&s=_=OK6 z4ZLW8&=kmgLU%dC{ufVP^>%xEacB3JP>+T6Q}pR|?AcJTtw@0D8_)wli+Fcp+y+Eu z=fSWq9UnMA9&Lj`4f2Mb(yZ(hd8b^lAzX)m z_)A?%{bthzXz4irtHRMZ<;IL36`3Vk?r{wx@{oQXd3k)B!xm;c9g-T)HuS+M8#;Z9N*q{j?k<^S|`?rTQGo?=1DF zxAm&|LiX_0nwnx7m$9Vlpr1|~Bl4PWoJ8*}YWPFVf#7?GxK;*x0#DG%L5FFYEIz*> zN%D)0hr)o71w)sy#$|IAAIdVq(Dv3kEqLz+?$>k9pw^(D+w2ZBq}xuks^WGO7xYjQ z5@vQy9D=gmazo^*M1t1)h zS=`Vwz{-f#aT>FxDEZRjybWFLC*C}g+<9BwI^4c&D>H-B{CsGd7v<!2ZFv^jz+!KZ_~4i3MeRj^8O^~06oB=&0b;+AZ0DUbMq&8ddg86(o z63>hVMKQ4>Wx9u}kTlASM?LnW%=F>-i$y-NSe*h%32Pmfe_CT1&Pr%2|tGnCBAUPF-4_F-u&@bkh`KltXs%z|8E+Nv+BWmNIsZkQcMM?_> ziGz=Dza9(&HDgz=P31Q)FuA9*cASD`43(m`X;xqMca#`-8658meG>rhWDCT`EG&FG zjo#F^R4QTYMdP9yc#DGeCukdM7ZE*h`*h5`-eO;D{jvJ=aI3L*?W-0o0#UiyqWR1V>T55gOx%xzeeQTr$C+-)QiJ5>?GT{_QI`xiz7k z6w!OBS=iq4cvYZ?G5EVPls(lKJB;h5o*PtC)DIKJTRi9{$<;C6i zm&%po<8}q~8}9Jr1O`XZf0-3V*??2Y(EQ;uz=KF#o8+w>op55Eh;%u~eSKo6Yim&s z@_4XxNV8hK1e>vglW%PGDs0o7s9O2YbfjVMP&<-ePPJ*I7!nNn9LE;hg)w_t2c5$_ zt$&WNSC>6yXI4|vp!6Bc=!~0#Z{6yxCIYVPd(_mE{NA~+?=FG9)lZ`81Jfp&?x2w3n`df5R(F@Tu`;zarG+8X{QIn zO-yHH|DL8Yn<605Mya)7tSiMq9ScK*>`4z<_%=WQ5$^QC^4HXd4A2*dh(S^up>fu3 zA;%n!p=DtOZO^1q?6>HSS3b<$PYGIs4Whdc(Csu5O>(PjG`#e51m>i*LLfNvjL6@& zI3?9T->2rrfa4hvw92qQ+2hrzChdDVZ@BV)RzK3Q>w?)?U|9V^DPI7XX7t6WL}!$2 z-NdBS{pab;QB1d}FZnE*wWY0FQ|x^)XD;KIv;ltOaVo-T`!aD-7>}m0h~8FD^#W1O zJ*QDJx9Inu{knwwW^R+uxV|ljPk$8uOEk4M67EgXg+6Xc{o0vXv93Rg0=#ZOjDZAsB6KY&7KyXjkL#-W@jiNrhyZ%_{xA74%g*`Q*hwD2cNHL?H?Pq zF6~O>@Qe}{=InZjl~J7+1b3CT+wnkJ{6rCt7ee0T)|!K`u55si`g2sgMI~P1Rkq!B z8~_$mC8c7{$;K(HjZ#zX6<2_)jG{!^T+$Vt>VCUTwmGBYI770`b*n_B+gUrqZuI+f z1CtwTbd~bi5aqIZI~~p)uIv)i&xkUhgiMfkh0zI)ja$mU)4f81De_5X(U292N}fXx zkMBON6E|#ooUgQ^vQ{InWb@qgIsUMv3&p&8`FomNyz=tyt05%dtOR>`hcUg<%(nMw zz+=dwHQ66}LwkM~eQy%dx9fdI10iI- z(b|G|@7HjXx<(qgX5_j)*9+mGJ8@L{*^|^8>UYGC*Q4mZYu_hnjI8pjrmFculP#Z1 zju`(pYqetj#XLy8zHnr&(;}u^jRyR#q9%)u7}&p{YO%{4{K&EPW~~7tSG0DL7g1Xu zc+;)pI|<3^osYi#ky7(d#aM-gp)`GU$y+dBrdGfIO?AmkLnMt)r2UMx0P%2iF#t~? zsXd556<5hbiW9rpC&Q8~BXFSJ?q|vL=`#Ous2Zm?p%1`L;qg}yX>!ID_RAe%^1Meg zN-y8)SL48vpwDy#efuw4BJfNm_|MK=WxOt7yyZJDA1eMdwhR)+BJngP$Syi$YHtIX zsMb6*4>07DsSC3Z5u>!Km;_JH3DM&Ks{=IY5oImty8tx;cvN6;LexN{DI}{)-U~@l zC-=HC(@6ID_txB0cD!|&ZX{uZ(fP-wBLGroyjg?xaaRFGs=xnS$~2k#nu8BZC<~9f z81w90h-;ZcEt^w0Q(_LG;f&R1|BH}+4op|ux`N~?2C%e~5O5c2l9lUpm3^K>Sy4<{ zKCTVA?*0B7IIcGJ$^L~V@8xx`pS(;QKx+J>0CQY&zuTd(-ANUm1X$nk3@y|pl#3X7 zwkyX=QGe?O+_EgbH`f6!HCg~mzo$>sZYn3TyIymGmQ5xfLOEn}X@06R)gD8_W>e?R zYJ)xlMS;*k#+?j&*byRG8c@R1agx!$C7-+c^ckcFxG`*%(gl4$L!p=FK$0Awr*{?L#MJA>J#n0$uJnlb>Lhzr zxs`Nb6aeqYfdKBCA}&UWSWUm~iIgm1TA|>H^{O%UEzA7O?cfZGpV8Xlxw}E*OU*z z1!D9#NfpjwYq@gksw&+hu$VLM$&}_blrCv{Pn4*OEJo*f7hBHyaXbV}9r?by%N-S^ z+FS3YPgaX-7P^-bO1AvLhA>X9RR75VIi>tnkLUbor;t1;-cE}YB3LnDM4S{S{E1hj z4(TGQyu{o+uF2Z)8NI9}i4>SdmS+3gi4c1VJFTGv;y>g?syjk7ZQJ-f8ye3JDn@+3 z#e z_Jr?VQ3gjC4jF7zg0D^GuV2F<-aHyB26+XOi#842=6;iZTOX^2(dN68vc0fq1owE4 z@ar}DZl=xUn{~#wP(Pi$EWzI`K0{_#Pv8pLZe?!W*x( zyY*2}WS6a>=wWl9c+?ir@m6k#2cTGTglG;=Fp};<=)v$=q-_LOouWc$1F(o-uE)*!x|gM z>7pe!7_&Tb$t(1`B331)3s!cvww)C^22)r5goJ@c;g5Y;G0;tXF}l0-9p@_=Atb@+5`!cdxzXP_g#wEC9(3W*VG^M z9uPvC^(f<2tfp_AbP_lDkY+{2z?kT&Hy)0vGV;(A$*1KuzJ}$=+v?HBJ8PWx8X>!> zk=Og8Y>|Mcedw%K^S0smm{nCMfXw%oHEnXsuO6s$Jg(AqvQ4bh>_mG-$@39x*xyK& zYPXdp%>^9v5X%0_Cgy!#y7q)Hxo}lEHlI3$FX+^Ydj4i}2jNYpg|BRFIqI~DjUvTy zYMf$(mK>MpP0T%RR4K{eVC+`O+Jo55CLF@Xu}OWRybU9}PqJKS6^T#X>X>8$e>>RX zt&i2a_XJTY387hD?emygecZMdF(NE$n_Gjejd7L)v9#$pT8fU)y;}|TzJUToHTU`d zQv`$#l@8Oyp)wLYPd%4k%UE~h<6W8=E<@O^sT#7>JAD4%zZq*@6eG2w47C3iCIGx@ zz?CF}t+s(s1Q6X&VmO)4ZcIM$sv(jin^u)lhAwN==O{h2-7s>7b5B`>N)K+lgNiFQ ze4NOJev2u(PliM|QofX|c>~#^xhZ2M#A67?-FAX8T#ptpjcrTNZ-8k^JENVAPrChw@-)_2|G5@&F& zBgZ9))un>%j}K`Ue?)XKkM`-5!#d`LTYK3@X4-g%-4W=$k}HCG`7!3|j?D;i1sRh~ z20aGMH$5GvNAaxz6 z1e0J808b5`i&zGZiaBO@`2ALWzU}w(-ix0%_(#*MnV_jTm(YiR z&<%A%E)9fQa_NV^PzMx$ylIg!Bew6(+cvqf5yI>hkbU1$bpN2cM)|Ux<>B953ekI? zlK!ore`Q$#+Hp&sHyHk5^NbCyLqL6<7GA$V8@B;QJEmwEtuo~ziZWS_quB2cf49?z zrf1b6Dzo0bNLa_|2@b4kSifG80|&jUV^xL=X+pM@d6T_jc3Odq8&g2OErpMe>f=Ba z#op8x`)H6jlYvKYs@KmvioE*{s}9I%Pb%V+kVE@n!rm6t9VE!2Kbmso8!UhP<_llj~8)`ch0hC!(t4 zQwzM9(^DYwWBI*3m>cROlI{g+zC^)K^>6cPulU$#JAJ#LzDyAz{v^4wxEf*pRGv-B z$-I-bTCR<%X^ma>LW5L3IR!LkCU0eKfhK>K9XPT#H5%OhmhV-4W}*S0T1>Z*nbaj& z!QkC$Yh#RO1(u5|QdS_r5U<&%y~feapdY&6aktqp5sEx-$*9 zxY1wi-4@k{nUUlNNc6g06x|m&aVJPRi$fDa>1WdaS!Sd>@@wlA)VWv>EMutHeu0vuT%E zhD-{!q^2m!D;!Hn#B+8XP2A7!h;~AA0?MN&N;hfekSUspE;% z)cU>G&nqMruZLFQ6toI4gY4DSTmY+|zj_;>st{pd+9;yxZ!O_t0crr2D3Z`jdDVdX zE7i5Do~#rWdWj6G+f>=Oo*D38?o3Y>Qy+2L;kzkCBe;D7E7P>pZ$Y@J?zd^RY<-J< zhrZ?PlW(W66|vEJpik4}X&beG3bDs^z?H@qX< z(8P>I3Q0Cs+(S81FB+u5{tM7wE_q$Z5J0c2H;eTwZ|FaR9&Z$z3v>EJLx2s?!#I)J z$!05dWSj%L92F7oTUy7~>h~-os&qH5t(sBOGFA*2OI=;^APov>A!FYesg|a>aOJ;e z&6`l)MhYpMB+c(y=~_4L?8yUf;iv>~0c^hx_fAgaaaKPUaxHn4K0AO1GH z&mYx%WS3sJw$m9CZ#z_;Rn>?9LnPW`4X)@p+BKwu)rYcJuR|mgV4Z@ZVwYaupdcmm z8seM59&EOemB@o`#No2~-O=i}1Hb&saEydKz-!<>qqhO8FV)%qyvVN=J`!kKhv(!- z;-)aOzfrKtlRG{-_kvAkfTD0hd98erp!8L05Wvh>-Zwv3AEJRsSz@bhu~@W$6Eo{W zLlG-~24}JNkEl!0_jDFV9il)>4|*oR1dar2lF_>L#RqB3&2E0$Kdy;2vSVE1hQ`Kw zPcPTXVTjPkvpdc>k-MasLY^#oyWYVea%|iRJ=t)8^fpy{7nrMwY_`u3Z|~|lePx5{ zcD{7D8u6jjh!RQO*=-1&MawImW0NE)&SRai8cN>aH-c#J1?A?MZ_qJ#z-kTl;m755 z^(A%bRst)HywVknXy5qI9V13_%#T*eGobG+F|&r^IaA+$q%5W|3-Ct*GI~4!y1@Gl zr=rtrWKw-&sks0dCVI~7heVrOD1Pq?@)jY+F=b}dEHvbo*oKL<@gh&7AoJ`SnRDAR z0@yg`y0cVT(j9Gpo-Um*Jp(185?{Kq$@Iq@lkdmdheXXs8Y+NP#(vOHFi#@NPtto* zJOxxjM{6`IXJ5B-W9rlJI;Ndn6*~lI;Cef}aA0#a?(wnNEQn+hKIDSPWcjcTmJnHK z9vIx8wk(NsX&$m}@it9HVMV1Eb$&+29qa|~f_B8Twp4~3pM{5@;wb>GCDd4u-M?)C zZ&4#Yr@==Q(f~<7w!azVtV*0oL``CK36M{8wZ3kFt@c3EQ+%pzUk1i1dI~gNNB1$o z#_ve?BB_+!yr#9ka(rfixXlz{!JJ>g&Q#CXuDea3Khy-6AV?zRsfz5FaGx;7xRed|Ne}9`6%UJ&>n^h45#}sHSxs=F0?UA zFQ9AGqMd2L4AO^E9DyZPBOW)HVMCpq+C*G~;razM4U?Oo;T8hVh;k(mC)=W+w=osT zeXRZW*ZdjwsbB73#_>A83)k9(_e7}TJjNorzg#nF>hg=eqx`ApiI1>+@qjo3+?71M zp`gim!%?Ym(MFfn)Y^iHhQXfTC!L$No9s8F$3 z_k;a-1c+Z_gGpJ~!6SXo4k4@MgxLE9h|=h55karH0hcubC<$ssC05q~Ns`5xXpiu);_`-b5b?PMJ+BM$E+vsn!kIrTT}?#k zHdtU`fxv9zg(gyOeFuEBZ*lJNAh=UpIc;9tugU4Pu2WTJ8=RGEtJi#dJRU@S(0ltjTIsu@sFzu)PPy{Jrg<}E9DA~pMd z2a?*QT;1S}KSaL+xXA-Mc3coN)+5Ya<{fPV%%T1B4UsAke7rowRjhX45WRZaFW7v& z#mH;QLp}H|mfQ0@*a$Oh=WOan{C&Q;n}@4100mpPLG8c#iO=Al-W|(_jAty#~SQb zpEw5IXM~JWBDI1^U1L3oPd+o(m>eT`q8K5g@F#)dy4iJ6`DL3dz@o`Bj8@a;28cxc zEmWcap2ij(!zWoM^svI&`+>S_W$=oF?w$Mzi4e*E$1E9+g3~o6#(dbf)i~7M6L(h=1JWif8UljBfh_-D!&+g;W7dybZ@N)ae z?@FiF-?dh0H)$}Kg#wpm*$`*CaCyF{e5a3)kaoV`4PmKHXX?$ai51egt*0$k<@^Yw zq`*r6;TB&4H-~O4qYTPOn&(=4R8$JqM z-dTzHzTW1!)BL$z$I$qN6{H}_VPEG(Yye$m&DbKgq^1U{3c$;Gnbr^|7_QjZx^~89 zFfGGajc{Xjo3yGX+_NY+7kpWaN^DpvM$NIuW(uEv$5bg7UkV30v0wp8>UaaUnSTi1 z7DfSjI&_SW4W^Vbi-NHkR2@2hsRDOeoW>Ob(DPErS9$8`eIbSI?_>o9#4ZxWN+nVu zd7-c>rM>l3Y@jl2Viy%dHa2$xRtIJw%~ws?y-!c|Q#Cxd5ym+9Y@5hq+%WE$(B3TksHyM%n(G3!k4 zX4y{(Y<)w$|2>6xcId@wt5>x9IIvwoY-%22GzD8|!G>TSq+so%>RF+P5+Xw^II-k1 zdLrk|X+V_qe#g9~-`qPn(@5H%x!VD_Ps)HDFJ?XHM%;&7vl{T&O2CeLf0{15MJMZu5?vQ_^0Do=*6<0m6^68o zZw6ftp245DM%@MM`7sMYp8VMu%S#rVg_3V8z#A*6=JqNR`IivlhLF|*MB*3DwVhI& z@>Yo5S)`Iw)FN#h%iQfi1o#QWjJetGL?{Hz?*3ozQ5~z(%O>4Qvw*ABC_aL$$P5?7 z5`jX?wHWU?KuN^CPlg&c%fGW@qXxD3HE&DQ<+j5<^VKLcHZv|=nyy@tmxCPts^zbE z46y~&!-jM%_v*zke6CbkN6Z*BaeayjA}b*yHpKM$s4vzNGGTw{P3(hLaw;mFp7EM6 zzu1l*XbXHG1xXt^oto^kZh(Rc&kiUv)wqnP+K~6ts4z^YPU4+f!{T|d2@@XhN0m@S zUQ(~NwAR^ew=qgZ+Z4`TcIEj;CMsbT(W^as*p|_Rst-19-6 z38qljZ-U$c{+E4W502(qsID1-+sbgOu(?lnQ54v3HfmLWJ1fJK2kw*0?q*`jF26M@ zhEE9Qtyp}D#EA{9m3|=1sR@>dKk^7$LF2EW-F+?um#k+QF7!3X1YuI}sW1H7INkqs zpj9UaycK!^1q?AOy;}~bC^1zD=AYT=Cd3B}IxYF}_qEiI@E?nrevnUKao^1uL^9b* zkdy82iH$DkSuiK%fx<5+r?J4YU+w$x&9I5ui-q27n+yWw@QHi?uE<)$ZzBvY2>w|R zz)bkbg{&TGiQ6yA<%U-eA#RY5CgY%!3#yCwDHeFx%>8N@%>k5bUTUv=VMrksVT)V= z@2bSmPK{s{HaIQ262@mh_I6b_^(V~wyq!*@Pyx zTM&xMIk@3#KWkN1^LVA;Y;A-VDlK* z=%LTun0ZJ;PZIcWosomA&f|q(@9r79TuWBAEUcpKDrFJjH!1ZCZ8<+Y4(Pms<&uz=sA#GB%Ew&sJMhJ|#y5MZ&Jar)*@~EK z2+fH(@%M*);~tW^Lir*Z{hhT~_sQFPMOJ-oErcQd{r8Q5vMxU!yWCuh2XC1hK92ZZ zKiU6P<&tC%sM8ZmN5eGPpMO1QU>)tPo=# zBigbDqr>T*WtF>>hu~qP_n7t3CMd@{C1DE07Zb=15hL5!-ssDVbeMoOo@|TLa{5v! z2t@`%#0T+VT?^T)J# z%{~p`viP^Ra(g9MBE{+lD?wC1LRCl|1Cx6t;@zKB8X8QBPB1_cM@li#lZ>5Qur4@K zf8}<-I7M?-?;YUs+rwtRJ-OnSFy1Jz4FED~Cxg29MKXQQV4xt%P_G})bMvw@?I|z~ z6w3Unp7dOKI+#a*%SHERsPs&ul`s(*jevs;1{i$SAW1aXeb=nNamF#{h$$mwiUC6? z7x1GTfOgl~y+8~EhdWP18+nAjw&pu)Mqu_o z3}eC`&jrud4@^E|W5-9V-dFk;4q#I0JhYjDm>H5bfRnUWCK)K@Q_Agc&J?V(sMR$36L+50FH&V>(qG=QN@jH`P`k5p^~2d5Z9a0WU>Ry(Px)q&~uLFQG76Z5zwOvq^*rVfRd}P3DUOEpk zbW%R$f+NyWYv8v;x^YYpK}LrU4XXW(Ig)+zIuPCcFpkVMf}vVwzE+!K$TS{c;ygR| ztnhx)mj{ivgbR7W8(wKe6d<+<8lA2YEuM7-iu82=3k($4*E8T`fTZ$J^L^Opu!QtR zIVkYR5Qfc9uD8>ygxqI{f4ON(KnHpt^Z!1@HAXSlmM+AXFJDxy5P?2UOU+L6JC4RV z$XIuHT3(n6B9IQy(;(jV#uiM!Y~Id`HUqYnmi3#C+M+8a$XC5AXu?s{t4);My=gA3 zJ$j3ih@hx@@=!b5??r&$ZB*Uw%%yxdcoM%X0^!Iua+Ahrh1&N*=nt2!>F2WE{v zzO#CS5LPv_SVrB%^i9GLVSOZ)A0SynpflX_KFWizNBT|=!v(0k*<2iu+#P}tDy$Ya zfLm(zP$&_@8d1%L@1}acV}7j4QO>0ZxS7~UdM{8x<>BYQ_b}_>tZzs;@9qCXj3i7F zJZ8$7r|E#WOpeOzqL|9F>MXx!H}lP*ITp785_~qO-01h^jo290bU;`}TPO=}-Nyb~ zk8sePLpd)XuIv^W{%J`V!&=`hi8%HbS3+F>_|RKiX6k64_zSzq@R2-B74$DOw{KO+ zc?*74fQz~DKZ2_`0G)H_Y4eV$uUm+MOxXJ>4jvwZej}X6dYqJZa$SC4dQn)JI#W%NTnr?$_Gp1_GB?`HO?9qNUGkJsg_pp|*FY=-J6saM zaC8-H7XKMQtPP%Qz|xd+Z^LgO!H2RrVz?mw-%$jS2W@p%eBy#GY~)Lq3n18f{3?A@ zV0f4WlFoBDsAyP-hHlUI_-H~+x64^a`yfcWu-E-6+fLMZ`dQMpoc6jy(~;}g0nhb` zgXd6T4;ml^)xdEPAHY)G|CT`r%0sYfduuP`eBh{>0bTLhk!T~X2x7k*dBA43F?xPT zujJV+*reK3%&*GFem)=+c#Px-ttJPV@L_siaRU*)DITPS#r4-s#ssLs27+W@t`#@(Nkr@J4Qo z?wlT~e{)j4Hzdw^1U0@*V%@zIj)wC%{qdHVx!v9HxN?se8Z`BI&8;ER(Q5Ym#R=V43g^8Zw3^|*Y zCe-HSO2Bs=s+|_n)mtkW4swY}Af8W7HiYuH9FJ0`4 zT|s#}$FB|wcrFiD-uFIVCxPe6nlOSSfBf8i(uNpxeDoc!8q-dhE{Op7Yem+Y+ztK>~{ZT0`C~z^m2!hLDw_5q|v>8 zKO?EbHOivGqD`?>3szJiVE4^xROUokir_FUf+4Dlx&+^FNy>BC;pr_FI3MJ|eIR5T zdvQO{B33V{;WtnDaP}Q76a0OeZW^5%K8)LeGbWk}KA9hIvsYHTl027UvL{-hXinD@ z3my(KFh38xK69Ts*9pf*LD=O$%nSFiPZ?Be$u=hoa$SQ8RZuS>1wh8}Ys`R}du-05 zl{BMi0c3HaCY}FMVEzI<_rri7ydF#9b4J00xV7ImU>j6r41aC;Zwvx#a)&~}N6xRK zN)RgjSwFGpma_L}g9%WNb~>RyTm80)815i`5ZTTlHeIsdk~6N^p4~1W>WQ^79CWO| z-z~m!l0VI*A4Zgp!5-t_C-k?*{AVt#M4ZT6t)Xiq$9+F63qj#G@`zsTg5W!F*aH_R zt_t0H{VPu09)Yr?GUnBu-+eBK*dbx7hn!5qUi4KfDr|Z*HNibq^x4_;f3!fLj5pNb zt((rwI`kHpqh3{=Mq3$uBhP{R!B+vde8(I*&s`u*qC&&K!!dc8Q&^Qoz2O zI0dlCSzOIYH(Mgm0n!IX{&P;<(?6H{nGlF+I zBbdqa<3#GnRy(PDTkBOWpXg?mo0gmDc0Zha?3jA(uWjJNfe;N0*gQm~IcBevbx!MR zLZ6`Tu!2whP)E+_+1}KH4io1$&sd)zBl|OVD7F(~+ajF)jB^$I*>85tq1|2`4%)?# zAL2#Vy(Sf@Yr^hhIM^h~dxzfV@Qr^tm7**GnMx+!BcIk66eh!%yncgG^D6+{J~Q1UFLHAuRUu^|9%}!(EIxv9)g81dF$NAjT>@X$+XO5fhUsZXr_ zNdQ~;E2<#5!+6O_-+d||437}b;$pOHCrJ8}mf%TDmtVy*-#*o2J{8c+wc@G~up8!G z|9T7ove|UE;GkB$wJricOaI%A+5<22HA&*rTTTAUj5GHrEg0%kBz60>)HFroqv zY^a8U=qFkQ6`d{$Q`5Tl_-H+x30udM@}t1z%D_?<8K(i$TjTJ0Pu-qq3lRhTMu3>o zC&b_@s(n~e$h}XIim8FNLJnyEMTT!lh)vlg>qY~O$4%M;HB**dBy>r1OKpl?OAaN>z-~k^oiXuF-#lkq2wzC|8+YFdxuE0( zUN$tbBp8re@i2hw-XIdWxmbF|D#xu5a^WA zQ7}Jk?K|me9y-YROUPqlIx8|Cn~jdy{sz6m(}gk-s}zEE-_as5s=Spk6$=mc&leX- zmDs%wB!ANXicW{=v;N9SG+NO-QWiZ)hGv!Cn$rSv=9qk~s_c{gGapCFnl@`2pe3pVUQzKBG-$Z$=D>8IPKBn{#?pJ-rkKZn`W3*u3z$rU_CFXh1quSXyvo4u=ezQRw7HEV=?`(%#(M-{gey)M? z!r;D$_7ve$VJ{ZO5xwZnN$p`yf(Zq31&OUV)y0;ZkNNHY$1-XWes*I;}gl;nz| zE3rUUAfSEyXAWR@DjP4#KUx2xp0P=I3V8P@jG_^17>vMe*O+CWuswtk6VQ|VWjw&8 z?!lfntwv;^)>KrP2yKvl7^~6DH<0{YW)=`82_)sWBd*FBE4`%zT6vW~zT0UlM9+eE z;U5g2p8vzwT{`zo*@V3#NPrfOfJd&|i?ZV5)AyqCLn2P$Lh5m^o|aR90+bn8Z8gK6 zM|b4&2u9hQ9f}{QYUN&Z+qVT zlF!^M4D_mrx|)LvU2Y&GWWVjc8OR90W}*$0fd}v*RLhu3`M$|_b0x|x_%|8ls6>(JmvisQ^>|C zekqA>I)L=#BMe0HmLC?^6CYnhTvEnq(B+PcqfEiJ0ZFfMw#N=g@HPH?VYMi5!0E!X zQ_MprutL)a8=4OIcq#D2OMFY@1KxBL5US3$X4VDQ9q8jpxra6lRU+)rO(kQdK(c`v zg#EZ*tpdC)I+YI}z^3H@F9Kk1+Stxe7)dtZy*k73P0}3y+od{|sp351<-HV!CQ>?l zWWcYu*mkwwk)&6?lvBdPZ4P0f6_s(N!>i5cGHcFmtNq6 z^$VMpx!XDCEJ4${E2&Sh_|A*R#frLJGnV* z?1^<iD!FL0o#WYghIkSE|-@+XApN^*vQaRE8g|7hpJcG~GipCtg3 zqE6x=c)amJj(MJJI$d2P55$blXKgQPLyrwdaD_3D!bgpRqdul6iqLGUK5t6M!ssrq(2om}?%u5`GpELbw&N zUC83GC!Xzu;>@@*EfJ$DQ!JvOu3e)i3uY%aJrqkAz@GkK?(-5}RB=>XTFxYTPpQga z&IUNc2kvdbEde-4ca#_2awA+OAH%nRlYK=J}=XtP?iG5v`9YLvtVEhRG};EF~Hi#AZFM` z;xI%)e4TF&K74ZV38zwbmF^?sB|Xg$!)wBtWPNg0+Ir=!A3-vg#Lq)af)GA4kU_y4 zhv3T@^|zA3qOvdLyb;Et^~j1Drc(k#thz7vopo}!nZEmv$59th530Jn zeL&5AM;mM@P3zf60Sr9df}-qyoHBq>Mh@f3v5yUEs)7Ll0qryiFvxHIqs`aN z(PoTUc7=pIC&zVqs3+Zva2|Z~5IHLX_n`W+2GF&`%gtx`J1fl;?yeW(ut!PaJ8Z-)f_2Q{v1vSJG;Mww2BF1UU zSsfrTApS5^cd}R68+M8wRCzr0S0%Bwqf~*iDgO!)!g=)YgZJW; z*JG|VjL?eCuSY8EPQ%~BYsN&4=0!AyAdIR{!9!vKIwZ}WcWX##uF&1q4XV)^9S)uEJZ~K582jH z_J#M0#>iM;w$No*lRT!gZ?QO{53=#_TCF0{up9#Xg^SzTW5UE}C5ID@2M7k`lJ|(nO1)06hYBA5fJ(?`v&W?#nc+ zBDKaUCn+`%w}H*5snzk>^iO63cUr}nu%dj(N9j$emnc0`rpx^cxEEccWMZA_~y)DL2>0|m6+;JuX%w=AODjiOOn z-ZFYqfP3D-$PhGql{CZxQjE8qx*0!QfL_9=24sS+9sUiX3O@_tYqO7LUTqZ48_~n%l;7Z7+>*)aV=w#lJG%WjLJwzO>p^C)z46&mk(_a&-G zW**yWP55+#L2B_}y;TNw?!xmPy6y&T@tWZtk$tMOZL1hwYaTv!Uq%kP3lJK)}>g6A?EXzL6> zqw*_SC`lG8mH9{dPUlkMk_J{8oCc>oV8I*V#<&YPy&t26lOv@m) z-gidj1+XIrGGATWf1V3N;9w+Wxggt7Sm|0wudsaRsB@b??ar|$7+hI~>1I+`zUg+X zS>)wg1qk`a+O7QiQY&=L9$O$n`Q1}J_$g!wJAlh7Y~Qsz@Wj0?U#bs2OJ+il6Au3n zllXCXS@;Xh|CK0452^fo-us#`E>^&gh4X`fz-7cGQ~33fHZcXIu&S@%D?e{>>z_>|?6dtmA%6;?c{~Aezbk2)#}>FB zHtlf^!;4MYw{*=EJPk)yo#iriXt?Js=gYO

    *PN>&44<2R37}vM%vsw@4teirz9W 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≀M8=(%WDiQEKm*5-r-$H=qL z!J@I(bl}r3m~@&W5fOTYqsprU&`TWmzWAMz5v#T+#Y036#dsBWfWOMQ{`rg&aw8~L zMvWh-;{2}+H2gzB@|J`FLnxjTBKZH^ANv0N&}BYpuVDf4i93O zZ)6U03JH&{feC?8Bd10nkSJ0As+V2{gM5Nk5?CKq@B9d|pK?b{hAlYXB_X`2*@M?w z3&HABw0IW0MkW+Va(4*BJ@u($dirA?ihc^FjJVt!PJ~Z&_zSe7@oSSYFL>4t4pp3H z!K51$x#a>v-hEaG{4bMJwwtvdM9%-surW6C;jd%z|2Qlv(^lN%=J(fStgf~%Vp-rj z1;!}kw)zX>=se|ui)-?k@x)*Q1TzLIZ$&i_R?2#_FppjP=Kifn`9_2nu{CN%HM24y zBQXxMv7$SEZFD$FI9aJ@xA&`s0z0Sg*EhPQ*5|NiKfOq3T_4e4FqAm>c)>n!H}k~R zsJ*XxAc7Yg@Z&q`AM+JAhq$=5Qdelq{Wf>3RQ#O*StNuuDN_8JINvX=Pkk?t7}_hL z$1=lZW?(c(PDROU`?I(?vNUy$e#zu{RrDsS=|=Iqaf$xN#gGr28V8vo^=vGMFbhUd z3!ZK>boVgZ?F1ELs`H#BT7T0^apNNq1=nEOW>yS@sd{$@`8yauVGwzor+1H*9QrXy zqxn-xiIy~0WFMWyk-CaV95qr=2GMn3#sm$0T?V}fvlQh^^Fg@Zwi82J_=~eZ)CH_8 zh=z_i8XhqNsM3i&nB~{7_!G@iMTgIS6Oa!(Cp>a0`q#wim;AGB(ZS2L_Y6rP z*<{P942hcb-ED|Xhi38!&8$NSMvsGWg#cy?Ivr)ravm`SILo%&)cvd_s(q4KAQ&KC z!GNPWTO#0JW|oMaOkgpWcmzHRn`MG!kaH+y^+-8SgUfxqO5F^*SJhRYAe0Hs`BYb*E{5;Bh ztRCJor>uYi7j5Su)+2}MNl|k`ep>LlKAcAYJ^T~QXOZN5)diVCT{`M(B2b4^W+)hq zCt2Hw+@A_|DF?t=cQ`WRD}YYj#9L&*_9m{@od6~}=c4QSYco=nm=e3Bb&M6;_P@1^ zQY9{?J2$p|Zw5xSeBF5K)}v$t_Pcnj!O~tRYE8UxmCfR!BS))k@YSR0m87m_()U8B z+)TUvkSS;bKP@$_?{|$X5H*6px72boHt$c&>YK!bAQmt$gI`C}jTD$uL&Z>tAq@>ug2K(T92CAg=CxVgI!B=!%fIm^N(t4xs3k zmA@#jkH^>jh!(Ac902$MqFeQ*^RZ!o)&FUL45DsAwl6sFhCHvW8w*)N!WCBP`06b* z7UD)2&Pu8%AobWj$Du61fws%#O16iQMl?(Y$b}Y)NXh&E=L$29je__R=?nn*BWue6k;3? zcF(I-LMfy_cFeHKw5?(sJpTS~gssAL|0y`1%40dW0fd9d3?=~0uqcBf@=l$PV-)Ds zw;lRQWm6SJgHEr3NEY^bgPx?*SGAq~VzK(tj$!>+HI%O4yy4(u-M21zVm=!~Tk>-Z z(-;|IOkhJlQHQXc&{h9txH2@MTM4hy5G*7FDdFG$7OD1}3f%dqT|U74~+?$8(m`$@;TOu~Y`$bR!H_La}G@ z(WDMszKyEPH`Y$UAfD5&X|ST@ojKBA4bms783aHcJO(?xDb{xXa;&I@?V0L~N+vm- z=>|E^LTE}DD$@g!K=HoODd!}ObvL$N8pf&e&}PJ7OhH#O~uJw1}IK2Y@g`NdCd}c>#!yy zbj}}cakW0edM$mDnHFAt;LVI#%f=Z$W663~~Tq3*%DyS1n2HF&gF+k9K z&J8=Ixgj7qCCo&PEC=95cW_vzIc(C1-(l@Dn9`%cy%^!S^)^OX{Qyctc<`FHTf~jJ z$||BQHMcl*T*iHCait~H)u^fqp)>P+9L5EuU%9f;4DuqQu@vZ<{U3czWnk&LpFN{2 z&y6G01)8i+GnHH{L5gq*^@jDQ_$HWmr^GIc5S$iGzMNyX9VN=Y%In61b0|aM(A1&|7SUx?&9}) z^RfHfvy68X)|w;|cy^T^l(nyjm>pTti%^M+C9KxFm7lOmK(m z%nxq4=9TT*eRe}(u8joRoEHd%R|8{L21j>{=|*U@VwZ&<&W3!;7NB?Ws%fImsTVyZ z7X-40w@L8DBcom_C!lzgpcNJ?Qe)-@IJa(`Qg6}n-#gmCle>*vjWsaRxMAMwV)>?B zT|t}>)v-rkJxLnZ29B8VqQ8GD&(ElFV0dMPI?DPTG&c#MNu#EFv2Kju`B8f>r|fNkTH_H{E- z^-=_W9Gh2{z@~AXI~_QulS3&9sR+GcwW`WP0;y@^f#Q!j6KJW5W`F?R;Rg)OEioda ztwsD`#GNi@s7WTqJ2?Uxo{hHeLc+&C%BXUPC66J~C$Bojo56UHX-P8aI;JPl$25$| zb%ZNgQ=1%XlnHaojZIUhB z!#)tPZ=)%MtZcmKJEL1fqNeO+jL zY!xZ*Tj3t=jx9hjlDD^6B5A4GS~7dZf5Bq8JOC5>KAVhl`B zvXF65vFD|j0P>jYJsaCXX4{5TtX3nUPNRFzA(^ElR0LEXzauPLZs;nC>Tk9}H?mSR zR5>zm<>`?pHF~LLTiG(IN3PehEU}NtdiZ>Bl zS-f@F*cSR%J?q$r{e2T39xW1$j(8B~F{ub)y7g*Z6ZCG>MZh3*)mwKu3G6ZPJ?`9QTMWT^p?wr%tPJ{H8`~+9iS6 zIb#YrL~g3eMlMxyk?F*}AW7tQd{XdpeQ#)dIVsuAR5K(cJkoP2DUz|;39Dg}_my#g z@A}+tc6`%Gcy<7zz218+b6}B_UHwVT(Q2ta8NfR1FblUv>|pC~o!iRqA*0BJ3mhMb zw|N~@n7;Rihb0*51MO=@pj^UcD>js~qpx=`3o2)K*)n39*p_EUNhB}v0o^+E~PMABTDrQ+jsisU_gI| zmw*AULO8Z#A2D$oPH&-OlSyxUT0Cu3Ag+o?&{3oo(td6XR$)cFxXbf5@3TW+nj05F zHTb_74XL;-6kL9AF3>~O<%?OP1_pE(78+CK{gCU)(PEG%=A8x8j3Rq(wJuEZikd4B zr^LD+w%L;ky;iumB*OuCrFZRXp1}posK!*#vf|mo7iPpdksSu2(!)aXsP*$54C9^q z7#)UAEjMyXRf5MaKjF+=yfG_-p2xlch#5P>plbQ&bJq*Qa;tBK&o9n)lXVe{(r1)1 zt0N@%4od^8Elhz(^ir+e2rUu*h>2rQZk+&m1}Uxu(Acvg8aRD%N{(iu{(&s~#|=H= zF|wR3u;{kOGaJct743TTHEmb{jf=0-;%yVI*@mfj5qV9>abg#IHntS1Jg<#ErcVtd zFQ6TWja<*zd}JvN5+sI?Us|5!i5r=`$tBtMk$#}Mc%qAYiqYxi}13Z75^ywuH=A zOVZo)e#)qOwoTsJ)VJ{i79J2{xfCg6>lvaRE=eU_7RBff^tld8B#<_c2#xhh-QUo) zaaFdphK6rJ>f;+PTB=neHRbpSd<55qeP{;5V_W!6CPF82d54j*t|1McoAd3Zo z16Lb^W~*VYr~GF`@bqb5K5tBnnnMvIBUq4nfU$npqSsu<%-(q1sew1ij4$u3We54$HE#hmR+=G1-xeW4C81#h_(=bK8_kAuKZt>d`K z?=g2NY%4~JzT4@dOU=d_F;hgBsZ&C~s}l3New&XQt;v2{;$;+1z`pPCBf?qI$`D=y z-{F*5$vc8aEF*%gN>=A!*_jVP9_$dUZrqnMU3D>=5h1y|3JYpO-1`)1A zk!8Sl^fNEIq76ReltV-{jMp$rg=sPp4s@*VE$9u~X(MgfXL!xMIfa-4-NjC=b_LSi zSylQ7xu%m02u5HxrR@0~5uM6%YEMrwDtAX~oEE!MD}&3Tzgus-aLUM;5GWe5RBx{RNtAL7N>H%ODL23#`*0snLA^21HnUND&H$xGaljggy{j^2d}{Y2D=N` z*XXmdfH?YA)*FznF%L6iP-r`MFIg_uePXLZJ}*61e}8QVk8bPiSt8oC@93~ck(G!A zC_Bw5lD z0+9mp2wlJl7Opd2nr%%(j&rkIeG}@*NK}Q-+@dCXNxoo3BN{|OCl>s3$D-0e#fTw% z>A-O03xkF(tnu54J?3IiE$RDPdg6MFfbauZ*A#{zb6N0=a;{klU8Jd^j;1BevsoZ= zSa2NlCN1ERErGmstf4l*>M9XbHBS7-{Iz^Hi~;Wn|10szDere;iy-QHEC0Tdc^EaXS*o9U2$nN8s#D>;mPO9Boeke=Ms z5+dhlj#PfjOa{Qyk`ey}SPm1iF-~hYd$Lg|mQWrl=^$^UfD@R0k~iU? zQ|=8MA9mj-8{f{!5OP$1HgQKW2kERw+<_rX#87|%GV0rV$$ShhUd-*omt_u|9Wpi_ zfJ@;)`qGO!5R`ejlmXYuW1fPe%WHC7^{qqyCT15JXZauq$<#aLKHmH=rP!$>gx2|o zPZXE3L|NL|Lx8$44OJ%h;*^97S*J*>l7Z}JS;2t-x>ZlDPz0!JVIqG)H_hy|%af=$ zO{=Sj93f0enLvkE9_!r286LCyBocD=qG^FwioxgN^W5 zDM2~*k^oXJMQUMxzYS44|I)UmLaYsY=j+u?T2cy#DZOJ*y6e@fDD0HUD3`4^S2Ou| z@%3(w4=hclGh7*=cQfdtw8QeG)Kvl@(Hu=J@O}UR8PtG_tZUB7u>sk4VjCqbnJ*9= zfT?jwFzvW&XG1av*lxO82WAO^qEP?KkV2kHZiK!+whg|`@|(bMCPLKBj^p=PVPN|i z2@4GM@*zkmbkFrV+~0OyMoG}w0h}hAx&KRV-=OwPWc-V6+`ji}qgHXHiwsA@5=;J% zJx^f<9vB2e=4j8Q!4fogFI;y;tU-@CHq#V5VL@_6<0tpW;6DR3Vn1=n&QBPGt4D!q zDouJZ%fayY&bLI(&b|Tj(Qjeee6^v|r_Z=foTX3+ZXDaV?R>EylHDEdIIn*t0UWW^ zl8_n^lb8k<^+K9DpRGa_Af%lPly;Fgb-7ewWDj$WU_Au!VZ(_kMeRyA(l?9~LE>4k!nJ#W=jp1nn_d+s`uRtGPwk?V}glynZg zTXM#e2&CSK)GSzh~wAR4NT& zJM$&Zj`?Z1%`k{JF?ozxNuehX6su8JJa&A*0m_5{I(hP<|Mg!3?BkP1>+|q{VZ@=& zVNq21&q6*N`XEGtbd@K*bl_dyrZ|t}IfwF_u;FQ*zu6aC)&UI<6@@4l^Q04VmIL({6d-uKPCPHM8pes}x z7cBxKmcR{sxYm}!lQ6t?VMguY;9T|JlqW1$|0qDi(W|lgC1iy zR6rjdCYJ+h64Q6Hs>Ve=G3=?986F6leEmah(Fny!+!JywlVb*feH1{rAl+WdY8i~9 zW7)nlZ&a|YCsXs}(A5}TZ1@vNm=wdS{gb6zW=d%i)@ucp;pak{I0btqIXOlv=n$dd z2Oz6*K7Dmmb@f^oCI3THzzy4LQTP3}S)szMv9elkoAh{nFib)%s8!u$1N`Tb1pcJT z2$8fl!?;zg003!xH5_l@_cWU?Gb1qlu3|g*rY-cFle6cfBY$VySt!E+E*frs(v}9t z004^F*%|ir9Y8_lkwp~oz+54}*qH&WC&^|AIa)iCvlsQSezRRgFk{VxBD9(dJWG;D zkvImxfbwEO1;Vls&<#t-Op8+|XG^d^EGk;@deS14O%?3_6wy)Lj#?l zYWF4QFu)G#*4?-B!S$y0ZUfyu{2Dn1VB@b}3^S>j50na%t|qq)zal+xWf0Y_NI%_E zWlNnR$#$|&(o#22+a~!y$tyx8K+h_e$9x>agEg=2`o@N&oXOP8y@^GH&Rl@t_&jC^ ziUy1BWwmUBu}&Dk+43f9BK&cbr#-2V&SX`FsUi!IHxV@|BC5~L?IMumj}(~Xv8Y`^ zCSt*!EJTw36QaOgkb5frf)Axa>4i%XwvpB6P_P)Zc-DoR@a^fXsgu_z%pUc}Ih>`< zdjtrIwscYQwP?WY9F#7t!${l@d1)RXD*zyuY?-L0 zgf=B#)P|*SMI|p(z|{Pg;Yyz@&$^FYx2z@6UGV%9|2dTVIrlbLV@q~aEp9LkP;drH z(mY{dUHlI|5u2Urelb`p9zXDz0Ce3Jk3o{MihYGysXzmI&U`;kL)xkkw%Xt)UjaHi zG)s-S6_jQtYE5l+kYYpw*X2T}QBUjqZv4QDhr0Rj0%{?rropQ(7ZQ@L;XMACq)od= zQCA$UVBh=zPS|Y`Xp;nvJHKqny{Iht8e^j%`d+N78vELJ*V@-6rc(2P{vmNh56zkJ*h4P z-6r_}6&hBq<9|HOpS5q;5_Gpa7_E`8J`B2Q2?Z9i4`(EC+)6htb5H0a* zf%DVW>%EU}zQG&pL|iQY6>%DtuKtKxsvnqNt5Z^C4Nc@~RiQRZ-S8&-P|KmR@VFz2V}bpej7cZGRTd?!pqr=uVnsSV;oQ zE7r8Ws4U1GWk=Jo)8x-5?#v-=KAI}x{bs!y} zjWvC!dfRB4s%Jt|DGHm1=$V{)T5jF_McMl2z_g5w?^ya1syW&avsKqB7NL2ra%9z^ zaGQ@A+^X%bnW_?g+K|Qb2jt9zF?~ojl9r)sP_I#Lk#TO>j#uE)bt*p=E4w(0tF<9a z2|=B{IHv*uA zI}ZY3Vnd^BG*;R^Kx>f^aP?lQMUwC=VD622462n1YM-x(C@U7G-ss;_7D?lvd5E3Ud~q6-9y_N=2Sq0g>Z25)gNK98hK`oztX*lokXOYFV_ zdO*fOkbi9!s1N++8Wc~4L~bdFiXJT_<=IT?`LBsN!SbunR>z>(uk`9fJ-mvHe^nrD zQgS8NtM3H^ z$xcS=ZVc9p#QiO00-oE@VY|MmX3CPSjw%Bz+^@f}34^#U^=O;Zg^$WLdi|Ll!;DeAx|9hOmjih#x{U9$kj)7V)29NwqB>-X(!%DE{^>ki=daMhr2_|&hHiC|D*IUW{FhzIDat`5J|S^-EYFMmsdZFu&p z3+WbE3^C^w-Ula-IeJ-3QZJ_jLLdqj)J;5`VJdT&XzLOT{Ig+ajSSDe6(uu{ri9aW zkYNpmK&Ley@p)E9dnYE7zPFrTF^@N>x{4w|*<(`i}s`bu0uGs;POkU5;)i zJsFe2Ol1Nj=ntVsS&eA1a%;u(IN4kxR@*N}ZOrY8fTNNP6Or?#v7NgeTL1v2f%r#X zLToa~Q~5Cwi##0s+0@m7kikTK>dls3C!U-rBUwevKHIl8&8}HO48}xx^QL>7K6d!d zbrFe~&ISO9bJ4wbwf;|D)aC@F3~V2*SV~_cki*G%oA*N?!Jq{nSpWUA75mA_BANvr zQ2V71RsJlAvUFy_z6_L`NXx~FU#sc_C!(QWXV$;7JHM+vr%Urx);RCXNUAx&hj%JT z(K-~J(1wY6q#>;Ne?__G48160mBZC5$J_4PK%8F zFk5*;{IicyNk@J0h@~^npFrh5^$)&u6 zFPW2l)r>-5nt<{cO2Ax;o3}R#G3ZQ)L=At=j(c8)>>B^m_&0pnJU{vW>?|wPoe0T; z7@&3&XV)@hbAqjKDD+F}Alo>q$ZEc1Cre-+2>hJUD>z?38ma6>dLs{WtF_pAe^TpZ zK;nyYEoHz7yL_@pl`BDIMWix2;6=t+34$AW$~rRmu$VRIn3EjF)h?bN*J-zKaba@M zhGWJ}ed9k;QJH?kMI-@j>peds(W7)cb$RyS$VI+v=OpMNFDRxQ*WHzvqv?+oY6un# z#B(G^P_3YQ$Ys-^*{ABF>y7o3MERc)37Ae-!{lW--wZ+?U8MQxpPvTnF7ZJ4JK*hv z^hpaapNQ?f$`!5R!N)p(rZPBp_4yoSFkcgP#+RT#c`&;~a08TF!}|AqKG`+nw*d?q zqlYn8&&We@fXnPfl(+N9;skf_M23N}UM43VhhIJYlcZB>DZq&5q4H?^L!8gHW8NGgY# z)8zSgfv@Po)duhYYbEAZ^dLZ*=U4i)GVZxId~eN5n`kVt<(jxOdN|SzX3b^;ej!>b z)4dy?E+bWmYQ1s2ghtOJubjQ7k8V%VKiYvCd+oKecmIv_oKjMusLJ90~;AXhaSoRu1SAJ;8K89vY zNMrwR!5Jz$z@`VV$7w*TI!h|cQGch;?thJ`nw49Y?Z#hDV_X1!bUE2R#NidgZ4o6$ z9xkj%1p5&>1zD_$j93vnO0g$+o-Iv7#rq~-g^E9>67I_=hd2%S`3CF00@k!A8_)uF z`E;S}zm5SxfI+Oy1zv~5nrz7D3pk<)Mp!%4Pgf~zEx~G+=d)gx;_>{nZC!Lg0~E%H zJa@Ev^?eChHq`O8SXY3=b-zU(&)@r0WC~m8>IPR7iHIqMX2pX`7=}7eH(qF9sp{Fy9Kxha^E5>z#Wj;^ zNb{^$4)&(AAJIZK0jO_;1vipGbF}54@`_;Fwj&eXr5qK|O27I*S0IE2UmM?w2YVFw z2|8G&k#vRMslD;L3M3`#H&4l5y=2gc6#BQ4kt%TWUYK^uV z6^bPLW2Gvp*34tsNc#B35>MYsta-CXBkK~egB~wP@8Vxa<}GH%DrIudX(T=3X}==B zjk{MJCn!v3Cvc5Zb0eY1y-pN1f7(()Nu1rVoj7(tz7FfH*~72MCakFet-k@+11>T) zdvt%>43vUYqI*k*HSV6AC-DpEll9N%Ivf8xT_0`&oje0#^AvC4RZ~BoFg$#T3+)m; zEV#8X`sp+n7;J^I$SP_Tt!7Tj@R5w)-N;IG&VI@|F&lYkjl0_K>`J~=aoZTnqWvh< z4GorVJ=JDJn(Nxiy1v3a=hjX%hOh~4@OjG2_OWmAR<~u@hELkof)K>GcQax5x7e2c zvq)f>K{TRo+MH=iK)UrrK7xYVX`5uro@fA@U0h!`I>_e*-?`T=>Snc zuD_-8)&EvS2VYeW}E!6H*b;p$A&@bN1c7Bs{PXlQLF2_&?v2EA6*#!`H*cS4oiPj#p>K{xe8FK}c zg>9l!F)-y%9A`P$^(J$(G$P9583c_dphjm=IZk7+JT5_!w-F>hKA@yXn9kbac*}db z&01y@nu#xK;$R`tlGsY}T6h<#?bMt0^~V~x7LCt-(_L(2P8qmy>k&His3OFX21f&@ z{VbT7gd6x09e&=r7^(ssM4dMg)G^R%4#;W)nQgy2*|RjTe}M`alh%rLRVuhQ&X4`n_U&7&#WJ{5gy_saC1%tb=tb(m2Qu(k{X%-dsd79*f?O?y5-+(p1pkkH-2hF@GKT~GJx z@)CL`BVDrgxl^4y(c zlo>1x1DVu|m#h4^jeGn&oblVmK`1+5zm-dMXTN70FT(h;D?pDwx-mzNrxyo0zNM~n zxV^ys5@P4nZUZxLF0E25A)P~AGCYi&2734~0K8AmQ459~gjk|_8)ELlGw0!17kCro z=rSHYQ6g;!h;GH%D2%!{|%VK z=rth;A!x3(-p&E!WUw#X|3lTLPK~}>5YHtU%*4J!qN;T4QeTBI^957c1vU%I=A2Sq z6Um2aw?i6};HZnDyQX^)j%e+f*K$s^vPFzH>E>k?@e6)2E6wyUtA%VY;TJO8T^$?_ zm%x#}11w}LW%Z{gXK9bWRqa)bz zqw51c3b@v65s2wucHkV>k&wL_K%j;jtqLU<{*tSzM<@Uh-+ih*&$jug%8#|-^NQ}y$1ZXhHR(@@-vEIpsh4H$N555W6Jx9ZLq;UErX)Mx5{hNY~(;~-w%XP=S zFL^yJXIU0ezKac}2-n(^%(&A_x*h}Z$acdiE+RA@-g?N-XMtiTosSRU08bCaV{}; z0eWf4<0CO)b5cpmh#^h|aAEq~YXcq>k=Mj#4x(A~2pX_I{jGd!TX@fVc&}~tUm+Q` zmO!nWoz3*QJT^c%_DFSUm|MP`=;&9N&GPXkOI380uH*5a%ktu~BC0wyeidPP>5FR? zG^Q4HbpDvR4NB?VZOHxS(V~|05~Zw0OO%<|0K4yYHbA?<+X22JkHmgSf8W%^<4AjR zlt6r){mwctmw=Z2JXyH{_oJ+6klj`W#tq!tmENck)~Nc=^LE5PTmAMq3|D}ZjKiqs z9<~~*FJQ3v?DWGuMHF5x$>@8gy+Cj}s3L%%8q*)(@W7b@5ym=@r3Qnl$r?1-BS(PK zeO57^K2!U)_h8K9sii}%El}h3&`TXiE%WmL0jT?Vf$w)^DN6W(m0$eh zdK6bHoG|Fj!z1`&YG>NKa;vvHcZ7BGQl2t^V;Ar4wL^iI;#+DT47SDq4ru8R0DE(P z`%@ijXTjMhmhiQV7dR&hQD6x}B zwSy@*V(jb4Ur|X`d0$E#ij#eg!px{Fv1;(Cu*Olm^kf`7*ZYl9S+nPu8x^+(1JHj=+W;^5D$4> zE~(t!YL=^k#f*B^%+|kGTvAe49mp9c^4B5c0s*1qHukvK7!lBlHa@}qy}Fa|*pUn0 zstdQv+)HQqlr&&GO}tvd^Tyq#+BVfUm!rHwg{e-%d^C;~*@dg=>^zDi%OHsp0OA#R z7Lv(Cg9=np3ItD&oHPfiGMgFMaB~41<>)7QUaPo=2K#BcL@T3Y1Xf@VP;XYVIkj%d z+zo+AiR(h3u#k`3nnp~%2Q|uu`3b#P*||#lJ*O%(Z2D5Kg9(Bb;#y&K83Y|FwRzrx z+9wH%`r1qEXzPR$I}Js>qHYHF_dI4O_3W0{DFayY+Xs9^Z>m$(osxz%fZLX?n>47- zK}t&b%4S`0z){Hos?{^<@89*eoyj1cG9@7FSxt{O)kRN4v9Rda^{gy3k?jgAOSDz1 z@Az~#KF>)(mGw7S?^Dge)Vc{Xdxo@7Y@dk%JoV<*%^PcRPLNMS0cu^3y4Lr(As+E$DZbjdsecF! zE`^x5k-libAbimT(55I%-Qd(pI5A}SBU)J|Cla7?$;D@cY?T+;HNX;Nvcxo$Sr{yD zo}*>J7CZlmPa4|UYSe-}W5SyYk0daFjz( zlHsJc;$s(XojgRZ6Z4PpFe1bn{~QzAJje3}z)yQrhI26_FdHnyBtQZXh9u4d?-`mq zBgS3PRdo=&*t0`ymwOF^_7T$*Z!NlFR|CFfzm9?Sw#giBWW#vCT_GOvVj#Q=_Ie`V zK1aB{-WZj3Aig=m5@@mSXXVb05Gc%_y&ft^`QWirFY#*wQPe0{tylsg@waz&b+Vvq z=I^6;7MVs4N!Z4aSjVl9-V^0m6X7Uq<**`}gzId0uZlj|4$EATvNSpn^AMIrC+(DCX9Ru%U2_C4*veMy95&AY4D`;q?ZIx|r{SqAj<7JKWfzRK(lLhyjj`2jL^(mZ@5s z2KmcdW57l2r|(dBT!okvr}Mr+Irf?nbts7n!!@~eIcDOmMXihyy@tf<2CTL+8Tyh( z`Xo+^Lb+*C{pDrcp|T)%PL;>+En7Od6VUDu{MYCn3viK!oB`AKWp!KAjf1nmH9KTk z^rjc;aooYcAI{^#7T+xTz7G~1G9#I7Y*Bg;yLa67c4#n9-?mjyKl&k7!brqrvRi6# zl?(Gep}cn&tcij(#j8RGYK0*OmDbivqpzTUbXyK|3h5_5 zI8@yx{YPL1(AKk~wN+PPnX|}{X#gnHLs0uL_IAQ&iTOVkU9I~*VM|s!L0GF_kN!lO zdIXpFFq#4JeI)D2W&Zi>0^Hc;5rbp)==B1LFh^jcXX$C3`=}P?>kyDmlTwR1FY7!c z$({%0rwUq=n*y6_4)XqE``K6rlw!$*$yoF9Z?8-|n(5Tv{!KTCJRcAAI`}^PdtYdE z;t2NLLmSZkuL9;U2t*)lSNs7q`mNmgDD=#$qWn`(m4JLpv`qA_jPxTsV}gmExurMR zA9{(#f`U0HQUjP5g8TH@Eq!69r$hKt^3QeZo(r*u4(8{3$}go5I|*ep!@-e%V`kGw za#XNzTdBR)wgkvB#kXAH-{tj;} zP7;C?a7a+vHQp}-0}kYn>0eKz*&I>N)PSs812-DF;hCeTeekVm^FWJM-;fLgKia~5 zMcrb;@B3(FIxNVt)8{=-zZbApAq=*+jczb0vI`cq9@=xfLPKxgm$mxIL)|;V63j}~ zO|Nv0yaLhoitU)=0a=XlU(r4bC&~+*J}y6sL(eUQT&3wQ>B>_q1cEL;DFK|MGn}DW z-1HLYCrj9^+@3ye4Bn;(W^=-BPz`j<=|`}enP%`2^Zr<1MH^GX60zyZ5dUB5=VUy) zI>;dq0L5M8W3iW%=^0Kth(wQt(qKGx4j=@+vRZkcfcYi9604hVWZE0x3m#f#llg5& z%~6br5KhqqNX7vOqjs&((aeFDT{&&DOZ6`eMiJDTo;>pV4fsU%9p?1Uo?bl|3DW|K z0BVff7_xD#b=|(hE^!N>NQvX|$)g<2K)a{idETUAVyFMP|M>FjzU8e~DW)Pn*Mmo9 zHpvFwPmdX;%5oV$+**wy!K(+`jnAC6V>zHF!P?%;PL9U@&7PE;0+Uzny|TouV+YuF zj(Mw8VB<=)f|UWIC^LKJpnX&6ErEBCj?Y3i4k{7BVpiYlyb)tA7_Yj_4?6z`Fm*4u zTK;4-y^J>Tdp;Elhp$3c)na&(RRO~)osgY(1p>ztahg(Dxe-D+*e$Hk2-{ZLdLnQiH=NsZEy0JAz~{J%n%F%D-qChVrq8jiY;NL zM@uma9BU(?B=xil%I+wdz@_o>Krp;bzzNtsZFaNLYz(Z#@RG1%k0gc-Sx0I(77tORPQGCxZp~STOf4 zA~EQEx`kitu4}xuB4nE*4YVIrn@=-)r|FOYc=fW3<(2Z`pv2VhLT$(@<0bLWIGt#Z zA@dP#ajxSmmYYXcaW^951t0-U8udfN+1kZ9ooH#H*3lw=3l+9PUBlz9J^Z+z{}wHq z0ISJ@Wxz|d-EMjHNuwc8B|3i$#IGToxVnwmQS%mn6>#bi_5{+~s2m^HH)PtBnLKI( z*XsHV8(CDSK>W&zES_zAH`Y@4Bg^La;UVC5iLx}+koE=3o#C5{Hh4s90{z`_v&>|O z(!7opu9ZO1*>?Zk=THu_71VMAXn3uMbh4Z*iw9WkwoX1tQ4@Wcgq*`a0jGm z2P_V#ATNn@Ui&xFWPd#q!*I`)684ZHLGxeLJ~(hSbDv&@Yn9X$AZY$a1_EJT#AJ`_ zs7+jGZ=u)%-*iT^OJUYq5JM~4CJGyb+>QhU%{LKbvQEGa{yd^g*6Wa2oUy9%f~*_^ z5@4I}I(d5L^}=)_Tp#_-$Ct25boL5NKmGtMVF9k^8YpW{@;E?~tarGyD>N`Wjk!F@fKTHNYl^;@E@ zd8U;q@>eRUtR;YvKl!;(Yyf>#h2i*&>L$Z@E&ta$`uPlTYS>HJC!B2D97{Lt6E*SP?4s1)s ze89?4FJ~*9Qf;om!K-@J`x<;odbZx7DqQ*YQa9Xp8Z_t$_IE*b5g#~NRR9};J_iJz z*g^?N2!Xt}?&O~eV7@PUoh(4pbC6Jae0hR&W|(5wxWs?8Xqrj>P++&5(vwk+)WPBN zWhT!L2Pce~Qck7J)Af)v;-|!Fn$0;h2CevHHefV6xY*N_2X@E_xi&GY%l|{Ma$QlT zpkxe6ZIat`i8wXS7VW@q+w5e=Ow7UjnsfX3UK4xO-Eywo8h*a1dkI@9uq%Suho_7N zbt8jXgt{)I?Pqd8Qdqv}cC1^`N!I={QFWXbj==HAVT@wQ$6@8WC=Tf%PMT& zwL9>{y)Iv>4?as~LXZ;<{}7Y-ad=ty3(fzPC`J#d{CwW~nlLU_z>kIVgMq+h#3fVs z^^rC)1*Nd=Z^3X)M-0)C5vr|V9kgKNQ~6_5VpW-X-Hx#Fr6MvEpx6HVY#;KKx8nt|IdcZS@_YyZM?fM*jNAyJZ=SUz- z>vPv;{>Yn2_AA~RLf{;uA9W^i%q9Uv?Kb=RqUY->=m+fB0q&5bR_gSAmcaM_)Rs1x zF-uR^#sA;kG?p2*kc>`YHxlV3SWg2{Vv=-8T*Pg%lINhv&IbhUpWdZH%ZNW*0FTg4 zuO=vzaUVU8B;jzLrz2nND9eS>m6(ctDv|Ohb@v&-2AEBl{n)S7kPpNqQ~33fHZcXI zu+cW>Q$b>2|DHMXg{< zv<3Nd9!b08dwV3CuMbwfB7Fx5VO_~0#6s{dk!(%l=PlaeoeOM0yy6Bno{dmL8~~Ga zWme)UmPqn?MT{3`0SfdMR6Q`B#-n2)RDZm$9^_V}&xb7_8{`s(*Vnx)1e{CMxHIY8 zQlAix93X` zHs?3syx`P~35MTIDS||m z;%bf>_Z`#|<~1KCuXh=f!+T{Wlub%X3JEG3hIqdWW?MFL)1DTYuFrz5w1ytb+JX z5yzWO^JF~sBm|H`l5O`=?rY260R^$5cB|qS?oK{0h@EBr35@l)H z?@mKZ(K~y+pJ42+WdWW8fZpm{lI7M*{I=F!LHzt_S{n8JdrlhzGUCV37er+&S5OlA zv+-#Pq8wZagk{Af#qJiB8BmoF6c9gT&g#WC(_;eHf7+LINLEZ;Jjv9I3aQNI zT*v=6K!p3eLYUbPqb0{CYMt7T8MquoKw<>%JlhCY`6NDb*nO)?v$moC?GVL1Dj@{7 zn+z&oscCw5Uo@uL=1wuUQ85UUb?WM^+}Y5R28$H)1eq~GU3jiACqK5?rdXg|$3#1N zGGSX$Y~q6^p9*w%QjJ)ER4xF|Ak5xvqv3quz3thh9F7HRA0d^f*wK;^}P+5f5+mP)h zlgVGL627;KJONVK$}}>}82`=A1uxC-Npn37=sjqj0TUeV4=1(ySkhb%iWmU_&I~l` zW1qBIAOjd<*QkC%W(R@+g+Rjs%^Rn1*NYss&Z^oM_~ldks6h;ji9Tw>=IAsN6>o8l zBc99vIT#DTVqcji$+2WGa4rLblUf4F@!9CEi$3Kb zeaRR(cgPtrSj}c8uCt)DpA^c44oabBQ5K*l#-2ai7t&`&cjAojM~7}+@qnqhX|V1e z8$#sB1}bJ?&DRi1>@SxRK|P?Tj6o)~+HI;6AM8`NZoGA~G@nmrq{>loZr_scY)?g` zTcJ)PQ6G{82$4Cz!tGyEbPjHQn@Qk3B-9q z9f{j z3y{`b9=d`_@)%Cb3}#Y>oEsD9aNOSY9%s{X$?mA|ht`GCVogn?s9JX5UFov~#>uAs zIo>wegeQ{CR4pwDG%A9F3OBbBrkRd#rr9jhYM?#5D#g}0jx0t9n>+Mj5i22*xd#gU z9-1(eq|Tu@oBJ{$Cms>uS~c+%6V%*uI=W?%_K-@&(<8iGCUP)F?1GlMu2ZMX8nt>4jea~Dvr@1)-C(1VZuz>Gfjo4I8;s3Oyjgo|Ek z_?Gq{j(!}$Dmj%R4HdKWA3hcG=t#D+CSVc;8X{+?8H<_)o0W9DhM|XJA=d5-8R{P3j6Vf~t>jVAK!#_#pNhwyvI)mJy z#3~2wG1V5&Y88f)is9&WZ`+PCQtsReVr}!!a!L+IxS2SRN9Q{P_L2k*qBbkHeDvPd z{IK-3y5q1RSoz)3GUK=MSos$<&m$Ld4}7sGw4{Jj>VJY8F&e z!UYo<*k=^3I}bk`B5I6;MZ@rhn8k{j+c_h3ez@Uyn5OjdHv#e80|ilscf45ApFzLdeU|mf0!M7mmMzuc^x?NBKQeuPG8zF!UZrP4Wvi zO+#VTNB;EpXXSL@E7sIHLDNV(4=;66T~K>iGC{x-jQ~2V%H-`Lf_rvfb~TXX(l%+8H{THzXJH^JAj!8N-$TEGrnY1dM|yE?{Q%t8bX&v% zOXvcGPGQ+RpIosx>=6_R+-lp=p2{gwCh5Dfb#`MQWuEDP8RE6P(Tc#Q)iTp0<2___ zX*%texYPYdB_mk#TpOYm8WDBsy-0E=@^Y^Ck^A>_p`Fif+X zu^5?)*AaO-s3k;;N##y1j3((jj?8Zk=>H$QPTWXgE!464MN8+We-A-COB4 zlv#_{HwJH3ml2}WB}=ktsWdcsZ_yvcT~d}fY=(>d;=BqbrdYO;9G{8yR_?Lbdan`l zYABZ_@B<;>UL0KNFzuVHDy;p==U9P88n@YPv&mtDW&pwW;Uxl>WM`~`$s>}42LeQ?+ z%1?4?J#n5yOX;>?BX@{9>;50{Z$I;<3bGAcvNuuTP%W| zuCG=A#1En|*jyTSHh=t5BUYk(m8nw_rp>_^6PUxa^QF{m+iIf|3^QO`5%Zh{Qc;m_ zt5X^p`TQ1cM%7RlP`KH-z0OTCid~-H&vQ3Ly3;#b6@*d#IAdCO-(4yCV7aiz+>*!k z&)>s6=#pfw&>QrbN@gOJTA4}q8ZvqiZNg>J=$OG387ZLpz3K34(A{kNKs^^Zn`gX3 z##OWqDQJ)|^l$7tgGJUjL+obr*w+R03Qp2PlYBZ#ypmYkXTg=mAKqR?Mt5UNRx6(R zKb1pOUp*kxI(|{cP{b|0N>YsV%@lW8)~dO3?T4}N?AZf-GCd$t;7MKFpE^@GsiW8J zfQ}fVlXt`8i;eoHIR_wnrKFw^#NHtZ%)~`I&@LD|vQWyP0B$JEc*zPQ_3Or?aIBOr3&qQE8c#{LD!GDVa54k>JLu&)8w*;_u??L1v6(DCLgg{Wf`ac zPSW2fgqJt#hpS|zDF1b+WhI7|skG)qCCFK}m_FjsvbW@t+a(4+3ITsK*bxn5P0wxB zT3=ZvqYS%Dzt4DWpT?9O?M7d}wn zBdy1EboVkLL7@*usL)mUz3N0?kwZJNC_Tapf7z>Hzr#-4U2+Fh5sWrtrQK5jF)A7I z4r6U94=D7YDm{Gs@QCQ$PpPJRf9i$Pxo5vy4SEu03EG6?I_g;JM-=E`g?1qG+L+0S z{RRwRRA>AN?D%@y1vELctE-$j>Vf64$sC7ua{Ht#oPB?U-MYB7t3}2g&NXGrhiSZ) z1@bzk6KDBEoOP!P`!5&$Z!e!3{88vCi}mm58N{OU&E7;~+Q#%y9C->kITA4v!iv}6 z?i4Yd6J6l-JnZOB=q~VYh|C}x1;5&5&8Z#-JM-$}jl+9CXy4|WG%V}#7}97;G^C>oQec>$^ z)$W8d%EA0mYqz+Qvkh>JSFd~xi|M2Pz(`h2pk(c_#rOa-#lN{+yI_*qNYX7G454|} z%iYoRcSSAwB=@H4gWXPW-vD%G=Qv6pYbW;#Est#sgQC~I!g&%puX0O>MR$7tcENRsFUyI}}I!0cn-8N0;t?;uC%*69A?g;WjOVXF08x}XemvKJsXSIPF z@D?qxKld~QS+$8PoN9OuGpE#4l;^G+6=>lL(Kda|zCrW-wi;kS-0XBL5*2SuMZm(W z!MPq91(PVf&NEQ>*HGmTZnAtKGx9;awQ1x6JreV3FA&tUtoXR=fw#7SKA25bID|XC zcv1q>Nn&LHS;{X27o8qC3EVT3Hgn90Cj^_%9XHo^1g`1(Q?vsnxfoP6m8|0%{i#Ps zoWCGM>7~H&R{nmh><Na9nul5Tsr=%#-|&XnNdw@5&Z67NrLzKQ zxZeEM4gSC)*j-S#>OJB0mJGH=#8!2jMGQwvbNqNoBUr|Gi&JRvpOlqYI-NU*r3BHJ;#GD%$$$@En9>9REbhjhw2 zl<)ZyTnDD@VpK>jUrKmU;vg!DuCD7IFQQ2*wjxTGR|Sk7Z6>#$TsZPax3ZZx4vlSJ z(zcE?ei?1GXunIohtljLY*kWSXL`56rDmEu$Y|ILSQp*OJf_&`6=$WsWV3iZ{z9#of{n! zu5}#-lhkL9HC<6~n9-=Q83k`4ufINcO%iJcQx+r&K>9}na2SJs8^8``f7vbvVBIy? zME|1$sabF-%CFmca~+f3@c)v;JYxS73ji#P3Y`kCpqMhQ)tENQGN?*99Z!LudvE>j zP~ImUrh2;@%mbeD`xu1at_*a+zVsd_xT=i-pn>)_)zkXWyC1ZK z&<0nXB?dh(){wk+`{Tg``JeVOa-Vu=l7Ww(;4gr&<&1dt#gOF0KQTg)ONW)X;xw^9 zFdcF?(M-DnGj#Q7(Q}J2do%PYj}VN)H16#s2`V%mJ&;=l0Py~Ab7pXMGB47OUPW%u zy(4MIp>NP)-2)L4Xqd(5+iXZtZQ|I!rdF(0D9tjg{sM8KvpXiiy87+moEPP$ z4BJ=EQ`5i`=o)IjT^Sc38+$8(3XB`6FofC~=Jx&c07^-dMo1YXupB1U5&lA+Y4-Lb zqabyyTlTj;LV{ItQ0=V#)F?R|L~MV82pZ8@it%o0s8gldCPQi%W~xaj##jFYNO3Q% zN`#;=yvPQ{A!ksXBd6yAfNs5ZkeAoab^Re@jP%DRY78?wN1x*-vN`7f)5^JVkHuxvkr zyaCYam&PixeLsxd^F5VRLj&SwNOL5GW#`*Fe>x{5p=2BoFSB-o@4xTO11E+e5o&y> zMnR=9z8pF~iifJI$38iv4lj#;7c=LFziIq4IqKwH*2>d`kdAa}@wY>z7%6-z0Oj7_ zs?GN*Q3!=9Ri$1|J|c?)PyP8-TP@0}kux&}i0_(@s&0>CWAZAxYl3mOceC4x;fsWMYiW@CK~jS;&Iv;FvY3VxxlivC&_feASaqHK=dccu7x2m%pSP|x4Yo@k z*jNh2F1!BhAKN3H6W|Rq(0M0M3+g8*POOjY8g9u{kF>q1+%KJ%D1pF%(ua2~7}rE~ zYG6;4c!>l{z$v9M%p&+T6-HOWNef+8(^>0x-20rkKeSC3Ef1NY)#R>inOqBlbO{a@ z2CP?0E;}ca{wAo4A@4H@LZ~ON%B?yaHeiHDSy-ts1v%+IGA?FjKtaAN$XXuf029?X z>dAz9Ad;hvcUR!QuNWRjB5^m&Bs;BK3fDpa%tXBs8=*apcx`0rPBc|Sr&&n)%HI<} z!hX{m@!O?t3fra&Ov}OJ^go{?9yOAHr2l+2K-bquVvfMgYMzWEUhtsc0@hDa_zL#} z4Y~6KOvRRD+s=|RfZ2sxlcD#Z5N*x_3rrNI=z*}s?UsJ|pWbout`d+Mq}3&jz0Z|^ zJ2o`Zp#8LH89da%78S=M0b4v9EpsE=z6-Sd#6-3hgLtw`Tzp|&a-E{?Gl+wC1(e4D zUZj^_b0y7imbaYKuj!$?=)fa{dBW^QsH;14_3ymL-7==ZE`-8qaXM8~snNHs)G>9J zN;a5p=H0kPBz3;;g4#y!#6w2{8z(g0-SZXM^piq#U#tEa2k}cYAZI-uflBdf7bm@G zm1LFvgf+jJw;u3GYz9q25J^JWR3TpTD|_g8l1*s9P+)##(_m$iUD5M8r346k86I*! zl=x%TY+3B|N)O8lqFnRf`b)=aUIczP>Tss8piPOeD%u{K;RYSeH^%E43C8-DQ0wMr z_cT^IkYs|1rIrgPaNX^VeFNLx3oPPl)1I1vd~t>>Y@!mG!6%av5q>C$!qoC)gVy5wm(s2NW^gw@H#*apMJ76w`ZLFWOvE?9}P7+?25 zt~jPf%-->FcX}MesjI}fVfQUHxuIZ{=p7T3AETDdy7-dwqb0$lowL*j*V0Xfz$E&P^vGJ=seEE!Kc{XXr&F36C!;qk5v)Rzi^jT~hk}Y>z<- zjMnXN0X@O`R|~LM4>GZg_M^L`%neF<^Z`7xru0`Fux}yP<-}z%lVE${NAiNMcDYgWta)eFs!{A#qoNHC=yAV&l4XGvXOW59nH9`{ zS2b^#0`u!`GI?T`UZcNDxG*&LY1 zk%ZkLBVHC_Wn>NJZ?Z1yFa`;mSF^91fPl=!XON6t|lL-kp43k z50Stq^YP$lie`Y*pI&&82sSbVUZUyfWK$HACHLM%vI%ds_?CIeZ=jHbZXupeh*Mxf%$ zT9J_qtd?4S8PY>Nyet{$ZP>jIY=QZG#ku_8{6d9XZa7!v zk17QbzJ=8$21_9fE{MH;+Cb}G)+06BJRC2i454nA>4?b_F2=Z6t`>r!^KQ3AyUnYG zm0$Gcqeh66Q09Sax`Zq~%)WoWF+cBQBeagbm$N2LXXz3?dRtoP;CpZeggV`7>J`<( z_xIbdUo_RHJKBo$r2qzFcjd}LKIo2mhZ(m(zFnf1=#PN>eXq!B7n&)ufnH3;s*zoM zoZHZrvtipeXp22nQ0Bp1AB&_o8=#yaAVuw6S46huYrU%V&u0s!Js? z13$F&SCi?hOq575;mq&f2b9+-kM#cDq~R8D5J@5?pcKL@uL~ms=cnIF6B!#s*+9c- z=0$sqRgMK*UHd%h$p?V%z2L4(qB%K{pNBu0BmElQ!3o9lW+6?4L5qTXQ%U5|2o$a3uEg1yX7mMYMF>_ywe z-c)!fE$4Y!-!HdZHqxY#cmJaFYEmv;xmaneoVSM)`F8!b%Q0q(8H14k^KKv;2g40a z@Z1HGGbCkAC;}oPdzFz2pEluC&r2#=m=rs%&wOwLPZ_U}ae)dD>Q=(JJA7_d;DJ9A zLcaeZ0F`(7*4I!k7eN)?BAd1PHQZTi=gG|7Je?SFP}72%RYxo4FY6f0ie7X|B*;|pC1mOz{kLu+fk}#a}Pdr zLJ7GuEi%u^42NF`4D{`62TskmYtrzk;y>fhJg`k9rJN8PORb*5R~r-*i&b2gbgZ8$ zs5x1s`0Cqg2C_R1fWMQbX~V4f2RQ^1`Gsq#>bGJf3L!i1h=;E9UYU0D1eOHKc7_i? z5^sgsrJPrXwXoft(Uk-Qs1Mc^S@Y(lq_X4T(|fAp#2S)wWKd2siN}abAr18R+>F_P z^qNRFGQ`Ls#@|yc{;xJ6=?-L=<}!vUr72ivO}Go|U(#U>!P6|0@rn8IEGiB#ej0IH zNF{alfB-RyxT%2o+*yxud7h&)nHSYBWy@?1mfT#Y{Y9f-GY)a-RN9VaWby=ckeh)pdqd}wdAHPR_D=x*=3n-Owu5hGv;>zd8L4C*?I{9I#7S~!u zZDbJ2{uLYx47&fMNB{6AV*ojDi*f7}1A%p1ghowewbVR+!qfx z3}>}6VmF`%Icci6ZUlcLTNV+mdW0lmc1<5^0{biJsjoH6S}DpWX^x_aGU@UzT);di zml!ebi#cbX>Q3jX^H1_~!Eoc9^>EGU?Ksn$26%`v50;37}ZylAIqR(Hn%aXzY3 z0OL2+bD(fvk^Z3F9%xxi=01G}OW2nWet&38{Pkl6WYC()B9Xsj`0DfQWo}-ThQ!y2ah*cFKL2ZGC${Br>@NAu6}oyh{2qAYkXdXpX*FfJ3PQeNw{p?en^K$M7G1-m5KV2Uuq|GRdfjljvS%=T+B*Qg?EuU5Gh z7GU&V6)*kNYuTyubFt@!0=D-N>+X>ehtA-{q;9m=0!0)~1S4sI>uAZP3ACM=|2)^S zDly(&*LG$H+xx7dkv~-8_6qKLrg+RT$(6c5U8_3TmRavg2NJe7s|#3`duQh63=var zjBvuFb4<_j46Gi34+`Sd9%CTmM1pK&NvUS<#ofz!rpw;1owcLULUZfMAPTJSNm98m z1LR+{411!%maLFgbx279^xk)*x{X(h_Z?K%GxFFLEyluO(rHn|`Vp%5!}qYsBArjJ zW)`lzO@|o6-)gp#Li#+Xq@Uo#FWf-v(e3p%T@JfuPK7`K!uQN56TJ1c?7DC{#R&^e zV%lCXznDyX{2VT~AtG1yi~Bd{y+2bhzvc4c2kPzEU7P^GKcRrmX5@u3ec06o2|fff z#^cL*hNqRXllS93nz3rTfKpf)-Fhp|n@e}^ytK8N)!OM+h;BEY2}WUtgGR4u{^+I0 zW%%c0!~=j_6gxyRj5qDut*@OE#V|L2z8-$>ry|top*YRD>XeE#0?nTy@-#_Ke_%t@8Aud!F}j#_>f2Y1rq+ zS%n~`zMb_SYmKBuL2h?&W2NxMCThhRZANQQI<^^WUVdokh@B;X5{=^vgR>#noir-& zL#l!>vx{W~at-lMUe)3;U~_om3ke=T3_xM(BUdhJMEG*4`Q7K7Q$gr)e4jBBPX4J5 zHtGO4%L9A0QxSnOK`L~0W~HRTm16MHOwI2F9nvvG+ijkfjoS@;%^0(T#F|Eo&!2hA ze541qYtz*EKM6Z;;8D}AOYCbGy&o>kbsn^Zy+NejYHgvygF$g99w-9R04hw5|F`i9 zMa&8*SGo>+uIxvY?Lf!lTbqW*@{*d=SZhVSfCxnzQM38#;J~cCBIIp`bB=O%0dxdP zddd6cm|Yj`^Jt{nv06+-1bJ&>o-JizWA2O4e)!E`7sM3Lw}}VeChrr8Cn(x+14E+t z*?Gxy#PVBp>DIU;E#~IiXZht4Hz@D$g^vW(yym-nER>LRK)1po{rBKc?5rH5WcH9> z#%?U5WTDds;dkg%(ILJYU94-iV13y3v~s5>GFm`WBp)5Xi#SdccI&S`pqY}hbhKJc zEuN|FU&0&$;?s?A`;Gz~$@z11*~l@#$g1Pk?2vU*jJnIO?Ne4ino|}15NZ4C7EVu11L#tF;JFg7mv}jF(ST+$3f5hMqxo?ELL*GiU@5cJ>-y6vNGGwAEehf z!#1xY^R}$#t?D?WX?Z;R38VbhkNp?+)wDA;r!F`O?INLIr(drfqVZ@hGTx!;_fw(f zrpZ$SZ*$Pceq=w4Z=Bo%EQcKWzbl{)=bY1JXHztcm>;%X$eCz6f;Zx#sGx_j(MCm^ z918dBI1xgce8+V~3D>C;`$uGAUwdf@m<|d)aRfsvMU`bz zdf4BR&izo|pQ=@dxxbbPwr`y;@pAcEUt>M%Ns!5qfRpcm3{X>1zF zunR3;7TwEJC)jXNQir$v7K&%>mQM{DJ!S4HJTAx!I8<5Q%`f$-{=ZX5nCIUYJW$gU z@O19hP>(I|JfItdh+8C)V=~$uKQAgQhOR7t_x)x*Bu&%d`KQL>FnO9Xg@|9TF8?ob zUt(rA*l>GL?YAJ$TS+Y=IZ`BeO1+=pcBZv*h)||pJcQgvgzh9>2QrG>fMxIzva2m1 z+!1!ve*Qrux9wocaOXFoDkS~t;_h!TVy<~x_L3_x8z^99EBg#paSnP60KV#z>&Jzf z_aK}-H>(18*$LPT2?$JIAU;^-P2ni;Z)Qok>6CHhY+a|IAb@Oj6nG0H6O}oSy*Pmx0S6K2)l>aQW)6 zZ=8E7fS{H6?}p+|bzk9gMBeK~_pOz#n}QX_Q?I9Dr-?BX$^XAQjc6AqTx-eM^?%k4 z8$W$_o63M<@ZZAO2CPnH+9coCw#!MBH$RdlJHh|=y8&jzU&c%p$t7vN>VziK8tsKM zdUXGu-!j2u29p%fSERSXFv%JWS>Zm+NlM{Z%^-nEzJ`)$deUwVVw4{G}gg&e5_7KVRUd^mEFmGdDAO8B0TyY!{ETI2r$qbcwxq{jss>C zl4=gQ=5~7kkrzR1q5NKz@^u-E#yo1lwfmG3Rgjyb{q({h)V|tWE?D&KV&)!&3>Jnwkd=dn!prLFwTxH-mc7+tqR1=OFJh zDtYH{40Cm$X#LRS<_vAaAG}*W*L$Q3j7fKnb}68dbewLHJnGpH&3rlhT?xV|WF2Xx zWEN7senxo;rV~+2FOM7M4;Lsn^;Qxh>>QH3I$+BS5y@=$AEZQb#^jI9e+Cj zp`cwi)zI`B-23t_F<~NpmC^5Y0k?f|K;G`1=4!%i)CUrOGchE+LB#G7J#4%0H8JQe z+>#3tu;tlLa6J@9S~u%qj@!_Wav)PTCcm?9{H={#nn6ru`WR zKIAS|p2|iifG{kPmT-mu9^%x|lEjy?Q#@J9Px4|Kk-uZYq6pZu1S;r1V?t~Ao9jc8Yv*GV8?Q1N2ZLw?E1es3|kG`+|YZfh{4AZf=*0*-Be-U5<= zQmtzy;Iu#6+q(2RefpjywQ>g?N!s}ElPL{v|1yA4PNG#VT5!Ew5l=NI_e@;K;DV7r z%c=|*oRT0mb8?D(SD{lN*`HIR!+ZfovBS)9SAKq+Q7L zEL()gQ#3oir07to*-`Pjol8oJ%T01T3udcAQR6dFPRlzxUoAnjY9J4ECAQ*A10<=p zgI|Aj4!mGFcNJIhd@G@0oBRVhjJd#;dtZ{484Eq+R;+#F8U&B(%;z_NxSn!$ZL1IrIp1Cx|D=BmTFDuhPYo~?;&**#vR=n z26f}gwb7-{0=Rs750mLMMgTiv`nUw;zeNA)xm+>GF=@HLB8|YCKelir_}bCM447MN zx8!Y0Pg;n#hhYA$mtz!30L{VsA4bbMgyXKK*D7U~YG^xDuf8)SG7Amb(6=;w6C(y* zm0%(BWjUmO{~NN`?f!Wqwby^1&BmoegU^WdM1ChTRSnFAffb+u-=h9XSN4YiovRcQ zLW~(T&;T(mFNjk~ghVEkeK>^-XVw0{VbocqMIHf|FeU4I`#1vbc_6@9gDeE)iC2|@ z^Ey5!7qxq9IAteSpBGv)>~kjhoBIG^s9qK#7=&Yz?Xj|Aji8ipw{=OckYal1bd;cR z)dC~-JF2l2O##P(-SvwbQ8AH1xXM`kq(AJ<;|J!{CQ4)7#RfCy5h&zrs&_%***rAJ z&>PA#=@#?aKPoNT7J{kG3Ff9!Z{EMGdO!gQ+3pehQgq+h6Pyd!4cQw%l_HrVOU+M^ znD3$7Z5Twc5S*i@i<-(h5ZVrHNLxPjkp%6fTh>dx=$gx4Yv%*W`0JWc76vGKO11Cv z5x|T3wL7IOdbtY0jDPWY(V9m$CDz7!Auz<9m17x<{z6eD!`+OKJ`!b z!;mF`#Q4cOF332=8!TXDwOX%9ZAvGqWFx*$`VaQg$gRWv2}sJie5eNZwRppk@rB#* z947G|ZCBypbc_%-q44)8hl}F$eqW4)T)@Q60VV z)t#@)UlFPjd~jJtG3tuUc@Qout6lK8HftotmZYLSrEI{~l}DH;X&?f9I0zoDw4%4T zjLimx;s!xd!18?L$+HUEE>N16H0j95&*22yB5IF>Q0vO{->{QstmOvQ9h zBKs|aoR3~lSWidIZNd&<7xow%5_IidH_4w)=B@f?pfR+oE4IE-3?P)hN>8#i)tL|`$HTG(FT z{5NnG5Jd}P)PqqwSTELe(SaC;Ke*XhR9WY)2PLQL10DF5egv3rhw0?CpJ4nxZsR|> zxx)INVWZlRwY$k-`f>N6JwGsD0D>OqY**dC3I3q_l+rix1KSL!6qm&N2#AY=LT!7| zBT!$z`4J}U0TNKHGc@Ptwr(tfYPHVpw&|(ihuufp941Qy>z*m~nR{h8qSDLCl+kvF zl43oS!Hq?z6A{eM!znb1i5?25`yD!d%Tx9>DIj5#79HGwSs4}M6o#z5m?FX&{uv3w zqWj$k7Ff2|t$jhSTiGRD1mB53e-4AiMvNhfpPOE>xWMHe7(h}r+{Rema*ju`0Gw9e zig8byXOL|H88vJN7hCC)?tFWWtzj+=3fiFLy38zzTUJ5P4q{$_ zCu;0eMoqzX^*fg-tHo5$q*OI2g?++IBBnya`!A+ERQPUS)J#TZ%fWM5gF2mkiuC-E z?{La&is8Bc)->`}6jiAh;9@7UMR)kit-%X;y*t9+Aj1UBDUKpDH^Y4LeU)L|MppHm z1#{ZR!zOoM)gTPW6qJy>oRLh<;TYMRdED-=qJnozwSRBaG&~KA#RGVi4DWu1fU#fF zytu=#7ymAv|3ITHWpy4vN@sBXhE(2B!mUi>BnvL%x36BMDphKp2r7A z0#7jWYxeK-N~WsIi{==XZ|Yy3pE1YYq8g%ZOE4LC<@l6Jeg3wHA{i2s^?#~7z4M-F zFNi_)gQOx&)CT_^kp^nYjV{J9+O>Y|a(m=9tr{-gbczoS;l>uYw3xAmvZ400@AwiY z1z#SJu+fjpxSiv>(X5;7eA5taqs|}r>cZd<@wvu9&z>8RTa;vdAr;@YZZr$xcPCtH z`j_)pT?B_@+tJKBprO&l^n<&Wf?JLZ>~Tg2xpaTt-E1O?VCBZoZ_Mpsd-}NjVg z#o+>{Uki?i#0Ut<4EYMr-~|upLTB6^W{(5udwAFp(JmDJITa}S;YC4L%pPrBK;^)I z5AUzGQy_#E1Crk<33~wKsV6m?XvBWH1Ncrv$`1;yd<&?@WbIDtLFTpcqc@U-p&G?0vbBZATE(VF!H{fimzR_fM2M(k4%gR$EbV-Q0UQ2~)tmr*e(ol;1YaHL>%ytn)|~HbWpj zH^yx80*Ijj-cy~wLpZuXWl|(4;p8D;K&u1ds2IhQx6I^fp_VTL3HHq(irnP#pY`Jb z$f&1*)R!>~Qo2x}>isWDCLk$G06zk2=nN?o4o%Twe zl1h;7V9|BV^H>CvnONG*lg#ki0EtE$UlTNp&HPXD8)Gw|1;p18on`Y6gA?j9pMd)v zlpw46&8SN`Cpp&tZjbf`&?5na{a!TJne2Bx_0O5RS|Y7ecQ6O~>hRPERfA2;NGEaa zInyuUC-^SHm(oKAnX0^f{2ej?*xSqLpv@3Y0AW)l-NS5`Sq~dhXBIdkSQ^_Wpg;V} z=sq7DTOI%t#x#Q1?Cwx*W}>f1t6M%bk!5n)+^953#_OfWeRqpBOGja~{a*0h;l4!p zf)ukHRg-|{x7%=bG*1_0ZfGdd9WoQni^1u|v==RJ+s9rx^fR4y0T5%#Q8kOWvUGwf zkY|QeC8>;c?RBQ&FLWag?66%QcFK_mS>2~;8kR|`PQlc0nImqUu13v(d5i?xjYL;I zH|q;lH=mZD$G75&`n}uI*g)RnUsdpt0R}(%(=khZ;V-JdH4~-*Rg|Q-w@rpx(-0x3 z!CBQU<1;TR^@A`9sVlrokl?vCOre))9&M46(G^bU_sv5k?I}QWBWwj#piP{+;Xdn| zO4}9QL{-js^sYv05{2g6CJ`Ez1|iycJ?*i9Ws@kvub`7mj0n?Tx~d}%y6I1@KIDyK z;&0K&PvQNV)JeI%P@_eSLph-NuHNa$@($msV1hQB_OCZ2bgsqZJtae3FweMWAW@M1 zXV&N%u_o*{{3&bbU5V76esQBbaaNyK{HHXQ*gILRMI^n97!X|?0x>}v-lFTgH$be- z1ghZ?pP6r8czntYowqZQI6SHKusu0&69{G$t-0TkfAAd9hls3HK3QxQrCV3I`Wk zw1D%K=E*vMhKV@IzA#MPBa1jUF`S{HF_PS;2v{A zWNJlCCi3m9-Y0n7He4IkfWAFpDGU+ZEfT+9%qkmpQ0fws7)D=Ty1htX$Zqsi%x1r5 z+`vW)k8l4V;SDRzapQk%4avT7_vzWGA1Ol`;crMq7h{xSqwX z;|s!vy|WZwj|#%ST^DH#%5;IvG+XwhK*yW;M4%M_IXJ^;n#B}l<)r~^=vNQUK!Mxk zVbR&0X!QyoCE}&)u5h#9fR#m1=0Nhd+#fLbQe1Q>UE^?QJ_07z*= zGb~PIx3GZ(=T|px+weMZZNDD7h;-84x_7A3xRl&AVfBbTSjk|#*E>vA&;}w+bivl_ zutQ@MInVTf+`Sbv%!7VJ<2WUkVf!$#?$RRqAJzj|Ay+W5D&CQvn$FfEuWY@`J zAo6tG*hl}=n?lY=L9t-iCD#VCE#7rrXO4ljFA(bT4jJo+3GoH)kJebJlYwOsn$f4| z7~L-V1rII%hV!h$qN%YP#IyS2nvMo_Q9-raHX5nd7zQ@Zn)yl!5;{#+WLBXZ9@)N3 zyH>qF9ngtE!$7S7S21w> zN`BV#)4va&C*LmTr0UFI?f&s%7sTvj{a|_ZtQb>MRFn&LU z`8k67oaS73#3bGEe4(K3d>`8qNqS-3)YU7X=SKcPOt3sDWaezhI!xB=vC6uHRb6bR z*XujCF{6yAV=L{W9O2fguT`d~I^~GyC(K(zrWOEnyY!6Ej7`-H)v0^iA=^#?&6DSP zay;CEfjc{c>B+~3&z{UINgSb)+$;_$50y*UI#=&yC%Acl3HNvC)946C>dEig8(lO|lRG<9rVXM2FbUIj6jp~^jSz(y&GLItV z+b)neqtgf`u{4wcGYw&t=jNd=RJit5dPKgJs(fWuO(ISd%1NoV^zpUUI zza_{s#@8-2tMnPZp{H&okFixf z0gF4F<`K*MQjfIwq##&*t`dNKXGMp%SNbT*3Ky3EtAIUJUFXvYd+13rFZL0nM~1np zu$zbO1NMoM%B7Azd);k-z*BFdVC*_WmvV#au2_~AlrFJU5i9DM*ig1-ZC*cdBMe>M z7I^Ry&o_z^!L9Qk5}Oc(%#FqpeNw=G8ch&EAZQtZs~?~Kcj)PbA`YsL7C_^JHKat| z3~nY%JI2}$U{>gv|G1<7jyP`=@Ls{Q0l()Mtv>Wjyv82O?r(^cS_x)rfIu%zE#np3uyvB+-#Z+}3`Jjv5xbqHkhTM%@bBU9@|opm3VD4NWl{nLlmvMftuM0}s*Hi{@z} z{J_~Wc7|k+x_??$L++E6@&pAnDK9`KIQTO;NDn(q+HkoUmtFKhAru)Wanc9R*2;sz z^OeguL>n-OP>JjLa2P>KSmzHi$2Kv$DtVwu4&@q@pk@Nn+xiX4rT|lS&kN<>+|h`x zh7oxZdOMYUWOInJ9^v|grE^x2u(t($${XD9CA?*1-aPf?db9%Y1ImrGv|?%I9kX~Z z%N30r3jYM9IFR_1Z75W&N)slGnQ3$7uyRESAhFSx4q`!6)BOty^uOCWp;T$1dh0_h zmFrV?m#&y^M~-yOuD+#oO9((onUGwjQ9@$Jq4xwh`2+9LV9AI65$BIV|P|C33Edp|F=j!0J;vGb2OMVvn= z)cEbPdgOdP`oQjvu!ZtFYMos?*`x^S?KYI9mQ>yyI)){U-O_hID9UxvZX-QfgUi9R zfJ=D$^flda*KB`=MX5SR?0c2Ube=u+&@c7PYX@mo=;TlhWolL0Dfxgv9X{%Rj`6E> zC$-m>w(b8*&c}jBCPxiO6dyUQ zm{N`T9=OL}D{eBtwdCD%5zshQG2EYPYRG)N;Lq?V$Zs5C#)1>-q1{K;tmgN|z0)hP zgR>PzMiD&tJY7w<;5T-$%G4HEW3`>2qihYL`_4#J@3)mP`2-022O$xfTbNvlLNqNq zl9NYdb`;g=9F-VwAXwr*c591S`k#?zKX%U7RP^lEd!qbG)z?Y{YJ&iUy_O@KAN!NF zbD_C_Knt!qB7Z1{P`OQS5aDZDhz@;5hkpJ_MF1~!Fw749anE>@9~lFlL&9r2oKQMR zNSpk0izeymLsEh8_w%NlKqt-pJzF+E*j{0ymq{-NDpGBCgwH|cXstr2G%gjwNeER^>e^m(>db@A)W6wj4nB} zY-9&7NC-mDDWM}hnAHDRS@q@F!a1oFbdJIyc7kWfw7US>i+RiM404lK1%ardd~9pV zqYi73(KUp9DYDI3;9MnJSySh{4%EgV00Uv8(t67ewNu|y9l2lD3%4| zbMjt7F`+o+5Tm^>d+Q@s*+>Ue^kl4_aD_GY$^)Gu#m6a}NfkVNLx)@mv*aK8z3EU6 zMD*b}wx#%ljqIY0k|13jMuHl0#=@n%$}xqm!}SFp7xha=Z9g}OVptkfeGV8id!>3eJsARY0PyQ_z#bqIk$uXnD(!G4 z9Ik`a60{_)K-15gJzz;X*$m9L9(RJAb(~C@YEYc*9#@PSZ^oXq0a)h%>x7%a7uPkF z4L5W6iHo7fxlz<$(MF%z4T^v)XyRL=#t`@=hn%eoWmO1u%zN;EmLVpW8{pHtjfPTE zP}8#%%;|9IE<$6_)b?Q|q`2jPR6SY`j7d`a+=E*=1M*DC+zCuBUWT7?N}d=Ci>DyBB)#mk1$2k;= zdiwEcYKwQbssd=vl($$r)_s@-vGh24?!t&3Vk}$I;JT4|Wur`>L3YQ-qay`Ru7r*1B(BVsV}*_9 zH*>i&AMJ3&Vf(DE_7&z`foWO`ghU7#Vr-g$xiPjmhVYT`)})4*z+OCDWW|k8S=^lL zA-dT9@J34}75ShKPP1Z;el~cy_es&$J8N7;=c>xGJ#FLT&Ooru7O^1j%qH(lPX-iN z^}Wh+yz-VPH~^$2ij-f>Pb;fPcNBWedA*Z69DSIQ06BIFs)_pdgGxC1o>lQvb>pzH ziBMW#z!XrU3>FrXUBeM0AG8(+N*bpo@I@Q|Tg}ZTkFZ0mTMDX2R*zgDEO0y)=#_XY|CU+eAp{$9&d|*rPALe%r(rFuPu* zH1fOXw`CY#>JlKRVhsq4Dqt6@g{h~%q{@MHg$Ufh2F*!$D~&!?@)s_S8$W8pCv;Fz zdd_ywNwzO@P?tO||9&lanns7QMw}+}e?e8#TxHK6S%{8Haf>Bb9}xvFcd9`vrk`fHz`FLE0Sfn!T!Vd^g8fIg?UC89{r+O3JX zcLSZcX39qX3V_4F6>69J?NB>CJ+RQ1M4qlc?#Cm3$s)sL;9NZRn|?t8B$*z~y!@7D z&BeGwviz2X5`#{H)k}fnXFbs{G34{3NTmSiA1i6}r0?Gfo*uuOkVjtH%M?ZSA9}#F zpEdkl;EeyObfOg-DciT*nYSLpFnE(_sv5X}_J;r?Xn*`b1zpItQT^4hW;kjJu z6rnG1VLhriyD8mMX2{2-hCgqWk{g_>_iS8MHS*y&9r#-WaULP^3eciRMM&3t)=uTR z{5qFO>Shra;JRmj3b>!51b-EHw^Ms$n#F~-5D|mEh&i)SF1T1$nEJN3Iv&cr)ZmB9 z#?jueF&`ea=9x1@6w`O&K>`HM+6!P%&H_|0&C6uPxeSHxe&rbP)(f5TsfBH@>rbJhAi&Eg@%+jJ$8ElhV=5QV z0jVI>d&z=w2m$PR`;go`0x4-5^-Dg)rq4lr-=}~Y@hz-vD1&+oUlMkrZbNRQ-9upf z`)mu;20$YVN(Hv*7K2n4Up>l_Y`##v5V~DDTIHc2;Fe#syaZ2nKx5B{cZ5FyLJp2fgZkM%Re3~Dk&_H zgBk|~e?m=yIVvxYLJwLK+6=}E*GFiFK4{qkd*d$NzCK(9hE3-+JZ^UvKi{98UE&)~ zW6L98;IY0Z`aU)f$ioz3zyi@8X|O3+kp>FKzE&NQiNNQ9{PzPh7a2=CAp z6HZG7hze=!_my!Gz_t+oUY2WFcAVu$E%*gI?sM$J^0=RQ)Fo$D@WlJ1m$HeI+Ma1) zK(E6oFm#SLWu*z)j81p1_{pBGZXnKRyE(F{D;_mxmzD|@eYfK<;CeLF=Lbyl6*ryH z&|Jta=Ndi1l?4=@I8$I}!nzthG|5}QCy*|)yp7_J)Tq~p zo{A}$`j(3Rgq_utuc}WkueJUM5F9@#4wg&WA|Q?%m*=@(Fs5G3{=BkJX+|k88_;$s zD!?sQ^95{cf}D`u?j7`$GOZEm?@UIO0JY7#dB%QU)ck(=c#P`@>-1@wb8tXKdnI-p zU1+lzIY$_9r^`TzP>4M=D*9`fhmMq_N(6>=*SdXns+ql!}fHB2b?q*Gzak$r6HT)P_A;I-#9 z&*@U2fs{H#cG|-RH5Kq>`6MabHd1~A4a=W3U}XHZPbHD6YpqqbZX`j05d@D`WD$Vq zIPDMY`JurOBQ{nHhH?al;17(aiYO7AB+iinYiM;Ond8C_qwl~V-UMtk$BLuvXS{*k z!ibjFfk4imb>o$ z4y_fMc|$WdxKqsZZ?lVs=ZIs!C4$u`z3Qv8qs??UWL9@^W8Xh4Ay@lf{V6Q3XU zCH+6Zyi!1o57****KOUs`r`zxHh??gIEi5y82fEwX7zl^W`r2>cRn7JCLvD#7nP}= zcp9P_E!Fh-9!p!-I%ga94^oDb=cyPZq$C4v?(&7dShpYt?^t%fwze|8LwYO8gTspI>c=1@hiAStLuX> z;1^@+Br0!_0tifoWFSr2!IyPW@&C@DlvlA^CdSa*fO-jB?C%Jlk!`y8C~W z^d~bp`HqBLl434?E0uCmokOqaN1+loijRa&H5sRIPR6{#1vGc7j53Sa$Z%AANk1w?yPbrz3)1qF05k;jmeNQ{KFH~QZdI|YJ{dXAru-} zL8BJq3X<@S&2WFUiL+F&f0rABBnxgh8Ufz1gqRrj3}gKsfe@KS9vDv(!OK~GJEHO$>A{_z~ep z#)Zp;)m_8y!1t8_>0K8WIX!VGgxot6zTtgU*&FHa=6rl3NvKG!3i07$$BrsZ`M>mi z=Ff|a+p@f$+@(>hL5I1Vh=ML65qdE1vgH{kLA`q5B0{*0>K$W2?Q@ZCa)qp8D@d<` zMGT^aS2dlOxUDMg9p1jZo@mTDNnxY377=zMGVG&LShkw65a77{u_d20$lD@xDRWJoqego21|gXX#E_m5k9mGh-)C0T$A9E_E|x z9XH(&aZrSV%3VUafI!+;fc70ymqDDfxjcKK@Fa4}2_>nVQO!AkcHLn&BkTDt@~pS% zmYC2$fZV#Od!TZjs3v&oK93uRX#~{K61HIZuv3Hn+8?<$+m2O<4vxlY(9~-H4;Q(AXM^c@ilvEnzMLjj{NQw^7I-j7@+Nu1j2&ylyXsy8E$=`}|NS_-G((`&d44 zNcbp3QWHEfjD*|tv8W%^{k=ejxD;1EMPlpo!NJ`t9|NY6zE?v>JwVq0*1x0^bS=Vn z;yL7N@&c`aJ#r^6_2t+E+Zp+t{}T+1qHxfP7Xx>faQ3}(3VHP*aAVzSHfI`}p-n8U zd#vrxW(9I-FGKEK7v*}?>3i<#CeFUS=jvBpO$`XDFoy)<;+AH5m}N(U)7-i-aNPoX zo?5ma8LgDXt{t`r;S7W9cCjQt>S~Je``mRd9nuIk>Ju0IhedA&^YrI0rkuUb=tbNU z(j4G*!N`llVG{VC$I3RYOmWzsWBRhvn(-dHp4}%p%=|SC1PUx5Yj%0L`>j6sJ|vfP z4>k(yuvS!=rc!U01>oXHGlhZbGDn3*ON_VPOT5rxD6A!wB;CtHg~P!RNrV|Sz?|LH zUTHM$@zM;+x0vGh7v4$-nyv_-z~6^e^U(+7fW*XZJZ+i>RmD{f>3Q>(0$Bjk*eYZo znV|d9jTv*sK?TpvV($BTT#=M`e{tR~sANjA+n%hTyvRN$Jl47_E+haOgF^uB6qgh2 z;z1rIQ?x(Q3G|6Cb_$gVuVgK0F<4cYUizcPb%s z)oOCP9sUe!iv7;m1>4^g3PkslG+&ELvu++gB58>0iec{hnS=WLG;x-A-#BmtzlKCq z5J#s?uPV-~xg$@r6|8_PLa0&ZN7!irUxJaqxK}7yGSSZC|9R(@`4MWlEea-+kzDER8(IH5Cj%STaNQoL(9>w0jSlgI3y8 z2$L!AQ+ZwNF9esXE&PxeoeFx84RZ>HETtsdIsNrv|~3;R9WZP z{={2)Oa&~RDpKntEQN$U4C=*zq-OAL!2Xo}FMgTdzcAsDp*NGRW>+toWOmYdp6IVj-y z9~~=jtvbM6ERaX*=y8X1^uW3Y%;A~711s(-3NW-nSj0EiUlT7QVq>oUwMz9 z7UGo3DlQ^&+uRgFzmNL!mMQlPUIaofD0QQVDH>Yzf`_}&V4e?wa4$x?yQHUa`ahUV zeviWjsG&;$(s3#3%#_>w8;1SUE2#`=&Y#K+zSgX+u+G|X64hFV+pH?s3urdU1#O*~ ze%kq$eFPEXU+0?CCuL>Q=KKYFkdnU|Bbs}%TP#bvXLzsM(OxL3n99n}A|E>*!7UeZ_Gylh}!7Hl*`NOWYWL*?_>dpY2w`g3n|IcEOdA$6Z+D#Nc z4Jcy_*@sYW+$Xa1TWFU2hM0jmikyPDS8YL9Fxdvb+oOx>A$0&`uo2)n{xP8??DqR^ z@Zb1@J|c&B_N|zWZuzKiee0v-sf}ESMbWE!xiVbgBakdZWZfE8V3KI4HirbkQ@2&R zEhnezX1%a-`R6fguQ=JJddbxHIwEDl5q=Nf?hosM$?dMzKE9@h$o5Njy9PF*Lo?f5 zmq;sm-f@(vFG@RW?c<#KE&#f9;T9&Y6&QB(x!K14pxu!4?pWd(KBVOomOl!Tq_9aH zUpdAqmgK_*U%$JhsU}RKuSZwyP#T$TPkSL?ey#Rp-jJ6IMU|FX?XOy;v+rimFx$-) zeB4ojdeL?U-$-!3)oX(V*o^@f8@t;_*k7h*dI3nxQJDJn)==hplc!{c&dJOZ23am- z&u9Pyi4r1ps*`3hAUZ~LY9#~21IwEnwgJHiT?FY0ZnVQy$@*s?oURzj<-X9Dw%$FD zSwUCyu*{%ff;Gnx$r0kWI>(o5{6*^gNqRQ=b%( zW(7j}!JvNO)mpv}HAav6EUMOD9~)&_qUb5-#<$(Lq2bl2V4%uQ1f98Vo;%lI*@|;$ zwe@gcG|$n$Zl@VCG~9!*%AEJ>E!PmhsJ(P;N0|lF-{ZJd1Pz-`o$bYRFLXQxzh}+; zA&NZdSD~^oZ7?97XBUHRe&vEPsJ5TdR^F%G_+6^H-k+Dgb%+E`24=SbPXQEX+331x zrvRvt=ke6;;m7aAZx#)ECSVm~Rdw{qJjv=|568G5;fO|$KP+X_K9@aqq z|Np3|IQN~jX6_>ck#Wxf=m}yy0thQfMM8KbYgE3c zMGR_B7LvfpGHm>k$ctQP^pNgz)rrjN>05@4_1c*Y+9nI6i3ic7}=9VhRso(YM z3!}l^ufLRX`i>0geS#hZ0Frx~%qPf3C)xg*hjGR^m$nC62n}*|L-yvJ_z>XVbS> z9gCW_mPE5=$td@I#*|uyTwqjid1sLPXUW_+|Ak!Q)RUH+>h-NCI`jz*grkOG1@J;r z$CH7^K9aUnrn2L{m6)NdnDxrAjIE4zrCnK>X|8*I1QLY)))}|tIpnh{aw%3^9il+- zGBJ(^ar3ZPd!mZ|D9z0v(p=M4wFi4WYR@mex=IlMv06o|!hF>yjP%IH;UbJ&`ToIu z*S$w1j&Be=s`SqE9X8)j&3<|gf~|!w8r#&`U-|^Bm^{Gnc~*e8mq;wox`r-tzjGPL z(9NH!$$CFp3e=yyC~n~QQ^#%ytadY`aenLMfriRn$YfKV6u@}*R9Nc;T+}lHT`Qgv zcbU~NeEu$O6$6`%V^_(_8?Z-^ONCT+@AaWU{cGIyT|76pp%V-Iy1W?)lG-Y|dZ1Ti zpL#Gm)NBTvAp&>~AC>67?dL|PE079Q=jlQP%U7)VVkO&TTXK7L`?OuGVBf5&^en?m zR1e*9-=b<$Zo|!WK{Lyy-?k?yLx!P&p1|(B=s4#3I6H{P6;{Rd+gpk zrM_I1_Ip(ud5~C*R&e5QhWbdIt&G}h_4q{GYJ#Ksy`ZgsOkGN(ePkeKM!VQa2fI{X zA?^82_a6pBQ4Hj}*0_Y2u@hQ`>)Y_-CnF4yQdZ#bk#3mEnYDU$dT49|1ExA+ZJ!Qs z6u^QBJ=|IXYsnO|cMn^R(G5cFw;!nVsM5P6m@11n=GOHtE#K&l3rp znc914u7wbM8&Qrr#&3Skda(wL4=Sgy2_O_4ceqI#>wn`>|A$j^!pZdMJR*C3XC=nf zRsV4qV(kf&hbnR|GRizo^3+c^I_MuF}zi$j+9U?(fB^F~1iYl3oin}uZ~n@1SM{LaypLLMh|Gi4AY<3sf%s^g}D zXMWbTi2in^g8#|XzPSH936Xhq%i1%_$fS%5Tjz`^v6!Vlx=I2Cvt*aS+Z|Ju-ac@> z08$IIw-)R>V28#?ZXf+31Dms20Te4qB#2T)#~2YZy+VyvnReenXeKg}le4i=cNp?$ zbL8GeW&g4HK6iQr>EJ1iA9Gc*-oE)h1}D{2p>&}Nw_6zo)w_J)It5`^qZXg z=eTNU@3J#~lP}#H)J4Ud%Mm-Zlv}KB2!o)4x))v}GsChfS$Md=a^xrDSCW z?#7b4sa(25U@gj|g+x|j`kmd#4IO5Dr>3t_B_KsmKJ@YN3Jj)MTt7}};7NQL=R)d$ zXry91g3^uos8nogG%_ND;!bK>8;ndg+h%DqCbJ8F%-@6^7Ep*k%J~c`)A!iU%5LeL zE;}#OPoh4_Pak;gufzB`jpQKYoGE?Hjm$Odw>b~sdCgBp3xu~trQ&(6BQ*Y3^<#MY zT~ld(B|bZ+fC3#UFH1Gezs-Fx2{XKw@ONE^j&e8d+r&uQY_UwRtj%vF*DS^WyaJ25 z1t903QZwLOH!P$@%U=0JBXu3TK&327$3zy=CiHbjL?SLV3;KeH%B7_$_yV*Q; zz}KNzRksM^6n@+RUy;zqLYzQR#`{~Rrr4XioVyplx5o(x96E9*oE1ie5uC`_Zy<>; zj+`Z%r7}3{zS>^3aT z6uOMoP=6nX!mmfm=CgmePCWw%=vk2kIo$u5ahy8-GniqV;8t<50xI?FL`|1rnGH?z zAzA?%l|qZ@V=;7HzUbwbv3jM1&F)CQF-B63BxX2hH55`@XgtyESm>ncAq#Gi*RkLv zumI_-i9;(e5InM%9MrV$L?Ea+V=x1nScDISKMw`$I>|WPt@G9XCwJr^Cjmnh^*WC* zJK`+VZI8#}*qF~JyrWr#_mW{iiV`z%-FgJ#p zkk5#{m>3}VrbZrkk7d!(rEsNb_BSPe{&;d(8JrT;=~CV8-?_}Sb@fND&EO^FEiPte zBc4Iy94p<~@Ny5uR6T|G%wgI?TV=4uJNxY8}t?j_ATj&Yh&2s{*+ z9-KuvqFCqL>V${-J4k%1EjV#K5L~!XC+sn@spE+ye0OB8O*G1E*$;peNZ*?K^x{G& z0*cCIypV}C%m7C~xW9XjSOgs18i&ifM%fDb#f*#&?%%e*;bt=y08D#!P`T!GYU$H4qX`o?O(~1td5B3 z>-2i#M>-YLD)@los*{Ulcx{9fQ=f2~G~4_~sBf8D0pAXsC=5+}nCOhI(f=d5q&VpY zuxzIyZ|3v~X}cYz+ucx+y#jG&EkOSuHIM%>V4Nx79>b#tf79PNgD=cH_xkpno}CkF z*r^zD`r0|@!P@Pek>qIahK}?t`}Io+WU_%o9qm;1#o?rkP^-O7{4j8v%Au5Lnevu0 zp*G2h9@7a9igk&>0wU;8k>cdf!~wA=V26Ym*IpFuFA}vcM)=?WYUgjtiKCtv(t0=3s%qH6tm>RZ&)8uHLq+^NYW$RpwYoz@uzBN|Z@OSNMPupPusjFy9b{TAoaA82;LniZ3_&E))747;_1 z{lT7nkLDfiLb)N}Y~~fZaOx8r%d1?-1wL5aUZ=3+vgG6yJX{z>3eI=rz0Yob$1M@u z4Twp?{|@7sB>B_RRUWE!!nIbWF0j{I;5+p*c@052Lw3*XlA=+aM+coOY3DDuz1R=N z*2JPsfCTeH*tv{_s^P+4mitk;&9Sj(?7odoMpOMJU^%{^9F5gzX#5C?ZkXUnvA&ew zrCbqYFES`wd+Z~6;M;36akrxwmK9L635eWY!J&ouIXQS4kk!{Bb%a@s=J3AX6nVtV zw&aSE3MR{!5>pg`8Iy%Wv*qkyxe0`mZOH&0M!>V6eRciP&r`2rL>-&2g*s&v82D~3 zpaON;{~Ay!vq{q6PVM0$t0~>X>h|U7S7=jUBDFnp*zkb@X7r{@Zk~4G>_r>*)IS%i zxAMrsUSc>5($gQ7?v>km*P5~)k#e{0tbrYwyjFB#JSfW){{*#OY<|DuNLg(*NHS4D z*)@DCckYWYP`ax;tkg3ciM;6v{c>hg<*%Ywyk(qi>CoVYSBX)TioR)+O(U#6_2C}P z?~L{UfBHt@R(XbkBvZO&ISZ22W|#pN#Wf#TDklb_XAdz1L*R3L{rI47rp5N*Acw<*BoxP|)6bvZe&D4UkAbf1YrO{&A^6pa72M5KL%6QrA`2=YhM(N^50nXSsCaAP@d=JpNe0VK+ zEafNfoEi_SWwjDO(#DI^3;7aTqvZ~C-u#axre)Y$B<5YC z`WpQq5>*xX$Lk?a#^3a?K46AA)Wb(U8t>&b!)VXXD_YK&5T1-kCvea733mk2vQMAg_I$X{*F4l-YK6dz*}qpc%h)VO~G;`009 z1x?bW2Rq4b^3Z~=i@{U;X4%In7&MW_s3haRxpTQw)~PE&hC@(6g9t8KNT)Q8J01e#xVUVy5icSG>oM$Z@C-sC2?aiza_kZh z(GcIr?CrJ59VygO5JOe#n8$X*5s2cPLkO!=NbNbCjbu+Qv0u``pw7NzDFr;~68fmW zlUK&bG$LCE_(v=xPTc>2o^K?^Hfqpx-m2^mIa6*4y8Oo~d2Xn=Y?JDdbRkou`D5w8 z{30Jf6l%>C3|kly+ibxj-_LorC!hQb{<-Uqm(~H>#3S(-=-Hn#yAu<0K~sDmMO&&T z9~^GxdHP`0JwCc34!zW7MJ907!+p;+>w1o1_{dmO};7fIdCPzB#1UTLx>3 zuG50pIsCqYcBD?IQV1oZrV436VreOsNV-_7a#8d$2!#OCCn6RW0CU46Q50W!kjx5e zYC=0!^dZrRgLC0Gux3XzJ)q8;t{ZO^RS%PEB5qsQdl#EpxTvm{=J=6iMSS2tb!LUZ z?jY*O=@E;nzs!E(yCfT6Dj`%c$}nPTCu#3a-=@yoIl@0shMJN(fT4#L)d))3_q3B1 zp{tG@iBR476&F5^P)#RC4bh*=Gn5_9&}_Rqz>eO@j_73{XnP}YsxpSEpeVXV8eg?5 z@$f9zfG&hAum~9J;0aa8+@-6NXg8&AK_N<5jVilwL+J?!aap-z8>`f0SI8m+sg=}| z(?4SBOj)=x?|sR9Rd^rz;l2<#2mI$c0mG^Lhb;e%hHl4D=fLLHf&rDF;aFOYmUt7l znVa!FqG+XwnxQ8a`>^Mj>cG1)bxZ+C{&VW+3_AYbiZt|P!9dWCP1Bujd~5%I-@=I! zj+9g!gn&Zu*AobGv$pDOdM*M}B_%aUwsIQs;4t}9vn(}Zdjd~eW}sQcaTZgQBpR9E zuNscQcBl)-{if@3p$c^xj`abj0|BmnW_&>2DhI#t2=LJx6_JEOD*p5xKYZ|+{Q6Me z;=k~P@0&&bNq{!y#MnkhPDsY3KfWr0*JUZ$`o{c1w%p1+jqj3rCTroEDNWa0&)`h6 zbrJX$SIj~F{;0(2w0^F$6*ZN>yhNR*bXNL?tUfRPAu@PLM%rNP?#&RvPPbNYY?S0^>=}alPFAN(p z*N1n1#b#CN_kj^fqc$~D#kXk7*LF-F11Dmt)fh_WlM8>Bj@iR30;7>&p{!yP{CSdS zrd4+xu)!#|;g2t9kBi26f*Oo>e3EzAOHbX|6|}7+d?|j=?e`{yG`ARqIqX{PV~EnS z)&JbQRF&jgyadCcy}UkCm;RP!z3m-ZPkJPAI7AI@AN=Q;g1^q2%)$9l6M8hgW(q-V zHzJc_n{&P5*)6(+3MtPZ5vEt*O4GWVqHau=bJNkkioDe!hj8m6YnjF#@o=h;c=Xz zs*}%-DN&IpYtt>Gm&dOH&BCD+79^3k`0de@ME{DR09YnEl}!6LOC)U#B{b~^gRl;f^{w;E$0uBqEigaxjm#3RhQvN2Ocf3gcS;nu_jfWWAu-DnMQW@e^E~A3tQvh1I1J2X%8B(z2$TPSTU`k+ z?>N0w9ky1~ABA^r!?>juneW?l4@z?Nm*Q20G~!+Dzd%j8IyXbooJTQOSN|O8@pjQ* z%!sr(comD=2Au|grxOW+DnE8Z(%_7%Qr(f3!o5 zE%6jQd|5KBGM>jnJY&`BHO_|5JC*WPBx2;? z-z^IG0Mn3CyUJYsobezTseJwj0&myF#g8d~Kk4v0A%^ zr)_ox0Fu9~z2iwIjZQvyc$~QODtp&P&K(s=8n}usdP9BNWRR?+de0B;>E&;A^m}02 zK>fO}Abc7q1ChJH6?sN+$d>t)WsAsKk!%tia>3b2jGUv`TZ#RL#Ih2Z=0F=k5>~T$ zLKP;@s?;f>Y9SVIPv@bpHnK1t($ons4&4vXe3sv1_Vz_YW%fI|+q;YIeiKB(<9|ON zpE|?mF6P%N4?JAAE(i_N#8%I;($BO3R3BA70HK)|{~t3R;Esn3IN`5-H=?;~v~3aN z53^y*1xAiwBdKm zw^}YDY4Vo4vQp(CN|rm(0`0#049USdku+T|m_(v&74MlohE8%m#UZnx@HDS4bF-UN z8BNYTBs3BFt@c5tKfS*97gc)ptu3Uz!VfJN09~o+UTGI~zSIJRP1ENYenB7M_D8=% zygld{c`g&kG9pfAt8bRFa9mNX3>|8}{>X5-R`>=cdDwX)0-?#(99eDM_!B%V;Pvc6}+R}VpS6RTcRdBd!=x~~nBCPRI)`f zY|7cVQPGPJ;Uc98(k*eBApWCfR!|DTmU|V93Z_6O|@l*vdhhU>~ zJlG5`YGwzm3KJOMJK-$s9HHKKNsRpdQX52-IV&Z?(j~K@H)dVO_|=!NC}E@r&{mxI zuyk+HuW6DFGMp=)Ze3GKb#E-I3V5>3QT(PoyxH=q^G)10&!1QBhUAh_<92a>N(4*S zo1uTobdFjK7r;;uJ$Y-0;(H~UsB9svk>fr6?6{!MM-u~Ngy+sj|GPZvce}o2^2=F$ z?3|8CRGZ{#6Se#$O1cJsyW2UWS5zC`X3klB8cZfaV8|hjFddu6!2Zh+7)<1G<(3Dk znV#T;QmoIm#$AhE`f(8LWkzG;UDUQ4#;jot6Jn_s5Do3h4x*2KQDMV>Z$v;0U_L!& z;=9Xz4qqv~px&GWkrFc{#c%v^ZeH7`-O=XSOyC-a4PtsAW&Ii<4+CTj+>Mt|y|4Qr zKPNc)le;QYL&AIzkRZ=3dGyr8d6sRWo^IkI`Uh6zJ(|TCus?xVodz*}6*&Xx#jtFF zsO}6z+$STUzOu2uT>t;)La4A@1BucL!t%7Ld_X#=0biyktfNv^b^N4{^^784ws|Ba zWEa4RLJQA3FB$JgqL>VNK0t_A7;c3nm?{@gEv-g{-b{+8;>Lhy4Eo;|FpliVVET+T z^mB_O1 z%+s9>?uc3qtF)t&Sz?sxg7_qpgF;T((6IV;~4tIO12=`0gXD6)e zg`QJZi6CmTWW6t-h3fr>sPtObbLv}pXy9m zqosU|f!4Zx%A8H#e{eZ8*F8>i zl{?Gk(|CD9_m$(smWIrYdJ3*B1l#dhW$wkzh>!X#H@!S=yfy+H1 zF5LKCDzZM{Jt!?W9oarOY4wDY_79MOfnEUTUBo_0xfw2$;b|B`^aGBTXVm1a0&&jC z0tle0oZB(`x58@DHPo`HHX0Y{^SVb|?Mw=MG!-G69-W&MxewpBxQCw%n-@ArfwIa| zz@aZHWytU@R8v*U@rV@M0Do*VkM6wKwqQPKRHUHFJ4(wO944;FA8OrUB80Pq71 z{yhCSY%@@A^LWGH?YMGbx4Dcdr(lvB!>|`KJ1`^Q2HddeCSpK(xuyy*bTddya@nUI zYXX1wXXkEZ@FwUYY5y=#Uy9jIfv5vTtcWp}PE<)d67CUx7zytphUW{byoMiD&z=Ox zA(u#p2E${Iqt&4lM`WsRJJ!nD?DaDE#YEK`xgeH+?Ps3i_$^}#-*Kv~RvX%?m8HHI z68(5vF&V|*`d<#~)_th2cKDU-&IFzydy#%TDS`QF*Cx)hJ>%2F-*|^G@44BL)W&}hWk@4;a zg+k z3$idu+qCcdt{sjSM=-qi3b7$IT^PnY9~E}GFPs!v4HOF+3>I3fgw&DreDrmcWWJHO z2{4tW&PNkO;!De3i`AU|cv4dt(bj!%98oEb|2E?TjUl6&GMPU=`0v4z#|dX* z+;i*5px^l`4AT0a6!9B&+C|wU2c~XiW4s=C+cx&z@QPa$Ve9R0_j^6lx%$+r$ttt^ zsSBQ4Akxo(OScHG^>HCRu23xeme+aq;_gcfO5Y#`q;(MKPk+)8i9~$o*EdH( zi(f-iq5zl#>G@9KyD-sWxZP_QFNrmDWJ5TrYd@Na;=a7oX9WS#-Pz?vMQX5*O*kEQWc5XL8q&{!3X|*I)N`n zS4M*?j^k3XJM|-G#3W;gPbhV2u*nrw*_ZQiO%qA!EHI?ifDnwm#8D$(-N3YgG6H-P>EMPIglrgy6y zz1~cNI{9~|2gC#YM)PGKJ;b1Tah_^92fabdRh8to>XN~?QM&zm-N!f^CzCoUMc-@@ zCmeh3W>oPa6A_mYfQzhuT!8C&B0liIP$-#H#7|U38&n<(#wm^F58|CkF_awmqH0x6 zSYxtxvDj+`j`(%xKC=Y?oc+MGMqop8Wya(BS$Fppa9YwNA34jGY0p3x$4rMm%3?oF zHR-6OuhC7lrAIq%H6=*)b3sV_XYk2TV>>j14ja$4ZD={5ipe|M>;xSI4+{^)e5!9( zbtf0%yGmLhKXrIe!ZUOKR|F#x;A+Dtyv_I0C4^X6ICITe?q;AafD64Fqb|%K12Hwt z0z~*H22o%et%r-H=_Xnfqrso+2sh!@2PdqfBlkD?*zml8>)CrYj>%a^IBk3?1G^zy zDLHWNcn$qG33)=U;aL--!0t%6te_tt=bPJ^0emwM!;JG|tqhi-AOI~0|DtPV!GIe% zOi2V6zAd{Bb8`{!bWipx0U%SixUas)M_qCtw46YiAX1^d33=6C*V})$0ycB^)VF#J z5G9vM(hWt8A6^w#H%+o7^9sF$_9pmUSDgd2i!p>M`kC~$@(+2OD#ePG82<U= zu?DG}by>3lW_YK(On6y#5hSK9P5uy`;Ba5ZU=|Q4v7NYbxt{~-{ho$~T(|=N)4>^{ zL%HFWgu(H~;zMl$8JG<-FFBuks#Xn1sTFU3f22@>35??^!mDJE0yFKxqU4M@0-4Ez zS?N-$f`izi=L3=3+ejWm6X=zxN#eoT&-tg#fe!dt8d_w3QChuZLDF;CH{{ z&C~1)3C*?>0MpYGfU%!Z> z#tia$tg7K087y9?DzPAX3T<4lqtw`1NLQNSlQm7iz3TzU9MItO8-VcR2r9Q||9= z`pX`2Z|}Ujr=378Kp3eK0cF`$RQL)TFH!sygP&cMjm>D3()pSd3&#a|iS)vfK)4kY zzc+q27VZFLIxwb*xMQanBnQrc2-1SWF zaPmLca4D%`UAB(4D~Zms?3wPQ_S`X2kplRlx<2aAL|c+3lGZq0T0QEXM&bNg6rmww zr#fvztVj-vhFA1Uo6EzCIy_!h!`zkhKm z6Qn|Fg~KUgIUbx^u=MxuES6rLw|F5j>oLm?)hl@88=35#b@O&OeC{?~@zFgH!dt#B zisAY$u_UDH_2mLtld?vb0LWJM)@{@wqtVfoK0R}men0EVzqKlbs;^HPK^7BW>LS~f zG7ki1qhhOZH@%ZRa^6i}r?GAB6+d;5l|F1ID$`ZMtVTwykk|7J1$&z$C?pS*DFyBE zL`)&eQejwzqrPwm31)1zn9gD6Z;U0C$|??X<3Jh%1b5ac1_?j$^uozWhrZqt;eIn= z;vysMxB07-4wgA#VJaGVcCOLJr^OSt2{up>9ym)oQYIOuvI`AuaA?k4BFLGPF%*;1 zf_ruKkhE+YIwOrC_1(4ZgqMO%mWz}TGk2WFZ$S(ViY{NQ^-W2S`L-5uVfz#RDHV-? zS(rQGTQ?wTt1MKJ^rZxp$32!v0`Iqpb|-}>$mT>wXPKNJ*|GN$s-#WamJA=0Gxs5O zu~)%CJfM^`9}f0$`{~axDiy%3fVI z6zGh_PLiti@W7f%CfPN0Ig_y$%8b#u!$?Z?w!3XEvKlA9|94;#kLC#lfx4Uq>?Q${ zh;oO=6DlQJ?wyVi%(u^|Hd2{&I~DmAPVM1&foQim7-xkrq`cA=H>yFp7^NY)Xb6s z!KRz_w?uB~0wia_7DD8qknGjHW;HAc>}sm-yghJgxn@k$0U<-=;<`}wJ|1DwjhMJ= zLxta}PTE~rr1}}DFLr5=$p>5dE#BfP`N5vnh)Y{klhlpOb6>SB2bGL=PP9!y;o-;b zY~7*K9IY-D5xizTICYhb-Q-Lwo>JA&%xSw6U`q+5WnSb^+(mnOaea%d4LR#L3nM4O z;-^4k`A0dh32Xjqw1(l1g9Okv(g)h3>I)L(I^<+-{;l>rC@5GH^`Dw*&yl&TPtvq| zaG#QppSLes5-g4TJE1~lK&~`=B~YrV9ShH%$$YZNk;<}JhdqB*=X&7>K8JL=f6(N~ zG!~bkw3bB0GeO`7N`eZF8E?t zn_$k@I;FgGrM|+B782zG7vjuR6++`yz-Z99&+OHCk_}tu%8Det)Q(J=qXoBk)+Tq+ zZXGz4wl&x{TE^*>@dJ}`3rJMPGfxrf^`fhkM-W?$9K1ed0|xf6I*%rVa+tCoK{gt3 z;4p7^`^5cKQTb~QmzXFeIj2W&q~c^RU}N?X!33aM525C3aeKbJJiF{n(xNLt|C^Zy zk}#0k-9n-3thryL5838c_n;J6HI@^}?<{_i8rb-Vl8EWLm9aV~QzAYrN9C zb(6oRov!T{v0nE>-xl-F$Gow+!y!N{JJ$Myp*!snO|wHZ`v<|iV{>-ie)eZqq0%y_ z3znmKeiGKPP#Aq+%x=jL_Bz*0YZrC9hE7pY)Oq%Eosu6?IDlUSx_OtT1q;%fr#A}B zCUB}3z*j1Xftq*fN!Q!OK2J#FYD3NLJ>utHr1~V>8^ccxTkrW(L>x~|C?L^-JncBY zyhDt}mH6r~|498?ijdJ@d)X?WWSuWO^-&b|=T9LQB1p^&g4?b9;cf8RXrp}+-Jr!;K(@4ybK!@Xq z&3-%#5u4%W&4CdcQ_q#tK`pu2QSwe)KM6S9$jLgsL2fz+f5;50imEcU-BeSk!G&)o zFvlZAtQY?80SbXnx>Fw4X9*|Ri|I=yL+KZ}tF~iYeZhqF=Z$dmd$By0L45yt zDX%)XA$43VO`l3(5?(gw&z#mec}+Gjh$^OL*Q@Z4|E-%g$l&Ydmi@U&=#pl(R^{$Q z^X%Mwcsup(AvEVd;^FYF-#?nb`>J6846R|o>B);r>E$3_yK=@F)#cbqsuZC2-mk47 zq#8WYlPlJ|GbdCtk4ujb>=QCX9>!>Lz4I`9kOn_Rh922qvfT~U*?DP>_sJ0KZt!YH zCnZY7wwrr6(?@Ep_cf3)5IPWcjl$N4iod%u@N>8+9x>)6l!3?fC&GsvJcFW?oJd@ zFOhsa+y)Y8Ry@ZWdG-@h6L>qb-JTh>u64bgVlj^ZqK*3UaFghj2>0`;)L0Y}NqQND zO}iN{!%YcPeXeM45f4N>FP!WkKH%ig(c8~0%`jdQyOhYCtj0!MB3_OoPRDwRsOY9~ zlcU_8tSwrB-pD#pr&`R*V3l4P8;G+(vn=25 zCL7QJIb9#z^@Zc+K~>47mk>E8^QxNB+O_(BJ4zv8JqWdtFWirx3r<5(^lbSs<>}Db zo8Q~g1y&OwC?hheWOT7_olt7Oa@VGE({+yKQ*NOGlJ8Z|*S1x5JcaWJ)%4HqRNe_M z)i5)KX25;sAwskZK}af+efi$7-UYSk^^= zX{cx`$N^Mpc#N#s$>QpnADW!gkepfi5)b`L9ZaB{&2^ARZ!q#{avY1Z#QI{DGNW+l zHC##S@gDsn>WnmA;clj^pX^WkVv`aR&Q#nO%bUqb_UqIbXDT|xl)r-N>F75#npZLW zr35V9d`UO;fmc6=(4R4wrAU!W2XP zqR;88%E4ZPtP;%4mc5HrFfeY{Dh~ddw|9wVgqOD*`~ogV1+LX591!1Xp__ zb#G~wy?KQOQ1~KzI47gPKa4u^Rj6hdR~x3baP8tRzqeR^gGv~B>5AUsOG;T z@4^Teu!Ha0X^iL?C@Ohl2~1*{lWP}n6TLoW4e=nZZgPE9;z|G2YL7{?bK&CO6_#7c zNG7Q)&h8>-w)Hy*x&7w^a8%#t>IxEG^a=rDN^kP9_t5A2<3VE1(k!+S9vb@fhXUlr zJN4Og@7CP%6W8BxQt7D6W0TGcsln0S1;Oqmr6eH`r&IKV6wb7F&u@9|`KPZPsM@VN z&A(#D&3L?wR=bBzhS%Gv&DjUYJs14=$745oxJNi5E|cEZQm9H~7!k(IBmZD7+sV1I zBU{0S1qiLCB~#eGW|gD=a3Cms0U+^XNy5O};?M1Pq9gKNN2obCHu;Y;*e7Yj2%B_oP#$DH)8uH zf)90|N0d)I16_sQ0+8ZLFaL4?|AY$wE&7*>j@cyd`zx6aGLG`d3P`FLlG=-hhL-s7 zbr`%%@&*sGoWQ?=sgYf0dX(Fr08@6^u`9IK(pZEVTVM(xMNCz*$2Ap|VF>fD92&-M z!Z1ymWIrZvGpA&6?u(r&Ohx`UHkM*wtEIP;A}*N8nq1-zTIAf?)3EwWKd{s%ByUB> zc@??PL{iB@WqqEig}$VIp*{UO(ybWp4R@lUF%BAsH;l?HfOX%S(1i_!s@0qKVZnV` z_WI|~fM2i2m7`%+A39O6#z-q!ek-)2xM^mPcvyREZ*-aIguE9s({Tz|1fm#fsl}nK z$7v9rI0I)_*x)t+YbG!^H?x;GSECeZLeFek&3Ss2b!Rnyij5NRiuIi%0{O`juLX%& z7uEnyp6Y+|*Vvzlekomtl@EQjVAZ5xu)V)R^6BA;GqVf&(`}k6x9pXAE2i0RZ7q;R z%HZ!aSBV0fJ8&aYgU6;?W*EbI`@YfYJ#H+iY-n6~TPNhkdiM@R<{!aEflgkL&DNwwBV*X}dfzVB`8c1(V$%>~rte;yqdu(;5UC!W z?>H)n$vn>}8UnJTm*k66NThb`?SsvVEMrkE5Z$oMx^;}V{47mIs0TGxxL=**>}j1E zvyUnEG4gz(xgZEa?N zy5Et8`iN7tf@fh_=!4Br?JVvn?KF)oZuUl26$O(?e_;Cot|z0lSfX@S z^T@#m?7bW~3<|GueRV59>@-~CjUe7JJuu)o&5!LrY;?$V@<#lpkOb2;HIChtFitSlZL?Z zp5GFhqlZZj1tMZ%ioII?6vCIpkyhp&kr)g_E%XgdEL83&2__ZN9sEGxPH>`7U z@)UCgc2oFcM$La0k=bg3)`TC!M@NGs?#03bdztzH{>A2Z^5@jVrNxnJ1j@w3AC?&i zuqsY6K_bW}H0J34p83VdIG6&ob=NWvqa#{M<*vBiTBQfMvQ7!eR_|guZ%fk(aW>=i zsa`8*Lu?9UeAnI($z|eND@^NONvTYA+Q|@i?IpY=N}Ce%tZu>!V3m&B;O%% z8r1X_tJXIL8OxC;C1CTW9}1wKg83|@6~zMk$!g-pFrf&NkVq#8j$j--1eY3^8cf7W zvGAJTW;}bcKI}`Fje2qd?S5L)+Z4OyeAilo2_~o}8=^{5eS1dXCDUXuKIsuT5f6q$~ec z87IBjf?P(}I=Ax2TcDxqF)`p5ol^Ob!Yn$^Fr2n`I}0L$s?C7y$!^&+Mw6=|`zWsd z4n1YA4B2PNE3a5L0CZY_i-VaPpg8dABDyhqdv3#Uc-NB9=s)r9oXOnE$W9KP3u8`n zT|rASiRh)JAj|MJ02JStHt`p*ho;li^V`I@Q*Vy=Q)1MU$2*7IVCjU`H;D$=Zd~K| z)~gOmwsnflR#)(hPdoj;`L@!N&EJBg*wQ$LWEpC)Pu0He(j=&pv(F^5uNf&DVAb*8 zm0wb$n)AIqzO~0^;9iLac$z>O-mjO)T82a{AYcOb&iPqNay_#6MPyArrlftRpy}j1b#9o`~kc;%Cd~JE2 zw>@VU0c=Pe{8b(9;Fim;Re6E1_$yLf7$`pXB5tx%sZ!kMF8|4;q z?fcjtL&Bsuu2Li|l=v!BvxTp?>C-w4rqs2$%3x|NF2O|^4* z7V~zW;#7JUPbe@eZW-=<;7i;|n}=u(U}Gqb+8QE0ej+fC4W=n=pr z#k%|^c>{>haVrmxvQV*nu}TAx$E&Tf^rQ-u6=HT6Q?^dJ^A8%JJ)#@F(K^}9v`L-t z+uxh0O}{x7rL3C-R~V6PAM%L*{Jv6poRBU)u&<;K0B*~Ri|NOWCQNBQJ*_PqN06j z@ZTDXy{e4)2W35I1=A4?m$%ET~L=5WTOhdV$aNb*7RZmA@< z7mhqF$>;i+?ULULB#jp}`cpsAh&dNDPqGL5clu#QOGUPnu`VZQ@OT%Jfhf?>H5JGe z8L$b+Nn_;*O7y@WU$*rs;fE;gU3HyMmtH~rhv1b|9QdliPk;(LHLHh=* zRqCR#XNQ6wOXFzZ#kfhLx6NW9JuIFHT0|2k0{Ksqz%m%fDsX|6luAAkI=qcQ zQZ~vxU*YmP$+y!3tg3rCf<}TBYOi%`(ElRuOrIBmg|>3HqwztoPT~}BYPy#=*AZpV ziK2a}G5nys3)xx6&=l2)Tbje2+XAd-=Xo{^oIw|OVNwarS7XJ3j5{&WSiPCKAXGk) zTW^iW2Jm7O^##ZD*ofz^Lo2!!cgRTTltTO&+?Z5i;p6@mOkss@?qO(deJ}1Oi_1g( z)KmJ&knRT{7fUvGG_dw*E^ViU28c!D$RA{bL+ zj*=;m|8tGfn$uO?v~G2Mf&<1Y4v%!46XWlLqJE@WS7YcC6Ho;%UsJmoFdU3Lkh*K6 zNFpZ$=+XzGgJ0pMEwy6IVU5cQBLDH}tdxk$Pj<{b1KBiivs_krJooN}V+tP&_Cajg zp}?YJqe`9bv%GB#wSf2iH~V{&Y=@!Gu}EzaxkKZQkp`J*7N|k_G^%ugK$Q;Z7L&y% zWcFK`0U&K;CJgV7zAsnn_W1Hu}qxT&PS?Q}E8QlCN1E+N9e&VpAo2>sS&G$kG9HDQ1%S-?4HneN@_WfD~Qq4Mak2;H)zWukj^fgqvTAhm|X1{bZ&u!F~~L*isiyrIq~I> z^k0okmUP*I8H5 zbnDoP&CINw&A0XobR0`@H$r3!etp-T=}D{WRic6?sltDy?k3+xr&@;osLAU) z8y;|zii%>?C;`IvRVG#cvt*zR)$FxOc}Y=8!b9WeF2yLG&N_g~_cTspdTZZ#);a|w zs;=Esb{MZfWx%TzBK??~9-RV{ZKQlRHcCF+_p0gyakolu9>;Jl_3j&-URgD=GM$^g zQFDhpOm5kEV$qWBUXEF?EsUr#Yt21X)IPm-B*U`ppQY zN)1@nw(xQrE+qL$hNq79Slr;L2TgMFt4zH?69I^ehGgX?A6;%=Hu z7?ZxG&SEh#&3a_79!j3i;8K~^gZ!sC+dZ;6sVke)I7Tu!8Ud*Zv+^SP;zxUGz>NBh zi-Cfsa*!Ke8y+T6S>XKnjAHRT4?DLwUZ!rUjtzlA=cG#ZP3{LPWjog3%w~so#X^1l zg#nr?I^i=STv*}IJ@c-NPk6)|5gyjGj(#r5G66#m9?v);=_Dr?j?4+GJ3yeFyO`UrjskVw!Pmra=Ql-}FW7FB2k>Qu3Dd~3>~uF#IPNP#N_UfhdASQ+|Dx1qXy$_9;S zLNiVK3&oig2`@zfO$kb(hqCqJQD}N`p%!#JkbjQ0J8<@d^_S1*csQf&&)f&XQL@HQ#6t>PBgb>|)i-=p6L}`9w-3e2=543;5s!}Cux0^~lh0U4wg>t= z{P(t8vGuF+szVigW;%dx3!MLlqlX_93DH1=Jqa4^42jjsHnAlH!B-tg!>@4j?J9(T z>X`TiOUv9VQTeznWjRF&vq8D{y1Yf1=*F5Y3mY)Dy025lhPpRwKB*6?%Vhvu1}>st zdDS*t25s-E0nQLAx?5Yddki&rP1p61$lc=|fovVDylGbk={ik(SM>SdjK}LFk%b94 zJU`M#L3a(p_8;vv$2X!a-tce_2+H}w0y4{(t!)yC#bY{csQ(=nmRZc=?==I&CrwR( zHg>C>{_ZiQKvkmDh;_gt5UZC}8^f5XzvI&sS|y3BK)XY*VPUQd(fN%UNqSll8jduN zc6XXp)D34IHJ0WgrqxBd)GAj{d|A*8=E=K=Dd{I zquV|pLl)f{8{4EYVC0NelB_udJ&VybGW+=kg>+Mbv!>u!zWDUV)BO+K zsuS6}<3d#oabdz4+Z>#J*@4JVCl6>>aSm>iNpt@|CfL~>-<*oPtmXm%Y8xa4waNz% zS^AXbUc};vf&`u^8soW|Rt=eh{^7js?%}TyfOO2O7vRSR+DUdDLvE=N>X(7qERG6TJsOnH{ASy8BU75*Ez-hgjb)_(MV10CF3zGmJ9>SvNtUgFO_oyc+})@A3OmhoE3qct z%!ILto-wlN`X<7zEI)bA3QC2$y%ag-c?hv{GuYb%9%p5-BvPPk_g7(@Xl&h&V2Q3| z=1;<-q7~8daaa<6lU5HMevKMZfR?Bk6P_x@Rw@zZ(4*Ly*;Y}TPTUcdEZy!eXd!$J zRME6Y@ABKe{m z5r{Lo`4*P8nq7f%RR6DWj+YT#1A`jAZ$PhJLw%O zUX$M3?%-6ZR6pH&=9F#gfM#{!dlXB6@{heG)eTvc5<>-_R~}4CHT+6T<-NMT3?%-> zxm2K_G#P^dyG+kmcQpMbR$T$zcNz=Uq7VF?FE|6sF>Oc6i!q-<*b0fR2zzzSvrprr z%5SqhF(OFPX)Oviy_0hq*Cs^hzo;Yf@y1dE`XDrn^CXy1|9kFqx@4levKU3D&K%;S(1zliJ*(u(aSm5-BS&% z{Ky;aYyX{uh3p~y89J`FBi!NY5bFyzX_mpQe^7#IWPoYgxt*Vg4wfMei80phdoT0( z^W$;f#-N*(2Obm@;YVw|JycnB`dTIBa>Er+!^+?8HqE+IZtLJMWy&^ltj|jVQ8a55 zm8E-MI$nGp3|QYVex^4JUFmRhQWNBl0ZSbJJoA;EX~VAG){24W53IcoF@#d_GL6AR z8FTpS`}knBtUhKI03&uFhRq(vVdvfLVrBo~MJ&G2jAlPAY zba00X9=>?(D}>cCd~0CVR!=^q;ju!Y<$y$cZg;D}`NfEd07_`y%mDf@AQTHsuI-8~ zcS&x(#5?sr>ubV=sI@c&N{wkGO0gFKr$>k8&S{cUwv%4ssO^rWjd&PyZ;h=J6aMY7 z@cw6wX;rJ}_zj!n+iBhtU)WY0gHk9%4W*1$_-ip^$~)2n`>3KHBfCupeh%YxQkjel zt0GNDQ&i>}Oi6+FbO&OHH@xS24QF?IE|$4lU(a@`3ziJ2yGHRzz$yU)oa9qfR%24k z(2S0bjI=kdX$1ICy8JDXCha9j4=iqdM8?${5PFj~Pgg*6w$yi^A8?B61TJVmVjWId z8fhaWdyYM4sBU9|JDQl4O964e7&i=@d_kDI-?zH|Cm}Vm~qOcHT-aW<$W|Frp z$OOsngFq5LETn@o1`Kz^WL`B(jz|f0p3Pw2k2R<4^Jx3r(-w4WD|ScsQVt^~a36)4N}G(F}Q+i`KGd=~v63(|%{G&6WIW^CG0nm`}&+-7HiuKkyr{oB9t#A#nwir^Jk90?|n~j*m(e5|2_lKH@bpZZ( zH)_zuRhC%Pr+wNPSNtY~E7BjnlC=tqG)=N_8a@hy8~o)1{MpmYx5NH{lF_#v+H`9Y zw!SAIJLBZc=_2dNk70sD!`D$u5(%&EgM_tV2-zNpFlNg22{|tc07;p(_Z*}2Wbyp! zLf<>cF2+cq{hbU8#!3MvnWVG?+T+?0RLJd&Msd-vO2KGCI(uX&;@YG$NEH7L5Qe%^ z)*F(G0H*ab=?l2z?0{s7r(JnV(;8vC3KFm(aorH~n&2XZ3@)|>%}!abX#&g_aGKDG76cotN@`wjx2?^nzJ6H?{;9 z4W#+d39xGA`3`r*FXBrrvt;C~#UKB(g7bLJ9>VjNcn)P1XFnRPWNjNF&}~M%w3Ud0k=Gn=r5&UvA<+k7bq?46P~k$G?Wmhgi>c=;@tKaztb zdPQBqfI*_CpCO_Y&PWYK%6+p#k;L)YEF-JG0Ms5`JWFQNs(QXn3K)t>Ffkt?(FLeV zZgF1km*T5wuS!NXa5yWN4}`V=X7fgery0VHj+dPP;t^4aAwbk!QiCCf4>Bni40h1~NS{ znp4n{P){x3A|8gdFn)i4!P)S44nA1uow3;I@gudC>_{Vn2e0At-YKy- zN^0R^mV+b0xj@s*nPmb?Ax0atpIt2CXyuTsc!A!}rZ##~;ZNCD;=@qWsx3|qITkAs z_KBTUK4C?F!%5L%=wwnxW{XB?YCD<6v24>*3Qh&cV@UtF-JsNWcw~H+ae}Ld=P#$) z(zLYKlt3Jj>5-4M$k%r3bzMd6ij81`PP z;*sfx>u=#aMnf$n@uOI_t6gGT=j*06V-c`+?iaJjI-bR}>xPL^ynw5+RQTrD;hy64 zu3ux}Jz!jDj%1F)q}~F8x{)7}=K;1QE(4Wls+$*jvd<|}SG@iZIea!2v?R5+B_28p z)10}&_}oK%xgbRj`$B2Y^4T-)1R62ymW~hH3s%Kme-Y!$W0}XE$HdJ;X97~LpmNs`G zifmL3v_uxh)U6Z<$ol;w$+?pMe$47AqR;N>F;^(vqwb@{bKgzFw6kT??HjEP`!3de zC907a^G*c&zdvH5Gde%>ndl3Lr>Q2iD@rC{K!tOc>WCFiUgPwHS^Hyc;59(K8}IBY zlbh)1(*d>TV`C1m&x1F}&hyI?&Ax!T=oR5>gz1{8DkrA(5}3YR-HdaGC~QrFG%%8Z4Tmhe9Ynkc2|_gpoM`^(-9p*`r5J;JZ*$lk?$RzjXKUGu z^F4L4NDGAOMr7~%+^4lcZOQRuP-=WADU%49>Zydc#eND$3OY( zYu>vzxwaaX7;*66i~CFTMeHU|8K+TFM4Svd!5xSM^R;zsR@OH(8z^>pHbmDB z&)Ox}O9`xS)LkcDy}+D0PW;Ki}>Gu`!+658-6L*=>(TZb0c}~kSTEy&{olqB~`3(3L5`tu-&!X z6h4J(^vU@b0q*@gvx_NA&blU6uKF_U{#qB!c9%gAzKwhJXO`jtNQeKCOH~WrdN~Ky zFx=_9D-!Y?<*X$nfJJe7`n zdS*JKY4fD?t8R(AIUZSl)fF0h);avh5=t8ZSxyof?z5rFq1DyP42Ra~7;_;$Q%FjF z{6&Hj4?4VYtkgR*&X%T;8PViW48IF%JEG6dGcOgPB@hLFE5QQw7bWL%r}7LSnANDE zZ2@C{hP%;Y-WGAq5S{lCc6U&0A}=XZoSD>`jN{!}G~!w+BK{=9_s={yOeWWn&foho zk%IK)R@<2FfNl+@Ne#5AR1!`dtDfpsE&Q-d-Y?G*UkwH?Jt$alYtcHiR}k?<0TI6J zHOq}_XKEK&ULdF;{O&=)J*P8QfZ2b5i-*Oap=jgv)@4^x;+xe0#jHODP3ql%dWeIw zEs!e%CX}wJI;b409Z*AV=k-WmhVor?+mSF}jhmkYj%TyMA9A$!^QMG$UgXTG)3hOt zz7aPanBU0OF5nH!BP81Yvf0mpbOBsh=vvd=#vZ33M;cr6+&$r*^Np&Q$}A4tuji?C zkAzZy@#{hX+88kv$i@K*hDw^K%RRbV#h4Jr#?MktzC;s-OWY1GG$9? z(^jI_?k+({Zuf*}LtYQj01{qv`?>k%*@`e}i#3F3e2?YfWNvWSxql$ZR{C0_HH77Y z^XF38iYFWX3NLMNT1XZ~v&&)yUQw=a6sgpi&WhTDO8ZFqgUDU@D`qTBTk;4e*XgDZ zr2ffjDl+}!iF)U0-)E##Z;bwnpVl)u7kB?Jy3p{_VRsOTL3|~9ehS~cE*LY#-NtNN zgarSHq+IY70FOuURbJFn{@3~B^CXQBoD?KW=;8XO_LhIYF&ApW-p{{jJir`4O~g57 z7|0@tqDoE#}`(!(TG8+*-0J`j**%Ephk8~TS zmgKO+*t)Xd7uUt$bw`EhPeC;k2Tdi83+&1Nuai}FxoNSLR55&dr4d^lx!EFqaUvj- ztz!q;R*M@8K>nJ}`KOI@?ocC}R?C4k-Mg9HmvO%vBO$G~0CB8}0BfJV^0=nxZQK{i zVzYTTc2H+gV@_T-r}`uE5eepHur4Xxn$^iaFSA_+e04=AqFD1T{3iX>i=0zy!Bn0a zYK>&!juTcNk^|5J^k4!C=~|z;Ddb-cz^{hQeZrR(aTPmL7&$b5I>Lgo!4)KTWmD%zDCBxcK%xafht;Tx-%|j97ag z<@uaN6Nc^$Z4_uWba8c#^e6!BZWfLwxQA+7KceK$(3B}UAap}>3oQXH+fr9jC-nfWp0rc>*U`-qr*h1~79 zA)Rh424f{(>40D=I>3WYL5?Bsp*7Ed$o{!$N_1CtEi3-at8HH$hV_dTPZn;s+T=Lg zZY5(3&<%jG0RS%Ru9Yyp2wQ7OW2W@k%rg8b05> zqrSG!Gh~RMbbL^{8SvM_S~1V3x0qKSCtQU2Qp+vsEJ$oz7}FHnP8DL80^8=zvuJ`I z5JL=Gvh}W$QD+bWtnc>?*4qHo5o=w6;%uWt1hTZ?Np7st&`Zdcnj=Z8tpaKuL(<+L z@Yq*GA$b#OA_?pFS+%)e_!79gf0~VI%aVKuIdJIU0_~zCwcAU5EM8{yT}o$cQ3H;| znY_Tl;`VyCer~L!5izs#Rx}gsjLKcCLoH$#XtN>Lhhb#s8G-yuq}b*OcNbBpony^- z@){QNNrrnt}4=KkJo|@4TqRe?I4l8K-*f2U->RiWhYDay*R+qI}xv47)_u*c6!V} zZNDmJd@XQokMS-0)c8nSxbx_5cpnWotS6LZBwg+F|S>Gp1A18wFs0{S?A7Pez>s3(3sztpk1j6c_MF1IxG8#+C$_|LRTHh@=-Nfu`?76&N? z%NYSX73!kFS*})qFva97ZD?nEWD=Dm3QG9h15!jPdj+l0(Mq^qcS}1`gqL1V1722PCQmDZ1r{#aN8(D3@GX`5}s0bMqsr8Zv>AoLiwb_Q~Ky&1C22cN8 zt_uPR24-hDS>@r3YqE7ruPq{&VAy8ebfIHxX85dc6CKX7w7(uKAeulx6*mlv= z$AMD<(h)3U8Hy;u*EqJdEn73HibS)KHx_d52G$LTXo?*MsFAP4#IG!up-Ny9@@MA! zUGhiiGoTlwc%!;9Ac?kLMohj&X&ePzoZ}#~SvxtO9afWRRQ=F9`K)No4U&=OR;TdG zq)RCS%SzKX(NUyAk8ed7&~t8x#v-vgQwJP#XefIpgyE|Im)mv=$jr zdvlW#w2w(WgC*YZJ z>F`i(RI%SdCvv+?3TM@Um)mDtLs0YpxJP4t@@n zIw{sX8jXchm}Jux51(G0lJByQ=+6}M`iSQY@3OyL6*8A&d(s9rz3N{+`U~XUfL<;! zPAOVL@-dE>1WLjlH>Y;TlMLq*G5iA%Fvc;me&e(C$adLDZli+ziqDd~9Gmb_E?|qA zi-oF&K34w28zs~d9);x*3btRB*oRj9mxRcHbCstrkEAYT!L0ooE1_s^ueIp|KT-dp z>4hgSo6V0f2n!(s`Q?;3fJ*6t&2u{Ns_Xw#7N+wT13idowmxT-s4zoeXOdUfyufIH za6G5Txj7(KtmK%Y=!y-^4x9lyw~t-tX(g8uKNM?RFe~-u2q~ePc+&Mc(#oC-i+g)w zLvfV`OAE}QcB@9=fR$YmophMU3=H4MiXxcv-lvlsO)_@tKqQ}wqab3IviX`mF) zB`}#VYC3&2>3QR+tM_~^*SC72R0;y=*wrbGcSu52cA+w%#arb8>bgp~VJp)hp`5A( z2AKPCdgcf|8xrGQS_9tEEom{KiSpi=OC6ZLXtQiA=%L`<@zvhQb(@5FE+D3a#+Gt! zr*55%*^K1DOYtjw4E)DT=<^em>H73<-Ao;d;OeTmbGFRNr{;^aj!d3hvdB4S|r=)YNoa^E&f>Nw;{#+ zAO|bytuRv;bhcAd3}JGOP#oo2~n)r&a&zkmkt#D@<}n*nYDcmJCBW3%nrxeH`zFN?FiJhWt`$e{2vK z4U_}M=<8UCQuLEC4Pmbom#oE4EC_Vk6&t+ezcIJU3&F4XwwTks#A%MFeQYPH2iqer z*iX%m)tY8@+HKq!B$csl(5ZKGSx73ZLz1-z45BzuQh{Empf}(@wMkW5+z8pv$X~As zs91X@IlR2yT5m?IytWudTl?HHV!dmMsgQ+~^hjT-ghz6hH_U#pbeZ&@^}3aK_+e6| z_m>1VM$nS_Te|^!88MiJ1jNc3ecaC3267B-jnE5IMfKhb*J_R96D?4PkFm{~?=MAa z=NUXL0>O_RC7yRmV@PiQDJtu|7Vi7u9*VQS(t5Ncym1x0cnVYi$)oNu*p1|ZnpQSzoPQ7a??~i1i2;kaDsqE+fdv(19+nzXW z`TFOq`z+yaf)EF*d{RA)jIpYQtZ>zTCXS6hi|T+V@}@sitBGBcc|OMFdzCQ9Q0TB( zq!%g%kJFoNYUPx|$UcW^T zBX3HJJ}czrQ8&Z{9zr2H?7zt!i*H{2dzXi=Mv2~%{MWN^6w;7>V?cJ`*?H()JD4)d z&t_Ra-{EEwCWvFFwrW;TwCKeXFu^I6l@B|6H<^-zZ)L~Q361zEU`>OCsJb+5K7-Ge zU+VaZ8Z$)Xk0#2n^tX@rlE*HLie9$-0Zynkg7r|!%aNH+YV=vBKx=gOV{0s;s%WHK zxXwpQA$mfT^~%cv41GZC@yjhslN1)hm0EMI;NLYF1FYB{xX%8o6Xl0ZAj`LjTB^W* z0;h>|&=x?noE45}4>}{L!R}#uru{7hI{~f|n|8J+U7;j;bCXTBV-9Y+jmpt#5!>v4s5+Y$cFT)+{EAH*|~-#M;@p zTJ_`7yk}uA4UOD18v%ucl1bo3Q`+ME`@F0Z^zmJ-Af0#`(vOo0ZRIwFVX~77FfuMLxz??YpwL=N+&2$Dzz&h_#zIUL3;UeSaY{3DLBc&mt>pcs-Z}kf)fR|?0YP$ zAA2Jomkv*V{4dE6T7;eNPQ4j0lSlQx3>5(62~V_=l3NLVOb1N+Dxb!c*B8?7|2}JW z+S<diDrrK^K47~4>&<*#Zl4a~aSD5I*!zk603owKC{{uIG0&|4ExUvyN@ zQ<*hsDXDcHo-d2i8IGa9ftvHCL7bA}rFVpEMg;<+PPoN`lo+h=)cu`ZCj))e?_Zn& z4>A44GOa3M+0bxo*1jY`ySL^A_fC|L<<`;}D|={&+2ztFiW~gCz$JQ%8{-7%JF8Ep zph?!;nO}nY{>~7v=>XnuWt&Oz$;b1kFMq4(P@NeLA6uu_FV0wqEs_-?32YxpDVwv& zB3An4_B{Cm2T|pVpmPk$)os19YCg*E#5|eBBlz(YHs=Fr3oQ~E*JSh)vJPXXdy3bv zeE86FjE{OXP5LY$GY3h(cgl%8_VUzsYUM%5sCi@MEgf%*P96(3i%k;7T#4951v_VK z^;+M?w8yJ^FldPMKn$&!coZU(dBar6J|gEWc0qE>5}Ly}{ev=8?kWdf|NEleJ@W6j zE?!Br5bAguo-NF;V`0=xSnB`$Pj7E(ZTS=^=0lwJz zE!jKx*X+9|gbA+c`J6VE1fW+#8+b&|jV2mprp;woQ#s|UP8cvNL3LqTP#EQ+{Jfya zFB4ZAes|||R|2|`oaGZY7Z!x#Q&X5VtdJg@@~*zEAS($;^)8VD-#sk*+y*kZ*%+`X zqgK~6WgC3>vK|SAr!8bZ=$+DgBkJD}5zcqo9>$u)#;wTULRLd_8~QK@^ny#t7eWRR zX(Vh#+adL;Cxc_ry;)4pnt3%`odY79{Uik@sb!0QRn@l_$5Gmz(5YdL8@cx%_kwF7 zyi(qh|Eb%kM#wrvi3?*Opk>M~{xn7*l%Z*8j8n(#cq*#W3_{fJxQ+?d(}km$xcDir zk+lkQV3p!0!`vLYVM3l{Ph5yKVCZ7@+J<^guMCAR1|y79wI%|xL29E!8h)<}a%#t1 z!C)Kk&7q9M6?E>83MibAOFC7;Ffh;x5d1#^Ri4vS46p7so9QV2k@#}=NA#`{mfKT~ zGdG>zhPk0Js|7i__|>Uz1X9Lsb-G^{lD#(aVkc2v zG#4gu<(#2Tq!1Q%b365!F(m4PkWIR<`XahfiPZ!z24TZynu=jR`6G8~x-o@WvszRz z0Qaep1YO=$<0o@HoP<|7n(8aQSyYm-(WytGt@~^6WgJ1rm!SbJ{WV+>GREhd!a*Yx z1F!I~WCD|#P|++AT$EnnK4|hFb7H@BW%fFc#UATtUy-oCQ4+VJ;I_h);EscP0f+KB zTg8HO#rQkEQc^&whv&2xwQJ@W+Vql#gS$VSNWHuBA(5~Ts0UQspLR#tf9(i%vsS(# z`C@R}TtxKDKYq-IVl?rfv65e}WQ99cj-%54u4>kB#? z_j=d|w1FttXg@MlcC{@(X`C?UiSO1EK_Qzw>~npDO-#gSux80|KI*QAXFIR4gtvE7 z756#HhFA69WRR3hT{%VUsRW+~1$6!6M!WPjZTHK|%fu7J9yIc6o)fmo)%4G|dD3ib zVOewX!nFRz{z~tQ@Ap|@Q;Q4bhth;jJomnE4J}xu3UQ;`KM%xm96e3jg9$)k10&e| zIoz8~Ny7Ur2{Q5X-U2K>6N(Jhd6OwpTx(N35}V-Q%!Yhqu6i>f7<{y=5UN)dP~7n~ zDaV0Sr zCAp@&_5&Svw{h5uW$OGlj3+>TgUo9!f}t2=W2u>1FQ@`&VFv@=B-#LrJzVdExEB4l zb*{}&H76Znx16DqZBFmfVmm+!J9{p@R#D3+>xjCIkg-7v66dF0@EIvY+U9lJO{y{5$N2&~p&l;NK?%2CH z*(m(Yy=Jh5FsmR4zidVeg2zkZcQe5eI|Bb!KOxF3pKBrpc6MpSLK7d|nIqs0hLi!( z$DucvsjHdmt902-v7<6HdalurcBCb31Zm(+6-89V$gbn&$&sfb(jKH#du?>TItn{q z?3gX+yVgw=1`yNa=AD-89m?g?im=CQzQrB47FPxk6ms#nlpSpMRpb*BGir!GxsH*5 zYeZqi?4&Tcr`D+Cwz5rNShEupm6{T~r*(1em@16VK=y7uzjj-USq^=Nldn>$le0*j z<^KZ)vF%$?@5bsXm7gs;Ch?={Kg7Mw`7ThfQs0s4`20!9z|v^#Z_ZTzE$d-N?IvMD z9L@)imchGnI@}cE?i}-;VCFWwwr=>j>x@%`%oE&xFq-|qhyup1Y8qYbv#d)0TMHOH z0*L%ksky!&>#l32pmudLctQ~C+#rsLo{6R|vJn0$UFBA@5aWu}vRbgqXT*{BDpg3C zg?<5TN>2Gpw2-M2|Lxjl2`TQPY$hxqOrUr;pKz6@p${+Q88V|YOgvbIV#*WMVMk)u zO{nM2>`q_*GO_BiRm&W8Pe=qYq#ll>KXUU}9;J>_DPC)en%hC-#%t631D7e(Rx684L26pU57I zxK2JWs6J%#_o@36lQ1Q!Bt`(m(Vrq#*Nt;Eu(U>L(RyE4R4t#bnXqfYzSsjjXke9k zBLL%E=Y#NbhCrjQ$9Fl?74{`iWgW3HQ<8`NHyXhNzcVdIYd6EgaB?Y)AN`287+;=!7G-F6N5hz9NiLKj*s{Hda4|3Bz{uj%VcVGOc*hXt=#%u|8Y9a+8%&w zX3jMqcn`Tlpt|>k6$na3yso)HY6E++u(tZ=m6SI{doRW*($C5kSZ;ld+kF21l*Qp# zYBXN?A7Y!xKL^&TStJw-J+k+CjSLFgZsc##22B+!Z4+9uQ3=4qxw(^u4q)(X@l4a5!KvvTvlw0o;i6b`1 z&9o|tk#f?lt*p5{##=+S;$w6YxIC>OsDt98#$MZ2Ld3aN$J2h#qJ-!_1x#TC!qzjB z{ztlAWjIe1PIDTSz}y-qzPvj;`03WJuU~G7$Llt>wOzZlWN5mjy&z>3S89kqnim79 z{Ez;jGKfd*i{&bh!zx#DRHGWzhM;bos6w_c$4E%}TKL|=sp=VGr5wDE;}Ieh{ye12 zXaWQleSbd>aEechad%*-R4z8mwW-n*+wV_VI~rZh4M6^DvT?o&N?_!VX%8A2PmFhy zy5Pq5xEd{840fiFHZw$J8yj-2;N)1%nJ6GV{y*dwtA-wivuIe8xPNvV1IU$_&)F#r z5U35Lh#XWE$=Td6DR7A@09chX9y<1#6~RXqn>9bbf{u%MJwm^RF_LXk~UVLy&fQzOC*%!j5X^sD%ei-9U1%lXdq+rhB8B&@`n8^oX=jws)+|a= z$HLyF3X9XS+d}?12vv&waSl-s!gS8iTNXuQvmO}n+;Wg9=v8#K98%m=T{;idyDNnK zPW9Z;!dJj#A)TftZ!IvsXi~L>*Rwp@^R-x`Q0c#3ONxfvGoh1tx+aY^BbZvAGe&*e zJijeuOm$VKCVK}v?w4$M-zlfRPSNcBxLu5LJZsi2wCtT3JrY%cf$^eLK1=jeS+&=B!&Cw^uT3v8np8MVO1VG zhyzymb$X9g>svj0o5x>kO}HTBW)3&a^Z~fbglCic^5@2Hf>&)WJ&~=Gva03QwxWSm zyia7RDPRGH2jC`Pv!?_gF`RO-Ei~weR&5HoH3@Xton`fNTNCwZ9NZl^MCa)R4 zI!s@m2t(3~EkSoc^ZvHl5KjI@-Xc3T#v$PF(ccGJtAvjYa32VH+TwNt65jyVeE%O> zUt1fk+9I~CXQY~KjxB^85AKkGPMc#zsaqQpY>Z&p9`4EAt)|GYF10=duyZgU$8Rnv_a> zTp_T=;MiGV>>K*1dEfG|d#iAMDOVnVVo5-w9io&gT^_jWDuW)wD8F(RX7>K@Iha)T zJZ=-vh$BEKytt9|P?$NJVBhrnb7^oTnUkA7frTM<>9h# zmBvE5XDW&n%s|#Um6Mh6A1_j#R|9&Xdy>up3#K!na*cb;?naqi#UXI_7&oNmb?cT2l`!7^$Zb zik|GHlP%X`BRP(Hkuze-SzW^9*VsfVkeo4F_vDWJ{N`5gAMd8V&ll%sbEY~+xnR^qene;tdy*bJFa%GX$ zly}M+ME`DFz?vF$6kP31JYmnbx$o?mB;7< zjW|xBu^pdM9#({ag7-Je ze#{k*{=?YjjGuxuomFI>gm2d93J&8^bK$h^!&TF*x|etGAV(%(NF1F)2cM1GA`D@` zODxyOBC{fTyPNrPH%-XKW zq0Jp|>v@v^Sj~-5^s@NId1Eu2k;5isGwm6rYBf5DdNV~SEXx!wE^TQTzpX8h0C{^K zr{Q1)2`0O>Sk?NFh0T$V&+m&ix)}ZN0)t z807LVZ8<3lSAg~_Z6G! zoJXC*E-`9BnCFdgn};+136YT8J`FNXkbvM9ava1BsZ&j|*&lTkXr07vNf6KwVWy80 zHTHh-9G0j}=U|U?sr^Y7x#_9+QS_j^(P%~9?5{Q6rB=1oUyEIVr+a9l$>Da>BMc%Z zhOJfDVJvCPo)k`GHAeqD1MRXxHy3HVMif4A2O&Im_Znv7)3e&xPtD%suCucONJ@>J zu{ZzxG95ES*G%P-H3-yZ71adxbq=@&B-bwPbOXVf1h0^4(Kc}yD&+O!vleJ1su&<} z>(I4ZI)=;t)rvrhTM6SX6%J69nxj!EM^`!(fXKUAK@lsy=;IIFMP1NTbrWyPVkkD8lhWAP0l`klA#;))- z1zEnwaGsUFhSr%uH#9jqjTfOLM)cyuQUjAO>x{OsKKLlv@)6Pwjz5HJn%(J!2eO2P zf>aJ(tOtw3%f~d#TKH)0P6*YXSmDWd zFU=P8rah;dVDK(J3-5c0P_U(&BY1g1i2FX{g>DEpo+9dLktX^QiIikBoA4c|3TzKK z_E4(G*cMuFqc4&WOY_o4=>9W@H-Q8sQ@gzscxXIdB-k9_5CMAB+R|4`-!XFXr0s-c zqkDKN(N&{g{fhi>AWg5jZ?oYWwi<(D#S#+`8%F>@3H;!H^7~K}0Xf2qg?Lg@HpIG} za4lu-O&Dvw4?mH--#%6E7S+x~ml+$vOEIAf6?C=90_RjToFY6W@N+XU#)rrPh$qLs zp$u~jiXg#p@uE)_J+=e*4%f@^ei&|?qaC5IHP$+`LjCG>RiU^+cyPDBv(X3nz0ihZ z-TWM3gppCnM9DEcXWX-&%3TCXHeA7=22%uxU>fysp=3y(w(sKE_4C|!g#r_OW3j6J zmRh|YKatq2{Lsi5tq?jfY0gKd;H+Msp6{f{UW))kveO$(>Qv@lm_i0$tsbM<4c7gjy9qrTsi z$`eL-eO%O07toQq=IAmj@wKixSj1~UNP$~MucJYIKL2^ET>5XO;^DW1VD7m~QG2Ml z+cDrAA8`eG_?bd*j`{XD$iWRy_{s(BL8mn-&?$_y^gv@#w4As)681sY$!uO$xgk88 z)=Uzuq279-PchDdU>%vht9+i&gjs6ie#x_D;-=qPgLWx21$y=ZP3a=^A%yZz@ys z8LjRg@j#CM*j>6*ynlSt`|7x)HT#hqd26hdrgvqSt#3^#tmf|JT>ySI@kI{d>7`vy zI38MgSdee0d9qDO?t)YJOI4FDx*pMgN0YPSv%_mhd&6mtzDG>@{K3RH%iAH6C5K5W z(m>W2a!|p=5S6DSo;hF7Sjp(M&kfB;Pz$>(9W%7S+J$Hl6R-`KlTrgv-cQ8k7hwAO zh6@(9xP9z#mFJ2y1t=hOG3q*sHzf&`InjlSYNB$k=%LKQ23B8kW*S4duc%O9g1-Hu zB}%~X&)kJ_YRR1WLOd0xy6U?QK`z1i3%Y;JXrp8-_Uw9y%C9{@IFsT{&!fq6_(BgC zP?AAe0amg5tQq(UU~!lAzoj6e@98~>?uglkShoW?I@!ts5N`1%jv@*_`v`7C;I^}7 zze_>bghP%qehv9Mgd34y{GmKgqtTzjux@QmcTl~#>iz(5QIxRNgpn`PzAXx8@ewbj zEsnR6tobr4*3OkC7A+VUQNuxs&XIP3G#9jC*ghzHaEPgA{A6K@4z9e2YNrTF;BTOW zT21{NmVHRwMkd(z%q~)DY%QMP-S3*Z@OgNQh#Wlcxp~!xJ_ve_=FVYAFI~36PPj?g zzKB_L^gk3&Q=AVHMDXY|{xLy|tkX{38$WVEzif-KZ|eksomXeJ5XX2<8J#7$NDXO` za_U_Dv)oX?hvrL;pzpUEi98MqFVXMO2`=*TgLqNGdM5B_56${QYW!kR=M$PEPt{SH zZ8L*b7*5QhO=H*bS9!watr)YC$txl>$PrX1!|VZ}mrAqblgg){#$f!T5T?GuR#9rY zDz5EC4!j1h_O3Hse&b^YB3a>B`ZnOn>!f^kMEOy8W$*_M_#3W;xAM-o zv%swhA_vvoStoXix@)zqx{ev@xMpmR|G8T3dM3K!$d(#_1urI-%EYdHFD}V8y*C1+0@I$Sp5$^TYITUu)54A zn`%*jNQTm=DXpl3*S?7y5N;FkvY+~{Q}l9OAdf8LLU23L9y!FDxcZ3`t+&ANNpU|} zm;hd1N)V5E=3-Z{^WyJB(gRh7F4l1f!0_;UHYx$_307*U?9hV*j9$v8dVHr{SOm|Q z6IAKvEfkT?7O04=X+7rw&J0z?z?gHT5PRU`ByBcsLZ!CTCdz*hD7rdW@0iCT+0%N; zQ*hiBtzq+4u*^>@pHW=^io!2=%{pJ9R!tw5PT)Vw*fhUkJj9AS7z~uPqViR z6dCOwBkD?BHY%Ji!mU+{>Y-q8ZKb9rxUW1~j7y9Byy^%sO5lIU%=lt1-oPk)Ndc*q zaUZVKMK39Aa}EN#)uVyDq78U}mQ^_I8}MMu`(1&xj5vB5F#fr_A%TbrLXLu|Ut>14 zasaFlgL>&VB}^|}oDQ^ofUH}f+<)c^q0klWBIb-eP<@<9kcKk#BRFbFP;Pu0nD@BR zT8{j7EN>d8vGQ*lU_=#Yu=dbfE#ek^{3w^98pRXlpN}PXe!jPy@6?=1325D7Y%2ee z`h}}%@3I5fnSK_~8a8X9F+(Kjrm!ObaV(5~-50k#e$Fa~t?yKcWucJ{g4=VTH7k}9 z9K!Eu>Iis8Y3-42`2xHzu=3Elu$y0M$|}q3p#dxRIJAkjqigY3%e_pu6i$pn91w%4 zW89IUIvKbR&L(7fhwelu$rc7J7WviT*=LR9(``{kb$fDi3rXGx^Kbpz+6orE@NM!2 zKn#;}V2kppmHY`Lc`kM!sDbquDkj31P7lWf6IsJ2c(Ur06$0kIg7*jOeWfw^Yva<{GNUN5)bI3^&!6kOT)#PAh0}|WP*wm>gWN6Kd4cpBEAIG{1pe;GBH_`0S$X$d9`<=38bB?81Z|ptz7^EK-((%o zH2=9jk@~~3ArT#wbERpi!5`fd@hBt>6Vv>4&&Nq}-wveKx1CU0FH$aCk~6?E%>2dz z+|$!GTkh;Yl4r%HhF}d(GvPANJWm0YR^Ji8RPuNQu-acOBMMD-9xh2n%DkOOE0alW zDL`XUh(Vkl0ND%2P*^*nSxUV3^#sg~}$yr3+#Lho+~2QwpjMbY)J zfb&EdRQ{4Sd$ldh0mtnXO~EufXMHDRR`T@7=&W|M0Es10^xWgKQ92^6WSk?!u}WWC zXvixC?-Mhni6q%(hi}FiY#qQuqGxwqVunnnux^k6Gqv^Dkult3i7fw`%I7pguK52m zp;+uE2;5giBh9BJk^! zW&RH>K+?YyV_d~iO#;z%c@+VX=y>^li6FDXfS=&I(4@v3xWBrTB_;($uJ3WzFb--#xRA+hP@}+*F}s79%jT}eYC~YbO|$f zL0X$kh-?K&GrfaP?XfPv2MbG1&@x8XW)g(ylM?bk2Zx9bdEtlN?!zCg{tMnS(WfH) zGxa)6xkM=BkC!a&nLi{@PO3osEs$z-zi=&N*7g+!$tK8(q#S-Z z6z}H8bsxj!+QIo|1kIVf}Zlgfh%M(-hV>5 z2DeMGNNv$1bEuN;#PsCj27Yb7RphhlF60%R(@zS!T|rzQEx4cxm)A(y2)OC@NU}xn z&3MNwm3kZdBT|UGZz)$fAVtY{*A9oLpbyk&v)AP$N^ub7ODlh0Z8IrRnxYtsE14ES z0`4vM5*9WLRZFSdFD8GL|(}4qov)R(|q1M+eG+-IX=8O zLQXf)Vu+QLNv=@6Nh{%|+@bs^gK>%tSE@BKuLF4U%78^_qT_+LXi%r)LZT*&Y-$m*CV+qF9BeZHdr zCQs@Hjd=08@y6GLFz*)J?XXBp22iee{<{c;TflB9ijqp-O^pyI>vad8rs|Vq@v#7N z@PQ^N z2g~WBkGs+IeGna}Tt`DUoiOb0hgsQ0%G!Zw`7RwY9R5ucfXxNIu>?fMb})UQps@eo zVpLgMvGVfFT%tMiHHi2?Kj5sXZR^lv?2Wt!@}A>J06&{Za8>ba4jL`UR_b;5h!!N{ zWpoy#)TT7)h$Z@NZmSY@^hTgWqCXskm@OvVOhZHXGzHFrz|oebqN2<%<{KoId3;jXlFUGLDRz@>? zRX#=@Bd%d|{=Xj9eGv@S122lo->}Vo_)s1brD-fjgyfw)pv#?$SZOkdHZ3J56X$by z8ax3zKZlxL*AfpoG5lr`AYXP|M8k8p_*AW4Yz>0oWwF#b?;{9%fkZeamB(Kd* zZpU!8hc?Q8h_xms+Rr)`&M7Cx4nOW@7G~M^n%Jj$Vt?H;JEm_-1K{2C8xrx()bUgf zhu3~eS{qbcc%0_K>-Esb_=BDkN&Y*%N+TQ~dL+$u<|B;)U;(wkA&THbnwqDAJUcHk zMVi91NJcKW83&6WHSS#i<9gL^SmK-%XtVf2t1_Xt1P83b`M}K5$wXxdWK!O5ymUfB zUvT*IxSxf-kRSOa0_7K$*b19{R(%hizLnH0m?CXgX2fY$&5&*-$XF<60u1R3_abra zmr!tF7YjU3>a{|=%|#8pyHP%^0?_5H*y6g8*I2G>4eJN$)ZgKCC)ekwe!k?6MG z2&P$0ffbRe=||%1#cEaa_9qPH_cZ6;NZkeCEbBXKk;S(qrLTRZ;=Y*J^xPZr$1gU& zypGc<022CX`XsFj*J^IAMP$Su3bSpE9~9pur$<>nc#e<|UC*1Qoj-4*zE_!M;seLLa*bFd8#pf_8Lx7XqC=Ck4UaMhwmE{m3+hRYp z-wsXDnfvM@K+fCRysB9W#|+Xp?8Vyh69?+%MT&&kPkhyk*tV>lm=2ReD&Rh_V@|ym zdz{))8ljmIt^x&W()HfgBw60h{HBo^U>;PL#dJGOwr`g3qn?M-I7kc*lCd?bFBi;Y zcLx}#xvCEh9+=nut(Ro+ob%dLt;q43w(V$p3762xcp)ows#D2V2+!%RFb=q58u0*U z61bh8us#O5URqWNa0P^Tsg>(cry?7H`cIot+mPTzryOuUIh7m!AUgpET0p;UJr-SukJ*JeiK|_0nq(*hpC zrFaoTrJ-pLnAYuvoCX}yW6AIwVW~)dc8n|{@JQ^%Jw*)yq$fwqN}D-vjRC^`A;=w7LljJ?^NveCVe-@KC6K@$HNu=#K)Qc-=?}7hReD1X zbfT+G7y!1z8@gyLhE7Ow%b-?dhbvt$ZH?1ekgo6@YG6>~4+)Xfg(py};*Ar~FeM(N zVsPQO^V8>LPCU=G>j@mPXQg?2IHY%Vz8EFnrvB!s3$Y|z_QQ; zC!a-u=RJhP>_h612PA8!rNg0~dr@B-v*rk<^0bqplYKQ0>emyotwUv7(gD6}D(Y8m4v*ElsY8C&iQ-oMQ%bzRD_HZg zmpl8#?f4&(SPltI`V`Js#~O5avzwGd(y;HvIOi2*dfIp!Ko@9Y4_CsYg2-YL%|TZX z8E5fCDEZl`Mvz*}=nXUc`$#~mkL5t}<724?PkkBQMR8lInQahVhm$4J*aW;v&v8TW zU49s6yABOe>jQ|Z&2#|0n718z=f}4PRZp-%n!|j_MRCf>!%|c%Ry1bKsSXR8jxv4|#j!%Qi1c)@oxu14!q}^cRVaYw*CzyO^{qd&F$AmZsIJs7_zf)sUsP#W>^4NuGHW13N*c7P;7cm)0(7uFG!)odx zTaC8K#90L!{@}+*_6SH>UUc_(zJakuIpymf=fN|2u5R)6?y+o9%IRu&kQ4o#nIAa( ztK;MalMPC^W^zth+A5UqBdpVs4msRL(P)rqm600FOCmsj`#%cI7E}UXi3$qL6~<8S zDn^Uk93Bd%P0|042lD;1+VAH3#cQb|$1d;@WZmR}=lN`D5K2EZAv`;&EM0S~xU&tV zmUAC0zRxB%DFUYy^wi(GC{1D{BS$X*obIN|fY-;=^N{2LkJu$`|Aka?^Z zkl6~t)=e3^O3pWN*UtEvrK^NA+<_@fwecfjhj!vVRkDcY#C5xnXW0LBx|}=1NA^8c zsrg3!?M?OYV})IHp`0c3^5IUR2cd8Dc37>87#Q}y4SU6tq&?Syr3>_(i;{e~=W;(p0UPTw zs3vJ~?pok@T&yI0l~^ruhTi&#*g<`fO-r_=uRC(0bH-};kZ5zRFZEFIrtn{czoZCd zz($5?`RZFOe;;s4^DVA)zEoV0=h2O`?9=ZqNhS#yD;wW_DF6q!?@HlDH4IJ@MAa(r zx@LN__vrr25Qg@mfKudKRy)-K{8tzhvjQ%#gFp4T{T6!KN$9F4KKb2@pc5qD+f-mB;zb~F1u%L2Uw1;@P}(iU*Me@KU6 zsX&kYrn7#62TCN#=O3BDV~V$|E7}O+D){AU>I|-ASp62`16vBA5OyLm%bAHLw&Q9L zzHRf1Gyf#wI|n1dBI^=z8ko0$lgCxKMz|1)IgvnsG@RHKyR?CPhPZ!z4rz3-g$>04 zyjO@4P0Rt@CS*a~)4TBro8g!*-YOn$&ykqOAc&kZc&6S8&c`0b_cPhhOJ}myhI>RT z9d?24uOd|3vxdH1US=8=KL(gN+Cg7XS!eO-w=k8^HZRp`rXGdOHx0Xr=*?|@E9n}( zzoXG#-`A~HA$hL<8*|e*>>U)+F@AOE-}6@7cIqR*^_u4f-Kv)8Jg#acWf-+1zyqUy z2yu{TG@gvVlSwei0126utZin2O?|6VTgJBCLz60HQCW$K1c;BUf#GTLh@=B!1qUq=$y&OZu!oD zpc)n(H4e2Ta87Eb%x11GmyprCmBKYvgn(4M)OS(dM>`jr+hOXwCQlkAm-I6LnVzc) z+AslvmRw~M7Nw@qn0V{kOpDcej1iqi++|Z(v#<$wRkD0la;B_-ZpzT~Tx!f?l_6sL zASQotg>Z0pQ}cxKQ*xM1cQ$L<3f}e^r)y-B_;1YZ)H#r?o8>ucsHDbFG4!_e%gxG5 z(388zasS@S8G^yQUvMML|;i z>4gm&QP?W`t^|6kv~yjw8is(#fR-T$-#_@A z>Wo3j>+=qM>?CFg{h5RYaFFWD4=yvXa*Tn_OsAWgm>EsD3@M;#{P^^N+y64WD^Dnn z^4qI6hYwMMls}!HUYqzTpsv$Wc+-9f|0TRSCj*bYeUiX6#fFw3%num93#OdwDef2= zy69CEd78kAPHRo;xeGcS&r<;XIMj+}>e8YR1w{UEJgf<5)50Y==1#9aXp~;_;9744 zCc1d%j0C0w3kl@@$tUYeZy)h@m4WHQEO5G1MS?inRN&lYNx9_|ViM}U>ae(fNJz#5 z&CW-KSv(;@Tl>n!zl6WBm%DMuH(D9L?Fu z1KKh*sDJFmfi|o#+5&4}ALz*s9b(mWj&JtQ*NvJL1(-!pa%`ZhQOO$)pyHgG50m`W zEHMhq{HY4xCXr900r$-scN(BMA;s?SZ~@YR$ThI| zuHH4#sAs)`@+Szff*U7+oyISlA}Jp&ho#H|09-LMCRmHwAcpFD?sM9q7Ul>7f4XI4 z{$ABmZa4rR?NLlGtp}&8YiLr$rsth7r0L$pEf8<)GI%tgmW_fg;WwEc62&_MPm><9Zu+x8aYg%ny)+rNm?i=Fy|)ZraRvr z+Q1p$9m$kZ>B1M;WX>@9I*mY&cJ(#az?^x@?vgjFta#zhTXTG!QvCkW6*(iNjY|k4 z-5cf!<%)NSkvmD)Q*fn+ZulWbkFD}yqwd14HxGZaMGSg58qA<#Y&)Q_NvlT=Y+6j(ofx8#R_)WKp#Tk2+bN z?UKIOqWuQVKSiKyIPQXM4*OAu>AJCh=r8XI=&Qtx78LnoNI2Fp{ zKFvq=e^Iot?30%SwhciU$j$-H71pS+?r#DiuBO|8GKqd^01U97&49oKO1M}dKRb%1 z{ib6iz44qSMo0TN68~nb3LOQJK$%Cp+!wC+Oa|>2;Q7r*l7l>PrYp;Hq|99dh=dLS&hWj0KU^*-Kq$2df-YZzSLS+!q4Q5x-T!N9g|3Ru@% z&?G5pnTK3iTL6zPo4KD-y~yytnH`6zQz0igcOY3W=}9?G746`Ao>tqZcjGmG{6zk6 zL5B0$oHw9G`Q3fe!vXfQCv-|w_1Scv zP1WkDw{!ntCr}oDeyf8StG8IP+NErvBw8jXZ91e?x=SP?cXlu}H$`_0$_>`a10lA? zAYpkVC9_Y>%AAUHn^G|`o4LdBA|JA%uEAFooy!y&paST%hML}NEbSv8<0Rl*IDKs4 zgJB*vrZa#_NaV~EWnsw?1O~D4L`pk+wA`Pu01E}U@(J~(I&D{gT19OeS^^=R1YFQM zNf$V9n5bJ5ursGwuBdWMFqISLz2l0f!|PL3J`L{t%9Q!u_SfM3oGvt>eqxcGai}Kd z=_P5-kqQC(A1PMrmu9v)s9yq!uiH=muO&8xAEA6Y0`pRb$T45G6wAQ=1&w{9oJbCz z1mD2(wHS%(gIYDq6bbZe6ydoUJ~!q+iKb8iJC5ayOZiBMj5LZA1P<_oGmI7HyBkye zxkVAJjv`!LM9IJHPIuh_kn4Fr^qyY*^|6j#v4~$~I2=hWeI1_4$$B0S%3LoML|_Cu zcZx%QtUxdbaV`5RHI$;J0kc(-h-uh!^CQBxohOD3eU%^JO90oehOs^yL=1^K9(XdX z>;0cBVB>}VF5>I*UV+Pnk<%@)o*2~|c5yDm6oY*AD1=2){Sg|Q-$iiW98Zo(KpE+@ zeG8#q*eNeMuG2oEw!1jMu;z=;yeLb*|= zM(!{fe}2VqQE1#OMpMr1B4+GSa&d25okdej-47zM<5u~&M8lkGx5(w`l<$Yb6xXaF zen3Kt43zN&Yz!I<3emj7jkpd~vfY)D+XHtJyZTp4h^Gr5D_$_zOpO10zpOLn6uR(W z!!4{4VQhngRUuw3q^}o55BSa!>DI065%H%I^4oFr1_D6sE1i+duf2Y*9a!V`6G<`I z?rY%-cMAlE0w3EfA%lZmL|Cd;l0pJ*LN4__@;#CN z1`u-cm{L0XDRXn1exsG(Y*2!w(;$^~kG9o3CCzowYVvWu^x~Po&ek%`t>6=xV>QML z>qU9&1RT`d8*%ysBEF4%o#@i=G!9p!1Q2)+lW227K9!tR0fOW?>L=8HH0dC5pTki0 zZrT%j?Iq(0AcmSx3zu-9>BH0du-G^T+XknCP1f>&1ik^A z7#AUdOoRY6w5J)QPGi0itzGR?6^d!UWQv7G*l~i>?K2pPD+;(wb?JS$2n|a_6l~Zm zA}apIR0|X6@I?kidoaqu3tygP<^M|&YS^RE6}b7_z~1~)E`z7Hear^D#)3)2a+f!n zJ`uEZ`S8(#RsU!|P_AGakH94LmPjEX^*SOTXEKN%$Bmb`hjPpx(slZ4$Synr5A zQL6E`Hp=Y@OHZ7IDt%lBxTT9Y&x$=sbG6Wpt9~8JaqFsO-wAsofa<-49Y=sw&VBAI z(0oo-kmt9>S|40-*_V1Y1X~|IOxCQ1v3|`okd9H5o8@wdbOAhATMtLJ0-5Ie65iA6 zCOTC(K$|Lj7=4mv3Bx3ENJQ2?9oq!QYNE}n(n+hvcpXj?90b_!i$UE_OC|l%Sc+X4><4Bzh;WX~E#R|@bRS4<>i*TpD%(hRhy29UunBC8v$>NLP_dUoUfV@=SAVJW zKJdp~gJeD_lR+0>48G&^`E_r_$sHq^NkX-@zvuH9D$R50!^F_t6vgE?zao(K3Ssj+ z63pzx=a@#KGsiVibhw(K@G_AuzEBlZDle}Is?luhdME|X$D;fdKbvQxPNJ9|Q{@D_ z)=6yW_>jpV$xP7-&b?-#+}*iYHh`sfk!0yO>mK+tZOpH?B`^Tqky3gTj}fb)z_S@U zDu~8&$x_O~kt2KAWRE6|>ALXRoJ6n|I5aI^pdX9%+CI-DFs&|cUe{LGGh-={;I?Gl zvX@+9Ftr(jjFArDj-jp{aTDY+fe^VukJyqZqF!rx3;=T218L4yY|WhzC9xe{U5x1j z-u`zicYpUCy-yvKx@9M|OX^sS%;8_HLVvsG=nkYq!iUBq)_aKpz)sR zYR{Rk&|v;%rEbtx2hugZ;F0D)_yurhvk*4^S%RT5#0-b|d4zTVR2|?hswvx8nv0Xs z+ilI17E_OVK+16x2aRX=Wk{v2F(STL-Qev>YMI06CUVKj=7P=6sQ~(`p!}`@TKs*U zl~MaINfRT4k&I&st0M2f$}_<2tu|758#OSyS0VjlX@ms%Bl@t@pq8gIsM0C*8ay|^ z2Bq=L`2@%NI0i&05T;3n*y^52Qyn}EeCzD8sak@#S$IY^#&4%|OkXi=%K~s=L3w{= ztZP}N!2&RnGv<+vE&2;-o9XE2y?+rZ@2UzO*Gm=d-_%_49swy@dvnCmt4U%QrxC`8 zV%~sTVu7-M)=zOX9hAp%jjYDVf5keW{VkN*0ga|-xE^W~^yUcnfq~<{I7CN;w=PVRSG*14) z*lRXoVw&N(h8qcjjT0rDvvk>UomT99zF!w;X{ME$zj&hyCYk{Zx>qIJlz)fky+EeF zozut1z)@no+rma>lx}Gyh?d;q`*a4Ch5hc732$~|O5lvP51qIoW z)O+g63^Yp-{R`e`8SIgr(^PH?!!45LN!@d-Drrk3---D}V|^}Ic+68`Z* zG|z$?Z)*A=9#JW6m6TY$zCG}AcPvm0!x>yi9n_GD`K($;1;KAX*EuF*+aVzbDWM7q z!FE}8ZdkaFGaE`+%WYA(LsCn&^>4qrAGfz12f7ef?7-&CiNdR5$0*SxMW^J0M&?+n zd>@sBdqXQYbD-c&I*1iLf?<}6QF}#iqXWTBfX0s4S#v;d+BWoc_$7Hb0At|32ZYcp zbP7V6v$S{)SVep|ln$Fud=D81fRgW`Cxkx4mSj^a0MOYpvzm zO1lGjps-o~IXJ%~JKb5iiwOW}a8+k8_#0ORh?Am3gA&s*)*M_W>FD<~Qw(7&C4t?B zN&Vh2cLiDx1nq3!E?GlWj~*%AC24Q}SqzK*8cd$_^R%j>b&XG1+qVcQUSB82u1Ds1 z$=W|{j;dwhSFIw51@dp=K~&(gD6F>)*9kMq4+ub5$yQ6gjnK>e@H2|$EM4LZ8|RAN zhB006YK0h%GA#x~@qZUE$%ZT8FV~s{gy!i3@Ca{JWpW&Vat{=VrO0yp?Y`Uw@;hJH zUmcM>pG!^l#|rHUOiSr6+rxKXkzXue4{@STc@6mr-`cO?u(^n^#WzEqD)Lxaz8rB- z+C+s^V@9Zaw?E`KFwr{EQ+^i1CDwQUc4(DH_WpH3&SYj_+RKa}5CB z95X|1-hqL@2i<&&yE^6Mc?_1zQv$D3bvsB|(e!mdZqy}uAtAX#YCW40jWUkzo0t3l z%i;n^$0@)mzNo61%jt2Tksno)DP98fYUS=(pBIwKr;ow-0AU^4;{<`Cnjq&2I>;?U1)MX*;Lrf3K|FTHq3wP+29RB-#byImkmc z0bSbDr~nI9bZmt%59l@{_UUvgxv#ea zus}j&G&P$@5{zsvKoZ7ro=H$1Z(!lymzwJPc;+c<+Gnm@1rNqu8Iz_V)Hw$WE?Kiv zpi=BiT|6uoc!C!@E6|d7qnw5oQ_^Ko<)<(NY>4->L#sbcH;_s?#=n;XMmZn|<-1-7 zb{4Wl{O_e@$^qb+-vO;NMsjTcdW>~AKxlvoszW1Z%qQf%qf0dTy7>O;=YmQwT!u_m z_gE(eezeg;Di8XDl^=DN+#aYe0(V%)UyFJm0gl53*X27I^fSFs8tJv|8GoNRzC{Yv z%TF#kIJ9)6+_FhuSUp;^pxNrwNgVe2s%FlHnXst`k-Ve*Hf3u{aN`euH0s1~j9|>{ zVd``A0u{RY5a+_mUL6_`Ks@_pJ8as)K${$6698S{v(=mXGLXu)mB{?Y098$hRidiW z3>w<1FPQpqap`46P6R;9!F)I@T;}api1t_$@^-hGI<>lNNkDdRX6XA z0h$p3SNdQ2EM zCeL7)oCj1@zfeT@yoj-rQbN-HJ=@khjH#@OVx1o{xk_4S-H+11-O9zU+!!xtS*MP~AfvZsRQP@g9uROgI!z_xsaen@=w z_7QY%>2gCL=rHwXz#c>>`P8GV!P)PZC(Ie*as(*MU96G*RT^|{kme!CY#9*q+GkEl z5imcX+h^;_8^c9pDSx^zi!Mfyj#uM50NpwF_@zRGA2otht0Ln%5oM8UnJ|#hfed3t z^$`3w)hntA$}$N81y4E?(^BVTrBAfhJJ5Z`#TR~4i@FL@ndHw07R)Z$Uv#>>L>D7# z3+XJ|ti2VFMvN-l780WKbo)*9yqu?ZcexiJ4_k|d2^k+X)5M|~AW)T8 zQ@KmtY`inX>6`*9k>ulZ1co@B)L-xomTCcI{Ail28zJ*zTW zPwjszIMeTmK6Nn|V@;a(^xT>F*?)c#I~^UN_J5f`BWYLok1(NbHVaOu(fRjYG=%!) z2W4ir!o;z+CzGm!*zjDEmseR?kbb^#GzR&1)hlaySmHIsJlA-U#F95m8zvf3oXyD5 zv+A``OTw|%m6v9dS$}hX)!kKw!MUo`-7^phij0#2 z6Fa4tcE0-mU1e#*Uyu{KBAEfGLd&4?8A*5l=`gkgMXAOwdH6X{K*Ul$ks(1|z8HXs z7FiT;)Q@*{fD+rSQhh-@!!iD1F6ftBYPBj1LZOCkRz>?La;Rw8JA{(dkPAoBR`F9y zHSj3|6}we?stwz-@Y5|~JHJD??8xk#Fs8tk0mEjsD>zV!hX?X&?Z^_fgz3)aH|Jl8 z>2@Cx0H+RVyP12((cE`!lrhCC1?IM_(R1o>9;f7-U8UeLE0hyTmbusbL`zFAhjj0o zkuzEtm+(_^a<9an^&+>e;ado0TH%q}F-l978YWsUBO7}$3+5L~Ms=Q0cfiO&?2%mn z?YGWU>c`^_KhJ1(RtCn4j&8Mb?b`_pf5p+3HOq^qqf{iu47PZ05$k1!Hvp~iRNZ_H z4-+q`)gl|{Z9leF+zS4rf^iwZ*zSCoS|+^9?r~g$K`=GD^h)5;Iv>v(L*1%13tVXq z1%%4#(>Nwl&FNCLgmNT9FT__2ssdfJeUkq8DQi7%)`2ZyocypPb&ex|)r2n=_a1yx zp41Jskmxe-=ZOg9QSw}bz34++oSGPFWv1}GpBn$(rtV{_Nfe)7da0{R}Z((Qjly3nY7*)_KwE7 z6z_L{>s$8!ewLm)w6MTz51f`F>);otBp%#rzt3KaAwYW|2Zu!d+?6#4fYNDy(FC=) zbSs=e`LO%93Q0Z?_3m)H>K`U_I4g##^2W@TSsG}5^(imrzwDC8GKG+}0(=qN4Be@02l-5u zp0VpbOA0|p{`({QAMHGZC1X2)&aYN8x)fi#!2zx z+?yI_wSYFn&TFv+CPSygE$rH8pjRb9;WZ1^-2wH8B`i1mBud-gd4Q|GT-XmWuRp4) zvm-5biis6+>{iAtwUlXa`jPc8`3?HQs8#S1NVc_$O(R7U2;sap%#A8luQNuYn&mhX z36{jm`e`pcD0awe;+@z7cm##6TXZ92%}I;smHonU15?<>tpTIP5vUmOF)b(@`BqwT z5Y>*goYHxYpwNxR{A`DybsXFtsO2yaFr5J?mLlWxLy<5E%4;etss{rBIk$~f2- zdNnLx23$Vq#!Z-1`1`gBJNwQoa%Zq1v~#qoIUCfRl5Qv;V>2lidtt`4Q&b=(Ig7ki z=#FQIYbn5q=Lt(Pw{Wi!>zPbH=xVvypHMo$kP4&{CR(u$cV@Eac@7PKiWS1EUN|8MQaJ}IyO`OEde#zK3 zr~a62cezJ;&uQJoy(4?OK%qq@AHnBZUI7#cQV-}hEutC5nXNb6%8Dk2z)!Pm{C$Q4 zB~X`ZI3?fyxW0&0gu*amoFixY^g^b9Q!Z6ucSDFvH=Jjv94)|RvpYJSR0mHqz`(-g z95al)Y-4Y{kn?Q&Qu^hJ4XLg&Uf7!)pxyd01(cG|suqY!+=dqFj#fj1w_4bD3v!!# zQJEk$VHY}F>)_(l4dUhDhC`c=R%+YXLcl2)Pg>rC^PF=Nz4-1XUC?AjD_A0L>)=<} zfXS0Io1(ja$-3N(w}}|ojb=Z0XjdnF!5hTyZtf~1(=A(0y!%cj!=ztD_R9o5L6nGE zTN>@QVCJVFL4`2TJDjW7v~Zn*hPb=XMYwIc{1+&BenPk+R$Y*bL5;ptd)X;1^wX2c zc^RNBs;klif?tic$pk)3(Yu}{Z|h+3GJ>kLp?=24_Zjxr_Y+X6=HOf|ROHBotkgZ7n16iIdj%Zj;gjO^50wvlG13{x4?dHWa{%?m;L(WWn)M#kkw?Fuy!wt1QUr;ntS0y|Z$lfR7a zlPJs(>kAG@>buFj%!|mXR2U8mGn%&Y9RsV;@fCb5px7H#c2+DZxNQkyYlslu&&mm_ z7P-y==Pzml2QKzS*W|Ku<$-Z}&s6zsIf% z#cIQ=ln2Ti4AEgI2O}5tDoy?VIr2g01|}}+`lR(=fd(yR@%R|^(rrm#CZ9W=!Xoch zfR@*h(b0UKoL}squkE68YcRn0daE_`;Qy3y9Sq!gEUY%Mz)TPxpjcxG4yC7<-cn7V7X+`o9F?=ifrOck6oGFWy>x#%kMCgSC`{ZCh6wH<0e`n%*90`X^LA-A=i6Sf;svkxeyMqd&?vvY`BCG4o{f7-#0Ee~ z#X@)pu8>G=fvj+bhewFTYdC}#%ndACwH<>fMHvUslYbdAcKmoi8=A|2DPX)6WMwd`D&>w$ z%@md^1nf8nh$D^>@kZcR=#KQn_k2rFy7XLtOv4H694oxXO!$4-wtyitbryhzK$O93 zH!B#k(od#qG*b;@gLKP9SNc@`7pZhvTMPlj*@?f!lxeUN90X*$xP`jB!Hz z-yw5Y{pk^RuBH9D^X@<%63-j ztveAY(m8IKYsQGjBc1KY!DO*TA_!{FTy8$nz_4y1Z9ISb#XD* z-was16ntN6NfX!YYNW1a6`6)DRO?nkCYh@N1hz`+iE@av6%VDqWed;ZMVi~hT%~>7 zxQ6r~%H6m|hFqP9O=c?cc(Swe_J>|;H-*2Kaw>NCaZAVfF~aUB_&p)D$%7U&(WHic zUQXrH+jwB{2@-8c1rjyVy(b3WbBkUMk;o!=OY2F59_gVQbuCSnZx*tv=@yPv+A+cE zSJgqr0LxE6LuUaX5$t=58yOTO*I~t%Dqxx(U<7WF_zB4Qr4*(O&@%sRq4Wd$f}MY4Y)y| zD|3s~uPF&Z08MSh3P~FPnllQ`zZXY?>dD?ViX)M;leTDjjr5^laeaYcIlwbFUz;xr zsSEz#(?z;NW|BK<3CuP8^F_%kD=^t!z1)bf`*(hG!$d}eNEvU>B)a&?y0=YCA8%)0I0XH#YxZA@T z=uqWWDFZPj)12;~#w_wrQv9STYoy>$Cd!U8lprEVe1xI2W;Iy=`tOVG_Pv)-xj7-` zgbL}(tBPxjU(RK}<{Se>avxZTgO=$F^Of(kKWhDf{^YLnI7G3isa>o*3XYjbdAZvU zc4?$2vGaF;&h$7Gw_*N`wDZYP7jhFe40Vs^!eiUe{FqV=g?tUhD3V|(l*%*uMLV2p zytXH*R2*Eso)WB{RB^0+7w^v4pX^w7(iW57P#$5c7aw}%J5Y}E@(1xQ{<-`T#M%g| zl6CvtMVtr#^iwOW+xOF>RjTX*K<=Y;;ksN$8L0Tv*BaF&Eaqit7jVwoqB#5yT5Rg? zM=df(WE%B3mKD~YeiCpP9HL2&%+Jl6&%C02o&A`^I<2z51?{|TfpRTV+=O609JTJI z2Y0(^iSS7B_GCaTKC_%EFog7@m~VQf56ps0UH&>^9F3<}=TzM}`0wIeLZ%2yMwS5! zqyE{H4gP3d;Oxb;%hESy82M|6%`x6UN&;X=Jr9s!UO?4NV&8(t-|!6d18X3ZKP zd5P95DRF33YcRCsd83n=v!`0f>*!+l;y-emLP*4nY#kY(xo4`S$7AsF;NL4RG4pl1 zmyq&QbcKs(OLi$z&kuAom@?U@`ZVCotTqJ|6=(t!P-5TthuLFx@NL)A*^sx}9n`VU zvNLYq*=~D})t3P(F#BCGz2_j2p4AbGVZ$?m5DYwHumbA=@79SyG?dZChU(`j|HQS7 z1E4)70!O)L^udJ)tDtpHmS_1}X^bc1*P6z;UQ(3ZK}^~>`>cLCNaM^ur7BYY`Ck+d z^42J(+-0z}xU zm%Rk*|0H`dk^k%68;MJClcsCYnyu=qUSy>!^TBH*``?TS-~&8TVB+Sb#si+-ZG}6X zR#8w9&rkqYvXp(w6*8phqTiau1F&*(?cX6{Thl7-Ykk4xs;tpS9KR20Yv6NXv5%Zz zkyAkDaPd>)qr)fmaQ8#89-fA9(We&xTy>V;JVR@?qDQ#rm37Mx7#>7?Fm_vtezJEB zL8FAORKbyyHX&=6p?5>P$oW<*R(q#R*Jj%+QxGcGU>6d6fF?&?E8Y*2mN}9~?|WRZ-qKf6tcck+n0FZy3cy<;yMm`&Ea4cIPSQP={n61pm-3t zW1dh4cML9+zsKQiY@w_U(L@EF-JYjKl(=p$EV~n)ci*fkH~(rsk1w?)uixjT0=Q>a zv9$Wh(4lM1B?6%+9szHXJe3aqVd*lx)p9y3$@& zgbAis@aCV2qo0N`HvTyYZau4W7Hed$OxF7EN|@{k3d!X;`3ZM6h5sFf<-22qQk=l> z^|Pf1Y8E*n1qx;rZEE*}?p`x1jW*v4nGCLg*e|b#9=)?SO`tmif6h-H&h9GQg~%e7IDWMNv!%bWezohjk@v zC9P47R}Pf?baDFr6S7w2mX>VlFj#HcTh&iQr3kJ8L~@ayRtZuVz43i*hUE+K-AE2b zU4FfO3MmCTcAS_X!B}<1QQ30SW`DJ145jQLs4`}L`)jxE5s?KrrEK9MfvA^ax3q7j zc^B3+iphMNm)$?o-$<(T43L2`yc;P!L2U$58Wk7XZC^0~fyy5Y{63Gcxgf;0+Nzuf zwd(?-5t1!qPb-auk}YELbO+M6Y?HLD@CDqYd1lv{!e`eau9?;HhC4(s{!^o!UB{r_ zb_Vqw`4(51a$IGAak=G~Za}4>q!%@+i=jEJz#@0TvybwaEFv}RNB-IMTOD}I!3a`y zmNT_*=890gw;fxyc|h4ZO2wadFwv1rdWE355P6@g1wxm3o^B0&${Yv7Z>k1*s%h@y zE$9oN=eifl#~C$?rTH7^yjRRRc(n8};s?uXA$M#?#b{WLfSF@WU67Z>Z)P9EKOCTZ z&NsQhgl4Tv7nb@e`=AX1_py|MUD6D1b=0b_5VNam8gN~>wyUgWT;(Ip=M$Kl`kJjJ z|Awr4hk}pzf_6sQvN9+hFo+Zw3Iuwx#E(O{*rB!1`=@`&GpUl1;o6o$Ns>{%Kx|Fc zbZT!v_UKzGJ)7#my?lvw&`O}zyCvw+%sSxp<(U*WGprTBTyb0GbS740R4I0 z%8-)1<0k~soSRVa&)SmBX5qT!>`;&;|7g#{?B5YlKEi@rU=Ch+8k7aJp7k&M`%ySs z+JevN(Ree7a`C(asAfb-$6v_+n$PXA6dtPX8U147o4MHC{?^^nkf0}w)MHI*W z?J8Z#X0%u#NA_Co&`YXgmusKYx-hZCOB9`M5*l!oOWjb9J_OyqlvgLsy+5@r(Lc>t zmP10H)rk-`6{UzL?FrIQj?=jeBvG+`?*w*Gbx-K1M zb*haAjkxDOUi%t?eZgY_g7;p_i&eYzu$r&7~Vh$XU?-5MS$ne9l( zec_;{bwB5)Z99mdZG83HR1`Q)N!%4Ioy!rs@q2Uc=Do1`^rsw@4h$;H8s#2?*j%h| zju75YtX2`_2vcxuhzP@PWWkQl-?^+~yC+wBogEDOat9=tWt&ED92O-n7B0;f9c_RB zq^LRYFD$GMEoxvZc{_+aSJ-Ol6v76Zy5#Aw>9%z^%nShC=9rATYeYHTL?*JM15XfN zLYcm}<=j6OLEgl$AU^9iB*+Q@>7Jjbb;qfGOZ>LtdJpu79UEbej z4C(-FQR1nY;hYk(Lx8B1bwIk+{v(Er)*8V!<{`iK9htDB=yMv3H+{iZ*jDLXfj5=( zF%vUoB3k<(-7@Vo{VZ6wSq<#;EJD!&uB+1GJJFzH#8W{rlXtvE=HQE#dQDFi90pa0 zlrXM?Yz#H=*XbU3&#Hl2cD`k3myJ~S>Qy9_hDFtm__c#e$S(ZB{B%|vT1kx<7)vn$giGR)eLSy74^2PF0 zz(P&NePyjFaKV_q{(~tP?|?bKijzPXhAY649nXLG^2fURyAf61+^x+h+`sw&14%13 zMq5%>3>;fVv~BHRXt^6n$g;T6lK+eM%k#?>t>Aj%@)VkpY3}6h>amh_{07#&2)L)~XoAnXgbI-z>MRVrmQPz-P5SvvPl78*AEzHQ!q6(KH(O{i8ctzH? zfD!DxZSkbIh{Bb+?h?@iam?VDz9YUwaypYGSUL&p`}$-YAz$x!5UeJyCBu1?*oa&+ zzj}=Oa*emSphWa4WC*kEkRIm?sR0gBhO=;wC?wW7)ZF^l-Ryj9yk!#q_&PS(5#{27 zFkVt2`0wGjt`? zpllJxh7|+AMN6Uh4z5Sl!nbG@g*+Iux=AI(YaruILWR{DUlFxy9e?VEyA5zF1x9MZ z5Pnj@$3Z0+Ubw`4K%5&xo{EUZFf!@Ht>Jt$J#8;Z6>NOz%Tg$Fq5J z9Uwdk0_QTn{bzx#q>`lI9eAkS^W_Jh`cbKYcI#imVpK(b)zi(+rlx-=&7#K>DkHl! zSW-{S?1ujs+yBfA(Caic;0bDnBpb-XCJ=Zl;eIK(Q9^YImQu25!WN=~og0$*5@I=m zLZH_pl8LdwD85`nESI*RW!~JGf!-B&b^bR9TWe7+EVz;3qj2=$Ar)P z#GM37FI1ugOu(kz$Q}g5P>9|vLY#P7VJa-8e`tWigD3&Vi2vPWt&4UqiwP{y%S}j; z;OGWU$eh>OZmtz~DBZ5WXpz4d^xq9jmpzRBcW5(A0t(jJn(3csf}BsTEpq&3##KofNp)u z-MjMyKOZR=+ag}nCiMQZkB_SM1IZ(x)-9v zz)H*CE~z@DgE2n^CXr`Qqs>?XfUz}ZX{|q@j+8oGYVE!~LAN?!S0#aY;^{kXJZ&ui zb56^MgW;q~U)FqW+QKV;-FV<9d)o((r`VII+aq2RqtT&l_A2h2mCwg|H;?b!>(s680 zxY&Vi9N5RLvTeTu%!5}hZ?b7qHc82kCdHB_jxF)ZCc#kL74Vo!Uq+V02Ojm!+WiJq zx{Q_x{G@FaLjkWS`vH7tGk!^47(0tUrcrVTeFSQ@GNMN`3H`NMTjae@5s)8CAW#NB zo-ldyr)W>AvDzpM_i!TiY`lb#i#$Sv%J#zx{E6cLrg~zEp-6VOC3D4#2Q=}!Vr--2Up0&10 zSHGLPqLz^IZ9dDn#BlW@hTU>B6O^ONG3)q|BL^raCpe=Z;gH(g2$MS zhW-S!_U6=GC+@#!?dnD3j}h9bD@zi-q&c4^0e`u{DFBnL6^f9Qmm)7eV#(gWI$1wN zSAZZre*d|(`>rs#g)v>2f=AIO*2P3sNUP0yA_>M9B?$`8`2C?zZn(!x8F;t>>XW6> zN<4EHGNe$)He>-@KM})K#uG)h&k59w+Fz)HMb7u^{nVU5YDB3^Yo~Uo`+*%S!tM=? zGICXAON-=Z&$uC(pvWd#ci(H!=sJE|B2q5Sv)R7MHCN*S^J^wcOL(HH4xwzo|GYK5 z`Q4Ybm2d8s{JLT5Fg3~AV$dBW{Sx1|=ls3TnHdS;>O^AA6AP5k&_R8uD{VWt@1vG4343`V5r zZK-7ia7uZ;*;`FR;lobT;`r|Ok!fvYOYlok+EjFSBKac55+t~`|IGH|a-8%)eDi8z z&WFIXhAkcs?`kCSx&YWKx#SEx*iKw#$0!JzN&+p4wg=>tScSAo5MY;?K-!kQ*}h5u zGRIeZ3$~|28Ub(2T;dpp;R&7I=Tx$WJ`ow;;fi3a!FyewckVhq`v!a{qI5ZdYRL7| zRg2_rDo8(DSOKNS^m3i-gND{OzqS<1ys_wb0heyqohO8vL z15VX^cuNV3G(7ac{!CFNlY(*DfQ$sr>1Y~v>#3U=Suv(Dq%U`>fW;ALo;Y0=S`EgF zF=`w3=>?wEFauKpOcgUNgL^V6$y56mmGn4@h=U?&15;P0eQ09DbKKdmo6)W|ge?n? z9I4pOlVXOdYm+M?)?VhWZeToaslQx1{8}DjWRlmVMS%|hiC_U&@2x9EW zjDfprg&;Sqtsf-7Gi&;e!hv$~?i2UIlspPN((-AP97Py`74q@JCBN5k2%U@FxWxJf zM!~{Kk-avpImjswxYM+|Ye+Q9!AB$GM~RjXjsY|{Ebf&P%-5LoONZcgCFfj<1Y!Cy z`diyqv&DbYl}T{Fa-?UGs7Aw!>&DFbkCocP#L63B3GV&vZCf!-6h~d->s(O}(?YSJ zRC@i5nomw!QYM=mbf6qodBMBwz{PGmL`~qJ!~0+{`Xa+E<{KhetoMu=fqC`!E}Kc8 z$;s>+?zA;O@YgdeO7@=T`4`0(WNTw~=EG>G-_2L}e`(_ zFZ*XQ0J`e?LTP3;;8mE?Wqv~1SP;gg7=ZYx7eUBAJV-H*+_O2$%4SX4fLMa!KN>AE zFh|o>+fS($Xd9pX^sm!vWn!p{DL~>HQ%7o8fMs@A*RR#Uydl53*7fGX`^okv2(XQ; zkr_RVaH`kzZ>!gY;H^#xCmz#H!k0(Sqo?F3oij#4h+n+(^v7HcY0e&$>L$(iax7eU znzXsUw8$h3UQs;G5jdMgV0IS-62D?V_w)g-?k#0D3AXCD zN-u-wjUtgPu~DP??)D-owkMt|=06q#$Kj|1%^_H%~b^@@bk1OgHfo8!@n z$N`x}1@C;zENY}0OfE#8m3o-&sFe4G)_>(1w@DPPLH0Y3BEstExoE8~OlNmQ;HD`y z=9~Nbhq*E3@pYFqJB`4-y_`zmn-JUK3Pa4kscVi^KZe%sxg}Q+-Kr|Cnm8Yq;>I_Q zAh=(Pp(XmzMhs>X319!*{=EP*sel%lK-l<8_gnA&2}w0MVIQNC#na86M4b!@I5oh_OyQ{=Z$d6@~Bf8eonXlOTu^X6#yAQm0PO{f*-u6te zHU-}LdQ)apDV+))a-a1YPRuS;xRd`I8*4kkeGz<+gsCFN;^pc^etIV!g%G*U{fO9# zJ;vh36Y!j-*mPRWNsdWX`a}Tvz?CGQ_&qVcQDAwawiAOM#2OeQ@?Z$c7uLwTuCrS9 znkoRXY01J6;DGiia+h&+2EN!uoXYtRcV6e@B?W(&aQEXww;F2NztIWD-kJPJaEr}-ozr%8wRJH+>BR68`zt0IFMwA*IOY@6$mnoRybuhH>_8H zeuihR>TTK^tP<0dBze&giK zTB8>uMEp{RD!lkr58TCDNEUetuzBkcvw`C<~Rfzgf3tX)Ne1;QZM;oqrrK81ZoG7H5Su=k@-F!kYyQ zP#W~KP`P|X^y0}_<6+c;)x04%VwYT(AuW9dFN>mbXt=z*^fV*j?Jxz6?LLW1 zlWB6~dOebmZ7i+8x?C}*96u9uk;Phl)IF&+YC3!dX+bc`;4#$r`TQ~50JleR zCwaph<@=C$S6D~A`GELzNbJ{!T6tUhv2QMjn7j4IQ3XiV+RIGd1C>D>y`9ak()pk z+;HKvB9yBE8}3{TykxKu9$zdiJNbXX{d(9XqVXJkt1gii_e5!fn9~vbH!qLx{YEtl zTK>wz(7Lney?amg^#35QonRO6tpt>&^&kb}BlmH%{V6@AQ&B_&UjjzqRrThWJBf`B z@;e+*s7Nn|3!DcKzgM!}8Z<{TKbM4tj6^`0C$aw09aQC9-w)3pu5W#rjg-_{sm==8xgV;78kNW_yC-vKky5WGHdrgZGFOb10 z#N&ey9X-3U`6EyE`cK9!y`P}QY%|Vm8|oBIgS4YHK6?U~2(h*?4TEd{V_U-dONGLA zZ|jurdL^VO6ccwqp@W~U0{V+%Pqm^xbFBJs{CLi#H0h9Dc{T@89H#)A2nk&k;J$4E{6Lh#` zwYBO3*WPd3kPdFZAAP%kRJ(arxRNds(S#g>=(Kn?uRz?3l!5#S@D~`!IJuchu*!iG z!qJ@hzc>?gH`5udbnF)OLkdXC-nL@%R`uz?D}+eV8grt7BSfa13ZPu^`W7J3->V~e#()8^z$1;4?Ss^P&+{r*Kyt)z-?WmunkTq z(j*#sC8Od&qbcW4zP8Vd;s|{xQW!Up>{X+E+epIQaeB@Kh<~o(UGVE#+tPC+kbpL%xpNifW49ebar|2NEYs(u`h^NBLUoM&!vV~?7%D^Z2 zezBOb3!!OaG5e>CCwp$Xp&`}9sV7vHlUIUoZ(&m)r){Sxql7I$c$ z8!*Z!*|QJeTLylmmx3VA=C}I|qbtC)RW74y5=+qC7w!}`H4Y9X#yMl$0q&Q!Ejd1_ zeI-g#Ok(|7roGVoKBarzN=bL_c^49iDPOU$j{7E6nVb7qvw7xTJeKf76Zu{8Hi3j? z)T!e_r}2ymWAO_ zu~u0KrqxGJ{sAe!hDK6d;W8&}D7=Fktlwf2?w>6sFn~QqE3yX`WcQ8kfgOytaQ^}?6r3TAPVnJZ!YLR9|QQEr$4e)e>Cv;?HV z4fxx*sgl#|u-YZ6tbg|Nzc>d9)@bVa-$N8E0K%waWcit)r@M@?(ZhMjK?S~LugEH= z#cx5g-BunHWpX@YSWU$aH|1ZZC z1^J!O65H^y3WaJ%H+oNoIJ{rv1ktiUvZuTx&NSJge>NN1zQEgP}f2qhk~*xq*}KK{|2 z8N(g9tlxyD_)x=}78qO62DSFbA63Qkk2N4E^d&$V?f1TuD~_DV2R?SQ<`^7TFSHS^ zC`oK`h?M)J0(-{4n4e|ILLAB#04m8sVh@~0rzxb64+TT)DfNOo)Ayp!?*{~TIRB?^ z!8B2e_Ma~$a6&|6E3^nl!8h`K7|P6fT(~XVLoP!slSaSho%oZ|neI-~mEvW@{v@4N zi_1XAmg?9!jH0k27~h{$);&CwCAlo|&d;#7O%j8JG=}@uw@@)qNeIz)$C-at8 zn^B~9o#{b^k%$Yx3-*=gV><-|bd&WMJP%d9{!wMUMK7sL7%)Y^YVMGqh^sbV7OzHT1qg`vl0j4=#9|yhhR7XqE`h0?{Kf)Fh z1GZ{ov$75yxe01$pJd9}D@PT4{rgR6D^Gyb{hG*nO-WNF!_3rO`!pV`oy{|==M+C||=DZlE zDX=o&h5eM^$-mMF_C1;##9SvBs_=59l0)8IC~$<|j2{Y43ivGe$!uT@%;Fn>H0a}& zXbYZrO*^Bbx8Xu(Q!X`)!w~rT*zN2RwlvAkEFSzYYGCXwv<_}{zs11@&HPlSFbQm( zdJ*r$>5|6bK)oxgyLt@5E9cC|E!(l+>eIxw1l$%kgUT1!YcC7DY~Vg23o{f-z7IwG zL!g?q!L7S5OyxHoXiEy}nY~YLn5k{n$GlTBhe@hf{6oRly)=QOM^Fki=eFu6`jNKG zBu``P-pb4r)!8_--uIv8o}$AxkI=u-_*aWgrCwl4EUwqR?Jt2-!4o4>4N%|z$;yf z@ETs%H7|AUG|Y~GR+oLN4*3h&W_=AlZ)`J1LBb*dYMjIU1d1o#NBDybT5{c0W3Ofz zr4+%v5?g^0WmIT4-7cDoR<{u3#wFzCpn7dl_9g%^?Q;B!gssZ3a#ENW&7EY$Y#lA? zyv=B(gD^Ylyi9lU!3>%{?p7;#egWDgu_%-MsA13Z@nE z@-lq>q0i}s)`!;eV{!E9KTwYv)4hBRjcVH~v?Ap*U8<-LLSNGh!1S$h$cpptIsFCY zGiy%@!H!Tyc9Cj_Eu%E>2!cJ`hhs5cVrj)odft!k6%4oLD7mwupX6c_IeNsRvn=4R z-R|bnBzzC*ezbHw>w1QQ1H}4>+yd5v)Nvz!qF`*gNk?=Uq5l3F6})2k(xzsbd6uq} zzR5~pKj`#%jM$1To86`}I1GpI+X#rf4e-~4WCRqUwiBP=Z;0fBX9maQ6AHC!OkXt# zgD8zQ+7qo8DckoxcfY!*8f7{AcsuZ+7h=N`R!zZ4G&JvreJ4H)EW4yED5r%4CNDpr zLX<`FY;*$JWN|fz2xCE8p`%9+;zqo!gA`;Q$jkB$#NR!}QC!!$rt^7O4%V$6>OP4I z1l@jAlM05(v9^O21f==r>=8{X$2H7Jp2YZFUHmKstDRZ(%CWoYDsd0WeGa0;>}tu` zaANNA#<41w#&NINKomJu7ofiwS= z4G}Jz++QU@pvTw4Elp%Kgz{Zx-V41doXjg7xku3085^Cx=}ieF{pvAdyv7MvhF*7?@e2pGAAD~_#|?*@U?%LEB~aV;l8 z>%kM5kaaOBu~mD1SBzYYe6EIYBlC0++qEozvaD5Zjz*ep_-|_C-Fs_z;=EEJ z`E*m^mIUfKJD%I@j~!~{$q2K8)n1^5OrevIMi@eA?W9xRw7w_QlAIgZAcwJPV#q?T zuxqUI4U*^e;aBwIc=NM6{EYfv@@54wsG--H3I^FgM3>+id`msXmroM;VBSv}YWl2~ zIWmMOg%CUEZjO^?rl*b^-$qkO!bRG7+#4MQ+^etr`sdMRnj78>(uc~7-+R7w~Z%VA+Y$YVuu zQuV-8ch(tseY3-WscpcBo)e0HdcEwIXOZZUGg(<$&S5R&ZzFP=Z!iJj%SmUuyx|Iv z&3xz*sEn%lPLW8jp+H8a-gB*EhJFPKHN-q}YOgd3C8~^Au^rs9@6wv}qJS9_;wjUB z*gh+vGUemj{IlEl1>xm^4n9|PfyDx7j1!QIO~YqP>9CSVBgtTA--!(Oiu`|_=VWS= zm55`7;I`>JP)wseya`8<;$!B)f$D$DZECg@AGBCUmDP!3ms0FF_?~<+e^8}Z9fe_> zlU5lDz!^0rV1ots(riUj#>>TPahoJO4dOU^)p=55hVd$trgrD%(eGa{bW$GgwH?2b zULp)QTX9D#m9mN2xcptYNYsDBRfoqs?4!>ga+tuatoA?>{+JWhDk=sQHZOc!cI2Sv z$_WiCpnjuq9X6`?nWZa_q~<8wuz}@Qm+4nU1x3xbE}W2u$t_I%glsJCV7N1R5#xrF zF9s(3jb=Z4StlTxHq4cZu*dY*vy>_?QAA=Bzz*7o7o?1aMzA0{Zm@O`^C&-bIoG@3 zv3c^zsC$Tc>>DTiSE~3DT4R=nDV>EEX3A=%clWp?-Hi`V3yc?nz$vXk&g`~>l^))3 z&jWfH3TDql(Upkk3FSnNb{_6TesGs%HP9nMBBK2g#bwsA)9ZNap;R3Y!u}076-jIB zwHNmG-uI+CqET`LAcM>*49sA(&N);vL9(bmRM$^~j)Lk~Uwn4UU+A31mSb&1=-^RX z95*P#DYFS?bOmag?S~T ze8z=pAKOQ;&>8u-kPmd%f4XiZ$Dw`zdkf{ljoqQp4zwU6=dG#B&S%4Nwa z-M(Hk`4|Y(_&qG!#HB`Byonfx%6x?RQY=(z^Dfp*Ag=xQurycIV9F0pI?sW5K0)Sa1K*?UK?+yZA}c#7Z5Tdg;A zg`Yzu|@D;V)I2b^Sr|ZX8d8hdzXS_XYbv`mJqd$s4Fz0%gM( zrqSuRBQS}|cmH&nY=nYicyR9-frkrYsN2hHni1>9kTf5h^5Jg_g_=bB)th% zFs~%EE>Iv|OJqBHtijE0qfv6yn{A*7NYwy@Xn#pnMn^b5T~6YPtJNq9zax@hK)C7D zVZX?sX6=?O=_S;CpFy_1vW`RQqD7kC^)|NI6C~U$f_*)LsbksSFwP&e<#F6Wm2@zq z%p399ks%||7B&W}ji(%4UbMHtXb4RL)fN{?A7XJ_-+f?Lo+HXhJ>-9vCdcwxHBezu zwY2!8NiKGe`~JwcOJs;2iDkw<{_fOt0X+YP9PNM|zb@I~|J+X`~bt2=lwY0uZq1?wS>)BldO8wb_%pdQ;A zflg>LQ74qb&$whd#eTxN(|n1lh3`euz62UN4dvxSGM&d@`N$Ro&2e`7jplSni-2m+ zRH4O#G%AmqZYQc9dwh3=*t?3O(s`GRttm#}x#&6V1TOq@N{(V?w z-}12pXOWU(x!`GXi`ac!k8YF;%HW;qQXZkZ=;EId2T3~a30{K62+CTl2 z4jsC;7@A?T2bC*__9*uVMirFrymZ%oo*?}tvTAm9y~>8w>YNV>9GloT#QB^)PO<8@ zeP{EPJW=5Pa&EvRWM`JH>K3W%cPZ3=sJlYJi3lP3-qvZWnFkjJepvg_>t{vlB`jOv zcco4MD0sB8vTM0-_fxfahiIC#txLFxVt?GIjuw$x`^!kR!r+ac(}|DOccf1*<}((! zUGomyyIR!^@1C#GyzXwJ0pUtNwvIk9DaB8(y=IFwP+Ib8Xynp-n~WeWp!STrmg_(D z0=aAPt|qrPZS3A%>*Hz;Pr(oX?angA8!0kGs$iK6ob)V@_}5xgteSlPKJh|{4zc=f z(Ep>rTRmKhJ%Frsazy|^%11_u{xld)G2Yg3a!?_|%S;E&&x-*_z6s!!L|jc%FIl&$ zbfGX7;vn!LjLt<aQ{O@o78zXWUleyM0Q zVHULQ(aj&A9fEwT>*mIj-*@s>h#hoF$Lrl$P8*llXE(8Z57dldkH6YbHVx$t_6(WPHFJg-&0IAcnkJAr@k8aCI5z{CynVTLfJ(caBxuS2 zrkBOXyp1&~yg1`)UCZggl-tw)w^Lx4GJZAR{2<5m5?|K9GJ~mSaW4-SCXlZ*nieQN z=cxda+c<__lE$o|+Z-%HVbZR)NSRJSGcX+va!iLKAHZP(k6k)GTZf_fx)$r4k40_LqCtg^xLX>rdKHUf?ZrQ%w58h>YV8I%bYWpND!!E(t2svS~qJ^S{##dh4fK|#hZj+o~JsDi3i1_pQGbCE6P zxdp}=gRD!jC~s#7d|q$I))C0u3G4+y!2HC#aI#vjDKn9gBukpBLq0cOO9u zlU(iHHP@ZH-*I3ju{xHBg0jKXpZ;xYRZZWEkCxq3iMt9_dKWBmQ-x_7e1OJBDosv2krK`*&RBjn z!yM(ZBLm&aAmOi83`rvnzl@Mi#<$juf!g0A>nv7S-KT>EFC z@wi>>X=sG_h_j4UP*GQ8nXg2g*v*utSxDf#l7(YH`&lvfsQ(`>)kLRTG;*yHgvSEK z$R4C*c+y7h+_GSXU%hOKWU|hGWgx#b{2q56gfkyIwG^Fc{lGLk=i3~$g6%>&l0VSg zr^`kO$&Idx2igGmHx`Zsj|+v_s(O}kbOpU4H{p{5Elz0$xG&J0jjp6b1W_0#g?%hr z-<>LXx}*!eb36H=o|O3TRRW>ffTifzr$f8V(ca#Hn&w#WMOm4oEZnFqu|!uO(bB^V z65SA42L*eXHAn)lO-Yc*XxnQ}xYBsmFWIGhpL2bh642fR=0?V!j(CfmlAAGaK{i>L z4N+w7G$-@h>cYPu%K`L(BbGI=EgrR!M|;YeBsG9Nuf6;Jij16O&Q`{9uSXvO%Dg`e zC_1fSc}N*A77Qw2vG&({?d2t2V5(YHgTfO zMn?^*zDq3P{!fn8f#-~<8eHJ1p$MYvd6}Qi*GK4G6pXowH0s7F)(9t)^SR!}n}_Pl z16UY@9KWEiM)YFLFelMT^LQ@*z2fiZNjO7s>#9KBKz3`RN%cW!)?^q5{3P@#&H2iZ zBc08Ck8daRhFqEn3Fb^LtkR9cD}OKD1}lCndFsg${0w*QK%SM1#v){{g4s!ZKhCm- z=M#?-a-vVCU!NXn4re5SYVV9PIH-ylf}vMNRN>`FNlZUbSsbM9(pZP9GeiKDrrh_f z=3bb_eNrp2NfO$`?E-3eok?2|Ru>?rv=?(_{Pml=iDQ1_`IP1sg#Q{b4t{?^Xy7+~-eeP@BV={Y$!d zlHf|8@Yd0Itpt#@uBxqH+c4}4C00%>G|UcnG3y5I6soRvy<~R;{LlU_AaLEq}mOU*hsd(&Wnb3V5+27CW+{}{)B4y19D4|)RS>dY~|*!tHU$MMayQLzEeZy@(; zaAFEaj|~Zm#U`FUhteZHLoSpHHHG2ED~(j_=>Z^bqOsqIMb-x012{kSBE}OvrYir2 zQ23l?nfyAjAssdj1}sPu@{lM0h+7PxA*(Tg>d2F>&igxfnZDwOva84nY)1}WP10!w zr(eyuk0Sx{WGe@Ldee2X@p2Q?>)pPZ!t;)lYEa4~1D}7y=rj98W6o8M2tl=RPBj^s zl2ro1qoU|hh>|1Kt&Y~M>wz&kUWHHlmvXapAkfQ0y|*a--SavZVDLIi>0A7sSg((S z;ctUhHgf4P+%_>Z0kj}L`LWMjCmoUZnL{SyGptam=vbO84So`-u7H95N-M$^qo{?} zzd6H5nEK+(T4Sc7wR;=6upei z=F2-mLM ziHWTZM}C#?-cQNIkc(vI@J>rB+I@2%zis@hfh-jnf*zaJTG^ubw43`L&7An z{*8q=!*8#wQafEJSs#Vz4Om1LvGyjwNyXiLeMOhIbLHw#cypxsIud3G$a$6*?GU~I zi15^YTfn@TF@K3BFqpjrRq^g;C)i)pA9!rYmv&^Po(pSJLx+OIOxA`gsplRc3oytv zHA)%#B{L|UM{O*8Mpb4#@}*|g+YD$^ivs!kfe$w_<^+0za`_=7vvQ*7%?eki)=B8q9thnQ&R{1$Ff#&Kd z2mkn%Qp8Jez~8eIp@RKWy)B}s>2i7eS7x8@pr@5{01Jl zmOJT^hL4sW>13h9pbNuI4+IJ=}Lt#q@Id9Yoef z*d#LRuie7AL&l{>;`J0Ue6bgs6Mk1j8DrPtj~_n6npw(6>qg2N#u8&f2AJ*@{idRB zzC6MRCRyJX^A$fk)Rt&&i^%TByuNc>thBPuPmWghdQAPJKEY7VNp)%YjpB2sLrn$L zPK8-B(z=RZXIyRVW@UrnC=Td=KW1WQNd2r?XwJL_PgoRkl5E01Qs$2HRdG=|&F@sR;BR7#O7fV*?XaSMt$ zbM4Y3e_eg0JJC#9pCMJh($EU0vC;~+9NWTrB&D$pUAnctuyvYZOntmoX`|cKXPd*V zUwIu{ccMvlTw{ikibx^t)tjDGqttsI`g1LT7zYam(|>p=__tANi`vF&N;w(o04h_N z>QeM+Kjy%K=y#2sjblp*AVYV0bgYrWC_}`JsR6kP)jrBMb{TS+PasyLhLKB-#a*{0 zX?|8pwPrj^Gi%t=n=BCV-`knOB0jT8+VGm1de&`@;{O;00&Su~WgL@CI33BNYiFRU z$w}Y)U-HZp-gq<=9>Cm|>+4HE$j3CuleyTj0A+|b77B6L&K~2ID8hk+^Ff;!DeArQ zQ?f+xn*n$f7%Y(e5hw-PQS5(Wan~jT9Y_GJn=b2@KShsBPUY5JM-V-p_C$QkQU_Mq zH1i8)@u%ON4j#7H#fcz)sfusXpvY$M`8H5%#ERUl>Jgty8{kw~Q?Vv6A+-D=bbbV3 ziBfVwcd%Nig?=9Eo-yb0IgLzH07ocL{08|aOX(uCkx#X@++%%&QyYgc`N_1v4zR?Y{BBFS`Ep<(={PBomaNWEYNj@XD4n8&eqF&d@#_Vtj@GLGon@11dlB*Dst z@sVkg0e_e%gJ<(RygGGi!t&PpI(M<}*Qw zkZtaU#~Znw1h{H~)KfSHA5opdL5GDk7~@2*U=uZ*kc>?SFFKrW!F%Yv=BY@SSOzg~ z&s2ZY`GCSqwS^_8d^{|sCL8>W%R18)$c<@kf?C{<^1eXvrB zHjfI2sj?tups-cqdnlk_X?TKayph4N>dg?mJ?3fTj~;Xr9NQ{}V(gSU1Hg&*n;om& z)^0PihUfiXOE36WA#8FQcVOAPJb%56sCX3oI7BZ_ADtd@al#Aq1X^`caj4-cKz5b9 zjvnV}jjiz$m>Z_Bxq+e9|G~q?tRsM0<5)G3hkRZSv6KIF%OSq0si*u34z)8(FDhIf znnISe?9Y<3((3t>m@7gMKYx>prSPAQO&-LL*40e-X8brXE(u?PnR|&X)pzoccKimt z1S(+E*j71OrL$_^OfUZzT`9D5+-)RF!7flW`O1}dMXtWU{YU&leHw8Ek8r)b4}F4f9wl(gj}lOJ%SV2J zih4{e01%Jtt|yy`=a@~18BThU$>PzXsgh|L`gt#{lW8OP7*De`dEOL-3p16a# z6|?YV(H{(!Mf+uh94dLqSg=LUc_fwr1N5Ht+vtwI{Z0U4K%Kw3l<%rpTd4RmA!CuR zk7aDZVL>{!G}J=QHUB7f4)7W0LG>Sj{=1QhAMlU`Bkj- z2eBH3VdyikjJ^ziAQEgdmy8>RjXFmnVK4JRdyWWFND`zRu4v!OwDcRQnVsldpu&aVbHcho=8U4 z7KDA|cTBivB7;IiJz>*-S1W^K2f!kCwN(K~&Na0iJ-M*q84FofJet63D-D$8&M=CvD@?dA36BgV>uV7|xqmoS|Bc2QnD%iJRiwrkOH;mO z2L2US!q%+2h=W-03D=+bQdPx`(P4#F9*pvXLjF}6ycbGHz$ic77w@qb*I4;=*x$T@ zuE)bcXn`k52qv)JT?+tF(3y>YZeM$6W1f(bHZ$NX0@~lN zlo!f^!%u`Wd;6*I&aZ;g@a2BJ?9qFRB7B1}{T~w);6Pw1Xx+>&>NcX2c+T*(r-_{j zz81@3&IDi|ZK-gd!uKdcdM!p?FmwpmN)7=5&+qCwP3Y%m5>d$-b=7Xi{KU4}s?k~Z zyoIhcMB*wt(Av$UBqE)4(T=>IwYb9OmOR|DjnaIk9{`2TT-4r1(l5KqAcT60XdCd^ z%m3vXRuZ}6Rr?|&bLy^vczo?vElgnJAN$bIKy3|>#g2&0tVcN2PJ6qx_BiB$(su12 zJaN4*{6d~2OoXeD+K=b_@CDCdiiRDG0YvQp<|df;2Ssgq>RMB4xpmqLziiL=QPK%r z8fc=`0y#wNdlpX9Fv|t}`xjnT*B@4fKfQIz^VSdbIh{MG2qqTU2qtOPS#GrXHUci~VWlV^vZtW6LCiTsin?IM;YNkKMk zN{vv)A<$9_Bs+_H;l2ymr!^oNzJ*i6z}wKE09&c*v1RmPRgAjQYuS`%W_Ca;IzI1(sD+yH$M_9N-?@CRG^LqJgq~ zZ4unJO(F>-F2b4}&AzPDM*tT$NKC&0J)OJHVKFpDXoo#gh!k;Da96O8*-E>u3I9i- zEme9acK&m8=g{{l)4(lnxke()cR99-0fN;Kaus{#CII?QgD@%V4UlRqThBFZ-@`}D zgK@Z%5Q&8?8aJE`MR5+}9bDP4O0Dvxf|)zdS*BWIjj;RA-}dVPRo5SE!KFYrtaP=R zU}{_9Ke!3EyMEh{$^RT7DiH=C(P}X9hWY^0Y-gKsrg5je z&$k8i9^8d)K3f*?x^Kw32G=aOA0U|tLW&|cQoUPP`0zqoa$ zfTXNW#c%W@B+HJm&9J()GK&vF1knfG_@R*}^)g9fgBCLB|GQC-1fqd25qfV?j@p>c z^H;;ve8_ZVB@!tVU?STiBn{sU9SBSv!NnaD7@VmX#7;>5#;;Kvj}OxhQey%<1~*B$ z&=Hgk(aO7z2uA_soTXq}(g7?>n0k6+1@Nf8-%TrnP=s>hZ@1qKae) zuOGy_H1=-`d0W~L8p6H<>!%vTE9F0zJ(qQImM(CWP94<0;NX(rBm#^3&!RcGfk8Wi zD>c9UltfRQ-oIH*E>2nedYB}6X2Yoli$FR{z`vs{QH5%}3B zT*)^lsz-JWq$RZmTUZ;^We+BhE*D9BFs7dAGPwSoZMQOlH+XS&X}c9?zoGI8t4MFw z>m9rBUp3mWSwO(2W57r>ME5}(^aoL)v7Y$=4G&?>^S8!uFB^P=@#&5F3%_&FsdI6c zEP2TyL>GKPRLrQVy-fuR!XA~?q|jjii_|{cEoz(^cC}sXP5C|R!wAj_*Mc4iMrE_Q zQY#V za-d28SLVx<(Cfp(j8a#DA=d%A3Z$KKIHzmb-dIWSD7$XGWuFp#>>!um2bzjki@c0> zqN(|+h=|I>GT~wenz}167TSgT&Vg|&1Xh{8joQadEm55j)k>y_B^bXhFm-Y5Phb&~L>C~m?JYNQv%BHaIAW$RzC5sB?4hNZA`ei2Rfwul*oyC3QS0%N%x8b?%)?}V&K6(^wFRza zVddRXbOyKbO~HLnb9W7o$m^VuI>CIm{vFs%FVA9@NsIRW*S7_}6TY{K1dp>t|>x06a`E_N!;y^ zEm2tAZ^6&4{9hLf-}obRQzL8Av1k%Ns=;Cwt!X_!_mQKy{d1(4%+NhnHet zRIb!`d>0i%u`RSFig96*dIX6qAs2&8W2U~BvLd;w|m)sGPq&khRqr;cE2dlZBDL9N7@DlHyRzth+$8b z_uw@CJ2MNjc(+i$cbbt0nT&qVjj0QRS!QwyEwa4e%>KFa+Kt|c@>AoD?d^B|KU!g{ zRLq~so#mlPdf^&jZ*Qv~Wy8?%|bi`@thEH6W^n zOYxSu=}tdK|1Ha>hlp^lSa>}?2^M%Q=`BV>*fq%BGM44 z!;z~wf@*EI7#!DGusOpXb@SkaYN}I3#A6fIrHE58phb`us_$YLKiSh5QBXmOWO&p< zGYoA8_)bztN}PI5(Rlxyvh)IYt6|Z^6UFca(k3sUz>C0w--U5(oZrzT2Q7iUXMYt- zv(@UcG{&FA4ki4o@Pj#u23(><{~K8#L>X`Al06~jk)*f!Pt-4}#m+O*aMijwjS^%^ z#Gjwoh`lGcJZ7xcSV(9mKsNsJP{&JBper*_3rO$eoxaW1f&KC3s)ktbM(1B`UzzE& zmtb40obTmb8tnQKRnrGqh4g{1GzT3s!qDP{xC?Ott0m~}HVDOkn2m|SPE49J!|+6_ z=D^c}PvLHu2iqCx)X-bQ{#4DTD|5SD%J{ow&aH>*?S z3IA5F1@_n$Ha`Syq|CdT_Bg0i@x})__K)4@#?8-t2+LI#ThZk!o}-W%jj;`HeJ8*e zi=0d0)sEu$U>7v!#h*MGBLb{|)2{{IS{Aw81D5`z)`Se=4it|wVPC=-@it(gRX;x- z9XYCSZVS3i4-Ny8>{y&g7ER1!5ocM>rg~^+z$DSvsI6Hhu|xEl(jcvZy63sTt@gfN zvnQzCrEYt%oc{W4v6&&}*XBh_;2CTNGs{bP$#Fj1q{((%k699Fv{?bR+<92 zQ&Dj~OCXzlnjq62RWgjLuPSN*yqXB@VT2FQa30)OSv>m33Va1rBW%(j?(CP;M7F9I zaQ*CroiT!vw*@lLjWXqGnYILQQ+6f>ccin?PK{kM#|*#b zD>*+N4wOSu!Nj-~cd)1-iKd(()v|dZZ-Pzt@N+@4=u_+8S*a34Gmwvh#NcLpKOWFG zy%;mIk&nWaeJN<$=1T-3CqG$zLtH10ZG@wCK6ne(?^9~;lq-k3tS-cM1hz?&LMu-x zWQ|G10NR)Xs)7l@babOMUo8PqFQ^XX5Y*FC1iu5`2Sh{!ul>PZO+FVkvns);5pCIG zk(ih|at*&B<%F+RLL*%3LQDsNBCI}T`nA-9Ku^c;8-RUma?YLG4S*Z%xdOAx4ca^A z6?zpPe3}C?VsR4hHUn#jpdf!SJw4 zzaiQ~)!dZ~<4*)qkyduxToPP0LP{@SU`B{2Bq6uRf~yh zu6vU)7{u|j0D}8@Y=@CQvhco=clb`-1>RnWsPO6dyz?3i5DVLs5GA-h#~wuzrO>Y6 zcb$AO$cMO%KbQ`VPLge~s6izU$e@ztMG0-6dtN3MIcDt>HG^Rup>3e?GNE%b#8i9X zq;@3eT<%DVdhdC9+v&~{ooiMpfDH%M1XGW8f9yZhfIpfM z)m+N2n3CXx5@f#)V_9>M*cfYIRN6=gsm2$Z`8I$u3&qN8N&XQC_$rWT;LMiv z>%$}{SOI4$)f|$_$4xR1-cJeer%Dh#DsYP-Gx2!n@ez)&Z<4d+`!h16`NdrFCR@Ac z5U@)2Q#hpMBbr7>6PXIzsIomUx<5~{X56}crm#JkwD%uY3=iO)k6&^1Pk9*Hr#z3u z=ozA^CqUk`G|&!2jPKOYeNvmk5L(n%Hk(OJAM9n@R^fCDEt&`*rXoH35zni}+{kW@ zpx434+>~5OQw4-^IZ6n0OWTKHFVOV87FGy)DJ*SFL*1Fz&>W#-$UIfrWV6gnlcviL z3HGQ4vm+Sx|MZzcQvEsI@LrB)u@>fINyPIrn~+6O#P*L3W7VXFa@1_UkKU^8p?rhD zFGSvN3k+lOq~beyQtDGusCyPwkgwr@o=xs^0Uy=yHT#_OO0|R(G$?oj=SuI4)ZbV9 zM9K|(lSfFcD5$Qb1s$t6UG-B~6G9t?TPZLW)L)4}PU8g#0i9*6a0<2yqHhL}5VL5kT_@AEl6E(7}*I76)c?-jwYv^^TI6d@7fX zT!koNJpRqV{ZacR2p9(qCe~tIEj{8VftKaH9NL56vzuM-J|7|f%wB^F-gfGK`~7<6 zr}r%8PyTCb$%uo{=lU*<{Ng;^b~Ogat#3d+l>Z`WZoo;;Hd)e@ms3aE%`qoI1PQ)Q ziPoWbOXXL7o5D>sn7_K(#Q1&guvo1lZ7#@D|5im~lKzMCWe{lt`7J>l zAMbcBx<;@^*L@MOwa(Pyvc4Ms5H`|QDl()X6)8@>pJ$P%VvE#1UrX+{LJ{RSkj;-G zvej;${e?xKem8VT3QQG0a|@aoFQTSoL(A8Zvl9(V#dN z&TI@JG4Th2c0r%o=Q?9eMwsE|sB|6HnF&|(Jzq+^s~9`1{!nihVhaMS09rTQYyU3? zD`9QCs`tG^HNvgdG59A%b|!a>K(Za{ClcEt^_6J9vFDF(ekLpB-M@A{XVuJ8N@$7U z7}De9YzNb3lL>1PR|05U?_4@~82NTXXcXh0&cuHRdPK>{(xT1e5gI(+u+8V{AFqOD zE_BiK$RcXw%DPQGHLN@6bP?Ld&gK%-EvhUkr~{5ZrB4<5K3M9z@nvi3CQR34sq?d0bhTQRSO(sPhtB^^ADKUMfgdX zi)AK_Fe|XPjq8d4jc;B4*lAH#4V#6Q-=Qz`%q54!j`qv&SqkzaBG->Nea(CweVffn zKh#)1-jSwMHI}y}9+_L6fFe7@QUMb8R+h$1?@+#;tW=h%(9$cb?T(iH2|T`*d3GT`?Dsu>cqSns&vd^3?#U8gvP82%jUcP_SDV!)kmi9`Rw}cEp!kGU4ycID z2z+po`gaUm^ro2O+n_zqn(>XFD*FKX7-0_ZGXKq@FE6b)|5k22&V(Ieqi&Y}p3Uji z$PMSbz{5K4IXCEu%)!~GV|ju1_Y>iuA#ercp?qKXeVj>qJ22;!^V#M6FALApf3(mX z4hZ$))Pvj9@*f)>|Ba@NSS)LJMMWNMe#yrbBi4U26WULzohxa5h{Eww9p3HuacURj zl#D>G9XoF=*$l68Dm^2!e}9+Wu5LgtIR>MC8^ZWZLY5sOpZcI&JRinW#PEVEevdp+ zBFy1BuEI$@MDs;h`merS56hdMC^akFcLUY=_#qi{pTv5QhqTecpm&_Zz)Q(w4@9Xw z@97jAd~iq_ua$DUxb0dU>sQlRSF0HEM`5fFeRGoNbelj~RahG`??0}(Ha5#sq@Wh) zx<)N3ol93tU9_jSt{})2L|~X_uGc<2`ixKOC-mm~BLA|sGH2k7->OQzeo`Gw3S`{Yd*Vvc2ToLTB|(Q<_9vjncP4 zF4}CM_zi=x8W#Wjs+LOQFD&Sj`?pc#Z=6y?0gn2}+V2UPt!JJxp$Z6nnV)Z)2IC6! zl29Dq(N$q<&)=-=Kpv6MpsOou`XuvTh{NoCM zMkPY5rE9+GxUY)(6`_yY+MeC~btq9v4oxe{&j>je;UnZ=t_W4Mlcu2^PHtrVF4E{n z9oO(WJgVV`8ZF$z=<@$}1>$ZS^;R+Zv2g&?qXqo6FYH%cfM=8Ua|6}<2whV$qO#Av z)QSr51xr(E|4F+d$s;A#-cMxRuF9iGvV3o;4e!Bl@zWlkP~$&?veqyE)AQ{cVB!@r2G2(WHy3?nRH480M#iqDp_D7DpNho6|qzYF*-bTHr!mOhdh zT%^gI6EcN{N8U%EMAgOvh%hF4C#>^qse9_ocpSJAIbA-x5EVGY4K@*N-r@JCp9CI8 zv_VYeS~pL!1+6fT{!cS_eLcC5m?f$cXbqj3*ubeOUK@>h6IjW?JVdUL--aVUU09h;Um4P9aZS8R&p`$T=J4cq_u$zZwcmgWx z>Oe_dg%+cbR5?U6V~^nZM_3zD%w0d{Arf$a5iQoA-qpfolgZhr0p9(qXNB)C?W-~$N4b&q%f#?(=NyRyV7$5L*3cGQ-K(S)rm=c+2yPaW-V^|f0-?T zIb;HRAedV;R!=&WlZdiDINW6&=0O;C{cA`332eom?krdco2jN3P3zNA_Dhc0=_)kp zy21r5pN@6m%qGb!j`{rUo$JLuZGx0^P_*a@wEuq~A-{#XGFJAa&U?g(U3p>8E?Rw=&q{3P*2M3?m6=$qJANHHUbyHUK>Gt_9#DdW^uWV}H&W98=?vF>KpCs6JI9iwarF@3FXQA6d+M1r_ z44YNr_r}iwf2#$$jUX%QM+)3|2~PXNH#sbL!efnViZu1Zdc>g^`vx%JyS6>G3C<^D z`l&8&dOi5BYG^0sBuW93GI@q7DiuA^MLx9T6-gbGVzx27f2!VfF!sv8h)n`!T$g&fhT>GnwRVlu0ba@Xc$* zhZER0zW$-qa1bseT5Z8Qd||ClKhx_OHa*R!E-{XY%6N&$XiqyzJQ$6JQz=9GcGdd( zCehu4<3;OL@$MnB;hCGOAe*Uqo|XP%H9*mx9ti#}7wGr0SdDad${wigpemKoe!oD= z<*{cUo}1H`d$zQ*qcS_^M^$^~r|D|i&i)2=ZLKP9vOoW!Lpzs-ikAFF9;tvvGTsD+ z+RG(ahLo?w76eYMJuUfWyOa zEcE~m5ky7=pF5im{ma>baQrM@U`_~QQ3VbzTEbG`h%f^e+_KN7CDHmjqA6Bq{6^}~ z3!r#$K+Ms+QD7v?RnsP*^0Hm=wa;EPYRk^P59Wp~fd`KHoo2#4+*lDu;yuJ0OW_Vz zBKl*tlH{>N&c`%nA#opj>`MeKyHLNkf2>#PMM`@t7hZ|X0ayCjg=utR0rSZouzHq~ zMJ;wK5^(omQ$KKQ#x~jTo>%br{lscSw7d{%JANET@I8TPQt-iV!Jb207Wj6VF?c6i zztEM3f!_1#ID9O*o&@v5I(7k1Ip>&8^PDNa$3Ve}~B4t_oWy==C z104*HGVoRI))06GUeXH@iwRT(Zj(2_Tu7_oS0Yapd zAL6=`^P53L6s!xWB3v@lyfRg8!U%)%j(zkyJv9WzdW<;;j&a2A{#@%atmvynmLy>Y zODIg?*}YcZCyYa>m;1HlV%@=BfYc7NgN-|pmxq3uQ?o|poM^R_QbF^m+CtaBW6!4- zpfkNHr1@h7IQp->SzK0J@7u#G6!pyJuzVycnB_;DW`3MaDWR-q_#Hi|(%)ygJHBdgP`l1i@;@Lib?2fv2CPuqi(D@wchQy3--m9d_YJa)|?R4(uk(0Q@=`DGMXQ)$u`?kQf{&ND%(^`X~qkuc?+SKc2u~tFEYvLwt7zLs(%TQ&<;i zGdAWz1)_)=TnP5&xi(qejT-75MRzAA%jjn|e1v-ImmB4D#;><=?}CA=$Q@HZIO8c| z-R_V$xEArVZXXWp;9F@JGsdJ+XXLq&ieiis#C zk0~YaWdEPHaWe@o-6qf%$OrZtZ_G0xOang@)&W)P=6DVsRprq32E}Vtn&(3gO%nSn zlR9NG-NOVfO?urO)ItI>G=PU*{cdLY$WB{p_K0L}U}!u(E$@-@n~Z#dGBRC}p)Wjg zta5=2$t%U(hZ)R2F~uh>lJxeVCn`sJ<5C?=16dD@b?fwHb7aIp&Oea4f)V=cv5rQDT*d2J-iw1JStWyfYC2vYQvB3=N;KCE32ki7*fX{;ie z!YUmwpbKc>Fy;W{?lyZ6$t)BVuzjk9E0 z$5XxKFt6`HCXzC-kw-&fgd#=V9F=ExsTkkHy_#RR)Fzenysi#4_7TYLWKfVEV z@iG(wrCwqYz}r?lUr|10ME#L9`^!2ocBzs`3lNm#A`(_-y+M{ZJ{R=C)##y=1>k~l zLJr@TR@2VJacM%yghHJXyMy;QydMv((+YCSh6&j*7ap{7!3J3=q0E3yuJjNZyI7^~ z;$$7S96~8@oBYM<41;^FAcn8#85rHKuV!J%m(oy!=hU$joX5Nh(s~kFd=rLuG1nKX z%4E>H(b>nqT7spatD1P)@g^S1w}RFl&W)R8W_3>g3&yt z^N@JgedE0~a;qT5iK}xi1C|fQ9wzc_!#QDezO7s_y{k5x1B^ZRRSD(Ng(FBZWtFtj zo`cUWq-@(iG3l29CNZudr@Voi3Z`#+BgM=^H5yUP90#*PdP==;)H4QGJ>IW%Y>e6|mg;6kQ5& zh@TLIRv|A%>aSWvxfi)8%!fSR7tBV0LQ*J!U)=};**yYQI9`9S&ZcCEA)vbn)-`Yt_x|Tm(GL%`3R@zf`EzAp?(E zsC&8ZH<_-qwi8BUER)NP4t`eWrsvBE-F zkc&-u6mzPVBLBI19%0_wG73wI543eJkMYw@T<7`MqQrknqn+~&0-#L!W82!`gYgS6UIMGy6carqkBvBkWQ*r$q1 zT1iX?E{PnnskcrYamRJ;f#u5z7K-SV4nw`w<&qHNoZI+G)89r&rGS~)iMz-g!3l^y z60%e_EwA`~)Ba~suQ~7NX$D5o)%N_0H=m=iSZiyQ*sXNw;659bJ=#H?vFH;;6D2-l zx4lNf`vjM&Zmvz?EZJeN%X@okvLvgT{4Lz1m_|AjI zqI9+24tj4BgBtzm?jjbSUw2YInx^T+>!-8q0V1>_?{_Y-5$4hpCj$S0ZuHcer=5&A zz1nr&F;k3{Kt(}Gc|?UL-cnPlmz7Xhk2}WFVk&vLxST5yw_2OQh9A-D?@kYYXKlq@U9% zMwx$C%D`^5VMJ)Nd!_ev2<7|qEfCHnBSACL8s4`~?j#Zc37DlC{e34Hz<;mc5n-39 zp-SU{SfYuONM&REaOu8*jL6x8^Y0PnXo9A}>3SFh;U^HozFSO||Ggpp;czlw7!0C+ zk$6wxw!udPT4l`(ol(_w2{2j1-->6c9hS?OFPU#?)j>ew$k#S1&>Ut`nxjD(`f#j( zbtVKR;)-*sG#A`e%~1K5$|jn6I6$m|SqJ?fTPVh+9h10$Nmc<*rGX_F4tVG#ie7<{ zZjR}dF&*(Ls#zTZc7zhHQ#dv(6>gY+KBp+MtC{VwIwvDOLH}h8^*--!s5~tUQq$RF z5pCz{mKps@7DeM1YYlrne%p|0~%cC z3q#1o`?+b*wVpL)=FB|yRt_!}WWr7gUNe0t+4hBEg{W?iH0%f->Hpgwn_iNDPOz0T|SgI_$#AFwR*qa3Ime zx-09LVsN~uFuUj@d`METq3c_DlZM2_qSSRRo;M=_Xg;3^eUq8e=_9!j9VMyEOH>t`Ycmkyor^(91n0(H;EC%(=Y5y`p7$ zg5@!av4M(fp0%b@q8FOPzk^hYJ}mQ_Y0%Iq^IFbHRzrMXyfZB1(*7RnYB^uP$6=y? zJ^A5xa#ObEMv@bauR~U`>>QE~%(sVD`Mc?>m#JNfAljl?a?5W#$_8!k2*2#(YqDB}ZWgJcek{vSWpv zag-YEWgY3mGl<#7I2o50R>@1Hme~Yex0bI^e9?6bD=`k1t%EtId8I0He#U7wk+q2a z*tu|rlD@US2&5H)irV{3FDQ%<3|eJ4cLlak}IOl0MD&rI-Og1GL_e~#E?uB z@>(!wOF8$@2si zv?>`>(+h1L>CAK;2G|7TH0=Z4Yk;Vq6Hrd#DH76k0>=iCWaULX_m`{FdcTe^MU;%= z8qutqWd{xA`YHjVXf(P&<=^qD6fd6hpb!j?;9jQuaUh+I>pBlP=>Qad!#X7ObDz21 zeAvILbX9YbCF%-+XA2yFLFhk?5 zU*><72rFJ3H7O+#7%st)h$cOQ+cQh_+G|554`a+u&Y7!@&!oo6d!f!Y;L7;*PTDe{ zBq}G<551x`kS5OX^cJ)+C0g#d4(md@Q;I#kE)(?en8)i4qlp0#0!am1^+m<%@-fC%=P57?@+jz66@q6@q_oJ9| z=Y;)K(U={XdkG5FM;@x4emtorntCx;-E5V+IaPt}1E~HNOVW(O-r24d#^qC8igxk; z!M_URUHVNQcoKn?25n?3jPNTyPI2)u{U3Slhw&loZ$BV$#yOx+!djOPcp$xYfDbPb zLt=D8XRY;9AqBn-*kwbhG;ZMAI)iP9hY(>9PsF7ct-tcW@cZn<>k+;*iq>*?*w6gL z($9gLubkM#zZLb!Hc8^8ko@LBH0@bDug9+ zT^;&M(`oO3$!5w!K`wR}vqG0T13U>rDd0z8=KQeAACQDj9eHrZk+r-K^5enW(6lSE zyf(fjCJ$=dP4L=&o@AFKGeRF34*3?P$$MfCl~8$<##IVi5pP&=o;SU zfJXM<*&ow_fCrL*#*}_1M?{b<=-w+z44VX(oS5yuP&>G9FVd$x4+H@`1kIg+?5?(a zQQsBxbL8XmMgJC1=ke|yFgiYtZWkZP*aBU^^6sRn6Xy1VW;hbJ!{a{df6Q|5RtW6} zc;YY?Sw-2eK`aiq@MJJuLT);(EtKLAxPkFm{!*qOJQx|zqx#e(9nY5grK6Y9bkF-; z8IO9)bvym>Jw0tgyz&4CU$Kg(^@>G%$^RL>Dt_lXly%mS;{^~#v;9G#3X(EW$lfUY zh=V3)Err8n=NjMJ(Yb25L9L5BuDMWU+G-v@=83byLZt*E{{?5BM^e-0*4(zXUqHm& z3K5bhZwLp`oDL#WRnCHcUtPR&&i#GfG@05Z5ToE`eZ#1cbTIyG>dK-|%hu)E1&Du^ zq20)niH=RIjqwA;Hh_vd6^3D71Qs&Jh8vCA)p~No+l_mFV)T6!ua+9>PCBa0$(q zbs;C~yT7dL?l4OJ(q6Ia-8C+)@rMU$Jq^7?tKW3ikyU12^QgqBZ>(44^@{o}__W&nD&*avo%? z1^$jT?c3AqTPiQ1S}^TMfnD`rPml07Q}{EYH}B_Y!&DK+5JLk24u;lq9ad?NL8bU2 zKL3PBemX4CX6Pg%BVc&PvBEuvzb|+`f7j6&2cMoCz#bUVvJ+I9@ql0H zw1)colt~6HW*u>*q$kHG8VNc^M_~69H}nf)Z|&dEt;Q2ufCx@xa3@}38d*6doyQ!S z8m`0Y%;3W{3vg71b};!(>ux=*PpP>!#!L<-`|0(!Nc_a)XzEo+!D2GN3}@9^dY|M{ zaIaSS*%@|$%N8yNPQDUL(?9c;GQ^ot5og7Y`tixQvD!$NoC>&t*M$b%z+(k5hSHZ( z9~~Ka#J$gDlbd@Go%wFjxOqnd4AN`Q7;X?DkUo=;p+-8NaimhAF$5Ssq3SEg?Ecv<)h&Ht4sMh~g{eBS$-FfLZWkA?Gtfxu1I+`zUg+XS>)wg1qk`a+O7QiQY&=L9$OqI8DUlH*xxAdS*`?u zDU>GcO4+k65J;qscLCkbdbN4J9n!SiFA`2dD(>+uQ-A-?dapWaiuDMH~Ih#dtMWKdm zb)7Z|2PhSNOkYFe7?9bJO?z2Jm*zpLT>VMUw68efRVFC7x)Dl)BR|m4jQF=tD6G}( zVj%TEzICIuyQ=xeL&;SX)?T9m^N4SHmPEi#`)4cfEldmXHa8f~!0>NdWQ#Bk8w z3sx@L!**X%7o06`x>E)>e38gpoV^A1*DRwcEdz*ie@9jCoW)9#v!~DM;u#6Vq0VyJ zH{6lX#6H;cQKnBcv#+aI6}+jDJV%|f#PpzNFIoUc1xcThZV70pSbfYa=a-^GZl$vn zjYo6ZvV??x3S7qIZ-k;ZvYTp3SUzti%3U`bz*v&;7{HHs^%v)xYPP#_w93Zmy_*lz zF05Z^i%)KYi~*_p+Qi$M1xEkYjiY2Q_1zSS6VQ(iWB!KWCrmh5on=LSBE1CmJ`I&b z^8{8d_ixyPEg!Q90y#4Rg^zTP1w6angX1C7VkWRgQS(C7O4akvPhEcmw`1b0N{>PMY$XS`t@?GVb#*-i{NshyWlKHw3rkn5ZKdyx|HPQ%(a*cu~e zBy<*N;ph|dVU#_Wr6PGbqUk1pkY-V`DoEDXe_Ww(4R2a-g>J|JEg27Rzz}%elRIym z!4;r~u7>;mc)YmTpBU!`%jVa|9t@PK3~#ntH@{nMPzazOCD@XFdYkvDt873~`!_2t z<=J{mKA$Vs`eTjNqsRJD8x;`GD{%L9-mhqyh@Z?KrHo6F#%Xvjae7?#=(LVA?$ z>sMJaJQWNrF)Prn5u!`o>ZW5kQ(}?X=1$PCJ#!Pf}y zt8i7UHP&Rt?EjnbB27>=1T&90+q+SZOGxEMCfT7~+Ssq-lVn}ruEUrJC@rQn>q%)P zhHNH+#GOGxBW*O0-V?4`Ov9#A@Ndut1kkTEvuOIETU8h3XJrcK0(ZDZ&9wbH6+{MG^+Y$~3>QZ;!~sh6S?Yq3tBhWwt4#L5V#KV=5cU7VUyM9!-ufrjK)N7&=QKmd$?;sF&r!OWE(f#O>SL< zpc8*XxHr1fnMt!uKb&YK^NNbQQj^cPR)Q@$wUg-MYpk>l4($>NbKm8l`;MF9n2{O^ zdRMtRKiS^OMT>+)zKP8-+6SM%G$yyio5lb^ri|`0JQ5t@g zhP$3Pt=QT1wEVYGAvWd);&-0jqh^TyJva0gB%W@KH1Y;ntQB$^3Ooj;ds-EUuRa7+5J0i|Lk2hLc#ZAzDCR3e5dhvU z*I^TW^NGEu{1nBGaZ^{Rcgd)by(L2k*d14KZt=o1ooTfVMAiB(twX{Ikt$DT&`I=v zZa3qsLm5{YkPW*f=9`-CabQypUub3=?@$m8s=md}OdzUc)t8x*v?nGn1%PomJ4W~y zSDk}{tmIL&J3ksZYd4y*&wg{EPq=CWSCJ4T+R%{gw|X%Y;`(zg9p%zDLS$7GZPtjh zDuP{!%DzIfrZK~Y>!tpSKIuT?<<}~s@KSOcp`Ht6~|2qtPEtIT*pvE#SB1fEoFHUaka;z-oO#@e++cTQAV$HOtc?PhiE~#;_`~c3(|JM?@sF zTa0HI?22D^8jwSwOO@8JtAL^UNCRdQLZ!brQ@}QXx3LbT5C2#!+rX`t=SxtMwSsT0 z^KPw=vuEeQ3Qz`AEv7p%b&)opVD7kkb~`=!tx#tA*u>&A9c;TXU2j>PT;LvvLq9cm z$zC2aY)p9vS;;PpE-cu5kCn|%jbez})gnm}P&{DsjopNp5@8o>6T+&3pJyF+^^)1O zm?GM2I|^WHC0% z&j$43buPNP<(r269z%dbrf`m6=Vc$V$h`~7Bj1>C3@giiJsQ?oUZDja)wUt_kI+78 zZmhhsm)&#=EHAodJpKiwd(79Mb<&s2TjNf&D9H6qqefY>6Ttl?I9%>h1Wk+v#g1{) zaQhp_pN=!fdTjn;Jy*L-{`=FP2t`0wG4Fkz1;roeOPa= z{ThdH;^Uf^81soLK$d&!p(E&Bb+wE-OgXPP9?V--vCiCDfg@S7sERK-pDX+*u;R-Y z2DXPALPODE;pPM4qPo1}bIH%gjxk5_X2iwZR=5s7v zaY=4@348x_z9PD6Ka`1UI%xf+f8@}XYzKU9Xj+Qf!=G3!Tl1pZ)wVNxdz$N&c1)D3 z7Jf95ZQ1>yS-ols?6=Sy^{q-0Zh>pv$U9g3lLe>Boi5@( zem@bDTFnwQbYLo#RG(6DFi;DB(y&{JV=4?k&hr_0TsvhOXh8*XL}`fg@w(}5|3Dpf zw8^2zit`Z^)C$jHdKSks%JW>5bYj#PgtqS+Dxx1zZsH-uHMKeuWqix^`iRv|Vop`J zs63{pU90R!vHw+)$qzAGM^TZLG-tXWqSBmD5*|M+P8!;BQ3%c$-D0wC-2~i}K@xAlIgugJxnlJNb)^C(@Au#L{$Rm##|*f{X6d|i*6kNnWKsX+cL4`W zKQjgK-Cz?(LPt$*^5*9%XA1iS9b^m?V;yuvpg(W{CH52gdX%G^A4wUC4a$`TuA=Mr z!8!gk+nHzf&r`TATh#{J7mGIf-pZ*%6+jx2PktEs4VLtG)q4Zu4n5Cq^vc}0?>%U}Af zCg|30=Q_*-ygUd>H{H1b5Y0u^CRKD&R)bfseM^JSH@XU!G{Y^#sUR`Ugt41GvRa!w zE14I2VuXW>hAe6`#ld{SRjvwHo1a8()QwxktH|&hZG;GKRHa=eE%@$`_M0l}9npg` zF{}H~shz}k5FdirV4mVn{HhcDB|4y^K$Z4smKXz&RB(&F@J$KD9D*wzZ9x}BeIty1)BtveCI5b9-t0 zm!+#VVISC!j-LPMq4X%Md~eYFNaM4khd|c*NbZq%AIuK(&`q`2nAYATcwj*6aSMrH zPSANqcAVL;vl}hR|8f7&M&V;b^<;94AIAUbWA+d?y<}iiix!*}pMT*xWA(`$wIhJnIh_Mp zZG{%GUXfzc<~Iq-8;F7(q9EKA~Cg^vcH)8vZ4)XEFa)5!A-U{9g3#6hie81GzkaM=1Ond*<#3 zbi`T^DO1{|1kSV^}XOV?4`dp^Lu`p0ZYcAg5o@|GNw8 z4;z1wZx>nKd+J*lxAiN}mD5A^V#6fi#%No*;Mak%uaq53=R6RuZ?%tBJIZZn+>4(c z2h#+q92SMjN9*h;@_Rq6;cY)q#aZ(i;$LyX=$Z1zn@1f~l*@+#>}WfMM?O#g$*L+c z2zyLEy!V>V*8}uY%zRCl*tjpCDB>#aq!etYcSaL;Zjx!TAz26O(ViU1Jgy5OdSGj4 zZMw^--HT zF(N?cX!QZU z@buO*(s*QO+)8|Ph*$i{X@%23C%Emw)`mN$UDkY0$7wX@+P(aTuc7} z|A#Qo+|LW0QKY_M?3Lkm#9i~*q_&t;;ItQ$ARlz4zCFJ_N$d&%k-U7}ugWSyp<_>( zP?BKlEd{hIqAa_VdY1zU#?8onI`HNfnrz|o9N|m-sFB~MwNIrGx0k8;K(pSR zo_kfA5JCQ+Zosv9-}3+8?iA7&j7P+nFcIUltu!z_+)}?>`vQdow&oyWrTKgc7&5}) z@Z5!r*SsWLu(Fy~Qu+#n{$kcVLm6woW79GUg@#Ncpuj^SCpXh0))A|!2*;BbKrjP) z5Z1-BEa}L0y&}#;(+?2^D%7$7Bo}(PES;Pm<)5+(4PBZC%VgtbOsU4=Kh^MK)kf$R z7|F!5>kVqp8Un8RE$S`T-Q99{`CH~^URPmRjHwP}AosUOA_|MBwtqE_eZK`BU_)QT zGII1;{26XCT21?^S`h*%>0c`JMp0RQ>EAf$e+B5QyEIU$7(w8E-K{Tx9fSyArfoF{ zlcL;-Ykl8=x-QmN8eTW={NsNDgYz1MU!DeMi_uNWH%#Yjc$^O@ylyv}6A=1%)r#VD z_njpyQt0TV(`Tq`dnrfc(`!0^gCmL6c!>lLODf(k2(B%6X&Vk5YU8aJ@t-CK20qNi z5nYHwOX4~+ahWgrO2&A_Xmmpt>I zE91m5zdl^EK^w&O(3J_J0K5iZ&=V40QG!Xp z4?dyrq2_X5#kzpHt-GQMGWpdZEc14ZP|kTCmj%*FvnXL-Y84$r?=Nhj3G1?nqAqO9 zdb6lr8#DlCfP@ee>BJTs%Qb{bWsPVc?7qKUIEUr-Ro$j2vJ9@V!l+b(qq!1SQGtTxnnnJO9$iz z_iaaLd0RxbzHPRUs~YDN?>}R!*jOpo=18I3 zpk-5)KC0q>QwrF&%uS47`n^;pQ7ul@t;Ir^b{n^_h|S6l?GC#yHa(<}IikHS1$YHJ zzsNFWWC!)(x-}YoL&sTi^LV{5DumS$aXZYmrMUj6F2VUH-2*tlAt)sd6dzUYh7v%wG?2?1 z75#f0JK0On^5ha5~m4!{$&&ihX8B`WMnjsqW7jv=fpbrlYxz$O>&f)(J%@0%sIFe^ShFnJ zcksW5-8EGhf?FJYP#3#k&(*j?nfhjY9Q69;fXpC4riKs14UlE;#?FtzL+tPOk^)98-i) z(nF%_c{w<;Ov2^cpW#Y9Z?AgN<45k`R6r7M0g(~v_Wzb>*OElwt&{oSExjE9S|VeV zYZuAQLM|B%#Z@!E+;2T-f7(hO1vl)gz^D+MFa16p zzw09HoH=X#q#ILtU!|&8Me>3E^)P5uhk$i-1pw^2$*acJhu!)YRUO~(@UBmyE%~T8 zP$iZYuVZt=tQor8U@(9xkCuT)`nY{!k#dZuO(oUkuwdL5{nlXQa=xu&SG4sriGj0( zU=*N?k*t$2-vknO*2ZXve=SH_)P#eR6xIxUR3z%1m<>cS!)_1oo2v7G$J+HB;<)-y zhQ{V%6xIU8&1S0;Gs}%ri!zN65nK2|ABT<5Y`##;ilndzZ0U3ed9gL?6>ggN@t0Xn z>_(fH0|HX#fFLYLEz!$SE-pWQ%;eJ7H=paUO$ikUUh?wEST?wHFX5=+sA;i119_s{ z4`R1SEbN1U4Q#W<+Y=qT-YJXBJpw)!Yp$_CcY>`#TQ`Me0a8`&Dj}_L(~}60KfPzf z@XBo@()Smc^Q3Ru$tJ?vF3@VC8<+Zs$*#@>WXUdkzX;%}VS zlJFMRXGsl@7kePK2Utm3Dk9u9Z=I#F-}666--rQm*0JzuA(j15{?B&#=PgJ_H%XXG z@k`Kr*uP-hN{~vGSEQZsE9QHTwx6v)gphA=gr|$=Tl9+LmJNwX!N)UIinq@=z9NNa zlnva6DR=jcER>Jg(dVT3_qJjZ{P1U3zQx5|+y6*HY;`OMbI~#x{l~k8=gh zq7SK$bp%JfEk~;&P0%6O%MH%@OZn$+e3z}yI>P3pNM{3X(yRb*|J-Mlr>)<~6(OZx zm?lJMe;!PfE4l!@@=V&TP=ODuL&kJf_9HnGTQTND?w`wvK5F#$s_a1k4ZRrzk>P1? ztwr$wYDZW*TOI|*3QRRk(?5W_1?jZ;=r+;Km`RdJ|JrfRs$n1Z^Sag#3rkFG-0tjV z>B!ZLQ3~(O@S=4w9;4hlf%!eFjORn-KGw+=Aiih5bM-T8Pw1Sk_v_EkKI$c241zj< zsxu>!zb9`(ks!^`>zQI$ihG!fz8<`*(%eruEBt+RB3a~bUyeRoT9JN87{bXa9Ms^) z&_E&4UvyNvum;8)k?4n&ZO*YQ4IK)MXEVq|Bo$z#VJQPBhY+Ify&ZVbua5ag3Na(V zrXK2}nqSI~hbo<(T}`A0Wo52`(iFQ+5QdIAI7t6FFg<2^9MEcKdP8IN_^8g^2oU3D zY~ZwMH7ddimKzRME=Ksb-yNufk)j_z!kq6nmb3JH^Yz!vU#*?z=#z?pX<~z zBsSNf1cghhLI;<(eH+pU_`}t+K?sn_N#wxAHGoNGtc3Ce`iJYEY%-Kd(#p-shUod* zFqST(H*b1e+=e#mnpE|#6JLqk^=+Bd6yTEWj9{~>q2uCed(k}{ z!@5q5WZ;D9sq9xk!4p*X>cKICS^AYq(?ku5hxp-^Hm6piGUWe5ixao+7vNnIfxEwt zN(66X6!?H`RFtIvZI^$AzN=R-{Sxwa%Ue+-k8I!AZ`{BMe+3LNqoeF%=K&LnDD`P( zjJ=$$)EH3~dujx|M$?R5#HaLldRvkC3QpOvDszo@^_RUf#^=vBxam46#sAC_y$o7_ zt$E}kj15nZH_7XuHd4iBj0QL5UYkrjXQG#Ps=|EsIf@+jwZhmmGnVS zDbpm8bkbQNuVkpwVbo8}Aw8n^2cAsb8dfJELqI5QtyS9bObSTvn~F-&XX)ol>XsNR z8|?qS@PILZNdMMDO@xPV47i2RF>4#FMIX9U{#o_$na_)GT&K7&xwQR5G!hVQetB0R zsB$#GoTF1tSZC?WDMUIR#6c{w4H$k+(lGO8bph0eHoAm{2=!rrRIPW{kcp*dH^>PF zfZzI(ZkcrrQ9eBIflSFB3BN$|oQtp_TbZ3_^v)Jt92SFPjNu&5~WJP-rh1HR+i>SEc|5Ii9+lpr%Wf{LY;R0OAhP0ivC z1X*4hMy`erowngzcy9Em;*f5s^`TpU&pUE9GF@(ta^myMcbN>Ps0GR*Z5n)chPuB@ef#b_S=R!dp?F(pJ)-*u$#m#TfaO+ zEP~76DP!=yg4?>&ml~z9YTsw*D+6fkDFJ0m<=s}1pX*Q7eRZPL#tx5%prN{~f^!F? zFRR%aCFM`ac{i9D!(~z2^sV7_rn=lW>2GSKDlYyUK)mBMsP|gbpi7MHYF{b0nXv1W z>ayjNdSLq1HZXrqZyAMvZf$^Yw6#q&2G${GIk>U7Gj=&<8(nmD867`SwMn9#?Koev zapAgFp+o*5iF7VeHp`K$WeG`ZgC-ek57Za7inu$=1hAi6gm@Z;FdFR6ZuJ9#!$~Iy z2^vGaiRdzym(>9G*WOMhfPhu7vU-B!Wb#!zX3qS8Yuf~F&u4m+d*7{@qo)=zY)`9- z`@KG;5H#A`Y>)f4(u%a0P(7C3pJkA6fl_gczY#Zp*)MYlXV0q- z{D5x)VoL+nQ{gZ+$(%YS%nHzC&cX9ow=fb{{We+Gl=X)+#vy^|RE3 z9DOqj^olHVf9kk;Nep;_e?>c^JO0T!eicyAXmIF<1ZKp(OAQ|vpdCYSw)boGLgEsx zLxX>^p67_dSsZJwP0>c2Erly+Sn%8-@FwJa!SZwC7$1OQRL3YFdi7%EV@#v0ms}U4%x_?+g)re>#&7cZ9Pzr`FX)Jtd0o?)#5!F|3Gmw zUiF^0IQK!Hu+^7=+qmQ6D}R{pwnGng74;q-aOsq7NvP?eZovKhkGzL^17&6N?qg)o z2B;I0TP6%Ay0;!Es_|mo=-d-nj;Bux=!vL(l*{MHbk?(u(@V#sg8j?Ghwc1ofh`WK zoGz|};6;!Wet3BkCT}ang=+&HAoxtO#{W5RU|v7XiB1psZ@lha3EX&E?cU3h21?DyB3>$7u= zY#T50>r93oh7q$Lt2v@$x@B}dVZxk+-dHwaN9AYjgk{o+%O=t#EHr(&odbSqmMJ#x zKAV+87E%bIqMWXrfW|Kl!u<@C{ejXAVUX`N6WA6vt2Io*(xn_QS`7p=jW8HW+ue)1 z3`te(hrn0IT;D2j1MaI}-z>Yr>zp<_4Q#7+%IVeH0V}OcIA1CZ0Snn({$Ma*Bdl)J zz{irW;`3G#S-p@+RW)1gAysZFz)y)H)G&*x!v!`sF60K_;^mY%KKZ6#+PiC*>Qdum zgLE-Pi*+8Z$h<~VgMfgRAHx!{j!ZN2IJ?6?5#wsnplb!astZMZgsiA5v*S|3AK`L? zWhFANk6vX5V>SRb+3YDp8c!q6rX7tAKQE(pw?>BRUhoviN87K=>iBsgJHuLluZH-( z!fub~Mc)w0b7k43gbhS$jXSioTw4d5!(T6vtEL;CB2H|Hp}oD?Y*o-};M7AaPA%#0 zc!o^O_znZz&CJ_@vLnkqk=-@oB8cu=ahD zP>!ywrp;xX2D?UUJC=zv=F0;>ZUsTEzg|6^nyyFY>9elU8!0|@ zX(H*OC{#*3xfd~nYHzT*7x z3+KeSmT^+VWW`+^XxQWRFl0ViOFs}^O&=1GLU{WKy(BQV8F>#45x$}*S)fC0bvk^r zt!klu1xj8jwL3400BmX{P6$T7pm=DJBg!LEK-``0_(9}`>5z!$7>wRHZk=c52$5_h z$8~6vSoy8}yELu0F|Rx+PrgefIzMPs+);FThQ05?MF<}%8+xJ$zf#Jz$h0xjDWl*Z zX~Zq2X$%1aPc5br?Tqn3&i$4C0MFQu6~|N%^e93__P7n~LxQxGrGG3w51T9WJz*BT zkkGMq3PW+X!qVv174cmI?T@iAX|~F~eaW0{*3!26ZX?VyM(tcnho_sWMhq05Hy>vU zSBL|~A04eZl4WTB)jtRJ2=^7I8k6)i{|%%-HH4yl?W$$&fgp{G(QD&v%7df3@B_!|;uRA0N_Yb@k(vXo=1DQtm0++F!Y`cD){B8hW-?$T1*b*W#fc-!^^1>3hEDVu4IpR%&=}a0Gsap6|9`pnh$wE!Z7LuE zlw+4y8s@-eq(_PRaXTkhFNb}A<)+hxg3em5)(LAhBSWA!i@dhO{Vd&vJUg_qNxO6DqIVMC-5SgzyoKtS}}I)Lcx&!RTn8t zCv`Z*$Ti850ifkrEEP5~eJGAzla_gcuE1<-8>$e+O>m$4Gu1~wWg5<%CXSOc@%6^CgJp37L<DWXq-{Y!4Xk!C<0O;C8{t%uJ%`2IWi)7NJ`$2YZ>~S#^f%Gk9X*GYotMTAl|94+ zvD$q8Whd>ZgMrJKLKX9Tz~_j?5%62Fh69Ead+K6l5TVQbcf{|^d-Lfr*egJDIZMu# z^T**%so(Mzz;MbVp^iTxS`Nd`fS|Cp_7KZTDy+$_Exz!l?8}1-!T$F2X43A19Ir>k z7I$IDVG0Wbl5ft$yeFTv5KvnDS^>j6*WWxkwQU0ZbUiJ!UxrI_H~^l5Fv?xmXgDW* znXTT`q&Dc1gKL9?1SXa_r>ft*q+`x(7abOK9hxuQ{)I}|hQy)8yvH$^61Y`7H}D<8 zqx!TDf?vjDJ5yWT0HgOuTj001N7_bSt{{8QqtKK;Rjl9FuMo2uf8%QWg1zfcxyD#H zpW3KMU1Kp-LICT~(5D(r7MI{$jGQ19+)oc$eYBqL zlGbc*@4clO-fBTyC2#WTby!YP`5Nqfy~Z*eT}=zI|EF)>%|!C4V*80hAVHhc(Jk_6 zw+9gKspH>=5AJi)MP-p7ek!eS+HjZh%A<2Hc zgKtE@i7x8v#nN!aHJF>g5mth6XbR+1(rN*2SyVSidP4S1NMFspX8+bj60S^uCLfU=lYwhs zk)KJ67Q)!r=5(zoSbnIBKY2AWBXg?g=8@O_Za?=#TItxS1Y3c)c0Ut(ehYoh+-U!u z9@mGDt{+~=K5&>V9ij0)lwhagkXHU`YI}o$MJINTjpte4eFE$;h?5*NeNY~CrV2c5 zKJL{CYAfEw>!u@Z-IcX?IRb?jtG1NK-5(LY$?52HXAGVONFJP1-Xk4#2Gq0dm|3L) zj0Z%eM5Q@DkHBk}BL@VY%ZKuAWw_p-aN+WT(CT(;FwU-c#Qjy;?1m~2@@D_pjYSW2 znMTAp+=Dn-;kN#tv*X5$lFB!+mE8Cm4zA{vH%^_vp^l>cO!t@&CNW8#z9z>Z~LYom-j577cmE;4(rzfR&6BjMB2Bl+>xDQ>Z~nq9_Y znMmU#Tvw4qq9itO7RyB-L@*v72f|Q&#QMZ%c%eD_dBPvcd3J=u;C)unJ66QiJqx6; zo*FoE1qA&jvbGWGJ2(fsMZZbGts*;@l{cFo%Hmd#wX=jfps0*p8{)VXjn%5xOrI|J7)&txAEr)A_M3lb)ijm^~Us~*Rd&46FC3t&I!zc^DG{+4^^ z4^DUTuEF4QRO~l|54dJ6UKX#$)_vJ z<0^+V9||Oh1l89p?ITm^J^iLeg`bR9IGeEl!Mvynequ&q!U@NQxI zozyG8FTx4GWsTMS8}3SgYt(X}9Qr*@8`hyKd3o0dLl5qLIymocdE)ql`=SM2F!0df zwTTTSKEFOeM`J``I}4yHm=2hv=if>jjH5?OSMD=GMjl|JEa4CkkdO4LFerZKLCsX{ zn2UTDAQvE7Q2HD(C+~_>E08C*C(^e(!y?=mk>;P$(R7Kp?CB_{Ti$+SC;RVpaoD{O+PT7P zFOdZ?s+^Qo8-9%D^7;@ISl-M#;vm=ArI5nmm95JAnzsBVbQb$)Lg+ZKj8mgqs6WRo zXpxSkln<9k2=}!@ix|wkC6N(e2xks?M_BhZ1I@U45#b7XW@&AE85wttABI`8O(QJ&VwSE{qoDt`>Nl7KeuVpt`b#M4 zj28ZDqQQQ8InX@hA<);*vC=@KZB0vhH%+@pTGHy8BqRW}u{#1jS4gZrX_Osu}qS**1Lg;$D{4Ke|hHsCdPm63gWt1 z==;aHRNAg$o~;_WJ0N)Rl3@U>dTlP{!R~1VxzJ=+Gg?}%*TK6MZiGxQLXnpBsJvX_ zE`+5y&07_e;Wbik{7;Y%$KpLaS?9~&e8X*S(c%BBgT}W3uLg8K&XU0AyjLu}EHJaq z8zXNYz6ue+1W35n>#qp2m%ps?x+xiq7uw6}zA3^g zloC_{b}S^`=Ts@Q1<8vpm64mr67`cL2+k)`8>kp?@D8yKDN3)b6gKjQPv(f>aUxqA zp|&OTGy)fVX!F@Xcmm30z2ppXSHsp~>$Xc0;lp65-lzNTw-d}=TZV!r+F{HD3cGhW zH5RV6M?sfV?w^_>zuiAxOX#6NY-Nfexh+^EYpjX`3S@uJ_56YF}c^~dRYslNhjt}S19>&X-Z9*iM zIWg3v|3ZK^v+I`lVhiy0hF?icI{gh@Vx%#)gMyTRhHu?0UZKRM)6F($M#?diI{qJ+Cor)j+@Sp0} zXIxoW+V|HqX>2?(plPTppmL!bw+u8Nf@qKA=o^k4I-6w1IUgi1`}C5OV=b3`3idYZ zvK=gLrZ>d2M1%x_F*4p{K?WRKMf(R5th-TF9K`+HgSL=dM=K}2XD4GK-{Mr255@!E!_rPrSAtwaH=Vb;7MtsteAJ6Zc|_jdB+neC(V<>??#Bk3sNQ1QDg}mz1EZ479=HWt}zrbfpcloYtSL-3brjV8Wo&-B@y;6h44`mo4Y+)$q8Pxo`EbSgQBXudQUXyn*#L(mK6Cu|`qBagW8drmSwPHxR|j9m=a zDR2s=B%ZrveOS`{aY>6)%3w{nZ_spwFBBrC&)lo^ z7uLF4fTeK_YNT6mQCry2ZKy z>AI!ww`0p^MZ*D>Z`}z4U2--vuq{kCMZ1%RI<;ky;tRNmhu#ACZpM@@Cu*pZ$=c zHw^-o{?gKmDyF=MzOz&S)}&lQYvOKg=Pg|bn2~V8*0�c^;c?>>rbv^`@buBvD-( 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 H_vO*Xt)dolqEdGS-(1Acz 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 z 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

    uXnT(c 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 exit 1; } + cp "$file" "$pick/" + done +done + +tar -cf "$work/weights.tar" -C "$pick" . +xz -9e --check=crc64 -c "$work/weights.tar" > "$out" + +raw=$(cat "$pick"/*.ttf | wc -c) +packed=$(wc -c < "$out") +echo "fonts: $raw bytes raw, $packed packed, written to $out" From 9fae8cb58478ee5bbfa1272b5f9820f9f0e7ab0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Tue, 3 Nov 2026 17:48:44 +0800 Subject: [PATCH 2/6] The text system names a family's own weights, so a picker offers only real faces Two platforms already expose the metadata: DirectWrite answers IDWriteFontFamily::GetFontCount and IDWriteFont1::IsMonospacedFont, and font-kit answers the same for macOS and Linux. gpui carried neither through. vendor/gpui-pre is zed's gpui-pre 0.3.8 snapshot with one addition: PlatformTextSystem::weights_for_family and ::is_monospaced, both defaulted, so a platform that cannot tell answers none and the caller keeps its own list. A defaulted method means the macOS and Linux forks compile unchanged. vendor/gpui-pre-windows adds the DirectWrite half: a family's faces by IDWriteFontFamily, its monospace flag by IDWriteFont1. The custom collection is asked first, so a bundled face answers before a system one of the same name. The upstream fix belongs in the forks, not here: a fork of zed's snapshot cannot be sent upstream, since gpui-pre has no repository of its own. --- vendor/gpui-pre-windows/Cargo.toml | 243 + vendor/gpui-pre-windows/Cargo.toml.orig | 59 + vendor/gpui-pre-windows/LICENSE-APACHE | 222 + vendor/gpui-pre-windows/README.md | 7 + vendor/gpui-pre-windows/build.rs | 242 + .../src/alpha_correction.hlsl | 49 + vendor/gpui-pre-windows/src/clipboard.rs | 394 + .../src/color_text_raster.hlsl | 44 + .../gpui-pre-windows/src/destination_list.rs | 207 + vendor/gpui-pre-windows/src/dialog.rs | 340 + .../src/direct_manipulation.rs | 359 + vendor/gpui-pre-windows/src/direct_write.rs | 2263 ++++ vendor/gpui-pre-windows/src/directx_atlas.rs | 420 + .../gpui-pre-windows/src/directx_devices.rs | 194 + .../gpui-pre-windows/src/directx_renderer.rs | 2070 ++++ vendor/gpui-pre-windows/src/dispatcher.rs | 191 + vendor/gpui-pre-windows/src/display.rs | 210 + vendor/gpui-pre-windows/src/events.rs | 1812 ++++ vendor/gpui-pre-windows/src/gpui_windows.rs | 43 + vendor/gpui-pre-windows/src/keyboard.rs | 371 + vendor/gpui-pre-windows/src/platform.rs | 1939 ++++ vendor/gpui-pre-windows/src/shaders.hlsl | 1268 +++ .../src/system_notifications.rs | 198 + .../gpui-pre-windows/src/system_settings.rs | 87 + vendor/gpui-pre-windows/src/util.rs | 191 + vendor/gpui-pre-windows/src/vsync.rs | 119 + vendor/gpui-pre-windows/src/window.rs | 1735 +++ vendor/gpui-pre-windows/src/wrapper.rs | 53 + vendor/gpui-pre/Cargo.toml | 683 ++ vendor/gpui-pre/Cargo.toml.orig | 247 + vendor/gpui-pre/LICENSE-APACHE | 222 + vendor/gpui-pre/README.md | 98 + vendor/gpui-pre/build.rs | 36 + .../resources/windows/gpui.manifest.xml | 33 + vendor/gpui-pre/resources/windows/gpui.rc | 2 + vendor/gpui-pre/src/_accessibility.rs | 295 + .../gpui-pre/src/_ownership_and_data_flow.rs | 140 + vendor/gpui-pre/src/action.rs | 459 + vendor/gpui-pre/src/app.rs | 3607 +++++++ vendor/gpui-pre/src/app/async_context.rs | 557 + vendor/gpui-pre/src/app/bench_context.rs | 1596 +++ vendor/gpui-pre/src/app/context.rs | 959 ++ vendor/gpui-pre/src/app/entity_map.rs | 1308 +++ .../gpui-pre/src/app/headless_app_context.rs | 284 + vendor/gpui-pre/src/app/test_app.rs | 645 ++ vendor/gpui-pre/src/app/test_context.rs | 1439 +++ .../gpui-pre/src/app/visual_test_context.rs | 484 + vendor/gpui-pre/src/arena.rs | 401 + vendor/gpui-pre/src/asset_cache.rs | 358 + vendor/gpui-pre/src/assets.rs | 133 + vendor/gpui-pre/src/bounds_tree.rs | 472 + vendor/gpui-pre/src/color.rs | 1070 ++ vendor/gpui-pre/src/colors.rs | 122 + vendor/gpui-pre/src/debug_overlay.rs | 428 + vendor/gpui-pre/src/element.rs | 813 ++ vendor/gpui-pre/src/elements/anchored.rs | 398 + vendor/gpui-pre/src/elements/animation.rs | 1028 ++ vendor/gpui-pre/src/elements/canvas.rs | 95 + .../gpui-pre/src/elements/container_query.rs | 126 + vendor/gpui-pre/src/elements/deferred.rs | 206 + vendor/gpui-pre/src/elements/div.rs | 5640 ++++++++++ vendor/gpui-pre/src/elements/image_cache.rs | 330 + vendor/gpui-pre/src/elements/img.rs | 983 ++ vendor/gpui-pre/src/elements/list.rs | 2973 +++++ vendor/gpui-pre/src/elements/mod.rs | 27 + vendor/gpui-pre/src/elements/surface.rs | 129 + vendor/gpui-pre/src/elements/svg.rs | 303 + vendor/gpui-pre/src/elements/text.rs | 1349 +++ vendor/gpui-pre/src/elements/uniform_list.rs | 865 ++ vendor/gpui-pre/src/executor.rs | 583 + vendor/gpui-pre/src/geometry.rs | 4020 +++++++ vendor/gpui-pre/src/gestures.rs | 2211 ++++ vendor/gpui-pre/src/global.rs | 75 + vendor/gpui-pre/src/gpui.rs | 402 + vendor/gpui-pre/src/input.rs | 485 + vendor/gpui-pre/src/inspector.rs | 271 + vendor/gpui-pre/src/interactive.rs | 971 ++ vendor/gpui-pre/src/key_dispatch.rs | 2196 ++++ vendor/gpui-pre/src/keymap.rs | 1135 ++ vendor/gpui-pre/src/keymap/binding.rs | 143 + vendor/gpui-pre/src/keymap/context.rs | 891 ++ vendor/gpui-pre/src/path_builder.rs | 347 + vendor/gpui-pre/src/platform.rs | 3786 +++++++ vendor/gpui-pre/src/platform/app_menu.rs | 426 + vendor/gpui-pre/src/platform/keyboard.rs | 41 + vendor/gpui-pre/src/platform/keystroke.rs | 782 ++ vendor/gpui-pre/src/platform/layer_shell.rs | 83 + vendor/gpui-pre/src/platform/popup.rs | 134 + .../src/platform/scap_screen_capture.rs | 325 + vendor/gpui-pre/src/platform/test.rs | 12 + .../gpui-pre/src/platform/test/dispatcher.rs | 148 + vendor/gpui-pre/src/platform/test/display.rs | 33 + vendor/gpui-pre/src/platform/test/platform.rs | 742 ++ vendor/gpui-pre/src/platform/test/window.rs | 591 + .../src/platform/threaded_dispatcher.rs | 744 ++ vendor/gpui-pre/src/platform/visual_test.rs | 272 + vendor/gpui-pre/src/platform_scheduler.rs | 457 + vendor/gpui-pre/src/prelude.rs | 9 + vendor/gpui-pre/src/profiler.rs | 1644 +++ vendor/gpui-pre/src/profiler/actions.rs | 213 + vendor/gpui-pre/src/profiler/hang.rs | 1506 +++ vendor/gpui-pre/src/profiler/hang/monitor.rs | 113 + vendor/gpui-pre/src/profiler/journal.rs | 3522 ++++++ vendor/gpui-pre/src/queue.rs | 499 + .../gpui-pre/src/randomized_element_tree.rs | 1745 +++ vendor/gpui-pre/src/scene.rs | 949 ++ vendor/gpui-pre/src/seeds.rs | 67 + vendor/gpui-pre/src/shared_uri.rs | 25 + vendor/gpui-pre/src/spring.rs | 830 ++ vendor/gpui-pre/src/style.rs | 1529 +++ vendor/gpui-pre/src/styled.rs | 904 ++ vendor/gpui-pre/src/subscription.rs | 351 + vendor/gpui-pre/src/svg_renderer.rs | 525 + vendor/gpui-pre/src/tab_stop.rs | 615 ++ vendor/gpui-pre/src/taffy.rs | 776 ++ vendor/gpui-pre/src/test.rs | 172 + vendor/gpui-pre/src/text_system.rs | 1521 +++ .../src/text_system/font_fallbacks.rs | 21 + .../gpui-pre/src/text_system/font_features.rs | 154 + vendor/gpui-pre/src/text_system/line.rs | 1979 ++++ .../gpui-pre/src/text_system/line_layout.rs | 1190 ++ .../gpui-pre/src/text_system/line_wrapper.rs | 1921 ++++ vendor/gpui-pre/src/util.rs | 252 + vendor/gpui-pre/src/view.rs | 593 + vendor/gpui-pre/src/window.rs | 9528 +++++++++++++++++ vendor/gpui-pre/src/window/a11y.rs | 905 ++ vendor/gpui-pre/src/window/a11y/debug.rs | 330 + vendor/gpui-pre/src/window/prompts.rs | 232 + 128 files changed, 103599 insertions(+) create mode 100644 vendor/gpui-pre-windows/Cargo.toml create mode 100644 vendor/gpui-pre-windows/Cargo.toml.orig create mode 100644 vendor/gpui-pre-windows/LICENSE-APACHE create mode 100644 vendor/gpui-pre-windows/README.md create mode 100644 vendor/gpui-pre-windows/build.rs create mode 100644 vendor/gpui-pre-windows/src/alpha_correction.hlsl create mode 100644 vendor/gpui-pre-windows/src/clipboard.rs create mode 100644 vendor/gpui-pre-windows/src/color_text_raster.hlsl create mode 100644 vendor/gpui-pre-windows/src/destination_list.rs create mode 100644 vendor/gpui-pre-windows/src/dialog.rs create mode 100644 vendor/gpui-pre-windows/src/direct_manipulation.rs create mode 100644 vendor/gpui-pre-windows/src/direct_write.rs create mode 100644 vendor/gpui-pre-windows/src/directx_atlas.rs create mode 100644 vendor/gpui-pre-windows/src/directx_devices.rs create mode 100644 vendor/gpui-pre-windows/src/directx_renderer.rs create mode 100644 vendor/gpui-pre-windows/src/dispatcher.rs create mode 100644 vendor/gpui-pre-windows/src/display.rs create mode 100644 vendor/gpui-pre-windows/src/events.rs create mode 100644 vendor/gpui-pre-windows/src/gpui_windows.rs create mode 100644 vendor/gpui-pre-windows/src/keyboard.rs create mode 100644 vendor/gpui-pre-windows/src/platform.rs create mode 100644 vendor/gpui-pre-windows/src/shaders.hlsl create mode 100644 vendor/gpui-pre-windows/src/system_notifications.rs create mode 100644 vendor/gpui-pre-windows/src/system_settings.rs create mode 100644 vendor/gpui-pre-windows/src/util.rs create mode 100644 vendor/gpui-pre-windows/src/vsync.rs create mode 100644 vendor/gpui-pre-windows/src/window.rs create mode 100644 vendor/gpui-pre-windows/src/wrapper.rs create mode 100644 vendor/gpui-pre/Cargo.toml create mode 100644 vendor/gpui-pre/Cargo.toml.orig create mode 100644 vendor/gpui-pre/LICENSE-APACHE create mode 100644 vendor/gpui-pre/README.md create mode 100644 vendor/gpui-pre/build.rs create mode 100644 vendor/gpui-pre/resources/windows/gpui.manifest.xml create mode 100644 vendor/gpui-pre/resources/windows/gpui.rc create mode 100644 vendor/gpui-pre/src/_accessibility.rs create mode 100644 vendor/gpui-pre/src/_ownership_and_data_flow.rs create mode 100644 vendor/gpui-pre/src/action.rs create mode 100644 vendor/gpui-pre/src/app.rs create mode 100644 vendor/gpui-pre/src/app/async_context.rs create mode 100644 vendor/gpui-pre/src/app/bench_context.rs create mode 100644 vendor/gpui-pre/src/app/context.rs create mode 100644 vendor/gpui-pre/src/app/entity_map.rs create mode 100644 vendor/gpui-pre/src/app/headless_app_context.rs create mode 100644 vendor/gpui-pre/src/app/test_app.rs create mode 100644 vendor/gpui-pre/src/app/test_context.rs create mode 100644 vendor/gpui-pre/src/app/visual_test_context.rs create mode 100644 vendor/gpui-pre/src/arena.rs create mode 100644 vendor/gpui-pre/src/asset_cache.rs create mode 100644 vendor/gpui-pre/src/assets.rs create mode 100644 vendor/gpui-pre/src/bounds_tree.rs create mode 100644 vendor/gpui-pre/src/color.rs create mode 100644 vendor/gpui-pre/src/colors.rs create mode 100644 vendor/gpui-pre/src/debug_overlay.rs create mode 100644 vendor/gpui-pre/src/element.rs create mode 100644 vendor/gpui-pre/src/elements/anchored.rs create mode 100644 vendor/gpui-pre/src/elements/animation.rs create mode 100644 vendor/gpui-pre/src/elements/canvas.rs create mode 100644 vendor/gpui-pre/src/elements/container_query.rs create mode 100644 vendor/gpui-pre/src/elements/deferred.rs create mode 100644 vendor/gpui-pre/src/elements/div.rs create mode 100644 vendor/gpui-pre/src/elements/image_cache.rs create mode 100644 vendor/gpui-pre/src/elements/img.rs create mode 100644 vendor/gpui-pre/src/elements/list.rs create mode 100644 vendor/gpui-pre/src/elements/mod.rs create mode 100644 vendor/gpui-pre/src/elements/surface.rs create mode 100644 vendor/gpui-pre/src/elements/svg.rs create mode 100644 vendor/gpui-pre/src/elements/text.rs create mode 100644 vendor/gpui-pre/src/elements/uniform_list.rs create mode 100644 vendor/gpui-pre/src/executor.rs create mode 100644 vendor/gpui-pre/src/geometry.rs create mode 100644 vendor/gpui-pre/src/gestures.rs create mode 100644 vendor/gpui-pre/src/global.rs create mode 100644 vendor/gpui-pre/src/gpui.rs create mode 100644 vendor/gpui-pre/src/input.rs create mode 100644 vendor/gpui-pre/src/inspector.rs create mode 100644 vendor/gpui-pre/src/interactive.rs create mode 100644 vendor/gpui-pre/src/key_dispatch.rs create mode 100644 vendor/gpui-pre/src/keymap.rs create mode 100644 vendor/gpui-pre/src/keymap/binding.rs create mode 100644 vendor/gpui-pre/src/keymap/context.rs create mode 100644 vendor/gpui-pre/src/path_builder.rs create mode 100644 vendor/gpui-pre/src/platform.rs create mode 100644 vendor/gpui-pre/src/platform/app_menu.rs create mode 100644 vendor/gpui-pre/src/platform/keyboard.rs create mode 100644 vendor/gpui-pre/src/platform/keystroke.rs create mode 100644 vendor/gpui-pre/src/platform/layer_shell.rs create mode 100644 vendor/gpui-pre/src/platform/popup.rs create mode 100644 vendor/gpui-pre/src/platform/scap_screen_capture.rs create mode 100644 vendor/gpui-pre/src/platform/test.rs create mode 100644 vendor/gpui-pre/src/platform/test/dispatcher.rs create mode 100644 vendor/gpui-pre/src/platform/test/display.rs create mode 100644 vendor/gpui-pre/src/platform/test/platform.rs create mode 100644 vendor/gpui-pre/src/platform/test/window.rs create mode 100644 vendor/gpui-pre/src/platform/threaded_dispatcher.rs create mode 100644 vendor/gpui-pre/src/platform/visual_test.rs create mode 100644 vendor/gpui-pre/src/platform_scheduler.rs create mode 100644 vendor/gpui-pre/src/prelude.rs create mode 100644 vendor/gpui-pre/src/profiler.rs create mode 100644 vendor/gpui-pre/src/profiler/actions.rs create mode 100644 vendor/gpui-pre/src/profiler/hang.rs create mode 100644 vendor/gpui-pre/src/profiler/hang/monitor.rs create mode 100644 vendor/gpui-pre/src/profiler/journal.rs create mode 100644 vendor/gpui-pre/src/queue.rs create mode 100644 vendor/gpui-pre/src/randomized_element_tree.rs create mode 100644 vendor/gpui-pre/src/scene.rs create mode 100644 vendor/gpui-pre/src/seeds.rs create mode 100644 vendor/gpui-pre/src/shared_uri.rs create mode 100644 vendor/gpui-pre/src/spring.rs create mode 100644 vendor/gpui-pre/src/style.rs create mode 100644 vendor/gpui-pre/src/styled.rs create mode 100644 vendor/gpui-pre/src/subscription.rs create mode 100644 vendor/gpui-pre/src/svg_renderer.rs create mode 100644 vendor/gpui-pre/src/tab_stop.rs create mode 100644 vendor/gpui-pre/src/taffy.rs create mode 100644 vendor/gpui-pre/src/test.rs create mode 100644 vendor/gpui-pre/src/text_system.rs create mode 100644 vendor/gpui-pre/src/text_system/font_fallbacks.rs create mode 100644 vendor/gpui-pre/src/text_system/font_features.rs create mode 100644 vendor/gpui-pre/src/text_system/line.rs create mode 100644 vendor/gpui-pre/src/text_system/line_layout.rs create mode 100644 vendor/gpui-pre/src/text_system/line_wrapper.rs create mode 100644 vendor/gpui-pre/src/util.rs create mode 100644 vendor/gpui-pre/src/view.rs create mode 100644 vendor/gpui-pre/src/window.rs create mode 100644 vendor/gpui-pre/src/window/a11y.rs create mode 100644 vendor/gpui-pre/src/window/a11y/debug.rs create mode 100644 vendor/gpui-pre/src/window/prompts.rs diff --git a/vendor/gpui-pre-windows/Cargo.toml b/vendor/gpui-pre-windows/Cargo.toml new file mode 100644 index 00000000..52a60ac5 --- /dev/null +++ b/vendor/gpui-pre-windows/Cargo.toml @@ -0,0 +1,243 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +name = "gpui-pre-windows" +version = "0.3.8" +build = "build.rs" +publish = true +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Zed's `gpui_windows` crate (gpui-pre snapshot of zed@279fe07)" +readme = false +license = "Apache-2.0" +repository = "https://github.com/zed-industries/zed" +resolver = "2" + +[package.metadata.cargo-shear] +ignored = ["scap"] + +[package.metadata.gpui-pre] +zed-crate = "gpui_windows" +zed-version = "0.1.0" +zed-rev = "279fe070bb389b79652e52065b2f001edcc0b11b" + +[features] +default = ["gpui/default"] +screen-capture = [ + "gpui/screen-capture", + "scap", +] +test-support = ["gpui/test-support"] + +[lib] +name = "gpui_windows" +path = "src/gpui_windows.rs" +doctest = false + +[dependencies.gpui] +version = "=0.3.8" +default-features = false +package = "gpui-pre" + +[target.'cfg(target_os = "windows")'.dependencies.accesskit] +version = "0.24.0" +features = ["enumn"] + +[target.'cfg(target_os = "windows")'.dependencies.accesskit_windows] +version = "0.34" + +[target.'cfg(target_os = "windows")'.dependencies.anyhow] +version = "1.0.86" + +[target.'cfg(target_os = "windows")'.dependencies.collections] +version = "=0.3.8" +package = "gpui-pre-collections" + +[target.'cfg(target_os = "windows")'.dependencies.dunce] +version = "1.0" + +[target.'cfg(target_os = "windows")'.dependencies.etagere] +version = "0.2" + +[target.'cfg(target_os = "windows")'.dependencies.futures] +version = "0.3.34" + +[target.'cfg(target_os = "windows")'.dependencies.gpui_util] +version = "=0.3.8" +package = "gpui-pre-util" + +[target.'cfg(target_os = "windows")'.dependencies.image] +version = "0.25.1" +features = [ + "bmp", + "dds", + "exr", + "ff", + "gif", + "hdr", + "ico", + "jpeg", + "png", + "pnm", + "qoi", + "rayon", + "tga", + "tiff", + "webp", +] +default-features = false + +[target.'cfg(target_os = "windows")'.dependencies.itertools] +version = "0.14.0" + +[target.'cfg(target_os = "windows")'.dependencies.log] +version = "0.4.16" +features = [ + "kv_unstable_serde", + "serde", +] + +[target.'cfg(target_os = "windows")'.dependencies.parking_lot] +version = "0.12.1" + +[target.'cfg(target_os = "windows")'.dependencies.rand] +version = "0.9" + +[target.'cfg(target_os = "windows")'.dependencies.raw-window-handle] +version = "0.6" + +[target.'cfg(target_os = "windows")'.dependencies.scap] +version = "0.0.8-zed" +optional = true +default-features = false +package = "zed-scap" + +[target.'cfg(target_os = "windows")'.dependencies.scheduler] +version = "=0.3.8" +package = "gpui-pre-scheduler" + +[target.'cfg(target_os = "windows")'.dependencies.smallvec] +version = "1.6" +features = [ + "union", + "const_new", +] + +[target.'cfg(target_os = "windows")'.dependencies.uuid] +version = "1.1.2" +features = [ + "v4", + "v5", + "v7", + "serde", +] + +[target.'cfg(target_os = "windows")'.dependencies.windows] +version = "0.62" +features = [ + "Data_Xml_Dom", + "Foundation_Numerics", + "Globalization_DateTimeFormatting", + "Storage_Search", + "Storage_Streams", + "System_Threading", + "UI_Notifications", + "UI_ViewManagement", + "Wdk_System_SystemServices", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Direct3D", + "Win32_Graphics_Direct3D11", + "Win32_Graphics_Direct3D_Fxc", + "Win32_Graphics_DirectComposition", + "Win32_Graphics_DirectWrite", + "Win32_Graphics_DirectManipulation", + "Win32_Graphics_Dwm", + "Win32_Graphics_Dxgi", + "Win32_Graphics_Dxgi_Common", + "Win32_Graphics_Gdi", + "Win32_Graphics_Imaging", + "Win32_Graphics_Hlsl", + "Win32_Networking_WinSock", + "Win32_Security", + "Win32_Security_Credentials", + "Win32_Security_Cryptography", + "Win32_Storage_FileSystem", + "Win32_Storage_Packaging_Appx", + "Win32_System_Com", + "Win32_System_Com_StructuredStorage", + "Win32_System_Console", + "Win32_System_Diagnostics_Debug", + "Win32_System_DataExchange", + "Win32_System_IO", + "Win32_System_JobObjects", + "Win32_System_LibraryLoader", + "Win32_System_Memory", + "Win32_System_Ole", + "Win32_System_Performance", + "Win32_System_Pipes", + "Win32_System_Power", + "Win32_System_RestartManager", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_Variant", + "Win32_System_WinRT", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Shell", + "Win32_UI_Shell_Common", + "Win32_UI_Shell_PropertiesSystem", + "Win32_UI_WindowsAndMessaging", + "Win32_Media", + "Win32_System_StationsAndDesktops", +] + +[target.'cfg(target_os = "windows")'.dependencies.windows-core] +version = "0.62" + +[target.'cfg(target_os = "windows")'.dependencies.windows-numerics] +version = "0.3" + +[target.'cfg(target_os = "windows")'.dependencies.windows-registry] +version = "0.6.0" + +[target.'cfg(target_os = "windows")'.build-dependencies.windows-registry] +version = "0.6.0" + +[lints.clippy] +dbg_macro = "deny" +declare_interior_mutable_const = "deny" +disallowed_methods = "deny" +large_enum_variant = "allow" +let_underscore_future = "allow" +nonminimal_bool = "allow" +redundant_clone = "deny" +single_range_in_vec_init = "allow" +todo = "deny" +too_many_arguments = "allow" +type_complexity = "allow" + +[lints.clippy.style] +level = "allow" +priority = -1 + +[lints.rust.unexpected_cfgs] +level = "allow" +priority = 0 diff --git a/vendor/gpui-pre-windows/Cargo.toml.orig b/vendor/gpui-pre-windows/Cargo.toml.orig new file mode 100644 index 00000000..8c3320e6 --- /dev/null +++ b/vendor/gpui-pre-windows/Cargo.toml.orig @@ -0,0 +1,59 @@ +[package] +name = "gpui-pre-windows" +version = "0.3.8" +edition = { workspace = true } +publish = true +license = "Apache-2.0" +description = "Zed's `gpui_windows` crate (gpui-pre snapshot of zed@279fe07)" +repository = "https://github.com/zed-industries/zed" + +[package.metadata.cargo-shear] +ignored = ["scap"] + +[package.metadata.gpui-pre] +zed-crate = "gpui_windows" +zed-version = "0.1.0" +zed-rev = "279fe070bb389b79652e52065b2f001edcc0b11b" + +[lib] +path = "src/gpui_windows.rs" +doctest = false +name = "gpui_windows" + +[features] +default = ["gpui/default"] +test-support = ["gpui/test-support"] +screen-capture = ["gpui/screen-capture", "scap"] + +[dependencies] +gpui = { workspace = true } + +[target.'cfg(target_os = "windows")'.dependencies] +accesskit = { workspace = true } +accesskit_windows = { workspace = true } +anyhow = { workspace = true } +collections = { workspace = true } +dunce = { workspace = true } +etagere = { workspace = true } +futures = { workspace = true } +gpui_util = { workspace = true } +image = { workspace = true } +itertools = { workspace = true } +log = { workspace = true } +parking_lot = { workspace = true } +rand = { workspace = true } +raw-window-handle = { workspace = true } +scheduler = { workspace = true } +smallvec = { workspace = true } +uuid = { workspace = true } +windows = { workspace = true, features = ["Win32_System_StationsAndDesktops"] } +windows-core = { workspace = true } +windows-numerics = "0.3" +windows-registry = { workspace = true } +scap = { workspace = true, optional = true } + +[target.'cfg(target_os = "windows")'.build-dependencies] +windows-registry = { workspace = true } + +[lints] +workspace = true diff --git a/vendor/gpui-pre-windows/LICENSE-APACHE b/vendor/gpui-pre-windows/LICENSE-APACHE new file mode 100644 index 00000000..461a0fe5 --- /dev/null +++ b/vendor/gpui-pre-windows/LICENSE-APACHE @@ -0,0 +1,222 @@ +Copyright 2022 - 2025 Zed Industries, Inc. + + + 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 + + + http://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. + + + + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + + 1. Definitions. + + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + + END OF TERMS AND CONDITIONS diff --git a/vendor/gpui-pre-windows/README.md b/vendor/gpui-pre-windows/README.md new file mode 100644 index 00000000..d23286db --- /dev/null +++ b/vendor/gpui-pre-windows/README.md @@ -0,0 +1,7 @@ +# gpui-pre-windows + +crates.io's `gpui-pre-windows` 0.3.8, Zed's `gpui_windows` at `279fe07`, with one fix for ELYTerminal, which takes it through `[patch.crates-io]`. + +DirectWrite shapes a fallback run with a face of its own choosing. gpui rebuilt that face from its family, weight and style and looked it up again, and the lookup can return another face: for Maple Mono NF CN's italic, its Regular file with an oblique simulation. The Italic file's glyph ids then drew from the Regular file, so CJK text in italic showed other characters (ELYTerminal issue #30). A fallback run now draws with the face DirectWrite served, which the text system keeps. + +Remove this fork once a gpui-pre release draws a fallback run with its served face. diff --git a/vendor/gpui-pre-windows/build.rs b/vendor/gpui-pre-windows/build.rs new file mode 100644 index 00000000..1db95715 --- /dev/null +++ b/vendor/gpui-pre-windows/build.rs @@ -0,0 +1,242 @@ +#![allow(clippy::disallowed_methods, reason = "build scripts are exempt")] + +fn main() { + #[cfg(target_os = "windows")] + { + // Compile HLSL shaders + #[cfg(not(debug_assertions))] + compile_shaders(); + } +} + +#[cfg(all(target_os = "windows", not(debug_assertions)))] +mod shader_compilation { + use std::{ + fs, + io::Write, + path::{Path, PathBuf}, + process::{self, Command}, + }; + + pub fn compile_shaders() { + let shader_path = + PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("src/shaders.hlsl"); + let out_dir = std::env::var("OUT_DIR").unwrap(); + + println!("cargo:rerun-if-changed={}", shader_path.display()); + + // Check if fxc.exe is available + let fxc_path = find_fxc_compiler(); + + // Define all modules + let modules = [ + "quad", + "shadow", + "path_rasterization", + "path_sprite", + "underline", + "monochrome_sprite", + "subpixel_sprite", + "polychrome_sprite", + ]; + + let rust_binding_path = format!("{}/shaders_bytes.rs", out_dir); + if Path::new(&rust_binding_path).exists() { + fs::remove_file(&rust_binding_path) + .expect("Failed to remove existing Rust binding file"); + } + for module in modules { + compile_shader_for_module( + module, + &out_dir, + &fxc_path, + shader_path.to_str().unwrap(), + &rust_binding_path, + ); + } + + { + let shader_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("src/color_text_raster.hlsl"); + compile_shader_for_module( + "emoji_rasterization", + &out_dir, + &fxc_path, + shader_path.to_str().unwrap(), + &rust_binding_path, + ); + } + } + + /// Locate `binary` in the newest installed Windows SDK. + pub fn find_latest_windows_sdk_binary( + binary: &str, + ) -> Result, Box> { + let key = windows_registry::LOCAL_MACHINE + .open("SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0")?; + + let install_folder: String = key.get_string("InstallationFolder")?; // "C:\Program Files (x86)\Windows Kits\10\" + let install_folder_bin = Path::new(&install_folder).join("bin"); + + let mut versions: Vec<_> = std::fs::read_dir(&install_folder_bin)? + .flatten() + .filter(|entry| entry.path().is_dir()) + .filter_map(|entry| entry.file_name().into_string().ok()) + .collect(); + + versions.sort_by_key(|s| { + s.split('.') + .filter_map(|p| p.parse().ok()) + .collect::>() + }); + + let arch = match std::env::consts::ARCH { + "x86_64" => "x64", + "aarch64" => "arm64", + _ => Err(format!( + "Unsupported architecture: {}", + std::env::consts::ARCH + ))?, + }; + + if let Some(highest_version) = versions.last() { + return Ok(Some( + install_folder_bin + .join(highest_version) + .join(arch) + .join(binary), + )); + } + + Ok(None) + } + + /// You can set the `GPUI_FXC_PATH` environment variable to specify the path to the fxc.exe compiler. + fn find_fxc_compiler() -> String { + // Check environment variable + if let Ok(path) = std::env::var("GPUI_FXC_PATH") + && Path::new(&path).exists() + { + return path; + } + + // Try to find in PATH + // NOTE: This has to be `where.exe` on Windows, not `where`, it must be ended with `.exe` + if let Ok(output) = std::process::Command::new("where.exe") + .arg("fxc.exe") + .output() + && output.status.success() + { + let path = String::from_utf8_lossy(&output.stdout); + return path.trim().to_string(); + } + + if let Ok(Some(path)) = find_latest_windows_sdk_binary("fxc.exe") { + return path.to_string_lossy().into_owned(); + } + + panic!("Failed to find fxc.exe"); + } + + fn compile_shader_for_module( + module: &str, + out_dir: &str, + fxc_path: &str, + shader_path: &str, + rust_binding_path: &str, + ) { + // Compile vertex shader + let output_file = format!("{}/{}_vs.h", out_dir, module); + let const_name = format!("{}_VERTEX_BYTES", module.to_uppercase()); + compile_shader_impl( + fxc_path, + &format!("{module}_vertex"), + &output_file, + &const_name, + shader_path, + "vs_4_1", + ); + generate_rust_binding(&const_name, &output_file, rust_binding_path); + + // Compile fragment shader + let output_file = format!("{}/{}_ps.h", out_dir, module); + let const_name = format!("{}_FRAGMENT_BYTES", module.to_uppercase()); + compile_shader_impl( + fxc_path, + &format!("{module}_fragment"), + &output_file, + &const_name, + shader_path, + "ps_4_1", + ); + generate_rust_binding(&const_name, &output_file, rust_binding_path); + } + + fn compile_shader_impl( + fxc_path: &str, + entry_point: &str, + output_path: &str, + var_name: &str, + shader_path: &str, + target: &str, + ) { + let output = Command::new(fxc_path) + .args([ + "/T", + target, + "/E", + entry_point, + "/Fh", + output_path, + "/Vn", + var_name, + "/O3", + shader_path, + ]) + .output(); + + match output { + Ok(result) => { + if result.status.success() { + return; + } + println!( + "cargo::error=Shader compilation failed for {}:\n{}", + entry_point, + String::from_utf8_lossy(&result.stderr) + ); + process::exit(1); + } + Err(e) => { + println!("cargo::error=Failed to run fxc for {}: {}", entry_point, e); + process::exit(1); + } + } + } + + fn generate_rust_binding(const_name: &str, head_file: &str, output_path: &str) { + let header_content = fs::read_to_string(head_file).expect("Failed to read header file"); + let const_definition = { + let global_var_start = header_content.find("const BYTE").unwrap(); + let global_var = &header_content[global_var_start..]; + let equal = global_var.find('=').unwrap(); + global_var[equal + 1..].trim() + }; + let rust_binding = format!( + "const {}: &[u8] = &{}\n", + const_name, + const_definition.replace('{', "[").replace('}', "]") + ); + let mut options = fs::OpenOptions::new() + .create(true) + .append(true) + .open(output_path) + .expect("Failed to open Rust binding file"); + options + .write_all(rust_binding.as_bytes()) + .expect("Failed to write Rust binding file"); + } +} + +#[cfg(all(target_os = "windows", not(debug_assertions)))] +use shader_compilation::compile_shaders; diff --git a/vendor/gpui-pre-windows/src/alpha_correction.hlsl b/vendor/gpui-pre-windows/src/alpha_correction.hlsl new file mode 100644 index 00000000..5a34a4eb --- /dev/null +++ b/vendor/gpui-pre-windows/src/alpha_correction.hlsl @@ -0,0 +1,49 @@ +// Adapted from https://github.com/microsoft/terminal/blob/1283c0f5b99a2961673249fa77c6b986efb5086c/src/renderer/atlas/dwrite.hlsl +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +float color_brightness(float3 color) { + // REC. 601 luminance coefficients for perceived brightness + return dot(color, float3(0.30f, 0.59f, 0.11f)); +} + +float light_on_dark_contrast(float enhancedContrast, float3 color) { + float brightness = color_brightness(color); + float multiplier = saturate(4.0f * (0.75f - brightness)); + return enhancedContrast * multiplier; +} + +float enhance_contrast(float alpha, float k) { + return alpha * (k + 1.0f) / (alpha * k + 1.0f); +} + +float3 enhance_contrast3(float3 alpha, float k) { + return alpha * (k + 1.0f) / (alpha * k + 1.0f); +} + +float apply_alpha_correction(float a, float b, float4 g) { + float brightness_adjustment = g.x * b + g.y; + float correction = brightness_adjustment * a + (g.z * b + g.w); + return a + a * (1.0f - a) * correction; +} + +float3 apply_alpha_correction3(float3 a, float3 b, float4 g) { + float3 brightness_adjustment = g.x * b + g.y; + float3 correction = brightness_adjustment * a + (g.z * b + g.w); + return a + a * (1.0f - a) * correction; +} + +float apply_contrast_and_gamma_correction(float sample, float3 color, float enhanced_contrast_factor, float4 gamma_ratios) { + float enhanced_contrast = light_on_dark_contrast(enhanced_contrast_factor, color); + float brightness = color_brightness(color); + + float contrasted = enhance_contrast(sample, enhanced_contrast); + return apply_alpha_correction(contrasted, brightness, gamma_ratios); +} + +float3 apply_contrast_and_gamma_correction3(float3 sample, float3 color, float enhanced_contrast_factor, float4 gamma_ratios) { + float enhanced_contrast = light_on_dark_contrast(enhanced_contrast_factor, color); + + float3 contrasted = enhance_contrast3(sample, enhanced_contrast); + return apply_alpha_correction3(contrasted, color, gamma_ratios); +} diff --git a/vendor/gpui-pre-windows/src/clipboard.rs b/vendor/gpui-pre-windows/src/clipboard.rs new file mode 100644 index 00000000..11eb2a81 --- /dev/null +++ b/vendor/gpui-pre-windows/src/clipboard.rs @@ -0,0 +1,394 @@ +use std::{borrow::Cow, sync::LazyLock}; + +use anyhow::Result; +use collections::FxHashMap; +use itertools::Itertools; +use windows::Win32::{ + Foundation::{HANDLE, HGLOBAL}, + System::{ + DataExchange::{ + CloseClipboard, CountClipboardFormats, EmptyClipboard, EnumClipboardFormats, + GetClipboardData, GetClipboardFormatNameW, OpenClipboard, RegisterClipboardFormatW, + SetClipboardData, + }, + Memory::{GMEM_MOVEABLE, GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock}, + Ole::{CF_DIB, CF_HDROP, CF_UNICODETEXT}, + }, + UI::Shell::{DragQueryFileW, HDROP}, +}; +use windows::core::{Owned, PCWSTR}; + +use gpui::{ + ClipboardEntry, ClipboardItem, ClipboardString, ExternalPaths, Image, ImageFormat, hash, +}; + +const DRAGDROP_GET_FILES_COUNT: u32 = 0xFFFFFFFF; + +static CLIPBOARD_HASH_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("GPUI internal text hash"))); +static CLIPBOARD_METADATA_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("GPUI internal metadata"))); +static CLIPBOARD_SVG_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("image/svg+xml"))); +static CLIPBOARD_GIF_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("GIF"))); +static CLIPBOARD_PNG_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("PNG"))); +static CLIPBOARD_JPG_FORMAT: LazyLock = + LazyLock::new(|| register_clipboard_format(windows::core::w!("JFIF"))); + +static IMAGE_FORMATS_MAP: LazyLock> = LazyLock::new(|| { + let mut map = FxHashMap::default(); + map.insert(*CLIPBOARD_PNG_FORMAT, ImageFormat::Png); + map.insert(*CLIPBOARD_GIF_FORMAT, ImageFormat::Gif); + map.insert(*CLIPBOARD_JPG_FORMAT, ImageFormat::Jpeg); + map.insert(*CLIPBOARD_SVG_FORMAT, ImageFormat::Svg); + map +}); + +fn register_clipboard_format(format: PCWSTR) -> u32 { + let ret = unsafe { RegisterClipboardFormatW(format) }; + if ret == 0 { + panic!( + "Error when registering clipboard format: {}", + std::io::Error::last_os_error() + ); + } + log::debug!( + "Registered clipboard format {} as {}", + unsafe { format.display() }, + ret + ); + ret +} + +fn get_clipboard_data(format: u32) -> Option { + let global = HGLOBAL(unsafe { GetClipboardData(format).ok() }?.0); + LockedGlobal::lock(global) +} + +pub(crate) fn write_to_clipboard(item: ClipboardItem) { + let Some(_clip) = ClipboardGuard::open() else { + return; + }; + + let result: Result<()> = (|| { + unsafe { EmptyClipboard()? }; + for entry in item.entries() { + match entry { + ClipboardEntry::String(string) => write_string(string)?, + ClipboardEntry::Image(image) => write_image(image)?, + ClipboardEntry::ExternalPaths(_) => {} + } + } + Ok(()) + })(); + + if let Err(e) = result { + log::error!("Failed to write to clipboard: {e}"); + } +} + +pub(crate) fn read_from_clipboard() -> Option { + let _clip = ClipboardGuard::open()?; + + let mut entries = Vec::new(); + let mut have_text = false; + let mut have_image = false; + let mut have_files = false; + + let count = unsafe { CountClipboardFormats() }; + let mut format = 0; + for _ in 0..count { + format = unsafe { EnumClipboardFormats(format) }; + + if !have_text && format == CF_UNICODETEXT.0 as u32 { + if let Some(entry) = read_string() { + entries.push(entry); + have_text = true; + } + } else if !have_image && is_image_format(format) { + if let Some(entry) = read_image(format) { + entries.push(entry); + have_image = true; + } + } else if !have_files && format == CF_HDROP.0 as u32 { + if let Some(entry) = read_files() { + entries.push(entry); + have_files = true; + } + } + } + + if entries.is_empty() { + log_unsupported_clipboard_formats(); + return None; + } + Some(ClipboardItem { entries }) +} + +pub(crate) fn with_file_names(hdrop: HDROP, mut f: F) +where + F: FnMut(String), +{ + let file_count = unsafe { DragQueryFileW(hdrop, DRAGDROP_GET_FILES_COUNT, None) }; + for file_index in 0..file_count { + let filename_length = unsafe { DragQueryFileW(hdrop, file_index, None) } as usize; + let mut buffer = vec![0u16; filename_length + 1]; + let ret = unsafe { DragQueryFileW(hdrop, file_index, Some(buffer.as_mut_slice())) }; + if ret == 0 { + log::error!("unable to read file name of dragged file"); + continue; + } + match String::from_utf16(&buffer[0..filename_length]) { + Ok(file_name) => f(file_name), + Err(e) => log::error!("dragged file name is not UTF-16: {}", e), + } + } +} + +fn set_clipboard_bytes(data: &[T], format: u32) -> Result<()> { + unsafe { + let global = Owned::new(GlobalAlloc(GMEM_MOVEABLE, std::mem::size_of_val(data))?); + let ptr = GlobalLock(*global); + anyhow::ensure!(!ptr.is_null(), "GlobalLock returned null"); + std::ptr::copy_nonoverlapping(data.as_ptr(), ptr as _, data.len()); + GlobalUnlock(*global).ok(); + SetClipboardData(format, Some(HANDLE(global.0)))?; + // SetClipboardData succeeded — the system now owns the memory. + std::mem::forget(global); + } + Ok(()) +} + +fn get_clipboard_string(format: u32) -> Option { + let locked = get_clipboard_data(format)?; + let bytes = locked.as_bytes(); + let words_len = bytes.len() / std::mem::size_of::(); + if words_len == 0 { + return Some(String::new()); + } + let slice = unsafe { std::slice::from_raw_parts(bytes.as_ptr() as *const u16, words_len) }; + let actual_len = slice.iter().position(|&c| c == 0).unwrap_or(words_len); + Some(String::from_utf16_lossy(&slice[..actual_len])) +} + +fn is_image_format(format: u32) -> bool { + IMAGE_FORMATS_MAP.contains_key(&format) || format == CF_DIB.0 as u32 +} + +fn write_string(item: &ClipboardString) -> Result<()> { + // CF_UNICODETEXT is null-terminated, so replace embedded NUL characters with spaces. + let text = if item.text.contains('\0') { + Cow::Owned(item.text.replace('\0', " ")) + } else { + Cow::Borrowed(item.text.as_str()) + }; + let wide: Vec = text.encode_utf16().chain(Some(0)).collect_vec(); + set_clipboard_bytes(&wide, CF_UNICODETEXT.0 as u32)?; + + if let Some(metadata) = item.metadata.as_ref() { + let hash_bytes = ClipboardString::text_hash(&text).to_ne_bytes(); + set_clipboard_bytes(&hash_bytes, *CLIPBOARD_HASH_FORMAT)?; + + let wide: Vec = metadata.encode_utf16().chain(Some(0)).collect_vec(); + set_clipboard_bytes(&wide, *CLIPBOARD_METADATA_FORMAT)?; + } + Ok(()) +} + +fn write_image(item: &Image) -> Result<()> { + let native_format = match item.format { + ImageFormat::Svg => Some(*CLIPBOARD_SVG_FORMAT), + ImageFormat::Gif => Some(*CLIPBOARD_GIF_FORMAT), + ImageFormat::Png => Some(*CLIPBOARD_PNG_FORMAT), + ImageFormat::Jpeg => Some(*CLIPBOARD_JPG_FORMAT), + _ => None, + }; + if let Some(format) = native_format { + set_clipboard_bytes(item.bytes(), format)?; + } + + // Also provide a PNG copy for broad compatibility. + // SVG can't be rasterized by the image crate, so skip it. + if item.format != ImageFormat::Svg && native_format != Some(*CLIPBOARD_PNG_FORMAT) { + if let Some(png_bytes) = convert_to_png(item.bytes(), item.format) { + set_clipboard_bytes(&png_bytes, *CLIPBOARD_PNG_FORMAT)?; + } + } + Ok(()) +} + +fn convert_to_png(bytes: &[u8], format: ImageFormat) -> Option> { + let img_format = gpui_to_image_format(format)?; + let image = image::load_from_memory_with_format(bytes, img_format) + .map_err(|e| log::warn!("Failed to decode image for PNG conversion: {e}")) + .ok()?; + let mut buf = Vec::new(); + image + .write_to(&mut std::io::Cursor::new(&mut buf), image::ImageFormat::Png) + .map_err(|e| log::warn!("Failed to encode PNG: {e}")) + .ok()?; + Some(buf) +} + +fn read_string() -> Option { + let text = get_clipboard_string(CF_UNICODETEXT.0 as u32)?; + let metadata = read_clipboard_metadata(&text); + Some(ClipboardEntry::String(ClipboardString { text, metadata })) +} + +fn read_clipboard_metadata(text: &str) -> Option { + let locked = get_clipboard_data(*CLIPBOARD_HASH_FORMAT)?; + let hash_bytes: [u8; 8] = locked.as_bytes().get(..8)?.try_into().ok()?; + let hash = u64::from_ne_bytes(hash_bytes); + if hash != ClipboardString::text_hash(text) { + return None; + } + get_clipboard_string(*CLIPBOARD_METADATA_FORMAT) +} + +fn read_image(format: u32) -> Option { + let locked = get_clipboard_data(format)?; + let (bytes, image_format) = if format == CF_DIB.0 as u32 { + (convert_dib_to_bmp(locked.as_bytes())?, ImageFormat::Bmp) + } else { + let image_format = *IMAGE_FORMATS_MAP.get(&format)?; + (locked.as_bytes().to_vec(), image_format) + }; + let id = hash(&bytes); + Some(ClipboardEntry::Image(Image { + format: image_format, + bytes, + id, + })) +} + +fn read_files() -> Option { + let locked = get_clipboard_data(CF_HDROP.0 as u32)?; + let hdrop = HDROP(locked.ptr as *mut _); + let mut filenames = Vec::new(); + with_file_names(hdrop, |name| filenames.push(std::path::PathBuf::from(name))); + Some(ClipboardEntry::ExternalPaths(ExternalPaths( + filenames.into(), + ))) +} + +/// DIB is BMP without the 14-byte BITMAPFILEHEADER. Prepend one. +fn convert_dib_to_bmp(dib: &[u8]) -> Option> { + if dib.len() < 40 { + return None; + } + + let header_size = u32::from_le_bytes(dib[0..4].try_into().ok()?); + let bit_count = u16::from_le_bytes(dib[14..16].try_into().ok()?); + let compression = u32::from_le_bytes(dib[16..20].try_into().ok()?); + + let color_table_size = if bit_count <= 8 { + let colors_used = u32::from_le_bytes(dib[32..36].try_into().ok()?); + (if colors_used == 0 { + 1u32 << bit_count + } else { + colors_used + }) * 4 + } else if compression == 3 { + 12 // BI_BITFIELDS + } else { + 0 + }; + + let pixel_offset = 14 + header_size + color_table_size; + let file_size = 14 + dib.len() as u32; + + let mut bmp = Vec::with_capacity(file_size as usize); + bmp.extend_from_slice(b"BM"); + bmp.extend_from_slice(&file_size.to_le_bytes()); + bmp.extend_from_slice(&[0u8; 4]); // reserved + bmp.extend_from_slice(&pixel_offset.to_le_bytes()); + bmp.extend_from_slice(dib); + Some(bmp) +} + +fn log_unsupported_clipboard_formats() { + let count = unsafe { CountClipboardFormats() }; + let mut format = 0; + for _ in 0..count { + format = unsafe { EnumClipboardFormats(format) }; + let mut buffer = [0u16; 64]; + unsafe { GetClipboardFormatNameW(format, &mut buffer) }; + let format_name = String::from_utf16_lossy(&buffer); + log::warn!( + "Try to paste with unsupported clipboard format: {}, {}.", + format, + format_name + ); + } +} + +fn gpui_to_image_format(value: ImageFormat) -> Option { + match value { + ImageFormat::Png => Some(image::ImageFormat::Png), + ImageFormat::Jpeg => Some(image::ImageFormat::Jpeg), + ImageFormat::Webp => Some(image::ImageFormat::WebP), + ImageFormat::Gif => Some(image::ImageFormat::Gif), + ImageFormat::Bmp => Some(image::ImageFormat::Bmp), + ImageFormat::Tiff => Some(image::ImageFormat::Tiff), + other => { + log::warn!("No image crate equivalent for format: {other:?}"); + None + } + } +} + +struct ClipboardGuard; + +impl ClipboardGuard { + fn open() -> Option { + match unsafe { OpenClipboard(None) } { + Ok(()) => Some(Self), + Err(e) => { + log::error!("Failed to open clipboard: {e}"); + None + } + } + } +} + +impl Drop for ClipboardGuard { + fn drop(&mut self) { + if let Err(e) = unsafe { CloseClipboard() } { + log::error!("Failed to close clipboard: {e}"); + } + } +} + +struct LockedGlobal { + global: HGLOBAL, + ptr: *const u8, + size: usize, +} + +impl LockedGlobal { + fn lock(global: HGLOBAL) -> Option { + let size = unsafe { GlobalSize(global) }; + let ptr = unsafe { GlobalLock(global) }; + if ptr.is_null() { + return None; + } + Some(Self { + global, + ptr: ptr as *const u8, + size, + }) + } + + fn as_bytes(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.ptr, self.size) } + } +} + +impl Drop for LockedGlobal { + fn drop(&mut self) { + unsafe { GlobalUnlock(self.global).ok() }; + } +} diff --git a/vendor/gpui-pre-windows/src/color_text_raster.hlsl b/vendor/gpui-pre-windows/src/color_text_raster.hlsl new file mode 100644 index 00000000..2fbc156b --- /dev/null +++ b/vendor/gpui-pre-windows/src/color_text_raster.hlsl @@ -0,0 +1,44 @@ +#include "alpha_correction.hlsl" + +struct RasterVertexOutput { + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +RasterVertexOutput emoji_rasterization_vertex(uint vertexID : SV_VERTEXID) +{ + RasterVertexOutput output; + output.texcoord = float2((vertexID << 1) & 2, vertexID & 2); + output.position = float4(output.texcoord * 2.0f - 1.0f, 0.0f, 1.0f); + output.position.y = -output.position.y; + + return output; +} + +struct PixelInput { + float4 position: SV_Position; + float2 texcoord : TEXCOORD0; +}; + +struct Bounds { + int2 origin; + int2 size; +}; + +Texture2D t_layer : register(t0); +SamplerState s_layer : register(s0); + +cbuffer GlyphLayerTextureParams : register(b0) { + Bounds bounds; + float4 run_color; + float4 gamma_ratios; + float grayscale_enhanced_contrast; + float3 _pad; +}; + +float4 emoji_rasterization_fragment(PixelInput input): SV_Target { + float sample = t_layer.Sample(s_layer, input.texcoord.xy).r; + float alpha_corrected = apply_contrast_and_gamma_correction(sample, run_color.rgb, grayscale_enhanced_contrast, gamma_ratios); + float alpha = alpha_corrected * run_color.a; + return float4(run_color.rgb * alpha, alpha); +} diff --git a/vendor/gpui-pre-windows/src/destination_list.rs b/vendor/gpui-pre-windows/src/destination_list.rs new file mode 100644 index 00000000..d6967c01 --- /dev/null +++ b/vendor/gpui-pre-windows/src/destination_list.rs @@ -0,0 +1,207 @@ +use std::{path::PathBuf, sync::Arc}; + +use itertools::Itertools; +use smallvec::SmallVec; +use windows::{ + Win32::{ + Foundation::PROPERTYKEY, + Globalization::u_strlen, + System::Com::{CLSCTX_INPROC_SERVER, CoCreateInstance, StructuredStorage::PROPVARIANT}, + UI::{ + Controls::INFOTIPSIZE, + Shell::{ + Common::{IObjectArray, IObjectCollection}, + DestinationList, EnumerableObjectCollection, ICustomDestinationList, IShellLinkW, + PropertiesSystem::IPropertyStore, + ShellLink, + }, + }, + }, + core::{GUID, HSTRING, Interface}, +}; + +use gpui::{Action, MenuItem, SharedString}; + +pub(crate) struct JumpList { + pub(crate) dock_menus: Vec, + pub(crate) recent_workspaces: Arc<[SmallVec<[PathBuf; 2]>]>, +} + +impl JumpList { + pub(crate) fn new() -> Self { + Self { + dock_menus: Vec::default(), + recent_workspaces: Arc::default(), + } + } +} + +pub(crate) struct DockMenuItem { + pub(crate) name: SharedString, + pub(crate) description: SharedString, + pub(crate) action: Box, +} + +impl DockMenuItem { + pub(crate) fn new(item: MenuItem) -> anyhow::Result { + match item { + MenuItem::Action { name, action, .. } => Ok(Self { + name: name.clone(), + description: if name == "New Window" { + "Opens a new window".into() + } else { + name + }, + action, + }), + _ => anyhow::bail!("Only `MenuItem::Action` is supported for dock menu on Windows."), + } + } +} + +// This code is based on the example from Microsoft: +// https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appshellintegration/RecipePropertyHandler/RecipePropertyHandler.cpp +pub(crate) fn update_jump_list( + recent_workspaces: &[SmallVec<[PathBuf; 2]>], + dock_menus: &[(SharedString, SharedString)], +) -> anyhow::Result>> { + let (list, removed) = create_destination_list()?; + add_recent_folders(&list, recent_workspaces, removed.as_ref())?; + add_dock_menu(&list, dock_menus)?; + unsafe { list.CommitList() }?; + Ok(removed) +} + +// Copied from: +// https://github.com/microsoft/windows-rs/blob/0fc3c2e5a13d4316d242bdeb0a52af611eba8bd4/crates/libs/windows/src/Windows/Win32/Storage/EnhancedStorage/mod.rs#L1881 +const PKEY_TITLE: PROPERTYKEY = PROPERTYKEY { + fmtid: GUID::from_u128(0xf29f85e0_4ff9_1068_ab91_08002b27b3d9), + pid: 2, +}; + +fn create_destination_list() -> anyhow::Result<(ICustomDestinationList, Vec>)> +{ + let list: ICustomDestinationList = + unsafe { CoCreateInstance(&DestinationList, None, CLSCTX_INPROC_SERVER) }?; + + let mut slots = 0; + let user_removed: IObjectArray = unsafe { list.BeginList(&mut slots) }?; + + let count = unsafe { user_removed.GetCount() }?; + if count == 0 { + return Ok((list, Vec::new())); + } + + let mut removed = Vec::with_capacity(count as usize); + for i in 0..count { + let shell_link: IShellLinkW = unsafe { user_removed.GetAt(i)? }; + let description = { + // INFOTIPSIZE is the maximum size of the buffer + // see https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishelllinkw-getdescription + let mut buffer = [0u16; INFOTIPSIZE as usize]; + unsafe { shell_link.GetDescription(&mut buffer)? }; + let len = unsafe { u_strlen(buffer.as_ptr()) }; + String::from_utf16_lossy(&buffer[..len as usize]) + }; + let args = description.split('\n').map(PathBuf::from).collect(); + + removed.push(args); + } + + Ok((list, removed)) +} + +fn add_dock_menu( + list: &ICustomDestinationList, + dock_menus: &[(SharedString, SharedString)], +) -> anyhow::Result<()> { + unsafe { + let tasks: IObjectCollection = + CoCreateInstance(&EnumerableObjectCollection, None, CLSCTX_INPROC_SERVER)?; + for (idx, (name, description)) in dock_menus.iter().enumerate() { + let argument = HSTRING::from(format!("--dock-action {}", idx)); + let description = HSTRING::from(description.as_str()); + let display = name.as_str(); + let task = create_shell_link(argument, description, None, display)?; + tasks.AddObject(&task)?; + } + list.AddUserTasks(&tasks)?; + Ok(()) + } +} + +fn add_recent_folders( + list: &ICustomDestinationList, + entries: &[SmallVec<[PathBuf; 2]>], + removed: &Vec>, +) -> anyhow::Result<()> { + unsafe { + let tasks: IObjectCollection = + CoCreateInstance(&EnumerableObjectCollection, None, CLSCTX_INPROC_SERVER)?; + + for folder_path in entries.iter().filter(|path| !removed.contains(path)) { + let argument = HSTRING::from( + folder_path + .iter() + .map(|path| format!("\"{}\"", path.display())) + .join(" "), + ); + + let description = HSTRING::from( + folder_path + .iter() + .map(|path| path.to_string_lossy()) + .collect::>() + .join("\n"), + ); + // simulate folder icon + // https://github.com/microsoft/vscode/blob/7a5dc239516a8953105da34f84bae152421a8886/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts#L380 + let icon = HSTRING::from("explorer.exe"); + + let display = folder_path + .iter() + .map(|p| { + p.file_name() + .map(|name| name.to_string_lossy()) + .unwrap_or_else(|| p.to_string_lossy()) + }) + .join(", "); + + tasks.AddObject(&create_shell_link( + argument, + description, + Some(icon), + &display, + )?)?; + } + + if tasks.GetCount().unwrap_or(0) > 0 { + list.AppendCategory(&HSTRING::from("Recent Folders"), &tasks)?; + } + Ok(()) + } +} + +fn create_shell_link( + argument: HSTRING, + description: HSTRING, + icon: Option, + display: &str, +) -> anyhow::Result { + unsafe { + let link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)?; + let exe_path = HSTRING::from(std::env::current_exe()?.as_os_str()); + link.SetPath(&exe_path)?; + link.SetArguments(&argument)?; + link.SetDescription(&description)?; + if let Some(icon) = icon { + link.SetIconLocation(&icon, 0)?; + } + let store: IPropertyStore = link.cast()?; + let title = PROPVARIANT::from(display); + store.SetValue(&PKEY_TITLE, &title)?; + store.Commit()?; + + Ok(link) + } +} diff --git a/vendor/gpui-pre-windows/src/dialog.rs b/vendor/gpui-pre-windows/src/dialog.rs new file mode 100644 index 00000000..16866cfc --- /dev/null +++ b/vendor/gpui-pre-windows/src/dialog.rs @@ -0,0 +1,340 @@ +use std::{ + cell::RefCell, + rc::Rc, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, +}; + +use anyhow::{Context as _, Result, anyhow}; +use futures::{ + channel::oneshot, + future::{Either, select}, + lock::Mutex, +}; +use gpui::ForegroundExecutor; +use gpui_util::ResultExt; +use windows::{ + Win32::{ + Foundation::*, + System::{Com::*, Threading::GetCurrentThreadId}, + UI::{ + Controls::{TASKDIALOG_NOTIFICATIONS, TDN_BUTTON_CLICKED}, + WindowsAndMessaging::*, + }, + }, + core::{BOOL, HRESULT, w}, +}; + +use crate::SafeHwnd; + +pub(crate) struct DialogOwner { + hwnd: HWND, + closed: Arc, + serialization: Mutex<()>, +} + +impl DialogOwner { + pub(crate) fn new(hwnd: HWND) -> Rc { + Rc::new(Self { + hwnd, + closed: Arc::new(AtomicBool::new(false)), + serialization: Mutex::new(()), + }) + } + + pub(crate) fn close(&self) { + self.closed.store(true, Ordering::Release); + } + + pub(crate) async fn when_idle(&self) { + // After close(), queued requests cannot start a native dialog. Only the + // active dialog can still use the HWND, and it holds this lock until exit. + let _guard = self.serialization.lock().await; + } +} + +#[derive(Clone, Default)] +struct Cancellation { + requested: Arc, + owner_closed: Option>, +} + +impl Cancellation { + fn new(owner: Option<&DialogOwner>) -> Self { + Self { + owner_closed: owner.map(|owner| owner.closed.clone()), + ..Self::default() + } + } + + fn is_requested(&self) -> bool { + self.requested.load(Ordering::Acquire) + || self + .owner_closed + .as_ref() + .is_some_and(|closed| closed.load(Ordering::Acquire)) + } +} + +/// Native modal loops may synchronously message their owner, so the foreground +/// thread must keep pumping messages rather than waiting for the dialog thread. +/// Holding the owner's lock through native completion also allows window +/// destruction to wait for the dialog without blocking the foreground thread. +pub(crate) fn show_dialog( + owner: Option>, + executor: &ForegroundExecutor, + dialog: impl FnOnce(HWND) -> Result + Send + 'static, +) -> oneshot::Receiver> { + let (mut sender, receiver) = oneshot::channel(); + let cancellation = Cancellation::new(owner.as_deref()); + if cancellation.is_requested() { + sender.send(Err(anyhow!("dialog owner has closed"))).ok(); + return receiver; + } + let hwnd = owner.as_ref().map(|owner| SafeHwnd::from(owner.hwnd)); + executor + .spawn(async move { + // Let Windows manage enabling and activating the owner. Overlapping + // modal loops could otherwise re-enable it while another dialog is open. + let serialization = if let Some(owner) = owner.as_ref() { + match select(owner.serialization.lock(), sender.cancellation()).await { + Either::Left((guard, _)) => Some(guard), + Either::Right(((), _)) => return, + } + } else { + None + }; + if sender.is_canceled() || cancellation.is_requested() { + return; + } + let (result_sender, mut result_receiver) = oneshot::channel(); + let thread = std::thread::Builder::new() + .name("windows-native-dialog".into()) + .spawn({ + let cancellation = cancellation.clone(); + move || { + let result = (|| { + let _apartment = Apartment::new()?; + let _timer = CancellationTimer::new(cancellation.clone())?; + if cancellation.is_requested() { + return Err(anyhow!("dialog cancelled")); + } + let result = dialog(hwnd.map(|hwnd| hwnd.as_raw()).unwrap_or_default()); + if cancellation.is_requested() { + return Err(anyhow!("dialog cancelled")); + } + result + })(); + result_sender.send(result).ok(); + } + }); + if let Err(error) = thread { + drop(serialization); + sender.send(Err(error.into())).ok(); + return; + } + let result = match select(&mut result_receiver, sender.cancellation()).await { + Either::Left((result, _)) => result, + Either::Right(((), _)) => { + cancellation.requested.store(true, Ordering::Release); + result_receiver.await + } + }; + // Neither launch another dialog nor destroy the owner until the + // native loop exits, even if the caller no longer wants its result. + drop(serialization); + sender + .send(result.unwrap_or_else(|error| Err(error.into()))) + .ok(); + }) + .detach(); + receiver +} + +struct Apartment; + +impl Apartment { + fn new() -> Result { + unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED).ok()? }; + Ok(Self) + } +} + +impl Drop for Apartment { + fn drop(&mut self) { + unsafe { CoUninitialize() }; + } +} + +thread_local! { + static CANCELLATION: RefCell> = const { RefCell::new(None) }; +} + +struct CancellationTimer(usize); + +impl CancellationTimer { + fn new(cancellation: Cancellation) -> Result { + let timer = unsafe { SetTimer(None, 0, 100, Some(cancel_dialog)) }; + if timer == 0 { + return Err(windows::core::Error::from_thread()) + .context("starting native dialog cancellation timer"); + } + CANCELLATION.with(|slot| slot.replace(Some(cancellation))); + Ok(Self(timer)) + } +} + +impl Drop for CancellationTimer { + fn drop(&mut self) { + CANCELLATION.with(|slot| slot.take()); + unsafe { KillTimer(None, self.0).log_err() }; + } +} + +unsafe extern "system" fn cancel_dialog(_: HWND, _: u32, _: usize, _: u32) { + if cancellation_requested() { + unsafe { + EnumThreadWindows(GetCurrentThreadId(), Some(close_dialog), LPARAM(0)) + .ok() + .log_err(); + }; + } +} + +fn cancellation_requested() -> bool { + CANCELLATION.with(|slot| { + slot.borrow() + .as_ref() + .is_some_and(Cancellation::is_requested) + }) +} + +pub(crate) unsafe extern "system" fn task_dialog_callback( + _: HWND, + notification: TASKDIALOG_NOTIFICATIONS, + button: WPARAM, + _: LPARAM, + has_cancel_button: isize, +) -> HRESULT { + // WM_CLOSE requires TDF_ALLOW_DIALOG_CANCELLATION, which also enables Esc/X. + // Only allow those user gestures when the prompt offered a Cancel button. + if notification == TDN_BUTTON_CLICKED + && button.0 == IDCANCEL.0 as usize + && has_cancel_button == 0 + && !cancellation_requested() + { + S_FALSE + } else { + S_OK + } +} + +unsafe extern "system" fn close_dialog(hwnd: HWND, _: LPARAM) -> BOOL { + // Shell dialogs can open further modal dialogs. Close only dialog windows + // on this dedicated thread, not hidden COM infrastructure windows. + let mut class_name = [0u16; 32]; + let length = unsafe { GetClassNameW(hwnd, &mut class_name) } as usize; + let dialog_class = w!("#32770"); + if class_name.get(..length) == Some(unsafe { dialog_class.as_wide() }) { + unsafe { PostMessageW(Some(hwnd), WM_CLOSE, WPARAM(0), LPARAM(0)).log_err() }; + } + TRUE +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::FutureExt as _; + + #[test] + fn task_dialog_cancellation_requires_cancel_button_or_internal_request() { + let cancellation = Cancellation::default(); + CANCELLATION.with(|slot| slot.replace(Some(cancellation.clone()))); + for internally_cancelled in [false, true] { + cancellation + .requested + .store(internally_cancelled, Ordering::Release); + for has_cancel_button in [false, true] { + for button in [IDCANCEL.0, IDOK.0, -1] { + let result = unsafe { + task_dialog_callback( + HWND::default(), + TDN_BUTTON_CLICKED, + WPARAM(button as usize), + LPARAM(0), + has_cancel_button as isize, + ) + }; + let should_veto = + button == IDCANCEL.0 && !has_cancel_button && !internally_cancelled; + assert_eq!(result, if should_veto { S_FALSE } else { S_OK }); + } + } + } + CANCELLATION.with(|slot| slot.take()); + } + + #[test] + fn closing_owner_cancels_every_outstanding_dialog() { + let owner = DialogOwner::new(HWND::default()); + let first = Cancellation::new(Some(&owner)); + let second = Cancellation::new(Some(&owner)); + assert!(!first.is_requested()); + assert!(!second.is_requested()); + + owner.close(); + owner.close(); + + assert!(first.is_requested()); + assert!(second.is_requested()); + assert!(Cancellation::new(Some(&owner)).is_requested()); + } + + #[test] + fn closed_owner_waits_for_active_dialog_but_queued_requests_stay_cancelled() { + let owner = DialogOwner::new(HWND::default()); + let active = owner.serialization.try_lock().expect("first dialog"); + let queued = Cancellation::new(Some(&owner)); + + owner.close(); + assert!(owner.when_idle().now_or_never().is_none()); + drop(active); + assert!(owner.when_idle().now_or_never().is_some()); + + let _guard = owner.serialization.try_lock().expect("queued request"); + assert!(queued.is_requested()); + } + + #[test] + fn cancelling_one_request_does_not_cancel_its_owner_or_other_requests() { + let owner = DialogOwner::new(HWND::default()); + let first = Cancellation::new(Some(&owner)); + let second = Cancellation::new(Some(&owner)); + first.requested.store(true, Ordering::Release); + assert!(first.is_requested()); + assert!(!second.is_requested()); + assert!(!owner.closed.load(Ordering::Acquire)); + } + + #[test] + fn dialogs_serialize_per_owner() { + let owner = DialogOwner::new(HWND::default()); + let other_owner = DialogOwner::new(HWND::default()); + let guard = owner.serialization.try_lock().expect("first dialog"); + + assert!(owner.serialization.try_lock().is_none()); + assert!(other_owner.serialization.try_lock().is_some()); + drop(guard); + assert!(owner.serialization.try_lock().is_some()); + } + + #[test] + fn ownerless_request_can_be_cancelled_without_a_window() { + let cancellation = Cancellation::new(None); + assert!(!cancellation.is_requested()); + cancellation.requested.store(true, Ordering::Release); + assert!(cancellation.is_requested()); + } +} diff --git a/vendor/gpui-pre-windows/src/direct_manipulation.rs b/vendor/gpui-pre-windows/src/direct_manipulation.rs new file mode 100644 index 00000000..9adcbed3 --- /dev/null +++ b/vendor/gpui-pre-windows/src/direct_manipulation.rs @@ -0,0 +1,359 @@ +use std::cell::{Cell, RefCell}; +use std::rc::Rc; + +use anyhow::Result; +use gpui::*; +use gpui_util::ResultExt; +use windows::Win32::{ + Foundation::*, + Graphics::{DirectManipulation::*, Gdi::*}, + System::Com::*, + UI::{Input::Pointer::*, WindowsAndMessaging::*}, +}; + +use crate::*; + +/// Default viewport size in pixels. The actual content size doesn't matter +/// because we're using the viewport only for gesture recognition, not for +/// visual output. +const DEFAULT_VIEWPORT_SIZE: i32 = 1000; + +pub(crate) struct DirectManipulationHandler { + manager: IDirectManipulationManager, + update_manager: IDirectManipulationUpdateManager, + viewport: IDirectManipulationViewport, + _handler_cookie: u32, + window: HWND, + scale_factor: Rc>, + pending_events: Rc>>, +} + +impl DirectManipulationHandler { + pub fn new(window: HWND, scale_factor: f32) -> Result { + unsafe { + let manager: IDirectManipulationManager = + CoCreateInstance(&DirectManipulationManager, None, CLSCTX_INPROC_SERVER)?; + + let update_manager: IDirectManipulationUpdateManager = manager.GetUpdateManager()?; + + let viewport: IDirectManipulationViewport = manager.CreateViewport(None, window)?; + + let configuration = DIRECTMANIPULATION_CONFIGURATION_INTERACTION + | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X + | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y + | DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA + | DIRECTMANIPULATION_CONFIGURATION_RAILS_X + | DIRECTMANIPULATION_CONFIGURATION_RAILS_Y + | DIRECTMANIPULATION_CONFIGURATION_SCALING; + viewport.ActivateConfiguration(configuration)?; + + viewport.SetViewportOptions( + DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE + | DIRECTMANIPULATION_VIEWPORT_OPTIONS_DISABLEPIXELSNAPPING, + )?; + + let mut rect = RECT { + left: 0, + top: 0, + right: DEFAULT_VIEWPORT_SIZE, + bottom: DEFAULT_VIEWPORT_SIZE, + }; + viewport.SetViewportRect(&mut rect)?; + + manager.Activate(window)?; + viewport.Enable()?; + + let scale_factor = Rc::new(Cell::new(scale_factor)); + let pending_events = Rc::new(RefCell::new(Vec::new())); + + let event_handler: IDirectManipulationViewportEventHandler = + DirectManipulationEventHandler::new( + window, + Rc::clone(&scale_factor), + Rc::clone(&pending_events), + ) + .into(); + + let handler_cookie = viewport.AddEventHandler(Some(window), &event_handler)?; + + update_manager.Update(None)?; + + Ok(Self { + manager, + update_manager, + viewport, + _handler_cookie: handler_cookie, + window, + scale_factor, + pending_events, + }) + } + } + + pub fn set_scale_factor(&self, scale_factor: f32) { + self.scale_factor.set(scale_factor); + } + + pub fn on_pointer_hit_test(&self, wparam: WPARAM) { + unsafe { + let pointer_id = wparam.loword() as u32; + let mut pointer_type = POINTER_INPUT_TYPE::default(); + if GetPointerType(pointer_id, &mut pointer_type).is_ok() && pointer_type == PT_TOUCHPAD + { + self.viewport.SetContact(pointer_id).log_err(); + } + } + } + + pub fn update(&self) { + unsafe { + self.update_manager.Update(None).log_err(); + } + } + + pub fn drain_events(&self) -> Vec { + std::mem::take(&mut *self.pending_events.borrow_mut()) + } +} + +impl Drop for DirectManipulationHandler { + fn drop(&mut self) { + unsafe { + self.viewport.Stop().log_err(); + self.viewport.Abandon().log_err(); + self.manager.Deactivate(self.window).log_err(); + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum GestureKind { + None, + Scroll, + Pinch, +} + +#[windows_core::implement(IDirectManipulationViewportEventHandler)] +struct DirectManipulationEventHandler { + window: HWND, + scale_factor: Rc>, + gesture_kind: Cell, + last_scale: Cell, + last_x_offset: Cell, + last_y_offset: Cell, + scroll_phase: Cell, + pending_events: Rc>>, +} + +impl DirectManipulationEventHandler { + fn new( + window: HWND, + scale_factor: Rc>, + pending_events: Rc>>, + ) -> Self { + Self { + window, + scale_factor, + gesture_kind: Cell::new(GestureKind::None), + last_scale: Cell::new(1.0), + last_x_offset: Cell::new(0.0), + last_y_offset: Cell::new(0.0), + scroll_phase: Cell::new(TouchPhase::Started), + pending_events, + } + } + + fn end_gesture(&self) { + let position = self.mouse_position(); + let modifiers = current_modifiers(); + match self.gesture_kind.get() { + GestureKind::Scroll => { + self.pending_events + .borrow_mut() + .push(PlatformInput::ScrollWheel(ScrollWheelEvent { + position, + delta: ScrollDelta::Pixels(point(px(0.0), px(0.0))), + modifiers, + touch_phase: TouchPhase::Ended, + })); + } + GestureKind::Pinch => { + self.pending_events + .borrow_mut() + .push(PlatformInput::Pinch(PinchEvent { + position, + delta: 0.0, + modifiers, + phase: TouchPhase::Ended, + })); + } + GestureKind::None => {} + } + self.gesture_kind.set(GestureKind::None); + } + + fn mouse_position(&self) -> Point { + let scale_factor = self.scale_factor.get(); + unsafe { + let mut point: POINT = std::mem::zeroed(); + let _ = GetCursorPos(&mut point); + let _ = ScreenToClient(self.window, &mut point); + logical_point(point.x as f32, point.y as f32, scale_factor) + } + } +} + +impl IDirectManipulationViewportEventHandler_Impl for DirectManipulationEventHandler_Impl { + fn OnViewportStatusChanged( + &self, + viewport: windows_core::Ref<'_, IDirectManipulationViewport>, + current: DIRECTMANIPULATION_STATUS, + previous: DIRECTMANIPULATION_STATUS, + ) -> windows_core::Result<()> { + if current == previous { + return Ok(()); + } + + // A new gesture interrupted inertia, so end the old sequence. + if current == DIRECTMANIPULATION_RUNNING && previous == DIRECTMANIPULATION_INERTIA { + self.end_gesture(); + } + + if current == DIRECTMANIPULATION_READY { + self.end_gesture(); + + // Reset the content transform so the viewport is ready for the next gesture. + // ZoomToRect triggers a second RUNNING -> READY cycle, so prevent an infinite loop here. + if self.last_scale.get() != 1.0 + || self.last_x_offset.get() != 0.0 + || self.last_y_offset.get() != 0.0 + { + if let Some(viewport) = viewport.as_ref() { + unsafe { + viewport + .ZoomToRect( + 0.0, + 0.0, + DEFAULT_VIEWPORT_SIZE as f32, + DEFAULT_VIEWPORT_SIZE as f32, + false, + ) + .log_err(); + } + } + } + + self.last_scale.set(1.0); + self.last_x_offset.set(0.0); + self.last_y_offset.set(0.0); + } + + Ok(()) + } + + fn OnViewportUpdated( + &self, + _viewport: windows_core::Ref<'_, IDirectManipulationViewport>, + ) -> windows_core::Result<()> { + Ok(()) + } + + fn OnContentUpdated( + &self, + _viewport: windows_core::Ref<'_, IDirectManipulationViewport>, + content: windows_core::Ref<'_, IDirectManipulationContent>, + ) -> windows_core::Result<()> { + let content = content.as_ref().ok_or(E_POINTER)?; + + // Get the 6-element content transform: [scale, 0, 0, scale, tx, ty] + let mut xform = [0.0f32; 6]; + unsafe { + content.GetContentTransform(&mut xform)?; + } + + let scale = xform[0]; + let scale_factor = self.scale_factor.get(); + let x_offset = xform[4] / scale_factor; + let y_offset = xform[5] / scale_factor; + + if scale == 0.0 { + return Ok(()); + } + + let last_scale = self.last_scale.get(); + let last_x = self.last_x_offset.get(); + let last_y = self.last_y_offset.get(); + + if float_equals(scale, last_scale) + && float_equals(x_offset, last_x) + && float_equals(y_offset, last_y) + { + return Ok(()); + } + + let position = self.mouse_position(); + let modifiers = current_modifiers(); + + // Direct Manipulation reports both translation and scale in every content update. + // Translation values can shift during a pinch due to the zoom center shifting. + // We classify each gesture as either scroll or pinch and only emit one type of event. + // We allow Scroll -> Pinch (a pinch can start with a small pan) but not the reverse. + if !float_equals(scale, 1.0) { + if self.gesture_kind.get() != GestureKind::Pinch { + self.end_gesture(); + self.gesture_kind.set(GestureKind::Pinch); + self.pending_events + .borrow_mut() + .push(PlatformInput::Pinch(PinchEvent { + position, + delta: 0.0, + modifiers, + phase: TouchPhase::Started, + })); + } + } else if self.gesture_kind.get() == GestureKind::None { + self.gesture_kind.set(GestureKind::Scroll); + self.scroll_phase.set(TouchPhase::Started); + } + + match self.gesture_kind.get() { + GestureKind::Scroll => { + let dx = x_offset - last_x; + let dy = y_offset - last_y; + let touch_phase = self.scroll_phase.get(); + self.scroll_phase.set(TouchPhase::Moved); + self.pending_events + .borrow_mut() + .push(PlatformInput::ScrollWheel(ScrollWheelEvent { + position, + delta: ScrollDelta::Pixels(point(px(dx), px(dy))), + modifiers, + touch_phase, + })); + } + GestureKind::Pinch => { + let scale_delta = scale / last_scale; + self.pending_events + .borrow_mut() + .push(PlatformInput::Pinch(PinchEvent { + position, + delta: scale_delta - 1.0, + modifiers, + phase: TouchPhase::Moved, + })); + } + GestureKind::None => {} + } + + self.last_scale.set(scale); + self.last_x_offset.set(x_offset); + self.last_y_offset.set(y_offset); + + Ok(()) + } +} + +fn float_equals(f1: f32, f2: f32) -> bool { + const EPSILON_SCALE: f32 = 0.00001; + (f1 - f2).abs() < EPSILON_SCALE * f1.abs().max(f2.abs()).max(EPSILON_SCALE) +} diff --git a/vendor/gpui-pre-windows/src/direct_write.rs b/vendor/gpui-pre-windows/src/direct_write.rs new file mode 100644 index 00000000..e9cd022a --- /dev/null +++ b/vendor/gpui-pre-windows/src/direct_write.rs @@ -0,0 +1,2263 @@ +use std::{ + borrow::Cow, + ffi::{c_uint, c_void}, + mem::ManuallyDrop, +}; + +use anyhow::{Context, Result}; +use collections::HashMap; +use gpui_util::{ResultExt, maybe}; +use parking_lot::{RwLock, RwLockUpgradableReadGuard}; +use windows::{ + Win32::{ + Foundation::*, + Globalization::GetUserDefaultLocaleName, + Graphics::{ + Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, Direct3D11::*, DirectWrite::*, + Dxgi::Common::*, Gdi::LOGFONTW, + }, + System::SystemServices::LOCALE_NAME_MAX_LENGTH, + UI::WindowsAndMessaging::*, + }, + core::*, +}; +use windows_numerics::Vector2; + +use crate::*; +use gpui::*; + +#[derive(Debug)] +struct FontInfo { + font_family_h: HSTRING, + font_face: IDWriteFontFace3, + features: IDWriteTypography, + fallbacks: Option, + font_collection: IDWriteFontCollection1, +} + +pub(crate) struct DirectWriteTextSystem { + components: DirectWriteComponents, + state: RwLock, +} + +struct DirectWriteComponents { + locale: HSTRING, + factory: IDWriteFactory5, + in_memory_loader: IDWriteInMemoryFontFileLoader, + builder: IDWriteFontSetBuilder1, + text_renderer: TextRendererWrapper, + system_ui_font_name: SharedString, + system_subpixel_rendering: bool, +} + +impl Drop for DirectWriteComponents { + fn drop(&mut self) { + unsafe { + let _ = self + .factory + .UnregisterFontFileLoader(&self.in_memory_loader); + } + } +} + +struct GPUState { + device: ID3D11Device, + device_context: ID3D11DeviceContext, + sampler: Option, + blend_state: ID3D11BlendState, + vertex_shader: ID3D11VertexShader, + pixel_shader: ID3D11PixelShader, +} + +struct DirectWriteState { + /// Used to rasterize color glyphs. `None` while the platform is headless: shaping and + /// layout don't need a GPU, and nothing is drawn. + gpu_state: Option, + system_font_collection: IDWriteFontCollection1, + custom_font_collection: IDWriteFontCollection1, + fonts: Vec, + font_to_font_id: HashMap, + font_info_cache: HashMap, + layout_line_scratch: Vec, +} + +impl GPUState { + fn new(directx_devices: &DirectXDevices) -> Result { + let device = directx_devices.device.clone(); + let device_context = directx_devices.device_context.clone(); + + let blend_state = { + let mut blend_state = None; + let desc = D3D11_BLEND_DESC { + AlphaToCoverageEnable: false.into(), + IndependentBlendEnable: false.into(), + RenderTarget: [ + D3D11_RENDER_TARGET_BLEND_DESC { + BlendEnable: true.into(), + SrcBlend: D3D11_BLEND_ONE, + DestBlend: D3D11_BLEND_INV_SRC_ALPHA, + BlendOp: D3D11_BLEND_OP_ADD, + SrcBlendAlpha: D3D11_BLEND_ONE, + DestBlendAlpha: D3D11_BLEND_INV_SRC_ALPHA, + BlendOpAlpha: D3D11_BLEND_OP_ADD, + RenderTargetWriteMask: D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8, + }, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ], + }; + unsafe { device.CreateBlendState(&desc, Some(&mut blend_state)) }?; + blend_state.unwrap() + }; + + let sampler = { + let mut sampler = None; + let desc = D3D11_SAMPLER_DESC { + Filter: D3D11_FILTER_MIN_MAG_MIP_POINT, + AddressU: D3D11_TEXTURE_ADDRESS_BORDER, + AddressV: D3D11_TEXTURE_ADDRESS_BORDER, + AddressW: D3D11_TEXTURE_ADDRESS_BORDER, + MipLODBias: 0.0, + MaxAnisotropy: 1, + ComparisonFunc: D3D11_COMPARISON_ALWAYS, + BorderColor: [0.0, 0.0, 0.0, 0.0], + MinLOD: 0.0, + MaxLOD: 0.0, + }; + unsafe { device.CreateSamplerState(&desc, Some(&mut sampler)) }?; + sampler + }; + + let vertex_shader = { + let source = shader_resources::RawShaderBytes::new( + shader_resources::ShaderModule::EmojiRasterization, + shader_resources::ShaderTarget::Vertex, + )?; + let mut shader = None; + unsafe { device.CreateVertexShader(source.as_bytes(), None, Some(&mut shader)) }?; + shader.unwrap() + }; + + let pixel_shader = { + let source = shader_resources::RawShaderBytes::new( + shader_resources::ShaderModule::EmojiRasterization, + shader_resources::ShaderTarget::Fragment, + )?; + let mut shader = None; + unsafe { device.CreatePixelShader(source.as_bytes(), None, Some(&mut shader)) }?; + shader.unwrap() + }; + + Ok(Self { + device, + device_context, + sampler, + blend_state, + vertex_shader, + pixel_shader, + }) + } +} + +impl DirectWriteTextSystem { + /// Creates the text system, able to rasterize color glyphs once it has `directx_devices`. + pub(crate) fn new(directx_devices: Option<&DirectXDevices>) -> Result { + let factory: IDWriteFactory5 = unsafe { DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)? }; + // The `IDWriteInMemoryFontFileLoader` here is supported starting from + // Windows 10 Creators Update, which consequently requires the entire + // `DirectWriteTextSystem` to run on `win10 1703`+. + let in_memory_loader = unsafe { factory.CreateInMemoryFontFileLoader()? }; + unsafe { factory.RegisterFontFileLoader(&in_memory_loader)? }; + let builder = unsafe { factory.CreateFontSetBuilder()? }; + let mut locale = [0u16; LOCALE_NAME_MAX_LENGTH as usize]; + unsafe { GetUserDefaultLocaleName(&mut locale) }; + let locale = HSTRING::from_wide(&locale); + let text_renderer = TextRendererWrapper::new(locale.clone()); + + let gpu_state = directx_devices.map(GPUState::new).transpose()?; + + let system_subpixel_rendering = get_system_subpixel_rendering(); + let system_ui_font_name = get_system_ui_font_name(); + let components = DirectWriteComponents { + locale, + factory, + in_memory_loader, + builder, + text_renderer, + system_ui_font_name, + system_subpixel_rendering, + }; + + let system_font_collection = unsafe { + let mut result = None; + components + .factory + .GetSystemFontCollection(false, &mut result, true)?; + result.context("Failed to get system font collection")? + }; + let custom_font_set = unsafe { components.builder.CreateFontSet()? }; + let custom_font_collection = unsafe { + components + .factory + .CreateFontCollectionFromFontSet(&custom_font_set)? + }; + + Ok(Self { + components, + state: RwLock::new(DirectWriteState { + gpu_state, + system_font_collection, + custom_font_collection, + fonts: Vec::new(), + font_to_font_id: HashMap::default(), + font_info_cache: HashMap::default(), + layout_line_scratch: Vec::new(), + }), + }) + } + + /// Uses `directx_devices` to rasterize color glyphs, replacing any previous devices, for + /// example after the device was lost. + pub(crate) fn handle_gpu_lost(&self, directx_devices: &DirectXDevices) -> Result<()> { + self.state.write().handle_gpu_lost(directx_devices) + } + + /// Releases the GPU state, when the platform switches to headless mode. + pub(crate) fn release_gpu(&self) { + self.state.write().gpu_state = None; + } +} + +impl PlatformTextSystem for DirectWriteTextSystem { + fn add_fonts(&self, fonts: Vec>) -> Result<()> { + self.state.write().add_fonts(&self.components, fonts) + } + + fn all_font_names(&self) -> Vec { + self.state.read().all_font_names(&self.components) + } + + fn weights_for_family(&self, family: &str) -> Vec { + self.state.read().weights_for_family(&self.components, family) + } + + fn is_monospaced(&self, family: &str) -> bool { + self.state.read().is_monospaced(&self.components, family) + } + + fn font_id(&self, font: &Font) -> Result { + let lock = self.state.upgradable_read(); + if let Some(font_id) = lock.font_to_font_id.get(font) { + Ok(*font_id) + } else { + RwLockUpgradableReadGuard::upgrade(lock) + .select_and_cache_font(&self.components, font) + .with_context(|| format!("Failed to select font: {:?}", font)) + } + } + + fn font_metrics(&self, font_id: FontId) -> FontMetrics { + self.state.read().font_metrics(font_id) + } + + fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { + self.state.read().get_typographic_bounds(font_id, glyph_id) + } + + fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result> { + self.state.read().get_advance(font_id, glyph_id) + } + + fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { + self.state.read().glyph_for_char(font_id, ch) + } + + fn glyph_raster_bounds( + &self, + params: &RenderGlyphParams, + ) -> anyhow::Result> { + self.state.read().raster_bounds(&self.components, params) + } + + fn rasterize_glyph( + &self, + params: &RenderGlyphParams, + raster_bounds: Bounds, + ) -> anyhow::Result<(Size, Vec)> { + self.state + .read() + .rasterize_glyph(&self.components, params, raster_bounds) + } + + fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout { + self.state + .write() + .layout_line(&self.components, text, font_size, runs) + .log_err() + .unwrap_or(LineLayout { + font_size, + ..Default::default() + }) + } + + fn recommended_rendering_mode( + &self, + _font_id: FontId, + _font_size: Pixels, + ) -> TextRenderingMode { + if self.components.system_subpixel_rendering { + TextRenderingMode::Subpixel + } else { + TextRenderingMode::Grayscale + } + } +} + +impl DirectWriteState { + fn select_and_cache_font( + &mut self, + components: &DirectWriteComponents, + font: &Font, + ) -> Option { + let select_font = |this: &mut DirectWriteState, font: &Font| -> Option { + let info = [&this.custom_font_collection, &this.system_font_collection] + .into_iter() + .find_map(|font_collection| unsafe { + DirectWriteState::make_font_from_font_collection( + font, + font_collection, + &components.factory, + &this.system_font_collection, + &components.system_ui_font_name, + ) + })?; + + let font_id = FontId(this.fonts.len()); + let font_face_key = info.font_face.cast::().unwrap().as_raw().addr(); + this.fonts.push(info); + this.font_info_cache.insert(font_face_key, font_id); + Some(font_id) + }; + + let mut font_id = select_font(self, font); + if font_id.is_none() { + // try updating system fonts and reselect + let mut collection = None; + let font_collection_updated = unsafe { + components + .factory + .GetSystemFontCollection(false, &mut collection, true) + } + .log_err() + .is_some(); + if font_collection_updated && let Some(collection) = collection { + self.system_font_collection = collection; + } + font_id = select_font(self, font); + }; + let font_id = font_id?; + self.font_to_font_id.insert(font.clone(), font_id); + Some(font_id) + } + + fn add_fonts( + &mut self, + components: &DirectWriteComponents, + fonts: Vec>, + ) -> Result<()> { + for font_data in fonts { + match font_data { + Cow::Borrowed(data) => unsafe { + let font_file = components + .in_memory_loader + .CreateInMemoryFontFileReference( + &components.factory, + data.as_ptr().cast(), + data.len() as _, + None, + )?; + components.builder.AddFontFile(&font_file)?; + }, + Cow::Owned(data) => unsafe { + let font_file = components + .in_memory_loader + .CreateInMemoryFontFileReference( + &components.factory, + data.as_ptr().cast(), + data.len() as _, + None, + )?; + components.builder.AddFontFile(&font_file)?; + }, + } + } + let set = unsafe { components.builder.CreateFontSet()? }; + let collection = unsafe { components.factory.CreateFontCollectionFromFontSet(&set)? }; + self.custom_font_collection = collection; + + Ok(()) + } + + fn generate_font_fallbacks( + fallbacks: &FontFallbacks, + factory: &IDWriteFactory5, + system_font_collection: &IDWriteFontCollection1, + ) -> Result> { + let fallback_list = fallbacks.fallback_list(); + if fallback_list.is_empty() { + return Ok(None); + } + unsafe { + let builder = factory.CreateFontFallbackBuilder()?; + let font_set = &system_font_collection.GetFontSet()?; + let mut unicode_ranges = Vec::new(); + for family_name in fallback_list { + let family_name = HSTRING::from(family_name); + let Some(fonts) = font_set + .GetMatchingFonts( + &family_name, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + ) + .log_err() + else { + continue; + }; + let Ok(font_face) = fonts.GetFontFaceReference(0) else { + continue; + }; + let font = font_face.CreateFontFace()?; + let mut count = 0; + font.GetUnicodeRanges(None, &mut count).ok(); + if count == 0 { + continue; + } + unicode_ranges.clear(); + unicode_ranges.resize_with(count as usize, DWRITE_UNICODE_RANGE::default); + let Some(_) = font + .GetUnicodeRanges(Some(&mut unicode_ranges), &mut count) + .log_err() + else { + continue; + }; + builder.AddMapping( + &unicode_ranges, + &[family_name.as_ptr()], + None, + None, + None, + 1.0, + )?; + } + let system_fallbacks = factory.GetSystemFontFallback()?; + builder.AddMappings(&system_fallbacks)?; + Ok(Some(builder.CreateFontFallback()?)) + } + } + + unsafe fn generate_font_features( + factory: &IDWriteFactory5, + font_features: &FontFeatures, + ) -> Result { + let direct_write_features = unsafe { factory.CreateTypography()? }; + apply_font_features(&direct_write_features, font_features)?; + Ok(direct_write_features) + } + + unsafe fn make_font_from_font_collection( + &Font { + ref family, + ref features, + ref fallbacks, + weight, + style, + }: &Font, + collection: &IDWriteFontCollection1, + factory: &IDWriteFactory5, + system_font_collection: &IDWriteFontCollection1, + system_ui_font_name: &SharedString, + ) -> Option { + const SYSTEM_UI_FONT_NAME: &str = ".SystemUIFont"; + let family = if family == SYSTEM_UI_FONT_NAME { + system_ui_font_name + } else { + gpui::font_name_with_fallbacks_shared(&family, &system_ui_font_name) + }; + let fontset = unsafe { collection.GetFontSet().log_err()? }; + let font_family_h = HSTRING::from(family.as_str()); + let font = unsafe { + fontset + .GetMatchingFonts( + &font_family_h, + font_weight_to_dwrite(weight), + DWRITE_FONT_STRETCH_NORMAL, + font_style_to_dwrite(style), + ) + .log_err()? + }; + let total_number = unsafe { font.GetFontCount() }; + for index in 0..total_number { + let res = maybe!({ + let font_face_ref = unsafe { font.GetFontFaceReference(index).log_err()? }; + let font_face = unsafe { font_face_ref.CreateFontFace().log_err()? }; + let direct_write_features = + unsafe { Self::generate_font_features(factory, features).log_err()? }; + let fallbacks = fallbacks.as_ref().and_then(|fallbacks| { + Self::generate_font_fallbacks(fallbacks, factory, system_font_collection) + .log_err() + .flatten() + }); + let font_info = FontInfo { + font_family_h: font_family_h.clone(), + font_face, + features: direct_write_features, + fallbacks, + font_collection: collection.clone(), + }; + Some(font_info) + }); + if res.is_some() { + return res; + } + } + None + } + + fn layout_line( + &mut self, + components: &DirectWriteComponents, + text: &str, + font_size: Pixels, + font_runs: &[FontRun], + ) -> Result { + if font_runs.is_empty() { + return Ok(LineLayout { + font_size, + ..Default::default() + }); + } + unsafe { + self.layout_line_scratch.clear(); + self.layout_line_scratch.extend(text.encode_utf16()); + let text_wide = &*self.layout_line_scratch; + + let mut utf8_offset = 0usize; + let mut utf16_offset = 0u32; + let text_layout = { + let first_run = &font_runs[0]; + let font_info = &self.fonts[first_run.font_id.0]; + let collection = &font_info.font_collection; + let format: IDWriteTextFormat1 = components + .factory + .CreateTextFormat( + &font_info.font_family_h, + collection, + font_info.font_face.GetWeight(), + font_info.font_face.GetStyle(), + DWRITE_FONT_STRETCH_NORMAL, + font_size.as_f32(), + &components.locale, + )? + .cast()?; + if let Some(ref fallbacks) = font_info.fallbacks { + format.SetFontFallback(fallbacks)?; + } + + let layout = components.factory.CreateTextLayout( + text_wide, + &format, + f32::INFINITY, + f32::INFINITY, + )?; + let current_text = &text[utf8_offset..(utf8_offset + first_run.len)]; + utf8_offset += first_run.len; + let current_text_utf16_length = current_text.encode_utf16().count() as u32; + let text_range = DWRITE_TEXT_RANGE { + startPosition: utf16_offset, + length: current_text_utf16_length, + }; + layout.SetTypography(&font_info.features, text_range)?; + utf16_offset += current_text_utf16_length; + + layout + }; + + let (ascent, descent) = { + let mut first_metrics = [DWRITE_LINE_METRICS::default(); 4]; + let mut line_count = 0u32; + text_layout.GetLineMetrics(Some(&mut first_metrics), &mut line_count)?; + ( + px(first_metrics[0].baseline), + px(first_metrics[0].height - first_metrics[0].baseline), + ) + }; + let mut break_ligatures = true; + for run in &font_runs[1..] { + let font_info = &self.fonts[run.font_id.0]; + let current_text = &text[utf8_offset..(utf8_offset + run.len)]; + utf8_offset += run.len; + let current_text_utf16_length = current_text.encode_utf16().count() as u32; + + let collection = &font_info.font_collection; + let text_range = DWRITE_TEXT_RANGE { + startPosition: utf16_offset, + length: current_text_utf16_length, + }; + utf16_offset += current_text_utf16_length; + text_layout.SetFontCollection(collection, text_range)?; + text_layout.SetFontFamilyName(&font_info.font_family_h, text_range)?; + let font_size = if break_ligatures { + font_size.as_f32().next_up() + } else { + font_size.as_f32() + }; + text_layout.SetFontSize(font_size, text_range)?; + text_layout.SetFontStyle(font_info.font_face.GetStyle(), text_range)?; + text_layout.SetFontWeight(font_info.font_face.GetWeight(), text_range)?; + text_layout.SetTypography(&font_info.features, text_range)?; + + break_ligatures = !break_ligatures; + } + + let mut runs = Vec::new(); + let mut renderer_context = RendererContext { + text_system: self, + components, + index_converter: StringIndexConverter::new(text), + runs: &mut runs, + width: 0.0, + }; + text_layout.Draw( + Some((&raw mut renderer_context).cast::().cast_const()), + &components.text_renderer.0, + 0.0, + 0.0, + )?; + let width = px(renderer_context.width); + + Ok(LineLayout { + font_size, + width, + ascent, + descent, + runs, + len: text.len(), + }) + } + } + + fn font_metrics(&self, font_id: FontId) -> FontMetrics { + unsafe { + let font_info = &self.fonts[font_id.0]; + let mut metrics = std::mem::zeroed(); + font_info.font_face.GetMetrics(&mut metrics); + + FontMetrics { + units_per_em: metrics.Base.designUnitsPerEm as _, + ascent: metrics.Base.ascent as _, + descent: -(metrics.Base.descent as f32), + line_gap: metrics.Base.lineGap as _, + underline_position: metrics.Base.underlinePosition as _, + underline_thickness: metrics.Base.underlineThickness as _, + cap_height: metrics.Base.capHeight as _, + x_height: metrics.Base.xHeight as _, + bounding_box: Bounds { + origin: Point { + x: metrics.glyphBoxLeft as _, + y: metrics.glyphBoxBottom as _, + }, + size: Size { + width: (metrics.glyphBoxRight - metrics.glyphBoxLeft) as _, + height: (metrics.glyphBoxTop - metrics.glyphBoxBottom) as _, + }, + }, + } + } + } + + fn create_glyph_run_analysis( + &self, + components: &DirectWriteComponents, + params: &RenderGlyphParams, + ) -> Result { + let font = &self.fonts[params.font_id.0]; + let glyph_id = [params.glyph_id.0 as u16]; + let advance = [0.0]; + let offset = [DWRITE_GLYPH_OFFSET::default()]; + let glyph_run = DWRITE_GLYPH_RUN { + fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&***font.font_face) })), + fontEmSize: params.font_size.as_f32(), + glyphCount: 1, + glyphIndices: glyph_id.as_ptr(), + glyphAdvances: advance.as_ptr(), + glyphOffsets: offset.as_ptr(), + isSideways: BOOL(0), + bidiLevel: 0, + }; + let transform = DWRITE_MATRIX { + m11: params.scale_factor, + m12: 0.0, + m21: 0.0, + m22: params.scale_factor, + dx: 0.0, + dy: 0.0, + }; + let baseline_origin_x = + params.subpixel_variant.x as f32 / SUBPIXEL_VARIANTS_X as f32 / params.scale_factor; + let baseline_origin_y = params.subpixel_variant.y as f32 + / gpui::SUBPIXEL_VARIANTS_Y as f32 + / params.scale_factor; + + let mut rendering_mode = DWRITE_RENDERING_MODE1::default(); + let mut grid_fit_mode = DWRITE_GRID_FIT_MODE::default(); + unsafe { + font.font_face.GetRecommendedRenderingMode( + params.font_size.as_f32(), + // Using 96 as scale is applied by the transform + 96.0, + 96.0, + Some(&transform), + false, + DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, + DWRITE_MEASURING_MODE_NATURAL, + None, + &mut rendering_mode, + &mut grid_fit_mode, + )?; + } + let rendering_mode = match rendering_mode { + DWRITE_RENDERING_MODE1_OUTLINE => DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC, + m => m, + }; + + let antialias_mode = if params.subpixel_rendering { + DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE + } else { + DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE + }; + + let glyph_analysis = unsafe { + components.factory.CreateGlyphRunAnalysis( + &glyph_run, + Some(&transform), + rendering_mode, + DWRITE_MEASURING_MODE_NATURAL, + grid_fit_mode, + antialias_mode, + baseline_origin_x, + baseline_origin_y, + ) + }?; + Ok(glyph_analysis) + } + + fn raster_bounds( + &self, + components: &DirectWriteComponents, + params: &RenderGlyphParams, + ) -> Result> { + let glyph_analysis = self.create_glyph_run_analysis(components, params)?; + + let texture_type = if params.subpixel_rendering { + DWRITE_TEXTURE_CLEARTYPE_3x1 + } else { + DWRITE_TEXTURE_ALIASED_1x1 + }; + + let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(texture_type)? }; + + if bounds.right < bounds.left { + Ok(Bounds { + origin: point(0.into(), 0.into()), + size: size(0.into(), 0.into()), + }) + } else { + Ok(Bounds { + origin: point(bounds.left.into(), bounds.top.into()), + size: size( + (bounds.right - bounds.left).into(), + (bounds.bottom - bounds.top).into(), + ), + }) + } + } + + fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { + let font_info = &self.fonts[font_id.0]; + let codepoints = ch as u32; + let mut glyph_indices = 0u16; + unsafe { + font_info + .font_face + .GetGlyphIndices(&raw const codepoints, 1, &raw mut glyph_indices) + .log_err() + } + .map(|_| GlyphId(glyph_indices as u32)) + } + + fn rasterize_glyph( + &self, + components: &DirectWriteComponents, + params: &RenderGlyphParams, + glyph_bounds: Bounds, + ) -> Result<(Size, Vec)> { + if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 { + anyhow::bail!("glyph bounds are empty"); + } + + let bitmap_data = if params.is_emoji { + if let Ok(color) = self.rasterize_color(components, params, glyph_bounds) { + color + } else { + let monochrome = self.rasterize_monochrome(components, params, glyph_bounds)?; + monochrome + .into_iter() + .flat_map(|pixel| [0, 0, 0, pixel]) + .collect::>() + } + } else { + self.rasterize_monochrome(components, params, glyph_bounds)? + }; + + Ok((glyph_bounds.size, bitmap_data)) + } + + fn rasterize_monochrome( + &self, + components: &DirectWriteComponents, + params: &RenderGlyphParams, + glyph_bounds: Bounds, + ) -> Result> { + let glyph_analysis = self.create_glyph_run_analysis(components, params)?; + if !params.subpixel_rendering { + let mut bitmap_data = + vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize]; + unsafe { + glyph_analysis.CreateAlphaTexture( + DWRITE_TEXTURE_ALIASED_1x1, + &RECT { + left: glyph_bounds.origin.x.0, + top: glyph_bounds.origin.y.0, + right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0, + bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0, + }, + &mut bitmap_data, + )?; + } + + return Ok(bitmap_data); + } + + let width = glyph_bounds.size.width.0 as usize; + let height = glyph_bounds.size.height.0 as usize; + let pixel_count = width * height; + + let mut bitmap_data = vec![0u8; pixel_count * 4]; + + unsafe { + glyph_analysis.CreateAlphaTexture( + DWRITE_TEXTURE_CLEARTYPE_3x1, + &RECT { + left: glyph_bounds.origin.x.0, + top: glyph_bounds.origin.y.0, + right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0, + bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0, + }, + &mut bitmap_data[..pixel_count * 3], + )?; + } + + // The output buffer expects RGBA data, so pad the alpha channel with zeros. + for pixel_ix in (0..pixel_count).rev() { + let src = pixel_ix * 3; + let dst = pixel_ix * 4; + ( + bitmap_data[dst], + bitmap_data[dst + 1], + bitmap_data[dst + 2], + bitmap_data[dst + 3], + ) = ( + bitmap_data[src], + bitmap_data[src + 1], + bitmap_data[src + 2], + 0, + ); + } + + Ok(bitmap_data) + } + + fn rasterize_color( + &self, + components: &DirectWriteComponents, + params: &RenderGlyphParams, + glyph_bounds: Bounds, + ) -> Result> { + // INVARIANT: the code below drives the *shared* D3D11 immediate context + // (`Map`/`Unmap`/`Draw`/`CopyResource`), which `DirectXRenderer` and `DirectXAtlas` also + // touch. An immediate `ID3D11DeviceContext` is not thread-safe, so this must only run on + // the main UI thread (which it always is; text rasterization never leaves that thread). + let gpu_state = self + .gpu_state + .as_ref() + .context("rasterizing color glyphs needs a GPU, which headless mode has none of")?; + let bitmap_size = glyph_bounds.size; + let subpixel_shift = params + .subpixel_variant + .map(|v| v as f32 / SUBPIXEL_VARIANTS_X as f32); + let baseline_origin_x = subpixel_shift.x / params.scale_factor; + let baseline_origin_y = subpixel_shift.y / params.scale_factor; + + let transform = DWRITE_MATRIX { + m11: params.scale_factor, + m12: 0.0, + m21: 0.0, + m22: params.scale_factor, + dx: 0.0, + dy: 0.0, + }; + + let font = &self.fonts[params.font_id.0]; + let glyph_id = [params.glyph_id.0 as u16]; + let advance = [glyph_bounds.size.width.0 as f32]; + let offset = [DWRITE_GLYPH_OFFSET { + advanceOffset: -glyph_bounds.origin.x.0 as f32 / params.scale_factor, + ascenderOffset: glyph_bounds.origin.y.0 as f32 / params.scale_factor, + }]; + let glyph_run = DWRITE_GLYPH_RUN { + fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&***font.font_face) })), + fontEmSize: params.font_size.as_f32(), + glyphCount: 1, + glyphIndices: glyph_id.as_ptr(), + glyphAdvances: advance.as_ptr(), + glyphOffsets: offset.as_ptr(), + isSideways: BOOL(0), + bidiLevel: 0, + }; + + // todo: support formats other than COLR + let color_enumerator = unsafe { + components.factory.TranslateColorGlyphRun( + Vector2::new(baseline_origin_x, baseline_origin_y), + &glyph_run, + None, + DWRITE_GLYPH_IMAGE_FORMATS_COLR, + DWRITE_MEASURING_MODE_NATURAL, + Some(&transform), + 0, + ) + }?; + + let mut glyph_layers = Vec::new(); + let mut alpha_data = Vec::new(); + loop { + let color_run = unsafe { color_enumerator.GetCurrentRun() }?; + let color_run = unsafe { &*color_run }; + let image_format = color_run.glyphImageFormat & !DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE; + if image_format == DWRITE_GLYPH_IMAGE_FORMATS_COLR { + let color_analysis = unsafe { + components.factory.CreateGlyphRunAnalysis( + &color_run.Base.glyphRun as *const _, + Some(&transform), + DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, + DWRITE_GRID_FIT_MODE_DEFAULT, + DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, + baseline_origin_x, + baseline_origin_y, + ) + }?; + + let color_bounds = + unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1) }?; + + let color_size = size( + color_bounds.right - color_bounds.left, + color_bounds.bottom - color_bounds.top, + ); + if color_size.width > 0 && color_size.height > 0 { + alpha_data.clear(); + alpha_data.resize((color_size.width * color_size.height) as usize, 0); + unsafe { + color_analysis.CreateAlphaTexture( + DWRITE_TEXTURE_ALIASED_1x1, + &color_bounds, + &mut alpha_data, + ) + }?; + + let run_color = { + let run_color = color_run.Base.runColor; + Rgba { + r: run_color.r, + g: run_color.g, + b: run_color.b, + a: run_color.a, + } + }; + let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size); + glyph_layers.push(GlyphLayerTexture::new( + gpu_state, + run_color, + bounds, + &alpha_data, + )?); + } + } + + let has_next = unsafe { color_enumerator.MoveNext() } + .map(|e| e.as_bool()) + .unwrap_or(false); + if !has_next { + break; + } + } + + let render_target_texture = { + let mut texture = None; + let desc = D3D11_TEXTURE2D_DESC { + Width: bitmap_size.width.0 as u32, + Height: bitmap_size.height.0 as u32, + MipLevels: 1, + ArraySize: 1, + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + unsafe { + gpu_state + .device + .CreateTexture2D(&desc, None, Some(&mut texture)) + }?; + texture.unwrap() + }; + + let render_target_view = { + let desc = D3D11_RENDER_TARGET_VIEW_DESC { + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D, + Anonymous: D3D11_RENDER_TARGET_VIEW_DESC_0 { + Texture2D: D3D11_TEX2D_RTV { MipSlice: 0 }, + }, + }; + let mut rtv = None; + unsafe { + gpu_state.device.CreateRenderTargetView( + &render_target_texture, + Some(&desc), + Some(&mut rtv), + ) + }?; + rtv + }; + + Self::composite_color_layers( + gpu_state, + &glyph_layers, + bitmap_size, + &render_target_texture, + &render_target_view, + ) + } + + fn composite_color_layers( + gpu_state: &GPUState, + glyph_layers: &[GlyphLayerTexture], + bitmap_size: Size, + render_target_texture: &ID3D11Texture2D, + render_target_view: &Option, + ) -> Result> { + let params_buffer = { + let desc = D3D11_BUFFER_DESC { + ByteWidth: std::mem::size_of::() as u32, + Usage: D3D11_USAGE_DYNAMIC, + BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32, + CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32, + MiscFlags: 0, + StructureByteStride: 0, + }; + + let mut buffer = None; + unsafe { + gpu_state + .device + .CreateBuffer(&desc, None, Some(&mut buffer)) + }?; + buffer + }; + + let staging_texture = { + let mut texture = None; + let desc = D3D11_TEXTURE2D_DESC { + Width: bitmap_size.width.0 as u32, + Height: bitmap_size.height.0 as u32, + MipLevels: 1, + ArraySize: 1, + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_STAGING, + BindFlags: 0, + CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32, + MiscFlags: 0, + }; + unsafe { + gpu_state + .device + .CreateTexture2D(&desc, None, Some(&mut texture)) + }?; + texture.unwrap() + }; + + let device_context = &gpu_state.device_context; + unsafe { device_context.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) }; + unsafe { device_context.VSSetShader(&gpu_state.vertex_shader, None) }; + unsafe { device_context.PSSetShader(&gpu_state.pixel_shader, None) }; + unsafe { + device_context.VSSetConstantBuffers(0, Some(std::slice::from_ref(¶ms_buffer))) + }; + unsafe { + device_context.PSSetConstantBuffers(0, Some(std::slice::from_ref(¶ms_buffer))) + }; + unsafe { + device_context.OMSetRenderTargets(Some(std::slice::from_ref(render_target_view)), None) + }; + unsafe { + if let Some(render_target_view) = render_target_view.as_ref() { + device_context.ClearRenderTargetView(render_target_view, &[0.0, 0.0, 0.0, 0.0]); + } + } + unsafe { device_context.PSSetSamplers(0, Some(std::slice::from_ref(&gpu_state.sampler))) }; + unsafe { device_context.OMSetBlendState(&gpu_state.blend_state, None, 0xffffffff) }; + + let crate::FontInfo { + gamma_ratios, + grayscale_enhanced_contrast, + .. + } = DirectXRenderer::get_font_info(); + + for layer in glyph_layers { + let params = GlyphLayerTextureParams { + run_color: layer.run_color, + bounds: layer.bounds, + gamma_ratios: *gamma_ratios, + grayscale_enhanced_contrast: *grayscale_enhanced_contrast, + _pad: [0f32; 3], + }; + unsafe { + let mut dest = std::mem::zeroed(); + gpu_state.device_context.Map( + params_buffer.as_ref().unwrap(), + 0, + D3D11_MAP_WRITE_DISCARD, + 0, + Some(&mut dest), + )?; + std::ptr::copy_nonoverlapping(¶ms as *const _, dest.pData as *mut _, 1); + gpu_state + .device_context + .Unmap(params_buffer.as_ref().unwrap(), 0); + }; + + let texture = [Some(layer.texture_view.clone())]; + unsafe { device_context.PSSetShaderResources(0, Some(&texture)) }; + + let viewport = [D3D11_VIEWPORT { + TopLeftX: layer.bounds.origin.x as f32, + TopLeftY: layer.bounds.origin.y as f32, + Width: layer.bounds.size.width as f32, + Height: layer.bounds.size.height as f32, + MinDepth: 0.0, + MaxDepth: 1.0, + }]; + unsafe { device_context.RSSetViewports(Some(&viewport)) }; + + unsafe { device_context.Draw(4, 0) }; + } + + unsafe { device_context.CopyResource(&staging_texture, render_target_texture) }; + + let mapped_data = { + let mut mapped_data = D3D11_MAPPED_SUBRESOURCE::default(); + unsafe { + device_context.Map( + &staging_texture, + 0, + D3D11_MAP_READ, + 0, + Some(&mut mapped_data), + ) + }?; + mapped_data + }; + let mut rasterized = + vec![0u8; (bitmap_size.width.0 as u32 * bitmap_size.height.0 as u32 * 4) as usize]; + + for y in 0..bitmap_size.height.0 as usize { + let width = bitmap_size.width.0 as usize; + unsafe { + std::ptr::copy_nonoverlapping::( + (mapped_data.pData as *const u8).byte_add(mapped_data.RowPitch as usize * y), + rasterized + .as_mut_ptr() + .byte_add(width * y * std::mem::size_of::()), + width * std::mem::size_of::(), + ) + }; + } + + // Release the mapping now that the rows have been copied out; leaving `staging_texture` + // mapped would leak the mapping and keep the resource pinned for later reuse. + unsafe { device_context.Unmap(&staging_texture, 0) }; + + // Convert from premultiplied to straight alpha + for chunk in rasterized.chunks_exact_mut(4) { + let b = chunk[0] as f32; + let g = chunk[1] as f32; + let r = chunk[2] as f32; + let a = chunk[3] as f32; + if a > 0.0 { + let inv_a = 255.0 / a; + chunk[0] = (b * inv_a).clamp(0.0, 255.0) as u8; + chunk[1] = (g * inv_a).clamp(0.0, 255.0) as u8; + chunk[2] = (r * inv_a).clamp(0.0, 255.0) as u8; + } + } + + Ok(rasterized) + } + + fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { + unsafe { + let font = &self.fonts[font_id.0].font_face; + let glyph_indices = [glyph_id.0 as u16]; + let mut metrics = [DWRITE_GLYPH_METRICS::default()]; + font.GetDesignGlyphMetrics(glyph_indices.as_ptr(), 1, metrics.as_mut_ptr(), false)?; + + let metrics = &metrics[0]; + let advance_width = metrics.advanceWidth as i32; + let advance_height = metrics.advanceHeight as i32; + let left_side_bearing = metrics.leftSideBearing; + let right_side_bearing = metrics.rightSideBearing; + let top_side_bearing = metrics.topSideBearing; + let bottom_side_bearing = metrics.bottomSideBearing; + let vertical_origin_y = metrics.verticalOriginY; + + let y_offset = vertical_origin_y + bottom_side_bearing - advance_height; + let width = advance_width - (left_side_bearing + right_side_bearing); + let height = advance_height - (top_side_bearing + bottom_side_bearing); + + Ok(Bounds { + origin: Point { + x: left_side_bearing as f32, + y: y_offset as f32, + }, + size: Size { + width: width as f32, + height: height as f32, + }, + }) + } + } + + fn get_advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { + unsafe { + let font = &self.fonts[font_id.0].font_face; + let glyph_indices = [glyph_id.0 as u16]; + let mut metrics = [DWRITE_GLYPH_METRICS::default()]; + font.GetDesignGlyphMetrics(glyph_indices.as_ptr(), 1, metrics.as_mut_ptr(), false)?; + + let metrics = &metrics[0]; + + Ok(Size { + width: metrics.advanceWidth as f32, + height: 0.0, + }) + } + } + + fn all_font_names(&self, components: &DirectWriteComponents) -> Vec { + let mut result = + get_font_names_from_collection(&self.system_font_collection, &components.locale); + result.extend(get_font_names_from_collection( + &self.custom_font_collection, + &components.locale, + )); + result + } + + /// The weights `family` ships, the custom collection first so a bundled face wins. + fn weights_for_family(&self, components: &DirectWriteComponents, family: &str) -> Vec { + let _ = components; + let mut weights = weights_for_family(&self.custom_font_collection, family); + if weights.is_empty() { + weights = weights_for_family(&self.system_font_collection, family); + } + weights + } + + /// Whether `family` is monospaced, the custom collection first. + fn is_monospaced(&self, components: &DirectWriteComponents, family: &str) -> bool { + let _ = components; + monospaced(&self.custom_font_collection, family) + || monospaced(&self.system_font_collection, family) + } + + fn handle_gpu_lost(&mut self, directx_devices: &DirectXDevices) -> Result<()> { + try_to_recover_from_device_lost(|| { + GPUState::new(directx_devices).context("Recreating GPU state for DirectWrite") + }) + .map(|gpu_state| self.gpu_state = Some(gpu_state)) + } +} + +struct GlyphLayerTexture { + run_color: Rgba, + bounds: Bounds, + texture_view: ID3D11ShaderResourceView, + // holding on to the texture to not RAII drop it + _texture: ID3D11Texture2D, +} + +impl GlyphLayerTexture { + fn new( + gpu_state: &GPUState, + run_color: Rgba, + bounds: Bounds, + alpha_data: &[u8], + ) -> Result { + let texture_size = bounds.size; + + let desc = D3D11_TEXTURE2D_DESC { + Width: texture_size.width as u32, + Height: texture_size.height as u32, + MipLevels: 1, + ArraySize: 1, + Format: DXGI_FORMAT_R8_UNORM, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + + let texture = { + let mut texture: Option = None; + unsafe { + gpu_state + .device + .CreateTexture2D(&desc, None, Some(&mut texture))? + }; + texture.unwrap() + }; + let texture_view = { + let mut view: Option = None; + unsafe { + gpu_state + .device + .CreateShaderResourceView(&texture, None, Some(&mut view))? + }; + view.unwrap() + }; + + unsafe { + gpu_state.device_context.UpdateSubresource( + &texture, + 0, + None, + alpha_data.as_ptr() as _, + texture_size.width as u32, + 0, + ) + }; + + Ok(GlyphLayerTexture { + run_color, + bounds, + texture_view, + _texture: texture, + }) + } +} + +#[repr(C)] +struct GlyphLayerTextureParams { + bounds: Bounds, + run_color: Rgba, + gamma_ratios: [f32; 4], + grayscale_enhanced_contrast: f32, + _pad: [f32; 3], +} + +struct TextRendererWrapper(IDWriteTextRenderer); + +impl TextRendererWrapper { + fn new(locale_str: HSTRING) -> Self { + let inner = TextRenderer::new(locale_str); + TextRendererWrapper(inner.into()) + } +} + +#[implement(IDWriteTextRenderer)] +struct TextRenderer { + locale: HSTRING, +} + +impl TextRenderer { + fn new(locale: HSTRING) -> Self { + TextRenderer { locale } + } +} + +struct RendererContext<'t, 'a, 'b> { + text_system: &'t mut DirectWriteState, + components: &'a DirectWriteComponents, + index_converter: StringIndexConverter<'a>, + runs: &'b mut Vec, + width: f32, +} + +#[derive(Debug)] +struct ClusterAnalyzer<'t> { + utf16_idx: usize, + glyph_idx: usize, + glyph_count: usize, + cluster_map: &'t [u16], +} + +impl<'t> ClusterAnalyzer<'t> { + fn new(cluster_map: &'t [u16], glyph_count: usize) -> Self { + ClusterAnalyzer { + utf16_idx: 0, + glyph_idx: 0, + glyph_count, + cluster_map, + } + } +} + +impl Iterator for ClusterAnalyzer<'_> { + type Item = (usize, usize); + + fn next(&mut self) -> Option<(usize, usize)> { + if self.utf16_idx >= self.cluster_map.len() { + return None; // No more clusters + } + let start_utf16_idx = self.utf16_idx; + let current_glyph = self.cluster_map[start_utf16_idx] as usize; + + // Find the end of current cluster (where glyph index changes) + let mut end_utf16_idx = start_utf16_idx + 1; + while end_utf16_idx < self.cluster_map.len() + && self.cluster_map[end_utf16_idx] as usize == current_glyph + { + end_utf16_idx += 1; + } + + let utf16_len = end_utf16_idx - start_utf16_idx; + + // Calculate glyph count for this cluster + let next_glyph = if end_utf16_idx < self.cluster_map.len() { + self.cluster_map[end_utf16_idx] as usize + } else { + self.glyph_count + }; + + let glyph_count = next_glyph - current_glyph; + + // Update state for next call + self.utf16_idx = end_utf16_idx; + self.glyph_idx = next_glyph; + + Some((utf16_len, glyph_count)) + } +} + +#[allow(non_snake_case)] +impl IDWritePixelSnapping_Impl for TextRenderer_Impl { + fn IsPixelSnappingDisabled( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + ) -> windows::core::Result { + Ok(BOOL(0)) + } + + fn GetCurrentTransform( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + transform: *mut DWRITE_MATRIX, + ) -> windows::core::Result<()> { + unsafe { + *transform = DWRITE_MATRIX { + m11: 1.0, + m12: 0.0, + m21: 0.0, + m22: 1.0, + dx: 0.0, + dy: 0.0, + }; + } + Ok(()) + } + + fn GetPixelsPerDip( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + ) -> windows::core::Result { + Ok(1.0) + } +} + +#[allow(non_snake_case)] +impl IDWriteTextRenderer_Impl for TextRenderer_Impl { + fn DrawGlyphRun( + &self, + clientdrawingcontext: *const ::core::ffi::c_void, + _baselineoriginx: f32, + _baselineoriginy: f32, + _measuringmode: DWRITE_MEASURING_MODE, + glyphrun: *const DWRITE_GLYPH_RUN, + glyphrundescription: *const DWRITE_GLYPH_RUN_DESCRIPTION, + _clientdrawingeffect: windows::core::Ref, + ) -> windows::core::Result<()> { + let glyphrun = unsafe { &*glyphrun }; + let glyph_count = glyphrun.glyphCount as usize; + if glyph_count == 0 { + return Ok(()); + } + let desc = unsafe { &*glyphrundescription }; + let context = unsafe { &mut *(clientdrawingcontext.cast::().cast_mut()) }; + let Some(font_face) = glyphrun.fontFace.as_ref() else { + return Ok(()); + }; + // This `cast()` action here should never fail since we are running on Win10+, and + // `IDWriteFontFace3` requires Win10 + let Ok(font_face) = &font_face.cast::() else { + return Err(Error::new( + DWRITE_E_UNSUPPORTEDOPERATION, + "Failed to cast font face", + )); + }; + + let font_face_key = font_face.cast::().unwrap().as_raw().addr(); + let font_id = context + .text_system + .font_info_cache + .get(&font_face_key) + .copied() + // A fallback face: draw with it, not a lookalike. + .map_or_else( + || { + let font = font_face_to_font(font_face, &self.locale) + .ok_or_else(|| Error::new(DWRITE_E_NOFONT, "Failed to create font"))?; + let features = unsafe { + DirectWriteState::generate_font_features( + &context.components.factory, + &font.features, + ) + } + .map_err(|error| Error::new(DWRITE_E_NOFONT, format!("{error:#}")))?; + let text_system = &mut context.text_system; + let font_id = FontId(text_system.fonts.len()); + text_system.fonts.push(FontInfo { + font_family_h: HSTRING::from(font.family.as_ref()), + font_face: font_face.clone(), + features, + fallbacks: None, + font_collection: text_system.system_font_collection.clone(), + }); + text_system.font_info_cache.insert(font_face_key, font_id); + windows::core::Result::Ok(font_id) + }, + Ok, + )?; + + let color_font = unsafe { font_face.IsColorFont().as_bool() }; + + let glyph_ids = unsafe { + slice_from_nullable( + glyphrun.glyphIndices, + glyph_count, + "DirectWrite returned a null glyph indices array", + )? + }; + let glyph_advances = unsafe { + slice_from_nullable( + glyphrun.glyphAdvances, + glyph_count, + "DirectWrite returned a null glyph advances array", + )? + }; + let glyph_offsets = unsafe { + slice_from_nullable( + glyphrun.glyphOffsets, + glyph_count, + "DirectWrite returned a null glyph offsets array", + )? + }; + let cluster_map = unsafe { + slice_from_nullable( + desc.clusterMap, + desc.stringLength as usize, + "DirectWrite returned a null cluster map", + )? + }; + + let cluster_analyzer = ClusterAnalyzer::new(cluster_map, glyph_count); + let mut utf16_idx = desc.textPosition as usize; + let mut glyph_idx = 0; + let mut glyphs = Vec::with_capacity(glyph_count); + for (cluster_utf16_len, cluster_glyph_count) in cluster_analyzer { + context.index_converter.advance_to_utf16_ix(utf16_idx); + utf16_idx += cluster_utf16_len; + for (cluster_glyph_idx, glyph_id) in glyph_ids + [glyph_idx..(glyph_idx + cluster_glyph_count)] + .iter() + .enumerate() + { + let id = GlyphId(*glyph_id as u32); + let is_emoji = + color_font && is_color_glyph(font_face, id, &context.components.factory); + let this_glyph_idx = glyph_idx + cluster_glyph_idx; + glyphs.push(ShapedGlyph { + id, + position: point( + px(context.width + glyph_offsets[this_glyph_idx].advanceOffset), + px(-glyph_offsets[this_glyph_idx].ascenderOffset), + ), + index: context.index_converter.utf8_ix, + is_emoji, + }); + context.width += glyph_advances[this_glyph_idx]; + } + glyph_idx += cluster_glyph_count; + } + context.runs.push(ShapedRun { font_id, glyphs }); + Ok(()) + } + + fn DrawUnderline( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + _baselineoriginx: f32, + _baselineoriginy: f32, + _underline: *const DWRITE_UNDERLINE, + _clientdrawingeffect: windows::core::Ref, + ) -> windows::core::Result<()> { + Err(windows::core::Error::new( + E_NOTIMPL, + "DrawUnderline unimplemented", + )) + } + + fn DrawStrikethrough( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + _baselineoriginx: f32, + _baselineoriginy: f32, + _strikethrough: *const DWRITE_STRIKETHROUGH, + _clientdrawingeffect: windows::core::Ref, + ) -> windows::core::Result<()> { + Err(windows::core::Error::new( + E_NOTIMPL, + "DrawStrikethrough unimplemented", + )) + } + + fn DrawInlineObject( + &self, + _clientdrawingcontext: *const ::core::ffi::c_void, + _originx: f32, + _originy: f32, + _inlineobject: windows::core::Ref, + _issideways: BOOL, + _isrighttoleft: BOOL, + _clientdrawingeffect: windows::core::Ref, + ) -> windows::core::Result<()> { + Err(windows::core::Error::new( + E_NOTIMPL, + "DrawInlineObject unimplemented", + )) + } +} + +/// Interprets an optional DirectWrite array pointer as a slice, treating a +/// null pointer with a zero length as an empty slice. A null pointer with a +/// nonzero length fails with `null_error_message`. +/// +/// # Safety +/// +/// When `ptr` is non-null, the caller must guarantee that it points to a valid +/// array of at least `len` elements that outlives the returned slice. +unsafe fn slice_from_nullable<'a, T>( + ptr: *const T, + len: usize, + null_error_message: &str, +) -> windows::core::Result<&'a [T]> { + if ptr.is_null() { + if len != 0 { + return Err(Error::new(E_INVALIDARG, null_error_message)); + } + Ok(&[]) + } else { + Ok(unsafe { std::slice::from_raw_parts(ptr, len) }) + } +} + +struct StringIndexConverter<'a> { + text: &'a str, + utf8_ix: usize, + utf16_ix: usize, +} + +impl<'a> StringIndexConverter<'a> { + fn new(text: &'a str) -> Self { + Self { + text, + utf8_ix: 0, + utf16_ix: 0, + } + } + + #[allow(dead_code)] + fn advance_to_utf8_ix(&mut self, utf8_target: usize) { + for (ix, c) in self.text[self.utf8_ix..].char_indices() { + if self.utf8_ix + ix >= utf8_target { + self.utf8_ix += ix; + return; + } + self.utf16_ix += c.len_utf16(); + } + self.utf8_ix = self.text.len(); + } + + fn advance_to_utf16_ix(&mut self, utf16_target: usize) { + for (ix, c) in self.text[self.utf8_ix..].char_indices() { + if self.utf16_ix >= utf16_target { + self.utf8_ix += ix; + return; + } + self.utf16_ix += c.len_utf16(); + } + self.utf8_ix = self.text.len(); + } +} + +fn font_style_to_dwrite(style: FontStyle) -> DWRITE_FONT_STYLE { + match style { + FontStyle::Normal => DWRITE_FONT_STYLE_NORMAL, + FontStyle::Italic => DWRITE_FONT_STYLE_ITALIC, + FontStyle::Oblique => DWRITE_FONT_STYLE_OBLIQUE, + } +} + +fn font_style_from_dwrite(value: DWRITE_FONT_STYLE) -> FontStyle { + match value.0 { + 0 => FontStyle::Normal, + 1 => FontStyle::Italic, + 2 => FontStyle::Oblique, + _ => unreachable!(), + } +} + +fn font_weight_to_dwrite(weight: FontWeight) -> DWRITE_FONT_WEIGHT { + DWRITE_FONT_WEIGHT(weight.0 as i32) +} + +fn font_weight_from_dwrite(value: DWRITE_FONT_WEIGHT) -> FontWeight { + FontWeight(value.0 as f32) +} + +/// The weights a family ships as its own faces, ascending and without repeats. +/// +/// A family that ships one face answers that one alone; the caller shows those +/// weights rather than a list the family cannot draw. +fn weights_for_family(collection: &IDWriteFontCollection1, family: &str) -> Vec { + unsafe { + let name = HSTRING::from(family); + let mut index = 0u32; + let mut exists = BOOL(0); + if collection + .FindFamilyName(&name, &mut index, &mut exists) + .is_err() + || !exists.as_bool() + { + return Vec::new(); + } + let Some(font_family) = collection.GetFontFamily(index).log_err() else { + return Vec::new(); + }; + let mut weights = Vec::new(); + for face in 0..font_family.GetFontCount() { + let Ok(font) = font_family.GetFont(face) else { + continue; + }; + let weight = u16::try_from(font.GetWeight().0).unwrap_or(u16::MAX); + if !weights.contains(&weight) { + weights.push(weight); + } + } + weights.sort_unstable(); + weights + } +} + +/// Whether `family` is monospaced, as DirectWrite's own metadata says. +/// +/// A family the collection does not hold answers false, and the caller keeps it out. +fn monospaced(collection: &IDWriteFontCollection1, family: &str) -> bool { + unsafe { + let name = HSTRING::from(family); + let mut index = 0u32; + let mut exists = BOOL(0); + if collection + .FindFamilyName(&name, &mut index, &mut exists) + .is_err() + || !exists.as_bool() + { + return false; + } + let Ok(font_family) = collection.GetFontFamily(index) else { + return false; + }; + let Ok(font) = font_family.GetFont(0) else { + return false; + }; + // IsMonospacedFont lives on IDWriteFont1, which every DirectWrite font answers. + match font.cast::() { + Ok(font) => font.IsMonospacedFont().as_bool(), + Err(_) => false, + } + } +} + +fn get_font_names_from_collection( + collection: &IDWriteFontCollection1, + locale: &HSTRING, +) -> Vec { + unsafe { + let mut result = Vec::new(); + let family_count = collection.GetFontFamilyCount(); + for index in 0..family_count { + let Some(font_family) = collection.GetFontFamily(index).log_err() else { + continue; + }; + let Some(localized_family_name) = font_family.GetFamilyNames().log_err() else { + continue; + }; + let Some(family_name) = get_name(localized_family_name, locale).log_err() else { + continue; + }; + result.push(family_name); + } + + result + } +} + +fn font_face_to_font(font_face: &IDWriteFontFace3, locale: &HSTRING) -> Option { + let localized_family_name = unsafe { font_face.GetFamilyNames().log_err() }?; + let family_name = get_name(localized_family_name, locale).log_err()?; + let weight = unsafe { font_face.GetWeight() }; + let style = unsafe { font_face.GetStyle() }; + Some(Font { + family: family_name.into(), + features: FontFeatures::default(), + weight: font_weight_from_dwrite(weight), + style: font_style_from_dwrite(style), + fallbacks: None, + }) +} + +// https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_font_feature_tag +fn apply_font_features( + direct_write_features: &IDWriteTypography, + features: &FontFeatures, +) -> Result<()> { + let tag_values = features.tag_value_list(); + + // All of these features are enabled by default by DirectWrite. + // If you want to (and can) peek into the source of DirectWrite + let mut feature_liga = make_direct_write_feature("liga", 1); + let mut feature_clig = make_direct_write_feature("clig", 1); + let mut feature_calt = make_direct_write_feature("calt", 1); + + for (tag, value) in tag_values { + if tag.as_str() == "liga" && *value == 0 { + feature_liga.parameter = 0; + continue; + } + if tag.as_str() == "clig" && *value == 0 { + feature_clig.parameter = 0; + continue; + } + if tag.as_str() == "calt" && *value == 0 { + feature_calt.parameter = 0; + continue; + } + + unsafe { + direct_write_features.AddFontFeature(make_direct_write_feature(tag, *value))?; + } + } + unsafe { + direct_write_features.AddFontFeature(feature_liga)?; + direct_write_features.AddFontFeature(feature_clig)?; + direct_write_features.AddFontFeature(feature_calt)?; + } + + Ok(()) +} + +#[inline] +const fn make_direct_write_feature(feature_name: &str, parameter: u32) -> DWRITE_FONT_FEATURE { + let tag = make_direct_write_tag(feature_name); + DWRITE_FONT_FEATURE { + nameTag: tag, + parameter, + } +} + +#[inline] +const fn make_open_type_tag(tag_name: &str) -> u32 { + let bytes = tag_name.as_bytes(); + debug_assert!(bytes.len() == 4); + u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) +} + +#[inline] +const fn make_direct_write_tag(tag_name: &str) -> DWRITE_FONT_FEATURE_TAG { + DWRITE_FONT_FEATURE_TAG(make_open_type_tag(tag_name)) +} + +#[inline] +fn get_name(string: IDWriteLocalizedStrings, locale: &HSTRING) -> Result { + let mut locale_name_index = 0u32; + let mut exists = BOOL(0); + unsafe { string.FindLocaleName(locale, &mut locale_name_index, &mut exists as _)? }; + if !exists.as_bool() { + unsafe { + string.FindLocaleName( + DEFAULT_LOCALE_NAME, + &mut locale_name_index as _, + &mut exists as _, + )? + }; + anyhow::ensure!(exists.as_bool(), "No localised string for {locale}"); + } + + let name_length = unsafe { string.GetStringLength(locale_name_index) }? as usize; + let mut name_vec = vec![0u16; name_length + 1]; + unsafe { + string.GetString(locale_name_index, &mut name_vec)?; + } + + Ok(String::from_utf16_lossy(&name_vec[..name_length])) +} + +fn get_system_subpixel_rendering() -> bool { + let mut value = c_uint::default(); + let result = unsafe { + SystemParametersInfoW( + SPI_GETFONTSMOOTHINGTYPE, + 0, + Some((&mut value) as *mut c_uint as *mut c_void), + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS::default(), + ) + }; + if result.log_err().is_some() { + value == FE_FONTSMOOTHINGCLEARTYPE + } else { + true + } +} + +fn get_system_ui_font_name() -> SharedString { + unsafe { + let mut info: LOGFONTW = std::mem::zeroed(); + let font_family = if SystemParametersInfoW( + SPI_GETICONTITLELOGFONT, + std::mem::size_of::() as u32, + Some(&mut info as *mut _ as _), + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0), + ) + .log_err() + .is_none() + { + // https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts + // Segoe UI is the Windows font intended for user interface text strings. + "Segoe UI".into() + } else { + let font_name = String::from_utf16_lossy(&info.lfFaceName); + font_name.trim_matches(char::from(0)).to_owned().into() + }; + log::info!("Use {} as UI font.", font_family); + font_family + } +} + +// One would think that with newer DirectWrite method: IDWriteFontFace4::GetGlyphImageFormats +// but that doesn't seem to work for some glyphs, say ❤ +fn is_color_glyph( + font_face: &IDWriteFontFace3, + glyph_id: GlyphId, + factory: &IDWriteFactory5, +) -> bool { + let glyph_run = DWRITE_GLYPH_RUN { + fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&****font_face) })), + fontEmSize: 14.0, + glyphCount: 1, + glyphIndices: &(glyph_id.0 as u16), + glyphAdvances: &0.0, + glyphOffsets: &DWRITE_GLYPH_OFFSET { + advanceOffset: 0.0, + ascenderOffset: 0.0, + }, + isSideways: BOOL(0), + bidiLevel: 0, + }; + unsafe { + factory.TranslateColorGlyphRun( + Vector2::default(), + &glyph_run as _, + None, + DWRITE_GLYPH_IMAGE_FORMATS_COLR + | DWRITE_GLYPH_IMAGE_FORMATS_SVG + | DWRITE_GLYPH_IMAGE_FORMATS_PNG + | DWRITE_GLYPH_IMAGE_FORMATS_JPEG + | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8, + DWRITE_MEASURING_MODE_NATURAL, + None, + 0, + ) + } + .is_ok() +} + +const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US"); + +#[cfg(test)] +mod tests { + use super::{DirectWriteState, DirectWriteTextSystem, GPUState, GlyphLayerTexture}; + use crate::direct_write::ClusterAnalyzer; + use crate::directx_devices::DirectXDevices; + use anyhow::Result; + use gpui::{ + DevicePixels, Font, PlatformTextSystem, RenderGlyphParams, Rgba, bounds, point, px, size, + }; + use std::ffi::c_void; + use windows::Win32::Graphics::Direct3D11::{ + D3D11_BIND_RENDER_TARGET, D3D11_RENDER_TARGET_VIEW_DESC, D3D11_RENDER_TARGET_VIEW_DESC_0, + D3D11_RTV_DIMENSION_TEXTURE2D, D3D11_SUBRESOURCE_DATA, D3D11_TEX2D_RTV, + D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, + }; + use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC}; + + #[test] + fn test_cluster_map() { + let cluster_map = [0]; + let mut analyzer = ClusterAnalyzer::new(&cluster_map, 1); + let next = analyzer.next(); + assert_eq!(next, Some((1, 1))); + let next = analyzer.next(); + assert_eq!(next, None); + + let cluster_map = [0, 1, 2]; + let mut analyzer = ClusterAnalyzer::new(&cluster_map, 3); + let next = analyzer.next(); + assert_eq!(next, Some((1, 1))); + let next = analyzer.next(); + assert_eq!(next, Some((1, 1))); + let next = analyzer.next(); + assert_eq!(next, Some((1, 1))); + let next = analyzer.next(); + assert_eq!(next, None); + // 👨‍👩‍👧‍👦👩‍💻 + let cluster_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4]; + let mut analyzer = ClusterAnalyzer::new(&cluster_map, 5); + let next = analyzer.next(); + assert_eq!(next, Some((11, 4))); + let next = analyzer.next(); + assert_eq!(next, Some((5, 1))); + let next = analyzer.next(); + assert_eq!(next, None); + // 👩‍💻 + let cluster_map = [0, 0, 0, 0, 0]; + let mut analyzer = ClusterAnalyzer::new(&cluster_map, 1); + let next = analyzer.next(); + assert_eq!(next, Some((5, 1))); + let next = analyzer.next(); + assert_eq!(next, None); + } + + #[test] + fn color_emoji_rasterization_is_stable_across_batches() -> Result<()> { + let devices = DirectXDevices::new()?; + let text_system = DirectWriteTextSystem::new(Some(&devices))?; + + let font = Font { + family: "Segoe UI Emoji".into(), + ..Default::default() + }; + let font_id = text_system.font_id(&font)?; + + let mut params_list = Vec::new(); + for ch in ['🫠', '🥹', '🧗', '🏋', '🚀', '🥺'] { + let Some(glyph_id) = text_system.glyph_for_char(font_id, ch) else { + log::info!("no glyph found for {ch}"); + continue; + }; + let params = RenderGlyphParams { + font_id, + glyph_id, + font_size: px(48.0), + subpixel_variant: point(0u8, 0u8), + scale_factor: 1.0, + is_emoji: true, + subpixel_rendering: false, + dilation: 0, + }; + let raster_bounds = text_system.glyph_raster_bounds(¶ms)?; + if raster_bounds.size.width.0 == 0 || raster_bounds.size.height.0 == 0 { + log::info!("raster bounds are empty for {ch}"); + continue; + } + params_list.push((params, raster_bounds)); + } + assert!(!params_list.is_empty()); + + let first: Vec<_> = params_list + .iter() + .map(|(params, bounds)| text_system.rasterize_glyph(params, *bounds)) + .collect::>()?; + + // Churn the texture heap with further rasterization passes. If the color + // compositing leaks leftover texture data (the render target is not cleared), + // the second batch can pick up different contents and differ from the first. + // With an explicit clear both batches are deterministic and identical. + for _ in 0..3 { + for (params, bounds) in ¶ms_list { + text_system.rasterize_glyph(params, *bounds)?; + } + } + let second: Vec<_> = params_list + .iter() + .map(|(params, bounds)| text_system.rasterize_glyph(params, *bounds)) + .collect::>()?; + + assert_eq!( + first, second, + "color glyph rasterization changed between batches; \ + render target contents are leaking into the glyph bitmaps" + ); + Ok(()) + } + + #[test] + fn color_emoji_composites_over_cleared_texture() -> Result<()> { + let devices = DirectXDevices::new()?; + let gpu_state = GPUState::new(&devices)?; + + const SIZE: u32 = 32; + // Seed the render target with solid red so that any texel which the + // compositing pass fails to clear/overwrite remains identifiable after + // the readback. + let poison = { + let mut v = vec![0u8; (SIZE * SIZE * 4) as usize]; + for pixel in v.chunks_exact_mut(4) { + pixel[2] = 255; + pixel[3] = 255; + } + v + }; + let desc = D3D11_TEXTURE2D_DESC { + Width: SIZE, + Height: SIZE, + MipLevels: 1, + ArraySize: 1, + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + let initial_data = D3D11_SUBRESOURCE_DATA { + pSysMem: poison.as_ptr() as *const c_void, + SysMemPitch: SIZE * 4, + SysMemSlicePitch: 0, + }; + let texture = unsafe { + let mut texture = None; + gpu_state + .device + .CreateTexture2D(&desc, Some(&initial_data), Some(&mut texture))?; + texture.unwrap() + }; + let render_target_view = unsafe { + let desc = D3D11_RENDER_TARGET_VIEW_DESC { + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D, + Anonymous: D3D11_RENDER_TARGET_VIEW_DESC_0 { + Texture2D: D3D11_TEX2D_RTV { MipSlice: 0 }, + }, + }; + let mut rtv = None; + gpu_state + .device + .CreateRenderTargetView(&texture, Some(&desc), Some(&mut rtv))?; + rtv.unwrap() + }; + + // A single opaque layer in the top-left corner; the bottom-right corner + // of the texture is covered by no layer at all. + let layer_alpha = vec![255u8; 4 * 4]; + let layer = GlyphLayerTexture::new( + &gpu_state, + Rgba { + r: 1.0, + g: 1.0, + b: 1.0, + a: 1.0, + }, + bounds(point(0, 0), size(4, 4)), + &layer_alpha, + )?; + + let rasterized = DirectWriteState::composite_color_layers( + &gpu_state, + std::slice::from_ref(&layer), + size(DevicePixels(SIZE as i32), DevicePixels(SIZE as i32)), + &texture, + &Some(render_target_view), + )?; + + let corner = (SIZE as usize - 1 + (SIZE as usize - 1) * SIZE as usize) * 4; + assert_eq!( + &rasterized[corner..corner + 4], + &[0, 0, 0, 0], + "uncovered texel retained the poison from the uninitialized render target" + ); + Ok(()) + } +} diff --git a/vendor/gpui-pre-windows/src/directx_atlas.rs b/vendor/gpui-pre-windows/src/directx_atlas.rs new file mode 100644 index 00000000..622c1cb6 --- /dev/null +++ b/vendor/gpui-pre-windows/src/directx_atlas.rs @@ -0,0 +1,420 @@ +use etagere::BucketedAtlasAllocator; +use parking_lot::Mutex; +use windows::Win32::Graphics::{ + Direct3D11::{ + D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, + ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView, ID3D11Texture2D, + }, + Dxgi::Common::*, +}; + +use gpui::{ + AtlasBackend, AtlasKey, AtlasState, AtlasTextureId, AtlasTextureKind, AtlasTextureList, + AtlasTile, Bounds, DevicePixels, PlatformAtlas, Point, Size, +}; + +pub(crate) struct DirectXAtlas(Mutex>); + +struct DirectXAtlasTextures { + device: ID3D11Device, + device_context: ID3D11DeviceContext, + monochrome_textures: AtlasTextureList, + polychrome_textures: AtlasTextureList, + subpixel_textures: AtlasTextureList, +} + +struct DirectXAtlasTexture { + id: AtlasTextureId, + bytes_per_pixel: u32, + allocator: BucketedAtlasAllocator, + texture: ID3D11Texture2D, + view: [Option; 1], + live_atlas_keys: u32, +} + +impl DirectXAtlas { + pub(crate) fn new(device: &ID3D11Device, device_context: &ID3D11DeviceContext) -> Self { + DirectXAtlas(Mutex::new(AtlasState::new(DirectXAtlasTextures { + device: device.clone(), + device_context: device_context.clone(), + monochrome_textures: Default::default(), + polychrome_textures: Default::default(), + subpixel_textures: Default::default(), + }))) + } + + /// Returns the view backing `id`, or `None` once every tile in it has been + /// removed. A scene can still reference such a texture when a cached view + /// replays a paint from before the image was dropped, so callers must skip + /// those sprites rather than assume the texture exists. + pub(crate) fn get_texture_view( + &self, + id: AtlasTextureId, + ) -> Option<[Option; 1]> { + let lock = self.0.lock(); + let texture = lock.backend.texture(id)?; + Some(texture.view.clone()) + } + + pub(crate) fn handle_device_lost( + &self, + device: &ID3D11Device, + device_context: &ID3D11DeviceContext, + ) { + let mut lock = self.0.lock(); + lock.clear(|textures| { + textures.device = device.clone(); + textures.device_context = device_context.clone(); + textures.monochrome_textures = AtlasTextureList::default(); + textures.polychrome_textures = AtlasTextureList::default(); + textures.subpixel_textures = AtlasTextureList::default(); + }); + } +} + +impl PlatformAtlas for DirectXAtlas { + fn get_or_insert_with<'a>( + &self, + key: AtlasKey, + build: &mut dyn FnMut() -> anyhow::Result< + Option<(Size, std::borrow::Cow<'a, [u8]>)>, + >, + ) -> anyhow::Result> { + self.0.lock().get_or_insert_with(key, build) + } + + fn remove(&self, key: &AtlasKey) { + self.0.lock().remove(key); + } +} + +impl AtlasBackend for DirectXAtlasTextures { + fn insert( + &mut self, + kind: AtlasTextureKind, + size: Size, + bytes: &[u8], + ) -> anyhow::Result { + let tile = self + .allocate(size, kind) + .ok_or_else(|| anyhow::anyhow!("failed to allocate"))?; + let texture = self + .texture(tile.texture_id) + .ok_or_else(|| anyhow::anyhow!("allocated tile refers to a missing texture"))?; + texture.upload(&self.device_context, tile.bounds, bytes); + Ok(tile) + } + + fn remove(&mut self, tile: AtlasTile) { + let id = tile.texture_id; + + let textures = match id.kind { + AtlasTextureKind::Monochrome => &mut self.monochrome_textures, + AtlasTextureKind::Polychrome => &mut self.polychrome_textures, + AtlasTextureKind::Subpixel => &mut self.subpixel_textures, + }; + + let Some(texture_slot) = textures.textures.get_mut(id.index as usize) else { + return; + }; + + if let Some(mut texture) = texture_slot.take() { + texture.allocator.deallocate(tile.tile_id.into()); + texture.decrement_ref_count(); + if texture.is_unreferenced() { + textures.free_list.push(texture.id.index as usize); + } else { + *texture_slot = Some(texture); + } + } + } +} + +impl DirectXAtlasTextures { + fn allocate( + &mut self, + size: Size, + texture_kind: AtlasTextureKind, + ) -> Option { + { + let textures = match texture_kind { + AtlasTextureKind::Monochrome => &mut self.monochrome_textures, + AtlasTextureKind::Polychrome => &mut self.polychrome_textures, + AtlasTextureKind::Subpixel => &mut self.subpixel_textures, + }; + + if let Some(tile) = textures + .iter_mut() + .rev() + .find_map(|texture| texture.allocate(size)) + { + return Some(tile); + } + } + + let texture = self.push_texture(size, texture_kind)?; + texture.allocate(size) + } + + fn push_texture( + &mut self, + min_size: Size, + kind: AtlasTextureKind, + ) -> Option<&mut DirectXAtlasTexture> { + const DEFAULT_ATLAS_SIZE: Size = Size { + width: DevicePixels(1024), + height: DevicePixels(1024), + }; + // Max texture size for DirectX. See: + // https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-limits + const MAX_ATLAS_SIZE: Size = Size { + width: DevicePixels(16384), + height: DevicePixels(16384), + }; + let size = min_size.min(&MAX_ATLAS_SIZE).max(&DEFAULT_ATLAS_SIZE); + let pixel_format; + let bind_flag; + let bytes_per_pixel; + match kind { + AtlasTextureKind::Monochrome => { + pixel_format = DXGI_FORMAT_R8_UNORM; + bind_flag = D3D11_BIND_SHADER_RESOURCE; + bytes_per_pixel = 1; + } + AtlasTextureKind::Polychrome => { + pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM; + bind_flag = D3D11_BIND_SHADER_RESOURCE; + bytes_per_pixel = 4; + } + AtlasTextureKind::Subpixel => { + pixel_format = DXGI_FORMAT_R8G8B8A8_UNORM; + bind_flag = D3D11_BIND_SHADER_RESOURCE; + bytes_per_pixel = 4; + } + } + let texture_desc = D3D11_TEXTURE2D_DESC { + Width: size.width.0 as u32, + Height: size.height.0 as u32, + MipLevels: 1, + ArraySize: 1, + Format: pixel_format, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: bind_flag.0 as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + let mut texture: Option = None; + unsafe { + // This only returns None if the device is lost, which we will recreate later. + // So it's ok to return None here. + self.device + .CreateTexture2D(&texture_desc, None, Some(&mut texture)) + .ok()?; + } + let texture = texture.unwrap(); + + let texture_list = match kind { + AtlasTextureKind::Monochrome => &mut self.monochrome_textures, + AtlasTextureKind::Polychrome => &mut self.polychrome_textures, + AtlasTextureKind::Subpixel => &mut self.subpixel_textures, + }; + let index = texture_list.free_list.pop(); + let view = unsafe { + let mut view = None; + self.device + .CreateShaderResourceView(&texture, None, Some(&mut view)) + .ok()?; + [view] + }; + let atlas_texture = DirectXAtlasTexture { + id: AtlasTextureId { + index: index.unwrap_or(texture_list.textures.len()) as u32, + kind, + }, + bytes_per_pixel, + allocator: etagere::BucketedAtlasAllocator::new(device_size_to_etagere(size)), + texture, + view, + live_atlas_keys: 0, + }; + if let Some(ix) = index { + texture_list.textures[ix] = Some(atlas_texture); + texture_list.textures.get_mut(ix).unwrap().as_mut() + } else { + texture_list.textures.push(Some(atlas_texture)); + texture_list.textures.last_mut().unwrap().as_mut() + } + } + + fn texture(&self, id: AtlasTextureId) -> Option<&DirectXAtlasTexture> { + let textures = match id.kind { + AtlasTextureKind::Monochrome => &self.monochrome_textures, + AtlasTextureKind::Polychrome => &self.polychrome_textures, + AtlasTextureKind::Subpixel => &self.subpixel_textures, + }; + textures.textures.get(id.index as usize)?.as_ref() + } +} + +impl DirectXAtlasTexture { + fn allocate(&mut self, size: Size) -> Option { + let allocation = self.allocator.allocate(device_size_to_etagere(size))?; + let tile = AtlasTile { + texture_id: self.id, + tile_id: allocation.id.into(), + bounds: Bounds { + origin: etagere_point_to_device(allocation.rectangle.min), + size, + }, + padding: 0, + }; + self.live_atlas_keys += 1; + Some(tile) + } + + fn upload( + &self, + device_context: &ID3D11DeviceContext, + bounds: Bounds, + bytes: &[u8], + ) { + // `UpdateSubresource` reads `row_pitch * height` bytes from `bytes` based on the + // `D3D11_BOX` below. If the caller hands us a slice shorter than that, the driver would + // over-read past the end of the source buffer (potentially by multiple megabytes), so bail + // out instead. This is a first-insert path rather than a per-frame one, so the check is + // effectively free. + let row_bytes = bounds.size.width.to_bytes(self.bytes_per_pixel as u8) as usize; + let expected = row_bytes * bounds.size.height.0.max(0) as usize; + if bytes.len() < expected { + log::error!( + "DirectXAtlasTexture::upload: source slice is {} bytes but the {}x{} region \ + requires {} bytes; skipping upload to avoid a driver over-read", + bytes.len(), + bounds.size.width.0, + bounds.size.height.0, + expected, + ); + return; + } + unsafe { + device_context.UpdateSubresource( + &self.texture, + 0, + Some(&D3D11_BOX { + left: bounds.left().0 as u32, + top: bounds.top().0 as u32, + front: 0, + right: bounds.right().0 as u32, + bottom: bounds.bottom().0 as u32, + back: 1, + }), + bytes.as_ptr() as _, + bounds.size.width.to_bytes(self.bytes_per_pixel as u8), + 0, + ); + } + } + + fn decrement_ref_count(&mut self) { + self.live_atlas_keys -= 1; + } + + fn is_unreferenced(&mut self) -> bool { + self.live_atlas_keys == 0 + } +} + +fn device_size_to_etagere(size: Size) -> etagere::Size { + etagere::Size::new(size.width.into(), size.height.into()) +} + +fn etagere_point_to_device(value: etagere::Point) -> Point { + Point { + x: DevicePixels::from(value.x), + y: DevicePixels::from(value.y), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use gpui::{ImageId, RenderImageParams}; + use std::borrow::Cow; + use windows::Win32::{ + Foundation::HMODULE, + Graphics::{ + Direct3D::D3D_DRIVER_TYPE_WARP, + Direct3D11::{D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_SDK_VERSION, D3D11CreateDevice}, + }, + }; + + fn create_atlas() -> Option { + let mut device: Option = None; + let mut device_context: Option = None; + unsafe { + D3D11CreateDevice( + None, + D3D_DRIVER_TYPE_WARP, + HMODULE::default(), + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + None, + D3D11_SDK_VERSION, + Some(&mut device), + None, + Some(&mut device_context), + ) + } + .ok()?; + Some(DirectXAtlas::new(&device?, &device_context?)) + } + + fn make_image_key(image_id: usize) -> AtlasKey { + AtlasKey::Image(RenderImageParams { + image_id: ImageId(image_id), + frame_index: 0, + }) + } + + fn insert_tile(atlas: &DirectXAtlas, key: AtlasKey, size: Size) -> AtlasTile { + atlas + .get_or_insert_with(key, &mut || { + let byte_count = (size.width.0 as usize) * (size.height.0 as usize) * 4; + Ok(Some((size, Cow::Owned(vec![0u8; byte_count])))) + }) + .expect("allocation should succeed") + .expect("callback returns Some") + } + + #[test] + fn test_remove_deallocates_tile_space_for_reuse() { + let Some(atlas) = create_atlas() else { + return; + }; + + let small = Size { + width: DevicePixels(64), + height: DevicePixels(64), + }; + let big = Size { + width: DevicePixels(700), + height: DevicePixels(700), + }; + + let keeper_key = make_image_key(1); + let big_key_a = make_image_key(2); + let big_key_b = make_image_key(3); + + let keeper_tile = insert_tile(&atlas, keeper_key, small); + let tile_a = insert_tile(&atlas, big_key_a.clone(), big); + assert_eq!(keeper_tile.texture_id, tile_a.texture_id); + + atlas.remove(&big_key_a); + + let tile_b = insert_tile(&atlas, big_key_b, big); + assert_eq!(tile_b.texture_id, keeper_tile.texture_id); + } +} diff --git a/vendor/gpui-pre-windows/src/directx_devices.rs b/vendor/gpui-pre-windows/src/directx_devices.rs new file mode 100644 index 00000000..8e65e6e6 --- /dev/null +++ b/vendor/gpui-pre-windows/src/directx_devices.rs @@ -0,0 +1,194 @@ +use anyhow::{Context, Result}; +use gpui_util::ResultExt; +use itertools::Itertools; +use windows::Win32::{ + Foundation::HMODULE, + Graphics::{ + Direct3D::{ + D3D_DRIVER_TYPE_UNKNOWN, D3D_FEATURE_LEVEL, D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, + }, + Direct3D11::{ + D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_CREATE_DEVICE_DEBUG, + D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS, + D3D11_SDK_VERSION, D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, + }, + Dxgi::{ + CreateDXGIFactory2, DXGI_CREATE_FACTORY_DEBUG, DXGI_CREATE_FACTORY_FLAGS, + IDXGIAdapter1, IDXGIFactory6, + }, + }, +}; +use windows::core::Interface; + +pub(crate) fn try_to_recover_from_device_lost(mut f: impl FnMut() -> Result) -> Result { + (0..5) + .map(|i| { + if i > 0 { + // Add a small delay before retrying + std::thread::sleep(std::time::Duration::from_millis(100 + i * 10)); + } + f() + }) + .find_or_last(Result::is_ok) + .unwrap() + .context("DirectXRenderer failed to recover from lost device after multiple attempts") +} + +#[derive(Clone)] +pub(crate) struct DirectXDevices { + pub(crate) adapter: IDXGIAdapter1, + pub(crate) dxgi_factory: IDXGIFactory6, + pub(crate) device: ID3D11Device, + pub(crate) device_context: ID3D11DeviceContext, +} + +impl DirectXDevices { + pub(crate) fn new() -> Result { + let debug_layer_available = check_debug_layer_available(); + let dxgi_factory = + get_dxgi_factory(debug_layer_available).context("Creating DXGI factory")?; + let (adapter, device, device_context, feature_level) = + get_adapter(&dxgi_factory, debug_layer_available).context("Getting DXGI adapter")?; + match feature_level { + D3D_FEATURE_LEVEL_11_1 => { + log::info!("Created device with Direct3D 11.1 feature level.") + } + D3D_FEATURE_LEVEL_11_0 => { + log::info!("Created device with Direct3D 11.0 feature level.") + } + D3D_FEATURE_LEVEL_10_1 => { + log::info!("Created device with Direct3D 10.1 feature level.") + } + _ => unreachable!(), + } + + Ok(Self { + adapter, + dxgi_factory, + device, + device_context, + }) + } +} + +#[inline] +fn check_debug_layer_available() -> bool { + #[cfg(debug_assertions)] + { + use windows::Win32::Graphics::Dxgi::{DXGIGetDebugInterface1, IDXGIInfoQueue}; + + unsafe { DXGIGetDebugInterface1::(0) } + .log_err() + .is_some() + } + #[cfg(not(debug_assertions))] + { + false + } +} + +#[inline] +fn get_dxgi_factory(debug_layer_available: bool) -> Result { + let factory_flag = if debug_layer_available { + DXGI_CREATE_FACTORY_DEBUG + } else { + #[cfg(debug_assertions)] + log::warn!( + "Failed to get DXGI debug interface. DirectX debugging features will be disabled." + ); + DXGI_CREATE_FACTORY_FLAGS::default() + }; + unsafe { Ok(CreateDXGIFactory2(factory_flag)?) } +} + +#[inline] +fn get_adapter( + dxgi_factory: &IDXGIFactory6, + debug_layer_available: bool, +) -> Result<( + IDXGIAdapter1, + ID3D11Device, + ID3D11DeviceContext, + D3D_FEATURE_LEVEL, +)> { + for adapter_index in 0.. { + let adapter: IDXGIAdapter1 = unsafe { dxgi_factory.EnumAdapters(adapter_index)?.cast()? }; + if let Ok(desc) = unsafe { adapter.GetDesc1() } { + let gpu_name = String::from_utf16_lossy(&desc.Description) + .trim_matches(char::from(0)) + .to_string(); + log::info!("Using GPU: {}", gpu_name); + } + // Check to see whether the adapter supports Direct3D 11 and create + // the device if it does. + let mut context: Option = None; + let mut feature_level = D3D_FEATURE_LEVEL::default(); + if let Some(device) = get_device( + &adapter, + Some(&mut context), + Some(&mut feature_level), + debug_layer_available, + ) + .log_err() + { + return Ok((adapter, device, context.unwrap(), feature_level)); + } + } + + unreachable!() +} + +#[inline] +fn get_device( + adapter: &IDXGIAdapter1, + context: Option<*mut Option>, + feature_level: Option<*mut D3D_FEATURE_LEVEL>, + debug_layer_available: bool, +) -> Result { + let mut device: Option = None; + let device_flags = if debug_layer_available { + D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG + } else { + D3D11_CREATE_DEVICE_BGRA_SUPPORT + }; + unsafe { + D3D11CreateDevice( + adapter, + D3D_DRIVER_TYPE_UNKNOWN, + HMODULE::default(), + device_flags, + // 4x MSAA is required for Direct3D Feature Level 10.1 or better + Some(&[ + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + ]), + D3D11_SDK_VERSION, + Some(&mut device), + feature_level, + context, + )?; + } + let device = device.unwrap(); + let mut data = D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS::default(); + unsafe { + device + .CheckFeatureSupport( + D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, + &mut data as *mut _ as _, + std::mem::size_of::() as u32, + ) + .context("Checking GPU device feature support")?; + } + if data + .ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x + .as_bool() + { + Ok(device) + } else { + Err(anyhow::anyhow!( + "Required feature StructuredBuffer is not supported by GPU/driver" + )) + } +} diff --git a/vendor/gpui-pre-windows/src/directx_renderer.rs b/vendor/gpui-pre-windows/src/directx_renderer.rs new file mode 100644 index 00000000..f8b86bc2 --- /dev/null +++ b/vendor/gpui-pre-windows/src/directx_renderer.rs @@ -0,0 +1,2070 @@ +use std::{ + slice, + sync::{Arc, OnceLock}, +}; + +use anyhow::{Context, Result}; +use gpui_util::ResultExt; +use windows::{ + Win32::{ + Foundation::HWND, + Graphics::{ + Direct3D::*, + Direct3D11::*, + DirectComposition::*, + DirectWrite::*, + Dxgi::{Common::*, *}, + }, + }, + core::{HSTRING, Interface}, +}; + +use crate::directx_renderer::shader_resources::{RawShaderBytes, ShaderModule, ShaderTarget}; +use crate::*; +use gpui::*; + +pub(crate) const DISABLE_DIRECT_COMPOSITION: &str = "GPUI_DISABLE_DIRECT_COMPOSITION"; +const RENDER_TARGET_FORMAT: DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM; +// This configuration is used for MSAA rendering on paths only, and it's guaranteed to be supported by DirectX 11. +const PATH_MULTISAMPLE_COUNT: u32 = 4; +const MAX_INSTANCE_BUFFER_SIZE: usize = 256 * 1024 * 1024; + +pub(crate) struct FontInfo { + pub gamma_ratios: [f32; 4], + pub grayscale_enhanced_contrast: f32, + pub subpixel_enhanced_contrast: f32, + pub is_bgr: bool, +} + +pub(crate) struct DirectXRenderer { + hwnd: HWND, + atlas: Arc, + devices: Option, + resources: Option, + globals: DirectXGlobalElements, + pipelines: DirectXRenderPipelines, + direct_composition: Option, + font_info: &'static FontInfo, + + width: u32, + height: u32, + + /// Whether we want to skip drwaing due to device lost events. + /// + /// In that case we want to discard the first frame that we draw as we got reset in the middle of a frame + /// meaning we lost all the allocated gpu textures and scene resources. + skip_draws: bool, +} + +/// Direct3D objects +#[derive(Clone)] +pub(crate) struct DirectXRendererDevices { + pub(crate) adapter: IDXGIAdapter1, + pub(crate) dxgi_factory: IDXGIFactory6, + pub(crate) device: ID3D11Device, + pub(crate) device_context: ID3D11DeviceContext, + dxgi_device: Option, + annotation: Option, +} + +struct DirectXResources { + // Direct3D rendering objects + swap_chain: IDXGISwapChain1, + render_target: Option, + render_target_view: Option, + + // Path intermediate textures (with MSAA) + path_intermediate_texture: ID3D11Texture2D, + path_intermediate_srv: Option, + path_intermediate_msaa_texture: ID3D11Texture2D, + path_intermediate_msaa_view: Option, + + // Cached viewport + viewport: D3D11_VIEWPORT, +} + +struct DirectXRenderPipelines { + shadow_pipeline: PipelineState, + quad_pipeline: PipelineState, + path_rasterization_pipeline: PipelineState, + path_sprite_pipeline: PipelineState, + underline_pipeline: PipelineState, + mono_sprites: PipelineState, + subpixel_sprites: PipelineState, + poly_sprites: PipelineState, +} + +struct DirectXGlobalElements { + global_params_buffer: Option, + batch_params_buffer: Option, + sampler: Option, +} + +struct Annotation<'a>(&'a ID3DUserDefinedAnnotation); + +impl<'a> Annotation<'a> { + fn new(annotation: &'a ID3DUserDefinedAnnotation, label: HSTRING) -> Self { + unsafe { annotation.BeginEvent(&label) }; + Self(annotation) + } +} + +impl Drop for Annotation<'_> { + fn drop(&mut self) { + unsafe { self.0.EndEvent() }; + } +} + +struct DirectComposition { + comp_device: IDCompositionDevice, + comp_target: IDCompositionTarget, + comp_visual: IDCompositionVisual, +} + +impl DirectXRendererDevices { + pub(crate) fn new( + directx_devices: &DirectXDevices, + disable_direct_composition: bool, + ) -> Result { + let DirectXDevices { + adapter, + dxgi_factory, + device, + device_context, + } = directx_devices; + let dxgi_device = if disable_direct_composition { + None + } else { + Some(device.cast().context("Creating DXGI device")?) + }; + let annotation = device_context.cast().ok(); + + Ok(Self { + adapter: adapter.clone(), + dxgi_factory: dxgi_factory.clone(), + device: device.clone(), + device_context: device_context.clone(), + dxgi_device, + annotation, + }) + } +} + +impl DirectXRenderer { + pub(crate) fn new( + hwnd: HWND, + directx_devices: &DirectXDevices, + disable_direct_composition: bool, + ) -> Result { + if disable_direct_composition { + log::info!("Direct Composition is disabled."); + } + + let devices = DirectXRendererDevices::new(directx_devices, disable_direct_composition) + .context("Creating DirectX devices")?; + let atlas = Arc::new(DirectXAtlas::new(&devices.device, &devices.device_context)); + + let resources = DirectXResources::new(&devices, 1, 1, hwnd, disable_direct_composition) + .context("Creating DirectX resources")?; + let globals = DirectXGlobalElements::new(&devices.device) + .context("Creating DirectX global elements")?; + let pipelines = DirectXRenderPipelines::new(&devices.device) + .context("Creating DirectX render pipelines")?; + + let direct_composition = if disable_direct_composition { + None + } else { + let composition = DirectComposition::new(devices.dxgi_device.as_ref().unwrap(), hwnd) + .context("Creating DirectComposition")?; + composition + .set_swap_chain(&resources.swap_chain) + .context("Setting swap chain for DirectComposition")?; + Some(composition) + }; + + Ok(DirectXRenderer { + hwnd, + atlas, + devices: Some(devices), + resources: Some(resources), + globals, + pipelines, + direct_composition, + font_info: Self::get_font_info(), + width: 1, + height: 1, + skip_draws: false, + }) + } + + pub(crate) fn sprite_atlas(&self) -> Arc { + self.atlas.clone() + } + + fn pre_draw(&self, clear_color: &[f32; 4]) -> Result<()> { + let resources = self.resources.as_ref().expect("resources missing"); + let device_context = &self + .devices + .as_ref() + .expect("devices missing") + .device_context; + update_buffer( + device_context, + self.globals.global_params_buffer.as_ref().unwrap(), + &[GlobalParams { + gamma_ratios: self.font_info.gamma_ratios, + viewport_size: [resources.viewport.Width, resources.viewport.Height], + grayscale_enhanced_contrast: self.font_info.grayscale_enhanced_contrast, + subpixel_enhanced_contrast: self.font_info.subpixel_enhanced_contrast, + is_bgr: self.font_info.is_bgr as u32, + _pad: [0; 3], + }], + )?; + unsafe { + device_context.ClearRenderTargetView( + resources + .render_target_view + .as_ref() + .context("missing render target view")?, + clear_color, + ); + device_context + .OMSetRenderTargets(Some(slice::from_ref(&resources.render_target_view)), None); + device_context.RSSetViewports(Some(slice::from_ref(&resources.viewport))); + device_context + .VSSetConstantBuffers(0, Some(slice::from_ref(&self.globals.global_params_buffer))); + device_context + .VSSetConstantBuffers(1, Some(slice::from_ref(&self.globals.batch_params_buffer))); + device_context + .PSSetConstantBuffers(0, Some(slice::from_ref(&self.globals.global_params_buffer))); + } + Ok(()) + } + + #[inline] + fn present(&mut self) -> Result<()> { + let result = unsafe { + self.resources + .as_ref() + .expect("resources missing") + .swap_chain + .Present(0, DXGI_PRESENT(0)) + }; + result.ok().context("Presenting swap chain failed") + } + + pub(crate) fn handle_device_lost(&mut self, directx_devices: &DirectXDevices) -> Result<()> { + try_to_recover_from_device_lost(|| { + self.handle_device_lost_impl(directx_devices) + .context("DirectXRenderer handling device lost") + }) + } + + fn handle_device_lost_impl(&mut self, directx_devices: &DirectXDevices) -> Result<()> { + let disable_direct_composition = self.direct_composition.is_none(); + + unsafe { + #[cfg(debug_assertions)] + if let Some(devices) = &self.devices { + report_live_objects(&devices.device) + .context("Failed to report live objects after device lost") + .log_err(); + } + + self.resources.take(); + if let Some(devices) = &self.devices { + devices.device_context.OMSetRenderTargets(None, None); + devices.device_context.ClearState(); + devices.device_context.Flush(); + #[cfg(debug_assertions)] + report_live_objects(&devices.device) + .context("Failed to report live objects after device lost") + .log_err(); + } + + self.direct_composition.take(); + self.devices.take(); + } + + let devices = DirectXRendererDevices::new(directx_devices, disable_direct_composition) + .context("Recreating DirectX devices")?; + let resources = DirectXResources::new( + &devices, + self.width, + self.height, + self.hwnd, + disable_direct_composition, + ) + .context("Creating DirectX resources")?; + let globals = DirectXGlobalElements::new(&devices.device) + .context("Creating DirectXGlobalElements")?; + let pipelines = DirectXRenderPipelines::new(&devices.device) + .context("Creating DirectXRenderPipelines")?; + + let direct_composition = if disable_direct_composition { + None + } else { + let composition = + DirectComposition::new(devices.dxgi_device.as_ref().unwrap(), self.hwnd)?; + composition.set_swap_chain(&resources.swap_chain)?; + Some(composition) + }; + + self.atlas + .handle_device_lost(&devices.device, &devices.device_context); + + unsafe { + devices + .device_context + .OMSetRenderTargets(Some(slice::from_ref(&resources.render_target_view)), None); + } + self.devices = Some(devices); + self.resources = Some(resources); + self.globals = globals; + self.pipelines = pipelines; + self.direct_composition = direct_composition; + self.skip_draws = true; + Ok(()) + } + + pub(crate) fn draw( + &mut self, + scene: &Scene, + background_appearance: WindowBackgroundAppearance, + ) -> Result<()> { + if self.skip_draws { + // skip drawing this frame, we just recovered from a device lost event + // and so likely do not have the textures anymore that are required for drawing + return Ok(()); + } + self.render(scene, background_appearance)?; + self.present() + } + + /// Clear the render target for `background_appearance` and encode every + /// primitive batch of `scene` into it, without presenting. Shared by + /// [`draw`](Self::draw) (which then presents) and + /// [`render_to_image`](Self::render_to_image) (which reads the target back + /// instead), so the two cannot drift. + fn render( + &mut self, + scene: &Scene, + background_appearance: WindowBackgroundAppearance, + ) -> Result<()> { + self.pre_draw(&match background_appearance { + WindowBackgroundAppearance::Opaque => [1.0f32; 4], + _ => [0.0f32; 4], + })?; + self.upload_scene_buffers(scene)?; + + let annotation = self + .devices + .as_ref() + .and_then(|devices| devices.annotation.clone()) + .filter(|annotation| unsafe { annotation.GetStatus().as_bool() }); + for batch in scene.batches() { + let _annotation = annotation + .as_ref() + .map(|annotation| Annotation::new(annotation, HSTRING::from(batch.label()))); + match batch { + PrimitiveBatch::Shadows(range) => self.draw_shadows(range.start, range.len()), + PrimitiveBatch::Quads(range) => self.draw_quads(range.start, range.len()), + PrimitiveBatch::Paths(range) => { + let paths = &scene.paths[range]; + self.draw_paths_to_intermediate(paths)?; + self.draw_paths_from_intermediate(paths) + } + PrimitiveBatch::Underlines(range) => self.draw_underlines(range.start, range.len()), + PrimitiveBatch::MonochromeSprites { texture_id, range } => { + self.draw_monochrome_sprites(texture_id, range.start, range.len()) + } + PrimitiveBatch::SubpixelSprites { texture_id, range } => { + self.draw_subpixel_sprites(texture_id, range.start, range.len()) + } + PrimitiveBatch::PolychromeSprites { texture_id, range } => { + self.draw_polychrome_sprites(texture_id, range.start, range.len()) + } + PrimitiveBatch::Surfaces(range) => self.draw_surfaces(&scene.surfaces[range]), + } + .with_context(|| { + format!( + "scene too large:\ + {} paths, {} shadows, {} quads, {} underlines, {} mono, {} subpixel, {} poly, {} surfaces", + scene.paths.len(), + scene.shadows.len(), + scene.quads.len(), + scene.underlines.len(), + scene.monochrome_sprites.len(), + scene.subpixel_sprites.len(), + scene.polychrome_sprites.len(), + scene.surfaces.len(), + ) + })?; + } + Ok(()) + } + + /// Render `scene` to an offscreen CPU image **without presenting** so + /// the window need never be shown or visible (the macOS headless path + /// goes through MetalRenderer; this is the Windows analogue). Draws into + /// the existing render target, copies it into a `D3D11_USAGE_STAGING` + /// texture, maps it, and converts BGRA to RGBA. + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn render_to_image( + &mut self, + scene: &Scene, + background_appearance: WindowBackgroundAppearance, + ) -> Result { + // A pending device-lost recovery (`skip_draws`) leaves the atlas holding + // tile references from the previous device; drawing before the forced + // re-render rebuilds them panics in `DirectXAtlasTextures::texture`. + anyhow::ensure!( + !self.skip_draws, + "render_to_image unavailable while recovering from a lost device" + ); + self.render(scene, background_appearance)?; + + let devices = self.devices.as_ref().context("devices missing")?; + let device = &devices.device; + let context = &devices.device_context; + let resources = self.resources.as_ref().context("resources missing")?; + let render_target = resources + .render_target + .as_ref() + .context("render target missing")?; + + // A CPU-readable copy of the render target. + let mut desc = D3D11_TEXTURE2D_DESC::default(); + unsafe { render_target.GetDesc(&mut desc) }; + let width = desc.Width; + let height = desc.Height; + let staging_desc = D3D11_TEXTURE2D_DESC { + Usage: D3D11_USAGE_STAGING, + BindFlags: 0, + CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32, + MiscFlags: 0, + MipLevels: 1, + ArraySize: 1, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + ..desc + }; + let mut staging: Option = None; + unsafe { device.CreateTexture2D(&staging_desc, None, Some(&mut staging))? }; + let staging = staging.context("creating staging texture")?; + unsafe { context.CopyResource(&staging, render_target) }; + + let mut mapped = D3D11_MAPPED_SUBRESOURCE::default(); + unsafe { context.Map(&staging, 0, D3D11_MAP_READ, 0, Some(&mut mapped))? }; + let row_bytes = (width as usize) * 4; + let mut pixels = vec![0u8; row_bytes * height as usize]; + // SAFETY: `Map` succeeded, so `pData` points at `RowPitch * height` + // readable bytes for as long as the mapping is held, and `RowPitch >= + // row_bytes` (it only ever adds trailing padding). `pixels` is sized + // `row_bytes * height`, so every copy stays in bounds on both sides, + // and the regions cannot overlap (`pixels` is a fresh allocation). + unsafe { + let src = mapped.pData as *const u8; + for row in 0..height as usize { + let s = src.add(row * mapped.RowPitch as usize); + let d = pixels.as_mut_ptr().add(row * row_bytes); + std::ptr::copy_nonoverlapping(s, d, row_bytes); + } + context.Unmap(&staging, 0); + } + // The render target is BGRA; image::RgbaImage expects RGBA. + for px in pixels.chunks_exact_mut(4) { + px.swap(0, 2); + } + image::RgbaImage::from_raw(width, height, pixels) + .context("Failed to build RgbaImage from staging readback") + } + + pub(crate) fn resize(&mut self, new_size: Size) -> Result<()> { + let width = new_size.width.0.max(1) as u32; + let height = new_size.height.0.max(1) as u32; + if self.width == width && self.height == height { + return Ok(()); + } + self.width = width; + self.height = height; + + // Clear the render target before resizing + let devices = self.devices.as_ref().context("devices missing")?; + unsafe { devices.device_context.OMSetRenderTargets(None, None) }; + let resources = self.resources.as_mut().context("resources missing")?; + resources.render_target.take(); + resources.render_target_view.take(); + + // Resizing the swap chain requires a call to the underlying DXGI adapter, which can return the device removed error. + // The app might have moved to a monitor that's attached to a different graphics device. + // When a graphics device is removed or reset, the desktop resolution often changes, resulting in a window size change. + // But here we just return the error, because we are handling device lost scenarios elsewhere. + unsafe { + resources + .swap_chain + .ResizeBuffers( + BUFFER_COUNT as u32, + width, + height, + RENDER_TARGET_FORMAT, + DXGI_SWAP_CHAIN_FLAG(0), + ) + .context("Failed to resize swap chain")?; + } + + resources.recreate_resources(devices, width, height)?; + + unsafe { + devices + .device_context + .OMSetRenderTargets(Some(slice::from_ref(&resources.render_target_view)), None); + } + + Ok(()) + } + + fn upload_scene_buffers(&mut self, scene: &Scene) -> Result<()> { + let devices = self.devices.as_ref().context("devices missing")?; + + if !scene.shadows.is_empty() { + self.pipelines.shadow_pipeline.update_buffer( + &devices.device, + &devices.device_context, + &scene.shadows, + )?; + } + + if !scene.quads.is_empty() { + self.pipelines.quad_pipeline.update_buffer( + &devices.device, + &devices.device_context, + &scene.quads, + )?; + } + + if !scene.underlines.is_empty() { + self.pipelines.underline_pipeline.update_buffer( + &devices.device, + &devices.device_context, + &scene.underlines, + )?; + } + + if !scene.monochrome_sprites.is_empty() { + self.pipelines.mono_sprites.update_buffer( + &devices.device, + &devices.device_context, + &scene.monochrome_sprites, + )?; + } + + if !scene.subpixel_sprites.is_empty() { + self.pipelines.subpixel_sprites.update_buffer( + &devices.device, + &devices.device_context, + &scene.subpixel_sprites, + )?; + } + + if !scene.polychrome_sprites.is_empty() { + self.pipelines.poly_sprites.update_buffer( + &devices.device, + &devices.device_context, + &scene.polychrome_sprites, + )?; + } + + Ok(()) + } + + fn draw_shadows(&mut self, start: usize, len: usize) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + self.pipelines.shadow_pipeline.draw_range( + &devices.device_context, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + start as u32, + len as u32, + ) + } + + fn draw_quads(&mut self, start: usize, len: usize) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + self.pipelines.quad_pipeline.draw_range( + &devices.device_context, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + start as u32, + len as u32, + ) + } + + fn draw_paths_to_intermediate(&mut self, paths: &[Path]) -> Result<()> { + if paths.is_empty() { + return Ok(()); + } + + let devices = self.devices.as_ref().context("devices missing")?; + let resources = self.resources.as_ref().context("resources missing")?; + // Clear intermediate MSAA texture + unsafe { + devices.device_context.ClearRenderTargetView( + resources.path_intermediate_msaa_view.as_ref().unwrap(), + &[0.0; 4], + ); + // Set intermediate MSAA texture as render target + devices.device_context.OMSetRenderTargets( + Some(slice::from_ref(&resources.path_intermediate_msaa_view)), + None, + ); + } + + // Collect all vertices and sprites for a single draw call + let mut vertices = Vec::new(); + + for path in paths { + vertices.extend(path.vertices.iter().map(|v| PathRasterizationSprite { + xy_position: v.xy_position, + st_position: v.st_position, + color: path.color, + bounds: path.clipped_bounds(), + })); + } + + self.pipelines.path_rasterization_pipeline.update_buffer( + &devices.device, + &devices.device_context, + &vertices, + )?; + + self.pipelines.path_rasterization_pipeline.draw( + &devices.device_context, + D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + vertices.len() as u32, + 1, + )?; + + // Resolve MSAA to non-MSAA intermediate texture + unsafe { + devices.device_context.ResolveSubresource( + &resources.path_intermediate_texture, + 0, + &resources.path_intermediate_msaa_texture, + 0, + RENDER_TARGET_FORMAT, + ); + // Restore main render target + devices + .device_context + .OMSetRenderTargets(Some(slice::from_ref(&resources.render_target_view)), None); + } + + Ok(()) + } + + fn draw_paths_from_intermediate(&mut self, paths: &[Path]) -> Result<()> { + let Some(first_path) = paths.first() else { + return Ok(()); + }; + + // When copying paths from the intermediate texture to the drawable, + // each pixel must only be copied once, in case of transparent paths. + // + // If all paths have the same draw order, then their bounds are all + // disjoint, so we can copy each path's bounds individually. If this + // batch combines different draw orders, we perform a single copy + // for a minimal spanning rect. + let sprites = if paths.last().unwrap().order == first_path.order { + paths + .iter() + .map(|path| PathSprite { + bounds: path.clipped_bounds(), + }) + .collect::>() + } else { + let mut bounds = first_path.clipped_bounds(); + for path in paths.iter().skip(1) { + bounds = bounds.union(&path.clipped_bounds()); + } + vec![PathSprite { bounds }] + }; + + let devices = self.devices.as_ref().context("devices missing")?; + let resources = self.resources.as_ref().context("resources missing")?; + self.pipelines.path_sprite_pipeline.update_buffer( + &devices.device, + &devices.device_context, + &sprites, + )?; + + // Draw the sprites with the path texture + self.pipelines.path_sprite_pipeline.draw_with_texture( + &devices.device_context, + slice::from_ref(&resources.path_intermediate_srv), + slice::from_ref(&self.globals.sampler), + sprites.len() as u32, + ) + } + + fn draw_underlines(&mut self, start: usize, len: usize) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + self.pipelines.underline_pipeline.draw_range( + &devices.device_context, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + start as u32, + len as u32, + ) + } + + fn draw_monochrome_sprites( + &mut self, + texture_id: AtlasTextureId, + start: usize, + len: usize, + ) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + let Some(texture_view) = self.atlas.get_texture_view(texture_id) else { + return Ok(()); + }; + self.pipelines.mono_sprites.draw_range_with_texture( + &devices.device_context, + &texture_view, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + slice::from_ref(&self.globals.sampler), + start as u32, + len as u32, + ) + } + + fn draw_subpixel_sprites( + &mut self, + texture_id: AtlasTextureId, + start: usize, + len: usize, + ) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + let Some(texture_view) = self.atlas.get_texture_view(texture_id) else { + return Ok(()); + }; + self.pipelines.subpixel_sprites.draw_range_with_texture( + &devices.device_context, + &texture_view, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + slice::from_ref(&self.globals.sampler), + start as u32, + len as u32, + ) + } + + fn draw_polychrome_sprites( + &mut self, + texture_id: AtlasTextureId, + start: usize, + len: usize, + ) -> Result<()> { + if len == 0 { + return Ok(()); + } + let devices = self.devices.as_ref().context("devices missing")?; + let Some(texture_view) = self.atlas.get_texture_view(texture_id) else { + return Ok(()); + }; + self.pipelines.poly_sprites.draw_range_with_texture( + &devices.device_context, + &texture_view, + self.globals + .batch_params_buffer + .as_ref() + .context("batch params buffer missing")?, + slice::from_ref(&self.globals.sampler), + start as u32, + len as u32, + ) + } + + fn draw_surfaces(&mut self, surfaces: &[PaintSurface]) -> Result<()> { + if surfaces.is_empty() { + return Ok(()); + } + Ok(()) + } + + pub(crate) fn gpu_specs(&self) -> Result { + let devices = self.devices.as_ref().context("devices missing")?; + let desc = unsafe { devices.adapter.GetDesc1() }?; + let is_software_emulated = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32) != 0; + let device_name = String::from_utf16_lossy(&desc.Description) + .trim_matches(char::from(0)) + .to_string(); + let driver_name = match desc.VendorId { + 0x10DE => "NVIDIA Corporation".to_string(), + 0x1002 => "AMD Corporation".to_string(), + 0x8086 => "Intel Corporation".to_string(), + id => format!("Unknown Vendor (ID: {:#X})", id), + }; + let driver_version = match desc.VendorId { + 0x10DE => nvidia::get_driver_version(), + 0x1002 => amd::get_driver_version(), + // For Intel and other vendors, we use the DXGI API to get the driver version. + _ => dxgi::get_driver_version(&devices.adapter), + } + .context("Failed to get gpu driver info") + .log_err() + .unwrap_or("Unknown Driver".to_string()); + Ok(GpuSpecs { + is_software_emulated, + device_name, + driver_name, + driver_info: driver_version, + }) + } + + pub(crate) fn get_font_info() -> &'static FontInfo { + static CACHED_FONT_INFO: OnceLock = OnceLock::new(); + CACHED_FONT_INFO.get_or_init(|| unsafe { + let factory: IDWriteFactory5 = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let render_params: IDWriteRenderingParams1 = + factory.CreateRenderingParams().unwrap().cast().unwrap(); + FontInfo { + gamma_ratios: gpui::get_gamma_correction_ratios(render_params.GetGamma()), + grayscale_enhanced_contrast: render_params.GetGrayscaleEnhancedContrast(), + subpixel_enhanced_contrast: render_params.GetEnhancedContrast(), + is_bgr: render_params.GetPixelGeometry() == DWRITE_PIXEL_GEOMETRY_BGR, + } + }) + } + + pub(crate) fn mark_drawable(&mut self) { + self.skip_draws = false; + } +} + +impl DirectXResources { + pub fn new( + devices: &DirectXRendererDevices, + width: u32, + height: u32, + hwnd: HWND, + disable_direct_composition: bool, + ) -> Result { + let swap_chain = if disable_direct_composition { + create_swap_chain(&devices.dxgi_factory, &devices.device, hwnd, width, height)? + } else { + create_swap_chain_for_composition( + &devices.dxgi_factory, + &devices.device, + width, + height, + )? + }; + + let ( + render_target, + render_target_view, + path_intermediate_texture, + path_intermediate_srv, + path_intermediate_msaa_texture, + path_intermediate_msaa_view, + viewport, + ) = create_resources(devices, &swap_chain, width, height)?; + set_rasterizer_state(&devices.device, &devices.device_context)?; + + Ok(Self { + swap_chain, + render_target: Some(render_target), + render_target_view, + path_intermediate_texture, + path_intermediate_msaa_texture, + path_intermediate_msaa_view, + path_intermediate_srv, + viewport, + }) + } + + #[inline] + fn recreate_resources( + &mut self, + devices: &DirectXRendererDevices, + width: u32, + height: u32, + ) -> Result<()> { + let ( + render_target, + render_target_view, + path_intermediate_texture, + path_intermediate_srv, + path_intermediate_msaa_texture, + path_intermediate_msaa_view, + viewport, + ) = create_resources(devices, &self.swap_chain, width, height)?; + self.render_target = Some(render_target); + self.render_target_view = render_target_view; + self.path_intermediate_texture = path_intermediate_texture; + self.path_intermediate_msaa_texture = path_intermediate_msaa_texture; + self.path_intermediate_msaa_view = path_intermediate_msaa_view; + self.path_intermediate_srv = path_intermediate_srv; + self.viewport = viewport; + Ok(()) + } +} + +impl DirectXRenderPipelines { + pub fn new(device: &ID3D11Device) -> Result { + let shadow_pipeline = PipelineState::new( + device, + "shadow_pipeline", + ShaderModule::Shadow, + 4, + create_blend_state(device)?, + )?; + let quad_pipeline = PipelineState::new( + device, + "quad_pipeline", + ShaderModule::Quad, + 64, + create_blend_state(device)?, + )?; + let path_rasterization_pipeline = PipelineState::new( + device, + "path_rasterization_pipeline", + ShaderModule::PathRasterization, + 32, + create_blend_state_for_path_rasterization(device)?, + )?; + let path_sprite_pipeline = PipelineState::new( + device, + "path_sprite_pipeline", + ShaderModule::PathSprite, + 4, + create_blend_state_for_path_sprite(device)?, + )?; + let underline_pipeline = PipelineState::new( + device, + "underline_pipeline", + ShaderModule::Underline, + 4, + create_blend_state(device)?, + )?; + let mono_sprites = PipelineState::new( + device, + "monochrome_sprite_pipeline", + ShaderModule::MonochromeSprite, + 512, + create_blend_state(device)?, + )?; + let subpixel_sprites = PipelineState::new( + device, + "subpixel_sprite_pipeline", + ShaderModule::SubpixelSprite, + 512, + create_blend_state_for_subpixel_rendering(device)?, + )?; + let poly_sprites = PipelineState::new( + device, + "polychrome_sprite_pipeline", + ShaderModule::PolychromeSprite, + 16, + create_blend_state(device)?, + )?; + + Ok(Self { + shadow_pipeline, + quad_pipeline, + path_rasterization_pipeline, + path_sprite_pipeline, + underline_pipeline, + mono_sprites, + subpixel_sprites, + poly_sprites, + }) + } +} + +impl DirectComposition { + pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result { + let comp_device = get_comp_device(dxgi_device)?; + let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?; + let comp_visual = unsafe { comp_device.CreateVisual() }?; + + Ok(Self { + comp_device, + comp_target, + comp_visual, + }) + } + + pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> { + unsafe { + self.comp_visual.SetContent(swap_chain)?; + self.comp_target.SetRoot(&self.comp_visual)?; + self.comp_device.Commit()?; + } + Ok(()) + } +} + +impl DirectXGlobalElements { + pub fn new(device: &ID3D11Device) -> Result { + let global_params_buffer = create_constant_buffer::(device)?; + let batch_params_buffer = create_constant_buffer::(device)?; + + let sampler = unsafe { + let desc = D3D11_SAMPLER_DESC { + Filter: D3D11_FILTER_MIN_MAG_MIP_LINEAR, + AddressU: D3D11_TEXTURE_ADDRESS_WRAP, + AddressV: D3D11_TEXTURE_ADDRESS_WRAP, + AddressW: D3D11_TEXTURE_ADDRESS_WRAP, + MipLODBias: 0.0, + MaxAnisotropy: 1, + ComparisonFunc: D3D11_COMPARISON_ALWAYS, + BorderColor: [0.0; 4], + MinLOD: 0.0, + MaxLOD: D3D11_FLOAT32_MAX, + }; + let mut output = None; + device.CreateSamplerState(&desc, Some(&mut output))?; + output + }; + + Ok(Self { + global_params_buffer, + batch_params_buffer, + sampler, + }) + } +} + +#[derive(Debug, Default)] +#[repr(C)] +struct GlobalParams { + gamma_ratios: [f32; 4], + viewport_size: [f32; 2], + grayscale_enhanced_contrast: f32, + subpixel_enhanced_contrast: f32, + is_bgr: u32, + _pad: [u32; 3], +} + +#[derive(Clone, Copy, Debug, Default)] +#[repr(C, align(16))] +struct BatchParams { + start_index: u32, + _padding: [u32; 3], +} + +const _: () = assert!(std::mem::size_of::() == 16); + +struct PipelineState { + label: &'static str, + vertex: ID3D11VertexShader, + fragment: ID3D11PixelShader, + buffer: ID3D11Buffer, + buffer_size: usize, + view: Option, + blend_state: ID3D11BlendState, + _marker: std::marker::PhantomData, +} + +impl PipelineState { + fn new( + device: &ID3D11Device, + label: &'static str, + shader_module: ShaderModule, + buffer_size: usize, + blend_state: ID3D11BlendState, + ) -> Result { + let vertex = { + let raw_shader = RawShaderBytes::new(shader_module, ShaderTarget::Vertex)?; + create_vertex_shader(device, raw_shader.as_bytes())? + }; + let fragment = { + let raw_shader = RawShaderBytes::new(shader_module, ShaderTarget::Fragment)?; + create_fragment_shader(device, raw_shader.as_bytes())? + }; + let buffer = create_buffer(device, std::mem::size_of::(), buffer_size)?; + let view = create_buffer_view(device, &buffer)?; + + Ok(PipelineState { + label, + vertex, + fragment, + buffer, + buffer_size, + view, + blend_state, + _marker: std::marker::PhantomData, + }) + } + + fn update_buffer( + &mut self, + device: &ID3D11Device, + device_context: &ID3D11DeviceContext, + data: &[T], + ) -> Result<()> { + if self.buffer_size < data.len() { + let element_size = std::mem::size_of::(); + let required_size = std::mem::size_of_val(data); + anyhow::ensure!( + required_size <= MAX_INSTANCE_BUFFER_SIZE, + "{} buffer needs {required_size} bytes, above the maximum of {MAX_INSTANCE_BUFFER_SIZE}", + self.label + ); + let new_buffer_size = data + .len() + .next_power_of_two() + .min(MAX_INSTANCE_BUFFER_SIZE / element_size); + log::debug!( + "Updating {} buffer size from {} to {}", + self.label, + self.buffer_size, + new_buffer_size + ); + let buffer = create_buffer(device, std::mem::size_of::(), new_buffer_size)?; + let view = create_buffer_view(device, &buffer)?; + self.buffer = buffer; + self.view = view; + self.buffer_size = new_buffer_size; + } + update_buffer(device_context, &self.buffer, data) + } + + fn draw( + &self, + device_context: &ID3D11DeviceContext, + topology: D3D_PRIMITIVE_TOPOLOGY, + vertex_count: u32, + instance_count: u32, + ) -> Result<()> { + set_pipeline_state( + device_context, + slice::from_ref(&self.view), + topology, + &self.vertex, + &self.fragment, + &self.blend_state, + ); + unsafe { + device_context.DrawInstanced(vertex_count, instance_count, 0, 0); + } + Ok(()) + } + + fn draw_with_texture( + &self, + device_context: &ID3D11DeviceContext, + texture: &[Option], + sampler: &[Option], + instance_count: u32, + ) -> Result<()> { + set_pipeline_state( + device_context, + slice::from_ref(&self.view), + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + &self.vertex, + &self.fragment, + &self.blend_state, + ); + unsafe { + device_context.PSSetSamplers(0, Some(sampler)); + device_context.VSSetShaderResources(0, Some(texture)); + device_context.PSSetShaderResources(0, Some(texture)); + + device_context.DrawInstanced(4, instance_count, 0, 0); + } + Ok(()) + } + + fn draw_range( + &self, + device_context: &ID3D11DeviceContext, + batch_params_buffer: &ID3D11Buffer, + first_instance: u32, + instance_count: u32, + ) -> Result<()> { + anyhow::ensure!( + first_instance as usize + instance_count as usize <= self.buffer_size, + "DirectX instance range exceeds the {} buffer", + self.label + ); + update_batch_start(device_context, batch_params_buffer, first_instance)?; + set_pipeline_state( + device_context, + slice::from_ref(&self.view), + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + &self.vertex, + &self.fragment, + &self.blend_state, + ); + unsafe { + device_context.DrawInstanced(4, instance_count, 0, 0); + } + Ok(()) + } + + fn draw_range_with_texture( + &self, + device_context: &ID3D11DeviceContext, + texture: &[Option], + batch_params_buffer: &ID3D11Buffer, + sampler: &[Option], + first_instance: u32, + instance_count: u32, + ) -> Result<()> { + anyhow::ensure!( + first_instance as usize + instance_count as usize <= self.buffer_size, + "DirectX instance range exceeds the {} buffer", + self.label + ); + update_batch_start(device_context, batch_params_buffer, first_instance)?; + set_pipeline_state( + device_context, + slice::from_ref(&self.view), + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + &self.vertex, + &self.fragment, + &self.blend_state, + ); + unsafe { + device_context.PSSetSamplers(0, Some(sampler)); + device_context.VSSetShaderResources(0, Some(texture)); + device_context.PSSetShaderResources(0, Some(texture)); + device_context.DrawInstanced(4, instance_count, 0, 0); + } + Ok(()) + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct PathRasterizationSprite { + xy_position: Point, + st_position: Point, + color: Background, + bounds: Bounds, +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct PathSprite { + bounds: Bounds, +} + +impl Drop for DirectXRenderer { + fn drop(&mut self) { + #[cfg(debug_assertions)] + if let Some(devices) = &self.devices { + report_live_objects(&devices.device).ok(); + } + } +} + +#[inline] +fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result { + Ok(unsafe { DCompositionCreateDevice(dxgi_device)? }) +} + +fn create_swap_chain_for_composition( + dxgi_factory: &IDXGIFactory6, + device: &ID3D11Device, + width: u32, + height: u32, +) -> Result { + let desc = DXGI_SWAP_CHAIN_DESC1 { + Width: width, + Height: height, + Format: RENDER_TARGET_FORMAT, + Stereo: false.into(), + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT, + BufferCount: BUFFER_COUNT as u32, + // Composition SwapChains only support the DXGI_SCALING_STRETCH Scaling. + Scaling: DXGI_SCALING_STRETCH, + SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, + AlphaMode: DXGI_ALPHA_MODE_PREMULTIPLIED, + Flags: 0, + }; + Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? }) +} + +fn create_swap_chain( + dxgi_factory: &IDXGIFactory6, + device: &ID3D11Device, + hwnd: HWND, + width: u32, + height: u32, +) -> Result { + use windows::Win32::Graphics::Dxgi::DXGI_MWA_NO_ALT_ENTER; + + let desc = DXGI_SWAP_CHAIN_DESC1 { + Width: width, + Height: height, + Format: RENDER_TARGET_FORMAT, + Stereo: false.into(), + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT, + BufferCount: BUFFER_COUNT as u32, + Scaling: DXGI_SCALING_NONE, + SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, + AlphaMode: DXGI_ALPHA_MODE_IGNORE, + Flags: 0, + }; + let swap_chain = + unsafe { dxgi_factory.CreateSwapChainForHwnd(device, hwnd, &desc, None, None) }?; + unsafe { dxgi_factory.MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER) }?; + Ok(swap_chain) +} + +#[inline] +fn create_resources( + devices: &DirectXRendererDevices, + swap_chain: &IDXGISwapChain1, + width: u32, + height: u32, +) -> Result<( + ID3D11Texture2D, + Option, + ID3D11Texture2D, + Option, + ID3D11Texture2D, + Option, + D3D11_VIEWPORT, +)> { + let (render_target, render_target_view) = + create_render_target_and_its_view(swap_chain, &devices.device)?; + let (path_intermediate_texture, path_intermediate_srv) = + create_path_intermediate_texture(&devices.device, width, height)?; + let (path_intermediate_msaa_texture, path_intermediate_msaa_view) = + create_path_intermediate_msaa_texture_and_view(&devices.device, width, height)?; + let viewport = D3D11_VIEWPORT { + TopLeftX: 0.0, + TopLeftY: 0.0, + Width: width as f32, + Height: height as f32, + MinDepth: 0.0, + MaxDepth: 1.0, + }; + Ok(( + render_target, + render_target_view, + path_intermediate_texture, + path_intermediate_srv, + path_intermediate_msaa_texture, + path_intermediate_msaa_view, + viewport, + )) +} + +#[inline] +fn create_render_target_and_its_view( + swap_chain: &IDXGISwapChain1, + device: &ID3D11Device, +) -> Result<(ID3D11Texture2D, Option)> { + let render_target: ID3D11Texture2D = unsafe { swap_chain.GetBuffer(0) }?; + let mut render_target_view = None; + unsafe { device.CreateRenderTargetView(&render_target, None, Some(&mut render_target_view))? }; + Ok((render_target, render_target_view)) +} + +#[inline] +fn create_path_intermediate_texture( + device: &ID3D11Device, + width: u32, + height: u32, +) -> Result<(ID3D11Texture2D, Option)> { + let texture = unsafe { + let mut output = None; + let desc = D3D11_TEXTURE2D_DESC { + Width: width, + Height: height, + MipLevels: 1, + ArraySize: 1, + Format: RENDER_TARGET_FORMAT, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: (D3D11_BIND_RENDER_TARGET.0 | D3D11_BIND_SHADER_RESOURCE.0) as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + device.CreateTexture2D(&desc, None, Some(&mut output))?; + output.unwrap() + }; + + let mut shader_resource_view = None; + unsafe { device.CreateShaderResourceView(&texture, None, Some(&mut shader_resource_view))? }; + + Ok((texture, Some(shader_resource_view.unwrap()))) +} + +#[inline] +fn create_path_intermediate_msaa_texture_and_view( + device: &ID3D11Device, + width: u32, + height: u32, +) -> Result<(ID3D11Texture2D, Option)> { + let msaa_texture = unsafe { + let mut output = None; + let desc = D3D11_TEXTURE2D_DESC { + Width: width, + Height: height, + MipLevels: 1, + ArraySize: 1, + Format: RENDER_TARGET_FORMAT, + SampleDesc: DXGI_SAMPLE_DESC { + Count: PATH_MULTISAMPLE_COUNT, + Quality: D3D11_STANDARD_MULTISAMPLE_PATTERN.0 as u32, + }, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32, + CPUAccessFlags: 0, + MiscFlags: 0, + }; + device.CreateTexture2D(&desc, None, Some(&mut output))?; + output.unwrap() + }; + let mut msaa_view = None; + unsafe { device.CreateRenderTargetView(&msaa_texture, None, Some(&mut msaa_view))? }; + Ok((msaa_texture, Some(msaa_view.unwrap()))) +} + +#[inline] +fn set_rasterizer_state(device: &ID3D11Device, device_context: &ID3D11DeviceContext) -> Result<()> { + let desc = D3D11_RASTERIZER_DESC { + FillMode: D3D11_FILL_SOLID, + CullMode: D3D11_CULL_NONE, + FrontCounterClockwise: false.into(), + DepthBias: 0, + DepthBiasClamp: 0.0, + SlopeScaledDepthBias: 0.0, + DepthClipEnable: true.into(), + ScissorEnable: false.into(), + MultisampleEnable: true.into(), + AntialiasedLineEnable: false.into(), + }; + let rasterizer_state = unsafe { + let mut state = None; + device.CreateRasterizerState(&desc, Some(&mut state))?; + state.unwrap() + }; + unsafe { device_context.RSSetState(&rasterizer_state) }; + Ok(()) +} + +// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_blend_desc +#[inline] +fn create_blend_state(device: &ID3D11Device) -> Result { + let mut desc = D3D11_BLEND_DESC::default(); + desc.RenderTarget[0].BlendEnable = true.into(); + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8; + unsafe { + let mut state = None; + device.CreateBlendState(&desc, Some(&mut state))?; + Ok(state.unwrap()) + } +} + +#[inline] +fn create_blend_state_for_subpixel_rendering(device: &ID3D11Device) -> Result { + let mut desc = D3D11_BLEND_DESC::default(); + desc.RenderTarget[0].BlendEnable = true.into(); + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC1_COLOR; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC1_COLOR; + // It does not make sense to draw transparent subpixel-rendered text, since it cannot be meaningfully alpha-blended onto anything else. + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].RenderTargetWriteMask = + D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8 & !D3D11_COLOR_WRITE_ENABLE_ALPHA.0 as u8; + + unsafe { + let mut state = None; + device.CreateBlendState(&desc, Some(&mut state))?; + Ok(state.unwrap()) + } +} + +#[inline] +fn create_blend_state_for_path_rasterization(device: &ID3D11Device) -> Result { + // If the feature level is set to greater than D3D_FEATURE_LEVEL_9_3, the display + // device performs the blend in linear space, which is ideal. + let mut desc = D3D11_BLEND_DESC::default(); + desc.RenderTarget[0].BlendEnable = true.into(); + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8; + unsafe { + let mut state = None; + device.CreateBlendState(&desc, Some(&mut state))?; + Ok(state.unwrap()) + } +} + +#[inline] +fn create_blend_state_for_path_sprite(device: &ID3D11Device) -> Result { + // If the feature level is set to greater than D3D_FEATURE_LEVEL_9_3, the display + // device performs the blend in linear space, which is ideal. + let mut desc = D3D11_BLEND_DESC::default(); + desc.RenderTarget[0].BlendEnable = true.into(); + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8; + unsafe { + let mut state = None; + device.CreateBlendState(&desc, Some(&mut state))?; + Ok(state.unwrap()) + } +} + +#[inline] +fn create_vertex_shader(device: &ID3D11Device, bytes: &[u8]) -> Result { + unsafe { + let mut shader = None; + device.CreateVertexShader(bytes, None, Some(&mut shader))?; + Ok(shader.unwrap()) + } +} + +#[inline] +fn create_fragment_shader(device: &ID3D11Device, bytes: &[u8]) -> Result { + unsafe { + let mut shader = None; + device.CreatePixelShader(bytes, None, Some(&mut shader))?; + Ok(shader.unwrap()) + } +} + +#[inline] +fn create_constant_buffer(device: &ID3D11Device) -> Result> { + const { assert!(std::mem::size_of::() != 0 && std::mem::size_of::().is_multiple_of(16)) }; + let desc = D3D11_BUFFER_DESC { + ByteWidth: std::mem::size_of::() as u32, + Usage: D3D11_USAGE_DYNAMIC, + BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32, + CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32, + MiscFlags: 0, + StructureByteStride: 0, + }; + let mut buffer = None; + unsafe { device.CreateBuffer(&desc, None, Some(&mut buffer)) }?; + Ok(buffer) +} + +#[inline] +fn create_buffer( + device: &ID3D11Device, + element_size: usize, + buffer_size: usize, +) -> Result { + let desc = D3D11_BUFFER_DESC { + ByteWidth: (element_size * buffer_size) as u32, + Usage: D3D11_USAGE_DYNAMIC, + BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32, + CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32, + MiscFlags: D3D11_RESOURCE_MISC_BUFFER_STRUCTURED.0 as u32, + StructureByteStride: element_size as u32, + }; + let mut buffer = None; + unsafe { device.CreateBuffer(&desc, None, Some(&mut buffer)) }?; + Ok(buffer.unwrap()) +} + +#[inline] +fn create_buffer_view( + device: &ID3D11Device, + buffer: &ID3D11Buffer, +) -> Result> { + let mut view = None; + unsafe { device.CreateShaderResourceView(buffer, None, Some(&mut view)) }?; + Ok(view) +} + +#[inline] +fn update_buffer( + device_context: &ID3D11DeviceContext, + buffer: &ID3D11Buffer, + data: &[T], +) -> Result<()> { + unsafe { + let mut dest = std::mem::zeroed(); + device_context.Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut dest))?; + std::ptr::copy_nonoverlapping(data.as_ptr(), dest.pData as _, data.len()); + device_context.Unmap(buffer, 0); + } + Ok(()) +} + +#[inline] +fn update_batch_start( + device_context: &ID3D11DeviceContext, + buffer: &ID3D11Buffer, + first_instance: u32, +) -> Result<()> { + update_buffer( + device_context, + buffer, + &[BatchParams { + start_index: first_instance, + _padding: [0; 3], + }], + ) +} + +#[inline] +fn set_pipeline_state( + device_context: &ID3D11DeviceContext, + buffer_view: &[Option], + topology: D3D_PRIMITIVE_TOPOLOGY, + vertex_shader: &ID3D11VertexShader, + fragment_shader: &ID3D11PixelShader, + blend_state: &ID3D11BlendState, +) { + unsafe { + device_context.VSSetShaderResources(1, Some(buffer_view)); + device_context.PSSetShaderResources(1, Some(buffer_view)); + device_context.IASetPrimitiveTopology(topology); + device_context.VSSetShader(vertex_shader, None); + device_context.PSSetShader(fragment_shader, None); + device_context.OMSetBlendState(blend_state, None, 0xFFFFFFFF); + } +} + +#[cfg(debug_assertions)] +fn report_live_objects(device: &ID3D11Device) -> Result<()> { + let debug_device: ID3D11Debug = device.cast()?; + unsafe { + debug_device.ReportLiveDeviceObjects(D3D11_RLDO_DETAIL)?; + } + Ok(()) +} + +const BUFFER_COUNT: usize = 3; + +pub(crate) mod shader_resources { + use anyhow::Result; + + #[cfg(debug_assertions)] + use windows::{ + Win32::Graphics::Direct3D::{ + Fxc::{D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION, D3DCompileFromFile}, + ID3DBlob, + }, + core::{HSTRING, PCSTR}, + }; + + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + pub(crate) enum ShaderModule { + Quad, + Shadow, + Underline, + PathRasterization, + PathSprite, + MonochromeSprite, + SubpixelSprite, + PolychromeSprite, + EmojiRasterization, + } + + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + pub(crate) enum ShaderTarget { + Vertex, + Fragment, + } + + pub(crate) struct RawShaderBytes<'t> { + inner: &'t [u8], + + #[cfg(debug_assertions)] + _blob: ID3DBlob, + } + + impl<'t> RawShaderBytes<'t> { + pub(crate) fn new(module: ShaderModule, target: ShaderTarget) -> Result { + #[cfg(not(debug_assertions))] + { + Ok(Self::from_bytes(module, target)) + } + #[cfg(debug_assertions)] + { + let blob = build_shader_blob(module, target)?; + let inner = unsafe { + std::slice::from_raw_parts( + blob.GetBufferPointer() as *const u8, + blob.GetBufferSize(), + ) + }; + Ok(Self { inner, _blob: blob }) + } + } + + pub(crate) fn as_bytes(&'t self) -> &'t [u8] { + self.inner + } + + #[cfg(not(debug_assertions))] + fn from_bytes(module: ShaderModule, target: ShaderTarget) -> Self { + let bytes = match module { + ShaderModule::Quad => match target { + ShaderTarget::Vertex => QUAD_VERTEX_BYTES, + ShaderTarget::Fragment => QUAD_FRAGMENT_BYTES, + }, + ShaderModule::Shadow => match target { + ShaderTarget::Vertex => SHADOW_VERTEX_BYTES, + ShaderTarget::Fragment => SHADOW_FRAGMENT_BYTES, + }, + ShaderModule::Underline => match target { + ShaderTarget::Vertex => UNDERLINE_VERTEX_BYTES, + ShaderTarget::Fragment => UNDERLINE_FRAGMENT_BYTES, + }, + ShaderModule::PathRasterization => match target { + ShaderTarget::Vertex => PATH_RASTERIZATION_VERTEX_BYTES, + ShaderTarget::Fragment => PATH_RASTERIZATION_FRAGMENT_BYTES, + }, + ShaderModule::PathSprite => match target { + ShaderTarget::Vertex => PATH_SPRITE_VERTEX_BYTES, + ShaderTarget::Fragment => PATH_SPRITE_FRAGMENT_BYTES, + }, + ShaderModule::MonochromeSprite => match target { + ShaderTarget::Vertex => MONOCHROME_SPRITE_VERTEX_BYTES, + ShaderTarget::Fragment => MONOCHROME_SPRITE_FRAGMENT_BYTES, + }, + ShaderModule::SubpixelSprite => match target { + ShaderTarget::Vertex => SUBPIXEL_SPRITE_VERTEX_BYTES, + ShaderTarget::Fragment => SUBPIXEL_SPRITE_FRAGMENT_BYTES, + }, + ShaderModule::PolychromeSprite => match target { + ShaderTarget::Vertex => POLYCHROME_SPRITE_VERTEX_BYTES, + ShaderTarget::Fragment => POLYCHROME_SPRITE_FRAGMENT_BYTES, + }, + ShaderModule::EmojiRasterization => match target { + ShaderTarget::Vertex => EMOJI_RASTERIZATION_VERTEX_BYTES, + ShaderTarget::Fragment => EMOJI_RASTERIZATION_FRAGMENT_BYTES, + }, + }; + Self { inner: bytes } + } + } + + #[cfg(debug_assertions)] + pub(super) fn build_shader_blob(entry: ShaderModule, target: ShaderTarget) -> Result { + unsafe { + use windows::Win32::Graphics::{ + Direct3D::ID3DInclude, Hlsl::D3D_COMPILE_STANDARD_FILE_INCLUDE, + }; + + let shader_name = if matches!(entry, ShaderModule::EmojiRasterization) { + "color_text_raster.hlsl" + } else { + "shaders.hlsl" + }; + + let entry = format!( + "{}_{}\0", + entry.as_str(), + match target { + ShaderTarget::Vertex => "vertex", + ShaderTarget::Fragment => "fragment", + } + ); + let target = match target { + ShaderTarget::Vertex => "vs_4_1\0", + ShaderTarget::Fragment => "ps_4_1\0", + }; + + let mut compile_blob = None; + let mut error_blob = None; + let shader_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join(&format!("src/{}", shader_name)) + .canonicalize()?; + + let entry_point = PCSTR::from_raw(entry.as_ptr()); + let target_cstr = PCSTR::from_raw(target.as_ptr()); + + // really dirty trick because winapi bindings are unhappy otherwise + let include_handler = &std::mem::transmute::( + D3D_COMPILE_STANDARD_FILE_INCLUDE as usize, + ); + + let ret = D3DCompileFromFile( + &HSTRING::from(shader_path.to_str().unwrap()), + None, + include_handler, + entry_point, + target_cstr, + D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, + 0, + &mut compile_blob, + Some(&mut error_blob), + ); + if ret.is_err() { + let Some(error_blob) = error_blob else { + return Err(anyhow::anyhow!("{ret:?}")); + }; + + let error_string = + std::ffi::CStr::from_ptr(error_blob.GetBufferPointer() as *const i8) + .to_string_lossy(); + log::error!("Shader compile error: {}", error_string); + return Err(anyhow::anyhow!("Compile error: {}", error_string)); + } + Ok(compile_blob.unwrap()) + } + } + + #[cfg(not(debug_assertions))] + include!(concat!(env!("OUT_DIR"), "/shaders_bytes.rs")); + + #[cfg(debug_assertions)] + impl ShaderModule { + pub fn as_str(self) -> &'static str { + match self { + ShaderModule::Quad => "quad", + ShaderModule::Shadow => "shadow", + ShaderModule::Underline => "underline", + ShaderModule::PathRasterization => "path_rasterization", + ShaderModule::PathSprite => "path_sprite", + ShaderModule::MonochromeSprite => "monochrome_sprite", + ShaderModule::SubpixelSprite => "subpixel_sprite", + ShaderModule::PolychromeSprite => "polychrome_sprite", + ShaderModule::EmojiRasterization => "emoji_rasterization", + } + } + } +} + +mod nvidia { + use std::{ + ffi::CStr, + os::raw::{c_char, c_int, c_uint}, + }; + + use anyhow::Result; + use windows::{Win32::System::LibraryLoader::GetProcAddress, core::s}; + + use crate::with_dll_library; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L180 + const NVAPI_SHORT_STRING_MAX: usize = 64; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L235 + #[allow(non_camel_case_types)] + type NvAPI_ShortString = [c_char; NVAPI_SHORT_STRING_MAX]; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L447 + #[allow(non_camel_case_types)] + type NvAPI_SYS_GetDriverAndBranchVersion_t = unsafe extern "C" fn( + driver_version: *mut c_uint, + build_branch_string: *mut NvAPI_ShortString, + ) -> c_int; + + pub(super) fn get_driver_version() -> Result { + #[cfg(target_pointer_width = "64")] + let nvidia_dll_name = s!("nvapi64.dll"); + #[cfg(target_pointer_width = "32")] + let nvidia_dll_name = s!("nvapi.dll"); + + with_dll_library(nvidia_dll_name, |nvidia_dll| unsafe { + let nvapi_query_addr = GetProcAddress(nvidia_dll, s!("nvapi_QueryInterface")) + .ok_or_else(|| anyhow::anyhow!("Failed to get nvapi_QueryInterface address"))?; + let nvapi_query: extern "C" fn(u32) -> *mut () = std::mem::transmute(nvapi_query_addr); + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_interface.h#L41 + let nvapi_get_driver_version_ptr = nvapi_query(0x2926aaad); + if nvapi_get_driver_version_ptr.is_null() { + anyhow::bail!("Failed to get NVIDIA driver version function pointer"); + } + let nvapi_get_driver_version: NvAPI_SYS_GetDriverAndBranchVersion_t = + std::mem::transmute(nvapi_get_driver_version_ptr); + + let mut driver_version: c_uint = 0; + let mut build_branch_string: NvAPI_ShortString = [0; NVAPI_SHORT_STRING_MAX]; + let result = nvapi_get_driver_version( + &mut driver_version as *mut c_uint, + &mut build_branch_string as *mut NvAPI_ShortString, + ); + + if result != 0 { + anyhow::bail!( + "Failed to get NVIDIA driver version, error code: {}", + result + ); + } + let major = driver_version / 100; + let minor = driver_version % 100; + let branch_string = CStr::from_ptr(build_branch_string.as_ptr()); + Ok(format!( + "{}.{} {}", + major, + minor, + branch_string.to_string_lossy() + )) + }) + } +} + +mod amd { + use std::os::raw::{c_char, c_int, c_void}; + + use anyhow::Result; + use windows::{Win32::System::LibraryLoader::GetProcAddress, core::s}; + + use crate::with_dll_library; + + // https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L145 + const AGS_CURRENT_VERSION: i32 = (6 << 22) | (3 << 12); + + // https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L204 + // This is an opaque type, using struct to represent it properly for FFI + #[repr(C)] + struct AGSContext { + _private: [u8; 0], + } + + #[repr(C)] + pub struct AGSGPUInfo { + pub driver_version: *const c_char, + pub radeon_software_version: *const c_char, + pub num_devices: c_int, + pub devices: *mut c_void, + } + + // https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L429 + #[allow(non_camel_case_types)] + type agsInitialize_t = unsafe extern "C" fn( + version: c_int, + config: *const c_void, + context: *mut *mut AGSContext, + gpu_info: *mut AGSGPUInfo, + ) -> c_int; + + // https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L436 + #[allow(non_camel_case_types)] + type agsDeInitialize_t = unsafe extern "C" fn(context: *mut AGSContext) -> c_int; + + pub(super) fn get_driver_version() -> Result { + #[cfg(target_pointer_width = "64")] + let amd_dll_name = s!("amd_ags_x64.dll"); + #[cfg(target_pointer_width = "32")] + let amd_dll_name = s!("amd_ags_x86.dll"); + + with_dll_library(amd_dll_name, |amd_dll| unsafe { + let ags_initialize_addr = GetProcAddress(amd_dll, s!("agsInitialize")) + .ok_or_else(|| anyhow::anyhow!("Failed to get agsInitialize address"))?; + let ags_deinitialize_addr = GetProcAddress(amd_dll, s!("agsDeInitialize")) + .ok_or_else(|| anyhow::anyhow!("Failed to get agsDeInitialize address"))?; + + let ags_initialize: agsInitialize_t = std::mem::transmute(ags_initialize_addr); + let ags_deinitialize: agsDeInitialize_t = std::mem::transmute(ags_deinitialize_addr); + + let mut context: *mut AGSContext = std::ptr::null_mut(); + let mut gpu_info: AGSGPUInfo = AGSGPUInfo { + driver_version: std::ptr::null(), + radeon_software_version: std::ptr::null(), + num_devices: 0, + devices: std::ptr::null_mut(), + }; + + let result = ags_initialize( + AGS_CURRENT_VERSION, + std::ptr::null(), + &mut context, + &mut gpu_info, + ); + if result != 0 { + anyhow::bail!("Failed to initialize AMD AGS, error code: {}", result); + } + + // Vulkan actually returns this as the driver version + let software_version = if !gpu_info.radeon_software_version.is_null() { + std::ffi::CStr::from_ptr(gpu_info.radeon_software_version) + .to_string_lossy() + .into_owned() + } else { + "Unknown Radeon Software Version".to_string() + }; + + let driver_version = if !gpu_info.driver_version.is_null() { + std::ffi::CStr::from_ptr(gpu_info.driver_version) + .to_string_lossy() + .into_owned() + } else { + "Unknown Radeon Driver Version".to_string() + }; + + ags_deinitialize(context); + Ok(format!("{} ({})", software_version, driver_version)) + }) + } +} + +mod dxgi { + use windows::{ + Win32::Graphics::Dxgi::{IDXGIAdapter1, IDXGIDevice}, + core::Interface, + }; + + pub(super) fn get_driver_version(adapter: &IDXGIAdapter1) -> anyhow::Result { + let number = unsafe { adapter.CheckInterfaceSupport(&IDXGIDevice::IID as _) }?; + Ok(format!( + "{}.{}.{}.{}", + number >> 48, + (number >> 32) & 0xFFFF, + (number >> 16) & 0xFFFF, + number & 0xFFFF + )) + } +} diff --git a/vendor/gpui-pre-windows/src/dispatcher.rs b/vendor/gpui-pre-windows/src/dispatcher.rs new file mode 100644 index 00000000..55f18b50 --- /dev/null +++ b/vendor/gpui-pre-windows/src/dispatcher.rs @@ -0,0 +1,191 @@ +use std::{ + ffi::c_void, + ptr::NonNull, + sync::atomic::{AtomicBool, Ordering}, + thread::{ThreadId, current}, + time::Duration, +}; + +use anyhow::Context; +use gpui_util::ResultExt; +use windows::Win32::{ + Foundation::{FILETIME, LPARAM, WPARAM}, + Media::{timeBeginPeriod, timeEndPeriod}, + System::Threading::{ + CloseThreadpoolTimer, CreateThreadpoolTimer, GetCurrentThread, PTP_CALLBACK_INSTANCE, + PTP_TIMER, SetThreadPriority, SetThreadpoolTimer, THREAD_PRIORITY_TIME_CRITICAL, + TP_CALLBACK_ENVIRON_V3, TP_CALLBACK_PRIORITY, TP_CALLBACK_PRIORITY_HIGH, + TP_CALLBACK_PRIORITY_LOW, TP_CALLBACK_PRIORITY_NORMAL, TrySubmitThreadpoolCallback, + }, + UI::WindowsAndMessaging::PostMessageW, +}; + +use crate::{HWND, SafeHwnd, WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD}; +use gpui::{ + PlatformDispatcher, Priority, PriorityQueueSender, RunnableVariant, TimerResolutionGuard, +}; + +pub(crate) struct WindowsDispatcher { + pub(crate) wake_posted: AtomicBool, + main_sender: PriorityQueueSender, + main_thread_id: ThreadId, + pub(crate) platform_window_handle: SafeHwnd, + validation_number: usize, +} + +impl WindowsDispatcher { + pub(crate) fn new( + main_sender: PriorityQueueSender, + platform_window_handle: HWND, + validation_number: usize, + ) -> Self { + let main_thread_id = current().id(); + let platform_window_handle = platform_window_handle.into(); + + WindowsDispatcher { + main_sender, + main_thread_id, + platform_window_handle, + validation_number, + wake_posted: AtomicBool::new(false), + } + } + + fn dispatch_on_threadpool(&self, priority: TP_CALLBACK_PRIORITY, runnable: RunnableVariant) { + let environ = TP_CALLBACK_ENVIRON_V3 { + Version: 3, + CallbackPriority: priority, + Size: size_of::() as u32, + ..Default::default() + }; + + // If the thread pool never runs our callback, the matching `from_raw` is never called, which leaks the runnable. + // Dropping the scheduled runnable would cancel its task and make the next poll of any awaiter panic. Since we expect + // the scenario to usually happen during shutdown, this leak is acceptable. + let context = runnable.into_raw().as_ptr() as *mut c_void; + + unsafe { + TrySubmitThreadpoolCallback(Some(run_work_callback), Some(context), Some(&environ)) + .log_err(); + } + } + + fn dispatch_on_threadpool_after(&self, runnable: RunnableVariant, duration: Duration) { + let context = runnable.into_raw().as_ptr() as *mut c_void; + + unsafe { + if let Ok(timer) = CreateThreadpoolTimer(Some(run_timer_callback), Some(context), None) + { + // Negative FILETIME expresses a relative delay in 100ns ticks + let ticks = (duration.as_nanos() / 100).min(i64::MAX as u128) as i64; + let due = (-ticks) as u64; + let due_time = FILETIME { + dwLowDateTime: due as u32, + dwHighDateTime: (due >> 32) as u32, + }; + SetThreadpoolTimer(timer, Some(&due_time), 0, None); + } + } + } + + #[inline(always)] + pub(crate) fn execute_runnable(runnable: RunnableVariant) { + let location = runnable.metadata().location; + let spawned = runnable.metadata().spawned; + gpui::profiler::update_running_task(spawned, location); + runnable.run(); + gpui::profiler::save_task_timing(); + } +} + +impl PlatformDispatcher for WindowsDispatcher { + fn is_main_thread(&self) -> bool { + current().id() == self.main_thread_id + } + + fn dispatch(&self, runnable: RunnableVariant, priority: Priority) { + let priority = match priority { + Priority::RealtimeAudio => { + panic!("RealtimeAudio priority should use spawn_realtime, not dispatch") + } + Priority::High => TP_CALLBACK_PRIORITY_HIGH, + Priority::Medium => TP_CALLBACK_PRIORITY_NORMAL, + Priority::Low => TP_CALLBACK_PRIORITY_LOW, + }; + self.dispatch_on_threadpool(priority, runnable); + } + + fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority) { + match self.main_sender.send(priority, runnable) { + Ok(_) => { + if !self.wake_posted.swap(true, Ordering::AcqRel) { + unsafe { + PostMessageW( + Some(self.platform_window_handle.as_raw()), + WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD, + WPARAM(self.validation_number), + LPARAM(0), + ) + .log_err(); + } + } + } + Err(runnable) => { + // NOTE: Runnable may wrap a Future that is !Send. + // + // This is usually safe because we only poll it on the main thread. + // However if the send fails, we know that: + // 1. main_receiver has been dropped (which implies the app is shutting down) + // 2. we are on a background thread. + // It is not safe to drop something !Send on the wrong thread, and + // the app will exit soon anyway, so we must forget the runnable. + std::mem::forget(runnable); + } + } + } + + fn dispatch_after(&self, duration: Duration, runnable: RunnableVariant) { + self.dispatch_on_threadpool_after(runnable, duration); + } + + fn spawn_realtime(&self, f: Box) { + std::thread::spawn(move || { + // SAFETY: always safe to call + let thread_handle = unsafe { GetCurrentThread() }; + + // SAFETY: thread_handle is a valid handle to the current thread + unsafe { SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL) } + .context("thread priority") + .log_err(); + + f(); + }); + } + + fn increase_timer_resolution(&self) -> TimerResolutionGuard { + unsafe { + timeBeginPeriod(1); + } + gpui_util::defer(Box::new(|| unsafe { + timeEndPeriod(1); + })) + } +} + +unsafe extern "system" fn run_work_callback( + _instance: PTP_CALLBACK_INSTANCE, + context: *mut c_void, +) { + let runnable = unsafe { RunnableVariant::from_raw(NonNull::new_unchecked(context as *mut ())) }; + WindowsDispatcher::execute_runnable(runnable); +} + +unsafe extern "system" fn run_timer_callback( + _instance: PTP_CALLBACK_INSTANCE, + context: *mut c_void, + timer: PTP_TIMER, +) { + let runnable = unsafe { RunnableVariant::from_raw(NonNull::new_unchecked(context as *mut ())) }; + WindowsDispatcher::execute_runnable(runnable); + unsafe { CloseThreadpoolTimer(timer) }; +} diff --git a/vendor/gpui-pre-windows/src/display.rs b/vendor/gpui-pre-windows/src/display.rs new file mode 100644 index 00000000..ee02309d --- /dev/null +++ b/vendor/gpui-pre-windows/src/display.rs @@ -0,0 +1,210 @@ +use gpui_util::ResultExt; +use itertools::Itertools; +use smallvec::SmallVec; +use std::rc::Rc; +use uuid::Uuid; +use windows::{ + Win32::{ + Foundation::*, + Graphics::Gdi::*, + UI::{ + HiDpi::{GetDpiForMonitor, MDT_EFFECTIVE_DPI}, + WindowsAndMessaging::USER_DEFAULT_SCREEN_DPI, + }, + }, + core::*, +}; + +use crate::logical_point; +use gpui::{Bounds, DevicePixels, DisplayId, Pixels, PlatformDisplay, point, size}; + +#[derive(Debug, Clone, Copy)] +pub(crate) struct WindowsDisplay { + pub handle: HMONITOR, + pub display_id: DisplayId, + scale_factor: f32, + bounds: Bounds, + visible_bounds: Bounds, + physical_bounds: Bounds, + uuid: Uuid, +} + +// The `HMONITOR` is thread-safe. +unsafe impl Send for WindowsDisplay {} +unsafe impl Sync for WindowsDisplay {} + +impl WindowsDisplay { + pub(crate) fn new(display_id: DisplayId) -> Option { + let handle = HMONITOR(u64::from(display_id) as _); + let info = get_monitor_info(handle).log_err()?; + let monitor_size = info.monitorInfo.rcMonitor; + let work_area = info.monitorInfo.rcWork; + let uuid = generate_uuid(&info.szDevice); + let scale_factor = get_scale_factor_for_monitor(handle).log_err()?; + let physical_size = size( + (monitor_size.right - monitor_size.left).into(), + (monitor_size.bottom - monitor_size.top).into(), + ); + + Some(WindowsDisplay { + handle, + display_id, + scale_factor, + bounds: Bounds { + origin: logical_point( + monitor_size.left as f32, + monitor_size.top as f32, + scale_factor, + ), + size: physical_size.to_pixels(scale_factor), + }, + visible_bounds: Bounds { + origin: logical_point(work_area.left as f32, work_area.top as f32, scale_factor), + size: size( + (work_area.right - work_area.left) as f32 / scale_factor, + (work_area.bottom - work_area.top) as f32 / scale_factor, + ) + .map(gpui::px), + }, + physical_bounds: Bounds { + origin: point(monitor_size.left.into(), monitor_size.top.into()), + size: physical_size, + }, + uuid, + }) + } + + pub(crate) fn display_id_for_monitor(monitor: HMONITOR) -> DisplayId { + DisplayId::new(monitor.0 as u64) + } + + pub fn primary_monitor() -> Option { + // https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643 + const POINT_ZERO: POINT = POINT { x: 0, y: 0 }; + let monitor = unsafe { MonitorFromPoint(POINT_ZERO, MONITOR_DEFAULTTOPRIMARY) }; + if monitor.is_invalid() { + log::error!( + "can not find the primary monitor: {}", + std::io::Error::last_os_error() + ); + return None; + } + WindowsDisplay::new(Self::display_id_for_monitor(monitor)) + } + + /// The DPI scale factor of this monitor, independent of whatever monitor + /// a not-yet-positioned window currently happens to be on. + pub(crate) fn scale_factor(&self) -> f32 { + self.scale_factor + } + + /// Check if the center point of given bounds is inside this monitor + pub fn check_given_bounds(&self, bounds: Bounds) -> bool { + let center = bounds.center(); + let center = POINT { + x: (center.x.as_f32() * self.scale_factor) as i32, + y: (center.y.as_f32() * self.scale_factor) as i32, + }; + let monitor = unsafe { MonitorFromPoint(center, MONITOR_DEFAULTTONULL) }; + if monitor.is_invalid() { + false + } else { + let Some(display) = WindowsDisplay::new(Self::display_id_for_monitor(monitor)) else { + return false; + }; + display.uuid == self.uuid + } + } + + pub fn displays() -> Vec> { + available_monitors() + .into_iter() + .filter_map(|handle| { + Some( + Rc::new(WindowsDisplay::new(Self::display_id_for_monitor(handle))?) + as Rc, + ) + }) + .collect() + } + + pub fn physical_bounds(&self) -> Bounds { + self.physical_bounds + } +} + +impl PlatformDisplay for WindowsDisplay { + fn id(&self) -> DisplayId { + self.display_id + } + + fn uuid(&self) -> anyhow::Result { + Ok(self.uuid) + } + + fn bounds(&self) -> Bounds { + self.bounds + } + + fn visible_bounds(&self) -> Bounds { + self.visible_bounds + } +} + +fn available_monitors() -> SmallVec<[HMONITOR; 4]> { + let mut monitors: SmallVec<[HMONITOR; 4]> = SmallVec::new(); + unsafe { + EnumDisplayMonitors( + None, + None, + Some(monitor_enum_proc), + LPARAM(&mut monitors as *mut _ as _), + ) + .ok() + .log_err(); + } + monitors +} + +unsafe extern "system" fn monitor_enum_proc( + hmonitor: HMONITOR, + _hdc: HDC, + _place: *mut RECT, + data: LPARAM, +) -> BOOL { + let monitors = data.0 as *mut SmallVec<[HMONITOR; 4]>; + unsafe { (*monitors).push(hmonitor) }; + BOOL(1) +} + +fn get_monitor_info(hmonitor: HMONITOR) -> anyhow::Result { + let mut monitor_info: MONITORINFOEXW = unsafe { std::mem::zeroed() }; + monitor_info.monitorInfo.cbSize = std::mem::size_of::() as u32; + let status = unsafe { + GetMonitorInfoW( + hmonitor, + &mut monitor_info as *mut MONITORINFOEXW as *mut MONITORINFO, + ) + }; + if status.as_bool() { + Ok(monitor_info) + } else { + Err(anyhow::anyhow!(std::io::Error::last_os_error())) + } +} + +fn generate_uuid(device_name: &[u16]) -> Uuid { + let name = device_name + .iter() + .flat_map(|&a| a.to_be_bytes()) + .collect_vec(); + Uuid::new_v5(&Uuid::NAMESPACE_DNS, &name) +} + +fn get_scale_factor_for_monitor(monitor: HMONITOR) -> Result { + let mut dpi_x = 0; + let mut dpi_y = 0; + unsafe { GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y) }?; + assert_eq!(dpi_x, dpi_y); + Ok(dpi_x as f32 / USER_DEFAULT_SCREEN_DPI as f32) +} diff --git a/vendor/gpui-pre-windows/src/events.rs b/vendor/gpui-pre-windows/src/events.rs new file mode 100644 index 00000000..4a9b18b0 --- /dev/null +++ b/vendor/gpui-pre-windows/src/events.rs @@ -0,0 +1,1812 @@ +use std::{cell::Cell, rc::Rc, sync::atomic::Ordering}; + +use anyhow::Context as _; +use gpui_util::ResultExt; +use windows::{ + Win32::{ + Foundation::*, + Graphics::Gdi::*, + System::SystemServices::*, + UI::{ + Controls::*, + HiDpi::*, + Input::{Ime::*, KeyboardAndMouse::*}, + WindowsAndMessaging::*, + }, + }, + core::PCWSTR, +}; + +use crate::*; +use gpui::*; + +pub(crate) const WM_GPUI_CURSOR_STYLE_CHANGED: u32 = WM_USER + 1; +pub(crate) const WM_GPUI_CLOSE_ONE_WINDOW: u32 = WM_USER + 2; +pub(crate) const WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD: u32 = WM_USER + 3; +pub(crate) const WM_GPUI_DOCK_MENU_ACTION: u32 = WM_USER + 4; +pub(crate) const WM_GPUI_FORCE_UPDATE_WINDOW: u32 = WM_USER + 5; +pub(crate) const WM_GPUI_KEYBOARD_LAYOUT_CHANGED: u32 = WM_USER + 6; +pub(crate) const WM_GPUI_GPU_DEVICE_LOST: u32 = WM_USER + 7; +pub(crate) const WM_GPUI_KEYDOWN: u32 = WM_USER + 8; +pub(crate) const WM_GPUI_END_SESSION: u32 = WM_USER + 9; + +const SIZE_MOVE_LOOP_TIMER_ID: usize = 1; + +/// Coordinates window draws on the UI thread. Owned by the platform and +/// shared with every window (like `WindowsPlatformState::cursor_visible`), +/// because the coordination is inherently cross-window: while window A is +/// drawing, a re-entrant paint request for window B must be deferred. +pub(crate) struct DrawCoordinator { + /// Whether some window is currently inside `draw_window`. Win32 can + /// re-enter the window procedure while a draw is in progress (e.g. + /// cross-thread `SendMessage` dispatch during message pumping, or modal + /// message loops entered by COM calls), and drawing re-entrantly would + /// nest GPUI draws. Nested draws are wasted work whose output is + /// immediately redrawn, so we defer them instead. + drawing: Cell, +} + +impl DrawCoordinator { + pub(crate) fn new() -> Self { + Self { + drawing: Cell::new(false), + } + } + + fn try_begin_draw(&self) -> Option> { + // This only covers the `draw_window` span (which extends past the GPUI + // draw, through presentation and IME updates). Requests that arrive + // re-entrantly during GPUI-initiated draws (e.g. key dispatch or + // opening a window draws synchronously) are deferred by GPUI's + // `on_request_frame` callback itself, which no-ops in that case. + if self.drawing.get() { + None + } else { + self.drawing.set(true); + Some(DrawWindowGuard { coordinator: self }) + } + } +} + +struct DrawWindowGuard<'a> { + coordinator: &'a DrawCoordinator, +} + +impl Drop for DrawWindowGuard<'_> { + fn drop(&mut self) { + self.coordinator.drawing.set(false); + } +} + +impl WindowsWindowInner { + pub(crate) fn handle_msg( + self: &Rc, + handle: HWND, + msg: u32, + wparam: WPARAM, + lparam: LPARAM, + ) -> LRESULT { + let handled = match msg { + // `DefWindowProc` answers `MA_NOACTIVATE` for a left click on `HTCAPTION`. + // The activation is only triggered when `DefWindowProc` handles the following `WM_NCLBUTTONDOWN`. + // The GPUI event is dispatched in between, so a click handler runs while `active_window` is still + // whichever window was active before the click. If that handler consumes the + // press, `DefWindowProc` never sees it, so the window is never activated at all. + // So, let's eagerly activate the window. + WM_MOUSEACTIVATE => Some(MA_ACTIVATE as isize), + WM_ACTIVATE => self.handle_activate_msg(wparam), + WM_CREATE => self.handle_create_msg(handle), + WM_MOVE => self.handle_move_msg(handle, lparam), + WM_SIZE => self.handle_size_msg(wparam, lparam), + WM_GETMINMAXINFO => self.handle_get_min_max_info_msg(lparam), + WM_ENTERSIZEMOVE | WM_ENTERMENULOOP => self.handle_size_move_loop(handle), + WM_EXITSIZEMOVE | WM_EXITMENULOOP => self.handle_size_move_loop_exit(handle), + WM_TIMER => self.handle_timer_msg(handle, wparam), + WM_NCCALCSIZE => self.handle_calc_client_size(handle, wparam, lparam), + WM_DPICHANGED => self.handle_dpi_changed_msg(handle, wparam, lparam), + WM_DISPLAYCHANGE => self.handle_display_change_msg(handle), + WM_NCHITTEST => self.handle_hit_test_msg(handle, lparam), + WM_PAINT => self.handle_paint_msg(handle), + WM_CLOSE => self.handle_close_msg(), + WM_DESTROY => self.handle_destroy_msg(handle), + WM_QUERYENDSESSION => Some(1), + WM_ENDSESSION => self.handle_end_session_msg(wparam), + WM_MOUSEMOVE => self.handle_mouse_move_msg(handle, lparam, wparam), + WM_MOUSELEAVE | WM_NCMOUSELEAVE => self.handle_mouse_leave_msg(), + WM_NCMOUSEMOVE => self.handle_nc_mouse_move_msg(handle, lparam), + // Treat double click as a second single click, since we track the double clicks ourselves. + // If you don't interact with any elements, this will fall through to the windows default + // behavior of toggling whether the window is maximized. + WM_NCLBUTTONDBLCLK | WM_NCLBUTTONDOWN => { + self.handle_nc_mouse_down_msg(handle, MouseButton::Left, wparam, lparam) + } + WM_NCRBUTTONDOWN => { + self.handle_nc_mouse_down_msg(handle, MouseButton::Right, wparam, lparam) + } + WM_NCMBUTTONDOWN => { + self.handle_nc_mouse_down_msg(handle, MouseButton::Middle, wparam, lparam) + } + WM_NCLBUTTONUP => { + self.handle_nc_mouse_up_msg(handle, MouseButton::Left, wparam, lparam) + } + WM_NCRBUTTONUP => { + self.handle_nc_mouse_up_msg(handle, MouseButton::Right, wparam, lparam) + } + WM_NCMBUTTONUP => { + self.handle_nc_mouse_up_msg(handle, MouseButton::Middle, wparam, lparam) + } + WM_LBUTTONDOWN => self.handle_mouse_down_msg(handle, MouseButton::Left, lparam), + WM_RBUTTONDOWN => self.handle_mouse_down_msg(handle, MouseButton::Right, lparam), + WM_MBUTTONDOWN => self.handle_mouse_down_msg(handle, MouseButton::Middle, lparam), + WM_XBUTTONDOWN => { + self.handle_xbutton_msg(handle, wparam, lparam, Self::handle_mouse_down_msg) + } + WM_LBUTTONUP => self.handle_mouse_up_msg(handle, MouseButton::Left, lparam), + WM_RBUTTONUP => self.handle_mouse_up_msg(handle, MouseButton::Right, lparam), + WM_MBUTTONUP => self.handle_mouse_up_msg(handle, MouseButton::Middle, lparam), + WM_XBUTTONUP => { + self.handle_xbutton_msg(handle, wparam, lparam, Self::handle_mouse_up_msg) + } + WM_MOUSEWHEEL => self.handle_mouse_wheel_msg(handle, wparam, lparam), + WM_MOUSEHWHEEL => self.handle_mouse_horizontal_wheel_msg(handle, wparam, lparam), + WM_SYSKEYUP => self.handle_syskeyup_msg(wparam, lparam), + WM_KEYUP => self.handle_keyup_msg(wparam, lparam), + WM_GPUI_KEYDOWN => self.handle_keydown_msg(wparam, lparam), + WM_CHAR => self.handle_char_msg(wparam), + WM_IME_STARTCOMPOSITION => self.handle_ime_position(handle), + WM_IME_COMPOSITION => self.handle_ime_composition(handle, lparam), + WM_SETCURSOR => self.handle_set_cursor(handle, lparam), + WM_SETTINGCHANGE => self.handle_system_settings_changed(handle, wparam, lparam), + WM_INPUTLANGCHANGE => self.handle_input_language_changed(), + WM_SHOWWINDOW => self.handle_window_visibility_changed(handle, wparam), + WM_GPUI_CURSOR_STYLE_CHANGED => self.handle_cursor_changed(lparam), + WM_GPUI_FORCE_UPDATE_WINDOW => self.draw_window(handle, true), + WM_GPUI_GPU_DEVICE_LOST => self.handle_device_lost(lparam), + DM_POINTERHITTEST => self.handle_dm_pointer_hit_test(wparam), + WM_GETOBJECT => self.handle_wm_getobject(wparam, lparam), + _ => None, + }; + if let Some(n) = handled { + LRESULT(n) + } else { + unsafe { DefWindowProcW(handle, msg, wparam, lparam) } + } + } + + fn handle_end_session_msg(&self, wparam: WPARAM) -> Option { + if wparam.0 != 0 { + unsafe { + SendMessageW( + self.platform_window_handle, + WM_GPUI_END_SESSION, + Some(WPARAM(self.validation_number)), + None, + ); + } + } + Some(0) + } + + fn handle_move_msg(&self, handle: HWND, lparam: LPARAM) -> Option { + let origin = logical_point( + lparam.signed_loword() as f32, + lparam.signed_hiword() as f32, + self.state.scale_factor.get(), + ); + self.state.origin.set(origin); + let size = self.state.logical_size.get(); + let center_x = origin.x.as_f32() + size.width.as_f32() / 2.; + let center_y = origin.y.as_f32() + size.height.as_f32() / 2.; + let monitor_bounds = self.state.display.get().bounds(); + if center_x < monitor_bounds.left().as_f32() + || center_x > monitor_bounds.right().as_f32() + || center_y < monitor_bounds.top().as_f32() + || center_y > monitor_bounds.bottom().as_f32() + { + // center of the window may have moved to another monitor + let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONULL) }; + // minimize the window can trigger this event too, in this case, + // monitor is invalid, we do nothing. + if !monitor.is_invalid() && self.state.display.get().handle != monitor { + // we will get the same monitor if we only have one + self.state.display.set(WindowsDisplay::new( + WindowsDisplay::display_id_for_monitor(monitor), + )?); + } + } + if let Some(mut callback) = self.state.callbacks.moved.take() { + callback(); + self.state.callbacks.moved.set(Some(callback)); + } + Some(0) + } + + fn handle_get_min_max_info_msg(&self, lparam: LPARAM) -> Option { + let min_size = self.state.min_size?; + let scale_factor = self.state.scale_factor.get(); + let boarder_offset = &self.state.border_offset; + + unsafe { + let minmax_info = &mut *(lparam.0 as *mut MINMAXINFO); + minmax_info.ptMinTrackSize.x = min_size.width.scale(scale_factor).as_f32() as i32 + + boarder_offset.width_offset.get(); + minmax_info.ptMinTrackSize.y = min_size.height.scale(scale_factor).as_f32() as i32 + + boarder_offset.height_offset.get(); + } + Some(0) + } + + fn handle_size_msg(self: &Rc, wparam: WPARAM, lparam: LPARAM) -> Option { + // Minimizing and restoring both arrive as `WM_SIZE`; the deferred report + // reads `IsIconic` at delivery, so one call covers both directions. + self.report_visibility(); + + // Don't resize the renderer when the window is minimized, but record that it was minimized so + // that on restore the swap chain can be recreated via `update_drawable_size_even_if_unchanged`. + if wparam.0 == SIZE_MINIMIZED as usize { + self.state + .restore_from_minimized + .set(self.state.callbacks.request_frame.take()); + return Some(0); + } + + let width = lparam.loword().max(1) as i32; + let height = lparam.hiword().max(1) as i32; + let new_size = size(DevicePixels(width), DevicePixels(height)); + + let scale_factor = self.state.scale_factor.get(); + let mut should_resize_renderer = false; + if let Some(restore_from_minimized) = self.state.restore_from_minimized.take() { + self.state + .callbacks + .request_frame + .set(Some(restore_from_minimized)); + } else { + should_resize_renderer = true; + } + + self.handle_size_change(new_size, scale_factor, should_resize_renderer); + Some(0) + } + + fn handle_size_change( + &self, + device_size: Size, + scale_factor: f32, + should_resize_renderer: bool, + ) { + let new_logical_size = device_size.to_pixels(scale_factor); + + self.state.logical_size.set(new_logical_size); + if should_resize_renderer + && let Err(e) = self.state.renderer.borrow_mut().resize(device_size) + { + log::error!("Failed to resize renderer, invalidating devices: {}", e); + self.state + .invalidate_devices + .store(true, std::sync::atomic::Ordering::Release); + } + if let Some(mut callback) = self.state.callbacks.resize.take() { + callback(new_logical_size, scale_factor); + self.state.callbacks.resize.set(Some(callback)); + } + } + + fn handle_size_move_loop(&self, handle: HWND) -> Option { + unsafe { + let ret = SetTimer( + Some(handle), + SIZE_MOVE_LOOP_TIMER_ID, + USER_TIMER_MINIMUM, + None, + ); + if ret == 0 { + log::error!( + "unable to create timer: {}", + std::io::Error::last_os_error() + ); + } + } + None + } + + fn handle_size_move_loop_exit(&self, handle: HWND) -> Option { + unsafe { + KillTimer(Some(handle), SIZE_MOVE_LOOP_TIMER_ID).log_err(); + } + None + } + + fn handle_timer_msg(&self, handle: HWND, wparam: WPARAM) -> Option { + if wparam.0 == SIZE_MOVE_LOOP_TIMER_ID { + let mut runnables = self.main_receiver.clone().try_iter(); + while let Some(Ok(runnable)) = runnables.next() { + WindowsDispatcher::execute_runnable(runnable); + } + self.handle_paint_msg(handle) + } else { + None + } + } + + fn handle_paint_msg(&self, handle: HWND) -> Option { + self.draw_window(handle, false) + } + + fn handle_close_msg(&self) -> Option { + let mut callback = self.state.callbacks.should_close.take()?; + let should_close = callback(); + self.state.callbacks.should_close.set(Some(callback)); + if should_close { None } else { Some(0) } + } + + fn handle_destroy_msg(&self, handle: HWND) -> Option { + let callback = { self.state.callbacks.close.take() }; + // Re-enable parent window if this was a modal dialog + if let Some(parent_hwnd) = self.parent_hwnd { + unsafe { + let _ = EnableWindow(parent_hwnd, true); + let _ = SetForegroundWindow(parent_hwnd); + } + } + + if let Some(callback) = callback { + callback(); + } + unsafe { + PostMessageW( + Some(self.platform_window_handle), + WM_GPUI_CLOSE_ONE_WINDOW, + WPARAM(self.validation_number), + LPARAM(handle.0 as isize), + ) + .log_err(); + } + Some(0) + } + + fn handle_mouse_move_msg(&self, handle: HWND, lparam: LPARAM, wparam: WPARAM) -> Option { + self.start_tracking_mouse(handle, TME_LEAVE); + self.restore_cursor_after_hide(); + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + let scale_factor = self.state.scale_factor.get(); + + let pressed_button = match MODIFIERKEYS_FLAGS(wparam.loword() as u32) { + flags if flags.contains(MK_LBUTTON) => Some(MouseButton::Left), + flags if flags.contains(MK_RBUTTON) => Some(MouseButton::Right), + flags if flags.contains(MK_MBUTTON) => Some(MouseButton::Middle), + flags if flags.contains(MK_XBUTTON1) => { + Some(MouseButton::Navigate(NavigationDirection::Back)) + } + flags if flags.contains(MK_XBUTTON2) => { + Some(MouseButton::Navigate(NavigationDirection::Forward)) + } + _ => None, + }; + let x = lparam.signed_loword() as f32; + let y = lparam.signed_hiword() as f32; + let input = PlatformInput::MouseMove(MouseMoveEvent { + position: logical_point(x, y, scale_factor), + pressed_button, + modifiers: current_modifiers(), + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_mouse_leave_msg(&self) -> Option { + self.state.hovered.set(false); + // The next window's `WM_SETCURSOR` picks its own cursor, so we just clear + // the flag for tight `is_cursor_visible()` semantics. + self.state.cursor_visible.store(true, Ordering::Relaxed); + if let Some(mut callback) = self.state.callbacks.hovered_status_change.take() { + callback(false); + self.state + .callbacks + .hovered_status_change + .set(Some(callback)); + } + + Some(0) + } + + fn handle_syskeyup_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option { + let input = handle_key_event(wparam, lparam, &self.state, |keystroke, _| { + PlatformInput::KeyUp(KeyUpEvent { keystroke }) + })?; + let mut func = self.state.callbacks.input.take()?; + + func(input); + self.state.callbacks.input.set(Some(func)); + + // Always return 0 to indicate that the message was handled, so we could properly handle `ModifiersChanged` event. + Some(0) + } + + // It's a known bug that you can't trigger `ctrl-shift-0`. See: + // https://superuser.com/questions/1455762/ctrl-shift-number-key-combination-has-stopped-working-for-a-few-numbers + fn handle_keydown_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option { + let Some(input) = handle_key_event( + wparam, + lparam, + &self.state, + |keystroke, prefer_character_input| { + PlatformInput::KeyDown(KeyDownEvent { + keystroke, + is_held: lparam.0 & (0x1 << 30) > 0, + prefer_character_input, + }) + }, + ) else { + return Some(1); + }; + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + + let handled = !func(input).propagate; + + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_keyup_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option { + let Some(input) = handle_key_event(wparam, lparam, &self.state, |keystroke, _| { + PlatformInput::KeyUp(KeyUpEvent { keystroke }) + }) else { + return Some(1); + }; + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_char_msg(&self, wparam: WPARAM) -> Option { + let input = self.parse_char_message(wparam)?; + self.with_input_handler(|input_handler| { + input_handler.replace_text_in_range(None, &input); + }); + + Some(0) + } + + fn handle_mouse_down_msg( + &self, + handle: HWND, + button: MouseButton, + lparam: LPARAM, + ) -> Option { + unsafe { SetCapture(handle) }; + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + let x = lparam.signed_loword(); + let y = lparam.signed_hiword(); + let physical_point = point(DevicePixels(x as i32), DevicePixels(y as i32)); + let click_count = self.state.click_state.update(button, physical_point); + let scale_factor = self.state.scale_factor.get(); + + let input = PlatformInput::MouseDown(MouseDownEvent { + button, + position: logical_point(x as f32, y as f32, scale_factor), + modifiers: current_modifiers(), + click_count, + first_mouse: false, + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_mouse_up_msg( + &self, + _handle: HWND, + button: MouseButton, + lparam: LPARAM, + ) -> Option { + unsafe { ReleaseCapture().log_err() }; + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + let x = lparam.signed_loword() as f32; + let y = lparam.signed_hiword() as f32; + let click_count = self.state.click_state.current_count.get(); + let scale_factor = self.state.scale_factor.get(); + + let input = PlatformInput::MouseUp(MouseUpEvent { + button, + position: logical_point(x, y, scale_factor), + modifiers: current_modifiers(), + click_count, + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_xbutton_msg( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + handler: impl Fn(&Self, HWND, MouseButton, LPARAM) -> Option, + ) -> Option { + let nav_dir = match wparam.hiword() { + XBUTTON1 => NavigationDirection::Back, + XBUTTON2 => NavigationDirection::Forward, + _ => return Some(1), + }; + handler(self, handle, MouseButton::Navigate(nav_dir), lparam) + } + + fn handle_mouse_wheel_msg( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + let modifiers = current_modifiers(); + + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + let scale_factor = self.state.scale_factor.get(); + let wheel_scroll_amount = match modifiers.shift { + true => self + .system_settings() + .mouse_wheel_settings + .wheel_scroll_chars + .get(), + false => self + .system_settings() + .mouse_wheel_settings + .wheel_scroll_lines + .get(), + }; + + let wheel_distance = + (wparam.signed_hiword() as f32 / WHEEL_DELTA as f32) * wheel_scroll_amount as f32; + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + let input = PlatformInput::ScrollWheel(ScrollWheelEvent { + position: logical_point(cursor_point.x as f32, cursor_point.y as f32, scale_factor), + delta: ScrollDelta::Lines(match modifiers.shift { + true => Point { + x: wheel_distance, + y: 0.0, + }, + false => Point { + y: wheel_distance, + x: 0.0, + }, + }), + modifiers, + touch_phase: TouchPhase::Moved, + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn handle_mouse_horizontal_wheel_msg( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + let Some(mut func) = self.state.callbacks.input.take() else { + return Some(1); + }; + let scale_factor = self.state.scale_factor.get(); + let wheel_scroll_chars = self + .system_settings() + .mouse_wheel_settings + .wheel_scroll_chars + .get(); + + let wheel_distance = + (-wparam.signed_hiword() as f32 / WHEEL_DELTA as f32) * wheel_scroll_chars as f32; + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + let event = PlatformInput::ScrollWheel(ScrollWheelEvent { + position: logical_point(cursor_point.x as f32, cursor_point.y as f32, scale_factor), + delta: ScrollDelta::Lines(Point { + x: wheel_distance, + y: 0.0, + }), + modifiers: current_modifiers(), + touch_phase: TouchPhase::Moved, + }); + let handled = !func(event).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { Some(1) } + } + + fn retrieve_caret_position(&self) -> Option { + self.with_input_handler_and_scale_factor(|input_handler, scale_factor| { + let caret_range = input_handler.selected_text_range(false)?; + let caret_position = input_handler.bounds_for_range(caret_range.range)?; + Some(POINT { + // logical to physical + x: (caret_position.origin.x.as_f32() * scale_factor) as i32, + y: (caret_position.origin.y.as_f32() * scale_factor) as i32 + + ((caret_position.size.height.as_f32() * scale_factor) as i32 / 2), + }) + }) + } + + fn handle_ime_position(&self, handle: HWND) -> Option { + if let Some(caret_position) = self.retrieve_caret_position() { + self.update_ime_position(handle, caret_position); + } + Some(0) + } + + pub(crate) fn update_ime_position(&self, handle: HWND, caret_position: POINT) { + let Some(ctx) = ImeContext::get(handle) else { + return; + }; + unsafe { + ImmSetCompositionWindow( + *ctx, + &COMPOSITIONFORM { + dwStyle: CFS_POINT, + ptCurrentPos: caret_position, + ..Default::default() + }, + ) + .ok() + .log_err(); + + ImmSetCandidateWindow( + *ctx, + &CANDIDATEFORM { + dwStyle: CFS_CANDIDATEPOS, + ptCurrentPos: caret_position, + ..Default::default() + }, + ) + .ok() + .log_err(); + } + } + + fn update_ime_enabled(&self, handle: HWND) { + let ime_enabled = self + .with_input_handler(|input_handler| input_handler.query_accepts_text_input()) + .unwrap_or(false); + if ime_enabled == self.state.ime_enabled.get() { + return; + } + self.state.ime_enabled.set(ime_enabled); + unsafe { + if ime_enabled { + ImmAssociateContextEx(handle, HIMC::default(), IACE_DEFAULT) + .ok() + .log_err(); + } else { + // The IME context is per-thread, so without this check a change in this + // window's text input state could commit an IME composition happening in another window. + if GetFocus() == handle + && let Some(ctx) = ImeContext::get(handle) + { + ImmNotifyIME(*ctx, NI_COMPOSITIONSTR, CPS_COMPLETE, 0) + .ok() + .log_err(); + } + ImmAssociateContextEx(handle, HIMC::default(), 0) + .ok() + .log_err(); + } + } + } + + fn handle_ime_composition(&self, handle: HWND, lparam: LPARAM) -> Option { + let ctx = ImeContext::get(handle)?; + self.handle_ime_composition_inner(*ctx, lparam) + } + + fn handle_ime_composition_inner(&self, ctx: HIMC, lparam: LPARAM) -> Option { + let lparam = lparam.0 as u32; + if lparam == 0 { + // Japanese IME may send this message with lparam = 0, which indicates that + // there is no composition string. + self.with_input_handler(|input_handler| { + input_handler.replace_text_in_range(None, ""); + })?; + Some(0) + } else { + if lparam & GCS_RESULTSTR.0 > 0 { + let comp_result = parse_ime_composition_string(ctx, GCS_RESULTSTR)?; + self.with_input_handler(|input_handler| { + input_handler + .replace_text_in_range(None, &String::from_utf16_lossy(&comp_result)); + })?; + } + if lparam & GCS_COMPSTR.0 > 0 { + let comp_string = parse_ime_composition_string(ctx, GCS_COMPSTR)?; + let caret_pos = + (!comp_string.is_empty() && lparam & GCS_CURSORPOS.0 > 0).then(|| { + let cursor_pos = retrieve_composition_cursor_position(ctx); + let pos = if should_use_ime_cursor_position(ctx, cursor_pos) { + cursor_pos + } else { + comp_string.len() + }; + pos..pos + }); + self.with_input_handler(|input_handler| { + input_handler.replace_and_mark_text_in_range( + None, + &String::from_utf16_lossy(&comp_string), + caret_pos, + ); + })?; + } + if lparam & (GCS_RESULTSTR.0 | GCS_COMPSTR.0) > 0 { + return Some(0); + } + + // currently, we don't care other stuff + None + } + } + + fn handle_calc_client_size( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + if !self.hide_title_bar || self.state.is_fullscreen() || wparam.0 == 0 { + return None; + } + + unsafe { + let params = lparam.0 as *mut NCCALCSIZE_PARAMS; + let saved_top = (*params).rgrc[0].top; + let result = DefWindowProcW(handle, WM_NCCALCSIZE, wparam, lparam); + (*params).rgrc[0].top = saved_top; + if self.state.is_maximized() { + let dpi = GetDpiForWindow(handle); + (*params).rgrc[0].top += get_frame_thicknessx(dpi); + } + Some(result.0 as isize) + } + } + + fn handle_activate_msg(self: &Rc, wparam: WPARAM) -> Option { + let activated = wparam.loword() > 0; + + let events = self + .state + .a11y + .try_borrow_mut() + .ok() + .and_then(|mut a11y| a11y.as_mut()?.adapter.update_window_focus_state(activated)); + if let Some(events) = events { + events.raise(); + } + + let this = self.clone(); + + if !activated { + this.state.cursor_visible.store(true, Ordering::Relaxed); + } + + // When the window is activated (gains focus), reset the modifier tracking state. + // This fixes the issue where Alt-Tab away and back leaves stale modifier state + // (especially the Alt key) because Windows doesn't always send key-up events to + // windows that have lost focus. + if activated { + this.state.last_reported_modifiers.set(None); + this.state.last_reported_capslock.set(None); + + if let Some(mut func) = this.state.callbacks.input.take() { + let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent { + modifiers: current_modifiers(), + capslock: current_capslock(), + }); + func(input); + this.state.callbacks.input.set(Some(func)); + } + } + + self.executor + .spawn(async move { + if let Some(mut func) = this.state.callbacks.active_status_change.take() { + func(activated); + this.state.callbacks.active_status_change.set(Some(func)); + } + }) + .detach(); + + None + } + + fn handle_wm_getobject(&self, wparam: WPARAM, lparam: LPARAM) -> Option { + let result = { + let mut a11y = self.state.a11y.borrow_mut(); + let a11y = a11y.as_mut()?; + a11y.adapter.handle_wm_getobject( + accesskit_windows::WPARAM(wparam.0), + accesskit_windows::LPARAM(lparam.0), + &mut a11y.activation_handler, + )? + }; + // The borrow above must be dropped before calling `.into()`, because + // it calls `UiaReturnRawElementProvider` which may send a nested + // `WM_GETOBJECT` back into this window procedure. + let lresult: accesskit_windows::LRESULT = result.into(); + Some(lresult.0) + } + + fn handle_create_msg(&self, handle: HWND) -> Option { + if self.hide_title_bar { + notify_frame_changed(handle); + Some(0) + } else { + None + } + } + + fn handle_dpi_changed_msg( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + let new_dpi = wparam.loword() as f32; + + let is_maximized = self.state.is_maximized(); + let new_scale_factor = new_dpi / USER_DEFAULT_SCREEN_DPI as f32; + self.state.scale_factor.set(new_scale_factor); + self.state.border_offset.update(handle).log_err(); + + self.state + .direct_manipulation + .set_scale_factor(new_scale_factor); + + if is_maximized { + // Get the monitor and its work area at the new DPI + let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST) }; + let mut monitor_info: MONITORINFO = unsafe { std::mem::zeroed() }; + monitor_info.cbSize = std::mem::size_of::() as u32; + if unsafe { GetMonitorInfoW(monitor, &mut monitor_info) }.as_bool() { + let work_area = monitor_info.rcWork; + let width = work_area.right - work_area.left; + let height = work_area.bottom - work_area.top; + + // Update the window size to match the new monitor work area + // This will trigger WM_SIZE which will handle the size change + unsafe { + SetWindowPos( + handle, + None, + work_area.left, + work_area.top, + width, + height, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED, + ) + .context("unable to set maximized window position after dpi has changed") + .log_err(); + } + + // SetWindowPos may not send WM_SIZE for maximized windows in some cases, + // so we manually update the size to ensure proper rendering + let device_size = size(DevicePixels(width), DevicePixels(height)); + self.handle_size_change(device_size, new_scale_factor, true); + } + } else { + // For non-maximized windows, use the suggested RECT from the system + let rect = unsafe { &*(lparam.0 as *const RECT) }; + let width = rect.right - rect.left; + let height = rect.bottom - rect.top; + // this will emit `WM_SIZE` and `WM_MOVE` right here + // even before this function returns + // the new size is handled in `WM_SIZE` + unsafe { + SetWindowPos( + handle, + None, + rect.left, + rect.top, + width, + height, + SWP_NOZORDER | SWP_NOACTIVATE, + ) + .context("unable to set window position after dpi has changed") + .log_err(); + } + } + + Some(0) + } + + fn handle_display_change_msg(&self, handle: HWND) -> Option { + let new_monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONULL) }; + if new_monitor.is_invalid() { + log::error!("No monitor detected!"); + return None; + } + let new_display = WindowsDisplay::new(WindowsDisplay::display_id_for_monitor(new_monitor))?; + self.state.display.set(new_display); + Some(0) + } + + fn handle_hit_test_msg(&self, handle: HWND, lparam: LPARAM) -> Option { + if self.state.is_fullscreen() { + return None; + } + + let callback = self.state.callbacks.hit_test_window_control.take(); + let drag_area = if let Some(mut callback) = callback { + let area = callback(); + self.state + .callbacks + .hit_test_window_control + .set(Some(callback)); + area.and_then(|area| match area { + WindowControlArea::Drag if self.is_movable => Some(HTCAPTION as _), + WindowControlArea::Drag => None, + WindowControlArea::Close => Some(HTCLOSE as _), + WindowControlArea::Max if self.is_resizable => Some(HTMAXBUTTON as _), + WindowControlArea::Max if self.is_movable => Some(HTCAPTION as _), + WindowControlArea::Max => Some(HTNOWHERE as _), + WindowControlArea::Min if self.is_minimizable => Some(HTMINBUTTON as _), + WindowControlArea::Min if self.is_movable => Some(HTCAPTION as _), + WindowControlArea::Min => Some(HTNOWHERE as _), + }) + } else { + None + }; + + if !self.hide_title_bar { + // If the OS draws the title bar, we don't need to handle hit test messages. + return drag_area; + } + + let dpi = unsafe { GetDpiForWindow(handle) }; + // We do not use the OS title bar, so the default `DefWindowProcW` will only register a 1px edge for resizes + // We need to calculate the frame thickness ourselves and do the hit test manually. + let frame_y = get_frame_thicknessx(dpi); + let frame_x = get_frame_thicknessy(dpi); + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + if self.is_resizable + && !self.state.is_maximized() + && 0 <= cursor_point.y + && cursor_point.y <= frame_y + { + // x-axis actually goes from -frame_x to 0 + return Some(if cursor_point.x <= 0 { + HTTOPLEFT + } else { + let mut rect = Default::default(); + unsafe { GetWindowRect(handle, &mut rect) }.log_err(); + // right and bottom bounds of RECT are exclusive, thus `-1` + let right = rect.right - rect.left - 1; + // the bounds include the padding frames, so accommodate for both of them + if right - 2 * frame_x <= cursor_point.x { + HTTOPRIGHT + } else { + HTTOP + } + } as _); + } + + drag_area + } + + fn handle_nc_mouse_move_msg(&self, handle: HWND, lparam: LPARAM) -> Option { + self.start_tracking_mouse(handle, TME_LEAVE | TME_NONCLIENT); + self.restore_cursor_after_hide(); + + let mut func = self.state.callbacks.input.take()?; + let scale_factor = self.state.scale_factor.get(); + + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + let input = PlatformInput::MouseMove(MouseMoveEvent { + position: logical_point(cursor_point.x as f32, cursor_point.y as f32, scale_factor), + pressed_button: None, + modifiers: current_modifiers(), + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { Some(0) } else { None } + } + + fn handle_nc_mouse_down_msg( + &self, + handle: HWND, + button: MouseButton, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + if let Some(mut func) = self.state.callbacks.input.take() { + let scale_factor = self.state.scale_factor.get(); + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + let physical_point = point(DevicePixels(cursor_point.x), DevicePixels(cursor_point.y)); + let click_count = self.state.click_state.update(button, physical_point); + + let input = PlatformInput::MouseDown(MouseDownEvent { + button, + position: logical_point(cursor_point.x as f32, cursor_point.y as f32, scale_factor), + modifiers: current_modifiers(), + click_count, + first_mouse: false, + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { + return Some(0); + } + } else { + }; + + // Since these are handled in handle_nc_mouse_up_msg we must prevent the default window proc + if button == MouseButton::Left { + match wparam.0 as u32 { + HTMINBUTTON => self.state.nc_button_pressed.set(Some(HTMINBUTTON)), + HTMAXBUTTON => self.state.nc_button_pressed.set(Some(HTMAXBUTTON)), + HTCLOSE => self.state.nc_button_pressed.set(Some(HTCLOSE)), + _ => return None, + }; + Some(0) + } else { + None + } + } + + fn handle_nc_mouse_up_msg( + &self, + handle: HWND, + button: MouseButton, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + if let Some(mut func) = self.state.callbacks.input.take() { + let scale_factor = self.state.scale_factor.get(); + + let mut cursor_point = POINT { + x: lparam.signed_loword().into(), + y: lparam.signed_hiword().into(), + }; + unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() }; + let input = PlatformInput::MouseUp(MouseUpEvent { + button, + position: logical_point(cursor_point.x as f32, cursor_point.y as f32, scale_factor), + modifiers: current_modifiers(), + click_count: 1, + }); + let handled = !func(input).propagate; + self.state.callbacks.input.set(Some(func)); + + if handled { + return Some(0); + } + } else { + } + + let last_pressed = self.state.nc_button_pressed.take(); + if button == MouseButton::Left + && let Some(last_pressed) = last_pressed + { + let handled = match (wparam.0 as u32, last_pressed) { + (HTMINBUTTON, HTMINBUTTON) if self.is_minimizable => { + unsafe { ShowWindowAsync(handle, SW_MINIMIZE).ok().log_err() }; + true + } + (HTMINBUTTON, HTMINBUTTON) => true, + (HTMAXBUTTON, HTMAXBUTTON) if self.is_resizable => { + if self.state.is_maximized() { + unsafe { ShowWindowAsync(handle, SW_NORMAL).ok().log_err() }; + } else { + unsafe { ShowWindowAsync(handle, SW_MAXIMIZE).ok().log_err() }; + } + true + } + (HTMAXBUTTON, HTMAXBUTTON) => true, + (HTCLOSE, HTCLOSE) => { + unsafe { + PostMessageW(Some(handle), WM_CLOSE, WPARAM::default(), LPARAM::default()) + .log_err() + }; + true + } + _ => false, + }; + if handled { + return Some(0); + } + } + + None + } + + fn handle_cursor_changed(&self, lparam: LPARAM) -> Option { + let had_cursor = self.state.current_cursor.get().is_some(); + + self.state.current_cursor.set(if lparam.0 == 0 { + None + } else { + Some(HCURSOR(lparam.0 as _)) + }); + + if had_cursor != self.state.current_cursor.get().is_some() { + unsafe { SetCursor(self.state.current_cursor.get()) }; + } + + Some(0) + } + + fn handle_set_cursor(&self, handle: HWND, lparam: LPARAM) -> Option { + if unsafe { !IsWindowEnabled(handle).as_bool() } + || matches!( + lparam.loword() as u32, + HTLEFT + | HTRIGHT + | HTTOP + | HTTOPLEFT + | HTTOPRIGHT + | HTBOTTOM + | HTBOTTOMLEFT + | HTBOTTOMRIGHT + ) + { + return None; + } + let cursor = if self.state.cursor_visible.load(Ordering::Relaxed) { + self.state.current_cursor.get() + } else { + None + }; + unsafe { + SetCursor(cursor); + }; + Some(0) + } + + fn handle_system_settings_changed( + &self, + handle: HWND, + wparam: WPARAM, + lparam: LPARAM, + ) -> Option { + if wparam.0 != 0 { + self.state.click_state.system_update(wparam.0); + self.state.border_offset.update(handle).log_err(); + // system settings may emit a window message which wants to take the refcell self.state, so drop it + + self.system_settings().update(wparam.0); + } else { + self.handle_system_theme_changed(handle, lparam)?; + }; + + Some(0) + } + + fn handle_system_theme_changed(&self, handle: HWND, lparam: LPARAM) -> Option { + // lParam is a pointer to a string that indicates the area containing the system parameter + // that was changed. + let parameter = PCWSTR::from_raw(lparam.0 as _); + if unsafe { !parameter.is_null() && !parameter.is_empty() } + && let Some(parameter_string) = unsafe { parameter.to_string() }.log_err() + { + log::info!("System settings changed: {}", parameter_string); + if parameter_string.as_str() == "ImmersiveColorSet" { + let new_appearance = system_appearance() + .context("unable to get system appearance when handling ImmersiveColorSet") + .log_err()?; + + if new_appearance != self.state.appearance.get() { + self.state.appearance.set(new_appearance); + let mut callback = self.state.callbacks.appearance_changed.take()?; + + callback(); + self.state.callbacks.appearance_changed.set(Some(callback)); + configure_dwm_dark_mode(handle, new_appearance); + } + } + } + Some(0) + } + + fn handle_input_language_changed(&self) -> Option { + unsafe { + PostMessageW( + Some(self.platform_window_handle), + WM_GPUI_KEYBOARD_LAYOUT_CHANGED, + WPARAM(self.validation_number), + LPARAM(0), + ) + .log_err(); + } + Some(0) + } + + fn handle_window_visibility_changed( + self: &Rc, + handle: HWND, + wparam: WPARAM, + ) -> Option { + self.report_visibility(); + if wparam.0 == 1 { + self.draw_window(handle, false); + } + None + } + + // The window procedure can run while GPUI is updating this window (e.g. + // `ShowWindow` from an action handler), so deliver observers after that + // update completes, as activation does. The state is read at delivery so + // a burst of messages collapses to the final value. + fn report_visibility(self: &Rc) { + if self.state.last_visibility.get().is_none() { + return; + } + let this = self.clone(); + self.executor + .spawn(async move { + let visibility = this.visibility(); + if this.state.last_visibility.get() == Some(visibility) { + return; + } + this.state.last_visibility.set(Some(visibility)); + if let Some(mut callback) = this.state.callbacks.visibility_change.take() { + callback(visibility); + this.state.callbacks.visibility_change.set(Some(callback)); + } + }) + .detach(); + } + + fn handle_device_lost(&self, lparam: LPARAM) -> Option { + let devices = lparam.0 as *const DirectXDevices; + let devices = unsafe { &*devices }; + if let Err(err) = self + .state + .renderer + .borrow_mut() + .handle_device_lost(&devices) + { + panic!("Device lost: {err}"); + } + // Make sure the first `draw_window` after recovery (whether it comes + // from the forced WM_GPUI_FORCE_UPDATE_WINDOW or a stray WM_PAINT in + // between) is treated as a forced render so it both clears + // `skip_draws` and bypasses the view cache. + self.state.force_render_pending.set(true); + Some(0) + } + + fn handle_dm_pointer_hit_test(&self, wparam: WPARAM) -> Option { + self.state.direct_manipulation.on_pointer_hit_test(wparam); + None + } + + #[inline] + fn draw_window(&self, handle: HWND, force_render: bool) -> Option { + let Some(_guard) = self.state.draw_coordinator.try_begin_draw() else { + log::debug!("deferring re-entrant draw of window {handle:?}"); + if force_render { + self.state.force_render_pending.set(true); + } + // Validate the region so a nested message pump doesn't keep + // re-dispatching WM_PAINT for the still-invalid region in a busy + // loop until the in-progress draw unwinds. The vsync thread + // re-invalidates every window on each vsync (see + // `begin_vsync_thread`), so the deferred frame still gets drawn, + // at most one vsync late. + unsafe { ValidateRect(Some(handle), None).ok().log_err() }; + return Some(0); + }; + let mut request_frame = self.state.callbacks.request_frame.take()?; + + self.state.direct_manipulation.update(); + + let events = self.state.direct_manipulation.drain_events(); + if !events.is_empty() { + if let Some(mut func) = self.state.callbacks.input.take() { + for event in events { + func(event); + } + self.state.callbacks.input.set(Some(func)); + } + } + + let force_render = force_render || self.state.force_render_pending.take(); + if force_render { + // Re-enable drawing after a device loss recovery. The forced render + // will rebuild the scene with fresh atlas textures. + self.state.renderer.borrow_mut().mark_drawable(); + } + let (signal_at, signal_source) = self.state.frame_signal.take().map_or( + (None, FrameRequestSource::NativeCallback), + |(at, source)| (Some(at), source), + ); + request_frame(RequestFrameOptions { + require_presentation: false, + force_render, + signal_at, + signal_source, + }); + + self.state.callbacks.request_frame.set(Some(request_frame)); + self.update_ime_enabled(handle); + unsafe { ValidateRect(Some(handle), None).ok().log_err() }; + + Some(0) + } + + #[inline] + fn parse_char_message(&self, wparam: WPARAM) -> Option { + let code_point = wparam.loword(); + + // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G2630 + match code_point { + 0xD800..=0xDBFF => { + // High surrogate, wait for low surrogate + self.state.pending_surrogate.set(Some(code_point)); + None + } + 0xDC00..=0xDFFF => { + if let Some(high_surrogate) = self.state.pending_surrogate.take() { + // Low surrogate, combine with pending high surrogate + String::from_utf16(&[high_surrogate, code_point]).ok() + } else { + // Invalid low surrogate without a preceding high surrogate + log::warn!( + "Received low surrogate without a preceding high surrogate: {code_point:x}" + ); + None + } + } + _ => { + self.state.pending_surrogate.set(None); + char::from_u32(code_point as u32) + .filter(|c| !c.is_control()) + .map(|c| c.to_string()) + } + } + } + + /// Clear the hidden flag and restore the cursor immediately + fn restore_cursor_after_hide(&self) { + if !self.state.cursor_visible.swap(true, Ordering::Relaxed) { + unsafe { + SetCursor(self.state.current_cursor.get()); + } + } + } + + fn start_tracking_mouse(&self, handle: HWND, flags: TRACKMOUSEEVENT_FLAGS) { + if !self.state.hovered.get() { + self.state.hovered.set(true); + unsafe { + TrackMouseEvent(&mut TRACKMOUSEEVENT { + cbSize: std::mem::size_of::() as u32, + dwFlags: flags, + hwndTrack: handle, + dwHoverTime: HOVER_DEFAULT, + }) + .log_err() + }; + if let Some(mut callback) = self.state.callbacks.hovered_status_change.take() { + callback(true); + self.state + .callbacks + .hovered_status_change + .set(Some(callback)); + } + } + } + + fn with_input_handler(&self, f: F) -> Option + where + F: FnOnce(&mut PlatformInputHandler) -> R, + { + let mut input_handler = self.state.input_handler.take()?; + let result = f(&mut input_handler); + self.state.input_handler.set(Some(input_handler)); + Some(result) + } + + fn with_input_handler_and_scale_factor(&self, f: F) -> Option + where + F: FnOnce(&mut PlatformInputHandler, f32) -> Option, + { + let mut input_handler = self.state.input_handler.take()?; + let scale_factor = self.state.scale_factor.get(); + + let result = f(&mut input_handler, scale_factor); + self.state.input_handler.set(Some(input_handler)); + result + } +} + +struct ImeContext { + hwnd: HWND, + himc: HIMC, +} + +impl ImeContext { + fn get(hwnd: HWND) -> Option { + let himc = unsafe { ImmGetContext(hwnd) }; + if himc.is_invalid() { + return None; + } + Some(Self { hwnd, himc }) + } +} + +impl std::ops::Deref for ImeContext { + type Target = HIMC; + fn deref(&self) -> &HIMC { + &self.himc + } +} + +impl Drop for ImeContext { + fn drop(&mut self) { + unsafe { + ImmReleaseContext(self.hwnd, self.himc).ok().log_err(); + } + } +} + +fn handle_key_event( + wparam: WPARAM, + lparam: LPARAM, + state: &WindowsWindowState, + f: F, +) -> Option +where + F: FnOnce(Keystroke, bool) -> PlatformInput, +{ + let virtual_key = VIRTUAL_KEY(wparam.loword()); + let modifiers = current_modifiers(); + + match virtual_key { + VK_SHIFT | VK_CONTROL | VK_MENU | VK_LMENU | VK_RMENU | VK_LWIN | VK_RWIN => { + if state + .last_reported_modifiers + .get() + .is_some_and(|prev_modifiers| prev_modifiers == modifiers) + { + return None; + } + state.last_reported_modifiers.set(Some(modifiers)); + Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent { + modifiers, + capslock: current_capslock(), + })) + } + VK_PACKET => None, + VK_CAPITAL => { + let capslock = current_capslock(); + if state + .last_reported_capslock + .get() + .is_some_and(|prev_capslock| prev_capslock == capslock) + { + return None; + } + state.last_reported_capslock.set(Some(capslock)); + Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent { + modifiers, + capslock, + })) + } + vkey => { + let keystroke = parse_normal_key(vkey, lparam, modifiers)?; + Some(f(keystroke.0, keystroke.1)) + } + } +} + +fn parse_immutable(vkey: VIRTUAL_KEY) -> Option { + Some( + match vkey { + VK_SPACE => "space", + VK_BACK => "backspace", + VK_RETURN => "enter", + VK_TAB => "tab", + VK_UP => "up", + VK_DOWN => "down", + VK_RIGHT => "right", + VK_LEFT => "left", + VK_HOME => "home", + VK_END => "end", + VK_PRIOR => "pageup", + VK_NEXT => "pagedown", + VK_BROWSER_BACK => "back", + VK_BROWSER_FORWARD => "forward", + VK_ESCAPE => "escape", + VK_INSERT => "insert", + VK_DELETE => "delete", + VK_APPS => "menu", + VK_F1 => "f1", + VK_F2 => "f2", + VK_F3 => "f3", + VK_F4 => "f4", + VK_F5 => "f5", + VK_F6 => "f6", + VK_F7 => "f7", + VK_F8 => "f8", + VK_F9 => "f9", + VK_F10 => "f10", + VK_F11 => "f11", + VK_F12 => "f12", + VK_F13 => "f13", + VK_F14 => "f14", + VK_F15 => "f15", + VK_F16 => "f16", + VK_F17 => "f17", + VK_F18 => "f18", + VK_F19 => "f19", + VK_F20 => "f20", + VK_F21 => "f21", + VK_F22 => "f22", + VK_F23 => "f23", + VK_F24 => "f24", + _ => return None, + } + .to_string(), + ) +} + +fn parse_normal_key( + vkey: VIRTUAL_KEY, + lparam: LPARAM, + mut modifiers: Modifiers, +) -> Option<(Keystroke, bool)> { + let (key_char, prefer_character_input) = process_key(vkey, lparam.hiword()); + + let key = parse_immutable(vkey).or_else(|| { + let scan_code = lparam.hiword() & 0xFF; + get_keystroke_key(vkey, scan_code as u32, &mut modifiers) + })?; + + Some(( + Keystroke { + modifiers, + key, + key_char, + }, + prefer_character_input, + )) +} + +fn process_key(vkey: VIRTUAL_KEY, scan_code: u16) -> (Option, bool) { + let mut keyboard_state = [0u8; 256]; + unsafe { + if GetKeyboardState(&mut keyboard_state).is_err() { + return (None, false); + } + } + + let mut buffer_c = [0u16; 8]; + let result_c = unsafe { + ToUnicode( + vkey.0 as u32, + scan_code as u32, + Some(&keyboard_state), + &mut buffer_c, + 0x4, + ) + }; + + if result_c == 0 { + return (None, false); + } + + let c = &buffer_c[..result_c.unsigned_abs() as usize]; + let key_char = String::from_utf16(c) + .ok() + .filter(|s| !s.is_empty() && !s.chars().next().unwrap().is_control()); + + if result_c < 0 { + return (key_char, true); + } + + if key_char.is_none() { + return (None, false); + } + + // Workaround for some bug that makes the compiler think keyboard_state is still zeroed out + let keyboard_state = std::hint::black_box(keyboard_state); + let ctrl_down = (keyboard_state[VK_CONTROL.0 as usize] & 0x80) != 0; + let alt_down = (keyboard_state[VK_MENU.0 as usize] & 0x80) != 0; + let win_down = (keyboard_state[VK_LWIN.0 as usize] & 0x80) != 0 + || (keyboard_state[VK_RWIN.0 as usize] & 0x80) != 0; + + let has_modifiers = ctrl_down || alt_down || win_down; + if !has_modifiers { + return (key_char, false); + } + + let mut state_no_modifiers = keyboard_state; + state_no_modifiers[VK_CONTROL.0 as usize] = 0; + state_no_modifiers[VK_LCONTROL.0 as usize] = 0; + state_no_modifiers[VK_RCONTROL.0 as usize] = 0; + state_no_modifiers[VK_MENU.0 as usize] = 0; + state_no_modifiers[VK_LMENU.0 as usize] = 0; + state_no_modifiers[VK_RMENU.0 as usize] = 0; + state_no_modifiers[VK_LWIN.0 as usize] = 0; + state_no_modifiers[VK_RWIN.0 as usize] = 0; + + let mut buffer_c_no_modifiers = [0u16; 8]; + let result_c_no_modifiers = unsafe { + ToUnicode( + vkey.0 as u32, + scan_code as u32, + Some(&state_no_modifiers), + &mut buffer_c_no_modifiers, + 0x4, + ) + }; + + let c_no_modifiers = &buffer_c_no_modifiers[..result_c_no_modifiers.unsigned_abs() as usize]; + ( + key_char, + result_c != result_c_no_modifiers || c != c_no_modifiers, + ) +} + +fn parse_ime_composition_string(ctx: HIMC, comp_type: IME_COMPOSITION_STRING) -> Option> { + unsafe { + let string_len = ImmGetCompositionStringW(ctx, comp_type, None, 0); + if string_len >= 0 { + let mut buffer = vec![0u8; string_len as usize + 2]; + ImmGetCompositionStringW( + ctx, + comp_type, + Some(buffer.as_mut_ptr() as _), + string_len as _, + ); + let wstring = std::slice::from_raw_parts::( + buffer.as_mut_ptr().cast::(), + string_len as usize / 2, + ); + Some(wstring.to_vec()) + } else { + None + } + } +} + +#[inline] +fn retrieve_composition_cursor_position(ctx: HIMC) -> usize { + unsafe { ImmGetCompositionStringW(ctx, GCS_CURSORPOS, None, 0) as usize } +} + +fn should_use_ime_cursor_position(ctx: HIMC, cursor_pos: usize) -> bool { + let attrs_size = unsafe { ImmGetCompositionStringW(ctx, GCS_COMPATTR, None, 0) } as usize; + if attrs_size == 0 { + return false; + } + + let mut attrs = vec![0u8; attrs_size]; + let result = unsafe { + ImmGetCompositionStringW( + ctx, + GCS_COMPATTR, + Some(attrs.as_mut_ptr() as *mut _), + attrs_size as u32, + ) + }; + if result <= 0 { + return false; + } + + // Keep the cursor adjacent to the inserted text by only using the suggested position + // if it's adjacent to unconverted text. + let at_cursor_is_input = cursor_pos < attrs.len() && attrs[cursor_pos] == (ATTR_INPUT as u8); + let before_cursor_is_input = cursor_pos > 0 + && (cursor_pos - 1) < attrs.len() + && attrs[cursor_pos - 1] == (ATTR_INPUT as u8); + + at_cursor_is_input || before_cursor_is_input +} + +#[inline] +fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool { + unsafe { GetKeyState(vkey.0 as i32) < 0 } +} + +#[inline] +pub(crate) fn current_modifiers() -> Modifiers { + Modifiers { + control: is_virtual_key_pressed(VK_CONTROL), + alt: is_virtual_key_pressed(VK_MENU), + shift: is_virtual_key_pressed(VK_SHIFT), + platform: is_virtual_key_pressed(VK_LWIN) || is_virtual_key_pressed(VK_RWIN), + function: false, + } +} + +#[inline] +pub(crate) fn current_capslock() -> Capslock { + let on = unsafe { GetKeyState(VK_CAPITAL.0 as i32) & 1 } > 0; + Capslock { on } +} + +// there is some additional non-visible space when talking about window +// borders on Windows: +// - SM_CXSIZEFRAME: The resize handle. +// - SM_CXPADDEDBORDER: Additional border space that isn't part of the resize handle. +fn get_frame_thicknessx(dpi: u32) -> i32 { + let resize_frame_thickness = unsafe { GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) }; + let padding_thickness = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) }; + resize_frame_thickness + padding_thickness +} + +fn get_frame_thicknessy(dpi: u32) -> i32 { + let resize_frame_thickness = unsafe { GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) }; + let padding_thickness = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) }; + resize_frame_thickness + padding_thickness +} + +fn notify_frame_changed(handle: HWND) { + unsafe { + SetWindowPos( + handle, + None, + 0, + 0, + 0, + 0, + SWP_FRAMECHANGED + | SWP_NOACTIVATE + | SWP_NOCOPYBITS + | SWP_NOMOVE + | SWP_NOOWNERZORDER + | SWP_NOREPOSITION + | SWP_NOSENDCHANGING + | SWP_NOSIZE + | SWP_NOZORDER, + ) + .log_err(); + } +} diff --git a/vendor/gpui-pre-windows/src/gpui_windows.rs b/vendor/gpui-pre-windows/src/gpui_windows.rs new file mode 100644 index 00000000..e7a45a03 --- /dev/null +++ b/vendor/gpui-pre-windows/src/gpui_windows.rs @@ -0,0 +1,43 @@ +#![cfg(target_os = "windows")] + +mod clipboard; +mod destination_list; +mod dialog; +mod direct_manipulation; +mod direct_write; +mod directx_atlas; +mod directx_devices; +mod directx_renderer; +mod dispatcher; +mod display; +mod events; +mod keyboard; +mod platform; +mod system_notifications; +mod system_settings; +mod util; +mod vsync; +mod window; +mod wrapper; + +pub(crate) use clipboard::*; +pub(crate) use destination_list::*; +pub(crate) use direct_write::*; +pub(crate) use directx_atlas::*; +pub(crate) use directx_devices::*; +pub(crate) use directx_renderer::*; +pub(crate) use dispatcher::*; +pub(crate) use display::*; +pub(crate) use events::*; +pub(crate) use keyboard::*; +pub(crate) use platform::*; +pub(crate) use system_notifications::*; +pub(crate) use system_settings::*; +pub(crate) use util::*; +pub(crate) use vsync::*; +pub(crate) use window::*; +pub(crate) use wrapper::*; + +pub use platform::WindowsPlatform; + +pub(crate) use windows::Win32::Foundation::HWND; diff --git a/vendor/gpui-pre-windows/src/keyboard.rs b/vendor/gpui-pre-windows/src/keyboard.rs new file mode 100644 index 00000000..8164bc15 --- /dev/null +++ b/vendor/gpui-pre-windows/src/keyboard.rs @@ -0,0 +1,371 @@ +use anyhow::Result; +use collections::HashMap; +use windows::Win32::UI::{ + Input::KeyboardAndMouse::{ + GetKeyboardLayoutNameW, MAPVK_VK_TO_CHAR, MAPVK_VK_TO_VSC, MapVirtualKeyW, ToUnicode, + VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_ABNT_C1, + VK_CONTROL, VK_MENU, VK_OEM_1, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, VK_OEM_7, + VK_OEM_8, VK_OEM_102, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_PLUS, VK_SHIFT, + }, + WindowsAndMessaging::KL_NAMELENGTH, +}; + +use gpui::{ + KeybindingKeystroke, Keystroke, Modifiers, PlatformKeyboardLayout, PlatformKeyboardMapper, +}; + +pub(crate) struct WindowsKeyboardLayout { + id: String, + name: String, +} + +pub(crate) struct WindowsKeyboardMapper { + key_to_vkey: HashMap, + vkey_to_key: HashMap, + vkey_to_shifted: HashMap, +} + +impl PlatformKeyboardLayout for WindowsKeyboardLayout { + fn id(&self) -> &str { + &self.id + } + + fn name(&self) -> &str { + &self.name + } +} + +impl PlatformKeyboardMapper for WindowsKeyboardMapper { + fn map_key_equivalent( + &self, + mut keystroke: Keystroke, + use_key_equivalents: bool, + ) -> KeybindingKeystroke { + let Some((vkey, shifted_key)) = self.get_vkey_from_key(&keystroke.key, use_key_equivalents) + else { + return KeybindingKeystroke::from_keystroke(keystroke); + }; + if shifted_key && keystroke.modifiers.shift { + log::warn!( + "Keystroke '{}' has both shift and a shifted key, this is likely a bug", + keystroke.key + ); + } + + let shift = shifted_key || keystroke.modifiers.shift; + keystroke.modifiers.shift = false; + + let Some(key) = self.vkey_to_key.get(&vkey).cloned() else { + log::error!( + "Failed to map key equivalent '{:?}' to a valid key", + keystroke + ); + return KeybindingKeystroke::from_keystroke(keystroke); + }; + + keystroke.key = if shift { + let Some(shifted_key) = self.vkey_to_shifted.get(&vkey).cloned() else { + log::error!( + "Failed to map keystroke {:?} with virtual key '{:?}' to a shifted key", + keystroke, + vkey + ); + return KeybindingKeystroke::from_keystroke(keystroke); + }; + shifted_key + } else { + key.clone() + }; + + let modifiers = Modifiers { + shift, + ..keystroke.modifiers + }; + + KeybindingKeystroke::new(keystroke, modifiers, key) + } + + fn get_key_equivalents(&self) -> Option<&HashMap> { + None + } +} + +impl WindowsKeyboardLayout { + pub(crate) fn new() -> Result { + let mut buffer = [0u16; KL_NAMELENGTH as usize]; // KL_NAMELENGTH includes the null terminator + unsafe { GetKeyboardLayoutNameW(&mut buffer)? }; + let id = String::from_utf16_lossy(&buffer[..buffer.len() - 1]); // Remove the null terminator + let entry = windows_registry::LOCAL_MACHINE.open(format!( + "System\\CurrentControlSet\\Control\\Keyboard Layouts\\{id}" + ))?; + let name = entry.get_string("Layout Text")?; + Ok(Self { id, name }) + } + + pub(crate) fn unknown() -> Self { + Self { + id: "unknown".to_string(), + name: "unknown".to_string(), + } + } +} + +impl WindowsKeyboardMapper { + pub(crate) fn new() -> Self { + let mut key_to_vkey = HashMap::default(); + let mut vkey_to_key = HashMap::default(); + let mut vkey_to_shifted = HashMap::default(); + for vkey in CANDIDATE_VKEYS { + if let Some(key) = get_key_from_vkey(*vkey) { + key_to_vkey.insert(key.clone(), (vkey.0, false)); + vkey_to_key.insert(vkey.0, key); + } + let scan_code = unsafe { MapVirtualKeyW(vkey.0 as u32, MAPVK_VK_TO_VSC) }; + if scan_code == 0 { + continue; + } + if let Some(shifted_key) = get_shifted_key(*vkey, scan_code) { + key_to_vkey.insert(shifted_key.clone(), (vkey.0, true)); + vkey_to_shifted.insert(vkey.0, shifted_key); + } + } + Self { + key_to_vkey, + vkey_to_key, + vkey_to_shifted, + } + } + + fn get_vkey_from_key(&self, key: &str, use_key_equivalents: bool) -> Option<(u16, bool)> { + if use_key_equivalents { + get_vkey_from_key_with_us_layout(key) + } else { + self.key_to_vkey.get(key).cloned() + } + } +} + +pub(crate) fn get_keystroke_key( + vkey: VIRTUAL_KEY, + scan_code: u32, + modifiers: &mut Modifiers, +) -> Option { + if modifiers.shift && need_to_convert_to_shifted_key(vkey) { + get_shifted_key(vkey, scan_code).inspect(|_| { + modifiers.shift = false; + }) + } else { + get_key_from_vkey(vkey) + } +} + +fn get_key_from_vkey(vkey: VIRTUAL_KEY) -> Option { + let key_data = unsafe { MapVirtualKeyW(vkey.0 as u32, MAPVK_VK_TO_CHAR) }; + if key_data == 0 { + return None; + } + + // The high word contains dead key flag, the low word contains the character + let key = char::from_u32(key_data & 0xFFFF)?; + + Some(key.to_ascii_lowercase().to_string()) +} + +#[inline] +fn need_to_convert_to_shifted_key(vkey: VIRTUAL_KEY) -> bool { + matches!( + vkey, + VK_OEM_3 + | VK_OEM_MINUS + | VK_OEM_PLUS + | VK_OEM_4 + | VK_OEM_5 + | VK_OEM_6 + | VK_OEM_1 + | VK_OEM_7 + | VK_OEM_COMMA + | VK_OEM_PERIOD + | VK_OEM_2 + | VK_OEM_102 + | VK_OEM_8 + | VK_ABNT_C1 + | VK_0 + | VK_1 + | VK_2 + | VK_3 + | VK_4 + | VK_5 + | VK_6 + | VK_7 + | VK_8 + | VK_9 + ) +} + +fn get_shifted_key(vkey: VIRTUAL_KEY, scan_code: u32) -> Option { + generate_key_char(vkey, scan_code, false, true, false) +} + +pub(crate) fn generate_key_char( + vkey: VIRTUAL_KEY, + scan_code: u32, + control: bool, + shift: bool, + alt: bool, +) -> Option { + let mut state = [0; 256]; + if control { + state[VK_CONTROL.0 as usize] = 0x80; + } + if shift { + state[VK_SHIFT.0 as usize] = 0x80; + } + if alt { + state[VK_MENU.0 as usize] = 0x80; + } + + let mut buffer = [0; 8]; + let len = unsafe { ToUnicode(vkey.0 as u32, scan_code, Some(&state), &mut buffer, 0x5) }; + + match len { + len if len > 0 => String::from_utf16(&buffer[..len as usize]) + .ok() + .filter(|candidate| { + !candidate.is_empty() && !candidate.chars().next().unwrap().is_control() + }), + len if len < 0 => String::from_utf16(&buffer[..(-len as usize)]).ok(), + _ => None, + } +} + +fn get_vkey_from_key_with_us_layout(key: &str) -> Option<(u16, bool)> { + match key { + // ` => VK_OEM_3 + "`" => Some((VK_OEM_3.0, false)), + "~" => Some((VK_OEM_3.0, true)), + "1" => Some((VK_1.0, false)), + "!" => Some((VK_1.0, true)), + "2" => Some((VK_2.0, false)), + "@" => Some((VK_2.0, true)), + "3" => Some((VK_3.0, false)), + "#" => Some((VK_3.0, true)), + "4" => Some((VK_4.0, false)), + "$" => Some((VK_4.0, true)), + "5" => Some((VK_5.0, false)), + "%" => Some((VK_5.0, true)), + "6" => Some((VK_6.0, false)), + "^" => Some((VK_6.0, true)), + "7" => Some((VK_7.0, false)), + "&" => Some((VK_7.0, true)), + "8" => Some((VK_8.0, false)), + "*" => Some((VK_8.0, true)), + "9" => Some((VK_9.0, false)), + "(" => Some((VK_9.0, true)), + "0" => Some((VK_0.0, false)), + ")" => Some((VK_0.0, true)), + "-" => Some((VK_OEM_MINUS.0, false)), + "_" => Some((VK_OEM_MINUS.0, true)), + "=" => Some((VK_OEM_PLUS.0, false)), + "+" => Some((VK_OEM_PLUS.0, true)), + "[" => Some((VK_OEM_4.0, false)), + "{" => Some((VK_OEM_4.0, true)), + "]" => Some((VK_OEM_6.0, false)), + "}" => Some((VK_OEM_6.0, true)), + "\\" => Some((VK_OEM_5.0, false)), + "|" => Some((VK_OEM_5.0, true)), + ";" => Some((VK_OEM_1.0, false)), + ":" => Some((VK_OEM_1.0, true)), + "'" => Some((VK_OEM_7.0, false)), + "\"" => Some((VK_OEM_7.0, true)), + "," => Some((VK_OEM_COMMA.0, false)), + "<" => Some((VK_OEM_COMMA.0, true)), + "." => Some((VK_OEM_PERIOD.0, false)), + ">" => Some((VK_OEM_PERIOD.0, true)), + "/" => Some((VK_OEM_2.0, false)), + "?" => Some((VK_OEM_2.0, true)), + _ => None, + } +} + +const CANDIDATE_VKEYS: &[VIRTUAL_KEY] = &[ + VK_OEM_3, + VK_OEM_MINUS, + VK_OEM_PLUS, + VK_OEM_4, + VK_OEM_5, + VK_OEM_6, + VK_OEM_1, + VK_OEM_7, + VK_OEM_COMMA, + VK_OEM_PERIOD, + VK_OEM_2, + VK_OEM_102, + VK_OEM_8, + VK_ABNT_C1, + VK_0, + VK_1, + VK_2, + VK_3, + VK_4, + VK_5, + VK_6, + VK_7, + VK_8, + VK_9, +]; + +#[cfg(test)] +mod tests { + use crate::WindowsKeyboardMapper; + use gpui::{Keystroke, Modifiers, PlatformKeyboardMapper}; + + #[test] + fn test_keyboard_mapper() { + let mapper = WindowsKeyboardMapper::new(); + + // Normal case + let keystroke = Keystroke { + modifiers: Modifiers::control(), + key: "a".to_string(), + key_char: None, + }; + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); + assert_eq!(*mapped.inner(), keystroke); + assert_eq!(mapped.key(), "a"); + assert_eq!(*mapped.modifiers(), Modifiers::control()); + + // Shifted case, ctrl-$ + let keystroke = Keystroke { + modifiers: Modifiers::control(), + key: "$".to_string(), + key_char: None, + }; + let mapped = mapper.map_key_equivalent(keystroke.clone(), true); + assert_eq!(*mapped.inner(), keystroke); + assert_eq!(mapped.key(), "4"); + assert_eq!(*mapped.modifiers(), Modifiers::control_shift()); + + // Shifted case, but shift is true + let keystroke = Keystroke { + modifiers: Modifiers::control_shift(), + key: "$".to_string(), + key_char: None, + }; + let mapped = mapper.map_key_equivalent(keystroke, true); + assert_eq!(mapped.inner().modifiers, Modifiers::control()); + assert_eq!(mapped.key(), "4"); + assert_eq!(*mapped.modifiers(), Modifiers::control_shift()); + + // Windows style + let keystroke = Keystroke { + modifiers: Modifiers::control_shift(), + key: "4".to_string(), + key_char: None, + }; + let mapped = mapper.map_key_equivalent(keystroke, true); + assert_eq!(mapped.inner().modifiers, Modifiers::control()); + assert_eq!(mapped.inner().key, "$"); + assert_eq!(mapped.key(), "4"); + assert_eq!(*mapped.modifiers(), Modifiers::control_shift()); + } +} diff --git a/vendor/gpui-pre-windows/src/platform.rs b/vendor/gpui-pre-windows/src/platform.rs new file mode 100644 index 00000000..995017fa --- /dev/null +++ b/vendor/gpui-pre-windows/src/platform.rs @@ -0,0 +1,1939 @@ +use std::{ + cell::{Cell, RefCell}, + ffi::{OsStr, OsString}, + os::windows::ffi::{OsStrExt as _, OsStringExt as _}, + path::{Path, PathBuf}, + rc::{Rc, Weak}, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, +}; + +use anyhow::{Context as _, Result, anyhow}; +use futures::channel::oneshot::Receiver; +use gpui_util::{ResultExt, get_powershell, new_std_command}; +use itertools::Itertools; +use parking_lot::RwLock; +use smallvec::SmallVec; +use windows::{ + UI::ViewManagement::UISettings, + Win32::{ + Foundation::*, + Graphics::{Direct3D11::ID3D11Device, Gdi::*}, + Security::Credentials::*, + System::{ + Com::*, + LibraryLoader::*, + Ole::*, + Power::*, + SystemInformation::*, + SystemServices::POWER_REQUEST_CONTEXT_VERSION, + Threading::{POWER_REQUEST_CONTEXT_SIMPLE_STRING, REASON_CONTEXT, REASON_CONTEXT_0}, + }, + UI::{Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, + }, + core::*, +}; + +use crate::*; +use gpui::*; + +struct TrackedWindow { + handle: SafeHwnd, + frame_signal: Arc, +} + +impl TrackedWindow { + fn as_raw(&self) -> HWND { + self.handle.as_raw() + } +} + +pub struct WindowsPlatform { + inner: Rc, + raw_window_handles: Arc>>, + /// The windowing mode to start in, applied when `run` starts. Windowed when unset. + initial_windowing: RefCell>, + /// Set to stop the current `VSyncProvider` thread, which runs while windowed. + vsync_stop: RefCell>>, + // The below members will never change throughout the entire lifecycle of the app. + /// Created with `headless()`: never windowed, and without a real text system. + headless: bool, + icon: HICON, + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + text_system: Arc, + direct_write_text_system: Option>, + drop_target_helper: Option, + /// Flag to instruct the `VSyncProvider` thread to invalidate the directx devices + /// as resizing them has failed, causing us to have lost at least the render target. + invalidate_devices: Arc, + handle: HWND, + suspend_resume_notification: RefCell>, + disable_direct_composition: bool, + has_package_identity: bool, + app_identity: RefCell>, + system_notifications: RefCell, +} + +struct WindowsPlatformInner { + state: WindowsPlatformState, + raw_window_handles: std::sync::Weak>>, + // The below members will never change throughout the entire lifecycle of the app. + validation_number: usize, + main_receiver: PriorityQueueReceiver, + dispatcher: Arc, +} + +pub(crate) struct WindowsPlatformState { + callbacks: PlatformCallbacks, + menus: RefCell>, + jump_list: RefCell, + // NOTE: standard cursor handles don't need to close. + pub(crate) current_cursor: Cell>, + /// Shared with each window so `WM_SETCURSOR` can read it directly. + pub(crate) cursor_visible: Arc, + /// Shared with each window to coordinate draws across windows on the UI + /// thread; see [`DrawCoordinator`]. + pub(crate) draw_coordinator: Rc, + directx_devices: RefCell>, +} + +#[derive(Default)] +struct PlatformCallbacks { + open_urls: Cell)>>>, + quit: Cell bool>>>, + reopen: Cell>>, + app_menu_action: Cell>>, + will_open_app_menu: Cell>>, + validate_app_menu_command: Cell bool>>>, + keyboard_layout_change: Cell>>, + system_sleep: Cell>>, + system_wake: Cell>>, +} + +impl WindowsPlatformState { + fn new(directx_devices: Option) -> Self { + let callbacks = PlatformCallbacks::default(); + let jump_list = JumpList::new(); + let current_cursor = load_cursor(CursorStyle::Arrow); + + Self { + callbacks, + jump_list: RefCell::new(jump_list), + current_cursor: Cell::new(current_cursor), + cursor_visible: Arc::new(AtomicBool::new(true)), + draw_coordinator: Rc::new(DrawCoordinator::new()), + directx_devices: RefCell::new(directx_devices), + menus: RefCell::new(Vec::new()), + } + } +} + +struct PowerRequest { + handle: HANDLE, + // `PowerCreateRequest` retains a pointer into the reason string for the + // lifetime of the handle, so the UTF-16 buffer must outlive the request. + _reason: Vec, +} + +unsafe impl Send for PowerRequest {} + +impl PowerRequest { + fn prevent_idle_sleep(reason: &str) -> Result { + let mut reason = reason.encode_utf16().chain([0]).collect::>(); + let context = REASON_CONTEXT { + Version: POWER_REQUEST_CONTEXT_VERSION, + Flags: POWER_REQUEST_CONTEXT_SIMPLE_STRING, + Reason: REASON_CONTEXT_0 { + SimpleReasonString: PWSTR(reason.as_mut_ptr()), + }, + }; + let handle = unsafe { PowerCreateRequest(&context) } + .context("Failed to create a Windows power request")?; + if let Err(error) = unsafe { PowerSetRequest(handle, PowerRequestSystemRequired) } { + unsafe { CloseHandle(handle) } + .context("Failed to close the Windows power request") + .log_err(); + return Err(error).context("Failed to set the Windows power request"); + } + Ok(Self { + handle, + _reason: reason, + }) + } +} + +impl Drop for PowerRequest { + fn drop(&mut self) { + unsafe { PowerClearRequest(self.handle, PowerRequestSystemRequired) } + .context("Failed to clear the Windows power request") + .log_err(); + unsafe { CloseHandle(self.handle) } + .context("Failed to close the Windows power request") + .log_err(); + } +} + +impl WindowsPlatform { + pub fn new(headless: bool) -> Result { + unsafe { + OleInitialize(None).context("unable to initialize Windows OLE")?; + } + // A platform that can become windowed needs the real text system from the start: the app + // keeps the one it's created with. It gets DirectX devices when it becomes windowed. + let (text_system, direct_write_text_system) = if !headless { + let dw_text_system = Arc::new( + DirectWriteTextSystem::new(None).context("Error creating DirectWriteTextSystem")?, + ); + ( + dw_text_system.clone() as Arc, + Some(dw_text_system), + ) + } else { + ( + Arc::new(gpui::NoopTextSystem::new()) as Arc, + None, + ) + }; + + let (main_sender, main_receiver) = PriorityQueueReceiver::new(); + let validation_number = if usize::BITS == 64 { + rand::random::() as usize + } else { + rand::random::() as usize + }; + let raw_window_handles = Arc::new(RwLock::new(SmallVec::new())); + + register_platform_window_class(); + let mut context = PlatformWindowCreateContext { + inner: None, + raw_window_handles: Arc::downgrade(&raw_window_handles), + validation_number, + main_sender: Some(main_sender), + main_receiver: Some(main_receiver), + directx_devices: None, + dispatcher: None, + }; + let result = unsafe { + CreateWindowExW( + WINDOW_EX_STYLE(0), + PLATFORM_WINDOW_CLASS_NAME, + None, + WINDOW_STYLE(0), + 0, + 0, + 0, + 0, + Some(HWND_MESSAGE), + None, + None, + Some(&raw const context as *const _), + ) + }; + let inner = context + .inner + .take() + .context("CreateWindowExW did not run correctly")??; + let dispatcher = context + .dispatcher + .take() + .context("CreateWindowExW did not run correctly")?; + let handle = result?; + + let disable_direct_composition = std::env::var(DISABLE_DIRECT_COMPOSITION) + .is_ok_and(|value| value == "true" || value == "1"); + let background_executor = BackgroundExecutor::new(dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(dispatcher); + + let drop_target_helper: Option = if !headless { + Some(unsafe { + CoCreateInstance(&CLSID_DragDropHelper, None, CLSCTX_INPROC_SERVER) + .context("Error creating drop target helper.")? + }) + } else { + None + }; + let icon = if !headless { + load_icon().unwrap_or_default() + } else { + HICON::default() + }; + + Ok(Self { + inner, + handle, + raw_window_handles, + initial_windowing: RefCell::new(None), + vsync_stop: RefCell::new(None), + headless, + icon, + background_executor, + foreground_executor, + text_system, + direct_write_text_system, + suspend_resume_notification: RefCell::new(None), + disable_direct_composition, + has_package_identity: has_package_identity(), + drop_target_helper, + invalidate_devices: Arc::new(AtomicBool::new(false)), + app_identity: RefCell::new(None), + system_notifications: RefCell::new(SystemNotificationState::new()), + }) + } + + pub(crate) fn window_from_hwnd(&self, hwnd: HWND) -> Option> { + self.raw_window_handles + .read() + .iter() + .find(|entry| entry.as_raw() == hwnd) + .and_then(|hwnd| window_from_hwnd(hwnd.as_raw())) + } + + #[inline] + fn post_message(&self, message: u32, wparam: WPARAM, lparam: LPARAM) { + self.raw_window_handles + .read() + .iter() + .for_each(|handle| unsafe { + PostMessageW(Some(handle.as_raw()), message, wparam, lparam).log_err(); + }); + } + + fn generate_creation_info(&self) -> WindowCreationInfo { + WindowCreationInfo { + icon: self.icon, + executor: self.foreground_executor.clone(), + current_cursor: self.inner.state.current_cursor.get(), + cursor_visible: self.inner.state.cursor_visible.clone(), + drop_target_helper: self.drop_target_helper.clone().unwrap(), + validation_number: self.inner.validation_number, + main_receiver: self.inner.main_receiver.clone(), + platform_window_handle: self.handle, + disable_direct_composition: self.disable_direct_composition, + directx_devices: self.inner.state.directx_devices.borrow().clone().unwrap(), + invalidate_devices: self.invalidate_devices.clone(), + draw_coordinator: self.inner.state.draw_coordinator.clone(), + } + } + + fn set_dock_menus(&self, menus: Vec) { + let mut actions = Vec::new(); + menus.into_iter().for_each(|menu| { + if let Some(dock_menu) = DockMenuItem::new(menu).log_err() { + actions.push(dock_menu); + } + }); + self.inner.state.jump_list.borrow_mut().dock_menus = actions; + let borrow = self.inner.state.jump_list.borrow(); + let dock_menus = borrow + .dock_menus + .iter() + .map(|menu| (menu.name.clone(), menu.description.clone())) + .collect::>(); + let recent_workspaces = borrow.recent_workspaces.clone(); + self.background_executor + .spawn(async move { + update_jump_list(&recent_workspaces, &dock_menus).log_err(); + }) + .detach(); + } + + fn update_jump_list( + &self, + menus: Vec, + entries: Vec>, + ) -> Task>> { + let mut actions = Vec::new(); + menus.into_iter().for_each(|menu| { + if let Some(dock_menu) = DockMenuItem::new(menu).log_err() { + actions.push(dock_menu); + } + }); + let mut jump_list = self.inner.state.jump_list.borrow_mut(); + jump_list.dock_menus = actions; + jump_list.recent_workspaces = entries.into(); + let dock_menus = jump_list + .dock_menus + .iter() + .map(|menu| (menu.name.clone(), menu.description.clone())) + .collect::>(); + let recent_workspaces = jump_list.recent_workspaces.clone(); + self.background_executor.spawn(async move { + update_jump_list(&recent_workspaces, &dock_menus) + .log_err() + .unwrap_or_default() + }) + } + + fn find_current_active_window(&self) -> Option { + let active_window_hwnd = unsafe { GetActiveWindow() }; + if active_window_hwnd.is_invalid() { + return None; + } + self.raw_window_handles + .read() + .iter() + .find(|hwnd| hwnd.as_raw() == active_window_hwnd) + .map(|hwnd| hwnd.as_raw()) + } + + fn is_windowed(&self) -> bool { + self.inner.state.directx_devices.borrow().is_some() + } + + /// Connects in the initial windowing mode, before the app finishes launching. + /// + /// # Panics + /// + /// Panics if DirectX can't be initialized, since the app can't start. Starts headless if this + /// process can't show windows, for example when started over SSH. + fn connect_initially(&self) { + let request = self + .initial_windowing + .borrow_mut() + .take() + .unwrap_or_else(|| WindowingRequest::Windowed(GraphicalEnvironment::detect())); + let WindowingRequest::Windowed(environment) = request else { + return; + }; + if let Err(error) = check_can_show_windows(&environment) { + log::info!("starting headless: {error:#}"); + return; + } + self.attach_gpu() + .unwrap_or_else(|error| panic!("failed to initialize DirectX: {error:#}")); + } + + /// Creates the DirectX devices that windows draw with, and starts vsync. + fn attach_gpu(&self) -> Result<()> { + let devices = DirectXDevices::new().context("Creating DirectX devices")?; + if let Some(text_system) = &self.direct_write_text_system { + text_system.handle_gpu_lost(&devices)?; + } + *self.inner.state.directx_devices.borrow_mut() = Some(devices); + self.begin_vsync_thread(); + Ok(()) + } + + /// Stops vsync and releases the DirectX devices. No window may be open. + fn detach_gpu(&self) { + if let Some(stop) = self.vsync_stop.borrow_mut().take() { + // Not joined: the thread can be sending this thread a message. It exits after its + // next vsync, and drops its reference to the devices then. + stop.store(true, Ordering::Release); + } + if let Some(text_system) = &self.direct_write_text_system { + text_system.release_gpu(); + } + self.inner.state.directx_devices.borrow_mut().take(); + } + + fn begin_vsync_thread(&self) { + let Some(directx_devices) = self.inner.state.directx_devices.borrow().clone() else { + return; + }; + let Some(direct_write_text_system) = &self.direct_write_text_system else { + return; + }; + let stop = Arc::new(AtomicBool::new(false)); + *self.vsync_stop.borrow_mut() = Some(stop.clone()); + let mut directx_device = directx_devices; + let platform_window: SafeHwnd = self.handle.into(); + let validation_number = self.inner.validation_number; + let all_windows = Arc::downgrade(&self.raw_window_handles); + let text_system = Arc::downgrade(direct_write_text_system); + let invalidate_devices = self.invalidate_devices.clone(); + + std::thread::Builder::new() + .name("VSyncProvider".to_owned()) + .spawn(move || { + let vsync_provider = VSyncProvider::new(); + loop { + let signal_source = vsync_provider.wait_for_vsync(); + let signal_at = PlatformFrameSignal::capture(scheduler::Instant::now); + if stop.load(Ordering::Acquire) { + break; + } + if check_device_lost(&directx_device.device) + || invalidate_devices.fetch_and(false, Ordering::Acquire) + { + if let Err(err) = handle_gpu_device_lost( + &mut directx_device, + platform_window.as_raw(), + validation_number, + &all_windows, + &text_system, + ) { + panic!("Device lost: {err}"); + } + } + let Some(all_windows) = all_windows.upgrade() else { + break; + }; + for hwnd in all_windows.read().iter() { + unsafe { + if let Some(signal_at) = signal_at { + if IsWindowVisible(hwnd.as_raw()).as_bool() + && !IsIconic(hwnd.as_raw()).as_bool() + { + hwnd.frame_signal.record(signal_at, signal_source); + } else { + // Hidden windows may not consume WM_PAINT until shown again. + hwnd.frame_signal.take(); + } + } + RedrawWindow(Some(hwnd.as_raw()), None, None, RDW_INVALIDATE) + .ok() + .log_err(); + } + } + } + }) + .unwrap(); + } +} + +fn translate_accelerator(msg: &MSG) -> Option<()> { + if msg.message != WM_KEYDOWN && msg.message != WM_SYSKEYDOWN { + return None; + } + + let result = unsafe { + SendMessageW( + msg.hwnd, + WM_GPUI_KEYDOWN, + Some(msg.wParam), + Some(msg.lParam), + ) + }; + (result.0 == 0).then_some(()) +} + +fn encode_restart_arguments(arguments: &[OsString]) -> OsString { + // `Start-Process` accepts a single native command line, so quote each argument according to + // the Windows argv parsing rules before passing the complete string through the environment. + let mut encoded = Vec::new(); + + for (index, argument) in arguments.iter().enumerate() { + if index > 0 { + encoded.push(b' ' as u16); + } + encoded.push(b'"' as u16); + + let mut backslash_count = 0; + for code_unit in argument.encode_wide() { + if code_unit == b'\\' as u16 { + backslash_count += 1; + } else { + if code_unit == b'"' as u16 { + encoded.extend(std::iter::repeat_n(b'\\' as u16, backslash_count * 2 + 1)); + } else { + encoded.extend(std::iter::repeat_n(b'\\' as u16, backslash_count)); + } + backslash_count = 0; + encoded.push(code_unit); + } + } + + encoded.extend(std::iter::repeat_n(b'\\' as u16, backslash_count * 2)); + encoded.push(b'"' as u16); + } + + OsString::from_wide(&encoded) +} + +impl Platform for WindowsPlatform { + fn background_executor(&self) -> BackgroundExecutor { + self.background_executor.clone() + } + + fn foreground_executor(&self) -> ForegroundExecutor { + self.foreground_executor.clone() + } + + fn text_system(&self) -> Arc { + self.text_system.clone() + } + + fn keyboard_layout(&self) -> Box { + Box::new( + WindowsKeyboardLayout::new() + .log_err() + .unwrap_or(WindowsKeyboardLayout::unknown()), + ) + } + + fn keyboard_mapper(&self) -> Rc { + Rc::new(WindowsKeyboardMapper::new()) + } + + fn on_keyboard_layout_change(&self, callback: Box) { + self.inner + .state + .callbacks + .keyboard_layout_change + .set(Some(callback)); + } + + fn on_thermal_state_change(&self, _callback: Box) {} + + fn thermal_state(&self) -> ThermalState { + ThermalState::Nominal + } + + fn prevent_idle_sleep(&self, reason: &str) -> Task> { + Task::ready( + PowerRequest::prevent_idle_sleep(reason) + .map(|request| ActivityGuard::new(move || drop(request))), + ) + } + + fn run(&self, on_finish_launching: Box) { + if !self.headless { + self.connect_initially(); + } + on_finish_launching(); + + let mut msg = MSG::default(); + unsafe { + while GetMessageW(&mut msg, None, 0, 0).as_bool() { + if translate_accelerator(&msg).is_none() { + _ = TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + } + + self.inner.with_callback( + |callbacks| &callbacks.quit, + |callback| { + callback(); + }, + ); + } + + fn quit(&self) { + self.foreground_executor() + .spawn(async { unsafe { PostQuitMessage(0) } }) + .detach(); + } + + fn set_initial_windowing(&self, request: WindowingRequest) { + *self.initial_windowing.borrow_mut() = Some(request); + } + + fn request_windowing(&self, request: WindowingRequest) -> Task> { + if self.headless { + return Task::ready(Err(anyhow!( + "a platform created headless can't switch windowing modes" + ))); + } + let windowed = self.is_windowed(); + Task::ready(match request { + WindowingRequest::Headless if !windowed => Err(anyhow!("already headless")), + WindowingRequest::Headless => { + self.detach_gpu(); + Ok(()) + } + WindowingRequest::Windowed(_) if windowed => Err(anyhow!("already windowed")), + WindowingRequest::Windowed(environment) => { + check_can_show_windows(&environment).and_then(|()| self.attach_gpu()) + } + }) + } + + fn graphical_environment(&self) -> Option { + self.is_windowed().then(GraphicalEnvironment::detect) + } + + fn restart(&self, binary_path: Option, arguments: Vec) { + let pid = std::process::id(); + let Some(app_path) = binary_path.or(self.app_path().log_err()) else { + return; + }; + let script = r#" + $pidToWaitFor = $env:ZED_RESTART_PID + $exePath = $env:ZED_RESTART_EXECUTABLE + $argumentList = $env:ZED_RESTART_ARGUMENTS + + [Environment]::SetEnvironmentVariable("ZED_RESTART_PID", $null) + [Environment]::SetEnvironmentVariable("ZED_RESTART_EXECUTABLE", $null) + [Environment]::SetEnvironmentVariable("ZED_RESTART_ARGUMENTS", $null) + + while ($true) { + $process = Get-Process -Id $pidToWaitFor -ErrorAction SilentlyContinue + if (-not $process) { + if ([string]::IsNullOrEmpty($argumentList)) { + Start-Process -FilePath $exePath + } else { + Start-Process -FilePath $exePath -ArgumentList $argumentList + } + break + } + Start-Sleep -Seconds 0.1 + } + "#; + + // Defer spawning to the foreground executor so it runs after the + // current `AppCell` borrow is released. On Windows, `Command::spawn()` + // can pump the Win32 message loop (via `CreateProcessW`), which + // re-enters message handling possibly resulting in another mutable + // borrow of the `AppCell` ending up with a double borrow panic + let Some(powershell) = get_powershell() else { + log::error!("failed to restart: PowerShell is unavailable"); + return; + }; + self.foreground_executor + .spawn(async move { + let mut command = new_std_command(powershell); + let arguments = encode_restart_arguments(&arguments); + command + .arg("-command") + .arg(script) + .env("ZED_RESTART_PID", pid.to_string()) + .env("ZED_RESTART_EXECUTABLE", app_path) + .env("ZED_RESTART_ARGUMENTS", arguments); + #[allow( + clippy::disallowed_methods, + reason = "We are restarting ourselves, using std command thus is fine" + )] + let restart_process = command.spawn(); + + match restart_process { + Ok(_) => unsafe { PostQuitMessage(0) }, + Err(e) => log::error!("failed to spawn restart script: {:?}", e), + } + }) + .detach(); + } + + fn activate(&self, _ignoring_other_apps: bool) {} + + fn hide(&self) {} + + // todo(windows) + fn hide_other_apps(&self) { + unimplemented!() + } + + // todo(windows) + fn unhide_other_apps(&self) { + unimplemented!() + } + + fn displays(&self) -> Vec> { + WindowsDisplay::displays() + } + + fn primary_display(&self) -> Option> { + WindowsDisplay::primary_monitor().map(|display| Rc::new(display) as Rc) + } + + #[cfg(feature = "screen-capture")] + fn is_screen_capture_supported(&self) -> bool { + true + } + + #[cfg(feature = "screen-capture")] + fn screen_capture_sources( + &self, + ) -> futures::channel::oneshot::Receiver>>> { + gpui::scap_screen_capture::scap_screen_sources(&self.foreground_executor) + } + + fn active_window(&self) -> Option { + let active_window_hwnd = unsafe { GetActiveWindow() }; + self.window_from_hwnd(active_window_hwnd) + .map(|inner| inner.handle) + } + + fn open_window( + &self, + handle: AnyWindowHandle, + options: WindowParams, + ) -> Result> { + if !self.is_windowed() { + return Err(anyhow!("cannot open windows while headless")); + } + let window = WindowsWindow::new(handle, options, self.generate_creation_info())?; + let handle = window.get_raw_handle(); + self.raw_window_handles.write().push(TrackedWindow { + handle: handle.into(), + frame_signal: window.state.frame_signal.clone(), + }); + + Ok(Box::new(window)) + } + + fn window_appearance(&self) -> WindowAppearance { + system_appearance().log_err().unwrap_or_default() + } + + fn open_url(&self, url: &str) { + if url.is_empty() { + return; + } + let url_string = url.to_string(); + self.background_executor() + .spawn(async move { + open_target(&url_string) + .with_context(|| format!("Opening url: {}", url_string)) + .log_err(); + }) + .detach(); + } + + fn on_open_urls(&self, callback: Box)>) { + self.inner.state.callbacks.open_urls.set(Some(callback)); + } + + fn prompt_for_paths( + &self, + options: PathPromptOptions, + ) -> Receiver>>> { + let owner = self + .find_current_active_window() + .and_then(|hwnd| self.window_from_hwnd(hwnd)) + .map(|window| window.dialog_owner.clone()); + crate::dialog::show_dialog(owner, &self.foreground_executor, move |window| { + file_open_dialog(options, Some(window)) + }) + } + + fn prompt_for_new_path( + &self, + directory: &Path, + suggested_name: Option<&str>, + ) -> Receiver>> { + let directory = directory.to_owned(); + let suggested_name = suggested_name.map(|s| s.to_owned()); + let owner = self + .find_current_active_window() + .and_then(|hwnd| self.window_from_hwnd(hwnd)) + .map(|window| window.dialog_owner.clone()); + crate::dialog::show_dialog(owner, &self.foreground_executor, move |window| { + file_save_dialog(directory, suggested_name, Some(window)) + }) + } + + fn can_select_mixed_files_and_dirs(&self) -> bool { + // The FOS_PICKFOLDERS flag toggles between "only files" and "only folders". + false + } + + fn reveal_path(&self, path: &Path) { + if path.as_os_str().is_empty() { + return; + } + let path = path.to_path_buf(); + self.background_executor() + .spawn(async move { + open_target_in_explorer(&path) + .with_context(|| format!("Revealing path {} in explorer", path.display())) + .log_err(); + }) + .detach(); + } + + fn open_with_system(&self, path: &Path) { + if path.as_os_str().is_empty() { + return; + } + let path = path.to_path_buf(); + self.background_executor() + .spawn(async move { + open_target(&path) + .with_context(|| format!("Opening {} with system", path.display())) + .log_err(); + }) + .detach(); + } + + fn on_quit(&self, callback: Box bool>) { + self.inner.state.callbacks.quit.set(Some(callback)); + } + + fn on_reopen(&self, callback: Box) { + self.inner.state.callbacks.reopen.set(Some(callback)); + } + + fn on_system_sleep(&self, callback: Box) { + self.inner.state.callbacks.system_sleep.set(Some(callback)); + } + + fn on_system_wake(&self, callback: Box) { + self.inner.state.callbacks.system_wake.set(Some(callback)); + let mut notification = self.suspend_resume_notification.borrow_mut(); + if notification.is_none() { + *notification = unsafe { + // SAFETY: self.handle is the platform window receiving WM_POWERBROADCAST. + RegisterSuspendResumeNotification( + HANDLE(self.handle.0), + DEVICE_NOTIFY_WINDOW_HANDLE, + ) + .log_err() + }; + } + } + + fn set_app_identity(&self, identifier: &str, name: &str) { + // If the process has package identity, it's automatally granted an AUMID by the system. + if self.has_package_identity { + return; + } + + let identifier_utf16 = windows::core::HSTRING::from(identifier); + // SAFETY: `identifier_utf16` outlives the call and is null-terminated. + if let Err(error) = unsafe { + windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID( + windows::core::PCWSTR(identifier_utf16.as_ptr()), + ) + } { + log::warn!("failed to set the process AppUserModelID: {error}"); + } + *self.app_identity.borrow_mut() = Some((identifier.to_string(), name.to_string())); + } + + fn show_system_notification(&self, notification: gpui::SystemNotification) { + let app_identity = self.app_identity.borrow().clone(); + self.system_notifications + .borrow_mut() + .show( + self.has_package_identity, + app_identity + .as_ref() + .map(|(identifier, name)| (identifier.as_str(), name.as_str())), + notification, + ) + .log_err(); + } + + fn dismiss_system_notification(&self, tag: &str) { + self.system_notifications.borrow_mut().dismiss(tag); + } + + fn on_system_notification_response( + &self, + callback: Box, + ) { + self.system_notifications + .borrow_mut() + .on_response(&self.foreground_executor, callback); + } + + fn set_menus(&self, menus: Vec

    , _keymap: &Keymap) { + *self.inner.state.menus.borrow_mut() = menus.into_iter().map(|menu| menu.owned()).collect(); + } + + fn get_menus(&self) -> Option> { + Some(self.inner.state.menus.borrow().clone()) + } + + fn set_dock_menu(&self, menus: Vec, _keymap: &Keymap) { + self.set_dock_menus(menus); + } + + fn on_app_menu_action(&self, callback: Box) { + self.inner + .state + .callbacks + .app_menu_action + .set(Some(callback)); + } + + fn on_will_open_app_menu(&self, callback: Box) { + self.inner + .state + .callbacks + .will_open_app_menu + .set(Some(callback)); + } + + fn on_validate_app_menu_command(&self, callback: Box bool>) { + self.inner + .state + .callbacks + .validate_app_menu_command + .set(Some(callback)); + } + + fn app_path(&self) -> Result { + Ok(std::env::current_exe()?) + } + + // todo(windows) + fn path_for_auxiliary_executable(&self, _name: &str) -> Result { + anyhow::bail!("not yet implemented"); + } + + fn set_cursor_style(&self, style: CursorStyle) { + let hcursor = load_cursor(style); + if self.inner.state.current_cursor.get().map(|c| c.0) != hcursor.map(|c| c.0) { + self.post_message( + WM_GPUI_CURSOR_STYLE_CHANGED, + WPARAM(0), + LPARAM(hcursor.map_or(0, |c| c.0 as isize)), + ); + self.inner.state.current_cursor.set(hcursor); + } + } + + fn hide_cursor_until_mouse_moves(&self) { + if !self + .inner + .state + .cursor_visible + .swap(false, Ordering::Relaxed) + { + return; + } + + for handle in self.raw_window_handles.read().iter() { + let Some(window) = window_from_hwnd(handle.as_raw()) else { + continue; + }; + if window.state.hovered.get() { + unsafe { SetCursor(None) }; + break; + } + } + } + + fn is_cursor_visible(&self) -> bool { + self.inner.state.cursor_visible.load(Ordering::Relaxed) + } + + fn should_auto_hide_scrollbars(&self) -> bool { + should_auto_hide_scrollbars().log_err().unwrap_or(false) + } + + fn write_to_clipboard(&self, item: ClipboardItem) { + write_to_clipboard(item); + } + + fn read_from_clipboard(&self) -> Option { + read_from_clipboard() + } + + fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task> { + // CredWriteW rejects larger blobs with the opaque RPC error + // 0x800706F7 "The stub received bad data", so fail with a clear + // message instead. + if password.len() > CRED_MAX_CREDENTIAL_BLOB_SIZE as usize { + return Task::ready(Err(anyhow!( + "credential for {url} is {} bytes, which exceeds the Windows Credential Manager limit of {CRED_MAX_CREDENTIAL_BLOB_SIZE} bytes", + password.len() + ))); + } + let password = password.to_vec(); + let mut username = username.encode_utf16().chain(Some(0)).collect_vec(); + let mut target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(Some(0)) + .collect_vec(); + self.background_executor().spawn(async move { + let credentials = CREDENTIALW { + LastWritten: unsafe { GetSystemTimeAsFileTime() }, + Flags: CRED_FLAGS(0), + Type: CRED_TYPE_GENERIC, + TargetName: PWSTR::from_raw(target_name.as_mut_ptr()), + CredentialBlobSize: password.len() as u32, + CredentialBlob: password.as_ptr() as *mut _, + Persist: CRED_PERSIST_LOCAL_MACHINE, + UserName: PWSTR::from_raw(username.as_mut_ptr()), + ..CREDENTIALW::default() + }; + unsafe { + CredWriteW(&credentials, 0).map_err(|err| { + anyhow!( + "Failed to write credentials to Windows Credential Manager: {}", + err, + ) + })?; + } + Ok(()) + }) + } + + fn read_credentials(&self, url: &str) -> Task)>>> { + let target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(Some(0)) + .collect_vec(); + self.background_executor().spawn(async move { + let mut credentials: *mut CREDENTIALW = std::ptr::null_mut(); + let result = unsafe { + CredReadW( + PCWSTR::from_raw(target_name.as_ptr()), + CRED_TYPE_GENERIC, + None, + &mut credentials, + ) + }; + + if let Err(err) = result { + // ERROR_NOT_FOUND means the credential doesn't exist. + // Return Ok(None) to match macOS and Linux behavior. + if err.code() == ERROR_NOT_FOUND.to_hresult() { + return Ok(None); + } + return Err(err.into()); + } + + if credentials.is_null() { + return Ok(None); + } + + // SAFETY: `CredReadW` succeeded, so this points to a valid `CREDENTIALW` until `CredFree` below. + let result = unsafe { username_and_password(&*credentials) }; + unsafe { CredFree(credentials as *const _ as _) }; + result.map(Some) + }) + } + + fn delete_credentials(&self, url: &str) -> Task> { + let target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(Some(0)) + .collect_vec(); + self.background_executor().spawn(async move { + unsafe { + CredDeleteW( + PCWSTR::from_raw(target_name.as_ptr()), + CRED_TYPE_GENERIC, + None, + )? + }; + Ok(()) + }) + } + + fn register_url_scheme(&self, _: &str) -> Task> { + Task::ready(Err(anyhow!("register_url_scheme unimplemented"))) + } + + fn perform_dock_menu_action(&self, action: usize) { + unsafe { + PostMessageW( + Some(self.handle), + WM_GPUI_DOCK_MENU_ACTION, + WPARAM(self.inner.validation_number), + LPARAM(action as isize), + ) + .log_err(); + } + } + + fn update_jump_list( + &self, + menus: Vec, + entries: Vec>, + ) -> Task>> { + self.update_jump_list(menus, entries) + } +} + +impl WindowsPlatformInner { + fn new(context: &mut PlatformWindowCreateContext) -> Result> { + let state = WindowsPlatformState::new(context.directx_devices.take()); + Ok(Rc::new(Self { + state, + raw_window_handles: context.raw_window_handles.clone(), + dispatcher: context + .dispatcher + .as_ref() + .context("missing dispatcher")? + .clone(), + validation_number: context.validation_number, + main_receiver: context + .main_receiver + .take() + .context("missing main receiver")?, + })) + } + + /// Calls `project` to project to the corresponding callback field, removes it from callbacks, calls `f` with the callback and then puts the callback back. + fn with_callback( + &self, + project: impl Fn(&PlatformCallbacks) -> &Cell>, + f: impl FnOnce(&mut T), + ) { + let callback = project(&self.state.callbacks).take(); + if let Some(mut callback) = callback { + f(&mut callback); + project(&self.state.callbacks).set(Some(callback)); + } + } + + fn handle_msg( + self: &Rc, + handle: HWND, + msg: u32, + wparam: WPARAM, + lparam: LPARAM, + ) -> LRESULT { + let handled = match msg { + WM_GPUI_CLOSE_ONE_WINDOW + | WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD + | WM_GPUI_DOCK_MENU_ACTION + | WM_GPUI_KEYBOARD_LAYOUT_CHANGED + | WM_GPUI_GPU_DEVICE_LOST + | WM_GPUI_END_SESSION => self.handle_gpui_events(msg, wparam, lparam), + WM_POWERBROADCAST => self.handle_power_broadcast(wparam), + _ => None, + }; + if let Some(result) = handled { + LRESULT(result) + } else { + unsafe { DefWindowProcW(handle, msg, wparam, lparam) } + } + } + + fn handle_gpui_events(&self, message: u32, wparam: WPARAM, lparam: LPARAM) -> Option { + if wparam.0 != self.validation_number { + log::error!("Wrong validation number while processing message: {message}"); + return None; + } + match message { + WM_GPUI_CLOSE_ONE_WINDOW => { + self.close_one_window(HWND(lparam.0 as _)); + Some(0) + } + WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD => self.run_foreground_task(), + WM_GPUI_DOCK_MENU_ACTION => self.handle_dock_action_event(lparam.0 as _), + WM_GPUI_KEYBOARD_LAYOUT_CHANGED => self.handle_keyboard_layout_change(), + WM_GPUI_GPU_DEVICE_LOST => self.handle_device_lost(lparam), + WM_GPUI_END_SESSION => self.handle_end_session(), + _ => unreachable!(), + } + } + + fn handle_end_session(&self) -> Option { + let mut shutdown_completed = false; + self.with_callback( + |callbacks| &callbacks.quit, + |callback| shutdown_completed = callback(), + ); + log::logger().flush(); + if shutdown_completed { + std::process::exit(0); + } + + // Shutdown couldn't run synchronously, since the AppCell is already borrowed. + // Windows may terminate the application as soon as we return from this handler, but if we post a WM_QUIT message now, + // we may get to gracefully shut down the app before we're terminated by the OS. + unsafe { PostQuitMessage(0) }; + Some(0) + } + + fn close_one_window(&self, target_window: HWND) -> bool { + let Some(all_windows) = self.raw_window_handles.upgrade() else { + log::error!("Failed to upgrade raw window handles"); + return false; + }; + let mut lock = all_windows.write(); + let index = lock + .iter() + .position(|handle| handle.as_raw() == target_window) + .unwrap(); + lock.remove(index); + + lock.is_empty() + } + + #[inline] + fn run_foreground_task(&self) -> Option { + const MAIN_TASK_TIMEOUT: u128 = 10; + + let start = std::time::Instant::now(); + 'tasks: loop { + 'timeout_loop: loop { + if start.elapsed().as_millis() >= MAIN_TASK_TIMEOUT { + log::debug!("foreground task timeout reached"); + // we spent our budget on gpui tasks, we likely have a lot of work queued so drain system events first to stay responsive + // then quit out of foreground work to allow us to process other gpui events first before returning back to foreground task work + // if we don't we might not for example process window quit events + let mut msg = MSG::default(); + let process_message = |msg: &_| { + if translate_accelerator(msg).is_none() { + _ = unsafe { TranslateMessage(msg) }; + unsafe { DispatchMessageW(msg) }; + } + }; + let peek_msg = |msg: &mut _, msg_kind| unsafe { + PeekMessageW(msg, None, 0, 0, PM_REMOVE | msg_kind).as_bool() + }; + // We need to process a paint message here as otherwise we will re-enter `run_foreground_task` before painting if we have work remaining. + // The reason for this is that windows prefers custom application message processing over system messages. + if peek_msg(&mut msg, PM_QS_PAINT) { + process_message(&msg); + } + while peek_msg(&mut msg, PM_QS_INPUT) { + process_message(&msg); + } + // Allow the main loop to process other gpui events before going back into `run_foreground_task` + unsafe { + if let Err(_) = PostMessageW( + Some(self.dispatcher.platform_window_handle.as_raw()), + WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD, + WPARAM(self.validation_number), + LPARAM(0), + ) { + self.dispatcher.wake_posted.store(false, Ordering::Release); + }; + } + break 'tasks; + } + let mut main_receiver = self.main_receiver.clone(); + match main_receiver.try_pop() { + Ok(Some(runnable)) => WindowsDispatcher::execute_runnable(runnable), + _ => break 'timeout_loop, + } + } + + // Someone could enqueue a Runnable here. The flag is still true, so they will not PostMessage. + // We need to check for those Runnables after we clear the flag. + self.dispatcher.wake_posted.store(false, Ordering::Release); + let mut main_receiver = self.main_receiver.clone(); + match main_receiver.try_pop() { + Ok(Some(runnable)) => { + self.dispatcher.wake_posted.store(true, Ordering::Release); + + WindowsDispatcher::execute_runnable(runnable); + } + _ => break 'tasks, + } + } + + Some(0) + } + + fn handle_dock_action_event(&self, action_idx: usize) -> Option { + let Some(action) = self + .state + .jump_list + .borrow() + .dock_menus + .get(action_idx) + .map(|dock_menu| dock_menu.action.boxed_clone()) + else { + log::error!("Dock menu for index {action_idx} not found"); + return Some(1); + }; + self.with_callback( + |callbacks| &callbacks.app_menu_action, + |callback| callback(&*action), + ); + Some(0) + } + + fn handle_keyboard_layout_change(&self) -> Option { + self.with_callback( + |callbacks| &callbacks.keyboard_layout_change, + |callback| callback(), + ); + Some(0) + } + + fn handle_power_broadcast(&self, wparam: WPARAM) -> Option { + match wparam.0 as u32 { + PBT_APMSUSPEND => { + self.with_callback(|callbacks| &callbacks.system_sleep, |callback| callback()); + } + PBT_APMRESUMEAUTOMATIC => { + self.with_callback(|callbacks| &callbacks.system_wake, |callback| callback()); + } + _ => {} + } + Some(1) + } + + fn handle_device_lost(&self, lparam: LPARAM) -> Option { + let directx_devices = lparam.0 as *const DirectXDevices; + let directx_devices = unsafe { &*directx_devices }; + let mut current = self.state.directx_devices.borrow_mut(); + // The platform may have switched to headless while the device was being recovered. + if current.is_some() { + *current = Some(directx_devices.clone()); + } + + Some(0) + } +} + +impl Drop for WindowsPlatform { + fn drop(&mut self) { + if let Some(stop) = self.vsync_stop.borrow_mut().take() { + stop.store(true, Ordering::Release); + } + unsafe { + if let Some(notification) = self.suspend_resume_notification.borrow_mut().take() { + // SAFETY: notification was returned by RegisterSuspendResumeNotification. + UnregisterSuspendResumeNotification(notification).log_err(); + } + DestroyWindow(self.handle) + .context("Destroying platform window") + .log_err(); + OleUninitialize(); + } + } +} + +pub(crate) struct WindowCreationInfo { + pub(crate) icon: HICON, + pub(crate) executor: ForegroundExecutor, + pub(crate) current_cursor: Option, + pub(crate) cursor_visible: Arc, + pub(crate) drop_target_helper: IDropTargetHelper, + pub(crate) validation_number: usize, + pub(crate) main_receiver: PriorityQueueReceiver, + pub(crate) platform_window_handle: HWND, + pub(crate) disable_direct_composition: bool, + pub(crate) directx_devices: DirectXDevices, + /// Flag to instruct the `VSyncProvider` thread to invalidate the directx devices + /// as resizing them has failed, causing us to have lost at least the render target. + pub(crate) invalidate_devices: Arc, + /// Shared with [`WindowsPlatformState::draw_coordinator`] and every other window. + pub(crate) draw_coordinator: Rc, +} + +struct PlatformWindowCreateContext { + inner: Option>>, + raw_window_handles: std::sync::Weak>>, + validation_number: usize, + main_sender: Option>, + main_receiver: Option>, + directx_devices: Option, + dispatcher: Option>, +} + +fn has_package_identity() -> bool { + let mut package_full_name_length = 0; + let result = unsafe { + windows::Win32::Storage::Packaging::Appx::GetCurrentPackageFullName( + &mut package_full_name_length, + None, + ) + }; + if result == ERROR_INSUFFICIENT_BUFFER { + true + } else if result == APPMODEL_ERROR_NO_PACKAGE { + false + } else { + log::warn!("failed to determine whether the process has package identity: {result:?}"); + false + } +} + +fn open_target(target: impl AsRef) -> Result<()> { + let target = target.as_ref(); + let ret = unsafe { + ShellExecuteW( + None, + windows::core::w!("open"), + &HSTRING::from(target), + None, + None, + SW_SHOWDEFAULT, + ) + }; + if ret.0 as isize <= 32 { + Err(anyhow::anyhow!( + "Unable to open target: {}", + std::io::Error::last_os_error() + )) + } else { + Ok(()) + } +} + +fn open_target_in_explorer(target: &Path) -> Result<()> { + let dir = target.parent().context("No parent folder found")?; + let desktop = unsafe { SHGetDesktopFolder()? }; + + let mut dir_item = std::ptr::null_mut(); + unsafe { + desktop.ParseDisplayName( + HWND::default(), + None, + &HSTRING::from(dir), + None, + &mut dir_item, + std::ptr::null_mut(), + )?; + } + + let mut file_item = std::ptr::null_mut(); + unsafe { + desktop.ParseDisplayName( + HWND::default(), + None, + &HSTRING::from(target), + None, + &mut file_item, + std::ptr::null_mut(), + )?; + } + + let highlight = [file_item as *const _]; + unsafe { SHOpenFolderAndSelectItems(dir_item as _, Some(&highlight), 0) }.or_else(|err| { + if err.code().0 == ERROR_FILE_NOT_FOUND.0 as i32 { + // On some systems, the above call mysteriously fails with "file not + // found" even though the file is there. In these cases, ShellExecute() + // seems to work as a fallback (although it won't select the file). + open_target(dir).context("Opening target parent folder") + } else { + Err(anyhow::anyhow!("Can not open target path: {}", err)) + } + }) +} + +fn file_open_dialog( + options: PathPromptOptions, + window: Option, +) -> Result>> { + let folder_dialog: IFileOpenDialog = + unsafe { CoCreateInstance(&FileOpenDialog, None, CLSCTX_ALL)? }; + + let mut dialog_options = FOS_FILEMUSTEXIST; + if options.multiple { + dialog_options |= FOS_ALLOWMULTISELECT; + } + if options.directories { + dialog_options |= FOS_PICKFOLDERS; + } + + unsafe { + folder_dialog.SetOptions(dialog_options)?; + + if let Some(prompt) = options.prompt { + let prompt: &str = &prompt; + folder_dialog.SetOkButtonLabel(&HSTRING::from(prompt))?; + } + + if let Err(error) = folder_dialog.Show(window) { + if error.code() == HRESULT::from_win32(ERROR_CANCELLED.0) { + return Ok(None); + } + return Err(error.into()); + } + } + + let results = unsafe { folder_dialog.GetResults()? }; + let file_count = unsafe { results.GetCount()? }; + if file_count == 0 { + return Ok(None); + } + + let mut paths = Vec::with_capacity(file_count as usize); + for i in 0..file_count { + let item = unsafe { results.GetItemAt(i)? }; + let path = unsafe { item.GetDisplayName(SIGDN_FILESYSPATH)?.to_string()? }; + paths.push(PathBuf::from(path)); + } + + Ok(Some(paths)) +} + +fn file_save_dialog( + directory: PathBuf, + suggested_name: Option, + window: Option, +) -> Result> { + let dialog: IFileSaveDialog = unsafe { CoCreateInstance(&FileSaveDialog, None, CLSCTX_ALL)? }; + if !directory.to_string_lossy().is_empty() + && let Some(full_path) = directory + .canonicalize() + .context("failed to canonicalize directory") + .log_err() + { + let full_path = dunce::simplified(&full_path); + let full_path_string = full_path.display().to_string(); + let path_item: IShellItem = + unsafe { SHCreateItemFromParsingName(&HSTRING::from(full_path_string), None)? }; + unsafe { + dialog + .SetFolder(&path_item) + .context("failed to set dialog folder") + .log_err() + }; + } + + if let Some(suggested_name) = suggested_name { + unsafe { + dialog + .SetFileName(&HSTRING::from(suggested_name)) + .context("failed to set file name") + .log_err() + }; + } + + unsafe { + dialog.SetFileTypes(&[Common::COMDLG_FILTERSPEC { + pszName: windows::core::w!("All files"), + pszSpec: windows::core::w!("*.*"), + }])?; + if let Err(error) = dialog.Show(window) { + if error.code() == HRESULT::from_win32(ERROR_CANCELLED.0) { + return Ok(None); + } + return Err(error.into()); + } + } + let shell_item = unsafe { dialog.GetResult()? }; + let file_path_string = unsafe { + let pwstr = shell_item.GetDisplayName(SIGDN_FILESYSPATH)?; + let string = pwstr.to_string()?; + CoTaskMemFree(Some(pwstr.0 as _)); + string + }; + Ok(Some(PathBuf::from(file_path_string))) +} + +fn load_icon() -> Result { + let module = unsafe { GetModuleHandleW(None).context("unable to get module handle")? }; + let handle = unsafe { + LoadImageW( + Some(module.into()), + windows::core::PCWSTR(1 as _), + IMAGE_ICON, + 0, + 0, + LR_DEFAULTSIZE | LR_SHARED, + ) + .context("unable to load icon file")? + }; + Ok(HICON(handle.0)) +} + +#[inline] +fn should_auto_hide_scrollbars() -> Result { + let ui_settings = UISettings::new()?; + Ok(ui_settings.AutoHideScrollBars()?) +} + +fn check_device_lost(device: &ID3D11Device) -> bool { + let device_state = unsafe { device.GetDeviceRemovedReason() }; + match device_state { + Ok(_) => false, + Err(err) => { + log::error!("DirectX device lost detected: {:?}", err); + true + } + } +} + +/// Checks that this process can show windows in the session `environment` names. +fn check_can_show_windows(environment: &GraphicalEnvironment) -> Result<()> { + let current = GraphicalEnvironment::detect().session_id; + if let (Some(requested), Some(current)) = (environment.session_id, current) + && requested != current + { + return Err(anyhow!( + "windows can only be shown in this process's session ({current}), not session \ + {requested}" + )); + } + if !is_window_station_visible() { + return Err(anyhow!( + "this process's window station is not interactive, so it can't show windows" + )); + } + Ok(()) +} + +/// Whether this process's window station has a visible desktop. A service's, or an SSH login's, +/// doesn't. +fn is_window_station_visible() -> bool { + use windows::Win32::System::StationsAndDesktops::{ + GetProcessWindowStation, GetUserObjectInformationW, UOI_FLAGS, USEROBJECTFLAGS, + }; + + let Ok(station) = (unsafe { GetProcessWindowStation() }) else { + return false; + }; + let mut flags = USEROBJECTFLAGS::default(); + // SAFETY: `flags` is valid for writes of the size passed. + let result = unsafe { + GetUserObjectInformationW( + HANDLE(station.0), + UOI_FLAGS, + Some(&mut flags as *mut USEROBJECTFLAGS as *mut std::ffi::c_void), + std::mem::size_of::() as u32, + None, + ) + }; + result.is_ok() && flags.dwFlags & WSF_VISIBLE as u32 != 0 +} + +fn handle_gpu_device_lost( + directx_devices: &mut DirectXDevices, + platform_window: HWND, + validation_number: usize, + all_windows: &std::sync::Weak>>, + text_system: &std::sync::Weak, +) -> Result<()> { + // Here we wait a bit to ensure the system has time to recover from the device lost state. + // If we don't wait, the final drawing result will be blank. + std::thread::sleep(std::time::Duration::from_millis(350)); + + *directx_devices = try_to_recover_from_device_lost(|| { + DirectXDevices::new().context("Failed to recreate new DirectX devices after device lost") + })?; + log::info!("DirectX devices successfully recreated."); + + let lparam = LPARAM(directx_devices as *const _ as _); + unsafe { + SendMessageW( + platform_window, + WM_GPUI_GPU_DEVICE_LOST, + Some(WPARAM(validation_number)), + Some(lparam), + ); + } + + if let Some(text_system) = text_system.upgrade() { + text_system.handle_gpu_lost(&directx_devices)?; + } + if let Some(all_windows) = all_windows.upgrade() { + for window in all_windows.read().iter() { + unsafe { + SendMessageW( + window.as_raw(), + WM_GPUI_GPU_DEVICE_LOST, + Some(WPARAM(validation_number)), + Some(lparam), + ); + } + } + std::thread::sleep(std::time::Duration::from_millis(200)); + for window in all_windows.read().iter() { + unsafe { + SendMessageW( + window.as_raw(), + WM_GPUI_FORCE_UPDATE_WINDOW, + Some(WPARAM(validation_number)), + None, + ); + } + } + } + Ok(()) +} + +const PLATFORM_WINDOW_CLASS_NAME: PCWSTR = w!("Zed::PlatformWindow"); + +fn register_platform_window_class() { + let wc = WNDCLASSW { + lpfnWndProc: Some(window_procedure), + lpszClassName: PCWSTR(PLATFORM_WINDOW_CLASS_NAME.as_ptr()), + ..Default::default() + }; + unsafe { RegisterClassW(&wc) }; +} + +unsafe extern "system" fn window_procedure( + hwnd: HWND, + msg: u32, + wparam: WPARAM, + lparam: LPARAM, +) -> LRESULT { + if msg == WM_NCCREATE { + let params = unsafe { &*(lparam.0 as *const CREATESTRUCTW) }; + let creation_context = params.lpCreateParams as *mut PlatformWindowCreateContext; + let creation_context = unsafe { &mut *creation_context }; + + let Some(main_sender) = creation_context.main_sender.take() else { + creation_context.inner = Some(Err(anyhow!("missing main sender"))); + return LRESULT(0); + }; + creation_context.dispatcher = Some(Arc::new(WindowsDispatcher::new( + main_sender, + hwnd, + creation_context.validation_number, + ))); + + return match WindowsPlatformInner::new(creation_context) { + Ok(inner) => { + let weak = Box::new(Rc::downgrade(&inner)); + unsafe { set_window_long(hwnd, GWLP_USERDATA, Box::into_raw(weak) as isize) }; + creation_context.inner = Some(Ok(inner)); + unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) } + } + Err(error) => { + creation_context.inner = Some(Err(error)); + LRESULT(0) + } + }; + } + + let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak; + if ptr.is_null() { + return unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) }; + } + let inner = unsafe { &*ptr }; + let result = if let Some(inner) = inner.upgrade() { + if cfg!(debug_assertions) { + let inner = std::panic::AssertUnwindSafe(inner); + match std::panic::catch_unwind(|| { inner }.handle_msg(hwnd, msg, wparam, lparam)) { + Ok(result) => result, + Err(_) => std::process::abort(), + } + } else { + inner.handle_msg(hwnd, msg, wparam, lparam) + } + } else { + unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) } + }; + + if msg == WM_NCDESTROY { + unsafe { set_window_long(hwnd, GWLP_USERDATA, 0) }; + unsafe { drop(Box::from_raw(ptr)) }; + } + + result +} + +/// Copies the username and secret out of a credential returned by `CredReadW`. +/// +/// Both `UserName` and `CredentialBlob` are optional in Credential Manager and +/// come back as null pointers when absent, so they are treated as empty here. +/// +/// # Safety +/// +/// A non-null `UserName` must point to a NUL-terminated wide string and a +/// non-null `CredentialBlob` must be readable for `CredentialBlobSize` bytes, +/// as is the case for credentials returned by `CredReadW`. +unsafe fn username_and_password(credential: &CREDENTIALW) -> Result<(String, Vec)> { + let username = if credential.UserName.is_null() { + String::new() + } else { + // SAFETY: guaranteed by the caller. + unsafe { credential.UserName.to_string()? } + }; + let password = if credential.CredentialBlob.is_null() { + Vec::new() + } else { + // SAFETY: guaranteed by the caller. + unsafe { + std::slice::from_raw_parts( + credential.CredentialBlob, + credential.CredentialBlobSize as usize, + ) + } + .to_vec() + }; + Ok((username, password)) +} + +#[cfg(test)] +mod tests { + use std::ffi::{OsStr, OsString}; + + use crate::{read_from_clipboard, write_to_clipboard}; + use gpui::ClipboardItem; + use windows::Win32::Security::Credentials::{ + CRED_PERSIST_SESSION, CRED_TYPE_GENERIC, CREDENTIALW, CredDeleteW, CredFree, CredReadW, + CredWriteW, + }; + use windows::core::{PCWSTR, PWSTR}; + + use super::{encode_restart_arguments, username_and_password}; + + #[test] + fn test_read_credential_with_username() { + assert_eq!( + round_trip_credential(Some("alice"), b"secret"), + ("alice".to_string(), b"secret".to_vec()) + ); + } + + #[test] + fn test_read_credential_without_username() { + assert_eq!( + round_trip_credential(None, b"secret"), + (String::new(), b"secret".to_vec()) + ); + } + + fn round_trip_credential(username: Option<&str>, secret: &[u8]) -> (String, Vec) { + let mut target_name: Vec = format!( + "zed-test-{}-{}", + std::process::id(), + username.unwrap_or_default() + ) + .encode_utf16() + .chain(Some(0)) + .collect(); + let mut username: Vec = username + .map(|username| username.encode_utf16().chain(Some(0)).collect()) + .unwrap_or_default(); + let mut secret = secret.to_vec(); + let credential = CREDENTIALW { + Type: CRED_TYPE_GENERIC, + TargetName: PWSTR::from_raw(target_name.as_mut_ptr()), + CredentialBlobSize: secret.len() as u32, + CredentialBlob: secret.as_mut_ptr(), + Persist: CRED_PERSIST_SESSION, + UserName: if username.is_empty() { + PWSTR::null() + } else { + PWSTR::from_raw(username.as_mut_ptr()) + }, + ..CREDENTIALW::default() + }; + let target_name = PCWSTR::from_raw(target_name.as_ptr()); + unsafe { CredWriteW(&credential, 0) }.unwrap(); + + let mut credentials: *mut CREDENTIALW = std::ptr::null_mut(); + unsafe { CredReadW(target_name, CRED_TYPE_GENERIC, None, &mut credentials) }.unwrap(); + let result = unsafe { username_and_password(&*credentials) }; + unsafe { CredFree(credentials as *const _ as _) }; + unsafe { CredDeleteW(target_name, CRED_TYPE_GENERIC, None) }.unwrap(); + result.unwrap() + } + + #[test] + fn test_encode_restart_arguments() { + assert_eq!(encode_restart_arguments(&[]), OsStr::new("")); + assert_eq!( + encode_restart_arguments(&[ + OsString::from("--user-data-dir"), + OsString::from(r"C:\Zed Data"), + ]), + OsStr::new(r#""--user-data-dir" "C:\Zed Data""#) + ); + assert_eq!( + encode_restart_arguments(&[OsString::from(r"C:\")]), + OsStr::new(r#""C:\\""#) + ); + } + + #[test] + fn test_clipboard() { + let item = ClipboardItem::new_string("你好,我是张小白".to_string()); + write_to_clipboard(item.clone()); + assert_eq!(read_from_clipboard(), Some(item)); + + let item = ClipboardItem::new_string("12345".to_string()); + write_to_clipboard(item.clone()); + assert_eq!(read_from_clipboard(), Some(item)); + + let item = ClipboardItem::new_string_with_json_metadata("abcdef".to_string(), vec![3, 4]); + write_to_clipboard(item.clone()); + assert_eq!(read_from_clipboard(), Some(item)); + + let item = + ClipboardItem::new_string_with_json_metadata("before\0after".to_string(), vec![12]); + write_to_clipboard(item); + assert_eq!( + read_from_clipboard(), + Some(ClipboardItem::new_string_with_json_metadata( + "before after".to_string(), + vec![12], + )), + ); + } +} diff --git a/vendor/gpui-pre-windows/src/shaders.hlsl b/vendor/gpui-pre-windows/src/shaders.hlsl new file mode 100644 index 00000000..ba89c687 --- /dev/null +++ b/vendor/gpui-pre-windows/src/shaders.hlsl @@ -0,0 +1,1268 @@ +#include "alpha_correction.hlsl" + +cbuffer GlobalParams: register(b0) { + float4 gamma_ratios; + float2 global_viewport_size; + float grayscale_enhanced_contrast; + float subpixel_enhanced_contrast; + uint is_bgr; + uint3 global_pad; +}; + +cbuffer BatchParams: register(b1) { + uint batch_start_index; + uint3 batch_pad; +}; + +Texture2D t_sprite: register(t0); +SamplerState s_sprite: register(s0); + +struct SubpixelSpriteFragmentOutput { + float4 foreground : SV_Target0; + float4 alpha : SV_Target1; +}; + +struct Bounds { + float2 origin; + float2 size; +}; + +struct Corners { + float top_left; + float top_right; + float bottom_right; + float bottom_left; +}; + +struct Edges { + float top; + float right; + float bottom; + float left; +}; + +struct Hsla { + float h; + float s; + float l; + float a; +}; + +struct LinearColorStop { + Hsla color; + float percentage; +}; + +struct Background { + // 0u is Solid + // 1u is LinearGradient + // 2u is PatternSlash + uint tag; + // 0u is sRGB linear color + // 1u is Oklab color + uint color_space; + Hsla solid; + float gradient_angle_or_pattern_height; + LinearColorStop colors[2]; + uint pad; +}; + +struct GradientColor { + float4 solid; + float4 color0; + float4 color1; +}; + +struct AtlasTextureId { + uint index; + uint kind; +}; + +struct AtlasBounds { + int2 origin; + int2 size; +}; + +struct AtlasTile { + AtlasTextureId texture_id; + uint tile_id; + uint padding; + AtlasBounds bounds; +}; + +struct TransformationMatrix { + float2x2 rotation_scale; + float2 translation; +}; + +static const float M_PI_F = 3.141592653f; +static const float3 GRAYSCALE_FACTORS = float3(0.2126f, 0.7152f, 0.0722f); + +float4 to_device_position_impl(float2 position) { + float2 device_position = position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0); + return float4(device_position, 0., 1.); +} + +float4 to_device_position(float2 unit_vertex, Bounds bounds) { + float2 position = unit_vertex * bounds.size + bounds.origin; + return to_device_position_impl(position); +} + +float4 distance_from_clip_rect_impl(float2 position, Bounds clip_bounds) { + float2 tl = position - clip_bounds.origin; + float2 br = clip_bounds.origin + clip_bounds.size - position; + return float4(tl.x, br.x, tl.y, br.y); +} + +float4 distance_from_clip_rect(float2 unit_vertex, Bounds bounds, Bounds clip_bounds) { + float2 position = unit_vertex * bounds.size + bounds.origin; + return distance_from_clip_rect_impl(position, clip_bounds); +} + +float4 distance_from_clip_rect_transformed(float2 unit_vertex, Bounds bounds, Bounds clip_bounds, TransformationMatrix transformation) { + float2 position = unit_vertex * bounds.size + bounds.origin; + float2 transformed = mul(position, transformation.rotation_scale) + transformation.translation; + return distance_from_clip_rect_impl(transformed, clip_bounds); +} + +// Convert linear RGB to sRGB +float3 linear_to_srgb(float3 color) { + return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); +} + +// Convert sRGB to linear RGB +float3 srgb_to_linear(float3 color) { + return pow(color, float3(2.2, 2.2, 2.2)); +} + +/// Hsla to linear RGBA conversion. +float4 hsla_to_rgba(Hsla hsla) { + float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range + float s = hsla.s; + float l = hsla.l; + float a = hsla.a; + + float c = (1.0 - abs(2.0 * l - 1.0)) * s; + float x = c * (1.0 - abs(fmod(h, 2.0) - 1.0)); + float m = l - c / 2.0; + + float r = 0.0; + float g = 0.0; + float b = 0.0; + + if (h >= 0.0 && h < 1.0) { + r = c; + g = x; + b = 0.0; + } else if (h >= 1.0 && h < 2.0) { + r = x; + g = c; + b = 0.0; + } else if (h >= 2.0 && h < 3.0) { + r = 0.0; + g = c; + b = x; + } else if (h >= 3.0 && h < 4.0) { + r = 0.0; + g = x; + b = c; + } else if (h >= 4.0 && h < 5.0) { + r = x; + g = 0.0; + b = c; + } else { + r = c; + g = 0.0; + b = x; + } + + float4 rgba; + rgba.x = (r + m); + rgba.y = (g + m); + rgba.z = (b + m); + rgba.w = a; + return rgba; +} + +// Converts a sRGB color to the Oklab color space. +// Reference: https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab +float4 srgb_to_oklab(float4 color) { + // Convert non-linear sRGB to linear sRGB + color = float4(srgb_to_linear(color.rgb), color.a); + + float l = 0.4122214708 * color.r + 0.5363325363 * color.g + 0.0514459929 * color.b; + float m = 0.2119034982 * color.r + 0.6806995451 * color.g + 0.1073969566 * color.b; + float s = 0.0883024619 * color.r + 0.2817188376 * color.g + 0.6299787005 * color.b; + + float l_ = pow(l, 1.0/3.0); + float m_ = pow(m, 1.0/3.0); + float s_ = pow(s, 1.0/3.0); + + return float4( + 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_, + 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_, + 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_, + color.a + ); +} + +// Converts an Oklab color to the sRGB color space. +float4 oklab_to_srgb(float4 color) { + float l_ = color.r + 0.3963377774 * color.g + 0.2158037573 * color.b; + float m_ = color.r - 0.1055613458 * color.g - 0.0638541728 * color.b; + float s_ = color.r - 0.0894841775 * color.g - 1.2914855480 * color.b; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + float3 linear_rgb = float3( + 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s, + -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s, + -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s + ); + + // Convert linear sRGB to non-linear sRGB + return float4(linear_to_srgb(linear_rgb), color.a); +} + +// This approximates the error function, needed for the gaussian integral +float2 erf(float2 x) { + float2 s = sign(x); + float2 a = abs(x); + x = 1. + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a; + x *= x; + return s - s / (x * x); +} + +float blur_along_x(float x, float y, float sigma, float corner, float2 half_size) { + float delta = min(half_size.y - corner - abs(y), 0.); + float curved = half_size.x - corner + sqrt(max(0., corner * corner - delta * delta)); + float2 integral = 0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma)); + return integral.y - integral.x; +} + +// A standard gaussian function, used for weighting samples +float gaussian(float x, float sigma) { + return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * M_PI_F) * sigma); +} + +float4 over(float4 below, float4 above) { + float4 result; + float alpha = above.a + below.a * (1.0 - above.a); + result.rgb = (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha; + result.a = alpha; + return result; +} + +float2 to_tile_position(float2 unit_vertex, AtlasTile tile) { + float2 atlas_size; + t_sprite.GetDimensions(atlas_size.x, atlas_size.y); + return (float2(tile.bounds.origin) + unit_vertex * float2(tile.bounds.size)) / atlas_size; +} + +// Selects corner radius based on quadrant. +float pick_corner_radius(float2 center_to_point, Corners corner_radii) { + if (center_to_point.x < 0.) { + if (center_to_point.y < 0.) { + return corner_radii.top_left; + } else { + return corner_radii.bottom_left; + } + } else { + if (center_to_point.y < 0.) { + return corner_radii.top_right; + } else { + return corner_radii.bottom_right; + } + } +} + +float4 to_device_position_transformed(float2 unit_vertex, Bounds bounds, + TransformationMatrix transformation) { + float2 position = unit_vertex * bounds.size + bounds.origin; + float2 transformed = mul(position, transformation.rotation_scale) + transformation.translation; + float2 device_position = transformed / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0); + return float4(device_position, 0.0, 1.0); +} + +// Implementation of quad signed distance field +float quad_sdf_impl(float2 corner_center_to_point, float corner_radius) { + if (corner_radius == 0.0) { + // Fast path for unrounded corners + return max(corner_center_to_point.x, corner_center_to_point.y); + } else { + // Signed distance of the point from a quad that is inset by corner_radius + // It is negative inside this quad, and positive outside + float signed_distance_to_inset_quad = + // 0 inside the inset quad, and positive outside + length(max(float2(0.0, 0.0), corner_center_to_point)) + + // 0 outside the inset quad, and negative inside + min(0.0, max(corner_center_to_point.x, corner_center_to_point.y)); + + return signed_distance_to_inset_quad - corner_radius; + } +} + +float quad_sdf(float2 pt, Bounds bounds, Corners corner_radii) { + float2 half_size = bounds.size / 2.; + float2 center = bounds.origin + half_size; + float2 center_to_point = pt - center; + float corner_radius = pick_corner_radius(center_to_point, corner_radii); + float2 corner_to_point = abs(center_to_point) - half_size; + float2 corner_center_to_point = corner_to_point + corner_radius; + return quad_sdf_impl(corner_center_to_point, corner_radius); +} + +GradientColor prepare_gradient_color(uint tag, uint color_space, Hsla solid, LinearColorStop colors[2]) { + GradientColor output; + if (tag == 0 || tag == 2 || tag == 3) { + output.solid = hsla_to_rgba(solid); + } else if (tag == 1) { + output.color0 = hsla_to_rgba(colors[0].color); + output.color1 = hsla_to_rgba(colors[1].color); + + // Prepare color space in vertex for avoid conversion + // in fragment shader for performance reasons + if (color_space == 1) { + // Oklab + output.color0 = srgb_to_oklab(output.color0); + output.color1 = srgb_to_oklab(output.color1); + } + } + + return output; +} + +float2x2 rotate2d(float angle) { + float s = sin(angle); + float c = cos(angle); + return float2x2(c, -s, s, c); +} + +float4 gradient_color(Background background, + float2 position, + Bounds bounds, + float4 solid_color, float4 color0, float4 color1) { + float4 color; + + switch (background.tag) { + case 0: + color = solid_color; + break; + case 1: { + // -90 degrees to match the CSS gradient angle. + float gradient_angle = background.gradient_angle_or_pattern_height; + float radians = (fmod(gradient_angle, 360.0) - 90.0) * (M_PI_F / 180.0); + float2 direction = float2(cos(radians), sin(radians)); + + // Expand the short side to be the same as the long side + if (bounds.size.x > bounds.size.y) { + direction.y *= bounds.size.y / bounds.size.x; + } else { + direction.x *= bounds.size.x / bounds.size.y; + } + + // Get the t value for the linear gradient with the color stop percentages. + float2 half_size = bounds.size * 0.5; + float2 center = bounds.origin + half_size; + float2 center_to_point = position - center; + float t = dot(center_to_point, direction) / length(direction); + // Check the direct to determine the use x or y + if (abs(direction.x) > abs(direction.y)) { + t = (t + half_size.x) / bounds.size.x; + } else { + t = (t + half_size.y) / bounds.size.y; + } + + // Adjust t based on the stop percentages + t = (t - background.colors[0].percentage) + / (background.colors[1].percentage + - background.colors[0].percentage); + t = clamp(t, 0.0, 1.0); + + switch (background.color_space) { + case 0: + color = lerp(color0, color1, t); + break; + case 1: { + float4 oklab_color = lerp(color0, color1, t); + color = oklab_to_srgb(oklab_color); + break; + } + } + + // Dither to reduce banding in gradients (especially dark/alpha). + // Triangular-distributed noise breaks up 8-bit quantization steps. + // ±2/255 for RGB (enough for dark-on-dark compositing), + // ±3/255 for alpha (needs more because alpha × dark color = tiny steps). + { + float2 seed = position * 0.6180339887; // golden ratio spread + float r1 = frac(sin(dot(seed, float2(12.9898, 78.233))) * 43758.5453); + float r2 = frac(sin(dot(seed, float2(39.3460, 11.135))) * 24634.6345); + float tri = r1 + r2 - 1.0; // triangular PDF, range [-1, +1] + color.rgb += tri * 2.0 / 255.0; + color.a += tri * 3.0 / 255.0; + } + + break; + } + case 2: { + float gradient_angle_or_pattern_height = background.gradient_angle_or_pattern_height; + float pattern_width = (gradient_angle_or_pattern_height / 65535.0f) / 255.0f; + float pattern_interval = fmod(gradient_angle_or_pattern_height, 65535.0f) / 255.0f; + float pattern_height = pattern_width + pattern_interval; + float stripe_angle = M_PI_F / 4.0; + float pattern_period = pattern_height * sin(stripe_angle); + float2x2 rotation = rotate2d(stripe_angle); + float2 relative_position = position - bounds.origin; + float2 rotated_point = mul(relative_position, rotation); + float pattern = fmod(rotated_point.x, pattern_period); + float distance = min(pattern, pattern_period - pattern) - pattern_period * (pattern_width / pattern_height) / 2.0f; + color = solid_color; + color.a *= saturate(0.5 - distance); + break; + } + case 3: { + // checkerboard + float size = background.gradient_angle_or_pattern_height; + float2 relative_position = position - bounds.origin; + + float x_index = floor(relative_position.x / size); + float y_index = floor(relative_position.y / size); + float should_be_colored = (x_index + y_index) % 2.0; + + color = solid_color; + color.a *= saturate(should_be_colored); + break; + } + } + + return color; +} + +// Returns the dash velocity of a corner given the dash velocity of the two +// sides, by returning the slower velocity (larger dashes). +// +// Since 0 is used for dash velocity when the border width is 0 (instead of +// +inf), this returns the other dash velocity in that case. +// +// An alternative to this might be to appropriately interpolate the dash +// velocity around the corner, but that seems overcomplicated. +float corner_dash_velocity(float dv1, float dv2) { + if (dv1 == 0.0) { + return dv2; + } else if (dv2 == 0.0) { + return dv1; + } else { + return min(dv1, dv2); + } +} + +// Returns alpha used to render antialiased dashes. +// `t` is within the dash when `fmod(t, period) < length`. +float dash_alpha( + float t, float period, float length, float dash_velocity, + float antialias_threshold +) { + float half_period = period / 2.0; + float half_length = length / 2.0; + // Value in [-half_period, half_period] + // The dash is in [-half_length, half_length] + float centered = fmod(t + half_period - half_length, period) - half_period; + // Signed distance for the dash, negative values are inside the dash + float signed_distance = abs(centered) - half_length; + // Antialiased alpha based on the signed distance + return saturate(antialias_threshold - signed_distance / dash_velocity); +} + +// This approximates distance to the nearest point to a quarter ellipse in a way +// that is sufficient for anti-aliasing when the ellipse is not very eccentric. +// The components of `point` are expected to be positive. +// +// Negative on the outside and positive on the inside. +float quarter_ellipse_sdf(float2 pt, float2 radii) { + // Scale the space to treat the ellipse like a unit circle + float2 circle_vec = pt / radii; + float unit_circle_sdf = length(circle_vec) - 1.0; + // Approximate up-scaling of the length by using the average of the radii. + // + // TODO: A better solution would be to use the gradient of the implicit + // function for an ellipse to approximate a scaling factor. + return unit_circle_sdf * (radii.x + radii.y) * -0.5; +} + +/* +** +** Quads +** +*/ + +struct Quad { + uint order; + uint border_style; + Bounds bounds; + Bounds content_mask; + Background background; + Hsla border_color; + Corners corner_radii; + Edges border_widths; +}; + +struct QuadVertexOutput { + nointerpolation uint quad_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 border_color: COLOR0; + nointerpolation float4 background_solid: COLOR1; + nointerpolation float4 background_color0: COLOR2; + nointerpolation float4 background_color1: COLOR3; + float4 clip_distance: SV_ClipDistance; +}; + +struct QuadFragmentInput { + nointerpolation uint quad_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 border_color: COLOR0; + nointerpolation float4 background_solid: COLOR1; + nointerpolation float4 background_color0: COLOR2; + nointerpolation float4 background_color1: COLOR3; +}; + +StructuredBuffer quads: register(t1); + +QuadVertexOutput quad_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + uint quad_id = batch_start_index + instance_id; + Quad quad = quads[quad_id]; + float4 device_position = to_device_position(unit_vertex, quad.bounds); + + GradientColor gradient = prepare_gradient_color( + quad.background.tag, + quad.background.color_space, + quad.background.solid, + quad.background.colors + ); + float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds, quad.content_mask); + float4 border_color = hsla_to_rgba(quad.border_color); + + QuadVertexOutput output; + output.position = device_position; + output.border_color = border_color; + output.quad_id = quad_id; + output.background_solid = gradient.solid; + output.background_color0 = gradient.color0; + output.background_color1 = gradient.color1; + output.clip_distance = clip_distance; + return output; +} + +float4 quad_fragment(QuadFragmentInput input): SV_Target { + Quad quad = quads[input.quad_id]; + float4 background_color = gradient_color(quad.background, input.position.xy, quad.bounds, + input.background_solid, input.background_color0, input.background_color1); + + bool unrounded = quad.corner_radii.top_left == 0.0 && + quad.corner_radii.top_right == 0.0 && + quad.corner_radii.bottom_left == 0.0 && + quad.corner_radii.bottom_right == 0.0; + + // Fast path when the quad is not rounded and doesn't have any border + if (quad.border_widths.top == 0.0 && + quad.border_widths.left == 0.0 && + quad.border_widths.right == 0.0 && + quad.border_widths.bottom == 0.0 && + unrounded) { + return background_color; + } + + float2 size = quad.bounds.size; + float2 half_size = size / 2.; + float2 the_point = input.position.xy - quad.bounds.origin; + float2 center_to_point = the_point - half_size; + + // Signed distance field threshold for inclusion of pixels. 0.5 is the + // minimum distance between the center of the pixel and the edge. + const float antialias_threshold = 0.5; + + // Radius of the nearest corner + float corner_radius = pick_corner_radius(center_to_point, quad.corner_radii); + + float2 border = float2( + center_to_point.x < 0.0 ? quad.border_widths.left : quad.border_widths.right, + center_to_point.y < 0.0 ? quad.border_widths.top : quad.border_widths.bottom + ); + + // 0-width borders are reduced so that `inner_sdf >= antialias_threshold`. + // The purpose of this is to not draw antialiasing pixels in this case. + float2 reduced_border = float2( + border.x == 0.0 ? -antialias_threshold : border.x, + border.y == 0.0 ? -antialias_threshold : border.y + ); + + // Vector from the corner of the quad bounds to the point, after mirroring + // the point into the bottom right quadrant. Both components are <= 0. + float2 corner_to_point = abs(center_to_point) - half_size; + + // Vector from the point to the center of the rounded corner's circle, also + // mirrored into bottom right quadrant. + float2 corner_center_to_point = corner_to_point + corner_radius; + + // Whether the nearest point on the border is rounded + bool is_near_rounded_corner = + corner_center_to_point.x >= 0.0 && + corner_center_to_point.y >= 0.0; + + // Vector from straight border inner corner to point. + // + // 0-width borders are turned into width -1 so that inner_sdf is > 1.0 near + // the border. Without this, antialiasing pixels would be drawn. + float2 straight_border_inner_corner_to_point = corner_to_point + reduced_border; + + // Whether the point is beyond the inner edge of the straight border + bool is_beyond_inner_straight_border = + straight_border_inner_corner_to_point.x > 0.0 || + straight_border_inner_corner_to_point.y > 0.0; + + // Whether the point is far enough inside the quad, such that the pixels are + // not affected by the straight border. + bool is_within_inner_straight_border = + straight_border_inner_corner_to_point.x < -antialias_threshold && + straight_border_inner_corner_to_point.y < -antialias_threshold; + + // Fast path for points that must be part of the background + if (is_within_inner_straight_border && !is_near_rounded_corner) { + return background_color; + } + + // Signed distance of the point to the outside edge of the quad's border + float outer_sdf = quad_sdf_impl(corner_center_to_point, corner_radius); + + // Approximate signed distance of the point to the inside edge of the quad's + // border. It is negative outside this edge (within the border), and + // positive inside. + // + // This is not always an accurate signed distance: + // * The rounded portions with varying border width use an approximation of + // nearest-point-on-ellipse. + // * When it is quickly known to be outside the edge, -1.0 is used. + float inner_sdf = 0.0; + if (corner_center_to_point.x <= 0.0 || corner_center_to_point.y <= 0.0) { + // Fast paths for straight borders + inner_sdf = -max(straight_border_inner_corner_to_point.x, + straight_border_inner_corner_to_point.y); + } else if (is_beyond_inner_straight_border) { + // Fast path for points that must be outside the inner edge + inner_sdf = -1.0; + } else if (reduced_border.x == reduced_border.y) { + // Fast path for circular inner edge. + inner_sdf = -(outer_sdf + reduced_border.x); + } else { + float2 ellipse_radii = max(float2(0.0, 0.0), float2(corner_radius, corner_radius) - reduced_border); + inner_sdf = quarter_ellipse_sdf(corner_center_to_point, ellipse_radii); + } + + // Negative when inside the border + float border_sdf = max(inner_sdf, outer_sdf); + + float4 color = background_color; + if (border_sdf < antialias_threshold) { + float4 border_color = input.border_color; + // Dashed border logic when border_style == 1 + if (quad.border_style == 1) { + // Position along the perimeter in "dash space", where each dash + // period has length 1 + float t = 0.0; + + // Total number of dash periods, so that the dash spacing can be + // adjusted to evenly divide it + float max_t = 0.0; + + // Border width is proportional to dash size. This is the behavior + // used by browsers, but also avoids dashes from different segments + // overlapping when dash size is smaller than the border width. + // + // Dash pattern: (2 * border width) dash, (1 * border width) gap + const float dash_length_per_width = 2.0; + const float dash_gap_per_width = 1.0; + const float dash_period_per_width = dash_length_per_width + dash_gap_per_width; + + // Since the dash size is determined by border width, the density of + // dashes varies. Multiplying a pixel distance by this returns a + // position in dash space - it has units (dash period / pixels). So + // a dash velocity of (1 / 10) is 1 dash every 10 pixels. + float dash_velocity = 0.0; + + // Dividing this by the border width gives the dash velocity + const float dv_numerator = 1.0 / dash_period_per_width; + + if (unrounded) { + // When corners aren't rounded, the dashes are separately laid + // out on each straight line, rather than around the whole + // perimeter. This way each line starts and ends with a dash. + bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y; + // Choosing the right border width for dashed borders. + // TODO: A better solution exists taking a look at the whole file. + // this does not fix single dashed borders at the corners + float2 dashed_border = float2( + max(quad.border_widths.bottom, quad.border_widths.top), + max(quad.border_widths.right, quad.border_widths.left) + ); + float border_width = is_horizontal ? dashed_border.x : dashed_border.y; + dash_velocity = dv_numerator / border_width; + t = is_horizontal ? the_point.x : the_point.y; + t *= dash_velocity; + max_t = is_horizontal ? size.x : size.y; + max_t *= dash_velocity; + } else { + // When corners are rounded, the dashes are laid out clockwise + // around the whole perimeter. + + float r_tr = quad.corner_radii.top_right; + float r_br = quad.corner_radii.bottom_right; + float r_bl = quad.corner_radii.bottom_left; + float r_tl = quad.corner_radii.top_left; + + float w_t = quad.border_widths.top; + float w_r = quad.border_widths.right; + float w_b = quad.border_widths.bottom; + float w_l = quad.border_widths.left; + + // Straight side dash velocities + float dv_t = w_t <= 0.0 ? 0.0 : dv_numerator / w_t; + float dv_r = w_r <= 0.0 ? 0.0 : dv_numerator / w_r; + float dv_b = w_b <= 0.0 ? 0.0 : dv_numerator / w_b; + float dv_l = w_l <= 0.0 ? 0.0 : dv_numerator / w_l; + + // Straight side lengths in dash space + float s_t = (size.x - r_tl - r_tr) * dv_t; + float s_r = (size.y - r_tr - r_br) * dv_r; + float s_b = (size.x - r_br - r_bl) * dv_b; + float s_l = (size.y - r_bl - r_tl) * dv_l; + + float corner_dash_velocity_tr = corner_dash_velocity(dv_t, dv_r); + float corner_dash_velocity_br = corner_dash_velocity(dv_b, dv_r); + float corner_dash_velocity_bl = corner_dash_velocity(dv_b, dv_l); + float corner_dash_velocity_tl = corner_dash_velocity(dv_t, dv_l); + + // Corner lengths in dash space + float c_tr = r_tr * (M_PI_F / 2.0) * corner_dash_velocity_tr; + float c_br = r_br * (M_PI_F / 2.0) * corner_dash_velocity_br; + float c_bl = r_bl * (M_PI_F / 2.0) * corner_dash_velocity_bl; + float c_tl = r_tl * (M_PI_F / 2.0) * corner_dash_velocity_tl; + + // Cumulative dash space upto each segment + float upto_tr = s_t; + float upto_r = upto_tr + c_tr; + float upto_br = upto_r + s_r; + float upto_b = upto_br + c_br; + float upto_bl = upto_b + s_b; + float upto_l = upto_bl + c_bl; + float upto_tl = upto_l + s_l; + max_t = upto_tl + c_tl; + + if (is_near_rounded_corner) { + float radians = atan2(corner_center_to_point.y, corner_center_to_point.x); + float corner_t = radians * corner_radius; + + if (center_to_point.x >= 0.0) { + if (center_to_point.y < 0.0) { + dash_velocity = corner_dash_velocity_tr; + // Subtracted because radians is pi/2 to 0 when + // going clockwise around the top right corner, + // since the y axis has been flipped + t = upto_r - corner_t * dash_velocity; + } else { + dash_velocity = corner_dash_velocity_br; + // Added because radians is 0 to pi/2 when going + // clockwise around the bottom-right corner + t = upto_br + corner_t * dash_velocity; + } + } else { + if (center_to_point.y >= 0.0) { + dash_velocity = corner_dash_velocity_bl; + // Subtracted because radians is pi/1 to 0 when + // going clockwise around the bottom-left corner, + // since the x axis has been flipped + t = upto_l - corner_t * dash_velocity; + } else { + dash_velocity = corner_dash_velocity_tl; + // Added because radians is 0 to pi/2 when going + // clockwise around the top-left corner, since both + // axis were flipped + t = upto_tl + corner_t * dash_velocity; + } + } + } else { + // Straight borders + bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y; + if (is_horizontal) { + if (center_to_point.y < 0.0) { + dash_velocity = dv_t; + t = (the_point.x - r_tl) * dash_velocity; + } else { + dash_velocity = dv_b; + t = upto_bl - (the_point.x - r_bl) * dash_velocity; + } + } else { + if (center_to_point.x < 0.0) { + dash_velocity = dv_l; + t = upto_tl - (the_point.y - r_tl) * dash_velocity; + } else { + dash_velocity = dv_r; + t = upto_r + (the_point.y - r_tr) * dash_velocity; + } + } + } + } + float dash_length = dash_length_per_width / dash_period_per_width; + float desired_dash_gap = dash_gap_per_width / dash_period_per_width; + + // Straight borders should start and end with a dash, so max_t is + // reduced to cause this. + max_t -= unrounded ? dash_length : 0.0; + if (max_t >= 1.0) { + // Adjust dash gap to evenly divide max_t + float dash_count = floor(max_t); + float dash_period = max_t / dash_count; + border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity, antialias_threshold); + } else if (unrounded) { + // When there isn't enough space for the full gap between the + // two start / end dashes of a straight border, reduce gap to + // make them fit. + float dash_gap = max_t - dash_length; + if (dash_gap > 0.0) { + float dash_period = dash_length + dash_gap; + border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity, antialias_threshold); + } + } + } + + // Blend the border on top of the background and then linearly interpolate + // between the two as we slide inside the background. + float4 blended_border = over(background_color, border_color); + color = lerp(background_color, blended_border, + saturate(antialias_threshold - inner_sdf)); + } + + return color * float4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf)); +} + +/* +** +** Shadows +** +*/ + +struct Shadow { + uint order; + float blur_radius; + Bounds bounds; + Corners corner_radii; + Bounds content_mask; + Hsla color; + Bounds element_bounds; + Corners element_corner_radii; + uint inset; + uint pad; // align to 8 bytes +}; + +struct ShadowVertexOutput { + nointerpolation uint shadow_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 color: COLOR; + float4 clip_distance: SV_ClipDistance; +}; + +struct ShadowFragmentInput { + nointerpolation uint shadow_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 color: COLOR; +}; + +StructuredBuffer shadows: register(t1); + +ShadowVertexOutput shadow_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + uint shadow_id = batch_start_index + instance_id; + Shadow shadow = shadows[shadow_id]; + + Bounds bounds; + if (shadow.inset != 0u) { + bounds = shadow.element_bounds; + } else { + // Leave room for the gaussian tail outside the shadow rect. + float margin = 3.0 * shadow.blur_radius; + bounds = shadow.bounds; + bounds.origin -= margin; + bounds.size += 2.0 * margin; + } + + float4 device_position = to_device_position(unit_vertex, bounds); + float4 clip_distance = distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask); + float4 color = hsla_to_rgba(shadow.color); + + ShadowVertexOutput output; + output.position = device_position; + output.color = color; + output.shadow_id = shadow_id; + output.clip_distance = clip_distance; + + return output; +} + +float4 shadow_fragment(ShadowFragmentInput input): SV_TARGET { + Shadow shadow = shadows[input.shadow_id]; + + float2 half_size = shadow.bounds.size / 2.; + float2 center = shadow.bounds.origin + half_size; + float2 point0 = input.position.xy - center; + float corner_radius = pick_corner_radius(point0, shadow.corner_radii); + + float alpha; + if (shadow.blur_radius == 0.) { + float distance = quad_sdf(input.position.xy, shadow.bounds, shadow.corner_radii); + alpha = saturate(0.5 - distance); + } else { + // The signal is only non-zero in a limited range, so don't waste samples + float low = point0.y - half_size.y; + float high = point0.y + half_size.y; + float start = clamp(-3. * shadow.blur_radius, low, high); + float end = clamp(3. * shadow.blur_radius, low, high); + + // Accumulate samples (we can get away with surprisingly few samples) + float step = (end - start) / 4.; + float y = start + step * 0.5; + alpha = 0.; + for (int i = 0; i < 4; i++) { + alpha += blur_along_x(point0.x, point0.y - y, shadow.blur_radius, + corner_radius, half_size) * + gaussian(y, shadow.blur_radius) * step; + y += step; + } + } + + if (shadow.inset != 0u) { + // The inset shadow is the complement of the (blurred) hole rect, clipped to the element. + // `saturate(0.5 - d)` gives a 1-pixel antialiased edge: d <= -0.5 -> 1, d >= 0.5 -> 0. + alpha = 1.0 - alpha; + float element_distance = quad_sdf(input.position.xy, shadow.element_bounds, + shadow.element_corner_radii); + alpha *= saturate(0.5 - element_distance); + } + + return input.color * float4(1., 1., 1., alpha); +} + +/* +** +** Path Rasterization +** +*/ + +struct PathRasterizationSprite { + float2 xy_position; + float2 st_position; + Background color; + Bounds bounds; +}; + +StructuredBuffer path_rasterization_sprites: register(t1); + +struct PathVertexOutput { + float4 position: SV_Position; + float2 st_position: TEXCOORD0; + nointerpolation uint vertex_id: TEXCOORD1; + float4 clip_distance: SV_ClipDistance; +}; + +struct PathFragmentInput { + float4 position: SV_Position; + float2 st_position: TEXCOORD0; + nointerpolation uint vertex_id: TEXCOORD1; +}; + +PathVertexOutput path_rasterization_vertex(uint vertex_id: SV_VertexID) { + PathRasterizationSprite sprite = path_rasterization_sprites[vertex_id]; + + PathVertexOutput output; + output.position = to_device_position_impl(sprite.xy_position); + output.st_position = sprite.st_position; + output.vertex_id = vertex_id; + output.clip_distance = distance_from_clip_rect_impl(sprite.xy_position, sprite.bounds); + + return output; +} + +float4 path_rasterization_fragment(PathFragmentInput input): SV_Target { + float2 dx = ddx(input.st_position); + float2 dy = ddy(input.st_position); + PathRasterizationSprite sprite = path_rasterization_sprites[input.vertex_id]; + + Background background = sprite.color; + Bounds bounds = sprite.bounds; + + float alpha; + if (length(float2(dx.x, dy.x))) { + alpha = 1.0; + } else { + float2 gradient = 2.0 * input.st_position.xx * float2(dx.x, dy.x) - float2(dx.y, dy.y); + float f = input.st_position.x * input.st_position.x - input.st_position.y; + float distance = f / length(gradient); + alpha = saturate(0.5 - distance); + } + + GradientColor gradient = prepare_gradient_color( + background.tag, background.color_space, background.solid, background.colors); + + float4 color = gradient_color(background, input.position.xy, bounds, + gradient.solid, gradient.color0, gradient.color1); + return float4(color.rgb * color.a * alpha, alpha * color.a); +} + +/* +** +** Path Sprites +** +*/ + +struct PathSprite { + Bounds bounds; +}; + +struct PathSpriteVertexOutput { + float4 position: SV_Position; + float2 texture_coords: TEXCOORD0; +}; + +StructuredBuffer path_sprites: register(t1); + +PathSpriteVertexOutput path_sprite_vertex(uint vertex_id: SV_VertexID, uint sprite_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + PathSprite sprite = path_sprites[sprite_id]; + + // Don't apply content mask because it was already accounted for when rasterizing the path + float4 device_position = to_device_position(unit_vertex, sprite.bounds); + + float2 screen_position = sprite.bounds.origin + unit_vertex * sprite.bounds.size; + float2 texture_coords = screen_position / global_viewport_size; + + PathSpriteVertexOutput output; + output.position = device_position; + output.texture_coords = texture_coords; + return output; +} + +float4 path_sprite_fragment(PathSpriteVertexOutput input): SV_Target { + return t_sprite.Sample(s_sprite, input.texture_coords); +} + +/* +** +** Underlines +** +*/ + +struct Underline { + uint order; + uint pad; + Bounds bounds; + Bounds content_mask; + Hsla color; + float thickness; + uint wavy; +}; + +struct UnderlineVertexOutput { + nointerpolation uint underline_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 color: COLOR; + float4 clip_distance: SV_ClipDistance; +}; + +struct UnderlineFragmentInput { + nointerpolation uint underline_id: TEXCOORD0; + float4 position: SV_Position; + nointerpolation float4 color: COLOR; +}; + +StructuredBuffer underlines: register(t1); + +UnderlineVertexOutput underline_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + uint underline_id = batch_start_index + instance_id; + Underline underline = underlines[underline_id]; + float4 device_position = to_device_position(unit_vertex, underline.bounds); + float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds, + underline.content_mask); + float4 color = hsla_to_rgba(underline.color); + + UnderlineVertexOutput output; + output.position = device_position; + output.color = color; + output.underline_id = underline_id; + output.clip_distance = clip_distance; + return output; +} + +float4 underline_fragment(UnderlineFragmentInput input): SV_Target { + const float WAVE_FREQUENCY = 2.0; + const float WAVE_HEIGHT_RATIO = 0.8; + + Underline underline = underlines[input.underline_id]; + if (underline.wavy) { + float half_thickness = underline.thickness * 0.5; + float2 origin = underline.bounds.origin; + + float2 st = ((input.position.xy - origin) / underline.bounds.size.y) - float2(0., 0.5); + float frequency = (M_PI_F * WAVE_FREQUENCY * underline.thickness) / underline.bounds.size.y; + float amplitude = (underline.thickness * WAVE_HEIGHT_RATIO) / underline.bounds.size.y; + + float sine = sin(st.x * frequency) * amplitude; + float dSine = cos(st.x * frequency) * amplitude * frequency; + float distance = (st.y - sine) / sqrt(1. + dSine * dSine); + float distance_in_pixels = distance * underline.bounds.size.y; + float distance_from_top_border = distance_in_pixels - half_thickness; + float distance_from_bottom_border = distance_in_pixels + half_thickness; + float alpha = saturate( + 0.5 - max(-distance_from_bottom_border, distance_from_top_border)); + return input.color * float4(1., 1., 1., alpha); + } else { + return input.color; + } +} + +/* +** +** Monochrome sprites +** +*/ + +struct MonochromeSprite { + uint order; + uint pad; + Bounds bounds; + Bounds content_mask; + Hsla color; + AtlasTile tile; + TransformationMatrix transformation; +}; + +struct MonochromeSpriteVertexOutput { + float4 position: SV_Position; + float2 tile_position: POSITION; + nointerpolation float4 color: COLOR; + float4 clip_distance: SV_ClipDistance; +}; + +struct MonochromeSpriteFragmentInput { + float4 position: SV_Position; + float2 tile_position: POSITION; + nointerpolation float4 color: COLOR; + float4 clip_distance: SV_ClipDistance; +}; + +StructuredBuffer mono_sprites: register(t1); + +MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + uint sprite_id = batch_start_index + instance_id; + MonochromeSprite sprite = mono_sprites[sprite_id]; + float4 device_position = + to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation); + float4 clip_distance = distance_from_clip_rect_transformed(unit_vertex, sprite.bounds, sprite.content_mask, sprite.transformation); + float2 tile_position = to_tile_position(unit_vertex, sprite.tile); + float4 color = hsla_to_rgba(sprite.color); + + MonochromeSpriteVertexOutput output; + output.position = device_position; + output.tile_position = tile_position; + output.color = color; + output.clip_distance = clip_distance; + return output; +} + +float4 monochrome_sprite_fragment(MonochromeSpriteFragmentInput input): SV_Target { + float sample = t_sprite.Sample(s_sprite, input.tile_position).r; + float alpha_corrected = apply_contrast_and_gamma_correction(sample, input.color.rgb, grayscale_enhanced_contrast, gamma_ratios); + return float4(input.color.rgb, input.color.a * alpha_corrected); +} + +MonochromeSpriteVertexOutput subpixel_sprite_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + return monochrome_sprite_vertex(vertex_id, instance_id); +} + +SubpixelSpriteFragmentOutput subpixel_sprite_fragment(MonochromeSpriteFragmentInput input) { + float3 sample = t_sprite.Sample(s_sprite, input.tile_position).rgb; + if (is_bgr) { + sample = sample.bgr; + } + float3 alpha_corrected = apply_contrast_and_gamma_correction3(sample, input.color.rgb, subpixel_enhanced_contrast, gamma_ratios); + + SubpixelSpriteFragmentOutput output; + output.foreground = float4(input.color.rgb, 1.0f); + output.alpha = float4(input.color.a * alpha_corrected, 1.0f); + return output; +} + +/* +** +** Polychrome sprites +** +*/ + +struct PolychromeSprite { + uint order; + uint pad; + uint grayscale; + float opacity; + Bounds bounds; + Bounds content_mask; + Corners corner_radii; + AtlasTile tile; +}; + +struct PolychromeSpriteVertexOutput { + nointerpolation uint sprite_id: TEXCOORD0; + float4 position: SV_Position; + float2 tile_position: POSITION; + float4 clip_distance: SV_ClipDistance; +}; + +struct PolychromeSpriteFragmentInput { + nointerpolation uint sprite_id: TEXCOORD0; + float4 position: SV_Position; + float2 tile_position: POSITION; +}; + +StructuredBuffer poly_sprites: register(t1); + +PolychromeSpriteVertexOutput polychrome_sprite_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) { + float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u)); + uint sprite_id = batch_start_index + instance_id; + PolychromeSprite sprite = poly_sprites[sprite_id]; + float4 device_position = to_device_position(unit_vertex, sprite.bounds); + float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds, + sprite.content_mask); + float2 tile_position = to_tile_position(unit_vertex, sprite.tile); + + PolychromeSpriteVertexOutput output; + output.position = device_position; + output.tile_position = tile_position; + output.sprite_id = sprite_id; + output.clip_distance = clip_distance; + return output; +} + +float4 polychrome_sprite_fragment(PolychromeSpriteFragmentInput input): SV_Target { + PolychromeSprite sprite = poly_sprites[input.sprite_id]; + float4 sample = t_sprite.Sample(s_sprite, input.tile_position); + float distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii); + + float4 color = sample; + if (sprite.grayscale != 0u) { + float3 grayscale = dot(color.rgb, GRAYSCALE_FACTORS); + color = float4(grayscale, sample.a); + } + color.a *= sprite.opacity * saturate(0.5 - distance); + return color; +} diff --git a/vendor/gpui-pre-windows/src/system_notifications.rs b/vendor/gpui-pre-windows/src/system_notifications.rs new file mode 100644 index 00000000..b0075f0e --- /dev/null +++ b/vendor/gpui-pre-windows/src/system_notifications.rs @@ -0,0 +1,198 @@ +//! System notifications as Windows toast notifications. + +use std::cell::RefCell; +use std::collections::{HashMap, hash_map::DefaultHasher}; +use std::hash::{Hash as _, Hasher as _}; +use std::rc::Rc; + +use futures::StreamExt as _; +use futures::channel::mpsc; +use gpui::{ + ForegroundExecutor, SharedString, SystemNotification, SystemNotificationResponse, Task, +}; +use windows::Data::Xml::Dom::XmlDocument; +use windows::Foundation::TypedEventHandler; +use windows::UI::Notifications::{ + ToastActivatedEventArgs, ToastNotification, ToastNotificationManager, ToastNotifier, +}; +use windows::core::{IInspectable, Interface as _, h}; + +type ResponseCallback = Rc>>>; + +pub(crate) struct SystemNotificationState { + notifier: Option, + active_toasts: HashMap, + response_sender: mpsc::UnboundedSender, + response_receiver: Option>, + callback: ResponseCallback, + _response_task: Option>, +} + +impl SystemNotificationState { + pub(crate) fn new() -> Self { + let (response_sender, response_receiver) = mpsc::unbounded(); + Self { + notifier: None, + active_toasts: HashMap::new(), + response_sender, + response_receiver: Some(response_receiver), + callback: Rc::new(RefCell::new(None)), + _response_task: None, + } + } + + pub(crate) fn show( + &mut self, + has_package_identity: bool, + app_identity: Option<(&str, &str)>, + notification: SystemNotification, + ) -> windows::core::Result<()> { + let Some(notifier) = self.notifier(has_package_identity, app_identity)? else { + return Ok(()); + }; + + let document = toast_document(¬ification)?; + let toast = ToastNotification::CreateToastNotification(&document)?; + // Windows caps toast tags at 64 characters (post-Creators Update), + // so hash the arbitrary GPUI tag down to a fixed-width value. + let tag = { + let mut hasher = DefaultHasher::new(); + notification.tag.hash(&mut hasher); + format!("{:016x}", hasher.finish()) + }; + toast.SetTag(&tag.into())?; + + let sender = self.response_sender.clone(); + let response_tag = notification.tag.clone(); + toast.Activated(&TypedEventHandler::::new( + move |_sender, arguments| { + let action_id = arguments + .as_ref() + .and_then(|arguments| arguments.cast::().ok()) + .and_then(|arguments| arguments.Arguments().ok()) + .filter(|arguments| !arguments.is_empty()) + .map(|arguments| SharedString::from(arguments.to_string())); + sender + .unbounded_send(SystemNotificationResponse { + tag: response_tag.clone(), + action_id, + }) + .ok(); + Ok(()) + }, + ))?; + + if let Some(previous) = self.active_toasts.remove(¬ification.tag) { + notifier.Hide(&previous)?; + } + notifier.Show(&toast)?; + self.active_toasts.insert(notification.tag, toast); + Ok(()) + } + + pub(crate) fn dismiss(&mut self, tag: &str) { + let Some(toast) = self.active_toasts.remove(tag) else { + return; + }; + let Some(notifier) = &self.notifier else { + return; + }; + if let Err(error) = notifier.Hide(&toast) { + log::warn!("failed to dismiss system notification: {error}"); + } + } + + pub(crate) fn on_response( + &mut self, + executor: &ForegroundExecutor, + callback: Box, + ) { + *self.callback.borrow_mut() = Some(callback); + + if let Some(mut receiver) = self.response_receiver.take() { + let callback = self.callback.clone(); + self._response_task = Some(executor.spawn(async move { + while let Some(response) = receiver.next().await { + // Take the callback out for the call: it may re-enter the + // platform (e.g. to dismiss the notification it was told + // about) or replace itself. + let taken = callback.borrow_mut().take(); + if let Some(mut taken) = taken { + taken(response); + callback.borrow_mut().get_or_insert(taken); + } + } + })); + } + } + + fn notifier( + &mut self, + has_package_identity: bool, + app_identity: Option<(&str, &str)>, + ) -> windows::core::Result> { + if let Some(notifier) = &self.notifier { + return Ok(Some(notifier.clone())); + } + + let notifier = if has_package_identity { + ToastNotificationManager::CreateToastNotifier()? + } else { + let Some((app_identifier, app_name)) = app_identity else { + log::warn!( + "cannot show a system notification without an app identity; \ + call `App::set_app_identity` during startup" + ); + return Ok(None); + }; + register_app_user_model_id(app_identifier, app_name); + ToastNotificationManager::CreateToastNotifierWithId(&app_identifier.into())? + }; + + self.notifier = Some(notifier.clone()); + Ok(Some(notifier)) + } +} + +fn toast_document(notification: &SystemNotification) -> windows::core::Result { + let document = XmlDocument::new()?; + let toast = document.CreateElement(h!("toast"))?; + document.AppendChild(&toast)?; + + let visual = document.CreateElement(h!("visual"))?; + toast.AppendChild(&visual)?; + let binding = document.CreateElement(h!("binding"))?; + binding.SetAttribute(h!("template"), h!("ToastGeneric"))?; + visual.AppendChild(&binding)?; + for text in [¬ification.title, ¬ification.body] { + let element = document.CreateElement(h!("text"))?; + element.SetInnerText(&text.as_ref().into())?; + binding.AppendChild(&element)?; + } + + if !notification.actions.is_empty() { + let actions = document.CreateElement(h!("actions"))?; + toast.AppendChild(&actions)?; + for action in ¬ification.actions { + let action_element = document.CreateElement(h!("action"))?; + action_element.SetAttribute(h!("content"), &action.label.as_ref().into())?; + action_element.SetAttribute(h!("arguments"), &action.id.as_ref().into())?; + actions.AppendChild(&action_element)?; + } + } + + let audio = document.CreateElement(h!("audio"))?; + audio.SetAttribute(h!("silent"), h!("true"))?; + toast.AppendChild(&audio)?; + Ok(document) +} + +/// Registers the app's AUMID so toasts display correctly for an unpackaged app without a Start Menu shortcut. +fn register_app_user_model_id(app_identifier: &str, app_name: &str) { + let result = windows_registry::CURRENT_USER + .create(format!(r"Software\Classes\AppUserModelId\{app_identifier}")) + .and_then(|key| key.set_string("DisplayName", app_name)); + if let Err(error) = result { + log::warn!("failed to register AppUserModelID; notifications may not display: {error}"); + } +} diff --git a/vendor/gpui-pre-windows/src/system_settings.rs b/vendor/gpui-pre-windows/src/system_settings.rs new file mode 100644 index 00000000..8cce544b --- /dev/null +++ b/vendor/gpui-pre-windows/src/system_settings.rs @@ -0,0 +1,87 @@ +use std::{ + cell::Cell, + ffi::{c_uint, c_void}, +}; + +use gpui_util::ResultExt; +use windows::Win32::UI::WindowsAndMessaging::{ + SPI_GETWHEELSCROLLCHARS, SPI_GETWHEELSCROLLLINES, SYSTEM_PARAMETERS_INFO_ACTION, + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, SystemParametersInfoW, +}; + +/// Windows settings pulled from SystemParametersInfo +/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfow +#[derive(Default, Debug, Clone)] +pub(crate) struct WindowsSystemSettings { + pub(crate) mouse_wheel_settings: MouseWheelSettings, +} + +#[derive(Default, Debug, Clone)] +pub(crate) struct MouseWheelSettings { + /// SEE: SPI_GETWHEELSCROLLCHARS + pub(crate) wheel_scroll_chars: Cell, + /// SEE: SPI_GETWHEELSCROLLLINES + pub(crate) wheel_scroll_lines: Cell, +} + +impl WindowsSystemSettings { + pub(crate) fn new() -> Self { + let mut settings = Self::default(); + settings.init(); + settings + } + + fn init(&mut self) { + self.mouse_wheel_settings.update(); + } + + pub(crate) fn update(&self, wparam: usize) { + match SYSTEM_PARAMETERS_INFO_ACTION(wparam as u32) { + SPI_GETWHEELSCROLLLINES | SPI_GETWHEELSCROLLCHARS => self.update_mouse_wheel_settings(), + _ => {} + } + } + + fn update_mouse_wheel_settings(&self) { + self.mouse_wheel_settings.update(); + } +} + +impl MouseWheelSettings { + fn update(&self) { + self.update_wheel_scroll_chars(); + self.update_wheel_scroll_lines(); + } + + fn update_wheel_scroll_chars(&self) { + let mut value = c_uint::default(); + let result = unsafe { + SystemParametersInfoW( + SPI_GETWHEELSCROLLCHARS, + 0, + Some((&mut value) as *mut c_uint as *mut c_void), + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS::default(), + ) + }; + + if result.log_err() != None && self.wheel_scroll_chars.get() != value { + self.wheel_scroll_chars.set(value); + } + } + + fn update_wheel_scroll_lines(&self) { + let mut value = c_uint::default(); + let result = unsafe { + SystemParametersInfoW( + SPI_GETWHEELSCROLLLINES, + 0, + Some((&mut value) as *mut c_uint as *mut c_void), + SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS::default(), + ) + }; + + if result.log_err() != None && self.wheel_scroll_lines.get() != value { + self.wheel_scroll_lines.set(value); + } + } +} diff --git a/vendor/gpui-pre-windows/src/util.rs b/vendor/gpui-pre-windows/src/util.rs new file mode 100644 index 00000000..b3badd84 --- /dev/null +++ b/vendor/gpui-pre-windows/src/util.rs @@ -0,0 +1,191 @@ +use std::sync::OnceLock; + +use anyhow::Context; +use gpui_util::ResultExt; +use windows::{ + UI::{ + Color, + ViewManagement::{UIColorType, UISettings}, + }, + Win32::{ + Foundation::*, Graphics::Dwm::*, System::LibraryLoader::LoadLibraryA, + UI::WindowsAndMessaging::*, + }, + core::{BOOL, PCSTR}, +}; + +use crate::*; +use gpui::*; + +pub(crate) trait HiLoWord { + fn hiword(&self) -> u16; + fn loword(&self) -> u16; + fn signed_hiword(&self) -> i16; + fn signed_loword(&self) -> i16; +} + +impl HiLoWord for WPARAM { + fn hiword(&self) -> u16 { + ((self.0 >> 16) & 0xFFFF) as u16 + } + + fn loword(&self) -> u16 { + (self.0 & 0xFFFF) as u16 + } + + fn signed_hiword(&self) -> i16 { + ((self.0 >> 16) & 0xFFFF) as i16 + } + + fn signed_loword(&self) -> i16 { + (self.0 & 0xFFFF) as i16 + } +} + +impl HiLoWord for LPARAM { + fn hiword(&self) -> u16 { + ((self.0 >> 16) & 0xFFFF) as u16 + } + + fn loword(&self) -> u16 { + (self.0 & 0xFFFF) as u16 + } + + fn signed_hiword(&self) -> i16 { + ((self.0 >> 16) & 0xFFFF) as i16 + } + + fn signed_loword(&self) -> i16 { + (self.0 & 0xFFFF) as i16 + } +} + +pub(crate) unsafe fn get_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize { + #[cfg(target_pointer_width = "64")] + unsafe { + GetWindowLongPtrW(hwnd, nindex) + } + #[cfg(target_pointer_width = "32")] + unsafe { + GetWindowLongW(hwnd, nindex) as isize + } +} + +pub(crate) unsafe fn set_window_long( + hwnd: HWND, + nindex: WINDOW_LONG_PTR_INDEX, + dwnewlong: isize, +) -> isize { + #[cfg(target_pointer_width = "64")] + unsafe { + SetWindowLongPtrW(hwnd, nindex, dwnewlong) + } + #[cfg(target_pointer_width = "32")] + unsafe { + SetWindowLongW(hwnd, nindex, dwnewlong as i32) as isize + } +} + +pub(crate) fn windows_credentials_target_name(url: &str) -> String { + format!("zed:url={}", url) +} + +pub(crate) fn load_cursor(style: CursorStyle) -> Option { + static ARROW: OnceLock = OnceLock::new(); + static IBEAM: OnceLock = OnceLock::new(); + static CROSS: OnceLock = OnceLock::new(); + static HAND: OnceLock = OnceLock::new(); + static SIZEWE: OnceLock = OnceLock::new(); + static SIZENS: OnceLock = OnceLock::new(); + static SIZENWSE: OnceLock = OnceLock::new(); + static SIZENESW: OnceLock = OnceLock::new(); + static NO: OnceLock = OnceLock::new(); + let (lock, name) = match style { + CursorStyle::IBeam | CursorStyle::IBeamCursorForVerticalLayout => (&IBEAM, IDC_IBEAM), + CursorStyle::Crosshair => (&CROSS, IDC_CROSS), + CursorStyle::PointingHand | CursorStyle::DragLink => (&HAND, IDC_HAND), + CursorStyle::ResizeLeft + | CursorStyle::ResizeRight + | CursorStyle::ResizeLeftRight + | CursorStyle::ResizeColumn => (&SIZEWE, IDC_SIZEWE), + CursorStyle::ResizeUp + | CursorStyle::ResizeDown + | CursorStyle::ResizeUpDown + | CursorStyle::ResizeRow => (&SIZENS, IDC_SIZENS), + CursorStyle::ResizeUpLeftDownRight => (&SIZENWSE, IDC_SIZENWSE), + CursorStyle::ResizeUpRightDownLeft => (&SIZENESW, IDC_SIZENESW), + CursorStyle::OperationNotAllowed => (&NO, IDC_NO), + _ => (&ARROW, IDC_ARROW), + }; + Some( + *(*lock.get_or_init(|| { + HCURSOR( + unsafe { LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED) } + .log_err() + .unwrap_or_default() + .0, + ) + .into() + })), + ) +} + +/// This function is used to configure the dark mode for the window built-in title bar. +pub(crate) fn configure_dwm_dark_mode(hwnd: HWND, appearance: WindowAppearance) { + let dark_mode_enabled: BOOL = match appearance { + WindowAppearance::Dark | WindowAppearance::VibrantDark => true.into(), + WindowAppearance::Light | WindowAppearance::VibrantLight => false.into(), + }; + unsafe { + DwmSetWindowAttribute( + hwnd, + DWMWA_USE_IMMERSIVE_DARK_MODE, + &dark_mode_enabled as *const _ as _, + std::mem::size_of::() as u32, + ) + .log_err(); + } +} + +#[inline] +pub(crate) fn logical_point(x: f32, y: f32, scale_factor: f32) -> Point { + Point { + x: px(x / scale_factor), + y: px(y / scale_factor), + } +} + +// https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-windows-themes +#[inline] +pub(crate) fn system_appearance() -> Result { + let ui_settings = UISettings::new()?; + let foreground_color = ui_settings.GetColorValue(UIColorType::Foreground)?; + // If the foreground is light, then is_color_light will evaluate to true, + // meaning Dark mode is enabled. + if is_color_light(&foreground_color) { + Ok(WindowAppearance::Dark) + } else { + Ok(WindowAppearance::Light) + } +} + +#[inline(always)] +fn is_color_light(color: &Color) -> bool { + ((5 * color.G as u32) + (2 * color.R as u32) + color.B as u32) > (8 * 128) +} + +pub(crate) fn with_dll_library(dll_name: PCSTR, f: F) -> Result +where + F: FnOnce(HMODULE) -> Result, +{ + let library = unsafe { + LoadLibraryA(dll_name).with_context(|| format!("Loading dll: {}", dll_name.display()))? + }; + let result = f(library); + unsafe { + FreeLibrary(library) + .with_context(|| format!("Freeing dll: {}", dll_name.display())) + .log_err(); + } + result +} diff --git a/vendor/gpui-pre-windows/src/vsync.rs b/vendor/gpui-pre-windows/src/vsync.rs new file mode 100644 index 00000000..5121c41b --- /dev/null +++ b/vendor/gpui-pre-windows/src/vsync.rs @@ -0,0 +1,119 @@ +use std::{ + sync::LazyLock, + time::{Duration, Instant}, +}; + +use anyhow::{Context, Result}; +use gpui::FrameRequestSource; +use gpui_util::ResultExt; +use windows::Win32::{ + Foundation::HWND, + Graphics::Dwm::{DWM_TIMING_INFO, DwmFlush, DwmGetCompositionTimingInfo}, + System::Performance::QueryPerformanceFrequency, +}; + +static QPC_TICKS_PER_SECOND: LazyLock = LazyLock::new(|| { + let mut frequency = 0; + // On systems that run Windows XP or later, the function will always succeed and + // will thus never return zero. + unsafe { QueryPerformanceFrequency(&mut frequency).unwrap() }; + frequency as u64 +}); + +const VSYNC_INTERVAL_THRESHOLD: Duration = Duration::from_millis(1); +const DEFAULT_VSYNC_INTERVAL: Duration = Duration::from_micros(16_666); // ~60Hz + +pub(crate) struct VSyncProvider { + interval: Duration, + f: Box bool>, +} + +impl VSyncProvider { + pub(crate) fn new() -> Self { + let interval = get_dwm_interval() + .context("Failed to get DWM interval") + .log_err() + .unwrap_or(DEFAULT_VSYNC_INTERVAL); + let f = Box::new(|| unsafe { DwmFlush().is_ok() }); + Self { interval, f } + } + + pub(crate) fn wait_for_vsync(&self) -> FrameRequestSource { + let vsync_start = Instant::now(); + let wait_succeeded = (self.f)(); + let elapsed = vsync_start.elapsed(); + // DwmFlush and DCompositionWaitForCompositorClock returns very early + // instead of waiting until vblank when the monitor goes to sleep or is + // unplugged (nothing to present due to desktop occlusion). We use 1ms as + // a threshold for the duration of the wait functions and fallback to + // Sleep() if it returns before that. This could happen during normal + // operation for the first call after the vsync thread becomes non-idle, + // but it shouldn't happen often. + if !wait_succeeded || elapsed < VSYNC_INTERVAL_THRESHOLD { + log::trace!("VSyncProvider::wait_for_vsync() took less time than expected"); + std::thread::sleep(self.interval); + FrameRequestSource::LocalSchedule + } else { + FrameRequestSource::NativeCallback + } + } +} + +fn get_dwm_interval() -> Result { + let mut timing_info = DWM_TIMING_INFO { + cbSize: std::mem::size_of::() as u32, + ..Default::default() + }; + unsafe { DwmGetCompositionTimingInfo(HWND::default(), &mut timing_info) }?; + let interval = retrieve_duration(timing_info.qpcRefreshPeriod, *QPC_TICKS_PER_SECOND); + // Check for interval values that are impossibly low. A 29 microsecond + // interval was seen (from a qpcRefreshPeriod of 60). + if interval < VSYNC_INTERVAL_THRESHOLD { + Ok(retrieve_duration( + timing_info.rateRefresh.uiDenominator as u64, + timing_info.rateRefresh.uiNumerator as u64, + )) + } else { + Ok(interval) + } +} + +#[inline] +fn retrieve_duration(counts: u64, ticks_per_second: u64) -> Duration { + let ticks_per_microsecond = ticks_per_second / 1_000_000; + Duration::from_micros(counts / ticks_per_microsecond) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn successful_compositor_wait_reports_native_callback() { + let provider = VSyncProvider { + interval: Duration::ZERO, + f: Box::new(|| { + std::thread::sleep(VSYNC_INTERVAL_THRESHOLD * 2); + true + }), + }; + + assert_eq!( + provider.wait_for_vsync(), + FrameRequestSource::NativeCallback + ); + } + + #[test] + fn failed_compositor_wait_reports_local_schedule_even_after_threshold() { + let provider = VSyncProvider { + interval: Duration::ZERO, + f: Box::new(|| { + std::thread::sleep(VSYNC_INTERVAL_THRESHOLD * 2); + false + }), + }; + + assert_eq!(provider.wait_for_vsync(), FrameRequestSource::LocalSchedule); + } +} diff --git a/vendor/gpui-pre-windows/src/window.rs b/vendor/gpui-pre-windows/src/window.rs new file mode 100644 index 00000000..8a5327d1 --- /dev/null +++ b/vendor/gpui-pre-windows/src/window.rs @@ -0,0 +1,1735 @@ +#![deny(unsafe_op_in_unsafe_fn)] + +use std::{ + cell::{Cell, RefCell}, + num::NonZeroIsize, + path::PathBuf, + rc::{Rc, Weak}, + str::FromStr, + sync::{Arc, Once, atomic::AtomicBool}, + time::{Duration, Instant}, +}; + +use anyhow::{Context as _, Result}; +use futures::channel::oneshot::{self, Receiver}; +use gpui_util::ResultExt; +use raw_window_handle as rwh; +use smallvec::SmallVec; +use windows::{ + Win32::{ + Foundation::*, + Graphics::Dwm::*, + Graphics::Gdi::*, + System::{ + Com::*, Diagnostics::Debug::MessageBeep, LibraryLoader::*, Ole::*, SystemServices::*, + }, + UI::{Controls::*, HiDpi::*, Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, + }, + core::*, +}; + +use crate::direct_manipulation::DirectManipulationHandler; +use crate::*; +use gpui::*; + +pub(crate) struct WindowsWindow(pub Rc); + +impl std::ops::Deref for WindowsWindow { + type Target = WindowsWindowInner; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct WindowsWindowState { + pub origin: Cell>, + pub logical_size: Cell>, + pub min_size: Option>, + pub fullscreen_restore_bounds: Cell>, + pub border_offset: WindowBorderOffset, + pub appearance: Cell, + pub background_appearance: Cell, + pub scale_factor: Cell, + pub restore_from_minimized: Cell>>, + + pub callbacks: Callbacks, + pub frame_signal: Arc, + pub input_handler: Cell>, + pub ime_enabled: Cell, + pub pending_surrogate: Cell>, + pub last_reported_modifiers: Cell>, + pub last_reported_capslock: Cell>, + pub hovered: Cell, + pub last_visibility: Cell>, + pub direct_manipulation: DirectManipulationHandler, + + pub renderer: RefCell, + /// Set when the next `draw_window` call must be treated as a forced + /// render. Used after a GPU device-lost recovery, where the next frame + /// must both re-enable drawing (via `mark_drawable`) and bypass the GPUI + /// view cache (which would otherwise replay stale atlas tile references + /// from the previous frame and panic in `DirectXAtlasTextures::texture`), + /// and when a forced render was requested while another draw was in + /// progress and had to be deferred. + pub force_render_pending: Cell, + + pub click_state: ClickState, + pub current_cursor: Cell>, + /// Shared with [`WindowsPlatformState::cursor_visible`]. + pub cursor_visible: Arc, + pub nc_button_pressed: Cell>, + + pub display: Cell, + /// Flag to instruct the `VSyncProvider` thread to invalidate the directx devices + /// as resizing them has failed, causing us to have lost at least the render target. + pub invalidate_devices: Arc, + /// Shared with [`WindowsPlatformState::draw_coordinator`] and every other window. + pub(crate) draw_coordinator: Rc, + fullscreen: Cell>, + initial_placement: Cell>, + hwnd: HWND, + pub(crate) a11y: RefCell>, +} + +pub(crate) struct WindowsWindowInner { + hwnd: HWND, + pub(crate) dialog_owner: Rc, + drop_target_helper: IDropTargetHelper, + pub(crate) state: WindowsWindowState, + system_settings: WindowsSystemSettings, + pub(crate) handle: AnyWindowHandle, + pub(crate) hide_title_bar: bool, + pub(crate) is_movable: bool, + pub(crate) is_resizable: bool, + pub(crate) is_minimizable: bool, + pub(crate) executor: ForegroundExecutor, + pub(crate) validation_number: usize, + pub(crate) main_receiver: PriorityQueueReceiver, + pub(crate) platform_window_handle: HWND, + pub(crate) parent_hwnd: Option, +} + +impl WindowsWindowState { + fn new( + hwnd: HWND, + directx_devices: &DirectXDevices, + window_params: &CREATESTRUCTW, + current_cursor: Option, + cursor_visible: Arc, + display: WindowsDisplay, + min_size: Option>, + appearance: WindowAppearance, + disable_direct_composition: bool, + invalidate_devices: Arc, + draw_coordinator: Rc, + ) -> Result { + let scale_factor = { + let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32; + monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32 + }; + let origin = logical_point(window_params.x as f32, window_params.y as f32, scale_factor); + let logical_size = { + let physical_size = size( + DevicePixels(window_params.cx), + DevicePixels(window_params.cy), + ); + physical_size.to_pixels(scale_factor) + }; + let fullscreen_restore_bounds = Bounds { + origin, + size: logical_size, + }; + let border_offset = WindowBorderOffset::default(); + let restore_from_minimized = None; + let renderer = DirectXRenderer::new(hwnd, directx_devices, disable_direct_composition) + .context("Creating DirectX renderer")?; + let callbacks = Callbacks::default(); + let input_handler = None; + let pending_surrogate = None; + let last_reported_modifiers = None; + let last_reported_capslock = None; + let hovered = false; + let click_state = ClickState::new(); + let nc_button_pressed = None; + let fullscreen = None; + let initial_placement = None; + + let direct_manipulation = DirectManipulationHandler::new(hwnd, scale_factor) + .context("initializing Direct Manipulation")?; + + Ok(Self { + origin: Cell::new(origin), + logical_size: Cell::new(logical_size), + fullscreen_restore_bounds: Cell::new(fullscreen_restore_bounds), + border_offset, + appearance: Cell::new(appearance), + background_appearance: Cell::new(WindowBackgroundAppearance::Opaque), + scale_factor: Cell::new(scale_factor), + restore_from_minimized: Cell::new(restore_from_minimized), + min_size, + callbacks, + frame_signal: Arc::new(PlatformFrameSignal::new()), + input_handler: Cell::new(input_handler), + ime_enabled: Cell::new(true), + pending_surrogate: Cell::new(pending_surrogate), + last_reported_modifiers: Cell::new(last_reported_modifiers), + last_reported_capslock: Cell::new(last_reported_capslock), + hovered: Cell::new(hovered), + last_visibility: Cell::new(None), + renderer: RefCell::new(renderer), + force_render_pending: Cell::new(false), + click_state, + current_cursor: Cell::new(current_cursor), + cursor_visible, + nc_button_pressed: Cell::new(nc_button_pressed), + display: Cell::new(display), + fullscreen: Cell::new(fullscreen), + initial_placement: Cell::new(initial_placement), + hwnd, + invalidate_devices, + draw_coordinator, + direct_manipulation, + a11y: RefCell::new(None), + }) + } + + #[inline] + pub(crate) fn is_fullscreen(&self) -> bool { + self.fullscreen.get().is_some() + } + + pub(crate) fn is_maximized(&self) -> bool { + !self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool() + } + + fn bounds(&self) -> Bounds { + Bounds { + origin: self.origin.get(), + size: self.logical_size.get(), + } + } + + // Calculate the bounds used for saving and whether the window is maximized. + fn calculate_window_bounds(&self) -> (Bounds, bool) { + let placement = unsafe { + let mut placement = WINDOWPLACEMENT { + length: std::mem::size_of::() as u32, + ..Default::default() + }; + GetWindowPlacement(self.hwnd, &mut placement) + .context("failed to get window placement") + .log_err(); + placement + }; + ( + calculate_client_rect( + placement.rcNormalPosition, + &self.border_offset, + self.scale_factor.get(), + ), + placement.showCmd == SW_SHOWMAXIMIZED.0 as u32, + ) + } + + fn window_bounds(&self) -> WindowBounds { + let (bounds, maximized) = self.calculate_window_bounds(); + + if self.is_fullscreen() { + WindowBounds::Fullscreen(self.fullscreen_restore_bounds.get()) + } else if maximized { + WindowBounds::Maximized(bounds) + } else { + WindowBounds::Windowed(bounds) + } + } + + /// get the logical size of the app's drawable area. + /// + /// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as + /// whether the mouse collides with other elements of GPUI). + fn content_size(&self) -> Size { + self.logical_size.get() + } +} + +impl WindowsWindowInner { + /// Whether the window is being presented: shown and not minimized. Windows + /// has no notification for a window fully covered by other windows, so + /// that case reports `Visible`. + pub(crate) fn visibility(&self) -> WindowVisibility { + let is_visible = + unsafe { IsWindowVisible(self.hwnd).as_bool() && !IsIconic(self.hwnd).as_bool() }; + if is_visible { + WindowVisibility::Visible + } else { + WindowVisibility::Hidden + } + } + + fn new(context: &mut WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Result> { + let state = WindowsWindowState::new( + hwnd, + &context.directx_devices, + cs, + context.current_cursor, + context.cursor_visible.clone(), + context.display, + context.min_size, + context.appearance, + context.disable_direct_composition, + context.invalidate_devices.clone(), + context.draw_coordinator.clone(), + )?; + + Ok(Rc::new(Self { + hwnd, + dialog_owner: crate::dialog::DialogOwner::new(hwnd), + drop_target_helper: context.drop_target_helper.clone(), + state, + handle: context.handle, + hide_title_bar: context.hide_title_bar, + is_movable: context.is_movable, + is_resizable: context.is_resizable, + is_minimizable: context.is_minimizable, + executor: context.executor.clone(), + validation_number: context.validation_number, + main_receiver: context.main_receiver.clone(), + platform_window_handle: context.platform_window_handle, + system_settings: WindowsSystemSettings::new(), + parent_hwnd: context.parent_hwnd, + })) + } + + fn toggle_fullscreen(self: &Rc) { + let this = self.clone(); + self.executor + .spawn(async move { + let StyleAndBounds { + style, + x, + y, + cx, + cy, + } = match this.state.fullscreen.take() { + Some(state) => state, + None => { + let (window_bounds, _) = this.state.calculate_window_bounds(); + this.state.fullscreen_restore_bounds.set(window_bounds); + + let style = + WINDOW_STYLE(unsafe { get_window_long(this.hwnd, GWL_STYLE) } as _); + let mut rc = RECT::default(); + unsafe { GetWindowRect(this.hwnd, &mut rc) } + .context("failed to get window rect") + .log_err(); + let _ = this.state.fullscreen.set(Some(StyleAndBounds { + style, + x: rc.left, + y: rc.top, + cx: rc.right - rc.left, + cy: rc.bottom - rc.top, + })); + let style = style + & !(WS_THICKFRAME + | WS_SYSMENU + | WS_MAXIMIZEBOX + | WS_MINIMIZEBOX + | WS_CAPTION); + let physical_bounds = this.state.display.get().physical_bounds(); + StyleAndBounds { + style, + x: physical_bounds.left().0, + y: physical_bounds.top().0, + cx: physical_bounds.size.width.0, + cy: physical_bounds.size.height.0, + } + } + }; + set_non_rude_hwnd(this.hwnd, !this.state.is_fullscreen()); + unsafe { set_window_long(this.hwnd, GWL_STYLE, style.0 as isize) }; + unsafe { + SetWindowPos( + this.hwnd, + None, + x, + y, + cx, + cy, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER, + ) + } + .log_err(); + }) + .detach(); + } + + fn set_window_placement(self: &Rc) -> Result<()> { + let Some(open_status) = self.state.initial_placement.take() else { + return Ok(()); + }; + match open_status.state { + WindowOpenState::Maximized => unsafe { + SetWindowPlacement(self.hwnd, &open_status.placement) + .context("failed to set window placement")?; + ShowWindowAsync(self.hwnd, SW_MAXIMIZE).ok()?; + }, + WindowOpenState::Fullscreen => { + unsafe { + SetWindowPlacement(self.hwnd, &open_status.placement) + .context("failed to set window placement")? + }; + self.toggle_fullscreen(); + } + WindowOpenState::Windowed => unsafe { + SetWindowPlacement(self.hwnd, &open_status.placement) + .context("failed to set window placement")?; + }, + } + Ok(()) + } + + pub(crate) fn system_settings(&self) -> &WindowsSystemSettings { + &self.system_settings + } +} + +#[derive(Default)] +pub(crate) struct Callbacks { + pub(crate) request_frame: Cell>>, + pub(crate) input: Cell DispatchEventResult>>>, + pub(crate) active_status_change: Cell>>, + pub(crate) visibility_change: Cell>>, + pub(crate) hovered_status_change: Cell>>, + pub(crate) resize: Cell, f32)>>>, + pub(crate) moved: Cell>>, + pub(crate) should_close: Cell bool>>>, + pub(crate) close: Cell>>, + pub(crate) hit_test_window_control: Cell Option>>>, + pub(crate) appearance_changed: Cell>>, +} + +struct WindowCreateContext { + inner: Option>>, + handle: AnyWindowHandle, + hide_title_bar: bool, + display: WindowsDisplay, + is_movable: bool, + is_resizable: bool, + is_minimizable: bool, + min_size: Option>, + executor: ForegroundExecutor, + current_cursor: Option, + cursor_visible: Arc, + drop_target_helper: IDropTargetHelper, + validation_number: usize, + main_receiver: PriorityQueueReceiver, + platform_window_handle: HWND, + appearance: WindowAppearance, + disable_direct_composition: bool, + directx_devices: DirectXDevices, + invalidate_devices: Arc, + draw_coordinator: Rc, + parent_hwnd: Option, +} + +impl WindowsWindow { + pub(crate) fn new( + handle: AnyWindowHandle, + params: WindowParams, + creation_info: WindowCreationInfo, + ) -> Result { + // Native popups are not implemented on Windows yet. Rejecting lets callers fall back to + // gpui's in-window popovers. + if let WindowKind::AnchoredPopup(_) = params.kind { + return Err(popup::PopupNotSupportedError.into()); + } + + let WindowCreationInfo { + icon, + executor, + current_cursor, + cursor_visible, + drop_target_helper, + validation_number, + main_receiver, + platform_window_handle, + disable_direct_composition, + directx_devices, + invalidate_devices, + draw_coordinator, + } = creation_info; + register_window_class(icon); + let parent_hwnd = if params.kind == WindowKind::Dialog { + let parent_window = unsafe { GetActiveWindow() }; + if parent_window.is_invalid() { + None + } else { + // Disable the parent window to make this dialog modal + unsafe { + EnableWindow(parent_window, false).as_bool(); + }; + Some(parent_window) + } + } else { + None + }; + let hide_title_bar = params + .titlebar + .as_ref() + .map(|titlebar| titlebar.appears_transparent) + .unwrap_or(true); + let window_name = HSTRING::from( + params + .titlebar + .as_ref() + .and_then(|titlebar| titlebar.title.as_ref()) + .map(|title| title.as_ref()) + .unwrap_or(""), + ); + + let (mut dwexstyle, dwstyle) = if params.kind == WindowKind::PopUp { + (WS_EX_TOOLWINDOW | WS_EX_TOPMOST, WINDOW_STYLE(0x0)) + } else { + let mut dwstyle = WS_SYSMENU; + + if params.is_resizable { + dwstyle |= WS_THICKFRAME | WS_MAXIMIZEBOX; + } + + if params.is_minimizable { + dwstyle |= WS_MINIMIZEBOX; + } + let dwexstyle = if params.kind == WindowKind::Dialog { + dwstyle |= WS_POPUP | WS_CAPTION; + WS_EX_DLGMODALFRAME + } else { + WS_EX_APPWINDOW + }; + + (dwexstyle, dwstyle) + }; + if !disable_direct_composition { + dwexstyle |= WS_EX_NOREDIRECTIONBITMAP; + } + + let hinstance = get_module_handle(); + let display = if let Some(display_id) = params.display_id { + WindowsDisplay::new(display_id) + } else { + None + } + .or_else(WindowsDisplay::primary_monitor) + .context("failed to find any monitor")?; + let appearance = system_appearance().unwrap_or_default(); + let mut context = WindowCreateContext { + inner: None, + handle, + hide_title_bar, + display, + is_movable: params.is_movable, + is_resizable: params.is_resizable, + is_minimizable: params.is_minimizable, + min_size: params.window_min_size, + executor, + current_cursor, + cursor_visible, + drop_target_helper, + validation_number, + main_receiver, + platform_window_handle, + appearance, + disable_direct_composition, + directx_devices, + invalidate_devices, + draw_coordinator, + parent_hwnd, + }; + let creation_result = unsafe { + CreateWindowExW( + dwexstyle, + WINDOW_CLASS_NAME, + &window_name, + dwstyle, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + parent_hwnd, + None, + Some(hinstance.into()), + Some(&context as *const _ as *const _), + ) + }; + + // Failure to create a `WindowsWindowState` can cause window creation to fail, + // so check the inner result first. + let this = context.inner.take().transpose()?; + let hwnd = creation_result?; + let this = this.unwrap(); + + register_drag_drop(&this)?; + set_non_rude_hwnd(hwnd, true); + configure_dwm_dark_mode(hwnd, appearance); + this.state.border_offset.update(hwnd)?; + let placement = + retrieve_window_placement(hwnd, display, params.bounds, &this.state.border_offset)?; + if params.show { + let mut placement = placement; + if !params.focus { + placement.showCmd = SW_SHOWNOACTIVATE.0 as u32; + } + unsafe { SetWindowPlacement(hwnd, &placement)? }; + } else { + this.state.initial_placement.set(Some(WindowOpenStatus { + placement, + state: WindowOpenState::Windowed, + })); + } + + Ok(Self(this)) + } +} + +impl rwh::HasWindowHandle for WindowsWindow { + fn window_handle(&self) -> std::result::Result, rwh::HandleError> { + let raw = rwh::Win32WindowHandle::new(unsafe { + NonZeroIsize::new_unchecked(self.0.hwnd.0 as isize) + }) + .into(); + Ok(unsafe { rwh::WindowHandle::borrow_raw(raw) }) + } +} + +impl rwh::HasDisplayHandle for WindowsWindow { + fn display_handle(&self) -> std::result::Result, rwh::HandleError> { + Ok(rwh::DisplayHandle::windows()) + } +} + +impl Drop for WindowsWindow { + fn drop(&mut self) { + self.0.dialog_owner.close(); + unsafe { ShowWindowAsync(self.0.hwnd, SW_HIDE).ok().log_err() }; + // `DestroyWindow` below sends `WM_SHOWWINDOW`; without a callback the + // resulting visibility report has nothing to notify. + self.0.state.callbacks.visibility_change.take(); + // clone this `Rc` to prevent early release of the pointer + let this = self.0.clone(); + self.0 + .executor + .spawn(async move { + this.dialog_owner.when_idle().await; + let handle = this.hwnd; + unsafe { + RevokeDragDrop(handle).log_err(); + DestroyWindow(handle).log_err(); + } + }) + .detach(); + } +} + +impl PlatformWindow for WindowsWindow { + fn bounds(&self) -> Bounds { + self.state.bounds() + } + + fn is_maximized(&self) -> bool { + self.state.is_maximized() + } + + fn window_bounds(&self) -> WindowBounds { + self.state.window_bounds() + } + + /// get the logical size of the app's drawable area. + /// + /// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as + /// whether the mouse collides with other elements of GPUI). + fn content_size(&self) -> Size { + self.state.content_size() + } + + fn resize(&mut self, size: Size) { + let hwnd = self.0.hwnd; + let bounds = gpui::bounds(self.bounds().origin, size).to_device_pixels(self.scale_factor()); + let rect = calculate_window_rect(bounds, &self.state.border_offset); + + self.0 + .executor + .spawn(async move { + unsafe { + SetWindowPos( + hwnd, + None, + bounds.origin.x.0, + bounds.origin.y.0, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOMOVE, + ) + .context("unable to set window content size") + .log_err(); + } + }) + .detach(); + } + + fn scale_factor(&self) -> f32 { + self.state.scale_factor.get() + } + + fn appearance(&self) -> WindowAppearance { + self.state.appearance.get() + } + + fn display(&self) -> Option> { + Some(Rc::new(self.state.display.get())) + } + + fn mouse_position(&self) -> Point { + let scale_factor = self.scale_factor(); + let point = unsafe { + let mut point: POINT = std::mem::zeroed(); + GetCursorPos(&mut point) + .context("unable to get cursor position") + .log_err(); + ScreenToClient(self.0.hwnd, &mut point).ok().log_err(); + point + }; + logical_point(point.x as f32, point.y as f32, scale_factor) + } + + fn modifiers(&self) -> Modifiers { + current_modifiers() + } + + fn capslock(&self) -> Capslock { + current_capslock() + } + + fn set_input_handler(&mut self, input_handler: PlatformInputHandler) { + self.state.input_handler.set(Some(input_handler)); + } + + fn take_input_handler(&mut self) -> Option { + self.state.input_handler.take() + } + + fn prompt( + &self, + level: PromptLevel, + msg: &str, + detail: Option<&str>, + answers: &[PromptButton], + ) -> Option> { + let (mut done_tx, done_rx) = oneshot::channel(); + let msg = msg.to_string(); + let detail_string = detail.map(|detail| detail.to_string()); + let answers = answers.to_vec(); + let dialog = crate::dialog::show_dialog( + Some(self.0.dialog_owner.clone()), + &self.0.executor, + move |handle| { + unsafe { + let mut config = TASKDIALOGCONFIG::default(); + config.cbSize = std::mem::size_of::() as _; + config.hwndParent = handle; + config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION; + let title; + let main_icon; + match level { + PromptLevel::Info => { + title = windows::core::w!("Info"); + main_icon = TD_INFORMATION_ICON; + } + PromptLevel::Warning => { + title = windows::core::w!("Warning"); + main_icon = TD_WARNING_ICON; + } + PromptLevel::Critical => { + title = windows::core::w!("Critical"); + main_icon = TD_ERROR_ICON; + } + }; + config.pszWindowTitle = title; + config.Anonymous1.pszMainIcon = main_icon; + let instruction = HSTRING::from(msg); + config.pszMainInstruction = PCWSTR::from_raw(instruction.as_ptr()); + let hints_encoded; + if let Some(ref hints) = detail_string { + hints_encoded = HSTRING::from(hints); + config.pszContent = PCWSTR::from_raw(hints_encoded.as_ptr()); + }; + let mut button_id_map = Vec::with_capacity(answers.len()); + let mut buttons = Vec::new(); + let mut btn_encoded = Vec::new(); + for (index, btn) in answers.iter().enumerate() { + let encoded = HSTRING::from(btn.label().as_ref()); + let button_id = match btn { + PromptButton::Ok(_) => IDOK.0, + PromptButton::Cancel(_) => IDCANCEL.0, + // the first few low integer values are reserved for known buttons + // so for simplicity we just go backwards from -1 + PromptButton::Other(_) => -(index as i32) - 1, + }; + button_id_map.push(button_id); + buttons.push(TASKDIALOG_BUTTON { + nButtonID: button_id, + pszButtonText: PCWSTR::from_raw(encoded.as_ptr()), + }); + btn_encoded.push(encoded); + } + config.cButtons = buttons.len() as _; + config.pButtons = buttons.as_ptr(); + + config.pfCallback = Some(crate::dialog::task_dialog_callback); + config.lpCallbackData = button_id_map.contains(&IDCANCEL.0) as isize; + let mut res = std::mem::zeroed(); + TaskDialogIndirect(&config, Some(&mut res), None, None) + .context("unable to create task dialog")?; + Ok(button_id_map.iter().position(|&button_id| button_id == res)) + } + }, + ); + self.0 + .executor + .spawn(async move { + if let futures::future::Either::Left((result, _)) = + futures::future::select(dialog, done_tx.cancellation()).await + && let Some(Some(clicked)) = result + .context("native dialog thread stopped") + .and_then(|result| result) + .log_err() + { + done_tx.send(clicked).ok(); + } + }) + .detach(); + + Some(done_rx) + } + + fn activate(&self) { + let hwnd = self.0.hwnd; + let this = self.0.clone(); + self.0 + .executor + .spawn(async move { + this.set_window_placement().log_err(); + + unsafe { + // If the window is minimized, restore it. + if IsIconic(hwnd).as_bool() { + ShowWindowAsync(hwnd, SW_RESTORE).ok().log_err(); + } + + SetActiveWindow(hwnd).ok(); + SetFocus(Some(hwnd)).ok(); + } + + // premium ragebait by windows, this is needed because the window + // must have received an input event to be able to set itself to foreground + // so let's just simulate user input as that seems to be the most reliable way + // some more info: https://gist.github.com/Aetopia/1581b40f00cc0cadc93a0e8ccb65dc8c + // bonus: this bug also doesn't manifest if you have vs attached to the process + let inputs = [ + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: VK_MENU, + dwFlags: KEYBD_EVENT_FLAGS(0), + ..Default::default() + }, + }, + }, + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: VK_MENU, + dwFlags: KEYEVENTF_KEYUP, + ..Default::default() + }, + }, + }, + ]; + unsafe { SendInput(&inputs, std::mem::size_of::() as i32) }; + + // todo(windows) + // crate `windows 0.56` reports true as Err + unsafe { SetForegroundWindow(hwnd).as_bool() }; + }) + .detach(); + } + + fn request_attention(&self) { + if self.is_active() { + return; + } + + let hwnd = self.0.hwnd; + self.0 + .executor + .spawn(async move { + let info = FLASHWINFO { + cbSize: std::mem::size_of::() as u32, + hwnd, + dwFlags: FLASHW_ALL, + uCount: 1, + dwTimeout: 0, + }; + unsafe { FlashWindowEx(&info).ok().log_err() }; + }) + .detach(); + } + + fn is_active(&self) -> bool { + self.0.hwnd == unsafe { GetActiveWindow() } + } + + fn visibility(&self) -> WindowVisibility { + self.0.visibility() + } + + fn is_hovered(&self) -> bool { + self.state.hovered.get() + } + + fn background_appearance(&self) -> WindowBackgroundAppearance { + self.state.background_appearance.get() + } + + fn is_subpixel_rendering_supported(&self) -> bool { + true + } + + fn set_title(&mut self, title: &str) { + unsafe { SetWindowTextW(self.0.hwnd, &HSTRING::from(title)) } + .inspect_err(|e| log::error!("Set title failed: {e}")) + .ok(); + } + + fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) { + self.state.background_appearance.set(background_appearance); + let hwnd = self.0.hwnd; + + // using Dwm APIs for Mica and MicaAlt backdrops. + // others follow the set_window_composition_attribute approach + match background_appearance { + WindowBackgroundAppearance::Opaque => { + set_window_composition_attribute(hwnd, None, 0); + } + WindowBackgroundAppearance::Transparent => { + set_window_composition_attribute(hwnd, None, 2); + } + WindowBackgroundAppearance::Blurred => { + set_window_composition_attribute(hwnd, Some((0, 0, 0, 0)), 4); + } + WindowBackgroundAppearance::MicaBackdrop => { + // DWMSBT_MAINWINDOW => MicaBase + dwm_set_window_composition_attribute(hwnd, 2); + } + WindowBackgroundAppearance::MicaAltBackdrop => { + // DWMSBT_TABBEDWINDOW => MicaAlt + dwm_set_window_composition_attribute(hwnd, 4); + } + } + } + + fn minimize(&self) { + unsafe { ShowWindowAsync(self.0.hwnd, SW_MINIMIZE).ok().log_err() }; + } + + fn zoom(&self) { + unsafe { + if IsWindowVisible(self.0.hwnd).as_bool() { + ShowWindowAsync(self.0.hwnd, SW_MAXIMIZE).ok().log_err(); + } else if let Some(mut status) = self.state.initial_placement.take() { + status.state = WindowOpenState::Maximized; + self.state.initial_placement.set(Some(status)); + } + } + } + + fn toggle_fullscreen(&self) { + if unsafe { IsWindowVisible(self.0.hwnd).as_bool() } { + self.0.toggle_fullscreen(); + } else if let Some(mut status) = self.state.initial_placement.take() { + status.state = WindowOpenState::Fullscreen; + self.state.initial_placement.set(Some(status)); + } + } + + fn is_fullscreen(&self) -> bool { + self.state.is_fullscreen() + } + + fn on_request_frame(&self, callback: Box) { + self.state.callbacks.request_frame.set(Some(callback)); + } + + fn on_input(&self, callback: Box DispatchEventResult>) { + self.state.callbacks.input.set(Some(callback)); + } + + fn on_active_status_change(&self, callback: Box) { + self.0 + .state + .callbacks + .active_status_change + .set(Some(callback)); + } + + fn on_visibility_change(&self, callback: Box) { + self.0.state.last_visibility.set(Some(self.0.visibility())); + self.0.state.callbacks.visibility_change.set(Some(callback)); + } + + fn on_hover_status_change(&self, callback: Box) { + self.0 + .state + .callbacks + .hovered_status_change + .set(Some(callback)); + } + + fn on_resize(&self, callback: Box, f32)>) { + self.state.callbacks.resize.set(Some(callback)); + } + + fn on_moved(&self, callback: Box) { + self.state.callbacks.moved.set(Some(callback)); + } + + fn on_should_close(&self, callback: Box bool>) { + self.state.callbacks.should_close.set(Some(callback)); + } + + fn on_close(&self, callback: Box) { + self.state.callbacks.close.set(Some(callback)); + } + + fn on_hit_test_window_control(&self, callback: Box Option>) { + self.0 + .state + .callbacks + .hit_test_window_control + .set(Some(callback)); + } + + fn on_appearance_changed(&self, callback: Box) { + self.0 + .state + .callbacks + .appearance_changed + .set(Some(callback)); + } + + fn draw(&self, scene: &Scene) { + self.state + .renderer + .borrow_mut() + .draw(scene, self.state.background_appearance.get()) + .log_err(); + } + + #[cfg(any(test, feature = "test-support"))] + fn render_to_image(&self, scene: &Scene) -> anyhow::Result { + self.state + .renderer + .borrow_mut() + .render_to_image(scene, self.state.background_appearance.get()) + } + + fn sprite_atlas(&self) -> Arc { + self.state.renderer.borrow().sprite_atlas() + } + + fn get_raw_handle(&self) -> HWND { + self.0.hwnd + } + + fn gpu_specs(&self) -> Option { + self.state.renderer.borrow().gpu_specs().log_err() + } + + fn update_ime_position(&self, bounds: Bounds) { + let scale_factor = self.state.scale_factor.get(); + let caret_position = POINT { + x: (bounds.origin.x.as_f32() * scale_factor) as i32, + y: (bounds.origin.y.as_f32() * scale_factor) as i32 + + ((bounds.size.height.as_f32() * scale_factor) as i32 / 2), + }; + + self.0.update_ime_position(self.0.hwnd, caret_position); + } + + fn play_system_bell(&self) { + // MB_OK: The sound specified as the Windows Default Beep sound. + let _ = unsafe { MessageBeep(MB_OK) }; + } + + fn a11y_init(&self, callbacks: gpui::A11yCallbacks) { + let action_handler = A11yActionHandler(callbacks.action); + let is_focused = unsafe { GetForegroundWindow() } == self.0.hwnd; + + let adapter = accesskit_windows::Adapter::new( + accesskit_windows::HWND(self.0.hwnd.0), + is_focused, + action_handler, + ); + + let activation_handler = A11yActivationHandler { + callback: callbacks.activation, + }; + + *self.state.a11y.borrow_mut() = Some(A11yState { + adapter, + activation_handler, + }); + } + + fn a11y_tree_update(&self, tree_update: accesskit::TreeUpdate) { + let events = { + let mut a11y = self.state.a11y.borrow_mut(); + a11y.as_mut() + .and_then(|a11y| a11y.adapter.update_if_active(|| tree_update)) + }; + // The borrow must be dropped before raising events, because + // `events.raise()` calls `UiaRaiseAutomationPropertyChangedEvent` + // which may send a nested `WM_GETOBJECT` back into this window + // procedure, re-entering `handle_wm_getobject` which also borrows + // `self.state.a11y`. + if let Some(events) = events { + events.raise(); + } + } + + fn a11y_update_window_bounds(&self) { + // Windows UIA handles window bounds tracking automatically. + } +} + +pub(crate) struct A11yState { + pub(crate) adapter: accesskit_windows::Adapter, + pub(crate) activation_handler: A11yActivationHandler, +} + +pub(crate) struct A11yActivationHandler { + callback: Box Option + Send + 'static>, +} + +impl accesskit::ActivationHandler for A11yActivationHandler { + fn request_initial_tree(&mut self) -> Option { + (self.callback)() + } +} + +struct A11yActionHandler(Box); + +impl accesskit::ActionHandler for A11yActionHandler { + fn do_action(&mut self, request: accesskit::ActionRequest) { + (self.0)(request); + } +} + +#[implement(IDropTarget)] +struct WindowsDragDropHandler(pub Rc); + +impl WindowsDragDropHandler { + fn handle_drag_drop(&self, input: PlatformInput) { + if let Some(mut func) = self.0.state.callbacks.input.take() { + func(input); + self.0.state.callbacks.input.set(Some(func)); + } + } +} + +#[allow(non_snake_case)] +impl IDropTarget_Impl for WindowsDragDropHandler_Impl { + fn DragEnter( + &self, + pdataobj: windows::core::Ref, + _grfkeystate: MODIFIERKEYS_FLAGS, + pt: &POINTL, + pdweffect: *mut DROPEFFECT, + ) -> windows::core::Result<()> { + unsafe { + let idata_obj = pdataobj.ok()?; + let config = FORMATETC { + cfFormat: CF_HDROP.0, + ptd: std::ptr::null_mut() as _, + dwAspect: DVASPECT_CONTENT.0, + lindex: -1, + tymed: TYMED_HGLOBAL.0 as _, + }; + let cursor_position = POINT { x: pt.x, y: pt.y }; + if idata_obj.QueryGetData(&config as _) == S_OK { + *pdweffect = DROPEFFECT_COPY; + let Some(mut idata) = idata_obj.GetData(&config as _).log_err() else { + return Ok(()); + }; + if idata.u.hGlobal.is_invalid() { + return Ok(()); + } + let hdrop = HDROP(idata.u.hGlobal.0); + let mut paths = SmallVec::<[PathBuf; 2]>::new(); + with_file_names(hdrop, |file_name| { + if let Some(path) = PathBuf::from_str(&file_name).log_err() { + paths.push(path); + } + }); + ReleaseStgMedium(&mut idata); + let mut cursor_position = cursor_position; + ScreenToClient(self.0.hwnd, &mut cursor_position) + .ok() + .log_err(); + let scale_factor = self.0.state.scale_factor.get(); + let input = PlatformInput::FileDrop(FileDropEvent::Entered { + position: logical_point( + cursor_position.x as f32, + cursor_position.y as f32, + scale_factor, + ), + paths: ExternalPaths(paths), + }); + self.handle_drag_drop(input); + } else { + *pdweffect = DROPEFFECT_NONE; + } + self.0 + .drop_target_helper + .DragEnter(self.0.hwnd, idata_obj, &cursor_position, *pdweffect) + .log_err(); + } + Ok(()) + } + + fn DragOver( + &self, + _grfkeystate: MODIFIERKEYS_FLAGS, + pt: &POINTL, + pdweffect: *mut DROPEFFECT, + ) -> windows::core::Result<()> { + let mut cursor_position = POINT { x: pt.x, y: pt.y }; + unsafe { + *pdweffect = DROPEFFECT_COPY; + self.0 + .drop_target_helper + .DragOver(&cursor_position, *pdweffect) + .log_err(); + ScreenToClient(self.0.hwnd, &mut cursor_position) + .ok() + .log_err(); + } + let scale_factor = self.0.state.scale_factor.get(); + let input = PlatformInput::FileDrop(FileDropEvent::Pending { + position: logical_point( + cursor_position.x as f32, + cursor_position.y as f32, + scale_factor, + ), + }); + self.handle_drag_drop(input); + + Ok(()) + } + + fn DragLeave(&self) -> windows::core::Result<()> { + unsafe { + self.0.drop_target_helper.DragLeave().log_err(); + } + let input = PlatformInput::FileDrop(FileDropEvent::Exited); + self.handle_drag_drop(input); + + Ok(()) + } + + fn Drop( + &self, + pdataobj: windows::core::Ref, + _grfkeystate: MODIFIERKEYS_FLAGS, + pt: &POINTL, + pdweffect: *mut DROPEFFECT, + ) -> windows::core::Result<()> { + let idata_obj = pdataobj.ok()?; + let mut cursor_position = POINT { x: pt.x, y: pt.y }; + unsafe { + *pdweffect = DROPEFFECT_COPY; + self.0 + .drop_target_helper + .Drop(idata_obj, &cursor_position, *pdweffect) + .log_err(); + ScreenToClient(self.0.hwnd, &mut cursor_position) + .ok() + .log_err(); + } + let scale_factor = self.0.state.scale_factor.get(); + let input = PlatformInput::FileDrop(FileDropEvent::Submit { + position: logical_point( + cursor_position.x as f32, + cursor_position.y as f32, + scale_factor, + ), + }); + self.handle_drag_drop(input); + + Ok(()) + } +} + +#[derive(Debug, Clone)] +pub(crate) struct ClickState { + button: Cell, + last_click: Cell, + last_position: Cell>, + double_click_spatial_tolerance_width: Cell, + double_click_spatial_tolerance_height: Cell, + double_click_interval: Cell, + pub(crate) current_count: Cell, +} + +impl ClickState { + pub fn new() -> Self { + let double_click_spatial_tolerance_width = unsafe { GetSystemMetrics(SM_CXDOUBLECLK) }; + let double_click_spatial_tolerance_height = unsafe { GetSystemMetrics(SM_CYDOUBLECLK) }; + let double_click_interval = Duration::from_millis(unsafe { GetDoubleClickTime() } as u64); + + ClickState { + button: Cell::new(MouseButton::Left), + last_click: Cell::new(Instant::now()), + last_position: Cell::new(Point::default()), + double_click_spatial_tolerance_width: Cell::new(double_click_spatial_tolerance_width), + double_click_spatial_tolerance_height: Cell::new(double_click_spatial_tolerance_height), + double_click_interval: Cell::new(double_click_interval), + current_count: Cell::new(0), + } + } + + /// update self and return the needed click count + pub fn update(&self, button: MouseButton, new_position: Point) -> usize { + if self.button.get() == button && self.is_double_click(new_position) { + self.current_count.update(|it| it + 1); + } else { + self.current_count.set(1); + } + self.last_click.set(Instant::now()); + self.last_position.set(new_position); + self.button.set(button); + + self.current_count.get() + } + + pub fn system_update(&self, wparam: usize) { + match wparam { + // SPI_SETDOUBLECLKWIDTH + 29 => self + .double_click_spatial_tolerance_width + .set(unsafe { GetSystemMetrics(SM_CXDOUBLECLK) }), + // SPI_SETDOUBLECLKHEIGHT + 30 => self + .double_click_spatial_tolerance_height + .set(unsafe { GetSystemMetrics(SM_CYDOUBLECLK) }), + // SPI_SETDOUBLECLICKTIME + 32 => self + .double_click_interval + .set(Duration::from_millis(unsafe { GetDoubleClickTime() } as u64)), + _ => {} + } + } + + #[inline] + fn is_double_click(&self, new_position: Point) -> bool { + let diff = self.last_position.get() - new_position; + + self.last_click.get().elapsed() < self.double_click_interval.get() + && diff.x.0.abs() <= self.double_click_spatial_tolerance_width.get() + && diff.y.0.abs() <= self.double_click_spatial_tolerance_height.get() + } +} + +#[derive(Copy, Clone)] +struct StyleAndBounds { + style: WINDOW_STYLE, + x: i32, + y: i32, + cx: i32, + cy: i32, +} + +#[repr(C)] +struct WINDOWCOMPOSITIONATTRIBDATA { + attrib: u32, + pv_data: *mut std::ffi::c_void, + cb_data: usize, +} + +#[repr(C)] +struct AccentPolicy { + accent_state: u32, + accent_flags: u32, + gradient_color: u32, + animation_id: u32, +} + +type Color = (u8, u8, u8, u8); + +#[derive(Debug, Default, Clone)] +pub(crate) struct WindowBorderOffset { + pub(crate) width_offset: Cell, + pub(crate) height_offset: Cell, +} + +impl WindowBorderOffset { + pub(crate) fn update(&self, hwnd: HWND) -> anyhow::Result<()> { + let window_rect = unsafe { + let mut rect = std::mem::zeroed(); + GetWindowRect(hwnd, &mut rect)?; + rect + }; + let client_rect = unsafe { + let mut rect = std::mem::zeroed(); + GetClientRect(hwnd, &mut rect)?; + rect + }; + self.width_offset + .set((window_rect.right - window_rect.left) - (client_rect.right - client_rect.left)); + self.height_offset + .set((window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top)); + Ok(()) + } +} + +#[derive(Clone)] +struct WindowOpenStatus { + placement: WINDOWPLACEMENT, + state: WindowOpenState, +} + +#[derive(Clone, Copy)] +enum WindowOpenState { + Maximized, + Fullscreen, + Windowed, +} + +const WINDOW_CLASS_NAME: PCWSTR = w!("Zed::Window"); + +fn register_window_class(icon_handle: HICON) { + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + let wc = WNDCLASSW { + lpfnWndProc: Some(window_procedure), + hIcon: icon_handle, + lpszClassName: PCWSTR(WINDOW_CLASS_NAME.as_ptr()), + style: CS_HREDRAW | CS_VREDRAW, + hInstance: get_module_handle().into(), + hbrBackground: unsafe { CreateSolidBrush(COLORREF(0x00000000)) }, + ..Default::default() + }; + unsafe { RegisterClassW(&wc) }; + }); +} + +unsafe extern "system" fn window_procedure( + hwnd: HWND, + msg: u32, + wparam: WPARAM, + lparam: LPARAM, +) -> LRESULT { + if msg == WM_NCCREATE { + let window_params = unsafe { &*(lparam.0 as *const CREATESTRUCTW) }; + let window_creation_context = window_params.lpCreateParams as *mut WindowCreateContext; + let window_creation_context = unsafe { &mut *window_creation_context }; + return match WindowsWindowInner::new(window_creation_context, hwnd, window_params) { + Ok(window_state) => { + let weak = Box::new(Rc::downgrade(&window_state)); + unsafe { set_window_long(hwnd, GWLP_USERDATA, Box::into_raw(weak) as isize) }; + window_creation_context.inner = Some(Ok(window_state)); + unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) } + } + Err(error) => { + window_creation_context.inner = Some(Err(error)); + LRESULT(0) + } + }; + } + + let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak; + if ptr.is_null() { + return unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) }; + } + let inner = unsafe { &*ptr }; + let result = if let Some(inner) = inner.upgrade() { + if msg == WM_NCDESTROY { + inner.dialog_owner.close(); + } + inner.handle_msg(hwnd, msg, wparam, lparam) + } else { + unsafe { DefWindowProcW(hwnd, msg, wparam, lparam) } + }; + + if msg == WM_NCDESTROY { + unsafe { set_window_long(hwnd, GWLP_USERDATA, 0) }; + unsafe { drop(Box::from_raw(ptr)) }; + } + + result +} + +pub(crate) fn window_from_hwnd(hwnd: HWND) -> Option> { + if hwnd.is_invalid() { + return None; + } + + let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak; + if !ptr.is_null() { + let inner = unsafe { &*ptr }; + inner.upgrade() + } else { + None + } +} + +fn get_module_handle() -> HMODULE { + unsafe { + let mut h_module = std::mem::zeroed(); + GetModuleHandleExW( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + windows::core::w!("ZedModule"), + &mut h_module, + ) + .expect("Unable to get module handle"); // this should never fail + + h_module + } +} + +fn register_drag_drop(window: &Rc) -> Result<()> { + let window_handle = window.hwnd; + let handler = WindowsDragDropHandler(window.clone()); + // The lifetime of `IDropTarget` is handled by Windows, it won't release until + // we call `RevokeDragDrop`. + // So, it's safe to drop it here. + let drag_drop_handler: IDropTarget = handler.into(); + unsafe { + RegisterDragDrop(window_handle, &drag_drop_handler) + .context("unable to register drag-drop event")?; + } + Ok(()) +} + +fn calculate_window_rect(bounds: Bounds, border_offset: &WindowBorderOffset) -> RECT { + // NOTE: + // The reason we're not using `AdjustWindowRectEx()` here is + // that the size reported by this function is incorrect. + // You can test it, and there are similar discussions online. + // See: https://stackoverflow.com/questions/12423584/how-to-set-exact-client-size-for-overlapped-window-winapi + // + // So we manually calculate these values here. + let mut rect = RECT { + left: bounds.left().0, + top: bounds.top().0, + right: bounds.right().0, + bottom: bounds.bottom().0, + }; + let left_offset = border_offset.width_offset.get() / 2; + let top_offset = border_offset.height_offset.get() / 2; + let right_offset = border_offset.width_offset.get() - left_offset; + let bottom_offset = border_offset.height_offset.get() - top_offset; + rect.left -= left_offset; + rect.top -= top_offset; + rect.right += right_offset; + rect.bottom += bottom_offset; + rect +} + +fn calculate_client_rect( + rect: RECT, + border_offset: &WindowBorderOffset, + scale_factor: f32, +) -> Bounds { + let left_offset = border_offset.width_offset.get() / 2; + let top_offset = border_offset.height_offset.get() / 2; + let right_offset = border_offset.width_offset.get() - left_offset; + let bottom_offset = border_offset.height_offset.get() - top_offset; + let left = rect.left + left_offset; + let top = rect.top + top_offset; + let right = rect.right - right_offset; + let bottom = rect.bottom - bottom_offset; + let physical_size = size(DevicePixels(right - left), DevicePixels(bottom - top)); + Bounds { + origin: logical_point(left as f32, top as f32, scale_factor), + size: physical_size.to_pixels(scale_factor), + } +} + +fn retrieve_window_placement( + hwnd: HWND, + display: WindowsDisplay, + initial_bounds: Bounds, + border_offset: &WindowBorderOffset, +) -> Result { + let mut placement = WINDOWPLACEMENT { + length: std::mem::size_of::() as u32, + ..Default::default() + }; + unsafe { GetWindowPlacement(hwnd, &mut placement)? }; + // the bounds may be not inside the display + let bounds = if display.check_given_bounds(initial_bounds) { + initial_bounds + } else { + display.default_bounds() + }; + // `bounds` is expressed in logical pixels for `display`, so it must be converted + // to device pixels using that display's own scale factor. The window's current + // scale factor can't be used here: `CreateWindowExW` was called with + // `CW_USEDEFAULT`, so at this point the window may still be sitting on whichever + // monitor Windows picked by default, which can have a different DPI than `display` + // and would otherwise throw off the physical position (e.g. leaving the window + // partially off-screen when moved to a monitor with a different scale factor). + let bounds = bounds.to_device_pixels(display.scale_factor()); + placement.rcNormalPosition = calculate_window_rect(bounds, border_offset); + Ok(placement) +} + +fn dwm_set_window_composition_attribute(hwnd: HWND, backdrop_type: u32) { + let mut version = unsafe { std::mem::zeroed() }; + let status = unsafe { windows::Wdk::System::SystemServices::RtlGetVersion(&mut version) }; + + // DWMWA_SYSTEMBACKDROP_TYPE is available only on version 22621 or later + // using SetWindowCompositionAttributeType as a fallback + if !status.is_ok() || version.dwBuildNumber < 22621 { + return; + } + + unsafe { + let result = DwmSetWindowAttribute( + hwnd, + DWMWA_SYSTEMBACKDROP_TYPE, + &backdrop_type as *const _ as *const _, + std::mem::size_of_val(&backdrop_type) as u32, + ); + + if !result.is_ok() { + return; + } + } +} + +fn set_window_composition_attribute(hwnd: HWND, color: Option, state: u32) { + let mut version = unsafe { std::mem::zeroed() }; + let status = unsafe { windows::Wdk::System::SystemServices::RtlGetVersion(&mut version) }; + + if !status.is_ok() || version.dwBuildNumber < 17763 { + return; + } + + unsafe { + type SetWindowCompositionAttributeType = + unsafe extern "system" fn(HWND, *mut WINDOWCOMPOSITIONATTRIBDATA) -> BOOL; + let module_name = PCSTR::from_raw(c"user32.dll".as_ptr() as *const u8); + if let Some(user32) = GetModuleHandleA(module_name) + .context("Unable to get user32.dll handle") + .log_err() + { + let func_name = PCSTR::from_raw(c"SetWindowCompositionAttribute".as_ptr() as *const u8); + let Some(raw_set_window_composition_attribute) = GetProcAddress(user32, func_name) + else { + return; + }; + let set_window_composition_attribute: SetWindowCompositionAttributeType = + std::mem::transmute(raw_set_window_composition_attribute); + let mut color = color.unwrap_or_default(); + let is_acrylic = state == 4; + if is_acrylic && color.3 == 0 { + color.3 = 1; + } + let accent = AccentPolicy { + accent_state: state, + accent_flags: if is_acrylic { 0 } else { 2 }, + gradient_color: (color.0 as u32) + | ((color.1 as u32) << 8) + | ((color.2 as u32) << 16) + | ((color.3 as u32) << 24), + animation_id: 0, + }; + let mut data = WINDOWCOMPOSITIONATTRIBDATA { + attrib: 0x13, + pv_data: &accent as *const _ as *mut _, + cb_data: std::mem::size_of::(), + }; + let _ = set_window_composition_attribute(hwnd, &mut data as *mut _ as _); + } + } +} + +// When the platform title bar is hidden, Windows may think that our application is meant to appear 'fullscreen' +// and will stop the taskbar from appearing on top of our window. Prevent this. +// https://devblogs.microsoft.com/oldnewthing/20250522-00/?p=111211 +fn set_non_rude_hwnd(hwnd: HWND, non_rude: bool) { + if non_rude { + unsafe { SetPropW(hwnd, w!("NonRudeHWND"), Some(HANDLE(1 as _))) }.log_err(); + } else { + unsafe { RemovePropW(hwnd, w!("NonRudeHWND")) }.log_err(); + } +} + +#[cfg(test)] +mod tests { + use super::ClickState; + use gpui::{DevicePixels, MouseButton, point}; + use std::time::Duration; + + #[test] + fn test_double_click_interval() { + let state = ClickState::new(); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))), + 1 + ); + assert_eq!( + state.update(MouseButton::Right, point(DevicePixels(0), DevicePixels(0))), + 1 + ); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))), + 1 + ); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))), + 2 + ); + state + .last_click + .update(|it| it - Duration::from_millis(700)); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))), + 1 + ); + } + + #[test] + fn test_double_click_spatial_tolerance() { + let state = ClickState::new(); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(-3), DevicePixels(0))), + 1 + ); + assert_eq!( + state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(3))), + 2 + ); + assert_eq!( + state.update(MouseButton::Right, point(DevicePixels(3), DevicePixels(2))), + 1 + ); + assert_eq!( + state.update(MouseButton::Right, point(DevicePixels(10), DevicePixels(0))), + 1 + ); + } +} diff --git a/vendor/gpui-pre-windows/src/wrapper.rs b/vendor/gpui-pre-windows/src/wrapper.rs new file mode 100644 index 00000000..60bbc433 --- /dev/null +++ b/vendor/gpui-pre-windows/src/wrapper.rs @@ -0,0 +1,53 @@ +use std::ops::Deref; + +use windows::Win32::{Foundation::HWND, UI::WindowsAndMessaging::HCURSOR}; + +#[derive(Debug, Clone, Copy)] +pub(crate) struct SafeCursor { + raw: HCURSOR, +} + +unsafe impl Send for SafeCursor {} +unsafe impl Sync for SafeCursor {} + +impl From for SafeCursor { + fn from(value: HCURSOR) -> Self { + SafeCursor { raw: value } + } +} + +impl Deref for SafeCursor { + type Target = HCURSOR; + + fn deref(&self) -> &Self::Target { + &self.raw + } +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct SafeHwnd { + raw: HWND, +} + +impl SafeHwnd { + pub(crate) fn as_raw(&self) -> HWND { + self.raw + } +} + +unsafe impl Send for SafeHwnd {} +unsafe impl Sync for SafeHwnd {} + +impl From for SafeHwnd { + fn from(value: HWND) -> Self { + SafeHwnd { raw: value } + } +} + +impl Deref for SafeHwnd { + type Target = HWND; + + fn deref(&self) -> &Self::Target { + &self.raw + } +} diff --git a/vendor/gpui-pre/Cargo.toml b/vendor/gpui-pre/Cargo.toml new file mode 100644 index 00000000..a7cc7f85 --- /dev/null +++ b/vendor/gpui-pre/Cargo.toml @@ -0,0 +1,683 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +name = "gpui-pre" +version = "0.3.8" +authors = ["Nathan Sobo "] +build = "build.rs" +publish = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Zed's GPU-accelerated UI framework (gpui-pre snapshot of zed@279fe07)" +homepage = "https://gpui.rs" +readme = "README.md" +keywords = [ + "desktop", + "gui", + "immediate", +] +categories = ["gui"] +license = "Apache-2.0" +repository = "https://github.com/zed-industries/zed" +resolver = "2" + +[package.metadata.cargo-shear] +ignored = [ + "bindgen", + "font-kit", + "getrandom", + "objc2", + "objc2-metal", +] +ignored-paths = ["src/_ownership_and_data_flow.rs"] + +[package.metadata.gpui-pre] +zed-crate = "gpui" +zed-version = "0.2.2" +zed-rev = "279fe070bb389b79652e52065b2f001edcc0b11b" + +[features] +bench = ["bench-support"] +bench-support = [ + "profiler", + "dep:criterion", + "dep:bench_metrics", +] +default = [ + "font-kit", + "wayland", + "x11", + "windows-manifest", +] +inspector = ["gpui_macros/inspector"] +leak-detection = [] +profiler = ["dep:hdrhistogram"] +screen-capture = ["scap"] +stacker = ["dep:stacksafe"] +test-support = [ + "collections/test-support", + "http_client/test-support", + "wayland", + "x11", + "proptest", +] +wayland = [] +windows-manifest = ["dep:embed-resource"] +x11 = ["scap?/x11"] + +[lib] +name = "gpui" +path = "src/gpui.rs" + +[[example]] +name = "a11y" +path = "examples/a11y.rs" + +[[example]] +name = "active_state_bug" +path = "examples/active_state_bug.rs" + +[[example]] +name = "anchor" +path = "examples/anchor.rs" + +[[example]] +name = "animation" +path = "examples/animation.rs" + +[[example]] +name = "data_table" +path = "examples/data_table.rs" + +[[example]] +name = "drag_drop" +path = "examples/drag_drop.rs" + +[[example]] +name = "focus_visible" +path = "examples/focus_visible.rs" + +[[example]] +name = "gif_viewer" +path = "examples/gif_viewer.rs" + +[[example]] +name = "gradient" +path = "examples/gradient.rs" + +[[example]] +name = "grid_layout" +path = "examples/grid_layout.rs" + +[[example]] +name = "hello_world" +path = "examples/hello_world.rs" + +[[example]] +name = "image" +path = "examples/image/image.rs" + +[[example]] +name = "image_gallery" +path = "examples/image_gallery.rs" + +[[example]] +name = "image_loading" +path = "examples/image_loading.rs" + +[[example]] +name = "input" +path = "examples/input.rs" + +[[example]] +name = "layer_shell" +path = "examples/layer_shell.rs" + +[[example]] +name = "list_example" +path = "examples/list_example.rs" + +[[example]] +name = "mouse_pressure" +path = "examples/mouse_pressure.rs" + +[[example]] +name = "move_entity_between_windows" +path = "examples/move_entity_between_windows.rs" + +[[example]] +name = "on_window_close_quit" +path = "examples/on_window_close_quit.rs" + +[[example]] +name = "opacity" +path = "examples/opacity.rs" + +[[example]] +name = "ownership_post" +path = "examples/ownership_post.rs" + +[[example]] +name = "painting" +path = "examples/painting.rs" + +[[example]] +name = "paths_bench" +path = "examples/paths_bench.rs" + +[[example]] +name = "pattern" +path = "examples/pattern.rs" + +[[example]] +name = "popover" +path = "examples/popover.rs" + +[[example]] +name = "scrollable" +path = "examples/scrollable.rs" + +[[example]] +name = "set_menus" +path = "examples/set_menus.rs" + +[[example]] +name = "shadow" +path = "examples/shadow.rs" + +[[example]] +name = "svg" +path = "examples/svg/svg.rs" + +[[example]] +name = "system_notifications" +path = "examples/system_notifications.rs" + +[[example]] +name = "tab_stop" +path = "examples/tab_stop.rs" + +[[example]] +name = "testing" +path = "examples/testing.rs" + +[[example]] +name = "text" +path = "examples/text.rs" + +[[example]] +name = "text_layout" +path = "examples/text_layout.rs" + +[[example]] +name = "text_wrapper" +path = "examples/text_wrapper.rs" + +[[example]] +name = "toggle_headless" +path = "examples/toggle_headless.rs" + +[[example]] +name = "tree" +path = "examples/tree.rs" + +[[example]] +name = "uniform_list" +path = "examples/uniform_list.rs" + +[[example]] +name = "view_example" +path = "examples/view_example/view_example_main.rs" + +[[example]] +name = "window" +path = "examples/window.rs" + +[[example]] +name = "window_movable" +path = "examples/window_movable.rs" + +[[example]] +name = "window_positioning" +path = "examples/window_positioning.rs" + +[[example]] +name = "window_shadow" +path = "examples/window_shadow.rs" + +[[test]] +name = "action_macros" +path = "tests/action_macros.rs" + +[dependencies.accesskit] +version = "0.24.0" +features = ["enumn"] + +[dependencies.anyhow] +version = "1.0.86" + +[dependencies.async-task] +version = "4.7" + +[dependencies.backtrace] +version = "0.3" + +[dependencies.bench_metrics] +version = "=0.3.8" +optional = true +package = "gpui-pre-bench-metrics" + +[dependencies.bitflags] +version = "2.6.0" + +[dependencies.chrono] +version = "0.4" +features = ["serde"] + +[dependencies.collections] +version = "=0.3.8" +package = "gpui-pre-collections" + +[dependencies.criterion] +version = "0.8.2" +features = ["html_reports"] +optional = true + +[dependencies.ctor] +version = "1.0.12" + +[dependencies.derive_more] +version = "2.1.1" +features = [ + "add", + "add_assign", + "deref", + "deref_mut", + "display", + "from", + "from_str", + "mul", + "mul_assign", + "not", +] + +[dependencies.etagere] +version = "0.2" + +[dependencies.futures] +version = "0.3.34" + +[dependencies.futures-concurrency] +version = "7.7.1" + +[dependencies.gpui_macros] +version = "=0.3.8" +package = "gpui-pre-macros" + +[dependencies.gpui_shared_string] +version = "=0.3.8" +package = "gpui-pre-shared-string" + +[dependencies.gpui_util] +version = "=0.3.8" +package = "gpui-pre-util" + +[dependencies.hdrhistogram] +version = "7" +optional = true +default-features = false + +[dependencies.heapless] +version = "0.9.2" + +[dependencies.http_client] +version = "=0.3.8" +package = "gpui-pre-http-client" + +[dependencies.image] +version = "0.25.1" +features = [ + "bmp", + "dds", + "exr", + "ff", + "gif", + "hdr", + "ico", + "jpeg", + "png", + "pnm", + "qoi", + "rayon", + "tga", + "tiff", + "webp", +] +default-features = false + +[dependencies.inventory] +version = "0.3.19" + +[dependencies.itertools] +version = "0.14.0" + +[dependencies.log] +version = "0.4.16" +features = [ + "kv_unstable_serde", + "serde", +] + +[dependencies.lyon] +version = "1.0" + +[dependencies.num_cpus] +version = "1.13" + +[dependencies.parking] +version = "2.0.0" + +[dependencies.parking_lot] +version = "0.12.1" + +[dependencies.pin-project] +version = "1.1.10" + +[dependencies.pollster] +version = "0.4.0" + +[dependencies.postage] +version = "0.5" +features = ["futures-traits"] + +[dependencies.profiling] +version = "1" + +[dependencies.proptest] +version = "1" +features = ["attr-macro"] +optional = true +package = "proptest" + +[dependencies.rand] +version = "0.9" + +[dependencies.raw-window-handle] +version = "0.6" + +[dependencies.refineable] +version = "=0.3.8" +package = "gpui-pre-refineable" + +[dependencies.regex] +version = "1.5" + +[dependencies.resvg] +version = "0.46.0" +features = [ + "text", + "system-fonts", + "memmap-fonts", + "raster-images", +] +default-features = false + +[dependencies.scheduler] +version = "=0.3.8" +package = "gpui-pre-scheduler" + +[dependencies.schemars] +version = "1.0" +features = ["indexmap2"] + +[dependencies.seahash] +version = "4.1" + +[dependencies.serde] +version = "1.0.221" +features = [ + "derive", + "rc", +] + +[dependencies.serde_json] +version = "1.0.144" +features = [ + "preserve_order", + "raw_value", +] + +[dependencies.slotmap] +version = "1.0.6" + +[dependencies.smallvec] +version = "1.6" +features = [ + "union", + "const_new", +] + +[dependencies.spin] +version = "0.10.0" + +[dependencies.stacksafe] +version = "1.0" +optional = true + +[dependencies.strum] +version = "0.28" +features = ["derive"] + +[dependencies.sum_tree] +version = "=0.3.8" +package = "gpui-pre-sum-tree" + +[dependencies.taffy] +version = "0.13.0" + +[dependencies.thiserror] +version = "2.0.12" + +[dependencies.ttf-parser] +version = "0.25" + +[dependencies.url] +version = "2.2" + +[dependencies.usvg] +version = "0.46.0" +default-features = false + +[dependencies.util_macros] +version = "=0.3.8" +package = "gpui-pre-util-macros" + +[dependencies.uuid] +version = "1.1.2" +features = [ + "v4", + "v5", + "v7", + "serde", +] + +[dependencies.waker-fn] +version = "1.2.0" + +[dependencies.web-time] +version = "1.1.0" + +[build-dependencies.embed-resource] +version = "3.0" +optional = true + +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies.async-channel] +version = "2.5.0" +default-features = false + +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies.libc] +version = "0.2" + +[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "windows"))'.dependencies.scap] +version = "0.0.8-zed" +optional = true +default-features = false +package = "zed-scap" + +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.core-video] +version = "0.5.2" +features = ["metal"] + +[target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies.async-channel] +version = "2.5.0" + +[target.'cfg(target_family = "wasm")'.dependencies.getrandom] +version = "0.3.4" +features = ["wasm_js"] + +[target.'cfg(target_family = "wasm")'.dependencies.uuid] +version = "1.1.2" +features = [ + "v4", + "v5", + "v7", + "serde", + "js", +] + +[target.'cfg(target_os = "macos")'.dependencies.font-kit] +version = "0.14.1-zed" +optional = true +package = "zed-font-kit" + +[target.'cfg(target_os = "macos")'.dependencies.log] +version = "0.4.16" +features = [ + "kv_unstable_serde", + "serde", +] + +[target.'cfg(target_os = "macos")'.dependencies.objc2] +version = "0.6" +optional = true + +[target.'cfg(target_os = "macos")'.dependencies.objc2-core-foundation] +version = "0.3.2" +default-features = false + +[target.'cfg(target_os = "macos")'.dependencies.objc2-core-video] +version = "0.3.2" +features = [ + "CVBuffer", + "CVImageBuffer", +] +default-features = false + +[target.'cfg(target_os = "macos")'.dependencies.objc2-metal] +version = "0.3" +optional = true + +[target.'cfg(target_os = "macos")'.build-dependencies.bindgen] +version = "0.72" + +[target.'cfg(target_os = "windows")'.dependencies.windows] +version = "0.62" +features = [ + "Data_Xml_Dom", + "Foundation_Numerics", + "Globalization_DateTimeFormatting", + "Storage_Search", + "Storage_Streams", + "System_Threading", + "UI_Notifications", + "UI_ViewManagement", + "Wdk_System_SystemServices", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Direct3D", + "Win32_Graphics_Direct3D11", + "Win32_Graphics_Direct3D_Fxc", + "Win32_Graphics_DirectComposition", + "Win32_Graphics_DirectWrite", + "Win32_Graphics_DirectManipulation", + "Win32_Graphics_Dwm", + "Win32_Graphics_Dxgi", + "Win32_Graphics_Dxgi_Common", + "Win32_Graphics_Gdi", + "Win32_Graphics_Imaging", + "Win32_Graphics_Hlsl", + "Win32_Networking_WinSock", + "Win32_Security", + "Win32_Security_Credentials", + "Win32_Security_Cryptography", + "Win32_Storage_FileSystem", + "Win32_Storage_Packaging_Appx", + "Win32_System_Com", + "Win32_System_Com_StructuredStorage", + "Win32_System_Console", + "Win32_System_Diagnostics_Debug", + "Win32_System_DataExchange", + "Win32_System_IO", + "Win32_System_JobObjects", + "Win32_System_LibraryLoader", + "Win32_System_Memory", + "Win32_System_Ole", + "Win32_System_Performance", + "Win32_System_Pipes", + "Win32_System_Power", + "Win32_System_RestartManager", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_Variant", + "Win32_System_WinRT", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Shell", + "Win32_UI_Shell_Common", + "Win32_UI_Shell_PropertiesSystem", + "Win32_UI_WindowsAndMessaging", + "Win32_Media", + "Win32_Foundation", + "Win32_System_Power", + "Win32_System_RemoteDesktop", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", +] + +[lints.clippy] +dbg_macro = "deny" +declare_interior_mutable_const = "deny" +disallowed_methods = "deny" +large_enum_variant = "allow" +let_underscore_future = "allow" +nonminimal_bool = "allow" +redundant_clone = "deny" +single_range_in_vec_init = "allow" +todo = "deny" +too_many_arguments = "allow" +type_complexity = "allow" + +[lints.clippy.style] +level = "allow" +priority = -1 + +[lints.rust.unexpected_cfgs] +level = "allow" +priority = 0 diff --git a/vendor/gpui-pre/Cargo.toml.orig b/vendor/gpui-pre/Cargo.toml.orig new file mode 100644 index 00000000..2c8eb1f1 --- /dev/null +++ b/vendor/gpui-pre/Cargo.toml.orig @@ -0,0 +1,247 @@ +[package] +name = "gpui-pre" +version = "0.3.8" +edition = { workspace = true } +authors = ["Nathan Sobo "] +description = "Zed's GPU-accelerated UI framework (gpui-pre snapshot of zed@279fe07)" +repository = "https://github.com/zed-industries/zed" +publish = true +license = "Apache-2.0" +homepage = "https://gpui.rs" +readme = "README.md" +keywords = ["desktop", "gui", "immediate"] +categories = ["gui"] + +[package.metadata.cargo-shear] +ignored = ["bindgen", "font-kit", "getrandom", "objc2", "objc2-metal"] +ignored-paths = ["src/_ownership_and_data_flow.rs"] + +[package.metadata.gpui-pre] +zed-crate = "gpui" +zed-version = "0.2.2" +zed-rev = "279fe070bb389b79652e52065b2f001edcc0b11b" + +[lib] +path = "src/gpui.rs" +name = "gpui" + +[features] +default = ["font-kit", "wayland", "x11", "windows-manifest"] +test-support = [ + "collections/test-support", + "http_client/test-support", + "wayland", + "x11", + "proptest", +] +bench-support = ["profiler", "dep:criterion", "dep:bench_metrics"] +bench = ["bench-support"] +inspector = ["gpui_macros/inspector"] +leak-detection = [] +wayland = [] +x11 = ["scap?/x11"] +screen-capture = ["scap"] +windows-manifest = ["dep:embed-resource"] +profiler = ["dep:hdrhistogram"] +stacker = ["dep:stacksafe"] + +[dependencies] +accesskit = { workspace = true } +anyhow = { workspace = true } +async-task = { workspace = true } +backtrace = { workspace = true } +bitflags = { workspace = true } +collections = { workspace = true } +bench_metrics = { workspace = true, optional = true } +criterion = { workspace = true, optional = true } +ctor = { workspace = true } +derive_more = { workspace = true } +etagere = { workspace = true } +futures = { workspace = true } +futures-concurrency = { workspace = true } +gpui_macros = { workspace = true } +gpui_shared_string = { workspace = true } +http_client = { workspace = true } +image = { workspace = true } +inventory = { workspace = true } +itertools = { workspace = true } +log = { workspace = true } +num_cpus = "1.13" +parking = "2.0.0" +parking_lot = { workspace = true } +postage = { workspace = true } +proptest = { workspace = true, optional = true } +chrono = { workspace = true } +profiling = { workspace = true } +rand = { workspace = true } +raw-window-handle = { workspace = true } +regex = { workspace = true } +refineable = { workspace = true } +scheduler = { workspace = true } +resvg = { workspace = true } +usvg = { workspace = true } +ttf-parser = "0.25" +util_macros = { workspace = true } +schemars = { workspace = true } +seahash = "4.1" +serde = { workspace = true } +serde_json = { workspace = true } +slotmap = { workspace = true } +smallvec = { workspace = true } +stacksafe = { workspace = true, optional = true } +strum = { workspace = true } +sum_tree = { workspace = true } +taffy = "0.13.0" +thiserror = { workspace = true } +gpui_util = { workspace = true } +hdrhistogram = { workspace = true, optional = true } +waker-fn = "1.2.0" +lyon = "1.0" +pin-project = "1.1.10" +spin = "0.10.0" +pollster = { workspace = true } +url = { workspace = true } +uuid = { workspace = true } +web-time = { workspace = true } +heapless = { workspace = true } + +[build-dependencies] +embed-resource = { version = "3.0", optional = true } + +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +async-channel = { version = "2.5.0", default-features = false } + +[target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies] +async-channel = { workspace = true } + +[target.'cfg(target_family = "wasm")'.dependencies] +getrandom = { version = "0.3.4", features = ["wasm_js"] } +uuid = { workspace = true, features = ["js"] } + +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] +core-video = { workspace = true } + +[target.'cfg(target_os = "macos")'.dependencies] +objc2-core-foundation = { workspace = true } +objc2-core-video = { workspace = true } +font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "94b0f28166665e8fd2f53ff6d268a14955c82269", package = "zed-font-kit", version = "0.14.1-zed", optional = true } +log = { workspace = true } +objc2 = { workspace = true, optional = true } +objc2-metal = { version = "0.3", optional = true } + +[target.'cfg(target_os = "macos")'.build-dependencies] +bindgen = "0.72" + +[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "windows"))'.dependencies] +scap = { workspace = true, optional = true } + +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +libc = { workspace = true } + +[target.'cfg(target_os = "windows")'.dependencies] +windows = { workspace = true, features = [ + "Win32_Foundation", + "Win32_System_Power", + "Win32_System_RemoteDesktop", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", +] } + +[lints] +workspace = true + +[[example]] +name = "hello_world" +path = "examples/hello_world.rs" + +[[example]] +name = "move_entity_between_windows" +path = "examples/move_entity_between_windows.rs" + +[[example]] +name = "image" +path = "examples/image/image.rs" + +[[example]] +name = "input" +path = "examples/input.rs" + +[[example]] +name = "on_window_close_quit" +path = "examples/on_window_close_quit.rs" + +[[example]] +name = "window_movable" +path = "examples/window_movable.rs" + +[[example]] +name = "opacity" +path = "examples/opacity.rs" + +[[example]] +name = "pattern" +path = "examples/pattern.rs" + +[[example]] +name = "set_menus" +path = "examples/set_menus.rs" + +[[example]] +name = "system_notifications" +path = "examples/system_notifications.rs" + +[[example]] +name = "shadow" +path = "examples/shadow.rs" + +[[example]] +name = "svg" +path = "examples/svg/svg.rs" + +[[example]] +name = "tab_stop" +path = "examples/tab_stop.rs" + +[[example]] +name = "text" +path = "examples/text.rs" + +[[example]] +name = "text_wrapper" +path = "examples/text_wrapper.rs" + +[[example]] +name = "tree" +path = "examples/tree.rs" + +[[example]] +name = "uniform_list" +path = "examples/uniform_list.rs" + +[[example]] +name = "window_shadow" +path = "examples/window_shadow.rs" + +[[example]] +name = "grid_layout" +path = "examples/grid_layout.rs" + +[[example]] +name = "list_example" +path = "examples/list_example.rs" + +[[example]] +name = "mouse_pressure" +path = "examples/mouse_pressure.rs" + +[[example]] +name = "a11y" +path = "examples/a11y.rs" + +[[example]] +name = "view_example" +path = "examples/view_example/view_example_main.rs" + +[[example]] +name = "toggle_headless" +path = "examples/toggle_headless.rs" diff --git a/vendor/gpui-pre/LICENSE-APACHE b/vendor/gpui-pre/LICENSE-APACHE new file mode 100644 index 00000000..461a0fe5 --- /dev/null +++ b/vendor/gpui-pre/LICENSE-APACHE @@ -0,0 +1,222 @@ +Copyright 2022 - 2025 Zed Industries, Inc. + + + 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 + + + http://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. + + + + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + + 1. Definitions. + + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + + END OF TERMS AND CONDITIONS diff --git a/vendor/gpui-pre/README.md b/vendor/gpui-pre/README.md new file mode 100644 index 00000000..132e5ac1 --- /dev/null +++ b/vendor/gpui-pre/README.md @@ -0,0 +1,98 @@ +# Welcome to GPUI! + +GPUI is a hybrid immediate and retained mode, GPU accelerated, UI framework +for Rust, designed to support a wide variety of applications. + +## Getting Started + +GPUI is still in active development as we work on the Zed code editor, and is still pre-1.0. There will often be breaking changes between versions. You'll also need to use the latest version of stable Rust. Add `gpui`, and optionally `gpui_platform`, to your `Cargo.toml`: + +```toml +gpui = { version = "*" } +gpui_platform = { version = "*", features = ["font-kit", "wayland", "x11"] } +``` + +Everything in a standalone GPUI app starts with an `Application`. You can create one with `gpui_platform::application()`, which picks the windowing and text backends for the host OS, and kick off your application by passing a callback to `Application::run()`. Inside this callback, you can create a new window with `App::open_window()` and register your first root view. + +```rust,no_run +use gpui::*; + +fn main() { + gpui_platform::application().run(|cx: &mut App| { + // .. + }); +} +``` + +### `gpui_platform` + +The features on `gpui_platform` are platform-specific, so the list above is a safe cross-platform default. If you build for a single platform, you can trim it: + +- **macOS** — Rendering uses Metal and is always available, but glyph rasterization needs `font-kit`. Without it, GPUI falls back to a placeholder text system that lays text out but renders no glyphs. + + ```toml + gpui_platform = { version = "*", features = ["font-kit"] } + ``` + +- **Linux / FreeBSD** — enable at least one windowing backend for desktop windows: `wayland`, `x11`, or both. These features also compile the renderer and text system, so no separate text feature is needed. + + ```toml + gpui_platform = { version = "*", features = ["wayland", "x11"] } + ``` + +- **Windows** — no features are required. Windowing uses Win32 and text uses DirectWrite. `font-kit` has no effect here. + +### Additional Topics + +- [Ownership and data flow](_ownership_and_data_flow) +- [Accessibility](_accessibility) + +### Dependencies + +GPUI has various system dependencies that it needs in order to work. + +#### macOS + +On macOS, GPUI uses Metal for rendering. In order to use Metal, you need to do the following: + +- Install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12) from the macOS App Store, or from the [Apple Developer](https://developer.apple.com/download/all/) website. Note this requires a developer account. + +> Ensure you launch Xcode after installing, and install the macOS components, which is the default option. + +- Install [Xcode command line tools](https://developer.apple.com/xcode/resources/) + + ```sh + xcode-select --install + ``` + +- Ensure that the Xcode command line tools are using your newly installed copy of Xcode: + + ```sh + sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer + ``` + +## The Big Picture + +GPUI offers three different [registers]() depending on your needs: + +- State management and communication with `Entity`'s. Whenever you need to store application state that communicates between different parts of your application, you'll want to use GPUI's entities. Entities are owned by GPUI and are only accessible through an owned smart pointer similar to an `Rc`. See the `app::context` module for more information. + +- High level, declarative UI with views. All UI in GPUI starts with a view. A view is simply an `Entity` that can be rendered, by implementing the `Render` trait. At the start of each frame, GPUI will call this render method on the root view of a given window. Views build a tree of `elements`, lay them out and style them with a tailwind-style API, and then give them to GPUI to turn into pixels. See the `div` element for an all purpose swiss-army knife of rendering. + +- Low level, imperative UI with Elements. Elements are the building blocks of UI in GPUI, and they provide a nice wrapper around an imperative API that provides as much flexibility and control as you need. Elements have total control over how they and their child elements are rendered and can be used for making efficient views into large lists, implement custom layouting for a code editor, and anything else you can think of. See the `element` module for more information. + +Each of these registers has one or more corresponding contexts that can be accessed from all GPUI services. This context is your main interface to GPUI, and is used extensively throughout the framework. + +## Other Resources + +In addition to the systems above, GPUI provides a range of smaller services that are useful for building complex applications: + +- Actions are user-defined structs that are used for converting keystrokes into logical operations in your UI. Use this for implementing keyboard shortcuts, such as cmd-q. See the `action` module for more information. + +- Platform services, such as `quit the app` or `open a URL` are available as methods on the `app::App`. + +- An async executor that is integrated with the platform's event loop. See the `executor` module for more information., + +- The `[gpui::test]` macro provides a convenient way to write tests for your GPUI applications. Tests also have their own kind of context, a `TestAppContext` which provides ways of simulating common platform input. See `app::test_context` and `test` modules for more details. + +Currently, the best way to learn about these APIs is to read the Zed source code or drop a question in the [Zed Discord](https://zed.dev/community-links). We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog). diff --git a/vendor/gpui-pre/build.rs b/vendor/gpui-pre/build.rs new file mode 100644 index 00000000..504a0152 --- /dev/null +++ b/vendor/gpui-pre/build.rs @@ -0,0 +1,36 @@ +#![allow(clippy::disallowed_methods, reason = "build scripts are exempt")] + +fn main() { + println!("cargo::rustc-check-cfg=cfg(gles)"); + + // Leak detection does bookkeeping on every entity handle, so `test-support` + // does not enable it: that feature must stay cheap enough to compile into + // every build. CI sets `GPUI_LEAK_DETECTION`; the `leak-detection` feature + // turns it on explicitly. + println!("cargo::rustc-check-cfg=cfg(gpui_leak_detection)"); + println!("cargo::rerun-if-env-changed=GPUI_LEAK_DETECTION"); + let requested_by_environment = + std::env::var_os("GPUI_LEAK_DETECTION").is_some_and(|value| !value.is_empty()); + if requested_by_environment || std::env::var_os("CARGO_FEATURE_LEAK_DETECTION").is_some() { + println!("cargo::rustc-cfg=gpui_leak_detection"); + } + + let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); + + if target_os == "windows" { + #[cfg(feature = "windows-manifest")] + embed_resource(); + } +} + +#[cfg(feature = "windows-manifest")] +fn embed_resource() { + let resource_dir = std::path::Path::new("resources/windows"); + let manifest = resource_dir.join("gpui.manifest.xml"); + let rc_file = resource_dir.join("gpui.rc"); + println!("cargo:rerun-if-changed={}", manifest.display()); + println!("cargo:rerun-if-changed={}", rc_file.display()); + embed_resource::compile(rc_file, embed_resource::ParamsIncludeDirs([resource_dir])) + .manifest_required() + .unwrap(); +} diff --git a/vendor/gpui-pre/resources/windows/gpui.manifest.xml b/vendor/gpui-pre/resources/windows/gpui.manifest.xml new file mode 100644 index 00000000..d11e1a4b --- /dev/null +++ b/vendor/gpui-pre/resources/windows/gpui.manifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + true/pm + PerMonitorV2 + SegmentHeap + + + + + + + + diff --git a/vendor/gpui-pre/resources/windows/gpui.rc b/vendor/gpui-pre/resources/windows/gpui.rc new file mode 100644 index 00000000..ab209572 --- /dev/null +++ b/vendor/gpui-pre/resources/windows/gpui.rc @@ -0,0 +1,2 @@ +#define RT_MANIFEST 24 +1 RT_MANIFEST "gpui.manifest.xml" diff --git a/vendor/gpui-pre/src/_accessibility.rs b/vendor/gpui-pre/src/_accessibility.rs new file mode 100644 index 00000000..af14b638 --- /dev/null +++ b/vendor/gpui-pre/src/_accessibility.rs @@ -0,0 +1,295 @@ +//! # Accessibility in GPUI +//! +//! "Accessibility" refers to the ability of your application to be used by all +//! users, regardless of disability status. There are many aspects, all important, including: +//! - Ensuring sufficient text contrast. +//! - Providing a mechanism to disable animations. +//! - Providing a mechanism to increase text sizes. +//! - etc. +//! +//! This guide is focused on **programmatic accessibility**. This allows +//! assistive technology, such as screen readers or Braille displays, to inspect +//! and interact with your app. Docs for contributors working on accessibility +//! support can be found in the `a11y` module's doc comment. +//! +//! GPUI integrates with [AccessKit] to provide programmatic accessibility +//! features (referred to as simply "accessibility" for the rest of this guide). +//! +//! A minimal example can be found in the `examples/a11y` directory. +//! +//! ## Background +//! +//! Accessibility support is based on two key capabilities: +//! - Exposing information about the current UI state to assistive technology. +//! - Responding to actions requested by assistive technology. +//! +//! For example, a screen reader might want to announce to the user that a new +//! button has appeared. The user may then want to use a voice control program +//! to press that button. +//! +//! ### IDs in GPUI - [`ElementId`] and [`GlobalElementId`] +//! +//! In GPUI, each [`Element`] can have an [`id`][Element::id]: +//! ```rust +//! # use gpui::*; +//! let div_with_id = div().id("my-id").child(text!("hello")); +//! +//! // IDs are optional +//! let div_without_id = div().child(text!("hello")); +//! ``` +//! +//! [`Element`]s with IDs are also assigned a [`GlobalElementId`]. This global +//! ID is formed by composing all the non-`None` IDs of its ancestors. For +//! example: +//! ```rust +//! # use gpui::*; +//! let inner = div().id("inner-id"); +//! let middle = div().child(inner); // no ID +//! let outer = div().id("outer-id").child(middle); +//! ``` +//! In this example, `inner`s global ID is (roughly speaking) `["outer-id", +//! "inner-id"]`. +//! +//! Since `middle` doesn't have an ID itself, it has no global ID. +//! +//! [`GlobalElementId`]s should be unique per-frame. Duplicate global IDs in the +//! same frame will likely cause bugs. +//! +//! ### IDs and accessibility +//! +//! When GPUI renders a frame, it walks your UI tree, and finds nodes with +//! global IDs, and informs assistive technology about this node. +//! +//! In order for nodes to be reported, they must also have a non-`None` +//! [`role`][Element::a11y_role]. This is used to inform assistive technology +//! what *sort* of node it is (button, label, table, etc.). You can use +//! [`div().id(...).role()`][StatefulInteractiveElement::role] to set the role. +//! +//! Nodes with the same global ID *across frames* are considered to be "the +//! same" node. For example: +//! ```rust +//! # use gpui::*; +//! // The UI in frame 1 +//! let frame_1 = div() +//! .id("parent") +//! .role(Role::Button) +//! .child( +//! div() +//! .id("id-1") +//! .role(Role::Label) +//! .child(text!("hello")) +//! ); +//! +//! // The UI on the next frame +//! let frame_2 = div() +//! .id("parent") +//! .role(Role::Button) +//! .child( +//! div() +//! .id("id-2") // <- different ID +//! .role(Role::Label) +//! .child(text!("hello")) +//! ); +//! ``` +//! Logically, the UI has not changed. But the screen reader has no way of +//! knowing that both child [`div`]s are "the same". So assistive technology +//! will interpret this as one node being removed, and another node being added. +//! This can be very disorienting for users, since announcements typically only +//! happen when something has *meaningfully* changed. +//! +//! In other words, by controlling the ID of an element, you can control whether +//! a change to a UI element is considered meaningful. You can also control +//! whether elements are reported to assistive technology *at all* by setting +//! the [`role`][Element::a11y_role], since nodes with no role are not reported. +//! +//! #### IDs and text +//! +//! Special care must be taken when dealing with text. +//! +//! GPUI provides the [`text!`] macro, which wraps strings in the [`Text`] type, +//! but automatically derives an ID. Usually, this is what you want. However, +//! the way it generates its ID is subtle and perhaps surprising. +//! +//! The ID of an invocation of the [`text!`] macro is derived from the +//! **location in the source code of that invocation**. For example: +//! +//! ```rust +//! # use gpui::*; +//! let a = text!("a"); +//! let b = text!("b"); +//! +//! // Different source locations, different IDs +//! assert_ne!(a.id(), b.id()); +//! +//! // However: +//! +//! fn make_text(s: &str) -> Text { text!(s) } +//! +//! let a = make_text("a"); +//! let b = make_text("b"); +//! +//! // Both `a` and `b` are produced by the same `text!` invocation, so the IDs +//! // are the same +//! assert_eq!(a.id(), b.id()); +//! ``` +//! This can produce surprising behaviour. For example, this footgun: +//! ```rust +//! # use gpui::*; +//! let todos = vec!["eat lunch", "drink water", "go to gym"]; +//! let todo_divs = todos.into_iter().map(|todo| { +//! text!(todo) +//! }); +//! +//! div() +//! .id("todo-list") +//! .role(Role::Document) +//! .children(todo_divs); // ERROR: multiple nodes with the same global ID +//! ``` +//! +//! Here, when we map the iterator, since we have only written [`text!`] once, +//! there is only one ID. And since they have the same ancestors and the same +//! ID, they will have the same global ID. In release builds, this will mean +//! some nodes get silently dropped! +//! +//! To fix this, you can set an ID: +//! ```rust +//! # use gpui::*; +//! let todos = vec!["eat lunch", "drink water", "go to gym"]; +//! let todo_divs = todos.into_iter().enumerate().map(|(index, todo)| { +//! text!(todo).with_id(index) // OR `text(id = index, todo)` +//! }); +//! +//! div() +//! .id("todo-list") +//! .role(Role::Document) +//! .children(todo_divs); +//! ``` +//! Another possible solution is to wrap the [`text!`] in another node that +//! *does* have a unique global ID. For example: +//! ```rust +//! # use gpui::*; +//! let todos = vec!["eat lunch", "drink water", "go to gym"]; +//! let todo_divs = todos.into_iter().enumerate().map(|(index, todo)| { +//! div().id(index).child(text!(todo)) +//! }); +//! +//! div() +//! .id("todo-list") +//! .role(Role::Document) +//! .children(todo_divs); +//! ``` +//! Since the AccessKit [`NodeId`][accesskit::NodeId] is derived from the global +//! ID, and the global ID takes into account the IDs of all ancestors, this +//! works too. +//! +//! Occasionally, you will need to create a [`Text`] element with *no* ID. You +//! can achieve this with [`Text::new_inaccessible`]. If you are creating a +//! custom UI component (e.g. a button), you may want this so that you can set a +//! label property on a parent [`div`] without duplicating the text in the +//! accessibility tree. +//! +//! ### Handling actions +//! +//! Assistive technology can dispatch actions to the UI. While many users of +//! assistive technology use traditional input devices (e.g. a keyboard), some +//! use more specialized systems. For example, users with limited mobility may +//! use voice control to interact with your app. +//! +//! When a user dispatches an action, it is dispatched *to a specific node*. It +//! is your responsibility to tell the UI elements how they should respond when +//! a request comes in. +//! +//! Note, these actions are **totally unrelated** to GPUI's [`Action`] trait. +//! AccessKit exposes [`accesskit::Action`]. In GPUI, this is re-exported as +//! [`AccessibleAction`]. +//! +//! To respond to an accessible action, use +//! [`div().on_a11y_action()`][InteractiveElement::on_a11y_action]: +//! ```rust,ignore +//! div() +//! .id("my-slider") +//! .role(Role::Slider) +//! .on_a11y_action(AccessibleAction::Increment, |_extra, _window, _cx| { +//! position += 1; +//! cx.notify(); +//! }) +//! .child(my_cool_slider()); +//! ``` +//! +//! Note that some common actions are automatically registered. For example, +//! [`.on_click()`][StatefulInteractiveElement::on_click] adds an +//! [`AccessibleAction::Click`] handler that calls the click handler. +//! +//! ## Synthetic children +//! +//! Sometimes, a custom [`Element`] may want to appear as if it is really made +//! of multiple nodes. For example, a totally hypothetical custom text editor +//! element may want to have [`Role::TextInput`], while presenting children +//! consisting of [`Role::TextRun`]s. +//! +//! This is possible using [`Element::a11y_synthetic_children`]. For example: +//! ```rust,ignore +//! # use gpui::*; +//! impl Element for MyCustomTextField { +//! +//! // ... +//! +//! fn a11y_role(&self) -> Option { +//! Some(Role::TextInput) +//! } +//! +//! fn a11y_synthetic_children( +//! &mut self, +//! _prepaint: &mut Self::PrepaintState, +//! builder: &mut A11ySubtreeBuilder, +//! ) { +//! // Create the synthetic child node +//! let mut run = accesskit::Node::new(Role::TextRun); +//! run.set_value(self.text.clone()); +//! run.set_character_lengths( +//! self.text.chars().map(|c| c.len_utf8() as u8).collect::>(), +//! ); +//! +//! // Insert it as a child of `MyCustomTextField` +//! let run_id = builder.synthetic_node_id(0); +//! builder.push_child(run_id, run); +//! +//! // You can also mutate the parent (i.e. the `MyCustomTextField`) +//! let caret = accesskit::TextPosition { +//! node: run_id, +//! character_index: self.cursor, +//! }; +//! builder.parent_node().set_text_selection(accesskit::TextSelection { +//! anchor: caret, +//! focus: caret, +//! }); +//! } +//! } +//! ``` +//! +//! Notably, synthetic children are added *after* an element is +//! [prepainted][Element::prepaint], so prepaint state can be used (for example, +//! to determine what is visible on screen). +//! +//! ## Further reading +//! +//! Designing high-quality accessible interfaces can be challenging, in the same +//! way that designing high-quality traditional interfaces can be. The +//! following pages have useful information: +//! +//! - [AccessKit]: The cross-platform accessibility toolkit GPUI uses +//! internally. +//! - [MDN WAI-ARIA basics][mdn-aria]: Introduction to roles, properties, and +//! states. +//! - [ARIA Authoring Practices Guide][apg]: W3C patterns for accessible +//! widgets. +//! +//! Note that, while GPUI mimics web APIs, it doesn't necessarily behave +//! *exactly* as a web browser would with the same attributes. +//! +//! [AccessKit]: https://accesskit.dev/ +//! [mdn-aria]: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/WAI-ARIA_basics +//! [apg]: https://www.w3.org/WAI/ARIA/apg/ + +#[cfg(doc)] +use crate::*; // so I don't have to qualify every type :) diff --git a/vendor/gpui-pre/src/_ownership_and_data_flow.rs b/vendor/gpui-pre/src/_ownership_and_data_flow.rs new file mode 100644 index 00000000..68699cce --- /dev/null +++ b/vendor/gpui-pre/src/_ownership_and_data_flow.rs @@ -0,0 +1,140 @@ +//! In GPUI, every model or view in the application is actually owned by a single top-level object called the `App`. When a new entity or view is created (referred to collectively as _entities_), the application is given ownership of their state to enable their participation in a variety of app services and interaction with other entities. +//! +//! To illustrate, consider the trivial app below. We start the app by calling `run` with a callback, which is passed a reference to the `App` that owns all the state for the application. This `App` is our gateway to all application-level services, such as opening windows, presenting dialogs, etc. It also has an `insert_entity` method, which is called below to create an entity and give ownership of it to the application. +//! +//! ```no_run +//! # use gpui::{App, AppContext, Application, Entity}; +//! # struct Counter { +//! # count: usize, +//! # } +//! gpui_platform::application().run(|cx: &mut App| { +//! let _counter: Entity = cx.new(|_cx| Counter { count: 0 }); +//! // ... +//! }); +//! ``` +//! +//! The call to `new_entity` returns an _entity handle_, which carries a type parameter based on the type of object it references. By itself, this `Entity` handle doesn't provide access to the entity's state. It's merely an inert identifier plus a compile-time type tag, and it maintains a reference counted pointer to the underlying `Counter` object that is owned by the app. +//! +//! Much like an `Rc` from the Rust standard library, this reference count is incremented when the handle is cloned and decremented when it is dropped to enable shared ownership over the underlying model, but unlike an `Rc` it only provides access to the model's state when a reference to an `App` is available. The handle doesn't truly _own_ the state, but it can be used to access the state from its true owner, the `App`. Stripping away some of the setup code for brevity: +//! +//! ```no_run +//! # use gpui::{App, AppContext, Application, Context, Entity}; +//! # struct Counter { +//! # count: usize, +//! # } +//! gpui_platform::application().run(|cx: &mut App| { +//! let counter: Entity = cx.new(|_cx| Counter { count: 0 }); +//! // Call `update` to access the model's state. +//! counter.update(cx, |counter: &mut Counter, _cx: &mut Context| { +//! counter.count += 1; +//! }); +//! }); +//! ``` +//! +//! To update the counter, we call `update` on the handle, passing the context reference and a callback. The callback is yielded a mutable reference to the counter, which can be used to manipulate state. +//! +//! The callback is also provided a second `Context` reference. This reference is similar to the `App` reference provided to the `run` callback. A `Context` is actually a wrapper around the `App`, including some additional data to indicate which particular entity it is tied to; in this case the counter. +//! +//! In addition to the application-level services provided by `App`, a `Context` provides access to entity-level services. For example, it can be used it to inform observers of this entity that its state has changed. Let's add that to our example, by calling `cx.notify()`. +//! +//! ```no_run +//! # use gpui::{App, AppContext, Application, Entity}; +//! # struct Counter { +//! # count: usize, +//! # } +//! gpui_platform::application().run(|cx: &mut App| { +//! let counter: Entity = cx.new(|_cx| Counter { count: 0 }); +//! counter.update(cx, |counter, cx| { +//! counter.count += 1; +//! cx.notify(); // Notify observers +//! }); +//! }); +//! ``` +//! +//! Next, these notifications need to be observed and reacted to. Before updating the counter, we'll construct a second counter that observes it. Whenever the first counter changes, twice its count is assigned to the second counter. Note how `observe` is called on the `Context` belonging to our second counter to arrange for it to be notified whenever the first counter notifies. The call to `observe` returns a `Subscription`, which is `detach`ed to preserve this behavior for as long as both counters exist. We could also store this subscription and drop it at a time of our choosing to cancel this behavior. +//! +//! The `observe` callback is passed a mutable reference to the observer and a _handle_ to the observed counter, whose state we access with the `read` method. +//! +//! ```no_run +//! # use gpui::{App, AppContext, Application, Entity, prelude::*}; +//! # struct Counter { +//! # count: usize, +//! # } +//! gpui_platform::application().run(|cx: &mut App| { +//! let first_counter: Entity = cx.new(|_cx| Counter { count: 0 }); +//! +//! let second_counter = cx.new(|cx: &mut Context| { +//! // Note we can set up the callback before the Counter is even created! +//! cx.observe( +//! &first_counter, +//! |second: &mut Counter, first: Entity, cx| { +//! second.count = first.read(cx).count * 2; +//! }, +//! ) +//! .detach(); +//! +//! Counter { count: 0 } +//! }); +//! +//! first_counter.update(cx, |counter, cx| { +//! counter.count += 1; +//! cx.notify(); +//! }); +//! +//! assert_eq!(second_counter.read(cx).count, 2); +//! }); +//! ``` +//! +//! After updating the first counter, it can be noted that the observing counter's state is maintained according to our subscription. +//! +//! In addition to `observe` and `notify`, which indicate that an entity's state has changed, GPUI also offers `subscribe` and `emit`, which enables entities to emit typed events. To opt into this system, the emitting object must implement the `EventEmitter` trait. +//! +//! Let's introduce a new event type called `CounterChangeEvent`, then indicate that `Counter` can emit this type of event: +//! +//! ```no_run +//! use gpui::EventEmitter; +//! # struct Counter { +//! # count: usize, +//! # } +//! struct CounterChangeEvent { +//! increment: usize, +//! } +//! +//! impl EventEmitter for Counter {} +//! ``` +//! +//! Next, the example should be updated, replacing the observation with a subscription. Whenever the counter is incremented, a `Change` event is emitted to indicate the magnitude of the increase. +//! +//! ```no_run +//! # use gpui::{App, AppContext, Application, Context, Entity, EventEmitter}; +//! # struct Counter { +//! # count: usize, +//! # } +//! # struct CounterChangeEvent { +//! # increment: usize, +//! # } +//! # impl EventEmitter for Counter {} +//! gpui_platform::application().run(|cx: &mut App| { +//! let first_counter: Entity = cx.new(|_cx| Counter { count: 0 }); +//! +//! let second_counter = cx.new(|cx: &mut Context| { +//! // Note we can set up the callback before the Counter is even created! +//! cx.subscribe(&first_counter, |second: &mut Counter, _first: Entity, event, _cx| { +//! second.count += event.increment * 2; +//! }) +//! .detach(); +//! +//! Counter { +//! count: first_counter.read(cx).count * 2, +//! } +//! }); +//! +//! first_counter.update(cx, |first, cx| { +//! first.count += 2; +//! cx.emit(CounterChangeEvent { increment: 2 }); +//! cx.notify(); +//! }); +//! +//! assert_eq!(second_counter.read(cx).count, 4); +//! }); +//! ``` diff --git a/vendor/gpui-pre/src/action.rs b/vendor/gpui-pre/src/action.rs new file mode 100644 index 00000000..f09d51c4 --- /dev/null +++ b/vendor/gpui-pre/src/action.rs @@ -0,0 +1,459 @@ +// Modified for gpui-pre (snapshot of zed@279fe07): the `actions!` derive paths are crate-relative. +use anyhow::{Context as _, Result}; +use collections::{HashMap, TypeIdHashMap}; +pub use gpui_macros::Action; +pub use no_action::{NoAction, Unbind, is_no_action, is_unbind}; +use serde_json::json; +use std::{ + any::{Any, TypeId}, + fmt::Display, +}; + +/// Defines and registers unit structs that can be used as actions. For more complex data types, derive `Action`. +/// +/// For example: +/// +/// ``` +/// use gpui::actions; +/// actions!(editor, [MoveUp, MoveDown, MoveLeft, MoveRight, Newline]); +/// ``` +/// +/// This will create actions with names like `editor::MoveUp`, `editor::MoveDown`, etc. +/// +/// The namespace argument `editor` can also be omitted, though it is required for Zed actions. +#[macro_export] +macro_rules! actions { + ($namespace:path, [ $( $(#[$attr:meta])* $name:ident),* $(,)? ]) => { + $( + #[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::default::Default, ::std::fmt::Debug, $crate::Action)] + #[action(namespace = $namespace)] + $(#[$attr])* + pub struct $name; + )* + }; + ([ $( $(#[$attr:meta])* $name:ident),* $(,)? ]) => { + $( + #[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::default::Default, ::std::fmt::Debug, $crate::Action)] + $(#[$attr])* + pub struct $name; + )* + }; +} + +/// Actions are used to implement keyboard-driven UI. When you declare an action, you can bind keys +/// to the action in the keymap and listeners for that action in the element tree. +/// +/// To declare a list of simple actions, you can use the actions! macro, which defines a simple unit +/// struct action for each listed action name in the given namespace. +/// +/// ``` +/// use gpui::actions; +/// actions!(editor, [MoveUp, MoveDown, MoveLeft, MoveRight, Newline]); +/// ``` +/// +/// Registering the actions with the same name will result in a panic during `App` creation. +/// +/// # Derive Macro +/// +/// More complex data types can also be actions, by using the derive macro for `Action`: +/// +/// ``` +/// use gpui::Action; +/// #[derive(Clone, PartialEq, serde::Deserialize, schemars::JsonSchema, Action)] +/// #[action(namespace = editor)] +/// pub struct SelectNext { +/// pub replace_newest: bool, +/// } +/// ``` +/// +/// The derive macro for `Action` requires that the type implement `Clone` and `PartialEq`. It also +/// requires `serde::Deserialize` and `schemars::JsonSchema` unless `#[action(no_json)]` is +/// specified. In Zed these trait impls are used to load keymaps from JSON. +/// +/// Multiple arguments separated by commas may be specified in `#[action(...)]`: +/// +/// - `namespace = some_namespace` sets the namespace. In Zed this is required. +/// +/// - `name = "ActionName"` overrides the action's name. This must not contain `::`. +/// +/// - `no_json` causes the `build` method to always error and `action_json_schema` to return `None`, +/// and allows actions not implement `serde::Serialize` and `schemars::JsonSchema`. +/// +/// - `no_register` skips registering the action. This is useful for implementing the `Action` trait +/// while not supporting invocation by name or JSON deserialization. +/// +/// - `deprecated_aliases = ["editor::SomeAction"]` specifies deprecated old names for the action. +/// These action names should *not* correspond to any actions that are registered. These old names +/// can then still be used to refer to invoke this action. In Zed, the keymap JSON schema will +/// accept these old names and provide warnings. +/// +/// - `deprecated = "Message about why this action is deprecation"` specifies a deprecation message. +/// In Zed, the keymap JSON schema will cause this to be displayed as a warning. +/// +/// # Manual Implementation +/// +/// If you want to control the behavior of the action trait manually, you can use the lower-level +/// `#[register_action]` macro, which only generates the code needed to register your action before +/// `main`. +/// +/// ``` +/// use gpui::{SharedString, register_action}; +/// #[derive(Clone, PartialEq, Eq, serde::Deserialize, schemars::JsonSchema)] +/// pub struct Paste { +/// pub content: SharedString, +/// } +/// +/// impl gpui::Action for Paste { +/// # fn boxed_clone(&self) -> Box { unimplemented!()} +/// # fn partial_eq(&self, other: &dyn gpui::Action) -> bool { unimplemented!() } +/// # fn name(&self) -> &'static str { "Paste" } +/// # fn name_for_type() -> &'static str { "Paste" } +/// # fn build(value: serde_json::Value) -> anyhow::Result> { +/// # unimplemented!() +/// # } +/// } +/// +/// register_action!(Paste); +/// ``` +pub trait Action: Any + Send { + /// Clone the action into a new box + fn boxed_clone(&self) -> Box; + + /// Do a partial equality check on this action and the other + fn partial_eq(&self, action: &dyn Action) -> bool; + + /// Get the name of this action, for displaying in UI + fn name(&self) -> &'static str; + + /// Get the name of this action type (static) + fn name_for_type() -> &'static str + where + Self: Sized; + + /// Build this action from a JSON value. This is used to construct actions from the keymap. + /// A value of `{}` will be passed for actions that don't have any parameters. + fn build(value: serde_json::Value) -> Result> + where + Self: Sized; + + /// Optional JSON schema for the action's input data. + fn action_json_schema(_: &mut schemars::SchemaGenerator) -> Option + where + Self: Sized, + { + None + } + + /// A list of alternate, deprecated names for this action. These names can still be used to + /// invoke the action. In Zed, the keymap JSON schema will accept these old names and provide + /// warnings. + fn deprecated_aliases() -> &'static [&'static str] + where + Self: Sized, + { + &[] + } + + /// Returns the deprecation message for this action, if any. In Zed, the keymap JSON schema will + /// cause this to be displayed as a warning. + fn deprecation_message() -> Option<&'static str> + where + Self: Sized, + { + None + } + + /// The documentation for this action, if any. When using the derive macro for actions + /// this will be automatically generated from the doc comments on the action struct. + fn documentation() -> Option<&'static str> + where + Self: Sized, + { + None + } +} + +impl std::fmt::Debug for dyn Action { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("dyn Action") + .field("name", &self.name()) + .finish() + } +} + +impl dyn Action { + /// Type-erase Action type. + pub fn as_any(&self) -> &dyn Any { + self as &dyn Any + } +} + +/// Error type for `Keystroke::parse`. This is used instead of `anyhow::Error` so that Zed can use +/// markdown to display it. +#[derive(Debug)] +pub enum ActionBuildError { + /// Indicates that an action with this name has not been registered. + NotFound { + /// Name of the action that was not found. + name: String, + }, + /// Indicates that an error occurred while building the action, typically a JSON deserialization + /// error. + BuildError { + /// Name of the action that was attempting to be built. + name: String, + /// Error that occurred while building the action. + error: anyhow::Error, + }, +} + +impl std::error::Error for ActionBuildError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + ActionBuildError::NotFound { .. } => None, + ActionBuildError::BuildError { error, .. } => error.source(), + } + } +} + +impl Display for ActionBuildError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ActionBuildError::NotFound { name } => { + write!(f, "Didn't find an action named \"{name}\"") + } + ActionBuildError::BuildError { name, error } => { + write!(f, "Error while building action \"{name}\": {error}") + } + } + } +} + +type ActionBuilder = fn(json: serde_json::Value) -> anyhow::Result>; + +pub(crate) struct ActionRegistry { + by_name: HashMap<&'static str, ActionData>, + names_by_type_id: TypeIdHashMap<&'static str>, + all_names: Vec<&'static str>, // So we can return a static slice. + deprecated_aliases: HashMap<&'static str, &'static str>, // deprecated name -> preferred name + deprecation_messages: HashMap<&'static str, &'static str>, // action name -> deprecation message + documentation: HashMap<&'static str, &'static str>, // action name -> documentation +} + +impl Default for ActionRegistry { + fn default() -> Self { + let mut this = ActionRegistry { + by_name: Default::default(), + names_by_type_id: Default::default(), + documentation: Default::default(), + all_names: Default::default(), + deprecated_aliases: Default::default(), + deprecation_messages: Default::default(), + }; + + this.load_actions(); + + this + } +} + +struct ActionData { + pub build: ActionBuilder, + pub json_schema: fn(&mut schemars::SchemaGenerator) -> Option, +} + +/// This type must be public so that our macros can build it in other crates. +/// But this is an implementation detail and should not be used directly. +#[doc(hidden)] +pub struct MacroActionBuilder(pub fn() -> MacroActionData); + +/// This type must be public so that our macros can build it in other crates. +/// But this is an implementation detail and should not be used directly. +#[doc(hidden)] +pub struct MacroActionData { + pub name: &'static str, + pub type_id: TypeId, + pub build: ActionBuilder, + pub json_schema: fn(&mut schemars::SchemaGenerator) -> Option, + pub deprecated_aliases: &'static [&'static str], + pub deprecation_message: Option<&'static str>, + pub documentation: Option<&'static str>, +} + +inventory::collect!(MacroActionBuilder); + +impl ActionRegistry { + /// Load all registered actions into the registry. + pub(crate) fn load_actions(&mut self) { + for builder in inventory::iter:: { + let action = builder.0(); + self.insert_action(action); + } + } + + fn insert_action(&mut self, action: MacroActionData) { + let name = action.name; + if self.by_name.contains_key(name) { + panic!( + "Action with name `{name}` already registered \ + (might be registered in `#[action(deprecated_aliases = [...])]`." + ); + } + self.by_name.insert( + name, + ActionData { + build: action.build, + json_schema: action.json_schema, + }, + ); + for &alias in action.deprecated_aliases { + if self.by_name.contains_key(alias) { + panic!( + "Action with name `{alias}` already registered. \ + `{alias}` is specified in `#[action(deprecated_aliases = [...])]` for action `{name}`." + ); + } + self.by_name.insert( + alias, + ActionData { + build: action.build, + json_schema: action.json_schema, + }, + ); + self.deprecated_aliases.insert(alias, name); + self.all_names.push(alias); + } + self.names_by_type_id.insert(action.type_id, name); + self.all_names.push(name); + if let Some(deprecation_msg) = action.deprecation_message { + self.deprecation_messages.insert(name, deprecation_msg); + } + if let Some(documentation) = action.documentation { + self.documentation.insert(name, documentation); + } + } + + /// Construct an action based on its name and optional JSON parameters sourced from the keymap. + pub fn build_action_type(&self, type_id: &TypeId) -> Result> { + let name = self + .names_by_type_id + .get(type_id) + .with_context(|| format!("no action type registered for {type_id:?}"))?; + + Ok(self.build_action(name, None)?) + } + + #[cfg(feature = "profiler")] + pub(crate) fn try_resolve_action(&self, type_id: &TypeId) -> Option<&'static str> { + self.names_by_type_id.get(type_id).copied() + } + + /// Construct an action based on its name and optional JSON parameters sourced from the keymap. + pub fn build_action( + &self, + name: &str, + params: Option, + ) -> std::result::Result, ActionBuildError> { + let build_action = self + .by_name + .get(name) + .ok_or_else(|| ActionBuildError::NotFound { + name: name.to_owned(), + })? + .build; + (build_action)(params.unwrap_or_else(|| json!({}))).map_err(|e| { + ActionBuildError::BuildError { + name: name.to_owned(), + error: e, + } + }) + } + + pub fn all_action_names(&self) -> &[&'static str] { + self.all_names.as_slice() + } + + pub fn action_schemas( + &self, + generator: &mut schemars::SchemaGenerator, + ) -> Vec<(&'static str, Option)> { + // Use the order from all_names so that the resulting schema has sensible order. + self.all_names + .iter() + .map(|name| { + let action_data = self + .by_name + .get(name) + .expect("All actions in all_names should be registered"); + (*name, (action_data.json_schema)(generator)) + }) + .collect::>() + } + + pub fn action_schema_by_name( + &self, + name: &str, + generator: &mut schemars::SchemaGenerator, + ) -> Option> { + self.by_name + .get(name) + .map(|action_data| (action_data.json_schema)(generator)) + } + + pub fn deprecated_aliases(&self) -> &HashMap<&'static str, &'static str> { + &self.deprecated_aliases + } + + pub fn deprecation_messages(&self) -> &HashMap<&'static str, &'static str> { + &self.deprecation_messages + } + + pub fn documentation(&self) -> &HashMap<&'static str, &'static str> { + &self.documentation + } +} + +/// Generate a list of all the registered actions. +/// Useful for transforming the list of available actions into a +/// format suited for static analysis such as in validating keymaps, or +/// generating documentation. +pub fn generate_list_of_all_registered_actions() -> impl Iterator { + inventory::iter:: + .into_iter() + .map(|builder| builder.0()) +} + +mod no_action { + use crate as gpui; + use schemars::JsonSchema; + use serde::Deserialize; + + actions!( + zed, + [ + /// Action with special handling which unbinds the keybinding this is associated with, + /// if it is the highest precedence match. + NoAction + ] + ); + + /// Action with special handling which unbinds later bindings for the same keystrokes when they + /// dispatch the named action, regardless of that action's context. + /// + /// In keymap JSON this is written as: + /// + /// `["zed::Unbind", "editor::NewLine"]` + #[derive(Clone, Debug, PartialEq, Deserialize, JsonSchema, gpui::Action)] + #[action(namespace = zed)] + pub struct Unbind(pub gpui::SharedString); + + /// Returns whether or not this action represents a removed key binding. + pub fn is_no_action(action: &dyn gpui::Action) -> bool { + action.as_any().is::() + } + + /// Returns whether or not this action represents an unbind marker. + pub fn is_unbind(action: &dyn gpui::Action) -> bool { + action.as_any().is::() + } +} diff --git a/vendor/gpui-pre/src/app.rs b/vendor/gpui-pre/src/app.rs new file mode 100644 index 00000000..a921de1a --- /dev/null +++ b/vendor/gpui-pre/src/app.rs @@ -0,0 +1,3607 @@ +use scheduler::Instant; +use std::{ + any::{TypeId, type_name}, + cell::{BorrowMutError, Cell, Ref, RefCell, RefMut}, + ffi::OsString, + marker::PhantomData, + mem, + ops::{Deref, DerefMut}, + path::{Path, PathBuf}, + rc::{Rc, Weak}, + sync::{Arc, atomic::Ordering::SeqCst}, + time::Duration, +}; + +use anyhow::{Context as _, Result, anyhow}; +use derive_more::{Deref, DerefMut}; +use futures::{Future, FutureExt, channel::oneshot, future::LocalBoxFuture}; +use itertools::Itertools; +use parking_lot::RwLock; +use slotmap::SlotMap; + +pub use async_context::*; +#[cfg(feature = "bench-support")] +pub use bench_context::{ + BenchAppContext, BenchMeasurement, BenchReport, BenchWindowContext, CountingAllocator, + MetricReport, bench_platform, +}; +use collections::{FxHashMap, FxHashSet, HashMap, TypeIdHashMap, TypeIdHashSet, VecDeque}; +pub use context::*; +pub use entity_map::*; +use gpui_util::{ResultExt, debug_panic}; +#[cfg(any(test, feature = "test-support"))] +pub use headless_app_context::*; +use http_client::{HttpClient, Url}; +use smallvec::SmallVec; +#[cfg(any(test, feature = "test-support"))] +pub use test_app::*; +#[cfg(any(test, feature = "test-support"))] +pub use test_context::*; +#[cfg(all(target_os = "macos", any(test, feature = "test-support")))] +pub use visual_test_context::*; + +#[cfg(any(feature = "inspector", debug_assertions))] +use crate::InspectorElementRegistry; +use crate::asset_cache::CachedLoad; +use crate::{ + Action, ActionBuildError, ActionRegistry, ActivationPolicy, ActivityGuard, Any, AnyView, + AnyWindowHandle, AppContext, Arena, ArenaBox, Asset, AssetSource, BackgroundExecutor, Bounds, + ClipboardItem, ClipboardReadError, CursorStyle, DispatchPhase, DisplayId, EventEmitter, + ExternalDragPayload, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, KeyContext, + Keymap, Keystroke, LayoutId, Menu, MenuItem, MissingGlyph, OwnedMenu, PathPromptOptions, + Pixels, Platform, PlatformDisplay, PlatformKeyboardLayout, PlatformKeyboardMapper, Point, + Priority, PromptBuilder, PromptButton, PromptHandle, PromptLevel, Render, RenderImage, + RenderablePromptHandle, Reservation, ScreenCaptureSource, SharedString, SubscriberSet, + Subscription, SvgRenderer, SystemNotification, SystemNotificationResponse, Task, + TextRenderingMode, TextSystem, ThermalState, Window, WindowAppearance, WindowButtonLayout, + WindowHandle, WindowId, WindowInvalidator, WindowingRequest, + colors::{Colors, GlobalColors}, + hash, init_app_menus, +}; + +mod async_context; +#[cfg(feature = "bench-support")] +mod bench_context; +mod context; +mod entity_map; +#[cfg(any(test, feature = "test-support"))] +mod headless_app_context; +#[cfg(any(test, feature = "test-support"))] +mod test_app; +#[cfg(any(test, feature = "test-support"))] +mod test_context; +#[cfg(all(target_os = "macos", any(test, feature = "test-support")))] +mod visual_test_context; + +/// The duration for which native applications wait for futures returned from +/// [Context::on_app_quit] before fully quitting. +pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(200); + +/// Temporary(?) wrapper around [`RefCell`] to help us debug any double borrows. +/// Strongly consider removing after stabilization. +#[doc(hidden)] +pub struct AppCell { + app: RefCell, +} + +impl AppCell { + #[doc(hidden)] + #[track_caller] + pub fn borrow(&self) -> AppRef<'_> { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("borrowed {thread_id:?}"); + } + AppRef(self.app.borrow()) + } + + #[doc(hidden)] + #[track_caller] + pub fn borrow_mut(&self) -> AppRefMut<'_> { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("borrowed {thread_id:?}"); + } + AppRefMut(self.app.borrow_mut()) + } + + #[doc(hidden)] + #[track_caller] + pub fn try_borrow_mut(&self) -> Result, BorrowMutError> { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("borrowed {thread_id:?}"); + } + Ok(AppRefMut(self.app.try_borrow_mut()?)) + } +} + +#[doc(hidden)] +#[derive(Deref, DerefMut)] +pub struct AppRef<'a>(Ref<'a, App>); + +impl Drop for AppRef<'_> { + fn drop(&mut self) { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("dropped borrow from {thread_id:?}"); + } + } +} + +#[doc(hidden)] +#[derive(Deref, DerefMut)] +pub struct AppRefMut<'a>(RefMut<'a, App>); + +impl Drop for AppRefMut<'_> { + fn drop(&mut self) { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("dropped {thread_id:?}"); + } + } +} + +/// A reference to a GPUI application, typically constructed in the `main` function of your app. +/// You won't interact with this type much outside of initial configuration and startup. +pub struct Application(Rc); + +/// A strong handle to an [`Application`] started with [`Application::run_embedded`]. +/// +/// Dropping this handle releases the app, so an embedder must hold it for as long as the +/// app should run. While held, it is the embedder's entry point back into GPUI each time +/// the external run loop gives it control. +pub struct ApplicationHandle { + app: Rc, +} + +impl ApplicationHandle { + /// Invoke `f` with the app context. Must not be called re-entrantly from code that + /// is already inside an update; the app state is a `RefCell` and will panic on a + /// double borrow. + pub fn update(&self, f: impl FnOnce(&mut App) -> R) -> R { + let cx = &mut *self.app.borrow_mut(); + f(cx) + } + + /// An [`AsyncApp`] for use across await points. It holds the app weakly; keeping the + /// app alive remains this handle's job. + pub fn to_async(&self) -> AsyncApp { + self.update(|cx| cx.to_async()) + } +} + +/// Represents an application before it is fully launched. Once your app is +/// configured, you'll start the app with `App::run`. +impl Application { + /// Builds an app with a caller-provided platform implementation. + pub fn with_platform(platform: Rc) -> Self { + Self(App::new_app( + platform, + Arc::new(()), + Arc::new(NullHttpClient), + )) + } + + /// Builds an app with accessibility (AccessKit) integration forcibly + /// disabled. + /// + /// In this mode, accessibility APIs (e.g. + /// [`div().role()`][crate::StatefulInteractiveElement::role]) silently + /// no-op. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview of + /// the features this disables. + pub fn new_inaccessible(platform: Rc) -> Self { + let this = Self::with_platform(platform); + this.0.borrow_mut().accessibility_force_disabled = true; + this + } + + /// Assigns the source of assets for the application. + pub fn with_assets(self, asset_source: impl AssetSource) -> Self { + let mut context_lock = self.0.borrow_mut(); + let asset_source = Arc::new(asset_source); + context_lock.asset_source = asset_source.clone(); + context_lock.svg_renderer = SvgRenderer::new(asset_source); + drop(context_lock); + self + } + + /// Configures arguments to pass when restarting the application. + pub fn with_restart_arguments(self, arguments: Vec) -> Self { + self.0.borrow_mut().restart_arguments = arguments; + self + } + + /// Sets the HTTP client for the application. + pub fn with_http_client(self, http_client: Arc) -> Self { + let mut context_lock = self.0.borrow_mut(); + context_lock.http_client = http_client; + drop(context_lock); + self + } + + /// Configures when the application should automatically quit. + /// By default, [`QuitMode::Default`] is used. + pub fn with_quit_mode(self, mode: QuitMode) -> Self { + self.0.borrow_mut().quit_mode = mode; + self + } + + /// Sets the windowing mode the app starts in. See [`App::request_windowing`]. + /// + /// Defaults to windowed. On Linux, the default environment is the process's own, and the app + /// starts headless if that names no allowed display server. On macOS, headless means the app + /// starts without a Dock icon or menu bar ([`ActivationPolicy::Accessory`]). Has no effect on + /// other platforms. + pub fn with_windowing(self, request: WindowingRequest) -> Self { + self.0.borrow().platform.set_initial_windowing(request); + self + } + + /// Start the application. The provided callback will be called once the + /// app is fully launched. + /// + /// On WebAssembly, this returns immediately and retains the app for the lifetime + /// of the Wasm instance. Use [`Self::run_embedded`] to control its lifetime explicitly. + pub fn run(self, on_finish_launching: F) + where + F: 'static + FnOnce(&mut App), + { + let this = self.0.clone(); + let platform = self.0.borrow().platform.clone(); + platform.run(Box::new(move || { + let cx = &mut *this.borrow_mut(); + on_finish_launching(cx); + })); + + #[cfg(target_family = "wasm")] + std::mem::forget(self); + } + + /// Start the application for an embedder that drives the run loop itself. + /// + /// On ordinary platforms `Platform::run` blocks for the lifetime of the app, and the + /// app state is kept alive by [`Application::run`]'s stack frame. Embedded platforms — + /// where the run loop belongs to someone else, e.g. GPUI compiled into a Wasm guest, + /// or a GPUI view hosted inside a foreign native application — implement + /// `Platform::run` to invoke the launch callback and return immediately. This method + /// supports that shape: it returns an [`ApplicationHandle`] that keeps the app alive + /// and lets the embedder re-enter it whenever the external run loop yields control. + pub fn run_embedded(self, on_finish_launching: F) -> ApplicationHandle + where + F: 'static + FnOnce(&mut App), + { + let this = self.0.clone(); + let platform = self.0.borrow().platform.clone(); + platform.run(Box::new(move || { + let cx = &mut *this.borrow_mut(); + on_finish_launching(cx); + })); + ApplicationHandle { app: self.0 } + } + + /// Register a handler to be invoked when the platform instructs the application + /// to open one or more URLs. + pub fn on_open_urls(&self, mut callback: F) -> &Self + where + F: 'static + FnMut(Vec), + { + self.0.borrow().platform.on_open_urls(Box::new(callback)); + self + } + + /// Invokes a handler when an already-running application is launched. + /// On macOS, this can occur when the application icon is double-clicked or the app is launched via the dock. + pub fn on_reopen(&self, mut callback: F) -> &Self + where + F: 'static + FnMut(&mut App), + { + let this = Rc::downgrade(&self.0); + self.0.borrow_mut().platform.on_reopen(Box::new(move || { + if let Some(app) = this.upgrade() { + callback(&mut app.borrow_mut()); + } + })); + self + } + + /// Returns a handle to the [`BackgroundExecutor`] associated with this app, which can be used to spawn futures in the background. + pub fn background_executor(&self) -> BackgroundExecutor { + self.0.borrow().background_executor.clone() + } + + /// Returns a handle to the [`ForegroundExecutor`] associated with this app, which can be used to spawn futures in the foreground. + pub fn foreground_executor(&self) -> ForegroundExecutor { + self.0.borrow().foreground_executor.clone() + } + + /// Returns a reference to the [`TextSystem`] associated with this app. + pub fn text_system(&self) -> Arc { + self.0.borrow().text_system.clone() + } + + /// Returns the file URL of the executable with the specified name in the application bundle + pub fn path_for_auxiliary_executable(&self, name: &str) -> Result { + self.0.borrow().path_for_auxiliary_executable(name) + } +} + +type Handler = Box bool + 'static>; +type Listener = Box bool + 'static>; +type MissingGlyphCallback = Box; +pub(crate) type KeystrokeObserver = + Box bool + 'static>; +type QuitHandler = Box LocalBoxFuture<'static, ()> + 'static>; +type WindowClosedHandler = Box; +type ReleaseListener = Box; +type NewEntityListener = Box, &mut App) + 'static>; + +struct MissingGlyphCallbackEntry { + registration: Rc<()>, + callback: Option, +} + +#[derive(Default)] +struct MissingGlyphCallbackSlot { + entry: RefCell>, +} + +impl MissingGlyphCallbackSlot { + fn replace(&self, callback: MissingGlyphCallback) -> Rc<()> { + let registration = Rc::new(()); + self.entry.borrow_mut().replace(MissingGlyphCallbackEntry { + registration: registration.clone(), + callback: Some(callback), + }); + registration + } + + fn invoke(&self, missing_glyphs: &[MissingGlyph], cx: &mut App) { + let Some((registration, mut callback)) = + self.entry.borrow_mut().as_mut().and_then(|entry| { + entry + .callback + .take() + .map(|callback| (entry.registration.clone(), callback)) + }) + else { + return; + }; + callback(missing_glyphs, cx); + + let mut entry = self.entry.borrow_mut(); + let is_current = entry + .as_ref() + .is_some_and(|entry| Rc::ptr_eq(&entry.registration, ®istration)); + if is_current { + let Some(entry) = entry.as_mut() else { + return; + }; + entry.callback = Some(callback); + } + } + + fn remove(&self, registration: &Rc<()>) -> bool { + let mut entry = self.entry.borrow_mut(); + let is_current = entry + .as_ref() + .is_some_and(|entry| Rc::ptr_eq(&entry.registration, registration)); + if is_current { + entry.take(); + } + is_current + } +} + +/// Defines when the application should automatically quit. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum QuitMode { + /// Use [`QuitMode::Explicit`] on macOS and [`QuitMode::LastWindowClosed`] on other platforms. + #[default] + Default, + /// Quit automatically when the last window is closed. + LastWindowClosed, + /// Quit only when requested via [`App::quit`]. + Explicit, +} + +/// Controls when GPUI hides the mouse cursor in response to keyboard input. +/// +/// Restoration on mouse motion is handled by the platform layer; this enum +/// only describes the policy for *triggering* a hide. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum CursorHideMode { + /// Never hide the cursor automatically. + Never, + /// Hide on character-producing key presses (typing). + OnTyping, + /// Hide on character-producing key presses, *and* when a key binding + /// resolves to an action that consumes the keystroke. + #[default] + OnTypingAndAction, +} + +#[doc(hidden)] +#[derive(Clone, PartialEq, Eq)] +pub struct SystemWindowTab { + pub id: WindowId, + pub title: SharedString, + pub handle: AnyWindowHandle, + pub last_active_at: Instant, +} + +impl SystemWindowTab { + /// Create a new instance of the window tab. + pub fn new(title: SharedString, handle: AnyWindowHandle) -> Self { + Self { + id: handle.id, + title, + handle, + last_active_at: Instant::now(), + } + } +} + +/// A controller for managing window tabs. +#[derive(Default)] +pub struct SystemWindowTabController { + visible: Option, + tab_groups: FxHashMap>, +} + +impl Global for SystemWindowTabController {} + +impl SystemWindowTabController { + /// Create a new instance of the window tab controller. + pub fn new() -> Self { + Self { + visible: None, + tab_groups: FxHashMap::default(), + } + } + + /// Initialize the global window tab controller. + pub fn init(cx: &mut App) { + cx.set_global(SystemWindowTabController::new()); + } + + /// Get all tab groups. + pub fn tab_groups(&self) -> &FxHashMap> { + &self.tab_groups + } + + /// Get the next tab group window handle. + pub fn get_next_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> { + let controller = cx.global::(); + let current_group = controller + .tab_groups + .iter() + .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group)); + + let current_group = current_group?; + // TODO: `.keys()` returns arbitrary order, what does "next" mean? + let mut group_ids: Vec<_> = controller.tab_groups.keys().collect(); + let idx = group_ids.iter().position(|g| *g == current_group)?; + let next_idx = (idx + 1) % group_ids.len(); + + controller + .tab_groups + .get(group_ids[next_idx]) + .and_then(|tabs| { + tabs.iter() + .max_by_key(|tab| tab.last_active_at) + .or_else(|| tabs.first()) + .map(|tab| &tab.handle) + }) + } + + /// Get the previous tab group window handle. + pub fn get_prev_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> { + let controller = cx.global::(); + let current_group = controller + .tab_groups + .iter() + .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group)); + + let current_group = current_group?; + // TODO: `.keys()` returns arbitrary order, what does "previous" mean? + let mut group_ids: Vec<_> = controller.tab_groups.keys().collect(); + let idx = group_ids.iter().position(|g| *g == current_group)?; + let prev_idx = if idx == 0 { + group_ids.len() - 1 + } else { + idx - 1 + }; + + controller + .tab_groups + .get(group_ids[prev_idx]) + .and_then(|tabs| { + tabs.iter() + .max_by_key(|tab| tab.last_active_at) + .or_else(|| tabs.first()) + .map(|tab| &tab.handle) + }) + } + + /// Get all tabs in the same window. + pub fn tabs(&self, id: WindowId) -> Option<&Vec> { + self.tab_groups + .values() + .find(|tabs| tabs.iter().any(|tab| tab.id == id)) + } + + /// Initialize the visibility of the system window tab controller. + pub fn init_visible(cx: &mut App, visible: bool) { + let mut controller = cx.global_mut::(); + if controller.visible.is_none() { + controller.visible = Some(visible); + } + } + + /// Get the visibility of the system window tab controller. + pub fn is_visible(&self) -> bool { + self.visible.unwrap_or(false) + } + + /// Set the visibility of the system window tab controller. + pub fn set_visible(cx: &mut App, visible: bool) { + let mut controller = cx.global_mut::(); + controller.visible = Some(visible); + } + + /// Update the last active of a window. + pub fn update_last_active(cx: &mut App, id: WindowId) { + let mut controller = cx.global_mut::(); + for windows in controller.tab_groups.values_mut() { + for tab in windows.iter_mut() { + if tab.id == id { + tab.last_active_at = Instant::now(); + } + } + } + } + + /// Update the position of a tab within its group. + pub fn update_tab_position(cx: &mut App, id: WindowId, ix: usize) { + let mut controller = cx.global_mut::(); + for (_, windows) in controller.tab_groups.iter_mut() { + if let Some(current_pos) = windows.iter().position(|tab| tab.id == id) { + if ix < windows.len() && current_pos != ix { + let window_tab = windows.remove(current_pos); + windows.insert(ix, window_tab); + } + break; + } + } + } + + /// Update the title of a tab. + pub fn update_tab_title(cx: &mut App, id: WindowId, title: SharedString) { + let controller = cx.global::(); + let tab = controller + .tab_groups + .values() + .flat_map(|windows| windows.iter()) + .find(|tab| tab.id == id); + + if tab.map_or(true, |t| t.title == title) { + return; + } + + let mut controller = cx.global_mut::(); + for windows in controller.tab_groups.values_mut() { + for tab in windows.iter_mut() { + if tab.id == id { + tab.title = title; + return; + } + } + } + } + + /// Insert a tab into a tab group. + pub fn add_tab(cx: &mut App, id: WindowId, tabs: Vec) { + let mut controller = cx.global_mut::(); + let Some(tab) = tabs.iter().find(|tab| tab.id == id).cloned() else { + return; + }; + + let mut expected_tab_ids: Vec<_> = tabs + .iter() + .filter(|tab| tab.id != id) + .map(|tab| tab.id) + .sorted() + .collect(); + + let mut tab_group_id = None; + for (group_id, group_tabs) in &controller.tab_groups { + let tab_ids: Vec<_> = group_tabs.iter().map(|tab| tab.id).sorted().collect(); + if tab_ids == expected_tab_ids { + tab_group_id = Some(*group_id); + break; + } + } + + if let Some(tab_group_id) = tab_group_id { + if let Some(tabs) = controller.tab_groups.get_mut(&tab_group_id) { + tabs.push(tab); + } + } else { + let new_group_id = controller.tab_groups.len(); + controller.tab_groups.insert(new_group_id, tabs); + } + } + + /// Remove a tab from a tab group. + pub fn remove_tab(cx: &mut App, id: WindowId) -> Option { + let mut controller = cx.global_mut::(); + let mut removed_tab = None; + + controller.tab_groups.retain(|_, tabs| { + if let Some(pos) = tabs.iter().position(|tab| tab.id == id) { + removed_tab = Some(tabs.remove(pos)); + } + !tabs.is_empty() + }); + + removed_tab + } + + /// Move a tab to a new tab group. + pub fn move_tab_to_new_window(cx: &mut App, id: WindowId) { + let mut removed_tab = Self::remove_tab(cx, id); + let mut controller = cx.global_mut::(); + + if let Some(tab) = removed_tab { + let new_group_id = controller.tab_groups.keys().max().map_or(0, |k| k + 1); + controller.tab_groups.insert(new_group_id, vec![tab]); + } + } + + /// Merge all tab groups into a single group. + pub fn merge_all_windows(cx: &mut App, id: WindowId) { + let mut controller = cx.global_mut::(); + let Some(initial_tabs) = controller.tabs(id) else { + return; + }; + + let initial_tabs_len = initial_tabs.len(); + let mut all_tabs = initial_tabs.clone(); + + for (_, mut tabs) in controller.tab_groups.drain() { + tabs.retain(|tab| !all_tabs[..initial_tabs_len].contains(tab)); + all_tabs.extend(tabs); + } + + controller.tab_groups.insert(0, all_tabs); + } + + /// Selects the next tab in the tab group in the trailing direction. + pub fn select_next_tab(cx: &mut App, id: WindowId) { + let mut controller = cx.global_mut::(); + let Some(tabs) = controller.tabs(id) else { + return; + }; + + let current_index = tabs.iter().position(|tab| tab.id == id).unwrap(); + let next_index = (current_index + 1) % tabs.len(); + + let _ = &tabs[next_index].handle.update(cx, |_, window, _| { + window.activate_window(); + }); + } + + /// Selects the previous tab in the tab group in the leading direction. + pub fn select_previous_tab(cx: &mut App, id: WindowId) { + let mut controller = cx.global_mut::(); + let Some(tabs) = controller.tabs(id) else { + return; + }; + + let current_index = tabs.iter().position(|tab| tab.id == id).unwrap(); + let previous_index = if current_index == 0 { + tabs.len() - 1 + } else { + current_index - 1 + }; + + let _ = &tabs[previous_index].handle.update(cx, |_, window, _| { + window.activate_window(); + }); + } +} + +pub(crate) enum GpuiMode { + #[cfg(any(test, feature = "test-support"))] + Test { + skip_drawing: bool, + }, + Production, +} + +impl GpuiMode { + #[cfg(any(test, feature = "test-support"))] + pub fn test() -> Self { + GpuiMode::Test { + skip_drawing: false, + } + } + + #[inline] + pub(crate) fn skip_drawing(&self) -> bool { + match self { + #[cfg(any(test, feature = "test-support"))] + GpuiMode::Test { skip_drawing } => *skip_drawing, + GpuiMode::Production => false, + } + } +} + +struct PlatformOwnedDrag { + source_window: WindowId, + state: PlatformOwnedDragState, +} + +enum PlatformOwnedDragState { + Suspended(AnyDrag), + // A source-window drop consumes `active_drag` before AppKit ends the dragging session, so this + // marker can outlive the active drag and is cleaned up by `FileDropEvent::Ended`. + RestoredInSourceWindow, +} + +/// Contains the state of the full application, and passed as a reference to a variety of callbacks. +/// Other [Context] derefs to this type. +/// You need a reference to an `App` to access the state of a [Entity]. +pub struct App { + pub(crate) this: Weak, + pub(crate) platform: Rc, + text_system: Arc, + + pub(crate) actions: Rc, + pub(crate) active_drag: Option, + platform_owned_drag: Option, + pub(crate) background_executor: BackgroundExecutor, + pub(crate) foreground_executor: ForegroundExecutor, + #[cfg(feature = "profiler")] + foreground_journal: crate::profiler::journal::ForegroundJournal, + #[cfg(all(feature = "profiler", not(target_family = "wasm")))] + hang_monitor: Option, + pub(crate) entities: EntityMap, + pub(crate) new_entity_observers: SubscriberSet, + pub(crate) windows: SlotMap>>, + pub(crate) window_handles: FxHashMap, + pub(crate) focus_handles: Arc, + pub(crate) keymap: Rc>, + pub(crate) keyboard_layout: Box, + pub(crate) keyboard_mapper: Rc, + pub(crate) global_action_listeners: + TypeIdHashMap>>, + pending_effects: VecDeque, + + pub(crate) observers: SubscriberSet, + pub(crate) event_listeners: SubscriberSet, + pub(crate) keystroke_observers: SubscriberSet<(), KeystrokeObserver>, + pub(crate) keystroke_interceptors: SubscriberSet<(), KeystrokeObserver>, + pub(crate) keyboard_layout_observers: SubscriberSet<(), Handler>, + missing_glyph_callback: Rc, + pub(crate) thermal_state_observers: SubscriberSet<(), Handler>, + pub(crate) system_sleep_observers: SubscriberSet<(), Handler>, + pub(crate) system_wake_observers: SubscriberSet<(), Handler>, + pub(crate) release_listeners: SubscriberSet, + pub(crate) global_observers: SubscriberSet, + pub(crate) quit_observers: SubscriberSet<(), QuitHandler>, + pub(crate) restart_observers: SubscriberSet<(), Handler>, + pub(crate) window_closed_observers: SubscriberSet<(), WindowClosedHandler>, + + /// Per-App element arena. This isolates element allocations between different + /// App instances (important for tests where multiple Apps run concurrently). + pub(crate) element_arena: RefCell, + /// Per-App event arena. + pub(crate) event_arena: Arena, + + // Drop globals last. We need to ensure all tasks owned by entities and + // callbacks are marked cancelled at this point as this will also shutdown + // the tokio runtime. As any task attempting to spawn a blocking tokio task, + // might panic. + pub(crate) globals_by_type: TypeIdHashMap>, + + // assets + pub(crate) loading_assets: FxHashMap<(TypeId, u64), Box>, + asset_source: Arc, + pub(crate) svg_renderer: SvgRenderer, + http_client: Arc, + + // below is plain data, the drop order is insignificant here + pub(crate) pending_notifications: FxHashSet, + pub(crate) pending_global_notifications: TypeIdHashSet, + pub(crate) restart_path: Option, + pub(crate) restart_arguments: Vec, + pub(crate) layout_id_buffer: Vec, // We recycle this memory across layout requests. + pub(crate) propagate_event: bool, + pub(crate) prompt_builder: Option, + pub(crate) window_invalidators_by_entity: + FxHashMap>, + pub(crate) tracked_entities: FxHashMap>, + pub(crate) current_window_by_entity: FxHashMap, + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) inspector_renderer: Option, + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) inspector_element_registry: InspectorElementRegistry, + #[cfg(any(test, feature = "test-support", debug_assertions))] + pub(crate) name: Option<&'static str>, + pub(crate) text_rendering_mode: Rc>, + + pub(crate) window_update_stack: Vec, + pub(crate) mode: GpuiMode, + pub(crate) cursor_hide_mode: CursorHideMode, + pub(crate) reduce_motion: bool, + /// Origin of the shared clock that phase-locks synced repeating animations. + pub(crate) synced_animation_epoch: Instant, + /// Whether the app was created by [`Application::new_inaccessible`]. No + /// accesskit APIs will be called when this flag is set. + pub(crate) accessibility_force_disabled: bool, + flushing_effects: bool, + pending_updates: usize, + quit_mode: QuitMode, + quitting: bool, + + // We need to ensure the leak detector drops last, after all tasks, callbacks and things have been dropped. + // Otherwise it may report false positives. + #[cfg(any(test, gpui_leak_detection))] + _ref_counts: Arc>, +} + +impl App { + #[allow(clippy::new_ret_no_self)] + pub(crate) fn new_app( + platform: Rc, + asset_source: Arc, + http_client: Arc, + ) -> Rc { + let background_executor = platform.background_executor(); + let foreground_executor = platform.foreground_executor(); + assert!( + background_executor.is_main_thread(), + "must construct App on main thread" + ); + #[cfg(feature = "profiler")] + let foreground_journal = crate::profiler::journal::install_foreground_journal(); + let synced_animation_epoch = background_executor.now(); + + let text_system = Arc::new(TextSystem::new(platform.text_system())); + let entities = EntityMap::new(); + let keyboard_layout = platform.keyboard_layout(); + let keyboard_mapper = platform.keyboard_mapper(); + + #[cfg(any(test, gpui_leak_detection))] + let _ref_counts = entities.ref_counts_drop_handle(); + + let app = Rc::new_cyclic(|this| AppCell { + app: RefCell::new(App { + this: this.clone(), + platform: platform.clone(), + text_system, + text_rendering_mode: Rc::new(Cell::new(TextRenderingMode::default())), + mode: GpuiMode::Production, + actions: Rc::new(ActionRegistry::default()), + flushing_effects: false, + pending_updates: 0, + active_drag: None, + platform_owned_drag: None, + background_executor, + foreground_executor, + #[cfg(feature = "profiler")] + foreground_journal, + #[cfg(all(feature = "profiler", not(target_family = "wasm")))] + hang_monitor: None, + svg_renderer: SvgRenderer::new(asset_source.clone()), + loading_assets: Default::default(), + asset_source, + http_client, + globals_by_type: Default::default(), + entities, + new_entity_observers: SubscriberSet::new(), + windows: SlotMap::with_key(), + window_update_stack: Vec::new(), + window_handles: FxHashMap::default(), + focus_handles: Arc::new(RwLock::new(SlotMap::with_key())), + keymap: Rc::new(RefCell::new(Keymap::default())), + keyboard_layout, + keyboard_mapper, + global_action_listeners: Default::default(), + pending_effects: VecDeque::new(), + pending_notifications: FxHashSet::default(), + pending_global_notifications: Default::default(), + observers: SubscriberSet::new(), + tracked_entities: FxHashMap::default(), + window_invalidators_by_entity: FxHashMap::default(), + current_window_by_entity: FxHashMap::default(), + event_listeners: SubscriberSet::new(), + release_listeners: SubscriberSet::new(), + keystroke_observers: SubscriberSet::new(), + keystroke_interceptors: SubscriberSet::new(), + keyboard_layout_observers: SubscriberSet::new(), + missing_glyph_callback: Rc::default(), + thermal_state_observers: SubscriberSet::new(), + system_sleep_observers: SubscriberSet::new(), + system_wake_observers: SubscriberSet::new(), + global_observers: SubscriberSet::new(), + quit_observers: SubscriberSet::new(), + restart_observers: SubscriberSet::new(), + restart_path: None, + restart_arguments: Vec::new(), + window_closed_observers: SubscriberSet::new(), + layout_id_buffer: Default::default(), + propagate_event: true, + prompt_builder: Some(PromptBuilder::Default), + #[cfg(any(feature = "inspector", debug_assertions))] + inspector_renderer: None, + #[cfg(any(feature = "inspector", debug_assertions))] + inspector_element_registry: InspectorElementRegistry::default(), + quit_mode: QuitMode::default(), + quitting: false, + cursor_hide_mode: CursorHideMode::default(), + reduce_motion: false, + synced_animation_epoch, + accessibility_force_disabled: false, + + #[cfg(any(test, feature = "test-support", debug_assertions))] + name: None, + element_arena: RefCell::new(Arena::new(1024 * 1024)), + event_arena: Arena::new(1024 * 1024), + + #[cfg(any(test, gpui_leak_detection))] + _ref_counts, + }), + }); + + init_app_menus(platform.as_ref(), &app.borrow()); + SystemWindowTabController::init(&mut app.borrow_mut()); + #[cfg(feature = "profiler")] + crate::profiler::journal::observe_power(&app.borrow()); + + platform.on_keyboard_layout_change(Box::new({ + let app = Rc::downgrade(&app); + move || { + if let Some(app) = app.upgrade() { + let cx = &mut app.borrow_mut(); + cx.keyboard_layout = cx.platform.keyboard_layout(); + cx.keyboard_mapper = cx.platform.keyboard_mapper(); + cx.keyboard_layout_observers + .clone() + .retain(&(), move |callback| (callback)(cx)); + } + } + })); + + platform.on_thermal_state_change(Box::new({ + let app = Rc::downgrade(&app); + move || { + if let Some(app) = app.upgrade() { + let cx = &mut app.borrow_mut(); + cx.thermal_state_observers + .clone() + .retain(&(), move |callback| (callback)(cx)); + } + } + })); + + platform.on_system_sleep(Box::new({ + let app = Rc::downgrade(&app); + move || { + if let Some(app) = app.upgrade() { + let cx = &mut app.borrow_mut(); + cx.system_sleep_observers + .clone() + .retain(&(), move |callback| (callback)(cx)); + } + } + })); + + platform.on_system_wake(Box::new({ + let app = Rc::downgrade(&app); + move || { + if let Some(app) = app.upgrade() { + let cx = &mut app.borrow_mut(); + cx.system_wake_observers + .clone() + .retain(&(), move |callback| (callback)(cx)); + } + } + })); + + platform.on_quit(Box::new({ + let cx = Rc::downgrade(&app); + move || { + let Some(cx) = cx.upgrade() else { + return true; + }; + match cx.try_borrow_mut() { + Ok(mut cx) => { + cx.shutdown(); + true + } + Err(_) => { + // Quit was requested while the AppCell was borrowed, so we can't shut down synchronously. + // The platform decides how to proceed. + false + } + } + } + })); + + app + } + + #[doc(hidden)] + pub fn ref_counts_drop_handle(&self) -> impl Sized + use<> { + self.entities.ref_counts_drop_handle() + } + + /// Captures a snapshot of all entities that currently have alive handles. + /// + /// The returned [`LeakDetectorSnapshot`] can later be passed to + /// [`assert_no_new_leaks`](Self::assert_no_new_leaks) to verify that no + /// entities created after the snapshot are still alive. + #[cfg(any(test, gpui_leak_detection))] + pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot { + self.entities.leak_detector_snapshot() + } + + /// Asserts that no entities created after `snapshot` still have alive handles. + /// + /// Entities that were already tracked at the time of the snapshot are ignored, + /// even if they still have handles. Only *new* entities (those whose + /// `EntityId` was not present in the snapshot) are considered leaks. + /// + /// # Panics + /// + /// Panics if any new entity handles exist. The panic message lists every + /// leaked entity with its type name, and includes allocation-site backtraces + /// when `LEAK_BACKTRACE` is set. + #[cfg(any(test, gpui_leak_detection))] + pub fn assert_no_new_leaks(&self, snapshot: &LeakDetectorSnapshot) { + self.entities.assert_no_new_leaks(snapshot) + } + + /// Without leak detection compiled in, this records nothing. + #[cfg(all(feature = "test-support", not(any(test, gpui_leak_detection))))] + pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot { + LeakDetectorSnapshot::default() + } + + /// Without leak detection compiled in, this checks nothing. Set + /// `GPUI_LEAK_DETECTION` when building to enable it. + #[cfg(all(feature = "test-support", not(any(test, gpui_leak_detection))))] + pub fn assert_no_new_leaks(&self, _snapshot: &LeakDetectorSnapshot) {} + + /// Quit the application gracefully. + /// + /// Native applications give handlers registered with [`Context::on_app_quit`] + /// [`SHUTDOWN_TIMEOUT`] to complete. WebAssembly runs them asynchronously as best-effort cleanup + /// because its event-loop thread cannot block. + pub fn shutdown(&mut self) { + // Requested first so the final hang poll overlaps with the quit + // handlers. It's awaited alongside them, within `SHUTDOWN_TIMEOUT`. + #[cfg(all(feature = "profiler", not(target_family = "wasm")))] + let hang_monitor_flush = self + .hang_monitor + .as_ref() + .and_then(|hang_monitor| hang_monitor.request_flush()); + + let mut futures: Vec> = Vec::new(); + + for observer in self.quit_observers.remove(&()) { + futures.push(observer(self)); + } + + #[cfg(all(feature = "profiler", not(target_family = "wasm")))] + if let Some(flushed) = hang_monitor_flush { + futures.push( + async move { + if flushed.await.is_err() { + log::warn!("hang monitor exited before flushing"); + } + } + .boxed_local(), + ); + } + + self.windows.clear(); + self.window_handles.clear(); + self.flush_effects(); + self.quitting = true; + + let futures = futures::future::join_all(futures); + #[cfg(not(target_family = "wasm"))] + if self + .foreground_executor + .block_with_timeout(SHUTDOWN_TIMEOUT, futures) + .is_err() + { + log::error!("timed out waiting on app_will_quit"); + } + #[cfg(target_family = "wasm")] + self.foreground_executor.spawn(futures).detach(); + + self.quitting = false; + } + + /// Get the id of the current keyboard layout + pub fn keyboard_layout(&self) -> &dyn PlatformKeyboardLayout { + self.keyboard_layout.as_ref() + } + + /// Get the current keyboard mapper. + pub fn keyboard_mapper(&self) -> &Rc { + &self.keyboard_mapper + } + + /// Invokes a handler when the current keyboard layout changes + pub fn on_keyboard_layout_change(&self, mut callback: F) -> Subscription + where + F: 'static + FnMut(&mut App), + { + let (subscription, activate) = self.keyboard_layout_observers.insert( + (), + Box::new(move |cx| { + callback(cx); + true + }), + ); + activate(); + subscription + } + + /// Gracefully quit the application via the platform's standard routine. + pub fn quit(&self) { + self.platform.quit(); + } + + /// Switches the platform between headless and windowed modes. + /// + /// On Linux, headless means no display server: windows opened afterwards lay out and handle + /// input but draw nothing. Windowed, the platform connects to the display server the + /// environment names. On macOS, the modes set the [`ActivationPolicy`]: headless is + /// `Accessory` (no Dock icon or menu bar) and windowed is `Regular`. Switching to windowed + /// doesn't activate the app: call [`App::activate`] for that. + /// + /// The returned task resolves once the switch has been applied. It fails if the platform is + /// already in the requested mode (switching to another display server means going headless + /// first), if the platform doesn't allow the mode or can't switch at all, if any window is + /// open (a window belongs to the display server that opened it), or if the display server + /// can't be reached. + pub fn request_windowing(&self, request: WindowingRequest) -> Task> { + if !self.windows.is_empty() { + return Task::ready(Err(anyhow::anyhow!( + "cannot switch windowing modes while windows are open" + ))); + } + self.platform.request_windowing(request) + } + + /// The environment of the display server the platform is connected to, or `None` while + /// headless. Its activation token is always unset, since the connection has used it. + /// + /// Programs an app launches inherit this process's environment, which may name another + /// graphical session, or none if the app started headless. Pass them this one with + /// [`GraphicalEnvironment::apply_to`](crate::GraphicalEnvironment::apply_to). + /// + /// On macOS, the environment carries nothing, and this is `None` while the activation + /// policy is `Accessory`. Always `None` on platforms that can't switch windowing modes. + pub fn graphical_environment(&self) -> Option { + self.platform.graphical_environment() + } + + /// Returns the current policy for hiding the cursor in response to + /// keyboard input. + pub fn cursor_hide_mode(&self) -> CursorHideMode { + self.cursor_hide_mode + } + + /// Sets the policy controlling when GPUI hides the cursor in response + /// to keyboard input. + pub fn set_cursor_hide_mode(&mut self, mode: CursorHideMode) { + self.cursor_hide_mode = mode; + } + + /// Returns whether the cursor is currently visible according to the + /// platform. This will report `false` after a keyboard input has hidden + /// the cursor and the user has not yet moved the mouse to restore it. + /// + /// See [`App::set_cursor_hide_mode`]. + pub fn is_cursor_visible(&self) -> bool { + self.platform.is_cursor_visible() + } + + /// Returns whether non-essential animations (e.g. loading spinners) should + /// be rendered in a static state instead of animating. + pub fn reduce_motion(&self) -> bool { + self.reduce_motion + } + + /// Sets whether non-essential animations (e.g. loading spinners) should be + /// rendered in a static state instead of animating. + pub fn set_reduce_motion(&mut self, reduce_motion: bool) { + if self.reduce_motion != reduce_motion { + self.reduce_motion = reduce_motion; + self.refresh_windows(); + } + } + + /// Schedules all windows in the application to be redrawn. This can be called + /// multiple times in an update cycle and still result in a single redraw. + pub fn refresh_windows(&mut self) { + self.pending_effects.push_back(Effect::RefreshWindows); + } + + #[inline(always)] + pub(crate) fn update(&mut self, update: impl FnOnce(&mut Self) -> R) -> R { + self.start_update(); + let result = update(self); + self.finish_update(); + result + } + + pub(crate) fn start_update(&mut self) { + self.pending_updates += 1; + } + + #[inline(never)] + pub(crate) fn finish_update(&mut self) { + if !self.flushing_effects && self.pending_updates == 1 { + self.flushing_effects = true; + self.flush_effects(); + self.flushing_effects = false; + } + self.pending_updates -= 1; + } + + /// Arrange a callback to be invoked when the given entity calls `notify` on its respective context. + pub fn observe( + &mut self, + entity: &Entity, + mut on_notify: impl FnMut(Entity, &mut App) + 'static, + ) -> Subscription + where + W: 'static, + { + self.observe_internal(entity, move |e, cx| { + on_notify(e, cx); + true + }) + } + + pub(crate) fn detect_accessed_entities( + &mut self, + callback: impl FnOnce(&mut App) -> R, + ) -> (R, FxHashSet) { + let accessed_entities_start = self.entities.accessed_entities.get_mut().clone(); + let result = callback(self); + let entities_accessed_in_callback = self + .entities + .accessed_entities + .get_mut() + .difference(&accessed_entities_start) + .copied() + .collect::>(); + (result, entities_accessed_in_callback) + } + + pub(crate) fn record_entities_accessed( + &mut self, + window_handle: AnyWindowHandle, + invalidator: WindowInvalidator, + entities: &FxHashSet, + ) { + let mut tracked_entities = + std::mem::take(self.tracked_entities.entry(window_handle.id).or_default()); + for entity in tracked_entities.iter() { + self.window_invalidators_by_entity + .entry(*entity) + .and_modify(|windows| { + windows.remove(&window_handle.id); + }); + } + for entity in entities.iter() { + self.window_invalidators_by_entity + .entry(*entity) + .or_default() + .insert(window_handle.id, invalidator.clone()); + self.current_window_by_entity + .insert(*entity, window_handle.id); + } + tracked_entities.clear(); + tracked_entities.extend(entities.iter().copied()); + self.tracked_entities + .insert(window_handle.id, tracked_entities); + } + + pub(crate) fn new_observer(&mut self, key: EntityId, value: Handler) -> Subscription { + let (subscription, activate) = self.observers.insert(key, value); + self.defer(move |_| activate()); + subscription + } + + pub(crate) fn observe_internal( + &mut self, + entity: &Entity, + mut on_notify: impl FnMut(Entity, &mut App) -> bool + 'static, + ) -> Subscription + where + W: 'static, + { + let entity_id = entity.entity_id(); + let handle = entity.downgrade(); + self.new_observer( + entity_id, + Box::new(move |cx| { + if let Some(entity) = handle.upgrade() { + on_notify(entity, cx) + } else { + false + } + }), + ) + } + + /// Arrange for the given callback to be invoked whenever the given entity emits an event of a given type. + /// The callback is provided a handle to the emitting entity and a reference to the emitted event. + pub fn subscribe( + &mut self, + entity: &Entity, + mut on_event: impl FnMut(Entity, &Event, &mut App) + 'static, + ) -> Subscription + where + T: 'static + EventEmitter, + Event: 'static, + { + self.subscribe_internal(entity, move |entity, event, cx| { + on_event(entity, event, cx); + true + }) + } + + pub(crate) fn new_subscription( + &mut self, + key: EntityId, + value: (TypeId, Listener), + ) -> Subscription { + let (subscription, activate) = self.event_listeners.insert(key, value); + self.defer(move |_| activate()); + subscription + } + pub(crate) fn subscribe_internal( + &mut self, + entity: &Entity, + mut on_event: impl FnMut(Entity, &Evt, &mut App) -> bool + 'static, + ) -> Subscription + where + T: 'static + EventEmitter, + Evt: 'static, + { + let entity_id = entity.entity_id(); + let handle = entity.downgrade(); + self.new_subscription( + entity_id, + ( + TypeId::of::(), + Box::new(move |event, cx| { + let event: &Evt = event.downcast_ref().expect("invalid event type"); + if let Some(entity) = handle.upgrade() { + on_event(entity, event, cx) + } else { + false + } + }), + ), + ) + } + + /// Returns handles to all open windows in the application. + /// Each handle could be downcast to a handle typed for the root view of that window. + /// To find all windows of a given type, you could filter on + pub fn windows(&self) -> Vec { + self.windows + .keys() + .flat_map(|window_id| self.window_handles.get(&window_id).copied()) + .collect() + } + + /// Returns the window handles ordered by their appearance on screen, front to back. + /// + /// The first window in the returned list is the active/topmost window of the application. + /// + /// This method returns None if the platform doesn't implement the method yet. + pub fn window_stack(&self) -> Option> { + self.platform.window_stack() + } + + /// Returns a handle to the window that is currently focused at the platform level, if one exists. + pub fn active_window(&self) -> Option { + self.platform.active_window() + } + + /// Opens a new window with the given option and the root view returned by the given function. + /// The function is invoked with a `Window`, which can be used to interact with window-specific + /// functionality. + pub fn open_window( + &mut self, + options: crate::WindowOptions, + build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity, + ) -> anyhow::Result> { + self.update(|cx| { + let id = cx.windows.insert(None); + let handle = WindowHandle::new(id); + match Window::new(handle.into(), options, cx) { + Ok(mut window) => { + cx.window_update_stack.push(id); + let root_view = build_root_view(&mut window, cx); + cx.window_update_stack.pop(); + window.root.replace(root_view.into()); + window.defer(cx, |window: &mut Window, cx| window.appearance_changed(cx)); + + // allow a window to draw at least once before returning + // this didn't cause any issues on non windows platforms as it seems we always won the race to on_request_frame + // on windows we quite frequently lose the race and return a window that has never rendered, which leads to a crash + // where DispatchTree::root_node_id asserts on empty nodes + let clear = window.draw(cx); + clear.clear(cx); + + cx.window_handles.insert(id, window.handle); + cx.windows.get_mut(id).unwrap().replace(Box::new(window)); + Ok(handle) + } + Err(e) => { + cx.windows.remove(id); + Err(e) + } + } + }) + } + + /// Instructs the platform to activate the application by bringing it to the foreground. + pub fn activate(&self, ignoring_other_apps: bool) { + self.platform.activate(ignoring_other_apps); + } + + /// Hide the application at the platform level. + pub fn hide(&self) { + self.platform.hide(); + } + + /// Hide other applications at the platform level. + pub fn hide_other_apps(&self) { + self.platform.hide_other_apps(); + } + + /// Unhide other applications at the platform level. + pub fn unhide_other_apps(&self) { + self.platform.unhide_other_apps(); + } + + /// Returns the list of currently active displays. + pub fn displays(&self) -> Vec> { + self.platform.displays() + } + + /// Returns the primary display that will be used for new windows. + pub fn primary_display(&self) -> Option> { + self.platform.primary_display() + } + + /// Returns whether `screen_capture_sources` may work. + pub fn is_screen_capture_supported(&self) -> bool { + self.platform.is_screen_capture_supported() + } + + /// Returns a list of available screen capture sources. + pub fn screen_capture_sources( + &self, + ) -> oneshot::Receiver>>> { + self.platform.screen_capture_sources() + } + + /// Returns the display with the given ID, if one exists. + pub fn find_display(&self, id: DisplayId) -> Option> { + self.displays() + .iter() + .find(|display| display.id() == id) + .cloned() + } + + /// Returns the current thermal state of the system. + pub fn thermal_state(&self) -> ThermalState { + self.platform.thermal_state() + } + + /// Prevents idle sleep while the returned guard is held. + pub fn prevent_idle_sleep(&self, reason: &str) -> Task> { + self.platform.prevent_idle_sleep(reason) + } + + /// Invokes a handler when the thermal state changes + pub fn on_thermal_state_change(&self, mut callback: F) -> Subscription + where + F: 'static + FnMut(&mut App), + { + let (subscription, activate) = self.thermal_state_observers.insert( + (), + Box::new(move |cx| { + callback(cx); + true + }), + ); + activate(); + subscription + } + + /// Invokes a handler when the system is about to sleep. + /// + /// The platform gives the process only a short time before suspending, so + /// handlers should record state or cancel work rather than start it. + pub fn on_system_sleep(&self, mut callback: F) -> Subscription + where + F: 'static + FnMut(&mut App), + { + let (subscription, activate) = self.system_sleep_observers.insert( + (), + Box::new(move |cx| { + callback(cx); + true + }), + ); + activate(); + subscription + } + + /// Invokes a handler when the system wakes from sleep. + pub fn on_system_wake(&self, mut callback: F) -> Subscription + where + F: 'static + FnMut(&mut App), + { + let (subscription, activate) = self.system_wake_observers.insert( + (), + Box::new(move |cx| { + callback(cx); + true + }), + ); + activate(); + subscription + } + + /// Returns the appearance of the application's windows. + pub fn window_appearance(&self) -> WindowAppearance { + self.platform.window_appearance() + } + + /// Overrides the appearance (light/dark) applied to the app's windows, independent of + /// the OS-wide setting. Pass `None` to clear the override and follow the system again. + /// The current value is reported by [`App::window_appearance`]. + /// + /// On macOS this sets the underlying `NSApplication.appearance`, which controls the + /// native window chrome (the window border and titlebar) of every window. Use this + /// when the app uses a dark theme while the system is in light mode (or vice versa) + /// so the window edges render to match the theme. While an appearance is forced, + /// windows stop tracking system light/dark changes; pass `None` to resume following + /// the system. On other platforms this is a no-op. + pub fn set_window_appearance(&self, appearance: Option) { + self.platform.set_window_appearance(appearance); + } + + /// Returns the window button layout configuration when supported. + pub fn button_layout(&self) -> Option { + self.platform.button_layout() + } + + /// Reads data from the platform clipboard. + pub fn read_from_clipboard(&self) -> Option { + self.platform.read_from_clipboard() + } + + /// Reads data from the platform clipboard, resolving once the contents + /// are available. + /// + /// Prefer this over [`App::read_from_clipboard`] in code that can await: + /// on platforms where clipboard access is asynchronous and + /// permission-gated (e.g. web), the synchronous read always returns + /// `None` while this method performs a real read. + pub fn read_from_clipboard_async( + &self, + ) -> Task, ClipboardReadError>> { + self.platform.read_from_clipboard_async() + } + + /// Sets the text rendering mode for the application. + pub fn set_text_rendering_mode(&mut self, mode: TextRenderingMode) { + self.text_rendering_mode.set(mode); + } + + /// Returns the current text rendering mode for the application. + pub fn text_rendering_mode(&self) -> TextRenderingMode { + self.text_rendering_mode.get() + } + + /// Writes data to the platform clipboard. + pub fn write_to_clipboard(&self, item: ClipboardItem) { + self.platform.write_to_clipboard(item) + } + + /// Reads data from the primary selection buffer. + /// Only available on Linux. + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + pub fn read_from_primary(&self) -> Option { + self.platform.read_from_primary() + } + + /// Writes data to the primary selection buffer. + /// Only available on Linux. + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + pub fn write_to_primary(&self, item: ClipboardItem) { + self.platform.write_to_primary(item) + } + + /// Reads data from macOS's "Find" pasteboard. + /// + /// Used to share the current search string between apps. + /// + /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find + #[cfg(target_os = "macos")] + pub fn read_from_find_pasteboard(&self) -> Option { + self.platform.read_from_find_pasteboard() + } + + /// Writes data to macOS's "Find" pasteboard. + /// + /// Used to share the current search string between apps. + /// + /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find + #[cfg(target_os = "macos")] + pub fn write_to_find_pasteboard(&self, item: ClipboardItem) { + self.platform.write_to_find_pasteboard(item) + } + + /// Writes credentials to the platform keychain. + pub fn write_credentials( + &self, + url: &str, + username: &str, + password: &[u8], + ) -> Task> { + self.platform.write_credentials(url, username, password) + } + + /// Reads credentials from the platform keychain. + pub fn read_credentials(&self, url: &str) -> Task)>>> { + self.platform.read_credentials(url) + } + + /// Deletes credentials from the platform keychain. + pub fn delete_credentials(&self, url: &str) -> Task> { + self.platform.delete_credentials(url) + } + + /// Directs the platform's default browser to open the given URL. + pub fn open_url(&self, url: &str) { + self.platform.open_url(url); + } + + /// Registers the given URL scheme (e.g. `zed` for `zed://` urls) to be + /// opened by the current app. + /// + /// On some platforms (e.g. macOS) you may be able to register URL schemes + /// as part of app distribution, but this method exists to let you register + /// schemes at runtime. + pub fn register_url_scheme(&self, scheme: &str) -> Task> { + self.platform.register_url_scheme(scheme) + } + + /// Sets the application's process-wide identity and user-visible name. + /// + /// The identifier is used for platform identity mechanisms such as the + /// Windows AppUserModelID. The name is used wherever the operating system + /// presents the application to the user. Call this once, early in startup, + /// before opening windows or posting notifications. + pub fn set_app_identity(&self, identifier: &str, name: &str) { + self.platform.set_app_identity(identifier, name); + } + + /// Posts a notification to the operating system's notification center. + /// + /// Posting a notification whose [`SystemNotification::tag`] matches an + /// earlier one replaces that notification where the platform supports it. + /// No-op on platforms without notification support, or when delivery is + /// unavailable (e.g. authorization was denied). + pub fn show_system_notification(&self, notification: SystemNotification) { + self.platform.show_system_notification(notification); + } + + /// Removes the delivered or pending notification with this tag. + /// + /// Best-effort: some platforms cannot retract a notification once shown, + /// in which case it ages out of the notification center on its own. + pub fn dismiss_system_notification(&self, tag: &str) { + self.platform.dismiss_system_notification(tag); + } + + /// Registers the handler invoked when the user activates a system + /// notification, either by clicking its body or one of its action + /// buttons. Subsequent registrations replace the handler. + pub fn on_system_notification_response(&self, mut callback: F) + where + F: 'static + FnMut(SystemNotificationResponse, &mut App), + { + let this = self.this.clone(); + self.platform + .on_system_notification_response(Box::new(move |response| { + if let Some(app) = this.upgrade() { + callback(response, &mut app.borrow_mut()); + } + })); + } + + /// Returns the full pathname of the current app bundle. + /// + /// Returns an error if the app is not being run from a bundle. + pub fn app_path(&self) -> Result { + self.platform.app_path() + } + + /// On Linux, returns the name of the compositor in use. + /// + /// Returns an empty string on other platforms. + pub fn compositor_name(&self) -> &'static str { + self.platform.compositor_name() + } + + /// Returns the file URL of the executable with the specified name in the application bundle + pub fn path_for_auxiliary_executable(&self, name: &str) -> Result { + self.platform.path_for_auxiliary_executable(name) + } + + /// Displays a platform modal for selecting paths. + /// + /// When one or more paths are selected, they'll be relayed asynchronously via the returned oneshot channel. + /// If cancelled, a `None` will be relayed instead. + /// May return an error on Linux if the file picker couldn't be opened. + pub fn prompt_for_paths( + &self, + options: PathPromptOptions, + ) -> oneshot::Receiver>>> { + self.platform.prompt_for_paths(options) + } + + /// Displays a platform modal for selecting a new path where a file can be saved. + /// + /// The provided directory will be used to set the initial location. + /// When a path is selected, it is relayed asynchronously via the returned oneshot channel. + /// If cancelled, a `None` will be relayed instead. + /// May return an error on Linux if the file picker couldn't be opened. + pub fn prompt_for_new_path( + &self, + directory: &Path, + suggested_name: Option<&str>, + ) -> oneshot::Receiver>> { + self.platform.prompt_for_new_path(directory, suggested_name) + } + + /// Reveals the specified path at the platform level, such as in Finder on macOS. + pub fn reveal_path(&self, path: &Path) { + self.platform.reveal_path(path) + } + + /// Opens the specified path with the system's default application. + pub fn open_with_system(&self, path: &Path) { + self.platform.open_with_system(path) + } + + /// Returns whether the user has configured scrollbars to auto-hide at the platform level. + pub fn should_auto_hide_scrollbars(&self) -> bool { + self.platform.should_auto_hide_scrollbars() + } + + /// Restarts the application. + pub fn restart(&mut self) { + self.restart_observers + .clone() + .retain(&(), |observer| observer(self)); + self.platform.restart( + self.restart_path.take(), + std::mem::take(&mut self.restart_arguments), + ) + } + + /// Sets the path to use when restarting the application. + pub fn set_restart_path(&mut self, path: PathBuf) { + self.restart_path = Some(path); + } + + /// Returns the HTTP client for the application. + pub fn http_client(&self) -> Arc { + self.http_client.clone() + } + + /// Sets the HTTP client for the application. + pub fn set_http_client(&mut self, new_client: Arc) { + self.http_client = new_client; + } + + /// Configures when the application should automatically quit. + /// By default, [`QuitMode::Default`] is used. + pub fn set_quit_mode(&mut self, mode: QuitMode) { + self.quit_mode = mode; + } + + /// Sets whether the application participates in the system's foreground UI. + /// + /// Only has an effect on macOS, where [`Self::request_windowing`] normally sets it. Use this + /// for an accessory app that shows windows, such as a menu bar utility. It overrides the + /// policy until the next [`Self::request_windowing`], and the app counts as headless while + /// `Accessory`. After switching to [`ActivationPolicy::Regular`], activate the app yourself + /// with [`Self::activate`]; otherwise its menu bar may not appear until the app is + /// reactivated. + pub fn set_activation_policy(&mut self, policy: ActivationPolicy) { + self.platform.set_activation_policy(policy); + } + + /// Returns the SVG renderer used by the application. + pub fn svg_renderer(&self) -> SvgRenderer { + self.svg_renderer.clone() + } + + pub(crate) fn push_effect(&mut self, effect: Effect) { + match &effect { + Effect::Notify { emitter } => { + if !self.pending_notifications.insert(*emitter) { + return; + } + } + Effect::NotifyGlobalObservers { global_type } => { + if !self.pending_global_notifications.insert(*global_type) { + return; + } + } + _ => {} + }; + + self.pending_effects.push_back(effect); + } + + /// Called at the end of [`App::update`] to complete any side effects + /// such as notifying observers, emitting events, etc. Effects can themselves + /// cause effects, so we continue looping until all effects are processed. + fn flush_effects(&mut self) { + loop { + self.release_dropped_entities(); + self.release_dropped_focus_handles(); + if let Some(effect) = self.pending_effects.pop_front() { + match effect { + Effect::Notify { emitter } => { + self.apply_notify_effect(emitter); + } + + Effect::Emit { + emitter, + event_type, + event, + } => self.apply_emit_effect(emitter, event_type, &*event), + + Effect::RefreshWindows => { + self.apply_refresh_effect(); + } + + Effect::NotifyGlobalObservers { global_type } => { + self.apply_notify_global_observers_effect(global_type); + } + + Effect::Defer { callback } => { + self.apply_defer_effect(callback); + } + Effect::EntityCreated { + entity, + tid, + window, + } => { + self.apply_entity_created_effect(entity, tid, window); + } + } + } else { + #[cfg(any(test, feature = "test-support"))] + if matches!(self.mode, GpuiMode::Test { .. }) { + for window in self + .windows + .values() + .filter_map(|window| { + let window = window.as_deref()?; + window.invalidator.is_dirty().then_some(window.handle) + }) + .collect::>() + { + self.update_window(window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + } + } + + if self.pending_effects.is_empty() { + for window in self.windows.values().filter_map(|window| window.as_deref()) { + if window.invalidator.is_dirty() + || window.needs_present.get() + || !window.next_frame_callbacks.borrow().is_empty() + { + window.platform_window.schedule_frame(); + } + } + + self.event_arena.clear(); + break; + } + } + } + } + + /// Repeatedly called during `flush_effects` to release any entities whose + /// reference count has become zero. We invoke any release observers before dropping + /// each entity. + fn release_dropped_entities(&mut self) { + loop { + let dropped = self.entities.take_dropped(); + if dropped.is_empty() { + break; + } + + for (entity_id, mut entity) in dropped { + self.observers.remove(&entity_id); + self.event_listeners.remove(&entity_id); + self.window_invalidators_by_entity.remove(&entity_id); + self.current_window_by_entity.remove(&entity_id); + for release_callback in self.release_listeners.remove(&entity_id) { + release_callback(entity.as_mut(), self); + } + } + } + } + + /// Repeatedly called during `flush_effects` to handle a focused handle being dropped. + fn release_dropped_focus_handles(&mut self) { + self.focus_handles + .clone() + .write() + .retain(|handle_id, focus| { + if focus.ref_count.load(SeqCst) == 0 { + for window_handle in self.windows() { + window_handle + .update(self, |_, window, cx| { + if window.focus == Some(handle_id) { + window.blur(cx); + } + }) + .unwrap(); + } + false + } else { + true + } + }); + } + + fn apply_notify_effect(&mut self, emitter: EntityId) { + self.pending_notifications.remove(&emitter); + + self.observers + .clone() + .retain(&emitter, |handler| handler(self)); + } + + fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: &dyn Any) { + self.event_listeners + .clone() + .retain(&emitter, |(stored_type, handler)| { + if *stored_type == event_type { + handler(event, self) + } else { + true + } + }); + } + + fn apply_refresh_effect(&mut self) { + for window in self.windows.values_mut() { + if let Some(window) = window.as_deref_mut() { + window.refreshing = true; + window.invalidator.set_dirty(true); + } + } + } + + fn apply_notify_global_observers_effect(&mut self, type_id: TypeId) { + self.pending_global_notifications.remove(&type_id); + self.global_observers + .clone() + .retain(&type_id, |observer| observer(self)); + } + + fn apply_defer_effect(&mut self, callback: Box) { + callback(self); + } + + fn apply_entity_created_effect( + &mut self, + entity: AnyEntity, + tid: TypeId, + window: Option, + ) { + // Seed the entity's current window from its creation context so + // `with_window` resolves correctly before the entity has ever been + // rendered. + if let Some(id) = window { + self.current_window_by_entity.insert(entity.entity_id(), id); + } + + self.new_entity_observers.clone().retain(&tid, |observer| { + if let Some(id) = window { + self.update_window_id(id, { + let entity = entity.clone(); + |_, window, cx| (observer)(entity, &mut Some(window), cx) + }) + .expect("All windows should be off the stack when flushing effects"); + } else { + (observer)(entity.clone(), &mut None, self) + } + true + }); + } + + /// Run `f` against the entity's *current* window — the most recently + /// rendered window that referenced the entity, or its creation window if + /// it has yet to be rendered. Returns `None` if the entity has no + /// current window, or if that window has been closed, or if it is + /// already on the update stack. + #[inline(always)] + pub fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let window_id = *self.current_window_by_entity.get(&entity_id)?; + self.update_window_id(window_id, |_, window, cx| f(window, cx)) + .ok() + } + + fn ensure_window(&mut self, entity_id: EntityId, window: WindowId) { + self.current_window_by_entity + .entry(entity_id) + .or_insert(window); + } + + #[inline(always)] + pub(crate) fn update_window_id(&mut self, id: WindowId, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut update = Some(update); + let mut result = None; + self.update_window_erased(id, &mut |arguments| { + if let Some((root_view, window, cx)) = arguments { + result = Some(update.take().unwrap()(root_view, window, cx)); + } else { + drop(update.take()); + drop(result.take()); + } + }); + result.context("window not found") + } + + /// Creates an `AsyncApp`, which can be cloned and has a static lifetime + /// so it can be held across `await` points. + pub fn to_async(&self) -> AsyncApp { + AsyncApp { + app: self.this.clone(), + background_executor: self.background_executor.clone(), + foreground_executor: self.foreground_executor.clone(), + } + } + + /// Obtains a reference to the executor, which can be used to spawn futures. + pub fn background_executor(&self) -> &BackgroundExecutor { + &self.background_executor + } + + /// Whether this app runs on the deterministic test scheduler. See + /// [`BackgroundExecutor::is_test`]. + pub fn is_test(&self) -> bool { + self.background_executor.is_test() + } + + /// Obtains a reference to the executor, which can be used to spawn futures. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + if self.quitting { + panic!("Can't spawn on main thread after on_app_quit") + }; + &self.foreground_executor + } + + /// Returns the foreground work journal for this app's foreground thread. + /// Apps constructed on the same thread share the stream. + #[cfg(feature = "profiler")] + pub fn foreground_journal(&self) -> crate::profiler::journal::ForegroundJournal { + self.foreground_journal.clone() + } + + /// Starts detecting foreground hangs on a dedicated thread. + /// + /// Nothing is spawned unless the app calls this. The thread polls a + /// detector over this app's foreground journal every `config.interval` + /// and passes each poll's incidents, including empty polls, to `on_poll` + /// on that thread. When the app quits, a final poll with + /// [`HangMonitorPollReason::Flush`] runs during shutdown, concurrently + /// with quit handlers and within [`SHUTDOWN_TIMEOUT`], so `on_poll` can + /// deliver batched results. + /// + /// # Errors + /// + /// Fails if the monitor was already started or its thread can't be + /// spawned. + /// + /// [`HangMonitorPollReason::Flush`]: crate::profiler::hang::HangMonitorPollReason::Flush + #[cfg(all(feature = "profiler", not(target_family = "wasm")))] + pub fn start_hang_monitor( + &mut self, + config: crate::profiler::hang::HangMonitorConfig, + on_poll: impl FnMut(crate::profiler::hang::HangMonitorPoll) + Send + 'static, + ) -> Result<(), crate::profiler::hang::HangMonitorError> { + use crate::profiler::hang::{HangDetector, HangMonitor, HangMonitorError}; + + if self.hang_monitor.is_some() { + debug_assert!(false, "the hang monitor was started twice"); + return Err(HangMonitorError::AlreadyStarted); + } + let detector = HangDetector::new( + self.foreground_journal(), + config.threshold, + config.frame_budget, + ); + let monitor = HangMonitor::spawn(detector, config.interval, on_poll) + .map_err(HangMonitorError::Spawn)?; + self.hang_monitor = Some(monitor); + Ok(()) + } + + /// Spawns the future returned by the given function on the main thread. The closure will be invoked + /// with [AsyncApp], which allows the application state to be accessed across await points. + #[track_caller] + #[inline(always)] + pub fn spawn(&self, f: AsyncFn) -> Task + where + AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static, + R: 'static, + { + let mut cx = self.prepare_spawn(); + + self.foreground_executor + .spawn(async move { f(&mut cx).await }.boxed_local()) + } + + /// Spawns the future returned by the given function on the main thread with + /// the given priority. The closure will be invoked with [AsyncApp], which + /// allows the application state to be accessed across await points. + pub fn spawn_with_priority(&self, priority: Priority, f: AsyncFn) -> Task + where + AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static, + R: 'static, + { + if self.quitting { + debug_panic!("Can't spawn on main thread after on_app_quit") + }; + + let mut cx = self.to_async(); + + self.foreground_executor + .spawn_with_priority(priority, async move { f(&mut cx).await }.boxed_local()) + } + + /// Schedules the given function to be run at the end of the current effect cycle, allowing entities + /// that are currently on the stack to be returned to the app. + pub fn defer(&mut self, f: impl FnOnce(&mut App) + 'static) { + self.push_effect(Effect::Defer { + callback: Box::new(f), + }); + } + + /// Accessor for the application's asset source, which is provided when constructing the `App`. + pub fn asset_source(&self) -> &Arc { + &self.asset_source + } + + /// Accessor for the text system. + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// Invokes a callback with grapheme clusters that exhausted font fallback. + /// + /// Registering a callback replaces the previous callback and enables missing-glyph + /// detection. The callback runs on the foreground executor after shaping has + /// released its internal locks. Dropping its subscription disables detection until + /// another callback is registered. + /// + /// Reports are queued without blocking shaping, then deduplicated before delivery. + /// The bounded queue can drop reports on overflow. Dropped reports may be reported + /// again when the text is reshaped; no retry is scheduled automatically. + pub fn on_missing_glyphs( + &self, + callback: impl FnMut(&[MissingGlyph], &mut App) + 'static, + ) -> Subscription { + let registration = self.missing_glyph_callback.replace(Box::new(callback)); + + if let Some(mut receiver) = self.text_system.take_missing_glyph_receiver() { + let callback = self.missing_glyph_callback.clone(); + self.spawn(async move |cx| { + while let Ok(missing_glyphs) = receiver.recv().await { + cx.update(|cx| callback.invoke(&missing_glyphs, cx)); + } + }) + .detach(); + } + self.text_system.enable_missing_glyph_reporting(); + + let callback = self.missing_glyph_callback.clone(); + let text_system = self.text_system.clone(); + Subscription::new(move || { + if callback.remove(®istration) { + text_system.disable_missing_glyph_reporting(); + } + }) + } + + /// Check whether a global of the given type has been assigned. + pub fn has_global(&self) -> bool { + self.globals_by_type.contains_key(&TypeId::of::()) + } + + /// Access the global of the given type. Panics if a global for that type has not been assigned. + #[track_caller] + pub fn global(&self) -> &G { + self.globals_by_type + .get(&TypeId::of::()) + .map(|any_state| any_state.downcast_ref::().unwrap()) + .unwrap_or_else(|| panic!("no state of type {} exists", type_name::())) + } + + /// Access the global of the given type if a value has been assigned. + pub fn try_global(&self) -> Option<&G> { + self.globals_by_type + .get(&TypeId::of::()) + .map(|any_state| any_state.downcast_ref::().unwrap()) + } + + /// Access the global of the given type mutably. Panics if a global for that type has not been assigned. + #[track_caller] + pub fn global_mut(&mut self) -> &mut G { + let global_type = TypeId::of::(); + self.push_effect(Effect::NotifyGlobalObservers { global_type }); + self.globals_by_type + .get_mut(&global_type) + .and_then(|any_state| any_state.downcast_mut::()) + .unwrap_or_else(|| panic!("no state of type {} exists", type_name::())) + } + + /// Access the global of the given type mutably. A default value is assigned if a global of this type has not + /// yet been assigned. + pub fn default_global(&mut self) -> &mut G { + let global_type = TypeId::of::(); + self.push_effect(Effect::NotifyGlobalObservers { global_type }); + self.globals_by_type + .entry(global_type) + .or_insert_with(|| Box::::default()) + .downcast_mut::() + .unwrap() + } + + /// Sets the value of the global of the given type. + pub fn set_global(&mut self, global: G) { + let global_type = TypeId::of::(); + self.push_effect(Effect::NotifyGlobalObservers { global_type }); + self.globals_by_type.insert(global_type, Box::new(global)); + } + + /// Clear all stored globals. Does not notify global observers. + #[cfg(any(test, feature = "test-support"))] + pub fn clear_globals(&mut self) { + self.globals_by_type.drain(); + } + + /// Remove the global of the given type from the app context. Does not notify global observers. + pub fn remove_global(&mut self) -> G { + let global_type = TypeId::of::(); + self.push_effect(Effect::NotifyGlobalObservers { global_type }); + *self + .globals_by_type + .remove(&global_type) + .unwrap_or_else(|| panic!("no global added for {}", type_name::())) + .downcast() + .unwrap() + } + + /// Register a callback to be invoked when a global of the given type is updated. + pub fn observe_global( + &mut self, + mut f: impl FnMut(&mut Self) + 'static, + ) -> Subscription { + let (subscription, activate) = self.global_observers.insert( + TypeId::of::(), + Box::new(move |cx| { + f(cx); + true + }), + ); + self.defer(move |_| activate()); + subscription + } + + /// Move the global of the given type to the stack. + #[track_caller] + pub(crate) fn lease_global(&mut self) -> GlobalLease { + GlobalLease::new( + self.globals_by_type + .remove(&TypeId::of::()) + .with_context(|| format!("no global registered of type {}", type_name::())) + .unwrap(), + ) + } + + /// Restore the global of the given type after it is moved to the stack. + pub(crate) fn end_global_lease(&mut self, lease: GlobalLease) { + let global_type = TypeId::of::(); + + self.push_effect(Effect::NotifyGlobalObservers { global_type }); + self.globals_by_type.insert(global_type, lease.global); + } + + pub(crate) fn new_entity_observer( + &self, + key: TypeId, + value: NewEntityListener, + ) -> Subscription { + let (subscription, activate) = self.new_entity_observers.insert(key, value); + activate(); + subscription + } + + /// Arrange for the given function to be invoked whenever a view of the specified type is created. + /// The function will be passed a mutable reference to the view along with an appropriate context. + pub fn observe_new( + &self, + on_new: impl 'static + Fn(&mut T, Option<&mut Window>, &mut Context), + ) -> Subscription { + self.new_entity_observer( + TypeId::of::(), + Box::new( + move |any_entity: AnyEntity, window: &mut Option<&mut Window>, cx: &mut App| { + any_entity + .downcast::() + .unwrap() + .update(cx, |entity_state, cx| { + on_new(entity_state, window.as_deref_mut(), cx) + }) + }, + ), + ) + } + + /// Observe the release of a entity. The callback is invoked after the entity + /// has no more strong references but before it has been dropped. + pub fn observe_release( + &self, + handle: &Entity, + on_release: impl FnOnce(&mut T, &mut App) + 'static, + ) -> Subscription + where + T: 'static, + { + let (subscription, activate) = self.release_listeners.insert( + handle.entity_id(), + Box::new(move |entity, cx| { + let entity = entity.downcast_mut().expect("invalid entity type"); + on_release(entity, cx) + }), + ); + activate(); + subscription + } + + /// Observe the release of a entity. The callback is invoked after the entity + /// has no more strong references but before it has been dropped. + pub fn observe_release_in( + &self, + handle: &Entity, + window: &Window, + on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static, + ) -> Subscription + where + T: 'static, + { + let window_handle = window.handle; + self.observe_release(handle, move |entity, cx| { + let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx)); + }) + } + + /// Register a callback to be invoked after a keystroke is resolved in any window, + /// including the action that handled it, if any. Keystrokes consumed by an + /// interceptor or raw keyboard event handler are not observed. + /// Standalone modifiers are observed on release. + pub fn observe_keystrokes( + &mut self, + mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static, + ) -> Subscription { + fn inner( + keystroke_observers: &SubscriberSet<(), KeystrokeObserver>, + handler: KeystrokeObserver, + ) -> Subscription { + let (subscription, activate) = keystroke_observers.insert((), handler); + activate(); + subscription + } + + inner( + &self.keystroke_observers, + Box::new(move |event, window, cx| { + f(event, window, cx); + true + }), + ) + } + + /// Register a callback to be invoked when a keystroke is received by the application + /// in any window. Note that this fires _before_ all other action and event mechanisms have resolved + /// unlike [`App::observe_keystrokes`] which fires after. This means that `cx.stop_propagation` calls + /// within interceptors will prevent action dispatch + pub fn intercept_keystrokes( + &mut self, + mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static, + ) -> Subscription { + fn inner( + keystroke_interceptors: &SubscriberSet<(), KeystrokeObserver>, + handler: KeystrokeObserver, + ) -> Subscription { + let (subscription, activate) = keystroke_interceptors.insert((), handler); + activate(); + subscription + } + + inner( + &self.keystroke_interceptors, + Box::new(move |event, window, cx| { + f(event, window, cx); + true + }), + ) + } + + /// Register key bindings. + pub fn bind_keys(&mut self, bindings: impl IntoIterator) { + self.keymap.borrow_mut().add_bindings(bindings); + self.pending_effects.push_back(Effect::RefreshWindows); + } + + /// Clear all key bindings in the app. + pub fn clear_key_bindings(&mut self) { + self.keymap.borrow_mut().clear(); + self.pending_effects.push_back(Effect::RefreshWindows); + } + + /// Get all key bindings in the app. + pub fn key_bindings(&self) -> Rc> { + self.keymap.clone() + } + + /// Register a global handler for actions invoked via the keyboard. These handlers are run at + /// the end of the bubble phase for actions, and so will only be invoked if there are no other + /// handlers or if they called `cx.propagate()`. + pub fn on_action( + &mut self, + listener: impl Fn(&A, &mut Self) + 'static, + ) -> &mut Self { + self.global_action_listeners + .entry(TypeId::of::()) + .or_default() + .push(Rc::new(move |action, phase, cx| { + if phase == DispatchPhase::Bubble { + let action = action.downcast_ref().unwrap(); + listener(action, cx) + } + })); + self + } + + /// Event handlers propagate events by default. Call this method to stop dispatching to + /// event handlers with a lower z-index (mouse) or higher in the tree (keyboard). This is + /// the opposite of [`Self::propagate`]. It's also possible to cancel a call to [`Self::propagate`] by + /// calling this method before effects are flushed. + pub fn stop_propagation(&mut self) { + self.propagate_event = false; + } + + /// Action handlers stop propagation by default during the bubble phase of action dispatch + /// dispatching to action handlers higher in the element tree. This is the opposite of + /// [`Self::stop_propagation`]. It's also possible to cancel a call to [`Self::stop_propagation`] by calling + /// this method before effects are flushed. + pub fn propagate(&mut self) { + self.propagate_event = true; + } + + /// Build an action from some arbitrary data, typically a keymap entry. + pub fn build_action( + &self, + name: &str, + data: Option, + ) -> std::result::Result, ActionBuildError> { + self.actions.build_action(name, data) + } + + /// Get all action names that have been registered. Note that registration only allows for + /// actions to be built dynamically, and is unrelated to binding actions in the element tree. + pub fn all_action_names(&self) -> &[&'static str] { + self.actions.all_action_names() + } + + /// Returns key bindings that invoke the given action on the currently focused element, without + /// checking context. Bindings are returned in the order they were added. For display, the last + /// binding should take precedence. + pub fn all_bindings_for_input(&self, input: &[Keystroke]) -> Vec { + RefCell::borrow(&self.keymap).all_bindings_for_input(input) + } + + /// Get all non-internal actions that have been registered, along with their schemas. + pub fn action_schemas( + &self, + generator: &mut schemars::SchemaGenerator, + ) -> Vec<(&'static str, Option)> { + self.actions.action_schemas(generator) + } + + /// Get the schema for a specific action by name. + /// Returns `None` if the action is not found. + /// Returns `Some(None)` if the action exists but has no schema. + /// Returns `Some(Some(schema))` if the action exists and has a schema. + pub fn action_schema_by_name( + &self, + name: &str, + generator: &mut schemars::SchemaGenerator, + ) -> Option> { + self.actions.action_schema_by_name(name, generator) + } + + /// Get a map from a deprecated action name to the canonical name. + pub fn deprecated_actions_to_preferred_actions(&self) -> &HashMap<&'static str, &'static str> { + self.actions.deprecated_aliases() + } + + /// Get a map from an action name to the deprecation messages. + pub fn action_deprecation_messages(&self) -> &HashMap<&'static str, &'static str> { + self.actions.deprecation_messages() + } + + /// Get a map from an action name to the documentation. + pub fn action_documentation(&self) -> &HashMap<&'static str, &'static str> { + self.actions.documentation() + } + + /// Register a callback to be invoked when the application is about to quit. + /// It is not possible to cancel the quit event at this point. + pub fn on_app_quit( + &self, + mut on_quit: impl FnMut(&mut App) -> Fut + 'static, + ) -> Subscription + where + Fut: 'static + Future, + { + let (subscription, activate) = self.quit_observers.insert( + (), + Box::new(move |cx| { + let future = on_quit(cx); + future.boxed_local() + }), + ); + activate(); + subscription + } + + /// Register a callback to be invoked when the application is about to restart. + /// + /// These callbacks are called before any `on_app_quit` callbacks. + pub fn on_app_restart(&self, mut on_restart: impl 'static + FnMut(&mut App)) -> Subscription { + let (subscription, activate) = self.restart_observers.insert( + (), + Box::new(move |cx| { + on_restart(cx); + true + }), + ); + activate(); + subscription + } + + /// Register a callback to be invoked when a window is closed + /// The window is no longer accessible at the point this callback is invoked. + pub fn on_window_closed( + &self, + mut on_closed: impl FnMut(&mut App, WindowId) + 'static, + ) -> Subscription { + let (subscription, activate) = self.window_closed_observers.insert((), Box::new(on_closed)); + activate(); + subscription + } + + pub(crate) fn clear_pending_keystrokes(&mut self) { + for window in self.windows() { + window + .update(self, |_, window, cx| { + window.clear_pending_keystrokes(cx); + }) + .ok(); + } + } + + /// Checks if the given action is bound in the current context, as defined by the app's current focus, + /// the bindings in the element tree, and any global action listeners. + pub fn is_action_available(&mut self, action: &dyn Action) -> bool { + let mut action_available = false; + if let Some(window) = self.active_window() + && let Ok(window_action_available) = + window.update(self, |_, window, cx| window.is_action_available(action, cx)) + { + action_available = window_action_available; + } + + action_available + || self + .global_action_listeners + .contains_key(&action.as_any().type_id()) + } + + /// Sets the menu bar for this application. This will replace any existing menu bar. + pub fn set_menus(&self, menus: impl IntoIterator) { + let menus: Vec = menus.into_iter().collect(); + self.platform.set_menus(menus, &self.keymap.borrow()); + } + + /// Gets the menu bar for this application. + pub fn get_menus(&self) -> Option> { + self.platform.get_menus() + } + + /// Sets the right click menu for the app icon in the dock + pub fn set_dock_menu(&self, menus: Vec) { + self.platform.set_dock_menu(menus, &self.keymap.borrow()) + } + + /// Performs the action associated with the given dock menu item, only used on Windows for now. + pub fn perform_dock_menu_action(&self, action: usize) { + self.platform.perform_dock_menu_action(action); + } + + /// Adds given path to the bottom of the list of recent paths for the application. + /// The list is usually shown on the application icon's context menu in the dock, + /// and allows to open the recent files via that context menu. + /// If the path is already in the list, it will be moved to the bottom of the list. + pub fn add_recent_document(&self, path: &Path) { + self.platform.add_recent_document(path); + } + + /// Updates the jump list with the updated list of recent paths for the application, only used on Windows for now. + /// Note that this also sets the dock menu on Windows. + pub fn update_jump_list( + &self, + menus: Vec, + entries: Vec>, + ) -> Task>> { + self.platform.update_jump_list(menus, entries) + } + + /// Dispatch an action to the currently active window or global action handler + /// See [`crate::Action`] for more information on how actions work + pub fn dispatch_action(&mut self, action: &dyn Action) { + if let Some(active_window) = self.active_window() { + active_window + .update(self, |_, window, cx| { + window.dispatch_action(action.boxed_clone(), cx) + }) + .log_err(); + } else { + self.dispatch_global_action(action); + } + } + + fn dispatch_global_action(&mut self, action: &dyn Action) { + self.propagate_event = true; + + if let Some(mut global_listeners) = self + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in &global_listeners { + listener(action.as_any(), DispatchPhase::Capture, self); + if !self.propagate_event { + break; + } + } + + global_listeners.extend( + self.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + self.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } + + if self.propagate_event + && let Some(mut global_listeners) = self + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in global_listeners.iter().rev() { + listener(action.as_any(), DispatchPhase::Bubble, self); + if !self.propagate_event { + break; + } + } + + global_listeners.extend( + self.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + self.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } + } + + /// Is there currently something being dragged? + pub fn has_active_drag(&self) -> bool { + self.active_drag.is_some() + } + + /// Gets the cursor style of the currently active drag operation. + pub fn active_drag_cursor_style(&self) -> Option { + self.active_drag.as_ref().and_then(|drag| drag.cursor_style) + } + + /// Stops active drag and clears any related effects. + pub fn stop_active_drag(&mut self, window: &mut Window) -> bool { + if self.active_drag.is_some() { + self.active_drag = None; + if self.platform_owned_drag.as_ref().is_some_and(|drag| { + drag.source_window == window.window_handle().window_id() + && matches!(&drag.state, PlatformOwnedDragState::RestoredInSourceWindow) + }) { + self.platform_owned_drag = None; + } + window.refresh(); + true + } else { + false + } + } + + pub(crate) fn hand_active_drag_to_platform(&mut self, source_window: WindowId) -> bool { + let Some(drag) = self.active_drag.take() else { + return false; + }; + self.platform_owned_drag = Some(PlatformOwnedDrag { + source_window, + state: PlatformOwnedDragState::Suspended(drag), + }); + true + } + + pub(crate) fn restore_platform_drag(&mut self, source_window: WindowId) -> bool { + let Some(platform_drag) = self + .platform_owned_drag + .as_mut() + .filter(|drag| drag.source_window == source_window) + else { + return false; + }; + let state = std::mem::replace( + &mut platform_drag.state, + PlatformOwnedDragState::RestoredInSourceWindow, + ); + let PlatformOwnedDragState::Suspended(drag) = state else { + return false; + }; + self.active_drag = Some(drag); + true + } + + pub(crate) fn hand_restored_drag_to_platform(&mut self, source_window: WindowId) -> bool { + let Some(platform_drag) = self.platform_owned_drag.as_mut().filter(|drag| { + drag.source_window == source_window + && matches!(&drag.state, PlatformOwnedDragState::RestoredInSourceWindow) + }) else { + return false; + }; + let Some(drag) = self.active_drag.take() else { + return false; + }; + platform_drag.state = PlatformOwnedDragState::Suspended(drag); + true + } + + pub(crate) fn end_platform_drag(&mut self, source_window: WindowId) -> bool { + if !self + .platform_owned_drag + .as_ref() + .is_some_and(|drag| drag.source_window == source_window) + { + return false; + } + self.platform_owned_drag = None; + self.active_drag = None; + true + } + + /// Sets the cursor style for the currently active drag operation. + pub fn set_active_drag_cursor_style( + &mut self, + cursor_style: CursorStyle, + window: &mut Window, + ) -> bool { + if let Some(ref mut drag) = self.active_drag { + drag.cursor_style = Some(cursor_style); + window.refresh(); + true + } else { + false + } + } + + /// Set the prompt renderer for GPUI. This will replace the default or platform specific + /// prompts with this custom implementation. + pub fn set_prompt_builder( + &mut self, + renderer: impl Fn( + PromptLevel, + &str, + Option<&str>, + &[PromptButton], + PromptHandle, + &mut Window, + &mut App, + ) -> RenderablePromptHandle + + 'static, + ) { + self.prompt_builder = Some(PromptBuilder::Custom(Box::new(renderer))); + } + + /// Reset the prompt builder to the default implementation. + pub fn reset_prompt_builder(&mut self) { + self.prompt_builder = Some(PromptBuilder::Default); + } + + /// Remove an asset from GPUI's cache + pub fn remove_asset(&mut self, source: &A::Source) { + let asset_id = (TypeId::of::(), hash(source)); + self.loading_assets.remove(&asset_id); + } + + /// Check whether an asset is present in GPUI's cache (loading or loaded), + /// without fetching it. + #[cfg(any(test, feature = "test-support"))] + pub fn has_asset(&self, source: &A::Source) -> bool { + let asset_id = (TypeId::of::(), hash(source)); + self.loading_assets.contains_key(&asset_id) + } + + /// Starts loading an uncached asset and returns its result once available. + /// + /// Pending loads and completed results are cached until [`Self::remove_asset`]. + /// This method does not subscribe a view to completion notifications. + pub fn fetch_asset(&mut self, source: &A::Source) -> Option { + self.asset_entry::(source).get() + } + + pub(crate) fn asset_entry(&mut self, source: &A::Source) -> &CachedLoad { + let asset_id = (TypeId::of::(), hash(source)); + if !self.loading_assets.contains_key(&asset_id) { + let future = A::load(source.clone(), self); + let entry = CachedLoad::new(future, self); + self.loading_assets.insert(asset_id, Box::new(entry)); + } + self.loading_assets + .get(&asset_id) + .and_then(|entry| entry.downcast_ref()) + .expect("asset cache entries are keyed by their asset type") + } + + /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus + /// for elements rendered within this window. + #[track_caller] + pub fn focus_handle(&self) -> FocusHandle { + FocusHandle::new(&self.focus_handles) + } + + /// Tell GPUI that an entity has changed and observers of it should be notified. + pub fn notify(&mut self, entity_id: EntityId) { + let window_invalidators = mem::take( + self.window_invalidators_by_entity + .entry(entity_id) + .or_default(), + ); + + // `window_invalidators_by_entity` is monotonic, so an entry alone + // doesn't mean the window is currently rendering the entity. Filter + // through `tracked_entities` to keep invalidation tight to windows + // that actually display this entity right now. + let live_invalidators: SmallVec<[WindowInvalidator; 2]> = window_invalidators + .iter() + .filter(|(window_id, _)| { + self.tracked_entities + .get(window_id) + .is_some_and(|set| set.contains(&entity_id)) + }) + .map(|(_, invalidator)| invalidator.clone()) + .collect(); + + if live_invalidators.is_empty() { + if self.pending_notifications.insert(entity_id) { + self.pending_effects + .push_back(Effect::Notify { emitter: entity_id }); + } + } else { + for invalidator in &live_invalidators { + invalidator.invalidate_view(entity_id, self); + } + } + + self.window_invalidators_by_entity + .insert(entity_id, window_invalidators); + } + + /// Returns the name for this [`App`]. + #[cfg(any(test, feature = "test-support", debug_assertions))] + pub fn get_name(&self) -> Option<&'static str> { + self.name + } + + /// Returns `true` if the platform file picker supports selecting a mix of files and directories. + pub fn can_select_mixed_files_and_dirs(&self) -> bool { + self.platform.can_select_mixed_files_and_dirs() + } + + /// Removes an image from the sprite atlas on all windows. + /// + /// If the current window is being updated, it will be removed from `App.windows`, you can use `current_window` to specify the current window. + /// This is a no-op if the image is not in the sprite atlas. + pub fn drop_image(&mut self, image: Arc, current_window: Option<&mut Window>) { + // remove the texture from all other windows + for window in self.windows.values_mut().flatten() { + _ = window.drop_image(image.clone()); + } + + // remove the texture from the current window + if let Some(window) = current_window { + _ = window.drop_image(image); + } + } + + /// Sets the renderer for the inspector. + #[cfg(any(feature = "inspector", debug_assertions))] + pub fn set_inspector_renderer(&mut self, f: crate::InspectorRenderer) { + self.inspector_renderer = Some(f); + } + + /// Registers a renderer specific to an inspector state. + #[cfg(any(feature = "inspector", debug_assertions))] + pub fn register_inspector_element( + &mut self, + factory: impl 'static + Fn(&mut Window, &mut App) -> F, + ) where + F: 'static + FnMut(crate::InspectorElementId, &T, &mut Window, &mut App) -> R, + { + self.inspector_element_registry.register(factory); + } + + /// Initializes gpui's default colors for the application. + /// + /// These colors can be accessed through `cx.default_colors()`. + pub fn init_colors(&mut self) { + self.set_global(GlobalColors(Arc::new(Colors::default()))); + } + + #[inline(never)] + fn update_window_erased( + &mut self, + window_id: WindowId, + update: &mut dyn FnMut(Option<(AnyView, &mut Window, &mut App)>), + ) { + self.update(|cx| { + let Some(mut window) = cx.windows.get_mut(window_id).and_then(Option::take) else { + update(None); + return; + }; + + let root_view = window.root.clone().unwrap(); + + cx.window_update_stack.push(window.handle.id); + update(Some((root_view, &mut window, cx))); + fn trail(window_id: WindowId, window: Box, cx: &mut App) -> Option<()> { + cx.window_update_stack.pop(); + + if window.removed { + cx.end_platform_drag(window_id); + cx.window_handles.remove(&window_id); + cx.windows.remove(window_id); + if let Some(tracked) = cx.tracked_entities.remove(&window_id) { + for entity_id in tracked { + if let Some(windows) = + cx.window_invalidators_by_entity.get_mut(&entity_id) + { + windows.remove(&window_id); + } + if cx.current_window_by_entity.get(&entity_id) == Some(&window_id) { + cx.current_window_by_entity.remove(&entity_id); + } + } + } + + cx.window_closed_observers.clone().retain(&(), |callback| { + callback(cx, window_id); + true + }); + + let quit_on_empty = match cx.quit_mode { + QuitMode::Explicit => false, + QuitMode::LastWindowClosed => true, + QuitMode::Default => cfg!(not(target_os = "macos")), + }; + + if quit_on_empty && cx.windows.is_empty() { + cx.quit(); + } + } else { + cx.windows.get_mut(window_id)?.replace(window); + } + Some(()) + } + if trail(window_id, window, cx).is_none() { + update(None); + } + }); + } + + #[inline(never)] + fn update_entity_erased( + &mut self, + handle: &AnyEntity, + entity_type: &str, + update: &mut dyn FnMut(&mut dyn Any, &mut App), + ) { + self.update(|cx| { + let mut lease = cx.entities.lease_erased(handle, entity_type); + update(lease.entity.as_deref_mut().unwrap(), cx); + cx.entities.end_lease_erased(handle.entity_id, lease); + }); + } + + #[inline(never)] + #[track_caller] + fn prepare_spawn(&self) -> AsyncApp { + if self.quitting { + debug_panic!("Can't spawn on main thread after on_app_quit") + }; + self.to_async() + } +} + +impl AppContext for App { + /// Builds an entity that is owned by the application. + /// + /// The given function will be invoked with a [`Context`] and must return an object representing the entity. An + /// [`Entity`] handle will be returned, which can be used to access the entity in a context. + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + self.update(|cx| { + let slot = cx.entities.reserve(); + let handle = slot.clone(); + let entity = build_entity(&mut Context::new_context(cx, slot.downgrade())); + + cx.push_effect(Effect::EntityCreated { + entity: handle.into_any(), + tid: TypeId::of::(), + window: cx.window_update_stack.last().cloned(), + }); + + cx.entities.insert(slot, entity) + }) + } + + fn reserve_entity(&mut self) -> Reservation { + Reservation(self.entities.reserve()) + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + self.update(|cx| { + let slot = reservation.0; + let entity = build_entity(&mut Context::new_context(cx, slot.downgrade())); + cx.entities.insert(slot, entity) + }) + } + + /// Updates the entity referenced by the given handle. The function is passed a mutable reference to the + /// entity along with a `Context` for the entity. + #[inline(always)] + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let mut update = Some(update); + let mut result = None; + self.update_entity_erased(handle, type_name::(), &mut |entity, cx| { + let value = update.take().unwrap()( + entity.downcast_mut::().unwrap(), + &mut Context::new_context(cx, handle.downgrade()), + ); + result = Some(value); + }); + result.unwrap() + } + + fn as_mut<'a, T>(&'a mut self, handle: &Entity) -> GpuiBorrow<'a, T> + where + T: 'static, + { + GpuiBorrow::new(handle.clone(), self) + } + + #[inline(always)] + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let entity = self.entities.read(handle); + read(entity, self) + } + + fn update_window(&mut self, handle: AnyWindowHandle, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + self.update_window_id(handle.id, update) + } + + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + App::with_window(self, entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let window = self + .windows + .get(window.id) + .context("window not found")? + .as_deref() + .expect("attempted to read a window that is already on the stack"); + + let root_view = window.root.clone().unwrap(); + let view = root_view + .downcast::() + .map_err(|_| anyhow!("root view's type has changed"))?; + + Ok(read(view, self)) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let mut g = self.global::(); + callback(g, self) + } +} + +/// These effects are processed at the end of each application update cycle. +pub(crate) enum Effect { + Notify { + emitter: EntityId, + }, + Emit { + emitter: EntityId, + event_type: TypeId, + event: ArenaBox, + }, + RefreshWindows, + NotifyGlobalObservers { + global_type: TypeId, + }, + Defer { + callback: Box, + }, + EntityCreated { + entity: AnyEntity, + tid: TypeId, + window: Option, + }, +} + +impl std::fmt::Debug for Effect { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Effect::Notify { emitter } => write!(f, "Notify({})", emitter), + Effect::Emit { emitter, .. } => write!(f, "Emit({:?})", emitter), + Effect::RefreshWindows => write!(f, "RefreshWindows"), + Effect::NotifyGlobalObservers { global_type } => { + write!(f, "NotifyGlobalObservers({:?})", global_type) + } + Effect::Defer { .. } => write!(f, "Defer(..)"), + Effect::EntityCreated { entity, .. } => write!(f, "EntityCreated({:?})", entity), + } + } +} + +/// Wraps a global variable value during `update_global` while the value has been moved to the stack. +pub(crate) struct GlobalLease { + global: Box, + global_type: PhantomData, +} + +impl GlobalLease { + fn new(global: Box) -> Self { + GlobalLease { + global, + global_type: PhantomData, + } + } +} + +impl Deref for GlobalLease { + type Target = G; + + fn deref(&self) -> &Self::Target { + self.global.downcast_ref().unwrap() + } +} + +impl DerefMut for GlobalLease { + fn deref_mut(&mut self) -> &mut Self::Target { + self.global.downcast_mut().unwrap() + } +} + +/// Contains state associated with an active drag operation, started by dragging an element +/// within the window or by dragging into the app from the underlying platform. +pub struct AnyDrag { + /// The view used to render this drag + pub view: AnyView, + + /// The value of the dragged item, to be dropped + pub value: Arc, + + /// This is used to render the dragged item in the same place + /// on the original element that the drag was initiated + pub cursor_offset: Point, + + /// The cursor style to use while dragging + pub cursor_style: Option, + + /// Resolves the payload to offer the platform if the drag leaves the window. + /// Invoked at most once per drag gesture, at promotion time. + pub external_payload_source: Option, +} + +/// Lazily resolves the payload handed to the platform when an internal drag is +/// promoted to a native drag session. +pub type ExternalDragPayloadSource = + Box Option + 'static>; + +/// Contains state associated with a tooltip. You'll only need this struct if you're implementing +/// tooltip behavior on a custom element. Otherwise, use [Div::tooltip](crate::Interactivity::tooltip). +#[derive(Clone)] +pub struct AnyTooltip { + /// The view used to display the tooltip + pub view: AnyView, + + /// The absolute position of the mouse when the tooltip was deployed. + pub mouse_position: Point, + + /// Given the bounds of the tooltip, checks whether the tooltip should still be visible and + /// updates its state accordingly. This is needed atop the hovered element's mouse move handler + /// to handle the case where the element is not painted (e.g. via use of `visible_on_hover`). + pub check_visible_and_update: Rc, &mut Window, &mut App) -> bool>, +} + +/// Whether a keystroke should prefer character input or key bindings. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum InputPreference { + /// Prefer typing text over triggering key bindings. + CharacterInput, + /// Dispatch key bindings normally, if any match. + KeyBindings, +} + +/// A keystroke event, and potentially the associated action +#[derive(Debug)] +pub struct KeystrokeEvent { + /// The keystroke that occurred + pub keystroke: Keystroke, + + /// Whether this keystroke should prefer character input or key bindings. + /// This is [`InputPreference::CharacterInput`] when the platform prefers text for the key + /// (e.g. AltGr on Windows) and the focused input accepts text. Interceptors still receive + /// these keystrokes and can consume them. + /// + /// If the keystroke is part of a multi-stroke binding, it still waits as pending input + /// even when this is [`InputPreference::CharacterInput`]. + pub input_preference: InputPreference, + + /// The action that was resolved for the keystroke, if any + pub action: Option>, + + /// The context stack at the time + pub context_stack: Vec, +} + +struct NullHttpClient; + +impl HttpClient for NullHttpClient { + fn send( + &self, + _req: http_client::Request, + ) -> futures::future::BoxFuture< + 'static, + anyhow::Result>, + > { + async move { + anyhow::bail!("No HttpClient available"); + } + .boxed() + } + + fn user_agent(&self) -> Option<&http_client::http::HeaderValue> { + None + } + + fn proxy(&self) -> Option<&Url> { + None + } +} + +/// A mutable reference to an entity owned by GPUI +pub struct GpuiBorrow<'a, T> { + inner: Option>, + app: &'a mut App, +} + +impl<'a, T: 'static> GpuiBorrow<'a, T> { + fn new(inner: Entity, app: &'a mut App) -> Self { + app.start_update(); + let lease = app.entities.lease(&inner); + Self { + inner: Some(lease), + app, + } + } +} + +impl<'a, T: 'static> std::borrow::Borrow for GpuiBorrow<'a, T> { + fn borrow(&self) -> &T { + self.inner.as_ref().unwrap().borrow() + } +} + +impl<'a, T: 'static> std::borrow::BorrowMut for GpuiBorrow<'a, T> { + fn borrow_mut(&mut self) -> &mut T { + self.inner.as_mut().unwrap().borrow_mut() + } +} + +impl<'a, T: 'static> std::ops::Deref for GpuiBorrow<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.inner.as_ref().unwrap() + } +} + +impl<'a, T: 'static> std::ops::DerefMut for GpuiBorrow<'a, T> { + fn deref_mut(&mut self) -> &mut T { + self.inner.as_mut().unwrap() + } +} + +impl<'a, T> Drop for GpuiBorrow<'a, T> { + fn drop(&mut self) { + let lease = self.inner.take().unwrap(); + self.app.notify(lease.id); + self.app.entities.end_lease(lease); + self.app.finish_update(); + } +} + +#[cfg(test)] +mod test { + use std::{ + cell::{Cell, RefCell}, + ffi::OsString, + path::PathBuf, + rc::Rc, + }; + + #[cfg(unix)] + use std::os::unix::ffi::OsStringExt; + + use crate::{ + AppContext, Context, Empty, FallbackFontClass, IntoElement, MissingGlyph, Render, + TestAppContext, Window, + }; + + struct RenderCounter(Rc>); + + impl Render for RenderCounter { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + self.0.set(self.0.get() + 1); + Empty + } + } + + #[gpui::test] + fn async_app_refresh_flushes_refresh_effect(cx: &mut TestAppContext) { + let render_count = Rc::new(Cell::new(0)); + + let _window = cx.add_window({ + let render_count = render_count.clone(); + move |_, _| RenderCounter(render_count) + }); + + cx.run_until_parked(); + let render_count_before_refresh = render_count.get(); + + cx.to_async().refresh(); + + assert_eq!(render_count.get(), render_count_before_refresh + 1); + } + + #[gpui::test] + fn missing_glyph_callbacks_follow_subscription_lifetime(cx: &mut TestAppContext) { + let observed = Rc::new(RefCell::new(Vec::new())); + let subscription = cx.update(|cx| { + let observed = observed.clone(); + cx.on_missing_glyphs(move |missing_glyphs, _| { + observed.borrow_mut().extend_from_slice(missing_glyphs); + }) + }); + cx.update(|cx| { + cx.text_system() + .report_missing_glyphs_in_test(vec![missing_glyph("active")]); + }); + cx.run_until_parked(); + assert_eq!(observed.borrow().as_slice(), &[missing_glyph("active")]); + + let second_observed = Rc::new(RefCell::new(Vec::new())); + let second_subscription = cx.update(|cx| { + let second_observed = second_observed.clone(); + cx.on_missing_glyphs(move |missing_glyphs, _| { + second_observed + .borrow_mut() + .extend_from_slice(missing_glyphs); + }) + }); + cx.update(|cx| { + cx.text_system() + .report_missing_glyphs_in_test(vec![missing_glyph("replacement")]); + }); + cx.run_until_parked(); + assert_eq!(observed.borrow().as_slice(), &[missing_glyph("active")]); + assert_eq!( + second_observed.borrow().as_slice(), + &[missing_glyph("replacement")] + ); + + drop(subscription); + cx.update(|cx| { + cx.text_system() + .report_missing_glyphs_in_test(vec![missing_glyph("after old drop")]); + }); + cx.run_until_parked(); + assert_eq!( + second_observed.borrow().as_slice(), + &[ + missing_glyph("replacement"), + missing_glyph("after old drop") + ] + ); + + drop(second_subscription); + cx.update(|cx| { + cx.text_system() + .report_missing_glyphs_in_test(vec![missing_glyph("inactive")]); + }); + cx.run_until_parked(); + assert_eq!(second_observed.borrow().len(), 2); + } + + #[test] + fn test_gpui_borrow() { + let cx = TestAppContext::single(); + let observation_count = Rc::new(RefCell::new(0)); + + let state = cx.update(|cx| { + let state = cx.new(|_| false); + cx.observe(&state, { + let observation_count = observation_count.clone(); + move |_, _| { + let mut count = observation_count.borrow_mut(); + *count += 1; + } + }) + .detach(); + + state + }); + + cx.update(|cx| { + // Calling this like this so that we don't clobber the borrow_mut above + *std::borrow::BorrowMut::borrow_mut(&mut state.as_mut(cx)) = true; + }); + + cx.update(|cx| { + state.write(cx, false); + }); + + assert_eq!(*observation_count.borrow(), 2); + } + + #[gpui::test] + async fn test_restart_preserves_path_and_arguments(cx: &mut TestAppContext) { + #[cfg(unix)] + let user_data_dir = OsString::from_vec(b"/tmp/zed data/\xff".to_vec()); + #[cfg(not(unix))] + let user_data_dir = OsString::from("C:\\zed data"); + let arguments = vec![OsString::from("--user-data-dir"), user_data_dir]; + let restart_path = PathBuf::from("updated-zed"); + let _application = + super::Application(cx.app.clone()).with_restart_arguments(arguments.clone()); + let restart = cx.expect_restart(); + + cx.update(|cx| { + cx.set_restart_path(restart_path.clone()); + cx.restart(); + }); + + let (path, restart_arguments) = restart.await.expect("restart was not requested"); + assert_eq!(path, Some(restart_path)); + assert_eq!(restart_arguments, arguments); + } + + fn missing_glyph(grapheme: &'static str) -> MissingGlyph { + MissingGlyph::new(grapheme.into(), FallbackFontClass::Proportional) + } +} diff --git a/vendor/gpui-pre/src/app/async_context.rs b/vendor/gpui-pre/src/app/async_context.rs new file mode 100644 index 00000000..7190dff7 --- /dev/null +++ b/vendor/gpui-pre/src/app/async_context.rs @@ -0,0 +1,557 @@ +use crate::{ + AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, + Entity, EntityId, EventEmitter, Focusable, ForegroundExecutor, Global, GpuiBorrow, + PromptButton, PromptLevel, Render, Reservation, Result, Subscription, Task, VisualContext, + Window, WindowHandle, +}; +use anyhow::{Context as _, bail}; +use derive_more::{Deref, DerefMut}; +use futures::channel::oneshot; +use futures::future::FutureExt; +use std::{future::Future, rc::Weak}; + +use super::{Context, WeakEntity}; + +/// An async-friendly version of [App] with a static lifetime so it can be held across `await` points in async code. +/// You're provided with an instance when calling [App::spawn], and you can also create one with [App::to_async]. +/// +/// Internally, this holds a weak reference to an `App`. Methods will panic if the app has been dropped, +/// but this should not happen in practice when using foreground tasks spawned via `cx.spawn()`, +/// as the executor checks if the app is alive before running each task. +#[derive(Clone)] +pub struct AsyncApp { + pub(crate) app: Weak, + pub(crate) background_executor: BackgroundExecutor, + pub(crate) foreground_executor: ForegroundExecutor, +} + +impl AsyncApp { + fn app(&self) -> std::rc::Rc { + self.app + .upgrade() + .expect("app was released before async operation completed") + } +} + +impl AppContext for AsyncApp { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + let app = self.app(); + let mut app = app.borrow_mut(); + app.new(build_entity) + } + + fn reserve_entity(&mut self) -> Reservation { + let app = self.app(); + let mut app = app.borrow_mut(); + app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let app = self.app(); + let mut app = app.borrow_mut(); + app.insert_entity(reservation, build_entity) + } + + #[inline(always)] + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let app = self.app(); + let mut app = app.borrow_mut(); + app.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, _handle: &Entity) -> GpuiBorrow<'a, T> + where + T: 'static, + { + panic!("Cannot as_mut with an async context. Try calling update() first") + } + + #[inline(always)] + fn read_entity(&self, handle: &Entity, callback: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let app = self.app(); + let lock = app.borrow(); + lock.read_entity(handle, callback) + } + + #[inline(always)] + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let app = self.app.upgrade().context("app was released")?; + let mut lock = app.try_borrow_mut()?; + if lock.quitting { + bail!("app is quitting"); + } + lock.update_window(window, f) + } + + #[inline(always)] + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let app = self.app.upgrade()?; + let mut lock = app.try_borrow_mut().ok()?; + if lock.quitting { + return None; + } + lock.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let app = self.app.upgrade().context("app was released")?; + let lock = app.borrow(); + if lock.quitting { + bail!("app is quitting"); + } + lock.read_window(window, read) + } + + #[track_caller] + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let app = self.app(); + let mut lock = app.borrow_mut(); + lock.update(|this| this.read_global(callback)) + } +} + +impl AsyncApp { + /// Schedules all windows in the application to be redrawn. + pub fn refresh(&self) { + let app = self.app(); + let mut lock = app.borrow_mut(); + // A direct call would leave the refresh effect queued, which cannot wake + // a platform render loop that has already parked. + lock.update(|cx| cx.refresh_windows()); + } + + /// Get an executor which can be used to spawn futures in the background. + pub fn background_executor(&self) -> &BackgroundExecutor { + &self.background_executor + } + + /// Whether this app runs on the deterministic test scheduler. See + /// [`BackgroundExecutor::is_test`]. + pub fn is_test(&self) -> bool { + self.background_executor.is_test() + } + + /// Get an executor which can be used to spawn futures in the foreground. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } + + /// Invoke the given function in the context of the app, then flush any effects produced during its invocation. + #[inline(always)] + pub fn update(&self, f: impl FnOnce(&mut App) -> R) -> R { + let app = self.app(); + let mut lock = app.borrow_mut(); + lock.update(f) + } + + /// Arrange for the given callback to be invoked whenever the given entity emits an event of a given type. + /// The callback is provided a handle to the emitting entity and a reference to the emitted event. + pub fn subscribe( + &mut self, + entity: &Entity, + on_event: impl FnMut(Entity, &Event, &mut App) + 'static, + ) -> Subscription + where + T: 'static + EventEmitter, + Event: 'static, + { + let app = self.app(); + let mut lock = app.borrow_mut(); + lock.subscribe(entity, on_event) + } + + /// Open a window with the given options based on the root view returned by the given function. + pub fn open_window( + &self, + options: crate::WindowOptions, + build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity, + ) -> Result> + where + V: 'static + Render, + { + let app = self.app(); + let mut lock = app.borrow_mut(); + if lock.quitting { + bail!("app is quitting"); + } + lock.open_window(options, build_root_view) + } + + /// Schedule a future to be polled in the foreground. + #[track_caller] + #[inline(always)] + pub fn spawn(&self, f: AsyncFn) -> Task + where + AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static, + R: 'static, + { + let mut cx = self.clone(); + self.foreground_executor + .spawn(async move { f(&mut cx).await }.boxed_local()) + } + + /// Determine whether global state of the specified type has been assigned. + pub fn has_global(&self) -> bool { + let app = self.app(); + let app = app.borrow_mut(); + app.has_global::() + } + + /// Reads the global state of the specified type, passing it to the given callback. + /// + /// Panics if no global state of the specified type has been assigned. + #[inline(always)] + pub fn read_global(&self, read: impl FnOnce(&G, &App) -> R) -> R { + let app = self.app(); + let app = app.borrow_mut(); + read(app.global(), &app) + } + + /// Reads the global state of the specified type, passing it to the given callback. + /// + /// Similar to [`AsyncApp::read_global`], but returns an error instead of panicking + pub fn try_read_global(&self, read: impl FnOnce(&G, &App) -> R) -> Option { + let app = self.app(); + let app = app.borrow_mut(); + if app.quitting { + return None; + } + Some(read(app.try_global()?, &app)) + } + + /// Reads the global state of the specified type, passing it to the given callback. + /// A default value is assigned if a global of this type has not yet been assigned. + pub fn read_default_global( + &self, + read: impl FnOnce(&G, &App) -> R, + ) -> R { + let app = self.app(); + let mut app = app.borrow_mut(); + app.update(|cx| { + cx.default_global::(); + }); + read(app.global(), &app) + } + + /// A convenience method for [`App::update_global`](BorrowAppContext::update_global) + /// for updating the global state of the specified type. + pub fn update_global(&self, update: impl FnOnce(&mut G, &mut App) -> R) -> R { + let app = self.app(); + let mut app = app.borrow_mut(); + app.update(|cx| cx.update_global(update)) + } + + /// Run something using this entity and cx, when the returned struct is dropped + pub fn on_drop) + 'static>( + &self, + entity: &WeakEntity, + f: Callback, + ) -> gpui_util::Deferred> { + let entity = entity.clone(); + let mut cx = self.clone(); + gpui_util::defer(move || { + entity.update(&mut cx, f).ok(); + }) + } +} + +/// A cloneable, owned handle to the application context, +/// composed with the window associated with the current task. +#[derive(Clone, Deref, DerefMut)] +pub struct AsyncWindowContext { + #[deref] + #[deref_mut] + app: AsyncApp, + window: AnyWindowHandle, +} + +impl AsyncWindowContext { + pub(crate) fn new_context(app: AsyncApp, window: AnyWindowHandle) -> Self { + Self { app, window } + } + + /// Get the handle of the window this context is associated with. + pub fn window_handle(&self) -> AnyWindowHandle { + self.window + } + + /// A convenience method for [`App::update_window`]. + #[inline(always)] + pub fn update(&mut self, update: impl FnOnce(&mut Window, &mut App) -> R) -> Result { + self.app + .update_window(self.window, |_, window, cx| update(window, cx)) + } + + /// A convenience method for [`App::update_window`]. + #[inline(always)] + pub fn update_root( + &mut self, + update: impl FnOnce(AnyView, &mut Window, &mut App) -> R, + ) -> Result { + self.app.update_window(self.window, update) + } + + /// A convenience method for [`Window::on_next_frame`]. + pub fn on_next_frame(&mut self, f: impl FnOnce(&mut Window, &mut App) + 'static) { + self.app + .update_window(self.window, |_, window, _| window.on_next_frame(f)) + .ok(); + } + + /// A convenience method for [`App::global`]. + pub fn read_global( + &mut self, + read: impl FnOnce(&G, &Window, &App) -> R, + ) -> Result { + self.app + .update_window(self.window, |_, window, cx| read(cx.global(), window, cx)) + } + + /// A convenience method for [`App::update_global`](BorrowAppContext::update_global). + /// for updating the global state of the specified type. + pub fn update_global( + &mut self, + update: impl FnOnce(&mut G, &mut Window, &mut App) -> R, + ) -> Result + where + G: Global, + { + self.app.update_window(self.window, |_, window, cx| { + cx.update_global(|global, cx| update(global, window, cx)) + }) + } + + /// Schedule a future to be executed on the main thread. This is used for collecting + /// the results of background tasks and updating the UI. + #[track_caller] + #[inline(always)] + pub fn spawn(&self, f: AsyncFn) -> Task + where + AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static, + R: 'static, + { + let mut cx = self.clone(); + self.foreground_executor + .spawn(async move { f(&mut cx).await }.boxed_local()) + } + + /// Present a platform dialog. + /// The provided message will be presented, along with buttons for each answer. + /// When a button is clicked, the returned Receiver will receive the index of the clicked button. + pub fn prompt( + &mut self, + level: PromptLevel, + message: &str, + detail: Option<&str>, + answers: &[T], + ) -> oneshot::Receiver + where + T: Clone + Into, + { + self.app + .update_window(self.window, |_, window, cx| { + window.prompt(level, message, detail, answers, cx) + }) + .unwrap_or_else(|_| oneshot::channel().1) + } +} + +impl AppContext for AsyncWindowContext { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity + where + T: 'static, + { + let mut build_entity = Some(build_entity); + match self.app.update_window(self.window, |_, _, cx| { + cx.new( + build_entity + .take() + .expect("build_entity is taken exactly once"), + ) + }) { + Ok(entity) => entity, + Err(_) => self.app.new( + build_entity + .take() + .expect("update_window returned Err without invoking the closure"), + ), + } + } + + fn reserve_entity(&mut self) -> Reservation { + self.app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let mut args = Some((reservation, build_entity)); + match self.app.update_window(self.window, |_, _, cx| { + let (reservation, build_entity) = args.take().expect("args are taken exactly once"); + cx.insert_entity(reservation, build_entity) + }) { + Ok(entity) => entity, + Err(_) => { + let (reservation, build_entity) = args + .take() + .expect("update_window returned Err without invoking the closure"); + self.app.insert_entity(reservation, build_entity) + } + } + } + + #[inline(always)] + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + self.app.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, _: &Entity) -> GpuiBorrow<'a, T> + where + T: 'static, + { + panic!("Cannot use as_mut() from an async context, call `update`") + } + + #[inline(always)] + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + self.app.read_entity(handle, read) + } + + #[inline(always)] + fn update_window(&mut self, window: AnyWindowHandle, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + self.app.update_window(window, update) + } + + #[inline(always)] + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + self.app.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + self.app.read_window(window, read) + } + + #[track_caller] + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.app.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + self.app.read_global(callback) + } +} + +impl VisualContext for AsyncWindowContext { + type Result = Result; + + fn window_handle(&self) -> AnyWindowHandle { + self.window + } + + fn new_window_entity( + &mut self, + build_entity: impl FnOnce(&mut Window, &mut Context) -> T, + ) -> Result> { + self.app.update_window(self.window, |_, window, cx| { + cx.new(|cx| build_entity(window, cx)) + }) + } + + fn update_window_entity( + &mut self, + view: &Entity, + update: impl FnOnce(&mut T, &mut Window, &mut Context) -> R, + ) -> Result { + let view = view.clone(); + self.app + .with_window(view.entity_id(), |window, app| { + view.update(app, |entity, cx| update(entity, window, cx)) + }) + .context("entity has no current window") + } + + fn replace_root_view( + &mut self, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> Result> + where + V: 'static + Render, + { + self.app.update_window(self.window, |_, window, cx| { + window.replace_root(cx, build_view) + }) + } + + fn focus(&mut self, view: &Entity) -> Result<()> + where + V: Focusable, + { + self.app.update_window(self.window, |_, window, cx| { + view.read(cx).focus_handle(cx).focus(window, cx); + }) + } +} diff --git a/vendor/gpui-pre/src/app/bench_context.rs b/vendor/gpui-pre/src/app/bench_context.rs new file mode 100644 index 00000000..2cf504c5 --- /dev/null +++ b/vendor/gpui-pre/src/app/bench_context.rs @@ -0,0 +1,1596 @@ +use std::{ + cell::{OnceCell, RefCell}, + future::Future, + rc::Rc, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, + time::{Duration, Instant}, +}; + +use anyhow::{Result, anyhow}; +pub use bench_metrics::{BenchMeasurement, CountingAllocator, MetricReport}; +use hdrhistogram::Histogram; + +use crate::{ + AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, Bounds, Context, Empty, + Entity, EntityId, Focusable, ForegroundExecutor, Global, Platform, PlatformHeadlessRenderer, + PlatformTextSystem, Render, Reservation, Task, TestPlatform, ThreadedDispatcher, VisualContext, + Window, WindowBounds, WindowHandle, WindowOptions, + app::GpuiBorrow, + profiler::{ + self, FrameEvent, FrameTimingCollector, + journal::{ForegroundEvent, ForegroundJournalCollector, ForegroundJournalEntry}, + }, +}; + +/// Returns a benchmark platform backed by this thread's shared dispatcher. +/// +/// The platform uses this thread's shared multithreaded [`ThreadedDispatcher`], so +/// background work runs with production concurrency in real time. The dispatcher +/// is cached per thread and reused across benchmark invocations so worker and +/// timer threads persist for the whole process instead of being recreated for +/// every Criterion calibration pass. +/// +/// Text is shaped with the provided platform text system. Benchmarks generated +/// by `#[gpui::bench]` use the current platform's text system, so text-heavy +/// benchmark measurements include production shaping and glyph rasterization. +/// +/// `headless_renderer_factory` supplies a renderer for benchmark windows, e.g. +/// `gpui_platform::current_headless_renderer`. When present, scenes drawn by +/// benchmarks are rasterized through the real sprite atlas and submitted to +/// the GPU on present, so quad/sprite regressions show up in measurements. +/// When `None`, presenting discards the scene. Currently only macOS provides +/// a headless renderer (Metal), so GPU submission is excluded from benchmark +/// measurements on other platforms. +pub fn bench_platform( + headless_renderer_factory: Option< + Box anyhow::Result>>>, + >, + text_system: Arc, +) -> Rc { + thread_local! { + static DISPATCHER: OnceCell> = const { OnceCell::new() }; + } + let dispatcher = DISPATCHER.with(|cell| { + cell.get_or_init(|| Arc::new(ThreadedDispatcher::new())) + .clone() + }); + let background_executor = BackgroundExecutor::new(dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(dispatcher); + TestPlatform::with_platform( + background_executor, + foreground_executor, + text_system, + headless_renderer_factory, + ) as Rc +} + +/// Default target frame rate when a benchmark doesn't specify `fps = N`. +const DEFAULT_FPS: u64 = 120; + +const NANOS_PER_SECOND: u128 = 1_000_000_000; + +/// Aggregate statistics for total foreground executor work observed during a +/// measured interval, returned by [`BenchReport::foreground_work`]. +#[derive(Clone, Copy, Debug)] +pub struct ForegroundWorkSummary { + /// Number of foreground work items recorded: task polls, action + /// handlers, input dispatches, and folded sub-floor poll flushes. + pub count: u64, + /// Sum of every recorded item's duration. + pub total: Duration, + /// The longest single recorded item. + pub max: Duration, + /// 50th percentile duration. + pub p50: Duration, + /// 90th percentile duration. + pub p90: Duration, + /// 95th percentile duration. + pub p95: Duration, + /// 99th percentile duration. + pub p99: Duration, + /// How many whole frame budgets (at the report's configured FPS) were + /// exceeded in total, summed across every recorded item. + pub frame_budget_overruns_total: u64, + /// How many whole frame budgets the longest recorded item exceeded. + pub frame_budget_overruns_max: u64, +} + +/// A small report produced by GPUI benchmarks. +#[derive(Clone)] +pub struct BenchReport { + frame_snapshot: Rc>, + metrics: MetricReport, + frame_budget_nanos: u128, +} + +impl Default for BenchReport { + fn default() -> Self { + Self::with_fps(DEFAULT_FPS) + } +} + +impl BenchReport { + /// Creates a report whose per-frame budget is one frame at `fps` when + /// counting frame budget overruns. + pub fn with_fps(fps: u64) -> Self { + assert!(fps > 0, "frame rate must be greater than zero"); + Self::with_frame_budget_nanos(NANOS_PER_SECOND / fps as u128) + } + + /// Creates a report that treats `frame_budget_nanos` as the per-frame budget + /// when counting frame budget overruns. + pub fn with_frame_budget_nanos(frame_budget_nanos: u128) -> Self { + assert!( + frame_budget_nanos > 0, + "frame budget must be at least one nanosecond" + ); + Self { + frame_snapshot: Rc::new(RefCell::new(WindowFrameSnapshot::new())), + metrics: MetricReport::new(), + frame_budget_nanos, + } + } + + /// Returns the per-iteration secondary metrics (retired instructions, + /// cycles, context switches, ...) recorded alongside Criterion's primary + /// measurement. + pub fn metrics(&self) -> &MetricReport { + &self.metrics + } + + fn record_frame_timings<'i>(&self, events: impl IntoIterator) { + let mut snapshot = self.frame_snapshot.borrow_mut(); + // `.ok()` on `record`: this operation is infallible (the histograms auto-resize). + for event in events { + match event { + FrameEvent::Draw(timing) => { + snapshot + .draw + .record(timing.draw_duration().as_nanos() as u64) + .ok(); + if let Some(dirty_to_draw) = timing.dirty_to_draw_duration() { + snapshot + .dirty_to_draw + .record(dirty_to_draw.as_nanos() as u64) + .ok(); + } + if timing.invalidations > 0 { + snapshot + .invalidations_per_frame + .record(timing.invalidations) + .ok(); + } + } + FrameEvent::Present(timing) => { + if let Some(animation_interval) = timing.animation_interval { + snapshot + .present_interval + .record(animation_interval.as_nanos() as u64) + .ok(); + } + } + } + } + } + + /// Records total foreground executor work observed during a measured + /// interval: task polls, action handlers, and input dispatches, whether + /// or not they produced a window draw. Draws and presents are excluded + /// here since [`Self::record_frame_timings`] already accounts for them. + fn record_foreground_events<'i>(&self, events: impl IntoIterator) { + let mut snapshot = self.frame_snapshot.borrow_mut(); + for event in events { + let duration = match event { + ForegroundEvent::Draw(_) | ForegroundEvent::Present(_) => continue, + // A flush's span (used by `ForegroundEvent::duration`) is not + // the time spent polling; its summary total is. + ForegroundEvent::SmallPolls(flush) => flush.summary.total, + _ => event.duration(), + }; + snapshot.foreground_work.record(duration); + } + } + + fn total_budget_overruns(&self, histogram: &Histogram) -> u64 { + histogram + .iter_recorded() + .map(|value| { + self.budget_overruns(Duration::from_nanos(value.value_iterated_to())) + * value.count_at_value() + }) + .sum() + } + + /// Returns how many whole frame budgets `foreground_time` exceeded the + /// per frame budget by. This is a synthetic proxy for missed frames: the + /// benchmark harness has no vsync, so it counts how many frame deadlines + /// would have elapsed while the foreground thread was busy. + fn budget_overruns(&self, foreground_time: Duration) -> u64 { + let foreground_nanos = foreground_time.as_nanos(); + if foreground_nanos <= self.frame_budget_nanos { + return 0; + } + + let over_budget_nanos = foreground_nanos - self.frame_budget_nanos; + over_budget_nanos.div_ceil(self.frame_budget_nanos) as u64 + } + + /// Returns aggregate statistics for total foreground executor work + /// observed during the measured interval: every task poll, action + /// handler, and input dispatch on the foreground thread, whether or not + /// it produced a window draw. This is captured through GPUI's foreground + /// journal, so it requires no window and surfaces a slow or stalled task + /// even when nothing was drawn while it ran. + /// + /// Returns `None` when no foreground work was recorded, e.g. a + /// [`BenchAppContext::bench_iter`] measurement that does no async work. + pub fn foreground_work(&self) -> Option { + let frame_snapshot = self.frame_snapshot.borrow(); + let foreground_work = &frame_snapshot.foreground_work; + if foreground_work.histogram.is_empty() { + return None; + } + + let max = Duration::from_nanos(foreground_work.histogram.max()); + Some(ForegroundWorkSummary { + count: foreground_work.histogram.len(), + total: Duration::from_nanos(foreground_work.total_nanos), + max, + p50: Duration::from_nanos(foreground_work.histogram.value_at_quantile(0.50)), + p90: Duration::from_nanos(foreground_work.histogram.value_at_quantile(0.90)), + p95: Duration::from_nanos(foreground_work.histogram.value_at_quantile(0.95)), + p99: Duration::from_nanos(foreground_work.histogram.value_at_quantile(0.99)), + frame_budget_overruns_total: self.total_budget_overruns(&foreground_work.histogram), + frame_budget_overruns_max: self.budget_overruns(max), + }) + } + + /// Prints this report to stderr. + pub fn print(&self, benchmark_name: &str) { + let frame_snapshot = self.frame_snapshot.borrow(); + if frame_snapshot.is_empty() && self.metrics.is_empty() { + return; + } + + eprintln!("GPUI bench report (all observed iterations): {benchmark_name}"); + eprintln!(" note: includes Criterion warmup/calibration"); + self.metrics.print(" "); + self.print_histogram("window dirty-to-draw", &frame_snapshot.dirty_to_draw); + self.print_histogram("window draw", &frame_snapshot.draw); + self.print_histogram("window present interval", &frame_snapshot.present_interval); + if !frame_snapshot.invalidations_per_frame.is_empty() { + eprintln!( + " invalidations per frame: mean {:.2}, max {}", + frame_snapshot.invalidations_per_frame.mean(), + frame_snapshot.invalidations_per_frame.max() + ); + } + self.print_foreground_work(&frame_snapshot.foreground_work); + } + + fn print_histogram(&self, name: &str, histogram: &Histogram) { + if histogram.is_empty() { + return; + } + + eprintln!(" {name}:"); + self.print_histogram_body(histogram); + } + + fn print_foreground_work(&self, foreground_work: &DurationHistogram) { + if foreground_work.histogram.is_empty() { + return; + } + + eprintln!(" foreground executor work (task polls, actions, input dispatch):"); + eprintln!(" note: excludes window draw/present, reported separately above"); + eprintln!( + " total: {}", + format_duration(Duration::from_nanos(foreground_work.total_nanos)) + ); + self.print_histogram_body(&foreground_work.histogram); + } + + fn print_histogram_body(&self, histogram: &Histogram) { + let max_foreground_time = Duration::from_nanos(histogram.max()); + eprintln!(" samples: {}", histogram.len()); + eprintln!( + " mean: {}", + format_duration(Duration::from_nanos(histogram.mean() as u64)) + ); + eprintln!( + " p50: {}", + format_duration(Duration::from_nanos(histogram.value_at_quantile(0.50))) + ); + eprintln!( + " p90: {}", + format_duration(Duration::from_nanos(histogram.value_at_quantile(0.90))) + ); + eprintln!( + " p95: {}", + format_duration(Duration::from_nanos(histogram.value_at_quantile(0.95))) + ); + eprintln!( + " p99: {}", + format_duration(Duration::from_nanos(histogram.value_at_quantile(0.99))) + ); + eprintln!(" max: {}", format_duration(max_foreground_time)); + eprintln!( + " frame budget overruns total: {}", + self.total_budget_overruns(histogram) + ); + eprintln!( + " frame budget overruns max: {}", + self.budget_overruns(max_foreground_time) + ); + } +} + +struct WindowFrameSnapshot { + dirty_to_draw: Histogram, + draw: Histogram, + present_interval: Histogram, + invalidations_per_frame: Histogram, + foreground_work: DurationHistogram, +} + +impl WindowFrameSnapshot { + fn new() -> Self { + Self { + dirty_to_draw: Histogram::new(3).expect("3 significant digits is valid"), + draw: Histogram::new(3).expect("3 significant digits is valid"), + present_interval: Histogram::new(3).expect("3 significant digits is valid"), + invalidations_per_frame: Histogram::new(3).expect("3 significant digits is valid"), + foreground_work: DurationHistogram::new(), + } + } + + fn is_empty(&self) -> bool { + self.dirty_to_draw.is_empty() + && self.draw.is_empty() + && self.present_interval.is_empty() + && self.foreground_work.histogram.is_empty() + } +} + +/// A duration histogram paired with an exact running total, since the +/// histogram's bucketed values (3 significant digits) approximate a sum less +/// precisely than tracking it directly. +struct DurationHistogram { + histogram: Histogram, + total_nanos: u64, +} + +impl DurationHistogram { + fn new() -> Self { + Self { + histogram: Histogram::new(3).expect("3 significant digits is valid"), + total_nanos: 0, + } + } + + fn record(&mut self, duration: Duration) { + let nanos = duration.as_nanos() as u64; + // Infallible: the histogram auto-resizes. + self.histogram.record(nanos).ok(); + self.total_nanos += nanos; + } +} + +fn format_duration(duration: Duration) -> String { + format!("{:.3}ms", duration.as_secs_f64() * 1000.) +} + +/// Enables profiler tracing for a measurement and collects its frame events +/// and foreground journal entries. +/// +/// The previous tracing state is restored on drop, so a panicking measurement +/// doesn't leave tracing enabled for unrelated code such as a later benchmark +/// in the same process. +/// +/// The foreground journal collector is created at the same point, so +/// foreground work recorded before the scope starts (e.g. per-iteration +/// setup) is excluded from what [`Self::finish`] returns: a collector only +/// observes entries recorded after its creation. +struct TraceScope { + collector: FrameTimingCollector, + journal_collector: ForegroundJournalCollector, + _trace_guard: profiler::TraceGuard, +} + +impl TraceScope { + fn start(journal_collector: ForegroundJournalCollector) -> Self { + let trace_guard = profiler::trace_scope(); + Self { + collector: FrameTimingCollector::new(), + journal_collector, + _trace_guard: trace_guard, + } + } + + fn finish(mut self) -> TracedEvents { + TracedEvents { + frame_events: self.collector.collect_unseen(), + journal_entries: self.journal_collector.collect_unseen().entries, + } + } +} + +/// Events observed during one [`TraceScope`]. +struct TracedEvents { + frame_events: Vec, + journal_entries: Vec, +} + +impl TracedEvents { + /// Foreground journal entries that describe completed work (task polls, + /// action handlers, input dispatches, draws, presents, and folded + /// sub-floor polls), excluding interval boundaries and metadata. + fn foreground_events(&self) -> impl Iterator { + self.journal_entries.iter().filter_map(|entry| match entry { + ForegroundJournalEntry::Event(event) => Some(event), + _ => None, + }) + } +} + +struct MeasuredTaskInput { + input: Input, + trace_scope: Option, +} + +struct MeasuredTaskOutput { + trace_scope: Option, + report: BenchReport, + _output: Output, +} + +impl Drop for MeasuredTaskOutput { + fn drop(&mut self) { + let trace_scope = self + .trace_scope + .take() + .expect("measured task output should retain its trace scope"); + let events = trace_scope.finish(); + self.report.record_frame_timings(events.frame_events.iter()); + self.report + .record_foreground_events(events.foreground_events()); + } +} + +#[cfg(test)] +fn run_task_to_completion( + foreground_executor: &ForegroundExecutor, + task: Task, +) -> Output +where + Output: 'static, +{ + let output = Rc::new(RefCell::new(None)); + foreground_executor + .spawn({ + let output = output.clone(); + async move { + *output.borrow_mut() = Some(task.await); + } + }) + .detach(); + + foreground_executor + .dispatcher() + .as_threaded() + .expect("BenchAppContext requires a ThreadedDispatcher") + .run_until(|| output.borrow_mut().take()) +} + +/// A GPUI app context for Criterion benchmarks. +/// +/// `BenchAppContext` is intentionally separate from `TestAppContext`: it owns a +/// benchmark app instance and exposes only the app/window operations needed by +/// benchmark setup. Criterion remains responsible for the measured loop via its +/// `Bencher` API. +#[derive(Clone)] +pub struct BenchAppContext<'a, 'measurement> { + app: Rc, + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + benchmark_name: Option<&'static str>, + bencher: Rc>>>, + report: BenchReport, +} + +impl<'a, 'measurement> BenchAppContext<'a, 'measurement> { + /// Creates a new benchmark app context backed by the provided platform. + /// + /// The platform's executors must be backed by a [`ThreadedDispatcher`] + /// (see [`bench_platform`]) so the context can drain foreground work via + /// [`Self::run_until_idle`]; panics otherwise. + pub fn new( + platform: Rc, + benchmark_name: Option<&'static str>, + bencher: &'a mut criterion::Bencher<'measurement, BenchMeasurement>, + ) -> Self { + Self::build(platform, benchmark_name, bencher, BenchReport::default()) + } + + /// Creates a new benchmark app context backed by the provided platform. + /// + /// The platform's executors must be backed by a [`ThreadedDispatcher`] + /// (see [`bench_platform`]) so the context can drain foreground work via + /// [`Self::run_until_idle`]; panics otherwise. + #[doc(hidden)] + pub fn new_with_platform_and_report( + platform: Rc, + benchmark_name: Option<&'static str>, + bencher: &'a mut criterion::Bencher<'measurement, BenchMeasurement>, + report: BenchReport, + ) -> Self { + Self::build(platform, benchmark_name, bencher, report) + } + + fn build( + platform: Rc, + benchmark_name: Option<&'static str>, + bencher: &'a mut criterion::Bencher<'measurement, BenchMeasurement>, + report: BenchReport, + ) -> Self { + let background_executor = platform.background_executor(); + // Validate up front so misconfiguration fails at construction with a + // clear message instead of deep inside `run_until_idle`. + assert!( + background_executor.dispatcher().as_threaded().is_some(), + "BenchAppContext requires a platform whose executors are backed by a \ + ThreadedDispatcher; construct one with gpui::bench_platform" + ); + let foreground_executor = platform.foreground_executor(); + let asset_source = Arc::new(()); + // Benchmark setup must not make accidental network requests. The + // production `BlockedHttpClient` reports them without enabling a + // configurable test double through `test-support`. + let http_client: Arc = + Arc::new(http_client::BlockedHttpClient::new()); + let app = App::new_app(platform, asset_source, http_client); + + Self { + app, + background_executor, + foreground_executor, + benchmark_name, + bencher: Rc::new(RefCell::new(Some(bencher))), + report, + } + } + + /// The benchmark function name that created this context. + pub fn benchmark_name(&self) -> Option<&'static str> { + self.benchmark_name + } + + /// Returns the background executor used by this benchmark app. + pub fn background_executor(&self) -> &BackgroundExecutor { + &self.background_executor + } + + /// Returns the foreground executor used by this benchmark app. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } + + /// Updates the app and flushes synchronous GPUI effects afterward. + pub fn update(&mut self, update: impl FnOnce(&mut App) -> R) -> R { + let mut app = self.app.borrow_mut(); + app.update(update) + } + + /// Reads app state. + pub fn read(&self, read: impl FnOnce(&App) -> R) -> R { + let app = self.app.borrow(); + read(&app) + } + + /// Runs queued foreground tasks on this thread and waits for in flight + /// background work to finish. Timers that aren't due yet are not waited + /// for (see [`ThreadedDispatcher::run_until_idle`]). Scheduled frames are + /// delivered after each task poll and when there are no ready tasks, but + /// animations alone do not keep this method running. + pub fn run_until_idle(&self) { + let dispatcher = self + .background_executor + .dispatcher() + .as_threaded() + .expect("validated in BenchAppContext::build"); + dispatcher.run_until_idle_with(|| { + let ran_tasks = dispatcher.run_ready_main_tasks_with( + || true, + || { + self.dispatch_pending_frames(|| true); + }, + ); + if !ran_tasks { + self.dispatch_pending_frames(|| true); + } + ran_tasks + }); + } + + /// Alternates draining queued work with GPUI update cycles until neither + /// makes progress, so state dropped by benchmark code is fully released. + /// + /// Dropped entities are released only inside an update's effect flush, and + /// releases cascade: one flush drops the entities whose handles are gone, + /// their drops release further handles and can queue foreground work, and + /// a later flush collects those. Executor pumping alone never runs a + /// flush, so without this dropped state would linger in the entity map + /// until some woken task happened to run an update. Production gets this + /// cadence for free from frames and input events. + pub fn settle(&mut self) { + let dispatcher = self.background_executor.dispatcher().clone(); + let dispatcher = dispatcher + .as_threaded() + .expect("validated in BenchAppContext::build"); + loop { + self.run_until_idle(); + self.update(|_| ()); + self.dispatch_pending_frames(|| true); + if dispatcher.is_idle() { + return; + } + } + } + + /// Runs main-thread tasks until `ready` returns a value. + /// + /// While incomplete, scheduled frames run after each task poll and while + /// waiting for work. Readiness is checked before frame delivery, so completion + /// does not wait for a final presentation; renderer sessions do that explicitly. + pub fn run_until(&self, ready: impl FnMut() -> Option) -> R { + self.background_executor + .dispatcher() + .as_threaded() + .expect("validated in BenchAppContext::build") + .run_until_with_frames(ready, || self.dispatch_pending_frames(|| true)) + } + + /// Creates a collector observing foreground journal entries recorded + /// from this point on, for use by a new [`TraceScope`]. + fn foreground_journal_collector(&self) -> ForegroundJournalCollector { + self.read(|app| app.foreground_journal().collector()) + } + + /// Measures a generic benchmark workload using Criterion's iteration loop. + /// + /// The closure is invoked once per Criterion iteration with this + /// benchmark app context so it can update GPUI state. Each iteration then + /// delivers the scheduled frame batch, without draining foreground tasks. + /// + /// Any window draws triggered by the workload are recorded into the + /// benchmark's frame report through the GPUI frame profiler. + pub fn bench_iter(&mut self, mut benchmark: impl FnMut(&mut Self)) { + let bencher = self.take_bencher("bench_iter"); + self.dispatch_pending_frames(|| true); + let collector = TraceScope::start(self.foreground_journal_collector()); + self.report.metrics.discard_pending(); + let mut iterations = 0; + let mut benchmark = || { + iterations += 1; + benchmark(self); + self.dispatch_pending_frames(|| true); + }; + bencher.iter(&mut benchmark); + let events = collector.finish(); + self.report.metrics.record_sample(iterations); + self.report.record_frame_timings(events.frame_events.iter()); + self.report + .record_foreground_events(events.foreground_events()); + self.replace_bencher(bencher); + } + + /// Measures a GPUI task to completion using Criterion's iteration loop. + /// + /// The closure is invoked once per Criterion iteration. The returned task + /// may depend on foreground work, background work, timers, or external + /// workers that wake GPUI tasks. Its output is dropped after the timed + /// interval. + /// + /// Any window draws triggered by the task are recorded into the benchmark's + /// frame report through the GPUI frame profiler. + pub fn bench_task(&mut self, mut benchmark: impl FnMut(&mut Self) -> Task) + where + Output: 'static, + { + self.bench_batched_task_internal("bench_task", |_| (), |_, cx| benchmark(cx)); + } + + /// Measures a GPUI task with per-iteration setup outside the timed interval. + /// + /// `setup` runs before timing starts. The returned input is passed by mutable + /// reference to `benchmark`, which returns the task whose completion is + /// measured. Both the setup input and task output are dropped after timing + /// stops. + /// + /// Each iteration is kept in its own Criterion batch so profiler tracing and + /// destruction cannot overlap adjacent measurements. + pub fn bench_batched_task( + &mut self, + setup: impl FnMut(&mut Self) -> Input, + benchmark: impl FnMut(&mut Input, &mut Self) -> Task, + ) where + Output: 'static, + { + self.bench_batched_task_internal("bench_batched_task", setup, benchmark); + } + + fn bench_batched_task_internal( + &mut self, + benchmark_kind: &str, + mut setup: impl FnMut(&mut Self) -> Input, + mut benchmark: impl FnMut(&mut Input, &mut Self) -> Task, + ) where + Output: 'static, + { + let bencher = self.take_bencher(benchmark_kind); + let mut setup_context = self.clone(); + let mut benchmark_context = self.clone(); + let foreground_executor = self.foreground_executor.clone(); + let report = self.report.clone(); + report.metrics.discard_pending(); + let iterations = std::cell::Cell::new(0); + + bencher.iter_batched_ref( + || { + // The previous iteration's input and output were just + // dropped; settling here releases their entities before the + // next setup, so per-iteration state cannot accumulate + // across a measurement. + setup_context.settle(); + let input = setup(&mut setup_context); + setup_context.dispatch_pending_frames(|| true); + MeasuredTaskInput { + input, + trace_scope: Some(TraceScope::start( + setup_context.foreground_journal_collector(), + )), + } + }, + |measured_input| { + iterations.set(iterations.get() + 1); + let task = benchmark(&mut measured_input.input, &mut benchmark_context); + benchmark_context.dispatch_pending_frames(|| true); + let output = Rc::new(RefCell::new(None)); + let completion = foreground_executor.spawn({ + let output = output.clone(); + async move { + *output.borrow_mut() = Some(task.await); + } + }); + let output = benchmark_context.run_until(|| output.borrow_mut().take()); + drop(completion); + MeasuredTaskOutput { + trace_scope: measured_input.trace_scope.take(), + report: report.clone(), + _output: output, + } + }, + criterion::BatchSize::PerIteration, + ); + report.metrics.record_sample(iterations.get()); + self.replace_bencher(bencher); + } + + /// Measures unpaced update and rendering work for an entity in its current window. + /// + /// Each iteration runs `update` against the entity in its current window. In + /// renderer measurements, effects flush without drawing until the platform + /// frame callback. The entity should be part of the window's render tree, such as the + /// root view or a child of it. + /// + /// Each iteration first pumps at most the initial ready task count, delivering + /// pending frames after every poll. It then runs `update` and delivers pending + /// frames again. Nested actions and effects finish before frame delivery. + /// This measures work and rendering cost, not display latency: there is no + /// pacing, and the report's frame budget does not control execution. + /// + /// Frame events are collected through the GPUI frame profiler + /// ([`crate::profiler::record_frame_event`]), which is enabled for the + /// duration of the measurement. + pub fn bench_renderer( + &mut self, + view: Entity, + mut update: impl FnMut(&mut V, &mut Window, &mut Context), + ) where + V: 'static + Render, + { + let bencher = self.take_bencher("bench_renderer"); + let dispatcher = self.background_executor.dispatcher().clone(); + self.dispatch_pending_frames(|| true); + let collector = TraceScope::start(self.foreground_journal_collector()); + self.report.metrics.discard_pending(); + let mut iterations = 0; + let mut benchmark = || { + iterations += 1; + dispatcher + .as_threaded() + .expect("validated in BenchAppContext::build") + .run_ready_main_tasks_with( + || true, + || { + self.dispatch_pending_frames(|| true); + }, + ); + self.with_window(view.entity_id(), |window, cx| { + view.update(cx, |view, cx| update(view, window, cx)); + }) + .expect("cannot benchmark renderer for entity without a current window"); + self.dispatch_pending_frames(|| true); + }; + bencher.iter(&mut benchmark); + + let events = collector.finish(); + self.report.metrics.record_sample(iterations); + self.report.record_frame_timings(events.frame_events.iter()); + self.report + .record_foreground_events(events.foreground_events()); + self.replace_bencher(bencher); + } + + /// Measures finite rendering sessions with fresh, untimed setup for each iteration. + /// + /// `setup` returns session state, its window, and a shared stop flag. + /// Loop turns pump at most the initial ready foreground task count, then call + /// `input` with a zero-based turn number unless stopped. Pending frames are + /// delivered after each task poll and input callback. Between polls, the stop + /// flag and session deadline are checked. The ready batch snapshots a count, + /// not task identities; rendering after a poll does not inject another input. + /// This is an unpaced work-and-render policy, not OS event-loop emulation. + /// Once stopped, only scheduled platform frame callbacks run until the window + /// is clean and its final changes have been submitted for presentation. + /// Pending animation callbacks alone do not delay completion. + /// Turns run without pacing or explicit OS-thread yields. A clean turn need not draw. + /// + /// Store `true` with release ordering to stop. Stopping does not imply success: + /// validate the workload in `Input::drop` or retained fixture state afterward. + /// Setup, session state destruction, and report aggregation are outside both + /// timing and tracing. Own outstanding tasks in `Input` so dropping it cancels + /// them; do not detach session work that could leak into subsequent iterations. + /// + /// # Panics + /// + /// Panics if the window is removed or stopping and final presentation exceed `timeout`. + /// The deadline is checked between polls and frames and cannot preempt a blocking task + /// poll, input callback, draw, or present. + pub fn bench_renderer_session( + &mut self, + timeout: Duration, + mut setup: impl FnMut(&mut Self) -> (Input, AnyWindowHandle, Arc), + mut input: impl FnMut(&mut Input, u64, &mut Window, &mut App), + ) { + let bencher = self.take_bencher("bench_renderer_session"); + let mut setup_context = self.clone(); + let mut benchmark_context = self.clone(); + let dispatcher = self.background_executor.dispatcher().clone(); + let dispatcher = dispatcher + .as_threaded() + .expect("validated in BenchAppContext::build"); + let report = self.report.clone(); + report.metrics.discard_pending(); + let iterations = std::cell::Cell::new(0); + + bencher.iter_batched_ref( + || { + setup_context.settle(); + let input = setup(&mut setup_context); + setup_context.dispatch_pending_frames(|| true); + MeasuredTaskInput { + input, + trace_scope: Some(TraceScope::start( + setup_context.foreground_journal_collector(), + )), + } + }, + |measured_input| { + iterations.set(iterations.get() + 1); + let (state, window, stopped) = &mut measured_input.input; + let started = Instant::now(); + let check_deadline = || { + assert!( + started.elapsed() < timeout, + "renderer session did not stop within {timeout:?} with final changes presented" + ); + }; + let can_poll = || { + check_deadline(); + !stopped.load(Ordering::Acquire) + }; + let is_finished = |cx: &Self| { + if !stopped.load(Ordering::Acquire) { + return false; + } + // Animation callbacks alone must not keep a stopped session alive. + let app = cx.app.borrow(); + let window = app + .windows + .get(window.window_id()) + .and_then(Option::as_deref) + .expect("renderer session window must remain open"); + !window.invalidator.is_dirty() && !window.needs_present.get() + }; + let dispatch_frames = |cx: &Self| { + check_deadline(); + cx.dispatch_pending_frames(|| { + check_deadline(); + !is_finished(cx) + }); + check_deadline(); + }; + let mut frame = 0; + loop { + check_deadline(); + if is_finished(&benchmark_context) { + break; + } + if can_poll() { + dispatcher.run_ready_main_tasks_with(&can_poll, || { + dispatch_frames(&benchmark_context); + }); + if !can_poll() { + continue; + } + benchmark_context + .update_window(*window, |_, window, cx| { + if can_poll() { + input(state, frame, window, cx); + } + }) + .expect("renderer session window must remain open"); + } + dispatch_frames(&benchmark_context); + frame += 1; + } + MeasuredTaskOutput { + trace_scope: measured_input.trace_scope.take(), + report: report.clone(), + _output: (), + } + }, + criterion::BatchSize::PerIteration, + ); + report.metrics.record_sample(iterations.get()); + self.replace_bencher(bencher); + } + + fn dispatch_pending_frames(&self, mut should_continue: impl FnMut() -> bool) -> bool { + let pending: Vec<_> = { + let mut app = self.app.borrow_mut(); + app.windows + .values_mut() + .filter_map(|window| { + let window = window.as_deref_mut()?; + let handle = window.window_handle(); + let platform_window = window + .platform_window + .as_test() + .expect("benchmark platform window"); + platform_window + .frame_scheduled() + .then(|| (handle, platform_window.clone())) + }) + .collect() + }; + + let mut dispatched = false; + for (handle, window) in pending { + if !should_continue() { + break; + } + // An earlier callback may have closed another window in the batch. + let is_open = self + .app + .borrow() + .windows + .get(handle.window_id()) + .and_then(Option::as_deref) + .is_some(); + if is_open { + dispatched |= window.simulate_scheduled_frame(); + } + } + dispatched + } + + /// Adds an active window with an empty root view for benchmark setup. + /// + /// Activation is settled before returning so renderer measurements exercise + /// foreground animation rather than the inactive-window frame throttle. + pub fn add_empty_window(&mut self) -> BenchWindowContext<'a, 'measurement> { + let bounds = { + let app = self.app.borrow(); + Bounds::maximized(None, &app) + }; + let window = { + let mut app = self.app.borrow_mut(); + let window: AnyWindowHandle = app + .open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..Default::default() + }, + |_, cx| cx.new(|_| Empty), + ) + .expect("failed to open benchmark window") + .into(); + // An active renderer workload must not inherit the platform + // callback's inactive-window animation throttle. + app.update_window(window, |_, window, _| window.activate_window()) + .expect("failed to activate newly created benchmark window"); + window + }; + + self.run_until_idle(); + BenchWindowContext { + cx: self.clone(), + window, + } + } + + fn take_bencher( + &self, + benchmark_kind: &str, + ) -> &'a mut criterion::Bencher<'measurement, BenchMeasurement> { + self.bencher.borrow_mut().take().unwrap_or_else(|| { + panic!("cannot start {benchmark_kind}: benchmark measurement is already running") + }) + } + + fn replace_bencher(&self, bencher: &'a mut criterion::Bencher<'measurement, BenchMeasurement>) { + let previous = self.bencher.borrow_mut().replace(bencher); + assert!( + previous.is_none(), + "benchmark bencher was unexpectedly present after measurement" + ); + } + + /// Runs GPUI benchmark teardown. + /// + /// Cancels any timers still armed on the shared dispatcher and drains the + /// work that cancellation unblocks so they can't fire during a later + /// benchmark; assumes no other `BenchAppContext` is live on this thread. + pub fn teardown(mut self) { + self.run_until_idle(); + self.update(|cx| { + cx.quit(); + }); + self.run_until_idle(); + + let dispatcher = self.background_executor.dispatcher(); + let dispatcher = dispatcher + .as_threaded() + .expect("validated in BenchAppContext::build"); + + drop(self.app); + drop(self.foreground_executor); + + for _ in 0..100 { + if dispatcher.cancel_pending_timers() == 0 { + return; + } + dispatcher.run_until_idle(); + } + panic!( + "benchmark teardown kept scheduling timers: {}", + dispatcher.debug_state() + ); + } +} + +impl AppContext for BenchAppContext<'_, '_> { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + let mut app = self.app.borrow_mut(); + app.new(build_entity) + } + + fn reserve_entity(&mut self) -> Reservation { + let mut app = self.app.borrow_mut(); + app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let mut app = self.app.borrow_mut(); + app.insert_entity(reservation, build_entity) + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let mut app = self.app.borrow_mut(); + app.update_entity(handle, update) + } + + fn as_mut<'b, T>(&'b mut self, _: &Entity) -> GpuiBorrow<'b, T> + where + T: 'static, + { + panic!("Cannot use as_mut with BenchAppContext. Call update() instead.") + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let app = self.app.borrow(); + app.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut app = self.app.borrow_mut(); + app.update_window(window, update) + } + + fn with_window( + &mut self, + entity_id: EntityId, + update: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let mut app = self.app.borrow_mut(); + app.with_window(entity_id, update) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let app = self.app.borrow(); + app.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let app = self.app.borrow(); + app.read_global(callback) + } +} + +/// A window-specific context for GPUI benchmarks. +/// +/// This is separate from `VisualTestContext`; it provides access to a benchmark +/// window without exposing test-only helpers such as input simulation. +#[derive(Clone)] +pub struct BenchWindowContext<'a, 'measurement> { + cx: BenchAppContext<'a, 'measurement>, + window: AnyWindowHandle, +} + +impl<'a, 'measurement> BenchWindowContext<'a, 'measurement> { + /// Returns the underlying benchmark app context. + pub fn app_context(&mut self) -> &mut BenchAppContext<'a, 'measurement> { + &mut self.cx + } + + /// Returns the window associated with this context. + pub fn window_handle(&self) -> AnyWindowHandle { + self.window + } + + /// Runs queued foreground tasks on this thread and waits for in-flight + /// background work to finish. Pending timers are not waited for. + pub fn run_until_idle(&self) { + self.cx.run_until_idle(); + } + + /// Updates the benchmark window. + pub fn update(&mut self, update: impl FnOnce(&mut Window, &mut App) -> R) -> R { + self.cx + .update_window(self.window, |_, window, cx| update(window, cx)) + .expect("benchmark window was unexpectedly closed") + } +} + +impl AppContext for BenchWindowContext<'_, '_> { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + self.window + .update(&mut self.cx, |_, _, cx| cx.new(build_entity)) + .expect("benchmark window was unexpectedly closed") + } + + fn reserve_entity(&mut self) -> Reservation { + self.cx.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + self.window + .update(&mut self.cx, |_, _, cx| { + cx.insert_entity(reservation, build_entity) + }) + .expect("benchmark window was unexpectedly closed") + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + self.cx.update_entity(handle, update) + } + + fn as_mut<'b, T>(&'b mut self, handle: &Entity) -> GpuiBorrow<'b, T> + where + T: 'static, + { + self.cx.as_mut(handle) + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + self.cx.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + self.cx.update_window(window, update) + } + + fn with_window( + &mut self, + entity_id: EntityId, + update: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + self.cx.with_window(entity_id, update) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + self.cx.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.cx.background_spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + self.cx.read_global(callback) + } +} + +impl VisualContext for BenchWindowContext<'_, '_> { + type Result = Result; + + fn window_handle(&self) -> AnyWindowHandle { + self.window + } + + fn update_window_entity( + &mut self, + entity: &Entity, + update: impl FnOnce(&mut T, &mut Window, &mut Context) -> R, + ) -> Result { + let entity = entity.clone(); + self.cx + .app + .borrow_mut() + .with_window(entity.entity_id(), |window, app| { + entity.update(app, |entity, cx| update(entity, window, cx)) + }) + .ok_or_else(|| { + anyhow!("entity has no current window; use `update` instead of `update_in`") + }) + } + + fn new_window_entity( + &mut self, + build_entity: impl FnOnce(&mut Window, &mut Context) -> T, + ) -> Result> { + self.window.update(&mut self.cx, |_, window, cx| { + cx.new(|cx| build_entity(window, cx)) + }) + } + + fn replace_root_view( + &mut self, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> Result> + where + V: 'static + Render, + { + self.window.update(&mut self.cx, |_, window, cx| { + window.replace_root(cx, build_view) + }) + } + + fn focus(&mut self, entity: &Entity) -> Result<()> + where + V: Focusable, + { + self.window.update(&mut self.cx, |_, window, cx| { + entity.read(cx).focus_handle(cx).focus(window, cx) + }) + } +} + +#[cfg(test)] +mod tests { + use std::{ + rc::Rc, + sync::{ + Arc, + atomic::{AtomicU64, Ordering}, + }, + }; + + use super::*; + use crate::profiler::journal::install_test_foreground_journal; + + /// Runs `benchmark` under a wall-time primary with a fake counter as the + /// secondary metric and returns the per-iteration values the report + /// recorded for it. + fn secondary_values_per_iteration( + counter: Arc, + benchmark: impl Fn(&mut BenchAppContext, &Arc), + ) -> Vec { + let platform = bench_platform(None, Arc::new(crate::NoopTextSystem::new())); + let report = BenchReport::default(); + let mut criterion = criterion::Criterion::default() + .with_measurement( + BenchMeasurement::new(criterion::measurement::WallTime).with_secondary( + "fake counter", + bench_metrics::FakeCounter::new(counter.clone()), + ), + ) + .without_plots() + .sample_size(10) + .warm_up_time(Duration::from_millis(1)) + .measurement_time(Duration::from_millis(1)); + + criterion.bench_function("secondary_values_per_iteration", |bencher| { + let mut cx = BenchAppContext::new_with_platform_and_report( + platform.clone(), + Some("secondary_values_per_iteration"), + bencher, + report.clone(), + ); + // Fixture work outside the measured loop must not be attributed + // to any iteration. + counter.fetch_add(1_000_000, Ordering::SeqCst); + benchmark(&mut cx, &counter); + cx.teardown(); + }); + + report + .metrics() + .values("fake counter") + .expect("the fake counter was recorded") + .into_iter() + .map(|value| value as u64) + .collect() + } + + #[test] + fn secondary_metric_is_normalized_per_iteration_for_bench_iter() { + let values = secondary_values_per_iteration(Arc::new(AtomicU64::new(0)), |cx, counter| { + cx.bench_iter(|_| { + counter.fetch_add(11, Ordering::SeqCst); + }); + }); + assert!(!values.is_empty()); + assert!( + values.iter().all(|value| *value == 11), + "each sample's total should be divided by its iteration count: {values:?}" + ); + } + + #[test] + fn secondary_metric_is_accumulated_across_per_iteration_batches() { + let values = secondary_values_per_iteration(Arc::new(AtomicU64::new(0)), |cx, counter| { + cx.bench_batched_task( + |_| { + // Setup runs outside every measured interval. + counter.fetch_add(1_000, Ordering::SeqCst); + }, + |(), cx| { + counter.fetch_add(11, Ordering::SeqCst); + cx.background_spawn(async {}) + }, + ); + }); + assert!(!values.is_empty()); + assert!( + values.iter().all(|value| *value == 11), + "PerIteration batches should sum to one per-iteration value: {values:?}" + ); + } + + #[test] + fn foreground_work_reports_long_task_without_window_draw() { + let (journal, _journal_guard) = install_test_foreground_journal(1024, 64); + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground_executor = ForegroundExecutor::new(dispatcher); + + let trace_scope = TraceScope::start(journal.collector()); + + // A single foreground task poll that never touches a window, akin + // to the stall a debounced background computation can cause. + let task = foreground_executor.spawn(async move { + std::thread::sleep(Duration::from_millis(60)); + }); + run_task_to_completion(&foreground_executor, task); + + let events = trace_scope.finish(); + assert!( + events.frame_events.is_empty(), + "no window was involved, so no frame events should be recorded" + ); + + let report = BenchReport::default(); + report.record_foreground_events(events.foreground_events()); + + let summary = report + .foreground_work() + .expect("a long task poll should be reported even without a window draw"); + // The spawned task's own poll is one sample; the tiny wrapper poll + // that observes its completion in `run_task_to_completion` folds + // into a second, near-zero sample rather than being dropped. + assert!(summary.count >= 1, "expected at least one recorded item"); + assert!( + summary.max >= Duration::from_millis(55), + "expected the long poll's duration to be recorded, got {:?}", + summary.max + ); + // `total` is an exact sum, while `max` may be rounded up to its + // histogram bucket's boundary, so compare each against the expected + // floor directly instead of against each other. + assert!( + summary.total >= Duration::from_millis(55), + "expected the long poll's duration to be included in the total, got {:?}", + summary.total + ); + } + + #[test] + fn foreground_work_excludes_setup_before_trace_scope_starts() { + let (journal, _journal_guard) = install_test_foreground_journal(1024, 64); + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground_executor = ForegroundExecutor::new(dispatcher); + + // Fixture/setup work that must not be attributed to the measurement: + // a long poll recorded before the trace scope (and its journal + // collector) is created. + let setup_task = foreground_executor.spawn(async move { + std::thread::sleep(Duration::from_millis(80)); + }); + run_task_to_completion(&foreground_executor, setup_task); + + let trace_scope = TraceScope::start(journal.collector()); + + let measured_task = foreground_executor.spawn(async move { + std::thread::sleep(Duration::from_millis(10)); + }); + run_task_to_completion(&foreground_executor, measured_task); + + let events = trace_scope.finish(); + let report = BenchReport::default(); + report.record_foreground_events(events.foreground_events()); + + let summary = report + .foreground_work() + .expect("the measured task's poll should be reported"); + assert!( + summary.max < Duration::from_millis(40), + "setup work's 80ms poll must not leak into the measured summary, got {:?}", + summary.max + ); + assert!( + summary.total < Duration::from_millis(40), + "setup work's 80ms poll must not leak into the measured total, got {:?}", + summary.total + ); + } + + #[test] + fn bench_task_reports_long_task_without_window() { + let platform = bench_platform(None, Arc::new(crate::NoopTextSystem::new())); + let report = BenchReport::default(); + let name = "bench_task_reports_long_task_without_window"; + + let mut criterion = criterion::Criterion::default() + .with_measurement(BenchMeasurement::new(criterion::measurement::WallTime)) + .without_plots() + .sample_size(10) + .warm_up_time(Duration::from_millis(1)) + .measurement_time(Duration::from_millis(1)); + + criterion.bench_function(name, |bencher| { + let mut cx = BenchAppContext::new_with_platform_and_report( + platform.clone(), + Some(name), + bencher, + report.clone(), + ); + cx.bench_task(|cx| { + cx.foreground_executor().spawn(async move { + std::thread::sleep(Duration::from_millis(20)); + }) + }); + cx.teardown(); + }); + + let summary = report + .foreground_work() + .expect("bench_task should report foreground work with no window involved"); + assert!( + summary.max >= Duration::from_millis(15), + "expected a ~20ms task poll to be recorded, got {:?}", + summary.max + ); + } + + #[test] + fn task_completion_supports_non_send_foreground_output() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let background_executor = BackgroundExecutor::new(dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(dispatcher); + let (sender, receiver) = futures::channel::oneshot::channel(); + + background_executor + .spawn(async move { + sender + .send(()) + .expect("foreground receiver should remain alive"); + }) + .detach(); + let expected_output = Rc::new(42); + let task_output = expected_output.clone(); + let task = foreground_executor.spawn(async move { + receiver.await.expect("background task should send a value"); + task_output + }); + + let output = run_task_to_completion(&foreground_executor, task); + assert!( + Rc::ptr_eq(&output, &expected_output), + "task runner should preserve non-Send foreground output" + ); + } +} diff --git a/vendor/gpui-pre/src/app/context.rs b/vendor/gpui-pre/src/app/context.rs new file mode 100644 index 00000000..bce22b59 --- /dev/null +++ b/vendor/gpui-pre/src/app/context.rs @@ -0,0 +1,959 @@ +use crate::{ + AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter, + FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Priority, Reservation, + SubscriberSet, Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle, + WindowVisibility, +}; +use anyhow::Result; +use futures::FutureExt; +use gpui_util::Deferred; +use std::{ + any::{Any, TypeId}, + borrow::{Borrow, BorrowMut}, + future::Future, + ops, + sync::Arc, +}; + +use super::{App, AsyncWindowContext, Entity, KeystrokeEvent}; + +/// The app context, with specialized behavior for the given entity. +pub struct Context<'a, T> { + app: &'a mut App, + entity_state: WeakEntity, +} + +impl<'a, T> ops::Deref for Context<'a, T> { + type Target = App; + + fn deref(&self) -> &Self::Target { + self.app + } +} + +impl<'a, T> ops::DerefMut for Context<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.app + } +} + +impl<'a, T: 'static> Context<'a, T> { + pub(crate) fn new_context(app: &'a mut App, entity_state: WeakEntity) -> Self { + Self { app, entity_state } + } + + /// The entity id of the entity backing this context. + pub fn entity_id(&self) -> EntityId { + self.entity_state.entity_id + } + + /// Returns a handle to the entity belonging to this context. + pub fn entity(&self) -> Entity { + self.weak_entity() + .upgrade() + .expect("The entity must be alive if we have a entity context") + } + + /// Returns a weak handle to the entity belonging to this context. + pub fn weak_entity(&self) -> WeakEntity { + self.entity_state.clone() + } + + /// Arranges for the given function to be called whenever [`Context::notify`] is + /// called with the given entity. + pub fn observe( + &mut self, + entity: &Entity, + mut on_notify: impl FnMut(&mut T, Entity, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + W: 'static, + { + let observer = self.weak_entity(); + self.app.observe_internal(entity, move |entity, cx| { + invoke_observer(&observer, entity, cx, &mut on_notify) + }) + } + + /// Observe changes to ourselves + pub fn observe_self( + &mut self, + mut on_event: impl FnMut(&mut T, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + { + let this = self.entity(); + self.app.observe(&this, move |this, cx| { + this.update(cx, |this, cx| on_event(this, cx)) + }) + } + + /// Subscribe to an event type from another entity + pub fn subscribe( + &mut self, + entity: &Entity, + mut on_event: impl FnMut(&mut T, Entity, &Evt, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + T2: 'static + EventEmitter, + Evt: 'static, + { + let subscriber = self.weak_entity(); + self.app + .subscribe_internal(entity, move |entity, event, cx| { + invoke_subscriber(&subscriber, entity, event, cx, &mut on_event) + }) + } + + /// Subscribe to an event type from ourself + pub fn subscribe_self( + &mut self, + mut on_event: impl FnMut(&mut T, &Evt, &mut Context) + 'static, + ) -> Subscription + where + T: 'static + EventEmitter, + Evt: 'static, + { + let this = self.entity(); + self.app.subscribe(&this, move |this, evt, cx| { + this.update(cx, |this, cx| on_event(this, evt, cx)) + }) + } + + /// Register a callback to be invoked when GPUI releases this entity. + pub fn on_release(&self, on_release: impl FnOnce(&mut T, &mut App) + 'static) -> Subscription + where + T: 'static, + { + let (subscription, activate) = self.app.release_listeners.insert( + self.entity_state.entity_id, + Box::new(move |this, cx| { + let this = this.downcast_mut().expect("invalid entity type"); + on_release(this, cx); + }), + ); + activate(); + subscription + } + + /// Register a callback to be run on the release of another entity + pub fn observe_release( + &self, + entity: &Entity, + on_release: impl FnOnce(&mut T, &mut T2, &mut Context) + 'static, + ) -> Subscription + where + T: Any, + T2: 'static, + { + let entity_id = entity.entity_id(); + let this = self.weak_entity(); + let (subscription, activate) = self.app.release_listeners.insert( + entity_id, + Box::new(move |entity, cx| { + let entity = entity.downcast_mut().expect("invalid entity type"); + if let Some(this) = this.upgrade() { + this.update(cx, |this, cx| on_release(this, entity, cx)); + } + }), + ); + activate(); + subscription + } + + /// Register a callback to for updates to the given global + pub fn observe_global( + &mut self, + mut f: impl FnMut(&mut T, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + { + let handle = self.weak_entity(); + let (subscription, activate) = self.global_observers.insert( + TypeId::of::(), + Box::new(move |cx| handle.update(cx, |view, cx| f(view, cx)).is_ok()), + ); + self.defer(move |_| activate()); + subscription + } + + /// Register a callback to be invoked when the application is about to restart. + pub fn on_app_restart( + &self, + mut on_restart: impl FnMut(&mut T, &mut App) + 'static, + ) -> Subscription + where + T: 'static, + { + let handle = self.weak_entity(); + self.app.on_app_restart(move |cx| { + handle.update(cx, |entity, cx| on_restart(entity, cx)).ok(); + }) + } + + /// Arrange for the given function to be invoked whenever the application is quit. + /// The future returned from this callback will be polled for up to [crate::SHUTDOWN_TIMEOUT] until the app fully quits. + pub fn on_app_quit( + &self, + mut on_quit: impl FnMut(&mut T, &mut Context) -> Fut + 'static, + ) -> Subscription + where + Fut: 'static + Future, + T: 'static, + { + let handle = self.weak_entity(); + self.app.on_app_quit(move |cx| { + let future = handle.update(cx, |entity, cx| on_quit(entity, cx)).ok(); + async move { + if let Some(future) = future { + future.await; + } + } + .boxed_local() + }) + } + + /// Tell GPUI that this entity has changed and observers of it should be notified. + pub fn notify(&mut self) { + self.app.notify(self.entity_state.entity_id); + } + + /// Spawn the future returned by the given function. + /// The function is provided a weak handle to the entity owned by this context and a context that can be held across await points. + /// The returned task must be held or detached. + #[track_caller] + #[inline(always)] + pub fn spawn(&self, f: AsyncFn) -> Task + where + T: 'static, + AsyncFn: AsyncFnOnce(WeakEntity, &mut AsyncApp) -> R + 'static, + R: 'static, + { + let this = self.weak_entity(); + self.app.spawn(async move |cx| f(this, cx).await) + } + + /// Convenience method for accessing view state in an event callback. + /// + /// Many GPUI callbacks take the form of `Fn(&E, &mut Window, &mut App)`, + /// but it's often useful to be able to access view state in these + /// callbacks. This method provides a convenient way to do so. + #[inline(always)] + pub fn listener( + &self, + listener: impl Fn(&mut T, &E, &mut Window, &mut Context) + 'static, + ) -> impl Fn(&E, &mut Window, &mut App) + 'static { + let view = self.entity().downgrade(); + move |event: &E, window: &mut Window, cx: &mut App| { + invoke_listener(&view, window, cx, &|view, window, cx| { + listener(view, event, window, cx); + }); + } + } + + /// Convenience method for producing view state in a closure. + /// See `listener` for more details. + pub fn processor( + &self, + f: impl Fn(&mut T, E, &mut Window, &mut Context) -> R + 'static, + ) -> impl Fn(E, &mut Window, &mut App) -> R + 'static { + let view = self.entity(); + move |e: E, window: &mut Window, cx: &mut App| { + view.update(cx, |view, cx| f(view, e, window, cx)) + } + } + + /// Run something using this entity and cx, when the returned struct is dropped + pub fn on_drop( + &self, + f: impl FnOnce(&mut T, &mut Context) + 'static, + ) -> Deferred { + let this = self.weak_entity(); + let mut cx = self.to_async(); + gpui_util::defer(move || { + this.update(&mut cx, f).ok(); + }) + } + + /// Focus the given view in the given window. View type is required to implement Focusable. + pub fn focus_view(&mut self, view: &Entity, window: &mut Window) { + window.focus(&view.focus_handle(self), self); + } + + /// Sets a given callback to be run on the next frame. + pub fn on_next_frame( + &self, + window: &mut Window, + f: impl FnOnce(&mut T, &mut Window, &mut Context) + 'static, + ) where + T: 'static, + { + let view = self.entity(); + window.on_next_frame(move |window, cx| view.update(cx, |view, cx| f(view, window, cx))); + } + + /// Schedules the given function to be run at the end of the current effect cycle, allowing entities + /// that are currently on the stack to be returned to the app. + pub fn defer_in( + &mut self, + window: &Window, + f: impl FnOnce(&mut T, &mut Window, &mut Context) + 'static, + ) { + let view = self.weak_entity(); + let entity_id = self.entity_id(); + self.ensure_window(entity_id, window.handle.id); + self.app.defer(move |cx| { + cx.with_window(entity_id, |window, cx| { + view.update(cx, |view, cx| f(view, window, cx)).ok(); + }); + }); + } + + /// Observe another entity for changes to its state, as tracked by [`Context::notify`]. + pub fn observe_in( + &mut self, + observed: &Entity, + window: &mut Window, + mut on_notify: impl FnMut(&mut T, Entity, &mut Window, &mut Context) + 'static, + ) -> Subscription + where + V2: 'static, + T: 'static, + { + let observed_id = observed.entity_id(); + let observed = observed.downgrade(); + let observer = self.weak_entity(); + let observer_id = self.entity_id(); + self.ensure_window(observer_id, window.handle.id); + self.new_observer( + observed_id, + Box::new(move |cx| invoke_observer_in(&observer, &observed, cx, &mut on_notify)), + ) + } + + /// Subscribe to events emitted by another entity. + /// The entity to which you're subscribing must implement the [`EventEmitter`] trait. + /// The callback will be invoked with a reference to the current view, a handle to the emitting `Entity`, the event, a mutable reference to the `Window`, and the context for the entity. + pub fn subscribe_in( + &mut self, + emitter: &Entity, + window: &Window, + mut on_event: impl FnMut(&mut T, &Entity, &Evt, &mut Window, &mut Context) + 'static, + ) -> Subscription + where + Emitter: EventEmitter, + Evt: 'static, + { + let emitter = emitter.downgrade(); + let subscriber = self.weak_entity(); + let subscriber_id = self.entity_id(); + self.ensure_window(subscriber_id, window.handle.id); + self.new_subscription( + emitter.entity_id(), + ( + TypeId::of::(), + Box::new(move |event, cx| { + invoke_subscriber_in(&subscriber, &emitter, event, cx, &mut on_event) + }), + ), + ) + } + + /// Register a callback to be invoked when the view is released. + /// + /// The callback receives a handle to the view's window. This handle may be + /// invalid, if the window was closed before the view was released. + pub fn on_release_in( + &mut self, + window: &Window, + on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static, + ) -> Subscription { + let entity = self.entity(); + self.app.observe_release_in(&entity, window, on_release) + } + + /// Register a callback to be invoked when the given Entity is released. + pub fn observe_release_in( + &self, + observed: &Entity, + window: &Window, + mut on_release: impl FnMut(&mut T, &mut T2, &mut Window, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + T2: 'static, + { + let observer = self.weak_entity(); + self.app + .observe_release_in(observed, window, move |observed, window, cx| { + observer + .update(cx, |observer, cx| { + on_release(observer, observed, window, cx) + }) + .ok(); + }) + } + + /// Register a callback to be invoked when the window is resized. + pub fn observe_window_bounds( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.bounds_observers.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| callback(view, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Register a callback to be invoked when the window is activated or deactivated. + pub fn observe_window_activation( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.activation_observers.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| callback(view, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Registers a callback to be invoked when the window's visibility changes + /// (see [`WindowVisibility`]). + pub fn observe_window_visibility( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, WindowVisibility, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.visibility_observers.insert( + (), + Box::new(move |visibility, window, cx| { + view.update(cx, |view, cx| callback(view, visibility, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Registers a callback to be invoked when the window appearance changes. + pub fn observe_window_appearance( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.appearance_observers.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| callback(view, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Registers a callback to be invoked when the window button layout changes. + pub fn observe_button_layout_changed( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.button_layout_observers.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| callback(view, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Registers a callback for [`App::observe_keystrokes`] that updates this entity. + pub fn observe_keystrokes( + &mut self, + mut f: impl FnMut(&mut T, &KeystrokeEvent, &mut Window, &mut Context) + 'static, + ) -> Subscription { + fn inner( + keystroke_observers: &SubscriberSet<(), KeystrokeObserver>, + handler: KeystrokeObserver, + ) -> Subscription { + let (subscription, activate) = keystroke_observers.insert((), handler); + activate(); + subscription + } + + let view = self.weak_entity(); + inner( + &self.keystroke_observers, + Box::new(move |event, window, cx| { + if let Some(view) = view.upgrade() { + view.update(cx, |view, cx| f(view, event, window, cx)); + true + } else { + false + } + }), + ) + } + + /// Register a callback to be invoked when the window's pending input changes. + pub fn observe_pending_input( + &self, + window: &mut Window, + mut callback: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.pending_input_observers.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| callback(view, window, cx)) + .is_ok() + }), + ); + activate(); + subscription + } + + /// Register a listener to be called when the given focus handle receives focus. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus( + &mut self, + handle: &FocusHandle, + window: &mut Window, + mut listener: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let focus_id = handle.id; + let (subscription, activate) = + window.new_focus_listener(Box::new(move |event, window, cx| { + view.update(cx, |view, cx| { + if event.previous_focus_path.last() != Some(&focus_id) + && event.current_focus_path.last() == Some(&focus_id) + { + listener(view, window, cx) + } + }) + .is_ok() + })); + self.defer(|_| activate()); + subscription + } + + /// Register a listener to be called when the given focus handle or one of its descendants receives focus. + /// This does not fire if the given focus handle - or one of its descendants - was previously focused. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus_in( + &mut self, + handle: &FocusHandle, + window: &mut Window, + mut listener: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let focus_id = handle.id; + let (subscription, activate) = + window.new_focus_listener(Box::new(move |event, window, cx| { + view.update(cx, |view, cx| { + if event.is_focus_in(focus_id) { + listener(view, window, cx) + } + }) + .is_ok() + })); + self.defer(|_| activate()); + subscription + } + + /// Register a listener to be called when the given focus handle loses focus. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_blur( + &mut self, + handle: &FocusHandle, + window: &mut Window, + mut listener: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let focus_id = handle.id; + let (subscription, activate) = + window.new_focus_listener(Box::new(move |event, window, cx| { + view.update(cx, |view, cx| { + if event.previous_focus_path.last() == Some(&focus_id) + && event.current_focus_path.last() != Some(&focus_id) + { + listener(view, window, cx) + } + }) + .is_ok() + })); + self.defer(|_| activate()); + subscription + } + + /// Register a listener to be called when nothing in the window has focus. + /// This typically happens when the node that was focused is removed from the tree, + /// and this callback lets you chose a default place to restore the users focus. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus_lost( + &mut self, + window: &mut Window, + mut listener: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let (subscription, activate) = window.focus_lost_listeners.insert( + (), + Box::new(move |window, cx| { + view.update(cx, |view, cx| listener(view, window, cx)) + .is_ok() + }), + ); + self.defer(|_| activate()); + subscription + } + + /// Register a listener to be called when the given focus handle or one of its descendants loses focus. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus_out( + &mut self, + handle: &FocusHandle, + window: &mut Window, + mut listener: impl FnMut(&mut T, FocusOutEvent, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let view = self.weak_entity(); + let focus_id = handle.id; + let (subscription, activate) = + window.new_focus_listener(Box::new(move |event, window, cx| { + view.update(cx, |view, cx| { + if let Some(blurred_id) = event.previous_focus_path.last().copied() + && event.is_focus_out(focus_id) + { + let event = FocusOutEvent { + blurred: WeakFocusHandle { + id: blurred_id, + handles: Arc::downgrade(&cx.focus_handles), + }, + }; + listener(view, event, window, cx) + } + }) + .is_ok() + })); + self.defer(|_| activate()); + subscription + } + + /// Schedule a future to be run asynchronously. + /// The given callback is invoked with a [`WeakEntity`] to avoid leaking the entity for a long-running process. + /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the entity across await points. + /// The returned future will be polled on the main thread. + #[track_caller] + #[inline(always)] + pub fn spawn_in(&self, window: &Window, f: AsyncFn) -> Task + where + R: 'static, + AsyncFn: AsyncFnOnce(WeakEntity, &mut AsyncWindowContext) -> R + 'static, + { + let view = self.weak_entity(); + window.spawn(self, async move |cx| f(view, cx).await) + } + + /// Schedule a future to be run asynchronously with the given priority. + /// The given callback is invoked with a [`WeakEntity`] to avoid leaking the entity for a long-running process. + /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the entity across await points. + /// The returned future will be polled on the main thread. + #[track_caller] + #[inline(always)] + pub fn spawn_in_with_priority( + &self, + priority: Priority, + window: &Window, + f: AsyncFn, + ) -> Task + where + R: 'static, + AsyncFn: AsyncFnOnce(WeakEntity, &mut AsyncWindowContext) -> R + 'static, + { + let view = self.weak_entity(); + window.spawn_with_priority(priority, self, async move |cx| f(view, cx).await) + } + + /// Register a callback to be invoked when the given global state changes. + pub fn observe_global_in( + &mut self, + window: &Window, + mut f: impl FnMut(&mut T, &mut Window, &mut Context) + 'static, + ) -> Subscription { + let window_handle = window.handle; + let view = self.weak_entity(); + let (subscription, activate) = self.global_observers.insert( + TypeId::of::(), + Box::new(move |cx| { + // If the entity has been dropped, remove this observer. + if view.upgrade().is_none() { + return false; + } + // If the window is unavailable (e.g. temporarily taken during a + // nested update, or already closed), skip this notification but + // keep the observer alive so it can fire on future changes. + let Ok(entity_alive) = window_handle.update(cx, |_, window, cx| { + view.update(cx, |view, cx| f(view, window, cx)).is_ok() + }) else { + return true; + }; + entity_alive + }), + ); + self.defer(move |_| activate()); + subscription + } + + /// Register a callback to be invoked when the given Action type is dispatched to the window. + pub fn on_action( + &mut self, + action_type: TypeId, + window: &mut Window, + listener: impl Fn(&mut T, &dyn Any, DispatchPhase, &mut Window, &mut Context) + 'static, + ) { + let handle = self.weak_entity(); + window.on_action(action_type, move |action, phase, window, cx| { + handle + .update(cx, |view, cx| { + listener(view, action, phase, window, cx); + }) + .ok(); + }); + } + + /// Move focus to the current view, assuming it implements [`Focusable`]. + pub fn focus_self(&mut self, window: &mut Window) + where + T: Focusable, + { + let view = self.entity(); + window.defer(self, move |window, cx| { + view.read(cx).focus_handle(cx).focus(window, cx) + }) + } +} + +impl Context<'_, T> { + /// Emit an event of the specified type, which can be handled by other entities that have subscribed via `subscribe` methods on their respective contexts. + pub fn emit(&mut self, event: Evt) + where + T: EventEmitter, + Evt: 'static, + { + let event = self + .event_arena + .alloc(|| event) + .map(|it| it as &mut dyn Any); + self.app.pending_effects.push_back(Effect::Emit { + emitter: self.entity_state.entity_id, + event_type: TypeId::of::(), + event, + }); + } +} + +impl AppContext for Context<'_, T> { + #[inline] + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> U) -> Entity { + self.app.new(build_entity) + } + + #[inline] + fn reserve_entity(&mut self) -> Reservation { + self.app.reserve_entity() + } + + #[inline] + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> U, + ) -> Entity { + self.app.insert_entity(reservation, build_entity) + } + + #[inline] + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut U, &mut Context) -> R, + ) -> R { + self.app.update_entity(handle, update) + } + + #[inline] + fn as_mut<'a, E>(&'a mut self, handle: &Entity) -> super::GpuiBorrow<'a, E> + where + E: 'static, + { + self.app.as_mut(handle) + } + + #[inline] + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&U, &App) -> R) -> R + where + U: 'static, + { + self.app.read_entity(handle, read) + } + + #[inline] + fn update_window(&mut self, window: AnyWindowHandle, update: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> R, + { + self.app.update_window(window, update) + } + + #[inline] + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + self.app.with_window(entity_id, f) + } + + #[inline] + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + U: 'static, + { + self.app.read_window(window, read) + } + + #[inline] + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.app.background_executor.spawn(future) + } + + #[inline] + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + self.app.read_global(callback) + } +} + +impl Borrow for Context<'_, T> { + fn borrow(&self) -> &App { + self.app + } +} + +impl BorrowMut for Context<'_, T> { + fn borrow_mut(&mut self) -> &mut App { + self.app + } +} + +#[inline(never)] +fn invoke_observer( + observer: &WeakEntity, + observed: Entity, + cx: &mut App, + on_notify: &mut dyn FnMut(&mut T, Entity, &mut Context), +) -> bool { + if let Some(observer) = observer.upgrade() { + observer.update(cx, |observer, cx| on_notify(observer, observed, cx)); + true + } else { + false + } +} + +#[inline(never)] +fn invoke_subscriber( + subscriber: &WeakEntity, + emitter: Entity, + event: &Event, + cx: &mut App, + on_event: &mut dyn FnMut(&mut T, Entity, &Event, &mut Context), +) -> bool { + if let Some(subscriber) = subscriber.upgrade() { + subscriber.update(cx, |subscriber, cx| { + on_event(subscriber, emitter, event, cx) + }); + true + } else { + false + } +} + +#[inline(never)] +fn invoke_observer_in( + observer: &WeakEntity, + observed: &WeakEntity, + cx: &mut App, + on_notify: &mut dyn FnMut(&mut T, Entity, &mut Window, &mut Context), +) -> bool { + let Some((observer, observed)) = observer.upgrade().zip(observed.upgrade()) else { + return false; + }; + cx.with_window(observer.entity_id(), |window, cx| { + observer.update(cx, |observer, cx| { + on_notify(observer, observed, window, cx); + }); + }); + true +} + +#[inline(never)] +fn invoke_subscriber_in( + subscriber: &WeakEntity, + emitter: &WeakEntity, + event: &dyn Any, + cx: &mut App, + on_event: &mut dyn FnMut(&mut T, &Entity, &Event, &mut Window, &mut Context), +) -> bool { + let Some((subscriber, emitter)) = subscriber.upgrade().zip(emitter.upgrade()) else { + return false; + }; + let event = event.downcast_ref().expect("invalid event type"); + cx.with_window(subscriber.entity_id(), |window, cx| { + subscriber.update(cx, |subscriber, cx| { + on_event(subscriber, &emitter, event, window, cx); + }); + }); + true +} + +#[inline(never)] +fn invoke_listener( + view: &WeakEntity, + window: &mut Window, + cx: &mut App, + listener: &dyn Fn(&mut T, &mut Window, &mut Context), +) { + view.update(cx, |view, cx| listener(view, window, cx)).ok(); +} diff --git a/vendor/gpui-pre/src/app/entity_map.rs b/vendor/gpui-pre/src/app/entity_map.rs new file mode 100644 index 00000000..38ba7604 --- /dev/null +++ b/vendor/gpui-pre/src/app/entity_map.rs @@ -0,0 +1,1308 @@ +use crate::{App, AppContext, GpuiBorrow, VisualContext, Window, seal::Sealed}; +use anyhow::{Context as _, Result}; +use collections::FxHashSet; +use derive_more::{Deref, DerefMut}; +use parking_lot::{RwLock, RwLockUpgradableReadGuard}; +use slotmap::{KeyData, SecondaryMap, SlotMap}; +use std::{ + any::{Any, TypeId, type_name}, + cell::RefCell, + cmp::Ordering, + fmt::{self, Display}, + hash::{Hash, Hasher}, + marker::PhantomData, + num::NonZeroU64, + sync::{ + Arc, Weak, + atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst}, + }, + thread::panicking, +}; + +use super::Context; +use crate::util::atomic_incr_if_not_zero; +#[cfg(any(test, gpui_leak_detection))] +use collections::HashMap; + +slotmap::new_key_type! { + /// A unique identifier for a entity across the application. + pub struct EntityId; +} + +impl From for EntityId { + fn from(value: u64) -> Self { + Self(KeyData::from_ffi(value)) + } +} + +impl EntityId { + /// Converts this entity id to a [NonZeroU64] + pub fn as_non_zero_u64(self) -> NonZeroU64 { + NonZeroU64::new(self.0.as_ffi()).unwrap() + } + + /// Converts this entity id to a [u64] + pub fn as_u64(self) -> u64 { + self.0.as_ffi() + } +} + +impl Display for EntityId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_u64()) + } +} + +pub(crate) struct EntityMap { + entities: SecondaryMap>, + pub accessed_entities: RefCell>, + ref_counts: Arc>, +} + +#[doc(hidden)] +pub(crate) struct EntityRefCounts { + counts: SlotMap, + dropped_entity_ids: Vec, + #[cfg(any(test, gpui_leak_detection))] + leak_detector: LeakDetector, +} + +pub(super) struct LeaseInner { + pub(super) entity: Option>, +} + +impl EntityMap { + pub fn new() -> Self { + Self { + entities: SecondaryMap::new(), + accessed_entities: RefCell::new(FxHashSet::default()), + ref_counts: Arc::new(RwLock::new(EntityRefCounts { + counts: SlotMap::with_key(), + dropped_entity_ids: Vec::new(), + #[cfg(any(test, gpui_leak_detection))] + leak_detector: LeakDetector { + next_handle_id: 0, + entity_handles: HashMap::default(), + }, + })), + } + } + + #[doc(hidden)] + pub fn ref_counts_drop_handle(&self) -> Arc> { + self.ref_counts.clone() + } + + /// Captures a snapshot of all entities that currently have alive handles. + /// + /// The returned [`LeakDetectorSnapshot`] can later be passed to + /// [`assert_no_new_leaks`](Self::assert_no_new_leaks) to verify that no + /// entities created after the snapshot are still alive. + #[cfg(any(test, gpui_leak_detection))] + pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot { + self.ref_counts.read().leak_detector.snapshot() + } + + /// Asserts that no entities created after `snapshot` still have alive handles. + /// + /// See [`LeakDetector::assert_no_new_leaks`] for details. + #[cfg(any(test, gpui_leak_detection))] + pub fn assert_no_new_leaks(&self, snapshot: &LeakDetectorSnapshot) { + self.ref_counts + .read() + .leak_detector + .assert_no_new_leaks(snapshot) + } + + /// Reserve a slot for an entity, which you can subsequently use with `insert`. + pub fn reserve(&self) -> Slot { + let id = self.ref_counts.write().counts.insert(1.into()); + Slot(Entity::new(id, Arc::downgrade(&self.ref_counts))) + } + + /// Insert an entity into a slot obtained by calling `reserve`. + pub fn insert(&mut self, slot: Slot, entity: T) -> Entity + where + T: 'static, + { + let mut accessed_entities = self.accessed_entities.get_mut(); + accessed_entities.insert(slot.entity_id); + + let handle = slot.0; + self.entities.insert(handle.entity_id, Box::new(entity)); + handle + } + + /// Move an entity to the stack. + #[track_caller] + pub fn lease(&mut self, pointer: &Entity) -> Lease { + Lease { + inner: self.lease_erased(pointer, type_name::()), + id: pointer.entity_id, + entity_type: PhantomData, + } + } + + /// Returns an entity after moving it to the stack. + pub fn end_lease(&mut self, lease: Lease) { + self.end_lease_erased(lease.id, lease.inner); + } + + #[inline(always)] + pub fn read(&self, entity: &Entity) -> &T { + self.assert_valid_context(entity); + self.read_inner(entity.entity_id) + .and_then(|entity| entity.downcast_ref()) + .unwrap_or_else(|| double_lease_panic("read", type_name::())) + } + + #[track_caller] + pub(super) fn lease_erased(&mut self, pointer: &AnyEntity, entity_type: &str) -> LeaseInner { + self.assert_valid_context(pointer); + let entity = Some( + self.lease_inner(pointer.entity_id) + .unwrap_or_else(|| double_lease_panic("update", entity_type)), + ); + LeaseInner { entity } + } + + pub(super) fn end_lease_erased(&mut self, entity_id: EntityId, mut lease: LeaseInner) { + self.end_lease_inner(entity_id, lease.entity.take().unwrap()); + } + + fn assert_valid_context(&self, entity: &AnyEntity) { + debug_assert!( + Weak::ptr_eq(&entity.entity_map, &Arc::downgrade(&self.ref_counts)), + "used a entity with the wrong context" + ); + } + + pub fn extend_accessed(&mut self, entities: &FxHashSet) { + self.accessed_entities + .get_mut() + .extend(entities.iter().copied()); + } + + pub fn clear_accessed(&mut self) { + self.accessed_entities.get_mut().clear(); + } + + pub fn take_dropped(&mut self) -> Vec<(EntityId, Box)> { + let mut ref_counts = &mut *self.ref_counts.write(); + let dropped_entity_ids = ref_counts.dropped_entity_ids.drain(..); + let mut accessed_entities = self.accessed_entities.get_mut(); + + dropped_entity_ids + .filter_map(|entity_id| { + let count = ref_counts.counts.remove(entity_id).unwrap(); + debug_assert_eq!( + count.load(SeqCst), + 0, + "dropped an entity that was referenced" + ); + accessed_entities.remove(&entity_id); + // If the EntityId was allocated with `Context::reserve`, + // the entity may not have been inserted. + Some((entity_id, self.entities.remove(entity_id)?)) + }) + .collect() + } + + #[inline(never)] + fn read_inner(&self, entity_id: EntityId) -> Option<&dyn Any> { + let mut accessed_entities = self.accessed_entities.borrow_mut(); + accessed_entities.insert(entity_id); + self.entities.get(entity_id).map(Box::as_ref) + } + + #[inline(never)] + fn lease_inner(&mut self, entity_id: EntityId) -> Option> { + self.accessed_entities.get_mut().insert(entity_id); + self.entities.remove(entity_id) + } + + #[inline(never)] + fn end_lease_inner(&mut self, entity_id: EntityId, entity: Box) { + self.entities.insert(entity_id, entity); + } +} + +#[track_caller] +fn double_lease_panic(operation: &str, entity_type: &str) -> ! { + panic!("cannot {operation} {entity_type} while it is already being updated") +} + +pub(crate) struct Lease { + pub id: EntityId, + inner: LeaseInner, + entity_type: PhantomData, +} + +impl core::ops::Deref for Lease { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.inner.entity.as_ref().unwrap().downcast_ref().unwrap() + } +} + +impl core::ops::DerefMut for Lease { + fn deref_mut(&mut self) -> &mut Self::Target { + self.inner.entity.as_mut().unwrap().downcast_mut().unwrap() + } +} + +impl Drop for LeaseInner { + fn drop(&mut self) { + if self.entity.is_some() && !panicking() { + panic!("Leases must be ended with EntityMap::end_lease") + } + } +} + +#[derive(Deref, DerefMut)] +pub(crate) struct Slot(Entity); + +/// A dynamically typed reference to a entity, which can be downcast into a `Entity`. +pub struct AnyEntity { + pub(crate) entity_id: EntityId, + pub(crate) entity_type: TypeId, + entity_map: Weak>, + #[cfg(any(test, gpui_leak_detection))] + handle_id: HandleId, +} + +impl AnyEntity { + fn new( + id: EntityId, + entity_type: TypeId, + entity_map: Weak>, + #[cfg(any(test, gpui_leak_detection))] type_name: &'static str, + ) -> Self { + Self { + entity_id: id, + entity_type, + #[cfg(any(test, gpui_leak_detection))] + handle_id: entity_map + .clone() + .upgrade() + .unwrap() + .write() + .leak_detector + .handle_created(id, Some(type_name)), + entity_map, + } + } + + /// Returns the id associated with this entity. + #[inline] + pub fn entity_id(&self) -> EntityId { + self.entity_id + } + + /// Returns the [TypeId] associated with this entity. + #[inline] + pub fn entity_type(&self) -> TypeId { + self.entity_type + } + + /// Converts this entity handle into a weak variant, which does not prevent it from being released. + pub fn downgrade(&self) -> AnyWeakEntity { + AnyWeakEntity { + entity_id: self.entity_id, + entity_type: self.entity_type, + entity_ref_counts: self.entity_map.clone(), + } + } + + /// Converts this entity handle into a strongly-typed entity handle of the given type. + /// If this entity handle is not of the specified type, returns itself as an error variant. + pub fn downcast(self) -> Result, AnyEntity> { + if TypeId::of::() == self.entity_type { + Ok(Entity { + any_entity: self, + entity_type: PhantomData, + }) + } else { + Err(self) + } + } +} + +impl Clone for AnyEntity { + fn clone(&self) -> Self { + if let Some(entity_map) = self.entity_map.upgrade() { + let entity_map = entity_map.read(); + let count = entity_map + .counts + .get(self.entity_id) + .expect("detected over-release of a entity"); + let prev_count = count.fetch_add(1, SeqCst); + assert_ne!(prev_count, 0, "Detected over-release of a entity."); + } + + Self { + entity_id: self.entity_id, + entity_type: self.entity_type, + entity_map: self.entity_map.clone(), + #[cfg(any(test, gpui_leak_detection))] + handle_id: self + .entity_map + .upgrade() + .unwrap() + .write() + .leak_detector + .handle_created(self.entity_id, None), + } + } +} + +impl Drop for AnyEntity { + fn drop(&mut self) { + if let Some(entity_map) = self.entity_map.upgrade() { + let entity_map = entity_map.upgradable_read(); + let count = entity_map + .counts + .get(self.entity_id) + .expect("detected over-release of a handle."); + let prev_count = count.fetch_sub(1, SeqCst); + assert_ne!(prev_count, 0, "Detected over-release of a entity."); + if prev_count == 1 { + // We were the last reference to this entity, so we can remove it. + let mut entity_map = RwLockUpgradableReadGuard::upgrade(entity_map); + entity_map.dropped_entity_ids.push(self.entity_id); + } + } + + #[cfg(any(test, gpui_leak_detection))] + if let Some(entity_map) = self.entity_map.upgrade() { + entity_map + .write() + .leak_detector + .handle_released(self.entity_id, self.handle_id) + } + } +} + +impl From> for AnyEntity { + #[inline] + fn from(entity: Entity) -> Self { + entity.any_entity + } +} + +impl Hash for AnyEntity { + #[inline] + fn hash(&self, state: &mut H) { + self.entity_id.hash(state); + } +} + +impl PartialEq for AnyEntity { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.entity_id == other.entity_id + } +} + +impl Eq for AnyEntity {} + +impl Ord for AnyEntity { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.entity_id.cmp(&other.entity_id) + } +} + +impl PartialOrd for AnyEntity { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl std::fmt::Debug for AnyEntity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyEntity") + .field("entity_id", &self.entity_id.as_u64()) + .finish() + } +} + +/// A strong, well-typed reference to a struct which is managed +/// by GPUI +#[derive(Deref, DerefMut)] +pub struct Entity { + #[deref] + #[deref_mut] + pub(crate) any_entity: AnyEntity, + pub(crate) entity_type: PhantomData T>, +} + +impl Sealed for Entity {} + +impl Entity { + #[inline] + fn new(id: EntityId, entity_map: Weak>) -> Self + where + T: 'static, + { + Self { + any_entity: AnyEntity::new( + id, + TypeId::of::(), + entity_map, + #[cfg(any(test, gpui_leak_detection))] + std::any::type_name::(), + ), + entity_type: PhantomData, + } + } + + /// Get the entity ID associated with this entity + #[inline] + pub fn entity_id(&self) -> EntityId { + self.any_entity.entity_id + } + + /// Downgrade this entity pointer to a non-retaining weak pointer + #[inline] + pub fn downgrade(&self) -> WeakEntity { + WeakEntity { + any_entity: self.any_entity.downgrade(), + entity_type: self.entity_type, + } + } + + /// Convert this into a dynamically typed entity. + #[inline] + pub fn into_any(self) -> AnyEntity { + self.any_entity + } + + /// Grab a reference to this entity from the context. + #[inline] + pub fn read<'a>(&self, cx: &'a App) -> &'a T { + cx.entities.read(self) + } + + /// Read the entity referenced by this handle with the given function. + #[inline] + pub fn read_with(&self, cx: &C, f: impl FnOnce(&T, &App) -> R) -> R { + cx.read_entity(self, f) + } + + /// Updates the entity referenced by this handle with the given function. + #[inline] + pub fn update( + &self, + cx: &mut C, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + cx.update_entity(self, update) + } + + /// Updates the entity referenced by this handle with the given function. + #[inline] + pub fn as_mut<'a, C: AppContext>(&self, cx: &'a mut C) -> GpuiBorrow<'a, T> { + cx.as_mut(self) + } + + /// Updates the entity referenced by this handle with the given function. + pub fn write(&self, cx: &mut C, value: T) { + self.update(cx, |entity, cx| { + *entity = value; + cx.notify(); + }) + } + + /// Updates the entity referenced by this handle with the given function if + /// the referenced entity still exists, within a visual context that has a window. + /// Returns an error if the window has been closed. + #[inline] + pub fn update_in( + &self, + cx: &mut C, + update: impl FnOnce(&mut T, &mut Window, &mut Context) -> R, + ) -> C::Result { + cx.update_window_entity(self, update) + } +} + +impl Clone for Entity { + #[inline] + fn clone(&self) -> Self { + Self { + any_entity: self.any_entity.clone(), + entity_type: self.entity_type, + } + } +} + +impl std::fmt::Debug for Entity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Entity") + .field("entity_id", &self.any_entity.entity_id) + .field("entity_type", &type_name::()) + .finish() + } +} + +impl Hash for Entity { + #[inline] + fn hash(&self, state: &mut H) { + self.any_entity.hash(state); + } +} + +impl PartialEq for Entity { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.any_entity == other.any_entity + } +} + +impl Eq for Entity {} + +impl PartialEq> for Entity { + #[inline] + fn eq(&self, other: &WeakEntity) -> bool { + self.any_entity.entity_id() == other.entity_id() + } +} + +impl Ord for Entity { + #[inline] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.entity_id().cmp(&other.entity_id()) + } +} + +impl PartialOrd for Entity { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// A type erased, weak reference to a entity. +#[derive(Clone)] +pub struct AnyWeakEntity { + pub(crate) entity_id: EntityId, + entity_type: TypeId, + entity_ref_counts: Weak>, +} + +impl AnyWeakEntity { + /// Get the entity ID associated with this weak reference. + #[inline] + pub fn entity_id(&self) -> EntityId { + self.entity_id + } + + /// Check if this weak handle can be upgraded, or if the entity has already been dropped + pub fn is_upgradable(&self) -> bool { + let ref_count = self + .entity_ref_counts + .upgrade() + .and_then(|ref_counts| Some(ref_counts.read().counts.get(self.entity_id)?.load(SeqCst))) + .unwrap_or(0); + ref_count > 0 + } + + /// Upgrade this weak entity reference to a strong reference. + pub fn upgrade(&self) -> Option { + let ref_counts = &self.entity_ref_counts.upgrade()?; + let ref_counts = ref_counts.read(); + let ref_count = ref_counts.counts.get(self.entity_id)?; + + if atomic_incr_if_not_zero(ref_count) == 0 { + // entity_id is in dropped_entity_ids + return None; + } + drop(ref_counts); + + Some(AnyEntity { + entity_id: self.entity_id, + entity_type: self.entity_type, + entity_map: self.entity_ref_counts.clone(), + #[cfg(any(test, gpui_leak_detection))] + handle_id: self + .entity_ref_counts + .upgrade() + .unwrap() + .write() + .leak_detector + .handle_created(self.entity_id, None), + }) + } + + /// Asserts that the entity referenced by this weak handle has been fully released. + /// + /// # Example + /// + /// ```ignore + /// let entity = cx.new(|_| MyEntity::new()); + /// let weak = entity.downgrade(); + /// drop(entity); + /// + /// // Verify the entity was released + /// weak.assert_released(); + /// ``` + /// + /// # Debugging Leaks + /// + /// With leak detection enabled (build with `GPUI_LEAK_DETECTION=1`), a failure + /// lists each leaked handle. Also set the `LEAK_BACKTRACE` environment variable + /// to see where they were allocated: + /// + /// ```bash + /// GPUI_LEAK_DETECTION=1 LEAK_BACKTRACE=1 cargo test my_test + /// ``` + /// + /// # Panics + /// + /// - Panics if any strong handles to the entity are still alive. + /// - Panics if the entity was recently dropped but cleanup hasn't completed yet + /// (resources are retained until the end of the effect cycle). + #[cfg(any(test, feature = "test-support", gpui_leak_detection))] + pub fn assert_released(&self) { + #[cfg(any(test, gpui_leak_detection))] + self.entity_ref_counts + .upgrade() + .unwrap() + .write() + .leak_detector + .assert_released(self.entity_id); + + if self + .entity_ref_counts + .upgrade() + .and_then(|ref_counts| Some(ref_counts.read().counts.get(self.entity_id)?.load(SeqCst))) + .is_some() + { + panic!( + "entity is still alive, or was recently dropped and its resources are retained \ + until the end of the effect cycle. Build with GPUI_LEAK_DETECTION=1 to list \ + its live handles." + ) + } + } + + /// Creates a weak entity that can never be upgraded. + pub fn new_invalid() -> Self { + /// To hold the invariant that all ids are unique, and considering that slotmap + /// increases their IDs from `0`, we can decrease ours from `u64::MAX` so these + /// two will never conflict (u64 is way too large). + static UNIQUE_NON_CONFLICTING_ID_GENERATOR: AtomicU64 = AtomicU64::new(u64::MAX); + let entity_id = UNIQUE_NON_CONFLICTING_ID_GENERATOR.fetch_sub(1, SeqCst); + + Self { + // Safety: + // Docs say this is safe but can be unspecified if slotmap changes the representation + // after `1.0.7`, that said, providing a valid entity_id here is not necessary as long + // as we guarantee that `entity_id` is never used if `entity_ref_counts` equals + // to `Weak::new()` (that is, it's unable to upgrade), that is the invariant that + // actually needs to be hold true. + // + // And there is no sane reason to read an entity slot if `entity_ref_counts` can't be + // read in the first place, so we're good! + entity_id: entity_id.into(), + entity_type: TypeId::of::<()>(), + entity_ref_counts: Weak::new(), + } + } +} + +impl std::fmt::Debug for AnyWeakEntity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(type_name::()) + .field("entity_id", &self.entity_id) + .field("entity_type", &self.entity_type) + .finish() + } +} + +impl From> for AnyWeakEntity { + #[inline] + fn from(entity: WeakEntity) -> Self { + entity.any_entity + } +} + +impl Hash for AnyWeakEntity { + #[inline] + fn hash(&self, state: &mut H) { + self.entity_id.hash(state); + } +} + +impl PartialEq for AnyWeakEntity { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.entity_id == other.entity_id + } +} + +impl Eq for AnyWeakEntity {} + +impl Ord for AnyWeakEntity { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.entity_id.cmp(&other.entity_id) + } +} + +impl PartialOrd for AnyWeakEntity { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// A weak reference to a entity of the given type. +#[derive(Deref, DerefMut)] +pub struct WeakEntity { + #[deref] + #[deref_mut] + any_entity: AnyWeakEntity, + entity_type: PhantomData T>, +} + +impl std::fmt::Debug for WeakEntity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(type_name::()) + .field("entity_id", &self.any_entity.entity_id) + .field("entity_type", &type_name::()) + .finish() + } +} + +impl Clone for WeakEntity { + fn clone(&self) -> Self { + Self { + any_entity: self.any_entity.clone(), + entity_type: self.entity_type, + } + } +} + +impl WeakEntity { + /// Upgrade this weak entity reference into a strong entity reference + pub fn upgrade(&self) -> Option> { + Some(Entity { + any_entity: self.any_entity.upgrade()?, + entity_type: self.entity_type, + }) + } + + /// Updates the entity referenced by this handle with the given function if + /// the referenced entity still exists. Returns an error if the entity has + /// been released. + #[inline(always)] + pub fn update( + &self, + cx: &mut C, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> Result + where + C: AppContext, + { + let entity = self.upgrade().context("entity released")?; + Ok(cx.update_entity(&entity, update)) + } + + /// Updates the entity referenced by this handle with the given function if + /// the referenced entity still exists, within a visual context that has a window. + /// Returns an error if the entity has been released. + #[inline(always)] + pub fn update_in( + &self, + cx: &mut C, + update: impl FnOnce(&mut T, &mut Window, &mut Context) -> R, + ) -> Result + where + C: AppContext, + { + let entity = self.upgrade().context("entity released")?; + cx.with_window(entity.entity_id(), |window, app| { + entity.update(app, |entity, cx| update(entity, window, cx)) + }) + .context("entity has no current window") + } + + /// Reads the entity referenced by this handle with the given function if + /// the referenced entity still exists. Returns an error if the entity has + /// been released. + #[inline(always)] + pub fn read_with(&self, cx: &C, read: impl FnOnce(&T, &App) -> R) -> Result + where + C: AppContext, + { + let entity = self.upgrade().context("entity released")?; + Ok(cx.read_entity(&entity, read)) + } + + /// Create a new weak entity that can never be upgraded. + #[inline] + pub fn new_invalid() -> Self { + Self { + any_entity: AnyWeakEntity::new_invalid(), + entity_type: PhantomData, + } + } +} + +impl Hash for WeakEntity { + #[inline] + fn hash(&self, state: &mut H) { + self.any_entity.hash(state); + } +} + +impl PartialEq for WeakEntity { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.any_entity == other.any_entity + } +} + +impl Eq for WeakEntity {} + +impl PartialEq> for WeakEntity { + #[inline] + fn eq(&self, other: &Entity) -> bool { + self.entity_id() == other.any_entity.entity_id() + } +} + +impl Ord for WeakEntity { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.entity_id().cmp(&other.entity_id()) + } +} + +impl PartialOrd for WeakEntity { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// Controls whether backtraces are captured when entity handles are created. +/// +/// Set the `LEAK_BACKTRACE` environment variable to any non-empty value to enable +/// backtrace capture. This helps identify where leaked handles were allocated. +#[cfg(any(test, gpui_leak_detection))] +static LEAK_BACKTRACE: std::sync::LazyLock = + std::sync::LazyLock::new(|| std::env::var("LEAK_BACKTRACE").is_ok_and(|b| !b.is_empty())); + +/// Unique identifier for a specific entity handle instance. +/// +/// This is distinct from `EntityId` - while multiple handles can point to the same +/// entity (same `EntityId`), each handle has its own unique `HandleId`. +#[cfg(any(test, gpui_leak_detection))] +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)] +pub(crate) struct HandleId { + id: u64, +} + +/// Tracks entity handle allocations to detect leaks. +/// +/// The leak detector is enabled in tests and when the `leak-detection` feature is active. +/// It tracks every `Entity` and `AnyEntity` handle that is created and released, +/// allowing you to verify that all handles to an entity have been properly dropped. +/// +/// # How do leaks happen? +/// +/// Entities are reference-counted structures that can own other entities +/// allowing to form cycles. If such a strong-reference counted cycle is +/// created, all participating strong entities in this cycle will effectively +/// leak as they cannot be released anymore. +/// +/// Cycles can also happen if an entity owns a task or subscription that it +/// itself owns a strong reference to the entity again. +/// +/// # Usage +/// +/// You can use `WeakEntity::assert_released` or `AnyWeakEntity::assert_released` +/// to verify that an entity has been fully released: +/// +/// ```ignore +/// let entity = cx.new(|_| MyEntity::new()); +/// let weak = entity.downgrade(); +/// drop(entity); +/// +/// // This will panic if any handles to the entity are still alive +/// weak.assert_released(); +/// ``` +/// +/// # Debugging Leaks +/// +/// When a leak is detected, the detector will panic with information about the leaked +/// handles. To see where the leaked handles were allocated, set the `LEAK_BACKTRACE` +/// environment variable: +/// +/// ```bash +/// LEAK_BACKTRACE=1 cargo test my_test +/// ``` +/// +/// This will capture and display backtraces for each leaked handle, helping you +/// identify where leaked handles were created. +/// +/// # How It Works +/// +/// - When an entity handle is created (via `Entity::new`, `Entity::clone`, or +/// `WeakEntity::upgrade`), `handle_created` is called to register the handle. +/// - When a handle is dropped, `handle_released` removes it from tracking. +/// - `assert_released` verifies that no handles remain for a given entity. +#[cfg(any(test, gpui_leak_detection))] +pub(crate) struct LeakDetector { + next_handle_id: u64, + entity_handles: HashMap, +} + +/// A snapshot of the set of alive entities at a point in time. +/// +/// Created by [`LeakDetector::snapshot`]. Can later be passed to +/// [`LeakDetector::assert_no_new_leaks`] to verify that no new entity +/// handles remain between the snapshot and the current state. +#[cfg(any(test, feature = "test-support", gpui_leak_detection))] +#[derive(Default)] +pub struct LeakDetectorSnapshot { + #[cfg(any(test, gpui_leak_detection))] + entity_ids: collections::HashSet, +} + +#[cfg(any(test, gpui_leak_detection))] +struct EntityLeakData { + handles: HashMap>, + type_name: &'static str, +} + +#[cfg(any(test, gpui_leak_detection))] +impl LeakDetector { + /// Records that a new handle has been created for the given entity. + /// + /// Returns a unique `HandleId` that must be passed to `handle_released` when + /// the handle is dropped. If `LEAK_BACKTRACE` is set, captures a backtrace + /// at the allocation site. + #[track_caller] + pub fn handle_created( + &mut self, + entity_id: EntityId, + type_name: Option<&'static str>, + ) -> HandleId { + let id = gpui_util::post_inc(&mut self.next_handle_id); + let handle_id = HandleId { id }; + let handles = self + .entity_handles + .entry(entity_id) + .or_insert_with(|| EntityLeakData { + handles: HashMap::default(), + type_name: type_name.unwrap_or(""), + }); + handles.handles.insert( + handle_id, + LEAK_BACKTRACE.then(backtrace::Backtrace::new_unresolved), + ); + handle_id + } + + /// Records that a handle has been released (dropped). + /// + /// This removes the handle from tracking. The `handle_id` should be the same + /// one returned by `handle_created` when the handle was allocated. + pub fn handle_released(&mut self, entity_id: EntityId, handle_id: HandleId) { + if let std::collections::hash_map::Entry::Occupied(mut data) = + self.entity_handles.entry(entity_id) + { + data.get_mut().handles.remove(&handle_id); + if data.get().handles.is_empty() { + data.remove(); + } + } + } + + /// Asserts that all handles to the given entity have been released. + /// + /// # Panics + /// + /// Panics if any handles to the entity are still alive. The panic message + /// includes backtraces for each leaked handle if `LEAK_BACKTRACE` is set, + /// otherwise it suggests setting the environment variable to get more info. + pub fn assert_released(&mut self, entity_id: EntityId) { + use std::fmt::Write as _; + + if let Some(data) = self.entity_handles.remove(&entity_id) { + let mut out = String::new(); + for (_, backtrace) in data.handles { + if let Some(mut backtrace) = backtrace { + backtrace.resolve(); + let backtrace = BacktraceFormatter(backtrace); + writeln!(out, "Leaked handle:\n{:?}", backtrace).unwrap(); + } else { + writeln!( + out, + "Leaked handle: (export LEAK_BACKTRACE to find allocation site)" + ) + .unwrap(); + } + } + panic!("Handles for {} leaked:\n{out}", data.type_name); + } + } + + /// Captures a snapshot of all entity IDs that currently have alive handles. + /// + /// The returned [`LeakDetectorSnapshot`] can later be passed to + /// [`assert_no_new_leaks`](Self::assert_no_new_leaks) to verify that no + /// entities created after the snapshot are still alive. + pub fn snapshot(&self) -> LeakDetectorSnapshot { + LeakDetectorSnapshot { + entity_ids: self.entity_handles.keys().copied().collect(), + } + } + + /// Asserts that no entities created after `snapshot` still have alive handles. + /// + /// Entities that were already tracked at the time of the snapshot are ignored, + /// even if they still have handles. Only *new* entities (those whose + /// `EntityId` was not present in the snapshot) are considered leaks. + /// + /// # Panics + /// + /// Panics if any new entity handles exist. The panic message lists every + /// leaked entity with its type name, and includes allocation-site backtraces + /// when `LEAK_BACKTRACE` is set. + pub fn assert_no_new_leaks(&self, snapshot: &LeakDetectorSnapshot) { + use std::fmt::Write as _; + + let mut out = String::new(); + for (entity_id, data) in &self.entity_handles { + if snapshot.entity_ids.contains(entity_id) { + continue; + } + for (_, backtrace) in &data.handles { + if let Some(backtrace) = backtrace { + let mut backtrace = backtrace.clone(); + backtrace.resolve(); + let backtrace = BacktraceFormatter(backtrace); + writeln!( + out, + "Leaked handle for entity {} ({entity_id:?}):\n{:?}", + data.type_name, backtrace + ) + .unwrap(); + } else { + writeln!( + out, + "Leaked handle for entity {} ({entity_id:?}): (export LEAK_BACKTRACE to find allocation site)", + data.type_name + ) + .unwrap(); + } + } + } + + if !out.is_empty() { + panic!("New entity leaks detected since snapshot:\n{out}"); + } + } +} + +#[cfg(any(test, gpui_leak_detection))] +impl Drop for LeakDetector { + fn drop(&mut self) { + use std::fmt::Write; + + if self.entity_handles.is_empty() || std::thread::panicking() { + return; + } + + let mut out = String::new(); + for (entity_id, data) in self.entity_handles.drain() { + for (_handle, backtrace) in data.handles { + if let Some(mut backtrace) = backtrace { + backtrace.resolve(); + let backtrace = BacktraceFormatter(backtrace); + writeln!( + out, + "Leaked handle for entity {} ({entity_id:?}):\n{:?}", + data.type_name, backtrace + ) + .unwrap(); + } else { + writeln!( + out, + "Leaked handle for entity {} ({entity_id:?}): (export LEAK_BACKTRACE to find allocation site)", + data.type_name + ) + .unwrap(); + } + } + } + panic!("Exited with leaked handles:\n{out}"); + } +} + +#[cfg(any(test, gpui_leak_detection))] +struct BacktraceFormatter(backtrace::Backtrace); + +#[cfg(any(test, gpui_leak_detection))] +impl fmt::Debug for BacktraceFormatter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + use backtrace::{BacktraceFmt, BytesOrWideString, PrintFmt}; + + let style = if fmt.alternate() { + PrintFmt::Full + } else { + PrintFmt::Short + }; + + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = std::env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| { + let path = path.into_path_buf(); + if style != PrintFmt::Full { + if let Ok(cwd) = &cwd { + if let Ok(suffix) = path.strip_prefix(cwd) { + return fmt::Display::fmt(&suffix.display(), fmt); + } + } + } + fmt::Display::fmt(&path.display(), fmt) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + let mut strip = true; + for frame in self.0.frames() { + if let [symbol, ..] = frame.symbols() + && let Some(name) = symbol.name() + && let Some(filename) = name.as_str() + { + match filename { + "test::run_test_in_process" + | "scheduler::executor::spawn_local_with_source_location::impl$1::poll > > > >,alloc::alloc::Global> > >" => { + strip = true + } + "gpui::app::entity_map::LeakDetector::handle_created" => { + strip = false; + continue; + } + "zed::main" => { + strip = true; + f.frame().backtrace_frame(frame)?; + } + _ => {} + } + } + if strip { + continue; + } + f.frame().backtrace_frame(frame)?; + } + f.finish()?; + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::EntityMap; + + struct TestEntity { + pub i: i32, + } + + #[test] + fn test_entity_map_slot_assignment_before_cleanup() { + // Tests that slots are not re-used before take_dropped. + let mut entity_map = EntityMap::new(); + + let slot = entity_map.reserve::(); + entity_map.insert(slot, TestEntity { i: 1 }); + + let slot = entity_map.reserve::(); + entity_map.insert(slot, TestEntity { i: 2 }); + + let dropped = entity_map.take_dropped(); + assert_eq!(dropped.len(), 2); + + assert_eq!( + dropped + .into_iter() + .map(|(_, entity)| entity.downcast::().unwrap().i) + .collect::>(), + vec![1, 2], + ); + } + + #[test] + fn test_entity_map_weak_upgrade_before_cleanup() { + // Tests that weak handles are not upgraded before take_dropped + let mut entity_map = EntityMap::new(); + + let slot = entity_map.reserve::(); + let handle = entity_map.insert(slot, TestEntity { i: 1 }); + let weak = handle.downgrade(); + drop(handle); + + let strong = weak.upgrade(); + assert_eq!(strong, None); + + let dropped = entity_map.take_dropped(); + assert_eq!(dropped.len(), 1); + + assert_eq!( + dropped + .into_iter() + .map(|(_, entity)| entity.downcast::().unwrap().i) + .collect::>(), + vec![1], + ); + } + + #[test] + fn test_leak_detector_snapshot_no_leaks() { + let mut entity_map = EntityMap::new(); + + let slot = entity_map.reserve::(); + let pre_existing = entity_map.insert(slot, TestEntity { i: 1 }); + + let snapshot = entity_map.leak_detector_snapshot(); + + let slot = entity_map.reserve::(); + let temporary = entity_map.insert(slot, TestEntity { i: 2 }); + drop(temporary); + + entity_map.assert_no_new_leaks(&snapshot); + + drop(pre_existing); + } + + #[test] + #[should_panic(expected = "New entity leaks detected since snapshot")] + fn test_leak_detector_snapshot_detects_new_leak() { + let mut entity_map = EntityMap::new(); + + let slot = entity_map.reserve::(); + let pre_existing = entity_map.insert(slot, TestEntity { i: 1 }); + + let snapshot = entity_map.leak_detector_snapshot(); + + let slot = entity_map.reserve::(); + let leaked = entity_map.insert(slot, TestEntity { i: 2 }); + + // `leaked` is still alive, so this should panic. + entity_map.assert_no_new_leaks(&snapshot); + + drop(pre_existing); + drop(leaked); + } +} diff --git a/vendor/gpui-pre/src/app/headless_app_context.rs b/vendor/gpui-pre/src/app/headless_app_context.rs new file mode 100644 index 00000000..6ac4bfe9 --- /dev/null +++ b/vendor/gpui-pre/src/app/headless_app_context.rs @@ -0,0 +1,284 @@ +//! Cross-platform headless app context for tests that need real text shaping. +//! +//! This replaces the macOS-only `HeadlessMetalAppContext` with a platform-neutral +//! implementation backed by `TestPlatform`. Tests supply a real `PlatformTextSystem` +//! (e.g. `DirectWriteTextSystem` on Windows, `MacTextSystem` on macOS) to get +//! accurate glyph measurements while keeping everything else deterministic. +//! +//! Optionally, a renderer factory can be provided to enable real GPU rendering +//! and screenshot capture via [`HeadlessAppContext::capture_screenshot`]. + +use crate::{ + AnyView, AnyWindowHandle, App, AppCell, AppContext, AssetSource, BackgroundExecutor, Bounds, + Context, Entity, EntityId, ForegroundExecutor, Global, Pixels, PlatformHeadlessRenderer, + PlatformTextSystem, Render, Reservation, Size, Task, TestDispatcher, TestPlatform, TextSystem, + Window, WindowBounds, WindowHandle, WindowOptions, + app::{GpuiBorrow, GpuiMode}, +}; +use anyhow::Result; +use image::RgbaImage; +use std::{future::Future, rc::Rc, sync::Arc, time::Duration}; + +/// A cross-platform headless app context for tests that need real text shaping. +/// +/// Unlike the old `HeadlessMetalAppContext`, this works on any platform. It uses +/// `TestPlatform` for deterministic scheduling and accepts a pluggable +/// `PlatformTextSystem` so tests get real glyph measurements. +/// +/// # Usage +/// +/// ```ignore +/// let text_system = Arc::new(gpui_wgpu::CosmicTextSystem::new("fallback")); +/// let mut cx = HeadlessAppContext::with_platform( +/// text_system, +/// Arc::new(Assets), +/// || gpui_platform::current_headless_renderer(), +/// ); +/// ``` +pub struct HeadlessAppContext { + /// The underlying app cell. + pub app: Rc, + /// The background executor for running async tasks. + pub background_executor: BackgroundExecutor, + /// The foreground executor for running tasks on the main thread. + pub foreground_executor: ForegroundExecutor, + dispatcher: TestDispatcher, + text_system: Arc, +} + +impl HeadlessAppContext { + /// Creates a new headless app context with the given text system. + pub fn new(platform_text_system: Arc) -> Self { + Self::with_platform(platform_text_system, Arc::new(()), || Ok(None)) + } + + /// Creates a new headless app context with a custom text system and asset source. + pub fn with_asset_source( + platform_text_system: Arc, + asset_source: Arc, + ) -> Self { + Self::with_platform(platform_text_system, asset_source, || Ok(None)) + } + + /// Creates a new headless app context with the given text system, asset source, + /// and an optional renderer factory for screenshot support. + pub fn with_platform( + platform_text_system: Arc, + asset_source: Arc, + renderer_factory: impl Fn() -> Result>> + 'static, + ) -> Self { + let seed = std::env::var("SEED") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(0); + + let dispatcher = TestDispatcher::new(seed); + let arc_dispatcher = Arc::new(dispatcher.clone()); + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + + let renderer_factory: Box Result>>> = + Box::new(renderer_factory); + let platform = TestPlatform::with_platform( + background_executor.clone(), + foreground_executor.clone(), + platform_text_system.clone(), + Some(renderer_factory), + ); + + let text_system = Arc::new(TextSystem::new(platform_text_system)); + let http_client = http_client::FakeHttpClient::with_404_response(); + let app = App::new_app(platform, asset_source, http_client); + app.borrow_mut().mode = GpuiMode::test(); + + Self { + app, + background_executor, + foreground_executor, + dispatcher, + text_system, + } + } + + /// Opens a window for headless rendering. + pub fn open_window( + &mut self, + size: Size, + build_root: impl FnOnce(&mut Window, &mut App) -> Entity, + ) -> Result> { + use crate::{point, px}; + + let bounds = Bounds { + origin: point(px(0.0), px(0.0)), + size, + }; + + let mut cx = self.app.borrow_mut(); + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + focus: false, + show: false, + ..Default::default() + }, + build_root, + ) + } + + /// Runs all pending tasks until parked. + pub fn run_until_parked(&self) { + self.dispatcher.run_until_parked(); + } + + /// Advances the simulated clock. + pub fn advance_clock(&self, duration: Duration) { + self.dispatcher.advance_clock(duration); + } + + /// Enables parking mode, allowing blocking on real I/O (e.g., async asset loading). + pub fn allow_parking(&self) { + self.dispatcher.allow_parking(); + } + + /// Disables parking mode, returning to deterministic test execution. + pub fn forbid_parking(&self) { + self.dispatcher.forbid_parking(); + } + + /// Updates app state. + pub fn update(&mut self, f: impl FnOnce(&mut App) -> R) -> R { + let mut app = self.app.borrow_mut(); + f(&mut app) + } + + /// Updates a window and calls draw to render. + pub fn update_window( + &mut self, + window: AnyWindowHandle, + f: impl FnOnce(AnyView, &mut Window, &mut App) -> R, + ) -> Result { + let mut app = self.app.borrow_mut(); + app.update_window(window, f) + } + + /// Captures a screenshot from a window. + /// + /// Requires that the context was created with a renderer factory that + /// returns `Some` via [`HeadlessAppContext::with_platform`]. + pub fn capture_screenshot(&mut self, window: AnyWindowHandle) -> Result { + let mut app = self.app.borrow_mut(); + app.update_window(window, |_, window, _| window.render_to_image())? + } + + /// Returns the text system. + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// Returns the background executor. + pub fn background_executor(&self) -> &BackgroundExecutor { + &self.background_executor + } + + /// Returns the foreground executor. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } +} + +impl Drop for HeadlessAppContext { + fn drop(&mut self) { + // Shut down the app so windows are closed and entity handles are + // released before the LeakDetector runs. + self.app.borrow_mut().shutdown(); + } +} + +impl AppContext for HeadlessAppContext { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + let mut app = self.app.borrow_mut(); + app.new(build_entity) + } + + fn reserve_entity(&mut self) -> Reservation { + let mut app = self.app.borrow_mut(); + app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let mut app = self.app.borrow_mut(); + app.insert_entity(reservation, build_entity) + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let mut app = self.app.borrow_mut(); + app.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, _: &Entity) -> GpuiBorrow<'a, T> + where + T: 'static, + { + panic!("Cannot use as_mut with HeadlessAppContext. Call update() instead.") + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let app = self.app.borrow(); + app.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut lock = self.app.borrow_mut(); + lock.update_window(window, f) + } + + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let mut lock = self.app.borrow_mut(); + lock.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let app = self.app.borrow(); + app.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let app = self.app.borrow(); + app.read_global(callback) + } +} diff --git a/vendor/gpui-pre/src/app/test_app.rs b/vendor/gpui-pre/src/app/test_app.rs new file mode 100644 index 00000000..bf265fd7 --- /dev/null +++ b/vendor/gpui-pre/src/app/test_app.rs @@ -0,0 +1,645 @@ +//! A clean testing API for GPUI applications. +//! +//! `TestApp` provides a simpler alternative to `TestAppContext` with: +//! - Automatic effect flushing after updates +//! - Clean window creation and inspection +//! - Input simulation helpers +//! +//! # Example +//! ```ignore +//! #[test] +//! fn test_my_view() { +//! let mut app = TestApp::new(); +//! +//! let mut window = app.open_window(|window, cx| { +//! MyView::new(window, cx) +//! }); +//! +//! window.update(|view, window, cx| { +//! view.do_something(cx); +//! }); +//! +//! // Check rendered state +//! assert_eq!(window.title(), Some("Expected Title")); +//! } +//! ``` + +use crate::{ + AnyWindowHandle, App, AppCell, AppContext, AsyncApp, BackgroundExecutor, BorrowAppContext, + Bounds, ClipboardItem, Context, Entity, ForegroundExecutor, Global, InputEvent, Keystroke, + MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Platform, + PlatformTextSystem, Point, Render, Size, Task, TestDispatcher, TestPlatform, TextSystem, + Window, WindowBounds, WindowHandle, WindowOptions, app::GpuiMode, +}; +use std::{future::Future, rc::Rc, sync::Arc, time::Duration}; + +/// A test application context with a clean API. +/// +/// Unlike `TestAppContext`, `TestApp` automatically flushes effects after +/// each update and provides simpler window management. +pub struct TestApp { + app: Rc, + platform: Rc, + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + #[allow(dead_code)] + dispatcher: TestDispatcher, + text_system: Arc, +} + +impl TestApp { + /// Create a new test application. + pub fn new() -> Self { + Self::with_seed(0) + } + + /// Create a new test application with a specific random seed. + pub fn with_seed(seed: u64) -> Self { + Self::build(seed, None, Arc::new(())) + } + + /// Create a new test application with a custom text system for real font shaping. + pub fn with_text_system(text_system: Arc) -> Self { + Self::build(0, Some(text_system), Arc::new(())) + } + + /// Create a new test application with a custom text system and asset source. + pub fn with_text_system_and_assets( + text_system: Arc, + asset_source: Arc, + ) -> Self { + Self::build(0, Some(text_system), asset_source) + } + + fn build( + seed: u64, + platform_text_system: Option>, + asset_source: Arc, + ) -> Self { + let dispatcher = TestDispatcher::new(seed); + let arc_dispatcher = Arc::new(dispatcher.clone()); + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + let platform = match platform_text_system.clone() { + Some(ts) => TestPlatform::with_text_system( + background_executor.clone(), + foreground_executor.clone(), + ts, + ), + None => TestPlatform::new(background_executor.clone(), foreground_executor.clone()), + }; + let http_client = http_client::FakeHttpClient::with_404_response(); + let text_system = Arc::new(TextSystem::new( + platform_text_system.unwrap_or_else(|| platform.text_system.clone()), + )); + + let app = App::new_app(platform.clone(), asset_source, http_client); + app.borrow_mut().mode = GpuiMode::test(); + + Self { + app, + platform, + background_executor, + foreground_executor, + dispatcher, + text_system, + } + } + + /// Run a closure with mutable access to the App context. + /// Automatically runs until parked after the closure completes. + pub fn update(&mut self, f: impl FnOnce(&mut App) -> R) -> R { + let result = { + let mut app = self.app.borrow_mut(); + app.update(f) + }; + self.run_until_parked(); + result + } + + /// Run a closure with read-only access to the App context. + pub fn read(&self, f: impl FnOnce(&App) -> R) -> R { + let app = self.app.borrow(); + f(&app) + } + + /// Create a new entity in the app. + pub fn new_entity( + &mut self, + build: impl FnOnce(&mut Context) -> T, + ) -> Entity { + self.update(|cx| cx.new(build)) + } + + /// Update an entity. + pub fn update_entity( + &mut self, + entity: &Entity, + f: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + self.update(|cx| entity.update(cx, f)) + } + + /// Read an entity. + pub fn read_entity( + &self, + entity: &Entity, + f: impl FnOnce(&T, &App) -> R, + ) -> R { + self.read(|cx| f(entity.read(cx), cx)) + } + + /// Open a test window with the given root view, using maximized bounds. + pub fn open_window( + &mut self, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> TestAppWindow { + let bounds = self.read(|cx| Bounds::maximized(None, cx)); + let handle = self.update(|cx| { + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..Default::default() + }, + |window, cx| cx.new(|cx| build_view(window, cx)), + ) + .unwrap() + }); + + TestAppWindow { + handle, + app: self.app.clone(), + platform: self.platform.clone(), + background_executor: self.background_executor.clone(), + } + } + + /// Open a test window with specific options. + pub fn open_window_with_options( + &mut self, + options: WindowOptions, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> TestAppWindow { + let handle = self.update(|cx| { + cx.open_window(options, |window, cx| cx.new(|cx| build_view(window, cx))) + .unwrap() + }); + + TestAppWindow { + handle, + app: self.app.clone(), + platform: self.platform.clone(), + background_executor: self.background_executor.clone(), + } + } + + /// Run pending tasks until there's nothing left to do. + pub fn run_until_parked(&self) { + self.background_executor.run_until_parked(); + } + + /// Advance the simulated clock by the given duration. + pub fn advance_clock(&self, duration: Duration) { + self.background_executor.advance_clock(duration); + } + + /// Spawn a future on the foreground executor. + pub fn spawn(&self, f: impl FnOnce(AsyncApp) -> Fut) -> Task + where + Fut: Future + 'static, + R: 'static, + { + self.foreground_executor.spawn(f(self.to_async())) + } + + /// Spawn a future on the background executor. + pub fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + /// Get an async handle to the app. + pub fn to_async(&self) -> AsyncApp { + AsyncApp { + app: Rc::downgrade(&self.app), + background_executor: self.background_executor.clone(), + foreground_executor: self.foreground_executor.clone(), + } + } + + /// Get the background executor. + pub fn background_executor(&self) -> &BackgroundExecutor { + &self.background_executor + } + + /// Get the foreground executor. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } + + /// Get the text system. + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// Check if a global of the given type exists. + pub fn has_global(&self) -> bool { + self.read(|cx| cx.has_global::()) + } + + /// Set a global value. + pub fn set_global(&mut self, global: G) { + self.update(|cx| cx.set_global(global)); + } + + /// Read a global value. + pub fn read_global(&self, f: impl FnOnce(&G, &App) -> R) -> R { + self.read(|cx| f(cx.global(), cx)) + } + + /// Update a global value. + pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut App) -> R) -> R { + self.update(|cx| cx.update_global(f)) + } + + // Platform simulation methods + + /// Write text to the simulated clipboard. + pub fn write_to_clipboard(&self, item: ClipboardItem) { + self.platform.write_to_clipboard(item); + } + + /// Read from the simulated clipboard. + pub fn read_from_clipboard(&self) -> Option { + self.platform.read_from_clipboard() + } + + /// Get URLs that have been opened via `cx.open_url()`. + pub fn opened_url(&self) -> Option { + self.platform.opened_url.borrow().clone() + } + + /// Check if a file path prompt is pending. + pub fn did_prompt_for_new_path(&self) -> bool { + self.platform.did_prompt_for_new_path() + } + + /// Simulate answering a path selection dialog. + pub fn simulate_new_path_selection( + &self, + select: impl FnOnce(&std::path::Path) -> Option, + ) { + self.platform.simulate_new_path_selection(select); + } + + /// Check if a prompt dialog is pending. + pub fn has_pending_prompt(&self) -> bool { + self.platform.has_pending_prompt() + } + + /// Simulate answering a prompt dialog. + pub fn simulate_prompt_answer(&self, button: &str) { + self.platform.simulate_prompt_answer(button); + } + + /// Get all open windows. + pub fn windows(&self) -> Vec { + self.read(|cx| cx.windows()) + } +} + +impl Default for TestApp { + fn default() -> Self { + Self::new() + } +} + +/// A test window with inspection and simulation capabilities. +pub struct TestAppWindow { + handle: WindowHandle, + app: Rc, + platform: Rc, + background_executor: BackgroundExecutor, +} + +impl TestAppWindow { + /// Get the window handle. + pub fn handle(&self) -> WindowHandle { + self.handle + } + + /// Get the root view entity. + pub fn root(&self) -> Entity { + let mut app = self.app.borrow_mut(); + let any_handle: AnyWindowHandle = self.handle.into(); + app.update_window(any_handle, |root_view, _, _| { + root_view.downcast::().expect("root view type mismatch") + }) + .expect("window not found") + } + + /// Update the root view. + pub fn update(&mut self, f: impl FnOnce(&mut V, &mut Window, &mut Context) -> R) -> R { + let result = { + let mut app = self.app.borrow_mut(); + let any_handle: AnyWindowHandle = self.handle.into(); + app.update_window(any_handle, |root_view, window, cx| { + let view = root_view.downcast::().expect("root view type mismatch"); + view.update(cx, |view, cx| f(view, window, cx)) + }) + .expect("window not found") + }; + self.background_executor.run_until_parked(); + result + } + + /// Read the root view. + pub fn read(&self, f: impl FnOnce(&V, &App) -> R) -> R { + let app = self.app.borrow(); + let view = self + .app + .borrow() + .windows + .get(self.handle.window_id()) + .and_then(|w| w.as_ref()) + .and_then(|w| w.root.clone()) + .and_then(|r| r.downcast::().ok()) + .expect("window or root view not found"); + f(view.read(&app), &app) + } + + /// Get the window title. + pub fn title(&self) -> Option { + let app = self.app.borrow(); + app.read_window(&self.handle, |_, _cx| { + // TODO: expose title through Window API + None + }) + .unwrap() + } + + /// Simulate a keystroke. + pub fn simulate_keystroke(&mut self, keystroke: &str) { + let keystroke = Keystroke::parse(keystroke).unwrap(); + { + let mut app = self.app.borrow_mut(); + let any_handle: AnyWindowHandle = self.handle.into(); + app.update_window(any_handle, |_, window, cx| { + window.dispatch_keystroke(keystroke, cx); + }) + .unwrap(); + } + self.background_executor.run_until_parked(); + } + + /// Simulate multiple keystrokes (space-separated). + pub fn simulate_keystrokes(&mut self, keystrokes: &str) { + for keystroke in keystrokes.split(' ') { + self.simulate_keystroke(keystroke); + } + } + + /// Simulate typing text. + pub fn simulate_input(&mut self, input: &str) { + for char in input.chars() { + self.simulate_keystroke(&char.to_string()); + } + } + + /// Simulate a mouse move. + pub fn simulate_mouse_move(&mut self, position: Point) { + self.simulate_event(MouseMoveEvent { + position, + modifiers: Default::default(), + pressed_button: None, + }); + } + + /// Simulate a mouse down event. + pub fn simulate_mouse_down(&mut self, position: Point, button: MouseButton) { + self.simulate_event(MouseDownEvent { + position, + button, + modifiers: Default::default(), + click_count: 1, + first_mouse: false, + }); + } + + /// Simulate a mouse up event. + pub fn simulate_mouse_up(&mut self, position: Point, button: MouseButton) { + self.simulate_event(MouseUpEvent { + position, + button, + modifiers: Default::default(), + click_count: 1, + }); + } + + /// Simulate a click at the given position. + pub fn simulate_click(&mut self, position: Point, button: MouseButton) { + self.simulate_mouse_down(position, button); + self.simulate_mouse_up(position, button); + } + + /// Simulate a scroll event. + pub fn simulate_scroll(&mut self, position: Point, delta: Point) { + self.simulate_event(crate::ScrollWheelEvent { + position, + delta: crate::ScrollDelta::Pixels(delta), + modifiers: Default::default(), + touch_phase: crate::TouchPhase::Moved, + }); + } + + /// Simulate an input event. + pub fn simulate_event(&mut self, event: E) { + let platform_input = event.to_platform_input(); + { + let mut app = self.app.borrow_mut(); + let any_handle: AnyWindowHandle = self.handle.into(); + app.update_window(any_handle, |_, window, cx| { + window.dispatch_event(platform_input, cx); + }) + .unwrap(); + } + self.background_executor.run_until_parked(); + } + + /// Simulate resizing the window. + pub fn simulate_resize(&mut self, size: Size) { + let window_id = self.handle.window_id(); + let mut app = self.app.borrow_mut(); + if let Some(Some(window)) = app.windows.get_mut(window_id) { + if let Some(test_window) = window.platform_window.as_test() { + test_window.simulate_resize(size); + } + } + drop(app); + self.background_executor.run_until_parked(); + } + + /// Simulate the window moving to a display with a different scale factor. + pub fn simulate_scale_factor_change(&mut self, scale_factor: f32) { + let window_id = self.handle.window_id(); + let test_window = { + let mut app = self.app.borrow_mut(); + app.windows + .get_mut(window_id) + .and_then(|window| window.as_mut()) + .and_then(|window| window.platform_window.as_test()) + .cloned() + }; + // The resize callback needs to borrow the app again synchronously. + if let Some(mut test_window) = test_window { + test_window.simulate_scale_factor_change(scale_factor); + } + self.background_executor.run_until_parked(); + } + + /// Force a redraw of the window. + pub fn draw(&mut self) { + let mut app = self.app.borrow_mut(); + let any_handle: AnyWindowHandle = self.handle.into(); + app.update_window(any_handle, |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + } +} + +impl Clone for TestAppWindow { + fn clone(&self) -> Self { + Self { + handle: self.handle, + app: self.app.clone(), + platform: self.platform.clone(), + background_executor: self.background_executor.clone(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{FocusHandle, Focusable, div, prelude::*}; + + struct Counter { + count: usize, + focus_handle: FocusHandle, + } + + impl Counter { + fn new(_window: &mut Window, cx: &mut Context) -> Self { + let focus_handle = cx.focus_handle(); + Self { + count: 0, + focus_handle, + } + } + + fn increment(&mut self, _cx: &mut Context) { + self.count += 1; + } + } + + impl Focusable for Counter { + fn focus_handle(&self, _cx: &App) -> FocusHandle { + self.focus_handle.clone() + } + } + + impl Render for Counter { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().child(format!("Count: {}", self.count)) + } + } + + #[test] + fn test_basic_usage() { + let mut app = TestApp::new(); + + let mut window = app.open_window(Counter::new); + + window.update(|counter, _window, cx| { + counter.increment(cx); + }); + + window.read(|counter, _| { + assert_eq!(counter.count, 1); + }); + + drop(window); + app.update(|cx| cx.shutdown()); + } + + #[test] + fn test_simulate_scale_factor_change() { + let mut app = TestApp::new(); + let mut window = app.open_window(|_, _| crate::EmptyView); + let viewport_size = window.update(|_, window, _| { + assert_eq!(window.scale_factor(), 2.0); + window.viewport_size() + }); + + window.simulate_scale_factor_change(1.0); + + window.update(|_, window, _| { + assert_eq!(window.scale_factor(), 1.0); + assert_eq!(window.viewport_size(), viewport_size); + }); + + drop(window); + app.update(|cx| cx.shutdown()); + } + + #[test] + fn test_entity_creation() { + let mut app = TestApp::new(); + + let entity = app.new_entity(|cx| Counter { + count: 42, + focus_handle: cx.focus_handle(), + }); + + app.read_entity(&entity, |counter, _| { + assert_eq!(counter.count, 42); + }); + + app.update_entity(&entity, |counter, _cx| { + counter.count += 1; + }); + + app.read_entity(&entity, |counter, _| { + assert_eq!(counter.count, 43); + }); + } + + #[test] + fn test_globals() { + let mut app = TestApp::new(); + + struct MyGlobal(String); + impl Global for MyGlobal {} + + assert!(!app.has_global::()); + + app.set_global(MyGlobal("hello".into())); + + assert!(app.has_global::()); + + app.read_global::(|global, _| { + assert_eq!(global.0, "hello"); + }); + + app.update_global::(|global, _| { + global.0 = "world".into(); + }); + + app.read_global::(|global, _| { + assert_eq!(global.0, "world"); + }); + } +} diff --git a/vendor/gpui-pre/src/app/test_context.rs b/vendor/gpui-pre/src/app/test_context.rs new file mode 100644 index 00000000..e7a8c06f --- /dev/null +++ b/vendor/gpui-pre/src/app/test_context.rs @@ -0,0 +1,1439 @@ +use crate::{ + Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace, + BackgroundExecutor, BorrowAppContext, Bounds, Capslock, ClipboardItem, DrawPhase, Drawable, + Element, Empty, EntityId, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, + Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, + Pixels, Platform, PlatformTextSystem, Point, Render, Result, SharedString, Size, + SystemNotification, SystemNotificationResponse, Task, TestDispatcher, TestPlatform, + TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds, + WindowHandle, WindowOptions, WindowVisibility, app::GpuiMode, window::ElementArenaScope, +}; +use anyhow::{anyhow, bail}; +use futures::{Stream, StreamExt, channel::oneshot}; + +use std::{ + cell::RefCell, future::Future, ops::Deref, path::PathBuf, rc::Rc, sync::Arc, time::Duration, +}; + +/// A TestAppContext is provided to tests created with `#[gpui::test]`, it provides +/// an implementation of `Context` with additional methods that are useful in tests. +#[derive(Clone)] +pub struct TestAppContext { + #[doc(hidden)] + pub background_executor: BackgroundExecutor, + #[doc(hidden)] + pub foreground_executor: ForegroundExecutor, + #[doc(hidden)] + pub dispatcher: TestDispatcher, + test_platform: Rc, + text_system: Arc, + fn_name: Option<&'static str>, + on_quit: Rc>>>, + #[doc(hidden)] + pub app: Rc, +} + +impl AppContext for TestAppContext { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + let mut app = self.app.borrow_mut(); + app.new(build_entity) + } + + fn reserve_entity(&mut self) -> crate::Reservation { + let mut app = self.app.borrow_mut(); + app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: crate::Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let mut app = self.app.borrow_mut(); + app.insert_entity(reservation, build_entity) + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let mut app = self.app.borrow_mut(); + app.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, _: &Entity) -> super::GpuiBorrow<'a, T> + where + T: 'static, + { + panic!("Cannot use as_mut with a test app context. Try calling update() first") + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let app = self.app.borrow(); + app.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut lock = self.app.borrow_mut(); + lock.update_window(window, f) + } + + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let mut lock = self.app.borrow_mut(); + lock.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let app = self.app.borrow(); + app.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let app = self.app.borrow(); + app.read_global(callback) + } +} + +impl TestAppContext { + /// Creates a new `TestAppContext`. Usually you can rely on `#[gpui::test]` to do this for you. + pub fn build(dispatcher: TestDispatcher, fn_name: Option<&'static str>) -> Self { + let arc_dispatcher = Arc::new(dispatcher.clone()); + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + let platform = TestPlatform::new(background_executor.clone(), foreground_executor.clone()); + Self::build_with_platform( + dispatcher, + fn_name, + background_executor, + foreground_executor, + platform, + ) + } + + /// Creates a test context backed by the provided platform text system. + pub fn build_with_text_system( + dispatcher: TestDispatcher, + fn_name: Option<&'static str>, + platform_text_system: Arc, + ) -> Self { + let arc_dispatcher = Arc::new(dispatcher.clone()); + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + let platform = TestPlatform::with_text_system( + background_executor.clone(), + foreground_executor.clone(), + platform_text_system, + ); + Self::build_with_platform( + dispatcher, + fn_name, + background_executor, + foreground_executor, + platform, + ) + } + + fn build_with_platform( + dispatcher: TestDispatcher, + fn_name: Option<&'static str>, + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + platform: Rc, + ) -> Self { + let asset_source = Arc::new(()); + let http_client = http_client::FakeHttpClient::with_404_response(); + let text_system = Arc::new(TextSystem::new(platform.text_system())); + + let app = App::new_app(platform.clone(), asset_source, http_client); + app.borrow_mut().mode = GpuiMode::test(); + + Self { + app, + background_executor, + foreground_executor, + dispatcher, + test_platform: platform, + text_system, + fn_name, + on_quit: Rc::new(RefCell::new(Vec::default())), + } + } + + /// Disables accessibility for subsequently created test windows. + pub fn disable_accessibility(&mut self) { + self.update(|cx| cx.accessibility_force_disabled = true); + } + + /// Skip all drawing operations for the duration of this test. + pub fn skip_drawing(&mut self) { + self.app.borrow_mut().mode = GpuiMode::Test { skip_drawing: true }; + } + + /// Create a single TestAppContext, for non-multi-client tests + pub fn single() -> Self { + let dispatcher = TestDispatcher::new(0); + Self::build(dispatcher, None) + } + + /// The name of the test function that created this `TestAppContext` + pub fn test_function_name(&self) -> Option<&'static str> { + self.fn_name + } + + /// Checks whether there have been any new path prompts received by the platform. + pub fn did_prompt_for_new_path(&self) -> bool { + self.test_platform.did_prompt_for_new_path() + } + + /// Returns the number of active idle sleep prevention tokens. + pub fn active_idle_sleep_preventions(&self) -> usize { + self.test_platform.active_idle_sleep_preventions() + } + + /// Sets the delay for subsequent idle sleep prevention acquisitions. + pub fn set_idle_sleep_prevention_delay(&self, delay: Duration) { + self.test_platform.set_idle_sleep_prevention_delay(delay); + } + + /// Makes subsequent idle sleep prevention acquisitions fail or succeed. + pub fn set_idle_sleep_prevention_fails(&self, fails: bool) { + self.test_platform.set_idle_sleep_prevention_fails(fails); + } + + /// returns a new `TestAppContext` re-using the same executors to interleave tasks. + pub fn new_app(&self) -> TestAppContext { + Self::build(self.dispatcher.clone(), self.fn_name) + } + + /// Called by the test helper to end the test. + /// public so the macro can call it. + pub fn quit(&self) { + self.on_quit.borrow_mut().drain(..).for_each(|f| f()); + self.app.borrow_mut().shutdown(); + } + + /// Register cleanup to run when the test ends. + pub fn on_quit(&mut self, f: impl FnOnce() + 'static) { + self.on_quit.borrow_mut().push(Box::new(f)); + } + + /// Schedules all windows to be redrawn on the next effect cycle. + pub fn refresh(&mut self) -> Result<()> { + let mut app = self.app.borrow_mut(); + app.refresh_windows(); + Ok(()) + } + + /// Returns an executor (for running tasks in the background) + pub fn executor(&self) -> BackgroundExecutor { + self.background_executor.clone() + } + + /// Returns an executor (for running tasks on the main thread) + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } + + /// Gives you an `&mut App` for the duration of the closure + pub fn update(&self, f: impl FnOnce(&mut App) -> R) -> R { + let mut cx = self.app.borrow_mut(); + cx.update(f) + } + + /// Gives you an `&App` for the duration of the closure + pub fn read(&self, f: impl FnOnce(&App) -> R) -> R { + let cx = self.app.borrow(); + f(&cx) + } + + /// Adds a new window. The Window will always be backed by a `TestWindow` which + /// can be retrieved with `self.test_window(handle)` + pub fn add_window(&mut self, build_window: F) -> WindowHandle + where + F: FnOnce(&mut Window, &mut Context) -> V, + V: 'static + Render, + { + let mut cx = self.app.borrow_mut(); + + // Some tests rely on the window size matching the bounds of the test display + let bounds = Bounds::maximized(None, &cx); + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..Default::default() + }, + |window, cx| cx.new(|cx| build_window(window, cx)), + ) + .unwrap() + } + + /// Opens a new window with a specific size. + /// + /// Unlike `add_window` which uses maximized bounds, this allows controlling + /// the window dimensions, which is important for layout-sensitive tests. + pub fn open_window( + &mut self, + window_size: Size, + build_window: F, + ) -> WindowHandle + where + F: FnOnce(&mut Window, &mut Context) -> V, + V: 'static + Render, + { + let mut cx = self.app.borrow_mut(); + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(Bounds { + origin: Point::default(), + size: window_size, + })), + ..Default::default() + }, + |window, cx| cx.new(|cx| build_window(window, cx)), + ) + .unwrap() + } + + /// Adds a new window with no content. + pub fn add_empty_window(&mut self) -> &mut VisualTestContext { + let mut cx = self.app.borrow_mut(); + let bounds = Bounds::maximized(None, &cx); + let window = cx + .open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..Default::default() + }, + |_, cx| cx.new(|_| Empty), + ) + .unwrap(); + drop(cx); + let cx = VisualTestContext::from_window(*window.deref(), self).into_mut(); + cx.run_until_parked(); + cx + } + + /// Adds a new window, and returns its root view and a `VisualTestContext` which can be used + /// as a `Window` and `App` for the rest of the test. Typically you would shadow this context with + /// the returned one. `let (view, cx) = cx.add_window_view(...);` + pub fn add_window_view( + &mut self, + build_root_view: F, + ) -> (Entity, &mut VisualTestContext) + where + F: FnOnce(&mut Window, &mut Context) -> V, + V: 'static + Render, + { + let mut cx = self.app.borrow_mut(); + let bounds = Bounds::maximized(None, &cx); + let window = cx + .open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + ..Default::default() + }, + |window, cx| cx.new(|cx| build_root_view(window, cx)), + ) + .unwrap(); + drop(cx); + let view = window.root(self).unwrap(); + let cx = VisualTestContext::from_window(*window.deref(), self).into_mut(); + cx.run_until_parked(); + + // it might be nice to try and cleanup these at the end of each test. + (view, cx) + } + + /// returns the TextSystem + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// Simulates writing to the platform clipboard + pub fn write_to_clipboard(&self, item: ClipboardItem) { + self.test_platform.write_to_clipboard(item) + } + + /// Simulates reading from the platform clipboard. + /// This will return the most recent value from `write_to_clipboard`. + pub fn read_from_clipboard(&self) -> Option { + self.test_platform.read_from_clipboard() + } + + /// Simulates choosing a File in the platform's "Open" dialog. + pub fn simulate_new_path_selection( + &self, + select_path: impl FnOnce(&std::path::Path) -> Option, + ) { + self.test_platform.simulate_new_path_selection(select_path); + } + + /// Simulates responding to a `prompt_for_paths` ("Open") dialog. + pub fn simulate_path_prompt_response( + &self, + select_paths: impl FnOnce(&crate::PathPromptOptions) -> Option>, + ) { + self.test_platform + .simulate_path_prompt_response(select_paths); + } + + /// Returns true if there's a path selection dialog pending. + pub fn did_prompt_for_paths(&self) -> bool { + self.test_platform.did_prompt_for_paths() + } + + /// Simulates clicking a button in an platform-level alert dialog. + #[track_caller] + pub fn simulate_prompt_answer(&self, button: &str) { + self.test_platform.simulate_prompt_answer(button); + } + + /// Returns true if there's an alert dialog open. + pub fn has_pending_prompt(&self) -> bool { + self.test_platform.has_pending_prompt() + } + + /// Returns true if there's an alert dialog open. + pub fn pending_prompt(&self) -> Option<(String, String)> { + self.test_platform.pending_prompt() + } + + /// All the urls that have been opened with cx.open_url() during this test. + pub fn opened_url(&self) -> Option { + self.test_platform.opened_url.borrow().clone() + } + + /// Returns the application identity configured during this test. + pub fn app_identity(&self) -> Option<(SharedString, SharedString)> { + self.test_platform.app_identity() + } + + /// Returns all system notifications shown during this test, in order. + pub fn shown_system_notifications(&self) -> Vec { + self.test_platform.shown_system_notifications() + } + + /// Returns the system notifications currently delivered by the test platform. + pub fn delivered_system_notifications(&self) -> Vec { + self.test_platform.delivered_system_notifications() + } + + /// Returns the tags of all system notifications dismissed during this test, in order. + pub fn dismissed_system_notifications(&self) -> Vec { + self.test_platform.dismissed_system_notifications() + } + + /// Simulates the user activating a system notification. + pub fn simulate_system_notification_response(&self, response: SystemNotificationResponse) { + self.test_platform + .simulate_system_notification_response(response); + } + + /// Simulates the user resizing the window to the new size. + pub fn simulate_window_resize(&self, window_handle: AnyWindowHandle, size: Size) { + self.test_window(window_handle).simulate_resize(size); + } + + /// Simulates a change in whether the platform is presenting the window. + pub fn simulate_window_visibility_change( + &self, + window_handle: AnyWindowHandle, + visibility: WindowVisibility, + ) { + self.test_window(window_handle) + .simulate_visibility_change(visibility); + } + + /// Simulates visible viewport changes without resizing the window's layout area. + pub fn simulate_window_visual_viewport_change( + &self, + window_handle: AnyWindowHandle, + bounds: Bounds, + ) { + self.test_window(window_handle) + .simulate_visual_viewport_change(bounds); + } + + /// Simulates the window moving to a display with a different scale factor. + pub fn simulate_window_scale_factor_change( + &self, + window_handle: AnyWindowHandle, + scale_factor: f32, + ) { + self.test_window(window_handle) + .simulate_scale_factor_change(scale_factor); + } + + /// Returns true if there's an alert dialog open. + pub fn expect_restart(&self) -> oneshot::Receiver<(Option, Vec)> { + let (tx, rx) = futures::channel::oneshot::channel(); + self.test_platform.expect_restart.borrow_mut().replace(tx); + rx + } + + /// Causes the given sources to be returned if the application queries for screen + /// capture sources. + pub fn set_screen_capture_sources(&self, sources: Vec) { + self.test_platform.set_screen_capture_sources(sources); + } + + /// Returns all windows open in the test. + pub fn windows(&self) -> Vec { + self.app.borrow().windows() + } + + /// Run the given task on the main thread. + #[track_caller] + pub fn spawn(&self, f: impl FnOnce(AsyncApp) -> Fut) -> Task + where + Fut: Future + 'static, + R: 'static, + { + self.foreground_executor.spawn(f(self.to_async())) + } + + /// true if the given global is defined + pub fn has_global(&self) -> bool { + let app = self.app.borrow(); + app.has_global::() + } + + /// runs the given closure with a reference to the global + /// panics if `has_global` would return false. + pub fn read_global(&self, read: impl FnOnce(&G, &App) -> R) -> R { + let app = self.app.borrow(); + read(app.global(), &app) + } + + /// runs the given closure with a reference to the global (if set) + pub fn try_read_global(&self, read: impl FnOnce(&G, &App) -> R) -> Option { + let lock = self.app.borrow(); + Some(read(lock.try_global()?, &lock)) + } + + /// sets the global in this context. + pub fn set_global(&mut self, global: G) { + let mut lock = self.app.borrow_mut(); + lock.update(|cx| cx.set_global(global)) + } + + /// updates the global in this context. (panics if `has_global` would return false) + pub fn update_global(&mut self, update: impl FnOnce(&mut G, &mut App) -> R) -> R { + let mut lock = self.app.borrow_mut(); + lock.update(|cx| cx.update_global(update)) + } + + /// Returns an `AsyncApp` which can be used to run tasks that expect to be on a background + /// thread on the current thread in tests. + pub fn to_async(&self) -> AsyncApp { + AsyncApp { + app: Rc::downgrade(&self.app), + background_executor: self.background_executor.clone(), + foreground_executor: self.foreground_executor.clone(), + } + } + + /// Wait until there are no more pending tasks. + pub fn run_until_parked(&self) { + self.dispatcher.run_until_parked(); + } + + /// Simulate dispatching an action to the currently focused node in the window. + pub fn dispatch_action(&mut self, window: AnyWindowHandle, action: A) + where + A: Action, + { + window + .update(self, |_, window, cx| { + window.dispatch_action(action.boxed_clone(), cx) + }) + .unwrap(); + + self.background_executor.run_until_parked() + } + + /// simulate_keystrokes takes a space-separated list of keys to type. + /// cx.simulate_keystrokes("cmd-shift-p b k s p enter") + /// in Zed, this will run backspace on the current editor through the command palette. + /// This will also run the background executor until it's parked. + pub fn simulate_keystrokes(&mut self, window: AnyWindowHandle, keystrokes: &str) { + for keystroke in keystrokes + .split(' ') + .map(Keystroke::parse) + .map(Result::unwrap) + { + self.dispatch_keystroke(window, keystroke); + } + + self.background_executor.run_until_parked() + } + + /// simulate_input takes a string of text to type. + /// cx.simulate_input("abc") + /// will type abc into your current editor + /// This will also run the background executor until it's parked. + pub fn simulate_input(&mut self, window: AnyWindowHandle, input: &str) { + for keystroke in input.split("").map(Keystroke::parse).map(Result::unwrap) { + self.dispatch_keystroke(window, keystroke); + } + + self.background_executor.run_until_parked() + } + + /// dispatches a single Keystroke (see also `simulate_keystrokes` and `simulate_input`) + pub fn dispatch_keystroke(&mut self, window: AnyWindowHandle, keystroke: Keystroke) { + self.update_window(window, |_, window, cx| { + window.dispatch_keystroke(keystroke, cx) + }) + .unwrap(); + } + + /// Returns the `TestWindow` backing the given handle. + pub(crate) fn test_window(&self, window: AnyWindowHandle) -> TestWindow { + self.app + .borrow_mut() + .windows + .get_mut(window.id) + .unwrap() + .as_deref_mut() + .unwrap() + .platform_window + .as_test() + .unwrap() + .clone() + } + + /// Returns a stream of notifications whenever the Entity is updated. + pub fn notifications( + &mut self, + entity: &Entity, + ) -> impl Stream + use { + let (tx, rx) = futures::channel::mpsc::unbounded(); + self.update(|cx| { + cx.observe(entity, { + let tx = tx.clone(); + move |_, _| { + let _ = tx.unbounded_send(()); + } + }) + .detach(); + cx.observe_release(entity, move |_, _| tx.close_channel()) + .detach() + }); + rx + } + + /// Returns a stream of events emitted by the given Entity. + pub fn events>( + &mut self, + entity: &Entity, + ) -> futures::channel::mpsc::UnboundedReceiver + where + Evt: 'static + Clone, + { + let (tx, rx) = futures::channel::mpsc::unbounded(); + entity + .update(self, |_, cx: &mut Context| { + cx.subscribe(entity, move |_entity, _handle, event, _cx| { + let _ = tx.unbounded_send(event.clone()); + }) + }) + .detach(); + rx + } + + /// Runs until the given condition becomes true. (Prefer `run_until_parked` if you + /// don't need to jump in at a specific time). + pub async fn condition( + &mut self, + entity: &Entity, + mut predicate: impl FnMut(&mut T, &mut Context) -> bool, + ) { + let timer = self.executor().timer(Duration::from_secs(3)); + let mut notifications = self.notifications(entity); + + use futures::FutureExt as _; + use futures_concurrency::future::Race as _; + + ( + async { + loop { + if entity.update(self, &mut predicate) { + return Ok(()); + } + + if notifications.next().await.is_none() { + bail!("entity dropped") + } + } + }, + timer.map(|_| Err(anyhow!("condition timed out"))), + ) + .race() + .await + .unwrap(); + } + + /// Set a name for this App. + #[cfg(any(test, feature = "test-support"))] + pub fn set_name(&mut self, name: &'static str) { + self.update(|cx| cx.name = Some(name)) + } +} + +impl Entity { + /// Block until the next event is emitted by the entity, then return it. + pub fn next_event(&self, cx: &mut TestAppContext) -> impl Future + where + Event: Send + Clone + 'static, + T: EventEmitter, + { + let (tx, mut rx) = oneshot::channel(); + let mut tx = Some(tx); + let subscription = self.update(cx, |_, cx| { + cx.subscribe(self, move |_, _, event, _| { + if let Some(tx) = tx.take() { + _ = tx.send(event.clone()); + } + }) + }); + + async move { + let event = rx.await.expect("no event emitted"); + drop(subscription); + event + } + } +} + +impl Entity { + /// Returns a future that resolves when the view is next updated. + pub fn next_notification( + &self, + advance_clock_by: Duration, + cx: &TestAppContext, + ) -> impl Future { + use postage::prelude::{Sink as _, Stream as _}; + + let (mut tx, mut rx) = postage::mpsc::channel(1); + let subscription = cx.app.borrow_mut().observe(self, move |_, _| { + tx.try_send(()).ok(); + }); + + cx.executor().advance_clock(advance_clock_by); + + async move { + rx.recv() + .await + .expect("entity dropped while test was waiting for its next notification"); + drop(subscription); + } + } +} + +impl Entity { + /// Returns a future that resolves when the condition becomes true. + pub fn condition( + &self, + cx: &TestAppContext, + mut predicate: impl FnMut(&V, &App) -> bool, + ) -> impl Future + where + Evt: 'static, + V: EventEmitter, + { + use postage::prelude::{Sink as _, Stream as _}; + + let (tx, mut rx) = postage::mpsc::channel(1024); + + let mut cx = cx.app.borrow_mut(); + let subscriptions = ( + cx.observe(self, { + let mut tx = tx.clone(); + move |_, _| { + tx.blocking_send(()).ok(); + } + }), + cx.subscribe(self, { + let mut tx = tx; + move |_, _: &Evt, _| { + tx.blocking_send(()).ok(); + } + }), + ); + + let cx = cx.this.upgrade().unwrap(); + let handle = self.downgrade(); + + async move { + loop { + { + let cx = cx.borrow(); + let cx = &*cx; + if predicate( + handle + .upgrade() + .expect("view dropped with pending condition") + .read(cx), + cx, + ) { + break; + } + } + + rx.recv() + .await + .expect("view dropped with pending condition"); + } + drop(subscriptions); + } + } +} + +use derive_more::{Deref, DerefMut}; + +use super::{Context, Entity}; +#[derive(Deref, DerefMut, Clone)] +/// A VisualTestContext is the test-equivalent of a `Window` and `App`. It allows you to +/// run window-specific test code. It can be dereferenced to a `TextAppContext`. +pub struct VisualTestContext { + #[deref] + #[deref_mut] + /// cx is the original TestAppContext (you can more easily access this using Deref) + pub cx: TestAppContext, + window: AnyWindowHandle, +} + +impl VisualTestContext { + /// Provides a `Window` and `App` for the duration of the closure. + pub fn update(&mut self, f: impl FnOnce(&mut Window, &mut App) -> R) -> R { + self.cx + .update_window(self.window, |_, window, cx| f(window, cx)) + .unwrap() + } + + /// Creates a new VisualTestContext. You would typically shadow the passed in + /// TestAppContext with this, as this is typically more useful. + /// `let cx = VisualTestContext::from_window(window, cx);` + pub fn from_window(window: AnyWindowHandle, cx: &TestAppContext) -> Self { + Self { + cx: cx.clone(), + window, + } + } + + /// Wait until there are no more pending tasks. + pub fn run_until_parked(&self) { + self.cx.background_executor.run_until_parked(); + } + + /// Dispatch the action to the currently focused node. + pub fn dispatch_action(&mut self, action: A) + where + A: Action, + { + self.cx.dispatch_action(self.window, action) + } + + /// Read the title off the window (set by `Window#set_window_title`) + pub fn window_title(&mut self) -> Option { + self.cx.test_window(self.window).0.lock().title.clone() + } + + /// Read the document path off the window (set by `Window#set_document_path`) + pub fn document_path(&mut self) -> Option { + self.cx + .test_window(self.window) + .0 + .lock() + .document_path + .clone() + } + + /// Simulate a sequence of keystrokes `cx.simulate_keystrokes("cmd-p escape")` + /// Automatically runs until parked. + pub fn simulate_keystrokes(&mut self, keystrokes: &str) { + self.cx.simulate_keystrokes(self.window, keystrokes) + } + + /// Simulate typing text `cx.simulate_input("hello")` + /// Automatically runs until parked. + pub fn simulate_input(&mut self, input: &str) { + self.cx.simulate_input(self.window, input) + } + + /// Simulate a mouse move event to the given point + pub fn simulate_mouse_move( + &mut self, + position: Point, + button: impl Into>, + modifiers: Modifiers, + ) { + self.simulate_event(MouseMoveEvent { + position, + modifiers, + pressed_button: button.into(), + }) + } + + /// Simulate a mouse down event to the given point + pub fn simulate_mouse_down( + &mut self, + position: Point, + button: MouseButton, + modifiers: Modifiers, + ) { + self.simulate_event(MouseDownEvent { + position, + modifiers, + button, + click_count: 1, + first_mouse: false, + }) + } + + /// Simulate a mouse up event to the given point + pub fn simulate_mouse_up( + &mut self, + position: Point, + button: MouseButton, + modifiers: Modifiers, + ) { + self.simulate_event(MouseUpEvent { + position, + modifiers, + button, + click_count: 1, + }) + } + + /// Simulate a primary mouse click at the given point + pub fn simulate_click(&mut self, position: Point, modifiers: Modifiers) { + self.simulate_event(MouseDownEvent { + position, + modifiers, + button: MouseButton::Left, + click_count: 1, + first_mouse: false, + }); + self.simulate_event(MouseUpEvent { + position, + modifiers, + button: MouseButton::Left, + click_count: 1, + }); + } + + /// Simulate a modifiers changed event + pub fn simulate_modifiers_change(&mut self, modifiers: Modifiers) { + self.simulate_event(ModifiersChangedEvent { + modifiers, + capslock: Capslock { on: false }, + }) + } + + /// Simulate a capslock changed event + pub fn simulate_capslock_change(&mut self, on: bool) { + self.simulate_event(ModifiersChangedEvent { + modifiers: Modifiers::none(), + capslock: Capslock { on }, + }) + } + + /// Simulates the user resizing the window to the new size. + pub fn simulate_resize(&self, size: Size) { + self.simulate_window_resize(self.window, size) + } + + /// Simulates a change in whether the platform is presenting this window. + pub fn simulate_visibility_change(&self, visibility: WindowVisibility) { + self.simulate_window_visibility_change(self.window, visibility); + } + + /// Simulates the window moving to a display with a different scale factor. + pub fn simulate_scale_factor_change(&self, scale_factor: f32) { + self.simulate_window_scale_factor_change(self.window, scale_factor) + } + + /// Returns the bounds of the element with the given debug selector. + /// + /// Returns `None` in builds without `debug_assertions`, which don't record + /// selectors; see [`crate::InteractiveElement::debug_selector`]. + pub fn debug_bounds(&mut self, selector: &'static str) -> Option> { + self.update(|window, _| window.rendered_frame.debug_bounds.get(selector).copied()) + } + + /// Draw an element to the window. Useful for simulating events or actions + pub fn draw( + &mut self, + origin: Point, + space: impl Into>, + f: impl FnOnce(&mut Window, &mut App) -> E, + ) -> (E::RequestLayoutState, E::PrepaintState) + where + E: Element, + { + self.update(|window, cx| { + let arena_scope = ElementArenaScope::enter(&cx.element_arena); + + window.invalidator.set_phase(DrawPhase::Prepaint); + let mut element = Drawable::new(f(window, cx)); + element.layout_as_root(space.into(), window, cx); + window.with_absolute_element_offset(origin, |window| element.prepaint(window, cx)); + + window.invalidator.set_phase(DrawPhase::Paint); + let (request_layout_state, prepaint_state) = element.paint(window, cx); + + window.invalidator.set_phase(DrawPhase::None); + window.refresh(); + + drop(element); + arena_scope.exit(&cx.element_arena).clear(cx); + + (request_layout_state, prepaint_state) + }) + } + + /// Simulate an event from the platform, e.g. a ScrollWheelEvent + /// Make sure you've called [VisualTestContext::draw] first! + pub fn simulate_event(&mut self, event: E) { + self.test_window(self.window) + .simulate_input(event.to_platform_input()); + self.background_executor.run_until_parked(); + } + + /// Simulates the user blurring the window. + pub fn deactivate_window(&mut self) { + if Some(self.window) == self.test_platform.active_window() { + self.test_platform.set_active_window(None) + } + self.background_executor.run_until_parked(); + } + + /// Simulates the user closing the window. + /// Returns true if the window was closed. + pub fn simulate_close(&mut self) -> bool { + let handler = self + .cx + .update_window(self.window, |_, window, _| { + window + .platform_window + .as_test() + .unwrap() + .0 + .lock() + .should_close_handler + .take() + }) + .unwrap(); + if let Some(mut handler) = handler { + let should_close = handler(); + self.cx + .update_window(self.window, |_, window, _| { + window.platform_window.on_should_close(handler); + }) + .unwrap(); + should_close + } else { + false + } + } + + /// Get an &mut VisualTestContext (which is mostly what you need to pass to other methods). + /// This method internally retains the VisualTestContext until the end of the test. + pub fn into_mut(self) -> &'static mut Self { + let ptr = Box::into_raw(Box::new(self)); + // safety: on_quit will be called after the test has finished. + // the executor will ensure that all tasks related to the test have stopped. + // so there is no way for cx to be accessed after on_quit is called. + // todo: This is unsound under stacked borrows (also tree borrows probably?) + // the mutable reference invalidates `ptr` which is later used in the closure + let cx = unsafe { &mut *ptr }; + cx.on_quit(move || unsafe { + drop(Box::from_raw(ptr)); + }); + cx + } +} + +impl AppContext for VisualTestContext { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + self.window + .update(&mut self.cx, |_, _, cx| cx.new(build_entity)) + .expect("window was unexpectedly closed") + } + + fn reserve_entity(&mut self) -> crate::Reservation { + self.cx.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: crate::Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + self.window + .update(&mut self.cx, |_, _, cx| { + cx.insert_entity(reservation, build_entity) + }) + .expect("window was unexpectedly closed") + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R + where + T: 'static, + { + self.cx.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, handle: &Entity) -> super::GpuiBorrow<'a, T> + where + T: 'static, + { + self.cx.as_mut(handle) + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + self.cx.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + self.cx.update_window(window, f) + } + + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + self.cx.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + self.cx.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.cx.background_spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + self.cx.read_global(callback) + } +} + +impl VisualContext for VisualTestContext { + type Result = T; + + /// Get the underlying window handle underlying this context. + fn window_handle(&self) -> AnyWindowHandle { + self.window + } + + fn new_window_entity( + &mut self, + build_entity: impl FnOnce(&mut Window, &mut Context) -> T, + ) -> Entity { + self.window + .update(&mut self.cx, |_, window, cx| { + cx.new(|cx| build_entity(window, cx)) + }) + .expect("window was unexpectedly closed") + } + + fn update_window_entity( + &mut self, + view: &Entity, + update: impl FnOnce(&mut V, &mut Window, &mut Context) -> R, + ) -> R { + let view = view.clone(); + self.cx + .app + .borrow_mut() + .with_window(view.entity_id(), |window, app| { + view.update(app, |v, cx| update(v, window, cx)) + }) + .expect("entity has no current window; use `update` instead of `update_in`") + } + + fn replace_root_view( + &mut self, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> Entity + where + V: 'static + Render, + { + self.window + .update(&mut self.cx, |_, window, cx| { + window.replace_root(cx, build_view) + }) + .expect("window was unexpectedly closed") + } + + fn focus(&mut self, view: &Entity) { + self.window + .update(&mut self.cx, |_, window, cx| { + view.read(cx).focus_handle(cx).focus(window, cx) + }) + .expect("window was unexpectedly closed") + } +} + +impl AnyWindowHandle { + /// Creates the given view in this window. + pub fn build_entity( + &self, + cx: &mut TestAppContext, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> Entity { + self.update(cx, |_, window, cx| cx.new(|cx| build_view(window, cx))) + .unwrap() + } +} + +#[cfg(test)] +mod tests { + use crate::{ + PathPromptOptions, SystemNotification, SystemNotificationAction, + SystemNotificationResponse, TestAppContext, + }; + use std::cell::RefCell; + use std::path::PathBuf; + use std::rc::Rc; + + #[gpui::test] + async fn test_system_notifications_require_identity_and_replace_matching_tags( + cx: &mut TestAppContext, + ) { + cx.update(|cx| { + cx.show_system_notification(SystemNotification { + tag: "thread-1".into(), + title: "Task started".into(), + body: "Running tests".into(), + actions: Vec::new(), + }); + }); + assert!(cx.shown_system_notifications().is_empty()); + assert!(cx.delivered_system_notifications().is_empty()); + + cx.update(|cx| { + cx.set_app_identity("com.example.tasks", "Tasks"); + cx.show_system_notification(SystemNotification { + tag: "thread-1".into(), + title: "Task started".into(), + body: "Running tests".into(), + actions: Vec::new(), + }); + cx.show_system_notification(SystemNotification { + tag: "thread-1".into(), + title: "Task finished".into(), + body: "All tests passed".into(), + actions: vec![SystemNotificationAction { + id: "open".into(), + label: "Open".into(), + }], + }); + }); + + assert_eq!( + cx.app_identity(), + Some(("com.example.tasks".into(), "Tasks".into())) + ); + assert_eq!(cx.shown_system_notifications().len(), 2); + assert_eq!( + cx.delivered_system_notifications(), + [SystemNotification { + tag: "thread-1".into(), + title: "Task finished".into(), + body: "All tests passed".into(), + actions: vec![SystemNotificationAction { + id: "open".into(), + label: "Open".into(), + }], + }] + ); + + cx.update(|cx| cx.dismiss_system_notification("thread-1")); + assert!(cx.delivered_system_notifications().is_empty()); + assert_eq!(cx.dismissed_system_notifications(), ["thread-1"]); + } + + #[gpui::test] + async fn test_system_notification_body_and_action_responses(cx: &mut TestAppContext) { + let responses = Rc::new(RefCell::new(Vec::new())); + cx.update(|cx| { + cx.on_system_notification_response({ + let responses = responses.clone(); + move |response, _cx| responses.borrow_mut().push(response) + }); + }); + + cx.simulate_system_notification_response(SystemNotificationResponse { + tag: "thread-1".into(), + action_id: None, + }); + cx.simulate_system_notification_response(SystemNotificationResponse { + tag: "thread-1".into(), + action_id: Some("default".into()), + }); + + assert_eq!( + responses.borrow().as_slice(), + &[ + SystemNotificationResponse { + tag: "thread-1".into(), + action_id: None, + }, + SystemNotificationResponse { + tag: "thread-1".into(), + action_id: Some("default".into()), + }, + ] + ); + } + + #[gpui::test] + async fn test_system_notification_response_handler_can_be_replaced(cx: &mut TestAppContext) { + let first_responses = Rc::new(RefCell::new(Vec::new())); + let second_responses = Rc::new(RefCell::new(Vec::new())); + cx.update(|cx| { + cx.on_system_notification_response({ + let first_responses = first_responses.clone(); + move |response, _cx| first_responses.borrow_mut().push(response) + }); + cx.on_system_notification_response({ + let second_responses = second_responses.clone(); + move |response, _cx| second_responses.borrow_mut().push(response) + }); + }); + + let response = SystemNotificationResponse { + tag: "thread-1".into(), + action_id: None, + }; + cx.simulate_system_notification_response(response.clone()); + + assert!(first_responses.borrow().is_empty()); + assert_eq!(second_responses.borrow().as_slice(), &[response]); + } + + #[gpui::test] + async fn test_system_notification_response_handler_can_reenter_app(cx: &mut TestAppContext) { + cx.update(|cx| { + cx.set_app_identity("com.example.tasks", "Tasks"); + cx.show_system_notification(SystemNotification { + tag: "thread-1".into(), + title: "Task finished".into(), + body: "All tests passed".into(), + actions: Vec::new(), + }); + cx.on_system_notification_response(|response, cx| { + cx.dismiss_system_notification(&response.tag); + }); + }); + + cx.simulate_system_notification_response(SystemNotificationResponse { + tag: "thread-1".into(), + action_id: None, + }); + + assert!(cx.delivered_system_notifications().is_empty()); + assert_eq!(cx.dismissed_system_notifications(), ["thread-1"]); + } + + #[gpui::test] + async fn test_simulate_path_prompt_response(cx: &mut TestAppContext) { + assert!(!cx.did_prompt_for_paths()); + + let receiver = cx.update(|cx| { + cx.prompt_for_paths(PathPromptOptions { + files: false, + directories: true, + multiple: true, + prompt: None, + }) + }); + assert!(cx.did_prompt_for_paths()); + + let selected = vec![PathBuf::from("/a"), PathBuf::from("/b")]; + cx.simulate_path_prompt_response({ + let selected = selected.clone(); + move |options| { + assert!(options.multiple); + Some(selected) + } + }); + assert!(!cx.did_prompt_for_paths()); + + let response = receiver.await.unwrap().unwrap(); + assert_eq!(response, Some(selected)); + } + + #[gpui::test] + async fn test_simulate_path_prompt_cancellation(cx: &mut TestAppContext) { + let receiver = cx.update(|cx| { + cx.prompt_for_paths(PathPromptOptions { + files: true, + directories: false, + multiple: false, + prompt: None, + }) + }); + + cx.simulate_path_prompt_response(|_options| None); + + let response = receiver.await.unwrap().unwrap(); + assert_eq!(response, None); + } +} diff --git a/vendor/gpui-pre/src/app/visual_test_context.rs b/vendor/gpui-pre/src/app/visual_test_context.rs new file mode 100644 index 00000000..b54802a2 --- /dev/null +++ b/vendor/gpui-pre/src/app/visual_test_context.rs @@ -0,0 +1,484 @@ +use crate::{ + Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AssetSource, BackgroundExecutor, + Bounds, ClipboardItem, Context, Entity, EntityId, ForegroundExecutor, Global, InputEvent, + Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, + Platform, Point, Render, Result, Size, Task, TestDispatcher, TextSystem, VisualTestPlatform, + Window, WindowBounds, WindowHandle, WindowOptions, app::GpuiMode, +}; +use anyhow::anyhow; +use image::RgbaImage; +use std::{future::Future, rc::Rc, sync::Arc, time::Duration}; + +/// A test context that uses real macOS rendering instead of mocked rendering. +/// This is used for visual tests that need to capture actual screenshots. +/// +/// Unlike `TestAppContext` which uses `TestPlatform` with mocked rendering, +/// `VisualTestAppContext` uses the real `MacPlatform` to produce actual rendered output. +/// +/// Windows created through this context are positioned off-screen (at coordinates like -10000, -10000) +/// so they are invisible to the user but still fully rendered by the compositor. +#[derive(Clone)] +pub struct VisualTestAppContext { + /// The underlying app cell + pub app: Rc, + /// The background executor for running async tasks + pub background_executor: BackgroundExecutor, + /// The foreground executor for running tasks on the main thread + pub foreground_executor: ForegroundExecutor, + /// The test dispatcher for deterministic task scheduling + dispatcher: TestDispatcher, + platform: Rc, + text_system: Arc, +} + +impl VisualTestAppContext { + /// Creates a new `VisualTestAppContext` with real macOS platform rendering + /// but deterministic task scheduling via TestDispatcher. + /// + /// This provides: + /// - Real Metal/compositor rendering for accurate screenshots + /// - Deterministic task scheduling via TestDispatcher + /// - Controllable time via `advance_clock` + /// + /// Note: This uses a no-op asset source, so SVG icons won't render. + /// Use `with_asset_source` to provide real assets for icon rendering. + pub fn new(platform: Rc) -> Self { + Self::with_asset_source(platform, Arc::new(())) + } + + /// Creates a new `VisualTestAppContext` with a custom asset source. + /// + /// Use this when you need SVG icons to render properly in visual tests. + /// Pass the real `Assets` struct to enable icon rendering. + pub fn with_asset_source( + platform: Rc, + asset_source: Arc, + ) -> Self { + // Use a seeded RNG for deterministic behavior + let seed = std::env::var("SEED") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(0); + + // Create a visual test platform that combines real Mac rendering + // with controllable TestDispatcher for deterministic task scheduling + let platform = Rc::new(VisualTestPlatform::new(platform, seed)); + + // Get the dispatcher and executors from the platform + let dispatcher = platform.dispatcher().clone(); + let background_executor = platform.background_executor(); + let foreground_executor = platform.foreground_executor(); + + let text_system = Arc::new(TextSystem::new(platform.text_system())); + + let http_client = http_client::FakeHttpClient::with_404_response(); + + let mut app = App::new_app(platform.clone(), asset_source, http_client); + app.borrow_mut().mode = GpuiMode::test(); + + Self { + app, + background_executor, + foreground_executor, + dispatcher, + platform, + text_system, + } + } + + /// Opens a window positioned off-screen for invisible rendering. + /// + /// The window is positioned at (-10000, -10000) so it's not visible on any display, + /// but it's still fully rendered by the compositor and can be captured via ScreenCaptureKit. + /// + /// # Arguments + /// * `size` - The size of the window to create + /// * `build_root` - A closure that builds the root view for the window + pub fn open_offscreen_window( + &mut self, + size: Size, + build_root: impl FnOnce(&mut Window, &mut App) -> Entity, + ) -> Result> { + use crate::{point, px}; + + let bounds = Bounds { + origin: point(px(-10000.0), px(-10000.0)), + size, + }; + + let mut cx = self.app.borrow_mut(); + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + focus: false, + show: true, + ..Default::default() + }, + build_root, + ) + } + + /// Opens an off-screen window with default size (1280x800). + pub fn open_offscreen_window_default( + &mut self, + build_root: impl FnOnce(&mut Window, &mut App) -> Entity, + ) -> Result> { + use crate::{px, size}; + self.open_offscreen_window(size(px(1280.0), px(800.0)), build_root) + } + + /// Returns whether screen capture is supported on this platform. + pub fn is_screen_capture_supported(&self) -> bool { + self.platform.is_screen_capture_supported() + } + + /// Returns the text system used by this context. + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// Returns the background executor. + pub fn executor(&self) -> BackgroundExecutor { + self.background_executor.clone() + } + + /// Returns the foreground executor. + pub fn foreground_executor(&self) -> ForegroundExecutor { + self.foreground_executor.clone() + } + + /// Runs all pending foreground and background tasks until there's nothing left to do. + /// This is essential for processing async operations like tooltip timers. + pub fn run_until_parked(&self) { + self.dispatcher.run_until_parked(); + } + + /// Advances the simulated clock by the given duration and processes any tasks + /// that become ready. This is essential for testing time-based behaviors like + /// tooltip delays. + pub fn advance_clock(&self, duration: Duration) { + self.dispatcher.advance_clock(duration); + } + + /// Updates the app state. + pub fn update(&mut self, f: impl FnOnce(&mut App) -> R) -> R { + let mut app = self.app.borrow_mut(); + f(&mut app) + } + + /// Reads from the app state. + pub fn read(&self, f: impl FnOnce(&App) -> R) -> R { + let app = self.app.borrow(); + f(&app) + } + + /// Updates a window. + pub fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut lock = self.app.borrow_mut(); + lock.update_window(window, f) + } + + /// Spawns a task on the foreground executor. + pub fn spawn(&self, f: F) -> Task + where + F: Future + 'static, + R: 'static, + { + self.foreground_executor.spawn(f) + } + + /// Checks if a global of type G exists. + pub fn has_global(&self) -> bool { + let app = self.app.borrow(); + app.has_global::() + } + + /// Reads a global value. + pub fn read_global(&self, f: impl FnOnce(&G, &App) -> R) -> R { + let app = self.app.borrow(); + f(app.global::(), &app) + } + + /// Sets a global value. + pub fn set_global(&mut self, global: G) { + let mut app = self.app.borrow_mut(); + app.set_global(global); + } + + /// Updates a global value. + pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut App) -> R) -> R { + let mut lock = self.app.borrow_mut(); + lock.update(|cx| { + let mut global = cx.lease_global::(); + let result = f(&mut global, cx); + cx.end_global_lease(global); + result + }) + } + + /// Simulates a sequence of keystrokes on the given window. + /// + /// Keystrokes are specified as a space-separated string, e.g., "cmd-p escape". + pub fn simulate_keystrokes(&mut self, window: AnyWindowHandle, keystrokes: &str) { + for keystroke_text in keystrokes.split_whitespace() { + let keystroke = Keystroke::parse(keystroke_text) + .unwrap_or_else(|_| panic!("Invalid keystroke: {}", keystroke_text)); + self.dispatch_keystroke(window, keystroke); + } + self.run_until_parked(); + } + + /// Dispatches a single keystroke to a window. + pub fn dispatch_keystroke(&mut self, window: AnyWindowHandle, keystroke: Keystroke) { + self.update_window(window, |_, window, cx| { + window.dispatch_keystroke(keystroke, cx); + }) + .ok(); + } + + /// Simulates typing text input on the given window. + pub fn simulate_input(&mut self, window: AnyWindowHandle, input: &str) { + for char in input.chars() { + let key = char.to_string(); + let keystroke = Keystroke { + modifiers: Modifiers::default(), + key: key.clone(), + key_char: Some(key), + }; + self.dispatch_keystroke(window, keystroke); + } + self.run_until_parked(); + } + + /// Simulates a mouse move event. + pub fn simulate_mouse_move( + &mut self, + window: AnyWindowHandle, + position: Point, + button: impl Into>, + modifiers: Modifiers, + ) { + self.simulate_event( + window, + MouseMoveEvent { + position, + modifiers, + pressed_button: button.into(), + }, + ); + } + + /// Simulates a mouse down event. + pub fn simulate_mouse_down( + &mut self, + window: AnyWindowHandle, + position: Point, + button: MouseButton, + modifiers: Modifiers, + ) { + self.simulate_event( + window, + MouseDownEvent { + position, + modifiers, + button, + click_count: 1, + first_mouse: false, + }, + ); + } + + /// Simulates a mouse up event. + pub fn simulate_mouse_up( + &mut self, + window: AnyWindowHandle, + position: Point, + button: MouseButton, + modifiers: Modifiers, + ) { + self.simulate_event( + window, + MouseUpEvent { + position, + modifiers, + button, + click_count: 1, + }, + ); + } + + /// Simulates a click (mouse down followed by mouse up). + pub fn simulate_click( + &mut self, + window: AnyWindowHandle, + position: Point, + modifiers: Modifiers, + ) { + self.simulate_mouse_down(window, position, MouseButton::Left, modifiers); + self.simulate_mouse_up(window, position, MouseButton::Left, modifiers); + } + + /// Simulates an input event on the given window. + pub fn simulate_event(&mut self, window: AnyWindowHandle, event: E) { + self.update_window(window, |_, window, cx| { + window.dispatch_event(event.to_platform_input(), cx); + }) + .ok(); + self.run_until_parked(); + } + + /// Dispatches an action to the given window. + pub fn dispatch_action(&mut self, window: AnyWindowHandle, action: impl Action) { + self.update_window(window, |_, window, cx| { + window.dispatch_action(action.boxed_clone(), cx); + }) + .ok(); + self.run_until_parked(); + } + + /// Writes to the clipboard. + pub fn write_to_clipboard(&self, item: ClipboardItem) { + self.platform.write_to_clipboard(item); + } + + /// Reads from the clipboard. + pub fn read_from_clipboard(&self) -> Option { + self.platform.read_from_clipboard() + } + + /// Waits for a condition to become true, with a timeout. + pub async fn wait_for( + &mut self, + entity: &Entity, + predicate: impl Fn(&T) -> bool, + timeout: Duration, + ) -> Result<()> { + let start = web_time::Instant::now(); + loop { + { + let app = self.app.borrow(); + if predicate(entity.read(&app)) { + return Ok(()); + } + } + + if start.elapsed() > timeout { + return Err(anyhow!("Timed out waiting for condition")); + } + + self.run_until_parked(); + self.background_executor + .timer(Duration::from_millis(10)) + .await; + } + } + + /// Captures a screenshot of the specified window using direct texture capture. + /// + /// This renders the scene to a Metal texture and reads the pixels directly, + /// which does not require the window to be visible on screen. + #[cfg(any(test, feature = "test-support"))] + pub fn capture_screenshot(&mut self, window: AnyWindowHandle) -> Result { + self.update_window(window, |_, window, _cx| window.render_to_image())? + } + + /// Waits for animations to complete by waiting a couple of frames. + pub async fn wait_for_animations(&self) { + self.background_executor + .timer(Duration::from_millis(32)) + .await; + self.run_until_parked(); + } +} + +impl AppContext for VisualTestAppContext { + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity { + let mut app = self.app.borrow_mut(); + app.new(build_entity) + } + + fn reserve_entity(&mut self) -> crate::Reservation { + let mut app = self.app.borrow_mut(); + app.reserve_entity() + } + + fn insert_entity( + &mut self, + reservation: crate::Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity { + let mut app = self.app.borrow_mut(); + app.insert_entity(reservation, build_entity) + } + + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R { + let mut app = self.app.borrow_mut(); + app.update_entity(handle, update) + } + + fn as_mut<'a, T>(&'a mut self, _: &Entity) -> crate::GpuiBorrow<'a, T> + where + T: 'static, + { + panic!("Cannot use as_mut with a visual test app context. Try calling update() first") + } + + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static, + { + let app = self.app.borrow(); + app.read_entity(handle, read) + } + + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T, + { + let mut lock = self.app.borrow_mut(); + lock.update_window(window, f) + } + + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option { + let mut lock = self.app.borrow_mut(); + lock.with_window(entity_id, f) + } + + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static, + { + let app = self.app.borrow(); + app.read_window(window, read) + } + + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.background_executor.spawn(future) + } + + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global, + { + let app = self.app.borrow(); + callback(app.global::(), &app) + } +} diff --git a/vendor/gpui-pre/src/arena.rs b/vendor/gpui-pre/src/arena.rs new file mode 100644 index 00000000..ea5968f8 --- /dev/null +++ b/vendor/gpui-pre/src/arena.rs @@ -0,0 +1,401 @@ +use std::{ + alloc::{self, handle_alloc_error}, + cell::Cell, + num::NonZeroUsize, + ops::{Deref, DerefMut}, + ptr::{self, NonNull}, + rc::Rc, +}; + +struct ArenaElement { + value: *mut u8, + drop: unsafe fn(*mut u8), +} + +impl Drop for ArenaElement { + #[inline(always)] + fn drop(&mut self) { + unsafe { (self.drop)(self.value) }; + } +} + +struct Chunk { + start: *mut u8, + end: *mut u8, + offset: *mut u8, +} + +impl Drop for Chunk { + fn drop(&mut self) { + unsafe { + let chunk_size = self.end.offset_from_unsigned(self.start); + // SAFETY: This succeeded during allocation. + let layout = alloc::Layout::from_size_align_unchecked(chunk_size, 1); + alloc::dealloc(self.start, layout); + } + } +} + +impl Chunk { + fn new(chunk_size: NonZeroUsize) -> Self { + // this only fails if chunk_size is unreasonably huge + let layout = alloc::Layout::from_size_align(chunk_size.get(), 1).unwrap(); + let start = unsafe { alloc::alloc(layout) }; + if start.is_null() { + handle_alloc_error(layout); + } + let end = unsafe { start.add(chunk_size.get()) }; + Self { + start, + end, + offset: start, + } + } + + fn allocate(&mut self, layout: alloc::Layout) -> Option> { + // Compute the allocation bounds in integer address space so that the + // bounds check happens before any pointer offsetting. Offsetting a + // pointer past the end of its allocation is undefined behavior even if + // the result is never dereferenced (as happens on the chunk-spill + // path), so `ptr::add` cannot be used until we know the result stays + // in bounds. `checked_add` also handles the documented case where + // `align_offset` returns `usize::MAX`. + let base = self.offset.addr(); + let aligned_addr = base.checked_add(self.offset.align_offset(layout.align()))?; + let next_addr = aligned_addr.checked_add(layout.size())?; + + if next_addr <= self.end.addr() { + let aligned = self.offset.with_addr(aligned_addr); + self.offset = self.offset.with_addr(next_addr); + NonNull::new(aligned) + } else { + None + } + } + + fn reset(&mut self) { + self.offset = self.start; + } +} + +pub struct Arena { + chunks: Vec, + elements: Vec, + valid: Rc>, + current_chunk_index: usize, + chunk_size: NonZeroUsize, + scope_depth: usize, +} + +impl Drop for Arena { + fn drop(&mut self) { + self.force_clear(); + } +} + +impl Arena { + pub fn new(chunk_size: usize) -> Self { + let chunk_size = NonZeroUsize::try_from(chunk_size).unwrap(); + Self { + chunks: vec![Chunk::new(chunk_size)], + elements: Vec::new(), + valid: Rc::new(Cell::new(true)), + current_chunk_index: 0, + chunk_size, + scope_depth: 0, + } + } + + pub fn capacity(&self) -> usize { + self.chunks.len() * self.chunk_size.get() + } + + /// Marks the start of a scope (e.g. a window draw) whose allocations must stay + /// live until the scope ends, even if `clear` is called by a nested scope in + /// the meantime. + pub fn begin_scope(&mut self) { + self.scope_depth += 1; + } + + /// Ends the innermost scope started with `begin_scope`. + /// + /// Panics if no scope is active: an unbalanced `end_scope` would let `clear` + /// run while an enclosing scope still references arena memory, which is + /// exactly the use-after-free this bookkeeping exists to prevent, so failing + /// loudly here is preferable. + pub fn end_scope(&mut self) { + self.scope_depth = self + .scope_depth + .checked_sub(1) + .expect("Arena::end_scope called without a matching begin_scope"); + } + + /// Drops all allocations and resets the arena, unless a scope is still active. + /// + /// When a draw triggers a nested draw (e.g. re-entrant window procedure + /// invocations on Windows, or opening a window from within a draw), the nested + /// draw's clear must not free memory the outer draw still references, so it is + /// deferred: the outer draw's own clear will drop both draws' allocations. + pub fn clear(&mut self) { + if self.scope_depth == 0 { + self.force_clear(); + } else { + log::debug!( + "deferring arena clear; {} enclosing scope(s) still active", + self.scope_depth + ); + } + } + + fn force_clear(&mut self) { + self.valid.set(false); + self.valid = Rc::new(Cell::new(true)); + self.elements.clear(); + for chunk_index in 0..=self.current_chunk_index { + self.chunks[chunk_index].reset(); + } + self.current_chunk_index = 0; + } + + #[inline(always)] + pub fn alloc(&mut self, f: impl FnOnce() -> T) -> ArenaBox { + #[inline(always)] + unsafe fn inner_writer(ptr: *mut T, f: F) + where + F: FnOnce() -> T, + { + unsafe { ptr::write(ptr, f()) }; + } + + unsafe fn drop(ptr: *mut u8) { + unsafe { std::ptr::drop_in_place(ptr.cast::()) }; + } + + let layout = alloc::Layout::new::(); + let current_chunk = &mut self.chunks[self.current_chunk_index]; + let ptr = if let Some(ptr) = current_chunk.allocate(layout) { + ptr.as_ptr() + } else { + self.allocate_next_chunk(layout) + }; + + unsafe { inner_writer(ptr.cast(), f) }; + self.elements.push(ArenaElement { + value: ptr, + drop: drop::, + }); + + ArenaBox { + ptr: ptr.cast(), + valid: self.valid.clone(), + } + } + + #[inline(never)] + fn allocate_next_chunk(&mut self, layout: alloc::Layout) -> *mut u8 { + self.current_chunk_index += 1; + if self.current_chunk_index >= self.chunks.len() { + self.chunks.push(Chunk::new(self.chunk_size)); + assert_eq!(self.current_chunk_index, self.chunks.len() - 1); + log::trace!( + "increased element arena capacity to {}kb", + self.capacity() / 1024, + ); + } + let current_chunk = &mut self.chunks[self.current_chunk_index]; + if let Some(pointer) = current_chunk.allocate(layout) { + pointer.as_ptr() + } else { + panic!( + "Arena chunk_size of {} is too small to allocate {} bytes", + self.chunk_size, + layout.size() + ); + } + } +} + +pub struct ArenaBox { + ptr: *mut T, + valid: Rc>, +} + +impl ArenaBox { + #[inline(always)] + pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaBox { + ArenaBox { + ptr: f(&mut self), + valid: self.valid, + } + } + + #[track_caller] + fn validate(&self) { + assert!( + self.valid.get(), + "attempted to dereference an ArenaRef after its Arena was cleared" + ); + } +} + +impl Deref for ArenaBox { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + self.validate(); + unsafe { &*self.ptr } + } +} + +impl DerefMut for ArenaBox { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + self.validate(); + unsafe { &mut *self.ptr } + } +} + +#[cfg(test)] +mod tests { + use std::{cell::Cell, rc::Rc}; + + use super::*; + + #[test] + fn test_arena() { + let mut arena = Arena::new(1024); + let a = arena.alloc(|| 1u64); + let b = arena.alloc(|| 2u32); + let c = arena.alloc(|| 3u16); + let d = arena.alloc(|| 4u8); + assert_eq!(*a, 1); + assert_eq!(*b, 2); + assert_eq!(*c, 3); + assert_eq!(*d, 4); + + arena.clear(); + let a = arena.alloc(|| 5u64); + let b = arena.alloc(|| 6u32); + let c = arena.alloc(|| 7u16); + let d = arena.alloc(|| 8u8); + assert_eq!(*a, 5); + assert_eq!(*b, 6); + assert_eq!(*c, 7); + assert_eq!(*d, 8); + + // Ensure drop gets called. + let dropped = Rc::new(Cell::new(false)); + struct DropGuard(Rc>); + impl Drop for DropGuard { + fn drop(&mut self) { + self.0.set(true); + } + } + arena.alloc(|| DropGuard(dropped.clone())); + arena.clear(); + assert!(dropped.get()); + } + + #[test] + fn test_arena_grow() { + let mut arena = Arena::new(8); + arena.alloc(|| 1u64); + arena.alloc(|| 2u64); + + assert_eq!(arena.capacity(), 16); + + arena.alloc(|| 3u32); + arena.alloc(|| 4u32); + + assert_eq!(arena.capacity(), 24); + } + + #[test] + fn test_arena_alignment() { + let mut arena = Arena::new(256); + let x1 = arena.alloc(|| 1u8); + let x2 = arena.alloc(|| 2u16); + let x3 = arena.alloc(|| 3u32); + let x4 = arena.alloc(|| 4u64); + let x5 = arena.alloc(|| 5u64); + + assert_eq!(*x1, 1); + assert_eq!(*x2, 2); + assert_eq!(*x3, 3); + assert_eq!(*x4, 4); + assert_eq!(*x5, 5); + + assert_eq!(x1.ptr.align_offset(std::mem::align_of_val(&*x1)), 0); + assert_eq!(x2.ptr.align_offset(std::mem::align_of_val(&*x2)), 0); + } + + #[test] + #[should_panic(expected = "attempted to dereference an ArenaRef after its Arena was cleared")] + fn test_arena_use_after_clear() { + let mut arena = Arena::new(16); + let value = arena.alloc(|| 1u64); + + arena.clear(); + let _read_value = *value; + } + + #[test] + fn test_clear_deferred_while_scope_active() { + struct DropCounter(Rc>); + impl Drop for DropCounter { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } + } + + let drops = Rc::new(Cell::new(0)); + let mut arena = Arena::new(1024); + + // Outer draw starts and allocates. + arena.begin_scope(); + let outer = arena.alloc(|| 42u64); + arena.alloc({ + let drops = drops.clone(); + || DropCounter(drops) + }); + + // Nested draw runs to completion and requests a clear. + arena.begin_scope(); + let inner = arena.alloc(|| 7u64); + arena.alloc({ + let drops = drops.clone(); + || DropCounter(drops) + }); + arena.end_scope(); + arena.clear(); + + // The clear must be deferred: the outer draw's allocations are still live. + assert_eq!(*outer, 42); + assert_eq!(*inner, 7); + assert_eq!(drops.get(), 0); + + // Once the outer draw finishes, its clear drops both draws' allocations. + arena.end_scope(); + arena.clear(); + assert_eq!(drops.get(), 2); + } + + #[test] + fn test_clear_without_scope_is_immediate() { + let mut arena = Arena::new(1024); + let value = arena.alloc(|| 1u64); + assert_eq!(*value, 1); + arena.clear(); + assert!(!value.valid.get()); + } + + #[test] + #[should_panic(expected = "Arena::end_scope called without a matching begin_scope")] + fn test_unbalanced_end_scope_panics() { + let mut arena = Arena::new(1024); + arena.begin_scope(); + arena.end_scope(); + arena.end_scope(); + } +} diff --git a/vendor/gpui-pre/src/asset_cache.rs b/vendor/gpui-pre/src/asset_cache.rs new file mode 100644 index 00000000..4c7bee12 --- /dev/null +++ b/vendor/gpui-pre/src/asset_cache.rs @@ -0,0 +1,358 @@ +use crate::{App, EntityId, SharedString, SharedUri, Task}; +use collections::FxHashSet; +use futures::{Future, TryFutureExt}; + +use std::cell::RefCell; +use std::fmt::Debug; +use std::hash::{BuildHasher, Hash}; +use std::marker::PhantomData; +use std::mem; +use std::path::{Path, PathBuf}; +use std::rc::Rc; +use std::sync::Arc; + +pub(crate) struct CachedLoad { + state: Rc>>, + // Keep the owner outside the state so publishing a result cannot cancel its own task. + _task: Task<()>, +} + +enum CachedLoadState { + Loading(FxHashSet), + Loaded(T), +} + +impl CachedLoad { + pub(crate) fn new(future: impl Future + Send + 'static, cx: &App) -> Self { + let state = Rc::new(RefCell::new(CachedLoadState::Loading(FxHashSet::default()))); + let task = cx.background_executor().spawn(future); + let task = cx.spawn({ + let state = Rc::downgrade(&state); + async move |cx| { + let result = task.await; + let Some(state) = state.upgrade() else { + return; + }; + let previous = + mem::replace(&mut *state.borrow_mut(), CachedLoadState::Loaded(result)); + let CachedLoadState::Loading(views) = previous else { + unreachable!("a cached load completes only once"); + }; + cx.update(|cx| { + for view in views { + cx.notify(view); + } + }); + } + }); + Self { state, _task: task } + } + + pub(crate) fn get(&self) -> Option { + match &*self.state.borrow() { + CachedLoadState::Loading(_) => None, + CachedLoadState::Loaded(result) => Some(result.clone()), + } + } + + pub(crate) fn use_by(&self, view: EntityId) -> Option { + match &mut *self.state.borrow_mut() { + CachedLoadState::Loading(views) => { + views.insert(view); + None + } + CachedLoadState::Loaded(result) => Some(result.clone()), + } + } +} + +/// An enum representing +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum Resource { + /// This resource is at a given URI + Uri(SharedUri), + /// This resource is at a given path in the file system + Path(Arc), + /// This resource is embedded in the application binary + Embedded(SharedString), +} + +impl From for Resource { + fn from(value: SharedUri) -> Self { + Self::Uri(value) + } +} + +impl From for Resource { + fn from(value: PathBuf) -> Self { + Self::Path(value.into()) + } +} + +impl From> for Resource { + fn from(value: Arc) -> Self { + Self::Path(value) + } +} + +/// A trait for asynchronous asset loading. +pub trait Asset: 'static { + /// The source of the asset. + type Source: Clone + Hash + Send; + + /// The loaded asset + type Output: Clone + Send; + + /// Load the asset asynchronously + fn load( + source: Self::Source, + cx: &mut App, + ) -> impl Future + Send + 'static; +} + +/// An asset Loader which logs the [`Err`] variant of a [`Result`] during loading +pub enum AssetLogger { + #[doc(hidden)] + _Phantom(PhantomData, &'static dyn crate::seal::Sealed), +} + +impl Asset for AssetLogger +where + T: Asset>, + R: Clone + Send, + E: Clone + Send + Debug, +{ + type Source = T::Source; + + type Output = T::Output; + + fn load( + source: Self::Source, + cx: &mut App, + ) -> impl Future + Send + 'static { + let load = T::load(source, cx); + load.inspect_err(|e| log::error!("Failed to load asset: {:?}", e)) + } +} + +/// Use a quick, non-cryptographically secure hash function to get an identifier from data +pub fn hash(data: &T) -> u64 { + collections::FxBuildHasher.hash_one(data) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{AppContext, TestAppContext}; + use futures::channel::oneshot; + use std::{ + cell::Cell, + collections::VecDeque, + hash::{Hash, Hasher}, + rc::Rc, + sync::{ + Arc, Mutex, + atomic::{AtomicUsize, Ordering}, + }, + }; + + #[gpui::test] + fn cached_load_caches_success_and_error(cx: &mut TestAppContext) { + let successful_load = + cx.update(|cx| CachedLoad::new(async { Ok::<_, &'static str>(42) }, cx)); + let failed_load = + cx.update(|cx| CachedLoad::new(async { Err::("load failed") }, cx)); + + assert_eq!(successful_load.get(), None); + assert_eq!(failed_load.get(), None); + + cx.run_until_parked(); + + assert_eq!(successful_load.get(), Some(Ok(42))); + assert_eq!(successful_load.get(), Some(Ok(42))); + assert_eq!(failed_load.get(), Some(Err("load failed"))); + assert_eq!(failed_load.get(), Some(Err("load failed"))); + } + + #[gpui::test] + fn completed_load_without_subscribers_is_cached_and_deduplicated(cx: &mut TestAppContext) { + let (sender, receiver) = oneshot::channel(); + let source = TestAssetSource::new(1, [receiver]); + + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + assert_eq!(source.load_count(), 1); + + assert!(sender.send(Ok(42)).is_ok()); + cx.run_until_parked(); + + assert_eq!( + cx.update(|cx| cx.fetch_asset::(&source)), + Some(Ok(42)) + ); + assert_eq!( + cx.update(|cx| cx.fetch_asset::(&source)), + Some(Ok(42)) + ); + assert_eq!(source.load_count(), 1); + } + + #[gpui::test] + fn load_completion_notifies_each_observing_entity_once(cx: &mut TestAppContext) { + let (sender, receiver) = oneshot::channel::(); + let load = cx.update(|cx| { + CachedLoad::new( + async move { receiver.await.expect("test sends a result") }, + cx, + ) + }); + let first_notification_count = Rc::new(Cell::new(0)); + let second_notification_count = Rc::new(Cell::new(0)); + let (first_entity, second_entity) = cx.update(|cx| { + let first_entity = cx.new(|_| ()); + let second_entity = cx.new(|_| ()); + cx.observe(&first_entity, { + let first_notification_count = first_notification_count.clone(); + move |_, _| first_notification_count.set(first_notification_count.get() + 1) + }) + .detach(); + cx.observe(&second_entity, { + let second_notification_count = second_notification_count.clone(); + move |_, _| second_notification_count.set(second_notification_count.get() + 1) + }) + .detach(); + (first_entity, second_entity) + }); + + assert_eq!(load.use_by(first_entity.entity_id()), None); + assert_eq!(load.use_by(first_entity.entity_id()), None); + assert_eq!(load.use_by(second_entity.entity_id()), None); + + assert!(sender.send(42).is_ok()); + cx.run_until_parked(); + + assert_eq!(first_notification_count.get(), 1); + assert_eq!(second_notification_count.get(), 1); + assert_eq!(load.use_by(first_entity.entity_id()), Some(42)); + assert_eq!(load.use_by(second_entity.entity_id()), Some(42)); + } + + #[gpui::test] + fn removing_pending_asset_cancels_it_and_replacement_ignores_stale_completion( + cx: &mut TestAppContext, + ) { + let (stale_sender, stale_receiver) = oneshot::channel(); + let (replacement_sender, replacement_receiver) = oneshot::channel(); + let source = TestAssetSource::new(2, [stale_receiver, replacement_receiver]); + + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + assert_eq!(source.load_count(), 1); + cx.run_until_parked(); + + cx.update(|cx| cx.remove_asset::(&source)); + assert!(!cx.update(|cx| cx.has_asset::(&source))); + cx.run_until_parked(); + assert!(stale_sender.send(Ok(1)).is_err()); + + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + assert_eq!(source.load_count(), 2); + + assert!(replacement_sender.send(Err("replacement failed")).is_ok()); + cx.run_until_parked(); + + assert_eq!( + cx.update(|cx| cx.fetch_asset::(&source)), + Some(Err("replacement failed")) + ); + assert_eq!(source.load_count(), 2); + } + + #[gpui::test] + fn eviction_after_worker_completion_does_not_publish_into_replacement(cx: &mut TestAppContext) { + let (sender, receiver) = oneshot::channel(); + let (replacement_sender, replacement_receiver) = oneshot::channel(); + let source = TestAssetSource::new(3, [receiver, replacement_receiver]); + + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + assert!(sender.send(Ok(1)).is_ok()); + while source.completion_count.load(Ordering::SeqCst) == 0 { + assert!(cx.background_executor.tick()); + } + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + + cx.update(|cx| { + cx.remove_asset::(&source); + assert_eq!(cx.fetch_asset::(&source), None); + }); + cx.run_until_parked(); + assert_eq!(cx.update(|cx| cx.fetch_asset::(&source)), None); + + assert!(replacement_sender.send(Ok(2)).is_ok()); + cx.run_until_parked(); + assert_eq!( + cx.update(|cx| cx.fetch_asset::(&source)), + Some(Ok(2)) + ); + assert_eq!(source.load_count(), 2); + } + + struct TestAsset; + + #[derive(Clone)] + struct TestAssetSource { + id: usize, + load_count: Arc, + completion_count: Arc, + receivers: Arc>>>>, + } + + impl TestAssetSource { + fn new( + id: usize, + receivers: impl IntoIterator>>, + ) -> Self { + Self { + id, + load_count: Arc::new(AtomicUsize::new(0)), + completion_count: Arc::new(AtomicUsize::new(0)), + receivers: Arc::new(Mutex::new(receivers.into_iter().collect())), + } + } + + fn load_count(&self) -> usize { + self.load_count.load(Ordering::SeqCst) + } + } + + impl Hash for TestAssetSource { + fn hash(&self, state: &mut H) { + self.id.hash(state); + } + } + + impl Asset for TestAsset { + type Source = TestAssetSource; + type Output = Result; + + fn load( + source: Self::Source, + _cx: &mut App, + ) -> impl Future + Send + 'static { + source.load_count.fetch_add(1, Ordering::SeqCst); + let receiver = source + .receivers + .lock() + .expect("test receiver mutex should not be poisoned") + .pop_front() + .expect("each test load should have a receiver"); + async move { + let result = match receiver.await { + Ok(result) => result, + Err(_) => Err("cancelled"), + }; + source.completion_count.fetch_add(1, Ordering::SeqCst); + result + } + } + } +} diff --git a/vendor/gpui-pre/src/assets.rs b/vendor/gpui-pre/src/assets.rs new file mode 100644 index 00000000..cb8b47ed --- /dev/null +++ b/vendor/gpui-pre/src/assets.rs @@ -0,0 +1,133 @@ +use crate::{DevicePixels, Pixels, Result, SharedString, Size, size}; +use smallvec::SmallVec; + +use image::{Delay, Frame}; +use std::{ + borrow::Cow, + fmt, + hash::Hash, + sync::atomic::{AtomicUsize, Ordering::SeqCst}, +}; + +/// A source of assets for this app to use. +pub trait AssetSource: 'static + Send + Sync { + /// Load the given asset from the source path. + fn load(&self, path: &str) -> Result>>; + + /// List the assets at the given path. + fn list(&self, path: &str) -> Result>; +} + +impl AssetSource for () { + fn load(&self, _path: &str) -> Result>> { + Ok(None) + } + + fn list(&self, _path: &str) -> Result> { + Ok(vec![]) + } +} + +/// A unique identifier for the image cache +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct ImageId(pub usize); + +#[derive(PartialEq, Eq, Hash, Clone)] +#[expect(missing_docs)] +pub struct RenderImageParams { + pub image_id: ImageId, + pub frame_index: usize, +} + +/// A cached and processed image, in BGRA format +pub struct RenderImage { + /// The ID associated with this image + pub id: ImageId, + /// The scale factor of this image on render. + pub(crate) scale_factor: f32, + data: SmallVec<[Frame; 1]>, +} + +impl PartialEq for RenderImage { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + +impl Eq for RenderImage {} + +impl RenderImage { + /// Create a new image from the given data. + pub fn new(data: impl Into>) -> Self { + static NEXT_ID: AtomicUsize = AtomicUsize::new(0); + + Self { + id: ImageId(NEXT_ID.fetch_add(1, SeqCst)), + scale_factor: 1.0, + data: data.into(), + } + } + + /// Convert this image into a byte slice. + pub fn as_bytes(&self, frame_index: usize) -> Option<&[u8]> { + self.data + .get(frame_index) + .map(|frame| frame.buffer().as_raw().as_slice()) + } + + /// Get the size of this image, in pixels. + pub fn size(&self, frame_index: usize) -> Size { + self.data + .get(frame_index) + .map(|frame| { + let (width, height) = frame.buffer().dimensions(); + size(width.into(), height.into()) + }) + .unwrap_or_default() + } + + /// Get the size of this image, in pixels for display, adjusted for the scale factor. + pub(crate) fn render_size(&self, frame_index: usize) -> Size { + self.size(frame_index) + .map(|v| (v.0 as f32 / self.scale_factor).into()) + } + + /// Get the delay of this frame from the previous + pub fn delay(&self, frame_index: usize) -> Delay { + self.data + .get(frame_index) + .map(|frame| frame.delay()) + .unwrap_or(Delay::from_numer_denom_ms(100, 1)) + } + + /// Get the number of frames for this image. + pub fn frame_count(&self) -> usize { + self.data.len() + } +} + +impl fmt::Debug for RenderImage { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ImageData") + .field("id", &self.id) + .field("size", &self.data.first().map(|f| f.buffer().dimensions())) + .finish() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use smallvec::SmallVec; + + #[test] + fn empty_render_image_does_not_panic() { + let image = RenderImage::new(SmallVec::new()); + assert_eq!(image.frame_count(), 0); + assert_eq!(image.size(0), Size::default()); + assert_eq!(image.as_bytes(0), None); + assert_eq!(image.render_size(0), Size::default()); + assert_eq!(image.delay(0), Delay::from_numer_denom_ms(100, 1)); + let _ = format!("{image:?}"); + } +} diff --git a/vendor/gpui-pre/src/bounds_tree.rs b/vendor/gpui-pre/src/bounds_tree.rs new file mode 100644 index 00000000..e95e3247 --- /dev/null +++ b/vendor/gpui-pre/src/bounds_tree.rs @@ -0,0 +1,472 @@ +use crate::{Bounds, Half}; +use std::{ + cmp, + fmt::Debug, + ops::{Add, Sub}, + ptr::NonNull, +}; + +/// Maximum children per internal node (R-tree style branching factor). +/// Higher values = shorter tree = fewer cache misses, but more work per node. +const MAX_CHILDREN: usize = 12; + +/// A spatial tree optimized for finding maximum ordering among intersecting bounds. +/// +/// This is an R-tree variant specifically designed for the use case of assigning +/// z-order to overlapping UI elements. Key optimizations: +/// - Tracks the leaf with global max ordering for O(1) fast-path queries +/// - Uses higher branching factor (4) for lower tree height +/// - Aggressive pruning during search based on max_order metadata +#[derive(Debug)] +pub(crate) struct BoundsTree +where + U: Clone + Debug + Default + PartialEq, +{ + /// All nodes stored contiguously for cache efficiency. + nodes: Vec>, + /// Index of the root node, if any. + root: Option, + /// Index of the leaf with the highest ordering (for fast-path lookups). + max_leaf: Option, + /// Reusable stack for tree traversal during insertion. + insert_path: Vec, + /// Reusable stack for search operations. + search_stack: Vec>>, +} + +/// A node in the bounds tree. +#[derive(Debug, Clone)] +struct Node +where + U: Clone + Debug + Default + PartialEq, +{ + /// Bounding box containing this node and all descendants. + bounds: Bounds, + /// Maximum ordering value in this subtree. + max_order: u32, + /// Node-specific data. + kind: NodeKind, +} + +#[derive(Debug, Clone)] +enum NodeKind { + /// Leaf node containing actual bounds data. + Leaf { + /// The ordering assigned to this bounds. + order: u32, + }, + /// Internal node with children. + Internal { + /// Indices of child nodes (2 to MAX_CHILDREN). + children: NodeChildren, + }, +} + +/// Fixed-size array for child indices, avoiding heap allocation. +#[derive(Debug, Clone)] +struct NodeChildren { + // Keeps an invariant where the max order child is always at the end + indices: [usize; MAX_CHILDREN], + len: u8, +} + +impl NodeChildren { + fn new() -> Self { + Self { + indices: [0; MAX_CHILDREN], + len: 0, + } + } + + fn push(&mut self, index: usize) { + debug_assert!((self.len as usize) < MAX_CHILDREN); + self.indices[self.len as usize] = index; + self.len += 1; + } + + fn len(&self) -> usize { + self.len as usize + } + + fn as_slice(&self) -> &[usize] { + &self.indices[..self.len as usize] + } +} + +impl BoundsTree +where + U: Clone + + Debug + + PartialEq + + PartialOrd + + Add + + Sub + + Half + + Default, +{ + /// Clears all nodes from the tree. + pub fn clear(&mut self) { + self.nodes.clear(); + self.root = None; + self.max_leaf = None; + self.insert_path.clear(); + self.search_stack.clear(); + } + + /// Inserts bounds into the tree and returns its assigned ordering. + /// + /// The ordering is one greater than the maximum ordering of any + /// existing bounds that intersect with the new bounds. + pub fn insert(&mut self, new_bounds: Bounds) -> u32 { + // Find maximum ordering among intersecting bounds + let max_intersecting = self.find_max_ordering(&new_bounds); + let ordering = max_intersecting + 1; + + // Insert the new leaf + let new_leaf_idx = self.insert_leaf(new_bounds, ordering); + + // Update max_leaf tracking + self.max_leaf = match self.max_leaf { + None => Some(new_leaf_idx), + Some(old_idx) if self.nodes[old_idx].max_order < ordering => Some(new_leaf_idx), + some => some, + }; + + ordering + } + + /// Finds the maximum ordering among all bounds that intersect with the query. + fn find_max_ordering(&mut self, query: &Bounds) -> u32 { + let Some(root_idx) = self.root else { + return 0; + }; + + // Fast path: check if the max-ordering leaf intersects + if let Some(max_idx) = self.max_leaf { + let max_node = &self.nodes[max_idx]; + if query.intersects(&max_node.bounds) { + return max_node.max_order; + } + } + + // Slow path: search the tree + self.search_stack.clear(); + self.search_stack.push(NonNull::from(&self.nodes[root_idx])); + + let mut max_found = 0u32; + + while let Some(node) = self.search_stack.pop() { + // SAFETY: `node` is guaranteed to be valid as the `nodes` stack is unmodified in this function + // and the `search_stack` only contains pointers from this function call. + let node = unsafe { node.as_ref() }; + + // Pruning: skip if this subtree can't improve our result + if node.max_order <= max_found { + continue; + } + + // Spatial pruning: skip if bounds don't intersect + if !query.intersects(&node.bounds) { + continue; + } + + match &node.kind { + NodeKind::Leaf { order } => { + max_found = cmp::max(max_found, *order); + } + NodeKind::Internal { children } => { + // Children are maintained with highest max_order at the end. + // Push in forward order to highest (last) is popped first. + self.search_stack.extend( + children + .as_slice() + .iter() + .map(|&child_idx| &self.nodes[child_idx]) + .filter(|node| node.max_order > max_found) + .map(NonNull::from), + ); + } + } + } + + max_found + } + + /// Inserts a leaf node with the given bounds and ordering. + /// Returns the index of the new leaf. + fn insert_leaf(&mut self, bounds: Bounds, order: u32) -> usize { + let new_leaf_idx = self.nodes.len(); + self.nodes.push(Node { + bounds: bounds.clone(), + max_order: order, + kind: NodeKind::Leaf { order }, + }); + + let Some(root_idx) = self.root else { + // Tree is empty, new leaf becomes root + self.root = Some(new_leaf_idx); + return new_leaf_idx; + }; + + // If root is a leaf, create internal node with both + if matches!(self.nodes[root_idx].kind, NodeKind::Leaf { .. }) { + let root_bounds = self.nodes[root_idx].bounds.clone(); + let root_order = self.nodes[root_idx].max_order; + + let mut children = NodeChildren::new(); + // Max end invariant + if order > root_order { + children.push(root_idx); + children.push(new_leaf_idx); + } else { + children.push(new_leaf_idx); + children.push(root_idx); + } + + let new_root_idx = self.nodes.len(); + self.nodes.push(Node { + bounds: root_bounds.union(&bounds), + max_order: cmp::max(root_order, order), + kind: NodeKind::Internal { children }, + }); + self.root = Some(new_root_idx); + return new_leaf_idx; + } + + // Descend to find the best internal node to insert into + self.insert_path.clear(); + let mut current_idx = root_idx; + + loop { + let current = &self.nodes[current_idx]; + let NodeKind::Internal { children } = ¤t.kind else { + unreachable!("Should only traverse internal nodes"); + }; + + self.insert_path.push(current_idx); + + // Find the best child to descend into + let mut best_child_idx = children.as_slice()[0]; + let mut best_child_pos = 0; + let mut best_cost = bounds + .union(&self.nodes[best_child_idx].bounds) + .half_perimeter(); + + for (pos, &child_idx) in children.as_slice().iter().enumerate().skip(1) { + let cost = bounds.union(&self.nodes[child_idx].bounds).half_perimeter(); + if cost < best_cost { + best_cost = cost; + best_child_idx = child_idx; + best_child_pos = pos; + } + } + + // Check if best child is a leaf or internal + if matches!(self.nodes[best_child_idx].kind, NodeKind::Leaf { .. }) { + // Best child is a leaf. Check if current node has room for another child. + if children.len() < MAX_CHILDREN { + // Add new leaf directly to this node + let node = &mut self.nodes[current_idx]; + + if let NodeKind::Internal { children } = &mut node.kind { + children.push(new_leaf_idx); + // Swap new leaf only if it has the highest max_order + if order <= node.max_order { + let last = children.len() - 1; + children.indices.swap(last - 1, last); + } + } + + node.bounds = node.bounds.union(&bounds); + node.max_order = cmp::max(node.max_order, order); + break; + } else { + // Node is full, create new internal with [best_leaf, new_leaf] + let sibling_bounds = self.nodes[best_child_idx].bounds.clone(); + let sibling_order = self.nodes[best_child_idx].max_order; + + let mut new_children = NodeChildren::new(); + // Max end invariant + if order > sibling_order { + new_children.push(best_child_idx); + new_children.push(new_leaf_idx); + } else { + new_children.push(new_leaf_idx); + new_children.push(best_child_idx); + } + + let new_internal_idx = self.nodes.len(); + let new_internal_max = cmp::max(sibling_order, order); + self.nodes.push(Node { + bounds: sibling_bounds.union(&bounds), + max_order: new_internal_max, + kind: NodeKind::Internal { + children: new_children, + }, + }); + + // Replace the leaf with the new internal in parent + let parent = &mut self.nodes[current_idx]; + if let NodeKind::Internal { children } = &mut parent.kind { + let children_len = children.len(); + + children.indices[best_child_pos] = new_internal_idx; + + // If new internal has highest max_order, swap it to the end + // to maintain sorting invariant + if new_internal_max > parent.max_order { + children.indices.swap(best_child_pos, children_len - 1); + } + } + break; + } + } else { + // Best child is internal, continue descent + current_idx = best_child_idx; + } + } + + // Propagate bounds and max_order updates up the tree + let mut updated_child_idx = None; + for &node_idx in self.insert_path.iter().rev() { + let node = &mut self.nodes[node_idx]; + node.bounds = node.bounds.union(&bounds); + + if node.max_order < order { + node.max_order = order; + + // Swap updated child to end (skip first iteration since the invariant is already handled by previous cases) + if let Some(child_idx) = updated_child_idx { + if let NodeKind::Internal { children } = &mut node.kind { + if let Some(pos) = children.as_slice().iter().position(|&c| c == child_idx) + { + let last = children.len() - 1; + if pos != last { + children.indices.swap(pos, last); + } + } + } + } + } + + updated_child_idx = Some(node_idx); + } + + new_leaf_idx + } +} + +impl Default for BoundsTree +where + U: Clone + Debug + Default + PartialEq, +{ + fn default() -> Self { + BoundsTree { + nodes: Vec::new(), + root: None, + max_leaf: None, + insert_path: Vec::new(), + search_stack: Vec::new(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Bounds, Point, Size}; + use rand::{Rng, SeedableRng}; + + #[test] + fn test_insert() { + let mut tree = BoundsTree::::default(); + let bounds1 = Bounds { + origin: Point { x: 0.0, y: 0.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + let bounds2 = Bounds { + origin: Point { x: 5.0, y: 5.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + let bounds3 = Bounds { + origin: Point { x: 10.0, y: 10.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + + // Insert the bounds into the tree and verify the order is correct + assert_eq!(tree.insert(bounds1), 1); + assert_eq!(tree.insert(bounds2), 2); + assert_eq!(tree.insert(bounds3), 3); + + // Insert non-overlapping bounds and verify they can reuse orders + let bounds4 = Bounds { + origin: Point { x: 20.0, y: 20.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + let bounds5 = Bounds { + origin: Point { x: 40.0, y: 40.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + let bounds6 = Bounds { + origin: Point { x: 25.0, y: 25.0 }, + size: Size { + width: 10.0, + height: 10.0, + }, + }; + assert_eq!(tree.insert(bounds4), 1); // bounds4 does not overlap with bounds1, bounds2, or bounds3 + assert_eq!(tree.insert(bounds5), 1); // bounds5 does not overlap with any other bounds + assert_eq!(tree.insert(bounds6), 2); // bounds6 overlaps with bounds4, so it should have a different order + } + + #[test] + fn test_random_iterations() { + let max_bounds = 100; + for seed in 1..=1000 { + // let seed = 44; + let mut tree = BoundsTree::default(); + let mut rng = rand::rngs::StdRng::seed_from_u64(seed as u64); + let mut expected_quads: Vec<(Bounds, u32)> = Vec::new(); + + // Insert a random number of random AABBs into the tree. + let num_bounds = rng.random_range(1..=max_bounds); + for _ in 0..num_bounds { + let min_x: f32 = rng.random_range(-100.0..100.0); + let min_y: f32 = rng.random_range(-100.0..100.0); + let width: f32 = rng.random_range(0.0..50.0); + let height: f32 = rng.random_range(0.0..50.0); + let bounds = Bounds { + origin: Point { x: min_x, y: min_y }, + size: Size { width, height }, + }; + + let expected_ordering = expected_quads + .iter() + .filter_map(|quad| quad.0.intersects(&bounds).then_some(quad.1)) + .max() + .unwrap_or(0) + + 1; + expected_quads.push((bounds, expected_ordering)); + + // Insert the AABB into the tree and collect intersections. + let actual_ordering = tree.insert(bounds); + assert_eq!(actual_ordering, expected_ordering); + } + } + } +} diff --git a/vendor/gpui-pre/src/color.rs b/vendor/gpui-pre/src/color.rs new file mode 100644 index 00000000..3bd893f9 --- /dev/null +++ b/vendor/gpui-pre/src/color.rs @@ -0,0 +1,1070 @@ +use anyhow::{Context as _, bail}; +use schemars::{JsonSchema, json_schema}; +use serde::{ + Deserialize, Deserializer, Serialize, Serializer, + de::{self, Visitor}, +}; +use std::borrow::Cow; +use std::{ + fmt::{self, Display, Formatter}, + hash::{Hash, Hasher}, +}; + +/// Convert an RGB hex color code number to a color type +pub fn rgb(hex: u32) -> Rgba { + let [_, r, g, b] = hex.to_be_bytes().map(|b| (b as f32) / 255.0); + Rgba { r, g, b, a: 1.0 } +} + +/// Convert an RGBA hex color code number to [`Rgba`] +pub fn rgba(hex: u32) -> Rgba { + let [r, g, b, a] = hex.to_be_bytes().map(|b| (b as f32) / 255.0); + Rgba { r, g, b, a } +} + +/// Swap from RGBA with premultiplied alpha to BGRA +pub fn swap_rgba_pa_to_bgra(color: &mut [u8]) { + color.swap(0, 2); + if color[3] > 0 { + let a = color[3] as f32 / 255.; + color[0] = (color[0] as f32 / a) as u8; + color[1] = (color[1] as f32 / a) as u8; + color[2] = (color[2] as f32 / a) as u8; + } +} + +/// An RGBA color +#[derive(PartialEq, Clone, Copy, Default)] +#[repr(C)] +pub struct Rgba { + /// The red component of the color, in the range 0.0 to 1.0 + pub r: f32, + /// The green component of the color, in the range 0.0 to 1.0 + pub g: f32, + /// The blue component of the color, in the range 0.0 to 1.0 + pub b: f32, + /// The alpha component of the color, in the range 0.0 to 1.0 + pub a: f32, +} + +impl fmt::Debug for Rgba { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "rgba({:#010x})", u32::from(*self)) + } +} + +impl Rgba { + /// Create a new [`Rgba`] color by blending this and another color together + pub fn blend(&self, other: Rgba) -> Self { + if other.a >= 1.0 { + other + } else if other.a <= 0.0 { + *self + } else { + Rgba { + r: (self.r * (1.0 - other.a)) + (other.r * other.a), + g: (self.g * (1.0 - other.a)) + (other.g * other.a), + b: (self.b * (1.0 - other.a)) + (other.b * other.a), + a: self.a, + } + } + } + + /// Returns a new RGBA color with the same red, green and blue channels, but + /// with a new alpha value. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0xFF0000FF); + /// let faded = color.alpha(0.25); + /// assert_eq!(faded.a, 0.25); + /// ``` + /// + /// This will return a red color with 25% opacity. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0x3399FFCC); + /// let transparent = color.alpha(0.0); + /// assert_eq!(transparent.a, 0.0); + /// ``` + /// + /// This will return the same blue color, fully transparent. + pub fn alpha(&self, a: f32) -> Self { + Rgba { + r: self.r, + g: self.g, + b: self.b, + a: a.clamp(0., 1.), + } + } + + /// Returns a new RGBA color with the same red, green, and blue channels, + /// but with the alpha channel multiplied by the given factor. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0xFF0000FF); // Fully opaque red + /// let faded = color.opacity(0.5); + /// assert_eq!(faded.a, 0.5); + /// ``` + /// + /// This will return a red color with 50% opacity. + /// + /// Example: + /// ``` + /// use gpui::rgba; + /// let color = rgba(0x3399FFCC); // A light blue with 80% opacity + /// let faded = color.opacity(0.5); + /// assert!((faded.a - 0.4).abs() < 1e-6); + /// ``` + /// + /// This will return the same blue color scaled down to 40% opacity. + pub fn opacity(&self, factor: f32) -> Self { + Rgba { + r: self.r, + g: self.g, + b: self.b, + a: self.a * factor.clamp(0., 1.), + } + } +} + +impl From for u32 { + fn from(rgba: Rgba) -> Self { + let r = (rgba.r * 255.0) as u32; + let g = (rgba.g * 255.0) as u32; + let b = (rgba.b * 255.0) as u32; + let a = (rgba.a * 255.0) as u32; + (r << 24) | (g << 16) | (b << 8) | a + } +} + +struct RgbaVisitor; + +impl Visitor<'_> for RgbaVisitor { + type Value = Rgba; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string in the format #rrggbb or #rrggbbaa") + } + + fn visit_str(self, value: &str) -> Result { + Rgba::try_from(value).map_err(E::custom) + } +} + +impl JsonSchema for Rgba { + fn schema_name() -> Cow<'static, str> { + "Rgba".into() + } + + fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + json_schema!({ + "type": "string", + "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$" + }) + } +} + +impl<'de> Deserialize<'de> for Rgba { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_str(RgbaVisitor) + } +} + +impl Serialize for Rgba { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let r = (self.r * 255.0).round() as u8; + let g = (self.g * 255.0).round() as u8; + let b = (self.b * 255.0).round() as u8; + let a = (self.a * 255.0).round() as u8; + + let s = format!("#{r:02x}{g:02x}{b:02x}{a:02x}"); + serializer.serialize_str(&s) + } +} + +impl From for Rgba { + fn from(color: Hsla) -> Self { + let h = color.h; + let s = color.s; + let l = color.l; + + let c = (1.0 - (2.0 * l - 1.0).abs()) * s; + let x = c * (1.0 - ((h * 6.0) % 2.0 - 1.0).abs()); + let m = l - c / 2.0; + let cm = c + m; + let xm = x + m; + + let (r, g, b) = match (h * 6.0).floor() as i32 { + 0 | 6 => (cm, xm, m), + 1 => (xm, cm, m), + 2 => (m, cm, xm), + 3 => (m, xm, cm), + 4 => (xm, m, cm), + _ => (cm, m, xm), + }; + + Rgba { + r: r.clamp(0., 1.), + g: g.clamp(0., 1.), + b: b.clamp(0., 1.), + a: color.a, + } + } +} + +impl TryFrom<&'_ str> for Rgba { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + const RGB: usize = "rgb".len(); + const RGBA: usize = "rgba".len(); + const RRGGBB: usize = "rrggbb".len(); + const RRGGBBAA: usize = "rrggbbaa".len(); + + const EXPECTED_FORMATS: &str = "Expected #rgb, #rgba, #rrggbb, or #rrggbbaa"; + const INVALID_UNICODE: &str = "invalid unicode characters in color"; + + let Some(("", hex)) = value.trim().split_once('#') else { + bail!("invalid RGBA hex color: '{value}'. {EXPECTED_FORMATS}"); + }; + + let (r, g, b, a) = match hex.len() { + RGB | RGBA => { + let r = u8::from_str_radix( + hex.get(0..1).with_context(|| { + format!("{INVALID_UNICODE}: r component of #rgb/#rgba for value: '{value}'") + })?, + 16, + )?; + let g = u8::from_str_radix( + hex.get(1..2).with_context(|| { + format!("{INVALID_UNICODE}: g component of #rgb/#rgba for value: '{value}'") + })?, + 16, + )?; + let b = u8::from_str_radix( + hex.get(2..3).with_context(|| { + format!("{INVALID_UNICODE}: b component of #rgb/#rgba for value: '{value}'") + })?, + 16, + )?; + let a = if hex.len() == RGBA { + u8::from_str_radix( + hex.get(3..4).with_context(|| { + format!("{INVALID_UNICODE}: a component of #rgba for value: '{value}'") + })?, + 16, + )? + } else { + 0xf + }; + + /// Duplicates a given hex digit. + /// E.g., `0xf` -> `0xff`. + const fn duplicate(value: u8) -> u8 { + (value << 4) | value + } + + (duplicate(r), duplicate(g), duplicate(b), duplicate(a)) + } + RRGGBB | RRGGBBAA => { + let r = u8::from_str_radix( + hex.get(0..2).with_context(|| { + format!( + "{}: r component of #rrggbb/#rrggbbaa for value: '{}'", + INVALID_UNICODE, value + ) + })?, + 16, + )?; + let g = u8::from_str_radix( + hex.get(2..4).with_context(|| { + format!( + "{INVALID_UNICODE}: g component of #rrggbb/#rrggbbaa for value: '{value}'" + ) + })?, + 16, + )?; + let b = u8::from_str_radix( + hex.get(4..6).with_context(|| { + format!( + "{INVALID_UNICODE}: b component of #rrggbb/#rrggbbaa for value: '{value}'" + ) + })?, + 16, + )?; + let a = if hex.len() == RRGGBBAA { + u8::from_str_radix( + hex.get(6..8).with_context(|| { + format!( + "{INVALID_UNICODE}: a component of #rrggbbaa for value: '{value}'" + ) + })?, + 16, + )? + } else { + 0xff + }; + (r, g, b, a) + } + _ => bail!("invalid RGBA hex color: '{value}'. {EXPECTED_FORMATS}"), + }; + + Ok(Rgba { + r: r as f32 / 255., + g: g as f32 / 255., + b: b as f32 / 255., + a: a as f32 / 255., + }) + } +} + +/// An HSLA color +#[derive(Default, Copy, Clone, Debug)] +#[repr(C)] +pub struct Hsla { + /// Hue, in a range from 0 to 1 + pub h: f32, + + /// Saturation, in a range from 0 to 1 + pub s: f32, + + /// Lightness, in a range from 0 to 1 + pub l: f32, + + /// Alpha, in a range from 0 to 1 + pub a: f32, +} + +#[cfg(feature = "proptest")] +mod property { + use super::Hsla; + use proptest::prelude::*; + + impl Hsla { + /// Proptest [`Strategy`] that produces opaque colors (i.e. alpha = 1). + /// + /// For truly arbitrary colors, use the [`Arbitrary`] implementation. + pub fn opaque_strategy() -> impl Strategy { + (0.0f32..=1.0, 0.0f32..=1.0, 0.0f32..=1.0).prop_map(|(h, s, l)| Hsla { h, s, l, a: 1. }) + } + } + + impl Arbitrary for Hsla { + type Strategy = BoxedStrategy; + type Parameters = (); + + fn arbitrary_with((): Self::Parameters) -> Self::Strategy { + (0.0f32..=1.0, 0.0f32..=1.0, 0.0f32..=1.0, 0.0f32..=1.0) + .prop_map(|(h, s, l, a)| Hsla { h, s, l, a }) + .boxed() + } + } +} + +impl PartialEq for Hsla { + fn eq(&self, other: &Self) -> bool { + self.h + .total_cmp(&other.h) + .then(self.s.total_cmp(&other.s)) + .then(self.l.total_cmp(&other.l).then(self.a.total_cmp(&other.a))) + .is_eq() + } +} + +impl PartialOrd for Hsla { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Hsla { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.h + .total_cmp(&other.h) + .then(self.s.total_cmp(&other.s)) + .then(self.l.total_cmp(&other.l).then(self.a.total_cmp(&other.a))) + } +} + +impl Eq for Hsla {} + +impl Hash for Hsla { + fn hash(&self, state: &mut H) { + state.write_u32(u32::from_be_bytes(self.h.to_be_bytes())); + state.write_u32(u32::from_be_bytes(self.s.to_be_bytes())); + state.write_u32(u32::from_be_bytes(self.l.to_be_bytes())); + state.write_u32(u32::from_be_bytes(self.a.to_be_bytes())); + } +} + +impl Display for Hsla { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "hsla({:.2}, {:.2}%, {:.2}%, {:.2})", + self.h * 360., + self.s * 100., + self.l * 100., + self.a + ) + } +} + +/// Construct an [`Hsla`] object from plain values +pub const fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla { + Hsla { + h: h.clamp(0., 1.), + s: s.clamp(0., 1.), + l: l.clamp(0., 1.), + a: a.clamp(0., 1.), + } +} + +/// Pure black in [`Hsla`] +pub const fn black() -> Hsla { + Hsla { + h: 0., + s: 0., + l: 0., + a: 1., + } +} + +/// Transparent black in [`Hsla`] +pub const fn transparent_black() -> Hsla { + Hsla { + h: 0., + s: 0., + l: 0., + a: 0., + } +} + +/// Transparent white in [`Hsla`] +pub const fn transparent_white() -> Hsla { + Hsla { + h: 0., + s: 0., + l: 1., + a: 0., + } +} + +/// Opaque grey in [`Hsla`], values will be clamped to the range [0, 1] +pub const fn opaque_grey(lightness: f32, opacity: f32) -> Hsla { + Hsla { + h: 0., + s: 0., + l: lightness.clamp(0., 1.), + a: opacity.clamp(0., 1.), + } +} + +/// Pure white in [`Hsla`] +pub const fn white() -> Hsla { + Hsla { + h: 0., + s: 0., + l: 1., + a: 1., + } +} + +/// The color red in [`Hsla`] +pub const fn red() -> Hsla { + Hsla { + h: 0., + s: 1., + l: 0.5, + a: 1., + } +} + +/// The color blue in [`Hsla`] +pub const fn blue() -> Hsla { + Hsla { + h: 0.6666666667, + s: 1., + l: 0.5, + a: 1., + } +} + +/// The color green in [`Hsla`] +pub const fn green() -> Hsla { + Hsla { + h: 0.3333333333, + s: 1., + l: 0.25, + a: 1., + } +} + +/// The color yellow in [`Hsla`] +pub const fn yellow() -> Hsla { + Hsla { + h: 0.1666666667, + s: 1., + l: 0.5, + a: 1., + } +} + +impl Hsla { + /// Converts this HSLA color to an RGBA color. + pub fn to_rgb(self) -> Rgba { + self.into() + } + + /// The color red + pub const fn red() -> Self { + red() + } + + /// The color green + pub const fn green() -> Self { + green() + } + + /// The color blue + pub const fn blue() -> Self { + blue() + } + + /// The color black + pub const fn black() -> Self { + black() + } + + /// The color white + pub const fn white() -> Self { + white() + } + + /// The color transparent black + pub const fn transparent_black() -> Self { + transparent_black() + } + + /// Returns true if the HSLA color is fully transparent, false otherwise. + pub fn is_transparent(&self) -> bool { + self.a == 0.0 + } + + /// Returns true if the HSLA color is fully opaque, false otherwise. + pub fn is_opaque(&self) -> bool { + self.a == 1.0 + } + + /// Blends `other` on top of `self` based on `other`'s alpha value. The resulting color is a combination of `self`'s and `other`'s colors. + /// + /// If `other`'s alpha value is 1.0 or greater, `other` color is fully opaque, thus `other` is returned as the output color. + /// If `other`'s alpha value is 0.0 or less, `other` color is fully transparent, thus `self` is returned as the output color. + /// Else, the output color is calculated as a blend of `self` and `other` based on their weighted alpha values. + /// + /// Assumptions: + /// - Alpha values are contained in the range [0, 1], with 1 as fully opaque and 0 as fully transparent. + /// - The relative contributions of `self` and `other` is based on `self`'s alpha value (`self.a`) and `other`'s alpha value (`other.a`), `self` contributing `self.a * (1.0 - other.a)` and `other` contributing its own alpha value. + /// - RGB color components are contained in the range [0, 1]. + /// - If `self` and `other` colors are out of the valid range, the blend operation's output and behavior is undefined. + pub fn blend(self, other: Hsla) -> Hsla { + let alpha = other.a; + + if alpha >= 1.0 { + other + } else if alpha <= 0.0 { + self + } else { + let converted_self = Rgba::from(self); + let converted_other = Rgba::from(other); + let blended_rgb = converted_self.blend(converted_other); + Hsla::from(blended_rgb) + } + } + + /// Returns a new HSLA color with the same hue, and lightness, but with no saturation. + pub fn grayscale(&self) -> Self { + Hsla { + h: self.h, + s: 0., + l: self.l, + a: self.a, + } + } + + /// Fade out the color by a given factor. This factor should be between 0.0 and 1.0. + /// Where 0.0 will leave the color unchanged, and 1.0 will completely fade out the color. + pub fn fade_out(&mut self, factor: f32) { + self.a *= 1.0 - factor.clamp(0., 1.); + } + + /// Multiplies the alpha value of the color by a given factor + /// and returns a new HSLA color. + /// + /// Useful for transforming colors with dynamic opacity, + /// like a color from an external source. + /// + /// Example: + /// ``` + /// let color = gpui::red(); + /// let faded_color = color.opacity(0.5); + /// assert_eq!(faded_color.a, 0.5); + /// ``` + /// + /// This will return a red color with half the opacity. + /// + /// Example: + /// ``` + /// use gpui::hsla; + /// let color = hsla(0.7, 1.0, 0.5, 0.7); // A saturated blue + /// let faded_color = color.opacity(0.16); + /// assert!((faded_color.a - 0.112).abs() < 1e-6); + /// ``` + /// + /// This will return a blue color with around ~10% opacity, + /// suitable for an element's hover or selected state. + /// + pub fn opacity(&self, factor: f32) -> Self { + Hsla { + h: self.h, + s: self.s, + l: self.l, + a: self.a * factor.clamp(0., 1.), + } + } + + /// Returns a new HSLA color with the same hue, saturation, + /// and lightness, but with a new alpha value. + /// + /// Example: + /// ``` + /// let color = gpui::red(); + /// let red_color = color.alpha(0.25); + /// assert_eq!(red_color.a, 0.25); + /// ``` + /// + /// This will return a red color with 25% opacity. + /// + /// Example: + /// ``` + /// use gpui::hsla; + /// let color = hsla(0.7, 1.0, 0.5, 0.7); // A saturated blue + /// let faded_color = color.alpha(0.25); + /// assert_eq!(faded_color.a, 0.25); + /// ``` + /// + /// This will return a blue color with 25% opacity. + pub fn alpha(&self, a: f32) -> Self { + Hsla { + h: self.h, + s: self.s, + l: self.l, + a: a.clamp(0., 1.), + } + } +} + +impl From for Hsla { + fn from(color: Rgba) -> Self { + let r = color.r; + let g = color.g; + let b = color.b; + + let max = r.max(g.max(b)); + let min = r.min(g.min(b)); + let delta = max - min; + + let l = (max + min) / 2.0; + let s = if l == 0.0 || l == 1.0 { + 0.0 + } else if l < 0.5 { + delta / (2.0 * l) + } else { + delta / (2.0 - 2.0 * l) + }; + + let h = if delta == 0.0 { + 0.0 + } else if max == r { + ((g - b) / delta).rem_euclid(6.0) / 6.0 + } else if max == g { + ((b - r) / delta + 2.0) / 6.0 + } else { + ((r - g) / delta + 4.0) / 6.0 + }; + + Hsla { + h, + s, + l, + a: color.a, + } + } +} + +impl JsonSchema for Hsla { + fn schema_name() -> Cow<'static, str> { + Rgba::schema_name() + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + Rgba::json_schema(generator) + } +} + +impl Serialize for Hsla { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Rgba::from(*self).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Hsla { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Rgba::deserialize(deserializer)?.into()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub(crate) enum BackgroundTag { + Solid = 0, + LinearGradient = 1, + PatternSlash = 2, + Checkerboard = 3, +} + +/// A color space for color interpolation. +/// +/// References: +/// - +/// - +#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub enum ColorSpace { + #[default] + /// The sRGB color space. + Srgb = 0, + /// The Oklab color space. + Oklab = 1, +} + +impl Display for ColorSpace { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + ColorSpace::Srgb => write!(f, "sRGB"), + ColorSpace::Oklab => write!(f, "Oklab"), + } + } +} + +/// A background color, which can be either a solid color or a linear gradient. +#[derive(Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct Background { + pub(crate) tag: BackgroundTag, + pub(crate) color_space: ColorSpace, + pub(crate) solid: Hsla, + pub(crate) gradient_angle_or_pattern_height: f32, + pub(crate) colors: [LinearColorStop; 2], + /// Padding for alignment for repr(C) layout. + pad: u32, +} + +impl std::fmt::Debug for Background { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self.tag { + BackgroundTag::Solid => write!(f, "Solid({:?})", self.solid), + BackgroundTag::LinearGradient => write!( + f, + "LinearGradient({}, {:?}, {:?})", + self.gradient_angle_or_pattern_height, self.colors[0], self.colors[1] + ), + BackgroundTag::PatternSlash => write!( + f, + "PatternSlash({:?}, {})", + self.solid, self.gradient_angle_or_pattern_height + ), + BackgroundTag::Checkerboard => write!( + f, + "Checkerboard({:?}, {})", + self.solid, self.gradient_angle_or_pattern_height + ), + } + } +} + +impl Eq for Background {} +impl Default for Background { + fn default() -> Self { + Self { + tag: BackgroundTag::Solid, + solid: Hsla::default(), + color_space: ColorSpace::default(), + gradient_angle_or_pattern_height: 0.0, + colors: [LinearColorStop::default(), LinearColorStop::default()], + pad: 0, + } + } +} + +/// Creates a hash pattern background +pub fn pattern_slash(color: impl Into, width: f32, interval: f32) -> Background { + let width_scaled = (width * 255.0) as u32; + let interval_scaled = (interval * 255.0) as u32; + let height = ((width_scaled * 0xFFFF) + interval_scaled) as f32; + + Background { + tag: BackgroundTag::PatternSlash, + solid: color.into(), + gradient_angle_or_pattern_height: height, + ..Default::default() + } +} + +/// Creates a checkerboard pattern background +pub fn checkerboard(color: impl Into, size: f32) -> Background { + Background { + tag: BackgroundTag::Checkerboard, + solid: color.into(), + gradient_angle_or_pattern_height: size, + ..Default::default() + } +} + +/// Creates a solid background color. +pub fn solid_background(color: impl Into) -> Background { + Background { + solid: color.into(), + ..Default::default() + } +} + +/// Creates a LinearGradient background color. +/// +/// The gradient line's angle of direction. A value of `0.` is equivalent to top; increasing values rotate clockwise from there. +/// +/// The `angle` is in degrees value in the range 0.0 to 360.0. +/// +/// +pub fn linear_gradient( + angle: f32, + from: impl Into, + to: impl Into, +) -> Background { + Background { + tag: BackgroundTag::LinearGradient, + gradient_angle_or_pattern_height: angle, + colors: [from.into(), to.into()], + ..Default::default() + } +} + +/// A color stop in a linear gradient. +/// +/// +#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct LinearColorStop { + /// The color of the color stop. + pub color: Hsla, + /// The percentage of the gradient, in the range 0.0 to 1.0. + pub percentage: f32, +} + +/// Creates a new linear color stop. +/// +/// The percentage of the gradient, in the range 0.0 to 1.0. +pub fn linear_color_stop(color: impl Into, percentage: f32) -> LinearColorStop { + LinearColorStop { + color: color.into(), + percentage, + } +} + +impl LinearColorStop { + /// Returns a new color stop with the same color, but with a modified alpha value. + pub fn opacity(&self, factor: f32) -> Self { + Self { + percentage: self.percentage, + color: self.color.opacity(factor), + } + } +} + +impl Background { + /// Returns the solid color if this is a solid background, None otherwise. + pub fn as_solid(&self) -> Option { + if self.tag == BackgroundTag::Solid { + Some(self.solid) + } else { + None + } + } + + /// Use specified color space for color interpolation. + /// + /// + pub fn color_space(mut self, color_space: ColorSpace) -> Self { + self.color_space = color_space; + self + } + + /// Returns a new background color with the same hue, saturation, and lightness, but with a modified alpha value. + pub fn opacity(&self, factor: f32) -> Self { + let mut background = *self; + background.solid = background.solid.opacity(factor); + background.colors = [ + self.colors[0].opacity(factor), + self.colors[1].opacity(factor), + ]; + background + } + + /// Returns whether the background color is transparent. + pub fn is_transparent(&self) -> bool { + match self.tag { + BackgroundTag::Solid => self.solid.is_transparent(), + BackgroundTag::LinearGradient => self.colors.iter().all(|c| c.color.is_transparent()), + BackgroundTag::PatternSlash => self.solid.is_transparent(), + BackgroundTag::Checkerboard => self.solid.is_transparent(), + } + } +} + +impl From for Background { + fn from(value: Hsla) -> Self { + Background { + tag: BackgroundTag::Solid, + solid: value, + ..Default::default() + } + } +} + +impl From for Background { + fn from(value: Rgba) -> Self { + Background { + tag: BackgroundTag::Solid, + solid: Hsla::from(value), + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use super::*; + + #[test] + fn test_deserialize_three_value_hex_to_rgba() { + let actual: Rgba = serde_json::from_value(json!("#f09")).unwrap(); + + assert_eq!(actual, rgba(0xff0099ff)) + } + + #[test] + fn test_deserialize_four_value_hex_to_rgba() { + let actual: Rgba = serde_json::from_value(json!("#f09f")).unwrap(); + + assert_eq!(actual, rgba(0xff0099ff)) + } + + #[test] + fn test_deserialize_six_value_hex_to_rgba() { + let actual: Rgba = serde_json::from_value(json!("#ff0099")).unwrap(); + + assert_eq!(actual, rgba(0xff0099ff)) + } + + #[test] + fn test_deserialize_eight_value_hex_to_rgba() { + let actual: Rgba = serde_json::from_value(json!("#ff0099ff")).unwrap(); + + assert_eq!(actual, rgba(0xff0099ff)) + } + + #[test] + fn test_deserialize_eight_value_hex_with_padding_to_rgba() { + let actual: Rgba = serde_json::from_value(json!(" #f5f5f5ff ")).unwrap(); + + assert_eq!(actual, rgba(0xf5f5f5ff)) + } + + #[test] + fn test_deserialize_eight_value_hex_with_mixed_case_to_rgba() { + let actual: Rgba = serde_json::from_value(json!("#DeAdbEeF")).unwrap(); + + assert_eq!(actual, rgba(0xdeadbeef)) + } + + #[test] + fn test_background_solid() { + let color = Hsla::from(rgba(0xff0099ff)); + let mut background = Background::from(color); + assert_eq!(background.tag, BackgroundTag::Solid); + assert_eq!(background.solid, color); + + assert_eq!(background.opacity(0.5).solid, color.opacity(0.5)); + assert!(!background.is_transparent()); + background.solid = hsla(0.0, 0.0, 0.0, 0.0); + assert!(background.is_transparent()); + } + + #[test] + fn test_background_linear_gradient() { + let from = linear_color_stop(rgba(0xff0099ff), 0.0); + let to = linear_color_stop(rgba(0x00ff99ff), 1.0); + let background = linear_gradient(90.0, from, to); + assert_eq!(background.tag, BackgroundTag::LinearGradient); + assert_eq!(background.colors[0], from); + assert_eq!(background.colors[1], to); + + assert_eq!(background.opacity(0.5).colors[0], from.opacity(0.5)); + assert_eq!(background.opacity(0.5).colors[1], to.opacity(0.5)); + assert!(!background.is_transparent()); + assert!(background.opacity(0.0).is_transparent()); + } + + #[test] + fn test_rgba_alpha() { + let color = Rgba { + r: 0.2, + g: 0.6, + b: 1.0, + a: 0.8, + }; + + assert_eq!(color.alpha(0.25).a, 0.25); + assert_eq!(color.alpha(1.5).a, 1.0); + } + + #[test] + fn test_rgba_opacity() { + let color = Rgba { + r: 0.2, + g: 0.6, + b: 1.0, + a: 0.8, + }; + assert!((color.opacity(0.5).a - 0.4).abs() < 1e-6); + assert_eq!(color.opacity(2.0).a, 0.8); + } +} diff --git a/vendor/gpui-pre/src/colors.rs b/vendor/gpui-pre/src/colors.rs new file mode 100644 index 00000000..ef11ef57 --- /dev/null +++ b/vendor/gpui-pre/src/colors.rs @@ -0,0 +1,122 @@ +use crate::{App, Global, Rgba, Window, WindowAppearance, rgb}; +use std::ops::Deref; +use std::sync::Arc; + +/// The default set of colors for gpui. +/// +/// These are used for styling base components, examples and more. +#[derive(Clone, Debug)] +pub struct Colors { + /// Text color + pub text: Rgba, + /// Selected text color + pub selected_text: Rgba, + /// Background color + pub background: Rgba, + /// Disabled color + pub disabled: Rgba, + /// Selected color + pub selected: Rgba, + /// Border color + pub border: Rgba, + /// Separator color + pub separator: Rgba, + /// Container color + pub container: Rgba, +} + +impl Default for Colors { + fn default() -> Self { + Self::light() + } +} + +impl Colors { + /// Returns the default colors for the given window appearance. + pub fn for_appearance(window: &Window) -> Self { + match window.appearance() { + WindowAppearance::Light | WindowAppearance::VibrantLight => Self::light(), + WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::dark(), + } + } + + /// Returns the default dark colors. + pub fn dark() -> Self { + Self { + text: rgb(0xffffff), + selected_text: rgb(0xffffff), + disabled: rgb(0x565656), + selected: rgb(0x2457ca), + background: rgb(0x222222), + border: rgb(0x000000), + separator: rgb(0xd9d9d9), + container: rgb(0x262626), + } + } + + /// Returns the default light colors. + pub fn light() -> Self { + Self { + text: rgb(0x252525), + selected_text: rgb(0xffffff), + background: rgb(0xffffff), + disabled: rgb(0xb0b0b0), + selected: rgb(0x2a63d9), + border: rgb(0xd9d9d9), + separator: rgb(0xe6e6e6), + container: rgb(0xf4f5f5), + } + } + + /// Get [Colors] from the global state + pub fn get_global(cx: &App) -> &Arc { + &cx.global::().0 + } +} + +/// Get [Colors] from the global state +#[derive(Clone, Debug)] +pub struct GlobalColors(pub Arc); + +impl Deref for GlobalColors { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Global for GlobalColors {} + +/// Implement this trait to allow global [Colors] access via `cx.default_colors()`. +pub trait DefaultColors { + /// Returns the default [`Colors`] + fn default_colors(&self) -> &Arc; +} + +impl DefaultColors for App { + fn default_colors(&self) -> &Arc { + &self.global::().0 + } +} + +/// The appearance of the base GPUI colors, used to style GPUI elements +/// +/// Varies based on the system's current [`WindowAppearance`]. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum DefaultAppearance { + /// Use the set of colors for light appearances. + #[default] + Light, + /// Use the set of colors for dark appearances. + Dark, +} + +impl From for DefaultAppearance { + fn from(appearance: WindowAppearance) -> Self { + match appearance { + WindowAppearance::Light | WindowAppearance::VibrantLight => Self::Light, + WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::Dark, + } + } +} diff --git a/vendor/gpui-pre/src/debug_overlay.rs b/vendor/gpui-pre/src/debug_overlay.rs new file mode 100644 index 00000000..0cca543e --- /dev/null +++ b/vendor/gpui-pre/src/debug_overlay.rs @@ -0,0 +1,428 @@ +//! A developer overlay that paints frame-time statistics directly into the +//! scene, bypassing layout, text, and view invalidation entirely (to avoid +//! infinitely triggering new frames). + +use crate::{ + BorderStyle, Bounds, ContentMask, Corners, Edges, Hsla, Pixels, Quad, ScaledPixels, Scene, + Size, point, rgba, size, transparent_black, +}; +use std::{collections::VecDeque, time::Duration}; + +#[allow(missing_docs)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum DebugFrameOverlayMode { + #[default] + Hidden, + Minimal, + Full, +} + +impl DebugFrameOverlayMode { + /// Returns the next mode in the Hidden → FrameTime → Detailed cycle. + pub fn next(self) -> Self { + match self { + Self::Hidden => Self::Minimal, + Self::Minimal => Self::Full, + Self::Full => Self::Hidden, + } + } +} + +/// The number of most recent draw durations retained for percentile statistics. +const MAX_SAMPLES: usize = 1000; + +const GLYPH_WIDTH: usize = 5; +const GLYPH_HEIGHT: usize = 7; +/// Glyph advance and line advance, in font cells. +const CHAR_ADVANCE: f32 = (GLYPH_WIDTH + 1) as f32; +const LINE_ADVANCE: f32 = (GLYPH_HEIGHT + 2) as f32; +/// Padding between the panel edge and the text, in font cells. +const PANEL_PADDING: f32 = 2.0; +/// Margin between the panel and the window corner, in font cells. +const PANEL_MARGIN: f32 = 4.0; +/// Side of one square font cell, in logical pixels. +const CELL_SIZE: f32 = 2.0; + +fn text_color() -> Hsla { + rgba(0x33ff33ff).into() +} + +fn panel_color() -> Hsla { + rgba(0x000000aa).into() +} + +pub(crate) struct DebugFrameOverlay { + mode: DebugFrameOverlayMode, + draw_durations: VecDeque, + total_frame_count: u64, +} + +impl DebugFrameOverlay { + pub(crate) fn new() -> Self { + Self { + mode: DebugFrameOverlayMode::default(), + draw_durations: VecDeque::new(), + total_frame_count: 0, + } + } + + pub(crate) fn mode(&self) -> DebugFrameOverlayMode { + self.mode + } + + pub(crate) fn set_mode(&mut self, mode: DebugFrameOverlayMode) { + self.mode = mode; + } + + /// Clears the draw-duration samples, restarting the percentile window. + /// The total frame count is left untouched. + pub(crate) fn reset_stats(&mut self) { + self.draw_durations.clear(); + } + + pub(crate) fn is_enabled(&self) -> bool { + self.mode != DebugFrameOverlayMode::Hidden + } + + pub(crate) fn record_frame(&mut self, draw_duration: Duration) { + self.total_frame_count += 1; + if self.draw_durations.len() >= MAX_SAMPLES { + self.draw_durations.pop_front(); + } + self.draw_durations.push_back(draw_duration); + } + + pub(crate) fn paint(&self, scene: &mut Scene, viewport_size: Size, scale_factor: f32) { + if !self.is_enabled() { + return; + } + + let lines = self.lines(); + let max_line_chars = lines.iter().map(|line| line.len()).max().unwrap_or(0); + // Ensure at least one physical pixel per cell so the text stays legible + // at fractional downscale factors. + let cell = (CELL_SIZE * scale_factor).max(1.0); + + let panel_width = cell * (max_line_chars as f32 * CHAR_ADVANCE + 2.0 * PANEL_PADDING); + let panel_height = cell * (lines.len() as f32 * LINE_ADVANCE + 2.0 * PANEL_PADDING); + let viewport = viewport_size.scale(scale_factor); + let panel_left = viewport.width.0 - panel_width - cell * PANEL_MARGIN; + let panel_top = cell * PANEL_MARGIN; + + let content_mask = ContentMask { + bounds: Bounds { + origin: point(ScaledPixels(0.), ScaledPixels(0.)), + size: viewport, + }, + }; + + scene.insert_primitive(solid_quad( + scaled_bounds(panel_left, panel_top, panel_width, panel_height), + &content_mask, + panel_color(), + )); + + let text_color = text_color(); + for (line_index, line) in lines.iter().enumerate() { + let line_top = panel_top + cell * (PANEL_PADDING + line_index as f32 * LINE_ADVANCE); + for (char_index, character) in line.chars().enumerate() { + let Some(rows) = glyph(character) else { + continue; + }; + let glyph_left = + panel_left + cell * (PANEL_PADDING + char_index as f32 * CHAR_ADVANCE); + for (row_index, row) in rows.iter().enumerate() { + let row_top = line_top + cell * row_index as f32; + // Merge horizontal runs of lit cells into single quads. + let mut column = 0; + while column < GLYPH_WIDTH { + if row & (1 << (GLYPH_WIDTH - 1 - column)) == 0 { + column += 1; + continue; + } + let run_start = column; + while column < GLYPH_WIDTH && row & (1 << (GLYPH_WIDTH - 1 - column)) != 0 { + column += 1; + } + scene.insert_primitive(solid_quad( + scaled_bounds( + glyph_left + cell * run_start as f32, + row_top, + cell * (column - run_start) as f32, + cell, + ), + &content_mask, + text_color, + )); + } + } + } + } + } + + fn lines(&self) -> Vec { + let current = self.draw_durations.back().copied(); + match self.mode { + DebugFrameOverlayMode::Hidden => Vec::new(), + DebugFrameOverlayMode::Minimal => vec![format_ms(current)], + DebugFrameOverlayMode::Full => { + let mut sorted: Vec = self.draw_durations.iter().copied().collect(); + sorted.sort_unstable(); + let percentile = |numerator: usize| { + (!sorted.is_empty()).then(|| sorted[(sorted.len() - 1) * numerator / 100]) + }; + // Past five digits the count would break the column + // alignment, so it saturates instead. + let frame_count = if self.total_frame_count > 99_999 { + "LOTS".to_string() + } else { + self.total_frame_count.to_string() + }; + // Labels are padded to a uniform width so the fixed-width + // durations start in the same column on every line. + vec![ + format!("CUR {}", format_ms(current)), + format!("1% {}", format_ms(percentile(99))), + format!("10% {}", format_ms(percentile(90))), + format!("MAX {}", format_ms(sorted.last().copied())), + format!("FRAMES {frame_count:>5}"), + ] + } + } + } +} + +/// Formats as `abc.d MS`, right-aligned in room for three integer digits and +/// one decimal (padded with spaces, not zeroes), so stacked readouts align. +fn format_ms(duration: Option) -> String { + match duration { + Some(duration) => { + let ms = duration.as_secs_f32() * 1000.0; + format!("{ms:>5.1} MS") + } + None => " -- MS".into(), + } +} + +fn scaled_bounds(left: f32, top: f32, width: f32, height: f32) -> Bounds { + Bounds { + origin: point(ScaledPixels(left), ScaledPixels(top)), + size: size(ScaledPixels(width), ScaledPixels(height)), + } +} + +fn solid_quad( + bounds: Bounds, + content_mask: &ContentMask, + color: Hsla, +) -> Quad { + Quad { + order: 0, + border_style: BorderStyle::Solid, + bounds, + content_mask: *content_mask, + background: color.into(), + border_color: transparent_black(), + corner_radii: Corners::default(), + border_widths: Edges::default(), + } +} + +/// Returns the 5x7 bitmap for the given character, one `u8` of column bits per +/// row with the most significant of the 5 bits leftmost. Only the characters +/// used by the overlay's readouts are defined. +fn glyph(character: char) -> Option<[u8; GLYPH_HEIGHT]> { + Some(match character { + '0' => [ + 0b01110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b01110, + ], + '1' => [ + 0b00100, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110, + ], + '2' => [ + 0b01110, 0b10001, 0b00001, 0b00010, 0b00100, 0b01000, 0b11111, + ], + '3' => [ + 0b11111, 0b00010, 0b00100, 0b00010, 0b00001, 0b10001, 0b01110, + ], + '4' => [ + 0b00010, 0b00110, 0b01010, 0b10010, 0b11111, 0b00010, 0b00010, + ], + '5' => [ + 0b11111, 0b10000, 0b11110, 0b00001, 0b00001, 0b10001, 0b01110, + ], + '6' => [ + 0b00110, 0b01000, 0b10000, 0b11110, 0b10001, 0b10001, 0b01110, + ], + '7' => [ + 0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b01000, 0b01000, + ], + '8' => [ + 0b01110, 0b10001, 0b10001, 0b01110, 0b10001, 0b10001, 0b01110, + ], + '9' => [ + 0b01110, 0b10001, 0b10001, 0b01111, 0b00001, 0b00010, 0b01100, + ], + '.' => [ + 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01100, 0b01100, + ], + '-' => [ + 0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000, 0b00000, + ], + '%' => [ + 0b11001, 0b11001, 0b00010, 0b00100, 0b01000, 0b10011, 0b10011, + ], + 'A' => [ + 0b01110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001, + ], + 'C' => [ + 0b01110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b01110, + ], + 'E' => [ + 0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111, + ], + 'F' => [ + 0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000, + ], + 'L' => [ + 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111, + ], + 'M' => [ + 0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001, 0b10001, + ], + 'N' => [ + 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001, 0b10001, + ], + 'O' => [ + 0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110, + ], + 'R' => [ + 0b11110, 0b10001, 0b10001, 0b11110, 0b10100, 0b10010, 0b10001, + ], + 'S' => [ + 0b01111, 0b10000, 0b10000, 0b01110, 0b00001, 0b00001, 0b11110, + ], + 'T' => [ + 0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, + ], + 'U' => [ + 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110, + ], + 'X' => [ + 0b10001, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001, 0b10001, + ], + _ => return None, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Every character the readouts can produce must have a glyph, or it + /// would silently render as blank space. + #[test] + fn all_rendered_characters_have_glyphs() { + let mut overlay = DebugFrameOverlay::new(); + overlay.set_mode(DebugFrameOverlayMode::Full); + + let mut lines = Vec::new(); + for duration in [ + Duration::ZERO, + Duration::from_micros(1), + Duration::from_micros(8_333), + Duration::from_millis(123), + Duration::from_secs(2), + ] { + overlay.record_frame(duration); + lines.extend(overlay.lines()); + } + // Counts beyond five digits render as "LOTS". + overlay.total_frame_count = 100_000; + lines.extend(overlay.lines()); + + // An enabled overlay with no samples yet renders placeholders. + let mut empty = DebugFrameOverlay::new(); + empty.set_mode(DebugFrameOverlayMode::Full); + lines.extend(empty.lines()); + + for line in lines { + for character in line.chars() { + assert!( + character == ' ' || glyph(character).is_some(), + "no glyph for {character:?} in line {line:?}" + ); + } + } + } + + #[test] + fn percentile_lows_are_reported_as_times() { + let mut overlay = DebugFrameOverlay::new(); + overlay.set_mode(DebugFrameOverlayMode::Full); + for milliseconds in 1..=100 { + overlay.record_frame(Duration::from_millis(milliseconds)); + } + let lines = overlay.lines(); + assert_eq!(lines[0], "CUR 100.0 MS"); + assert_eq!(lines[1], "1% 99.0 MS"); + assert_eq!(lines[2], "10% 90.0 MS"); + assert_eq!(lines[3], "MAX 100.0 MS"); + assert_eq!(lines[4], "FRAMES 100"); + } + + #[test] + fn reset_clears_durations_but_keeps_frame_count() { + let mut overlay = DebugFrameOverlay::new(); + overlay.set_mode(DebugFrameOverlayMode::Full); + for _ in 0..10 { + overlay.record_frame(Duration::from_millis(10)); + } + overlay.reset_stats(); + let lines = overlay.lines(); + assert_eq!(lines[0], "CUR -- MS"); + assert_eq!(lines[3], "MAX -- MS"); + assert_eq!(lines[4], "FRAMES 10"); + overlay.record_frame(Duration::from_millis(20)); + let lines = overlay.lines(); + assert_eq!(lines[0], "CUR 20.0 MS"); + assert_eq!(lines[4], "FRAMES 11"); + } + + #[test] + fn frame_count_accumulates_across_mode_changes() { + let mut overlay = DebugFrameOverlay::new(); + for _ in 0..3 { + overlay.record_frame(Duration::from_millis(10)); + } + overlay.set_mode(DebugFrameOverlayMode::Minimal); + assert_eq!(overlay.lines(), vec![" 10.0 MS".to_string()]); + overlay.set_mode(DebugFrameOverlayMode::Full); + overlay.record_frame(Duration::from_millis(10)); + assert_eq!(overlay.lines()[4], "FRAMES 4"); + overlay.set_mode(DebugFrameOverlayMode::Hidden); + overlay.record_frame(Duration::from_millis(10)); + overlay.set_mode(DebugFrameOverlayMode::Full); + assert_eq!(overlay.lines()[4], "FRAMES 5"); + } + + #[test] + fn frame_count_is_right_aligned_and_saturates() { + let mut overlay = DebugFrameOverlay::new(); + overlay.set_mode(DebugFrameOverlayMode::Full); + overlay.record_frame(Duration::from_millis(10)); + assert_eq!(overlay.lines()[4], "FRAMES 1"); + overlay.total_frame_count = 99_999; + assert_eq!(overlay.lines()[4], "FRAMES 99999"); + overlay.total_frame_count = 100_000; + assert_eq!(overlay.lines()[4], "FRAMES LOTS"); + } + + #[test] + fn toggling_on_shows_previous_frame_immediately() { + let mut overlay = DebugFrameOverlay::new(); + overlay.record_frame(Duration::from_millis(10)); + overlay.set_mode(DebugFrameOverlayMode::Minimal); + assert_eq!(overlay.lines(), vec![" 10.0 MS".to_string()]); + } +} diff --git a/vendor/gpui-pre/src/element.rs b/vendor/gpui-pre/src/element.rs new file mode 100644 index 00000000..d6556258 --- /dev/null +++ b/vendor/gpui-pre/src/element.rs @@ -0,0 +1,813 @@ +//! Elements are the workhorses of GPUI. They are responsible for laying out and painting all of +//! the contents of a window. Elements form a tree and are laid out according to the web layout +//! standards as implemented by [taffy](https://github.com/DioxusLabs/taffy). Most of the time, +//! you won't need to interact with this module or these APIs directly. Elements provide their +//! own APIs and GPUI, or other element implementation, uses the APIs in this module to convert +//! that element tree into the pixels you see on the screen. +//! +//! # Element Basics +//! +//! Elements are constructed by calling [`Render::render()`] on the root view of the window, +//! which recursively constructs the element tree from the current state of the application,. +//! These elements are then laid out by Taffy, and painted to the screen according to their own +//! implementation of [`Element::paint()`]. Before the start of the next frame, the entire element +//! tree and any callbacks they have registered with GPUI are dropped and the process repeats. +//! +//! But some state is too simple and voluminous to store in every view that needs it, e.g. +//! whether a hover has been started or not. For this, GPUI provides the [`Element::PrepaintState`], associated type. +//! +//! # Implementing your own elements +//! +//! Elements are intended to be the low level, imperative API to GPUI. They are responsible for upholding, +//! or breaking, GPUI's features as they deem necessary. As an example, most GPUI elements are expected +//! to stay in the bounds that their parent element gives them. But with [`Window::with_content_mask`], +//! you can ignore this restriction and paint anywhere inside of the window's bounds. This is useful for overlays +//! and popups and anything else that shows up 'on top' of other elements. +//! With great power, comes great responsibility. +//! +//! However, most of the time, you won't need to implement your own elements. GPUI provides a number of +//! elements that should cover most common use cases out of the box and it's recommended that you use those +//! to construct `components`, using the [`RenderOnce`] trait and the `#[derive(IntoElement)]` macro. Only implement +//! elements when you need to take manual control of the layout and painting process, such as when using +//! your own custom layout algorithm or rendering a code editor. + +#[cfg(any(feature = "inspector", debug_assertions))] +use crate::InspectorElementPath; +use crate::{ + A11ySubtreeBuilder, App, ArenaBox, AvailableSpace, Bounds, Context, DispatchNodeId, ElementId, + FocusHandle, InspectorElementId, LayoutId, Pixels, Point, Size, Style, Window, + util::FluentBuilder, window::with_element_arena, +}; +use derive_more::{Deref, DerefMut}; +use std::{ + any::Any, + fmt::{self, Debug, Display}, + mem, panic, + sync::Arc, +}; + +/// Implemented by types that participate in laying out and painting the contents of a window. +/// Elements form a tree and are laid out according to web-based layout rules, as implemented by Taffy. +/// You can create custom elements by implementing this trait, see the module-level documentation +/// for more details. +pub trait Element: 'static + IntoElement { + /// The type of state returned from [`Element::request_layout`]. A mutable reference to this state is subsequently + /// provided to [`Element::prepaint`] and [`Element::paint`]. + type RequestLayoutState: 'static; + + /// The type of state returned from [`Element::prepaint`]. A mutable reference to this state is subsequently + /// provided to [`Element::paint`]. + type PrepaintState: 'static; + + /// If this element has a unique identifier, return it here. This is used to track elements across frames, and + /// will cause a GlobalElementId to be passed to the request_layout, prepaint, and paint methods. + /// + /// The global id can in turn be used to access state that's connected to an element with the same id across + /// frames. This id must be unique among children of the first containing element with an id. + fn id(&self) -> Option; + + /// Source location where this element was constructed, used to disambiguate elements in the + /// inspector and navigate to their source code. + fn source_location(&self) -> Option<&'static panic::Location<'static>>; + + /// Before an element can be painted, we need to know where it's going to be and how big it is. + /// Use this method to request a layout from Taffy and initialize the element's state. + fn request_layout( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState); + + /// After laying out an element, we need to commit its bounds to the current frame for hitbox + /// purposes. The state argument is the same state that was returned from [`Element::request_layout()`]. + fn prepaint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState; + + /// Once layout has been completed, this method will be called to paint the element to the screen. + /// The state argument is the same state that was returned from [`Element::request_layout()`]. + fn paint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ); + + /// Returns the accessible role for this element, if any. + /// Elements that return `None` are not included in the accessibility tree. + /// + /// Note: inclusion in accessibility tree requires non-`None` [`id`][Element::id]. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + fn a11y_role(&self) -> Option { + None + } + + /// Write accessibility properties to the given node. + /// Called only when `a11y_role()` returns `Some`. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + fn write_a11y_info(&self, _node: &mut accesskit::Node) {} + + /// Add synthetic child nodes to an [`Element`] that has an + /// [`.id()`][Element::id] and a [`.role()`][Element::a11y_role]. + /// + /// Some elements may want to inject accessibility nodes that do not + /// correspond to any GPUI element. For example, a custom text field element + /// may want to inject synthetic child nodes for the text content. + /// + /// See [Synthetic children](crate::_accessibility#synthetic-children) in + /// the accessibility guide for more detail. + fn a11y_synthetic_children( + &mut self, + _prepaint: &mut Self::PrepaintState, + _builder: &mut A11ySubtreeBuilder, + ) { + } + + /// Convert this element into a dynamically-typed [`AnyElement`]. + fn into_any(self) -> AnyElement { + AnyElement::new(self) + } +} + +/// Implemented by any type that can be converted into an element. +pub trait IntoElement: Sized { + /// The specific type of element into which the implementing type is converted. + /// Useful for converting other types into elements automatically, like Strings + type Element: Element; + + /// Convert self into a type that implements [`Element`]. + fn into_element(self) -> Self::Element; + + /// Convert self into a dynamically-typed [`AnyElement`]. + fn into_any_element(self) -> AnyElement { + self.into_element().into_any() + } +} + +impl FluentBuilder for T {} + +/// An object that can be drawn to the screen. This is the trait that distinguishes "views" from +/// other entities. Views are `Entity`'s which `impl Render` and drawn to the screen. +pub trait Render: 'static + Sized { + /// Render this view into an element tree. + fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement; +} + +impl Render for Empty { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + Empty + } +} + +/// You can derive [`IntoElement`] on any type that implements this trait. +/// It is used to construct reusable `components` out of plain data. Think of +/// components as a recipe for a certain pattern of elements. RenderOnce allows +/// you to invoke this pattern, without breaking the fluent builder pattern of +/// the element APIs. +pub trait RenderOnce: 'static { + /// Render this component into an element tree. Note that this method + /// takes ownership of self, as compared to [`Render::render()`] method + /// which takes a mutable reference. + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement; +} + +/// This is a helper trait to provide a uniform interface for constructing elements that +/// can accept any number of any kind of child elements +pub trait ParentElement { + /// Extend this element's children with the given child elements. + fn extend(&mut self, elements: impl IntoIterator); + + /// Add a single child element to this element. + fn child(mut self, child: impl IntoElement) -> Self + where + Self: Sized, + { + self.extend(std::iter::once(child.into_any_element())); + self + } + + /// Add multiple child elements to this element. + fn children(mut self, children: impl IntoIterator) -> Self + where + Self: Sized, + { + self.extend(children.into_iter().map(|child| child.into_any_element())); + self + } +} + +/// A globally unique identifier for an element, used to track state across frames. +#[derive(Deref, DerefMut, Clone, Default, Debug, Eq, PartialEq, Hash)] +pub struct GlobalElementId(pub(crate) Arc<[ElementId]>); + +impl Display for GlobalElementId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, element_id) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ".")?; + } + write!(f, "{}", element_id)?; + } + Ok(()) + } +} + +impl GlobalElementId { + pub(crate) fn accesskit_node_id(&self) -> accesskit::NodeId { + use std::hash::{Hash, Hasher}; + let mut hasher = std::hash::DefaultHasher::default(); + self.hash(&mut hasher); + accesskit::NodeId(hasher.finish()) + } +} + +trait ElementObject { + fn inner_element(&mut self) -> &mut dyn Any; + + fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId; + + fn prepaint(&mut self, window: &mut Window, cx: &mut App); + + fn paint(&mut self, window: &mut Window, cx: &mut App); + + fn layout_as_root( + &mut self, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) -> Size; +} + +/// A wrapper around an implementer of [`Element`] that allows it to be drawn in a window. +pub struct Drawable { + /// The drawn element. + pub element: E, + phase: ElementDrawPhase, +} + +#[derive(Default)] +enum ElementDrawPhase { + #[default] + Start, + RequestLayout { + layout_id: LayoutId, + global_id: Option, + inspector_id: Option, + request_layout: RequestLayoutState, + }, + LayoutComputed { + layout_id: LayoutId, + global_id: Option, + inspector_id: Option, + available_space: Size, + request_layout: RequestLayoutState, + }, + Prepaint { + node_id: DispatchNodeId, + global_id: Option, + inspector_id: Option, + bounds: Bounds, + request_layout: RequestLayoutState, + prepaint: PrepaintState, + }, + Painted, +} + +/// A wrapper around an implementer of [`Element`] that allows it to be drawn in a window. +impl Drawable { + pub(crate) fn new(element: E) -> Self { + Drawable { + element, + phase: ElementDrawPhase::Start, + } + } + + fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId { + match mem::take(&mut self.phase) { + ElementDrawPhase::Start => { + let global_id = self + .element + .id() + .map(|element_id| prepare_element_id(element_id, window)); + + let inspector_id; + #[cfg(any(feature = "inspector", debug_assertions))] + { + inspector_id = if window.inspector_enabled() { + self.element + .source_location() + .map(|source| prepare_inspector_id(source, window)) + } else { + None + }; + } + #[cfg(not(any(feature = "inspector", debug_assertions)))] + { + inspector_id = None; + } + + let (layout_id, request_layout) = self.element.request_layout( + global_id.as_ref(), + inspector_id.as_ref(), + window, + cx, + ); + + if global_id.is_some() { + window.element_id_stack.pop(); + } + + self.phase = ElementDrawPhase::RequestLayout { + layout_id, + global_id, + inspector_id, + request_layout, + }; + layout_id + } + _ => panic!("must call request_layout only once"), + } + } + + pub(crate) fn prepaint(&mut self, window: &mut Window, cx: &mut App) { + match mem::take(&mut self.phase) { + ElementDrawPhase::RequestLayout { + layout_id, + global_id, + inspector_id, + mut request_layout, + } + | ElementDrawPhase::LayoutComputed { + layout_id, + global_id, + inspector_id, + mut request_layout, + .. + } => { + if let Some(element_id) = self.element.id() { + window.element_id_stack.push(element_id); + debug_assert_eq!(&*global_id.as_ref().unwrap().0, &*window.element_id_stack); + } + + let bounds = window.layout_bounds(layout_id); + let mut pushed_a11y_node = false; + if window.a11y.is_active() { + if let Some(global_id) = global_id.as_ref() { + if let Some(role) = self.element.a11y_role() { + let node_id = global_id.accesskit_node_id(); + let mut node = accesskit::Node::new(role); + let scale = window.scale_factor(); + node.set_bounds(accesskit::Rect { + x0: (bounds.origin.x.0 * scale) as f64, + y0: (bounds.origin.y.0 * scale) as f64, + x1: ((bounds.origin.x.0 + bounds.size.width.0) * scale) as f64, + y1: ((bounds.origin.y.0 + bounds.size.height.0) * scale) as f64, + }); + self.element.write_a11y_info(&mut node); + window.a11y.node_bounds.insert(node_id, bounds); + pushed_a11y_node = window.a11y.nodes.push(node_id, node); + #[cfg(debug_assertions)] + if pushed_a11y_node { + let view = window + .a11y + .view_type_names + .get(&window.current_view()) + .copied(); + let source_location = self.element.source_location(); + window.a11y.nodes.record_node_info( + node_id, + crate::window::a11y::debug::NodeDebugInfo { + synthetic: false, + view, + element_id: global_id.0.last().map(|id| format!("{id:?}")), + source_location, + }, + ); + } + } + } + } + + let node_id = window.next_frame.dispatch_tree.push_node(); + let mut prepaint = self.element.prepaint( + global_id.as_ref(), + inspector_id.as_ref(), + bounds, + &mut request_layout, + window, + cx, + ); + window.next_frame.dispatch_tree.pop_node(); + + if pushed_a11y_node { + if let Some(global_id) = global_id.as_ref() { + #[cfg(debug_assertions)] + let creator = crate::window::a11y::debug::NodeCreator { + view: window + .a11y + .view_type_names + .get(&window.current_view()) + .copied(), + element_id: global_id.0.last().map(|id| format!("{id:?}")), + source_location: self.element.source_location(), + }; + let mut builder = A11ySubtreeBuilder::new( + global_id.accesskit_node_id(), + &mut window.a11y.nodes, + ); + #[cfg(debug_assertions)] + { + builder = builder.with_creator(creator); + } + self.element + .a11y_synthetic_children(&mut prepaint, &mut builder); + } + window.a11y.nodes.pop(); + } + + if global_id.is_some() { + window.element_id_stack.pop(); + } + + self.phase = ElementDrawPhase::Prepaint { + node_id, + global_id, + inspector_id, + bounds, + request_layout, + prepaint, + }; + } + _ => panic!("must call request_layout before prepaint"), + } + } + + pub(crate) fn paint( + &mut self, + window: &mut Window, + cx: &mut App, + ) -> (E::RequestLayoutState, E::PrepaintState) { + match mem::take(&mut self.phase) { + ElementDrawPhase::Prepaint { + node_id, + global_id, + inspector_id, + bounds, + mut request_layout, + mut prepaint, + .. + } => { + if let Some(element_id) = self.element.id() { + window.element_id_stack.push(element_id); + debug_assert_eq!(&*global_id.as_ref().unwrap().0, &*window.element_id_stack); + } + + window.next_frame.dispatch_tree.set_active_node(node_id); + self.element.paint( + global_id.as_ref(), + inspector_id.as_ref(), + bounds, + &mut request_layout, + &mut prepaint, + window, + cx, + ); + + if global_id.is_some() { + window.element_id_stack.pop(); + } + + self.phase = ElementDrawPhase::Painted; + (request_layout, prepaint) + } + _ => panic!("must call prepaint before paint"), + } + } + + pub(crate) fn layout_as_root( + &mut self, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) -> Size { + if matches!(&self.phase, ElementDrawPhase::Start) { + self.request_layout(window, cx); + } + + let layout_id = match mem::take(&mut self.phase) { + ElementDrawPhase::RequestLayout { + layout_id, + global_id, + inspector_id, + request_layout, + } => { + window.compute_layout(layout_id, available_space, cx); + self.phase = ElementDrawPhase::LayoutComputed { + layout_id, + global_id, + inspector_id, + available_space, + request_layout, + }; + layout_id + } + ElementDrawPhase::LayoutComputed { + layout_id, + global_id, + inspector_id, + available_space: prev_available_space, + request_layout, + } => { + if available_space != prev_available_space { + window.compute_layout(layout_id, available_space, cx); + } + self.phase = ElementDrawPhase::LayoutComputed { + layout_id, + global_id, + inspector_id, + available_space, + request_layout, + }; + layout_id + } + _ => panic!("cannot measure after painting"), + }; + + window.layout_bounds(layout_id).size + } +} + +impl ElementObject for Drawable +where + E: Element, + E::RequestLayoutState: 'static, +{ + fn inner_element(&mut self) -> &mut dyn Any { + &mut self.element + } + + #[inline] + fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId { + Drawable::request_layout(self, window, cx) + } + + #[inline] + fn prepaint(&mut self, window: &mut Window, cx: &mut App) { + Drawable::prepaint(self, window, cx); + } + + #[inline] + fn paint(&mut self, window: &mut Window, cx: &mut App) { + Drawable::paint(self, window, cx); + } + + #[inline] + fn layout_as_root( + &mut self, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) -> Size { + Drawable::layout_as_root(self, available_space, window, cx) + } +} + +/// A dynamically typed element that can be used to store any element type. +pub struct AnyElement(ArenaBox); + +impl AnyElement { + pub(crate) fn new(element: E) -> Self + where + E: 'static + Element, + E::RequestLayoutState: Any, + { + let element = with_element_arena(|arena| arena.alloc(|| Drawable::new(element))) + .map(|element| element as &mut dyn ElementObject); + AnyElement(element) + } + + /// Attempt to downcast a reference to the boxed element to a specific type. + pub fn downcast_mut(&mut self) -> Option<&mut T> { + self.0.inner_element().downcast_mut::() + } + + /// Request the layout ID of the element stored in this `AnyElement`. + /// Used for laying out child elements in a parent element. + pub fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId { + self.0.request_layout(window, cx) + } + + /// Prepares the element to be painted by storing its bounds, giving it a chance to draw hitboxes and + /// request autoscroll before the final paint pass is confirmed. + pub fn prepaint(&mut self, window: &mut Window, cx: &mut App) -> Option { + let focus_assigned = window.next_frame.focus.is_some(); + + self.0.prepaint(window, cx); + + if !focus_assigned && let Some(focus_id) = window.next_frame.focus { + return FocusHandle::for_id(focus_id, &cx.focus_handles); + } + + None + } + + /// Paints the element stored in this `AnyElement`. + pub fn paint(&mut self, window: &mut Window, cx: &mut App) { + self.0.paint(window, cx); + } + + /// Performs layout for this element within the given available space and returns its size. + pub fn layout_as_root( + &mut self, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) -> Size { + self.0.layout_as_root(available_space, window, cx) + } + + /// Prepaints this element at the given absolute origin. + /// If any element in the subtree beneath this element is focused, its FocusHandle is returned. + pub fn prepaint_at( + &mut self, + origin: Point, + window: &mut Window, + cx: &mut App, + ) -> Option { + window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx)) + } + + /// Performs layout on this element in the available space, then prepaints it at the given absolute origin. + /// If any element in the subtree beneath this element is focused, its FocusHandle is returned. + pub fn prepaint_as_root( + &mut self, + origin: Point, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) -> Option { + self.layout_as_root(available_space, window, cx); + window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx)) + } +} + +impl Element for AnyElement { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let layout_id = self.request_layout(window, cx); + (layout_id, ()) + } + + fn prepaint( + &mut self, + _: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) { + self.prepaint(window, cx); + } + + fn paint( + &mut self, + _: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + self.paint(window, cx); + } +} + +impl IntoElement for AnyElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } + + fn into_any_element(self) -> AnyElement { + self + } +} + +/// The empty element, which renders nothing. +pub struct Empty; + +impl IntoElement for Empty { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Element for Empty { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + ( + window.request_layout( + Style { + display: crate::Display::None, + ..Default::default() + }, + None, + cx, + ), + (), + ) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _state: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) { + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + _window: &mut Window, + _cx: &mut App, + ) { + } +} + +#[inline(never)] +fn prepare_element_id(element_id: ElementId, window: &mut Window) -> GlobalElementId { + window.element_id_stack.push(element_id); + GlobalElementId(Arc::from(&*window.element_id_stack)) +} + +#[cfg(any(feature = "inspector", debug_assertions))] +#[inline(never)] +fn prepare_inspector_id( + source: &'static panic::Location<'static>, + window: &mut Window, +) -> InspectorElementId { + let path = InspectorElementPath { + global_id: GlobalElementId(Arc::from(&*window.element_id_stack)), + source_location: source, + }; + window.build_inspector_element_id(path) +} diff --git a/vendor/gpui-pre/src/elements/anchored.rs b/vendor/gpui-pre/src/elements/anchored.rs new file mode 100644 index 00000000..29260061 --- /dev/null +++ b/vendor/gpui-pre/src/elements/anchored.rs @@ -0,0 +1,398 @@ +use smallvec::SmallVec; + +use crate::{ + Anchor, AnyElement, App, Axis, Bounds, Display, Edges, Element, GlobalElementId, + InspectorElementId, IntoElement, LayoutId, ParentElement, Pixels, Point, Position, Size, Style, + Window, point, px, +}; + +/// The state that the anchored element element uses to track its children. +pub struct AnchoredState { + child_layout_ids: SmallVec<[LayoutId; 4]>, +} + +/// An anchored element that can be used to display UI that +/// will avoid overflowing the window bounds. +pub struct Anchored { + children: SmallVec<[AnyElement; 2]>, + anchor: Anchor, + fit_mode: AnchoredFitMode, + anchor_position: Option>, + position_mode: AnchoredPositionMode, + offset: Option>, +} + +/// anchored gives you an element that will avoid overflowing the window bounds. +/// Its children should have no margin to avoid measurement issues. +pub fn anchored() -> Anchored { + Anchored { + children: SmallVec::new(), + anchor: Anchor::TopLeft, + fit_mode: AnchoredFitMode::SwitchAnchor, + anchor_position: None, + position_mode: AnchoredPositionMode::Window, + offset: None, + } +} + +impl Anchored { + /// Sets which corner of the anchored element should be anchored to the current position. + pub fn anchor(mut self, anchor: Anchor) -> Self { + self.anchor = anchor; + self + } + + /// Sets the position in window coordinates + /// (otherwise the location the anchored element is rendered is used) + pub fn position(mut self, anchor: Point) -> Self { + self.anchor_position = Some(anchor); + self + } + + /// Offset the final position by this amount. + /// Useful when you want to anchor to an element but offset from it, such as in PopoverMenu. + pub fn offset(mut self, offset: Point) -> Self { + self.offset = Some(offset); + self + } + + /// Sets the position mode for this anchored element. Local will have this + /// interpret its [`Anchored::position`] as relative to the parent element. + /// While Window will have it interpret the position as relative to the window. + pub fn position_mode(mut self, mode: AnchoredPositionMode) -> Self { + self.position_mode = mode; + self + } + + /// Snap to window edge instead of switching anchor corner when an overflow would occur. + pub fn snap_to_window(mut self) -> Self { + self.fit_mode = AnchoredFitMode::SnapToWindow; + self + } + + /// Snap to window edge and leave some margins. + pub fn snap_to_window_with_margin(mut self, edges: impl Into>) -> Self { + self.fit_mode = AnchoredFitMode::SnapToWindowWithMargin(edges.into()); + self + } +} + +impl ParentElement for Anchored { + fn extend(&mut self, elements: impl IntoIterator) { + self.children.extend(elements) + } +} + +impl Element for Anchored { + type RequestLayoutState = AnchoredState; + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (crate::LayoutId, Self::RequestLayoutState) { + let child_layout_ids = self + .children + .iter_mut() + .map(|child| child.request_layout(window, cx)) + .collect::>(); + + let anchored_style = Style { + position: Position::Absolute, + display: Display::Flex, + ..Style::default() + }; + + let layout_id = window.request_layout(anchored_style, child_layout_ids.iter().copied(), cx); + + (layout_id, AnchoredState { child_layout_ids }) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) { + if request_layout.child_layout_ids.is_empty() { + return; + } + + let children_bounds = request_layout + .child_layout_ids + .iter() + .map(|id| window.layout_bounds(*id)) + .reduce(|acc, bounds| acc.union(&bounds)) + .unwrap(); + + let (origin, mut desired) = self.position_mode.get_position_and_bounds( + self.anchor_position, + self.anchor, + children_bounds.size, + bounds, + self.offset, + ); + + let limits = Bounds { + origin: Point::default(), + size: window.viewport_size(), + }; + + if self.fit_mode == AnchoredFitMode::SwitchAnchor { + let mut anchor = self.anchor; + + if desired.left() < limits.left() || desired.right() > limits.right() { + let switched = Bounds::from_anchor_and_size( + anchor.other_side_along(Axis::Horizontal), + origin, + children_bounds.size, + ); + if !(switched.left() < limits.left() || switched.right() > limits.right()) { + anchor = anchor.other_side_along(Axis::Horizontal); + desired = switched + } + } + + if desired.top() < limits.top() || desired.bottom() > limits.bottom() { + let switched = Bounds::from_anchor_and_size( + anchor.other_side_along(Axis::Vertical), + origin, + children_bounds.size, + ); + if !(switched.top() < limits.top() || switched.bottom() > limits.bottom()) { + desired = switched; + } + } + } + + let client_inset = window.client_inset.unwrap_or(px(0.)); + let edges = match self.fit_mode { + AnchoredFitMode::SnapToWindowWithMargin(edges) => edges, + _ => Edges::default(), + } + .map(|edge| *edge + client_inset); + + // Snap the horizontal edges of the anchored element to the horizontal edges of the window if + // its horizontal bounds overflow, aligning to the left if it is wider than the limits. + if desired.right() > limits.right() { + desired.origin.x -= desired.right() - limits.right() + edges.right; + } + if desired.left() < limits.left() { + desired.origin.x = limits.origin.x + edges.left; + } + + // Snap the vertical edges of the anchored element to the vertical edges of the window if + // its vertical bounds overflow, aligning to the top if it is taller than the limits. + if desired.bottom() > limits.bottom() { + desired.origin.y -= desired.bottom() - limits.bottom() + edges.bottom; + } + if desired.top() < limits.top() { + desired.origin.y = limits.origin.y + edges.top; + } + + let offset = desired.origin - bounds.origin; + let offset = point(offset.x.round(), offset.y.round()); + + window.with_element_offset(offset, |window| { + for child in &mut self.children { + child.prepaint(window, cx); + } + }) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: crate::Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + for child in &mut self.children { + child.paint(window, cx); + } + } +} + +impl IntoElement for Anchored { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +/// Which algorithm to use when fitting the anchored element to be inside the window. +#[derive(Copy, Clone, PartialEq)] +pub enum AnchoredFitMode { + /// Snap the anchored element to the window edge. + SnapToWindow, + /// Snap to window edge and leave some margins. + SnapToWindowWithMargin(Edges), + /// Switch which corner anchor this anchored element is attached to. + SwitchAnchor, +} + +/// Which algorithm to use when positioning the anchored element. +#[derive(Copy, Clone, PartialEq)] +pub enum AnchoredPositionMode { + /// Position the anchored element relative to the window. + Window, + /// Position the anchored element relative to its parent. + Local, +} + +impl AnchoredPositionMode { + fn get_position_and_bounds( + &self, + anchor_position: Option>, + anchor: Anchor, + size: Size, + bounds: Bounds, + offset: Option>, + ) -> (Point, Bounds) { + let offset = offset.unwrap_or_default(); + + match self { + AnchoredPositionMode::Window => { + let anchor_position = anchor_position.unwrap_or(bounds.origin); + let bounds = Bounds::from_anchor_and_size(anchor, anchor_position + offset, size); + (anchor_position, bounds) + } + AnchoredPositionMode::Local => { + let anchor_position = anchor_position.unwrap_or_default(); + let bounds = Bounds::from_anchor_and_size( + anchor, + bounds.origin + anchor_position + offset, + size, + ); + (anchor_position, bounds) + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::{ + Context, Pixels, PlatformInput, Point, TestAppContext, Window, deferred, div, point, + prelude::*, px, size, + }; + + struct AnchoredTestView { + position: Point, + } + + impl Render for AnchoredTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().size_full().child( + div() + .id("scroll-container") + .overflow_y_scroll() + .size_full() + .child(div().h(px(2000.)).w_full()) + .child( + deferred( + super::anchored() + .snap_to_window() + .position(self.position) + .child( + div() + .id("menu") + .debug_selector(|| "MENU".into()) + .w(px(200.)) + .h(px(300.)), + ), + ) + .with_priority(1), + ), + ) + } + } + + #[gpui::test] + fn test_anchored_position_without_scroll(cx: &mut TestAppContext) { + let window = cx.open_window(size(px(800.), px(600.)), |_, _| AnchoredTestView { + position: point(px(100.), px(100.)), + }); + + cx.run_until_parked(); + + let menu_bounds = window + .update(cx, |_, window, _| { + window.rendered_frame.debug_bounds.get("MENU").copied() + }) + .unwrap() + .expect("MENU debug bounds not found"); + + assert_eq!(menu_bounds.origin, point(px(100.), px(100.))); + assert_eq!(menu_bounds.size, size(px(200.), px(300.))); + } + + #[gpui::test] + fn test_anchored_position_when_scrolled(cx: &mut TestAppContext) { + let window = cx.open_window(size(px(800.), px(600.)), |_, _| AnchoredTestView { + position: point(px(100.), px(100.)), + }); + + cx.run_until_parked(); + + window + .update(cx, |_, window, cx| { + let event = gpui::ScrollWheelEvent { + position: point(px(400.), px(300.)), + delta: gpui::ScrollDelta::Pixels(point(px(0.), px(-1000.))), + ..Default::default() + }; + window.dispatch_event(PlatformInput::ScrollWheel(event), cx); + }) + .unwrap(); + + cx.run_until_parked(); + + let menu_bounds = window + .update(cx, |_, window, _| { + window.rendered_frame.debug_bounds.get("MENU").copied() + }) + .unwrap() + .expect("MENU debug bounds not found"); + + assert_eq!(menu_bounds.origin, point(px(100.), px(100.))); + assert_eq!(menu_bounds.size, size(px(200.), px(300.))); + } + + #[gpui::test] + fn test_anchored_snaps_to_window(cx: &mut TestAppContext) { + let window = cx.open_window(size(px(800.), px(600.)), |_, _| AnchoredTestView { + position: point(px(100.), px(500.)), + }); + + cx.run_until_parked(); + + let menu_bounds = window + .update(cx, |_, window, _| { + window.rendered_frame.debug_bounds.get("MENU").copied() + }) + .unwrap() + .expect("MENU debug bounds not found"); + + assert_eq!(menu_bounds.origin, point(px(100.), px(300.))); + assert_eq!(menu_bounds.size, size(px(200.), px(300.))); + } +} diff --git a/vendor/gpui-pre/src/elements/animation.rs b/vendor/gpui-pre/src/elements/animation.rs new file mode 100644 index 00000000..e0768935 --- /dev/null +++ b/vendor/gpui-pre/src/elements/animation.rs @@ -0,0 +1,1028 @@ +use scheduler::Instant; +use std::{cell::Cell, rc::Rc, time::Duration}; + +use crate::{ + AnyElement, App, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement, + ParentElement, SpringAnimation, SpringConfig, SpringPlayback, SpringState, SpringTarget, + Window, +}; + +pub use easing::*; +use smallvec::SmallVec; + +/// An animation that can be applied to an element. +#[derive(Clone)] +pub struct Animation { + /// The amount of time for which this animation should run + pub duration: Duration, + /// Whether to repeat this animation when it finishes + pub oneshot: bool, + /// Whether to derive the phase from a shared clock. See [`Animation::repeat_synced`]. + pub synced: bool, + /// A function that maps normalized time to an animated value. + /// The result may exceed 0..1 for easing functions that overshoot. + pub easing: Rc f32>, + /// The maximum number of times per second this animation re-renders. + /// When `None`, the animation re-renders on every frame. + pub max_fps: Option, +} + +impl Animation { + /// Create a new animation with the given duration. + /// By default the animation will only run once and will use a linear easing function. + pub fn new(duration: Duration) -> Self { + Self { + duration, + oneshot: true, + synced: false, + easing: Rc::new(linear), + max_fps: None, + } + } + + /// Set the animation to loop when it finishes. + pub fn repeat(mut self) -> Self { + self.oneshot = false; + self + } + + /// Set the animation to loop when it finishes, phase-locked to a clock shared by the whole [`App`]. + pub fn repeat_synced(mut self) -> Self { + self.oneshot = false; + self.synced = true; + self + } + + /// Sets the easing function used to map normalized time to an animated value. + /// + /// The output is not clamped, allowing physical easing functions such as + /// springs to overshoot. + pub fn with_easing(mut self, easing: impl Fn(f32) -> f32 + 'static) -> Self { + self.easing = Rc::new(easing); + self + } + + /// Limit how often this animation re-renders. Instead of re-rendering on + /// every frame, the animation schedules its next render `1 / max_fps` + /// seconds after the current one. Values that are not finite and positive + /// are ignored. + pub fn with_max_fps(mut self, max_fps: f32) -> Self { + self.max_fps = Some(max_fps); + self + } +} + +/// An extension trait for adding the animation wrapper to both Elements and Components +/// +/// Animations rendered through this trait automatically respect +/// [`App::reduce_motion`](crate::App::reduce_motion): when it is set, +/// the element is rendered in a static state (the end state for oneshot +/// animations, the start state for repeating ones) and no animation frames are +/// scheduled. +pub trait AnimationExt { + /// Render this component or element with an animation + fn with_animation( + self, + id: impl Into, + animation: Animation, + animator: impl Fn(Self, f32) -> Self + 'static, + ) -> AnimationElement + where + Self: Sized, + { + AnimationElement { + id: id.into(), + element: Some(self), + animator: Box::new(move |this, _, value| animator(this, value)), + animations: smallvec::smallvec![animation], + } + } + + /// Render this component or element with a chain of animations + fn with_animations( + self, + id: impl Into, + animations: Vec, + animator: impl Fn(Self, usize, f32) -> Self + 'static, + ) -> AnimationElement + where + Self: Sized, + { + AnimationElement { + id: id.into(), + element: Some(self), + animator: Box::new(animator), + animations: animations.into(), + } + } + + /// Renders this component or element at the value produced by a spring. + /// + /// The element ID preserves position and velocity across target changes. + /// A newly mounted spring starts at its target unless configured with + /// [`SpringAnimation::from`]. + fn with_spring( + self, + id: impl Into, + animation: SpringAnimation, + animator: impl FnOnce(Self, T::Output) -> Self + 'static, + ) -> SpringAnimationElement + where + Self: Sized, + T: SpringTarget, + T::Output: 'static, + { + let SpringAnimation { + config, + target, + epsilon, + initial, + playback, + } = animation; + let scalar_target = target.target(); + SpringAnimationElement { + id: id.into(), + element: Some(self), + config, + target: scalar_target, + epsilon, + initial, + playback, + animator: Some(Box::new(move |this, value| { + animator(this, target.resolve(value)) + })), + } + } +} + +impl AnimationExt for E {} + +/// A GPUI element that applies an animation to another element +pub struct AnimationElement { + id: ElementId, + element: Option, + animations: SmallVec<[Animation; 1]>, + animator: Box E + 'static>, +} + +/// A GPUI element driven by a stateful spring. +pub struct SpringAnimationElement { + id: ElementId, + element: Option, + config: SpringConfig, + target: f32, + epsilon: f32, + initial: Option, + playback: SpringPlayback, + animator: Option E + 'static>>, +} + +impl ParentElement for SpringAnimationElement { + fn extend(&mut self, elements: impl IntoIterator) { + let Some(element) = &mut self.element else { + return; + }; + + element.extend(elements); + } +} + +impl SpringAnimationElement { + /// Returns a new [`SpringAnimationElement`] after applying the given function + /// to the element being animated. + pub fn map_element(mut self, f: impl FnOnce(E) -> E) -> SpringAnimationElement { + self.element = self.element.map(f); + self + } +} + +impl IntoElement for SpringAnimationElement { + type Element = SpringAnimationElement; + + fn into_element(self) -> Self::Element { + self + } +} + +impl ParentElement for AnimationElement { + fn extend(&mut self, elements: impl IntoIterator) { + let Some(element) = &mut self.element else { + return; + }; + + element.extend(elements); + } +} + +impl AnimationElement { + /// Returns a new [`AnimationElement`] after applying the given function + /// to the element being animated. + pub fn map_element(mut self, f: impl FnOnce(E) -> E) -> AnimationElement { + self.element = self.element.map(f); + self + } +} + +impl IntoElement for AnimationElement { + type Element = AnimationElement; + + fn into_element(self) -> Self::Element { + self + } +} + +struct AnimationState { + start: Instant, + animation_ix: usize, + /// Whether a throttled re-render (see [`Animation::with_max_fps`]) is + /// already scheduled, so overlapping renders don't stack extra timers. + delayed_frame_pending: Rc>, +} + +struct SpringElementState { + spring: SpringState, + target: f32, + config: SpringConfig, + initial: f32, + playback: SpringPlayback, + updated_at: Instant, +} + +impl Element for SpringAnimationElement { + type RequestLayoutState = AnyElement; + type PrepaintState = (); + + fn id(&self) -> Option { + Some(self.id.clone()) + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (crate::LayoutId, Self::RequestLayoutState) { + window.with_element_state(global_id.unwrap(), |state, window| { + let now = Instant::now(); + let initial = self.initial.unwrap_or(self.target); + let mut state = state.unwrap_or_else(|| SpringElementState { + spring: SpringState { + position: initial, + velocity: 0.0, + }, + target: self.target, + config: self.config, + initial, + playback: self.playback, + updated_at: now, + }); + + let elapsed = now.duration_since(state.updated_at).as_secs_f32(); + match state.playback { + SpringPlayback::Running => { + state.spring = state.config.step(state.spring, state.target, elapsed); + } + SpringPlayback::Paused + | SpringPlayback::Stopped + | SpringPlayback::Completed + | SpringPlayback::Cancelled => {} + } + + state.config = self.config; + state.target = self.target; + + let done = match self.playback { + SpringPlayback::Running => { + if cx.reduce_motion() { + state.spring = SpringState { + position: state.target, + velocity: 0.0, + }; + true + } else { + let done = + state + .config + .is_settled(state.spring, state.target, self.epsilon); + if done { + state.spring = SpringState { + position: state.target, + velocity: 0.0, + }; + } + done + } + } + SpringPlayback::Paused => true, + SpringPlayback::Stopped => { + state.spring.velocity = 0.0; + true + } + SpringPlayback::Completed => { + state.spring = SpringState { + position: state.target, + velocity: 0.0, + }; + true + } + SpringPlayback::Cancelled => { + state.spring = SpringState { + position: state.initial, + velocity: 0.0, + }; + true + } + }; + state.playback = self.playback; + state.updated_at = now; + + let element = self.element.take().expect("should only be called once"); + let animator = self.animator.take().expect("should only be called once"); + let mut element = animator(element, state.spring.position).into_any_element(); + + if !done { + window.request_animation_frame(); + } + + ((element.request_layout(window, cx), element), state) + }) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: crate::Bounds, + element: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + element.prepaint(window, cx); + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: crate::Bounds, + element: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + element.paint(window, cx); + } +} + +impl Element for AnimationElement { + type RequestLayoutState = AnyElement; + type PrepaintState = (); + + fn id(&self) -> Option { + Some(self.id.clone()) + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (crate::LayoutId, Self::RequestLayoutState) { + window.with_element_state(global_id.unwrap(), |state, window| { + let mut state = state.unwrap_or_else(|| AnimationState { + start: Instant::now(), + animation_ix: 0, + delayed_frame_pending: Rc::new(Cell::new(false)), + }); + let (animation_ix, delta, done) = if cx.reduce_motion() { + let animation_ix = self.animations.len() - 1; + let delta = if self.animations[animation_ix].oneshot { + 1.0 + } else { + 0.0 + }; + (animation_ix, delta, true) + } else { + let animation_ix = state.animation_ix; + let duration = self.animations[animation_ix].duration; + + let elapsed = if self.animations[animation_ix].synced && !duration.is_zero() { + let elapsed = cx.background_executor().now() - cx.synced_animation_epoch; + // Reduce modulo the duration before f32 conversion, which loses sub-second precision at scale. + Duration::from_nanos((elapsed.as_nanos() % duration.as_nanos()) as u64) + } else { + state.start.elapsed() + }; + let mut delta = elapsed.as_secs_f32() / duration.as_secs_f32(); + + let mut done = false; + if delta > 1.0 { + if self.animations[animation_ix].oneshot { + if animation_ix >= self.animations.len() - 1 { + done = true; + } else { + state.start = Instant::now(); + state.animation_ix += 1; + } + delta = 1.0; + } else { + delta %= 1.0; + } + } + (animation_ix, delta, done) + }; + let delta = (self.animations[animation_ix].easing)(delta); + + debug_assert!(delta.is_finite(), "animated value should be finite"); + + let element = self.element.take().expect("should only be called once"); + let mut element = (self.animator)(element, animation_ix, delta).into_any_element(); + + if !done { + match self.animations[animation_ix].max_fps { + Some(max_fps) if max_fps.is_finite() && max_fps > 0.0 => { + if !state.delayed_frame_pending.get() { + state.delayed_frame_pending.set(true); + let delayed_frame_pending = state.delayed_frame_pending.clone(); + let view = window.current_view(); + let interval = Duration::from_secs_f32(1.0 / max_fps); + window + .spawn(cx, async move |cx| { + cx.background_executor().timer(interval).await; + delayed_frame_pending.set(false); + cx.update(move |_, cx| cx.notify(view)).ok(); + }) + .detach(); + } + } + _ => window.request_animation_frame(), + } + } + + ((element.request_layout(window, cx), element), state) + }) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: crate::Bounds, + element: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + element.prepaint(window, cx); + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: crate::Bounds, + element: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + element.paint(window, cx); + } +} + +mod easing { + use std::f32::consts::PI; + + /// The linear easing function, or delta itself + pub fn linear(delta: f32) -> f32 { + delta + } + + /// The quadratic easing function, delta * delta + pub fn quadratic(delta: f32) -> f32 { + delta * delta + } + + /// The quadratic ease-in-out function, which starts and ends slowly but speeds up in the middle + pub fn ease_in_out(delta: f32) -> f32 { + if delta < 0.5 { + 2.0 * delta * delta + } else { + let x = -2.0 * delta + 2.0; + 1.0 - x * x / 2.0 + } + } + + /// The Quint ease-out function, which starts quickly and decelerates to a stop + pub fn ease_out_quint() -> impl Fn(f32) -> f32 { + move |delta| 1.0 - (1.0 - delta).powi(5) + } + + /// Apply the given easing function, first in the forward direction and then in the reverse direction + pub fn bounce(easing: impl Fn(f32) -> f32) -> impl Fn(f32) -> f32 { + move |delta| { + if delta < 0.5 { + easing(delta * 2.0) + } else { + easing((1.0 - delta) * 2.0) + } + } + } + + /// A custom easing function for pulsating alpha that slows down as it approaches 0.1 + pub fn pulsating_between(min: f32, max: f32) -> impl Fn(f32) -> f32 { + let range = max - min; + + move |delta| { + // Use a combination of sine and cubic functions for a more natural breathing rhythm + let t = (delta * 2.0 * PI).sin(); + let breath = (t * t * t + t) / 2.0; + + // Map the breath to our desired alpha range + let normalized_alpha = (breath + 1.0) / 2.0; + + min + (normalized_alpha * range) + } + } +} + +#[cfg(test)] +mod tests { + use std::{cell::RefCell, rc::Rc, time::Duration}; + + use crate::{ + Animation, Context, InteractiveElement, Pixels, Render, SpringAnimation, SpringConfig, + TestAppContext, WindowHandle, div, prelude::*, px, size, + }; + + use super::*; + + struct AnimationTestView { + rendered_deltas: Rc>>, + max_fps: Option, + } + + struct SyncedAnimationTestView { + show_second: bool, + first_deltas: Rc>>, + second_deltas: Rc>>, + } + + struct SpringAnimationTestView { + target: Pixels, + initial: Option, + playback: SpringPlayback, + rendered_values: Rc>>, + } + + impl Render for SpringAnimationTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let rendered_values = self.rendered_values.clone(); + let mut animation = SpringAnimation::new(SpringConfig::new(100.0, 2.0, 1.0)) + .to(self.target) + .with_epsilon(0.01) + .playback(self.playback); + if let Some(initial) = self.initial { + animation = animation.from(initial); + } + div().with_spring("spring-animation", animation, move |this, value| { + rendered_values.borrow_mut().push(value); + this.left(value) + }) + } + } + + impl Render for SyncedAnimationTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let record_deltas = |deltas: Rc>>| { + move |this, delta| { + deltas.borrow_mut().push(delta); + this + } + }; + div() + .size_full() + .child(div().with_animation( + "first-synced-animation", + Animation::new(Duration::from_secs(1)).repeat_synced(), + record_deltas(self.first_deltas.clone()), + )) + .when(self.show_second, |this| { + this.child(div().with_animation( + "second-synced-animation", + Animation::new(Duration::from_secs(1)).repeat_synced(), + record_deltas(self.second_deltas.clone()), + )) + }) + } + } + + impl Render for AnimationTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let rendered_deltas = self.rendered_deltas.clone(); + // The throttled variant syncs to the shared clock so the deltas + // follow the test scheduler's clock rather than wall time. + let mut animation = Animation::new(Duration::from_secs(1)); + if let Some(max_fps) = self.max_fps { + animation = animation.repeat_synced().with_max_fps(max_fps); + } else { + animation = animation.repeat(); + } + div().size_full().child(div().with_animation( + "repeating-animation", + animation, + move |this, delta| { + rendered_deltas.borrow_mut().push(delta); + this + }, + )) + } + } + + fn open_test_window( + cx: &mut TestAppContext, + ) -> (Rc>>, WindowHandle) { + open_test_window_with_max_fps(cx, None) + } + + fn open_test_window_with_max_fps( + cx: &mut TestAppContext, + max_fps: Option, + ) -> (Rc>>, WindowHandle) { + let rendered_deltas = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.), px(100.)), { + let rendered_deltas = rendered_deltas.clone(); + move |_, _| AnimationTestView { + rendered_deltas, + max_fps, + } + }); + cx.run_until_parked(); + (rendered_deltas, window) + } + + fn simulate_next_frame(window: &WindowHandle, cx: &mut TestAppContext) -> usize { + let callback_count = window + .update(cx, |_, window, cx| window.simulate_next_frame(cx)) + .unwrap(); + cx.run_until_parked(); + callback_count + } + // Before parent-animation-element, using .with_animation + // would not allow chaining .parent after. This is just a + // build check that we can call div().id().with_animation().child() + #[test] + fn test_animation_parent() { + div() + .id("id") + // + .with_animation( + "animation", + Animation::new(Duration::from_secs(1)), + |el, _t| { + // + el + }, + ) + .child( + // + div(), + ); + } + + #[test] + fn test_spring_animation_parent() { + div() + .id("id") + .with_spring( + "spring-animation", + SpringAnimation::new(SpringConfig::new(100.0, 10.0, 1.0)) + .to(px(10.0)) + .from(px(0.0)), + |element, value| element.left(value), + ) + .child(div()); + } + + #[gpui::test] + fn test_spring_animation_preserves_velocity_when_retargeted(cx: &mut TestAppContext) { + let rendered_values = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.0), px(100.0)), { + let rendered_values = rendered_values.clone(); + move |_, _| SpringAnimationTestView { + target: px(0.0), + initial: None, + playback: SpringPlayback::Running, + rendered_values, + } + }); + cx.run_until_parked(); + assert_eq!(*rendered_values.borrow(), vec![px(0.0)]); + + window + .update(cx, |view, _, cx| { + view.target = px(100.0); + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + + cx.executor().advance_clock(Duration::from_millis(50)); + assert!(simulate_next_frame(&window, cx) > 0); + let value_before_retargeting = *rendered_values.borrow().last().unwrap(); + assert!(value_before_retargeting > px(0.0)); + assert!(value_before_retargeting < px(100.0)); + + window + .update(cx, |view, _, cx| { + view.target = px(0.0); + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + + cx.executor().advance_clock(Duration::from_millis(5)); + assert!(simulate_next_frame(&window, cx) > 0); + let value_after_retargeting = *rendered_values.borrow().last().unwrap(); + assert!(value_after_retargeting > value_before_retargeting); + } + + #[gpui::test] + fn test_paused_spring_resumes_with_its_velocity(cx: &mut TestAppContext) { + let rendered_values = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.0), px(100.0)), { + let rendered_values = rendered_values.clone(); + move |_, _| SpringAnimationTestView { + target: px(0.0), + initial: None, + playback: SpringPlayback::Running, + rendered_values, + } + }); + cx.run_until_parked(); + + window + .update(cx, |view, _, cx| { + view.target = px(100.0); + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + cx.executor().advance_clock(Duration::from_millis(50)); + assert!(simulate_next_frame(&window, cx) > 0); + + window + .update(cx, |view, _, cx| { + view.target = px(0.0); + view.playback = SpringPlayback::Paused; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + let paused_value = *rendered_values.borrow().last().unwrap(); + + cx.executor().advance_clock(Duration::from_millis(500)); + assert!(simulate_next_frame(&window, cx) > 0); + assert_eq!(*rendered_values.borrow().last().unwrap(), paused_value); + assert_eq!(simulate_next_frame(&window, cx), 0); + + window + .update(cx, |view, _, cx| { + view.playback = SpringPlayback::Running; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + cx.executor().advance_clock(Duration::from_millis(5)); + assert!(simulate_next_frame(&window, cx) > 0); + assert!(*rendered_values.borrow().last().unwrap() > paused_value); + } + + #[gpui::test] + fn test_stopped_spring_resumes_without_velocity(cx: &mut TestAppContext) { + let rendered_values = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.0), px(100.0)), { + let rendered_values = rendered_values.clone(); + move |_, _| SpringAnimationTestView { + target: px(0.0), + initial: None, + playback: SpringPlayback::Running, + rendered_values, + } + }); + cx.run_until_parked(); + + window + .update(cx, |view, _, cx| { + view.target = px(1_000_000.0); + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + cx.executor().advance_clock(Duration::from_millis(50)); + assert!(simulate_next_frame(&window, cx) > 0); + + window + .update(cx, |view, _, cx| { + view.target = px(0.0); + view.playback = SpringPlayback::Stopped; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + let stopped_value = *rendered_values.borrow().last().unwrap(); + + cx.executor().advance_clock(Duration::from_millis(500)); + assert!(simulate_next_frame(&window, cx) > 0); + assert_eq!(*rendered_values.borrow().last().unwrap(), stopped_value); + assert_eq!(simulate_next_frame(&window, cx), 0); + + window + .update(cx, |view, _, cx| { + view.target = stopped_value; + view.playback = SpringPlayback::Running; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + assert_eq!(*rendered_values.borrow().last().unwrap(), stopped_value); + assert_eq!(simulate_next_frame(&window, cx), 0); + } + + #[gpui::test] + fn test_cancelled_and_completed_springs_resolve_their_endpoints(cx: &mut TestAppContext) { + let rendered_values = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.0), px(100.0)), { + let rendered_values = rendered_values.clone(); + move |_, _| SpringAnimationTestView { + target: px(100.0), + initial: Some(px(20.0)), + playback: SpringPlayback::Running, + rendered_values, + } + }); + cx.run_until_parked(); + assert_eq!(*rendered_values.borrow(), vec![px(20.0)]); + + cx.executor().advance_clock(Duration::from_millis(50)); + assert!(simulate_next_frame(&window, cx) > 0); + assert!(*rendered_values.borrow().last().unwrap() > px(20.0)); + + window + .update(cx, |view, _, cx| { + view.playback = SpringPlayback::Cancelled; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + assert_eq!(*rendered_values.borrow().last().unwrap(), px(20.0)); + assert!(simulate_next_frame(&window, cx) > 0); + assert_eq!(simulate_next_frame(&window, cx), 0); + + window + .update(cx, |view, _, cx| { + view.playback = SpringPlayback::Completed; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + assert_eq!(*rendered_values.borrow().last().unwrap(), px(100.0)); + assert_eq!(simulate_next_frame(&window, cx), 0); + } + + #[gpui::test] + fn test_spring_animation_respects_reduced_motion(cx: &mut TestAppContext) { + cx.update(|cx| cx.set_reduce_motion(true)); + let rendered_values = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.0), px(100.0)), { + let rendered_values = rendered_values.clone(); + move |_, _| SpringAnimationTestView { + target: px(100.0), + initial: None, + playback: SpringPlayback::Running, + rendered_values, + } + }); + cx.run_until_parked(); + + assert_eq!(*rendered_values.borrow(), vec![px(100.0)]); + assert_eq!(simulate_next_frame(&window, cx), 0); + } + + #[gpui::test] + fn test_repeating_animation_schedules_animation_frames(cx: &mut TestAppContext) { + let (rendered_deltas, window) = open_test_window(cx); + + assert_eq!(rendered_deltas.borrow().len(), 1); + + for expected_frames in 2..=3 { + assert_eq!(simulate_next_frame(&window, cx), 1); + assert_eq!(rendered_deltas.borrow().len(), expected_frames); + } + } + + #[gpui::test] + fn test_max_fps_schedules_timer_driven_frames(cx: &mut TestAppContext) { + let (rendered_deltas, window) = open_test_window_with_max_fps(cx, Some(10.0)); + + // The test scheduler's clock jitters forward slightly on each poll, + // so compare against expectations loosely. + let assert_deltas_approx_eq = |expected: &[f32]| { + let actual = rendered_deltas.borrow(); + assert_eq!(actual.len(), expected.len(), "deltas: {actual:?}"); + for (actual, expected) in actual.iter().zip(expected) { + assert!( + (actual - expected).abs() < 1e-2, + "expected {expected}, got {actual}" + ); + } + }; + + assert_deltas_approx_eq(&[0.0]); + + // No per-frame callback is scheduled; re-renders are timer-driven. + assert_eq!(simulate_next_frame(&window, cx), 0); + assert_deltas_approx_eq(&[0.0]); + + cx.executor().advance_clock(Duration::from_millis(105)); + cx.run_until_parked(); + assert_deltas_approx_eq(&[0.0, 0.105]); + + cx.executor().advance_clock(Duration::from_millis(105)); + cx.run_until_parked(); + assert_deltas_approx_eq(&[0.0, 0.105, 0.21]); + } + + #[gpui::test] + fn test_synced_animations_share_phase_across_elements(cx: &mut TestAppContext) { + let first_deltas = Rc::new(RefCell::new(Vec::new())); + let second_deltas = Rc::new(RefCell::new(Vec::new())); + let window = cx.open_window(size(px(100.), px(100.)), { + let first_deltas = first_deltas.clone(); + let second_deltas = second_deltas.clone(); + move |_, _| SyncedAnimationTestView { + show_second: false, + first_deltas, + second_deltas, + } + }); + cx.run_until_parked(); + + assert_eq!(*first_deltas.borrow(), vec![0.0]); + + cx.executor().advance_clock(Duration::from_millis(250)); + simulate_next_frame(&window, cx); + assert_eq!(*first_deltas.borrow(), vec![0.0, 0.25]); + + // The second element mounts a quarter through the cycle, yet renders + // the shared phase rather than starting at zero. + window + .update(cx, |view, _, cx| { + view.show_second = true; + cx.notify(); + }) + .unwrap(); + cx.run_until_parked(); + cx.executor().advance_clock(Duration::from_millis(250)); + simulate_next_frame(&window, cx); + + assert_eq!(*second_deltas.borrow().last().unwrap(), 0.5); + assert_eq!( + *first_deltas.borrow().last().unwrap(), + *second_deltas.borrow().last().unwrap() + ); + assert!(second_deltas.borrow().iter().all(|delta| *delta > 0.0)); + + // The phase wraps around each full cycle. + cx.executor().advance_clock(Duration::from_millis(2250)); + simulate_next_frame(&window, cx); + assert_eq!(*first_deltas.borrow().last().unwrap(), 0.75); + + // Sub-second precision survives months of uptime: converting the raw + // elapsed time to f32 would round 0.25 away entirely. + cx.executor() + .advance_clock(Duration::from_secs(300 * 24 * 60 * 60) + Duration::from_millis(500)); + simulate_next_frame(&window, cx); + assert_eq!(*first_deltas.borrow().last().unwrap(), 0.25); + } + + #[gpui::test] + fn test_reduce_motion_renders_single_static_frame(cx: &mut TestAppContext) { + cx.update(|cx| cx.set_reduce_motion(true)); + let (rendered_deltas, window) = open_test_window(cx); + + assert_eq!(*rendered_deltas.borrow(), vec![0.0]); + + assert_eq!(simulate_next_frame(&window, cx), 0); + assert_eq!(*rendered_deltas.borrow(), vec![0.0]); + } +} diff --git a/vendor/gpui-pre/src/elements/canvas.rs b/vendor/gpui-pre/src/elements/canvas.rs new file mode 100644 index 00000000..d57d2f60 --- /dev/null +++ b/vendor/gpui-pre/src/elements/canvas.rs @@ -0,0 +1,95 @@ +use refineable::Refineable as _; + +use crate::{ + App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement, Pixels, + Style, StyleRefinement, Styled, Window, +}; + +/// Construct a canvas element with the given paint callback. +/// Useful for adding short term custom drawing to a view. +pub fn canvas( + prepaint: impl 'static + FnOnce(Bounds, &mut Window, &mut App) -> T, + paint: impl 'static + FnOnce(Bounds, T, &mut Window, &mut App), +) -> Canvas { + Canvas { + prepaint: Some(Box::new(prepaint)), + paint: Some(Box::new(paint)), + style: StyleRefinement::default(), + } +} + +/// A canvas element, meant for accessing the low level paint API without defining a whole +/// custom element +pub struct Canvas { + prepaint: Option, &mut Window, &mut App) -> T>>, + paint: Option, T, &mut Window, &mut App)>>, + style: StyleRefinement, +} + +impl IntoElement for Canvas { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Element for Canvas { + type RequestLayoutState = Style; + type PrepaintState = Option; + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (crate::LayoutId, Self::RequestLayoutState) { + let mut style = Style::default(); + style.refine(&self.style); + let layout_id = window.request_layout(style.clone(), [], cx); + (layout_id, style) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Style, + window: &mut Window, + cx: &mut App, + ) -> Option { + Some(self.prepaint.take().unwrap()(bounds, window, cx)) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + style: &mut Style, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let prepaint = prepaint.take().unwrap(); + style.paint(bounds, window, cx, |window, cx| { + (self.paint.take().unwrap())(bounds, prepaint, window, cx) + }); + } +} + +impl Styled for Canvas { + fn style(&mut self) -> &mut crate::StyleRefinement { + &mut self.style + } +} diff --git a/vendor/gpui-pre/src/elements/container_query.rs b/vendor/gpui-pre/src/elements/container_query.rs new file mode 100644 index 00000000..0363ce69 --- /dev/null +++ b/vendor/gpui-pre/src/elements/container_query.rs @@ -0,0 +1,126 @@ +//! A container query element, in the spirit of CSS container queries. +//! The element's own size is determined solely by its style and the space +//! offered by its parent. + +use refineable::Refineable as _; + +use crate::{ + AnyElement, App, AvailableSpace, Bounds, Element, ElementId, GlobalElementId, + InspectorElementId, IntoElement, LayoutId, Pixels, Size, Style, StyleRefinement, Styled, + Window, relative, +}; + +/// Construct a container query element with the given render callback. +/// The callback receives the size the element was assigned during layout and +/// returns the contents to display within it. +/// +/// By default the element fills its parent (equivalent to `.size_full()`); +/// use the [`Styled`] methods to size it differently. Because the contents +/// don't exist until after layout, they cannot influence the element's size. +/// +/// # Example +/// +/// ``` +/// # use gpui::{container_query, div, px, IntoElement, ParentElement}; +/// container_query(|size, _window, _cx| { +/// if size.width < px(240.) { +/// div().child("Narrow layout") +/// } else { +/// div().child("Wide layout") +/// } +/// }); +/// ``` +pub fn container_query( + render: impl 'static + FnOnce(Size, &mut Window, &mut App) -> E, +) -> ContainerQuery +where + E: IntoElement, +{ + let mut base_style = StyleRefinement::default(); + base_style.size.width = Some(relative(1.).into()); + base_style.size.height = Some(relative(1.).into()); + + ContainerQuery { + render: Some(Box::new(|size, window, cx| { + render(size, window, cx).into_any_element() + })), + style: base_style, + } +} + +/// A container query element, created with [`container_query`]. +pub struct ContainerQuery { + render: Option, &mut Window, &mut App) -> AnyElement>>, + style: StyleRefinement, +} + +impl Element for ContainerQuery { + type RequestLayoutState = (); + type PrepaintState = Option; + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut style = Style::default(); + style.refine(&self.style); + let layout_id = window.request_layout(style, [], cx); + (layout_id, ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Option { + let render = self.render.take()?; + let mut child = render(bounds.size, window, cx); + child.layout_as_root(bounds.size.map(AvailableSpace::Definite), window, cx); + child.prepaint_at(bounds.origin, window, cx); + Some(child) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + if let Some(child) = prepaint { + child.paint(window, cx); + } + } +} + +impl IntoElement for ContainerQuery { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Styled for ContainerQuery { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} diff --git a/vendor/gpui-pre/src/elements/deferred.rs b/vendor/gpui-pre/src/elements/deferred.rs new file mode 100644 index 00000000..ddf324a6 --- /dev/null +++ b/vendor/gpui-pre/src/elements/deferred.rs @@ -0,0 +1,206 @@ +use crate::{ + AnyElement, App, Bounds, Element, GlobalElementId, InspectorElementId, IntoElement, LayoutId, + Pixels, Window, +}; + +/// Builds a `Deferred` element, which delays the layout and paint of its child. +pub fn deferred(child: impl IntoElement) -> Deferred { + Deferred { + child: Some(child.into_any_element()), + priority: 0, + } +} + +/// An element which delays the painting of its child until after all of +/// its ancestors, while keeping its layout as part of the current element tree. +pub struct Deferred { + child: Option, + priority: usize, +} + +impl Deferred { + /// Sets the `priority` value of the `deferred` element, which + /// determines the drawing order relative to other deferred elements, + /// with higher values being drawn on top. + pub fn with_priority(mut self, priority: usize) -> Self { + self.priority = priority; + self + } +} + +impl Element for Deferred { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, ()) { + let layout_id = self.child.as_mut().unwrap().request_layout(window, cx); + (layout_id, ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + _cx: &mut App, + ) { + let child = self.child.take().unwrap(); + let element_offset = window.element_offset(); + window.defer_draw(child, element_offset, self.priority, None) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + _window: &mut Window, + _cx: &mut App, + ) { + } +} + +impl IntoElement for Deferred { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Deferred { + /// Sets a priority for the element. A higher priority conceptually means painting the element + /// on top of deferred draws with a lower priority (i.e. closer to the viewer). + pub fn priority(mut self, priority: usize) -> Self { + self.priority = priority; + self + } +} + +#[cfg(test)] +mod tests { + use crate::{ + Context, Entity, StyleRefinement, TestAppContext, Window, anchored, deferred, div, point, + prelude::*, px, size, + }; + + /// A stand-in for a dock panel hosting a popover (deferred draw) whose + /// content opens another popover (a deferred draw created while + /// prepainting the first one's content). + struct PanelView; + + impl Render for PanelView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().key_context("Panel").size_full().child( + deferred( + anchored().position(point(px(10.), px(10.))).child( + div().key_context("Popover").w(px(200.)).h(px(200.)).child( + deferred( + anchored().position(point(px(30.), px(30.))).child( + div() + .key_context("NestedMenu") + .debug_selector(|| "NESTED_MENU".into()) + .w(px(50.)) + .h(px(50.)), + ), + ) + .with_priority(2), + ), + ), + ) + .with_priority(1), + ) + } + } + + struct RootView { + panel: Entity, + } + + impl Render for RootView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().key_context("Root").size_full().child( + self.panel + .clone() + .cached(StyleRefinement::default().size_full()), + ) + } + } + + /// Regression test for a crash with nested deferred draws (e.g. a popover + /// menu inside a popover hosted by a cached dock panel). Prepaint indices + /// recorded during the deferred draw rounds must index the same + /// `deferred_draws` vector that `reuse_prepaint` slices on the next frame; + /// previously they were measured against a transient per-round vector, so + /// reusing the panel's subtree grafted the wrong deferred draws and + /// panicked in the dispatch tree. + #[gpui::test] + fn test_nested_deferred_draws_with_reused_views(cx: &mut TestAppContext) { + let window = cx.open_window(size(px(800.), px(600.)), |_, cx| { + let panel = cx.new(|_| PanelView); + RootView { panel } + }); + cx.run_until_parked(); + + let menu_bounds = window + .update(cx, |_, window, _| { + window + .rendered_frame + .debug_bounds + .get("NESTED_MENU") + .copied() + }) + .unwrap() + .expect("NESTED_MENU debug bounds not found"); + assert_eq!(menu_bounds.size, size(px(50.), px(50.))); + + // Re-render only the root view; the panel is cached, so its subtree - + // including both deferred draw records - is reused from the previous + // frame. + window.update(cx, |_, _, cx| cx.notify()).unwrap(); + cx.run_until_parked(); + + // Reuse the subtree a second time, exercising ranges that were + // themselves recorded during a reused frame. + window.update(cx, |_, _, cx| cx.notify()).unwrap(); + cx.run_until_parked(); + + // Re-render the panel itself again to prove the popovers still draw. + window + .update(cx, |root, _, cx| { + root.panel.update(cx, |_, cx| cx.notify()); + }) + .unwrap(); + cx.run_until_parked(); + + window + .update(cx, |_, window, _| { + assert_eq!(window.rendered_frame.deferred_draws.len(), 2); + assert!( + window + .rendered_frame + .debug_bounds + .contains_key("NESTED_MENU") + ); + }) + .unwrap(); + } +} diff --git a/vendor/gpui-pre/src/elements/div.rs b/vendor/gpui-pre/src/elements/div.rs new file mode 100644 index 00000000..fc292f2a --- /dev/null +++ b/vendor/gpui-pre/src/elements/div.rs @@ -0,0 +1,5640 @@ +//! Div is the central, reusable element that most GPUI trees will be built from. +//! It functions as a container for other elements, and provides a number of +//! useful features for laying out and styling its children as well as binding +//! mouse events and action handlers. It is meant to be similar to the HTML `
    ` +//! element, but for GPUI. +//! +//! # Build your own div +//! +//! GPUI does not directly provide APIs for stateful, multi step events like `click` +//! and `drag`. We want GPUI users to be able to build their own abstractions for +//! their own needs. However, as a UI framework, we're also obliged to provide some +//! building blocks to make the process of building your own elements easier. +//! For this we have the [`Interactivity`] and the [`StyleRefinement`] structs, as well +//! as several associated traits. Together, these provide the full suite of Dom-like events +//! and Tailwind-like styling that you can use to build your own custom elements. Div is +//! constructed by combining these two systems into an all-in-one element. + +use crate::{ + Action, AnyDrag, AnyElement, AnyTooltip, AnyView, App, Bounds, ClickEvent, DispatchPhase, + Display, Element, ElementId, Entity, EntityId, ExternalDragPayload, ExternalDragPayloadSource, + FileDropEvent, FocusHandle, Global, GlobalElementId, Hitbox, HitboxBehavior, HitboxId, + InspectorElementId, IntoElement, IsZero, KeyContext, KeyDownEvent, KeyUpEvent, KeyboardButton, + KeyboardClickEvent, LayoutId, LongPressEvent, ModifiersChangedEvent, MouseButton, + MouseClickEvent, MouseDownEvent, MouseExitEvent, MouseMoveEvent, MousePressureEvent, + MouseUpEvent, OngoingScroll, Overflow, ParentElement, PinchEvent, Pixels, Point, Render, + ScrollWheelEvent, SharedString, Size, Style, StyleRefinement, Styled, Task, TooltipId, + TouchPhase, Visibility, Window, WindowControlArea, point, px, size, +}; +use collections::HashMap; +use gpui_util::ResultExt; +use refineable::Refineable; +use smallvec::SmallVec; +use std::{ + any::{Any, TypeId}, + cell::{Cell, RefCell}, + cmp::Ordering, + fmt::Debug, + marker::PhantomData, + mem, + rc::Rc, + sync::Arc, + time::Duration, +}; + +use super::ImageCacheProvider; + +#[cfg(feature = "stacker")] +type StackSafe = stacksafe::StackSafe; +#[cfg(not(feature = "stacker"))] +type StackSafe = T; + +const DRAG_THRESHOLD: f64 = 2.; +const DEFAULT_TOOLTIP_SHOW_DELAY: Duration = Duration::from_millis(500); +const HOVERABLE_TOOLTIP_HIDE_DELAY: Duration = Duration::from_millis(500); + +/// The styling information for a given group. +pub struct GroupStyle { + /// The identifier for this group. + pub group: SharedString, + + /// The specific style refinement that this group would apply + /// to its children. + pub style: Box, +} + +/// An event for when a drag is moving over this element, with the given state type. +pub struct DragMoveEvent { + /// The mouse move event that triggered this drag move event. + pub event: MouseMoveEvent, + + /// The bounds of this element. + pub bounds: Bounds, + drag: PhantomData, + dragged_item: Arc, +} + +impl DragMoveEvent { + /// Returns the drag state for this event. + pub fn drag<'b>(&self, cx: &'b App) -> &'b T { + cx.active_drag + .as_ref() + .and_then(|drag| drag.value.downcast_ref::()) + .expect("DragMoveEvent is only valid when the stored active drag is of the same type.") + } + + /// An item that is about to be dropped. + pub fn dragged_item(&self) -> &dyn Any { + self.dragged_item.as_ref() + } +} + +impl Interactivity { + /// Create an `Interactivity`, capturing the caller location in debug mode. + #[cfg(any(feature = "inspector", debug_assertions))] + #[track_caller] + pub fn new() -> Interactivity { + Interactivity { + source_location: Some(core::panic::Location::caller()), + ..Default::default() + } + } + + /// Create an `Interactivity`, capturing the caller location in debug mode. + #[cfg(not(any(feature = "inspector", debug_assertions)))] + pub fn new() -> Interactivity { + Interactivity::default() + } + + /// Gets the source location of construction. Returns `None` when not in debug mode. + pub fn source_location(&self) -> Option<&'static std::panic::Location<'static>> { + #[cfg(any(feature = "inspector", debug_assertions))] + { + self.source_location + } + + #[cfg(not(any(feature = "inspector", debug_assertions)))] + { + None + } + } + + /// Bind the given callback to the mouse down event for the given mouse button, during the bubble phase. + /// The imperative API equivalent of [`InteractiveElement::on_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to the view state from this callback. + pub fn on_mouse_down( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && hitbox.is_hovered(window) + { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse down event for any button, during the capture phase. + /// The imperative API equivalent of [`InteractiveElement::capture_any_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_any_mouse_down( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse down event for any button, during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_any_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_any_mouse_down( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse pressure event, during the bubble phase + /// the imperative API equivalent to [`InteractiveElement::on_mouse_pressure`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_pressure( + &mut self, + listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_pressure_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse pressure event, during the capture phase + /// the imperative API equivalent to [`InteractiveElement::on_mouse_pressure`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_mouse_pressure( + &mut self, + listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_pressure_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse up event for the given button, during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_mouse_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_up( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && hitbox.is_hovered(window) + { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse up event for any button, during the capture phase. + /// The imperative API equivalent to [`InteractiveElement::capture_any_mouse_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_any_mouse_up( + &mut self, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse up event for any button, during the bubble phase. + /// The imperative API equivalent to [`Interactivity::on_any_mouse_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_any_mouse_up( + &mut self, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse down event, on any button, during the capture phase, + /// when the mouse is outside of the bounds of this element. + /// The imperative API equivalent to [`InteractiveElement::on_mouse_down_out`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_down_out( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture + && !window.has_active_prompt() + && !hitbox.contains(&window.mouse_position()) + { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to the mouse up event, for the given button, during the capture phase, + /// when the mouse is outside of the bounds of this element. + /// The imperative API equivalent to [`InteractiveElement::on_mouse_up_out`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_up_out( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture + && event.button == button + && !hitbox.is_hovered(window) + { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to the mouse move event, during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_mouse_move`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_move( + &mut self, + listener: impl Fn(&MouseMoveEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_move_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to the mouse exit event, during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_mouse_exit`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_mouse_exit( + &mut self, + listener: impl Fn(&MouseExitEvent, &mut Window, &mut App) + 'static, + ) { + self.mouse_exit_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to [`FileDropEvent::Exited`] when a platform file drag + /// leaves this element's window while the element is hovered. + /// + /// This is a window-local exit event, not notification that the platform drag session ended. + /// The imperative API equivalent to [`InteractiveElement::on_file_drop_exit`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_file_drop_exit( + &mut self, + listener: impl Fn(&FileDropEvent, &mut Window, &mut App) + 'static, + ) { + self.file_drop_exit_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble + && matches!(event, FileDropEvent::Exited) + && hitbox.id.is_hovered_ignoring_last_input(window) + { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to the mouse drag event of the given type. Note that this + /// will be called for all move events, inside or outside of this element, as long as the + /// drag was started with this element under the mouse. Useful for implementing draggable + /// UIs that don't conform to a drag and drop style interaction, like resizing. + /// The imperative API equivalent to [`InteractiveElement::on_drag_move`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_drag_move( + &mut self, + listener: impl Fn(&DragMoveEvent, &mut Window, &mut App) + 'static, + ) where + T: 'static, + { + self.mouse_move_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Capture + && let Some(drag) = &cx.active_drag + && drag.value.as_ref().type_id() == TypeId::of::() + { + (listener)( + &DragMoveEvent { + event: event.clone(), + bounds: hitbox.bounds, + drag: PhantomData, + dragged_item: Arc::clone(&drag.value), + }, + window, + cx, + ); + } + })); + } + + /// Bind the given callback to scroll wheel events during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_scroll_wheel`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_scroll_wheel( + &mut self, + listener: impl Fn(&ScrollWheelEvent, &mut Window, &mut App) + 'static, + ) { + self.scroll_wheel_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.should_handle_scroll(window) { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to pinch gesture events during the bubble phase. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_pinch(&mut self, listener: impl Fn(&PinchEvent, &mut Window, &mut App) + 'static) { + self.pinch_listeners + .push(Box::new(move |event, phase, hitbox, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + (listener)(event, window, cx); + } + })); + } + + /// Bind the given callback to pinch gesture events during the capture phase. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_pinch( + &mut self, + listener: impl Fn(&PinchEvent, &mut Window, &mut App) + 'static, + ) { + self.pinch_listeners + .push(Box::new(move |event, phase, _hitbox, window, cx| { + if phase == DispatchPhase::Capture { + (listener)(event, window, cx); + } else { + cx.propagate(); + } + })); + } + + /// Bind the given callback to an action dispatch during the capture phase. + /// The imperative API equivalent to [`InteractiveElement::capture_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_action( + &mut self, + listener: impl Fn(&A, &mut Window, &mut App) + 'static, + ) { + self.action_listeners.push(( + TypeId::of::(), + Box::new(move |action, phase, window, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Capture { + (listener)(action, window, cx) + } else { + cx.propagate(); + } + }), + )); + } + + /// Bind the given callback to an action dispatch during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + #[track_caller] + #[inline(always)] + pub fn on_action(&mut self, listener: impl Fn(&A, &mut Window, &mut App) + 'static) { + self.action_listeners.push(( + TypeId::of::(), + Box::new(move |action, phase, window, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Bubble { + (listener)(action, window, cx) + } + }), + )); + } + + /// Bind the given callback to an action dispatch, based on a dynamic action parameter + /// instead of a type parameter. Useful for component libraries that want to expose + /// action bindings to their users. + /// The imperative API equivalent to [`InteractiveElement::on_boxed_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_boxed_action( + &mut self, + action: &dyn Action, + listener: impl Fn(&dyn Action, &mut Window, &mut App) + 'static, + ) { + let action = action.boxed_clone(); + self.action_listeners.push(( + (*action).type_id(), + Box::new(move |_, phase, window, cx| { + if phase == DispatchPhase::Bubble { + (listener)(&*action, window, cx) + } + }), + )); + } + + /// Bind the given callback to key down events during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_key_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_key_down( + &mut self, + listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static, + ) { + self.key_down_listeners + .push(Box::new(move |event, phase, window, cx| { + if phase == DispatchPhase::Bubble { + (listener)(event, window, cx) + } + })); + } + + /// Bind the given callback to key down events during the capture phase. + /// The imperative API equivalent to [`InteractiveElement::capture_key_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_key_down( + &mut self, + listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static, + ) { + self.key_down_listeners + .push(Box::new(move |event, phase, window, cx| { + if phase == DispatchPhase::Capture { + listener(event, window, cx) + } + })); + } + + /// Bind the given callback to key up events during the bubble phase. + /// The imperative API equivalent to [`InteractiveElement::on_key_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static) { + self.key_up_listeners + .push(Box::new(move |event, phase, window, cx| { + if phase == DispatchPhase::Bubble { + listener(event, window, cx) + } + })); + } + + /// Bind the given callback to key up events during the capture phase. + /// The imperative API equivalent to [`InteractiveElement::on_key_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn capture_key_up( + &mut self, + listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static, + ) { + self.key_up_listeners + .push(Box::new(move |event, phase, window, cx| { + if phase == DispatchPhase::Capture { + listener(event, window, cx) + } + })); + } + + /// Bind the given callback to modifiers changing events. + /// The imperative API equivalent to [`InteractiveElement::on_modifiers_changed`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_modifiers_changed( + &mut self, + listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static, + ) { + self.modifiers_changed_listeners.push(Box::new(listener)); + } + + /// Bind the given callback to drop events of the given type, whether or not the drag started on this element. + /// The imperative API equivalent to [`InteractiveElement::on_drop`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_drop(&mut self, listener: impl Fn(&T, &mut Window, &mut App) + 'static) { + self.drop_listeners.push(( + TypeId::of::(), + Box::new(move |dragged_value, window, cx| { + listener(dragged_value.downcast_ref().unwrap(), window, cx); + }), + )); + } + + /// Use the given predicate to determine whether or not a drop event should be dispatched to this element. + /// The imperative API equivalent to [`InteractiveElement::can_drop`]. + pub fn can_drop( + &mut self, + predicate: impl Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static, + ) { + self.can_drop_predicate = Some(Box::new(predicate)); + } + + /// Bind the given callback to click events of this element. + /// The imperative API equivalent to [`StatefulInteractiveElement::on_click`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + #[inline(always)] + pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) + where + Self: Sized, + { + self.click_listeners.push(Rc::new(listener)); + } + + /// Bind the given callback to non-primary click events of this element. + /// The imperative API equivalent to [`StatefulInteractiveElement::on_aux_click`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_aux_click(&mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) + where + Self: Sized, + { + self.aux_click_listeners.push(Rc::new(listener)); + } + + /// On drag initiation, this callback will be used to create a new view to render the dragged value for a + /// drag and drop operation. This API should also be used as the equivalent of 'on drag start' with + /// the [`Self::on_drag_move`] API. + /// The imperative API equivalent to [`StatefulInteractiveElement::on_drag`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_drag( + &mut self, + value: T, + constructor: impl Fn(&T, Point, &mut Window, &mut App) -> Entity + 'static, + ) where + Self: Sized, + T: 'static, + W: 'static + Render, + { + debug_assert!( + self.drag_listener.is_none(), + "calling on_drag more than once on the same element is not supported" + ); + self.drag_listener = Some(DragListener { + value: Arc::new(value), + render: Box::new(move |value, offset, window, cx| { + constructor(value.downcast_ref().unwrap(), offset, window, cx).into() + }), + external_payload: None, + }); + } + + /// Registers a callback resolving a payload to offer the platform if a drag started by this + /// element leaves the window. It is invoked at most once per drag gesture, when the pointer + /// exits the viewport. Must be called after [`Self::on_drag`], with the same dragged value + /// type `T`. + pub fn external_drag_payload( + &mut self, + resolver: impl Fn(&T, &mut Window, &mut App) -> Option + 'static, + ) where + Self: Sized, + T: 'static, + { + let Some(drag_listener) = self.drag_listener.as_mut() else { + debug_assert!(false, "external_drag_payload must be called after on_drag"); + return; + }; + debug_assert!( + drag_listener.value.as_ref().type_id() == TypeId::of::(), + "external_drag_payload must use the same dragged value type as on_drag" + ); + debug_assert!( + drag_listener.external_payload.is_none(), + "calling external_drag_payload more than once on the same element is not supported" + ); + drag_listener.external_payload = Some(Box::new(move |value, window, cx| { + resolver(value.downcast_ref::()?, window, cx) + })); + } + + /// Bind the given callback on the hover start and end events of this element. Note that the boolean + /// passed to the callback is true when the hover starts and false when it ends. + /// Transitions caused by layout changes under a stationary mouse also invoke the callback. + /// + /// By default, keyboard input suppresses hover until the next mouse move, mouse down, or touch. Set + /// [`HoverListenerMode::InputModalityIndependent`] with [`Self::hover_listener_mode`] to + /// continue hit-testing hover after keyboard input. + /// The imperative API equivalent to [`StatefulInteractiveElement::on_hover`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + pub fn on_hover(&mut self, listener: impl Fn(&bool, &mut Window, &mut App) + 'static) + where + Self: Sized, + { + debug_assert!( + self.hover_listener.is_none(), + "calling on_hover more than once on the same element is not supported" + ); + self.hover_listener = Some(Box::new(listener)); + } + + /// Sets how [`Self::on_hover`] responds to key presses while the mouse is stationary. + /// This affects only the hover listener, not hover styles or tooltips. The imperative API + /// equivalent to [`StatefulInteractiveElement::hover_listener_mode`]. + pub fn hover_listener_mode(&mut self, mode: HoverListenerMode) + where + Self: Sized, + { + self.hover_listener_mode = mode; + } + + /// Constructs a tooltip when the element is hovered or long-pressed. + /// The imperative API equivalent to [`StatefulInteractiveElement::tooltip`]. + pub fn tooltip(&mut self, build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) + where + Self: Sized, + { + debug_assert!( + self.tooltip_builder.is_none(), + "calling tooltip more than once on the same element is not supported" + ); + self.tooltip_builder = Some(TooltipBuilder { + build: Rc::new(build_tooltip), + hoverable: false, + }); + } + + /// Constructs a tooltip when the element is hovered or long-pressed. + /// The tooltip itself is also hoverable and won't disappear when the user moves the mouse into + /// the tooltip. The imperative API equivalent to [`StatefulInteractiveElement::hoverable_tooltip`]. + pub fn hoverable_tooltip( + &mut self, + build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static, + ) where + Self: Sized, + { + debug_assert!( + self.tooltip_builder.is_none(), + "calling tooltip more than once on the same element is not supported" + ); + self.tooltip_builder = Some(TooltipBuilder { + build: Rc::new(build_tooltip), + hoverable: true, + }); + } + + /// Sets the delay before this element's tooltip is shown on hover. + /// + /// Touch long presses show the tooltip immediately once the gesture is recognized. + /// The imperative API equivalent to [`StatefulInteractiveElement::tooltip_show_delay`]. + pub fn tooltip_show_delay(&mut self, delay: Duration) { + self.tooltip_show_delay = Some(delay); + } + + /// Block the mouse from all interactions with elements behind this element's hitbox. Typically + /// `block_mouse_except_scroll` should be preferred. + /// + /// The imperative API equivalent to [`InteractiveElement::occlude`] + pub fn occlude_mouse(&mut self) { + self.hitbox_behavior = HitboxBehavior::BlockMouse; + } + + /// Set the bounds of this element as a window control area for the platform window. + /// The imperative API equivalent to [`InteractiveElement::window_control_area`] + pub fn window_control_area(&mut self, area: WindowControlArea) { + self.window_control = Some(area); + } + + /// Block non-scroll mouse interactions with elements behind this element's hitbox. + /// The imperative API equivalent to [`InteractiveElement::block_mouse_except_scroll`]. + /// + /// See [`Hitbox::is_hovered`] for details. + pub fn block_mouse_except_scroll(&mut self) { + self.hitbox_behavior = HitboxBehavior::BlockMouseExceptScroll; + } + + fn has_pinch_listeners(&self) -> bool { + !self.pinch_listeners.is_empty() + } +} + +/// A trait for elements that want to use the standard GPUI event handlers that don't +/// require any state. +pub trait InteractiveElement: Sized { + /// Retrieve the interactivity state associated with this element + fn interactivity(&mut self) -> &mut Interactivity; + + /// Assign this element to a group of elements that can be styled together + fn group(mut self, group: impl Into) -> Self { + self.interactivity().group = Some(group.into()); + self + } + + /// Assign this element an ID, so that it can be used with interactivity + fn id(mut self, id: impl Into) -> Stateful { + self.interactivity().element_id = Some(id.into()); + + Stateful { element: self } + } + + /// Track the focus state of the given focus handle on this element. + /// If the focus handle is focused by the application, this element will + /// apply its focused styles. + fn track_focus(mut self, focus_handle: &FocusHandle) -> Self { + self.interactivity().focusable = true; + self.interactivity().tracked_focus_handle = Some(focus_handle.clone()); + self + } + + /// Set whether this element is a tab stop. + /// + /// When false, the element remains in tab-index order but cannot be reached via keyboard navigation. + /// Useful for container elements: focus the container, then call `window.focus_next(cx)` to focus + /// the first tab stop inside it while having the container element itself be unreachable via the keyboard. + /// Should only be used with `tab_index`. + fn tab_stop(mut self, tab_stop: bool) -> Self { + self.interactivity().tab_stop = tab_stop; + self + } + + /// Set index of the tab stop order, and set this node as a tab stop. + /// This will default the element to being a tab stop. See [`Self::tab_stop`] for more information. + /// This should only be used in conjunction with `tab_group` + /// in order to not interfere with the tab index of other elements. + fn tab_index(mut self, index: isize) -> Self { + self.interactivity().focusable = true; + self.interactivity().tab_index = Some(index); + self.interactivity().tab_stop = true; + self + } + + /// Designate this div as a "tab group". Tab groups have their own location in the tab-index order, + /// but for children of the tab group, the tab index is reset to 0. This can be useful for swapping + /// the order of tab stops within the group, without having to renumber all the tab stops in the whole + /// application. + fn tab_group(mut self) -> Self { + self.interactivity().tab_group = true; + if self.interactivity().tab_index.is_none() { + self.interactivity().tab_index = Some(0); + } + self + } + + /// Set the keymap context for this element. This will be used to determine + /// which action to dispatch from the keymap. + fn key_context(mut self, key_context: C) -> Self + where + C: TryInto, + E: std::fmt::Display, + { + if let Some(key_context) = key_context.try_into().log_err() { + self.interactivity().key_context = Some(key_context); + } + self + } + + /// Apply the given style to this element when the mouse hovers over it + fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self { + debug_assert!( + self.interactivity().hover_style.is_none(), + "hover style already set" + ); + self.interactivity().hover_style = Some(Box::new(f(StyleRefinement::default()))); + self + } + + /// Apply the given style to this element when the mouse hovers over a group member + fn group_hover( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self { + self.interactivity().group_hover_style = Some(GroupStyle { + group: group_name.into(), + style: Box::new(f(StyleRefinement::default())), + }); + self + } + + /// Bind the given callback to the mouse down event for the given mouse button. + /// The fluent API equivalent to [`Interactivity::on_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to the view state from this callback. + #[inline(always)] + fn on_mouse_down( + mut self, + button: MouseButton, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_down(button, listener); + self + } + + /// Set a key that can be used to look up this element's bounds + /// in the [`crate::VisualTestContext::debug_bounds`] map. + /// + /// Selectors are only recorded in debug builds with the `test-support` + /// feature. Elsewhere this is a no-op, so `test-support` can stay enabled + /// in release builds without the per-frame cost. + #[cfg(any(test, all(debug_assertions, feature = "test-support")))] + fn debug_selector(mut self, f: impl FnOnce() -> String) -> Self { + self.interactivity().debug_selector = Some(f()); + self + } + + /// Set a key that can be used to look up this element's bounds + /// in the [`crate::VisualTestContext::debug_bounds`] map. + /// + /// Selectors are only recorded in debug builds with the `test-support` + /// feature. Elsewhere this is a no-op, so `test-support` can stay enabled + /// in release builds without the per-frame cost. + #[cfg(not(any(test, all(debug_assertions, feature = "test-support"))))] + #[inline] + fn debug_selector(self, _: impl FnOnce() -> String) -> Self { + self + } + + /// Bind the given callback to the mouse down event for any button, during the capture phase. + /// The fluent API equivalent to [`Interactivity::capture_any_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_any_mouse_down( + mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_any_mouse_down(listener); + self + } + + /// Bind the given callback to the mouse down event for any button, during the capture phase. + /// The fluent API equivalent to [`Interactivity::on_any_mouse_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_any_mouse_down( + mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_any_mouse_down(listener); + self + } + + /// Bind the given callback to the mouse up event for the given button, during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_mouse_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_up( + mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_up(button, listener); + self + } + + /// Bind the given callback to the mouse up event for any button, during the capture phase. + /// The fluent API equivalent to [`Interactivity::capture_any_mouse_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_any_mouse_up( + mut self, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_any_mouse_up(listener); + self + } + + /// Bind the given callback to the mouse pressure event, during the bubble phase + /// the fluent API equivalent to [`Interactivity::on_mouse_pressure`] + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_pressure( + mut self, + listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_pressure(listener); + self + } + + /// Bind the given callback to the mouse pressure event, during the capture phase + /// the fluent API equivalent to [`Interactivity::on_mouse_pressure`] + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_mouse_pressure( + mut self, + listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_mouse_pressure(listener); + self + } + + /// Bind the given callback to the mouse down event, on any button, during the capture phase, + /// when the mouse is outside of the bounds of this element. + /// The fluent API equivalent to [`Interactivity::on_mouse_down_out`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_down_out( + mut self, + listener: impl Fn(&MouseDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_down_out(listener); + self + } + + /// Bind the given callback to the mouse up event, for the given button, during the capture phase, + /// when the mouse is outside of the bounds of this element. + /// The fluent API equivalent to [`Interactivity::on_mouse_up_out`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_up_out( + mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_up_out(button, listener); + self + } + + /// Bind the given callback to the mouse move event, during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_mouse_move`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_move( + mut self, + listener: impl Fn(&MouseMoveEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_move(listener); + self + } + + /// Bind the given callback to the mouse exit event, during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_mouse_exit`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_mouse_exit( + mut self, + listener: impl Fn(&MouseExitEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_mouse_exit(listener); + self + } + + /// Bind the given callback to [`FileDropEvent::Exited`] when a platform file drag + /// leaves this element's window while the element is hovered. + /// + /// This is a window-local exit event, not notification that the platform drag session ended. + /// The fluent API equivalent to [`Interactivity::on_file_drop_exit`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_file_drop_exit( + mut self, + listener: impl Fn(&FileDropEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_file_drop_exit(listener); + self + } + + /// Bind the given callback to the mouse drag event of the given type. Note that this + /// will be called for all move events, inside or outside of this element, as long as the + /// drag was started with this element under the mouse. Useful for implementing draggable + /// UIs that don't conform to a drag and drop style interaction, like resizing. + /// The fluent API equivalent to [`Interactivity::on_drag_move`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_drag_move( + mut self, + listener: impl Fn(&DragMoveEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_drag_move(listener); + self + } + + /// Bind the given callback to scroll wheel events during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_scroll_wheel`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_scroll_wheel( + mut self, + listener: impl Fn(&ScrollWheelEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_scroll_wheel(listener); + self + } + + /// Bind the given callback to pinch gesture events during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_pinch`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_pinch(mut self, listener: impl Fn(&PinchEvent, &mut Window, &mut App) + 'static) -> Self { + self.interactivity().on_pinch(listener); + self + } + + /// Bind the given callback to pinch gesture events during the capture phase. + /// The fluent API equivalent to [`Interactivity::capture_pinch`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_pinch( + mut self, + listener: impl Fn(&PinchEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_pinch(listener); + self + } + /// Capture the given action, before normal action dispatch can fire. + /// The fluent API equivalent to [`Interactivity::capture_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_action( + mut self, + listener: impl Fn(&A, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_action(listener); + self + } + + /// Bind the given callback to an action dispatch during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + #[track_caller] + #[inline(always)] + fn on_action( + mut self, + listener: impl Fn(&A, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_action(listener); + self + } + + /// Bind the given callback to an action dispatch, based on a dynamic action parameter + /// instead of a type parameter. Useful for component libraries that want to expose + /// action bindings to their users. + /// The fluent API equivalent to [`Interactivity::on_boxed_action`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_boxed_action( + mut self, + action: &dyn Action, + listener: impl Fn(&dyn Action, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_boxed_action(action, listener); + self + } + + /// Bind the given callback to key down events during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_key_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_key_down( + mut self, + listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_key_down(listener); + self + } + + /// Bind the given callback to key down events during the capture phase. + /// The fluent API equivalent to [`Interactivity::capture_key_down`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_key_down( + mut self, + listener: impl Fn(&KeyDownEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_key_down(listener); + self + } + + /// Bind the given callback to key up events during the bubble phase. + /// The fluent API equivalent to [`Interactivity::on_key_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_key_up( + mut self, + listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_key_up(listener); + self + } + + /// Bind the given callback to key up events during the capture phase. + /// The fluent API equivalent to [`Interactivity::capture_key_up`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn capture_key_up( + mut self, + listener: impl Fn(&KeyUpEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().capture_key_up(listener); + self + } + + /// Bind the given callback to modifiers changing events. + /// The fluent API equivalent to [`Interactivity::on_modifiers_changed`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + #[inline(always)] + fn on_modifiers_changed( + mut self, + listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_modifiers_changed(listener); + self + } + + /// Apply the given style when the given data type is dragged over this element + fn drag_over( + mut self, + f: impl 'static + Fn(StyleRefinement, &S, &mut Window, &mut App) -> StyleRefinement, + ) -> Self { + self.interactivity().drag_over_styles.push(( + TypeId::of::(), + Box::new(move |currently_dragged: &dyn Any, window, cx| { + f( + StyleRefinement::default(), + currently_dragged.downcast_ref::().unwrap(), + window, + cx, + ) + }), + )); + self + } + + /// Apply the given style when the given data type is dragged over this element's group + fn group_drag_over( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self { + self.interactivity().group_drag_over_styles.push(( + TypeId::of::(), + GroupStyle { + group: group_name.into(), + style: Box::new(f(StyleRefinement::default())), + }, + )); + self + } + + /// Bind the given callback to drop events of the given type, whether or not the drag started on this element. + /// The fluent API equivalent to [`Interactivity::on_drop`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_drop( + mut self, + listener: impl Fn(&T, &mut Window, &mut App) + 'static, + ) -> Self { + self.interactivity().on_drop(listener); + self + } + + /// Use the given predicate to determine whether or not a drop event should be dispatched to this element. + /// The fluent API equivalent to [`Interactivity::can_drop`]. + fn can_drop( + mut self, + predicate: impl Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static, + ) -> Self { + self.interactivity().can_drop(predicate); + self + } + + /// Block the mouse from all interactions with elements behind this element's hitbox. Typically + /// `block_mouse_except_scroll` should be preferred. + /// The fluent API equivalent to [`Interactivity::occlude_mouse`]. + fn occlude(mut self) -> Self { + self.interactivity().occlude_mouse(); + self + } + + /// Set the bounds of this element as a window control area for the platform window. + /// The fluent API equivalent to [`Interactivity::window_control_area`]. + fn window_control_area(mut self, area: WindowControlArea) -> Self { + self.interactivity().window_control_area(area); + self + } + + /// Block non-scroll mouse interactions with elements behind this element's hitbox. + /// The fluent API equivalent to [`Interactivity::block_mouse_except_scroll`]. + /// + /// See [`Hitbox::is_hovered`] for details. + fn block_mouse_except_scroll(mut self) -> Self { + self.interactivity().block_mouse_except_scroll(); + self + } + + /// Set the given styles to be applied when this element, specifically, is focused. + /// Requires that the element is focusable. Elements can be made focusable using [`InteractiveElement::track_focus`]. + fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().focus_style = Some(Box::new(f(StyleRefinement::default()))); + self + } + + /// Set the given styles to be applied when this element is inside another element that is focused. + /// Requires that the element is focusable. Elements can be made focusable using [`InteractiveElement::track_focus`]. + fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().in_focus_style = Some(Box::new(f(StyleRefinement::default()))); + self + } + + /// Set the given styles to be applied when this element is focused via keyboard navigation. + /// This is similar to CSS's `:focus-visible` pseudo-class - it only applies when the element + /// is focused AND the user is navigating via keyboard (not mouse clicks). + /// Requires that the element is focusable. Elements can be made focusable using [`InteractiveElement::track_focus`]. + fn focus_visible(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().focus_visible_style = Some(Box::new(f(StyleRefinement::default()))); + self + } +} + +/// A trait for elements that want to use the standard GPUI interactivity features +/// that require state. +pub trait StatefulInteractiveElement: InteractiveElement { + /// Set the accessible role for this element. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + fn role(mut self, role: accesskit::Role) -> Self { + debug_assert!( + role != accesskit::Role::GenericContainer, + "GenericContainer is filtered out of the a11y tree and has no effect" + ); + self.interactivity().override_role = Some(role); + self + } + + /// Set the author-provided identifier exposed to accessibility clients. + /// + /// Unlike the GPUI element ID, this value is visible outside the process. + /// Keep it stable and unique within its accessibility tree. + /// AccessKit maps it to platform identifiers where supported, including + /// UIA `AutomationId` on Windows, `AXIdentifier` on macOS, and AT-SPI + /// `AccessibleId` on Linux stacks whose deployed adapter exposes it. + fn accessibility_id(mut self, id: impl Into) -> Self { + self.interactivity().aria.author_id = Some(id.into()); + self + } + + /// Set the accessible label for this element. + fn aria_label(mut self, label: impl Into) -> Self { + self.interactivity().aria.label = Some(label.into()); + self + } + + /// Set the accessible description for this element. Unlike the label (which + /// names the element), the description provides supplementary information + /// that assistive technology announces after the name, role, and value - + /// for example a settings subtitle or a hint. + fn aria_description(mut self, description: impl Into) -> Self { + self.interactivity().aria.description = Some(description.into()); + self + } + + /// Set the keyboard shortcut(s) that activate this element, announced by + /// assistive technology (maps to AccessKit's `keyboard_shortcut`). + /// + /// Note that this does not create a keymap. It simply instructs assistive + /// technology what the keymap is. + fn aria_keyshortcuts(mut self, keyshortcuts: impl Into) -> Self { + self.interactivity().aria.keyshortcuts = Some(keyshortcuts.into()); + self + } + + /// Report this element as the focused node in the accessibility tree, + /// overriding the element that holds real keyboard focus — but only while + /// one of its ancestors actually holds focus. + /// + /// This implements the `aria-activedescendant` pattern for composite + /// widgets that keep keyboard focus on a container (e.g. a menu or + /// listbox) while a child is "selected": set this on the selected child so + /// assistive technology announces and highlights it as focused. + /// + /// The element must also have a [`role`][Self::role] (and an id) so it + /// produces an accessibility node. Unlike the web's container-side + /// `aria-activedescendant`, this is set on the descendant; GPUI honors it + /// only when a focused ancestor is present in the tree, so it is safe to + /// set unconditionally on the selected child — if the container isn't + /// focused, the claim is ignored. + fn aria_active_descendant(mut self) -> Self { + self.interactivity().report_active_descendant_focus = true; + self + } + + /// Contribute synthetic accessibility nodes — nodes that don't correspond + /// to any element — as children of this element's a11y node. For example, + /// text runs describing an editor's text content. + /// + /// The closure is called after this element is prepainted, and only if it + /// contributed a node to the accessibility tree (i.e. it has an id and a + /// [`role`][StatefulInteractiveElement::role]). + /// + /// See [`Element::a11y_synthetic_children`] for details. + fn a11y_synthetic_children( + mut self, + f: impl FnOnce(&mut crate::A11ySubtreeBuilder) + 'static, + ) -> Self { + self.interactivity().a11y_synthetic_children = Some(Box::new(f)); + self + } + + /// Set the selected state for this element. + fn aria_selected(mut self, selected: bool) -> Self { + self.interactivity().aria.selected = Some(selected); + self + } + + /// Set the expanded state for this element. + fn aria_expanded(mut self, expanded: bool) -> Self { + self.interactivity().aria.expanded = Some(expanded); + self + } + + /// Set the toggled state for this element. + fn aria_toggled(mut self, toggled: accesskit::Toggled) -> Self { + self.interactivity().aria.toggled = Some(toggled); + self + } + + /// Set the numeric value for this element. + fn aria_numeric_value(mut self, value: f64) -> Self { + self.interactivity().aria.numeric_value = Some(value); + self + } + + /// Set the step by which assistive technology should expect the numeric + /// value of this element to change (e.g. when incrementing a spin button). + fn aria_numeric_value_step(mut self, step: f64) -> Self { + self.interactivity().aria.numeric_value_step = Some(step); + self + } + + /// Set the string value of this element, e.g. the text content of a simple + /// text input. + fn aria_value(mut self, value: impl Into) -> Self { + self.interactivity().aria.value = Some(value.into()); + self + } + + /// Set the placeholder text reported to assistive technology for this + /// element, shown when a text input is empty. + fn aria_placeholder(mut self, placeholder: impl Into) -> Self { + self.interactivity().aria.placeholder = Some(placeholder.into()); + self + } + + /// Set the minimum numeric value for this element. + fn aria_min_numeric_value(mut self, value: f64) -> Self { + self.interactivity().aria.min_numeric_value = Some(value); + self + } + + /// Set the maximum numeric value for this element. + fn aria_max_numeric_value(mut self, value: f64) -> Self { + self.interactivity().aria.max_numeric_value = Some(value); + self + } + + /// Set the orientation of this element. + fn aria_orientation(mut self, orientation: accesskit::Orientation) -> Self { + self.interactivity().aria.orientation = Some(orientation); + self + } + + /// Set the heading level of this element. + fn aria_level(mut self, level: usize) -> Self { + self.interactivity().aria.level = Some(level); + self + } + + /// Set the position in set of this element. + fn aria_position_in_set(mut self, position: usize) -> Self { + self.interactivity().aria.position_in_set = Some(position); + self + } + + /// Set the size of set for this element. + fn aria_size_of_set(mut self, size: usize) -> Self { + self.interactivity().aria.size_of_set = Some(size); + self + } + + /// Set the row index for this element. + fn aria_row_index(mut self, index: usize) -> Self { + self.interactivity().aria.row_index = Some(index); + self + } + + /// Set the column index for this element. + fn aria_column_index(mut self, index: usize) -> Self { + self.interactivity().aria.column_index = Some(index); + self + } + + /// Set the row count for this element. + fn aria_row_count(mut self, count: usize) -> Self { + self.interactivity().aria.row_count = Some(count); + self + } + + /// Set the column count for this element. + fn aria_column_count(mut self, count: usize) -> Self { + self.interactivity().aria.column_count = Some(count); + self + } + + /// Register a handler for an accessibility action on this element. + /// The handler is called when a screen reader requests the given action. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + #[inline(always)] + fn on_a11y_action( + mut self, + action: accesskit::Action, + listener: impl FnMut(Option<&accesskit::ActionData>, &mut crate::Window, &mut crate::App) + + 'static, + ) -> Self { + self.interactivity() + .a11y_action_listeners + .push((action, Box::new(listener))); + self + } + + /// Set this element to focusable. + fn focusable(mut self) -> Self { + self.interactivity().focusable = true; + self + } + + /// Set the overflow x and y to scroll. + fn overflow_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.x = Some(Overflow::Scroll); + self.interactivity().base_style.overflow.y = Some(Overflow::Scroll); + self + } + + /// Set the overflow x to scroll. + fn overflow_x_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.x = Some(Overflow::Scroll); + self + } + + /// Set the overflow y to scroll. + fn overflow_y_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.y = Some(Overflow::Scroll); + self + } + + /// Restrict scrolling of this element to the axis of the input gesture. + /// + /// See [`Style::restrict_scroll_to_axis`](crate::Style::restrict_scroll_to_axis) for details. + fn restrict_scroll_to_axis(mut self) -> Self { + self.interactivity().base_style.restrict_scroll_to_axis = Some(true); + self + } + + /// Track the scroll state of this element with the given handle. + fn track_scroll(mut self, scroll_handle: &ScrollHandle) -> Self { + self.interactivity().tracked_scroll_handle = Some(scroll_handle.clone()); + self + } + + /// Track the scroll state of this element with the given handle. + fn anchor_scroll(mut self, scroll_anchor: Option) -> Self { + self.interactivity().scroll_anchor = scroll_anchor; + self + } + + /// Set the given styles to be applied when this element is active. + fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().active_style = Some(Box::new(f(StyleRefinement::default()))); + self + } + + /// Set the given styles to be applied when this element's group is active. + fn group_active( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self + where + Self: Sized, + { + self.interactivity().group_active_style = Some(GroupStyle { + group: group_name.into(), + style: Box::new(f(StyleRefinement::default())), + }); + self + } + + /// Bind the given callback to click events of this element. + /// The fluent API equivalent to [`Interactivity::on_click`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + #[inline(always)] + fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self + where + Self: Sized, + { + self.interactivity().on_click(listener); + self + } + + /// Bind the given callback to non-primary click events of this element. + /// The fluent API equivalent to [`Interactivity::on_aux_click`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_aux_click( + mut self, + listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().on_aux_click(listener); + self + } + + /// On drag initiation, this callback will be used to create a new view to render the dragged value for a + /// drag and drop operation. This API should also be used as the equivalent of 'on drag start' with + /// the [`InteractiveElement::on_drag_move`] API. + /// The callback also has access to the offset of triggering click from the origin of parent element. + /// The fluent API equivalent to [`Interactivity::on_drag`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_drag( + mut self, + value: T, + constructor: impl Fn(&T, Point, &mut Window, &mut App) -> Entity + 'static, + ) -> Self + where + Self: Sized, + T: 'static, + W: 'static + Render, + { + self.interactivity().on_drag(value, constructor); + self + } + + /// Registers a callback resolving a payload to offer the platform if a drag started by this + /// element leaves the window. It is invoked at most once per drag gesture, when the pointer + /// exits the viewport. Must be called after [`Self::on_drag`], with the same dragged value + /// type `T`. + /// The fluent API equivalent to [`Interactivity::external_drag_payload`]. + fn external_drag_payload( + mut self, + resolver: impl Fn(&T, &mut Window, &mut App) -> Option + 'static, + ) -> Self + where + Self: Sized, + T: 'static, + { + self.interactivity().external_drag_payload(resolver); + self + } + + /// Bind the given callback on the hover start and end events of this element. Note that the boolean + /// passed to the callback is true when the hover starts and false when it ends. + /// Transitions caused by layout changes under a stationary mouse also invoke the callback. + /// + /// By default, keyboard input suppresses hover until the next mouse move, mouse down, or touch. Set + /// [`HoverListenerMode::InputModalityIndependent`] with [`Self::hover_listener_mode`] to + /// continue hit-testing hover after keyboard input. + /// The fluent API equivalent to [`Interactivity::on_hover`]. + /// + /// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback. + fn on_hover(mut self, listener: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self + where + Self: Sized, + { + self.interactivity().on_hover(listener); + self + } + + /// Sets how [`Self::on_hover`] responds to key presses while the mouse is stationary. + /// This affects only the hover listener, not hover styles or tooltips. The fluent API + /// equivalent to [`Interactivity::hover_listener_mode`]. + fn hover_listener_mode(mut self, mode: HoverListenerMode) -> Self + where + Self: Sized, + { + self.interactivity().hover_listener_mode(mode); + self + } + + /// Constructs a tooltip when the element is hovered or long-pressed. + /// The fluent API equivalent to [`Interactivity::tooltip`]. + fn tooltip(mut self, build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self + where + Self: Sized, + { + self.interactivity().tooltip(build_tooltip); + self + } + + /// Constructs a tooltip when the element is hovered or long-pressed. + /// The tooltip itself is also hoverable and won't disappear when the user moves the mouse into + /// the tooltip. The fluent API equivalent to [`Interactivity::hoverable_tooltip`]. + fn hoverable_tooltip( + mut self, + build_tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().hoverable_tooltip(build_tooltip); + self + } + + /// Sets the delay before this element's tooltip is shown on hover. + /// + /// Touch long presses show the tooltip immediately once the gesture is recognized. + /// The fluent API equivalent to [`Interactivity::tooltip_show_delay`]. + fn tooltip_show_delay(mut self, delay: Duration) -> Self + where + Self: Sized, + { + self.interactivity().tooltip_show_delay(delay); + self + } +} + +pub(crate) type MouseDownListener = + Box; +pub(crate) type MouseUpListener = + Box; +pub(crate) type MousePressureListener = + Box; +pub(crate) type MouseMoveListener = + Box; +pub(crate) type MouseExitListener = + Box; + +pub(crate) type FileDropExitListener = + Box; + +pub(crate) type ScrollWheelListener = + Box; + +pub(crate) type PinchListener = + Box; + +pub(crate) type ClickListener = Rc; + +/// Controls how [`StatefulInteractiveElement::on_hover`] responds to key presses while the mouse +/// is stationary. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub enum HoverListenerMode { + /// Use input-modality-aware hit testing. Keyboard input suppresses hover until the mouse moves + /// again, unless pointer capture or an active mouse-down interaction keeps the listener hovered. + #[default] + InputModalityAware, + /// Use hit testing even when the last input was from the keyboard. This changes only + /// keyboard-modality filtering; all other [`StatefulInteractiveElement::on_hover`] behavior + /// remains unchanged. + InputModalityIndependent, +} + +impl HoverListenerMode { + fn is_hovered(self, hitbox: &Hitbox, window: &Window) -> bool { + match self { + Self::InputModalityAware => hitbox.is_hovered(window), + Self::InputModalityIndependent => hitbox.id.is_hovered_ignoring_last_input(window), + } + } +} + +pub(crate) struct DragListener { + value: Arc, + render: Box, &mut Window, &mut App) -> AnyView + 'static>, + external_payload: Option, +} + +type ExternalDragPayloadResolver = + Box Option + 'static>; + +type DropListener = Box; + +type CanDropPredicate = Box bool + 'static>; + +pub(crate) struct TooltipBuilder { + build: Rc AnyView + 'static>, + hoverable: bool, +} + +pub(crate) type KeyDownListener = + Box; + +pub(crate) type KeyUpListener = + Box; + +pub(crate) type ModifiersChangedListener = + Box; + +pub(crate) type ActionListener = + Box; + +/// Construct a new [`Div`] element +#[track_caller] +pub fn div() -> Div { + Div { + interactivity: Interactivity::new(), + children: SmallVec::default(), + prepaint_listener: None, + image_cache: None, + prepaint_order_fn: None, + } +} + +/// A [`Div`] element, the all-in-one element for building complex UIs in GPUI +pub struct Div { + interactivity: Interactivity, + children: SmallVec<[StackSafe; 2]>, + prepaint_listener: Option>, &mut Window, &mut App) + 'static>>, + image_cache: Option>, + prepaint_order_fn: Option SmallVec<[usize; 8]>>>, +} + +impl Div { + /// Add a listener to be called when the children of this `Div` are prepainted. + /// This allows you to store the [`Bounds`] of the children for later use. + pub fn on_children_prepainted( + mut self, + listener: impl Fn(Vec>, &mut Window, &mut App) + 'static, + ) -> Self { + self.prepaint_listener = Some(Box::new(listener)); + self + } + + /// Add an image cache at the location of this div in the element tree. + pub fn image_cache(mut self, cache: impl ImageCacheProvider) -> Self { + self.image_cache = Some(Box::new(cache)); + self + } + + /// Specify a function that determines the order in which children are prepainted. + /// + /// The function is called at prepaint time and should return a vector of child indices + /// in the desired prepaint order. Each index should appear exactly once. + /// + /// This is useful when the prepaint of one child affects state that another child reads. + /// For example, in split editor views, the editor with an autoscroll request should + /// be prepainted first so its scroll position update is visible to the other editor. + pub fn with_dynamic_prepaint_order( + mut self, + order_fn: impl Fn(&mut Window, &mut App) -> SmallVec<[usize; 8]> + 'static, + ) -> Self { + self.prepaint_order_fn = Some(Box::new(order_fn)); + self + } +} + +/// A frame state for a `Div` element, which contains layout IDs for its children. +/// +/// This struct is used internally by the `Div` element to manage the layout state of its children +/// during the UI update cycle. It holds a small vector of `LayoutId` values, each corresponding to +/// a child element of the `Div`. These IDs are used to query the layout engine for the computed +/// bounds of the children after the layout phase is complete. +pub struct DivFrameState { + child_layout_ids: SmallVec<[LayoutId; 2]>, +} + +/// Interactivity state displayed an manipulated in the inspector. +#[derive(Clone)] +pub struct DivInspectorState { + /// The inspected element's base style. This is used for both inspecting and modifying the + /// state. In the future it will make sense to separate the read and write, possibly tracking + /// the modifications. + #[cfg(any(feature = "inspector", debug_assertions))] + pub base_style: Box, + /// Inspects the bounds of the element. + pub bounds: Bounds, + /// Size of the children of the element, or `bounds.size` if it has no children. + pub content_size: Size, +} + +impl Styled for Div { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.interactivity.base_style + } +} + +impl InteractiveElement for Div { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity + } +} + +impl ParentElement for Div { + fn extend(&mut self, elements: impl IntoIterator) { + #[cfg(feature = "stacker")] + self.children + .extend(elements.into_iter().map(StackSafe::new)); + #[cfg(not(feature = "stacker"))] + self.children.extend(elements); + } +} + +impl Element for Div { + type RequestLayoutState = DivFrameState; + type PrepaintState = Option; + + fn id(&self) -> Option { + self.interactivity.element_id.clone() + } + + fn source_location(&self) -> Option<&'static std::panic::Location<'static>> { + self.interactivity.source_location() + } + + fn a11y_role(&self) -> Option { + // Nodes with `GenericContainer` should never be reported to accesskit. + // Equivalent to an HTML div with no role. + self.interactivity + .override_role + .filter(|role| *role != accesskit::Role::GenericContainer) + } + + fn write_a11y_info(&self, node: &mut accesskit::Node) { + self.interactivity.write_a11y_info(node); + } + + fn a11y_synthetic_children( + &mut self, + _prepaint: &mut Self::PrepaintState, + builder: &mut crate::A11ySubtreeBuilder, + ) { + if let Some(f) = self.interactivity.a11y_synthetic_children.take() { + f(builder); + } + } + + #[cfg_attr(feature = "stacker", stacksafe::stacksafe)] + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut child_layout_ids = SmallVec::new(); + let image_cache = self + .image_cache + .as_mut() + .map(|provider| provider.provide(window, cx)); + + let layout_id = window.with_image_cache(image_cache, |window| { + self.interactivity.request_layout( + global_id, + inspector_id, + window, + cx, + |style, window, cx| { + window.with_text_style(style.text_style().cloned(), |window| { + child_layout_ids = self + .children + .iter_mut() + .map(|child| child.request_layout(window, cx)) + .collect::>(); + window.request_layout(style, child_layout_ids.iter().copied(), cx) + }) + }, + ) + }); + + (layout_id, DivFrameState { child_layout_ids }) + } + + #[cfg_attr(feature = "stacker", stacksafe::stacksafe)] + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Option { + let image_cache = self + .image_cache + .as_mut() + .map(|provider| provider.provide(window, cx)); + + let has_prepaint_listener = self.prepaint_listener.is_some(); + let mut children_bounds = Vec::with_capacity(if has_prepaint_listener { + request_layout.child_layout_ids.len() + } else { + 0 + }); + + let mut child_min = point(Pixels::MAX, Pixels::MAX); + let mut child_max = Point::default(); + if let Some(handle) = self.interactivity.scroll_anchor.as_ref() { + *handle.last_origin.borrow_mut() = bounds.origin - window.element_offset(); + } + let content_size = if request_layout.child_layout_ids.is_empty() { + bounds.size + } else if let Some(scroll_handle) = self.interactivity.tracked_scroll_handle.as_ref() { + let mut state = scroll_handle.0.borrow_mut(); + state.child_bounds = Vec::with_capacity(request_layout.child_layout_ids.len()); + for child_layout_id in &request_layout.child_layout_ids { + let child_bounds = window.layout_bounds(*child_layout_id); + child_min = child_min.min(&child_bounds.origin); + child_max = child_max.max(&child_bounds.bottom_right()); + state.child_bounds.push(child_bounds); + } + (child_max - child_min).into() + } else { + for child_layout_id in &request_layout.child_layout_ids { + let child_bounds = window.layout_bounds(*child_layout_id); + child_min = child_min.min(&child_bounds.origin); + child_max = child_max.max(&child_bounds.bottom_right()); + + if has_prepaint_listener { + children_bounds.push(child_bounds); + } + } + (child_max - child_min).into() + }; + + if let Some(scroll_handle) = self.interactivity.tracked_scroll_handle.as_ref() { + scroll_handle.scroll_to_active_item(); + } + + self.interactivity.prepaint( + global_id, + inspector_id, + bounds, + content_size, + window, + cx, + |style, scroll_offset, hitbox, window, cx| { + // skip children + if style.display == Display::None { + return hitbox; + } + + window.with_image_cache(image_cache, |window| { + window.with_element_offset(scroll_offset, |window| { + if let Some(order_fn) = &self.prepaint_order_fn { + let order = order_fn(window, cx); + for idx in order { + if let Some(child) = self.children.get_mut(idx) { + child.prepaint(window, cx); + } + } + } else { + for child in &mut self.children { + child.prepaint(window, cx); + } + } + }); + + if let Some(listener) = self.prepaint_listener.as_ref() { + listener(children_bounds, window, cx); + } + }); + + hitbox + }, + ) + } + + #[cfg_attr(feature = "stacker", stacksafe::stacksafe)] + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + hitbox: &mut Option, + window: &mut Window, + cx: &mut App, + ) { + let image_cache = self + .image_cache + .as_mut() + .map(|provider| provider.provide(window, cx)); + + window.with_image_cache(image_cache, |window| { + self.interactivity.paint( + global_id, + inspector_id, + bounds, + hitbox.as_ref(), + window, + cx, + |style, window, cx| { + // skip children + if style.display == Display::None { + return; + } + + for child in &mut self.children { + child.paint(window, cx); + } + }, + ) + }); + } +} + +impl IntoElement for Div { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +#[derive(Default)] +pub(crate) struct AriaProperties { + pub(crate) author_id: Option, + pub(crate) label: Option, + pub(crate) description: Option, + pub(crate) keyshortcuts: Option, + pub(crate) selected: Option, + pub(crate) expanded: Option, + pub(crate) toggled: Option, + pub(crate) numeric_value: Option, + pub(crate) min_numeric_value: Option, + pub(crate) max_numeric_value: Option, + pub(crate) numeric_value_step: Option, + pub(crate) value: Option, + pub(crate) placeholder: Option, + pub(crate) orientation: Option, + pub(crate) level: Option, + pub(crate) position_in_set: Option, + pub(crate) size_of_set: Option, + pub(crate) row_index: Option, + pub(crate) column_index: Option, + pub(crate) row_count: Option, + pub(crate) column_count: Option, +} + +/// The interactivity struct. Powers all of the general-purpose +/// interactivity in the `Div` element. +#[derive(Default)] +pub struct Interactivity { + /// The element ID of the element. In id is required to support a stateful subset of the interactivity such as on_click. + pub element_id: Option, + /// Whether the element was clicked. This will only be present after layout. + pub active: Option, + /// Whether the element was hovered. This will only be present after paint if an hitbox + /// was created for the interactive element. + pub hovered: Option, + pub(crate) tooltip_id: Option, + pub(crate) content_size: Size, + pub(crate) key_context: Option, + pub(crate) focusable: bool, + pub(crate) tracked_focus_handle: Option, + pub(crate) tracked_scroll_handle: Option, + pub(crate) scroll_anchor: Option, + pub(crate) scroll_offset: Option>>>, + pub(crate) ongoing_scroll: Option>>, + pub(crate) group: Option, + /// The base style of the element, before any modifications are applied + /// by focus, active, etc. + pub base_style: Box, + pub(crate) focus_style: Option>, + pub(crate) in_focus_style: Option>, + pub(crate) focus_visible_style: Option>, + pub(crate) hover_style: Option>, + pub(crate) group_hover_style: Option, + pub(crate) active_style: Option>, + pub(crate) group_active_style: Option, + pub(crate) drag_over_styles: Vec<( + TypeId, + Box StyleRefinement>, + )>, + pub(crate) group_drag_over_styles: Vec<(TypeId, GroupStyle)>, + pub(crate) mouse_down_listeners: Vec, + pub(crate) mouse_up_listeners: Vec, + pub(crate) mouse_pressure_listeners: Vec, + pub(crate) mouse_move_listeners: Vec, + pub(crate) mouse_exit_listeners: Vec, + pub(crate) file_drop_exit_listeners: Vec, + pub(crate) scroll_wheel_listeners: Vec, + pub(crate) pinch_listeners: Vec, + pub(crate) key_down_listeners: Vec, + pub(crate) key_up_listeners: Vec, + pub(crate) modifiers_changed_listeners: Vec, + pub(crate) action_listeners: Vec<(TypeId, ActionListener)>, + pub(crate) drop_listeners: Vec<(TypeId, DropListener)>, + pub(crate) can_drop_predicate: Option, + pub(crate) click_listeners: Vec, + pub(crate) aux_click_listeners: Vec, + pub(crate) drag_listener: Option, + pub(crate) hover_listener: Option>, + pub(crate) hover_listener_mode: HoverListenerMode, + pub(crate) tooltip_builder: Option, + pub(crate) tooltip_show_delay: Option, + pub(crate) window_control: Option, + pub(crate) hitbox_behavior: HitboxBehavior, + pub(crate) tab_index: Option, + pub(crate) tab_group: bool, + pub(crate) tab_stop: bool, + + pub(crate) a11y_action_listeners: + Vec<(accesskit::Action, crate::window::a11y::A11yActionListener)>, + pub(crate) a11y_synthetic_children: Option>, + pub(crate) report_active_descendant_focus: bool, + pub(crate) override_role: Option, + pub(crate) aria: AriaProperties, + + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) source_location: Option<&'static core::panic::Location<'static>>, + + #[cfg(any(test, all(debug_assertions, feature = "test-support")))] + pub(crate) debug_selector: Option, +} + +impl Interactivity { + /// Layout this element according to this interactivity state's configured styles + pub fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + f: impl FnOnce(Style, &mut Window, &mut App) -> LayoutId, + ) -> LayoutId { + #[cfg(any(feature = "inspector", debug_assertions))] + window.with_inspector_state( + _inspector_id, + cx, + |inspector_state: &mut Option, _window| { + if let Some(inspector_state) = inspector_state { + self.base_style = inspector_state.base_style.clone(); + } else { + *inspector_state = Some(DivInspectorState { + base_style: self.base_style.clone(), + bounds: Default::default(), + content_size: Default::default(), + }) + } + }, + ); + + window.with_optional_element_state::( + global_id, + |element_state, window| { + let mut element_state = + element_state.map(|element_state| element_state.unwrap_or_default()); + + if let Some(element_state) = element_state.as_ref() + && cx.has_active_drag() + { + if let Some(pending_mouse_down) = element_state.pending_mouse_down.as_ref() { + *pending_mouse_down.borrow_mut() = None; + } + if let Some(clicked_state) = element_state.clicked_state.as_ref() { + *clicked_state.borrow_mut() = ElementClickedState::default(); + } + } + + // Ensure we store a focus handle in our element state if we're focusable. + // If there's an explicit focus handle we're tracking, use that. Otherwise + // create a new handle and store it in the element state, which lives for as + // as frames contain an element with this id. + if self.focusable + && self.tracked_focus_handle.is_none() + && let Some(element_state) = element_state.as_mut() + { + let mut handle = element_state + .focus_handle + .get_or_insert_with(|| cx.focus_handle()) + .clone() + .tab_stop(self.tab_stop); + + if let Some(index) = self.tab_index { + handle = handle.tab_index(index); + } + + self.tracked_focus_handle = Some(handle); + } + + if let Some(scroll_handle) = self.tracked_scroll_handle.as_ref() { + let scroll_handle_state = scroll_handle.0.borrow(); + self.scroll_offset = Some(scroll_handle_state.offset.clone()); + self.ongoing_scroll = Some(scroll_handle_state.ongoing_scroll.clone()); + } else if (self.base_style.overflow.x == Some(Overflow::Scroll) + || self.base_style.overflow.y == Some(Overflow::Scroll)) + && let Some(element_state) = element_state.as_mut() + { + self.scroll_offset = Some( + element_state + .scroll_offset + .get_or_insert_with(Rc::default) + .clone(), + ); + self.ongoing_scroll = Some( + element_state + .ongoing_scroll + .get_or_insert_with(|| Rc::new(RefCell::new(OngoingScroll::default()))) + .clone(), + ); + } + + let style = self.compute_style_internal(None, element_state.as_mut(), window, cx); + let layout_id = f(style, window, cx); + (layout_id, element_state) + }, + ) + } + + /// Commit the bounds of this element according to this interactivity state's configured styles. + pub fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + content_size: Size, + window: &mut Window, + cx: &mut App, + f: impl FnOnce(&Style, Point, Option, &mut Window, &mut App) -> R, + ) -> R { + self.content_size = content_size; + + #[cfg(any(feature = "inspector", debug_assertions))] + window.with_inspector_state( + _inspector_id, + cx, + |inspector_state: &mut Option, _window| { + if let Some(inspector_state) = inspector_state { + inspector_state.bounds = bounds; + inspector_state.content_size = content_size; + } + }, + ); + + if let Some(focus_handle) = self.tracked_focus_handle.as_ref() { + window.set_focus_handle(focus_handle, cx); + + if window.a11y.is_active() { + if let Some(global_id) = global_id { + let node_id = global_id.accesskit_node_id(); + window.a11y.set_focusable(node_id, focus_handle.id); + if focus_handle.is_focused(window) { + window.a11y.set_focus(node_id); + } + } else if focus_handle.is_focused(window) { + // Focusable, but with no element id it can't have an + // accessibility node, so screen readers fall back to the + // whole window. + window + .a11y + .note_focus_without_node(focus_handle.id, "it has no element id"); + } + } + } + + if self.report_active_descendant_focus && window.a11y.is_active() { + if let Some(global_id) = global_id { + window + .a11y + .set_active_descendant(global_id.accesskit_node_id()); + } + } + window.with_optional_element_state::( + global_id, + |element_state, window| { + let mut element_state = + element_state.map(|element_state| element_state.unwrap_or_default()); + let style = self.compute_style_internal(None, element_state.as_mut(), window, cx); + + if let Some(element_state) = element_state.as_mut() { + if let Some(clicked_state) = element_state.clicked_state.as_ref() { + let clicked_state = clicked_state.borrow(); + self.active = Some(clicked_state.element); + } + if self.hover_style.is_some() || self.group_hover_style.is_some() { + element_state + .hover_state + .get_or_insert_with(Default::default); + } + if let Some(active_tooltip) = element_state.active_tooltip.as_ref() { + if self.tooltip_builder.is_some() { + self.tooltip_id = set_tooltip_on_window(active_tooltip, window); + } else { + // If there is no longer a tooltip builder, remove the active tooltip. + if let Some(long_press_tooltip_active) = + element_state.long_press_tooltip_active.as_ref() + { + long_press_tooltip_active.set(false); + } + element_state.active_tooltip.take(); + } + } + } + + window.with_text_style(style.text_style().cloned(), |window| { + window.with_content_mask( + style.overflow_mask(bounds, window.rem_size()), + |window| { + let hitbox = if self.should_insert_hitbox(&style, window, cx) { + Some(window.insert_hitbox(bounds, self.hitbox_behavior)) + } else { + None + }; + + let scroll_offset = + self.clamp_scroll_position(bounds, &style, window, cx); + let result = f(&style, scroll_offset, hitbox, window, cx); + (result, element_state) + }, + ) + }) + }, + ) + } + + fn should_insert_hitbox(&self, style: &Style, window: &Window, cx: &App) -> bool { + self.hitbox_behavior != HitboxBehavior::Normal + || self.window_control.is_some() + || style.mouse_cursor.is_some() + || self.group.is_some() + || self.scroll_offset.is_some() + || self.tracked_focus_handle.is_some() + || self.hover_style.is_some() + || self.group_hover_style.is_some() + || self.hover_listener.is_some() + || !self.mouse_up_listeners.is_empty() + || !self.mouse_pressure_listeners.is_empty() + || !self.mouse_down_listeners.is_empty() + || !self.mouse_move_listeners.is_empty() + || !self.mouse_exit_listeners.is_empty() + || !self.file_drop_exit_listeners.is_empty() + || !self.click_listeners.is_empty() + || !self.aux_click_listeners.is_empty() + || !self.scroll_wheel_listeners.is_empty() + || self.has_pinch_listeners() + || self.drag_listener.is_some() + || !self.drop_listeners.is_empty() + || !self.drag_over_styles.is_empty() + || self.tooltip_builder.is_some() + || window.is_inspector_picking(cx) + } + + fn clamp_scroll_position( + &self, + bounds: Bounds, + style: &Style, + window: &mut Window, + _cx: &mut App, + ) -> Point { + fn round_to_two_decimals(pixels: Pixels) -> Pixels { + const ROUNDING_FACTOR: f32 = 100.0; + (pixels * ROUNDING_FACTOR).round() / ROUNDING_FACTOR + } + + if let Some(scroll_offset) = self.scroll_offset.as_ref() { + let mut scroll_to_bottom = false; + let mut tracked_scroll_handle = self + .tracked_scroll_handle + .as_ref() + .map(|handle| handle.0.borrow_mut()); + if let Some(mut scroll_handle_state) = tracked_scroll_handle.as_deref_mut() { + scroll_handle_state.overflow = style.overflow; + scroll_to_bottom = mem::take(&mut scroll_handle_state.scroll_to_bottom); + } + + let rem_size = window.rem_size(); + // Taffy lays the box out with the padding snapped to the device pixel + // grid (`to_taffy`); recomputed unsnapped, e.g. py_1 at a fractional + // rem size, it exceeds `bounds` and leaves the box scrollable by the + // sub-pixel difference. + let padding = style + .padding + .to_pixels(bounds.size.into(), rem_size) + .map(|edge| window.pixel_snap(*edge)); + let padding_size = size(padding.left + padding.right, padding.top + padding.bottom); + // The floating point values produced by Taffy and ours often vary + // slightly after ~5 decimal places. This can lead to cases where after + // subtracting these, the container becomes scrollable for less than + // 0.00000x pixels. As we generally don't benefit from a precision that + // high for the maximum scroll, we round the scroll max to 2 decimal + // places here. + let padded_content_size = self.content_size + padding_size; + let scroll_max = Point::from(padded_content_size - bounds.size) + .map(round_to_two_decimals) + .max(&Default::default()); + // Clamp scroll offset in case scroll max is smaller now (e.g., if children + // were removed or the bounds became larger). + let mut scroll_offset = scroll_offset.borrow_mut(); + + scroll_offset.x = scroll_offset.x.clamp(-scroll_max.x, px(0.)); + if scroll_to_bottom { + scroll_offset.y = -scroll_max.y; + } else { + scroll_offset.y = scroll_offset.y.clamp(-scroll_max.y, px(0.)); + } + + if let Some(mut scroll_handle_state) = tracked_scroll_handle { + scroll_handle_state.max_offset = scroll_max; + scroll_handle_state.bounds = bounds; + } + + *scroll_offset + } else { + Point::default() + } + } + + /// Paint this element according to this interactivity state's configured styles + /// and bind the element's mouse and keyboard events. + /// + /// content_size is the size of the content of the element, which may be larger than the + /// element's bounds if the element is scrollable. + /// + /// the final computed style will be passed to the provided function, along + /// with the current scroll offset + pub fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + hitbox: Option<&Hitbox>, + window: &mut Window, + cx: &mut App, + f: impl FnOnce(&Style, &mut Window, &mut App), + ) { + self.hovered = hitbox.map(|hitbox| hitbox.is_hovered(window)); + window.with_optional_element_state::( + global_id, + |element_state, window| { + let mut element_state = + element_state.map(|element_state| element_state.unwrap_or_default()); + + let style = self.compute_style_internal(hitbox, element_state.as_mut(), window, cx); + + #[cfg(any(test, all(debug_assertions, feature = "test-support")))] + if let Some(debug_selector) = &self.debug_selector { + window + .next_frame + .record_debug_bounds(debug_selector.clone(), bounds); + } + + self.paint_hover_group_handler(window, cx); + + if style.visibility == Visibility::Hidden { + return ((), element_state); + } + + let mut tab_group = None; + if self.tab_group { + tab_group = self.tab_index; + } + + window.with_element_opacity(style.opacity, |window| { + style.paint(bounds, window, cx, |window: &mut Window, cx: &mut App| { + window.with_text_style(style.text_style().cloned(), |window| { + window.with_content_mask( + style.overflow_mask(bounds, window.rem_size()), + |window| { + window.with_tab_group(tab_group, |window| { + // Register the container's own focus handle *inside* its + // tab group, so that focusing the container and then + // calling `focus_next` descends into this group's first + // item. Inserting it before `with_tab_group` would give the + // container a shallower tab path than its children; with + // sibling groups every container would then sort ahead of + // every item, and `focus_next` from a container would jump + // to the first item in the whole window instead of its own. + if let Some(focus_handle) = &self.tracked_focus_handle { + window.next_frame.tab_stops.insert(focus_handle); + } + if let Some(hitbox) = hitbox { + #[cfg(debug_assertions)] + self.paint_debug_info( + global_id, hitbox, &style, window, cx, + ); + + if let Some(drag) = cx.active_drag.as_ref() { + if let Some(mouse_cursor) = drag.cursor_style { + window.set_window_cursor_style(mouse_cursor); + } + } else { + if let Some(mouse_cursor) = style.mouse_cursor { + window.set_cursor_style(mouse_cursor, hitbox); + } + } + + if let Some(group) = self.group.clone() { + GroupHitboxes::push(group, hitbox.id, cx); + } + + if let Some(area) = self.window_control { + window.insert_window_control_hitbox( + area, + hitbox.clone(), + ); + } + + self.paint_mouse_listeners( + hitbox, + element_state.as_mut(), + window, + cx, + ); + self.paint_scroll_listener(hitbox, &style, window, cx); + } + + self.paint_keyboard_listeners(window, cx); + + if window.a11y.is_active() { + if let Some(global_id) = global_id { + if !self.a11y_action_listeners.is_empty() { + let node_id = global_id.accesskit_node_id(); + for (action, listener) in + self.a11y_action_listeners.drain(..) + { + window.on_a11y_action( + node_id, action, listener, + ); + } + } + } + } + + f(&style, window, cx); + + if let Some(_hitbox) = hitbox { + #[cfg(any(feature = "inspector", debug_assertions))] + window.insert_inspector_hitbox( + _hitbox.id, + _inspector_id, + cx, + ); + + if let Some(group) = self.group.as_ref() { + GroupHitboxes::pop(group, cx); + } + } + }) + }, + ); + }); + }); + }); + + ((), element_state) + }, + ); + } + + #[cfg(debug_assertions)] + fn paint_debug_info( + &self, + global_id: Option<&GlobalElementId>, + hitbox: &Hitbox, + style: &Style, + window: &mut Window, + cx: &mut App, + ) { + use crate::{BorderStyle, TextAlign}; + + if let Some(global_id) = global_id + && (style.debug || style.debug_below || cx.has_global::()) + && hitbox.is_hovered(window) + { + const FONT_SIZE: crate::Pixels = crate::Pixels(10.); + let element_id = format!("{global_id:?}"); + let str_len = element_id.len(); + + let render_debug_text = |window: &mut Window| { + if let Some(text) = window + .text_system() + .shape_text( + element_id.into(), + FONT_SIZE, + &[window.text_style().to_run(str_len)], + None, + None, + ) + .ok() + .and_then(|mut text| text.pop()) + { + text.paint(hitbox.origin, FONT_SIZE, TextAlign::Left, None, window, cx) + .ok(); + + let text_bounds = crate::Bounds { + origin: hitbox.origin, + size: text.size(FONT_SIZE), + }; + if let Some(source_location) = self.source_location + && text_bounds.contains(&window.mouse_position()) + && window.modifiers().secondary() + { + let secondary_held = window.modifiers().secondary(); + window.on_key_event({ + move |e: &crate::ModifiersChangedEvent, _phase, window, _cx| { + if e.modifiers.secondary() != secondary_held + && text_bounds.contains(&window.mouse_position()) + { + window.refresh(); + } + } + }); + + let was_hovered = hitbox.is_hovered(window); + let current_view = window.current_view(); + window.on_mouse_event({ + let hitbox = hitbox.clone(); + move |_: &MouseMoveEvent, phase, window, cx| { + if phase == DispatchPhase::Capture { + let hovered = hitbox.is_hovered(window); + if hovered != was_hovered { + cx.notify(current_view) + } + } + } + }); + + window.on_mouse_event({ + let hitbox = hitbox.clone(); + move |e: &crate::MouseDownEvent, phase, window, cx| { + if text_bounds.contains(&e.position) + && phase.capture() + && hitbox.is_hovered(window) + { + cx.stop_propagation(); + let Ok(dir) = std::env::current_dir() else { + return; + }; + + eprintln!( + "This element was created at:\n{}:{}:{}", + dir.join(source_location.file()).to_string_lossy(), + source_location.line(), + source_location.column() + ); + } + } + }); + window.paint_quad(crate::outline( + crate::Bounds { + origin: hitbox.origin + + crate::point(crate::px(0.), FONT_SIZE - px(2.)), + size: crate::Size { + width: text_bounds.size.width, + height: crate::px(1.), + }, + }, + crate::red(), + BorderStyle::default(), + )) + } + } + }; + + window.with_text_style( + Some(crate::TextStyleRefinement { + color: Some(crate::red()), + line_height: Some(FONT_SIZE.into()), + background_color: Some(crate::white()), + ..Default::default() + }), + render_debug_text, + ) + } + } + + fn paint_mouse_listeners( + &mut self, + hitbox: &Hitbox, + element_state: Option<&mut InteractiveElementState>, + window: &mut Window, + cx: &mut App, + ) { + let is_focused = self + .tracked_focus_handle + .as_ref() + .map(|handle| handle.is_focused(window)) + .unwrap_or(false); + + // If this element can be focused, register a mouse down listener + // that will automatically transfer focus when hitting the element. + // This behavior can be suppressed by using `cx.prevent_default()`. + if let Some(focus_handle) = self.tracked_focus_handle.clone() { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |_: &MouseDownEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble + && hitbox.is_hovered(window) + && !window.default_prevented() + { + window.focus(&focus_handle, cx); + // If there is a parent that is also focusable, prevent it + // from transferring focus because we already did so. + window.prevent_default(); + } + }); + } + + for listener in self.mouse_down_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MouseDownEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.mouse_up_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MouseUpEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.mouse_pressure_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MousePressureEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.mouse_move_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MouseMoveEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.mouse_exit_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MouseExitEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.file_drop_exit_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &FileDropEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.scroll_wheel_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + for listener in self.pinch_listeners.drain(..) { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &PinchEvent, phase, window, cx| { + listener(event, phase, &hitbox, window, cx); + }) + } + + if self.hover_style.is_some() + || self.base_style.mouse_cursor.is_some() + || cx.active_drag.is_some() && !self.drag_over_styles.is_empty() + { + let hitbox = hitbox.clone(); + let hover_state = self.hover_style.as_ref().and_then(|_| { + element_state + .as_ref() + .and_then(|state| state.hover_state.as_ref()) + .cloned() + }); + let current_view = window.current_view(); + + window.on_mouse_event(move |_: &MouseMoveEvent, phase, window, cx| { + let hovered = hitbox.is_hovered(window); + let was_hovered = hover_state + .as_ref() + .is_some_and(|state| state.borrow().element); + if phase == DispatchPhase::Capture && hovered != was_hovered { + if let Some(hover_state) = &hover_state { + hover_state.borrow_mut().element = hovered; + cx.notify(current_view); + } + } + }); + } + + if let Some(group_hover) = self.group_hover_style.as_ref() { + if let Some(group_hitbox_id) = GroupHitboxes::get(&group_hover.group, cx) { + let hover_state = element_state + .as_ref() + .and_then(|element| element.hover_state.as_ref()) + .cloned(); + let current_view = window.current_view(); + + window.on_mouse_event(move |_: &MouseMoveEvent, phase, window, cx| { + let group_hovered = group_hitbox_id.is_hovered(window); + let was_group_hovered = hover_state + .as_ref() + .is_some_and(|state| state.borrow().group); + if phase == DispatchPhase::Capture && group_hovered != was_group_hovered { + if let Some(hover_state) = &hover_state { + hover_state.borrow_mut().group = group_hovered; + cx.notify(current_view); + } + } + }); + } + } + + let drag_cursor_style = self.base_style.as_ref().mouse_cursor; + + let mut drag_listener = mem::take(&mut self.drag_listener); + let drop_listeners = mem::take(&mut self.drop_listeners); + let click_listeners = mem::take(&mut self.click_listeners); + let aux_click_listeners = mem::take(&mut self.aux_click_listeners); + let can_drop_predicate = mem::take(&mut self.can_drop_predicate); + + if !drop_listeners.is_empty() { + let hitbox = hitbox.clone(); + window.on_mouse_event({ + move |_: &MouseUpEvent, phase, window, cx| { + if let Some(drag) = &cx.active_drag + && phase == DispatchPhase::Bubble + && hitbox.is_hovered(window) + { + let drag_state_type = drag.value.as_ref().type_id(); + for (drop_state_type, listener) in &drop_listeners { + if *drop_state_type == drag_state_type { + let drag = cx + .active_drag + .take() + .expect("checked for type drag state type above"); + + let mut can_drop = true; + if let Some(predicate) = &can_drop_predicate { + can_drop = predicate(drag.value.as_ref(), window, cx); + } + + if can_drop { + listener(drag.value.as_ref(), window, cx); + window.refresh(); + cx.stop_propagation(); + } + } + } + } + } + }); + } + + if let Some(element_state) = element_state { + if !click_listeners.is_empty() + || !aux_click_listeners.is_empty() + || drag_listener.is_some() + { + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + + let pending_keyboard_down = element_state + .pending_keyboard_down + .get_or_insert_with(Default::default) + .clone(); + + let clicked_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); + + window.on_mouse_event({ + let pending_mouse_down = pending_mouse_down.clone(); + let hitbox = hitbox.clone(); + let has_aux_click_listeners = !aux_click_listeners.is_empty(); + move |event: &MouseDownEvent, phase, window, _cx| { + if phase == DispatchPhase::Bubble + && (event.button == MouseButton::Left || has_aux_click_listeners) + && hitbox.is_hovered(window) + { + *pending_mouse_down.borrow_mut() = Some(event.clone()); + window.refresh(); + } + } + }); + + window.on_mouse_event({ + let pending_mouse_down = pending_mouse_down.clone(); + let hitbox = hitbox.clone(); + move |event: &MouseMoveEvent, phase, window, cx| { + if phase == DispatchPhase::Capture { + return; + } + + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if let Some(mouse_down) = pending_mouse_down.clone() + && !cx.has_active_drag() + && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD + && let Some(listener) = drag_listener.take() + && mouse_down.button == MouseButton::Left + { + *clicked_state.borrow_mut() = ElementClickedState::default(); + let cursor_offset = event.position - hitbox.origin; + let drag = (listener.render)( + listener.value.as_ref(), + cursor_offset, + window, + cx, + ); + let external_payload_source = + listener.external_payload.map(|external_payload| { + let value = listener.value.clone(); + Box::new(move |window: &mut Window, cx: &mut App| { + external_payload(value.as_ref(), window, cx) + }) + as ExternalDragPayloadSource + }); + cx.active_drag = Some(AnyDrag { + view: drag, + value: listener.value, + cursor_offset, + cursor_style: drag_cursor_style, + external_payload_source, + }); + pending_mouse_down.take(); + window.refresh(); + cx.stop_propagation(); + } + } + }); + + if is_focused { + // Record the focus generation at which an enter/space key + // down event happened on this element. The next key up + // event will be mapped to a click event if both of the + // following are true: + // - no other key events happen in between + // - the focus generation is the same (implying focus did not move) + // + // This design avoids an ABA problem that happens if you + // store the focus handle that registered the keypress. + window.on_key_event({ + let pending_keyboard_down = pending_keyboard_down.clone(); + move |event: &KeyDownEvent, phase, window, _cx| { + if phase.bubble() && !window.default_prevented() { + let stroke = &event.keystroke; + let is_activation_key = (stroke.key.eq("enter") + || stroke.key.eq("space")) + && !stroke.modifiers.modified(); + *pending_keyboard_down.borrow_mut() = + is_activation_key.then_some(window.focus_generation); + } + } + }); + + // Press enter, space to trigger click, when the element is focused. + window.on_key_event({ + let click_listeners = click_listeners.clone(); + let hitbox = hitbox.clone(); + move |event: &KeyUpEvent, phase, window, cx| { + if phase.bubble() && !window.default_prevented() { + let stroke = &event.keystroke; + let keyboard_button = if stroke.key.eq("enter") { + Some(KeyboardButton::Enter) + } else if stroke.key.eq("space") { + Some(KeyboardButton::Space) + } else { + None + }; + + if let Some(button) = keyboard_button + && !stroke.modifiers.modified() + { + let pending = + std::mem::take(&mut *pending_keyboard_down.borrow_mut()); + if pending != Some(window.focus_generation) { + return; + } + + let click_event = ClickEvent::Keyboard(KeyboardClickEvent { + button, + bounds: hitbox.bounds, + }); + + for listener in &click_listeners { + listener(&click_event, window, cx); + } + } else { + // Releasing any other key mid-press means + // this isn't a clean activation, so cancel + // the pending keydown. + *pending_keyboard_down.borrow_mut() = None; + } + } + } + }); + } + + window.on_mouse_event({ + let mut captured_mouse_down = None; + let hitbox = hitbox.clone(); + move |event: &MouseUpEvent, phase, window, cx| match phase { + // Clear the pending mouse down during the capture phase, + // so that it happens even if another event handler stops + // propagation. + DispatchPhase::Capture => { + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if pending_mouse_down.is_some() && hitbox.is_hovered(window) { + captured_mouse_down = pending_mouse_down.take(); + window.refresh(); + } else if pending_mouse_down.is_some() { + // Clear the pending mouse down event (without firing click handlers) + // if the hitbox is not being hovered. + // This avoids dragging elements that changed their position + // immediately after being clicked. + // See https://github.com/zed-industries/zed/issues/24600 for more details + pending_mouse_down.take(); + window.refresh(); + } + } + // Fire click handlers during the bubble phase. + DispatchPhase::Bubble => { + if let Some(mouse_down) = captured_mouse_down.take() { + let btn = mouse_down.button; + + let mouse_click = ClickEvent::Mouse(MouseClickEvent { + down: mouse_down, + up: event.clone(), + }); + + match btn { + MouseButton::Left => { + for listener in &click_listeners { + listener(&mouse_click, window, cx); + } + } + _ => { + for listener in &aux_click_listeners { + listener(&mouse_click, window, cx); + } + } + } + } + } + } + }); + } + + if let Some(hover_listener) = self.hover_listener.take() { + let was_hovered = element_state + .hover_listener_state + .get_or_insert_with(Default::default) + .clone(); + let has_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let hover_listener = Rc::new(hover_listener); + let hover_listener_state = was_hovered.clone(); + let update_hover = move |is_hovered: bool, window: &mut Window, cx: &mut App| { + let mut was_hovered = hover_listener_state.borrow_mut(); + if is_hovered != *was_hovered { + *was_hovered = is_hovered; + drop(was_hovered); + hover_listener(&is_hovered, window, cx); + } + }; + let hover_listener_mode = self.hover_listener_mode; + + if has_mouse_down.borrow().is_none() { + let is_hovered = + !cx.has_active_drag() && hover_listener_mode.is_hovered(hitbox, window); + if is_hovered != *was_hovered.borrow() { + let update_hover = update_hover.clone(); + window.defer(cx, move |window, cx| { + update_hover(is_hovered, window, cx); + }); + } + } + + window.on_mouse_event({ + let update_hover = update_hover.clone(); + let hitbox = hitbox.clone(); + move |_: &MouseMoveEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble { + let is_hovered = has_mouse_down.borrow().is_none() + && !cx.has_active_drag() + && hover_listener_mode.is_hovered(&hitbox, window); + update_hover(is_hovered, window, cx); + } + } + }); + + // The pointer can leave the window without a final MouseMove, so also + // clear hover on MouseExited. + window.on_mouse_event(move |_: &MouseExitEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble { + update_hover(false, window, cx); + } + }); + } + + if let Some(tooltip_builder) = self.tooltip_builder.take() { + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let long_press_tooltip_active = element_state + .long_press_tooltip_active + .get_or_insert_with(Default::default) + .clone(); + + let tooltip_is_hoverable = tooltip_builder.hoverable; + let build_tooltip = Rc::new(move |window: &mut Window, cx: &mut App| { + Some(((tooltip_builder.build)(window, cx), tooltip_is_hoverable)) + }); + // Use bounds instead of testing hitbox since this is called during prepaint. + let check_is_hovered_during_prepaint = Rc::new({ + let pending_mouse_down = pending_mouse_down.clone(); + let source_bounds = hitbox.bounds; + move |window: &Window| { + !window.last_input_was_keyboard() + && pending_mouse_down.borrow().is_none() + && source_bounds.contains(&window.mouse_position()) + } + }); + let check_is_hovered = Rc::new({ + let hitbox = hitbox.clone(); + move |window: &Window| { + pending_mouse_down.borrow().is_none() && hitbox.is_hovered(window) + } + }); + register_tooltip_mouse_handlers( + &active_tooltip, + self.tooltip_id, + build_tooltip, + check_is_hovered, + check_is_hovered_during_prepaint, + long_press_tooltip_active, + self.tooltip_show_delay, + window, + ); + } + + // We unconditionally bind both the mouse up and mouse down active state handlers + // Because we might not get a chance to render a frame before the mouse up event arrives. + let active_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); + + { + let active_state = active_state.clone(); + window.on_mouse_event(move |_: &MouseUpEvent, phase, window, _cx| { + if phase == DispatchPhase::Capture && active_state.borrow().is_clicked() { + *active_state.borrow_mut() = ElementClickedState::default(); + window.refresh(); + } + }); + } + + { + let active_group_hitbox = self + .group_active_style + .as_ref() + .and_then(|group_active| GroupHitboxes::get(&group_active.group, cx)); + let hitbox = hitbox.clone(); + window.on_mouse_event(move |_: &MouseDownEvent, phase, window, _cx| { + if phase == DispatchPhase::Bubble && !window.default_prevented() { + let group_hovered = active_group_hitbox + .is_some_and(|group_hitbox_id| group_hitbox_id.is_hovered(window)); + let element_hovered = hitbox.is_hovered(window); + if group_hovered || element_hovered { + *active_state.borrow_mut() = ElementClickedState { + group: group_hovered, + element: element_hovered, + }; + window.refresh(); + } + } + }); + } + } + } + + fn paint_keyboard_listeners(&mut self, window: &mut Window, _cx: &mut App) { + let key_down_listeners = mem::take(&mut self.key_down_listeners); + let key_up_listeners = mem::take(&mut self.key_up_listeners); + let modifiers_changed_listeners = mem::take(&mut self.modifiers_changed_listeners); + let action_listeners = mem::take(&mut self.action_listeners); + if let Some(context) = self.key_context.clone() { + window.set_key_context(context); + } + + for listener in key_down_listeners { + window.on_key_event(move |event: &KeyDownEvent, phase, window, cx| { + listener(event, phase, window, cx); + }) + } + + for listener in key_up_listeners { + window.on_key_event(move |event: &KeyUpEvent, phase, window, cx| { + listener(event, phase, window, cx); + }) + } + + for listener in modifiers_changed_listeners { + window.on_modifiers_changed(move |event: &ModifiersChangedEvent, window, cx| { + listener(event, window, cx); + }) + } + + for (action_type, listener) in action_listeners { + window.on_action(action_type, listener) + } + } + + fn paint_hover_group_handler(&self, window: &mut Window, cx: &mut App) { + let group_hitbox = self + .group_hover_style + .as_ref() + .and_then(|group_hover| GroupHitboxes::get(&group_hover.group, cx)); + + if let Some(group_hitbox) = group_hitbox { + let was_hovered = group_hitbox.is_hovered(window); + let current_view = window.current_view(); + window.on_mouse_event(move |_: &MouseMoveEvent, phase, window, cx| { + let hovered = group_hitbox.is_hovered(window); + if phase == DispatchPhase::Capture && hovered != was_hovered { + cx.notify(current_view); + } + }); + } + } + + fn paint_scroll_listener( + &self, + hitbox: &Hitbox, + style: &Style, + window: &mut Window, + _cx: &mut App, + ) { + if let Some(scroll_offset) = self.scroll_offset.clone() { + let ongoing_scroll = self.ongoing_scroll.clone(); + let overflow = style.overflow; + let allow_concurrent_scroll = style.allow_concurrent_scroll; + let restrict_scroll_to_axis = style.restrict_scroll_to_axis; + let line_height = window.line_height(); + let hitbox = hitbox.clone(); + let current_view = window.current_view(); + window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.should_handle_scroll(window) { + let mut scroll_offset = scroll_offset.borrow_mut(); + let old_scroll_offset = *scroll_offset; + let mut delta = event.delta.pixel_delta(line_height); + + if restrict_scroll_to_axis + && event.delta.precise() + && let Some(ongoing_scroll) = &ongoing_scroll + { + ongoing_scroll + .borrow_mut() + .filter(&mut delta, event.touch_phase); + } + + let mut delta_x = match overflow.x { + Overflow::Scroll if !delta.x.is_zero() => delta.x, + Overflow::Scroll + if !restrict_scroll_to_axis && overflow.y != Overflow::Scroll => + { + delta.y + } + _ => Pixels::ZERO, + }; + let mut delta_y = match overflow.y { + Overflow::Scroll if !delta.y.is_zero() => delta.y, + Overflow::Scroll + if !restrict_scroll_to_axis && overflow.x != Overflow::Scroll => + { + delta.x + } + _ => Pixels::ZERO, + }; + if !allow_concurrent_scroll && !delta_x.is_zero() && !delta_y.is_zero() { + if delta_x.abs() > delta_y.abs() { + delta_y = Pixels::ZERO; + } else { + delta_x = Pixels::ZERO; + } + } + scroll_offset.y += delta_y; + scroll_offset.x += delta_x; + if *scroll_offset != old_scroll_offset { + cx.notify(current_view); + } + } + }); + } + } + + /// Compute the visual style for this element, based on the current bounds and the element's state. + pub fn compute_style( + &self, + global_id: Option<&GlobalElementId>, + hitbox: Option<&Hitbox>, + window: &mut Window, + cx: &mut App, + ) -> Style { + window.with_optional_element_state(global_id, |element_state, window| { + let mut element_state = + element_state.map(|element_state| element_state.unwrap_or_default()); + let style = self.compute_style_internal(hitbox, element_state.as_mut(), window, cx); + (style, element_state) + }) + } + + /// Called from internal methods that have already called with_element_state. + fn compute_style_internal( + &self, + hitbox: Option<&Hitbox>, + element_state: Option<&mut InteractiveElementState>, + window: &mut Window, + cx: &mut App, + ) -> Style { + let mut style = Style::default(); + style.refine(&self.base_style); + + if let Some(focus_handle) = self.tracked_focus_handle.as_ref() { + if let Some(in_focus_style) = self.in_focus_style.as_ref() + && focus_handle.within_focused(window, cx) + { + style.refine(in_focus_style); + } + + if let Some(focus_style) = self.focus_style.as_ref() + && focus_handle.is_focused(window) + { + style.refine(focus_style); + } + + if let Some(focus_visible_style) = self.focus_visible_style.as_ref() + && focus_handle.is_focused(window) + && window.last_input_was_keyboard() + { + style.refine(focus_visible_style); + } + } + + if !cx.has_active_drag() { + if let Some(group_hover) = self.group_hover_style.as_ref() { + let is_group_hovered = + if let Some(group_hitbox_id) = GroupHitboxes::get(&group_hover.group, cx) { + !window.last_input_was_touch() && group_hitbox_id.is_hovered(window) + } else if let Some(element_state) = element_state.as_ref() { + !window.last_input_was_touch() + && element_state + .hover_state + .as_ref() + .map(|state| state.borrow().group) + .unwrap_or(false) + } else { + false + }; + + if is_group_hovered { + style.refine(&group_hover.style); + } + } + + if let Some(hover_style) = self.hover_style.as_ref() { + let is_hovered = if let Some(hitbox) = hitbox { + !window.last_input_was_touch() && hitbox.is_hovered(window) + } else if let Some(element_state) = element_state.as_ref() { + !window.last_input_was_touch() + && element_state + .hover_state + .as_ref() + .map(|state| state.borrow().element) + .unwrap_or(false) + } else { + false + }; + + if is_hovered { + style.refine(hover_style); + } + } + } + + if let Some(hitbox) = hitbox { + if let Some(drag) = cx.active_drag.take() { + let mut can_drop = true; + if let Some(can_drop_predicate) = &self.can_drop_predicate { + can_drop = can_drop_predicate(drag.value.as_ref(), window, cx); + } + + if can_drop { + for (state_type, group_drag_style) in &self.group_drag_over_styles { + if let Some(group_hitbox_id) = + GroupHitboxes::get(&group_drag_style.group, cx) + && *state_type == drag.value.as_ref().type_id() + && group_hitbox_id.is_hovered(window) + { + style.refine(&group_drag_style.style); + } + } + + for (state_type, build_drag_over_style) in &self.drag_over_styles { + if *state_type == drag.value.as_ref().type_id() && hitbox.is_hovered(window) + { + style.refine(&build_drag_over_style(drag.value.as_ref(), window, cx)); + } + } + } + + style.mouse_cursor = drag.cursor_style; + cx.active_drag = Some(drag); + } + } + + if let Some(element_state) = element_state { + let clicked_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .borrow(); + if clicked_state.group + && let Some(group) = self.group_active_style.as_ref() + { + style.refine(&group.style) + } + + if let Some(active_style) = self.active_style.as_ref() + && clicked_state.element + { + style.refine(active_style) + } + } + + style + } + + pub(crate) fn write_a11y_info(&self, node: &mut accesskit::Node) { + if let Some(id) = &self.aria.author_id { + node.set_author_id(id.to_string()); + } + if let Some(label) = &self.aria.label { + node.set_label(label.to_string()); + } + if let Some(description) = &self.aria.description { + node.set_description(description.to_string()); + } + if let Some(keyshortcuts) = &self.aria.keyshortcuts { + node.set_keyboard_shortcut(keyshortcuts.to_string()); + } + if let Some(selected) = self.aria.selected { + node.set_selected(selected); + } + if let Some(expanded) = self.aria.expanded { + node.set_expanded(expanded); + } + if let Some(toggled) = self.aria.toggled { + node.set_toggled(toggled); + } + if let Some(value) = self.aria.numeric_value { + node.set_numeric_value(value); + } + if let Some(value) = self.aria.min_numeric_value { + node.set_min_numeric_value(value); + } + if let Some(value) = self.aria.max_numeric_value { + node.set_max_numeric_value(value); + } + if let Some(step) = self.aria.numeric_value_step { + node.set_numeric_value_step(step); + } + if let Some(value) = &self.aria.value { + node.set_value(value.to_string()); + } + if let Some(placeholder) = &self.aria.placeholder { + node.set_placeholder(placeholder.to_string()); + } + if let Some(orientation) = self.aria.orientation { + node.set_orientation(orientation); + } + if let Some(level) = self.aria.level { + node.set_level(level); + } + if let Some(position) = self.aria.position_in_set { + node.set_position_in_set(position); + } + if let Some(size) = self.aria.size_of_set { + node.set_size_of_set(size); + } + if let Some(index) = self.aria.row_index { + node.set_row_index(index); + } + if let Some(index) = self.aria.column_index { + node.set_column_index(index); + } + if let Some(count) = self.aria.row_count { + node.set_row_count(count); + } + if let Some(count) = self.aria.column_count { + node.set_column_count(count); + } + if !self.click_listeners.is_empty() { + node.add_action(accesskit::Action::Click); + } + if self.tracked_focus_handle.is_some() || self.focusable { + node.add_action(accesskit::Action::Focus); + } + for (action, _) in &self.a11y_action_listeners { + node.add_action(*action); + } + } +} + +/// The per-frame state of an interactive element. Used for tracking stateful interactions like clicks +/// and scroll offsets. +#[derive(Default)] +pub struct InteractiveElementState { + pub(crate) focus_handle: Option, + pub(crate) clicked_state: Option>>, + pub(crate) hover_state: Option>>, + pub(crate) hover_listener_state: Option>>, + pub(crate) pending_mouse_down: Option>>>, + /// Set to the window's [`focus_generation`](crate::Window::focus_generation) + /// when an Enter/Space keydown is received while this element is focused, + /// recording that we are waiting for the matching keyup to fire a keyboard + /// click. On keyup the click only fires if the stored generation still + /// matches the window's current one, i.e. focus never moved during the + /// press (mirroring the browser clearing a control's pressed state on + /// blur). `None` means no activation key is pending. + pub(crate) pending_keyboard_down: Option>>>, + pub(crate) scroll_offset: Option>>>, + ongoing_scroll: Option>>, + pub(crate) active_tooltip: Option>>>, + long_press_tooltip_active: Option>>, +} + +/// Whether or not the element or a group that contains it is clicked by the mouse. +#[derive(Copy, Clone, Default, Eq, PartialEq)] +pub struct ElementClickedState { + /// True if this element's group has been clicked, false otherwise + pub group: bool, + + /// True if this element has been clicked, false otherwise + pub element: bool, +} + +impl ElementClickedState { + fn is_clicked(&self) -> bool { + self.group || self.element + } +} + +/// Whether or not the element or a group that contains it is hovered. +#[derive(Copy, Clone, Default, Eq, PartialEq)] +pub struct ElementHoverState { + /// True if this element's group is hovered, false otherwise + pub group: bool, + + /// True if this element is hovered, false otherwise + pub element: bool, +} + +pub(crate) enum ActiveTooltip { + /// Currently delaying before showing the tooltip. + WaitingForShow { _task: Task<()> }, + /// Tooltip is visible, element was hovered or for hoverable tooltips, the tooltip was hovered. + Visible { + tooltip: AnyTooltip, + is_hoverable: bool, + }, + /// Tooltip is visible and hoverable, but the mouse is no longer hovering. Currently delaying + /// before hiding it. + WaitingForHide { + tooltip: AnyTooltip, + _task: Task<()>, + }, +} + +pub(crate) fn clear_active_tooltip( + active_tooltip: &Rc>>, + window: &mut Window, +) { + match active_tooltip.borrow_mut().take() { + None => {} + Some(ActiveTooltip::WaitingForShow { .. }) => {} + Some(ActiveTooltip::Visible { .. }) => window.refresh(), + Some(ActiveTooltip::WaitingForHide { .. }) => window.refresh(), + } +} + +pub(crate) fn clear_active_tooltip_if_not_hoverable( + active_tooltip: &Rc>>, + window: &mut Window, +) { + let should_clear = match active_tooltip.borrow().as_ref() { + None => false, + Some(ActiveTooltip::WaitingForShow { .. }) => false, + Some(ActiveTooltip::Visible { is_hoverable, .. }) => !is_hoverable, + Some(ActiveTooltip::WaitingForHide { .. }) => false, + }; + if should_clear { + active_tooltip.borrow_mut().take(); + window.refresh(); + } +} + +pub(crate) fn set_tooltip_on_window( + active_tooltip: &Rc>>, + window: &mut Window, +) -> Option { + let tooltip = match active_tooltip.borrow().as_ref() { + None => return None, + Some(ActiveTooltip::WaitingForShow { .. }) => return None, + Some(ActiveTooltip::Visible { tooltip, .. }) => tooltip.clone(), + Some(ActiveTooltip::WaitingForHide { tooltip, .. }) => tooltip.clone(), + }; + Some(window.set_tooltip(tooltip)) +} + +pub(crate) fn register_tooltip_mouse_handlers( + active_tooltip: &Rc>>, + tooltip_id: Option, + build_tooltip: Rc Option<(AnyView, bool)>>, + check_is_hovered: Rc bool>, + check_is_hovered_during_prepaint: Rc bool>, + long_press_tooltip_active: Rc>, + show_delay: Option, + window: &mut Window, +) { + let current_view = window.current_view(); + let show_delay = show_delay.unwrap_or(DEFAULT_TOOLTIP_SHOW_DELAY); + + window.on_mouse_event({ + let active_tooltip = active_tooltip.clone(); + let build_tooltip = build_tooltip.clone(); + let check_is_hovered = check_is_hovered.clone(); + let check_is_hovered_during_prepaint = check_is_hovered_during_prepaint.clone(); + move |_: &MouseMoveEvent, phase, window, cx| { + handle_tooltip_mouse_move( + &active_tooltip, + &build_tooltip, + &check_is_hovered, + &check_is_hovered_during_prepaint, + tooltip_id, + current_view, + phase, + show_delay, + window, + cx, + ) + } + }); + + window.on_mouse_event({ + let active_tooltip = active_tooltip.clone(); + move |_: &MouseDownEvent, _phase, window: &mut Window, _cx| { + if !tooltip_id.is_some_and(|tooltip_id| tooltip_id.is_hovered(window)) { + clear_active_tooltip_if_not_hoverable(&active_tooltip, window); + } + } + }); + + window.on_mouse_event({ + let active_tooltip = active_tooltip.clone(); + let build_tooltip = build_tooltip.clone(); + let check_is_hovered_during_prepaint = check_is_hovered_during_prepaint.clone(); + move |event: &LongPressEvent, phase, window, cx| { + if !phase.bubble() { + return; + } + + match event.phase { + TouchPhase::Started if !window.default_prevented() && check_is_hovered(window) => { + if show_tooltip( + &active_tooltip, + &build_tooltip, + &check_is_hovered_during_prepaint, + Some(long_press_tooltip_active.clone()), + window, + cx, + ) { + long_press_tooltip_active.set(true); + window.prevent_default(); + cx.stop_propagation(); + } + } + TouchPhase::Ended | TouchPhase::Cancelled + if long_press_tooltip_active.replace(false) => + { + clear_active_tooltip(&active_tooltip, window); + cx.stop_propagation(); + } + TouchPhase::Started + | TouchPhase::Moved + | TouchPhase::Ended + | TouchPhase::Cancelled => {} + } + } + }); + + window.on_mouse_event({ + let active_tooltip = active_tooltip.clone(); + move |_: &ScrollWheelEvent, _phase, window: &mut Window, _cx| { + if !tooltip_id.is_some_and(|tooltip_id| tooltip_id.is_hovered(window)) { + clear_active_tooltip_if_not_hoverable(&active_tooltip, window); + } + } + }); +} + +/// Handles displaying tooltips when an element is hovered. +/// +/// The mouse hovering logic also relies on being called from window prepaint in order to handle the +/// case where the element the tooltip is on is not rendered - in that case its mouse listeners are +/// also not registered. During window prepaint, the hitbox information is not available, so +/// `check_is_hovered_during_prepaint` is used which bases the check off of the absolute bounds of +/// the element. +/// +/// TODO: There's a minor bug due to the use of absolute bounds while checking during prepaint - it +/// does not know if the hitbox is occluded. In the case where a tooltip gets displayed and then +/// gets occluded after display, it will stick around until the mouse exits the hover bounds. +fn handle_tooltip_mouse_move( + active_tooltip: &Rc>>, + build_tooltip: &Rc Option<(AnyView, bool)>>, + check_is_hovered: &Rc bool>, + check_is_hovered_during_prepaint: &Rc bool>, + tooltip_id: Option, + current_view: EntityId, + phase: DispatchPhase, + show_delay: Duration, + window: &mut Window, + cx: &mut App, +) { + // Separates logic for what mutation should occur from applying it, to avoid overlapping + // RefCell borrows. + enum Action { + None, + CancelShow, + ScheduleShow, + CheckVisible, + } + + let action = match active_tooltip.borrow().as_ref() { + None => { + let is_hovered = check_is_hovered(window); + if is_hovered && phase.bubble() { + Action::ScheduleShow + } else { + Action::None + } + } + Some(ActiveTooltip::WaitingForShow { .. }) => { + let is_hovered = check_is_hovered(window); + if is_hovered { + Action::None + } else { + Action::CancelShow + } + } + Some(ActiveTooltip::Visible { is_hoverable, .. }) => { + if phase.capture() + && !check_is_hovered(window) + && (!*is_hoverable + || !tooltip_id.is_some_and(|tooltip_id| tooltip_id.is_hovered(window))) + { + Action::CheckVisible + } else { + Action::None + } + } + Some(ActiveTooltip::WaitingForHide { .. }) => { + if phase.capture() + && (check_is_hovered(window) + || tooltip_id.is_some_and(|tooltip_id| tooltip_id.is_hovered(window))) + { + Action::CheckVisible + } else { + Action::None + } + } + }; + + match action { + Action::None => {} + Action::CancelShow => { + // Cancel waiting to show tooltip when it is no longer hovered. + active_tooltip.borrow_mut().take(); + } + Action::ScheduleShow => { + let delayed_show_task = window.spawn(cx, { + let weak_active_tooltip = Rc::downgrade(active_tooltip); + let build_tooltip = build_tooltip.clone(); + let check_is_hovered_during_prepaint = check_is_hovered_during_prepaint.clone(); + async move |cx| { + cx.background_executor().timer(show_delay).await; + let Some(active_tooltip) = weak_active_tooltip.upgrade() else { + return; + }; + cx.update(|window, cx| { + show_tooltip( + &active_tooltip, + &build_tooltip, + &check_is_hovered_during_prepaint, + None, + window, + cx, + ); + }) + .ok(); + } + }); + active_tooltip + .borrow_mut() + .replace(ActiveTooltip::WaitingForShow { + _task: delayed_show_task, + }); + } + Action::CheckVisible => cx.notify(current_view), + } +} + +fn show_tooltip( + active_tooltip: &Rc>>, + build_tooltip: &Rc Option<(AnyView, bool)>>, + check_is_hovered_during_prepaint: &Rc bool>, + long_press_tooltip_active: Option>>, + window: &mut Window, + cx: &mut App, +) -> bool { + let new_tooltip = build_tooltip(window, cx).map(|(view, tooltip_is_hoverable)| { + let weak_active_tooltip = Rc::downgrade(active_tooltip); + let check_is_hovered_during_prepaint = check_is_hovered_during_prepaint.clone(); + ActiveTooltip::Visible { + tooltip: AnyTooltip { + view, + mouse_position: window.mouse_position(), + check_visible_and_update: Rc::new(move |tooltip_bounds, window, cx| { + if long_press_tooltip_active + .as_ref() + .is_some_and(|active| active.get()) + { + return true; + } + let Some(active_tooltip) = weak_active_tooltip.upgrade() else { + return false; + }; + handle_tooltip_check_visible_and_update( + &active_tooltip, + tooltip_is_hoverable, + &check_is_hovered_during_prepaint, + tooltip_bounds, + window, + cx, + ) + }), + }, + is_hoverable: tooltip_is_hoverable, + } + }); + let did_show = new_tooltip.is_some(); + *active_tooltip.borrow_mut() = new_tooltip; + window.refresh(); + did_show +} + +/// Returns a callback which will be called by window prepaint to update tooltip visibility. The +/// purpose of doing this logic here instead of the mouse move handler is that the mouse move +/// handler won't get called when the element is not painted (e.g. via use of `visible_on_hover`). +fn handle_tooltip_check_visible_and_update( + active_tooltip: &Rc>>, + tooltip_is_hoverable: bool, + check_is_hovered: &Rc bool>, + tooltip_bounds: Bounds, + window: &mut Window, + cx: &mut App, +) -> bool { + // Separates logic for what mutation should occur from applying it, to avoid overlapping RefCell + // borrows. + enum Action { + None, + Hide, + ScheduleHide(AnyTooltip), + CancelHide(AnyTooltip), + } + + let is_hovered = check_is_hovered(window) + || (tooltip_is_hoverable && tooltip_bounds.contains(&window.mouse_position())); + let action = match active_tooltip.borrow().as_ref() { + Some(ActiveTooltip::Visible { tooltip, .. }) => { + if is_hovered { + Action::None + } else { + if tooltip_is_hoverable { + Action::ScheduleHide(tooltip.clone()) + } else { + Action::Hide + } + } + } + Some(ActiveTooltip::WaitingForHide { tooltip, .. }) => { + if is_hovered { + Action::CancelHide(tooltip.clone()) + } else { + Action::None + } + } + None | Some(ActiveTooltip::WaitingForShow { .. }) => Action::None, + }; + + match action { + Action::None => {} + Action::Hide => clear_active_tooltip(active_tooltip, window), + Action::ScheduleHide(tooltip) => { + let delayed_hide_task = window.spawn(cx, { + let weak_active_tooltip = Rc::downgrade(active_tooltip); + async move |cx| { + cx.background_executor() + .timer(HOVERABLE_TOOLTIP_HIDE_DELAY) + .await; + let Some(active_tooltip) = weak_active_tooltip.upgrade() else { + return; + }; + if active_tooltip.borrow_mut().take().is_some() { + cx.update(|window, _cx| window.refresh()).ok(); + } + } + }); + active_tooltip + .borrow_mut() + .replace(ActiveTooltip::WaitingForHide { + tooltip, + _task: delayed_hide_task, + }); + } + Action::CancelHide(tooltip) => { + // Cancel waiting to hide tooltip when it becomes hovered. + active_tooltip.borrow_mut().replace(ActiveTooltip::Visible { + tooltip, + is_hoverable: true, + }); + } + } + + active_tooltip.borrow().is_some() +} + +#[derive(Default)] +pub(crate) struct GroupHitboxes(HashMap>); + +impl Global for GroupHitboxes {} + +impl GroupHitboxes { + pub fn get(name: &SharedString, cx: &mut App) -> Option { + cx.default_global::() + .0 + .get(name) + .and_then(|bounds_stack| bounds_stack.last()) + .cloned() + } + + pub fn push(name: SharedString, hitbox_id: HitboxId, cx: &mut App) { + cx.default_global::() + .0 + .entry(name) + .or_default() + .push(hitbox_id); + } + + pub fn pop(name: &SharedString, cx: &mut App) { + cx.default_global::().0.get_mut(name).unwrap().pop(); + } +} + +/// A wrapper around an element that can store state, produced after assigning an ElementId. +pub struct Stateful { + pub(crate) element: E, +} + +impl Styled for Stateful +where + E: Styled, +{ + fn style(&mut self) -> &mut StyleRefinement { + self.element.style() + } +} + +impl StatefulInteractiveElement for Stateful +where + E: Element, + Self: InteractiveElement, +{ +} + +impl InteractiveElement for Stateful +where + E: InteractiveElement, +{ + fn interactivity(&mut self) -> &mut Interactivity { + self.element.interactivity() + } +} + +impl Element for Stateful +where + E: Element, +{ + type RequestLayoutState = E::RequestLayoutState; + type PrepaintState = E::PrepaintState; + + fn id(&self) -> Option { + self.element.id() + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + self.element.source_location() + } + + fn a11y_role(&self) -> Option { + self.element.a11y_role() + } + + fn write_a11y_info(&self, node: &mut accesskit::Node) { + self.element.write_a11y_info(node); + } + + fn a11y_synthetic_children( + &mut self, + prepaint: &mut Self::PrepaintState, + builder: &mut crate::A11ySubtreeBuilder, + ) { + self.element.a11y_synthetic_children(prepaint, builder); + } + + fn request_layout( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + self.element.request_layout(id, inspector_id, window, cx) + } + + fn prepaint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + state: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> E::PrepaintState { + self.element + .prepaint(id, inspector_id, bounds, state, window, cx) + } + + fn paint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + self.element.paint( + id, + inspector_id, + bounds, + request_layout, + prepaint, + window, + cx, + ); + } +} + +impl IntoElement for Stateful +where + E: Element, +{ + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl ParentElement for Stateful +where + E: ParentElement, +{ + fn extend(&mut self, elements: impl IntoIterator) { + self.element.extend(elements) + } +} + +/// Represents an element that can be scrolled *to* in its parent element. +/// Contrary to [ScrollHandle::scroll_to_active_item], an anchored element does not have to be an immediate child of the parent. +#[derive(Clone)] +pub struct ScrollAnchor { + handle: ScrollHandle, + last_origin: Rc>>, +} + +impl ScrollAnchor { + /// Creates a [ScrollAnchor] associated with a given [ScrollHandle]. + pub fn for_handle(handle: ScrollHandle) -> Self { + Self { + handle, + last_origin: Default::default(), + } + } + /// Request scroll to this item on the next frame. + pub fn scroll_to(&self, window: &mut Window, _cx: &mut App) { + let this = self.clone(); + + window.on_next_frame(move |_, _| { + let viewport_bounds = this.handle.bounds(); + let self_bounds = *this.last_origin.borrow(); + this.handle.set_offset(viewport_bounds.origin - self_bounds); + }); + } +} + +#[derive(Default, Debug)] +struct ScrollHandleState { + offset: Rc>>, + ongoing_scroll: Rc>, + bounds: Bounds, + max_offset: Point, + child_bounds: Vec>, + scroll_to_bottom: bool, + overflow: Point, + active_item: Option, +} + +#[derive(Default, Debug, Clone, Copy)] +struct ScrollActiveItem { + index: usize, + strategy: ScrollStrategy, +} + +#[derive(Default, Debug, Clone, Copy)] +enum ScrollStrategy { + #[default] + FirstVisible, + Top, +} + +/// A handle to the scrollable aspects of an element. +/// Used for accessing scroll state, like the current scroll offset, +/// and for mutating the scroll state, like scrolling to a specific child. +#[derive(Clone, Debug)] +pub struct ScrollHandle(Rc>); + +impl Default for ScrollHandle { + fn default() -> Self { + Self::new() + } +} + +impl ScrollHandle { + /// Construct a new scroll handle. + pub fn new() -> Self { + Self(Rc::default()) + } + + /// Get the current scroll offset. + pub fn offset(&self) -> Point { + *self.0.borrow().offset.borrow() + } + + /// Get the maximum scroll offset. + pub fn max_offset(&self) -> Point { + self.0.borrow().max_offset + } + + /// Get the top child that's scrolled into view. + pub fn top_item(&self) -> usize { + let state = self.0.borrow(); + let top = state.bounds.top() - state.offset.borrow().y; + + match state.child_bounds.binary_search_by(|bounds| { + if top < bounds.top() { + Ordering::Greater + } else if top > bounds.bottom() { + Ordering::Less + } else { + Ordering::Equal + } + }) { + Ok(ix) => ix, + Err(ix) => ix.min(state.child_bounds.len().saturating_sub(1)), + } + } + + /// Get the bottom child that's scrolled into view. + pub fn bottom_item(&self) -> usize { + let state = self.0.borrow(); + let bottom = state.bounds.bottom() - state.offset.borrow().y; + + match state.child_bounds.binary_search_by(|bounds| { + if bottom < bounds.top() { + Ordering::Greater + } else if bottom > bounds.bottom() { + Ordering::Less + } else { + Ordering::Equal + } + }) { + Ok(ix) => ix, + Err(ix) => ix.min(state.child_bounds.len().saturating_sub(1)), + } + } + + /// Return the bounds into which this child is painted + pub fn bounds(&self) -> Bounds { + self.0.borrow().bounds + } + + /// Get the bounds for a specific child. + pub fn bounds_for_item(&self, ix: usize) -> Option> { + self.0.borrow().child_bounds.get(ix).cloned() + } + + /// Update [ScrollHandleState]'s active item for scrolling to in prepaint + pub fn scroll_to_item(&self, ix: usize) { + let mut state = self.0.borrow_mut(); + state.active_item = Some(ScrollActiveItem { + index: ix, + strategy: ScrollStrategy::default(), + }); + } + + /// Update [ScrollHandleState]'s active item for scrolling to in prepaint + /// This scrolls the minimal amount to ensure that the child is the first visible element + pub fn scroll_to_top_of_item(&self, ix: usize) { + let mut state = self.0.borrow_mut(); + state.active_item = Some(ScrollActiveItem { + index: ix, + strategy: ScrollStrategy::Top, + }); + } + + /// Scrolls the minimal amount to either ensure that the child is + /// fully visible or the top element of the view depends on the + /// scroll strategy + fn scroll_to_active_item(&self) { + let mut state = self.0.borrow_mut(); + + let Some(active_item) = state.active_item else { + return; + }; + + let active_item = match state.child_bounds.get(active_item.index) { + Some(bounds) => { + let mut scroll_offset = state.offset.borrow_mut(); + + match active_item.strategy { + ScrollStrategy::FirstVisible => { + if state.overflow.y == Overflow::Scroll { + let child_height = bounds.size.height; + let viewport_height = state.bounds.size.height; + if child_height > viewport_height { + scroll_offset.y = state.bounds.top() - bounds.top(); + } else if bounds.top() + scroll_offset.y < state.bounds.top() { + scroll_offset.y = state.bounds.top() - bounds.top(); + } else if bounds.bottom() + scroll_offset.y > state.bounds.bottom() { + scroll_offset.y = state.bounds.bottom() - bounds.bottom(); + } + } + } + ScrollStrategy::Top => { + scroll_offset.y = state.bounds.top() - bounds.top(); + } + } + + if state.overflow.x == Overflow::Scroll { + let child_width = bounds.size.width; + let viewport_width = state.bounds.size.width; + if child_width > viewport_width { + scroll_offset.x = state.bounds.left() - bounds.left(); + } else if bounds.left() + scroll_offset.x < state.bounds.left() { + scroll_offset.x = state.bounds.left() - bounds.left(); + } else if bounds.right() + scroll_offset.x > state.bounds.right() { + scroll_offset.x = state.bounds.right() - bounds.right(); + } + } + None + } + None => Some(active_item), + }; + state.active_item = active_item; + } + + /// Scrolls to the bottom. + pub fn scroll_to_bottom(&self) { + let mut state = self.0.borrow_mut(); + state.scroll_to_bottom = true; + } + + /// Set the offset explicitly. The offset is the distance from the top left of the + /// parent container to the top left of the first child. + /// As you scroll further down the offset becomes more negative. + pub fn set_offset(&self, mut position: Point) { + let state = self.0.borrow(); + *state.offset.borrow_mut() = position; + } + + /// Get the logical scroll top, based on a child index and a pixel offset. + pub fn logical_scroll_top(&self) -> (usize, Pixels) { + let ix = self.top_item(); + let state = self.0.borrow(); + + if let Some(child_bounds) = state.child_bounds.get(ix) { + ( + ix, + child_bounds.top() + state.offset.borrow().y - state.bounds.top(), + ) + } else { + (ix, px(0.)) + } + } + + /// Get the logical scroll bottom, based on a child index and a pixel offset. + pub fn logical_scroll_bottom(&self) -> (usize, Pixels) { + let ix = self.bottom_item(); + let state = self.0.borrow(); + + if let Some(child_bounds) = state.child_bounds.get(ix) { + ( + ix, + child_bounds.bottom() + state.offset.borrow().y - state.bounds.bottom(), + ) + } else { + (ix, px(0.)) + } + } + + /// Get the count of children for scrollable item. + pub fn children_count(&self) -> usize { + self.0.borrow().child_bounds.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AnyWindowHandle, AppContext as _, Context, GestureTuning, InputEvent, Keystroke, + MouseMoveEvent, TestAppContext, TouchEvent, TouchId, canvas, util::FluentBuilder as _, + }; + use std::{cell::Cell, rc::Weak}; + + struct GroupHoverTestView { + render_count: Rc>, + anonymous_paint_count: Rc>, + stateful_width: Rc>, + } + + impl Render for GroupHoverTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + self.render_count.set(self.render_count.get() + 1); + let anonymous_paint_count = self.anonymous_paint_count.clone(); + let stateful_width = self.stateful_width.clone(); + div().size_full().child( + div() + .ml(px(20.)) + .mt(px(20.)) + .size(px(50.)) + .relative() + .group("hover-group") + .child( + div() + .absolute() + .size_full() + .invisible() + .group_hover("hover-group", |style| style.visible()) + .child(canvas( + |_, _, _| {}, + move |_, _, _, _| { + anonymous_paint_count.set(anonymous_paint_count.get() + 1) + }, + )), + ) + .child( + div() + .id("stateful-group-hover-target") + .absolute() + .top_0() + .left_0() + .size(px(10.)) + .group_hover("hover-group", |style| style.size(px(20.))) + .child(canvas( + move |bounds, _, _| stateful_width.set(bounds.size.width), + |_, _, _, _| {}, + )), + ), + ) + } + } + + #[gpui::test] + fn group_hover_styles_update_only_on_transitions(cx: &mut TestAppContext) { + let render_count = Rc::new(Cell::new(0)); + let anonymous_paint_count = Rc::new(Cell::new(0)); + let stateful_width = Rc::new(Cell::new(px(0.))); + let window = cx.add_window({ + let render_count = render_count.clone(); + let anonymous_paint_count = anonymous_paint_count.clone(); + let stateful_width = stateful_width.clone(); + move |_, _| GroupHoverTestView { + render_count, + anonymous_paint_count, + stateful_width, + } + }); + let window = AnyWindowHandle::from(window); + + cx.update_window(window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(anonymous_paint_count.get(), 0); + assert_eq!(stateful_width.get(), px(10.)); + + let move_mouse = |cx: &mut TestAppContext, position| { + cx.update_window(window, |_, window, cx| { + window.simulate_mouse_move(position, cx) + }) + .unwrap(); + }; + + let initial_render_count = render_count.get(); + move_mouse(cx, point(px(25.), px(25.))); + assert_eq!(render_count.get(), initial_render_count + 1); + assert_eq!(anonymous_paint_count.get(), 1); + assert_eq!(stateful_width.get(), px(20.)); + + move_mouse(cx, point(px(30.), px(30.))); + assert_eq!(render_count.get(), initial_render_count + 1); + assert_eq!(anonymous_paint_count.get(), 1); + assert_eq!(stateful_width.get(), px(20.)); + + move_mouse(cx, point(px(5.), px(5.))); + assert_eq!(render_count.get(), initial_render_count + 2); + assert_eq!(anonymous_paint_count.get(), 1); + assert_eq!(stateful_width.get(), px(10.)); + + move_mouse(cx, point(px(10.), px(10.))); + assert_eq!(render_count.get(), initial_render_count + 2); + assert_eq!(anonymous_paint_count.get(), 1); + assert_eq!(stateful_width.get(), px(10.)); + } + + struct HoverListenerLayoutTestView { + target_left: Pixels, + hover_transitions: Rc>>, + } + + impl Render for HoverListenerLayoutTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let hover_transitions = self.hover_transitions.clone(); + div().relative().size_full().child( + div() + .id("hover-target") + .absolute() + .left(self.target_left) + .top_0() + .size(px(20.)) + .on_click(|_, _, _| {}) + .on_hover(move |is_hovered, _, _| { + hover_transitions.borrow_mut().push(*is_hovered); + }), + ) + } + } + + #[gpui::test] + fn default_hover_listener_updates_when_layout_changes_under_stationary_mouse( + cx: &mut TestAppContext, + ) { + let hover_transitions = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let hover_transitions = hover_transitions.clone(); + move |_, _| HoverListenerLayoutTestView { + target_left: px(40.), + hover_transitions, + } + }); + let any_window = AnyWindowHandle::from(window); + + cx.update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + window.simulate_mouse_move(point(px(10.), px(10.)), cx); + }) + .unwrap(); + assert!(hover_transitions.borrow().is_empty()); + + window + .update(cx, |view, _, cx| { + view.target_left = px(0.); + cx.notify(); + }) + .unwrap(); + cx.update_window(any_window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + window + .update(cx, |view, _, cx| { + view.target_left = px(40.); + cx.notify(); + }) + .unwrap(); + cx.update_window(any_window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true, false]); + } + + #[gpui::test] + fn default_hover_listener_ends_after_key_press(cx: &mut TestAppContext) { + let hover_transitions = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let hover_transitions = hover_transitions.clone(); + move |_, _| HoverListenerLayoutTestView { + target_left: px(0.), + hover_transitions, + } + }); + let any_window = AnyWindowHandle::from(window); + + cx.update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + window.simulate_mouse_move(point(px(10.), px(10.)), cx); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + key_down(cx, any_window, "a"); + cx.update_window(any_window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true, false]); + } + + struct HoverListenerModeLayoutTestView { + target_left: Pixels, + hover_transitions: Rc>>, + } + + impl Render for HoverListenerModeLayoutTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let hover_transitions = self.hover_transitions.clone(); + div().relative().size_full().child( + div() + .id("hover-target") + .absolute() + .left(self.target_left) + .top_0() + .size(px(20.)) + .hover_listener_mode(HoverListenerMode::InputModalityIndependent) + .on_hover(move |is_hovered, _, _| { + hover_transitions.borrow_mut().push(*is_hovered); + }), + ) + } + } + + #[gpui::test] + fn input_modality_independent_hover_listener_updates_after_key_press(cx: &mut TestAppContext) { + let hover_transitions = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let hover_transitions = hover_transitions.clone(); + move |_, _| HoverListenerModeLayoutTestView { + target_left: px(40.), + hover_transitions, + } + }); + let any_window = AnyWindowHandle::from(window); + let pointer_position = point(px(10.), px(10.)); + + cx.update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + window.simulate_mouse_move(pointer_position, cx); + }) + .unwrap(); + assert!(hover_transitions.borrow().is_empty()); + + key_down(cx, any_window, "a"); + window + .update(cx, |view, _, cx| { + view.target_left = px(0.); + cx.notify(); + }) + .unwrap(); + cx.update_window(any_window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + key_down(cx, any_window, "b"); + cx.update_window(any_window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + cx.update_window(any_window, |_, window, cx| { + window.simulate_mouse_move(point(px(30.), px(10.)), cx); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true, false]); + + cx.update_window(any_window, |_, window, cx| { + window.simulate_mouse_move(pointer_position, cx); + window.dispatch_event( + MouseExitEvent { + position: pointer_position, + ..Default::default() + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true, false, true, false]); + } + + #[gpui::test] + fn default_hover_listener_remains_hovered_during_stationary_mouse_press( + cx: &mut TestAppContext, + ) { + let hover_transitions = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let hover_transitions = hover_transitions.clone(); + move |_, _| HoverListenerLayoutTestView { + target_left: px(0.), + hover_transitions, + } + }); + let any_window = AnyWindowHandle::from(window); + let mouse_position = point(px(10.), px(10.)); + + cx.update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + window.simulate_mouse_move(mouse_position, cx); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + cx.update_window(any_window, |_, window, cx| { + window.dispatch_event( + MouseDownEvent { + position: mouse_position, + button: MouseButton::Left, + modifiers: Default::default(), + click_count: 1, + first_mouse: false, + } + .to_platform_input(), + cx, + ); + window.draw(cx).clear(cx); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + + cx.update_window(any_window, |_, window, cx| { + window.dispatch_event( + MouseUpEvent { + position: mouse_position, + button: MouseButton::Left, + modifiers: Default::default(), + click_count: 1, + } + .to_platform_input(), + cx, + ); + window.draw(cx).clear(cx); + }) + .unwrap(); + assert_eq!(*hover_transitions.borrow(), [true]); + } + + struct TestTooltipView; + + impl Render for TestTooltipView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().w(px(20.)).h(px(20.)).child("tooltip") + } + } + + type CapturedActiveTooltip = Rc>>>>>; + + struct TooltipCaptureElement { + child: AnyElement, + captured_active_tooltip: CapturedActiveTooltip, + } + + impl IntoElement for TooltipCaptureElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } + } + + impl Element for TooltipCaptureElement { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + (self.child.request_layout(window, cx), ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + self.child.prepaint(window, cx); + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + self.child.paint(window, cx); + window.with_global_id("target".into(), |global_id, window| { + window.with_element_state::( + global_id, + |state, _window| { + let state = state.unwrap(); + *self.captured_active_tooltip.borrow_mut() = + state.active_tooltip.as_ref().map(Rc::downgrade); + ((), state) + }, + ) + }); + } + } + + struct TooltipOwner { + captured_active_tooltip: CapturedActiveTooltip, + show_delay_override: Option, + } + + impl Render for TooltipOwner { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + TooltipCaptureElement { + child: div() + .size_full() + .child( + div() + .id("target") + .w(px(50.)) + .h(px(50.)) + .tooltip(|_, cx| cx.new(|_| TestTooltipView).into()) + .when_some(self.show_delay_override, |this, delay| { + this.tooltip_show_delay(delay) + }), + ) + .into_any_element(), + captured_active_tooltip: self.captured_active_tooltip.clone(), + } + } + } + + #[test] + fn scroll_handle_aligns_wide_children_to_left_edge() { + let handle = ScrollHandle::new(); + { + let mut state = handle.0.borrow_mut(); + state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(80.), px(20.))); + state.child_bounds = vec![Bounds::new(point(px(25.), px(0.)), size(px(200.), px(20.)))]; + state.overflow.x = Overflow::Scroll; + state.active_item = Some(ScrollActiveItem { + index: 0, + strategy: ScrollStrategy::default(), + }); + } + + handle.scroll_to_active_item(); + + assert_eq!(handle.offset().x, px(-25.)); + } + + #[test] + fn scroll_handle_aligns_tall_children_to_top_edge() { + let handle = ScrollHandle::new(); + { + let mut state = handle.0.borrow_mut(); + state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(20.), px(80.))); + state.child_bounds = vec![Bounds::new(point(px(0.), px(25.)), size(px(20.), px(200.)))]; + state.overflow.y = Overflow::Scroll; + state.active_item = Some(ScrollActiveItem { + index: 0, + strategy: ScrollStrategy::default(), + }); + } + + handle.scroll_to_active_item(); + + assert_eq!(handle.offset().y, px(-25.)); + } + + #[test] + fn long_press_shows_tooltip_until_touch_ends() { + let (mut test_app, any_window, captured_active_tooltip) = create_tooltip_owner_test(None); + let active_tooltip = captured_active_tooltip + .borrow() + .clone() + .unwrap() + .upgrade() + .unwrap(); + let touch_id = TouchId(1); + let touch_position = point(px(49.), px(10.)); + + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + TouchEvent { + id: touch_id, + phase: TouchPhase::Started, + position: touch_position, + predicted_position: None, + force: None, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + test_app + .dispatcher + .advance_clock(GestureTuning::default().long_press_duration + Duration::from_millis(1)); + test_app.run_until_parked(); + + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::Visible { .. }) + )); + + let moved_position = point(px(55.), px(10.)); + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + TouchEvent { + id: touch_id, + phase: TouchPhase::Moved, + position: moved_position, + predicted_position: None, + force: None, + } + .to_platform_input(), + cx, + ); + window.draw(cx).clear(cx); + }) + .unwrap(); + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::Visible { .. }) + )); + + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + TouchEvent { + id: touch_id, + phase: TouchPhase::Ended, + position: moved_position, + predicted_position: None, + force: None, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + + assert!(active_tooltip.borrow().is_none()); + } + + fn setup_tooltip_owner_test( + show_delay_override: Option, + ) -> ( + TestAppContext, + crate::AnyWindowHandle, + CapturedActiveTooltip, + ) { + let (mut test_app, any_window, captured_active_tooltip) = + create_tooltip_owner_test(show_delay_override); + + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + MouseMoveEvent { + position: point(px(10.), px(10.)), + modifiers: Default::default(), + pressed_button: None, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + + test_app + .update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + + (test_app, any_window, captured_active_tooltip) + } + + fn create_tooltip_owner_test( + show_delay_override: Option, + ) -> ( + TestAppContext, + crate::AnyWindowHandle, + CapturedActiveTooltip, + ) { + let mut test_app = TestAppContext::single(); + let captured_active_tooltip: CapturedActiveTooltip = Rc::new(RefCell::new(None)); + let window = test_app.add_window({ + let captured_active_tooltip = captured_active_tooltip.clone(); + move |_, _| TooltipOwner { + captured_active_tooltip, + show_delay_override, + } + }); + let any_window = window.into(); + + test_app + .update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + + (test_app, any_window, captured_active_tooltip) + } + + #[test] + fn tooltip_waiting_for_show_is_released_when_its_owner_disappears() { + let (mut test_app, any_window, captured_active_tooltip) = setup_tooltip_owner_test(None); + + let weak_active_tooltip = captured_active_tooltip.borrow().clone().unwrap(); + let active_tooltip = weak_active_tooltip.upgrade().unwrap(); + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::WaitingForShow { .. }) + )); + + test_app + .update_window(any_window, |_, window, _| { + window.remove_window(); + }) + .unwrap(); + test_app.run_until_parked(); + drop(active_tooltip); + + assert!(weak_active_tooltip.upgrade().is_none()); + } + + #[test] + fn tooltip_respects_custom_show_delay() { + let extra_delay = Duration::from_secs(1); + let show_delay_override = DEFAULT_TOOLTIP_SHOW_DELAY + extra_delay; + let (mut test_app, _any_window, captured_active_tooltip) = + setup_tooltip_owner_test(Some(show_delay_override)); + + let weak_active_tooltip = captured_active_tooltip.borrow().clone().unwrap(); + let active_tooltip = weak_active_tooltip.upgrade().unwrap(); + + test_app + .dispatcher + .advance_clock(DEFAULT_TOOLTIP_SHOW_DELAY); + test_app.run_until_parked(); + + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::WaitingForShow { .. }) + )); + + test_app.dispatcher.advance_clock(extra_delay); + test_app.run_until_parked(); + + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::Visible { .. }) + )); + } + + #[test] + fn tooltip_is_released_when_its_owner_disappears() { + let (mut test_app, any_window, captured_active_tooltip) = setup_tooltip_owner_test(None); + + let weak_active_tooltip = captured_active_tooltip.borrow().clone().unwrap(); + let active_tooltip = weak_active_tooltip.upgrade().unwrap(); + + test_app + .dispatcher + .advance_clock(DEFAULT_TOOLTIP_SHOW_DELAY); + test_app.run_until_parked(); + + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::Visible { .. }) + )); + + test_app + .update_window(any_window, |_, window, _| { + window.remove_window(); + }) + .unwrap(); + test_app.run_until_parked(); + drop(active_tooltip); + + assert!(weak_active_tooltip.upgrade().is_none()); + } + + #[test] + fn tooltip_hides_after_mouse_leaves_origin() { + let (mut test_app, any_window, captured_active_tooltip) = setup_tooltip_owner_test(None); + + let weak_active_tooltip = captured_active_tooltip.borrow().clone().unwrap(); + let active_tooltip = weak_active_tooltip.upgrade().unwrap(); + + test_app + .dispatcher + .advance_clock(DEFAULT_TOOLTIP_SHOW_DELAY); + test_app.run_until_parked(); + + assert!(matches!( + active_tooltip.borrow().as_ref(), + Some(ActiveTooltip::Visible { .. }) + )); + + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + MouseMoveEvent { + position: point(px(75.), px(75.)), + modifiers: Default::default(), + pressed_button: None, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + + assert!(active_tooltip.borrow().is_none()); + } + + struct MouseDownOutOwner { + mouse_down_out_count: Rc>, + } + + impl Render for MouseDownOutOwner { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let mouse_down_out_count = self.mouse_down_out_count.clone(); + div() + .size_full() + .child(div().id("target").w(px(50.)).h(px(50.)).on_mouse_down_out( + move |_, _, _| { + *mouse_down_out_count.borrow_mut() += 1; + }, + )) + } + } + + #[test] + fn mouse_down_out_is_suppressed_while_window_prompt_is_active() { + let mut test_app = TestAppContext::single(); + let mouse_down_out_count = Rc::new(RefCell::new(0)); + let window = test_app.add_window({ + let mouse_down_out_count = mouse_down_out_count.clone(); + move |_, _| MouseDownOutOwner { + mouse_down_out_count, + } + }); + let any_window: AnyWindowHandle = window.into(); + + fn dispatch_mouse_down_outside_target( + test_app: &mut TestAppContext, + any_window: AnyWindowHandle, + ) { + test_app + .update_window(any_window, |_, window, cx| { + window.dispatch_event( + MouseDownEvent { + position: point(px(75.), px(75.)), + button: MouseButton::Left, + modifiers: Default::default(), + click_count: 1, + first_mouse: false, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + } + + test_app + .update_window(any_window, |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + + dispatch_mouse_down_outside_target(&mut test_app, any_window); + assert_eq!( + *mouse_down_out_count.borrow(), + 1, + "mouse down outside the element should fire mouse-down-out listeners" + ); + + test_app + .update_window(any_window, |_, window, cx| { + cx.set_prompt_builder(crate::fallback_prompt_renderer); + let _receiver = + window.prompt(crate::PromptLevel::Warning, "message", None, &["Ok"], cx); + assert!(window.has_active_prompt()); + window.draw(cx).clear(cx); + }) + .unwrap(); + + dispatch_mouse_down_outside_target(&mut test_app, any_window); + assert_eq!( + *mouse_down_out_count.borrow(), + 1, + "mouse down over an active prompt should not fire mouse-down-out listeners" + ); + } + + #[test] + fn test_accessibility_id_builder_writes_author_id() { + let mut element = div() + .id("buffer-font-size") + .accessibility_id("settings.buffer-font-size"); + let mut node = accesskit::Node::new(accesskit::Role::SpinButton); + + element.interactivity().write_a11y_info(&mut node); + + assert_eq!(node.author_id(), Some("settings.buffer-font-size")); + } + + #[test] + fn test_write_a11y_info_string_and_numeric_properties() { + let mut interactivity = Interactivity::default(); + interactivity.aria.author_id = Some("settings.buffer-font-size".into()); + interactivity.aria.label = Some("Buffer Font Size".into()); + interactivity.aria.value = Some("15".into()); + interactivity.aria.placeholder = Some("Search".into()); + interactivity.aria.numeric_value = Some(15.0); + interactivity.aria.min_numeric_value = Some(6.0); + interactivity.aria.max_numeric_value = Some(72.0); + interactivity.aria.numeric_value_step = Some(1.0); + + let mut node = accesskit::Node::new(accesskit::Role::SpinButton); + interactivity.write_a11y_info(&mut node); + + assert_eq!(node.author_id(), Some("settings.buffer-font-size")); + assert_eq!(node.label(), Some("Buffer Font Size")); + assert_eq!(node.value(), Some("15")); + assert_eq!(node.placeholder(), Some("Search")); + assert_eq!(node.numeric_value(), Some(15.0)); + assert_eq!(node.min_numeric_value(), Some(6.0)); + assert_eq!(node.max_numeric_value(), Some(72.0)); + assert_eq!(node.numeric_value_step(), Some(1.0)); + } + + /// Two focusable, clickable elements ("a" and "b") used to exercise the + /// Enter/Space -> synthesized click press/release pairing. + struct KeyboardActivationTest { + focus_a: FocusHandle, + focus_b: FocusHandle, + clicks: Rc>>, + } + + impl Render for KeyboardActivationTest { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let clicks_a = self.clicks.clone(); + let clicks_b = self.clicks.clone(); + div() + .size_full() + .child( + div() + .id("a") + .w(px(50.)) + .h(px(50.)) + .track_focus(&self.focus_a) + .on_click(move |_, _, _| clicks_a.borrow_mut().push("a")), + ) + .child( + div() + .id("b") + .w(px(50.)) + .h(px(50.)) + .track_focus(&self.focus_b) + .on_click(move |_, _, _| clicks_b.borrow_mut().push("b")), + ) + } + } + + fn setup_keyboard_activation_test() -> ( + TestAppContext, + AnyWindowHandle, + Rc>>, + FocusHandle, + FocusHandle, + ) { + let mut cx = TestAppContext::single(); + let (focus_a, focus_b) = cx.update(|cx| (cx.focus_handle(), cx.focus_handle())); + let clicks: Rc>> = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let focus_a = focus_a.clone(); + let focus_b = focus_b.clone(); + let clicks = clicks.clone(); + move |_, _| KeyboardActivationTest { + focus_a, + focus_b, + clicks, + } + }); + (cx, window.into(), clicks, focus_a, focus_b) + } + + /// Move focus to `handle`, flush effects, then paint so the newly focused + /// element registers its key handlers for the next dispatched event. + fn focus_and_draw(cx: &mut TestAppContext, window: AnyWindowHandle, handle: &FocusHandle) { + cx.update_window(window, |_, window, cx| window.focus(handle, cx)) + .unwrap(); + cx.run_until_parked(); + cx.update_window(window, |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + } + + fn key_down(cx: &mut TestAppContext, window: AnyWindowHandle, key: &str) { + let keystroke = Keystroke::parse(key).unwrap(); + cx.update_window(window, |_, window, cx| { + window.dispatch_event( + KeyDownEvent { + keystroke, + is_held: false, + prefer_character_input: false, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + } + + fn key_up(cx: &mut TestAppContext, window: AnyWindowHandle, key: &str) { + let keystroke = Keystroke::parse(key).unwrap(); + cx.update_window(window, |_, window, cx| { + window.dispatch_event(KeyUpEvent { keystroke }.to_platform_input(), cx); + }) + .unwrap(); + } + + /// Pressing and releasing Enter on the same focused element fires a click. + #[test] + fn keyboard_activation_fires_click_on_same_element() { + let (mut cx, window, clicks, focus_a, _focus_b) = setup_keyboard_activation_test(); + + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "enter"); + key_up(&mut cx, window, "enter"); + + assert_eq!(*clicks.borrow(), vec!["a"]); + } + + /// A key-down whose key-up lands on a *different* element (because focus + /// moved in between) must not leak a synthesized click onto the newly + /// focused element. This is the core regression: previously the key-up + /// handler fired unconditionally on whatever was focused at key-up time. + #[test] + fn keyboard_activation_does_not_leak_across_focus_change() { + let (mut cx, window, clicks, focus_a, focus_b) = setup_keyboard_activation_test(); + + // Enter pressed while "a" is focused... + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "enter"); + + // ...focus moves to "b" before the release (as a confirm action would)... + focus_and_draw(&mut cx, window, &focus_b); + key_up(&mut cx, window, "enter"); + + // ...so neither element is clicked: "a" never saw the up, and "b" + // never saw the down. + assert!(clicks.borrow().is_empty(), "clicks: {:?}", clicks.borrow()); + } + + /// A keydown whose flag is left pending because focus moved away before + /// the keyup must not fire a click when focus later *returns* to the same + /// element (the menu trigger reopening case). The stamped focus generation + /// no longer matches, so the stale pending state is ignored. + #[test] + fn keyboard_activation_does_not_leak_when_focus_returns() { + let (mut cx, window, clicks, focus_a, focus_b) = setup_keyboard_activation_test(); + + // Enter pressed on "a"... + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "enter"); + + // ...focus leaves "a" before its keyup (so the pending state is never + // consumed), then comes back to "a"... + focus_and_draw(&mut cx, window, &focus_b); + focus_and_draw(&mut cx, window, &focus_a); + key_up(&mut cx, window, "enter"); + + // ...and the now-stale pending keydown must not fire a click. + assert!(clicks.borrow().is_empty(), "clicks: {:?}", clicks.borrow()); + } + + /// A non-activation key *released* during the press must cancel the pending + /// activation. For the sequence escape-down, space-down, escape-up, + /// space-up the space forms a clean down/up pair, but the intervening + /// escape-up means this isn't a plain space activation, so no click fires. + #[test] + fn keyboard_activation_cleared_by_intervening_key_release() { + let (mut cx, window, clicks, focus_a, _focus_b) = setup_keyboard_activation_test(); + + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "escape"); + key_down(&mut cx, window, "space"); + key_up(&mut cx, window, "escape"); + key_up(&mut cx, window, "space"); + + assert!(clicks.borrow().is_empty(), "clicks: {:?}", clicks.borrow()); + } + + /// The flag is a single activation marker, not keyed by which activation + /// key was used, so a Space down paired with an Enter up on the same + /// element still fires a click. + #[test] + fn keyboard_activation_does_not_distinguish_space_and_enter() { + let (mut cx, window, clicks, focus_a, _focus_b) = setup_keyboard_activation_test(); + + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "space"); + key_up(&mut cx, window, "enter"); + + assert_eq!(*clicks.borrow(), vec!["a"]); + } + + /// A non-activation key pressed between the activation down and up clears + /// the pending flag, suppressing the click. + #[test] + fn keyboard_activation_cleared_by_intervening_keydown() { + let (mut cx, window, clicks, focus_a, _focus_b) = setup_keyboard_activation_test(); + + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "enter"); + key_down(&mut cx, window, "a"); + key_up(&mut cx, window, "enter"); + + assert!(clicks.borrow().is_empty(), "clicks: {:?}", clicks.borrow()); + } + + /// A modified Enter (e.g. cmd-enter) is not treated as an activation key, + /// so it neither sets the pending flag nor fires a click on release. + #[test] + fn keyboard_activation_ignores_modified_keys() { + let (mut cx, window, clicks, focus_a, _focus_b) = setup_keyboard_activation_test(); + + focus_and_draw(&mut cx, window, &focus_a); + key_down(&mut cx, window, "cmd-enter"); + key_up(&mut cx, window, "cmd-enter"); + + assert!(clicks.borrow().is_empty(), "clicks: {:?}", clicks.borrow()); + } + + /// Two sibling tab groups, each a focusable container that is *not* itself a + /// tab stop and holds a single tab stop. Mirrors how the title bar and + /// status bar expose their controls as ARIA toolbars. + struct TabGroupFocus { + group_a: FocusHandle, + item_a: FocusHandle, + group_b: FocusHandle, + item_b: FocusHandle, + } + + impl Render for TabGroupFocus { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + fn group(container: &FocusHandle, item: &FocusHandle) -> Div { + div() + .track_focus(container) + .tab_group() + .child(div().track_focus(item)) + } + div() + .child(group(&self.group_a, &self.item_a)) + .child(group(&self.group_b, &self.item_b)) + } + } + + /// Focusing a tab-group container and pressing Tab (`focus_next`) must move + /// focus to the first tab stop *inside that container*, as documented on + /// [`InteractiveElement::tab_stop`]. + #[test] + fn focus_next_from_tab_group_container_enters_that_group() { + let mut cx = TestAppContext::single(); + let (group_a, item_a, group_b, item_b) = cx.update(|cx| { + ( + cx.focus_handle(), + cx.focus_handle().tab_stop(true), + cx.focus_handle(), + cx.focus_handle().tab_stop(true), + ) + }); + let window: AnyWindowHandle = cx + .add_window({ + let (group_a, item_a, group_b, item_b) = + (group_a, item_a, group_b.clone(), item_b.clone()); + move |_, _| TabGroupFocus { + group_a, + item_a, + group_b, + item_b, + } + }) + .into(); + cx.update_window(window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + + // Focus the *second* group's container, then advance like Tab would. + let focused = cx + .update_window(window, |_, window, cx| { + window.focus(&group_b, cx); + window.focus_next(cx); + window.focused(cx).map(|handle| handle.id) + }) + .unwrap(); + + assert_eq!(focused, Some(item_b.id)); + } + + #[gpui::test] + fn test_fractional_padding_does_not_make_a_fitting_container_scrollable( + cx: &mut TestAppContext, + ) { + struct PaddedContainer { + scroll_handle: ScrollHandle, + } + + impl Render for PaddedContainer { + fn render( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> impl IntoElement { + // 4.25px of padding snaps to 4px in layout, so a 42px child + // fits the 50px box exactly. + div().size_full().child( + div() + .id("container") + .h(px(50.)) + .w(px(100.)) + .py(px(4.25)) + .overflow_y_scroll() + .track_scroll(&self.scroll_handle) + .child(div().w_full().h(px(42.))), + ) + } + } + + let scroll_handle = ScrollHandle::new(); + let window: AnyWindowHandle = cx + .add_window({ + let scroll_handle = scroll_handle.clone(); + move |_, _| PaddedContainer { scroll_handle } + }) + .into(); + cx.update_window(window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + + assert_eq!(scroll_handle.max_offset().y, px(0.)); + } + + struct ContentSizedGrid; + + impl Render for ContentSizedGrid { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let widths = [px(100.), px(200.), px(50.)]; + div().size_full().child( + div() + .w_full() + .grid() + .grid_cols_max_content(widths.len() as u16) + .children(widths.into_iter().enumerate().map(|(index, width)| { + div() + .debug_selector(move || format!("cell-{index}")) + .w(width) + .h(px(10.)) + })), + ) + } + } + + #[gpui::test] + fn grid_cols_max_content_sizes_columns_to_their_content(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| ContentSizedGrid); + cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + + let mut bounds = |selector: &'static str| { + cx.update_window(window.into(), |_, window, _| { + window.rendered_frame.debug_bounds.get(selector).copied() + }) + .unwrap() + .unwrap_or_else(|| panic!("{selector} was not rendered")) + }; + + assert_eq!(bounds("cell-0").origin.x, px(0.)); + assert_eq!(bounds("cell-1").origin.x, px(100.)); + assert_eq!(bounds("cell-2").origin.x, px(300.)); + } +} diff --git a/vendor/gpui-pre/src/elements/image_cache.rs b/vendor/gpui-pre/src/elements/image_cache.rs new file mode 100644 index 00000000..84948145 --- /dev/null +++ b/vendor/gpui-pre/src/elements/image_cache.rs @@ -0,0 +1,330 @@ +use crate::{ + AnyElement, AnyEntity, App, AppContext, Asset, AssetLogger, Bounds, Element, ElementId, Entity, + GlobalElementId, ImageAssetLoader, ImageCacheError, InspectorElementId, IntoElement, LayoutId, + ParentElement, Pixels, RenderImage, Resource, Style, StyleRefinement, Styled, Window, hash, +}; + +use crate::asset_cache::CachedLoad; +use refineable::Refineable; +use smallvec::SmallVec; +use std::{collections::HashMap, fmt, sync::Arc}; + +/// An image cache element, all its child img elements will use the cache specified by this element. +/// Note that this could as simple as passing an `Entity` +pub fn image_cache(image_cache_provider: impl ImageCacheProvider) -> ImageCacheElement { + ImageCacheElement { + image_cache_provider: Box::new(image_cache_provider), + style: StyleRefinement::default(), + children: SmallVec::default(), + } +} + +/// A dynamically typed image cache, which can be used to store any image cache +#[derive(Clone)] +pub struct AnyImageCache { + image_cache: AnyEntity, + load_fn: fn( + image_cache: &AnyEntity, + resource: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>>, +} + +impl From> for AnyImageCache { + fn from(image_cache: Entity) -> Self { + Self { + image_cache: image_cache.into_any(), + load_fn: any_image_cache::load::, + } + } +} + +impl AnyImageCache { + /// Load an image given a resource + /// returns the result of loading the image if it has finished loading, or None if it is still loading + pub fn load( + &self, + resource: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + (self.load_fn)(&self.image_cache, resource, window, cx) + } +} + +mod any_image_cache { + use super::*; + + pub(crate) fn load( + image_cache: &AnyEntity, + resource: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + let image_cache = image_cache.clone().downcast::().unwrap(); + image_cache.update(cx, |image_cache, cx| image_cache.load(resource, window, cx)) + } +} + +/// An image cache element. +pub struct ImageCacheElement { + image_cache_provider: Box, + style: StyleRefinement, + children: SmallVec<[AnyElement; 2]>, +} + +impl ParentElement for ImageCacheElement { + fn extend(&mut self, elements: impl IntoIterator) { + self.children.extend(elements) + } +} + +impl Styled for ImageCacheElement { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} + +impl IntoElement for ImageCacheElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Element for ImageCacheElement { + type RequestLayoutState = SmallVec<[LayoutId; 4]>; + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let image_cache = self.image_cache_provider.provide(window, cx); + window.with_image_cache(Some(image_cache), |window| { + let child_layout_ids = self + .children + .iter_mut() + .map(|child| child.request_layout(window, cx)) + .collect::>(); + let mut style = Style::default(); + style.refine(&self.style); + let layout_id = window.request_layout(style, child_layout_ids.iter().copied(), cx); + (layout_id, child_layout_ids) + }) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + for child in &mut self.children { + child.prepaint(window, cx); + } + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let image_cache = self.image_cache_provider.provide(window, cx); + window.with_image_cache(Some(image_cache), |window| { + for child in &mut self.children { + child.paint(window, cx); + } + }) + } +} + +/// Owns an image load and its cached result. +/// +/// Dropping the entry cancels a pending load. Image caches must remove loaded +/// images from windows before discarding the entry. +pub struct ImageCacheItem(CachedLoad, ImageCacheError>>); + +impl std::fmt::Debug for ImageCacheItem { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ImageCacheItem") + .field("result", &self.get()) + .finish() + } +} + +impl ImageCacheItem { + /// Starts loading an image into a new cache entry. + pub fn new(source: &Resource, cx: &mut App) -> Self { + let future = AssetLogger::::load(source.clone(), cx); + Self(CachedLoad::new(future, cx)) + } + + /// Returns the cached result without subscribing to completion notifications. + pub fn get(&self) -> Option, ImageCacheError>> { + self.0.get() + } + + /// Returns the cached result or subscribes the current view to completion. + pub fn use_image(&self, window: &Window) -> Option, ImageCacheError>> { + self.0.use_by(window.current_view()) + } +} + +/// An object that can handle the caching and unloading of images. +/// Implementations of this trait should ensure that images are removed from all windows when they are no longer needed. +pub trait ImageCache: 'static { + /// Load an image given a resource + /// returns the result of loading the image if it has finished loading, or None if it is still loading + fn load( + &mut self, + resource: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>>; +} + +/// An object that can create an ImageCache during the render phase. +/// See the ImageCache trait for more information. +pub trait ImageCacheProvider: 'static { + /// Called during the request_layout phase to create an ImageCache. + fn provide(&mut self, _window: &mut Window, _cx: &mut App) -> AnyImageCache; +} + +impl ImageCacheProvider for Entity { + fn provide(&mut self, _window: &mut Window, _cx: &mut App) -> AnyImageCache { + self.clone().into() + } +} + +/// An implementation of ImageCache, that uses an LRU caching strategy to unload images when the cache is full +pub struct RetainAllImageCache(HashMap); + +impl fmt::Debug for RetainAllImageCache { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("HashMapImageCache") + .field("num_images", &self.0.len()) + .finish() + } +} + +impl RetainAllImageCache { + /// Create a new image cache. + #[inline] + pub fn new(cx: &mut App) -> Entity { + let e = cx.new(|_cx| RetainAllImageCache(HashMap::new())); + cx.observe_release(&e, |image_cache, cx| { + for (_, item) in std::mem::replace(&mut image_cache.0, HashMap::new()) { + if let Some(Ok(image)) = item.get() { + cx.drop_image(image, None); + } + } + }) + .detach(); + e + } + + /// Load an image from the given source. + /// + /// Returns `None` if the image is loading. + pub fn load( + &mut self, + source: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + let hash = hash(source); + + self.0 + .entry(hash) + .or_insert_with(|| ImageCacheItem::new(source, cx)) + .use_image(window) + } + + /// Clear the image cache. + pub fn clear(&mut self, window: &mut Window, cx: &mut App) { + for (_, item) in std::mem::replace(&mut self.0, HashMap::new()) { + if let Some(Ok(image)) = item.get() { + cx.drop_image(image, Some(window)); + } + } + } + + /// Remove the image from the cache by the given source. + pub fn remove(&mut self, source: &Resource, window: &mut Window, cx: &mut App) { + let hash = hash(source); + if let Some(item) = self.0.remove(&hash) + && let Some(Ok(image)) = item.get() + { + cx.drop_image(image, Some(window)); + } + } + + /// Returns the number of images in the cache. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns true if the cache is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl ImageCache for RetainAllImageCache { + fn load( + &mut self, + resource: &Resource, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + RetainAllImageCache::load(self, resource, window, cx) + } +} + +/// Constructs a retain-all image cache that uses the element state associated with the given ID. +pub fn retain_all(id: impl Into) -> RetainAllImageCacheProvider { + RetainAllImageCacheProvider { id: id.into() } +} + +/// A provider struct for creating a retain-all image cache inline +pub struct RetainAllImageCacheProvider { + id: ElementId, +} + +impl ImageCacheProvider for RetainAllImageCacheProvider { + fn provide(&mut self, window: &mut Window, cx: &mut App) -> AnyImageCache { + window + .with_global_id(self.id.clone(), |global_id, window| { + window.with_element_state::, _>( + global_id, + |cache, _window| { + let mut cache = cache.unwrap_or_else(|| RetainAllImageCache::new(cx)); + (cache.clone(), cache) + }, + ) + }) + .into() + } +} diff --git a/vendor/gpui-pre/src/elements/img.rs b/vendor/gpui-pre/src/elements/img.rs new file mode 100644 index 00000000..2c77e5f3 --- /dev/null +++ b/vendor/gpui-pre/src/elements/img.rs @@ -0,0 +1,983 @@ +use crate::{ + AnyElement, AnyImageCache, App, Asset, AssetLogger, Bounds, DefiniteLength, Element, ElementId, + Entity, GlobalElementId, Hitbox, Image, ImageCache, InspectorElementId, InteractiveElement, + Interactivity, IntoElement, LayoutId, Length, ObjectFit, Pixels, RenderImage, Resource, + SharedString, SharedUri, StyleRefinement, Styled, Task, Window, decode_static_image, + decode_static_image_from_decoder, px, +}; +use anyhow::Result; + +use futures::Future; +use gpui_util::ResultExt; +use image::{ + AnimationDecoder, ImageError, ImageFormat, Rgba, + codecs::{gif::GifDecoder, webp::WebPDecoder}, +}; +use scheduler::Instant; +use smallvec::SmallVec; +use std::{ + fs, + io::{self, Cursor}, + ops::{Deref, DerefMut}, + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, + time::Duration, +}; +use thiserror::Error; + +use super::{Stateful, StatefulInteractiveElement}; + +/// The delay before showing the loading state. +pub const LOADING_DELAY: Duration = Duration::from_millis(200); + +/// A type alias to the resource loader that the `img()` element uses. +/// +/// Note: that this is only for Resources, like URLs or file paths. +/// Custom loaders, or external images will not use this asset loader +pub type ImgResourceLoader = AssetLogger; + +/// A source of image content. +#[derive(Clone)] +pub enum ImageSource { + /// The image content will be loaded from some resource location + Resource(Resource), + /// Cached image data + Render(Arc), + /// Cached image data + Image(Arc), + /// A custom loading function to use + Custom(Arc Option, ImageCacheError>>>), +} + +fn is_uri(uri: &str) -> bool { + url::Url::from_str(uri).is_ok() +} + +impl From for ImageSource { + fn from(value: SharedUri) -> Self { + Self::Resource(Resource::Uri(value)) + } +} + +impl<'a> From<&'a str> for ImageSource { + fn from(s: &'a str) -> Self { + if is_uri(s) { + Self::Resource(Resource::Uri(s.to_string().into())) + } else { + Self::Resource(Resource::Embedded(s.to_string().into())) + } + } +} + +impl From for ImageSource { + fn from(s: String) -> Self { + if is_uri(&s) { + Self::Resource(Resource::Uri(s.into())) + } else { + Self::Resource(Resource::Embedded(s.into())) + } + } +} + +impl From for ImageSource { + fn from(s: SharedString) -> Self { + s.as_ref().into() + } +} + +impl From<&Path> for ImageSource { + fn from(value: &Path) -> Self { + Self::Resource(value.to_path_buf().into()) + } +} + +impl From> for ImageSource { + fn from(value: Arc) -> Self { + Self::Resource(value.into()) + } +} + +impl From for ImageSource { + fn from(value: PathBuf) -> Self { + Self::Resource(value.into()) + } +} + +impl From> for ImageSource { + fn from(value: Arc) -> Self { + Self::Render(value) + } +} + +impl From> for ImageSource { + fn from(value: Arc) -> Self { + Self::Image(value) + } +} + +impl From for ImageSource +where + F: Fn(&mut Window, &mut App) -> Option, ImageCacheError>> + 'static, +{ + fn from(value: F) -> Self { + Self::Custom(Arc::new(value)) + } +} + +/// The style of an image element. +pub struct ImageStyle { + grayscale: bool, + object_fit: ObjectFit, + loading: Option AnyElement>>, + fallback: Option AnyElement>>, +} + +impl Default for ImageStyle { + fn default() -> Self { + Self { + grayscale: false, + object_fit: ObjectFit::Contain, + loading: None, + fallback: None, + } + } +} + +/// Style an image element. +pub trait StyledImage: Sized { + /// Get a mutable [ImageStyle] from the element. + fn image_style(&mut self) -> &mut ImageStyle; + + /// Set the image to be displayed in grayscale. + fn grayscale(mut self, grayscale: bool) -> Self { + self.image_style().grayscale = grayscale; + self + } + + /// Set the object fit for the image. + fn object_fit(mut self, object_fit: ObjectFit) -> Self { + self.image_style().object_fit = object_fit; + self + } + + /// Set a fallback function that will be invoked to render an error view should + /// the image fail to load. + fn with_fallback(mut self, fallback: impl Fn() -> AnyElement + 'static) -> Self { + self.image_style().fallback = Some(Box::new(fallback)); + self + } + + /// Set a fallback function that will be invoked to render a view while the image + /// is still being loaded. + fn with_loading(mut self, loading: impl Fn() -> AnyElement + 'static) -> Self { + self.image_style().loading = Some(Box::new(loading)); + self + } +} + +impl StyledImage for Img { + fn image_style(&mut self) -> &mut ImageStyle { + &mut self.style + } +} + +impl StyledImage for Stateful { + fn image_style(&mut self) -> &mut ImageStyle { + &mut self.element.style + } +} + +/// An image element. +pub struct Img { + interactivity: Interactivity, + source: ImageSource, + style: ImageStyle, + image_cache: Option, +} + +/// Create a new image element. +#[track_caller] +pub fn img(source: impl Into) -> Img { + Img { + interactivity: Interactivity::new(), + source: source.into(), + style: ImageStyle::default(), + image_cache: None, + } +} + +impl Img { + /// A list of all format extensions currently supported by this img element + pub fn extensions() -> &'static [&'static str] { + // This is the list in [image::ImageFormat::from_extension] + `svg` + &[ + "avif", "jpg", "jpeg", "png", "gif", "webp", "tif", "tiff", "tga", "dds", "bmp", "ico", + "hdr", "exr", "pbm", "pam", "ppm", "pgm", "ff", "farbfeld", "qoi", "svg", + ] + } + + /// Sets the image cache for the current node. + /// + /// If the `image_cache` is not explicitly provided, the function will determine the image cache by: + /// + /// 1. Checking if any ancestor node of the current node contains an `ImageCacheElement`, If such a node exists, the image cache specified by that ancestor will be used. + /// 2. If no ancestor node contains an `ImageCacheElement`, the global image cache will be used as a fallback. + /// + /// This mechanism provides a flexible way to manage image caching, allowing precise control when needed, + /// while ensuring a default behavior when no cache is explicitly specified. + #[inline] + pub fn image_cache(self, image_cache: &Entity) -> Self { + Self { + image_cache: Some(image_cache.clone().into()), + ..self + } + } +} + +impl Deref for Stateful { + type Target = Img; + + fn deref(&self) -> &Self::Target { + &self.element + } +} + +impl DerefMut for Stateful { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.element + } +} + +/// The image state between frames +struct ImgState { + frame_index: usize, + last_frame_time: Option, + started_loading: Option<(Instant, Task<()>)>, +} + +/// The image layout state between frames +pub struct ImgLayoutState { + frame_index: usize, + replacement: Option, +} + +impl Element for Img { + type RequestLayoutState = ImgLayoutState; + type PrepaintState = Option; + + fn id(&self) -> Option { + self.interactivity.element_id.clone() + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + self.interactivity.source_location() + } + + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut layout_state = ImgLayoutState { + frame_index: 0, + replacement: None, + }; + + window.with_optional_element_state(global_id, |state, window| { + let mut state = state.map(|state| { + state.unwrap_or(ImgState { + frame_index: 0, + last_frame_time: None, + started_loading: None, + }) + }); + + let mut frame_index = state.as_ref().map(|state| state.frame_index).unwrap_or(0); + + let layout_id = self.interactivity.request_layout( + global_id, + inspector_id, + window, + cx, + |mut style, window, cx| { + let mut replacement_id = None; + + match self.source.use_data( + self.image_cache + .clone() + .or_else(|| window.image_cache_stack.last().cloned()), + window, + cx, + ) { + Some(Ok(data)) => { + let frame_count = data.frame_count(); + let max_frame_index = frame_count.saturating_sub(1); + + if let Some(state) = &mut state { + state.frame_index = state.frame_index.min(max_frame_index); + if frame_count > 1 && !cx.reduce_motion() { + if window.is_window_active() { + let current_time = Instant::now(); + if let Some(last_frame_time) = state.last_frame_time { + let elapsed = current_time - last_frame_time; + let frame_duration = + Duration::from(data.delay(state.frame_index)); + + if elapsed >= frame_duration { + state.frame_index = + (state.frame_index + 1) % frame_count; + state.last_frame_time = + Some(current_time - (elapsed - frame_duration)); + } + } else { + state.last_frame_time = Some(current_time); + } + } else { + state.last_frame_time = None; + } + } else { + state.last_frame_time = None; + } + state.started_loading = None; + frame_index = state.frame_index; + } + + let image_size = data.render_size(frame_index); + + if style.aspect_ratio.is_none() { + style.aspect_ratio = Some(image_size.width / image_size.height); + } + + if let Length::Auto = style.size.width { + style.size.width = match style.size.height { + Length::Definite(DefiniteLength::Absolute(abs_length)) => { + let height_px = abs_length.to_pixels(window.rem_size()); + Length::Definite( + px(image_size.width.0 * height_px.0 + / image_size.height.0) + .into(), + ) + } + _ => Length::Definite(image_size.width.into()), + }; + } + + if let Length::Auto = style.size.height { + style.size.height = match style.size.width { + Length::Definite(DefiniteLength::Absolute(abs_length)) => { + let width_px = abs_length.to_pixels(window.rem_size()); + Length::Definite( + px(image_size.height.0 * width_px.0 + / image_size.width.0) + .into(), + ) + } + _ => Length::Definite(image_size.height.into()), + }; + } + + if global_id.is_some() + && data.frame_count() > 1 + && window.is_window_active() + && !cx.reduce_motion() + { + window.request_animation_frame(); + } + } + Some(_err) => { + if let Some(fallback) = self.style.fallback.as_ref() { + let mut element = fallback(); + replacement_id = Some(element.request_layout(window, cx)); + layout_state.replacement = Some(element); + } + if let Some(state) = &mut state { + state.started_loading = None; + } + } + None => { + if let Some(state) = &mut state { + if let Some((started_loading, _)) = state.started_loading { + if started_loading.elapsed() > LOADING_DELAY + && let Some(loading) = self.style.loading.as_ref() + { + let mut element = loading(); + replacement_id = Some(element.request_layout(window, cx)); + layout_state.replacement = Some(element); + } + } else { + let current_view = window.current_view(); + let task = window.spawn(cx, async move |cx| { + cx.background_executor().timer(LOADING_DELAY).await; + cx.update(move |_, cx| { + cx.notify(current_view); + }) + .ok(); + }); + state.started_loading = Some((Instant::now(), task)); + } + } + } + } + + window.request_layout(style, replacement_id, cx) + }, + ); + + layout_state.frame_index = frame_index; + + ((layout_id, layout_state), state) + }) + } + + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + self.interactivity.prepaint( + global_id, + inspector_id, + bounds, + bounds.size, + window, + cx, + |_, _, hitbox, window, cx| { + if let Some(replacement) = &mut request_layout.replacement { + replacement.prepaint(window, cx); + } + + hitbox + }, + ) + } + + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + layout_state: &mut Self::RequestLayoutState, + hitbox: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let source = self.source.clone(); + self.interactivity.paint( + global_id, + inspector_id, + bounds, + hitbox.as_ref(), + window, + cx, + |style, window, cx| { + if let Some(Ok(data)) = source.use_data( + self.image_cache + .clone() + .or_else(|| window.image_cache_stack.last().cloned()), + window, + cx, + ) { + if data.frame_count() == 0 { + return; + } + let new_bounds = self + .style + .object_fit + .get_bounds(bounds, data.size(layout_state.frame_index)); + let corner_radii = style.corner_radii.to_pixels(window.rem_size()); + window + .paint_image( + bounds, + new_bounds, + corner_radii, + data, + layout_state.frame_index, + self.style.grayscale, + ) + .log_err(); + } else if let Some(replacement) = &mut layout_state.replacement { + replacement.paint(window, cx); + } + }, + ) + } +} + +impl Styled for Img { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.interactivity.base_style + } +} + +impl InteractiveElement for Img { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity + } +} + +impl IntoElement for Img { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl StatefulInteractiveElement for Img {} + +impl ImageSource { + pub(crate) fn use_data( + &self, + cache: Option, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + match self { + ImageSource::Resource(resource) => { + if let Some(cache) = cache { + cache.load(resource, window, cx) + } else { + window.use_asset::(resource, cx) + } + } + ImageSource::Custom(loading_fn) => loading_fn(window, cx), + ImageSource::Render(data) => Some(Ok(data.to_owned())), + ImageSource::Image(data) => window.use_asset::>(data, cx), + } + } + + pub(crate) fn get_data( + &self, + cache: Option, + window: &mut Window, + cx: &mut App, + ) -> Option, ImageCacheError>> { + match self { + ImageSource::Resource(resource) => { + if let Some(cache) = cache { + cache.load(resource, window, cx) + } else { + window.get_asset::(resource, cx) + } + } + ImageSource::Custom(loading_fn) => loading_fn(window, cx), + ImageSource::Render(data) => Some(Ok(data.to_owned())), + ImageSource::Image(data) => window.get_asset::>(data, cx), + } + } + + /// Remove this image source from the asset system + pub fn remove_asset(&self, cx: &mut App) { + match self { + ImageSource::Resource(resource) => { + cx.remove_asset::(resource); + } + ImageSource::Custom(_) | ImageSource::Render(_) => {} + ImageSource::Image(data) => cx.remove_asset::>(data), + } + } + + /// Check whether this image source is present in the asset system (loading + /// or loaded), without fetching it. + #[cfg(any(test, feature = "test-support"))] + pub fn is_asset_cached(&self, cx: &App) -> bool { + match self { + ImageSource::Resource(resource) => cx.has_asset::(resource), + ImageSource::Custom(_) | ImageSource::Render(_) => false, + ImageSource::Image(data) => cx.has_asset::>(data), + } + } +} + +#[derive(Clone)] +enum ImageDecoder {} + +impl Asset for ImageDecoder { + type Source = Arc; + type Output = Result, ImageCacheError>; + + fn load( + source: Self::Source, + cx: &mut App, + ) -> impl Future + Send + 'static { + let renderer = cx.svg_renderer(); + async move { source.to_image_data(renderer).map_err(Into::into) } + } +} + +/// An image loader for the GPUI asset system +#[derive(Clone)] +pub enum ImageAssetLoader {} + +impl Asset for ImageAssetLoader { + type Source = Resource; + type Output = Result, ImageCacheError>; + + fn load( + source: Self::Source, + cx: &mut App, + ) -> impl Future + Send + 'static { + let client = cx.http_client(); + // TODO: Can we make SVGs always rescale? + // let scale_factor = cx.scale_factor(); + let svg_renderer = cx.svg_renderer(); + let asset_source = cx.asset_source().clone(); + async move { + let bytes = match source.clone() { + Resource::Path(uri) => fs::read(uri.as_ref())?, + Resource::Uri(uri) => { + use anyhow::Context as _; + use futures::AsyncReadExt as _; + + let mut response = client + .get(uri.as_ref(), ().into(), true) + .await + .with_context(|| format!("loading image asset from {uri:?}"))?; + let mut body = Vec::new(); + response.body_mut().read_to_end(&mut body).await?; + if !response.status().is_success() { + let mut body = String::from_utf8_lossy(&body).into_owned(); + let first_line = body.lines().next().unwrap_or("").trim_end(); + body.truncate(first_line.len()); + return Err(ImageCacheError::BadStatus { + uri, + status: response.status(), + body, + }); + } + body + } + Resource::Embedded(path) => { + let data = asset_source.load(&path).ok().flatten(); + if let Some(data) = data { + data.to_vec() + } else { + return Err(ImageCacheError::Asset( + format!("Embedded resource not found: {}", path).into(), + )); + } + } + }; + + if let Ok(format) = image::guess_format(&bytes) { + let data = match format { + ImageFormat::Gif => { + let decoder = GifDecoder::new(Cursor::new(&bytes))?; + let mut frames = SmallVec::new(); + + for frame in decoder.into_frames() { + match frame { + Ok(mut frame) => { + // Convert from RGBA to BGRA. + for pixel in frame.buffer_mut().chunks_exact_mut(4) { + pixel.swap(0, 2); + } + frames.push(frame); + } + Err(err) => { + log::debug!( + "Skipping GIF frame in {source:?} due to decode error: {err}" + ); + } + } + } + + if frames.is_empty() { + return Err(ImageCacheError::Other(Arc::new(anyhow::anyhow!( + "GIF could not be decoded: all frames failed ({source:?})" + )))); + } + + frames + } + ImageFormat::WebP => { + let mut decoder = WebPDecoder::new(Cursor::new(&bytes))?; + + if decoder.has_animation() { + let _ = decoder.set_background_color(Rgba([0, 0, 0, 0])); + let mut frames = SmallVec::new(); + + for frame in decoder.into_frames() { + match frame { + Ok(mut frame) => { + // Convert from RGBA to BGRA. + for pixel in frame.buffer_mut().chunks_exact_mut(4) { + pixel.swap(0, 2); + } + frames.push(frame); + } + Err(err) => { + log::debug!( + "Skipping WebP frame in {source:?} due to decode error: {err}" + ); + } + } + } + + if frames.is_empty() { + return Err(ImageCacheError::Other(Arc::new(anyhow::anyhow!( + "WebP could not be decoded: all frames failed ({source:?})" + )))); + } + + frames + } else { + decode_static_image_from_decoder(decoder)? + } + } + _ => decode_static_image(&bytes, format)?, + }; + + Ok(Arc::new(RenderImage::new(data))) + } else { + svg_renderer + .render_single_frame(&bytes, 1.0) + .map_err(Into::into) + } + } + } +} + +/// An error that can occur when interacting with the image cache. +#[derive(Debug, Error, Clone)] +pub enum ImageCacheError { + /// Some other kind of error occurred + #[error("error: {0}")] + Other(#[from] Arc), + /// An error that occurred while reading the image from disk. + #[error("IO error: {0}")] + Io(Arc), + /// An error that occurred while processing an image. + #[error("unexpected http status for {uri}: {status}, body: {body}")] + BadStatus { + /// The URI of the image. + uri: SharedUri, + /// The HTTP status code. + status: http_client::StatusCode, + /// The HTTP response body. + body: String, + }, + /// An error that occurred while processing an asset. + #[error("asset error: {0}")] + Asset(SharedString), + /// An error that occurred while processing an image. + #[error("image error: {0}")] + Image(Arc), + /// An error that occurred while processing an SVG. + #[error("svg error: {0}")] + Usvg(Arc), +} + +impl From for ImageCacheError { + fn from(value: anyhow::Error) -> Self { + Self::Other(Arc::new(value)) + } +} + +impl From for ImageCacheError { + fn from(value: io::Error) -> Self { + Self::Io(Arc::new(value)) + } +} + +impl From for ImageCacheError { + fn from(value: usvg::Error) -> Self { + Self::Usvg(Arc::new(value)) + } +} + +impl From for ImageCacheError { + fn from(value: image::ImageError) -> Self { + Self::Image(Arc::new(value)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ParentElement as _, TestAppContext, canvas, div, point, px, size}; + use image::{Frame, ImageBuffer, Rgba}; + + const TEST_IMG_ID: &str = "test-img"; + + fn test_image(frame_count: usize) -> Arc { + let frame = Frame::new(ImageBuffer::from_pixel(1, 1, Rgba([0, 0, 0, 0]))); + Arc::new(RenderImage::new(SmallVec::from_iter( + (0..frame_count).map(|_| frame.clone()), + ))) + } + + fn test_image_with_size(width: u32, height: u32) -> Arc { + let frame = Frame::new(ImageBuffer::from_pixel(width, height, Rgba([0, 0, 0, 0]))); + Arc::new(RenderImage::new(SmallVec::from_elem(frame, 1))) + } + + /// Overwrites the cached `frame_index` of the sibling `img` during paint. + fn seed_frame_index(frame_index: usize) -> impl IntoElement { + canvas( + |_, _, _| (), + move |_, _, window, _| { + window.with_global_id(TEST_IMG_ID.into(), |id, window| { + window.with_element_state::(id, |state, _| { + let mut state = state.expect("img state should be initialized"); + state.frame_index = frame_index; + ((), state) + }); + }); + }, + ) + } + + #[gpui::test] + fn zero_frame_image_does_not_panic_on_paint(cx: &mut TestAppContext) { + cx.add_empty_window() + .draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + img(ImageSource::Render(test_image(0))).into_any_element() + }); + } + + #[gpui::test] + fn image_object_fit_cover_crops_to_element_bounds(cx: &mut TestAppContext) { + let window = cx.add_empty_window(); + let image = test_image_with_size(200, 100); + window.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + img(ImageSource::Render(image.clone())) + .size_full() + .object_fit(ObjectFit::Fill) + .into_any_element() + }); + let full_tile_bounds = window.update(|window, _| { + window + .rendered_frame + .scene + .polychrome_sprites + .last() + .expect("fill image should paint a sprite") + .tile + .bounds + }); + + window.draw(point(px(10.), px(20.)), size(px(100.), px(100.)), |_, _| { + img(ImageSource::Render(image)) + .size_full() + .object_fit(ObjectFit::Cover) + .into_any_element() + }); + + let (rendered_bounds, rendered_tile_bounds, scale_factor) = window.update(|window, _| { + let sprite = window + .rendered_frame + .scene + .polychrome_sprites + .last() + .expect("cover image should paint a sprite"); + (sprite.bounds, sprite.tile.bounds, window.scale_factor()) + }); + assert_eq!( + rendered_bounds, + Bounds { + origin: point(px(10.).scale(scale_factor), px(20.).scale(scale_factor)), + size: size(px(100.).scale(scale_factor), px(100.).scale(scale_factor)), + } + ); + assert_eq!( + ( + rendered_tile_bounds.origin.x.0 - full_tile_bounds.origin.x.0, + rendered_tile_bounds.origin.y.0 - full_tile_bounds.origin.y.0, + rendered_tile_bounds.size.width.0, + rendered_tile_bounds.size.height.0, + ), + (50, 0, 100, 100), + ); + } + + #[gpui::test] + fn explicit_aspect_ratio_is_not_overridden_by_intrinsic_ratio(cx: &mut TestAppContext) { + let window = cx.add_empty_window(); + + // A portrait image in a square container + window.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + div() + .size(px(100.)) + .overflow_hidden() + .child( + img(ImageSource::Render(test_image_with_size(100, 200))) + .size_full() + .aspect_square() + .object_fit(ObjectFit::Contain), + ) + .into_any_element() + }); + + let (rendered_bounds, scale_factor) = window.update(|window, _| { + let sprite = window + .rendered_frame + .scene + .polychrome_sprites + .last() + .expect("contained image should paint a sprite"); + (sprite.bounds, window.scale_factor()) + }); + + // The element stays 100x100, so the image is letterboxed horizontally + assert_eq!( + rendered_bounds, + Bounds { + origin: point(px(25.).scale(scale_factor), px(0.).scale(scale_factor)), + size: size(px(50.).scale(scale_factor), px(100.).scale(scale_factor)), + } + ); + } + + #[gpui::test] + fn image_object_fit_cover_clamps_corner_radii_to_visible_bounds(cx: &mut TestAppContext) { + let window = cx.add_empty_window(); + window.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + img(ImageSource::Render(test_image_with_size(200, 100))) + .size_full() + .rounded(px(100.)) + .object_fit(ObjectFit::Cover) + .into_any_element() + }); + + let (corner_radius, expected_corner_radius) = window.update(|window, _| { + ( + window + .rendered_frame + .scene + .polychrome_sprites + .last() + .map(|sprite| sprite.corner_radii.top_left), + px(50.).scale(window.scale_factor()), + ) + }); + assert_eq!(corner_radius, Some(expected_corner_radius)); + } + + #[gpui::test] + fn stale_frame_index_is_clamped_when_image_changes(cx: &mut TestAppContext) { + let window = cx.add_empty_window(); + + // Assert that a cached frame_index from a previous multi-frame image + // does not cause an out-of-bounds panic when the image is replaced + // with one that has fewer frames. + window.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + div() + .child(img(ImageSource::Render(test_image(5))).id(TEST_IMG_ID)) + .child(seed_frame_index(4)) + .into_any_element() + }); + window.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| { + img(ImageSource::Render(test_image(1))) + .id(TEST_IMG_ID) + .into_any_element() + }); + } +} diff --git a/vendor/gpui-pre/src/elements/list.rs b/vendor/gpui-pre/src/elements/list.rs new file mode 100644 index 00000000..fa21d107 --- /dev/null +++ b/vendor/gpui-pre/src/elements/list.rs @@ -0,0 +1,2973 @@ +//! A list element that can be used to render a large number of differently sized elements +//! efficiently. Clients of this API need to ensure that elements outside of the scrolled +//! area do not change their height for this element to function correctly. If your elements +//! do change height, notify the list element via [`ListState::splice`] or [`ListState::reset`]. +//! In order to minimize re-renders, this element's state is stored intrusively +//! on your own views, so that your code can coordinate directly with the list element's cached state. +//! +//! If all of your elements are the same height, see [`crate::UniformList`] for a simpler API + +use crate::{ + AnyElement, App, AvailableSpace, Bounds, ContentMask, DispatchPhase, Edges, Element, EntityId, + FocusHandle, GlobalElementId, Hitbox, HitboxBehavior, InspectorElementId, IntoElement, + Overflow, Pixels, Point, ScrollDelta, ScrollWheelEvent, Size, Style, StyleRefinement, Styled, + Window, point, px, size, +}; +use collections::VecDeque; +use refineable::Refineable as _; +use std::{cell::RefCell, ops::Range, rc::Rc}; +use sum_tree::{Bias, Dimensions, SumTree}; + +type RenderItemFn = dyn FnMut(usize, &mut Window, &mut App) -> AnyElement + 'static; + +/// Construct a new list element +pub fn list( + state: ListState, + render_item: impl FnMut(usize, &mut Window, &mut App) -> AnyElement + 'static, +) -> List { + List { + state, + render_item: Box::new(render_item), + style: StyleRefinement::default(), + sizing_behavior: ListSizingBehavior::default(), + } +} + +/// A list element +pub struct List { + state: ListState, + render_item: Box, + style: StyleRefinement, + sizing_behavior: ListSizingBehavior, +} + +impl List { + /// Set the sizing behavior for the list. + pub fn with_sizing_behavior(mut self, behavior: ListSizingBehavior) -> Self { + self.sizing_behavior = behavior; + self + } +} + +/// The list state that views must hold on behalf of the list element. +#[derive(Clone)] +pub struct ListState(Rc>); + +impl std::fmt::Debug for ListState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("ListState") + } +} + +struct StateInner { + last_layout_bounds: Option>, + last_padding: Option>, + items: SumTree, + logical_scroll_top: Option, + alignment: ListAlignment, + overdraw: Pixels, + reset: bool, + #[allow(clippy::type_complexity)] + scroll_handler: Option>, + scrollbar_drag_start_height: Option, + measuring_behavior: ListMeasuringBehavior, + pending_scroll: Option, + follow_state: FollowState, +} + +/// Deferred scroll adjustment applied after the scroll-top item has been remeasured. +/// +/// An absolute pending scroll preserves the same pixel offset into the item, which keeps +/// visible text stable while content is appended to or removed from that item. A +/// proportional pending scroll preserves the same fractional position within the item, +/// which is useful when the whole list is being resized and each item scales similarly. +#[derive(Clone)] +enum PendingScroll { + /// Preserve the same pixel offset into the item after it is remeasured. + Absolute { item_ix: usize, offset: Pixels }, + /// Preserve the same fractional offset into the item after it is remeasured. + Proportional(PendingScrollFraction), +} + +/// Keeps track of a fractional scroll position within an item for restoration +/// after remeasurement. +#[derive(Clone)] +struct PendingScrollFraction { + /// The index of the item to scroll within. + item_ix: usize, + /// Fractional offset (0.0 to 1.0) within the item's height. + fraction: f32, +} + +/// Determines how remeasurement preserves the scroll position when the scroll-top item +/// changes height. +enum ScrollAnchor { + /// Preserve the same pixel offset into the scroll-top item. + Absolute, + /// Preserve the same fractional position within the scroll-top item. + Proportional, +} + +/// Controls whether the list automatically follows new content at the end. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub enum FollowMode { + /// Normal scrolling — no automatic following. + #[default] + Normal, + /// The list should auto-scroll along with the tail, when scrolled to bottom. + Tail, +} + +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +enum FollowState { + #[default] + Normal, + Tail { + is_following: bool, + }, +} + +impl FollowState { + fn is_following(&self) -> bool { + matches!(self, FollowState::Tail { is_following: true }) + } + + fn has_stopped_following(&self) -> bool { + matches!( + self, + FollowState::Tail { + is_following: false + } + ) + } + + fn start_following(&mut self) { + if let FollowState::Tail { + is_following: false, + } = self + { + *self = FollowState::Tail { is_following: true }; + } + } + + fn stop_following(&mut self) { + if let FollowState::Tail { is_following: true } = self { + *self = FollowState::Tail { + is_following: false, + }; + } + } +} + +/// Whether the list is scrolling from top to bottom or bottom to top. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ListAlignment { + /// The list is scrolling from top to bottom, like most lists. + Top, + /// The list is scrolling from bottom to top, like a chat log. + Bottom, +} + +/// A scroll event that has been converted to be in terms of the list's items. +pub struct ListScrollEvent { + /// The range of items currently visible in the list, after applying the scroll event. + pub visible_range: Range, + + /// The number of items that are currently visible in the list, after applying the scroll event. + pub count: usize, + + /// Whether the list has been scrolled. + pub is_scrolled: bool, + + /// Whether the list is currently in follow-tail mode (auto-scrolling to end). + pub is_following_tail: bool, +} + +/// The sizing behavior to apply during layout. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ListSizingBehavior { + /// The list should calculate its size based on the size of its items. + Infer, + /// The list should not calculate a fixed size. + #[default] + Auto, +} + +/// The measuring behavior to apply during layout. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ListMeasuringBehavior { + /// Measure all items in the list. + /// Note: This can be expensive for the first frame in a large list. + Measure(bool), + /// Only measure visible items + #[default] + Visible, +} + +impl ListMeasuringBehavior { + fn reset(&mut self) { + match self { + ListMeasuringBehavior::Measure(has_measured) => *has_measured = false, + ListMeasuringBehavior::Visible => {} + } + } +} + +/// The horizontal sizing behavior to apply during layout. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ListHorizontalSizingBehavior { + /// List items' width can never exceed the width of the list. + #[default] + FitList, + /// List items' width may go over the width of the list, if any item is wider. + Unconstrained, +} + +struct LayoutItemsResponse { + max_item_width: Pixels, + scroll_top: ListOffset, + item_layouts: VecDeque, +} + +struct ItemLayout { + index: usize, + element: AnyElement, + size: Size, +} + +/// Frame state used by the [List] element after layout. +pub struct ListPrepaintState { + hitbox: Hitbox, + layout: LayoutItemsResponse, +} + +#[derive(Clone)] +enum ListItem { + Unmeasured { + size_hint: Option>, + focus_handle: Option, + }, + Measured { + size: Size, + focus_handle: Option, + }, +} + +impl ListItem { + fn size(&self) -> Option> { + if let ListItem::Measured { size, .. } = self { + Some(*size) + } else { + None + } + } + + fn size_hint(&self) -> Option> { + match self { + ListItem::Measured { size, .. } => Some(*size), + ListItem::Unmeasured { size_hint, .. } => *size_hint, + } + } + + fn focus_handle(&self) -> Option { + match self { + ListItem::Unmeasured { focus_handle, .. } | ListItem::Measured { focus_handle, .. } => { + focus_handle.clone() + } + } + } + + fn contains_focused(&self, window: &Window, cx: &App) -> bool { + match self { + ListItem::Unmeasured { focus_handle, .. } | ListItem::Measured { focus_handle, .. } => { + focus_handle + .as_ref() + .is_some_and(|handle| handle.contains_focused(window, cx)) + } + } + } +} + +#[derive(Clone, Debug, Default, PartialEq)] +struct ListItemSummary { + count: usize, + rendered_count: usize, + unrendered_count: usize, + height: Pixels, + has_focus_handles: bool, + has_unknown_height: bool, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +struct Count(usize); + +#[derive(Clone, Debug, Default)] +struct Height(Pixels); + +impl ListState { + /// Construct a new list state, for storage on a view. + /// + /// The overdraw parameter controls how much extra space is rendered + /// above and below the visible area. Elements within this area will + /// be measured even though they are not visible. This can help ensure + /// that the list doesn't flicker or pop in when scrolling. + pub fn new(item_count: usize, alignment: ListAlignment, overdraw: Pixels) -> Self { + let this = Self(Rc::new(RefCell::new(StateInner { + last_layout_bounds: None, + last_padding: None, + items: SumTree::default(), + logical_scroll_top: None, + alignment, + overdraw, + scroll_handler: None, + reset: false, + scrollbar_drag_start_height: None, + measuring_behavior: ListMeasuringBehavior::default(), + pending_scroll: None, + follow_state: FollowState::default(), + }))); + this.splice(0..0, item_count); + this + } + + /// Set the list to measure all items in the list in the first layout phase. + /// + /// This is useful for ensuring that the scrollbar size is correct instead of based on only rendered elements. + pub fn measure_all(self) -> Self { + self.0.borrow_mut().measuring_behavior = ListMeasuringBehavior::Measure(false); + self + } + + /// Pre-populate every unmeasured item with a uniform height hint so the scrollbar thumb + /// is correctly sized from the first frame, without measuring all items up front. + /// + /// As items are actually rendered their real heights replace the hint, so the scrollbar + /// converges to the exact size over time. This is a cheaper alternative to [`Self::measure_all`] + /// for lists where items have roughly uniform heights (e.g. table rows). + pub fn with_uniform_item_height(self, height: Pixels) -> Self { + self.apply_uniform_item_height(height); + self + } + + /// Reset this instantiation of the list state. + /// + /// Note that this will cause scroll events to be dropped until the next paint. + pub fn reset(&self, element_count: usize) { + let old_count = { + let state = &mut *self.0.borrow_mut(); + state.reset = true; + state.measuring_behavior.reset(); + state.logical_scroll_top = None; + state.pending_scroll = None; + state.scrollbar_drag_start_height = None; + state.items.summary().count + }; + + self.splice(0..old_count, element_count); + } + + /// Reset the list to `element_count` items, pre-populating every item with a + /// uniform height hint so the scrollbar thumb is correctly sized from the first + /// frame even for off-screen items. + pub fn reset_with_uniform_height(&self, element_count: usize, height: Pixels) { + self.reset(element_count); + self.apply_uniform_item_height(height); + } + + fn apply_uniform_item_height(&self, height: Pixels) { + let size_hint = Size { + width: px(0.), + height, + }; + let mut state = self.0.borrow_mut(); + let new_items = state + .items + .iter() + .map(|item| ListItem::Unmeasured { + size_hint: Some(item.size_hint().unwrap_or(size_hint)), + focus_handle: item.focus_handle(), + }) + .collect::>(); + let mut tree = SumTree::default(); + tree.extend(new_items, ()); + state.items = tree; + } + + /// Remeasure all items while preserving proportional scroll position. + /// + /// Use this when item heights may have changed (e.g., font size changes) + /// but the number and identity of items remains the same. + pub fn remeasure(&self) { + let count = self.item_count(); + self.remeasure_items_with_scroll_anchor(0..count, ScrollAnchor::Proportional); + } + + /// Mark items in `range` as needing remeasurement while preserving + /// the current scroll position. Unlike [`Self::splice`], this does + /// not change the number of items or blow away `logical_scroll_top`. + /// + /// Use this when an item's content has changed and its rendered + /// height may be different (e.g., streaming text, tool results + /// loading), but the item itself still exists at the same index. + pub fn remeasure_items(&self, range: Range) { + self.remeasure_items_with_scroll_anchor(range, ScrollAnchor::Absolute); + } + + fn remeasure_items_with_scroll_anchor(&self, range: Range, scroll_anchor: ScrollAnchor) { + let state = &mut *self.0.borrow_mut(); + + if let Some(scroll_top) = state.logical_scroll_top { + if range.contains(&scroll_top.item_ix) { + state.pending_scroll = match scroll_anchor { + ScrollAnchor::Absolute => Some(PendingScroll::Absolute { + item_ix: scroll_top.item_ix, + offset: scroll_top.offset_in_item, + }), + ScrollAnchor::Proportional => { + // If the scroll-top item falls within the remeasured range, + // store a fractional offset so the layout can restore the + // proportional scroll position after the item is re-rendered + // at its new height. + let mut cursor = state.items.cursor::(()); + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + + cursor + .item() + .and_then(|item| { + item.size().map(|size| { + let fraction = if size.height.0 > 0.0 { + (scroll_top.offset_in_item.0 / size.height.0) + .clamp(0.0, 1.0) + } else { + 0.0 + }; + + PendingScroll::Proportional(PendingScrollFraction { + item_ix: scroll_top.item_ix, + fraction, + }) + }) + }) + .or_else(|| state.pending_scroll.clone()) + } + }; + } + } + + // Rebuild the tree, replacing items in the range with + // Unmeasured copies that keep their focus handles. + let new_items = { + let mut cursor = state.items.cursor::(()); + let mut new_items = cursor.slice(&Count(range.start), Bias::Right); + let invalidated = cursor.slice(&Count(range.end), Bias::Right); + new_items.extend( + invalidated.iter().map(|item| ListItem::Unmeasured { + size_hint: item.size_hint(), + focus_handle: item.focus_handle(), + }), + (), + ); + new_items.append(cursor.suffix(), ()); + new_items + }; + state.items = new_items; + state.measuring_behavior.reset(); + } + + /// The number of items in this list. + pub fn item_count(&self) -> usize { + self.0.borrow().items.summary().count + } + + /// Whether the list is scrolled to the end, or `None` if the list is + /// not scrollable or the total content height is not yet known. + pub fn is_scrolled_to_end(&self) -> Option { + let state = self.0.borrow(); + let bounds = state.last_layout_bounds?; + let summary = state.items.summary(); + if summary.has_unknown_height { + return None; + } + let padding = state.last_padding.unwrap_or_default(); + let content_height = summary.height + padding.top + padding.bottom; + let scroll_max = (content_height - bounds.size.height).max(px(0.)); + if scroll_max <= px(0.) { + return None; + } + let scroll_top = state.scroll_top(&state.logical_scroll_top()); + Some(scroll_top >= scroll_max) + } + + /// Inform the list state that the items in `old_range` have been replaced + /// by `count` new items that must be recalculated. + pub fn splice(&self, old_range: Range, count: usize) { + self.splice_focusable(old_range, (0..count).map(|_| None)) + } + + /// Register with the list state that the items in `old_range` have been replaced + /// by new items. As opposed to [`Self::splice`], this method allows an iterator of optional focus handles + /// to be supplied to properly integrate with items in the list that can be focused. If a focused item + /// is scrolled out of view, the list will continue to render it to allow keyboard interaction. + pub fn splice_focusable( + &self, + old_range: Range, + focus_handles: impl IntoIterator>, + ) { + let state = &mut *self.0.borrow_mut(); + + let mut old_items = state.items.cursor::(()); + let mut new_items = old_items.slice(&Count(old_range.start), Bias::Right); + old_items.seek_forward(&Count(old_range.end), Bias::Right); + + let mut spliced_count = 0; + new_items.extend( + focus_handles.into_iter().map(|focus_handle| { + spliced_count += 1; + ListItem::Unmeasured { + size_hint: None, + focus_handle, + } + }), + (), + ); + new_items.append(old_items.suffix(), ()); + drop(old_items); + state.items = new_items; + + if let Some(ListOffset { + item_ix, + offset_in_item, + }) = state.logical_scroll_top.as_mut() + { + if old_range.contains(item_ix) { + *item_ix = old_range.start; + *offset_in_item = px(0.); + } else if old_range.end <= *item_ix { + *item_ix = *item_ix - (old_range.end - old_range.start) + spliced_count; + } + } + } + + /// Set a handler that will be called when the list is scrolled. + pub fn set_scroll_handler( + &self, + handler: impl FnMut(&ListScrollEvent, &mut Window, &mut App) + 'static, + ) { + self.0.borrow_mut().scroll_handler = Some(Box::new(handler)) + } + + /// Get the current scroll offset, in terms of the list's items. + pub fn logical_scroll_top(&self) -> ListOffset { + self.0.borrow().logical_scroll_top() + } + + /// Scroll the list by the given offset + pub fn scroll_by(&self, distance: Pixels) { + if distance == px(0.) { + return; + } + + let current_offset = self.logical_scroll_top(); + let state = &mut *self.0.borrow_mut(); + + if distance < px(0.) { + state.follow_state.stop_following(); + } + + let mut cursor = state.items.cursor::(()); + cursor.seek(&Count(current_offset.item_ix), Bias::Right); + + let start_pixel_offset = cursor.start().height + current_offset.offset_in_item; + let new_pixel_offset = (start_pixel_offset + distance).max(px(0.)); + if new_pixel_offset > start_pixel_offset { + cursor.seek_forward(&Height(new_pixel_offset), Bias::Right); + } else { + cursor.seek(&Height(new_pixel_offset), Bias::Right); + } + + let scroll_top = ListOffset { + item_ix: cursor.start().count, + offset_in_item: new_pixel_offset - cursor.start().height, + }; + drop(cursor); + state.rebase_pending_scroll(scroll_top); + state.logical_scroll_top = Some(scroll_top); + } + + /// Scroll the list to the very end (past the last item). + /// + /// Unlike [`scroll_to_reveal_item`], this uses the total item count as the + /// anchor, so the list's layout pass will walk backwards from the end and + /// always show the bottom of the last item — even when that item is still + /// growing (e.g. during streaming). + pub fn scroll_to_end(&self) { + let state = &mut *self.0.borrow_mut(); + let item_count = state.items.summary().count; + state.pending_scroll = None; + state.logical_scroll_top = Some(ListOffset { + item_ix: item_count, + offset_in_item: px(0.), + }); + } + + /// Set the follow mode for the list. In `Tail` mode, the list + /// will auto-scroll to the end and re-engage after the user + /// scrolls back to the bottom. In `Normal` mode, no automatic + /// following occurs. + pub fn set_follow_mode(&self, mode: FollowMode) { + let state = &mut *self.0.borrow_mut(); + + match mode { + FollowMode::Normal => { + state.follow_state = FollowState::Normal; + } + FollowMode::Tail => { + state.follow_state = FollowState::Tail { is_following: true }; + if matches!(mode, FollowMode::Tail) { + let item_count = state.items.summary().count; + state.logical_scroll_top = Some(ListOffset { + item_ix: item_count, + offset_in_item: px(0.), + }); + } + } + } + } + + /// Pause tail-following, freezing the list at its current scroll + /// position. Unlike [`Self::set_follow_mode`] with [`FollowMode::Normal`], + /// this keeps the list in `Tail` mode, so it will resume following + /// automatically once the view returns to the bottom. No-op when the list + /// isn't currently following. + /// + /// Useful when something other than the user grows an item (e.g. zooming a + /// diagram) and the current position should stay put rather than snapping + /// to the end. + pub fn pause_following_tail(&self) { + self.0.borrow_mut().follow_state.stop_following(); + } + + /// Returns whether the list is currently actively following the + /// tail (snapping to the end on each layout). + pub fn is_following_tail(&self) -> bool { + matches!( + self.0.borrow().follow_state, + FollowState::Tail { is_following: true } + ) + } + + /// Scroll the list to the given offset + pub fn scroll_to(&self, mut scroll_top: ListOffset) { + let state = &mut *self.0.borrow_mut(); + let item_count = state.items.summary().count; + if scroll_top.item_ix >= item_count { + scroll_top.item_ix = item_count; + scroll_top.offset_in_item = px(0.); + } + + if scroll_top.item_ix < item_count { + state.follow_state.stop_following(); + } + + state.rebase_pending_scroll(scroll_top); + state.logical_scroll_top = Some(scroll_top); + } + + /// Scroll the list to the given item, such that the item is fully visible. + pub fn scroll_to_reveal_item(&self, ix: usize) { + let state = &mut *self.0.borrow_mut(); + + let mut scroll_top = state.logical_scroll_top(); + let height = state + .last_layout_bounds + .map_or(px(0.), |bounds| bounds.size.height); + let padding = state.last_padding.unwrap_or_default(); + + if ix <= scroll_top.item_ix { + scroll_top.item_ix = ix; + scroll_top.offset_in_item = px(0.); + } else { + let mut cursor = state.items.cursor::(()); + cursor.seek(&Count(ix + 1), Bias::Right); + let bottom = cursor.start().height + padding.top; + let goal_top = px(0.).max(bottom - height + padding.bottom); + + cursor.seek(&Height(goal_top), Bias::Left); + let start_ix = cursor.start().count; + let start_item_top = cursor.start().height; + + if start_ix >= scroll_top.item_ix { + scroll_top.item_ix = start_ix; + scroll_top.offset_in_item = goal_top - start_item_top; + } + } + + state.rebase_pending_scroll(scroll_top); + state.logical_scroll_top = Some(scroll_top); + } + + /// Get the bounds for the given item in window coordinates, if it's + /// been rendered. + pub fn bounds_for_item(&self, ix: usize) -> Option> { + let state = &*self.0.borrow(); + + let bounds = state.last_layout_bounds.unwrap_or_default(); + let scroll_top = state.logical_scroll_top(); + if ix < scroll_top.item_ix { + return None; + } + + let mut cursor = state.items.cursor::>(()); + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + + let scroll_top = cursor.start().1.0 + scroll_top.offset_in_item; + + cursor.seek_forward(&Count(ix), Bias::Right); + if let Some(&ListItem::Measured { size, .. }) = cursor.item() { + let &Dimensions(Count(count), Height(top), _) = cursor.start(); + if count == ix { + let top = bounds.top() + top - scroll_top; + return Some(Bounds::from_corners( + point(bounds.left(), top), + point(bounds.right(), top + size.height), + )); + } + } + None + } + + /// Call this method when the user starts dragging the scrollbar. + /// + /// This will prevent the height reported to the scrollbar from changing during the drag + /// as items in the overdraw get measured, and help offset scroll position changes accordingly. + pub fn scrollbar_drag_started(&self) { + let mut state = self.0.borrow_mut(); + state.scrollbar_drag_start_height = Some(state.items.summary().height); + } + + /// Called when the user stops dragging the scrollbar. + /// + /// See `scrollbar_drag_started`. + pub fn scrollbar_drag_ended(&self) { + self.0.borrow_mut().scrollbar_drag_start_height.take(); + } + + /// Returns `true` if the scrollbar is currently being dragged. + /// + /// This is set between [`scrollbar_drag_started`](Self::scrollbar_drag_started) + /// and [`scrollbar_drag_ended`](Self::scrollbar_drag_ended) calls. Useful for + /// consumers that need to distinguish scrollbar drags from wheel/trackpad scrolls, + /// e.g. to suppress auto-scroll behavior during manual positioning. + pub fn is_scrollbar_dragging(&self) -> bool { + self.0.borrow().scrollbar_drag_start_height.is_some() + } + + /// Set the offset from the scrollbar + pub fn set_offset_from_scrollbar(&self, point: Point) { + self.0.borrow_mut().set_offset_from_scrollbar(point); + } + + /// Returns the maximum scroll offset according to the items we have measured. + /// This value remains constant while dragging to prevent the scrollbar from moving away unexpectedly. + pub fn max_offset_for_scrollbar(&self) -> Point { + let state = self.0.borrow(); + point(Pixels::ZERO, state.max_scroll_offset()) + } + + /// Returns the current scroll offset adjusted for the scrollbar. + /// + /// The returned offset has a negative `y` component representing + /// how far the content has scrolled. + pub fn scroll_px_offset_for_scrollbar(&self) -> Point { + let state = &self.0.borrow(); + + if state.logical_scroll_top.is_none() && state.alignment == ListAlignment::Bottom { + return Point::new(px(0.), -state.max_scroll_offset()); + } + + let logical_scroll_top = state.logical_scroll_top(); + + let mut cursor = state.items.cursor::(()); + let summary: ListItemSummary = + cursor.summary(&Count(logical_scroll_top.item_ix), Bias::Right); + let offset = summary.height + logical_scroll_top.offset_in_item; + + Point::new(px(0.), -offset) + } + + /// Return the bounds of the viewport in pixels. + pub fn viewport_bounds(&self) -> Bounds { + self.0.borrow().last_layout_bounds.unwrap_or_default() + } + + /// Returns whether the item is entirely above the viewport, or `None` if + /// the list has not measured enough layout to know. + /// + /// A zero-height viewport still yields a definitive answer: callers may + /// size sibling UI based on this query (potentially squeezing the list + /// itself to zero height), so returning `None` in that case would make + /// the answer oscillate from frame to frame. + pub fn item_is_above_viewport(&self, ix: usize) -> Option { + let viewport_bounds = self.0.borrow().last_layout_bounds?; + + let scroll_top = self.logical_scroll_top(); + if ix < scroll_top.item_ix { + // Rows before the logical scroll top have no item bounds, but + // their position relative to the viewport is known from scroll state. + return Some(true); + } + + let item_bounds = self.bounds_for_item(ix)?; + Some(item_bounds.bottom() <= viewport_bounds.top()) + } + + /// Returns whether the item is entirely below the viewport, or `None` if + /// the list has not measured enough layout to know. + /// + /// See [`Self::item_is_above_viewport`] for why a zero-height viewport + /// still yields a definitive answer. + pub fn item_is_below_viewport(&self, ix: usize) -> Option { + let viewport_bounds = self.0.borrow().last_layout_bounds?; + + let scroll_top = self.logical_scroll_top(); + if ix < scroll_top.item_ix { + // Rows before the logical scroll top have no item bounds, but + // their position relative to the viewport is known from scroll state. + return Some(false); + } + + let item_bounds = self.bounds_for_item(ix)?; + Some(item_bounds.top() >= viewport_bounds.bottom()) + } +} + +impl StateInner { + /// Re-anchor a pending scroll adjustment from a remeasure onto a newly set + /// scroll position, so it clamps to the remeasured item's new height on + /// the next layout instead of reverting the scroll. + fn rebase_pending_scroll(&mut self, scroll_top: ListOffset) { + let Some(pending) = self.pending_scroll.take() else { + return; + }; + if scroll_top.item_ix >= self.items.summary().count { + return; + } + + self.pending_scroll = match pending { + PendingScroll::Absolute { .. } => Some(PendingScroll::Absolute { + item_ix: scroll_top.item_ix, + offset: scroll_top.offset_in_item, + }), + PendingScroll::Proportional(_) => { + let mut cursor = self.items.cursor::(()); + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + cursor + .item() + .and_then(|item| item.size_hint()) + .filter(|size| size.height.0 > 0.0) + .map(|size| { + PendingScroll::Proportional(PendingScrollFraction { + item_ix: scroll_top.item_ix, + fraction: (scroll_top.offset_in_item.0 / size.height.0).clamp(0.0, 1.0), + }) + }) + } + }; + } + + fn max_scroll_offset(&self) -> Pixels { + let bounds = self.last_layout_bounds.unwrap_or_default(); + let height = self + .scrollbar_drag_start_height + .unwrap_or_else(|| self.items.summary().height); + (height - bounds.size.height).max(px(0.)) + } + + fn visible_range( + items: &SumTree, + height: Pixels, + scroll_top: &ListOffset, + ) -> Range { + let mut cursor = items.cursor::(()); + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + let start_y = cursor.start().height + scroll_top.offset_in_item; + cursor.seek_forward(&Height(start_y + height), Bias::Left); + scroll_top.item_ix..cursor.start().count + 1 + } + + fn scroll( + &mut self, + scroll_top: &ListOffset, + height: Pixels, + delta: Point, + current_view: EntityId, + window: &mut Window, + cx: &mut App, + ) { + // Drop scroll events after a reset, since we can't calculate + // the new logical scroll top without the item heights + if self.reset { + return; + } + + let padding = self.last_padding.unwrap_or_default(); + let scroll_max = + (self.items.summary().height + padding.top + padding.bottom - height).max(px(0.)); + let new_scroll_top = (self.scroll_top(scroll_top) - delta.y) + .max(px(0.)) + .min(scroll_max); + + if self.alignment == ListAlignment::Bottom && new_scroll_top == scroll_max { + self.pending_scroll = None; + self.logical_scroll_top = None; + } else { + let (start, ..) = + self.items + .find::((), &Height(new_scroll_top), Bias::Right); + let scroll_top = ListOffset { + item_ix: start.count, + offset_in_item: new_scroll_top - start.height, + }; + // The user's scroll supersedes the position stashed by a + // remeasure; re-anchor the pending adjustment so it doesn't revert + // this scroll on the next layout. + self.rebase_pending_scroll(scroll_top); + self.logical_scroll_top = Some(scroll_top); + } + + if delta.y > px(0.) { + self.follow_state.stop_following(); + } + + if let Some(handler) = self.scroll_handler.as_mut() { + let visible_range = Self::visible_range(&self.items, height, scroll_top); + handler( + &ListScrollEvent { + visible_range, + count: self.items.summary().count, + is_scrolled: self.logical_scroll_top.is_some(), + is_following_tail: matches!( + self.follow_state, + FollowState::Tail { is_following: true } + ), + }, + window, + cx, + ); + } + + cx.notify(current_view); + } + + fn logical_scroll_top(&self) -> ListOffset { + self.logical_scroll_top + .unwrap_or_else(|| match self.alignment { + ListAlignment::Top => ListOffset { + item_ix: 0, + offset_in_item: px(0.), + }, + ListAlignment::Bottom => ListOffset { + item_ix: self.items.summary().count, + offset_in_item: px(0.), + }, + }) + } + + fn scroll_top(&self, logical_scroll_top: &ListOffset) -> Pixels { + let (start, ..) = self.items.find::( + (), + &Count(logical_scroll_top.item_ix), + Bias::Right, + ); + start.height + logical_scroll_top.offset_in_item + } + + fn layout_all_items( + &mut self, + available_width: Pixels, + render_item: &mut RenderItemFn, + window: &mut Window, + cx: &mut App, + ) { + match &mut self.measuring_behavior { + ListMeasuringBehavior::Visible => { + return; + } + ListMeasuringBehavior::Measure(has_measured) => { + if *has_measured { + return; + } + *has_measured = true; + } + } + + let mut cursor = self.items.cursor::(()); + let available_item_space = size( + AvailableSpace::Definite(available_width), + AvailableSpace::MinContent, + ); + + let mut measured_items = Vec::default(); + + for (ix, item) in cursor.enumerate() { + let size = item.size().unwrap_or_else(|| { + let mut element = render_item(ix, window, cx); + element.layout_as_root(available_item_space, window, cx) + }); + + measured_items.push(ListItem::Measured { + size, + focus_handle: item.focus_handle(), + }); + } + + self.items = SumTree::from_iter(measured_items, ()); + } + + fn layout_items( + &mut self, + available_width: Option, + available_height: Pixels, + padding: &Edges, + render_item: &mut RenderItemFn, + window: &mut Window, + cx: &mut App, + ) -> LayoutItemsResponse { + let old_items = self.items.clone(); + let mut measured_items = VecDeque::new(); + let mut item_layouts = VecDeque::new(); + let mut rendered_height = padding.top; + let mut max_item_width = px(0.); + let mut scroll_top = self.logical_scroll_top(); + + if self.follow_state.is_following() { + scroll_top = ListOffset { + item_ix: self.items.summary().count, + offset_in_item: px(0.), + }; + self.logical_scroll_top = Some(scroll_top); + } + + let mut rendered_focused_item = false; + + let available_item_space = size( + available_width.map_or(AvailableSpace::MaxContent, |width| { + AvailableSpace::Definite(width) + }), + AvailableSpace::MinContent, + ); + + let mut cursor = old_items.cursor::(()); + + // Render items after the scroll top, including those in the trailing overdraw + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + for (ix, item) in cursor.by_ref().enumerate() { + let visible_height = rendered_height - scroll_top.offset_in_item; + if visible_height >= available_height + self.overdraw { + break; + } + + // Use the previously cached height and focus handle if available + let mut size = item.size(); + + // If we're within the visible area or the height wasn't cached, render and measure the item's element + if visible_height < available_height || size.is_none() { + let item_index = scroll_top.item_ix + ix; + let mut element = render_item(item_index, window, cx); + let element_size = element.layout_as_root(available_item_space, window, cx); + size = Some(element_size); + + // If there's a pending scroll adjustment for the scroll-top + // item, apply it. + if ix == 0 { + if let Some(pending_scroll) = self.pending_scroll.take() { + match pending_scroll { + PendingScroll::Absolute { item_ix, offset } + if item_ix == scroll_top.item_ix => + { + scroll_top.offset_in_item = offset.min(element_size.height); + self.logical_scroll_top = Some(scroll_top); + } + PendingScroll::Proportional(pending_scroll) + if pending_scroll.item_ix == scroll_top.item_ix => + { + // Ensuring proportional scroll position is + // maintained after re-measuring. + scroll_top.offset_in_item = + Pixels(pending_scroll.fraction * element_size.height.0); + self.logical_scroll_top = Some(scroll_top); + } + _ => {} + } + } + } + + if visible_height < available_height { + item_layouts.push_back(ItemLayout { + index: item_index, + element, + size: element_size, + }); + if item.contains_focused(window, cx) { + rendered_focused_item = true; + } + } + } + + let size = size.unwrap(); + rendered_height += size.height; + max_item_width = max_item_width.max(size.width); + measured_items.push_back(ListItem::Measured { + size, + focus_handle: item.focus_handle(), + }); + } + rendered_height += padding.bottom; + + // Prepare to start walking upward from the item at the scroll top. + cursor.seek(&Count(scroll_top.item_ix), Bias::Right); + + // If the rendered items do not fill the visible region, then adjust + // the scroll top upward. + if rendered_height - scroll_top.offset_in_item < available_height { + while rendered_height < available_height { + cursor.prev(); + if let Some(item) = cursor.item() { + let item_index = cursor.start().0; + let mut element = render_item(item_index, window, cx); + let element_size = element.layout_as_root(available_item_space, window, cx); + let focus_handle = item.focus_handle(); + rendered_height += element_size.height; + measured_items.push_front(ListItem::Measured { + size: element_size, + focus_handle, + }); + item_layouts.push_front(ItemLayout { + index: item_index, + element, + size: element_size, + }); + if item.contains_focused(window, cx) { + rendered_focused_item = true; + } + } else { + break; + } + } + + scroll_top = ListOffset { + item_ix: cursor.start().0, + offset_in_item: rendered_height - available_height, + }; + + match self.alignment { + ListAlignment::Top => { + scroll_top.offset_in_item = scroll_top.offset_in_item.max(px(0.)); + self.logical_scroll_top = Some(scroll_top); + } + ListAlignment::Bottom => { + scroll_top = ListOffset { + item_ix: cursor.start().0, + offset_in_item: rendered_height - available_height, + }; + self.logical_scroll_top = None; + } + }; + } + + // Measure items in the leading overdraw + let mut leading_overdraw = scroll_top.offset_in_item; + while leading_overdraw < self.overdraw { + cursor.prev(); + if let Some(item) = cursor.item() { + let size = if let ListItem::Measured { size, .. } = item { + *size + } else { + let mut element = render_item(cursor.start().0, window, cx); + element.layout_as_root(available_item_space, window, cx) + }; + + leading_overdraw += size.height; + measured_items.push_front(ListItem::Measured { + size, + focus_handle: item.focus_handle(), + }); + } else { + break; + } + } + + let measured_range = cursor.start().0..(cursor.start().0 + measured_items.len()); + let mut cursor = old_items.cursor::(()); + let mut new_items = cursor.slice(&Count(measured_range.start), Bias::Right); + new_items.extend(measured_items, ()); + cursor.seek(&Count(measured_range.end), Bias::Right); + new_items.append(cursor.suffix(), ()); + self.items = new_items; + + // If follow_tail mode is on but the user scrolled away + // (is_following is false), check whether the current scroll + // position has returned to the bottom. + if self.follow_state.has_stopped_following() { + let padding = self.last_padding.unwrap_or_default(); + let total_height = self.items.summary().height + padding.top + padding.bottom; + let scroll_offset = self.scroll_top(&scroll_top); + if scroll_offset + available_height >= total_height - px(1.0) { + self.follow_state.start_following(); + } + } + + // If none of the visible items are focused, check if an off-screen item is focused + // and include it to be rendered after the visible items so keyboard interaction continues + // to work for it. + if !rendered_focused_item { + let mut cursor = self + .items + .filter::<_, Count>((), |summary| summary.has_focus_handles); + cursor.next(); + while let Some(item) = cursor.item() { + if item.contains_focused(window, cx) { + let item_index = cursor.start().0; + let mut element = render_item(cursor.start().0, window, cx); + let size = element.layout_as_root(available_item_space, window, cx); + item_layouts.push_back(ItemLayout { + index: item_index, + element, + size, + }); + break; + } + cursor.next(); + } + } + + LayoutItemsResponse { + max_item_width, + scroll_top, + item_layouts, + } + } + + fn prepaint_items( + &mut self, + bounds: Bounds, + padding: Edges, + autoscroll: bool, + render_item: &mut RenderItemFn, + window: &mut Window, + cx: &mut App, + ) -> Result { + window.transact(|window| { + match self.measuring_behavior { + ListMeasuringBehavior::Measure(has_measured) if !has_measured => { + self.layout_all_items(bounds.size.width, render_item, window, cx); + } + _ => {} + } + + let mut layout_response = self.layout_items( + Some(bounds.size.width), + bounds.size.height, + &padding, + render_item, + window, + cx, + ); + + // Avoid honoring autoscroll requests from elements other than our children. + window.take_autoscroll(); + + // Only paint the visible items, if there is actually any space for them (taking padding into account) + if bounds.size.height > padding.top + padding.bottom { + let mut item_origin = bounds.origin + Point::new(px(0.), padding.top); + item_origin.y -= layout_response.scroll_top.offset_in_item; + for item in &mut layout_response.item_layouts { + window.with_content_mask(Some(ContentMask { bounds }), |window| { + item.element.prepaint_at(item_origin, window, cx); + }); + + if let Some(autoscroll_bounds) = window.take_autoscroll() + && autoscroll + { + if autoscroll_bounds.top() < bounds.top() { + let mut item_ix = item.index; + let mut offset_in_item = autoscroll_bounds.top() - item_origin.y; + + // The requested top can sit above this item's own + // top. Walk into earlier items so the offset stays + // non-negative and no blank space appears above the + // list. + if offset_in_item < Pixels::ZERO { + let mut cursor = self.items.cursor::(()); + cursor.seek(&Count(item_ix), Bias::Right); + while offset_in_item < Pixels::ZERO { + cursor.prev(); + let Some(prev_item) = cursor.item() else { + offset_in_item = Pixels::ZERO; + break; + }; + let size = prev_item.size().unwrap_or_else(|| { + let mut element = render_item(cursor.start().0, window, cx); + let item_available_size = size( + bounds.size.width.into(), + AvailableSpace::MinContent, + ); + element.layout_as_root(item_available_size, window, cx) + }); + item_ix = cursor.start().0; + offset_in_item += size.height; + } + } + + return Err(ListOffset { + item_ix, + offset_in_item, + }); + } else if autoscroll_bounds.bottom() > bounds.bottom() { + let mut cursor = self.items.cursor::(()); + cursor.seek(&Count(item.index), Bias::Right); + let mut height = bounds.size.height - padding.top - padding.bottom; + + // Account for the height of the element down until the autoscroll bottom. + height -= autoscroll_bounds.bottom() - item_origin.y; + + // Keep decreasing the scroll top until we fill all the available space. + while height > Pixels::ZERO { + cursor.prev(); + let Some(item) = cursor.item() else { break }; + + let size = item.size().unwrap_or_else(|| { + let mut item = render_item(cursor.start().0, window, cx); + let item_available_size = + size(bounds.size.width.into(), AvailableSpace::MinContent); + item.layout_as_root(item_available_size, window, cx) + }); + height -= size.height; + } + + return Err(ListOffset { + item_ix: cursor.start().0, + offset_in_item: if height < Pixels::ZERO { + -height + } else { + Pixels::ZERO + }, + }); + } + } + + item_origin.y += item.size.height; + } + } else { + layout_response.item_layouts.clear(); + } + + Ok(layout_response) + }) + } + + // Scrollbar support + + fn set_offset_from_scrollbar(&mut self, point: Point) { + let Some(bounds) = self.last_layout_bounds else { + return; + }; + let height = bounds.size.height; + + let padding = self.last_padding.unwrap_or_default(); + // Scrollbar drag positions are computed from the content height + // captured at drag start, so map them back using the same height. + let content_height = self + .scrollbar_drag_start_height + .unwrap_or_else(|| self.items.summary().height); + let scroll_max = (content_height + padding.top + padding.bottom - height).max(px(0.)); + let new_scroll_top = (-point.y).max(px(0.)).min(scroll_max); + + // If content grew during the drag, the frozen bottom is below the + // live bottom. Treat dragging to the frozen end as resuming tail follow. + let dragged_to_end = + scroll_max > px(0.) && new_scroll_top >= (scroll_max - px(1.0)).max(px(0.)); + if dragged_to_end && matches!(self.follow_state, FollowState::Tail { .. }) { + self.follow_state = FollowState::Tail { is_following: true }; + let item_count = self.items.summary().count; + self.pending_scroll = None; + self.logical_scroll_top = Some(ListOffset { + item_ix: item_count, + offset_in_item: px(0.), + }); + return; + } + + self.follow_state.stop_following(); + + if self.alignment == ListAlignment::Bottom && new_scroll_top == scroll_max { + self.pending_scroll = None; + self.logical_scroll_top = None; + } else { + let (start, _, _) = + self.items + .find::((), &Height(new_scroll_top), Bias::Right); + + let scroll_top = ListOffset { + item_ix: start.count, + offset_in_item: new_scroll_top - start.height, + }; + self.rebase_pending_scroll(scroll_top); + self.logical_scroll_top = Some(scroll_top); + } + } +} + +impl std::fmt::Debug for ListItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Unmeasured { .. } => write!(f, "Unrendered"), + Self::Measured { size, .. } => f.debug_struct("Rendered").field("size", size).finish(), + } + } +} + +/// An offset into the list's items, in terms of the item index and the number +/// of pixels off the top left of the item. +#[derive(Debug, Clone, Copy, Default)] +pub struct ListOffset { + /// The index of an item in the list + pub item_ix: usize, + /// The number of pixels to offset from the item index. + pub offset_in_item: Pixels, +} + +impl Element for List { + type RequestLayoutState = (); + type PrepaintState = ListPrepaintState; + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (crate::LayoutId, Self::RequestLayoutState) { + let layout_id = match self.sizing_behavior { + ListSizingBehavior::Infer => { + let mut style = Style::default(); + style.overflow.y = Overflow::Scroll; + style.refine(&self.style); + window.with_text_style(style.text_style().cloned(), |window| { + let state = &mut *self.state.0.borrow_mut(); + + let available_height = if let Some(last_bounds) = state.last_layout_bounds { + last_bounds.size.height + } else { + // If we don't have the last layout bounds (first render), + // we might just use the overdraw value as the available height to layout enough items. + state.overdraw + }; + let padding = style.padding.to_pixels( + state.last_layout_bounds.unwrap_or_default().size.into(), + window.rem_size(), + ); + + let layout_response = state.layout_items( + None, + available_height, + &padding, + &mut self.render_item, + window, + cx, + ); + let max_element_width = layout_response.max_item_width; + + let summary = state.items.summary(); + let total_height = summary.height; + + window.request_measured_layout( + style, + move |known_dimensions, available_space, _window, _cx| { + let width = + known_dimensions + .width + .unwrap_or(match available_space.width { + AvailableSpace::Definite(x) => x, + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + max_element_width + } + }); + let height = match available_space.height { + AvailableSpace::Definite(height) => total_height.min(height), + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + total_height + } + }; + size(width, height) + }, + ) + }) + } + ListSizingBehavior::Auto => { + let mut style = Style::default(); + style.refine(&self.style); + window.with_text_style(style.text_style().cloned(), |window| { + window.request_layout(style, None, cx) + }) + } + }; + (layout_id, ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> ListPrepaintState { + let state = &mut *self.state.0.borrow_mut(); + state.reset = false; + + let mut style = Style::default(); + style.refine(&self.style); + + let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal); + + // If the width of the list has changed, invalidate all cached item heights + if state + .last_layout_bounds + .is_none_or(|last_bounds| last_bounds.size.width != bounds.size.width) + { + let new_items = SumTree::from_iter( + state.items.iter().map(|item| ListItem::Unmeasured { + size_hint: None, + focus_handle: item.focus_handle(), + }), + (), + ); + + state.items = new_items; + state.measuring_behavior.reset(); + } + + let padding = style + .padding + .to_pixels(bounds.size.into(), window.rem_size()); + let layout = + match state.prepaint_items(bounds, padding, true, &mut self.render_item, window, cx) { + Ok(layout) => layout, + Err(autoscroll_request) => { + state.logical_scroll_top = Some(autoscroll_request); + state + .prepaint_items(bounds, padding, false, &mut self.render_item, window, cx) + .unwrap() + } + }; + + state.last_layout_bounds = Some(bounds); + state.last_padding = Some(padding); + ListPrepaintState { hitbox, layout } + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let current_view = window.current_view(); + + // Register the scroll listener before painting children so that, in + // the bubble phase (which runs in reverse registration order), + // children's scroll-wheel handlers run first and can stop propagation + // to prevent the list from scrolling. This matches the ordering of + // div-based scroll containers. + let list_state = self.state.clone(); + let height = bounds.size.height; + let scroll_top = prepaint.layout.scroll_top; + let hitbox_id = prepaint.hitbox.id; + let mut accumulated_scroll_delta = ScrollDelta::default(); + window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble && hitbox_id.should_handle_scroll(window) { + accumulated_scroll_delta = accumulated_scroll_delta.coalesce(event.delta); + let pixel_delta = accumulated_scroll_delta.pixel_delta(px(20.)); + list_state.0.borrow_mut().scroll( + &scroll_top, + height, + pixel_delta, + current_view, + window, + cx, + ) + } + }); + + window.with_content_mask(Some(ContentMask { bounds }), |window| { + for item in &mut prepaint.layout.item_layouts { + item.element.paint(window, cx); + } + }); + } +} + +impl IntoElement for List { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Styled for List { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} + +impl sum_tree::Item for ListItem { + type Summary = ListItemSummary; + + fn summary(&self, _: ()) -> Self::Summary { + match self { + ListItem::Unmeasured { + size_hint, + focus_handle, + } => ListItemSummary { + count: 1, + rendered_count: 0, + unrendered_count: 1, + height: if let Some(size) = size_hint { + size.height + } else { + px(0.) + }, + has_focus_handles: focus_handle.is_some(), + has_unknown_height: size_hint.is_none(), + }, + ListItem::Measured { + size, focus_handle, .. + } => ListItemSummary { + count: 1, + rendered_count: 1, + unrendered_count: 0, + height: size.height, + has_focus_handles: focus_handle.is_some(), + has_unknown_height: false, + }, + } + } +} + +impl sum_tree::ContextLessSummary for ListItemSummary { + fn zero() -> Self { + Default::default() + } + + fn add_summary(&mut self, summary: &Self) { + self.count += summary.count; + self.rendered_count += summary.rendered_count; + self.unrendered_count += summary.unrendered_count; + self.height += summary.height; + self.has_focus_handles |= summary.has_focus_handles; + self.has_unknown_height |= summary.has_unknown_height; + } +} + +impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Count { + fn zero(_cx: ()) -> Self { + Default::default() + } + + fn add_summary(&mut self, summary: &'a ListItemSummary, _: ()) { + self.0 += summary.count; + } +} + +impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Height { + fn zero(_cx: ()) -> Self { + Default::default() + } + + fn add_summary(&mut self, summary: &'a ListItemSummary, _: ()) { + self.0 += summary.height; + } +} + +impl sum_tree::SeekTarget<'_, ListItemSummary, ListItemSummary> for Count { + fn cmp(&self, other: &ListItemSummary, _: ()) -> std::cmp::Ordering { + self.0.partial_cmp(&other.count).unwrap() + } +} + +impl sum_tree::SeekTarget<'_, ListItemSummary, ListItemSummary> for Height { + fn cmp(&self, other: &ListItemSummary, _: ()) -> std::cmp::Ordering { + self.0.partial_cmp(&other.height).unwrap() + } +} + +#[cfg(test)] +mod test { + + use gpui::{ScrollDelta, ScrollWheelEvent}; + use std::cell::Cell; + use std::rc::Rc; + + use crate::{ + self as gpui, AppContext, Bounds, Context, Element, FollowMode, InteractiveElement, + IntoElement, ListState, Render, Styled, TestAppContext, Window, canvas, div, list, point, + px, size, + }; + + #[gpui::test] + fn test_autoscroll_above_item_top_renders_items_above(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)); + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(0.), + }); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |ix, _, _| { + if ix == 2 { + // Request an autoscroll whose top sits 30px above item 2's + // own top, mimicking a scroll-margin overshoot. + canvas( + |bounds, window, _| { + window.request_autoscroll(Bounds::from_corners( + point(bounds.left(), bounds.top() - px(30.)), + point(bounds.right(), bounds.top() + px(5.)), + )); + }, + |_, _, _, _| {}, + ) + .h(px(20.)) + .w_full() + .into_any() + } else { + div().h(px(20.)).w_full().into_any() + } + }) + .w_full() + .h_full() + } + } + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(60.)), |_, cx| { + cx.new(|_| TestView(state.clone())).into_any_element() + }); + + // 30px above item 2's top, with 20px items, lands 10px into item 0. + let scroll_top = state.logical_scroll_top(); + assert!( + scroll_top.offset_in_item >= px(0.), + "offset_in_item must never be negative (would leave blank space above), got {:?}", + scroll_top.offset_in_item, + ); + assert_eq!(scroll_top.item_ix, 0); + assert_eq!(scroll_top.offset_in_item, px(10.)); + } + + #[gpui::test] + fn test_reset_after_paint_before_scroll(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)); + + // Ensure that the list is scrolled to the top + state.scroll_to(gpui::ListOffset { + item_ix: 0, + offset_in_item: px(0.0), + }); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(10.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + // Paint + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestView(state.clone())).into_any_element() + }); + + // Reset + state.reset(5); + + // And then receive a scroll event _before_ the next paint + cx.simulate_event(ScrollWheelEvent { + position: point(px(1.), px(1.)), + delta: ScrollDelta::Pixels(point(px(0.), px(-500.))), + ..Default::default() + }); + + // Scroll position should stay at the top of the list + assert_eq!(state.logical_scroll_top().item_ix, 0); + assert_eq!(state.logical_scroll_top().offset_in_item, px(0.)); + } + + #[gpui::test] + fn test_scroll_by_positive_and_negative_distance(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(20.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + // Paint + cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, cx| { + cx.new(|_| TestView(state.clone())).into_any_element() + }); + + // Test positive distance: start at item 1, move down 30px + state.scroll_by(px(30.)); + + // Should move to item 2 + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 1); + assert_eq!(offset.offset_in_item, px(10.)); + + // Test negative distance: start at item 2, move up 30px + state.scroll_by(px(-30.)); + + // Should move back to item 1 + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 0); + assert_eq!(offset.offset_in_item, px(0.)); + + // Test zero distance + state.scroll_by(px(0.)); + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 0); + assert_eq!(offset.offset_in_item, px(0.)); + } + + #[gpui::test] + fn test_child_scroll_handler_can_stop_list_scroll(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)); + let child_saw_event = Rc::new(Cell::new(false)); + + struct TestView { + state: ListState, + child_saw_event: Rc>, + } + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let child_saw_event = self.child_saw_event.clone(); + list(self.state.clone(), move |_, _, _| { + let child_saw_event = child_saw_event.clone(); + div() + .h(px(20.)) + .w_full() + .on_scroll_wheel(move |_, _, cx| { + child_saw_event.set(true); + cx.stop_propagation(); + }) + .into_any() + }) + .w_full() + .h_full() + } + } + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, cx| { + cx.new(|_| TestView { + state: state.clone(), + child_saw_event: child_saw_event.clone(), + }) + .into_any_element() + }); + + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(10.)), + delta: ScrollDelta::Pixels(point(px(0.), px(-30.))), + ..Default::default() + }); + + assert!( + child_saw_event.get(), + "the child's scroll-wheel handler should run" + ); + // The child stopped propagation, so the list must not have scrolled. + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 0); + assert_eq!(offset.offset_in_item, px(0.)); + } + + struct TestListView(ListState); + impl Render for TestListView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(20.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + #[gpui::test] + fn test_item_viewport_queries_return_none_before_layout(_cx: &mut TestAppContext) { + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + assert_eq!(state.item_is_above_viewport(0), None); + assert_eq!(state.item_is_below_viewport(0), None); + } + + #[gpui::test] + fn test_item_viewport_queries_before_logical_scroll_top(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(0.), + }); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(1), Some(true)); + assert_eq!(state.item_is_below_viewport(1), Some(false)); + } + + #[gpui::test] + fn test_item_viewport_queries_measured_item_inside_viewport(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(0.), + }); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(2), Some(false)); + assert_eq!(state.item_is_below_viewport(2), Some(false)); + } + + #[gpui::test] + fn test_item_viewport_queries_measured_item_above_viewport(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(20.), + }); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(2), Some(true)); + assert_eq!(state.item_is_below_viewport(2), Some(false)); + } + + #[gpui::test] + fn test_item_viewport_queries_measured_item_below_viewport(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(0.), + }); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(3), Some(false)); + assert_eq!(state.item_is_below_viewport(3), Some(true)); + } + + #[gpui::test] + fn test_item_viewport_queries_remain_stable_with_zero_height_viewport(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(0.), + }); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(3), Some(false)); + assert_eq!(state.item_is_below_viewport(3), Some(true)); + + // Squeeze the list to zero height, e.g. because a sibling element + // (sized based on the queries above) consumed all the space. The + // answers must remain definitive rather than becoming `None`, + // otherwise the sibling's size can oscillate between frames. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(0.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + assert_eq!(state.item_is_above_viewport(1), Some(true)); + assert_eq!(state.item_is_below_viewport(1), Some(false)); + assert_eq!(state.item_is_above_viewport(3), Some(false)); + assert_eq!(state.item_is_below_viewport(3), Some(true)); + } + + #[gpui::test] + fn test_item_viewport_queries_after_scroll_to_end_before_layout(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(5, crate::ListAlignment::Top, px(10.)).measure_all(); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| { + cx.new(|_| TestListView(state.clone())).into_any_element() + }); + + state.scroll_to_end(); + + assert_eq!(state.logical_scroll_top().item_ix, state.item_count()); + assert_eq!(state.item_is_above_viewport(0), Some(true)); + assert_eq!(state.item_is_below_viewport(0), Some(false)); + } + + #[gpui::test] + fn test_measure_all_after_width_change(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all(); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + // First draw at width 100: all 10 items measured (total 500px). + // Viewport is 200px, so max scroll offset should be 300px. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert_eq!(state.max_offset_for_scrollbar().y, px(300.)); + + // Second draw at a different width: items get invalidated. + // Without the fix, max_offset would drop because unmeasured items + // contribute 0 height. + cx.draw(point(px(0.), px(0.)), size(px(200.), px(200.)), |_, _| { + view.into_any_element() + }); + assert_eq!(state.max_offset_for_scrollbar().y, px(300.)); + } + + #[gpui::test] + fn test_remeasure(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // Create a list with 10 items, each 100px tall. We'll keep a reference + // to the item height so we can later change the height and assert how + // `ListState` handles it. + let item_height = Rc::new(Cell::new(100usize)); + let state = ListState::new(10, crate::ListAlignment::Top, px(10.)); + + struct TestView { + state: ListState, + item_height: Rc>, + } + + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.item_height.get(); + list(self.state.clone(), move |_, _, _| { + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let state_clone = state.clone(); + let item_height_clone = item_height.clone(); + let view = cx.update(|_, cx| { + cx.new(|_| TestView { + state: state_clone, + item_height: item_height_clone, + }) + }); + + // Simulate scrolling 40px inside the element with index 2. Since the + // original item height is 100px, this equates to 40% inside the item. + state.scroll_to(gpui::ListOffset { + item_ix: 2, + offset_in_item: px(40.), + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 2); + assert_eq!(offset.offset_in_item, px(40.)); + + // Update the `item_height` to be 50px instead of 100px so we can assert + // that the scroll position is proportionally preserved, that is, + // instead of 40px from the top of item 2, it should be 20px, since the + // item's height has been halved. + item_height.set(50); + state.remeasure(); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 2); + assert_eq!(offset.offset_in_item, px(20.)); + } + + #[gpui::test] + fn test_remeasure_item_preserves_scroll_offset(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let item_height = Rc::new(Cell::new(100usize)); + let state = ListState::new(20, crate::ListAlignment::Top, px(10.)); + + struct TestView { + state: ListState, + item_height: Rc>, + } + + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.item_height.get(); + list(self.state.clone(), move |index, _, _| { + let height = if index == 5 { height } else { 100 }; + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let state_clone = state.clone(); + let item_height_clone = item_height.clone(); + let view = cx.update(|_, cx| { + cx.new(|_| TestView { + state: state_clone, + item_height: item_height_clone, + }) + }); + + state.scroll_to(gpui::ListOffset { + item_ix: 5, + offset_in_item: px(40.), + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + item_height.set(200); + state.remeasure_items(5..6); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 5); + assert_eq!(offset.offset_in_item, px(40.)); + } + + #[gpui::test] + fn test_remeasure_then_scroll_does_not_revert_scroll_position(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let state = ListState::new(20, crate::ListAlignment::Top, px(10.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(100.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = { + let state = state.clone(); + cx.update(|_, cx| cx.new(|_| TestView(state))) + }; + + state.scroll_to(gpui::ListOffset { + item_ix: 5, + offset_in_item: px(40.), + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + state.remeasure_items(5..6); + + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(-30.))), + ..Default::default() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 5); + assert_eq!(offset.offset_in_item, px(70.)); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 5); + assert_eq!( + offset.offset_in_item, + px(70.), + "scrolling after a remeasure should not be reverted by the stale pending scroll" + ); + } + + #[gpui::test] + fn test_scroll_after_remeasure_clamps_to_shrunk_item_height(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let item_height = Rc::new(Cell::new(100usize)); + let state = ListState::new(20, crate::ListAlignment::Top, px(10.)); + + struct TestView { + state: ListState, + item_height: Rc>, + } + + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.item_height.get(); + list(self.state.clone(), move |index, _, _| { + let height = if index == 5 { height } else { 100 }; + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = { + let state = state.clone(); + let item_height = item_height.clone(); + cx.update(|_, cx| cx.new(|_| TestView { state, item_height })) + }; + + state.scroll_to(gpui::ListOffset { + item_ix: 5, + offset_in_item: px(40.), + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + // Item 5 shrinks from 100px to 50px and is remeasured... + item_height.set(50); + state.remeasure_items(5..6); + + // ...and then the user scrolls down by 30px before the next frame, + // landing at offset 70. + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(-30.))), + ..Default::default() + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + // The rebased pending scroll clamps the user's offset to the item's + // new height instead of leaving it pointing past the end of the item. + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 5); + assert_eq!(offset.offset_in_item, px(50.)); + } + + #[gpui::test] + fn test_follow_tail_stays_at_bottom_as_items_grow(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items, each 50px tall → 500px total content, 200px viewport. + // With follow-tail on, the list should always show the bottom. + let item_height = Rc::new(Cell::new(50usize)); + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView { + state: ListState, + item_height: Rc>, + } + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.item_height.get(); + list(self.state.clone(), move |_, _, _| { + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let state_clone = state.clone(); + let item_height_clone = item_height.clone(); + let view = cx.update(|_, cx| { + cx.new(|_| TestView { + state: state_clone, + item_height: item_height_clone, + }) + }); + + state.set_follow_mode(FollowMode::Tail); + + // First paint — items are 50px, total 500px, viewport 200px. + // Follow-tail should anchor to the end. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + // The scroll should be at the bottom: the last visible items fill the + // 200px viewport from the end of 500px of content (offset 300px). + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 6); + assert_eq!(offset.offset_in_item, px(0.)); + assert!(state.is_following_tail()); + + // Simulate items growing (e.g. streaming content makes each item taller). + // 10 items × 80px = 800px total. + item_height.set(80); + state.remeasure(); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + // After growth, follow-tail should have re-anchored to the new end. + // 800px total − 200px viewport = 600px offset → item 7 at offset 40px, + // but follow-tail anchors to item_count (10), and layout walks back to + // fill 200px, landing at item 7 (7 × 80 = 560, 800 − 560 = 240 > 200, + // so item 8: 8 × 80 = 640, 800 − 640 = 160 < 200 → keeps walking → + // item 7: offset = 800 − 200 = 600, item_ix = 600/80 = 7, remainder 40). + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 7); + assert_eq!(offset.offset_in_item, px(40.)); + assert!(state.is_following_tail()); + } + + #[gpui::test] + fn test_pause_following_tail_reengages_when_still_at_bottom(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + state.set_follow_mode(FollowMode::Tail); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + // Pausing while the view is still at the bottom (e.g. a no-op zoom) + // must not strand follow-tail: the next layout has to re-engage so the + // invariant "at the bottom + new content => visible" is preserved. + state.pause_following_tail(); + assert!(!state.is_following_tail()); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + assert!( + state.is_following_tail(), + "pausing while at the bottom must re-engage follow-tail on the next layout" + ); + } + + #[gpui::test] + fn test_pause_following_tail_freezes_off_bottom(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items, 200px viewport. Item height is adjustable to simulate a + // diagram block growing/shrinking on zoom. + let item_height = Rc::new(Cell::new(50usize)); + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView { + state: ListState, + item_height: Rc>, + } + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.item_height.get(); + list(self.state.clone(), move |_, _, _| { + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| { + cx.new(|_| TestView { + state: state.clone(), + item_height: item_height.clone(), + }) + }); + state.set_follow_mode(FollowMode::Tail); + + // At the bottom: 500px content, 200px viewport → top at item 6. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert_eq!(state.logical_scroll_top().item_ix, 6); + assert!(state.is_following_tail()); + + // Pause, then grow items (a zoom-in that pushes content below the fold). + // The frozen top must stay put rather than snapping to the new end, and + // following stays paused since we're no longer at the bottom. + state.pause_following_tail(); + item_height.set(80); + state.remeasure(); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 6); + assert_eq!(offset.offset_in_item, px(0.)); + assert!( + !state.is_following_tail(), + "a paused list must not re-engage while the frozen top is off the bottom" + ); + + // Shrink back (zoom-out) so the frozen top once again reaches the + // bottom: follow-tail must re-engage on its own. + item_height.set(50); + state.remeasure(); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + assert!( + state.is_following_tail(), + "returning to the bottom must restore follow-tail" + ); + } + + #[gpui::test] + fn test_follow_tail_disengages_on_user_scroll(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + state.set_follow_mode(FollowMode::Tail); + + // Paint with follow-tail — scroll anchored to the bottom. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, cx| { + cx.new(|_| TestView(state.clone())).into_any_element() + }); + assert!(state.is_following_tail()); + + // Simulate the user scrolling up. + // This should disengage follow-tail. + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(100.))), + ..Default::default() + }); + + assert!( + !state.is_following_tail(), + "follow-tail should disengage when the user scrolls toward the start" + ); + } + + #[gpui::test] + fn test_follow_tail_disengages_on_scrollbar_reposition(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all(); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + state.set_follow_mode(FollowMode::Tail); + + // Paint with follow-tail — scroll anchored to the bottom. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + // Simulate the scrollbar moving the viewport to the middle. + state.set_offset_from_scrollbar(point(px(0.), px(-150.))); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 3); + assert_eq!(offset.offset_in_item, px(0.)); + assert!( + !state.is_following_tail(), + "follow-tail should disengage when the scrollbar manually repositions the list" + ); + + // A subsequent draw should preserve the user's manual position instead + // of snapping back to the end. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 3); + assert_eq!(offset.offset_in_item, px(0.)); + } + + #[gpui::test] + fn test_scrollbar_drag_with_growing_content(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + let last_item_height = Rc::new(Cell::new(50usize)); + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all(); + + struct TestView { + state: ListState, + last_item_height: Rc>, + } + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let last_item_height = self.last_item_height.clone(); + list(self.state.clone(), move |index, _, _| { + let height = if index == 9 { + last_item_height.get() + } else { + 50 + }; + div().h(px(height as f32)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| { + cx.new(|_| TestView { + state: state.clone(), + last_item_height: last_item_height.clone(), + }) + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + state.scrollbar_drag_started(); + + state.set_offset_from_scrollbar(point(px(0.), px(-150.))); + let scrollbar_offset_before_growth = state.scroll_px_offset_for_scrollbar(); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 3); + assert_eq!(offset.offset_in_item, px(0.)); + + last_item_height.set(550); + state.remeasure_items(9..10); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + assert_eq!(state.max_offset_for_scrollbar().y, px(300.)); + assert_eq!( + state.scroll_px_offset_for_scrollbar(), + scrollbar_offset_before_growth + ); + + state.set_offset_from_scrollbar(point(px(0.), px(-150.))); + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 3); + assert_eq!(offset.offset_in_item, px(0.)); + } + + #[gpui::test] + fn test_set_follow_tail_snaps_to_bottom(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + // Scroll to the middle of the list (item 3). + state.scroll_to(gpui::ListOffset { + item_ix: 3, + offset_in_item: px(0.), + }); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 3); + assert_eq!(offset.offset_in_item, px(0.)); + assert!(!state.is_following_tail()); + + // Enable follow-tail — this should immediately snap the scroll anchor + // to the end, like the user just sent a prompt. + state.set_follow_mode(FollowMode::Tail); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + // After paint, scroll should be at the bottom. + // 500px total − 200px viewport = 300px offset → item 6, offset 0. + let offset = state.logical_scroll_top(); + assert_eq!(offset.item_ix, 6); + assert_eq!(offset.offset_in_item, px(0.)); + assert!(state.is_following_tail()); + } + + #[gpui::test] + fn test_bottom_aligned_scrollbar_offset_at_end(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + const ITEMS: usize = 10; + const ITEM_SIZE: f32 = 50.0; + + let state = ListState::new( + ITEMS, + crate::ListAlignment::Bottom, + px(ITEMS as f32 * ITEM_SIZE), + ); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(ITEM_SIZE)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, cx| { + cx.new(|_| TestView(state.clone())).into_any_element() + }); + + // Bottom-aligned lists start pinned to the end: logical_scroll_top returns + // item_ix == item_count, meaning no explicit scroll position has been set. + assert_eq!(state.logical_scroll_top().item_ix, ITEMS); + + let max_offset = state.max_offset_for_scrollbar(); + let scroll_offset = state.scroll_px_offset_for_scrollbar(); + + assert_eq!( + -scroll_offset.y, max_offset.y, + "scrollbar offset ({}) should equal max offset ({}) when list is pinned to bottom", + -scroll_offset.y, max_offset.y, + ); + } + + /// When the user scrolls away from the bottom during follow_tail, + /// follow_tail suspends. If they scroll back to the bottom, the + /// next paint should re-engage follow_tail using fresh measurements. + #[gpui::test] + fn test_follow_tail_reengages_when_scrolled_back_to_bottom(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + state.set_follow_mode(FollowMode::Tail); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + // Scroll up — follow_tail should suspend (not fully disengage). + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(50.))), + ..Default::default() + }); + assert!(!state.is_following_tail()); + + // Scroll back down to the bottom. + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(-10000.))), + ..Default::default() + }); + + // After a paint, follow_tail should re-engage because the + // layout confirmed we're at the true bottom. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!( + state.is_following_tail(), + "follow_tail should re-engage after scrolling back to the bottom" + ); + } + + /// When an item is spliced to unmeasured (0px) while follow_tail + /// is suspended, the re-engagement check should still work correctly + #[gpui::test] + fn test_follow_tail_reengagement_not_fooled_by_unmeasured_items(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 20 items × 50px = 1000px total, 200px viewport, 1000px + // overdraw so all items get measured during the follow_tail + // paint (matching realistic production settings). + let state = ListState::new(20, crate::ListAlignment::Top, px(1000.)); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + state.set_follow_mode(FollowMode::Tail); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + // Scroll up a meaningful amount — suspends follow_tail. + // 20 items × 50px = 1000px. viewport 200px. scroll_max = 800px. + // Scrolling up 200px puts us at 600px, clearly not at bottom. + cx.simulate_event(ScrollWheelEvent { + position: point(px(50.), px(100.)), + delta: ScrollDelta::Pixels(point(px(0.), px(200.))), + ..Default::default() + }); + assert!(!state.is_following_tail()); + + // Invalidate the last item (simulates EntryUpdated calling + // remeasure_items). This makes items.summary().height + // temporarily wrong (0px for the invalidated item). + state.remeasure_items(19..20); + + // Paint — layout re-measures the invalidated item with its true + // height. The re-engagement check uses these fresh measurements. + // Since we scrolled 200px up from the 800px max, we're at + // ~600px — NOT at the bottom, so follow_tail should NOT + // re-engage. + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!( + !state.is_following_tail(), + "follow_tail should not falsely re-engage due to an unmeasured item \ + reducing items.summary().height" + ); + } + + #[gpui::test] + fn test_follow_tail_reengages_after_scrollbar_disengagement(cx: &mut TestAppContext) { + let cx = cx.add_empty_window(); + + // 10 items × 50px = 500px total, 200px viewport, scroll_max = 300px. + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all(); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + state.set_follow_mode(FollowMode::Tail); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + // Drag the scrollbar up to the middle — follow_tail should suspend. + state.set_offset_from_scrollbar(point(px(0.), px(-150.))); + assert!(!state.is_following_tail()); + + // Drag the scrollbar back to the bottom — follow_tail should re-engage + // on the next paint. + state.set_offset_from_scrollbar(point(px(0.), px(-300.))); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + assert!( + state.is_following_tail(), + "follow_tail should re-engage after scrolling back to the bottom via the scrollbar" + ); + } + + #[gpui::test] + fn test_follow_tail_reengages_after_scrollbar_drag_to_bottom_while_growing( + cx: &mut TestAppContext, + ) { + let cx = cx.add_empty_window(); + + let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all(); + + struct TestView(ListState); + impl Render for TestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + list(self.0.clone(), |_, _, _| { + div().h(px(50.)).w_full().into_any() + }) + .w_full() + .h_full() + } + } + + let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone()))); + + state.set_follow_mode(FollowMode::Tail); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + assert!(state.is_following_tail()); + + state.scrollbar_drag_started(); + + state.splice(10..10, 10); + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.clone().into_any_element() + }); + + state.set_offset_from_scrollbar(point(px(0.), px(-300.))); + state.scrollbar_drag_ended(); + + cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| { + view.into_any_element() + }); + + assert!( + state.is_following_tail(), + "follow_tail should re-engage when the user drags the scrollbar to \ + the bottom of its track, even when content has grown during the drag \ + (so frozen_bottom < live_bottom)" + ); + } +} diff --git a/vendor/gpui-pre/src/elements/mod.rs b/vendor/gpui-pre/src/elements/mod.rs new file mode 100644 index 00000000..8a2a1b70 --- /dev/null +++ b/vendor/gpui-pre/src/elements/mod.rs @@ -0,0 +1,27 @@ +mod anchored; +mod animation; +mod canvas; +mod container_query; +mod deferred; +mod div; +mod image_cache; +mod img; +mod list; +mod surface; +mod svg; +mod text; +mod uniform_list; + +pub use anchored::*; +pub use animation::*; +pub use canvas::*; +pub use container_query::*; +pub use deferred::*; +pub use div::*; +pub use image_cache::*; +pub use img::*; +pub use list::*; +pub use surface::*; +pub use svg::*; +pub use text::*; +pub use uniform_list::*; diff --git a/vendor/gpui-pre/src/elements/surface.rs b/vendor/gpui-pre/src/elements/surface.rs new file mode 100644 index 00000000..fb072809 --- /dev/null +++ b/vendor/gpui-pre/src/elements/surface.rs @@ -0,0 +1,129 @@ +use crate::{ + App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement, LayoutId, + ObjectFit, Pixels, Style, StyleRefinement, Styled, Window, +}; +#[cfg(any(target_os = "macos", target_os = "ios"))] +use core_video::pixel_buffer::CVPixelBuffer; +use refineable::Refineable; + +/// A source of a surface's content. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SurfaceSource { + /// A CoreVideo image buffer + #[cfg(any(target_os = "macos", target_os = "ios"))] + Surface(CVPixelBuffer), +} + +#[cfg(any(target_os = "macos", target_os = "ios"))] +impl From for SurfaceSource { + fn from(value: CVPixelBuffer) -> Self { + SurfaceSource::Surface(value) + } +} + +/// A surface element. +pub struct Surface { + source: SurfaceSource, + object_fit: ObjectFit, + style: StyleRefinement, +} + +/// Create a new surface element. +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub fn surface(source: impl Into) -> Surface { + Surface { + source: source.into(), + object_fit: ObjectFit::Contain, + style: Default::default(), + } +} + +impl Surface { + /// Set the object fit for the image. + pub fn object_fit(mut self, object_fit: ObjectFit) -> Self { + self.object_fit = object_fit; + self + } +} + +impl Element for Surface { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut style = Style::default(); + style.refine(&self.style); + let layout_id = window.request_layout(style, [], cx); + (layout_id, ()) + } + + fn prepaint( + &mut self, + _global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) -> Self::PrepaintState { + } + + fn paint( + &mut self, + _global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + #[cfg_attr( + not(any(target_os = "macos", target_os = "ios")), + allow(unused_variables) + )] + bounds: Bounds, + _: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + #[cfg_attr( + not(any(target_os = "macos", target_os = "ios")), + allow(unused_variables) + )] + window: &mut Window, + _: &mut App, + ) { + match &self.source { + #[cfg(any(target_os = "macos", target_os = "ios"))] + SurfaceSource::Surface(surface) => { + let size = crate::size(surface.get_width().into(), surface.get_height().into()); + let new_bounds = self.object_fit.get_bounds(bounds, size); + // TODO: Add support for corner_radii + window.paint_surface(new_bounds, surface.clone()); + } + #[allow(unreachable_patterns)] + _ => {} + } + } +} + +impl IntoElement for Surface { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Styled for Surface { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} diff --git a/vendor/gpui-pre/src/elements/svg.rs b/vendor/gpui-pre/src/elements/svg.rs new file mode 100644 index 00000000..176072f1 --- /dev/null +++ b/vendor/gpui-pre/src/elements/svg.rs @@ -0,0 +1,303 @@ +use std::{ + fs, + hash::{Hash, Hasher}, + path::Path, + sync::Arc, +}; + +use crate::{ + App, Asset, Bounds, Element, GlobalElementId, Hitbox, InspectorElementId, InteractiveElement, + Interactivity, IntoElement, LayoutId, Pixels, Point, Radians, SharedString, Size, + StyleRefinement, Styled, TransformationMatrix, Window, point, px, radians, size, +}; +use gpui_util::ResultExt; + +/// An SVG element. +pub struct Svg { + interactivity: Interactivity, + transformation: Option, + path: Option, + external_path: Option, + data: Option>, + data_path: Option, +} + +/// Create a new SVG element. +#[track_caller] +pub fn svg() -> Svg { + Svg { + interactivity: Interactivity::new(), + transformation: None, + path: None, + external_path: None, + data: None, + data_path: None, + } +} + +impl Svg { + /// Set the path to the SVG file for this element. + pub fn path(mut self, path: impl Into) -> Self { + self.path = Some(path.into()); + self + } + + /// Set the path to the SVG file for this element. + pub fn external_path(mut self, path: impl Into) -> Self { + self.external_path = Some(path.into()); + self + } + + /// Set the raw SVG data for this element. + /// The SVG will be rendered directly from the provided bytes. + pub fn data(mut self, data: &[u8]) -> Self { + // Generate a unique deterministic path based on the data hash for caching + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + data.hash(&mut hasher); + let hash = hasher.finish(); + let path = SharedString::from(format!("__binary_svg__{}", hash)); + self.data = Some(Arc::from(data)); + self.data_path = Some(path); + self + } + + /// Transform the SVG element with the given transformation. + /// Note that this won't effect the hitbox or layout of the element, only the rendering. + pub fn with_transformation(mut self, transformation: Transformation) -> Self { + self.transformation = Some(transformation); + self + } +} + +impl Element for Svg { + type RequestLayoutState = (); + type PrepaintState = Option; + + fn id(&self) -> Option { + self.interactivity.element_id.clone() + } + + fn source_location(&self) -> Option<&'static std::panic::Location<'static>> { + self.interactivity.source_location() + } + + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let layout_id = self.interactivity.request_layout( + global_id, + inspector_id, + window, + cx, + |style, window, cx| window.request_layout(style, None, cx), + ); + (layout_id, ()) + } + + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Option { + self.interactivity.prepaint( + global_id, + inspector_id, + bounds, + bounds.size, + window, + cx, + |_, _, hitbox, _, _| hitbox, + ) + } + + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + hitbox: &mut Option, + window: &mut Window, + cx: &mut App, + ) where + Self: Sized, + { + self.interactivity.paint( + global_id, + inspector_id, + bounds, + hitbox.as_ref(), + window, + cx, + |style, window, cx| { + let transformation = self + .transformation + .as_ref() + .map(|transformation| { + transformation.into_matrix(bounds.center(), window.scale_factor()) + }) + .unwrap_or_default(); + + if let Some((data, path)) = self.data.as_ref().zip(self.data_path.as_ref()) { + if let Some(color) = style.text.color { + window + .paint_svg( + bounds, + path.clone(), + Some(&**data), + transformation, + color, + cx, + ) + .log_err(); + } + } else if let Some((path, color)) = + self.external_path.as_ref().zip(style.text.color) + { + let Some(bytes) = window + .use_asset::(path, cx) + .and_then(|asset| asset.log_err()) + else { + return; + }; + + window + .paint_svg( + bounds, + path.clone(), + Some(&bytes), + transformation, + color, + cx, + ) + .log_err(); + } else if let Some((path, color)) = self.path.as_ref().zip(style.text.color) { + window + .paint_svg(bounds, path.clone(), None, transformation, color, cx) + .log_err(); + } + }, + ) + } +} + +impl IntoElement for Svg { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Styled for Svg { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.interactivity.base_style + } +} + +impl InteractiveElement for Svg { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity + } +} + +/// A transformation to apply to an SVG element. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Transformation { + scale: Size, + translate: Point, + rotate: Radians, +} + +impl Default for Transformation { + fn default() -> Self { + Self { + scale: size(1.0, 1.0), + translate: point(px(0.0), px(0.0)), + rotate: radians(0.0), + } + } +} + +impl Transformation { + /// Create a new Transformation with the specified scale along each axis. + pub fn scale(scale: Size) -> Self { + Self { + scale, + translate: point(px(0.0), px(0.0)), + rotate: radians(0.0), + } + } + + /// Create a new Transformation with the specified translation. + pub fn translate(translate: Point) -> Self { + Self { + scale: size(1.0, 1.0), + translate, + rotate: radians(0.0), + } + } + + /// Create a new Transformation with the specified rotation in radians. + pub fn rotate(rotate: impl Into) -> Self { + let rotate = rotate.into(); + Self { + scale: size(1.0, 1.0), + translate: point(px(0.0), px(0.0)), + rotate, + } + } + + /// Update the scaling factor of this transformation. + pub fn with_scaling(mut self, scale: Size) -> Self { + self.scale = scale; + self + } + + /// Update the translation value of this transformation. + pub fn with_translation(mut self, translate: Point) -> Self { + self.translate = translate; + self + } + + /// Update the rotation angle of this transformation. + pub fn with_rotation(mut self, rotate: impl Into) -> Self { + self.rotate = rotate.into(); + self + } + + fn into_matrix(self, center: Point, scale_factor: f32) -> TransformationMatrix { + //Note: if you read this as a sequence of matrix multiplications, start from the bottom + TransformationMatrix::unit() + .translate(center.scale(scale_factor) + self.translate.scale(scale_factor)) + .rotate(self.rotate) + .scale(self.scale) + .translate(center.scale(-scale_factor)) + } +} + +enum SvgAsset {} + +impl Asset for SvgAsset { + type Source = SharedString; + type Output = Result, Arc>; + + fn load( + source: Self::Source, + _cx: &mut App, + ) -> impl Future + Send + 'static { + async move { + let bytes = fs::read(Path::new(source.as_ref())).map_err(|e| Arc::new(e))?; + let bytes = Arc::from(bytes); + Ok(bytes) + } + } +} diff --git a/vendor/gpui-pre/src/elements/text.rs b/vendor/gpui-pre/src/elements/text.rs new file mode 100644 index 00000000..d1896ad0 --- /dev/null +++ b/vendor/gpui-pre/src/elements/text.rs @@ -0,0 +1,1349 @@ +use crate::{ + ActiveTooltip, AnyView, App, Bounds, DispatchPhase, Element, ElementId, GlobalElementId, + HighlightStyle, Hitbox, HitboxBehavior, InspectorElementId, IntoElement, LayoutId, + MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, SharedString, Size, TextOverflow, + TextRun, TextStyle, TooltipId, TruncateFrom, WhiteSpace, Window, WrappedLine, + WrappedLineLayout, register_tooltip_mouse_handlers, set_tooltip_on_window, +}; +use anyhow::Context as _; +use gpui_util::ResultExt; +use itertools::Itertools; +use smallvec::SmallVec; +use std::{ + borrow::Cow, + cell::{Cell, RefCell}, + mem, + ops::{Deref, DerefMut, Range}, + rc::Rc, + sync::Arc, +}; + +/// An [`Element`] that renders text. +/// +/// In general, [`Text`] objects should be created via the [`text`] macro: +/// ```rust +/// # use gpui::*; +/// # fn render() -> impl IntoElement { +/// div().child(text!("hello")) +/// # } +/// ``` +/// ## IDs and Accessibility +/// +/// [`Text`] elements have an ID. This ID is primarily used to produce nodes in +/// the accessibility tree, which allows the text to be visible to screen +/// readers and other assistive technologies. +/// +/// This ID is stable across frames. If the same text, with the same ID, is +/// present in two consecutive frames, no updates are reported to the screen +/// reader. If the text changes, but the ID stays the same, then the screen +/// reader will be notified that a text node's content has changed. **However**, +/// if the ID changes, then the screen reader will be notified that a node has +/// been removed, and a new node has been added. +/// +/// When using the [`text`] macro, each invocation of the macro will get a +/// unique ID, derived from its position in the source code (filename, line, and +/// column). For example: +/// ```rust +/// # use gpui::*; +/// let x = text!("hello"); +/// let y = text!("hello"); +/// // not equal, because different `text!` invocations produced them +/// assert_ne!(x.id(), y.id()); +/// +/// fn make_text(s: &str) -> Text { text!(s) } +/// let x = make_text("hello"); +/// let y = make_text("hello"); +/// // equal, because the same `text!` invocation produced them +/// assert_eq!(x.id(), y.id()); +/// ``` +/// When the contents of an invocation of [`text`] do not change, this +/// distinction is less relevant (with the caveat that you still need to take +/// care to ensure that duplicate IDs do not appear). +/// +/// However, when a [`text`] invocation's argument *does* change, you should +/// consider whether this change should be reported as a node "updating its +/// contents", or an old node being destroyed and a new node being created. +#[derive(Debug, Clone)] +pub struct Text { + id: Option, + text: SharedString, +} + +impl Text { + /// Create a new [`Text`] element with a specific ID. + /// + /// If you want a unique ID to be assigned automatically, use the [`text`] + /// macro. The docs for [`Text`] have more detail about choosing IDs. + #[inline] + pub const fn new(id: ElementId, text: SharedString) -> Self { + Self { id: Some(id), text } + } + + /// Create a new [`Text`] element that is inaccessible to screen readers. + /// + /// In order for text to be accessible to screen readers, it must have an ID + /// provided. If you want text to be accessible, either use [`text`] to have + /// an ID automatically assigned, or use [`Text::new`] to manually assign an + /// ID. + /// + /// This function is intended for use inside custom UI components, where + /// accessible properties may be set on parent containers. + #[inline] + pub const fn new_inaccessible(text: SharedString) -> Self { + Self { id: None, text } + } + + /// The ID of this [`Text`] element. + #[inline] + pub const fn id(&self) -> Option<&ElementId> { + self.id.as_ref() + } + + /// Produce a new [`Text`] with the given `id`. + pub fn with_id(mut self, id: impl Into) -> Self { + self.id = Some(id.into()); + self + } + + /// The text that this [`Text`] element will display. + #[inline] + pub const fn text(&self) -> &SharedString { + &self.text + } +} + +impl Deref for Text { + type Target = SharedString; + fn deref(&self) -> &Self::Target { + &self.text + } +} + +impl DerefMut for Text { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.text + } +} + +/// Trivial hash function for the location information produced by the [`text`] +/// macro. Not covered by semver guarantees. Performance is not particularly +/// significant because it's only used on small strings in const contexts. +#[doc(hidden)] +pub const fn __hash_text_macro_location_unstable_do_not_use(s: &'static str) -> u64 { + const BASIS: u64 = 0xcbf29ce484222325; + const PRIME: u64 = 0x100000001b3; + + let bytes = s.as_bytes(); + let mut hash = BASIS; + let mut i = 0; + while i < bytes.len() { + hash ^= bytes[i] as u64; + hash = hash.wrapping_mul(PRIME); + i += 1; + } + hash +} + +/// Create a new [`Text`] element. +/// +/// ```rust +/// # use gpui::*; +/// let a = text!("hello"); +/// let b = text!(id = "farewell-message", "hello"); +/// +/// ``` +/// +/// Text created with this macro is *accessible*. The macro generates an ID +/// based on the source location. See the docs for [`Text`] for a more in-depth +/// explanation of the significance of the ID of a [`Text`] element. +#[macro_export] +macro_rules! text { + (id = $id:expr, $text:expr) => {{ $crate::Text::new($id.into(), $text.into()) }}; + ($text:expr) => {{ + const ID: &'static str = concat!(file!(), "/", line!(), ":", column!()); + const HASH: u64 = $crate::__hash_text_macro_location_unstable_do_not_use(ID); + $crate::Text::new($crate::ElementId::Integer(HASH), $text.into()) + }}; +} + +impl IntoElement for Text { + type Element = Self; + #[inline] + fn into_element(self) -> Self::Element { + self + } +} + +impl Element for Text { + type RequestLayoutState = TextLayout; + type PrepaintState = (); + + fn id(&self) -> Option { + self.id.clone() + } + + fn source_location(&self) -> Option<&'static std::panic::Location<'static>> { + None + } + + fn a11y_role(&self) -> Option { + if self.id.is_some() { + Some(accesskit::Role::Label) + } else { + None + } + } + + fn write_a11y_info(&self, node: &mut accesskit::Node) { + node.set_value(self.text.to_string()); + } + + fn request_layout( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + ::request_layout(&mut self.text, id, inspector_id, window, cx) + } + + fn prepaint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + ::prepaint( + &mut self.text, + id, + inspector_id, + bounds, + request_layout, + window, + cx, + ) + } + + fn paint( + &mut self, + id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + ::paint( + &mut self.text, + id, + inspector_id, + bounds, + request_layout, + prepaint, + window, + cx, + ); + } +} + +impl Element for &'static str { + type RequestLayoutState = TextLayout; + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut state = TextLayout::default(); + let layout_id = state.layout(SharedString::from(*self), None, window, cx); + (layout_id, state) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + text_layout: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) { + text_layout.prepaint(bounds, self) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + text_layout: &mut TextLayout, + _: &mut (), + window: &mut Window, + cx: &mut App, + ) { + text_layout.paint(self, window, cx) + } +} + +impl IntoElement for &'static str { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl IntoElement for String { + type Element = SharedString; + + fn into_element(self) -> Self::Element { + self.into() + } +} + +impl IntoElement for Cow<'static, str> { + type Element = SharedString; + + fn into_element(self) -> Self::Element { + self.into() + } +} + +impl Element for SharedString { + type RequestLayoutState = TextLayout; + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut state = TextLayout::default(); + let layout_id = state.layout(self.clone(), None, window, cx); + (layout_id, state) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + text_layout: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) { + text_layout.prepaint(bounds, self.as_ref()) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + text_layout: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + text_layout.paint(self.as_ref(), window, cx) + } +} + +impl IntoElement for SharedString { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +/// Renders text with runs of different styles. +/// +/// Callers are responsible for setting the correct style for each run. +/// For text with a uniform style, you can usually avoid calling this constructor +/// and just pass text directly. +pub struct StyledText { + text: SharedString, + runs: Option>, + delayed_highlights: Option, HighlightStyle)>>, + delayed_font_family_overrides: Option, SharedString)>>, + layout: TextLayout, +} + +impl StyledText { + /// Construct a new styled text element from the given string. + pub fn new(text: impl Into) -> Self { + StyledText { + text: text.into(), + runs: None, + delayed_highlights: None, + delayed_font_family_overrides: None, + layout: TextLayout::default(), + } + } + + /// Get the layout for this element. This can be used to map indices to pixels and vice versa. + pub fn layout(&self) -> &TextLayout { + &self.layout + } + + /// Set the styling attributes for the given text, as well as + /// as any ranges of text that have had their style customized. + pub fn with_default_highlights( + mut self, + default_style: &TextStyle, + highlights: impl IntoIterator, HighlightStyle)>, + ) -> Self { + debug_assert!( + self.delayed_highlights.is_none(), + "Can't use `with_default_highlights` and `with_highlights`" + ); + let runs = Self::compute_runs(&self.text, default_style, highlights); + self.with_runs(runs) + } + + /// Set the styling attributes for the given text, as well as + /// as any ranges of text that have had their style customized. + pub fn with_highlights( + mut self, + highlights: impl IntoIterator, HighlightStyle)>, + ) -> Self { + debug_assert!( + self.runs.is_none(), + "Can't use `with_highlights` and `with_default_highlights`" + ); + self.delayed_highlights = Some( + highlights + .into_iter() + .inspect(|(run, _)| { + debug_assert!(self.text.is_char_boundary(run.start)); + debug_assert!(self.text.is_char_boundary(run.end)); + }) + .collect::>(), + ); + self + } + + fn compute_runs( + text: &str, + default_style: &TextStyle, + highlights: impl IntoIterator, HighlightStyle)>, + ) -> Vec { + let mut runs = Vec::new(); + let mut ix = 0; + for (range, highlight) in highlights { + if ix < range.start { + debug_assert!(text.is_char_boundary(range.start)); + runs.push(default_style.clone().to_run(range.start - ix)); + } + debug_assert!(text.is_char_boundary(range.end)); + runs.push( + default_style + .clone() + .highlight(highlight) + .to_run(range.len()), + ); + ix = range.end; + } + if ix < text.len() { + runs.push(default_style.to_run(text.len() - ix)); + } + runs + } + + /// Override the font family for specific byte ranges of the text. + /// + /// This is resolved lazily at layout time, so the overrides are applied + /// on top of the inherited text style from the parent element. + /// Can be combined with [`with_highlights`](Self::with_highlights). + /// + /// The overrides must be sorted by range start and non-overlapping. + /// Each override range must fall on character boundaries. + pub fn with_font_family_overrides( + mut self, + overrides: impl IntoIterator, SharedString)>, + ) -> Self { + self.delayed_font_family_overrides = Some( + overrides + .into_iter() + .inspect(|(range, _)| { + debug_assert!(self.text.is_char_boundary(range.start)); + debug_assert!(self.text.is_char_boundary(range.end)); + }) + .collect(), + ); + self + } + + fn apply_font_family_overrides( + runs: &mut [TextRun], + overrides: &[(Range, SharedString)], + ) { + let mut byte_offset = 0; + let mut override_idx = 0; + for run in runs.iter_mut() { + let run_end = byte_offset + run.len; + while override_idx < overrides.len() && overrides[override_idx].0.end <= byte_offset { + override_idx += 1; + } + if override_idx < overrides.len() { + let (ref range, ref family) = overrides[override_idx]; + if byte_offset >= range.start && run_end <= range.end { + run.font.family = family.clone(); + } + } + byte_offset = run_end; + } + } + + /// Set the text runs for this piece of text. + pub fn with_runs(mut self, runs: Vec) -> Self { + let mut text = &*self.text; + for run in &runs { + text = text.get(run.len..).unwrap_or_else(|| { + #[cfg(debug_assertions)] + panic!("invalid text run. Text: '{text}', run: {run:?}"); + #[cfg(not(debug_assertions))] + panic!("invalid text run"); + }); + } + assert!(text.is_empty(), "invalid text run"); + self.runs = Some(runs); + self + } +} + +impl Element for StyledText { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let font_family_overrides = self.delayed_font_family_overrides.take(); + let mut runs = self.runs.take().or_else(|| { + self.delayed_highlights.take().map(|delayed_highlights| { + Self::compute_runs(&self.text, &window.text_style(), delayed_highlights) + }) + }); + + if let Some(ref overrides) = font_family_overrides { + let runs = + runs.get_or_insert_with(|| vec![window.text_style().to_run(self.text.len())]); + Self::apply_font_family_overrides(runs, overrides); + } + + let layout_id = self.layout.layout(self.text.clone(), runs, window, cx); + (layout_id, ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) { + self.layout.prepaint(bounds, &self.text) + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + self.layout.paint(&self.text, window, cx) + } +} + +impl IntoElement for StyledText { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +/// The Layout for TextElement. This can be used to map indices to pixels and vice versa. +#[derive(Default, Clone)] +pub struct TextLayout(Rc>>); + +#[derive(Clone, Copy)] +enum TextPaintPass { + All, + Background, + Foreground, +} + +struct TextLayoutInner { + len: usize, + lines: SmallVec<[WrappedLine; 1]>, + line_height: Pixels, + wrap_width: Option, + truncate_width: Option, + size: Option>, + bounds: Option>, +} + +impl TextLayout { + fn layout( + &self, + text: SharedString, + runs: Option>, + window: &mut Window, + _: &mut App, + ) -> LayoutId { + let text_style = window.text_style(); + let font_size = text_style.font_size.to_pixels(window.rem_size()); + let line_height = window.pixel_snap( + text_style + .line_height + .to_pixels(font_size.into(), window.rem_size()), + ); + + let runs = if let Some(runs) = runs { + runs + } else { + vec![text_style.to_run(text.len())] + }; + window.request_measured_layout(Default::default(), { + let element_state = self.clone(); + + move |known_dimensions, available_space, window, cx| { + let wrap_width = if text_style.white_space == WhiteSpace::Normal { + known_dimensions.width.or(match available_space.width { + crate::AvailableSpace::Definite(x) => Some(x), + _ => None, + }) + } else { + None + }; + + let (truncate_width, truncation_affix, truncate_from) = + if let Some(text_overflow) = text_style.text_overflow.clone() { + let width = known_dimensions.width.or(match available_space.width { + crate::AvailableSpace::Definite(x) => match text_style.line_clamp { + Some(max_lines) => Some(x * max_lines), + None => Some(x), + }, + _ => None, + }); + + match text_overflow { + TextOverflow::Truncate(s) => (width, s, TruncateFrom::End), + TextOverflow::TruncateStart(s) => (width, s, TruncateFrom::Start), + TextOverflow::TruncateMiddle(s) => (width, s, TruncateFrom::Middle), + } + } else { + (None, "".into(), TruncateFrom::End) + }; + + // Only use cached layout if: + // 1. We have a cached size + // 2. wrap_width matches (or both are None) + // 3. truncate_width is None (if truncate_width is Some, we need to re-layout + // because the previous layout may have been computed without truncation) + // 4. the cached layout was not truncated (a truncated layout answers an + // unconstrained probe with the truncated size, which poisons intrinsic + // sizing with whatever width some earlier measure pass happened to use) + if let Some(text_layout) = element_state.0.borrow().as_ref() + && let Some(size) = text_layout.size + && (wrap_width.is_none() || wrap_width == text_layout.wrap_width) + && truncate_width.is_none() + && text_layout.truncate_width.is_none() + { + return size; + } + + let mut line_wrapper = cx.text_system().line_wrapper(text_style.font(), font_size); + let (text, runs) = if let Some(truncate_width) = truncate_width { + if let Some(max_lines) = text_style.line_clamp + && let Some(wrap_width) = wrap_width + { + line_wrapper.truncate_wrapped_line( + text.clone(), + wrap_width, + max_lines, + &truncation_affix, + &runs, + truncate_from, + ) + } else if let Some(unclipped) = window + .text_system() + .shape_text(text.clone(), font_size, &runs, None, None) + .log_err() + && unclipped + .iter() + .all(|line| line.size(line_height).width <= truncate_width) + { + // The truncation decision below sums per-character advances, + // which overestimates the shaped width (no kerning), truncating + // text that fits exactly in its measured width. Skip truncation + // whenever the honestly-shaped text fits; the shaping result + // comes from the line layout cache when the same text was + // already measured untruncated this frame. + (text.clone(), Cow::Borrowed(&*runs)) + } else { + line_wrapper.truncate_line( + text.clone(), + truncate_width, + &truncation_affix, + &runs, + truncate_from, + ) + } + } else { + (text.clone(), Cow::Borrowed(&*runs)) + }; + let len = text.len(); + + let Some(lines) = window + .text_system() + .shape_text( + text, + font_size, + &runs, + wrap_width, // Wrap if we know the width. + text_style.line_clamp, // Limit the number of lines if line_clamp is set. + ) + .log_err() + else { + element_state.0.borrow_mut().replace(TextLayoutInner { + lines: Default::default(), + len: 0, + line_height, + wrap_width, + truncate_width, + size: Some(Size::default()), + bounds: None, + }); + return Size::default(); + }; + + let mut size: Size = Size::default(); + for line in &lines { + let line_size = line.size(line_height); + size.height += line_size.height; + size.width = size.width.max(line_size.width).ceil(); + } + + element_state.0.borrow_mut().replace(TextLayoutInner { + lines, + len, + line_height, + wrap_width, + truncate_width, + size: Some(size), + bounds: None, + }); + + size + } + }) + } + + fn prepaint(&self, bounds: Bounds, text: &str) { + let mut element_state = self.0.borrow_mut(); + let element_state = element_state + .as_mut() + .with_context(|| format!("measurement has not been performed on {text}")) + .unwrap(); + element_state.bounds = Some(bounds); + } + + fn paint(&self, text: &str, window: &mut Window, cx: &mut App) { + self.paint_lines(TextPaintPass::All, window, cx) + .with_context(|| format!("failed to paint {text}")) + .unwrap(); + } + + /// Paints the backgrounds of the text runs without the glyphs, so that callers can paint + /// content, such as highlights, between the backgrounds and the text. Follow it with + /// [`Self::paint_foreground`] to paint the glyphs. + pub fn paint_background(&self, window: &mut Window, cx: &mut App) -> anyhow::Result<()> { + self.paint_lines(TextPaintPass::Background, window, cx) + } + + /// Paints the glyphs and decorations of the text without the run backgrounds. + pub fn paint_foreground(&self, window: &mut Window, cx: &mut App) -> anyhow::Result<()> { + self.paint_lines(TextPaintPass::Foreground, window, cx) + } + + fn paint_lines( + &self, + pass: TextPaintPass, + window: &mut Window, + cx: &mut App, + ) -> anyhow::Result<()> { + let element_state = self.0.borrow(); + let element_state = element_state + .as_ref() + .context("measurement has not been performed")?; + let bounds = element_state + .bounds + .context("prepaint has not been performed")?; + + let line_height = element_state.line_height; + let mut line_origin = bounds.origin; + let text_style = window.text_style(); + for line in &element_state.lines { + if matches!(pass, TextPaintPass::All | TextPaintPass::Background) { + line.paint_background( + line_origin, + line_height, + text_style.text_align, + Some(bounds), + window, + cx, + ) + .log_err(); + } + if matches!(pass, TextPaintPass::All | TextPaintPass::Foreground) { + line.paint( + line_origin, + line_height, + text_style.text_align, + Some(bounds), + window, + cx, + ) + .log_err(); + } + line_origin.y += line.size(line_height).height; + } + Ok(()) + } + + /// Get the byte index into the input of the pixel position. + pub fn index_for_position(&self, mut position: Point) -> Result { + let element_state = self.0.borrow(); + let element_state = element_state + .as_ref() + .expect("measurement has not been performed"); + let bounds = element_state + .bounds + .expect("prepaint has not been performed"); + + if position.y < bounds.top() { + return Err(0); + } + + let line_height = element_state.line_height; + let mut line_origin = bounds.origin; + let mut line_start_ix = 0; + for line in &element_state.lines { + let line_bottom = line_origin.y + line.size(line_height).height; + if position.y > line_bottom { + line_origin.y = line_bottom; + line_start_ix += line.len() + 1; + } else { + let position_within_line = position - line_origin; + match line.index_for_position(position_within_line, line_height) { + Ok(index_within_line) => return Ok(line_start_ix + index_within_line), + Err(index_within_line) => return Err(line_start_ix + index_within_line), + } + } + } + + Err(line_start_ix.saturating_sub(1)) + } + + /// Get the pixel position for the given byte index. + pub fn position_for_index(&self, index: usize) -> Option> { + let element_state = self.0.borrow(); + let element_state = element_state + .as_ref() + .expect("measurement has not been performed"); + let bounds = element_state + .bounds + .expect("prepaint has not been performed"); + let line_height = element_state.line_height; + + let mut line_origin = bounds.origin; + let mut line_start_ix = 0; + + for line in &element_state.lines { + let line_end_ix = line_start_ix + line.len(); + if index < line_start_ix { + break; + } else if index > line_end_ix { + line_origin.y += line.size(line_height).height; + line_start_ix = line_end_ix + 1; + continue; + } else { + let ix_within_line = index - line_start_ix; + return Some(line_origin + line.position_for_index(ix_within_line, line_height)?); + } + } + + None + } + + /// Retrieve the layout for the line containing the given byte index. + pub fn line_layout_for_index(&self, index: usize) -> Option> { + let element_state = self.0.borrow(); + let element_state = element_state + .as_ref() + .expect("measurement has not been performed"); + let mut line_start_ix = 0; + + for line in &element_state.lines { + let line_end_ix = line_start_ix + line.len(); + if index < line_start_ix { + break; + } else if index > line_end_ix { + line_start_ix = line_end_ix + 1; + continue; + } else { + return Some(line.layout.clone()); + } + } + + None + } + + /// Retrieve all line layouts in source order. + pub fn line_layouts(&self) -> SmallVec<[Arc; 1]> { + self.0 + .borrow() + .as_ref() + .expect("measurement has not been performed") + .lines + .iter() + .map(|line| line.layout.clone()) + .collect() + } + + /// The bounds of this layout. + pub fn bounds(&self) -> Bounds { + self.0.borrow().as_ref().unwrap().bounds.unwrap() + } + + /// The line height for this layout. + pub fn line_height(&self) -> Pixels { + self.0.borrow().as_ref().unwrap().line_height + } + + /// The UTF-8 length of the underlying text. + pub fn len(&self) -> usize { + self.0.borrow().as_ref().unwrap().len + } + + /// The text for this layout. + pub fn text(&self) -> String { + self.0 + .borrow() + .as_ref() + .unwrap() + .lines + .iter() + .map(|s| &s.text) + .join("\n") + } + + /// The text for this layout (with soft-wraps as newlines) + pub fn wrapped_text(&self) -> String { + let mut accumulator = String::new(); + + for wrapped in self.0.borrow().as_ref().unwrap().lines.iter() { + let mut seen = 0; + for boundary in wrapped.layout.wrap_boundaries.iter() { + let index = wrapped.layout.unwrapped_layout.runs[boundary.run_ix].glyphs + [boundary.glyph_ix] + .index; + + accumulator.push_str(&wrapped.text[seen..index]); + accumulator.push('\n'); + seen = index; + } + accumulator.push_str(&wrapped.text[seen..]); + accumulator.push('\n'); + } + // Remove trailing newline + accumulator.pop(); + accumulator + } +} + +/// A text element that can be interacted with. +pub struct InteractiveText { + element_id: ElementId, + text: StyledText, + click_listener: + Option], InteractiveTextClickEvent, &mut Window, &mut App)>>, + hover_listener: Option, MouseMoveEvent, &mut Window, &mut App)>>, + tooltip_builder: Option Option>>, + tooltip_id: Option, + clickable_ranges: Vec>, +} + +struct InteractiveTextClickEvent { + mouse_down_index: usize, + mouse_up_index: usize, +} + +#[doc(hidden)] +#[derive(Default)] +pub struct InteractiveTextState { + mouse_down_index: Rc>>, + hovered_index: Rc>>, + active_tooltip: Rc>>, + long_press_tooltip_active: Rc>, +} + +/// InteractiveTest is a wrapper around StyledText that adds mouse interactions. +impl InteractiveText { + /// Creates a new InteractiveText from the given text. + pub fn new(id: impl Into, text: StyledText) -> Self { + Self { + element_id: id.into(), + text, + click_listener: None, + hover_listener: None, + tooltip_builder: None, + tooltip_id: None, + clickable_ranges: Vec::new(), + } + } + + /// on_click is called when the user clicks on one of the given ranges, passing the index of + /// the clicked range. + pub fn on_click( + mut self, + ranges: Vec>, + listener: impl Fn(usize, &mut Window, &mut App) + 'static, + ) -> Self { + self.click_listener = Some(Box::new(move |ranges, event, window, cx| { + for (range_ix, range) in ranges.iter().enumerate() { + if range.contains(&event.mouse_down_index) && range.contains(&event.mouse_up_index) + { + listener(range_ix, window, cx); + } + } + })); + self.clickable_ranges = ranges; + self + } + + /// on_hover is called when the mouse moves over a character within the text, passing the + /// index of the hovered character, or None if the mouse leaves the text. + pub fn on_hover( + mut self, + listener: impl Fn(Option, MouseMoveEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.hover_listener = Some(Box::new(listener)); + self + } + + /// tooltip lets you specify a tooltip for a given character index in the string. + pub fn tooltip( + mut self, + builder: impl Fn(usize, &mut Window, &mut App) -> Option + 'static, + ) -> Self { + self.tooltip_builder = Some(Rc::new(builder)); + self + } +} + +impl Element for InteractiveText { + type RequestLayoutState = (); + type PrepaintState = Hitbox; + + fn id(&self) -> Option { + Some(self.element_id.clone()) + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn a11y_role(&self) -> Option { + Some(accesskit::Role::Label) + } + + fn write_a11y_info(&self, node: &mut accesskit::Node) { + node.set_value(self.text.text.to_string()); + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + self.text.request_layout(None, inspector_id, window, cx) + } + + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + state: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Hitbox { + window.with_optional_element_state::( + global_id, + |interactive_state, window| { + let mut interactive_state = interactive_state + .map(|interactive_state| interactive_state.unwrap_or_default()); + + if let Some(interactive_state) = interactive_state.as_mut() { + if self.tooltip_builder.is_some() { + self.tooltip_id = + set_tooltip_on_window(&interactive_state.active_tooltip, window); + } else { + // If there is no longer a tooltip builder, remove the active tooltip. + interactive_state.long_press_tooltip_active.set(false); + interactive_state.active_tooltip.take(); + } + } + + self.text + .prepaint(None, inspector_id, bounds, state, window, cx); + let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal); + (hitbox, interactive_state) + }, + ) + } + + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + _: &mut Self::RequestLayoutState, + hitbox: &mut Hitbox, + window: &mut Window, + cx: &mut App, + ) { + let current_view = window.current_view(); + let text_layout = self.text.layout().clone(); + window.with_element_state::( + global_id.unwrap(), + |interactive_state, window| { + let mut interactive_state = interactive_state.unwrap_or_default(); + if let Some(click_listener) = self.click_listener.take() { + let mouse_position = window.mouse_position(); + if let Ok(ix) = text_layout.index_for_position(mouse_position) + && self + .clickable_ranges + .iter() + .any(|range| range.contains(&ix)) + { + window.set_cursor_style(crate::CursorStyle::PointingHand, hitbox) + } + + let text_layout = text_layout.clone(); + let mouse_down = interactive_state.mouse_down_index.clone(); + if let Some(mouse_down_index) = mouse_down.get() { + let hitbox = hitbox.clone(); + let clickable_ranges = mem::take(&mut self.clickable_ranges); + window.on_mouse_event( + move |event: &MouseUpEvent, phase, window: &mut Window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + if let Ok(mouse_up_index) = + text_layout.index_for_position(event.position) + { + click_listener( + &clickable_ranges, + InteractiveTextClickEvent { + mouse_down_index, + mouse_up_index, + }, + window, + cx, + ) + } + + mouse_down.take(); + window.refresh(); + } + }, + ); + } else { + let hitbox = hitbox.clone(); + window.on_mouse_event(move |event: &MouseDownEvent, phase, window, _| { + if phase == DispatchPhase::Bubble + && hitbox.is_hovered(window) + && let Ok(mouse_down_index) = + text_layout.index_for_position(event.position) + { + mouse_down.set(Some(mouse_down_index)); + window.refresh(); + } + }); + } + } + + window.on_mouse_event({ + let mut hover_listener = self.hover_listener.take(); + let hitbox = hitbox.clone(); + let text_layout = text_layout.clone(); + let hovered_index = interactive_state.hovered_index.clone(); + move |event: &MouseMoveEvent, phase, window, cx| { + if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) { + let current = hovered_index.get(); + let updated = text_layout.index_for_position(event.position).ok(); + if current != updated { + hovered_index.set(updated); + if let Some(hover_listener) = hover_listener.as_ref() { + hover_listener(updated, event.clone(), window, cx); + } + cx.notify(current_view); + } + } + } + }); + + if let Some(tooltip_builder) = self.tooltip_builder.clone() { + let active_tooltip = interactive_state.active_tooltip.clone(); + let build_tooltip = Rc::new({ + let tooltip_is_hoverable = false; + let text_layout = text_layout.clone(); + move |window: &mut Window, cx: &mut App| { + text_layout + .index_for_position(window.mouse_position()) + .ok() + .and_then(|position| tooltip_builder(position, window, cx)) + .map(|view| (view, tooltip_is_hoverable)) + } + }); + + // Use bounds instead of testing hitbox since this is called during prepaint. + let check_is_hovered_during_prepaint = Rc::new({ + let source_bounds = hitbox.bounds; + let text_layout = text_layout.clone(); + let pending_mouse_down = interactive_state.mouse_down_index.clone(); + move |window: &Window| { + text_layout + .index_for_position(window.mouse_position()) + .is_ok() + && source_bounds.contains(&window.mouse_position()) + && pending_mouse_down.get().is_none() + } + }); + + let check_is_hovered = Rc::new({ + let hitbox = hitbox.clone(); + let text_layout = text_layout.clone(); + let pending_mouse_down = interactive_state.mouse_down_index.clone(); + move |window: &Window| { + text_layout + .index_for_position(window.mouse_position()) + .is_ok() + && hitbox.is_hovered(window) + && pending_mouse_down.get().is_none() + } + }); + + register_tooltip_mouse_handlers( + &active_tooltip, + self.tooltip_id, + build_tooltip, + check_is_hovered, + check_is_hovered_during_prepaint, + interactive_state.long_press_tooltip_active.clone(), + None, + window, + ); + } + + self.text + .paint(None, inspector_id, bounds, &mut (), &mut (), window, cx); + + ((), interactive_state) + }, + ); + } +} + +impl IntoElement for InteractiveText { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_into_element_for() { + use crate::{ParentElement as _, SharedString, div}; + use std::borrow::Cow; + + let _ = div().child("static str"); + let _ = div().child("String".to_string()); + let _ = div().child(Cow::Borrowed("Cow")); + let _ = div().child(SharedString::from("SharedString")); + } + + #[test] + fn text_macro_id() { + // one call to `text!` = one id + fn make_text_stable_id(happy: bool) -> Text { + text!(if happy { "happy" } else { "sad" }) + } + + // two calls to `text!` = two ids + fn make_text_unstable_id(happy: bool) -> Text { + if happy { text!("happy") } else { text!("sad") } + } + + assert_eq!(make_text_stable_id(false).id, make_text_stable_id(true).id); + assert_ne!( + make_text_unstable_id(false).id, + make_text_unstable_id(true).id + ); + } +} diff --git a/vendor/gpui-pre/src/elements/uniform_list.rs b/vendor/gpui-pre/src/elements/uniform_list.rs new file mode 100644 index 00000000..0a449a20 --- /dev/null +++ b/vendor/gpui-pre/src/elements/uniform_list.rs @@ -0,0 +1,865 @@ +//! A scrollable list of elements with uniform height, optimized for large lists. +//! Rather than use the full taffy layout system, uniform_list simply measures +//! the first element and then lays out all remaining elements in a line based on that +//! measurement. This is much faster than the full layout system, but only works for +//! elements with uniform height. + +use crate::{ + AnyElement, App, AvailableSpace, Bounds, ContentMask, Element, ElementId, Entity, + GlobalElementId, Hitbox, InspectorElementId, InteractiveElement, Interactivity, IntoElement, + IsZero, LayoutId, ListSizingBehavior, Overflow, Pixels, Point, ScrollHandle, Size, + StyleRefinement, Styled, Window, point, px, size, +}; +use smallvec::SmallVec; +use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; + +use super::ListHorizontalSizingBehavior; + +/// uniform_list provides lazy rendering for a set of items that are of uniform height. +/// When rendered into a container with overflow-y: hidden and a fixed (or max) height, +/// uniform_list will only render the visible subset of items. +#[track_caller] +pub fn uniform_list( + id: impl Into, + item_count: usize, + f: impl 'static + Fn(Range, &mut Window, &mut App) -> Vec, +) -> UniformList +where + R: IntoElement, +{ + let id = id.into(); + let mut base_style = StyleRefinement::default(); + base_style.overflow.y = Some(Overflow::Scroll); + + let render_range = move |range: Range, window: &mut Window, cx: &mut App| { + f(range, window, cx) + .into_iter() + .map(|component| component.into_any_element()) + .collect() + }; + + UniformList { + item_count, + item_to_measure_index: 0, + render_items: Box::new(render_range), + decorations: Vec::new(), + interactivity: Interactivity { + element_id: Some(id), + base_style: Box::new(base_style), + ..Interactivity::new() + }, + scroll_handle: None, + sizing_behavior: ListSizingBehavior::default(), + horizontal_sizing_behavior: ListHorizontalSizingBehavior::default(), + } +} + +/// A list element for efficiently laying out and displaying a list of uniform-height elements. +pub struct UniformList { + item_count: usize, + item_to_measure_index: usize, + render_items: Box< + dyn for<'a> Fn(Range, &'a mut Window, &'a mut App) -> SmallVec<[AnyElement; 64]>, + >, + decorations: Vec>, + interactivity: Interactivity, + scroll_handle: Option, + sizing_behavior: ListSizingBehavior, + horizontal_sizing_behavior: ListHorizontalSizingBehavior, +} + +/// Frame state used by the [UniformList]. +pub struct UniformListFrameState { + items: SmallVec<[AnyElement; 32]>, + decorations: SmallVec<[AnyElement; 2]>, +} + +/// A handle for controlling the scroll position of a uniform list. +/// This should be stored in your view and passed to the uniform_list on each frame. +#[derive(Clone, Debug, Default)] +pub struct UniformListScrollHandle(pub Rc>); + +/// Where to place the element scrolled to. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ScrollStrategy { + /// Place the element at the top of the list's viewport. + Top, + /// Attempt to place the element in the middle of the list's viewport. + /// May not be possible if there's not enough list items above the item scrolled to: + /// in this case, the element will be placed at the closest possible position. + Center, + /// Attempt to place the element at the bottom of the list's viewport. + /// May not be possible if there's not enough list items above the item scrolled to: + /// in this case, the element will be placed at the closest possible position. + Bottom, + /// If the element is not visible attempt to place it at: + /// - The top of the list's viewport if the target element is above currently visible elements. + /// - The bottom of the list's viewport if the target element is above currently visible elements. + Nearest, +} + +#[derive(Clone, Copy, Debug)] +#[allow(missing_docs)] +pub struct DeferredScrollToItem { + /// The item index to scroll to + pub item_index: usize, + /// The scroll strategy to use + pub strategy: ScrollStrategy, + /// The offset in number of items + pub offset: usize, + pub scroll_strict: bool, +} + +#[derive(Clone, Debug, Default)] +#[allow(missing_docs)] +pub struct UniformListScrollState { + pub base_handle: ScrollHandle, + pub deferred_scroll_to_item: Option, + /// Size of the item, captured during last layout. + pub last_item_size: Option, + /// Whether the list was vertically flipped during last layout. + pub y_flipped: bool, +} + +#[derive(Copy, Clone, Debug, Default)] +/// The size of the item and its contents. +pub struct ItemSize { + /// The size of the item. + pub item: Size, + /// The size of the item's contents, which may be larger than the item itself, + /// if the item was bounded by a parent element. + pub contents: Size, +} + +impl UniformListScrollHandle { + /// Create a new scroll handle to bind to a uniform list. + pub fn new() -> Self { + Self(Rc::new(RefCell::new(UniformListScrollState { + base_handle: ScrollHandle::new(), + deferred_scroll_to_item: None, + last_item_size: None, + y_flipped: false, + }))) + } + + /// Scroll the list so that the given item index is visible. + /// + /// This uses non-strict scrolling: if the item is already fully visible, no scrolling occurs. + /// If the item is out of view, it scrolls the minimum amount to bring it into view according + /// to the strategy. + pub fn scroll_to_item(&self, ix: usize, strategy: ScrollStrategy) { + self.0.borrow_mut().deferred_scroll_to_item = Some(DeferredScrollToItem { + item_index: ix, + strategy, + offset: 0, + scroll_strict: false, + }); + } + + /// Scroll the list so that the given item index is at scroll strategy position. + /// + /// This uses strict scrolling: the item will always be scrolled to match the strategy position, + /// even if it's already visible. Use this when you need precise positioning. + pub fn scroll_to_item_strict(&self, ix: usize, strategy: ScrollStrategy) { + self.0.borrow_mut().deferred_scroll_to_item = Some(DeferredScrollToItem { + item_index: ix, + strategy, + offset: 0, + scroll_strict: true, + }); + } + + /// Scroll the list to the given item index with an offset in number of items. + /// + /// This uses non-strict scrolling: if the item is already visible within the offset region, + /// no scrolling occurs. + /// + /// The offset parameter shrinks the effective viewport by the specified number of items + /// from the corresponding edge, then applies the scroll strategy within that reduced viewport: + /// - `ScrollStrategy::Top`: Shrinks from top, positions item at the new top + /// - `ScrollStrategy::Center`: Shrinks from top, centers item in the reduced viewport + /// - `ScrollStrategy::Bottom`: Shrinks from bottom, positions item at the new bottom + pub fn scroll_to_item_with_offset(&self, ix: usize, strategy: ScrollStrategy, offset: usize) { + self.0.borrow_mut().deferred_scroll_to_item = Some(DeferredScrollToItem { + item_index: ix, + strategy, + offset, + scroll_strict: false, + }); + } + + /// Scroll the list so that the given item index is at the exact scroll strategy position with an offset. + /// + /// This uses strict scrolling: the item will always be scrolled to match the strategy position, + /// even if it's already visible. + /// + /// The offset parameter shrinks the effective viewport by the specified number of items + /// from the corresponding edge, then applies the scroll strategy within that reduced viewport: + /// - `ScrollStrategy::Top`: Shrinks from top, positions item at the new top + /// - `ScrollStrategy::Center`: Shrinks from top, centers item in the reduced viewport + /// - `ScrollStrategy::Bottom`: Shrinks from bottom, positions item at the new bottom + pub fn scroll_to_item_strict_with_offset( + &self, + ix: usize, + strategy: ScrollStrategy, + offset: usize, + ) { + self.0.borrow_mut().deferred_scroll_to_item = Some(DeferredScrollToItem { + item_index: ix, + strategy, + offset, + scroll_strict: true, + }); + } + + /// Check if the list is flipped vertically. + pub fn y_flipped(&self) -> bool { + self.0.borrow().y_flipped + } + + /// Get the index of the topmost visible child. + #[cfg(any(test, feature = "test-support"))] + pub fn logical_scroll_top_index(&self) -> usize { + let this = self.0.borrow(); + this.deferred_scroll_to_item + .as_ref() + .map(|deferred| deferred.item_index) + .unwrap_or_else(|| this.base_handle.logical_scroll_top().0) + } + + /// Checks if the list can be scrolled vertically. + pub fn is_scrollable(&self) -> bool { + if let Some(size) = self.0.borrow().last_item_size { + size.contents.height > size.item.height + } else { + false + } + } + + /// Whether the list is scrolled to the end, or `None` if the list is + /// not scrollable. + pub fn is_scrolled_to_end(&self) -> Option { + let state = self.0.borrow(); + let max_offset = state.base_handle.max_offset(); + if max_offset.y <= px(0.) { + return None; + } + let offset = state.base_handle.offset(); + Some(-offset.y >= max_offset.y) + } + + /// Scroll to the bottom of the list. + pub fn scroll_to_bottom(&self) { + self.scroll_to_item(usize::MAX, ScrollStrategy::Bottom); + } +} + +impl Styled for UniformList { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.interactivity.base_style + } +} + +impl Element for UniformList { + type RequestLayoutState = UniformListFrameState; + type PrepaintState = Option; + + fn id(&self) -> Option { + self.interactivity.element_id.clone() + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let max_items = self.item_count; + let item_size = self.measure_item(None, window, cx); + let layout_id = self.interactivity.request_layout( + global_id, + inspector_id, + window, + cx, + |style, window, cx| match self.sizing_behavior { + ListSizingBehavior::Infer => { + window.with_text_style(style.text_style().cloned(), |window| { + window.request_measured_layout( + style, + move |known_dimensions, available_space, _window, _cx| { + let desired_height = item_size.height * max_items; + let width = known_dimensions.width.unwrap_or(match available_space + .width + { + AvailableSpace::Definite(x) => x, + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + item_size.width + } + }); + let height = match available_space.height { + AvailableSpace::Definite(height) => desired_height.min(height), + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + desired_height + } + }; + size(width, height) + }, + ) + }) + } + ListSizingBehavior::Auto => window + .with_text_style(style.text_style().cloned(), |window| { + window.request_layout(style, None, cx) + }), + }, + ); + + ( + layout_id, + UniformListFrameState { + items: SmallVec::new(), + decorations: SmallVec::new(), + }, + ) + } + + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + frame_state: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Option { + let style = self + .interactivity + .compute_style(global_id, None, window, cx); + let border = style.border_widths.to_pixels(window.rem_size()); + let padding = style + .padding + .to_pixels(bounds.size.into(), window.rem_size()); + + let padded_bounds = Bounds::from_corners( + bounds.origin + point(border.left + padding.left, border.top + padding.top), + bounds.bottom_right() + - point(border.right + padding.right, border.bottom + padding.bottom), + ); + + let can_scroll_horizontally = matches!( + self.horizontal_sizing_behavior, + ListHorizontalSizingBehavior::Unconstrained + ); + + let longest_item_size = self.measure_item(None, window, cx); + let content_width = if can_scroll_horizontally { + padded_bounds.size.width.max(longest_item_size.width) + } else { + padded_bounds.size.width + }; + let content_size = Size { + width: content_width, + height: longest_item_size.height * self.item_count, + }; + + let shared_scroll_offset = self.interactivity.scroll_offset.clone().unwrap(); + let item_height = longest_item_size.height; + let shared_scroll_to_item = self.scroll_handle.as_mut().and_then(|handle| { + let mut handle = handle.0.borrow_mut(); + handle.last_item_size = Some(ItemSize { + item: padded_bounds.size, + contents: content_size, + }); + handle.deferred_scroll_to_item.take() + }); + + self.interactivity.prepaint( + global_id, + inspector_id, + bounds, + content_size, + window, + cx, + |_style, mut scroll_offset, hitbox, window, cx| { + let y_flipped = if let Some(scroll_handle) = &self.scroll_handle { + let scroll_state = scroll_handle.0.borrow(); + scroll_state.y_flipped + } else { + false + }; + + if self.item_count > 0 { + let content_height = item_height * self.item_count; + + let is_scrolled_vertically = !scroll_offset.y.is_zero(); + let max_scroll_offset = padded_bounds.size.height - content_height; + + if is_scrolled_vertically && scroll_offset.y < max_scroll_offset { + shared_scroll_offset.borrow_mut().y = max_scroll_offset; + scroll_offset.y = max_scroll_offset; + } + + let content_width = content_size.width + padding.left + padding.right; + let is_scrolled_horizontally = + can_scroll_horizontally && !scroll_offset.x.is_zero(); + if is_scrolled_horizontally && content_width <= padded_bounds.size.width { + shared_scroll_offset.borrow_mut().x = Pixels::ZERO; + scroll_offset.x = Pixels::ZERO; + } + + if let Some(DeferredScrollToItem { + mut item_index, + mut strategy, + offset, + scroll_strict, + }) = shared_scroll_to_item + { + if y_flipped { + item_index = self.item_count.saturating_sub(item_index + 1); + } + let list_height = padded_bounds.size.height; + let mut updated_scroll_offset = shared_scroll_offset.borrow_mut(); + let item_top = item_height * item_index; + let item_bottom = item_top + item_height; + let scroll_top = -updated_scroll_offset.y; + let offset_pixels = item_height * offset; + + // is the selected item above/below currently visible items + let is_above = item_top < scroll_top + offset_pixels; + let is_below = item_bottom > scroll_top + list_height; + + if scroll_strict || is_above || is_below { + if strategy == ScrollStrategy::Nearest { + if is_above { + strategy = ScrollStrategy::Top; + } else if is_below { + strategy = ScrollStrategy::Bottom; + } + } + + let max_scroll_offset = + (content_height - list_height).max(Pixels::ZERO); + match strategy { + ScrollStrategy::Top => { + updated_scroll_offset.y = -(item_top - offset_pixels) + .clamp(Pixels::ZERO, max_scroll_offset); + } + ScrollStrategy::Center => { + let item_center = item_top + item_height / 2.0; + + let viewport_height = list_height - offset_pixels; + let viewport_center = offset_pixels + viewport_height / 2.0; + let target_scroll_top = item_center - viewport_center; + updated_scroll_offset.y = + -target_scroll_top.clamp(Pixels::ZERO, max_scroll_offset); + } + ScrollStrategy::Bottom => { + updated_scroll_offset.y = -(item_bottom - list_height) + .clamp(Pixels::ZERO, max_scroll_offset); + } + ScrollStrategy::Nearest => { + // Nearest, but the item is visible -> no scroll is required + } + } + } + scroll_offset = *updated_scroll_offset + } + + let first_visible_element_ix = + (-(scroll_offset.y + padding.top) / item_height).floor() as usize; + let last_visible_element_ix = ((-scroll_offset.y + padded_bounds.size.height) + / item_height) + .ceil() as usize; + + let visible_range = first_visible_element_ix + ..cmp::min(last_visible_element_ix, self.item_count); + + let items = if y_flipped { + let flipped_range = self.item_count.saturating_sub(visible_range.end) + ..self.item_count.saturating_sub(visible_range.start); + let mut items = (self.render_items)(flipped_range, window, cx); + items.reverse(); + items + } else { + (self.render_items)(visible_range.clone(), window, cx) + }; + + let content_mask = ContentMask { bounds }; + window.with_content_mask(Some(content_mask), |window| { + for (mut item, ix) in items.into_iter().zip(visible_range.clone()) { + let item_origin = padded_bounds.origin + + scroll_offset + + point(Pixels::ZERO, item_height * ix); + + let available_width = if can_scroll_horizontally { + padded_bounds.size.width + scroll_offset.x.abs() + } else { + padded_bounds.size.width + }; + let available_space = size( + AvailableSpace::Definite(available_width), + AvailableSpace::Definite(item_height), + ); + item.layout_as_root(available_space, window, cx); + item.prepaint_at(item_origin, window, cx); + frame_state.items.push(item); + } + + let bounds = + Bounds::new(padded_bounds.origin + scroll_offset, padded_bounds.size); + for decoration in &self.decorations { + let mut decoration = decoration.as_ref().compute( + visible_range.clone(), + bounds, + scroll_offset, + item_height, + self.item_count, + window, + cx, + ); + let available_space = size( + AvailableSpace::Definite(bounds.size.width), + AvailableSpace::Definite(bounds.size.height), + ); + decoration.layout_as_root(available_space, window, cx); + decoration.prepaint_at(bounds.origin, window, cx); + frame_state.decorations.push(decoration); + } + }); + } + + hitbox + }, + ) + } + + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + request_layout: &mut Self::RequestLayoutState, + hitbox: &mut Option, + window: &mut Window, + cx: &mut App, + ) { + self.interactivity.paint( + global_id, + inspector_id, + bounds, + hitbox.as_ref(), + window, + cx, + |_, window, cx| { + for item in &mut request_layout.items { + item.paint(window, cx); + } + for decoration in &mut request_layout.decorations { + decoration.paint(window, cx); + } + }, + ) + } +} + +impl IntoElement for UniformList { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +/// A decoration for a [`UniformList`]. This can be used for various things, +/// such as rendering indent guides, or other visual effects. +pub trait UniformListDecoration { + /// Compute the decoration element, given the visible range of list items, + /// the bounds of the list, and the height of each item. + fn compute( + &self, + visible_range: Range, + bounds: Bounds, + scroll_offset: Point, + item_height: Pixels, + item_count: usize, + window: &mut Window, + cx: &mut App, + ) -> AnyElement; +} + +impl UniformListDecoration for Entity { + fn compute( + &self, + visible_range: Range, + bounds: Bounds, + scroll_offset: Point, + item_height: Pixels, + item_count: usize, + window: &mut Window, + cx: &mut App, + ) -> AnyElement { + self.update(cx, |inner, cx| { + inner.compute( + visible_range, + bounds, + scroll_offset, + item_height, + item_count, + window, + cx, + ) + }) + } +} + +impl UniformList { + /// Selects a specific list item for measurement. + pub fn with_width_from_item(mut self, item_index: Option) -> Self { + self.item_to_measure_index = item_index.unwrap_or(0); + self + } + + /// Sets the sizing behavior, similar to the `List` element. + pub fn with_sizing_behavior(mut self, behavior: ListSizingBehavior) -> Self { + self.sizing_behavior = behavior; + self + } + + /// Sets the horizontal sizing behavior, controlling the way list items laid out horizontally. + /// With [`ListHorizontalSizingBehavior::Unconstrained`] behavior, every item and the list itself will + /// have the size of the widest item and lay out pushing the `end_slot` to the right end. + pub fn with_horizontal_sizing_behavior( + mut self, + behavior: ListHorizontalSizingBehavior, + ) -> Self { + self.horizontal_sizing_behavior = behavior; + match behavior { + ListHorizontalSizingBehavior::FitList => { + self.interactivity.base_style.overflow.x = None; + } + ListHorizontalSizingBehavior::Unconstrained => { + self.interactivity.base_style.overflow.x = Some(Overflow::Scroll); + } + } + self + } + + /// Adds a decoration element to the list. + pub fn with_decoration(mut self, decoration: impl UniformListDecoration + 'static) -> Self { + self.decorations.push(Box::new(decoration)); + self + } + + fn measure_item( + &self, + list_width: Option, + window: &mut Window, + cx: &mut App, + ) -> Size { + if self.item_count == 0 { + return Size::default(); + } + + let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1); + let mut items = (self.render_items)(item_ix..item_ix + 1, window, cx); + let Some(mut item_to_measure) = items.pop() else { + return Size::default(); + }; + let available_space = size( + list_width.map_or(AvailableSpace::MaxContent, |width| { + AvailableSpace::Definite(width) + }), + AvailableSpace::MinContent, + ); + item_to_measure.layout_as_root(available_space, window, cx) + } + + /// Track and render scroll state of this list with reference to the given scroll handle. + pub fn track_scroll(mut self, handle: &UniformListScrollHandle) -> Self { + self.interactivity.tracked_scroll_handle = Some(handle.0.borrow().base_handle.clone()); + self.scroll_handle = Some(handle.clone()); + self + } + + /// Sets whether the list is flipped vertically, such that item 0 appears at the bottom. + pub fn y_flipped(mut self, y_flipped: bool) -> Self { + if let Some(ref scroll_handle) = self.scroll_handle { + let mut scroll_state = scroll_handle.0.borrow_mut(); + let mut base_handle = &scroll_state.base_handle; + let offset = base_handle.offset(); + match scroll_state.last_item_size { + Some(last_size) if scroll_state.y_flipped != y_flipped => { + let new_y_offset = + -(offset.y + last_size.contents.height - last_size.item.height); + base_handle.set_offset(point(offset.x, new_y_offset)); + scroll_state.y_flipped = y_flipped; + } + // Handle case where list is initially flipped. + None if y_flipped => { + base_handle.set_offset(point(offset.x, Pixels::MIN)); + scroll_state.y_flipped = y_flipped; + } + _ => {} + } + } + self + } +} + +impl InteractiveElement for UniformList { + fn interactivity(&mut self) -> &mut crate::Interactivity { + &mut self.interactivity + } +} + +#[cfg(test)] +mod test { + use crate::TestAppContext; + + #[gpui::test] + fn test_scroll_strategy_nearest(cx: &mut TestAppContext) { + use crate::{ + Context, FocusHandle, ScrollStrategy, UniformListScrollHandle, Window, div, prelude::*, + px, uniform_list, + }; + use std::ops::Range; + + actions!(example, [SelectNext, SelectPrev]); + + struct TestView { + index: usize, + length: usize, + scroll_handle: UniformListScrollHandle, + focus_handle: FocusHandle, + visible_range: Range, + } + + impl TestView { + pub fn select_next( + &mut self, + _: &SelectNext, + window: &mut Window, + _: &mut Context, + ) { + if self.index + 1 == self.length { + self.index = 0 + } else { + self.index += 1; + } + self.scroll_handle + .scroll_to_item(self.index, ScrollStrategy::Nearest); + window.refresh(); + } + + pub fn select_previous( + &mut self, + _: &SelectPrev, + window: &mut Window, + _: &mut Context, + ) { + if self.index == 0 { + self.index = self.length - 1 + } else { + self.index -= 1; + } + self.scroll_handle + .scroll_to_item(self.index, ScrollStrategy::Nearest); + window.refresh(); + } + } + + impl Render for TestView { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + div() + .id("list-example") + .track_focus(&self.focus_handle) + .on_action(cx.listener(Self::select_next)) + .on_action(cx.listener(Self::select_previous)) + .size_full() + .child( + uniform_list( + "entries", + self.length, + cx.processor(|this, range: Range, _window, _cx| { + this.visible_range = range.clone(); + range + .map(|ix| div().id(ix).h(px(20.0)).child(format!("Item {ix}"))) + .collect() + }), + ) + .track_scroll(&self.scroll_handle) + .h(px(200.0)), + ) + } + } + + let (view, cx) = cx.add_window_view(|window, cx| { + let focus_handle = cx.focus_handle(); + window.focus(&focus_handle, cx); + TestView { + scroll_handle: UniformListScrollHandle::new(), + index: 0, + focus_handle, + length: 47, + visible_range: 0..0, + } + }); + + // 10 out of 47 items are visible + + // First 9 times selecting next item does not scroll + for ix in 1..10 { + cx.dispatch_action(SelectNext); + view.read_with(cx, |view, _| { + assert_eq!(view.index, ix); + assert_eq!(view.visible_range, 0..10); + }) + } + + // Now each time the list scrolls down by 1 + for ix in 10..47 { + cx.dispatch_action(SelectNext); + view.read_with(cx, |view, _| { + assert_eq!(view.index, ix); + assert_eq!(view.visible_range, ix - 9..ix + 1); + }) + } + + // After the last item we move back to the start + cx.dispatch_action(SelectNext); + view.read_with(cx, |view, _| { + assert_eq!(view.index, 0); + assert_eq!(view.visible_range, 0..10); + }); + + // Return to the last element + cx.dispatch_action(SelectPrev); + view.read_with(cx, |view, _| { + assert_eq!(view.index, 46); + assert_eq!(view.visible_range, 37..47); + }); + + // First 9 times selecting previous does not scroll + for ix in (37..46).rev() { + cx.dispatch_action(SelectPrev); + view.read_with(cx, |view, _| { + assert_eq!(view.index, ix); + assert_eq!(view.visible_range, 37..47); + }) + } + + // Now each time the list scrolls up by 1 + for ix in (0..37).rev() { + cx.dispatch_action(SelectPrev); + view.read_with(cx, |view, _| { + assert_eq!(view.index, ix); + assert_eq!(view.visible_range, ix..ix + 10); + }) + } + } +} diff --git a/vendor/gpui-pre/src/executor.rs b/vendor/gpui-pre/src/executor.rs new file mode 100644 index 00000000..78928d0f --- /dev/null +++ b/vendor/gpui-pre/src/executor.rs @@ -0,0 +1,583 @@ +use crate::{ActivityGuard, App, PlatformDispatcher, PlatformScheduler}; +#[cfg(not(target_family = "wasm"))] +use futures::channel::mpsc; +use futures::prelude::*; +use gpui_util::{TryFutureExt, TryFutureExtBacktrace}; +use scheduler::Instant; +use scheduler::Scheduler; +use std::{future::Future, marker::PhantomData, rc::Rc, sync::Arc, time::Duration}; +#[cfg(not(target_family = "wasm"))] +use std::{mem, pin::Pin}; + +pub use scheduler::{ + DedicatedExecutor, FallibleTask, LocalExecutor as SchedulerLocalExecutor, Priority, Task, +}; + +/// A pointer to the executor that is currently running, +/// for spawning background tasks. +#[derive(Clone)] +pub struct BackgroundExecutor { + inner: scheduler::BackgroundExecutor, + dispatcher: Arc, +} + +/// A pointer to the executor that is currently running, +/// for spawning tasks on the main thread. +#[derive(Clone)] +pub struct ForegroundExecutor { + inner: scheduler::LocalExecutor, + dispatcher: Arc, + #[cfg(feature = "profiler")] + foreground_runnables: Option, + not_send: PhantomData>, +} + +/// Extension trait for `Task>` that adds `detach_and_log_err` with an `&App` context. +/// +/// This trait is automatically implemented for all `Task>` types. +pub trait TaskExt { + /// Run the task to completion in the background and log any errors that occur. + fn detach_and_log_err(self, cx: &App); + /// Like [`Self::detach_and_log_err`], but uses `{:?}` formatting on failure so `anyhow::Error` + /// values emit their full backtrace. Prefer `detach_and_log_err` unless a backtrace is wanted. + fn detach_and_log_err_with_backtrace(self, cx: &App); +} + +impl TaskExt for Task> +where + T: 'static, + E: 'static + std::fmt::Display + std::fmt::Debug, +{ + #[track_caller] + fn detach_and_log_err(self, cx: &App) { + let location = core::panic::Location::caller(); + cx.foreground_executor() + .spawn(self.log_tracked_err(*location)) + .detach(); + } + + #[track_caller] + fn detach_and_log_err_with_backtrace(self, cx: &App) { + let location = *core::panic::Location::caller(); + cx.foreground_executor() + .spawn(self.log_tracked_err_with_backtrace(location)) + .detach(); + } +} + +impl BackgroundExecutor { + /// Creates a new BackgroundExecutor from the given PlatformDispatcher. + pub fn new(dispatcher: Arc) -> Self { + #[cfg(any(test, feature = "test-support"))] + let scheduler: Arc = if let Some(test_dispatcher) = dispatcher.as_test() { + test_dispatcher.scheduler().clone() + } else { + Arc::new(PlatformScheduler::new(dispatcher.clone())) + }; + + #[cfg(not(any(test, feature = "test-support")))] + let scheduler: Arc = Arc::new(PlatformScheduler::new(dispatcher.clone())); + + Self { + inner: scheduler::BackgroundExecutor::new(scheduler), + dispatcher, + } + } + + /// Returns the underlying scheduler::BackgroundExecutor. + /// + /// This is used by Ex to pass the executor to thread/worktree code. + pub fn scheduler_executor(&self) -> scheduler::BackgroundExecutor { + self.inner.clone() + } + + /// Prevents App Nap-style throttling while the returned guard is held. + /// + /// This does not prevent the system from entering idle sleep. + pub fn prevent_app_nap(&self, reason: &str) -> ActivityGuard { + self.dispatcher.prevent_app_nap(reason) + } + + /// Enqueues the given future to be run to completion on a background thread. + #[track_caller] + pub fn spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static, + { + self.spawn_with_priority(Priority::default(), future.boxed()) + } + + /// Enqueues the given future to be run to completion on a background thread with the given priority. + /// + /// When `Priority::RealtimeAudio` is used, the task runs on a dedicated thread with + /// realtime scheduling priority, suitable for audio processing. + #[track_caller] + pub fn spawn_with_priority( + &self, + priority: Priority, + future: impl Future + Send + 'static, + ) -> Task + where + R: Send + 'static, + { + if priority == Priority::RealtimeAudio { + self.inner.spawn_realtime(future) + } else { + self.inner.spawn_with_priority(priority, future) + } + } + + /// Runs background tasks that may borrow from their environment and waits for all of them to complete. + /// + /// Dropping the returned future cancels its tasks and synchronously waits for their futures to + /// be destroyed before returning. + #[cfg(not(target_family = "wasm"))] + pub async fn scoped<'scope, F>(&self, scheduler: F) + where + F: FnOnce(&mut Scope<'scope>), + { + let mut scope = Scope::new(self.clone(), Priority::default()); + (scheduler)(&mut scope); + let spawned = mem::take(&mut scope.futures) + .into_iter() + .map(|f| self.spawn_with_priority(scope.priority, f)) + .collect::>(); + for task in spawned { + task.await; + } + } + + /// Runs prioritized background tasks that may borrow from their environment and waits for all + /// of them to complete. + /// + /// Dropping the returned future cancels its tasks and synchronously waits for their futures to + /// be destroyed before returning. + #[cfg(not(target_family = "wasm"))] + pub async fn scoped_priority<'scope, F>(&self, priority: Priority, scheduler: F) + where + F: FnOnce(&mut Scope<'scope>), + { + let mut scope = Scope::new(self.clone(), priority); + (scheduler)(&mut scope); + let spawned = mem::take(&mut scope.futures) + .into_iter() + .map(|f| self.spawn_with_priority(scope.priority, f)) + .collect::>(); + for task in spawned { + task.await; + } + } + + /// Get the current time. + /// + /// Calling this instead of `std::time::Instant::now` allows the use + /// of fake timers in tests. + pub fn now(&self) -> Instant { + self.inner.scheduler().clock().now() + } + + /// Returns a task that will complete after the given duration. + /// Depending on other concurrent tasks the elapsed duration may be longer + /// than requested. + #[track_caller] + pub fn timer(&self, duration: Duration) -> Task<()> { + if duration.is_zero() { + return Task::ready(()); + } + self.spawn(self.inner.scheduler().timer(duration)) + } + + /// In tests, run an arbitrary number of tasks (determined by the SEED environment variable) + #[cfg(any(test, feature = "test-support"))] + pub fn simulate_random_delay(&self) -> impl Future + use<> { + self.dispatcher.as_test().unwrap().simulate_random_delay() + } + + /// In tests, move time forward. This does not run any tasks, but does make `timer`s ready. + #[cfg(any(test, feature = "test-support"))] + pub fn advance_clock(&self, duration: Duration) { + self.dispatcher.as_test().unwrap().advance_clock(duration) + } + + /// In tests, run one task. + #[cfg(any(test, feature = "test-support"))] + pub fn tick(&self) -> bool { + self.dispatcher.as_test().unwrap().scheduler().tick() + } + + /// In tests, run tasks until the scheduler would park. + /// + /// Under the scheduler-backed test dispatcher, `tick()` will not advance the clock, so a pending + /// timer can keep `has_pending_tasks()` true even after all currently-runnable tasks have been + /// drained. To preserve the historical semantics that tests relied on (drain all work that can + /// make progress), we advance the clock to the next timer when no runnable tasks remain. + #[cfg(any(test, feature = "test-support"))] + pub fn run_until_parked(&self) { + let scheduler = self.dispatcher.as_test().unwrap().scheduler(); + scheduler.run(); + } + + /// In tests, prevents `run_until_parked` from panicking if there are outstanding tasks. + #[cfg(any(test, feature = "test-support"))] + pub fn allow_parking(&self) { + self.dispatcher + .as_test() + .unwrap() + .scheduler() + .allow_parking(); + + if std::env::var("GPUI_RUN_UNTIL_PARKED_LOG").ok().as_deref() == Some("1") { + log::warn!("[gpui::executor] allow_parking: enabled"); + } + } + + /// Sets the range of ticks to run before timing out in block_on. + #[cfg(any(test, feature = "test-support"))] + pub fn set_block_on_ticks(&self, range: std::ops::RangeInclusive) { + self.dispatcher + .as_test() + .unwrap() + .scheduler() + .set_timeout_ticks(range); + } + + /// Undoes the effect of [`Self::allow_parking`]. + #[cfg(any(test, feature = "test-support"))] + pub fn forbid_parking(&self) { + self.dispatcher + .as_test() + .unwrap() + .scheduler() + .forbid_parking(); + } + + /// In tests, returns the rng used by the dispatcher. + #[cfg(any(test, feature = "test-support"))] + pub fn rng(&self) -> scheduler::SharedRng { + self.dispatcher.as_test().unwrap().scheduler().rng() + } + + /// How many CPUs are available to the dispatcher. + pub fn num_cpus(&self) -> usize { + #[cfg(any(test, feature = "test-support"))] + if let Some(test) = self.dispatcher.as_test() { + return test.num_cpus_override().unwrap_or(4); + } + num_cpus::get() + } + + /// Override the number of CPUs reported by this executor in tests. + /// Panics if not called on a test executor. + #[cfg(any(test, feature = "test-support"))] + pub fn set_num_cpus(&self, count: usize) { + self.dispatcher + .as_test() + .expect("set_num_cpus can only be called on a test executor") + .set_num_cpus(count); + } + + /// Whether we're on the main thread. + pub fn is_main_thread(&self) -> bool { + self.dispatcher.is_main_thread() + } + + /// Whether this executor runs on the deterministic test scheduler. + /// + /// Available in every build. Use it, rather than `cfg(feature = + /// "test-support")`, for behavior that must differ under tests, so that + /// compiling `test-support` into an application doesn't change it. + pub fn is_test(&self) -> bool { + self.inner.is_test() + } + + #[doc(hidden)] + pub fn dispatcher(&self) -> &Arc { + &self.dispatcher + } +} + +impl ForegroundExecutor { + /// Creates a new ForegroundExecutor from the given PlatformDispatcher. + pub fn new(dispatcher: Arc) -> Self { + #[cfg(any(test, feature = "test-support"))] + let (scheduler, session_id): (Arc, _) = + if let Some(test_dispatcher) = dispatcher.as_test() { + ( + test_dispatcher.scheduler().clone(), + test_dispatcher.session_id(), + ) + } else { + let platform_scheduler = Arc::new(PlatformScheduler::new(dispatcher.clone())); + let inner = platform_scheduler.foreground_executor(); + return Self { + inner, + dispatcher, + #[cfg(feature = "profiler")] + foreground_runnables: Some(platform_scheduler.foreground_runnable_counter()), + not_send: PhantomData, + }; + }; + + #[cfg(not(any(test, feature = "test-support")))] + let platform_scheduler = Arc::new(PlatformScheduler::new(dispatcher.clone())); + #[cfg(not(any(test, feature = "test-support")))] + let inner = platform_scheduler.foreground_executor(); + #[cfg(all(not(any(test, feature = "test-support")), feature = "profiler"))] + let foreground_runnables = Some(platform_scheduler.foreground_runnable_counter()); + + #[cfg(any(test, feature = "test-support"))] + let inner = { + let scheduler_for_dispatch = Arc::downgrade(&scheduler); + scheduler::LocalExecutor::new(session_id, scheduler, move |runnable| { + if let Some(scheduler) = scheduler_for_dispatch.upgrade() { + scheduler.schedule_local(session_id, runnable); + } + }) + }; + + #[cfg(all(any(test, feature = "test-support"), feature = "profiler"))] + // The deterministic test scheduler does not invoke GPUI's task profiler + // hooks, so an increment here would have no matching decrement. + let foreground_runnables = None; + + Self { + inner, + dispatcher, + #[cfg(feature = "profiler")] + foreground_runnables, + not_send: PhantomData, + } + } + + /// Enqueues the given Task to run on the main thread. + #[track_caller] + pub fn spawn(&self, future: impl Future + 'static) -> Task + where + R: 'static, + { + self.inner.spawn(future.boxed_local()) + } + + /// Enqueues the given Task to run on the main thread with the given priority. + #[track_caller] + pub fn spawn_with_priority( + &self, + _priority: Priority, + future: impl Future + 'static, + ) -> Task + where + R: 'static, + { + // Priority is ignored for foreground tasks - they run in order on the main thread + self.inner.spawn(future) + } + + /// On platforms with dedicated support, enqueues the given future to run + /// on the main thread during platform idle time. Without a `timeout`, + /// polls may be deferred indefinitely while the platform stays busy; + /// with one, a poll still waiting after that long runs as ordinary main-thread work. + /// Each poll occupies part of one idle slice, so long synchronous stretches + /// should bound themselves against [`Self::idle_time_remaining`] and yield. + /// + /// On platforms without dedicated support, schedules the given future to run + /// with a low priority, ignoring `timeout`. + #[track_caller] + pub fn spawn_when_idle( + &self, + timeout: Option, + future: impl Future + 'static, + ) -> Task + where + R: 'static, + { + let dispatcher = self.dispatcher.clone(); + #[cfg(feature = "profiler")] + let foreground_runnables = self.foreground_runnables.clone(); + self.inner + .spawn_with_dispatch(future.boxed_local(), move |runnable| { + #[cfg(feature = "profiler")] + if let Some(foreground_runnables) = &foreground_runnables { + foreground_runnables.queued(); + } + dispatcher.dispatch_on_main_thread_when_idle(runnable, timeout); + }) + } + + /// The time remaining in the current idle slice, when called from a task + /// spawned via [`Self::spawn_when_idle`] on a platform that meters idle + /// time. `None` when idle time is unmetered (or the caller is not inside + /// an idle slice); work that must bound itself should then fall back to a + /// budget of its own. + pub fn idle_time_remaining(&self) -> Option { + self.dispatcher.idle_time_remaining() + } + + /// Used by the test harness to run an async test in a synchronous fashion. + #[cfg(all(not(target_family = "wasm"), any(test, feature = "test-support")))] + #[track_caller] + pub fn block_test(&self, future: impl Future) -> R { + use std::cell::Cell; + + let scheduler = self.inner.scheduler(); + + let output = Cell::new(None); + let future = async { + output.set(Some(future.await)); + }; + let mut future = std::pin::pin!(future); + + // In async GPUI tests, we must allow foreground tasks scheduled by the test itself + // (which are associated with the test session) to make progress while we block. + // Otherwise, awaiting futures that depend on same-session foreground work can deadlock. + scheduler.block(None, future.as_mut(), None); + + output.take().expect("block_test future did not complete") + } + + /// Block the current thread until the given future resolves. + /// Consider using `block_with_timeout` instead. + #[cfg(not(target_family = "wasm"))] + pub fn block_on(&self, future: impl Future) -> R { + self.inner.block_on(future) + } + + /// Block the current thread until the given future resolves or the timeout elapses. + #[cfg(not(target_family = "wasm"))] + pub fn block_with_timeout>( + &self, + duration: Duration, + future: Fut, + ) -> Result + use> { + self.inner.block_with_timeout(duration, future) + } + + #[doc(hidden)] + pub fn dispatcher(&self) -> &Arc { + &self.dispatcher + } + + #[doc(hidden)] + pub fn scheduler_executor(&self) -> SchedulerLocalExecutor { + self.inner.clone() + } +} + +/// Scope manages a set of tasks that are enqueued and waited on together. See [`BackgroundExecutor::scoped`]. +#[cfg(not(target_family = "wasm"))] +pub struct Scope<'a> { + executor: BackgroundExecutor, + priority: Priority, + futures: Vec + Send + 'static>>>, + tx: Option>, + rx: mpsc::Receiver<()>, + lifetime: PhantomData<&'a ()>, +} + +#[cfg(not(target_family = "wasm"))] +impl<'a> Scope<'a> { + fn new(executor: BackgroundExecutor, priority: Priority) -> Self { + let (tx, rx) = mpsc::channel(1); + Self { + executor, + priority, + tx: Some(tx), + rx, + futures: Default::default(), + lifetime: PhantomData, + } + } + + /// How many CPUs are available to the dispatcher. + pub fn num_cpus(&self) -> usize { + self.executor.num_cpus() + } + + /// Spawn a future into this scope. + #[track_caller] + pub fn spawn(&mut self, f: F) + where + F: Future + Send + 'a, + { + let tx = self.tx.clone().unwrap(); + + // SAFETY: The 'a lifetime is guaranteed to outlive any of these futures because + // dropping this `Scope` blocks until all of the futures have resolved. + let f = unsafe { + mem::transmute::< + Pin + Send + 'a>>, + Pin + Send + 'static>>, + >(Box::pin(async move { + f.await; + drop(tx); + })) + }; + self.futures.push(f); + } +} + +#[cfg(not(target_family = "wasm"))] +impl Drop for Scope<'_> { + fn drop(&mut self) { + self.tx.take().unwrap(); + + // Wait until the channel is closed, which means that all of the spawned + // futures have resolved. + let future = async { + self.rx.next().await; + }; + let mut future = std::pin::pin!(future); + self.executor + .inner + .scheduler() + .block(None, future.as_mut(), None); + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{App, TestDispatcher, TestPlatform}; + use std::cell::RefCell; + + /// Helper to create test infrastructure. + /// Returns (dispatcher, background_executor, app). + fn create_test_app() -> (TestDispatcher, BackgroundExecutor, Rc) { + let dispatcher = TestDispatcher::new(0); + let arc_dispatcher = Arc::new(dispatcher.clone()); + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + + let platform = TestPlatform::new(background_executor.clone(), foreground_executor); + let asset_source = Arc::new(()); + let http_client = http_client::FakeHttpClient::with_404_response(); + + let app = App::new_app(platform, asset_source, http_client); + (dispatcher, background_executor, app) + } + + #[test] + fn sanity_test_tasks_run() { + let (dispatcher, _background_executor, app) = create_test_app(); + let foreground_executor = app.borrow().foreground_executor.clone(); + + let task_ran = Rc::new(RefCell::new(false)); + + foreground_executor + .spawn({ + let task_ran = Rc::clone(&task_ran); + async move { + *task_ran.borrow_mut() = true; + } + }) + .detach(); + + // Run dispatcher while app is still alive + dispatcher.run_until_parked(); + + // Task should have run + assert!( + *task_ran.borrow(), + "Task should run normally when app is alive" + ); + } +} diff --git a/vendor/gpui-pre/src/geometry.rs b/vendor/gpui-pre/src/geometry.rs new file mode 100644 index 00000000..1c87031c --- /dev/null +++ b/vendor/gpui-pre/src/geometry.rs @@ -0,0 +1,4020 @@ +//! The GPUI geometry module is a collection of types and traits that +//! can be used to describe common units, concepts, and the relationships +//! between them. + +use anyhow::{Context as _, anyhow}; +use core::fmt::Debug; +use derive_more::{Add, AddAssign, Div, DivAssign, Mul, Neg, Sub, SubAssign}; +use refineable::Refineable; +use schemars::{JsonSchema, json_schema}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; +use std::borrow::Cow; +use std::ops::{AddAssign, Range}; +use std::{ + cmp::{self, PartialOrd}, + fmt::{self, Display}, + hash::Hash, + ops::{Add, Div, Mul, MulAssign, Neg, Sub}, +}; +use taffy::prelude::{TaffyGridLine, TaffyGridSpan}; + +use crate::{App, DisplayId}; + +/// Axis in a 2D cartesian space. +#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +pub enum Axis { + /// The y axis, or up and down + Vertical, + /// The x axis, or left and right + Horizontal, +} + +impl Axis { + /// Swap this axis to the opposite axis. + pub fn invert(self) -> Self { + match self { + Axis::Vertical => Axis::Horizontal, + Axis::Horizontal => Axis::Vertical, + } + } +} + +/// A trait for accessing the given unit along a certain axis. +pub trait Along { + /// The unit associated with this type + type Unit; + + /// Returns the unit along the given axis. + fn along(&self, axis: Axis) -> Self::Unit; + + /// Applies the given function to the unit along the given axis and returns a new value. + fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self; +} + +/// Describes a location in a 2D cartesian space. +/// +/// It holds two public fields, `x` and `y`, which represent the coordinates in the space. +/// The type `T` for the coordinates can be any type that implements `Default`, `Clone`, and `Debug`. +/// +/// # Examples +/// +/// ``` +/// # use gpui::Point; +/// let point = Point { x: 10, y: 20 }; +/// println!("{:?}", point); // Outputs: Point { x: 10, y: 20 } +/// ``` +#[derive( + Refineable, + Default, + Add, + AddAssign, + Sub, + SubAssign, + Copy, + Debug, + PartialEq, + Eq, + Serialize, + Deserialize, + JsonSchema, + Hash, + Neg, +)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct Point { + /// The x coordinate of the point. + pub x: T, + /// The y coordinate of the point. + pub y: T, +} + +/// Constructs a new `Point` with the given x and y coordinates. +/// +/// # Arguments +/// +/// * `x` - The x coordinate of the point. +/// * `y` - The y coordinate of the point. +/// +/// # Returns +/// +/// Returns a `Point` with the specified coordinates. +/// +/// # Examples +/// +/// ``` +/// use gpui::point; +/// let p = point(10, 20); +/// assert_eq!(p.x, 10); +/// assert_eq!(p.y, 20); +/// ``` +pub const fn point(x: T, y: T) -> Point { + Point { x, y } +} + +impl Point { + /// Creates a new `Point` with the specified `x` and `y` coordinates. + /// + /// # Arguments + /// + /// * `x` - The horizontal coordinate of the point. + /// * `y` - The vertical coordinate of the point. + /// + /// # Examples + /// + /// ``` + /// use gpui::Point; + /// let p = Point::new(10, 20); + /// assert_eq!(p.x, 10); + /// assert_eq!(p.y, 20); + /// ``` + pub const fn new(x: T, y: T) -> Self { + Self { x, y } + } + + /// Transforms the point to a `Point` by applying the given function to both coordinates. + /// + /// This method allows for converting a `Point` to a `Point` by specifying a closure + /// that defines how to convert between the two types. The closure is applied to both the `x` + /// and `y` coordinates, resulting in a new point of the desired type. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Point; + /// let p = Point { x: 3, y: 4 }; + /// let p_float = p.map(|coord| coord as f32); + /// assert_eq!(p_float, Point { x: 3.0, y: 4.0 }); + /// ``` + #[must_use] + pub fn map(&self, f: impl Fn(T) -> U) -> Point { + Point { + x: f(self.x.clone()), + y: f(self.y.clone()), + } + } +} + +impl Along for Point { + type Unit = T; + + fn along(&self, axis: Axis) -> T { + match axis { + Axis::Horizontal => self.x.clone(), + Axis::Vertical => self.y.clone(), + } + } + + fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Point { + match axis { + Axis::Horizontal => Point { + x: f(self.x.clone()), + y: self.y.clone(), + }, + Axis::Vertical => Point { + x: self.x.clone(), + y: f(self.y.clone()), + }, + } + } +} + +impl Point { + /// Scales the point by a given factor, which is typically derived from the resolution + /// of a target display to ensure proper sizing of UI elements. + /// + /// # Arguments + /// + /// * `factor` - The scaling factor to apply to both the x and y coordinates. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Point, Pixels, ScaledPixels}; + /// let p = Point { x: Pixels::from(10.0), y: Pixels::from(20.0) }; + /// let scaled_p = p.scale(1.5); + /// assert_eq!(scaled_p, Point { x: ScaledPixels::from(15.0), y: ScaledPixels::from(30.0) }); + /// ``` + pub fn scale(&self, factor: f32) -> Point { + Point { + x: self.x.scale(factor), + y: self.y.scale(factor), + } + } + + /// Calculates the Euclidean distance from the origin (0, 0) to this point. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Pixels, Point}; + /// let p = Point { x: Pixels::from(3.0), y: Pixels::from(4.0) }; + /// assert_eq!(p.magnitude(), 5.0); + /// ``` + pub fn magnitude(&self) -> f64 { + ((self.x.0.powi(2) + self.y.0.powi(2)) as f64).sqrt() + } +} + +impl Point +where + T: Sub + Clone + Debug + Default + PartialEq, +{ + /// Get the position of this point, relative to the given origin + pub fn relative_to(&self, origin: &Point) -> Point { + point( + self.x.clone() - origin.x.clone(), + self.y.clone() - origin.y.clone(), + ) + } +} + +impl Mul for Point +where + T: Mul + Clone + Debug + Default + PartialEq, + Rhs: Clone + Debug, +{ + type Output = Point; + + fn mul(self, rhs: Rhs) -> Self::Output { + Point { + x: self.x * rhs.clone(), + y: self.y * rhs, + } + } +} + +impl MulAssign for Point +where + T: Mul + Clone + Debug + Default + PartialEq, + S: Clone, +{ + fn mul_assign(&mut self, rhs: S) { + self.x = self.x.clone() * rhs.clone(); + self.y = self.y.clone() * rhs; + } +} + +impl Div for Point +where + T: Div + Clone + Debug + Default + PartialEq, + S: Clone, +{ + type Output = Self; + + fn div(self, rhs: S) -> Self::Output { + Self { + x: self.x / rhs.clone(), + y: self.y / rhs, + } + } +} + +impl Point +where + T: PartialOrd + Clone + Debug + Default + PartialEq, +{ + /// Returns a new point with the maximum values of each dimension from `self` and `other`. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Point` to compare with `self`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Point; + /// let p1 = Point { x: 3, y: 7 }; + /// let p2 = Point { x: 5, y: 2 }; + /// let max_point = p1.max(&p2); + /// assert_eq!(max_point, Point { x: 5, y: 7 }); + /// ``` + pub fn max(&self, other: &Self) -> Self { + Point { + x: if self.x > other.x { + self.x.clone() + } else { + other.x.clone() + }, + y: if self.y > other.y { + self.y.clone() + } else { + other.y.clone() + }, + } + } + + /// Returns a new point with the minimum values of each dimension from `self` and `other`. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Point` to compare with `self`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Point; + /// let p1 = Point { x: 3, y: 7 }; + /// let p2 = Point { x: 5, y: 2 }; + /// let min_point = p1.min(&p2); + /// assert_eq!(min_point, Point { x: 3, y: 2 }); + /// ``` + pub fn min(&self, other: &Self) -> Self { + Point { + x: if self.x <= other.x { + self.x.clone() + } else { + other.x.clone() + }, + y: if self.y <= other.y { + self.y.clone() + } else { + other.y.clone() + }, + } + } + + /// Clamps the point to a specified range. + /// + /// Given a minimum point and a maximum point, this method constrains the current point + /// such that its coordinates do not exceed the range defined by the minimum and maximum points. + /// If the current point's coordinates are less than the minimum, they are set to the minimum. + /// If they are greater than the maximum, they are set to the maximum. + /// + /// # Arguments + /// + /// * `min` - A reference to a `Point` representing the minimum allowable coordinates. + /// * `max` - A reference to a `Point` representing the maximum allowable coordinates. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Point; + /// let p = Point { x: 10, y: 20 }; + /// let min = Point { x: 0, y: 5 }; + /// let max = Point { x: 15, y: 25 }; + /// let clamped_p = p.clamp(&min, &max); + /// assert_eq!(clamped_p, Point { x: 10, y: 20 }); + /// + /// let p_out_of_bounds = Point { x: -5, y: 30 }; + /// let clamped_p_out_of_bounds = p_out_of_bounds.clamp(&min, &max); + /// assert_eq!(clamped_p_out_of_bounds, Point { x: 0, y: 25 }); + /// ``` + pub fn clamp(&self, min: &Self, max: &Self) -> Self { + self.max(min).min(max) + } +} + +impl Clone for Point { + fn clone(&self) -> Self { + Self { + x: self.x.clone(), + y: self.y.clone(), + } + } +} + +impl Display for Point { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} + +/// A structure representing a two-dimensional size with width and height in a given unit. +/// +/// This struct is generic over the type `T`, which can be any type that implements `Clone`, `Default`, and `Debug`. +/// It is commonly used to specify dimensions for elements in a UI, such as a window or element. +#[derive( + Add, Clone, Copy, Default, Deserialize, Div, Hash, Neg, PartialEq, Refineable, Serialize, Sub, +)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct Size { + /// The width component of the size. + pub width: T, + /// The height component of the size. + pub height: T, +} + +impl Size { + /// Create a new Size, a synonym for [`size`] + pub fn new(width: T, height: T) -> Self { + size(width, height) + } +} + +/// Constructs a new `Size` with the provided width and height. +/// +/// # Arguments +/// +/// * `width` - The width component of the `Size`. +/// * `height` - The height component of the `Size`. +/// +/// # Examples +/// +/// ``` +/// use gpui::size; +/// let my_size = size(10, 20); +/// assert_eq!(my_size.width, 10); +/// assert_eq!(my_size.height, 20); +/// ``` +pub const fn size(width: T, height: T) -> Size +where + T: Clone + Debug + Default + PartialEq, +{ + Size { width, height } +} + +impl Size +where + T: Clone + Debug + Default + PartialEq, +{ + /// Applies a function to the width and height of the size, producing a new `Size`. + /// + /// This method allows for converting a `Size` to a `Size` by specifying a closure + /// that defines how to convert between the two types. The closure is applied to both the `width` + /// and `height`, resulting in a new size of the desired type. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Size; + /// let my_size = Size { width: 10, height: 20 }; + /// let my_new_size = my_size.map(|dimension| dimension as f32 * 1.5); + /// assert_eq!(my_new_size, Size { width: 15.0, height: 30.0 }); + /// ``` + pub fn map(&self, f: impl Fn(T) -> U) -> Size + where + U: Clone + Debug + Default + PartialEq, + { + Size { + width: f(self.width.clone()), + height: f(self.height.clone()), + } + } +} + +impl Size +where + T: Clone + Debug + Default + PartialEq + Half, +{ + /// Compute the center point of the size.g + pub fn center(&self) -> Point { + Point { + x: self.width.half(), + y: self.height.half(), + } + } +} + +impl Size { + /// Scales the size by a given factor. + /// + /// This method multiplies both the width and height by the provided scaling factor, + /// resulting in a new `Size` that is proportionally larger or smaller + /// depending on the factor. + /// + /// # Arguments + /// + /// * `factor` - The scaling factor to apply to the width and height. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Size, Pixels, ScaledPixels}; + /// let size = Size { width: Pixels::from(100.0), height: Pixels::from(50.0) }; + /// let scaled_size = size.scale(2.0); + /// assert_eq!(scaled_size, Size { width: ScaledPixels::from(200.0), height: ScaledPixels::from(100.0) }); + /// ``` + pub fn scale(&self, factor: f32) -> Size { + Size { + width: self.width.scale(factor), + height: self.height.scale(factor), + } + } +} + +impl Along for Size +where + T: Clone + Debug + Default + PartialEq, +{ + type Unit = T; + + fn along(&self, axis: Axis) -> T { + match axis { + Axis::Horizontal => self.width.clone(), + Axis::Vertical => self.height.clone(), + } + } + + /// Returns the value of this size along the given axis. + fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Self { + match axis { + Axis::Horizontal => Size { + width: f(self.width.clone()), + height: self.height.clone(), + }, + Axis::Vertical => Size { + width: self.width.clone(), + height: f(self.height.clone()), + }, + } + } +} + +impl Size +where + T: PartialOrd + Clone + Debug + Default + PartialEq, +{ + /// Returns a new `Size` with the maximum width and height from `self` and `other`. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Size` to compare with `self`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Size; + /// let size1 = Size { width: 30, height: 40 }; + /// let size2 = Size { width: 50, height: 20 }; + /// let max_size = size1.max(&size2); + /// assert_eq!(max_size, Size { width: 50, height: 40 }); + /// ``` + pub fn max(&self, other: &Self) -> Self { + Size { + width: if self.width >= other.width { + self.width.clone() + } else { + other.width.clone() + }, + height: if self.height >= other.height { + self.height.clone() + } else { + other.height.clone() + }, + } + } + + /// Returns a new `Size` with the minimum width and height from `self` and `other`. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Size` to compare with `self`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Size; + /// let size1 = Size { width: 30, height: 40 }; + /// let size2 = Size { width: 50, height: 20 }; + /// let min_size = size1.min(&size2); + /// assert_eq!(min_size, Size { width: 30, height: 20 }); + /// ``` + pub fn min(&self, other: &Self) -> Self { + Size { + width: if self.width >= other.width { + other.width.clone() + } else { + self.width.clone() + }, + height: if self.height >= other.height { + other.height.clone() + } else { + self.height.clone() + }, + } + } +} + +impl Mul for Size +where + T: Mul + Clone + Debug + Default + PartialEq, + Rhs: Clone + Debug + Default + PartialEq, +{ + type Output = Size; + + fn mul(self, rhs: Rhs) -> Self::Output { + Size { + width: self.width * rhs.clone(), + height: self.height * rhs, + } + } +} + +impl MulAssign for Size +where + T: Mul + Clone + Debug + Default + PartialEq, + S: Clone, +{ + fn mul_assign(&mut self, rhs: S) { + self.width = self.width.clone() * rhs.clone(); + self.height = self.height.clone() * rhs; + } +} + +impl Eq for Size where T: Eq + Clone + Debug + Default + PartialEq {} + +impl Debug for Size +where + T: Clone + Debug + Default + PartialEq, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Size {{ {:?} × {:?} }}", self.width, self.height) + } +} + +impl Display for Size { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} × {}", self.width, self.height) + } +} + +impl From> for Size { + fn from(point: Point) -> Self { + Self { + width: point.x, + height: point.y, + } + } +} + +impl From> for Size { + fn from(size: Size) -> Self { + Size { + width: size.width.into(), + height: size.height.into(), + } + } +} + +impl From> for Size { + fn from(size: Size) -> Self { + Size { + width: size.width.into(), + height: size.height.into(), + } + } +} + +impl Size { + /// Returns a `Size` with both width and height set to fill the available space. + /// + /// This function creates a `Size` instance where both the width and height are set to `Length::Definite(DefiniteLength::Fraction(1.0))`, + /// which represents 100% of the available space in both dimensions. + /// + /// # Returns + /// + /// A `Size` that will fill the available space when used in a layout. + pub fn full() -> Self { + Self { + width: relative(1.).into(), + height: relative(1.).into(), + } + } +} + +impl Size { + /// Returns a `Size` with both width and height set to `auto`, which allows the layout engine to determine the size. + /// + /// This function creates a `Size` instance where both the width and height are set to `Length::Auto`, + /// indicating that their size should be computed based on the layout context, such as the content size or + /// available space. + /// + /// # Returns + /// + /// A `Size` with width and height set to `Length::Auto`. + pub fn auto() -> Self { + Self { + width: Length::Auto, + height: Length::Auto, + } + } +} + +/// Represents a rectangular area in a 2D space with an origin point and a size. +/// +/// The `Bounds` struct is generic over a type `T` which represents the type of the coordinate system. +/// The origin is represented as a `Point` which defines the top left corner of the rectangle, +/// and the size is represented as a `Size` which defines the width and height of the rectangle. +/// +/// # Examples +/// +/// ``` +/// # use gpui::{Bounds, Point, Size}; +/// let origin = Point { x: 0, y: 0 }; +/// let size = Size { width: 10, height: 20 }; +/// let bounds = Bounds::new(origin, size); +/// +/// assert_eq!(bounds.origin, origin); +/// assert_eq!(bounds.size, size); +/// ``` +#[derive(Refineable, Copy, Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[refineable(Debug)] +#[repr(C)] +pub struct Bounds { + /// The origin point of this area. + pub origin: Point, + /// The size of the rectangle. + pub size: Size, +} + +/// Create a bounds with the given origin and size +pub fn bounds( + origin: Point, + size: Size, +) -> Bounds { + Bounds { origin, size } +} + +impl Bounds { + /// Generate a centered bounds for the given display or primary display if none is provided + pub fn centered(display_id: Option, size: Size, cx: &App) -> Self { + let display = display_id + .and_then(|id| cx.find_display(id)) + .or_else(|| cx.primary_display()); + + display + .map(|display| { + let visible_bounds = display.visible_bounds(); + Bounds::centered_at(visible_bounds.center(), size.min(&visible_bounds.size)) + }) + .unwrap_or_else(|| Bounds { + origin: point(px(0.), px(0.)), + size, + }) + } + + /// Generate maximized bounds for the given display or primary display if none is provided + pub fn maximized(display_id: Option, cx: &App) -> Self { + let display = display_id + .and_then(|id| cx.find_display(id)) + .or_else(|| cx.primary_display()); + + display + .map(|display| display.bounds()) + .unwrap_or_else(|| Bounds { + origin: point(px(0.), px(0.)), + size: size(px(1024.), px(768.)), + }) + } +} + +impl Bounds +where + T: Clone + Debug + Default + PartialEq, +{ + /// Creates a new `Bounds` with the specified origin and size. + /// + /// # Arguments + /// + /// * `origin` - A `Point` representing the origin of the bounds. + /// * `size` - A `Size` representing the size of the bounds. + /// + /// # Returns + /// + /// Returns a `Bounds` that has the given origin and size. + pub fn new(origin: Point, size: Size) -> Self { + Bounds { origin, size } + } +} + +impl Bounds +where + T: Sub + Clone + Debug + Default + PartialEq, +{ + /// Constructs a `Bounds` from two corner points: the top left and bottom right corners. + /// + /// This function calculates the origin and size of the `Bounds` based on the provided corner points. + /// The origin is set to the top left corner, and the size is determined by the difference between + /// the x and y coordinates of the bottom right and top left points. + /// + /// # Arguments + /// + /// * `top_left` - A `Point` representing the top left corner of the rectangle. + /// * `bottom_right` - A `Point` representing the bottom right corner of the rectangle. + /// + /// # Returns + /// + /// Returns a `Bounds` that encompasses the area defined by the two corner points. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point}; + /// let top_left = Point { x: 0, y: 0 }; + /// let bottom_right = Point { x: 10, y: 10 }; + /// let bounds = Bounds::from_corners(top_left, bottom_right); + /// + /// assert_eq!(bounds.origin, top_left); + /// assert_eq!(bounds.size.width, 10); + /// assert_eq!(bounds.size.height, 10); + /// ``` + pub fn from_corners(top_left: Point, bottom_right: Point) -> Self { + let origin = Point { + x: top_left.x.clone(), + y: top_left.y.clone(), + }; + let size = Size { + width: bottom_right.x - top_left.x, + height: bottom_right.y - top_left.y, + }; + Bounds { origin, size } + } +} + +impl Bounds +where + T: Sub + Half + Clone + Debug + Default + PartialEq, +{ + /// Constructs a `Bounds` from a corner point and size. The specified corner will be placed at + /// the specified origin. + pub fn from_anchor_and_size(corner: Anchor, origin: Point, size: Size) -> Bounds { + let origin = match corner { + Anchor::TopLeft => origin, + Anchor::TopRight => Point { + x: origin.x - size.width.clone(), + y: origin.y, + }, + Anchor::BottomLeft => Point { + x: origin.x, + y: origin.y - size.height.clone(), + }, + Anchor::BottomRight => Point { + x: origin.x - size.width.clone(), + y: origin.y - size.height.clone(), + }, + Anchor::TopCenter => Point { + x: origin.x - size.width.half(), + y: origin.y, + }, + Anchor::BottomCenter => Point { + x: origin.x - size.width.half(), + y: origin.y - size.height.clone(), + }, + Anchor::LeftCenter => Point { + x: origin.x, + y: origin.y - size.height.half(), + }, + Anchor::RightCenter => Point { + x: origin.x - size.width.clone(), + y: origin.y - size.height.half(), + }, + }; + + Bounds { origin, size } + } +} + +impl Bounds +where + T: Sub + Half + Clone + Debug + Default + PartialEq, +{ + /// Creates a new bounds centered at the given point. + pub fn centered_at(center: Point, size: Size) -> Self { + let origin = Point { + x: center.x - size.width.half(), + y: center.y - size.height.half(), + }; + Self::new(origin, size) + } +} + +impl Bounds +where + T: Add + Half + Clone + Debug + Default + PartialEq, +{ + /// Returns the top center point of the bounds. + pub fn top_center(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.half(), + y: self.origin.y.clone(), + } + } + + /// Returns the bottom center point of the bounds. + pub fn bottom_center(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.half(), + y: self.origin.y.clone() + self.size.height.clone(), + } + } + + /// Returns the left center point of the bounds. + pub fn left_center(&self) -> Point { + Point { + x: self.origin.x.clone(), + y: self.origin.y.clone() + self.size.height.half(), + } + } + + /// Returns the right center point of the bounds. + pub fn right_center(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.clone(), + y: self.origin.y.clone() + self.size.height.half(), + } + } +} + +impl Bounds +where + T: PartialOrd + Add + Clone + Debug + Default + PartialEq, +{ + /// Checks if this `Bounds` intersects with another `Bounds`. + /// + /// Two `Bounds` instances intersect if they overlap in the 2D space they occupy. + /// This method checks if there is any overlapping area between the two bounds. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Bounds` to check for intersection with. + /// + /// # Returns + /// + /// Returns `true` if there is any intersection between the two bounds, `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds1 = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let bounds2 = Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let bounds3 = Bounds { + /// origin: Point { x: 20, y: 20 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// + /// assert_eq!(bounds1.intersects(&bounds2), true); // Overlapping bounds + /// assert_eq!(bounds1.intersects(&bounds3), false); // Non-overlapping bounds + /// ``` + pub fn intersects(&self, other: &Bounds) -> bool { + let my_lower_right = self.bottom_right(); + let their_lower_right = other.bottom_right(); + + self.origin.x < their_lower_right.x + && my_lower_right.x > other.origin.x + && self.origin.y < their_lower_right.y + && my_lower_right.y > other.origin.y + } +} + +impl Bounds +where + T: Add + Half + Clone + Debug + Default + PartialEq, +{ + /// Returns the center point of the bounds. + /// + /// Calculates the center by taking the origin's x and y coordinates and adding half the width and height + /// of the bounds, respectively. The center is represented as a `Point` where `T` is the type of the + /// coordinate system. + /// + /// # Returns + /// + /// A `Point` representing the center of the bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let center = bounds.center(); + /// assert_eq!(center, Point { x: 5, y: 10 }); + /// ``` + pub fn center(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.clone().half(), + y: self.origin.y.clone() + self.size.height.clone().half(), + } + } +} + +impl Bounds +where + T: Add + Clone + Debug + Default + PartialEq, +{ + /// Calculates the half perimeter of a rectangle defined by the bounds. + /// + /// The half perimeter is calculated as the sum of the width and the height of the rectangle. + /// This method is generic over the type `T` which must implement the `Sub` trait to allow + /// calculation of the width and height from the bounds' origin and size, as well as the `Add` trait + /// to sum the width and height for the half perimeter. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let half_perimeter = bounds.half_perimeter(); + /// assert_eq!(half_perimeter, 30); + /// ``` + pub fn half_perimeter(&self) -> T { + self.size.width.clone() + self.size.height.clone() + } +} + +impl Bounds +where + T: Add + Sub + Clone + Debug + Default + PartialEq, +{ + /// Dilates the bounds by a specified amount in all directions. + /// + /// This method expands the bounds by the given `amount`, increasing the size + /// and adjusting the origin so that the bounds grow outwards equally in all directions. + /// The resulting bounds will have its width and height increased by twice the `amount` + /// (since it grows in both directions), and the origin will be moved by `-amount` + /// in both the x and y directions. + /// + /// # Arguments + /// + /// * `amount` - The amount by which to dilate the bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let mut bounds = Bounds { + /// origin: Point { x: 10, y: 10 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let expanded_bounds = bounds.dilate(5); + /// assert_eq!(expanded_bounds, Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 20, height: 20 }, + /// }); + /// ``` + #[must_use] + pub fn dilate(&self, amount: T) -> Bounds { + let double_amount = amount.clone() + amount.clone(); + Bounds { + origin: self.origin.clone() - point(amount.clone(), amount), + size: self.size.clone() + size(double_amount.clone(), double_amount), + } + } + + /// Extends the bounds different amounts in each direction. + #[must_use] + pub fn extend(&self, amount: Edges) -> Bounds { + Bounds { + origin: self.origin.clone() - point(amount.left.clone(), amount.top.clone()), + size: self.size.clone() + + size( + amount.left.clone() + amount.right.clone(), + amount.top.clone() + amount.bottom, + ), + } + } +} + +impl Bounds +where + T: Add + + Sub + + Neg + + Clone + + Debug + + Default + + PartialEq, +{ + /// Inset the bounds by a specified amount. Equivalent to `dilate` with the amount negated. + /// + /// Note that this may panic if T does not support negative values. + pub fn inset(&self, amount: T) -> Self { + self.dilate(-amount) + } +} + +impl + Sub + Clone + Debug + Default + PartialEq> + Bounds +{ + /// Calculates the intersection of two `Bounds` objects. + /// + /// This method computes the overlapping region of two `Bounds`. If the bounds do not intersect, + /// the resulting `Bounds` will have a size with width and height of zero. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Bounds` to intersect with. + /// + /// # Returns + /// + /// Returns a `Bounds` representing the intersection area. If there is no intersection, + /// the returned `Bounds` will have a size with width and height of zero. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds1 = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let bounds2 = Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let intersection = bounds1.intersect(&bounds2); + /// + /// assert_eq!(intersection, Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 5, height: 5 }, + /// }); + /// ``` + pub fn intersect(&self, other: &Self) -> Self { + let upper_left = self.origin.max(&other.origin); + let bottom_right = self + .bottom_right() + .min(&other.bottom_right()) + .max(&upper_left); + Self::from_corners(upper_left, bottom_right) + } + + /// Computes the union of two `Bounds`. + /// + /// This method calculates the smallest `Bounds` that contains both the current `Bounds` and the `other` `Bounds`. + /// The resulting `Bounds` will have an origin that is the minimum of the origins of the two `Bounds`, + /// and a size that encompasses the furthest extents of both `Bounds`. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Bounds` to create a union with. + /// + /// # Returns + /// + /// Returns a `Bounds` representing the union of the two `Bounds`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds1 = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let bounds2 = Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 15, height: 15 }, + /// }; + /// let union_bounds = bounds1.union(&bounds2); + /// + /// assert_eq!(union_bounds, Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 20, height: 20 }, + /// }); + /// ``` + pub fn union(&self, other: &Self) -> Self { + let top_left = self.origin.min(&other.origin); + let bottom_right = self.bottom_right().max(&other.bottom_right()); + Bounds::from_corners(top_left, bottom_right) + } +} + +impl Bounds +where + T: Add + Sub + Clone + Debug + Default + PartialEq, +{ + /// Computes the space available within outer bounds. + pub fn space_within(&self, outer: &Self) -> Edges { + Edges { + top: self.top() - outer.top(), + right: outer.right() - self.right(), + bottom: outer.bottom() - self.bottom(), + left: self.left() - outer.left(), + } + } +} + +impl Mul for Bounds +where + T: Mul + Clone + Debug + Default + PartialEq, + Point: Mul>, + Rhs: Clone + Debug + Default + PartialEq, +{ + type Output = Bounds; + + fn mul(self, rhs: Rhs) -> Self::Output { + Bounds { + origin: self.origin * rhs.clone(), + size: self.size * rhs, + } + } +} + +impl MulAssign for Bounds +where + T: Mul + Clone + Debug + Default + PartialEq, + S: Clone, +{ + fn mul_assign(&mut self, rhs: S) { + self.origin *= rhs.clone(); + self.size *= rhs; + } +} + +impl Div for Bounds +where + Size: Div>, + T: Div + Clone + Debug + Default + PartialEq, + S: Clone, +{ + type Output = Self; + + fn div(self, rhs: S) -> Self { + Self { + origin: self.origin / rhs.clone(), + size: self.size / rhs, + } + } +} + +impl Add> for Bounds +where + T: Add + Clone + Debug + Default + PartialEq, +{ + type Output = Self; + + fn add(self, rhs: Point) -> Self { + Self { + origin: self.origin + rhs, + size: self.size, + } + } +} + +impl Sub> for Bounds +where + T: Sub + Clone + Debug + Default + PartialEq, +{ + type Output = Self; + + fn sub(self, rhs: Point) -> Self { + Self { + origin: self.origin - rhs, + size: self.size, + } + } +} + +impl From> for Point { + fn from(size: Size) -> Self { + Self { + x: size.width, + y: size.height, + } + } +} + +impl Bounds +where + T: Add + Clone + Debug + Default + PartialEq, +{ + /// Returns the top edge of the bounds. + /// + /// # Returns + /// + /// A value of type `T` representing the y-coordinate of the top edge of the bounds. + pub fn top(&self) -> T { + self.origin.y.clone() + } + + /// Returns the bottom edge of the bounds. + /// + /// # Returns + /// + /// A value of type `T` representing the y-coordinate of the bottom edge of the bounds. + pub fn bottom(&self) -> T { + self.origin.y.clone() + self.size.height.clone() + } + + /// Returns the left edge of the bounds. + /// + /// # Returns + /// + /// A value of type `T` representing the x-coordinate of the left edge of the bounds. + pub fn left(&self) -> T { + self.origin.x.clone() + } + + /// Returns the right edge of the bounds. + /// + /// # Returns + /// + /// A value of type `T` representing the x-coordinate of the right edge of the bounds. + pub fn right(&self) -> T { + self.origin.x.clone() + self.size.width.clone() + } + + /// Returns the top right corner point of the bounds. + /// + /// # Returns + /// + /// A `Point` representing the top right corner of the bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let top_right = bounds.top_right(); + /// assert_eq!(top_right, Point { x: 10, y: 0 }); + /// ``` + pub fn top_right(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.clone(), + y: self.origin.y.clone(), + } + } + + /// Returns the bottom right corner point of the bounds. + /// + /// # Returns + /// + /// A `Point` representing the bottom right corner of the bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let bottom_right = bounds.bottom_right(); + /// assert_eq!(bottom_right, Point { x: 10, y: 20 }); + /// ``` + pub fn bottom_right(&self) -> Point { + Point { + x: self.origin.x.clone() + self.size.width.clone(), + y: self.origin.y.clone() + self.size.height.clone(), + } + } + + /// Returns the bottom left corner point of the bounds. + /// + /// # Returns + /// + /// A `Point` representing the bottom left corner of the bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let bottom_left = bounds.bottom_left(); + /// assert_eq!(bottom_left, Point { x: 0, y: 20 }); + /// ``` + pub fn bottom_left(&self) -> Point { + Point { + x: self.origin.x.clone(), + y: self.origin.y.clone() + self.size.height.clone(), + } + } +} + +impl Bounds +where + T: Add + Half + Clone + Debug + Default + PartialEq, +{ + /// Returns the requested corner point of the bounds. + /// + /// # Returns + /// + /// A `Point` representing the corner of the bounds requested by the parameter. + /// + /// # Examples + /// + /// ``` + /// use gpui::{Bounds, Anchor, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 20 }, + /// }; + /// let bottom_left = bounds.corner(Anchor::BottomLeft); + /// assert_eq!(bottom_left, Point { x: 0, y: 20 }); + /// ``` + pub fn corner(&self, corner: Anchor) -> Point { + match corner { + Anchor::TopLeft => self.origin.clone(), + Anchor::TopRight => self.top_right(), + Anchor::BottomLeft => self.bottom_left(), + Anchor::BottomRight => self.bottom_right(), + Anchor::TopCenter => self.top_center(), + Anchor::BottomCenter => self.bottom_center(), + Anchor::LeftCenter => self.left_center(), + Anchor::RightCenter => self.right_center(), + } + } +} + +impl Bounds +where + T: Add + PartialOrd + Clone + Debug + Default + PartialEq, +{ + /// Checks if the given point is within the bounds. + /// + /// This method determines whether a point lies inside the rectangle defined by the bounds, + /// including the edges. The point is considered inside if its x-coordinate is greater than + /// or equal to the left edge and less than or equal to the right edge, and its y-coordinate + /// is greater than or equal to the top edge and less than or equal to the bottom edge of the bounds. + /// + /// # Arguments + /// + /// * `point` - A reference to a `Point` that represents the point to check. + /// + /// # Returns + /// + /// Returns `true` if the point is within the bounds, `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Point, Bounds, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let inside_point = Point { x: 5, y: 5 }; + /// let outside_point = Point { x: 15, y: 15 }; + /// + /// assert!(bounds.contains(&inside_point)); + /// assert!(!bounds.contains(&outside_point)); + /// ``` + pub fn contains(&self, point: &Point) -> bool { + point.x >= self.origin.x + && point.x < self.origin.x.clone() + self.size.width.clone() + && point.y >= self.origin.y + && point.y < self.origin.y.clone() + self.size.height.clone() + } + + /// Checks if this bounds is completely contained within another bounds. + /// + /// This method determines whether the current bounds is entirely enclosed by the given bounds. + /// A bounds is considered to be contained within another if its origin (top-left corner) and + /// its bottom-right corner are both contained within the other bounds. + /// + /// # Arguments + /// + /// * `other` - A reference to another `Bounds` that might contain this bounds. + /// + /// # Returns + /// + /// Returns `true` if this bounds is completely inside the other bounds, `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let outer_bounds = Bounds { + /// origin: Point { x: 0, y: 0 }, + /// size: Size { width: 20, height: 20 }, + /// }; + /// let inner_bounds = Bounds { + /// origin: Point { x: 5, y: 5 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// let overlapping_bounds = Bounds { + /// origin: Point { x: 15, y: 15 }, + /// size: Size { width: 10, height: 10 }, + /// }; + /// + /// assert!(inner_bounds.is_contained_within(&outer_bounds)); + /// assert!(!overlapping_bounds.is_contained_within(&outer_bounds)); + /// ``` + pub fn is_contained_within(&self, other: &Self) -> bool { + other.contains(&self.origin) && other.contains(&self.bottom_right()) + } + + /// Applies a function to the origin and size of the bounds, producing a new `Bounds`. + /// + /// This method allows for converting a `Bounds` to a `Bounds` by specifying a closure + /// that defines how to convert between the two types. The closure is applied to the `origin` and + /// `size` fields, resulting in new bounds of the desired type. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`. + /// + /// # Returns + /// + /// Returns a new `Bounds` with the origin and size mapped by the provided function. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 10.0, y: 10.0 }, + /// size: Size { width: 10.0, height: 20.0 }, + /// }; + /// let new_bounds = bounds.map(|value| value as f64 * 1.5); + /// + /// assert_eq!(new_bounds, Bounds { + /// origin: Point { x: 15.0, y: 15.0 }, + /// size: Size { width: 15.0, height: 30.0 }, + /// }); + /// ``` + pub fn map(&self, f: impl Fn(T) -> U) -> Bounds + where + U: Clone + Debug + Default + PartialEq, + { + Bounds { + origin: self.origin.map(&f), + size: self.size.map(f), + } + } + + /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 10.0, y: 10.0 }, + /// size: Size { width: 10.0, height: 20.0 }, + /// }; + /// let new_bounds = bounds.map_origin(|value| value * 1.5); + /// + /// assert_eq!(new_bounds, Bounds { + /// origin: Point { x: 15.0, y: 15.0 }, + /// size: Size { width: 10.0, height: 20.0 }, + /// }); + /// ``` + pub fn map_origin(self, f: impl Fn(T) -> T) -> Bounds { + Bounds { + origin: self.origin.map(f), + size: self.size, + } + } + + /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size}; + /// let bounds = Bounds { + /// origin: Point { x: 10.0, y: 10.0 }, + /// size: Size { width: 10.0, height: 20.0 }, + /// }; + /// let new_bounds = bounds.map_size(|value| value * 1.5); + /// + /// assert_eq!(new_bounds, Bounds { + /// origin: Point { x: 10.0, y: 10.0 }, + /// size: Size { width: 15.0, height: 30.0 }, + /// }); + /// ``` + pub fn map_size(self, f: impl Fn(T) -> T) -> Bounds { + Bounds { + origin: self.origin, + size: self.size.map(f), + } + } +} + +impl Bounds +where + T: Add + Sub + PartialOrd + Clone + Debug + Default + PartialEq, +{ + /// Convert a point to the coordinate space defined by this Bounds + pub fn localize(&self, point: &Point) -> Option> { + self.contains(point) + .then(|| point.relative_to(&self.origin)) + } +} + +/// Checks if the bounds represent an empty area. +/// +/// # Returns +/// +/// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area. +impl Bounds { + /// Checks if the bounds represent an empty area. + /// + /// # Returns + /// + /// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area. + #[must_use] + pub fn is_empty(&self) -> bool { + self.size.width <= T::default() || self.size.height <= T::default() + } +} + +impl> Display for Bounds { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{} - {} (size {})", + self.origin, + self.bottom_right(), + self.size + ) + } +} + +impl Size { + /// Converts the size from physical to logical pixels. + pub fn to_pixels(self, scale_factor: f32) -> Size { + size( + px(self.width.0 as f32 / scale_factor), + px(self.height.0 as f32 / scale_factor), + ) + } +} + +impl Size { + /// Converts the size from logical to physical pixels. + pub fn to_device_pixels(self, scale_factor: f32) -> Size { + size( + DevicePixels((self.width.0 * scale_factor).round() as i32), + DevicePixels((self.height.0 * scale_factor).round() as i32), + ) + } +} + +impl Bounds { + /// Scales the bounds by a given factor, typically used to adjust for display scaling. + /// + /// This method multiplies the origin and size of the bounds by the provided scaling factor, + /// resulting in a new `Bounds` that is proportionally larger or smaller + /// depending on the scaling factor. This can be used to ensure that the bounds are properly + /// scaled for different display densities. + /// + /// # Arguments + /// + /// * `factor` - The scaling factor to apply to the origin and size, typically the display's scaling factor. + /// + /// # Returns + /// + /// Returns a new `Bounds` that represents the scaled bounds. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Bounds, Point, Size, Pixels, ScaledPixels, DevicePixels}; + /// let bounds = Bounds { + /// origin: Point { x: Pixels::from(10.0), y: Pixels::from(20.0) }, + /// size: Size { width: Pixels::from(30.0), height: Pixels::from(40.0) }, + /// }; + /// let display_scale_factor = 2.0; + /// let scaled_bounds = bounds.scale(display_scale_factor); + /// assert_eq!(scaled_bounds, Bounds { + /// origin: Point { + /// x: ScaledPixels::from(20.0), + /// y: ScaledPixels::from(40.0), + /// }, + /// size: Size { + /// width: ScaledPixels::from(60.0), + /// height: ScaledPixels::from(80.0) + /// }, + /// }); + /// ``` + pub fn scale(&self, factor: f32) -> Bounds { + Bounds { + origin: self.origin.scale(factor), + size: self.size.scale(factor), + } + } + + /// Convert the bounds from logical pixels to physical pixels + pub fn to_device_pixels(self, factor: f32) -> Bounds { + Bounds { + origin: point( + DevicePixels((self.origin.x.0 * factor).round() as i32), + DevicePixels((self.origin.y.0 * factor).round() as i32), + ), + size: self.size.to_device_pixels(factor), + } + } +} + +impl Bounds { + /// Convert the bounds from physical pixels to logical pixels + pub fn to_pixels(self, scale_factor: f32) -> Bounds { + Bounds { + origin: point( + px(self.origin.x.0 as f32 / scale_factor), + px(self.origin.y.0 as f32 / scale_factor), + ), + size: self.size.to_pixels(scale_factor), + } + } +} + +/// Represents the edges of a box in a 2D space, such as padding or margin. +/// +/// Each field represents the size of the edge on one side of the box: `top`, `right`, `bottom`, and `left`. +/// +/// # Examples +/// +/// ``` +/// # use gpui::Edges; +/// let edges = Edges { +/// top: 10.0, +/// right: 20.0, +/// bottom: 30.0, +/// left: 40.0, +/// }; +/// +/// assert_eq!(edges.top, 10.0); +/// assert_eq!(edges.right, 20.0); +/// assert_eq!(edges.bottom, 30.0); +/// assert_eq!(edges.left, 40.0); +/// ``` +#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct Edges { + /// The size of the top edge. + pub top: T, + /// The size of the right edge. + pub right: T, + /// The size of the bottom edge. + pub bottom: T, + /// The size of the left edge. + pub left: T, +} + +impl Mul for Edges +where + T: Mul + Clone + Debug + Default + PartialEq, +{ + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + Self { + top: self.top.clone() * rhs.top, + right: self.right.clone() * rhs.right, + bottom: self.bottom.clone() * rhs.bottom, + left: self.left * rhs.left, + } + } +} + +impl MulAssign for Edges +where + T: Mul + Clone + Debug + Default + PartialEq, + S: Clone, +{ + fn mul_assign(&mut self, rhs: S) { + self.top = self.top.clone() * rhs.clone(); + self.right = self.right.clone() * rhs.clone(); + self.bottom = self.bottom.clone() * rhs.clone(); + self.left = self.left.clone() * rhs; + } +} + +impl Copy for Edges {} + +impl Edges { + /// Constructs `Edges` where all sides are set to the same specified value. + /// + /// This function creates an `Edges` instance with the `top`, `right`, `bottom`, and `left` fields all initialized + /// to the same value provided as an argument. This is useful when you want to have uniform edges around a box, + /// such as padding or margin with the same size on all sides. + /// + /// # Arguments + /// + /// * `value` - The value to set for all four sides of the edges. + /// + /// # Returns + /// + /// An `Edges` instance with all sides set to the given value. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Edges; + /// let uniform_edges = Edges::all(10.0); + /// assert_eq!(uniform_edges.top, 10.0); + /// assert_eq!(uniform_edges.right, 10.0); + /// assert_eq!(uniform_edges.bottom, 10.0); + /// assert_eq!(uniform_edges.left, 10.0); + /// ``` + pub fn all(value: T) -> Self { + Self { + top: value.clone(), + right: value.clone(), + bottom: value.clone(), + left: value, + } + } + + /// Applies a function to each field of the `Edges`, producing a new `Edges`. + /// + /// This method allows for converting an `Edges` to an `Edges` by specifying a closure + /// that defines how to convert between the two types. The closure is applied to each field + /// (`top`, `right`, `bottom`, `left`), resulting in new edges of the desired type. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`. + /// + /// # Returns + /// + /// Returns a new `Edges` with each field mapped by the provided function. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Edges; + /// let edges = Edges { top: 10, right: 20, bottom: 30, left: 40 }; + /// let edges_float = edges.map(|&value| value as f32 * 1.1); + /// assert_eq!(edges_float, Edges { top: 11.0, right: 22.0, bottom: 33.0, left: 44.0 }); + /// ``` + pub fn map(&self, f: impl Fn(&T) -> U) -> Edges + where + U: Clone + Debug + Default + PartialEq, + { + Edges { + top: f(&self.top), + right: f(&self.right), + bottom: f(&self.bottom), + left: f(&self.left), + } + } + + /// Checks if any of the edges satisfy a given predicate. + /// + /// This method applies a predicate function to each field of the `Edges` and returns `true` if any field satisfies the predicate. + /// + /// # Arguments + /// + /// * `predicate` - A closure that takes a reference to a value of type `T` and returns a `bool`. + /// + /// # Returns + /// + /// Returns `true` if the predicate returns `true` for any of the edge values, `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Edges; + /// let edges = Edges { + /// top: 10, + /// right: 0, + /// bottom: 5, + /// left: 0, + /// }; + /// + /// assert!(edges.any(|value| *value == 0)); + /// assert!(edges.any(|value| *value > 0)); + /// assert!(!edges.any(|value| *value > 10)); + /// ``` + pub fn any bool>(&self, predicate: F) -> bool { + predicate(&self.top) + || predicate(&self.right) + || predicate(&self.bottom) + || predicate(&self.left) + } +} + +impl Edges { + /// Sets the edges of the `Edges` struct to `auto`, which is a special value that allows the layout engine to automatically determine the size of the edges. + /// + /// This is typically used in layout contexts where the exact size of the edges is not important, or when the size should be calculated based on the content or container. + /// + /// # Returns + /// + /// Returns an `Edges` with all edges set to `Length::Auto`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Edges, Length}; + /// let auto_edges = Edges::auto(); + /// assert_eq!(auto_edges.top, Length::Auto); + /// assert_eq!(auto_edges.right, Length::Auto); + /// assert_eq!(auto_edges.bottom, Length::Auto); + /// assert_eq!(auto_edges.left, Length::Auto); + /// ``` + pub fn auto() -> Self { + Self { + top: Length::Auto, + right: Length::Auto, + bottom: Length::Auto, + left: Length::Auto, + } + } + + /// Sets the edges of the `Edges` struct to zero, which means no size or thickness. + /// + /// This is typically used when you want to specify that a box (like a padding or margin area) + /// should have no edges, effectively making it non-existent or invisible in layout calculations. + /// + /// # Returns + /// + /// Returns an `Edges` with all edges set to zero length. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{DefiniteLength, Edges, Length, Pixels}; + /// let no_edges = Edges::::zero(); + /// assert_eq!(no_edges.top, Length::Definite(DefiniteLength::from(Pixels::ZERO))); + /// assert_eq!(no_edges.right, Length::Definite(DefiniteLength::from(Pixels::ZERO))); + /// assert_eq!(no_edges.bottom, Length::Definite(DefiniteLength::from(Pixels::ZERO))); + /// assert_eq!(no_edges.left, Length::Definite(DefiniteLength::from(Pixels::ZERO))); + /// ``` + pub fn zero() -> Self { + Self { + top: px(0.).into(), + right: px(0.).into(), + bottom: px(0.).into(), + left: px(0.).into(), + } + } +} + +impl Edges { + /// Sets the edges of the `Edges` struct to zero, which means no size or thickness. + /// + /// This is typically used when you want to specify that a box (like a padding or margin area) + /// should have no edges, effectively making it non-existent or invisible in layout calculations. + /// + /// # Returns + /// + /// Returns an `Edges` with all edges set to zero length. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{px, DefiniteLength, Edges}; + /// let no_edges = Edges::::zero(); + /// assert_eq!(no_edges.top, DefiniteLength::from(px(0.))); + /// assert_eq!(no_edges.right, DefiniteLength::from(px(0.))); + /// assert_eq!(no_edges.bottom, DefiniteLength::from(px(0.))); + /// assert_eq!(no_edges.left, DefiniteLength::from(px(0.))); + /// ``` + pub fn zero() -> Self { + Self { + top: px(0.).into(), + right: px(0.).into(), + bottom: px(0.).into(), + left: px(0.).into(), + } + } + + /// Converts the `DefiniteLength` to `Pixels` based on the parent size and the REM size. + /// + /// This method allows for a `DefiniteLength` value to be converted into pixels, taking into account + /// the size of the parent element (for percentage-based lengths) and the size of a rem unit (for rem-based lengths). + /// + /// # Arguments + /// + /// * `parent_size` - `Size` representing the size of the parent element. + /// * `rem_size` - `Pixels` representing the size of one REM unit. + /// + /// # Returns + /// + /// Returns an `Edges` representing the edges with lengths converted to pixels. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Edges, DefiniteLength, px, AbsoluteLength, rems, Size}; + /// let edges = Edges { + /// top: DefiniteLength::Absolute(AbsoluteLength::Pixels(px(10.0))), + /// right: DefiniteLength::Fraction(0.5), + /// bottom: DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0))), + /// left: DefiniteLength::Fraction(0.25), + /// }; + /// let parent_size = Size { + /// width: AbsoluteLength::Pixels(px(200.0)), + /// height: AbsoluteLength::Pixels(px(100.0)), + /// }; + /// let rem_size = px(16.0); + /// let edges_in_pixels = edges.to_pixels(parent_size, rem_size); + /// + /// assert_eq!(edges_in_pixels.top, px(10.0)); // Absolute length in pixels + /// assert_eq!(edges_in_pixels.right, px(100.0)); // 50% of parent width + /// assert_eq!(edges_in_pixels.bottom, px(32.0)); // 2 rems + /// assert_eq!(edges_in_pixels.left, px(50.0)); // 25% of parent width + /// ``` + pub fn to_pixels(self, parent_size: Size, rem_size: Pixels) -> Edges { + Edges { + top: self.top.to_pixels(parent_size.height, rem_size), + right: self.right.to_pixels(parent_size.width, rem_size), + bottom: self.bottom.to_pixels(parent_size.height, rem_size), + left: self.left.to_pixels(parent_size.width, rem_size), + } + } +} + +impl Edges { + /// Sets the edges of the `Edges` struct to zero, which means no size or thickness. + /// + /// This is typically used when you want to specify that a box (like a padding or margin area) + /// should have no edges, effectively making it non-existent or invisible in layout calculations. + /// + /// # Returns + /// + /// Returns an `Edges` with all edges set to zero length. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{AbsoluteLength, Edges, Pixels}; + /// let no_edges = Edges::::zero(); + /// assert_eq!(no_edges.top, AbsoluteLength::Pixels(Pixels::ZERO)); + /// assert_eq!(no_edges.right, AbsoluteLength::Pixels(Pixels::ZERO)); + /// assert_eq!(no_edges.bottom, AbsoluteLength::Pixels(Pixels::ZERO)); + /// assert_eq!(no_edges.left, AbsoluteLength::Pixels(Pixels::ZERO)); + /// ``` + pub fn zero() -> Self { + Self { + top: px(0.).into(), + right: px(0.).into(), + bottom: px(0.).into(), + left: px(0.).into(), + } + } + + /// Converts the `AbsoluteLength` to `Pixels` based on the `rem_size`. + /// + /// If the `AbsoluteLength` is already in pixels, it simply returns the corresponding `Pixels` value. + /// If the `AbsoluteLength` is in rems, it multiplies the number of rems by the `rem_size` to convert it to pixels. + /// + /// # Arguments + /// + /// * `rem_size` - The size of one rem unit in pixels. + /// + /// # Returns + /// + /// Returns an `Edges` representing the edges with lengths converted to pixels. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Edges, AbsoluteLength, Pixels, px, rems}; + /// let edges = Edges { + /// top: AbsoluteLength::Pixels(px(10.0)), + /// right: AbsoluteLength::Rems(rems(1.0)), + /// bottom: AbsoluteLength::Pixels(px(20.0)), + /// left: AbsoluteLength::Rems(rems(2.0)), + /// }; + /// let rem_size = px(16.0); + /// let edges_in_pixels = edges.to_pixels(rem_size); + /// + /// assert_eq!(edges_in_pixels.top, px(10.0)); // Already in pixels + /// assert_eq!(edges_in_pixels.right, px(16.0)); // 1 rem converted to pixels + /// assert_eq!(edges_in_pixels.bottom, px(20.0)); // Already in pixels + /// assert_eq!(edges_in_pixels.left, px(32.0)); // 2 rems converted to pixels + /// ``` + pub fn to_pixels(self, rem_size: Pixels) -> Edges { + Edges { + top: self.top.to_pixels(rem_size), + right: self.right.to_pixels(rem_size), + bottom: self.bottom.to_pixels(rem_size), + left: self.left.to_pixels(rem_size), + } + } +} + +impl Edges { + /// Scales the `Edges` by a given factor, returning `Edges`. + /// + /// This method is typically used for adjusting the edge sizes for different display densities or scaling factors. + /// + /// # Arguments + /// + /// * `factor` - The scaling factor to apply to each edge. + /// + /// # Returns + /// + /// Returns a new `Edges` where each edge is the result of scaling the original edge by the given factor. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Edges, Pixels, ScaledPixels}; + /// let edges = Edges { + /// top: Pixels::from(10.0), + /// right: Pixels::from(20.0), + /// bottom: Pixels::from(30.0), + /// left: Pixels::from(40.0), + /// }; + /// let scaled_edges = edges.scale(2.0); + /// assert_eq!(scaled_edges.top, ScaledPixels::from(20.0)); + /// assert_eq!(scaled_edges.right, ScaledPixels::from(40.0)); + /// assert_eq!(scaled_edges.bottom, ScaledPixels::from(60.0)); + /// assert_eq!(scaled_edges.left, ScaledPixels::from(80.0)); + /// ``` + pub fn scale(&self, factor: f32) -> Edges { + Edges { + top: self.top.scale(factor), + right: self.right.scale(factor), + bottom: self.bottom.scale(factor), + left: self.left.scale(factor), + } + } + + /// Returns the maximum value of any edge. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four edges. + pub fn max(&self) -> Pixels { + self.top.max(self.right).max(self.bottom).max(self.left) + } +} + +impl From for Edges { + fn from(val: f32) -> Self { + let val: Pixels = val.into(); + val.into() + } +} + +impl From for Edges { + fn from(val: Pixels) -> Self { + Edges { + top: val, + right: val, + bottom: val, + left: val, + } + } +} + +/// Identifies a reference point on a 2D box, used to anchor positioned elements. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Anchor { + /// The top left corner + TopLeft, + /// The top right corner + TopRight, + /// The bottom left corner + BottomLeft, + /// The bottom right corner + BottomRight, + /// The top center position + TopCenter, + /// The bottom center position + BottomCenter, + /// The left center position + LeftCenter, + /// The right center position + RightCenter, +} + +impl Anchor { + /// Returns the directly opposite corner. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Anchor; + /// assert_eq!(Anchor::TopLeft.opposite(), Anchor::BottomRight); + /// ``` + #[must_use] + pub fn opposite(self) -> Self { + match self { + Anchor::TopLeft => Anchor::BottomRight, + Anchor::TopRight => Anchor::BottomLeft, + Anchor::BottomLeft => Anchor::TopRight, + Anchor::BottomRight => Anchor::TopLeft, + Anchor::TopCenter => Anchor::BottomCenter, + Anchor::BottomCenter => Anchor::TopCenter, + Anchor::LeftCenter => Anchor::RightCenter, + Anchor::RightCenter => Anchor::LeftCenter, + } + } + + /// Returns the corner across from this corner, moving along the specified axis. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Axis, Anchor}; + /// let result = Anchor::TopLeft.other_side_along(Axis::Horizontal); + /// assert_eq!(result, Anchor::TopRight); + /// ``` + #[must_use] + pub fn other_side_along(self, axis: Axis) -> Self { + match axis { + Axis::Vertical => match self { + Anchor::TopLeft => Anchor::BottomLeft, + Anchor::TopRight => Anchor::BottomRight, + Anchor::BottomLeft => Anchor::TopLeft, + Anchor::BottomRight => Anchor::TopRight, + Anchor::TopCenter => Anchor::BottomCenter, + Anchor::BottomCenter => Anchor::TopCenter, + Anchor::LeftCenter => Anchor::LeftCenter, + Anchor::RightCenter => Anchor::RightCenter, + }, + Axis::Horizontal => match self { + Anchor::TopLeft => Anchor::TopRight, + Anchor::TopRight => Anchor::TopLeft, + Anchor::BottomLeft => Anchor::BottomRight, + Anchor::BottomRight => Anchor::BottomLeft, + Anchor::TopCenter => Anchor::TopCenter, + Anchor::BottomCenter => Anchor::BottomCenter, + Anchor::LeftCenter => Anchor::RightCenter, + Anchor::RightCenter => Anchor::LeftCenter, + }, + } + } + + /// Returns whether the anchor is center-positioned. + #[inline] + pub fn is_center(&self) -> bool { + matches!( + self, + Self::TopCenter | Self::BottomCenter | Self::LeftCenter | Self::RightCenter + ) + } + + /// Returns whether the anchor is bottom-positioned. + #[inline] + pub fn is_bottom(&self) -> bool { + matches!( + self, + Self::BottomCenter | Self::BottomLeft | Self::BottomRight + ) + } +} + +/// Represents the corners of a box in a 2D space, such as border radius. +/// +/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`. +#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub struct Corners { + /// The value associated with the top left corner. + pub top_left: T, + /// The value associated with the top right corner. + pub top_right: T, + /// The value associated with the bottom right corner. + pub bottom_right: T, + /// The value associated with the bottom left corner. + pub bottom_left: T, +} + +impl Corners +where + T: Add + Half + Clone + Debug + Default + PartialEq, +{ + /// Constructs `Corners` where all sides are set to the same specified value. + /// + /// This function creates a `Corners` instance with the `top_left`, `top_right`, `bottom_right`, and `bottom_left` fields all initialized + /// to the same value provided as an argument. This is useful when you want to have uniform corners around a box, + /// such as a uniform border radius on a rectangle. + /// + /// # Arguments + /// + /// * `value` - The value to set for all four corners. + /// + /// # Returns + /// + /// An `Corners` instance with all corners set to the given value. + /// + /// # Examples + /// + /// ``` + /// # use gpui::Corners; + /// let uniform_corners = Corners::all(5.0); + /// assert_eq!(uniform_corners.top_left, 5.0); + /// assert_eq!(uniform_corners.top_right, 5.0); + /// assert_eq!(uniform_corners.bottom_right, 5.0); + /// assert_eq!(uniform_corners.bottom_left, 5.0); + /// ``` + pub fn all(value: T) -> Self { + Self { + top_left: value.clone(), + top_right: value.clone(), + bottom_right: value.clone(), + bottom_left: value, + } + } + + /// Returns the requested corner value, supporting all eight corner positions. + /// + /// For the four basic corners (TopLeft, TopRight, BottomLeft, BottomRight), + /// this returns the corresponding field value directly. + /// + /// For the center positions (TopCenter, BottomCenter, LeftCenter, RightCenter), + /// this calculates the average of the two adjacent corners. + /// + /// # Returns + /// + /// A value of type `T` representing the corner requested by the parameter. + /// + /// # Examples + /// + /// Basic corner positions: + /// + /// ``` + /// # use gpui::{Anchor, Corners}; + /// let corners = Corners { + /// top_left: 10, + /// top_right: 20, + /// bottom_left: 30, + /// bottom_right: 40 + /// }; + /// assert_eq!(corners.corner(Anchor::TopLeft), 10); + /// assert_eq!(corners.corner(Anchor::BottomRight), 40); + /// ``` + /// + /// Center positions (calculated as average of adjacent corners): + /// + /// ``` + /// # use gpui::{Anchor, Corners}; + /// let corners = Corners { + /// top_left: 10, + /// top_right: 20, + /// bottom_left: 30, + /// bottom_right: 40 + /// }; + /// assert_eq!(corners.corner(Anchor::TopCenter), 15); + /// assert_eq!(corners.corner(Anchor::BottomCenter), 35); + /// assert_eq!(corners.corner(Anchor::LeftCenter), 20); + /// assert_eq!(corners.corner(Anchor::RightCenter), 30); + /// ``` + #[must_use] + pub fn corner(&self, corner: Anchor) -> T { + match corner { + Anchor::TopLeft => self.top_left.clone(), + Anchor::TopRight => self.top_right.clone(), + Anchor::BottomLeft => self.bottom_left.clone(), + Anchor::BottomRight => self.bottom_right.clone(), + Anchor::TopCenter => (self.top_left.clone() + self.top_right.clone()).half(), + Anchor::BottomCenter => (self.bottom_left.clone() + self.bottom_right.clone()).half(), + Anchor::LeftCenter => (self.top_left.clone() + self.bottom_left.clone()).half(), + Anchor::RightCenter => (self.top_right.clone() + self.bottom_right.clone()).half(), + } + } +} + +impl Corners { + /// Converts the `AbsoluteLength` to `Pixels` based on the provided rem size. + /// + /// # Arguments + /// + /// * `rem_size` - The size of one REM unit in pixels, used for conversion if the `AbsoluteLength` is in REMs. + /// + /// # Returns + /// + /// Returns a `Corners` instance with each corner's length converted to pixels. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Corners, AbsoluteLength, Pixels, Rems, Size}; + /// let corners = Corners { + /// top_left: AbsoluteLength::Pixels(Pixels::from(15.0)), + /// top_right: AbsoluteLength::Rems(Rems(1.0)), + /// bottom_right: AbsoluteLength::Pixels(Pixels::from(30.0)), + /// bottom_left: AbsoluteLength::Rems(Rems(2.0)), + /// }; + /// let rem_size = Pixels::from(16.0); + /// let corners_in_pixels = corners.to_pixels(rem_size); + /// + /// assert_eq!(corners_in_pixels.top_left, Pixels::from(15.0)); + /// assert_eq!(corners_in_pixels.top_right, Pixels::from(16.0)); // 1 rem converted to pixels + /// assert_eq!(corners_in_pixels.bottom_right, Pixels::from(30.0)); + /// assert_eq!(corners_in_pixels.bottom_left, Pixels::from(32.0)); // 2 rems converted to pixels + /// ``` + pub fn to_pixels(self, rem_size: Pixels) -> Corners { + Corners { + top_left: self.top_left.to_pixels(rem_size), + top_right: self.top_right.to_pixels(rem_size), + bottom_right: self.bottom_right.to_pixels(rem_size), + bottom_left: self.bottom_left.to_pixels(rem_size), + } + } +} + +impl Corners { + /// Scales the `Corners` by a given factor, returning `Corners`. + /// + /// This method is typically used for adjusting the corner sizes for different display densities or scaling factors. + /// + /// # Arguments + /// + /// * `factor` - The scaling factor to apply to each corner. + /// + /// # Returns + /// + /// Returns a new `Corners` where each corner is the result of scaling the original corner by the given factor. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Corners, Pixels, ScaledPixels}; + /// let corners = Corners { + /// top_left: Pixels::from(10.0), + /// top_right: Pixels::from(20.0), + /// bottom_right: Pixels::from(30.0), + /// bottom_left: Pixels::from(40.0), + /// }; + /// let scaled_corners = corners.scale(2.0); + /// assert_eq!(scaled_corners.top_left, ScaledPixels::from(20.0)); + /// assert_eq!(scaled_corners.top_right, ScaledPixels::from(40.0)); + /// assert_eq!(scaled_corners.bottom_right, ScaledPixels::from(60.0)); + /// assert_eq!(scaled_corners.bottom_left, ScaledPixels::from(80.0)); + /// ``` + #[must_use] + pub fn scale(&self, factor: f32) -> Corners { + Corners { + top_left: self.top_left.scale(factor), + top_right: self.top_right.scale(factor), + bottom_right: self.bottom_right.scale(factor), + bottom_left: self.bottom_left.scale(factor), + } + } + + /// Returns the maximum value of any corner. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four corners. + #[must_use] + pub fn max(&self) -> Pixels { + self.top_left + .max(self.top_right) + .max(self.bottom_right) + .max(self.bottom_left) + } +} + +impl + Ord + Clone + Debug + Default + PartialEq> Corners { + /// Clamps corner radii to be less than or equal to half the shortest side of a quad. + /// + /// # Arguments + /// + /// * `size` - The size of the quad which limits the size of the corner radii. + /// + /// # Returns + /// + /// Anchor radii values clamped to fit. + #[must_use] + pub fn clamp_radii_for_quad_size(self, size: Size) -> Corners { + let max = cmp::min(size.width, size.height) / 2.; + Corners { + top_left: cmp::min(self.top_left, max.clone()), + top_right: cmp::min(self.top_right, max.clone()), + bottom_right: cmp::min(self.bottom_right, max.clone()), + bottom_left: cmp::min(self.bottom_left, max), + } + } +} + +impl Corners { + /// Applies a function to each field of the `Corners`, producing a new `Corners`. + /// + /// This method allows for converting a `Corners` to a `Corners` by specifying a closure + /// that defines how to convert between the two types. The closure is applied to each field + /// (`top_left`, `top_right`, `bottom_right`, `bottom_left`), resulting in new corners of the desired type. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`. + /// + /// # Returns + /// + /// Returns a new `Corners` with each field mapped by the provided function. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{Corners, Pixels, Rems}; + /// let corners = Corners { + /// top_left: Pixels::from(10.0), + /// top_right: Pixels::from(20.0), + /// bottom_right: Pixels::from(30.0), + /// bottom_left: Pixels::from(40.0), + /// }; + /// let corners_in_rems = corners.map(|&px| Rems(f32::from(px) / 16.0)); + /// assert_eq!(corners_in_rems, Corners { + /// top_left: Rems(0.625), + /// top_right: Rems(1.25), + /// bottom_right: Rems(1.875), + /// bottom_left: Rems(2.5), + /// }); + /// ``` + #[must_use] + pub fn map(&self, f: impl Fn(&T) -> U) -> Corners + where + U: Clone + Debug + Default + PartialEq, + { + Corners { + top_left: f(&self.top_left), + top_right: f(&self.top_right), + bottom_right: f(&self.bottom_right), + bottom_left: f(&self.bottom_left), + } + } +} + +impl Mul for Corners +where + T: Mul + Clone + Debug + Default + PartialEq, +{ + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + Self { + top_left: self.top_left.clone() * rhs.top_left, + top_right: self.top_right.clone() * rhs.top_right, + bottom_right: self.bottom_right.clone() * rhs.bottom_right, + bottom_left: self.bottom_left * rhs.bottom_left, + } + } +} + +impl MulAssign for Corners +where + T: Mul + Clone + Debug + Default + PartialEq, + S: Clone, +{ + fn mul_assign(&mut self, rhs: S) { + self.top_left = self.top_left.clone() * rhs.clone(); + self.top_right = self.top_right.clone() * rhs.clone(); + self.bottom_right = self.bottom_right.clone() * rhs.clone(); + self.bottom_left = self.bottom_left.clone() * rhs; + } +} + +impl Copy for Corners where T: Copy + Clone + Debug + Default + PartialEq {} + +impl From for Corners { + fn from(val: f32) -> Self { + Corners { + top_left: val.into(), + top_right: val.into(), + bottom_right: val.into(), + bottom_left: val.into(), + } + } +} + +impl From for Corners { + fn from(val: Pixels) -> Self { + Corners { + top_left: val, + top_right: val, + bottom_right: val, + bottom_left: val, + } + } +} + +/// Represents an angle in Radians +#[derive( + Clone, + Copy, + Default, + Add, + AddAssign, + Sub, + SubAssign, + Neg, + Div, + DivAssign, + PartialEq, + Serialize, + Deserialize, + Debug, +)] +#[repr(transparent)] +pub struct Radians(pub f32); + +/// Create a `Radian` from a raw value +pub fn radians(value: f32) -> Radians { + Radians(value) +} + +/// A type representing a percentage value. +#[derive( + Clone, + Copy, + Default, + Add, + AddAssign, + Sub, + SubAssign, + Neg, + Div, + DivAssign, + PartialEq, + Serialize, + Deserialize, + Debug, +)] +#[repr(transparent)] +pub struct Percentage(pub f32); + +/// Generate a `Radian` from a percentage of a full circle. +pub fn percentage(value: f32) -> Percentage { + debug_assert!( + (0.0..=1.0).contains(&value), + "Percentage must be between 0 and 1" + ); + Percentage(value) +} + +impl From for Radians { + fn from(value: Percentage) -> Self { + radians(value.0 * std::f32::consts::PI * 2.0) + } +} + +/// Represents a length in pixels, the base unit of measurement in the UI framework. +/// +/// `Pixels` is a value type that represents an absolute length in pixels, which is used +/// for specifying sizes, positions, and distances in the UI. It is the fundamental unit +/// of measurement for all visual elements and layout calculations. +/// +/// The inner value is an `f32`, allowing for sub-pixel precision which can be useful for +/// anti-aliasing and animations. However, when applied to actual pixel grids, the value +/// is typically rounded to the nearest integer. +/// +/// # Examples +/// +/// ``` +/// use gpui::{Pixels, ScaledPixels}; +/// +/// // Define a length of 10 pixels +/// let length = Pixels::from(10.0); +/// +/// // Define a length and scale it by a factor of 2 +/// let scaled_length = length.scale(2.0); +/// assert_eq!(scaled_length, ScaledPixels::from(20.0)); +/// ``` +#[derive( + Clone, + Copy, + Default, + Add, + AddAssign, + Sub, + SubAssign, + Neg, + Div, + DivAssign, + PartialEq, + Serialize, + Deserialize, + JsonSchema, +)] +#[repr(transparent)] +pub struct Pixels(pub(crate) f32); + +impl Div for Pixels { + type Output = f32; + + fn div(self, rhs: Self) -> Self::Output { + self.0 / rhs.0 + } +} + +impl std::ops::DivAssign for Pixels { + fn div_assign(&mut self, rhs: Self) { + *self = Self(self.0 / rhs.0); + } +} + +impl std::ops::RemAssign for Pixels { + fn rem_assign(&mut self, rhs: Self) { + self.0 %= rhs.0; + } +} + +impl std::ops::Rem for Pixels { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } +} + +impl Mul for Pixels { + type Output = Self; + + fn mul(self, rhs: f32) -> Self { + Self(self.0 * rhs) + } +} + +impl Mul for f32 { + type Output = Pixels; + + fn mul(self, rhs: Pixels) -> Self::Output { + rhs * self + } +} + +impl Mul for Pixels { + type Output = Self; + + fn mul(self, rhs: usize) -> Self { + self * (rhs as f32) + } +} + +impl Mul for usize { + type Output = Pixels; + + fn mul(self, rhs: Pixels) -> Pixels { + rhs * self + } +} + +impl MulAssign for Pixels { + fn mul_assign(&mut self, rhs: f32) { + self.0 *= rhs; + } +} + +impl Display for Pixels { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}px", self.0) + } +} + +impl Debug for Pixels { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +impl std::iter::Sum for Pixels { + fn sum>(iter: I) -> Self { + iter.fold(Self::ZERO, |a, b| a + b) + } +} + +impl<'a> std::iter::Sum<&'a Pixels> for Pixels { + fn sum>(iter: I) -> Self { + iter.fold(Self::ZERO, |a, b| a + *b) + } +} + +impl TryFrom<&'_ str> for Pixels { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + value + .strip_suffix("px") + .context("expected 'px' suffix") + .and_then(|number| Ok(number.parse()?)) + .map(Self) + } +} + +impl Pixels { + /// Represents zero pixels. + pub const ZERO: Pixels = Pixels(0.0); + /// The maximum value that can be represented by `Pixels`. + pub const MAX: Pixels = Pixels(f32::MAX); + /// The minimum value that can be represented by `Pixels`. + pub const MIN: Pixels = Pixels(f32::MIN); + + /// Returns the raw `f32` value of this `Pixels`. + pub fn as_f32(self) -> f32 { + self.0 + } + + /// Floors the `Pixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `Pixels` instance with the floored value. + pub fn floor(&self) -> Self { + Self(self.0.floor()) + } + + /// Rounds the `Pixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `Pixels` instance with the rounded value. + pub fn round(&self) -> Self { + Self(self.0.round()) + } + + /// Returns the ceiling of the `Pixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `Pixels` instance with the ceiling value. + pub fn ceil(&self) -> Self { + Self(self.0.ceil()) + } + + /// Scales the `Pixels` value by a given factor, producing `ScaledPixels`. + /// + /// This method is used when adjusting pixel values for display scaling factors, + /// such as high DPI (dots per inch) or Retina displays, where the pixel density is higher and + /// thus requires scaling to maintain visual consistency and readability. + /// + /// The resulting `ScaledPixels` represent the scaled value which can be used for rendering + /// calculations where display scaling is considered. + #[must_use] + pub fn scale(&self, factor: f32) -> ScaledPixels { + ScaledPixels(self.0 * factor) + } + + /// Raises the `Pixels` value to a given power. + /// + /// # Arguments + /// + /// * `exponent` - The exponent to raise the `Pixels` value by. + /// + /// # Returns + /// + /// Returns a new `Pixels` instance with the value raised to the given exponent. + pub fn pow(&self, exponent: f32) -> Self { + Self(self.0.powf(exponent)) + } + + /// Returns the absolute value of the `Pixels`. + /// + /// # Returns + /// + /// A new `Pixels` instance with the absolute value of the original `Pixels`. + pub fn abs(&self) -> Self { + Self(self.0.abs()) + } + + /// Returns the sign of the `Pixels` value. + /// + /// # Returns + /// + /// Returns: + /// * `1.0` if the value is positive + /// * `-1.0` if the value is negative + pub fn signum(&self) -> f32 { + self.0.signum() + } + + /// Returns the f64 value of `Pixels`. + /// + /// # Returns + /// + /// A f64 value of the `Pixels`. + pub fn to_f64(self) -> f64 { + self.0 as f64 + } +} + +impl Eq for Pixels {} + +impl PartialOrd for Pixels { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Pixels { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.0.total_cmp(&other.0) + } +} + +impl std::hash::Hash for Pixels { + fn hash(&self, state: &mut H) { + self.0.to_bits().hash(state); + } +} + +impl From for Pixels { + fn from(pixels: f64) -> Self { + Pixels(pixels as f32) + } +} + +impl From for Pixels { + fn from(pixels: f32) -> Self { + Pixels(pixels) + } +} + +impl From for f32 { + fn from(pixels: Pixels) -> Self { + pixels.0 + } +} + +impl From<&Pixels> for f32 { + fn from(pixels: &Pixels) -> Self { + pixels.0 + } +} + +impl From for f64 { + fn from(pixels: Pixels) -> Self { + pixels.0 as f64 + } +} + +impl From for u32 { + fn from(pixels: Pixels) -> Self { + pixels.0 as u32 + } +} + +impl From<&Pixels> for u32 { + fn from(pixels: &Pixels) -> Self { + pixels.0 as u32 + } +} + +impl From for Pixels { + fn from(pixels: u32) -> Self { + Pixels(pixels as f32) + } +} + +impl From for usize { + fn from(pixels: Pixels) -> Self { + pixels.0 as usize + } +} + +impl From for Pixels { + fn from(pixels: usize) -> Self { + Pixels(pixels as f32) + } +} + +/// Represents physical pixels on the display. +/// +/// `DevicePixels` is a unit of measurement that refers to the actual pixels on a device's screen. +/// This type is used when precise pixel manipulation is required, such as rendering graphics or +/// interfacing with hardware that operates on the pixel level. Unlike logical pixels that may be +/// affected by the device's scale factor, `DevicePixels` always correspond to real pixels on the +/// display. +#[derive( + Add, + AddAssign, + Clone, + Copy, + Default, + Div, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + Sub, + SubAssign, + Serialize, + Deserialize, +)] +#[repr(transparent)] +pub struct DevicePixels(pub i32); + +impl DevicePixels { + /// Converts the `DevicePixels` value to the number of bytes needed to represent it in memory. + /// + /// This function is useful when working with graphical data that needs to be stored in a buffer, + /// such as images or framebuffers, where each pixel may be represented by a specific number of bytes. + /// + /// # Arguments + /// + /// * `bytes_per_pixel` - The number of bytes used to represent a single pixel. + /// + /// # Returns + /// + /// The number of bytes required to represent the `DevicePixels` value in memory. + /// + /// # Examples + /// + /// ``` + /// # use gpui::DevicePixels; + /// let pixels = DevicePixels(10); // 10 device pixels + /// let bytes_per_pixel = 4; // Assume each pixel is represented by 4 bytes (e.g., RGBA) + /// let total_bytes = pixels.to_bytes(bytes_per_pixel); + /// assert_eq!(total_bytes, 40); // 10 pixels * 4 bytes/pixel = 40 bytes + /// ``` + pub fn to_bytes(self, bytes_per_pixel: u8) -> u32 { + self.0 as u32 * bytes_per_pixel as u32 + } +} + +impl fmt::Debug for DevicePixels { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} px (device)", self.0) + } +} + +impl From for i32 { + fn from(device_pixels: DevicePixels) -> Self { + device_pixels.0 + } +} + +impl From for DevicePixels { + fn from(device_pixels: i32) -> Self { + DevicePixels(device_pixels) + } +} + +impl From for DevicePixels { + fn from(device_pixels: u32) -> Self { + DevicePixels(device_pixels as i32) + } +} + +impl From for u32 { + fn from(device_pixels: DevicePixels) -> Self { + device_pixels.0 as u32 + } +} + +impl From for u64 { + fn from(device_pixels: DevicePixels) -> Self { + device_pixels.0 as u64 + } +} + +impl From for DevicePixels { + fn from(device_pixels: u64) -> Self { + DevicePixels(device_pixels as i32) + } +} + +impl From for usize { + fn from(device_pixels: DevicePixels) -> Self { + device_pixels.0 as usize + } +} + +impl From for DevicePixels { + fn from(device_pixels: usize) -> Self { + DevicePixels(device_pixels as i32) + } +} + +/// Represents scaled pixels that take into account the device's scale factor. +/// +/// `ScaledPixels` are used to ensure that UI elements appear at the correct size on devices +/// with different pixel densities. When a device has a higher scale factor (such as Retina displays), +/// a single logical pixel may correspond to multiple physical pixels. By using `ScaledPixels`, +/// dimensions and positions can be specified in a way that scales appropriately across different +/// display resolutions. +#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, DivAssign, PartialEq)] +#[repr(transparent)] +pub struct ScaledPixels(pub f32); + +impl ScaledPixels { + /// Returns the raw `f32` value of this `ScaledPixels`. + pub fn as_f32(self) -> f32 { + self.0 + } + + /// Floors the `ScaledPixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `ScaledPixels` instance with the floored value. + pub fn floor(&self) -> Self { + Self(self.0.floor()) + } + + /// Rounds the `ScaledPixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `ScaledPixels` instance with the rounded value. + pub fn round(&self) -> Self { + Self(self.0.round()) + } + + /// Ceils the `ScaledPixels` value to the nearest whole number. + /// + /// # Returns + /// + /// Returns a new `ScaledPixels` instance with the ceiled value. + pub fn ceil(&self) -> Self { + Self(self.0.ceil()) + } +} + +impl Eq for ScaledPixels {} + +impl PartialOrd for ScaledPixels { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ScaledPixels { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.0.total_cmp(&other.0) + } +} + +impl Debug for ScaledPixels { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}px (scaled)", self.0) + } +} + +impl From for DevicePixels { + fn from(scaled: ScaledPixels) -> Self { + DevicePixels(scaled.0.ceil() as i32) + } +} + +impl From for ScaledPixels { + fn from(device: DevicePixels) -> Self { + ScaledPixels(device.0 as f32) + } +} + +impl From for f64 { + fn from(scaled_pixels: ScaledPixels) -> Self { + scaled_pixels.0 as f64 + } +} + +impl From for u32 { + fn from(pixels: ScaledPixels) -> Self { + pixels.0 as u32 + } +} + +impl From for ScaledPixels { + fn from(pixels: f32) -> Self { + Self(pixels) + } +} + +impl Div for ScaledPixels { + type Output = f32; + + fn div(self, rhs: Self) -> Self::Output { + self.0 / rhs.0 + } +} + +impl std::ops::DivAssign for ScaledPixels { + fn div_assign(&mut self, rhs: Self) { + *self = Self(self.0 / rhs.0); + } +} + +impl std::ops::RemAssign for ScaledPixels { + fn rem_assign(&mut self, rhs: Self) { + self.0 %= rhs.0; + } +} + +impl std::ops::Rem for ScaledPixels { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + Self(self.0 % rhs.0) + } +} + +impl Mul for ScaledPixels { + type Output = Self; + + fn mul(self, rhs: f32) -> Self { + Self(self.0 * rhs) + } +} + +impl Mul for f32 { + type Output = ScaledPixels; + + fn mul(self, rhs: ScaledPixels) -> Self::Output { + rhs * self + } +} + +impl Mul for ScaledPixels { + type Output = Self; + + fn mul(self, rhs: usize) -> Self { + self * (rhs as f32) + } +} + +impl Mul for usize { + type Output = ScaledPixels; + + fn mul(self, rhs: ScaledPixels) -> ScaledPixels { + rhs * self + } +} + +impl MulAssign for ScaledPixels { + fn mul_assign(&mut self, rhs: f32) { + self.0 *= rhs; + } +} + +/// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with [`Window::set_rem_size`][set_rem_size]. +/// +/// Rems are used for defining lengths that are scalable and consistent across different UI elements. +/// The value of `1rem` is typically equal to the font-size of the root element (often the `` element in browsers), +/// making it a flexible unit that adapts to the user's text size preferences. In this framework, `rems` serve a similar +/// purpose, allowing for scalable and accessible design that can adjust to different display settings or user preferences. +/// +/// For example, if the root element's font-size is `16px`, then `1rem` equals `16px`. A length of `2rems` would then be `32px`. +/// +/// [set_rem_size]: crate::Window::set_rem_size +#[derive(Clone, Copy, Default, Add, Sub, Mul, Div, Neg, PartialEq)] +pub struct Rems(pub f32); + +impl Rems { + /// A length of zero. + pub const ZERO: Self = Self(0.0); + /// Convert this Rem value to pixels. + pub fn to_pixels(self, rem_size: Pixels) -> Pixels { + self * rem_size + } + /// Convert from pixels to Rem + pub fn from_pixels(length: Pixels, window: &gpui::Window) -> Self { + Self(length / window.rem_size()) + } +} + +impl Mul for Rems { + type Output = Pixels; + + fn mul(self, other: Pixels) -> Pixels { + Pixels(self.0 * other.0) + } +} + +impl AddAssign for Rems { + fn add_assign(&mut self, rhs: Rems) { + self.0 += rhs.0 + } +} + +impl Display for Rems { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}rem", self.0) + } +} + +impl Debug for Rems { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +impl TryFrom<&'_ str> for Rems { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + value + .strip_suffix("rem") + .context("expected 'rem' suffix") + .and_then(|number| Ok(number.parse()?)) + .map(Self) + } +} + +/// Represents an absolute length in pixels or rems. +/// +/// `AbsoluteLength` can be either a fixed number of pixels, which is an absolute measurement not +/// affected by the current font size, or a number of rems, which is relative to the font size of +/// the root element. It is used for specifying dimensions that are either independent of or +/// related to the typographic scale. +#[derive(Clone, Copy, Neg, PartialEq)] +pub enum AbsoluteLength { + /// A length in pixels. + Pixels(Pixels), + /// A length in rems. + Rems(Rems), +} + +impl AbsoluteLength { + /// Checks if the absolute length is zero. + pub fn is_zero(&self) -> bool { + match self { + AbsoluteLength::Pixels(px) => px.0 == 0.0, + AbsoluteLength::Rems(rems) => rems.0 == 0.0, + } + } +} + +impl From for AbsoluteLength { + fn from(pixels: Pixels) -> Self { + AbsoluteLength::Pixels(pixels) + } +} + +impl From for AbsoluteLength { + fn from(rems: Rems) -> Self { + AbsoluteLength::Rems(rems) + } +} + +impl AbsoluteLength { + /// Converts an `AbsoluteLength` to `Pixels` based on a given `rem_size`. + /// + /// # Arguments + /// + /// * `rem_size` - The size of one rem in pixels. + /// + /// # Returns + /// + /// Returns the `AbsoluteLength` as `Pixels`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{AbsoluteLength, Pixels, Rems}; + /// let length_in_pixels = AbsoluteLength::Pixels(Pixels::from(42.0)); + /// let length_in_rems = AbsoluteLength::Rems(Rems(2.0)); + /// let rem_size = Pixels::from(16.0); + /// + /// assert_eq!(length_in_pixels.to_pixels(rem_size), Pixels::from(42.0)); + /// assert_eq!(length_in_rems.to_pixels(rem_size), Pixels::from(32.0)); + /// ``` + pub fn to_pixels(self, rem_size: Pixels) -> Pixels { + match self { + AbsoluteLength::Pixels(pixels) => pixels, + AbsoluteLength::Rems(rems) => rems.to_pixels(rem_size), + } + } + + /// Converts an `AbsoluteLength` to `Rems` based on a given `rem_size`. + /// + /// # Arguments + /// + /// * `rem_size` - The size of one rem in pixels. + /// + /// # Returns + /// + /// Returns the `AbsoluteLength` as `Pixels`. + pub fn to_rems(self, rem_size: Pixels) -> Rems { + match self { + AbsoluteLength::Pixels(pixels) => Rems(pixels.0 / rem_size.0), + AbsoluteLength::Rems(rems) => rems, + } + } +} + +impl Default for AbsoluteLength { + fn default() -> Self { + px(0.).into() + } +} + +impl Display for AbsoluteLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Pixels(pixels) => write!(f, "{pixels}"), + Self::Rems(rems) => write!(f, "{rems}"), + } + } +} + +impl Debug for AbsoluteLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +const EXPECTED_ABSOLUTE_LENGTH: &str = "number with 'px' or 'rem' suffix"; + +impl TryFrom<&'_ str> for AbsoluteLength { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + if let Ok(pixels) = value.try_into() { + Ok(Self::Pixels(pixels)) + } else if let Ok(rems) = value.try_into() { + Ok(Self::Rems(rems)) + } else { + Err(anyhow!( + "invalid AbsoluteLength '{value}', expected {EXPECTED_ABSOLUTE_LENGTH}" + )) + } + } +} + +impl JsonSchema for AbsoluteLength { + fn schema_name() -> Cow<'static, str> { + "AbsoluteLength".into() + } + + fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + json_schema!({ + "type": "string", + "pattern": r"^-?\d+(\.\d+)?(px|rem)$" + }) + } +} + +impl<'de> Deserialize<'de> for AbsoluteLength { + fn deserialize>(deserializer: D) -> Result { + struct StringVisitor; + + impl de::Visitor<'_> for StringVisitor { + type Value = AbsoluteLength; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{EXPECTED_ABSOLUTE_LENGTH}") + } + + fn visit_str(self, value: &str) -> Result { + AbsoluteLength::try_from(value).map_err(E::custom) + } + } + + deserializer.deserialize_str(StringVisitor) + } +} + +impl Serialize for AbsoluteLength { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{self}")) + } +} + +/// A non-auto length that can be defined in pixels, rems, or percent of parent. +/// +/// This enum represents lengths that have a specific value, as opposed to lengths that are automatically +/// determined by the context. It includes absolute lengths in pixels or rems, and relative lengths as a +/// fraction of the parent's size. +#[derive(Clone, Copy, Neg, PartialEq)] +pub enum DefiniteLength { + /// An absolute length specified in pixels or rems. + Absolute(AbsoluteLength), + /// A relative length specified as a fraction of the parent's size, between 0 and 1. + Fraction(f32), +} + +impl DefiniteLength { + /// Converts the `DefiniteLength` to `Pixels` based on a given `base_size` and `rem_size`. + /// + /// If the `DefiniteLength` is an absolute length, it will be directly converted to `Pixels`. + /// If it is a fraction, the fraction will be multiplied by the `base_size` to get the length in pixels. + /// + /// # Arguments + /// + /// * `base_size` - The base size in `AbsoluteLength` to which the fraction will be applied. + /// * `rem_size` - The size of one rem in pixels, used to convert rems to pixels. + /// + /// # Returns + /// + /// Returns the `DefiniteLength` as `Pixels`. + /// + /// # Examples + /// + /// ``` + /// # use gpui::{DefiniteLength, AbsoluteLength, Pixels, px, rems}; + /// let length_in_pixels = DefiniteLength::Absolute(AbsoluteLength::Pixels(px(42.0))); + /// let length_in_rems = DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0))); + /// let length_as_fraction = DefiniteLength::Fraction(0.5); + /// let base_size = AbsoluteLength::Pixels(px(100.0)); + /// let rem_size = px(16.0); + /// + /// assert_eq!(length_in_pixels.to_pixels(base_size, rem_size), Pixels::from(42.0)); + /// assert_eq!(length_in_rems.to_pixels(base_size, rem_size), Pixels::from(32.0)); + /// assert_eq!(length_as_fraction.to_pixels(base_size, rem_size), Pixels::from(50.0)); + /// ``` + pub fn to_pixels(self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels { + match self { + DefiniteLength::Absolute(size) => size.to_pixels(rem_size), + DefiniteLength::Fraction(fraction) => match base_size { + AbsoluteLength::Pixels(px) => px * fraction, + AbsoluteLength::Rems(rems) => rems * rem_size * fraction, + }, + } + } +} + +impl Debug for DefiniteLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +impl Display for DefiniteLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DefiniteLength::Absolute(length) => write!(f, "{length}"), + DefiniteLength::Fraction(fraction) => write!(f, "{}%", (fraction * 100.0) as i32), + } + } +} + +const EXPECTED_DEFINITE_LENGTH: &str = "expected number with 'px', 'rem', or '%' suffix"; + +impl TryFrom<&'_ str> for DefiniteLength { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + if let Some(percentage) = value.strip_suffix('%') { + let fraction: f32 = percentage.parse::().with_context(|| { + format!("invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}") + })?; + Ok(DefiniteLength::Fraction(fraction / 100.0)) + } else if let Ok(absolute_length) = value.try_into() { + Ok(DefiniteLength::Absolute(absolute_length)) + } else { + Err(anyhow!( + "invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}" + )) + } + } +} + +impl JsonSchema for DefiniteLength { + fn schema_name() -> Cow<'static, str> { + "DefiniteLength".into() + } + + fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + json_schema!({ + "type": "string", + "pattern": r"^-?\d+(\.\d+)?(px|rem|%)$" + }) + } +} + +impl<'de> Deserialize<'de> for DefiniteLength { + fn deserialize>(deserializer: D) -> Result { + struct StringVisitor; + + impl de::Visitor<'_> for StringVisitor { + type Value = DefiniteLength; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{EXPECTED_DEFINITE_LENGTH}") + } + + fn visit_str(self, value: &str) -> Result { + DefiniteLength::try_from(value).map_err(E::custom) + } + } + + deserializer.deserialize_str(StringVisitor) + } +} + +impl Serialize for DefiniteLength { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{self}")) + } +} + +impl From for DefiniteLength { + fn from(pixels: Pixels) -> Self { + Self::Absolute(pixels.into()) + } +} + +impl From for DefiniteLength { + fn from(rems: Rems) -> Self { + Self::Absolute(rems.into()) + } +} + +impl From for DefiniteLength { + fn from(length: AbsoluteLength) -> Self { + Self::Absolute(length) + } +} + +impl Default for DefiniteLength { + fn default() -> Self { + Self::Absolute(AbsoluteLength::default()) + } +} + +/// A length that can be defined in pixels, rems, percent of parent, or auto. +#[derive(Clone, Copy, PartialEq)] +pub enum Length { + /// A definite length specified either in pixels, rems, or as a fraction of the parent's size. + Definite(DefiniteLength), + /// An automatic length that is determined by the context in which it is used. + Auto, +} + +impl Debug for Length { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +impl Display for Length { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Length::Definite(definite_length) => write!(f, "{}", definite_length), + Length::Auto => write!(f, "auto"), + } + } +} + +const EXPECTED_LENGTH: &str = "expected 'auto' or number with 'px', 'rem', or '%' suffix"; + +impl TryFrom<&'_ str> for Length { + type Error = anyhow::Error; + + fn try_from(value: &'_ str) -> Result { + if value == "auto" { + Ok(Length::Auto) + } else if let Ok(definite_length) = value.try_into() { + Ok(Length::Definite(definite_length)) + } else { + Err(anyhow!( + "invalid Length '{value}', expected {EXPECTED_LENGTH}" + )) + } + } +} + +impl JsonSchema for Length { + fn schema_name() -> Cow<'static, str> { + "Length".into() + } + + fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + json_schema!({ + "type": "string", + "pattern": r"^(auto|-?\d+(\.\d+)?(px|rem|%))$" + }) + } +} + +impl<'de> Deserialize<'de> for Length { + fn deserialize>(deserializer: D) -> Result { + struct StringVisitor; + + impl de::Visitor<'_> for StringVisitor { + type Value = Length; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{EXPECTED_LENGTH}") + } + + fn visit_str(self, value: &str) -> Result { + Length::try_from(value).map_err(E::custom) + } + } + + deserializer.deserialize_str(StringVisitor) + } +} + +impl Serialize for Length { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{self}")) + } +} + +/// Constructs a `DefiniteLength` representing a relative fraction of a parent size. +/// +/// This function creates a `DefiniteLength` that is a specified fraction of a parent's dimension. +/// The fraction should be a floating-point number between 0.0 and 1.0, where 1.0 represents 100% of the parent's size. +/// +/// # Arguments +/// +/// * `fraction` - The fraction of the parent's size, between 0.0 and 1.0. +/// +/// # Returns +/// +/// A `DefiniteLength` representing the relative length as a fraction of the parent's size. +pub const fn relative(fraction: f32) -> DefiniteLength { + DefiniteLength::Fraction(fraction) +} + +/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`. +pub const fn phi() -> DefiniteLength { + relative(1.618_034) +} + +/// Constructs a `Rems` value representing a length in rems. +/// +/// # Arguments +/// +/// * `rems` - The number of rems for the length. +/// +/// # Returns +/// +/// A `Rems` representing the specified number of rems. +pub const fn rems(rems: f32) -> Rems { + Rems(rems) +} + +/// Constructs a `Pixels` value representing a length in pixels. +/// +/// # Arguments +/// +/// * `pixels` - The number of pixels for the length. +/// +/// # Returns +/// +/// A `Pixels` representing the specified number of pixels. +pub const fn px(pixels: f32) -> Pixels { + Pixels(pixels) +} + +/// Returns a `Length` representing an automatic length. +/// +/// The `auto` length is often used in layout calculations where the length should be determined +/// by the layout context itself rather than being explicitly set. This is commonly used in CSS +/// for properties like `width`, `height`, `margin`, `padding`, etc., where `auto` can be used +/// to instruct the layout engine to calculate the size based on other factors like the size of the +/// container or the intrinsic size of the content. +/// +/// # Returns +/// +/// A `Length` variant set to `Auto`. +pub const fn auto() -> Length { + Length::Auto +} + +impl From for Length { + fn from(pixels: Pixels) -> Self { + Self::Definite(pixels.into()) + } +} + +impl From for Length { + fn from(rems: Rems) -> Self { + Self::Definite(rems.into()) + } +} + +impl From for Length { + fn from(length: DefiniteLength) -> Self { + Self::Definite(length) + } +} + +impl From for Length { + fn from(length: AbsoluteLength) -> Self { + Self::Definite(length.into()) + } +} + +impl Default for Length { + fn default() -> Self { + Self::Definite(DefiniteLength::default()) + } +} + +impl From<()> for Length { + fn from(_: ()) -> Self { + Self::Definite(DefiniteLength::default()) + } +} + +/// A location in a grid layout. +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)] +pub struct GridLocation { + /// The rows this item uses within the grid. + pub row: Range, + /// The columns this item uses within the grid. + pub column: Range, +} + +/// The placement of an item within a grid layout's column or row. +#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)] +pub enum GridPlacement { + /// The grid line index to place this item. + Line(i16), + /// The number of grid lines to span. + Span(u16), + /// Automatically determine the placement, equivalent to Span(1) + #[default] + Auto, +} + +impl From for taffy::GridPlacement { + fn from(placement: GridPlacement) -> Self { + match placement { + GridPlacement::Line(index) => taffy::GridPlacement::from_line_index(index), + GridPlacement::Span(span) => taffy::GridPlacement::from_span(span), + GridPlacement::Auto => taffy::GridPlacement::Auto, + } + } +} + +/// Provides a trait for types that can calculate half of their value. +/// +/// The `Half` trait is used for types that can be evenly divided, returning a new instance of the same type +/// representing half of the original value. This is commonly used for types that represent measurements or sizes, +/// such as lengths or pixels, where halving is a frequent operation during layout calculations or animations. +pub trait Half { + /// Returns half of the current value. + /// + /// # Returns + /// + /// A new instance of the implementing type, representing half of the original value. + fn half(&self) -> Self; +} + +impl Half for i32 { + fn half(&self) -> Self { + self / 2 + } +} + +impl Half for f32 { + fn half(&self) -> Self { + self / 2. + } +} + +impl Half for DevicePixels { + fn half(&self) -> Self { + Self(self.0 / 2) + } +} + +impl Half for ScaledPixels { + fn half(&self) -> Self { + Self(self.0 / 2.) + } +} + +impl Half for Pixels { + fn half(&self) -> Self { + Self(self.0 / 2.) + } +} + +impl Half for Rems { + fn half(&self) -> Self { + Self(self.0 / 2.) + } +} + +/// A trait for checking if a value is zero. +/// +/// This trait provides a method to determine if a value is considered to be zero. +/// It is implemented for various numeric and length-related types where the concept +/// of zero is applicable. This can be useful for comparisons, optimizations, or +/// determining if an operation has a neutral effect. +pub trait IsZero { + /// Determines if the value is zero. + /// + /// # Returns + /// + /// Returns `true` if the value is zero, `false` otherwise. + fn is_zero(&self) -> bool; +} + +impl IsZero for DevicePixels { + fn is_zero(&self) -> bool { + self.0 == 0 + } +} + +impl IsZero for ScaledPixels { + fn is_zero(&self) -> bool { + self.0 == 0. + } +} + +impl IsZero for Pixels { + fn is_zero(&self) -> bool { + self.0 == 0. + } +} + +impl IsZero for Rems { + fn is_zero(&self) -> bool { + self.0 == 0. + } +} + +impl IsZero for AbsoluteLength { + fn is_zero(&self) -> bool { + match self { + AbsoluteLength::Pixels(pixels) => pixels.is_zero(), + AbsoluteLength::Rems(rems) => rems.is_zero(), + } + } +} + +impl IsZero for DefiniteLength { + fn is_zero(&self) -> bool { + match self { + DefiniteLength::Absolute(length) => length.is_zero(), + DefiniteLength::Fraction(fraction) => *fraction == 0., + } + } +} + +impl IsZero for Length { + fn is_zero(&self) -> bool { + match self { + Length::Definite(length) => length.is_zero(), + Length::Auto => false, + } + } +} + +impl IsZero for Point { + fn is_zero(&self) -> bool { + self.x.is_zero() && self.y.is_zero() + } +} + +impl IsZero for Size +where + T: IsZero + Clone + Debug + Default + PartialEq, +{ + fn is_zero(&self) -> bool { + self.width.is_zero() || self.height.is_zero() + } +} + +impl IsZero for Bounds { + fn is_zero(&self) -> bool { + self.size.is_zero() + } +} + +impl IsZero for Corners +where + T: IsZero + Clone + Debug + Default + PartialEq, +{ + fn is_zero(&self) -> bool { + self.top_left.is_zero() + && self.top_right.is_zero() + && self.bottom_right.is_zero() + && self.bottom_left.is_zero() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bounds_intersects() { + let bounds1 = Bounds { + origin: Point { x: 0.0, y: 0.0 }, + size: Size { + width: 5.0, + height: 5.0, + }, + }; + let bounds2 = Bounds { + origin: Point { x: 4.0, y: 4.0 }, + size: Size { + width: 5.0, + height: 5.0, + }, + }; + let bounds3 = Bounds { + origin: Point { x: 10.0, y: 10.0 }, + size: Size { + width: 5.0, + height: 5.0, + }, + }; + + // Test Case 1: Intersecting bounds + assert!(bounds1.intersects(&bounds2)); + + // Test Case 2: Non-Intersecting bounds + assert!(!bounds1.intersects(&bounds3)); + + // Test Case 3: Bounds intersecting with themselves + assert!(bounds1.intersects(&bounds1)); + } +} diff --git a/vendor/gpui-pre/src/gestures.rs b/vendor/gpui-pre/src/gestures.rs new file mode 100644 index 00000000..ec611576 --- /dev/null +++ b/vendor/gpui-pre/src/gestures.rs @@ -0,0 +1,2211 @@ +//! Touch gesture recognition vocabulary. +//! +//! GPUI recognizes gestures from raw [`TouchEvent`](crate::TouchEvent)s in a +//! single, portable arena in gpui core: recognizers compete for in-flight +//! touches, winners claim them, and losers are cancelled. Recognized gestures +//! are surfaced through *existing* semantic events wherever possible, a tap +//! becomes [`ClickEvent::Touch`](crate::ClickEvent), a pan becomes +//! [`ScrollWheelEvent`](crate::ScrollWheelEvent)s carrying a +//! [`TouchPhase`](crate::TouchPhase), and a pinch becomes +//! [`PinchEvent`](crate::PinchEvent)s — so components written against +//! `on_click` and scroll containers work untouched on mobile. + +use std::collections::VecDeque; +use std::mem; +use std::time::Duration; + +use scheduler::Instant; +use smallvec::SmallVec; + +use crate::{ + Axis, GestureEvent, InputEvent, IsZero, Modifiers, MouseButton, MouseDownEvent, MouseEvent, + MouseUpEvent, Pixels, PlatformInput, Point, ScrollDelta, ScrollWheelEvent, TouchEvent, TouchId, + TouchPhase, point, px, seal::Sealed, +}; + +const SCROLL_EVENT_SEPARATION: Duration = Duration::from_millis(28); + +fn dominant_axis(delta: Point) -> Axis { + if delta.x.abs() <= delta.y.abs() { + Axis::Vertical + } else { + Axis::Horizontal + } +} + +fn lock_delta_to_axis(delta: &mut Point, axis: Axis) { + match axis { + Axis::Vertical => delta.x = Pixels::ZERO, + Axis::Horizontal => delta.y = Pixels::ZERO, + } +} + +fn movements_oppose(left: Point, right: Point) -> bool { + f32::from(left.x) * f32::from(right.x) + f32::from(left.y) * f32::from(right.y) < 0. +} + +/// Tracks the dominant axis across the events in a scroll gesture. +#[derive(Clone, Copy, Debug, Default)] +pub struct OngoingScroll { + last_event: Option, + axis: Option, +} + +impl OngoingScroll { + /// Filters the given delta to the dominant axis of the current scroll gesture. + /// + /// Gestures are delimited by their touch phase when available, with a timeout + /// fallback for platforms that only emit [`TouchPhase::Moved`]. + pub fn filter(&mut self, delta: &mut Point, touch_phase: TouchPhase) { + self.filter_at(delta, touch_phase, Instant::now()) + } + + fn filter_at(&mut self, delta: &mut Point, touch_phase: TouchPhase, now: Instant) { + const UNLOCK_PERCENT: f32 = 1.9; + const UNLOCK_LOWER_BOUND: Pixels = px(6.); + + if matches!(touch_phase, TouchPhase::Ended | TouchPhase::Cancelled) { + self.last_event = None; + self.axis = None; + return; + } + + let x = delta.x.abs(); + let y = delta.y.abs(); + if x.is_zero() && y.is_zero() { + if touch_phase == TouchPhase::Started { + self.last_event = None; + self.axis = None; + } + return; + } + + let starts_new_gesture = touch_phase == TouchPhase::Started + || self + .last_event + .is_none_or(|last_event| now.duration_since(last_event) >= SCROLL_EVENT_SEPARATION); + let mut axis = self.axis; + if starts_new_gesture { + axis = Some(dominant_axis(*delta)); + } else if x.max(y) >= UNLOCK_LOWER_BOUND { + match axis { + Some(Axis::Vertical) if x > y && x >= y * UNLOCK_PERCENT => { + axis = None; + } + Some(Axis::Horizontal) if y > x && y >= x * UNLOCK_PERCENT => { + axis = None; + } + _ => {} + } + } + + self.last_event = Some(now); + self.axis = axis; + if let Some(axis) = axis { + lock_delta_to_axis(delta, axis); + } + } +} + +/// Feel constants consumed by gesture recognizers. Provided on a best-effort +/// basis, depending on each platform's support, defaulting to GPUI's own +/// (iOS flavored) values +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct GestureTuning { + /// Distance a touch may travel before it stops being a potential tap and + /// becomes a pan/drag. + pub touch_slop: Pixels, + /// Maximum interval between taps for them to accumulate a tap count. + pub multi_tap_interval: Duration, + /// Maximum distance between taps for them to accumulate a tap count. + pub multi_tap_slop: Pixels, + /// How long a touch must remain within [`Self::touch_slop`] to be + /// recognized as a long press. + pub long_press_duration: Duration, + /// How scroll momentum decelerates after a fling. + pub scroll_physics: ScrollPhysics, + /// Minimum release velocity, in pixels per second, required to start + /// scroll momentum. + pub min_fling_velocity: f32, +} + +impl Default for GestureTuning { + fn default() -> Self { + Self { + touch_slop: px(8.), + multi_tap_interval: Duration::from_millis(400), + multi_tap_slop: px(16.), + long_press_duration: Duration::from_millis(500), + scroll_physics: ScrollPhysics::ios(), + min_fling_velocity: 50., + } + } +} + +/// How free scrolling decelerates after a fling. +/// +/// This models deceleration only. Boundary behavior — bouncing, edge glow, +/// clamping — is the scroll container's policy: the container is the one that +/// knows its extents. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum ScrollPhysics { + /// Exponential velocity decay, the `UIScrollView` model: + /// `velocity(t) = v₀ · decay_per_msᵐˢ`. + Exponential { + /// Per-millisecond velocity decay factor. `UIScrollView`'s normal + /// deceleration rate is `0.998`. + decay_per_ms: f32, + }, + /// The friction spline of Android's `OverScroller`: fling duration and + /// distance follow a logarithmic deceleration law, and progress along + /// the fling follows a cubic-Bezier ease-out curve. Transcribed from + /// AOSP's `SplineOverScroller` (Apache-2.0). + FrictionSpline { + /// The scroll friction coefficient; + /// `ViewConfiguration.getScrollFriction()` is `0.015` on Android. + friction: f32, + /// Pixels per physical inch of the display, in the coordinate space + /// the fling runs in. Android folds display density into its + /// deceleration coefficient, so the same finger speed flings + /// further in pixels on a denser screen. + pixels_per_inch: f32, + }, +} + +impl ScrollPhysics { + /// iOS scroll feel: `UIScrollView`'s normal deceleration rate. + pub fn ios() -> Self { + Self::Exponential { + decay_per_ms: 0.998, + } + } + + /// Android scroll feel: `OverScroller` with stock friction, at Android's + /// nominal density of 160 density-independent pixels per inch — the + /// right pairing when fling distances are in logical pixels. Platforms + /// that fling in physical pixels, or know the display's true density in + /// their logical space, should construct + /// [`ScrollPhysics::FrictionSpline`] directly. + pub fn android() -> Self { + Self::FrictionSpline { + friction: 0.015, + pixels_per_inch: 160., + } + } + + /// How long a fling released at `speed` pixels per second coasts before + /// it stops. + fn fling_duration(self, speed: f32) -> Duration { + match self { + Self::Exponential { decay_per_ms } => { + if speed <= MOMENTUM_STOP_VELOCITY { + return Duration::ZERO; + } + let milliseconds = (MOMENTUM_STOP_VELOCITY / speed).ln() / decay_per_ms.ln(); + Duration::from_secs_f32(milliseconds / 1000.) + } + Self::FrictionSpline { + friction, + pixels_per_inch, + } => { + if speed <= 0. { + return Duration::ZERO; + } + let deceleration = friction_spline::deceleration(speed, friction, pixels_per_inch); + let seconds = (deceleration / (friction_spline::deceleration_rate() - 1.)).exp(); + Duration::from_secs_f64(seconds) + } + } + } + + /// Distance traveled `elapsed` into a fling released at `speed` pixels + /// per second, in pixels along the fling direction. Evaluated in closed + /// form so the trajectory is independent of tick timing. + fn fling_distance(self, speed: f32, elapsed: Duration) -> f32 { + let duration = self.fling_duration(speed); + if duration.is_zero() { + return 0.; + } + let elapsed = elapsed.min(duration); + match self { + Self::Exponential { decay_per_ms } => { + // ∫₀ᵗ v₀·kᵐˢ dms, with speed converted to pixels per + // millisecond. + let milliseconds = elapsed.as_secs_f32() * 1000.; + (speed / 1000.) * (decay_per_ms.powf(milliseconds) - 1.) / decay_per_ms.ln() + } + Self::FrictionSpline { + friction, + pixels_per_inch, + } => { + let deceleration = friction_spline::deceleration(speed, friction, pixels_per_inch); + let rate = friction_spline::deceleration_rate(); + let total_distance = friction as f64 + * friction_spline::physical_coefficient(pixels_per_inch) + * (rate / (rate - 1.) * deceleration).exp(); + let progress = elapsed.as_secs_f64() / duration.as_secs_f64(); + total_distance as f32 * friction_spline::distance_coefficient(progress as f32) + } + } + } +} + +/// The fling model of Android's `OverScroller.SplineOverScroller`, +/// transcribed from AOSP (Apache-2.0). `SPLINE_TIME`, which AOSP uses for +/// programmatic scroll animations rather than flings, is intentionally not +/// transcribed. +mod friction_spline { + use std::sync::LazyLock; + + const NB_SAMPLES: usize = 100; + const INFLEXION: f32 = 0.35; + const START_TENSION: f32 = 0.5; + const END_TENSION: f32 = 1.0; + const P1: f32 = START_TENSION * INFLEXION; + const P2: f32 = 1.0 - END_TENSION * (1.0 - INFLEXION); + + /// Android's `DECELERATION_RATE`: `ln(0.78) / ln(0.9)`. + pub(super) fn deceleration_rate() -> f64 { + 0.78f64.ln() / 0.9f64.ln() + } + + /// `SPLINE_POSITION` from AOSP's static initializer: fractional fling + /// distance sampled at 100 evenly spaced fractions of the fling + /// duration, from a cubic Bezier with control points shaped by + /// `INFLEXION` and the start/end tensions. + static SPLINE_POSITION: LazyLock<[f32; NB_SAMPLES + 1]> = LazyLock::new(|| { + let mut spline_position = [0f32; NB_SAMPLES + 1]; + let mut x_min = 0f32; + for (i, sample) in spline_position.iter_mut().take(NB_SAMPLES).enumerate() { + let alpha = i as f32 / NB_SAMPLES as f32; + let mut x_max = 1f32; + let (x, coefficient) = loop { + let x = x_min + (x_max - x_min) / 2.; + let coefficient = 3. * x * (1. - x); + let time = coefficient * ((1. - x) * P1 + x * P2) + x * x * x; + if (time - alpha).abs() < 1e-5 { + break (x, coefficient); + } + if time > alpha { + x_max = x; + } else { + x_min = x; + } + }; + *sample = coefficient * ((1. - x) * START_TENSION + x) + x * x * x; + } + spline_position[NB_SAMPLES] = 1.; + spline_position + }); + + /// `SensorManager.GRAVITY_EARTH · 39.37 in/m · ppi · 0.84`, AOSP's + /// `mPhysicalCoeff`: gravity expressed in pixels, times an empirical + /// "look and feel" tuning factor. + pub(super) fn physical_coefficient(pixels_per_inch: f32) -> f64 { + 9.80665 * 39.37 * pixels_per_inch as f64 * 0.84 + } + + /// AOSP's `getSplineDeceleration`. + pub(super) fn deceleration(speed: f32, friction: f32, pixels_per_inch: f32) -> f64 { + (INFLEXION as f64 * speed as f64 + / (friction as f64 * physical_coefficient(pixels_per_inch))) + .ln() + } + + /// Fraction of the total fling distance covered at fraction `time` of + /// the fling duration: table lookup plus linear interpolation, as in + /// `SplineOverScroller.update`. + pub(super) fn distance_coefficient(time: f32) -> f32 { + if time >= 1. { + return 1.; + } + let index = ((NB_SAMPLES as f32 * time) as usize).min(NB_SAMPLES - 1); + let time_lower = index as f32 / NB_SAMPLES as f32; + let time_upper = (index + 1) as f32 / NB_SAMPLES as f32; + let distance_lower = SPLINE_POSITION[index]; + let distance_upper = SPLINE_POSITION[index + 1]; + let velocity_coefficient = (distance_upper - distance_lower) / (time_upper - time_lower); + distance_lower + (time - time_lower) * velocity_coefficient + } + + #[cfg(test)] + pub(super) fn bezier_time_and_position(parameter: f32) -> (f32, f32) { + let coefficient = 3. * parameter * (1. - parameter); + let cubed = parameter * parameter * parameter; + ( + coefficient * ((1. - parameter) * P1 + parameter * P2) + cubed, + coefficient * ((1. - parameter) * START_TENSION + parameter) + cubed, + ) + } + + #[cfg(test)] + pub(super) fn spline_position_samples() -> &'static [f32; NB_SAMPLES + 1] { + &SPLINE_POSITION + } +} + +/// The set of gesture kinds that participate in recognition. +/// +/// Used by [`PlatformGestures::native_recognizers`] to declare which gestures +/// the platform recognizes natively rather than leaving to gpui core's +/// portable recognizers. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct GestureKinds { + /// Tap (and multi-tap), surfaced as [`ClickEvent::Touch`](crate::ClickEvent). + pub tap: bool, + /// Long press, surfaced as [`LongPressEvent`]. + pub long_press: bool, + /// Pan/scroll (including fling momentum), surfaced as + /// [`ScrollWheelEvent`](crate::ScrollWheelEvent)s. + pub pan: bool, + /// Pinch to zoom, surfaced as [`PinchEvent`](crate::PinchEvent)s. + pub pinch: bool, +} + +impl GestureKinds { + /// No gestures; gpui core's portable recognizers handle everything. + pub const NONE: Self = Self { + tap: false, + long_press: false, + pan: false, + pinch: false, + }; + + /// All gesture kinds. + pub const ALL: Self = Self { + tap: true, + long_press: true, + pan: true, + pinch: true, + }; +} + +/// A direct touch drag claimed by an element before touch input becomes a tap, +/// long press, or scrolling gesture. +#[derive(Clone, Debug)] +pub struct TouchDragEvent { + /// The phase of the touch drag. + pub phase: TouchPhase, + /// The position where the touch started. + pub start_position: Point, + /// The touch's current position. + pub position: Point, +} + +impl Sealed for TouchDragEvent {} +impl InputEvent for TouchDragEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::TouchDrag(self) + } +} +impl GestureEvent for TouchDragEvent {} +impl MouseEvent for TouchDragEvent {} + +/// A phased long-press gesture recognized from a touch. +#[derive(Clone, Debug)] +pub struct LongPressEvent { + /// The phase of the long press. + pub phase: TouchPhase, + /// The position where the touch started. + pub start_position: Point, + /// The touch's current position. + pub position: Point, +} + +impl Default for LongPressEvent { + fn default() -> Self { + Self { + phase: TouchPhase::Started, + start_position: Point::default(), + position: Point::default(), + } + } +} + +impl Sealed for LongPressEvent {} +impl InputEvent for LongPressEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::LongPress(self) + } +} +impl GestureEvent for LongPressEvent {} +impl MouseEvent for LongPressEvent {} + +/// Platform gesture recognition services. +/// +/// If your mobile platform supports native gesture recognition, use this +/// to share it with GPUI. +pub trait PlatformGestures { + /// Feel constants for the portable recognizers on this platform. + fn tuning(&self) -> GestureTuning { + GestureTuning::default() + } + + /// The gesture kinds this platform recognizes natively. + fn native_recognizers(&self) -> GestureKinds { + GestureKinds::NONE + } +} + +/// A no-op [`PlatformGestures`] implementation: no native recognizers and +/// default tuning. Suitable for desktop platforms and tests. +pub struct NullPlatformGestures; + +impl PlatformGestures for NullPlatformGestures {} + +/// Ceiling on recognized fling velocity, in pixels per second (matches +/// Flutter's `kMaxFlingVelocity`). +const MAX_FLING_VELOCITY: f32 = 8000.; + +/// Momentum below this speed, in pixels per second, is imperceptible. The +/// exponential model, which never mathematically stops, treats reaching this +/// speed as the end of the fling. (The friction spline has a finite duration +/// of its own.) +const MOMENTUM_STOP_VELOCITY: f32 = 10.; + +/// How far back the release-velocity estimate looks. Samples older than this +/// reflect an earlier part of the gesture, not the speed at release. +const VELOCITY_WINDOW: Duration = Duration::from_millis(100); + +/// A pause between samples longer than this means the finger stopped: +/// anything before the pause describes an earlier motion, not the release +/// (Flutter's `kAssumePointerMoveStoppedMilliseconds`). Touch hardware +/// reports movement every 8–16ms while the finger is in motion. +const VELOCITY_ASSUME_STOPPED_GAP: Duration = Duration::from_millis(40); + +const VELOCITY_MAX_SAMPLES: usize = 20; + +/// The portable recognizer behind raw touch input: it watches the +/// [`TouchEvent`] stream for one touch at a time and resolves it into either +/// a tap or a pan, following the competition model described in the module +/// docs. Pans continue into post-release momentum when the touch lifts at +/// speed; the window drives that phase through [`Self::tick_momentum`]. +/// +/// Taps are currently surfaced as synthesized mouse presses rather than +/// [`ClickEvent::Touch`](crate::ClickEvent), which keeps every existing +/// mouse-driven behavior (click listeners, caret placement, double-tap +/// selection) working before elements grow a direct tap-delivery path. +/// Pinch recognition is not implemented yet, and additional touches are ignored +/// while one is being recognized. +pub(crate) struct TouchGestureRecognizer { + tuning: GestureTuning, + state: TouchGestureState, + momentum: Option, + last_tap: Option, +} + +/// A semantic event recognized from raw touches, ready to dispatch through +/// the window's existing input paths. +#[derive(Debug)] +pub(crate) enum RecognizedTouchGesture { + /// One step of a pan (or of its post-release momentum), delivered to + /// scroll listeners at the pan's starting position. + Scroll(ScrollWheelEvent), + /// A recognized tap, delivered as a synthesized mouse press and release. + Tap { + down: MouseDownEvent, + up: MouseUpEvent, + }, + TouchDrag(TouchDragEvent), + LongPress(LongPressEvent), +} + +enum TouchGestureState { + Idle, + /// The touch is still within `touch_slop` of where it started: it can + /// still resolve into either a tap or a pan. + Pending { + touch: ActiveTouch, + deadline: Instant, + long_press_offered: bool, + touch_drag_offered: bool, + }, + /// The touch exceeded `touch_slop`: it is a pan until it ends, and its + /// movement flows out as scroll events. + Panning { + touch: ActiveTouch, + axis: Axis, + }, + LongPressing(ActiveTouch), + TouchDragging(ActiveTouch), +} + +struct ActiveTouch { + id: TouchId, + start_position: Point, + /// The latest raw position reported for this touch. + last_position: Point, + /// The position pan output has scrolled to so far. While panning this + /// may run ahead of the raw touch by the event's predicted position; + /// the release event targets the raw position again, so the total + /// scrolled distance always converges to the finger's actual travel. + emitted_position: Point, + /// Retained across stationary samples so prediction corrections cannot + /// reverse a pan when integer browser coordinates repeat. + last_movement: Point, + velocity_tracker: VelocityTracker, +} + +struct CompletedTap { + position: Point, + time: Instant, + count: usize, +} + +/// One fling in progress. The trajectory is a closed-form curve of elapsed +/// time — each tick evaluates it and emits the increment — so the fling is +/// exactly frame-rate independent: a stalled frame simply resumes further +/// along the same curve. +struct Momentum { + /// Where the pan started; synthesized scroll events keep hit-testing + /// there so momentum stays with the container the gesture began on. + position: Point, + /// Unit vector of the release velocity. + direction: Point, + axis: Axis, + /// Release speed in pixels per second. + speed: f32, + started_at: Instant, + duration: Duration, + /// Distance already emitted along `direction`, in pixels. + emitted_distance: f32, +} + +impl TouchGestureRecognizer { + pub(crate) fn new(tuning: GestureTuning) -> Self { + Self { + tuning, + state: TouchGestureState::Idle, + momentum: None, + last_tap: None, + } + } + + pub(crate) fn handle_event( + &mut self, + event: &TouchEvent, + ) -> SmallVec<[RecognizedTouchGesture; 2]> { + self.handle_event_at(event, Instant::now()) + } + + fn handle_event_at( + &mut self, + event: &TouchEvent, + now: Instant, + ) -> SmallVec<[RecognizedTouchGesture; 2]> { + let mut recognized = SmallVec::new(); + match event.phase { + TouchPhase::Started => { + let caught_fling = if let Some(momentum) = self.momentum.take() { + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + momentum.position, + Point::default(), + TouchPhase::Ended, + ))); + Some(momentum.axis) + } else { + None + }; + if matches!(self.state, TouchGestureState::Idle) { + let mut velocity_tracker = VelocityTracker::default(); + velocity_tracker.push(now, event.position); + let touch = ActiveTouch { + id: event.id, + start_position: event.position, + last_position: event.position, + emitted_position: event.position, + last_movement: Point::default(), + velocity_tracker, + }; + if let Some(axis) = caught_fling { + // A touch that catches a fling is a drag from the + // first pixel: waiting out the slop would freeze the + // content mid-scroll and then jump. It can also never + // be a tap; releasing it just leaves the content + // stopped, as on Android and iOS. + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + touch.start_position, + Point::default(), + TouchPhase::Started, + ))); + self.state = TouchGestureState::Panning { touch, axis }; + } else { + self.state = TouchGestureState::Pending { + touch, + deadline: now + self.tuning.long_press_duration, + long_press_offered: false, + touch_drag_offered: false, + }; + } + } + } + TouchPhase::Moved => match mem::replace(&mut self.state, TouchGestureState::Idle) { + TouchGestureState::Pending { + mut touch, + deadline, + long_press_offered, + touch_drag_offered, + } if touch.id == event.id => { + touch.velocity_tracker.push(now, event.position); + touch.last_position = event.position; + let accumulated = event.position - touch.start_position; + if accumulated.magnitude() > f64::from(self.tuning.touch_slop) { + // Carry the full movement so far into the first scroll + // step: the content catches up to the finger instead + // of losing the slop distance. + let mut target = event.predicted_position.unwrap_or(event.position); + let axis = dominant_axis(accumulated); + let mut delta = target - touch.start_position; + lock_delta_to_axis(&mut delta, axis); + touch.last_movement = accumulated; + lock_delta_to_axis(&mut touch.last_movement, axis); + if movements_oppose(delta, touch.last_movement) { + target = event.position; + delta = accumulated; + lock_delta_to_axis(&mut delta, axis); + } + touch.emitted_position = target; + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + touch.start_position, + delta, + TouchPhase::Started, + ))); + self.state = TouchGestureState::Panning { touch, axis }; + } else { + self.state = TouchGestureState::Pending { + touch, + deadline, + long_press_offered, + touch_drag_offered, + }; + } + } + TouchGestureState::Panning { mut touch, axis } if touch.id == event.id => { + let mut raw_delta = event.position - touch.last_position; + lock_delta_to_axis(&mut raw_delta, axis); + if raw_delta != Point::default() { + touch.last_movement = raw_delta; + } + touch.velocity_tracker.push(now, event.position); + touch.last_position = event.position; + let mut target = event.predicted_position.unwrap_or(event.position); + let mut delta = target - touch.emitted_position; + lock_delta_to_axis(&mut delta, axis); + // Prediction error must not reverse content while the raw + // touch still advances. Fall back to the raw position so a + // real finger reversal remains responsive. + if movements_oppose(delta, touch.last_movement) { + target = event.position; + delta = target - touch.emitted_position; + lock_delta_to_axis(&mut delta, axis); + if movements_oppose(delta, touch.last_movement) { + target = touch.emitted_position; + delta = Point::default(); + } + } + touch.emitted_position = target; + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + touch.start_position, + delta, + TouchPhase::Moved, + ))); + self.state = TouchGestureState::Panning { touch, axis }; + } + TouchGestureState::LongPressing(mut touch) if touch.id == event.id => { + touch.last_position = event.position; + recognized.push(RecognizedTouchGesture::LongPress(LongPressEvent { + phase: TouchPhase::Moved, + start_position: touch.start_position, + position: event.position, + })); + self.state = TouchGestureState::LongPressing(touch); + } + TouchGestureState::TouchDragging(mut touch) if touch.id == event.id => { + touch.last_position = event.position; + recognized.push(RecognizedTouchGesture::TouchDrag(TouchDragEvent { + phase: TouchPhase::Moved, + start_position: touch.start_position, + position: event.position, + })); + self.state = TouchGestureState::TouchDragging(touch); + } + other => self.state = other, + }, + TouchPhase::Ended => match mem::replace(&mut self.state, TouchGestureState::Idle) { + TouchGestureState::Pending { touch, .. } if touch.id == event.id => { + let tap_count = match &self.last_tap { + Some(tap) + if now.duration_since(tap.time) <= self.tuning.multi_tap_interval + && (event.position - tap.position).magnitude() + <= f64::from(self.tuning.multi_tap_slop) => + { + tap.count + 1 + } + _ => 1, + }; + self.last_tap = Some(CompletedTap { + position: event.position, + time: now, + count: tap_count, + }); + recognized.push(RecognizedTouchGesture::Tap { + down: MouseDownEvent { + button: MouseButton::Left, + position: event.position, + modifiers: Modifiers::default(), + click_count: tap_count, + first_mouse: false, + }, + up: MouseUpEvent { + button: MouseButton::Left, + position: event.position, + modifiers: Modifiers::default(), + click_count: tap_count, + }, + }); + } + TouchGestureState::Panning { touch, axis } if touch.id == event.id => { + // The release deliberately contributes no velocity + // sample: it usually repeats the last movement's position + // with a later timestamp, which would dilute the + // estimate. But a release long after the last movement + // means the finger had already stopped, so nothing + // flings. + let finger_stopped = + touch + .velocity_tracker + .latest_sample_time() + .is_none_or(|latest| { + now.duration_since(latest) > VELOCITY_ASSUME_STOPPED_GAP + }); + let mut velocity = if finger_stopped { + Point::default() + } else { + touch.velocity_tracker.velocity() + }; + match axis { + Axis::Vertical => velocity.x = 0., + Axis::Horizontal => velocity.y = 0., + } + let speed = (velocity.x.powi(2) + velocity.y.powi(2)).sqrt(); + let mut release_delta = event.position - touch.emitted_position; + lock_delta_to_axis(&mut release_delta, axis); + if speed >= self.tuning.min_fling_velocity { + let direction = point(velocity.x / speed, velocity.y / speed); + let speed = speed.min(MAX_FLING_VELOCITY); + let duration = self.tuning.scroll_physics.fling_duration(speed); + if !duration.is_zero() { + let total_distance = + self.tuning.scroll_physics.fling_distance(speed, duration); + // Prediction may have left the content ahead of + // the raw release position. Emitting that + // correction here would visibly snap the content + // backwards just as the fling launches, so fold + // it into the fling instead: start the curve + // already advanced by the overshoot, keeping the + // total travel exact while staying monotonic. + let overshoot = -(f32::from(release_delta.x) * direction.x + + f32::from(release_delta.y) * direction.y); + let emitted_distance = if overshoot > 0. && overshoot < total_distance { + release_delta += + point(px(direction.x * overshoot), px(direction.y * overshoot)); + overshoot + } else { + 0. + }; + self.momentum = Some(Momentum { + position: touch.start_position, + direction, + axis, + speed, + started_at: now, + duration, + emitted_distance, + }); + } + } + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + touch.start_position, + release_delta, + TouchPhase::Ended, + ))); + } + TouchGestureState::LongPressing(touch) if touch.id == event.id => { + recognized.push(RecognizedTouchGesture::LongPress(LongPressEvent { + phase: TouchPhase::Ended, + start_position: touch.start_position, + position: event.position, + })); + } + TouchGestureState::TouchDragging(touch) if touch.id == event.id => { + recognized.push(RecognizedTouchGesture::TouchDrag(TouchDragEvent { + phase: TouchPhase::Ended, + start_position: touch.start_position, + position: event.position, + })); + } + other => self.state = other, + }, + TouchPhase::Cancelled => match mem::replace(&mut self.state, TouchGestureState::Idle) { + TouchGestureState::Pending { touch, .. } if touch.id == event.id => {} + TouchGestureState::Panning { touch, .. } if touch.id == event.id => { + recognized.push(RecognizedTouchGesture::Scroll(scroll_event( + touch.start_position, + Point::default(), + TouchPhase::Cancelled, + ))); + } + TouchGestureState::LongPressing(touch) if touch.id == event.id => { + recognized.push(RecognizedTouchGesture::LongPress(LongPressEvent { + phase: TouchPhase::Cancelled, + start_position: touch.start_position, + position: event.position, + })); + } + TouchGestureState::TouchDragging(touch) if touch.id == event.id => { + recognized.push(RecognizedTouchGesture::TouchDrag(TouchDragEvent { + phase: TouchPhase::Cancelled, + start_position: touch.start_position, + position: event.position, + })); + } + other => self.state = other, + }, + } + recognized + } + + pub(crate) fn pending_long_press(&self) -> Option<(TouchId, Duration)> { + let TouchGestureState::Pending { + touch, + deadline, + long_press_offered: false, + .. + } = &self.state + else { + return None; + }; + Some((touch.id, deadline.saturating_duration_since(Instant::now()))) + } + + pub(crate) fn offer_long_press(&mut self, id: TouchId) -> Option { + let TouchGestureState::Pending { + touch, + long_press_offered, + .. + } = &mut self.state + else { + return None; + }; + if touch.id != id || *long_press_offered { + return None; + } + *long_press_offered = true; + Some(RecognizedTouchGesture::LongPress(LongPressEvent { + phase: TouchPhase::Started, + start_position: touch.start_position, + position: touch.last_position, + })) + } + + pub(crate) fn resolve_long_press(&mut self, claimed: bool) { + if !claimed { + return; + } + let state = mem::replace(&mut self.state, TouchGestureState::Idle); + self.state = match state { + TouchGestureState::Pending { + touch, + long_press_offered: true, + .. + } => TouchGestureState::LongPressing(touch), + other => other, + }; + } + + pub(crate) fn offer_touch_drag(&mut self, id: TouchId) -> Option { + let TouchGestureState::Pending { + touch, + touch_drag_offered, + .. + } = &mut self.state + else { + return None; + }; + if touch.id != id || *touch_drag_offered { + return None; + } + *touch_drag_offered = true; + Some(RecognizedTouchGesture::TouchDrag(TouchDragEvent { + phase: TouchPhase::Started, + start_position: touch.start_position, + position: touch.last_position, + })) + } + + pub(crate) fn resolve_touch_drag(&mut self, claimed: bool) { + if !claimed { + return; + } + let state = mem::replace(&mut self.state, TouchGestureState::Idle); + self.state = match state { + TouchGestureState::Pending { + touch, + touch_drag_offered: true, + .. + } => TouchGestureState::TouchDragging(touch), + other => other, + }; + } + + pub(crate) fn has_momentum(&self) -> bool { + self.momentum.is_some() + } + + /// Advances post-fling momentum by one frame, returning the scroll step + /// to dispatch, or `None` when no momentum is in progress. The final step + /// carries [`TouchPhase::Ended`] to close the synthetic scroll stream. + pub(crate) fn tick_momentum(&mut self) -> Option { + self.tick_momentum_at(Instant::now()) + } + + fn tick_momentum_at(&mut self, now: Instant) -> Option { + let momentum = self.momentum.as_mut()?; + let elapsed = now.duration_since(momentum.started_at); + let distance = self + .tuning + .scroll_physics + .fling_distance(momentum.speed, elapsed); + // Prediction overshoot can start momentum ahead of its curve. Hold + // that position until the curve catches up instead of stepping back. + let step = (distance - momentum.emitted_distance).max(0.); + momentum.emitted_distance = momentum.emitted_distance.max(distance); + let delta = point( + px(momentum.direction.x * step), + px(momentum.direction.y * step), + ); + let position = momentum.position; + if elapsed >= momentum.duration { + self.momentum = None; + Some(RecognizedTouchGesture::Scroll(scroll_event( + position, + delta, + TouchPhase::Ended, + ))) + } else { + Some(RecognizedTouchGesture::Scroll(scroll_event( + position, + delta, + TouchPhase::Moved, + ))) + } + } +} + +fn scroll_event( + position: Point, + delta: Point, + touch_phase: TouchPhase, +) -> ScrollWheelEvent { + ScrollWheelEvent { + position, + delta: ScrollDelta::Pixels(delta), + modifiers: Modifiers::default(), + touch_phase, + } +} + +/// Estimates the velocity a touch had at its newest sample. +#[derive(Default)] +struct VelocityTracker { + samples: VecDeque<(Instant, Point)>, +} + +impl VelocityTracker { + fn push(&mut self, time: Instant, position: Point) { + self.samples.push_back((time, position)); + while self.samples.len() > VELOCITY_MAX_SAMPLES { + self.samples.pop_front(); + } + } + + fn latest_sample_time(&self) -> Option { + self.samples.back().map(|(time, _)| *time) + } + + /// The velocity at the newest sample, in pixels per second. + /// + /// Fits a second-degree polynomial by least squares over the trailing + /// [`VELOCITY_WINDOW`] and takes its derivative at the newest sample, + /// like Flutter's `VelocityTracker` and Android's `lsq2` strategy. An + /// endpoint difference over the same window would report the window's + /// *average* speed, which for a flick — still accelerating at lift-off — + /// is roughly half the speed the finger actually had at release. + fn velocity(&self) -> Point { + let Some((newest_time, _)) = self.samples.back() else { + return Point::default(); + }; + let mut times_seconds: SmallVec<[f64; VELOCITY_MAX_SAMPLES]> = SmallVec::new(); + let mut horizontal: SmallVec<[f64; VELOCITY_MAX_SAMPLES]> = SmallVec::new(); + let mut vertical: SmallVec<[f64; VELOCITY_MAX_SAMPLES]> = SmallVec::new(); + let mut previous_time = *newest_time; + for (time, position) in self.samples.iter().rev() { + let age = newest_time.duration_since(*time); + if age > VELOCITY_WINDOW + || previous_time.duration_since(*time) > VELOCITY_ASSUME_STOPPED_GAP + { + break; + } + previous_time = *time; + times_seconds.push(-age.as_secs_f64()); + horizontal.push(f64::from(f32::from(position.x))); + vertical.push(f64::from(f32::from(position.y))); + } + + let endpoint_estimate = |values: &[f64]| -> f32 { + let elapsed = -times_seconds.last().copied().unwrap_or(0.); + if elapsed <= f64::EPSILON { + return 0.; + } + ((values.first().copied().unwrap_or(0.) - values.last().copied().unwrap_or(0.)) + / elapsed) as f32 + }; + if times_seconds.len() < 3 { + return point(endpoint_estimate(&horizontal), endpoint_estimate(&vertical)); + } + point( + quadratic_velocity_at_newest(×_seconds, &horizontal).map_or_else( + || endpoint_estimate(&horizontal), + |velocity| velocity as f32, + ), + quadratic_velocity_at_newest(×_seconds, &vertical) + .map_or_else(|| endpoint_estimate(&vertical), |velocity| velocity as f32), + ) + } +} + +/// Least-squares fit of `value = a0 + a1·t + a2·t²` returning `a1`: the +/// fitted curve's velocity at `t = 0`, which callers place at the newest +/// sample. `None` when the samples are too degenerate to fit (all +/// simultaneous, for example). +fn quadratic_velocity_at_newest(times: &[f64], values: &[f64]) -> Option { + let count = times.len() as f64; + let (mut sum_t1, mut sum_t2, mut sum_t3, mut sum_t4) = (0., 0., 0., 0.); + let (mut sum_v, mut sum_vt, mut sum_vt2) = (0., 0., 0.); + for (&time, &value) in times.iter().zip(values) { + let time_squared = time * time; + sum_t1 += time; + sum_t2 += time_squared; + sum_t3 += time_squared * time; + sum_t4 += time_squared * time_squared; + sum_v += value; + sum_vt += value * time; + sum_vt2 += value * time_squared; + } + // Cramer's rule on the 3×3 normal equations, solved for the linear + // coefficient only. + let determinant = count * (sum_t2 * sum_t4 - sum_t3 * sum_t3) + - sum_t1 * (sum_t1 * sum_t4 - sum_t3 * sum_t2) + + sum_t2 * (sum_t1 * sum_t3 - sum_t2 * sum_t2); + if determinant.abs() < 1e-12 { + return None; + } + let linear_determinant = count * (sum_vt * sum_t4 - sum_t3 * sum_vt2) + - sum_v * (sum_t1 * sum_t4 - sum_t3 * sum_t2) + + sum_t2 * (sum_t1 * sum_vt2 - sum_vt * sum_t2); + Some(linear_determinant / determinant) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::point; + + #[test] + fn ongoing_scroll_locks_to_dominant_axis() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Started, now); + assert_eq!(ongoing_scroll.axis, Some(Axis::Horizontal)); + assert_eq!(horizontal_delta, point(px(10.), px(0.))); + + let mut continued_delta = point(px(3.), px(2.)); + ongoing_scroll.filter_at( + &mut continued_delta, + TouchPhase::Moved, + now + Duration::from_millis(1), + ); + assert_eq!(ongoing_scroll.axis, Some(Axis::Horizontal)); + assert_eq!(continued_delta, point(px(3.), px(0.))); + } + + #[test] + fn ongoing_scroll_unlocks_when_direction_changes() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Started, now); + + let mut vertical_delta = point(px(2.), px(10.)); + ongoing_scroll.filter_at( + &mut vertical_delta, + TouchPhase::Moved, + now + Duration::from_millis(1), + ); + assert_eq!(ongoing_scroll.axis, None); + assert_eq!(vertical_delta, point(px(2.), px(10.))); + } + + #[test] + fn ongoing_scroll_starts_new_gesture_at_timeout_boundary() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Moved, now); + + let mut vertical_delta = point(px(2.), px(10.)); + ongoing_scroll.filter_at( + &mut vertical_delta, + TouchPhase::Moved, + now + SCROLL_EVENT_SEPARATION, + ); + assert_eq!(ongoing_scroll.axis, Some(Axis::Vertical)); + assert_eq!(vertical_delta, point(px(0.), px(10.))); + } + + #[test] + fn ongoing_scroll_ignores_zero_delta_and_resets_when_ended() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Started, now); + + let mut zero_delta = Point::default(); + ongoing_scroll.filter_at( + &mut zero_delta, + TouchPhase::Ended, + now + Duration::from_millis(1), + ); + assert_eq!(ongoing_scroll.axis, None); + + let mut vertical_delta = point(px(2.), px(3.)); + ongoing_scroll.filter_at( + &mut vertical_delta, + TouchPhase::Moved, + now + Duration::from_millis(2), + ); + assert_eq!(ongoing_scroll.axis, Some(Axis::Vertical)); + assert_eq!(vertical_delta, point(px(0.), px(3.))); + } + + #[test] + fn ongoing_scroll_ignores_zero_delta_movement() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Started, now); + + let mut zero_delta = Point::default(); + ongoing_scroll.filter_at( + &mut zero_delta, + TouchPhase::Moved, + now + SCROLL_EVENT_SEPARATION, + ); + + let mut vertical_delta = point(px(2.), px(10.)); + ongoing_scroll.filter_at( + &mut vertical_delta, + TouchPhase::Moved, + now + SCROLL_EVENT_SEPARATION, + ); + assert_eq!(ongoing_scroll.axis, Some(Axis::Vertical)); + assert_eq!(vertical_delta, point(px(0.), px(10.))); + } + + #[test] + fn ongoing_scroll_supports_moved_only_platforms() { + let now = Instant::now(); + let mut ongoing_scroll = OngoingScroll::default(); + let mut horizontal_delta = point(px(10.), px(2.)); + ongoing_scroll.filter_at(&mut horizontal_delta, TouchPhase::Moved, now); + assert_eq!(ongoing_scroll.axis, Some(Axis::Horizontal)); + assert_eq!(horizontal_delta, point(px(10.), px(0.))); + } + + #[test] + fn touch_within_slop_resolves_to_tap() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + let recognized = + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 10., 10.), now); + assert!(recognized.is_empty()); + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 12., 11.), + now + Duration::from_millis(20), + ); + assert!(recognized.is_empty()); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 12., 11.), + now + Duration::from_millis(60), + ); + let [RecognizedTouchGesture::Tap { down, up }] = recognized.as_slice() else { + panic!("expected tap, got {recognized:?}"); + }; + assert_eq!(down.click_count, 1); + assert_eq!(down.position, point(px(12.), px(11.))); + assert_eq!(up.click_count, 1); + } + + #[test] + fn consecutive_taps_accumulate_tap_count() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + + recognizer.handle_event_at(&touch_event(TouchId(1), TouchPhase::Started, 10., 10.), now); + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Ended, 10., 10.), + now + Duration::from_millis(40), + ); + + let second_down = now + Duration::from_millis(200); + recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Started, 14., 10.), + second_down, + ); + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Ended, 14., 10.), + second_down + Duration::from_millis(40), + ); + let [RecognizedTouchGesture::Tap { down, .. }] = recognized.as_slice() else { + panic!("expected tap, got {recognized:?}"); + }; + assert_eq!(down.click_count, 2); + + let late_down = second_down + Duration::from_secs(2); + recognizer.handle_event_at( + &touch_event(TouchId(3), TouchPhase::Started, 14., 10.), + late_down, + ); + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(3), TouchPhase::Ended, 14., 10.), + late_down + Duration::from_millis(40), + ); + let [RecognizedTouchGesture::Tap { down, .. }] = recognized.as_slice() else { + panic!("expected tap, got {recognized:?}"); + }; + assert_eq!(down.click_count, 1); + } + + #[test] + fn touch_beyond_slop_resolves_to_pan() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 120.), + now + Duration::from_millis(16), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Started); + assert_eq!(scroll.position, point(px(100.), px(100.))); + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(20.))); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 135.), + now + Duration::from_millis(32), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Moved); + assert_eq!(scroll.position, point(px(100.), px(100.))); + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(15.))); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 100., 135.), + now + Duration::from_millis(48), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Ended); + } + + #[test] + fn touch_pan_stays_locked_to_its_initial_dominant_axis() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 104., 120.), + now + Duration::from_millis(16), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(20.))); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 134., 125.), + now + Duration::from_millis(32), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(5.))); + } + + #[test] + fn touch_pan_locks_to_horizontal_axis() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 120., 104.), + now + Duration::from_millis(16), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(20.), px(0.))); + } + + #[test] + fn predicted_positions_lead_the_pan_but_totals_converge_on_release() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + + // The first pan step scrolls to the predicted position, not the raw one. + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 120.); + moved.predicted_position = Some(point(px(106.), px(128.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(16)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(28.))); + + // The next step is measured from where the previous prediction left + // the content, so an overshoot is paid back here. + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 130.); + moved.predicted_position = Some(point(px(104.), px(134.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(32)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(6.))); + + // A release without a fling (the finger stopped long before lifting) + // targets the raw position: the total scrolled distance equals the + // finger's actual travel despite the predictions. + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 100., 130.), + now + Duration::from_millis(120), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Ended); + assert!(!recognizer.has_momentum()); + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(-4.))); + } + + #[test] + fn predicted_positions_do_not_emit_false_reversals() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 120.); + moved.predicted_position = Some(point(px(100.), px(130.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(16)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(30.))); + + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 125.); + moved.predicted_position = Some(point(px(100.), px(127.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(32)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!( + scroll.delta.pixel_delta(px(16.)), + Point::::default() + ); + + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 125.); + moved.predicted_position = Some(point(px(100.), px(126.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(40)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!( + scroll.delta.pixel_delta(px(16.)), + Point::::default() + ); + + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 132.); + moved.predicted_position = Some(point(px(100.), px(136.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(48)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(6.))); + + let mut moved = touch_event(touch, TouchPhase::Moved, 100., 124.); + moved.predicted_position = Some(point(px(100.), px(140.))); + let recognized = recognizer.handle_event_at(&moved, now + Duration::from_millis(64)); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(-12.))); + } + + #[test] + fn predicted_overshoot_folds_into_the_fling_without_scrolling_backwards() { + let now = Instant::now(); + let mut total_with_prediction = 0f32; + let mut total_without_prediction = 0f32; + for use_prediction in [true, false] { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let mut total = 0f32; + let mut drain = |recognized: &[RecognizedTouchGesture], upward_only: bool| { + for gesture in recognized { + let RecognizedTouchGesture::Scroll(scroll) = gesture else { + panic!("expected scroll, got {gesture:?}"); + }; + let delta = scroll.delta.pixel_delta(px(16.)).y; + if upward_only { + assert!( + delta <= px(0.), + "content moved backwards by {delta:?} during an upward gesture" + ); + } + total += f32::from(delta); + } + }; + + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Started, 100., 500.), + now, + ); + for step in 1..=5u64 { + let raw_y = 500. - step as f32 * 40.; + let mut moved = touch_event(TouchId(1), TouchPhase::Moved, 100., raw_y); + if use_prediction { + moved.predicted_position = Some(point(px(100.), px(raw_y - 25.))); + } + let recognized = + recognizer.handle_event_at(&moved, now + Duration::from_millis(step * 16)); + drain(&recognized, use_prediction); + } + // The release leaves the emitted position 25px ahead of the raw + // one; with prediction the correction must not scroll backwards. + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Ended, 100., 300.), + now + Duration::from_millis(90), + ); + drain(&recognized, use_prediction); + assert!(recognizer.has_momentum()); + let mut tick = now + Duration::from_millis(91); + while recognizer.has_momentum() { + if let Some(gesture) = recognizer.tick_momentum_at(tick) { + drain(&[gesture], use_prediction); + } + tick += Duration::from_millis(16); + } + + if use_prediction { + total_with_prediction = total; + } else { + total_without_prediction = total; + } + } + // Folding the overshoot into the fling redistributes the travel but + // must not change where the content comes to rest. + assert!( + (total_with_prediction - total_without_prediction).abs() < 0.01, + "totals diverged: {total_with_prediction} vs {total_without_prediction}" + ); + } + + #[test] + fn fast_release_starts_momentum_that_decays_to_a_stop() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 300.), now); + for step in 1..=5 { + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 300. - step as f32 * 20.), + now + Duration::from_millis(step * 16), + ); + } + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 100., 200.), + now + Duration::from_millis(6 * 16), + ); + assert!(recognizer.has_momentum()); + + let tick = now + Duration::from_millis(6 * 16 + 16); + let recognized = recognizer.tick_momentum_at(tick); + let Some(RecognizedTouchGesture::Scroll(scroll)) = recognized else { + panic!("expected momentum scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Moved); + assert_eq!(scroll.position, point(px(100.), px(300.))); + let delta = scroll.delta.pixel_delta(px(16.)); + assert!( + delta.y < px(0.), + "momentum should continue upward, got {delta:?}" + ); + // The least-squares fit may leave float residue on the motionless axis. + assert!( + delta.x.abs() < px(0.001), + "expected no x motion, got {delta:?}" + ); + + let mut last_phase = TouchPhase::Moved; + let mut ticks = 0; + let mut time = tick; + while recognizer.has_momentum() { + time += Duration::from_millis(16); + ticks += 1; + assert!(ticks < 1000, "momentum never stopped"); + if let Some(RecognizedTouchGesture::Scroll(scroll)) = recognizer.tick_momentum_at(time) + { + last_phase = scroll.touch_phase; + } + } + assert_eq!(last_phase, TouchPhase::Ended); + assert!(recognizer.tick_momentum_at(time).is_none()); + } + + #[test] + fn diagonal_release_flings_only_on_locked_axis() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 300.), now); + for step in 1..=5 { + let recognized = recognizer.handle_event_at( + &touch_event( + touch, + TouchPhase::Moved, + 100. + step as f32 * 3., + 300. - step as f32 * 20., + ), + now + Duration::from_millis(step * 16), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.delta.pixel_delta(px(16.)).x, px(0.)); + } + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 115., 200.), + now + Duration::from_millis(6 * 16), + ); + assert!(recognizer.has_momentum()); + + let mut time = now + Duration::from_millis(6 * 16); + while recognizer.has_momentum() { + time += Duration::from_millis(16); + if let Some(RecognizedTouchGesture::Scroll(scroll)) = recognizer.tick_momentum_at(time) + { + let delta = scroll.delta.pixel_delta(px(16.)); + assert_eq!(delta.x, px(0.)); + assert!(delta.y <= px(0.)); + } + } + } + + #[test] + fn slow_release_does_not_start_momentum() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 300.), now); + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 280.), + now + Duration::from_millis(16), + ); + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 279.), + now + Duration::from_millis(500), + ); + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 100., 279.), + now + Duration::from_millis(600), + ); + assert!(!recognizer.has_momentum()); + } + + #[test] + fn new_touch_interrupts_momentum() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Started, 100., 300.), + now, + ); + for step in 1..=3 { + recognizer.handle_event_at( + &touch_event( + TouchId(1), + TouchPhase::Moved, + 100., + 300. - step as f32 * 33., + ), + now + Duration::from_millis(step * 16), + ); + } + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Ended, 100., 200.), + now + Duration::from_millis(64), + ); + assert!(recognizer.has_momentum()); + + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Started, 100., 200.), + now + Duration::from_millis(200), + ); + assert!(!recognizer.has_momentum()); + let [ + RecognizedTouchGesture::Scroll(closing), + RecognizedTouchGesture::Scroll(opening), + ] = recognized.as_slice() + else { + panic!("expected closing and opening scrolls, got {recognized:?}"); + }; + assert_eq!(closing.touch_phase, TouchPhase::Ended); + assert!(closing.delta.pixel_delta(px(16.)).is_zero()); + assert_eq!(opening.touch_phase, TouchPhase::Started); + assert!(opening.delta.pixel_delta(px(16.)).is_zero()); + } + + #[test] + fn catching_a_fling_pans_immediately_and_never_taps() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Started, 100., 300.), + now, + ); + for step in 1..=3 { + recognizer.handle_event_at( + &touch_event( + TouchId(1), + TouchPhase::Moved, + 100., + 300. - step as f32 * 33., + ), + now + Duration::from_millis(step * 16), + ); + } + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Ended, 100., 200.), + now + Duration::from_millis(64), + ); + assert!(recognizer.has_momentum()); + + recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Started, 100., 200.), + now + Duration::from_millis(200), + ); + + // A movement well within the slop scrolls immediately. + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Moved, 100., 197.), + now + Duration::from_millis(216), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Moved); + assert_eq!(scroll.delta.pixel_delta(px(16.)), point(px(0.), px(-3.))); + + // Releasing the catch is not a tap. + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Ended, 100., 197.), + now + Duration::from_millis(232), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Ended); + } + + #[test] + fn cancelled_pan_emits_cancelled_scroll_and_no_tap() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + let touch = TouchId(1); + + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 100., 150.), + now + Duration::from_millis(16), + ); + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Cancelled, 100., 150.), + now + Duration::from_millis(32), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected cancelled scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Cancelled); + assert!(!recognizer.has_momentum()); + + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 100., 100.), now); + let recognized = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Cancelled, 100., 102.), + now + Duration::from_millis(16), + ); + assert!(recognized.is_empty(), "cancelled tap must not click"); + } + + #[test] + fn concurrent_touches_are_ignored_while_one_is_active() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let now = Instant::now(); + + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Started, 100., 100.), + now, + ); + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Started, 200., 200.), + now + Duration::from_millis(8), + ); + assert!(recognized.is_empty()); + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Moved, 200., 300.), + now + Duration::from_millis(16), + ); + assert!(recognized.is_empty()); + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(2), TouchPhase::Ended, 200., 300.), + now + Duration::from_millis(24), + ); + assert!(recognized.is_empty()); + + // The first touch still resolves normally. + let recognized = recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Moved, 100., 150.), + now + Duration::from_millis(32), + ); + let [RecognizedTouchGesture::Scroll(scroll)] = recognized.as_slice() else { + panic!("expected scroll, got {recognized:?}"); + }; + assert_eq!(scroll.touch_phase, TouchPhase::Started); + } + + #[test] + fn spline_position_table_matches_the_bezier_curve() { + let samples = friction_spline::spline_position_samples(); + // AOSP's initializer solves sample 0 numerically like every other + // sample, so it lands within solver tolerance of zero, not at zero. + assert!(samples[0].abs() < 1e-4); + assert_eq!(samples[100], 1.); + for window in samples.windows(2) { + assert!(window[0] < window[1], "table must be strictly increasing"); + } + // Each table entry must lie on the defining parametric Bezier: for + // sample i there must be a curve parameter whose time component is + // i/100 and whose position component is the stored value. + for (i, &stored_position) in samples.iter().enumerate().take(100) { + let alpha = i as f32 / 100.; + let (mut lower, mut upper) = (0f32, 1f32); + for _ in 0..50 { + let middle = (lower + upper) / 2.; + let (time, _) = friction_spline::bezier_time_and_position(middle); + if time > alpha { + upper = middle; + } else { + lower = middle; + } + } + let (time, position) = friction_spline::bezier_time_and_position((lower + upper) / 2.); + assert!( + (time - alpha).abs() < 1e-4, + "sample {i}: time {time} != {alpha}" + ); + assert!( + (position - stored_position).abs() < 1e-3, + "sample {i}: position {position} != stored {stored_position}" + ); + } + } + + #[test] + fn fling_curves_are_sane_for_both_physics() { + for physics in [ScrollPhysics::ios(), ScrollPhysics::android()] { + let slow = physics.fling_duration(500.); + let fast = physics.fling_duration(4000.); + assert!(slow > Duration::ZERO, "{physics:?}"); + assert!(fast > slow, "faster flings must coast longer: {physics:?}"); + + let halfway = physics.fling_distance(4000., fast / 2); + let total = physics.fling_distance(4000., fast); + assert!(halfway > 0. && halfway < total, "{physics:?}"); + assert!( + physics.fling_distance(4000., fast * 2) == total, + "distance must not grow past the fling duration: {physics:?}" + ); + assert!( + physics.fling_distance(4000., fast) > physics.fling_distance(500., slow), + "faster flings must travel further: {physics:?}" + ); + } + } + + #[test] + fn momentum_is_frame_rate_independent() { + // The same fling ticked at 60Hz and as one huge stalled frame must + // cover identical ground. + let total_distance_with_tick_length = |tick: Duration| -> f32 { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning { + scroll_physics: ScrollPhysics::android(), + ..GestureTuning::default() + }); + let now = Instant::now(); + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Started, 100., 500.), + now, + ); + for step in 1..=3 { + recognizer.handle_event_at( + &touch_event( + TouchId(1), + TouchPhase::Moved, + 100., + 500. - step as f32 * 40., + ), + now + Duration::from_millis(step * 16), + ); + } + recognizer.handle_event_at( + &touch_event(TouchId(1), TouchPhase::Ended, 100., 380.), + now + Duration::from_millis(64), + ); + assert!(recognizer.has_momentum()); + + let mut total = 0f32; + let mut time = now + Duration::from_millis(64); + let mut guard = 0; + while recognizer.has_momentum() { + time += tick; + guard += 1; + assert!(guard < 10_000, "momentum never stopped"); + if let Some(RecognizedTouchGesture::Scroll(scroll)) = + recognizer.tick_momentum_at(time) + { + total += f32::from(scroll.delta.pixel_delta(px(16.)).y); + } + } + total + }; + + let smooth = total_distance_with_tick_length(Duration::from_millis(16)); + let stalled = total_distance_with_tick_length(Duration::from_secs(10)); + assert!( + (smooth - stalled).abs() < 0.01, + "expected identical fling distance, got {smooth} vs {stalled}" + ); + } + + #[test] + fn flick_velocity_reflects_release_speed_not_window_average() { + // A uniformly accelerating flick: position grows quadratically, so + // the speed at the newest sample (2·k·t) is twice the window + // average (k·t). The estimator must report the former. + let mut velocity_tracker = VelocityTracker::default(); + let start = Instant::now(); + for step in 0..=6 { + let t = step as f32 * 0.016; + velocity_tracker.push( + start + Duration::from_millis(step * 16), + point(px(0.), px(1000. * t * t)), + ); + } + let velocity = velocity_tracker.velocity(); + let release_speed = 2. * 1000. * 0.096; + assert!( + (velocity.y - release_speed).abs() < 1., + "expected ≈{release_speed} px/s at release, got {} px/s", + velocity.y + ); + assert_eq!(velocity.x, 0.); + } + + #[test] + fn samples_before_a_pause_do_not_contribute_velocity() { + // Fast motion, then a hold longer than the stopped-finger gap, then + // a slow nudge: only the motion after the pause describes the + // release. + let mut velocity_tracker = VelocityTracker::default(); + let start = Instant::now(); + velocity_tracker.push(start, point(px(0.), px(0.))); + velocity_tracker.push(start + Duration::from_millis(16), point(px(0.), px(50.))); + velocity_tracker.push(start + Duration::from_millis(80), point(px(0.), px(52.))); + velocity_tracker.push(start + Duration::from_millis(96), point(px(0.), px(54.))); + let velocity = velocity_tracker.velocity(); + assert!( + velocity.y < 200., + "pre-pause motion leaked into the estimate: {} px/s", + velocity.y + ); + } + + #[test] + fn claimed_touch_drag_emits_phased_stream_without_pan_or_tap() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 10., 20.), now); + let Some(RecognizedTouchGesture::TouchDrag(started)) = recognizer.offer_touch_drag(touch) + else { + panic!("expected touch drag"); + }; + assert_eq!(started.phase, TouchPhase::Started); + assert_eq!(started.start_position, point(px(10.), px(20.))); + recognizer.resolve_touch_drag(true); + + let moved = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 40., 50.), + now + Duration::from_millis(10), + ); + let [RecognizedTouchGesture::TouchDrag(moved)] = moved.as_slice() else { + panic!("expected moved touch drag, got {moved:?}"); + }; + assert_eq!(moved.phase, TouchPhase::Moved); + assert_eq!(moved.position, point(px(40.), px(50.))); + + let ended = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 45., 55.), + now + Duration::from_millis(20), + ); + let [RecognizedTouchGesture::TouchDrag(ended)] = ended.as_slice() else { + panic!("expected ended touch drag, got {ended:?}"); + }; + assert_eq!(ended.phase, TouchPhase::Ended); + assert_eq!(ended.position, point(px(45.), px(55.))); + } + + #[test] + fn unclaimed_touch_drag_remains_a_pan_candidate() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 0., 0.), now); + assert!(recognizer.offer_touch_drag(touch).is_some()); + recognizer.resolve_touch_drag(false); + + let moved = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 20., 0.), + now + Duration::from_millis(10), + ); + assert!(matches!( + moved.as_slice(), + [RecognizedTouchGesture::Scroll(ScrollWheelEvent { + touch_phase: TouchPhase::Started, + .. + })] + )); + } + + #[test] + fn claimed_long_press_emits_phased_stream_without_tap() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 10., 20.), now); + let Some(RecognizedTouchGesture::LongPress(started)) = recognizer.offer_long_press(touch) + else { + panic!("expected long press"); + }; + assert_eq!(started.phase, TouchPhase::Started); + assert_eq!(started.start_position, point(px(10.), px(20.))); + recognizer.resolve_long_press(true); + + let moved = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 12., 21.), + now + Duration::from_millis(510), + ); + let [RecognizedTouchGesture::LongPress(moved)] = moved.as_slice() else { + panic!("expected moved long press, got {moved:?}"); + }; + assert_eq!(moved.phase, TouchPhase::Moved); + + let ended = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 12., 21.), + now + Duration::from_millis(520), + ); + let [RecognizedTouchGesture::LongPress(ended)] = ended.as_slice() else { + panic!("expected ended long press, got {ended:?}"); + }; + assert_eq!(ended.phase, TouchPhase::Ended); + } + + #[test] + fn unclaimed_long_press_remains_a_tap_candidate() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 10., 20.), now); + assert!(recognizer.offer_long_press(touch).is_some()); + recognizer.resolve_long_press(false); + + let ended = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Ended, 10., 20.), + now + Duration::from_millis(510), + ); + assert!(matches!( + ended.as_slice(), + [RecognizedTouchGesture::Tap { .. }] + )); + } + + #[test] + fn unclaimed_long_press_can_still_become_a_pan() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 0., 0.), now); + assert!(recognizer.offer_long_press(touch).is_some()); + recognizer.resolve_long_press(false); + + let moved = recognizer.handle_event_at( + &touch_event(touch, TouchPhase::Moved, 20., 0.), + now + Duration::from_millis(510), + ); + assert!(matches!( + moved.as_slice(), + [RecognizedTouchGesture::Scroll(ScrollWheelEvent { + touch_phase: TouchPhase::Started, + .. + })] + )); + } + + #[test] + fn long_press_offer_is_one_shot_and_specific_to_pending_touch() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + recognizer.handle_event(&touch_event(touch, TouchPhase::Started, 0., 0.)); + + assert!( + recognizer + .handle_event(&touch_event(TouchId(2), TouchPhase::Moved, 20., 0.)) + .is_empty() + ); + assert!(recognizer.offer_long_press(TouchId(2)).is_none()); + assert!(recognizer.offer_long_press(touch).is_some()); + assert!(recognizer.offer_long_press(touch).is_none()); + } + + #[test] + fn long_press_cannot_be_offered_after_pending_touch_resolves() { + for phase in [TouchPhase::Ended, TouchPhase::Cancelled, TouchPhase::Moved] { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + let now = Instant::now(); + recognizer.handle_event_at(&touch_event(touch, TouchPhase::Started, 0., 0.), now); + let position = if phase == TouchPhase::Moved { 20. } else { 0. }; + recognizer.handle_event_at( + &touch_event(touch, phase, position, 0.), + now + Duration::from_millis(10), + ); + assert!(recognizer.offer_long_press(touch).is_none()); + } + } + + #[test] + fn claimed_long_press_emits_cancelled_for_its_touch_only() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + recognizer.handle_event(&touch_event(touch, TouchPhase::Started, 4., 5.)); + assert!(recognizer.offer_long_press(touch).is_some()); + recognizer.resolve_long_press(true); + + assert!( + recognizer + .handle_event(&touch_event(TouchId(2), TouchPhase::Cancelled, 9., 9.)) + .is_empty() + ); + let cancelled = recognizer.handle_event(&touch_event(touch, TouchPhase::Cancelled, 6., 7.)); + let [RecognizedTouchGesture::LongPress(cancelled)] = cancelled.as_slice() else { + panic!("expected cancelled long press, got {cancelled:?}"); + }; + assert_eq!(cancelled.phase, TouchPhase::Cancelled); + assert_eq!(cancelled.start_position, point(px(4.), px(5.))); + assert_eq!(cancelled.position, point(px(6.), px(7.))); + } + + #[test] + fn unrelated_touch_cannot_end_or_cancel_pending_touch() { + for phase in [TouchPhase::Ended, TouchPhase::Cancelled] { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let touch = TouchId(1); + recognizer.handle_event(&touch_event(touch, TouchPhase::Started, 4., 5.)); + + assert!( + recognizer + .handle_event(&touch_event(TouchId(2), phase, 9., 9.)) + .is_empty() + ); + assert!(recognizer.offer_long_press(touch).is_some()); + } + } + + #[test] + fn completed_touch_id_cannot_claim_replacement_touch() { + let mut recognizer = TouchGestureRecognizer::new(GestureTuning::default()); + let completed_touch = TouchId(1); + let replacement_touch = TouchId(2); + recognizer.handle_event(&touch_event(completed_touch, TouchPhase::Started, 0., 0.)); + recognizer.handle_event(&touch_event(completed_touch, TouchPhase::Cancelled, 0., 0.)); + recognizer.handle_event(&touch_event(replacement_touch, TouchPhase::Started, 5., 5.)); + + assert!(recognizer.offer_long_press(completed_touch).is_none()); + assert!(recognizer.offer_long_press(replacement_touch).is_some()); + } + + fn touch_event(id: TouchId, phase: TouchPhase, x: f32, y: f32) -> TouchEvent { + TouchEvent { + id, + phase, + position: point(px(x), px(y)), + predicted_position: None, + force: None, + } + } +} diff --git a/vendor/gpui-pre/src/global.rs b/vendor/gpui-pre/src/global.rs new file mode 100644 index 00000000..a16934c1 --- /dev/null +++ b/vendor/gpui-pre/src/global.rs @@ -0,0 +1,75 @@ +use crate::{App, BorrowAppContext}; + +/// A marker trait for types that can be stored in GPUI's global state. +/// +/// This trait exists to provide type-safe access to globals by ensuring only +/// types that implement [`Global`] can be used with the accessor methods. For +/// example, trying to access a global with a type that does not implement +/// [`Global`] will result in a compile-time error. +/// +/// Implement this on types you want to store in the context as a global. +/// +/// ## Restricting Access to Globals +/// +/// In some situations you may need to store some global state, but want to +/// restrict access to reading it or writing to it. +/// +/// In these cases, Rust's visibility system can be used to restrict access to +/// a global value. For example, you can create a private struct that implements +/// [`Global`] and holds the global state. Then create a newtype struct that wraps +/// the global type and create custom accessor methods to expose the desired subset +/// of operations. +pub trait Global: 'static { + // This trait is intentionally left empty, by virtue of being a marker trait. + // + // Use additional traits with blanket implementations to attach functionality + // to types that implement `Global`. +} + +/// A trait for reading a global value from the context. +pub trait ReadGlobal { + /// Returns the global instance of the implementing type. + /// + /// Panics if a global for that type has not been assigned. + fn global(cx: &App) -> &Self; +} + +impl ReadGlobal for T { + fn global(cx: &App) -> &Self { + cx.global::() + } +} + +/// A trait for updating a global value in the context. +pub trait UpdateGlobal { + /// Updates the global instance of the implementing type using the provided closure. + /// + /// This method provides the closure with mutable access to the context and the global simultaneously. + fn update_global(cx: &mut C, update: F) -> R + where + C: BorrowAppContext, + F: FnOnce(&mut Self, &mut C) -> R; + + /// Set the global instance of the implementing type. + fn set_global(cx: &mut C, global: Self) + where + C: BorrowAppContext; +} + +impl UpdateGlobal for T { + #[track_caller] + fn update_global(cx: &mut C, update: F) -> R + where + C: BorrowAppContext, + F: FnOnce(&mut Self, &mut C) -> R, + { + cx.update_global(update) + } + + fn set_global(cx: &mut C, global: Self) + where + C: BorrowAppContext, + { + cx.set_global(global) + } +} diff --git a/vendor/gpui-pre/src/gpui.rs b/vendor/gpui-pre/src/gpui.rs new file mode 100644 index 00000000..d4da5aa3 --- /dev/null +++ b/vendor/gpui-pre/src/gpui.rs @@ -0,0 +1,402 @@ +#![doc = include_str!("../README.md")] +#![warn(missing_docs)] +#![allow(clippy::type_complexity)] // Not useful, GPUI makes heavy use of callbacks +#![allow(clippy::collapsible_else_if)] // False positives in platform specific code +#![allow(unused_mut)] // False positives in platform specific code + +extern crate self as gpui; +#[macro_use] +mod action; +mod app; + +mod arena; +mod asset_cache; +mod assets; +mod bounds_tree; +mod color; +/// The default colors used by GPUI. +pub mod colors; +#[cfg(feature = "profiler")] +mod debug_overlay; +mod element; +mod elements; +mod executor; +mod platform_scheduler; +pub(crate) use platform_scheduler::PlatformScheduler; +mod geometry; +mod gestures; +mod global; +mod input; +mod inspector; +mod interactive; +mod key_dispatch; +mod keymap; +mod path_builder; +mod platform; +pub mod prelude; +/// Profiling utilities for task, frame, and thread performance tracking. +pub mod profiler; +#[cfg(any( + test, + target_os = "windows", + target_os = "linux", + target_family = "wasm", + feature = "test-support", + feature = "bench-support" +))] +#[expect(missing_docs)] +pub mod queue; +/// A seeded, mutable element tree for benchmarks and tests of GPUI rendering. +#[cfg(any(test, feature = "bench-support"))] +pub mod randomized_element_tree; +mod scene; +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +mod seeds; +mod shared_uri; +mod spring; +mod style; +mod styled; +mod subscription; +mod svg_renderer; +mod tab_stop; +mod taffy; +#[cfg(any(test, feature = "test-support"))] +pub mod test; +mod text_system; +mod util; +mod view; +mod window; + +#[cfg(any(test, feature = "test-support"))] +pub use proptest; +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +pub use seeds::calculate_seeds; + +#[cfg(doc)] +pub mod _accessibility; +#[cfg(doc)] +pub mod _ownership_and_data_flow; + +/// Do not touch, here be dragons for use by gpui_macros and such. +#[doc(hidden)] +pub mod private { + pub use anyhow; + pub use inventory; + pub use rand; + pub use schemars; + pub use serde; + pub use serde_json; +} + +mod seal { + /// A mechanism for restricting implementations of a trait to only those in GPUI. + /// See: + pub trait Sealed {} +} + +pub use accesskit; +pub use accesskit::Action as AccessibleAction; +pub use accesskit::{Orientation, Role, Toggled}; +pub use action::*; +pub use anyhow::Result; +pub use app::*; +pub(crate) use arena::*; +pub use asset_cache::*; +pub use assets::*; +pub use color::*; +pub use ctor::ctor; +#[cfg(feature = "profiler")] +pub use debug_overlay::*; +pub use element::*; +pub use elements::*; +pub use executor::*; +pub use geometry::*; +pub use gestures::*; +pub use global::*; +pub use gpui_macros::{ + AppContext, IntoElement, Render, VisualContext, bench, property_test, register_action, test, +}; +pub use spring::*; + +/// Defines a Criterion benchmark group for benchmarks annotated with [`gpui::bench`]. +/// +/// This mirrors `criterion::criterion_group!`, but the group measures with the +/// `gpui::BenchMeasurement` configured by `BENCH_MEASUREMENT` (see +/// `BenchMeasurement::from_env`). By default Criterion analyzes wall time +/// while retired instructions, cycles, IPC, context switches, and the other +/// counters this machine supports are printed per iteration in the GPUI bench +/// report. `BENCH_MEASUREMENT=instructions` makes Criterion analyze +/// process-wide instructions instead, `foreground-instructions` the benchmark +/// thread's alone, and `wall-time` disables all counters. A +/// `config = ...` expression may set any other Criterion option; its +/// measurement is replaced. To measure with something else, call +/// `criterion::criterion_group!` directly with +/// `config = criterion::Criterion::default().with_measurement(gpui::BenchMeasurement::new(...))`. +/// +/// [`gpui::bench`]: crate::bench +#[macro_export] +macro_rules! bench_group { + (name = $name:ident; config = $config:expr; targets = $($target:path),+ $(,)?) => { + criterion::criterion_group! { + name = $name; + config = ($config).with_measurement($crate::BenchMeasurement::from_env_or_exit()); + targets = $($target),+ + } + }; + ($name:ident, $($target:path),+ $(,)?) => { + $crate::bench_group! { + name = $name; + config = criterion::Criterion::default(); + targets = $($target),+ + } + }; +} + +/// Defines the entry point for GPUI Criterion benchmark groups. +/// +/// This mirrors `criterion::criterion_main!` so GPUI benchmark files can keep the +/// same shape as ordinary Criterion benchmarks. It also installs +/// [`CountingAllocator`] as the binary's global allocator, so reports include +/// heap allocations per iteration. It wraps the system allocator by default; +/// `allocator = Path;` wraps another unit-struct allocator instead, e.g. to +/// compare allocators, which pay the same small counting cost: +/// +/// ```ignore +/// gpui::bench_main!(allocator = mimalloc::MiMalloc; benches); +/// ``` +/// +/// `allocator = none;` installs no global allocator, leaving Rust's default and +/// dropping the allocation metrics from reports. +#[macro_export] +macro_rules! bench_main { + (allocator = none; $($groups:tt)*) => { + criterion::criterion_main!($($groups)*); + }; + (allocator = $allocator:path; $($groups:tt)*) => { + #[global_allocator] + static GPUI_BENCH_ALLOCATOR: $crate::CountingAllocator<$allocator> = + $crate::CountingAllocator::new($allocator); + + criterion::criterion_main!($($groups)*); + }; + ($($groups:tt)*) => { + $crate::bench_main!(allocator = ::std::alloc::System; $($groups)*); + }; +} +pub use gpui_shared_string::*; +pub use gpui_util::arc_cow::ArcCow; +pub use http_client; +pub use input::*; +pub use inspector::*; +pub use interactive::*; +use key_dispatch::*; +pub use keymap::*; +pub use path_builder::*; +pub use platform::*; +pub use profiler::*; +#[cfg(any(target_os = "windows", target_os = "linux", target_family = "wasm"))] +pub use queue::{PriorityQueueReceiver, PriorityQueueSender}; +pub use refineable::*; +pub use scene::*; +pub use shared_uri::*; +use std::{any::Any, future::Future}; +pub use style::*; +pub use styled::*; +pub use subscription::*; +pub use svg_renderer::*; +pub(crate) use tab_stop::*; +use taffy::TaffyLayoutEngine; +pub use taffy::{AvailableSpace, LayoutId}; +#[cfg(any(test, feature = "test-support"))] +pub use test::*; +pub use text_system::*; +pub use util::{FutureExt, Timeout}; +pub use view::*; +pub use window::*; + +#[cfg(not(target_family = "wasm"))] +pub use pollster::block_on; + +/// The context trait, allows the different contexts in GPUI to be used +/// interchangeably for certain operations. +pub trait AppContext { + /// Create a new entity in the app context. + #[expect( + clippy::wrong_self_convention, + reason = "`App::new` is an ubiquitous function for creating entities" + )] + fn new(&mut self, build_entity: impl FnOnce(&mut Context) -> T) -> Entity; + + /// Reserve a slot for a entity to be inserted later. + /// The returned [Reservation] allows you to obtain the [EntityId] for the future entity. + fn reserve_entity(&mut self) -> Reservation; + + /// Insert a new entity in the app context based on a [Reservation] previously obtained from [`reserve_entity`]. + /// + /// [`reserve_entity`]: Self::reserve_entity + fn insert_entity( + &mut self, + reservation: Reservation, + build_entity: impl FnOnce(&mut Context) -> T, + ) -> Entity; + + /// Update a entity in the app context. + fn update_entity( + &mut self, + handle: &Entity, + update: impl FnOnce(&mut T, &mut Context) -> R, + ) -> R + where + T: 'static; + + /// Update a entity in the app context. + fn as_mut<'a, T>(&'a mut self, handle: &Entity) -> GpuiBorrow<'a, T> + where + T: 'static; + + /// Read a entity from the app context. + fn read_entity(&self, handle: &Entity, read: impl FnOnce(&T, &App) -> R) -> R + where + T: 'static; + + /// Update a window for the given handle. + fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result + where + F: FnOnce(AnyView, &mut Window, &mut App) -> T; + + /// Run `f` against the entity's *current* window — the most recently + /// rendered window that referenced the entity. Returns `None` if the + /// entity has no current window or that window is unavailable. See + /// [`App::with_window`] for the underlying lookup. + fn with_window( + &mut self, + entity_id: EntityId, + f: impl FnOnce(&mut Window, &mut App) -> R, + ) -> Option; + + /// Read a window off of the application context. + fn read_window( + &self, + window: &WindowHandle, + read: impl FnOnce(Entity, &App) -> R, + ) -> Result + where + T: 'static; + + /// Spawn a future on a background thread + fn background_spawn(&self, future: impl Future + Send + 'static) -> Task + where + R: Send + 'static; + + /// Read a global from this app context + fn read_global(&self, callback: impl FnOnce(&G, &App) -> R) -> R + where + G: Global; +} + +/// Returned by [Context::reserve_entity] to later be passed to [Context::insert_entity]. +/// Allows you to obtain the [EntityId] for a entity before it is created. +pub struct Reservation(pub(crate) Slot); + +impl Reservation { + /// Returns the [EntityId] that will be associated with the entity once it is inserted. + pub fn entity_id(&self) -> EntityId { + self.0.entity_id() + } +} + +/// This trait is used for the different visual contexts in GPUI that +/// require a window to be present. +pub trait VisualContext: AppContext { + /// The result type for window operations. + type Result; + + /// Returns the handle of the window associated with this context. + fn window_handle(&self) -> AnyWindowHandle; + + /// Update a view with the given callback + fn update_window_entity( + &mut self, + entity: &Entity, + update: impl FnOnce(&mut T, &mut Window, &mut Context) -> R, + ) -> Self::Result; + + /// Create a new entity, with access to `Window`. + fn new_window_entity( + &mut self, + build_entity: impl FnOnce(&mut Window, &mut Context) -> T, + ) -> Self::Result>; + + /// Replace the root view of a window with a new view. + fn replace_root_view( + &mut self, + build_view: impl FnOnce(&mut Window, &mut Context) -> V, + ) -> Self::Result> + where + V: 'static + Render; + + /// Focus a entity in the window, if it implements the [`Focusable`] trait. + fn focus(&mut self, entity: &Entity) -> Self::Result<()> + where + V: Focusable; +} + +/// A trait for tying together the types of a GPUI entity and the events it can +/// emit. +pub trait EventEmitter: 'static {} + +/// A helper trait for auto-implementing certain methods on contexts that +/// can be used interchangeably. +pub trait BorrowAppContext { + /// Set a global value on the context. + fn set_global(&mut self, global: T); + /// Updates the global state of the given type. + fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R + where + G: Global; + /// Updates the global state of the given type, creating a default if it didn't exist before. + fn update_default_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R + where + G: Global + Default; +} + +impl BorrowAppContext for C +where + C: std::borrow::BorrowMut, +{ + fn set_global(&mut self, global: G) { + self.borrow_mut().set_global(global) + } + + #[track_caller] + fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R + where + G: Global, + { + let mut global = self.borrow_mut().lease_global::(); + let result = f(&mut global, self); + self.borrow_mut().end_global_lease(global); + result + } + + fn update_default_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R + where + G: Global + Default, + { + self.borrow_mut().default_global::(); + self.update_global(f) + } +} + +/// Information about the GPU GPUI is running on. +#[derive(Default, Debug, serde::Serialize, serde::Deserialize, Clone)] +pub struct GpuSpecs { + /// Whether the GPU is really a fake (like `llvmpipe`) running on the CPU. + pub is_software_emulated: bool, + /// The name of the device, as reported by Vulkan. + pub device_name: String, + /// The name of the driver, as reported by Vulkan. + pub driver_name: String, + /// Further information about the driver, as reported by Vulkan. + pub driver_info: String, +} diff --git a/vendor/gpui-pre/src/input.rs b/vendor/gpui-pre/src/input.rs new file mode 100644 index 00000000..4167aa09 --- /dev/null +++ b/vendor/gpui-pre/src/input.rs @@ -0,0 +1,485 @@ +use crate::{ + App, Bounds, ClipboardItem, Context, Entity, InputHandler, Pixels, TextInputConfiguration, + UTF16Selection, Window, +}; +use std::ops::Range; + +/// Implement this trait to allow views to handle textual input when implementing an editor, field, etc. +/// +/// Once your view implements this trait, you can use it to construct an [`ElementInputHandler`]. +/// This input handler can then be assigned during paint by calling [`Window::handle_input`]. +/// +/// See [`InputHandler`] for details on how to implement each method. +pub trait EntityInputHandler: 'static + Sized { + /// See [`InputHandler::text_for_range`] for details + fn text_for_range( + &mut self, + range: Range, + adjusted_range: &mut Option>, + window: &mut Window, + cx: &mut Context, + ) -> Option; + + /// See [`InputHandler::selected_text_range`] for details + fn selected_text_range( + &mut self, + ignore_disabled_input: bool, + window: &mut Window, + cx: &mut Context, + ) -> Option; + + /// See [`InputHandler::marked_text_range`] for details + fn marked_text_range( + &self, + window: &mut Window, + cx: &mut Context, + ) -> Option>; + + /// See [`InputHandler::unmark_text`] for details + fn unmark_text(&mut self, window: &mut Window, cx: &mut Context); + + /// See [`InputHandler::paste`] for details + fn paste(&mut self, item: ClipboardItem, window: &mut Window, cx: &mut Context) { + if let Some(text) = item.text() { + self.replace_text_in_range(None, &text, window, cx); + } + } + + /// See [`InputHandler::replace_text_in_range`] for details + fn replace_text_in_range( + &mut self, + range: Option>, + text: &str, + window: &mut Window, + cx: &mut Context, + ); + + /// See [`InputHandler::replace_and_mark_text_in_range`] for details + fn replace_and_mark_text_in_range( + &mut self, + range: Option>, + new_text: &str, + new_selected_range: Option>, + window: &mut Window, + cx: &mut Context, + ); + + /// See [`InputHandler::bounds_for_range`] for details + fn bounds_for_range( + &mut self, + range_utf16: Range, + element_bounds: Bounds, + window: &mut Window, + cx: &mut Context, + ) -> Option>; + + /// See [`InputHandler::character_index_for_point`] for details + fn character_index_for_point( + &mut self, + point: crate::Point, + window: &mut Window, + cx: &mut Context, + ) -> Option; + + /// See [`InputHandler::set_selected_text_range`] for details + fn set_selected_text_range( + &mut self, + _range_utf16: Range, + _window: &mut Window, + _cx: &mut Context, + ) { + } + + /// See [`InputHandler::text_length_utf16`] for details + fn text_length_utf16( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + None + } + + /// See [`InputHandler::accepts_text_input`] for details + fn accepts_text_input(&self, _window: &mut Window, _cx: &mut Context) -> bool { + true + } + + /// See [`InputHandler::text_input_configuration`] for details + fn text_input_configuration( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> TextInputConfiguration { + TextInputConfiguration::default() + } + + /// See [`InputHandler::text_input_editable_range`] for details + fn text_input_editable_range( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> Option> { + None + } +} + +/// The canonical implementation of [`crate::PlatformInputHandler`]. Call [`Window::handle_input`] +/// with an instance during your element's paint. +pub struct ElementInputHandler { + view: Entity, + element_bounds: Bounds, +} + +impl ElementInputHandler { + /// Used in [`Element::paint`][element_paint] with the element's bounds, a `Window`, and a `App` context. + /// + /// [element_paint]: crate::Element::paint + pub fn new(element_bounds: Bounds, view: Entity) -> Self { + ElementInputHandler { + view, + element_bounds, + } + } +} + +impl InputHandler for ElementInputHandler { + fn selected_text_range( + &mut self, + ignore_disabled_input: bool, + window: &mut Window, + cx: &mut App, + ) -> Option { + self.view.update(cx, |view, cx| { + view.selected_text_range(ignore_disabled_input, window, cx) + }) + } + + fn marked_text_range(&mut self, window: &mut Window, cx: &mut App) -> Option> { + self.view + .update(cx, |view, cx| view.marked_text_range(window, cx)) + } + + fn text_for_range( + &mut self, + range_utf16: Range, + adjusted_range: &mut Option>, + window: &mut Window, + cx: &mut App, + ) -> Option { + self.view.update(cx, |view, cx| { + view.text_for_range(range_utf16, adjusted_range, window, cx) + }) + } + + fn replace_text_in_range( + &mut self, + replacement_range: Option>, + text: &str, + window: &mut Window, + cx: &mut App, + ) { + self.view.update(cx, |view, cx| { + view.replace_text_in_range(replacement_range, text, window, cx) + }); + } + + fn replace_and_mark_text_in_range( + &mut self, + range_utf16: Option>, + new_text: &str, + new_selected_range: Option>, + window: &mut Window, + cx: &mut App, + ) { + self.view.update(cx, |view, cx| { + view.replace_and_mark_text_in_range( + range_utf16, + new_text, + new_selected_range, + window, + cx, + ) + }); + } + + fn unmark_text(&mut self, window: &mut Window, cx: &mut App) { + self.view + .update(cx, |view, cx| view.unmark_text(window, cx)); + } + + fn paste(&mut self, item: ClipboardItem, window: &mut Window, cx: &mut App) { + self.view + .update(cx, |view, cx| view.paste(item, window, cx)); + } + + fn bounds_for_range( + &mut self, + range_utf16: Range, + window: &mut Window, + cx: &mut App, + ) -> Option> { + self.view.update(cx, |view, cx| { + view.bounds_for_range(range_utf16, self.element_bounds, window, cx) + }) + } + + fn character_index_for_point( + &mut self, + point: crate::Point, + window: &mut Window, + cx: &mut App, + ) -> Option { + self.view.update(cx, |view, cx| { + view.character_index_for_point(point, window, cx) + }) + } + + fn set_selected_text_range( + &mut self, + range_utf16: Range, + window: &mut Window, + cx: &mut App, + ) { + self.view.update(cx, |view, cx| { + view.set_selected_text_range(range_utf16, window, cx) + }) + } + + fn element_bounds(&mut self, _window: &mut Window, _cx: &mut App) -> Option> { + Some(self.element_bounds) + } + + fn text_length_utf16(&mut self, window: &mut Window, cx: &mut App) -> Option { + self.view + .update(cx, |view, cx| view.text_length_utf16(window, cx)) + } + + fn accepts_text_input(&mut self, window: &mut Window, cx: &mut App) -> bool { + self.view + .update(cx, |view, cx| view.accepts_text_input(window, cx)) + } + + fn prefers_ime_for_printable_keys(&mut self, window: &mut Window, cx: &mut App) -> bool { + self.view + .update(cx, |view, cx| view.accepts_text_input(window, cx)) + } + + fn text_input_configuration( + &mut self, + window: &mut Window, + cx: &mut App, + ) -> TextInputConfiguration { + self.view + .update(cx, |view, cx| view.text_input_configuration(window, cx)) + } + + fn text_input_editable_range( + &mut self, + window: &mut Window, + cx: &mut App, + ) -> Option> { + self.view + .update(cx, |view, cx| view.text_input_editable_range(window, cx)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AnyWindowHandle, AppContext as _, FocusHandle, InteractiveElement as _, IntoElement, + ParentElement as _, Render, Styled as _, TestAppContext, TextInputAction, + TextInputStateChange, canvas, div, + }; + + #[gpui::test] + fn text_input_configuration_and_focus_state_are_forwarded_on_change(cx: &mut TestAppContext) { + let custom = TextInputConfiguration { + autocorrect: true, + input_action: TextInputAction::Send, + ..Default::default() + }; + let window = cx.add_window({ + let custom = custom.clone(); + move |_, cx| ConfigurationTestView { + focus_handle: cx.focus_handle(), + configuration: custom, + } + }); + let view = window.root(cx).unwrap(); + let test_window = cx.test_window(window.into()); + let window = AnyWindowHandle::from(window); + let draw = |cx: &mut TestAppContext| { + cx.update_window(window, |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + }; + + // Nothing is focused, so the platform learns the default configuration. + draw(cx); + assert_eq!( + test_window.text_input_configurations(), + vec![TextInputConfiguration::default()] + ); + assert!(test_window.text_input_state_changes().is_empty()); + + // Focusing the view routes its configuration to the platform. + cx.update_window(window, |_, window, cx| { + let focus_handle = view.read(cx).focus_handle.clone(); + window.focus(&focus_handle, cx); + }) + .unwrap(); + draw(cx); + assert_eq!( + test_window.text_input_configurations(), + vec![TextInputConfiguration::default(), custom.clone()] + ); + assert_eq!( + test_window.text_input_state_changes(), + vec![TextInputStateChange::FocusGained] + ); + + // Redrawing without a change forwards nothing. + draw(cx); + assert_eq!(test_window.text_input_configurations().len(), 2); + assert_eq!(test_window.text_input_state_changes().len(), 1); + + // Changing the configuration forwards the new value. + let updated = TextInputConfiguration { + suggestions: true, + ..custom + }; + view.update(cx, { + let updated = updated.clone(); + |view, cx| { + view.configuration = updated; + cx.notify(); + } + }); + draw(cx); + assert_eq!( + test_window.text_input_configurations().last(), + Some(&updated) + ); + assert_eq!(test_window.text_input_configurations().len(), 3); + assert_eq!(test_window.text_input_state_changes().len(), 1); + + // Losing focus reverts the platform to the default configuration. + cx.update_window(window, |_, window, cx| window.blur(cx)) + .unwrap(); + draw(cx); + assert_eq!( + test_window.text_input_configurations().last(), + Some(&TextInputConfiguration::default()) + ); + assert_eq!(test_window.text_input_configurations().len(), 4); + assert_eq!( + test_window.text_input_state_changes(), + vec![ + TextInputStateChange::FocusGained, + TextInputStateChange::FocusLost + ] + ); + } + + struct ConfigurationTestView { + focus_handle: FocusHandle, + configuration: TextInputConfiguration, + } + + impl Render for ConfigurationTestView { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + let focus_handle = self.focus_handle.clone(); + div().size_full().track_focus(&self.focus_handle).child( + canvas( + |_, _, _| {}, + move |bounds, _, window, cx| { + window.handle_input( + &focus_handle, + ElementInputHandler::new(bounds, view), + cx, + ); + }, + ) + .size_full(), + ) + } + } + + impl EntityInputHandler for ConfigurationTestView { + fn text_for_range( + &mut self, + _range: std::ops::Range, + _adjusted_range: &mut Option>, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + None + } + + fn selected_text_range( + &mut self, + _ignore_disabled_input: bool, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + None + } + + fn marked_text_range( + &self, + _window: &mut Window, + _cx: &mut Context, + ) -> Option> { + None + } + + fn unmark_text(&mut self, _window: &mut Window, _cx: &mut Context) {} + + fn replace_text_in_range( + &mut self, + _range: Option>, + _text: &str, + _window: &mut Window, + _cx: &mut Context, + ) { + } + + fn replace_and_mark_text_in_range( + &mut self, + _range: Option>, + _new_text: &str, + _new_selected_range: Option>, + _window: &mut Window, + _cx: &mut Context, + ) { + } + + fn bounds_for_range( + &mut self, + _range_utf16: std::ops::Range, + _element_bounds: Bounds, + _window: &mut Window, + _cx: &mut Context, + ) -> Option> { + None + } + + fn character_index_for_point( + &mut self, + _point: crate::Point, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + None + } + + fn text_input_configuration( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> TextInputConfiguration { + self.configuration.clone() + } + } +} diff --git a/vendor/gpui-pre/src/inspector.rs b/vendor/gpui-pre/src/inspector.rs new file mode 100644 index 00000000..d353690e --- /dev/null +++ b/vendor/gpui-pre/src/inspector.rs @@ -0,0 +1,271 @@ +/// A unique identifier for an element that can be inspected. +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub struct InspectorElementId { + /// Stable part of the ID. + #[cfg(any(feature = "inspector", debug_assertions))] + pub path: std::rc::Rc, + /// Disambiguates elements that have the same path. + #[cfg(any(feature = "inspector", debug_assertions))] + pub instance_id: usize, +} + +impl Into for &InspectorElementId { + fn into(self) -> InspectorElementId { + self.clone() + } +} + +#[cfg(any(feature = "inspector", debug_assertions))] +pub use conditional::*; + +#[cfg(any(feature = "inspector", debug_assertions))] +mod conditional { + use super::*; + use crate::{AnyElement, App, Context, Empty, IntoElement, Render, Window}; + use collections::{FxHashMap, TypeIdHashMap, hash_map::Entry}; + use std::any::{Any, TypeId}; + + /// `GlobalElementId` qualified by source location of element construction. + #[derive(Debug, Eq, PartialEq, Hash)] + pub struct InspectorElementPath { + /// The path to the nearest ancestor element that has an `ElementId`. + #[cfg(any(feature = "inspector", debug_assertions))] + pub global_id: crate::GlobalElementId, + /// Source location where this element was constructed. + #[cfg(any(feature = "inspector", debug_assertions))] + pub source_location: &'static std::panic::Location<'static>, + } + + impl Clone for InspectorElementPath { + fn clone(&self) -> Self { + Self { + global_id: self.global_id.clone(), + source_location: self.source_location, + } + } + } + + impl Into for &InspectorElementPath { + fn into(self) -> InspectorElementPath { + self.clone() + } + } + + /// Function set on `App` to render the inspector UI. + pub type InspectorRenderer = + Box) -> AnyElement>; + + /// Manages inspector state - which element is currently selected and whether the inspector is + /// in picking mode. + pub struct Inspector { + active_element: Option, + pub(crate) pick_depth: Option, + renderers: TypeIdHashMap, + } + + struct InspectedElement { + id: InspectorElementId, + states: TypeIdHashMap>, + } + + impl InspectedElement { + fn new(id: InspectorElementId) -> Self { + InspectedElement { + id, + states: Default::default(), + } + } + } + + impl Inspector { + pub(crate) fn new() -> Self { + Self { + active_element: None, + pick_depth: Some(0.0), + renderers: TypeIdHashMap::default(), + } + } + + pub(crate) fn select(&mut self, id: InspectorElementId, window: &mut Window) { + self.set_active_element_id(id, window); + self.pick_depth = None; + } + + pub(crate) fn hover(&mut self, id: InspectorElementId, window: &mut Window) { + if self.is_picking() { + let changed = self.set_active_element_id(id, window); + if changed { + self.pick_depth = Some(0.0); + } + } + } + + pub(crate) fn set_active_element_id( + &mut self, + id: InspectorElementId, + window: &mut Window, + ) -> bool { + let changed = Some(&id) != self.active_element_id(); + if changed { + self.active_element = Some(InspectedElement::new(id)); + window.refresh(); + } + changed + } + + /// ID of the currently hovered or selected element. + pub fn active_element_id(&self) -> Option<&InspectorElementId> { + self.active_element.as_ref().map(|e| &e.id) + } + + pub(crate) fn with_active_element_state( + &mut self, + window: &mut Window, + f: impl FnOnce(&mut Option, &mut Window) -> R, + ) -> R { + let Some(active_element) = &mut self.active_element else { + return f(&mut None, window); + }; + + let type_id = TypeId::of::(); + let mut inspector_state = active_element + .states + .remove(&type_id) + .map(|state| *state.downcast().unwrap()); + + let result = f(&mut inspector_state, window); + + if let Some(inspector_state) = inspector_state { + active_element + .states + .insert(type_id, Box::new(inspector_state)); + } + + result + } + + /// Starts element picking mode, allowing the user to select elements by clicking. + pub fn start_picking(&mut self) { + self.pick_depth = Some(0.0); + } + + /// Returns whether the inspector is currently in picking mode. + pub fn is_picking(&self) -> bool { + self.pick_depth.is_some() + } + + /// Renders elements for all registered inspector states of the active inspector element. + pub fn render_inspector_states( + &mut self, + window: &mut Window, + cx: &mut Context, + ) -> Vec { + let mut elements = Vec::new(); + if let Some(active_element) = self.active_element.take() { + for (type_id, state) in &active_element.states { + let renderer = match self.renderers.entry(*type_id) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let Some(factory) = cx + .inspector_element_registry + .factories_by_type_id + .remove(type_id) + else { + continue; + }; + let renderer = factory(window, cx); + cx.inspector_element_registry + .factories_by_type_id + .insert(*type_id, factory); + entry.insert(renderer) + } + }; + elements.push(renderer( + active_element.id.clone(), + state.as_ref(), + window, + cx, + )); + } + + self.active_element = Some(active_element); + } + + elements + } + } + + impl Render for Inspector { + fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { + if let Some(inspector_renderer) = cx.inspector_renderer.take() { + let result = inspector_renderer(self, window, cx); + cx.inspector_renderer = Some(inspector_renderer); + result + } else { + Empty.into_any_element() + } + } + } + + #[derive(Default)] + pub(crate) struct InspectorElementRegistry { + factories_by_type_id: + FxHashMap InspectorElementRenderer>>, + } + + impl InspectorElementRegistry { + pub fn register( + &mut self, + factory: impl 'static + Fn(&mut Window, &mut App) -> F, + ) where + F: 'static + FnMut(InspectorElementId, &T, &mut Window, &mut App) -> R, + { + self.factories_by_type_id.insert( + TypeId::of::(), + Box::new(move |window, cx| { + let mut renderer = factory(window, cx); + Box::new(move |id, value, window, cx| { + let value = value + .downcast_ref() + .expect("registered inspector state type"); + renderer(id, value, window, cx).into_any_element() + }) + }), + ); + } + } + + type InspectorElementRenderer = + Box AnyElement>; +} + +/// Provides definitions used by `#[derive_inspector_reflection]`. +#[cfg(any(feature = "inspector", debug_assertions))] +pub mod inspector_reflection { + use std::any::Any; + + /// Reification of a function that has the signature `fn some_fn(T) -> T`. Provides the name, + /// documentation, and ability to invoke the function. + #[derive(Clone, Copy)] + pub struct FunctionReflection { + /// The name of the function + pub name: &'static str, + /// The method + pub function: fn(Box) -> Box, + /// Documentation for the function + pub documentation: Option<&'static str>, + /// `PhantomData` for the type of the argument and result + pub _type: std::marker::PhantomData, + } + + impl FunctionReflection { + /// Invoke this method on a value and return the result. + pub fn invoke(&self, value: T) -> T { + let boxed = Box::new(value) as Box; + let result = (self.function)(boxed); + *result + .downcast::() + .expect("Type mismatch in reflection invoke") + } + } +} diff --git a/vendor/gpui-pre/src/interactive.rs b/vendor/gpui-pre/src/interactive.rs new file mode 100644 index 00000000..913cf1ba --- /dev/null +++ b/vendor/gpui-pre/src/interactive.rs @@ -0,0 +1,971 @@ +use crate::{ + Bounds, Capslock, Context, Empty, IntoElement, Keystroke, LongPressEvent, Modifiers, Pixels, + Point, Render, TouchDragEvent, Window, point, seal::Sealed, +}; +use smallvec::SmallVec; +use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf}; + +/// An event from a platform input source. +pub trait InputEvent: Sealed + 'static { + /// Convert this event into the platform input enum. + fn to_platform_input(self) -> PlatformInput; +} + +/// A key event from the platform. +pub trait KeyEvent: InputEvent {} + +/// A mouse event from the platform. +pub trait MouseEvent: InputEvent {} + +/// A gesture event from the platform. +pub trait GestureEvent: InputEvent {} + +/// The key down event equivalent for the platform. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct KeyDownEvent { + /// The keystroke that was generated. + pub keystroke: Keystroke, + + /// Whether the key is currently held down. + pub is_held: bool, + + /// Whether to prefer character input over keybindings for this keystroke. + /// In some cases, like AltGr on Windows, modifiers are significant for character input. + pub prefer_character_input: bool, +} + +impl Sealed for KeyDownEvent {} +impl InputEvent for KeyDownEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::KeyDown(self) + } +} +impl KeyEvent for KeyDownEvent {} + +/// The key up event equivalent for the platform. +#[derive(Clone, Debug)] +pub struct KeyUpEvent { + /// The keystroke that was released. + pub keystroke: Keystroke, +} + +impl Sealed for KeyUpEvent {} +impl InputEvent for KeyUpEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::KeyUp(self) + } +} +impl KeyEvent for KeyUpEvent {} + +/// The modifiers changed event equivalent for the platform. +#[derive(Clone, Debug, Default)] +pub struct ModifiersChangedEvent { + /// The new state of the modifier keys + pub modifiers: Modifiers, + /// The new state of the capslock key + pub capslock: Capslock, +} + +impl Sealed for ModifiersChangedEvent {} +impl InputEvent for ModifiersChangedEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::ModifiersChanged(self) + } +} +impl KeyEvent for ModifiersChangedEvent {} + +impl Deref for ModifiersChangedEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +/// The phase of a touch motion event. +/// Based on the winit enum of the same name. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum TouchPhase { + /// The touch started. + Started, + /// The touch event is moving. + #[default] + Moved, + /// The touch phase has ended + Ended, + /// The touch was cancelled: the system took it and it will not end + /// normally. Consumers must fully unwind any in-progress interaction, + /// treating the touch as if it never committed. + Cancelled, +} + +/// Identifies one touch (finger or stylus contact) for its lifetime, from +/// [`TouchPhase::Started`] through [`TouchPhase::Ended`] or +/// [`TouchPhase::Cancelled`]. +/// +/// The value is opaque and assigned by the platform. A platform window must +/// not reuse an identifier for a later touch. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct TouchId(pub u64); + +/// A raw touch event from the platform. +/// +/// +/// Dispatch contract (core implementation pending): a touch is hit-tested +/// once, at [`TouchPhase::Started`], occlusion-aware; all subsequent events +/// for the same [`TouchId`] are delivered to the elements under the starting +/// position, even after the touch moves outside them. +#[derive(Clone, Debug, Default)] +pub struct TouchEvent { + /// Which touch this event belongs to. + pub id: TouchId, + /// The phase of the touch. + pub phase: TouchPhase, + /// The position of the touch in window coordinates. + pub position: Point, + /// Where the platform predicts the touch will be roughly one frame from + /// now, in the same coordinate space as `position`, when the platform + /// offers a prediction for a [`TouchPhase::Moved`] event. + /// + /// Best-effort latency compensation only: it may influence how far a + /// recognized pan scrolls within a frame, but never hit testing, gesture + /// classification, or velocity estimation, and any error it introduces + /// must be corrected by later events for the same touch. + pub predicted_position: Option>, + /// Normalized touch force in `0.0..=1.0`, if the hardware reports it. + pub force: Option, +} + +impl Sealed for TouchEvent {} +impl InputEvent for TouchEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::Touch(self) + } +} + +/// A mouse down event from the platform +#[derive(Clone, Debug, Default)] +pub struct MouseDownEvent { + /// Which mouse button was pressed. + pub button: MouseButton, + + /// The position of the mouse on the window. + pub position: Point, + + /// The modifiers that were held down when the mouse was pressed. + pub modifiers: Modifiers, + + /// The number of times the button has been clicked. + pub click_count: usize, + + /// Whether this is the first, focusing click. + pub first_mouse: bool, +} + +impl Sealed for MouseDownEvent {} +impl InputEvent for MouseDownEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::MouseDown(self) + } +} +impl MouseEvent for MouseDownEvent {} + +impl MouseDownEvent { + /// Returns true if this mouse up event should focus the element. + pub fn is_focusing(&self) -> bool { + match self.button { + MouseButton::Left => true, + _ => false, + } + } +} + +/// A mouse up event from the platform +#[derive(Clone, Debug, Default)] +pub struct MouseUpEvent { + /// Which mouse button was released. + pub button: MouseButton, + + /// The position of the mouse on the window. + pub position: Point, + + /// The modifiers that were held down when the mouse was released. + pub modifiers: Modifiers, + + /// The number of times the button has been clicked. + pub click_count: usize, +} + +impl Sealed for MouseUpEvent {} +impl InputEvent for MouseUpEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::MouseUp(self) + } +} + +impl MouseEvent for MouseUpEvent {} + +impl MouseUpEvent { + /// Returns true if this mouse up event should focus the element. + pub fn is_focusing(&self) -> bool { + match self.button { + MouseButton::Left => true, + _ => false, + } + } +} + +/// A click event, generated when a mouse button is pressed and released. +#[derive(Clone, Debug, Default)] +pub struct MouseClickEvent { + /// The mouse event when the button was pressed. + pub down: MouseDownEvent, + + /// The mouse event when the button was released. + pub up: MouseUpEvent, +} + +/// The stage of a pressure click event. +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub enum PressureStage { + /// No pressure. + #[default] + Zero, + /// Normal click pressure. + Normal, + /// High pressure, enough to trigger a force click. + Force, +} + +/// A mouse pressure event from the platform. Generated when a force-sensitive trackpad is pressed hard. +/// Currently only implemented for macOS trackpads. +#[derive(Debug, Clone, Default)] +pub struct MousePressureEvent { + /// Pressure of the current stage as a float between 0 and 1 + pub pressure: f32, + /// The pressure stage of the event. + pub stage: PressureStage, + /// The position of the mouse on the window. + pub position: Point, + /// The modifiers that were held down when the mouse pressure changed. + pub modifiers: Modifiers, +} + +impl Sealed for MousePressureEvent {} +impl InputEvent for MousePressureEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::MousePressure(self) + } +} +impl MouseEvent for MousePressureEvent {} + +/// A click event that was generated by a keyboard button being pressed and released. +#[derive(Clone, Debug, Default)] +pub struct KeyboardClickEvent { + /// The keyboard button that was pressed to trigger the click. + pub button: KeyboardButton, + + /// The bounds of the element that was clicked. + pub bounds: Bounds, +} + +/// A click event that was generated by a recognized tap gesture on a touch +/// screen. +#[derive(Clone, Debug, Default)] +pub struct TouchClickEvent { + /// The position of the tap in window coordinates. + pub position: Point, + /// The number of consecutive taps at this location (double tap = 2), + /// analogous to the mouse `click_count`. + pub tap_count: usize, + /// Whether this was a long press rather than a tap. Long presses are + /// touch's secondary activation: they are delivered to aux-click + /// listeners alongside right clicks, not to primary click listeners. + pub long_press: bool, +} + +/// A click event, generated when a mouse button or keyboard button is pressed and released, +/// or when a tap gesture is recognized on a touch screen. +#[derive(Clone, Debug)] +pub enum ClickEvent { + /// A click event trigger by a mouse button being pressed and released. + Mouse(MouseClickEvent), + /// A click event trigger by a keyboard button being pressed and released. + Keyboard(KeyboardClickEvent), + /// A click event triggered by a recognized tap gesture on a touch screen. + Touch(TouchClickEvent), +} + +impl Default for ClickEvent { + fn default() -> Self { + ClickEvent::Keyboard(KeyboardClickEvent::default()) + } +} + +impl ClickEvent { + /// Returns the modifiers that were held during the click event + /// + /// `Keyboard`: The keyboard click events never have modifiers. + /// `Mouse`: Modifiers that were held during the mouse key up event. + pub fn modifiers(&self) -> Modifiers { + match self { + // Click events are only generated from keyboard events _without any modifiers_, so we know the modifiers are always Default + ClickEvent::Keyboard(_) => Modifiers::default(), + // Click events on the web only reflect the modifiers for the keyup event, + // tested via observing the behavior of the `ClickEvent.shiftKey` field in Chrome 138 + // under various combinations of modifiers and keyUp / keyDown events. + ClickEvent::Mouse(event) => event.up.modifiers, + // Touch screens have no modifier keys. + ClickEvent::Touch(_) => Modifiers::default(), + } + } + + /// Returns the position of the click event + /// + /// `Keyboard`: The bottom left corner of the clicked hitbox + /// `Mouse`: The position of the mouse when the button was released. + /// `Touch`: The position of the tap. + pub fn position(&self) -> Point { + match self { + ClickEvent::Keyboard(event) => event.bounds.bottom_left(), + ClickEvent::Mouse(event) => event.up.position, + ClickEvent::Touch(event) => event.position, + } + } + + /// Returns the mouse position of the click event + /// + /// `Keyboard`: None + /// `Mouse`: The position of the mouse when the button was released. + /// `Touch`: None, touches are not mouse input and there is no cursor. + pub fn mouse_position(&self) -> Option> { + match self { + ClickEvent::Keyboard(_) => None, + ClickEvent::Mouse(event) => Some(event.up.position), + ClickEvent::Touch(_) => None, + } + } + + /// Returns if this was a right click + /// + /// `Keyboard`: false + /// `Mouse`: Whether the right button was pressed and released + pub fn is_right_click(&self) -> bool { + match self { + ClickEvent::Keyboard(_) => false, + ClickEvent::Mouse(event) => { + event.down.button == MouseButton::Right && event.up.button == MouseButton::Right + } + ClickEvent::Touch(_) => false, + } + } + + /// Returns if this was a middle click + /// + /// `Keyboard`: false + /// `Mouse`: Whether the middle button was pressed and released + pub fn is_middle_click(&self) -> bool { + match self { + ClickEvent::Keyboard(_) => false, + ClickEvent::Mouse(event) => { + event.down.button == MouseButton::Middle && event.up.button == MouseButton::Middle + } + ClickEvent::Touch(_) => false, + } + } + + /// Returns whether the click is a secondary activation, i.e. a context + /// menu trigger: a right click from a mouse (macOS ctrl-clicks arrive + /// already converted to right clicks by the platform layer), or a long + /// press on a touch screen. + pub fn is_secondary(&self) -> bool { + match self { + ClickEvent::Keyboard(_) => false, + ClickEvent::Mouse(event) => { + event.down.button == MouseButton::Right && event.up.button == MouseButton::Right + } + ClickEvent::Touch(event) => event.long_press, + } + } + + /// Returns whether the click was a standard click + /// + /// `Keyboard`: Always true + /// `Mouse`: Left button pressed and released + /// `Touch`: A tap, but not a long press + pub fn standard_click(&self) -> bool { + match self { + ClickEvent::Keyboard(_) => true, + ClickEvent::Mouse(event) => { + event.down.button == MouseButton::Left && event.up.button == MouseButton::Left + } + ClickEvent::Touch(event) => !event.long_press, + } + } + + /// Returns whether the click focused the element + /// + /// `Keyboard`: false, keyboard clicks only work if an element is already focused + /// `Mouse`: Whether this was the first focusing click + /// `Touch`: false, mobile windows are already active when tappable + pub fn first_focus(&self) -> bool { + match self { + ClickEvent::Keyboard(_) => false, + ClickEvent::Mouse(event) => event.down.first_mouse, + ClickEvent::Touch(_) => false, + } + } + + /// Returns the click count of the click event + /// + /// `Keyboard`: Always 1 + /// `Mouse`: Count of clicks from MouseUpEvent + /// `Touch`: Count of consecutive taps + pub fn click_count(&self) -> usize { + match self { + ClickEvent::Keyboard(_) => 1, + ClickEvent::Mouse(event) => event.up.click_count, + ClickEvent::Touch(event) => event.tap_count, + } + } + + /// Returns whether the click event is generated by a keyboard event + pub fn is_keyboard(&self) -> bool { + match self { + ClickEvent::Mouse(_) | ClickEvent::Touch(_) => false, + ClickEvent::Keyboard(_) => true, + } + } +} + +/// An enum representing the keyboard button that was pressed for a click event. +#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug, Default)] +pub enum KeyboardButton { + /// Enter key was clicked + #[default] + Enter, + /// Space key was clicked + Space, +} + +/// An enum representing the mouse button that was pressed. +#[derive(Hash, Default, PartialEq, Eq, Copy, Clone, Debug)] +pub enum MouseButton { + /// The left mouse button. + #[default] + Left, + + /// The right mouse button. + Right, + + /// The middle mouse button. + Middle, + + /// A navigation button, such as back or forward. + Navigate(NavigationDirection), +} + +impl MouseButton { + /// Get all the mouse buttons in a list. + pub fn all() -> Vec { + vec![ + MouseButton::Left, + MouseButton::Right, + MouseButton::Middle, + MouseButton::Navigate(NavigationDirection::Back), + MouseButton::Navigate(NavigationDirection::Forward), + ] + } +} + +/// A navigation direction, such as back or forward. +#[derive(Hash, Default, PartialEq, Eq, Copy, Clone, Debug)] +pub enum NavigationDirection { + /// The back button. + #[default] + Back, + + /// The forward button. + Forward, +} + +/// A mouse move event from the platform. +#[derive(Clone, Debug, Default)] +pub struct MouseMoveEvent { + /// The position of the mouse on the window. + pub position: Point, + + /// The mouse button that was pressed, if any. + pub pressed_button: Option, + + /// The modifiers that were held down when the mouse was moved. + pub modifiers: Modifiers, +} + +impl Sealed for MouseMoveEvent {} +impl InputEvent for MouseMoveEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::MouseMove(self) + } +} +impl MouseEvent for MouseMoveEvent {} + +impl MouseMoveEvent { + /// Returns true if the left mouse button is currently held down. + pub fn dragging(&self) -> bool { + self.pressed_button == Some(MouseButton::Left) + } +} + +/// A mouse wheel event from the platform. +#[derive(Clone, Debug, Default)] +pub struct ScrollWheelEvent { + /// The position of the mouse on the window. + pub position: Point, + + /// The change in scroll wheel position for this event. + pub delta: ScrollDelta, + + /// The modifiers that were held down when the mouse was moved. + pub modifiers: Modifiers, + + /// The phase of the touch event. + pub touch_phase: TouchPhase, +} + +impl Sealed for ScrollWheelEvent {} +impl InputEvent for ScrollWheelEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::ScrollWheel(self) + } +} +impl MouseEvent for ScrollWheelEvent {} + +impl Deref for ScrollWheelEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +/// The scroll delta for a scroll wheel event. +#[derive(Clone, Copy, Debug)] +pub enum ScrollDelta { + /// An exact scroll delta in pixels. + Pixels(Point), + /// An inexact scroll delta in lines. + Lines(Point), +} + +impl Default for ScrollDelta { + fn default() -> Self { + Self::Lines(Default::default()) + } +} + +/// A pinch gesture event from the platform, generated when the user performs +/// a pinch-to-zoom gesture (typically on a trackpad). +/// +#[derive(Clone, Debug, Default)] +pub struct PinchEvent { + /// The position of the pinch center on the window. + pub position: Point, + + /// The zoom delta for this event. + /// Positive values indicate zooming in, negative values indicate zooming out. + /// For example, 0.1 represents a 10% zoom increase. + pub delta: f32, + + /// The modifiers that were held down during the pinch gesture. + pub modifiers: Modifiers, + + /// The phase of the pinch gesture. + pub phase: TouchPhase, +} + +impl Sealed for PinchEvent {} +impl InputEvent for PinchEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::Pinch(self) + } +} +impl GestureEvent for PinchEvent {} +impl MouseEvent for PinchEvent {} + +impl Deref for PinchEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +impl ScrollDelta { + /// Returns true if this is a precise scroll delta in pixels. + pub fn precise(&self) -> bool { + match self { + ScrollDelta::Pixels(_) => true, + ScrollDelta::Lines(_) => false, + } + } + + /// Converts this scroll event into exact pixels. + pub fn pixel_delta(&self, line_height: Pixels) -> Point { + match self { + ScrollDelta::Pixels(delta) => *delta, + ScrollDelta::Lines(delta) => point(line_height * delta.x, line_height * delta.y), + } + } + + /// Combines two scroll deltas into one. + /// If the signs of the deltas are the same (both positive or both negative), + /// the deltas are added together. If the signs are opposite, the second delta + /// (other) is used, effectively overriding the first delta. + pub fn coalesce(self, other: ScrollDelta) -> ScrollDelta { + match (self, other) { + (ScrollDelta::Pixels(a), ScrollDelta::Pixels(b)) => { + let x = if a.x.signum() == b.x.signum() { + a.x + b.x + } else { + b.x + }; + + let y = if a.y.signum() == b.y.signum() { + a.y + b.y + } else { + b.y + }; + + ScrollDelta::Pixels(point(x, y)) + } + + (ScrollDelta::Lines(a), ScrollDelta::Lines(b)) => { + let x = if a.x.signum() == b.x.signum() { + a.x + b.x + } else { + b.x + }; + + let y = if a.y.signum() == b.y.signum() { + a.y + b.y + } else { + b.y + }; + + ScrollDelta::Lines(point(x, y)) + } + + _ => other, + } + } +} + +/// A mouse exit event from the platform, generated when the mouse leaves the window. +#[derive(Clone, Debug, Default)] +pub struct MouseExitEvent { + /// The position of the mouse relative to the window. + pub position: Point, + /// The mouse button that was pressed, if any. + pub pressed_button: Option, + /// The modifiers that were held down when the mouse was moved. + pub modifiers: Modifiers, +} + +impl Sealed for MouseExitEvent {} +impl InputEvent for MouseExitEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::MouseExited(self) + } +} + +impl MouseEvent for MouseExitEvent {} + +impl Deref for MouseExitEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +/// A collection of paths from the platform, such as from a file drop. +#[derive(Debug, Clone, Default, Eq, PartialEq)] +pub struct ExternalPaths(pub SmallVec<[PathBuf; 2]>); + +impl ExternalPaths { + /// Convert this collection of paths into a slice. + pub fn paths(&self) -> &[PathBuf] { + &self.0 + } +} + +/// Data offered to the platform when an internal drag leaves the window and is +/// promoted to a native drag session. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum ExternalDragPayload { + /// Real on-disk paths, handed to the platform as an outbound file drag. + Files(FileDragPaths), +} + +/// Paths handed to the platform for a native file drag. Directory metadata is +/// provided by the caller to avoid querying it when the platform drag starts. +#[derive(Debug, Clone, Default, Eq, PartialEq)] +pub struct FileDragPaths(SmallVec<[(PathBuf, bool); 2]>); + +impl FileDragPaths { + /// Creates a native file-drag payload from paths paired with whether each path is a directory. + pub fn new(entries: impl IntoIterator) -> Self { + Self(entries.into_iter().collect()) + } + + /// The dragged paths, each paired with whether it is a directory. + pub fn entries(&self) -> &[(PathBuf, bool)] { + &self.0 + } +} + +impl Render for ExternalPaths { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + // the platform will render icons for the dragged files + Empty + } +} + +/// A file drop event from the platform, generated when files are dragged and dropped onto the window. +#[derive(Debug, Clone)] +pub enum FileDropEvent { + /// The files have entered the window. + Entered { + /// The position of the mouse relative to the window. + position: Point, + /// The paths of the files that are being dragged. + paths: ExternalPaths, + }, + /// The files are being dragged over the window + Pending { + /// The position of the mouse relative to the window. + position: Point, + }, + /// The files have been dropped onto the window. + Submit { + /// The position of the mouse relative to the window. + position: Point, + }, + /// The user has stopped dragging the files over the window. + Exited, + /// The platform-owned drag session has ended. + Ended, +} + +impl Sealed for FileDropEvent {} +impl InputEvent for FileDropEvent { + fn to_platform_input(self) -> PlatformInput { + PlatformInput::FileDrop(self) + } +} +impl MouseEvent for FileDropEvent {} + +/// An enum corresponding to all kinds of platform input events. +#[derive(Clone, Debug)] +pub enum PlatformInput { + /// A key was pressed. + KeyDown(KeyDownEvent), + /// A key was released. + KeyUp(KeyUpEvent), + /// The keyboard modifiers were changed. + ModifiersChanged(ModifiersChangedEvent), + /// The mouse was pressed. + MouseDown(MouseDownEvent), + /// The mouse was released. + MouseUp(MouseUpEvent), + /// Mouse pressure. + MousePressure(MousePressureEvent), + /// The mouse was moved. + MouseMove(MouseMoveEvent), + /// The mouse exited the window. + MouseExited(MouseExitEvent), + /// The scroll wheel was used. + ScrollWheel(ScrollWheelEvent), + /// A pinch gesture was performed. + Pinch(PinchEvent), + /// A long-press gesture recognized from touch input. + LongPress(LongPressEvent), + /// A direct touch drag claimed by an element. + TouchDrag(TouchDragEvent), + /// Files were dragged and dropped onto the window. + FileDrop(FileDropEvent), + /// A raw touch event on a touch screen. + Touch(TouchEvent), +} + +impl PlatformInput { + pub(crate) fn mouse_event(&self) -> Option<&dyn Any> { + match self { + PlatformInput::KeyDown { .. } => None, + PlatformInput::KeyUp { .. } => None, + PlatformInput::ModifiersChanged { .. } => None, + PlatformInput::MouseDown(event) => Some(event), + PlatformInput::MouseUp(event) => Some(event), + PlatformInput::MouseMove(event) => Some(event), + PlatformInput::MousePressure(event) => Some(event), + PlatformInput::MouseExited(event) => Some(event), + PlatformInput::ScrollWheel(event) => Some(event), + PlatformInput::Pinch(event) => Some(event), + PlatformInput::LongPress(event) => Some(event), + PlatformInput::TouchDrag(event) => Some(event), + PlatformInput::FileDrop(event) => Some(event), + PlatformInput::Touch(_) => None, + } + } + + pub(crate) fn keyboard_event(&self) -> Option<&dyn Any> { + match self { + PlatformInput::KeyDown(event) => Some(event), + PlatformInput::KeyUp(event) => Some(event), + PlatformInput::ModifiersChanged(event) => Some(event), + PlatformInput::MouseDown(_) => None, + PlatformInput::MouseUp(_) => None, + PlatformInput::MouseMove(_) => None, + PlatformInput::MousePressure(_) => None, + PlatformInput::MouseExited(_) => None, + PlatformInput::ScrollWheel(_) => None, + PlatformInput::Pinch(_) => None, + PlatformInput::LongPress(_) => None, + PlatformInput::TouchDrag(_) => None, + PlatformInput::FileDrop(_) => None, + PlatformInput::Touch(_) => None, + } + } + + /// A short static name for this input's variant, for diagnostics and + /// telemetry. + pub fn kind_name(&self) -> &'static str { + match self { + PlatformInput::KeyDown(_) => "key_down", + PlatformInput::KeyUp(_) => "key_up", + PlatformInput::ModifiersChanged(_) => "modifiers_changed", + PlatformInput::MouseDown(_) => "mouse_down", + PlatformInput::MouseUp(_) => "mouse_up", + PlatformInput::MousePressure(_) => "mouse_pressure", + PlatformInput::MouseMove(_) => "mouse_move", + PlatformInput::MouseExited(_) => "mouse_exited", + PlatformInput::ScrollWheel(_) => "scroll_wheel", + PlatformInput::Pinch(_) => "pinch", + PlatformInput::LongPress(_) => "long_press", + PlatformInput::TouchDrag(_) => "touch_drag", + PlatformInput::FileDrop(_) => "file_drop", + PlatformInput::Touch(_) => "touch", + } + } + + /// Returns the touch event contained in this input, if any. + pub fn touch_event(&self) -> Option<&TouchEvent> { + match self { + PlatformInput::Touch(event) => Some(event), + _ => None, + } + } +} + +#[cfg(test)] +mod test { + + use crate::{ + self as gpui, AppContext as _, Context, FocusHandle, InteractiveElement, IntoElement, + KeyBinding, Keystroke, Modifiers, ParentElement, Render, TestAppContext, Window, div, + }; + + struct TestView { + saw_key_down: bool, + saw_action: bool, + focus_handle: FocusHandle, + } + + actions!(test_only, [TestAction]); + + impl Render for TestView { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + div().id("testview").child( + div() + .key_context("parent") + .on_key_down(cx.listener(|this, _, _, cx| { + cx.stop_propagation(); + this.saw_key_down = true + })) + .on_action(cx.listener(|this: &mut TestView, _: &TestAction, _, _| { + this.saw_action = true + })) + .child( + div() + .key_context("nested") + .track_focus(&self.focus_handle) + .into_element(), + ), + ) + } + } + + #[gpui::test] + fn test_on_events(cx: &mut TestAppContext) { + let window = cx.update(|cx| { + cx.open_window(Default::default(), |_, cx| { + cx.new(|cx| TestView { + saw_key_down: false, + saw_action: false, + focus_handle: cx.focus_handle(), + }) + }) + .unwrap() + }); + + cx.update(|cx| { + cx.bind_keys(vec![KeyBinding::new("ctrl-g", TestAction, Some("parent"))]); + }); + + window + .update(cx, |test_view, window, cx| { + window.focus(&test_view.focus_handle, cx) + }) + .unwrap(); + + cx.dispatch_keystroke(*window, Keystroke::parse("a").unwrap()); + cx.dispatch_keystroke(*window, Keystroke::parse("ctrl-g").unwrap()); + + window + .update(cx, |test_view, _, _| { + assert!(test_view.saw_key_down || test_view.saw_action); + assert!(test_view.saw_key_down); + assert!(test_view.saw_action); + }) + .unwrap(); + } + + #[gpui::test] + fn test_multi_modifier_gesture_does_not_dispatch_standalone_modifier_binding( + cx: &mut TestAppContext, + ) { + let (test_view, cx) = cx.add_window_view(|_, cx| TestView { + saw_key_down: false, + saw_action: false, + focus_handle: cx.focus_handle(), + }); + + cx.update(|_, cx| { + cx.bind_keys(vec![KeyBinding::new("shift", TestAction, None)]); + }); + test_view.update_in(cx, |test_view, window, cx| { + window.focus(&test_view.focus_handle, cx); + }); + + cx.simulate_modifiers_change(Modifiers::alt()); + cx.simulate_modifiers_change(Modifiers::alt() | Modifiers::shift()); + cx.simulate_modifiers_change(Modifiers::shift()); + cx.simulate_modifiers_change(Modifiers::none()); + assert!(!test_view.read_with(cx, |test_view, _| test_view.saw_action)); + + cx.simulate_modifiers_change(Modifiers::shift()); + cx.simulate_modifiers_change(Modifiers::none()); + assert!(test_view.read_with(cx, |test_view, _| test_view.saw_action)); + } +} diff --git a/vendor/gpui-pre/src/key_dispatch.rs b/vendor/gpui-pre/src/key_dispatch.rs new file mode 100644 index 00000000..2f755b1d --- /dev/null +++ b/vendor/gpui-pre/src/key_dispatch.rs @@ -0,0 +1,2196 @@ +//! KeyDispatch is where GPUI deals with binding actions to key events. +//! +//! The key pieces to making a key binding work are to define an action, +//! implement a method that takes that action as a type parameter, +//! and then to register the action during render on a focused node +//! with a keymap context: +//! +//! ```ignore +//! actions!(editor,[Undo, Redo]); +//! +//! impl Editor { +//! fn undo(&mut self, _: &Undo, _window: &mut Window, _cx: &mut Context) { ... } +//! fn redo(&mut self, _: &Redo, _window: &mut Window, _cx: &mut Context) { ... } +//! } +//! +//! impl Render for Editor { +//! fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { +//! div() +//! .track_focus(&self.focus_handle(cx)) +//! .key_context("Editor") +//! .on_action(cx.listener(Editor::undo)) +//! .on_action(cx.listener(Editor::redo)) +//! ... +//! } +//! } +//!``` +//! +//! The keybindings themselves are managed independently by calling cx.bind_keys(). +//! (Though mostly when developing Zed itself, you just need to add a new line to +//! assets/keymaps/default-{platform}.json). +//! +//! ```ignore +//! cx.bind_keys([ +//! KeyBinding::new("cmd-z", Editor::undo, Some("Editor")), +//! KeyBinding::new("cmd-shift-z", Editor::redo, Some("Editor")), +//! ]) +//! ``` +//! +//! With all of this in place, GPUI will ensure that if you have an Editor that contains +//! the focus, hitting cmd-z will Undo. +//! +//! In real apps, it is a little more complicated than this, because typically you have +//! several nested views that each register keyboard handlers. In this case action matching +//! bubbles up from the bottom. For example in Zed, the Workspace is the top-level view, which contains Pane's, which contain Editors. If there are conflicting keybindings defined +//! then the Editor's bindings take precedence over the Pane's bindings, which take precedence over the Workspace. +//! +//! In GPUI, keybindings are not limited to just single keystrokes, you can define +//! sequences by separating the keys with a space: +//! +//! KeyBinding::new("cmd-k left", pane::SplitLeft, Some("Pane")) + +use crate::{ + Action, ActionRegistry, App, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap, + Keystroke, ModifiersChangedEvent, Window, +}; +use collections::FxHashMap; +use smallvec::SmallVec; +use std::{ + any::{Any, TypeId}, + cell::RefCell, + mem, + ops::Range, + rc::Rc, +}; + +/// ID of a node within `DispatchTree`. Note that these are **not** stable between frames, and so a +/// `DispatchNodeId` should only be used with the `DispatchTree` that provided it. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub(crate) struct DispatchNodeId(usize); + +pub(crate) struct DispatchTree { + node_stack: Vec, + pub(crate) context_stack: Vec, + view_stack: Vec, + nodes: Vec, + focusable_node_ids: FxHashMap, + view_node_ids: FxHashMap, + keymap: Rc>, + action_registry: Rc, +} + +#[derive(Default)] +pub(crate) struct DispatchNode { + pub key_listeners: Vec, + pub action_listeners: Vec, + pub modifiers_changed_listeners: Vec, + pub context: Option, + pub focus_id: Option, + view_id: Option, + parent: Option, +} + +pub(crate) struct ReusedSubtree { + old_range: Range, + new_range: Range, + contains_focus: bool, +} + +impl ReusedSubtree { + pub fn refresh_node_id(&self, node_id: DispatchNodeId) -> DispatchNodeId { + debug_assert!( + self.old_range.contains(&node_id.0), + "node {} was not part of the reused subtree {:?}", + node_id.0, + self.old_range + ); + DispatchNodeId((node_id.0 - self.old_range.start) + self.new_range.start) + } + + pub fn contains_focus(&self) -> bool { + self.contains_focus + } +} + +#[derive(Default, Debug)] +pub(crate) struct Replay { + pub(crate) keystroke: Keystroke, + pub(crate) bindings: SmallVec<[KeyBinding; 1]>, +} + +#[derive(Default, Debug)] +pub(crate) struct DispatchResult { + pub(crate) pending: SmallVec<[Keystroke; 1]>, + pub(crate) pending_has_binding: bool, + pub(crate) bindings: SmallVec<[KeyBinding; 1]>, + pub(crate) to_replay: SmallVec<[Replay; 1]>, + pub(crate) context_stack: Vec, +} + +type KeyListener = Rc; +type ModifiersChangedListener = Rc; + +#[derive(Clone)] +pub(crate) struct DispatchActionListener { + pub(crate) action_type: TypeId, + pub(crate) listener: Rc, +} + +impl DispatchTree { + pub fn new(keymap: Rc>, action_registry: Rc) -> Self { + Self { + node_stack: Vec::new(), + context_stack: Vec::new(), + view_stack: Vec::new(), + nodes: Vec::new(), + focusable_node_ids: FxHashMap::default(), + view_node_ids: FxHashMap::default(), + keymap, + action_registry, + } + } + + pub fn clear(&mut self) { + self.node_stack.clear(); + self.context_stack.clear(); + self.view_stack.clear(); + self.nodes.clear(); + self.focusable_node_ids.clear(); + self.view_node_ids.clear(); + } + + pub fn len(&self) -> usize { + self.nodes.len() + } + + pub fn push_node(&mut self) -> DispatchNodeId { + let parent = self.node_stack.last().copied(); + let node_id = DispatchNodeId(self.nodes.len()); + + self.nodes.push(DispatchNode { + parent, + ..Default::default() + }); + self.node_stack.push(node_id); + node_id + } + + pub fn set_active_node(&mut self, node_id: DispatchNodeId) { + let next_node_parent = self.nodes[node_id.0].parent; + while self.node_stack.last().copied() != next_node_parent && !self.node_stack.is_empty() { + self.pop_node(); + } + + if self.node_stack.last().copied() == next_node_parent { + self.node_stack.push(node_id); + let active_node = &self.nodes[node_id.0]; + if let Some(view_id) = active_node.view_id { + self.view_stack.push(view_id) + } + if let Some(context) = active_node.context.clone() { + self.context_stack.push(context); + } + } else { + debug_assert_eq!(self.node_stack.len(), 0); + + let mut current_node_id = Some(node_id); + while let Some(node_id) = current_node_id { + let node = &self.nodes[node_id.0]; + if let Some(context) = node.context.clone() { + self.context_stack.push(context); + } + if let Some(view_id) = node.view_id { + self.view_stack.push(view_id); + } + self.node_stack.push(node_id); + current_node_id = node.parent; + } + + self.context_stack.reverse(); + self.view_stack.reverse(); + self.node_stack.reverse(); + } + } + + pub fn set_key_context(&mut self, context: KeyContext) { + self.active_node().context = Some(context.clone()); + self.context_stack.push(context); + } + + pub fn set_focus_id(&mut self, focus_id: FocusId) { + let node_id = *self.node_stack.last().unwrap(); + self.nodes[node_id.0].focus_id = Some(focus_id); + self.focusable_node_ids.insert(focus_id, node_id); + } + + pub fn set_view_id(&mut self, view_id: EntityId) { + if self.view_stack.last().copied() != Some(view_id) { + let node_id = *self.node_stack.last().unwrap(); + self.nodes[node_id.0].view_id = Some(view_id); + self.view_node_ids.insert(view_id, node_id); + self.view_stack.push(view_id); + } + } + + pub fn pop_node(&mut self) { + let node = &self.nodes[self.active_node_id().unwrap().0]; + if node.context.is_some() { + self.context_stack.pop(); + } + if node.view_id.is_some() { + self.view_stack.pop(); + } + self.node_stack.pop(); + } + + fn move_node(&mut self, source: &mut DispatchNode) { + self.push_node(); + if let Some(context) = source.context.clone() { + self.set_key_context(context); + } + if let Some(focus_id) = source.focus_id { + self.set_focus_id(focus_id); + } + if let Some(view_id) = source.view_id { + self.set_view_id(view_id); + } + + let target = self.active_node(); + target.key_listeners = mem::take(&mut source.key_listeners); + target.action_listeners = mem::take(&mut source.action_listeners); + target.modifiers_changed_listeners = mem::take(&mut source.modifiers_changed_listeners); + } + + pub fn reuse_subtree( + &mut self, + old_range: Range, + source: &mut Self, + focus: Option, + ) -> ReusedSubtree { + let new_range = self.nodes.len()..self.nodes.len() + old_range.len(); + + let mut contains_focus = false; + let mut source_stack = vec![]; + for (source_node_id, source_node) in source + .nodes + .iter_mut() + .enumerate() + .skip(old_range.start) + .take(old_range.len()) + { + let source_node_id = DispatchNodeId(source_node_id); + while let Some(source_ancestor) = source_stack.last() { + if source_node.parent == Some(*source_ancestor) { + break; + } else { + source_stack.pop(); + self.pop_node(); + } + } + + source_stack.push(source_node_id); + if source_node.focus_id.is_some() && source_node.focus_id == focus { + contains_focus = true; + } + self.move_node(source_node); + } + + while !source_stack.is_empty() { + source_stack.pop(); + self.pop_node(); + } + + ReusedSubtree { + old_range, + new_range, + contains_focus, + } + } + + pub fn truncate(&mut self, index: usize) { + for node in &self.nodes[index..] { + if let Some(focus_id) = node.focus_id { + self.focusable_node_ids.remove(&focus_id); + } + + if let Some(view_id) = node.view_id { + self.view_node_ids.remove(&view_id); + } + } + self.nodes.truncate(index); + } + + pub fn on_key_event(&mut self, listener: KeyListener) { + self.active_node().key_listeners.push(listener); + } + + pub fn on_modifiers_changed(&mut self, listener: ModifiersChangedListener) { + self.active_node() + .modifiers_changed_listeners + .push(listener); + } + + pub fn on_action( + &mut self, + action_type: TypeId, + listener: Rc, + ) { + self.active_node() + .action_listeners + .push(DispatchActionListener { + action_type, + listener, + }); + } + + pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool { + if parent == child { + return true; + } + + if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) { + let mut current_node_id = self.focusable_node_ids.get(&child).copied(); + while let Some(node_id) = current_node_id { + if node_id == *parent_node_id { + return true; + } + current_node_id = self.nodes[node_id.0].parent; + } + } + false + } + + pub fn available_actions(&self, target: DispatchNodeId) -> Vec> { + let mut actions = Vec::>::new(); + for node_id in self.dispatch_path(target) { + let node = &self.nodes[node_id.0]; + for DispatchActionListener { action_type, .. } in &node.action_listeners { + if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) + { + // Intentionally silence these errors without logging. + // If an action cannot be built by default, it's not available. + let action = self.action_registry.build_action_type(action_type).ok(); + if let Some(action) = action { + actions.insert(ix, action); + } + } + } + } + actions + } + + pub fn is_action_available(&self, action: &dyn Action, target: DispatchNodeId) -> bool { + for node_id in self.dispatch_path(target) { + let node = &self.nodes[node_id.0]; + if node + .action_listeners + .iter() + .any(|listener| listener.action_type == action.as_any().type_id()) + { + return true; + } + } + false + } + + /// Returns key bindings that invoke an action on the currently focused element. Bindings are + /// returned in the order they were added. For display, the last binding should take precedence. + /// + /// Bindings are only included if they are the highest precedence match for their keystrokes, so + /// shadowed bindings are not included. + pub fn bindings_for_action( + &self, + action: &dyn Action, + context_stack: &[KeyContext], + ) -> Vec { + // Ideally this would return a `DoubleEndedIterator` to avoid `highest_precedence_*` + // methods, but this can't be done very cleanly since keymap must be borrowed. + let keymap = self.keymap.borrow(); + keymap + .bindings_for_action(action) + .filter(|binding| { + Self::binding_matches_predicate_and_not_shadowed(&keymap, binding, context_stack) + }) + .cloned() + .collect() + } + + /// Returns the highest precedence binding for the given action and context stack. This is the + /// same as the last result of `bindings_for_action`, but more efficient than getting all bindings. + pub fn highest_precedence_binding_for_action( + &self, + action: &dyn Action, + context_stack: &[KeyContext], + ) -> Option { + let keymap = self.keymap.borrow(); + keymap + .bindings_for_action(action) + .rev() + .find(|binding| { + Self::binding_matches_predicate_and_not_shadowed(&keymap, binding, context_stack) + }) + .cloned() + } + + fn binding_matches_predicate_and_not_shadowed( + keymap: &Keymap, + binding: &KeyBinding, + context_stack: &[KeyContext], + ) -> bool { + let (bindings, _) = keymap.bindings_for_input(&binding.keystrokes, context_stack); + if let Some(found) = bindings.iter().next() { + found.action.partial_eq(binding.action.as_ref()) + } else { + false + } + } + + fn bindings_for_input( + &self, + input: &[Keystroke], + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + ) -> (SmallVec<[KeyBinding; 1]>, bool, Vec) { + let context_stack: Vec = dispatch_path + .iter() + .filter_map(|node_id| self.node(*node_id).context.clone()) + .collect(); + + let (bindings, partial) = self + .keymap + .borrow() + .bindings_for_input(input, &context_stack); + (bindings, partial, context_stack) + } + + /// Find the bindings that can follow the current input sequence. + pub fn possible_next_bindings_for_input( + &self, + input: &[Keystroke], + context_stack: &[KeyContext], + ) -> Vec { + self.keymap + .borrow() + .possible_next_bindings_for_input(input, context_stack) + } + + /// dispatch_key processes the keystroke + /// input should be set to the value of `pending` from the previous call to dispatch_key. + /// This returns three instructions to the input handler: + /// - bindings: any bindings to execute before processing this keystroke + /// - pending: the new set of pending keystrokes to store + /// - to_replay: any keystroke that had been pushed to pending, but are no-longer matched, + /// these should be replayed first. + pub fn dispatch_key( + &mut self, + mut input: SmallVec<[Keystroke; 1]>, + keystroke: Keystroke, + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + ) -> DispatchResult { + input.push(keystroke.clone()); + let (bindings, pending, context_stack) = self.bindings_for_input(&input, dispatch_path); + + if pending { + return DispatchResult { + pending: input, + pending_has_binding: !bindings.is_empty(), + context_stack, + ..Default::default() + }; + } else if !bindings.is_empty() { + return DispatchResult { + bindings, + context_stack, + ..Default::default() + }; + } else if input.len() == 1 { + return DispatchResult { + context_stack, + ..Default::default() + }; + } + input.pop(); + + let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path); + + let mut result = self.dispatch_key(suffix, keystroke, dispatch_path); + to_replay.extend(result.to_replay); + result.to_replay = to_replay; + result + } + + /// If the user types a matching prefix of a binding and then waits for a timeout + /// flush_dispatch() converts any previously pending input to replay events. + pub fn flush_dispatch( + &mut self, + input: SmallVec<[Keystroke; 1]>, + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + ) -> SmallVec<[Replay; 1]> { + let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path); + + if !suffix.is_empty() { + to_replay.extend(self.flush_dispatch(suffix, dispatch_path)) + } + + to_replay + } + + /// Converts the longest prefix of input to a replay event and returns the rest. + fn replay_prefix( + &self, + mut input: SmallVec<[Keystroke; 1]>, + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + ) -> (SmallVec<[Keystroke; 1]>, SmallVec<[Replay; 1]>) { + let mut to_replay: SmallVec<[Replay; 1]> = Default::default(); + for last in (0..input.len()).rev() { + let (bindings, _, _) = self.bindings_for_input(&input[0..=last], dispatch_path); + if !bindings.is_empty() { + to_replay.push(Replay { + keystroke: input.drain(0..=last).next_back().unwrap(), + bindings, + }); + break; + } + } + if to_replay.is_empty() { + to_replay.push(Replay { + keystroke: input.remove(0), + ..Default::default() + }); + } + (input, to_replay) + } + + pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> { + let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new(); + let mut current_node_id = Some(target); + while let Some(node_id) = current_node_id { + dispatch_path.push(node_id); + current_node_id = self.nodes.get(node_id.0).and_then(|node| node.parent); + } + dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node. + dispatch_path + } + + pub fn focus_path(&self, focus_id: FocusId) -> SmallVec<[FocusId; 8]> { + let mut focus_path: SmallVec<[FocusId; 8]> = SmallVec::new(); + let mut current_node_id = self.focusable_node_ids.get(&focus_id).copied(); + while let Some(node_id) = current_node_id { + let node = self.node(node_id); + if let Some(focus_id) = node.focus_id { + focus_path.push(focus_id); + } + current_node_id = node.parent; + } + focus_path.reverse(); // Reverse the path so it goes from the root to the focused node. + focus_path + } + + pub fn view_path_reversed(&self, view_id: EntityId) -> impl Iterator { + let mut current_node_id = self.view_node_ids.get(&view_id).copied(); + + std::iter::successors( + current_node_id.map(|node_id| self.node(node_id)), + |node_id| Some(self.node(node_id.parent?)), + ) + .filter_map(|node| node.view_id) + } + + pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode { + &self.nodes[node_id.0] + } + + fn active_node(&mut self) -> &mut DispatchNode { + let active_node_id = self.active_node_id().unwrap(); + &mut self.nodes[active_node_id.0] + } + + pub fn focusable_node_id(&self, target: FocusId) -> Option { + self.focusable_node_ids.get(&target).copied() + } + + pub fn root_node_id(&self) -> DispatchNodeId { + debug_assert!(!self.nodes.is_empty()); + DispatchNodeId(0) + } + + pub fn active_node_id(&self) -> Option { + self.node_stack.last().copied() + } +} + +#[cfg(test)] +mod tests { + use crate::{ + self as gpui, AppContext, DispatchResult, Element, ElementId, GlobalElementId, + InspectorElementId, Keystroke, LayoutId, Style, + }; + use core::panic; + use smallvec::SmallVec; + use std::{ + cell::{Cell, RefCell}, + ops::Range, + rc::Rc, + }; + + use crate::{ + Action, ActionRegistry, App, Bounds, Context, DispatchEventResult, DispatchPhase, + DispatchTree, Entity, FocusHandle, InputHandler, InputPreference, IntoElement, KeyBinding, + KeyContext, KeyDownEvent, Keymap, Modifiers, Pixels, PlatformInput, PlatformWindow, Point, + Render, Subscription, TestAppContext, UTF16Selection, Unbind, VisualContext, + VisualTestContext, Window, + }; + + actions!(dispatch_test, [TestAction, SecondaryTestAction]); + + fn test_dispatch_tree(bindings: Vec) -> DispatchTree { + let registry = ActionRegistry::default(); + + DispatchTree::new( + Rc::new(RefCell::new(Keymap::new(bindings))), + Rc::new(registry), + ) + } + + struct PendingInputTestView { + focus_handle: FocusHandle, + action_count: Rc>, + secondary_action_count: Rc>, + } + + #[derive(Clone)] + struct PendingTextInputTestView { + focus_handle: FocusHandle, + text: Rc>, + action_count: Rc>, + accepts_text_input: Rc>, + } + + impl PendingTextInputTestView { + fn new(cx: &mut Context) -> Self { + Self { + focus_handle: cx.focus_handle(), + text: Rc::default(), + action_count: Rc::default(), + accepts_text_input: Rc::new(Cell::new(true)), + } + } + } + + impl Element for PendingTextInputTestView { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + Some("pending-text-input-test".into()) + } + + fn source_location(&self) -> Option<&'static panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + (window.request_layout(Style::default(), [], cx), ()) + } + + fn prepaint( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + window.set_focus_handle(&self.focus_handle, cx); + } + + fn paint( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let mut key_context = KeyContext::default(); + key_context.add("Terminal"); + window.set_key_context(key_context); + window.handle_input(&self.focus_handle, self.clone(), cx); + let action_count = self.action_count.clone(); + window.on_action( + std::any::TypeId::of::(), + move |_, phase, _, _| { + if phase == DispatchPhase::Bubble { + action_count.set(action_count.get() + 1); + } + }, + ); + } + } + + impl IntoElement for PendingTextInputTestView { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } + } + + impl InputHandler for PendingTextInputTestView { + fn accepts_text_input(&mut self, _: &mut Window, _: &mut App) -> bool { + self.accepts_text_input.get() + } + + fn selected_text_range( + &mut self, + _: bool, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + + fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option> { + None + } + + fn text_for_range( + &mut self, + _: Range, + _: &mut Option>, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + + fn replace_text_in_range( + &mut self, + replacement_range: Option>, + text: &str, + _: &mut Window, + _: &mut App, + ) { + if replacement_range.is_some() { + unimplemented!() + } + self.text.borrow_mut().push_str(text) + } + + fn replace_and_mark_text_in_range( + &mut self, + replacement_range: Option>, + new_text: &str, + _: Option>, + _: &mut Window, + _: &mut App, + ) { + if replacement_range.is_some() { + unimplemented!() + } + self.text.borrow_mut().push_str(new_text) + } + + fn unmark_text(&mut self, _: &mut Window, _: &mut App) {} + + fn prefers_ime_for_printable_keys(&mut self, _: &mut Window, _: &mut App) -> bool { + true + } + + fn bounds_for_range( + &mut self, + _: Range, + _: &mut Window, + _: &mut App, + ) -> Option> { + None + } + + fn character_index_for_point( + &mut self, + _: Point, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + } + + impl Render for PendingTextInputTestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + self.clone() + } + } + + struct PendingInputTimeoutPauseOwner; + + impl Render for PendingInputTestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + use crate::{InteractiveElement as _, Styled as _}; + let action_count = self.action_count.clone(); + let secondary_action_count = self.secondary_action_count.clone(); + crate::div() + .key_context("Terminal") + .track_focus(&self.focus_handle) + .size_full() + .on_action(move |_: &TestAction, _, _| { + action_count.set(action_count.get() + 1); + }) + .on_action(move |_: &SecondaryTestAction, _, _| { + secondary_action_count.set(secondary_action_count.get() + 1); + }) + } + } + + fn setup_pending_input_test( + cx: &mut TestAppContext, + bindings: impl IntoIterator, + ) -> (&mut VisualTestContext, Rc>, Rc>) { + cx.update(|cx| cx.bind_keys(bindings)); + + let action_count = Rc::new(Cell::new(0)); + let secondary_action_count = Rc::new(Cell::new(0)); + let (view, cx) = cx.add_window_view(|_, cx| PendingInputTestView { + focus_handle: cx.focus_handle(), + action_count: action_count.clone(), + secondary_action_count: secondary_action_count.clone(), + }); + let focus_handle = cx.update(|_, cx| view.read(cx).focus_handle.clone()); + cx.update(|window, cx| { + window.focus(&focus_handle, cx); + window.activate_window(); + }); + + (cx, action_count, secondary_action_count) + } + + #[derive(Debug, PartialEq)] + struct ObservedKeystroke { + keystroke: Keystroke, + action_name: Option<&'static str>, + context_stack: Vec, + } + + fn capture_observed_keystrokes( + cx: &mut VisualTestContext, + ) -> (Rc>>, Subscription) { + let observed_keystrokes = Rc::new(RefCell::new(Vec::new())); + let subscription = cx.update(|_, cx| { + cx.observe_keystrokes({ + let observed_keystrokes = observed_keystrokes.clone(); + move |event, _, _| { + observed_keystrokes.borrow_mut().push(ObservedKeystroke { + keystroke: event.keystroke.clone(), + action_name: event.action.as_ref().map(|action| action.name()), + context_stack: event.context_stack.clone(), + }); + } + }) + }); + (observed_keystrokes, subscription) + } + + fn simulate_modifier_tap(cx: &mut VisualTestContext, modifiers: Modifiers) { + cx.simulate_modifiers_change(modifiers); + cx.simulate_modifiers_change(Modifiers::none()); + } + + fn terminal_context() -> KeyContext { + KeyContext::parse("Terminal").expect("valid key context") + } + + fn setup_pending_input_timeout_test( + cx: &mut TestAppContext, + ) -> (&mut VisualTestContext, Rc>, Rc>) { + setup_pending_input_test( + cx, + [ + KeyBinding::new("ctrl-b", TestAction, Some("Terminal")), + KeyBinding::new("ctrl-b h", SecondaryTestAction, Some("Terminal")), + KeyBinding::new("ctrl-b h j", TestAction, Some("Terminal")), + ], + ) + } + + fn query_prefers_ime_for_printable_keys(cx: &mut VisualTestContext) -> Option { + let mut platform_window = cx.test_window(cx.window_handle()); + let mut input_handler = platform_window.take_input_handler()?; + let prefers_ime = input_handler.query_prefers_ime_for_printable_keys(); + platform_window.set_input_handler(input_handler); + Some(prefers_ime) + } + + fn setup_altgr_test( + cx: &mut TestAppContext, + ) -> (Entity, &mut VisualTestContext) { + let (test, cx) = cx.add_window_view(|_, cx| PendingTextInputTestView::new(cx)); + test.update_in(cx, |test, window, cx| { + window.focus(&test.focus_handle, cx); + window.activate_window(); + cx.bind_keys([KeyBinding::new("ctrl-alt-a", TestAction, Some("Terminal"))]); + }); + (test, cx) + } + + fn dispatch_altgr_key_down( + cx: &mut VisualTestContext, + prefer_character_input: bool, + ) -> DispatchEventResult { + cx.update(|window, cx| { + window.dispatch_event( + PlatformInput::KeyDown(KeyDownEvent { + keystroke: Keystroke { + key_char: Some("ą".into()), + ..Keystroke::parse("ctrl-alt-a").expect("valid keystroke") + }, + is_held: false, + prefer_character_input, + }), + cx, + ) + }) + } + + fn simulate_pending_binding(cx: &mut VisualTestContext) { + cx.simulate_modifiers_change(crate::Modifiers::control()); + cx.simulate_keystrokes("ctrl-b"); + cx.simulate_modifiers_change(crate::Modifiers::default()); + } + + #[test] + fn test_keybinding_for_action_bounds() { + let tree = test_dispatch_tree(vec![KeyBinding::new( + "cmd-n", + TestAction, + Some("ProjectPanel"), + )]); + + let contexts = vec![ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("ProjectPanel").unwrap(), + ]; + + let keybinding = tree.bindings_for_action(&TestAction, &contexts); + + assert!(keybinding[0].action.partial_eq(&TestAction)) + } + + #[test] + fn test_bindings_for_action_hides_targeted_unbind_in_active_context() { + let tree = test_dispatch_tree(vec![ + KeyBinding::new("tab", TestAction, Some("Editor")), + KeyBinding::new( + "tab", + Unbind("dispatch_test::TestAction".into()), + Some("Editor && edit_prediction"), + ), + KeyBinding::new( + "tab", + SecondaryTestAction, + Some("Editor && showing_completions"), + ), + ]); + + let contexts = vec![ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("Editor showing_completions edit_prediction").unwrap(), + ]; + + let bindings = tree.bindings_for_action(&TestAction, &contexts); + assert!(bindings.is_empty()); + + let highest = tree.highest_precedence_binding_for_action(&TestAction, &contexts); + assert!(highest.is_none()); + + let fallback_bindings = tree.bindings_for_action(&SecondaryTestAction, &contexts); + assert_eq!(fallback_bindings.len(), 1); + assert!(fallback_bindings[0].action.partial_eq(&SecondaryTestAction)); + } + + #[test] + fn test_bindings_for_action_keeps_targeted_binding_outside_unbind_context() { + let tree = test_dispatch_tree(vec![ + KeyBinding::new("tab", TestAction, Some("Editor")), + KeyBinding::new( + "tab", + Unbind("dispatch_test::TestAction".into()), + Some("Editor && edit_prediction"), + ), + KeyBinding::new( + "tab", + SecondaryTestAction, + Some("Editor && showing_completions"), + ), + ]); + + let contexts = vec![ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("Editor").unwrap(), + ]; + + let bindings = tree.bindings_for_action(&TestAction, &contexts); + assert_eq!(bindings.len(), 1); + assert!(bindings[0].action.partial_eq(&TestAction)); + + let highest = tree.highest_precedence_binding_for_action(&TestAction, &contexts); + assert!(highest.is_some_and(|binding| binding.action.partial_eq(&TestAction))); + } + + /// Models the picker preview footer scenario: a picker action is bound in + /// `Picker > Editor`, but a base keymap binds the same chord to an editor + /// action in `Editor`. `Picker > Editor` and `Editor` resolve at the same + /// context depth, so at equal depth precedence is decided purely by load + /// order (later wins). Because base keymaps load after the default keymap, + /// the picker binding is shadowed unless it is (re)bound by an overlay that + /// loads after the base keymap - which is exactly what + /// `keymaps/specific-overrides*.json` does. + #[test] + fn test_overlay_after_base_restores_shadowed_picker_binding() { + // SecondaryTestAction stands in for the editor/base action (e.g. + // editor::AddSelectionBelow), TestAction for the picker action. + let contexts = vec![ + KeyContext::parse("Picker").unwrap(), + KeyContext::parse("Editor").unwrap(), + ]; + + // Default keymap (picker binding) followed by a base keymap that binds + // the same chord to an editor action: the base binding wins and the + // picker action is shadowed, so its footer tooltip renders no shortcut. + let shadowed = test_dispatch_tree(vec![ + KeyBinding::new("ctrl-alt-down", TestAction, Some("Picker > Editor")), + KeyBinding::new("ctrl-alt-down", SecondaryTestAction, Some("Editor")), + ]); + let highest = shadowed.highest_precedence_binding_for_action(&TestAction, &contexts); + assert!( + highest.is_none(), + "picker binding should be shadowed by the base editor binding" + ); + + // Re-binding the picker action in an overlay loaded after the base keymap + // restores it as the resolved binding. + let fixed = test_dispatch_tree(vec![ + KeyBinding::new("ctrl-alt-down", TestAction, Some("Picker > Editor")), + KeyBinding::new("ctrl-alt-down", SecondaryTestAction, Some("Editor")), + // overlay loaded last: + KeyBinding::new("ctrl-alt-down", TestAction, Some("Picker > Editor")), + ]); + let highest = fixed.highest_precedence_binding_for_action(&TestAction, &contexts); + assert!( + highest.is_some_and(|binding| binding.action.partial_eq(&TestAction)), + "overlay loaded after base should restore the picker binding" + ); + + // Conversely, putting the override in the default keymap (i.e. before the + // base keymap) does NOT help: the later base binding still wins at equal + // depth. This is why the overlay must be loaded after the base keymap. + let override_before_base = test_dispatch_tree(vec![ + KeyBinding::new("ctrl-alt-down", TestAction, Some("Picker > Editor")), + KeyBinding::new("ctrl-alt-down", TestAction, Some("Picker > Editor")), + KeyBinding::new("ctrl-alt-down", SecondaryTestAction, Some("Editor")), + ]); + let highest = + override_before_base.highest_precedence_binding_for_action(&TestAction, &contexts); + assert!( + highest.is_none(), + "an override loaded before the base binding cannot win the equal-depth tie" + ); + } + + #[test] + fn test_pending_has_binding_state() { + let bindings = vec![ + KeyBinding::new("ctrl-b h", TestAction, None), + KeyBinding::new("space", TestAction, Some("ContextA")), + KeyBinding::new("space f g", TestAction, Some("ContextB")), + ]; + let mut tree = test_dispatch_tree(bindings); + + type DispatchPath = SmallVec<[super::DispatchNodeId; 32]>; + fn dispatch( + tree: &mut DispatchTree, + pending: SmallVec<[Keystroke; 1]>, + key: &str, + path: &DispatchPath, + ) -> DispatchResult { + tree.dispatch_key(pending, Keystroke::parse(key).unwrap(), path) + } + + let dispatch_path: DispatchPath = SmallVec::new(); + let result = dispatch(&mut tree, SmallVec::new(), "ctrl-b", &dispatch_path); + assert_eq!(result.pending.len(), 1); + assert!(!result.pending_has_binding); + + let result = dispatch(&mut tree, result.pending, "h", &dispatch_path); + assert_eq!(result.pending.len(), 0); + assert_eq!(result.bindings.len(), 1); + assert!(!result.pending_has_binding); + + let node_id = tree.push_node(); + tree.set_key_context(KeyContext::parse("ContextB").unwrap()); + tree.pop_node(); + + let dispatch_path = tree.dispatch_path(node_id); + let result = dispatch(&mut tree, SmallVec::new(), "space", &dispatch_path); + + assert_eq!(result.pending.len(), 1); + assert!(!result.pending_has_binding); + } + + #[crate::test] + fn test_pending_input_observers_notified_on_focus_change_and_blur(cx: &mut TestAppContext) { + #[derive(Clone)] + struct CustomElement { + focus_handle: FocusHandle, + text: Rc>, + } + + impl CustomElement { + fn new(cx: &mut Context) -> Self { + Self { + focus_handle: cx.focus_handle(), + text: Rc::default(), + } + } + } + + impl Element for CustomElement { + type RequestLayoutState = (); + + type PrepaintState = (); + + fn id(&self) -> Option { + Some("custom".into()) + } + + fn source_location(&self) -> Option<&'static panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + (window.request_layout(Style::default(), [], cx), ()) + } + + fn prepaint( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Self::PrepaintState { + window.set_focus_handle(&self.focus_handle, cx); + } + + fn paint( + &mut self, + _: Option<&GlobalElementId>, + _: Option<&InspectorElementId>, + _: Bounds, + _: &mut Self::RequestLayoutState, + _: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + let mut key_context = KeyContext::default(); + key_context.add("Terminal"); + window.set_key_context(key_context); + window.handle_input(&self.focus_handle, self.clone(), cx); + window.on_action(std::any::TypeId::of::(), |_, _, _, _| {}); + } + } + + impl IntoElement for CustomElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } + } + + impl InputHandler for CustomElement { + fn selected_text_range( + &mut self, + _: bool, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + + fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option> { + None + } + + fn text_for_range( + &mut self, + _: Range, + _: &mut Option>, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + + fn replace_text_in_range( + &mut self, + replacement_range: Option>, + text: &str, + _: &mut Window, + _: &mut App, + ) { + if replacement_range.is_some() { + unimplemented!() + } + self.text.borrow_mut().push_str(text) + } + + fn replace_and_mark_text_in_range( + &mut self, + replacement_range: Option>, + new_text: &str, + _: Option>, + _: &mut Window, + _: &mut App, + ) { + if replacement_range.is_some() { + unimplemented!() + } + self.text.borrow_mut().push_str(new_text) + } + + fn unmark_text(&mut self, _: &mut Window, _: &mut App) {} + + fn bounds_for_range( + &mut self, + _: Range, + _: &mut Window, + _: &mut App, + ) -> Option> { + None + } + + fn character_index_for_point( + &mut self, + _: Point, + _: &mut Window, + _: &mut App, + ) -> Option { + None + } + } + + impl Render for CustomElement { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + self.clone() + } + } + + cx.update(|cx| { + cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]); + cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]); + cx.bind_keys([KeyBinding::new("ctrl-d", TestAction, None)]); + cx.bind_keys([KeyBinding::new("ctrl-d h", TestAction, None)]); + }); + + let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx)); + let focus_handle = test.update(cx, |test, _| test.focus_handle.clone()); + + let pending_input_changed_count = Rc::new(RefCell::new(0usize)); + let pending_input_changed_count_for_observer = pending_input_changed_count.clone(); + + struct PendingInputObserver { + _subscription: Subscription, + } + + let _observer = cx.update(|window, cx| { + cx.new(|cx| PendingInputObserver { + _subscription: cx.observe_pending_input(window, move |_, _, _| { + *pending_input_changed_count_for_observer.borrow_mut() += 1; + }), + }) + }); + + cx.update(|window, cx| { + window.focus(&focus_handle, cx); + window.activate_window(); + }); + + cx.simulate_keystrokes("ctrl-b"); + + let count_after_pending = Rc::new(RefCell::new(0usize)); + let count_after_pending_for_assertion = count_after_pending.clone(); + + cx.update(|window, cx| { + assert!(window.has_pending_keystrokes()); + *count_after_pending.borrow_mut() = *pending_input_changed_count.borrow(); + assert!(*count_after_pending.borrow() > 0); + + window.focus(&cx.focus_handle(), cx); + + assert!(!window.has_pending_keystrokes()); + }); + + // Focus-triggered pending-input notifications are deferred to the end of the current + // effect cycle, so the observer callback should run after the focus update completes. + cx.update(|_, _| { + let count_after_focus_change = *pending_input_changed_count.borrow(); + assert!(count_after_focus_change > *count_after_pending_for_assertion.borrow()); + }); + + cx.update(|window, cx| window.focus(&focus_handle, cx)); + cx.simulate_keystrokes("ctrl-b"); + let count_before_blur = *pending_input_changed_count.borrow(); + + cx.update(|window, cx| { + assert!(window.has_pending_keystrokes()); + window.blur(cx); + assert!(!window.has_pending_keystrokes()); + assert!(window.pending_input_is_none()); + }); + + cx.update(|_, _| { + assert!(*pending_input_changed_count.borrow() > count_before_blur); + }); + + cx.update(|window, cx| window.disable_focus(cx)); + cx.simulate_keystrokes("ctrl-d"); + + cx.update(|window, cx| { + assert!(window.has_pending_keystrokes()); + window.blur(cx); + assert!(window.pending_input_is_none()); + }); + } + + #[crate::test] + fn test_standalone_modifier_dispatch(cx: &mut TestAppContext) { + let (cx, action_count, _) = + setup_pending_input_test(cx, [KeyBinding::new("shift", TestAction, Some("Terminal"))]); + let intercepted_keystrokes = Rc::new(RefCell::new(Vec::new())); + let should_consume = Rc::new(Cell::new(true)); + let terminal_context = terminal_context(); + let (observed_keystrokes, _observer) = capture_observed_keystrokes(cx); + let _interceptor = cx.update(|_, cx| { + cx.intercept_keystrokes({ + let intercepted_keystrokes = intercepted_keystrokes.clone(); + let should_consume = should_consume.clone(); + let terminal_context = terminal_context.clone(); + move |event, _, cx| { + assert!(event.action.is_none()); + assert_eq!(event.context_stack, vec![terminal_context.clone()]); + intercepted_keystrokes + .borrow_mut() + .push(event.keystroke.clone()); + if should_consume.get() { + cx.stop_propagation(); + } + } + }) + }); + let shift = Keystroke::parse("shift").expect("valid keystroke"); + + // Pressing Shift is not a keystroke. Consuming its recognized release suppresses + // the binding. + cx.simulate_modifiers_change(Modifiers::shift()); + assert!(intercepted_keystrokes.borrow().is_empty()); + cx.simulate_modifiers_change(Modifiers::none()); + assert_eq!( + intercepted_keystrokes.borrow().as_slice(), + std::slice::from_ref(&shift) + ); + assert_eq!(action_count.get(), 0); + assert!(observed_keystrokes.borrow().is_empty()); + + // Without consumption, the same recognized release reaches keymap dispatch. + should_consume.set(false); + intercepted_keystrokes.borrow_mut().clear(); + cx.simulate_modifiers_change(Modifiers::shift()); + assert!(intercepted_keystrokes.borrow().is_empty()); + cx.simulate_modifiers_change(Modifiers::none()); + assert_eq!( + intercepted_keystrokes.borrow().as_slice(), + std::slice::from_ref(&shift) + ); + assert_eq!(action_count.get(), 1); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: shift, + action_name: Some(TestAction.name()), + context_stack: vec![terminal_context], + }] + ); + } + + #[crate::test] + fn test_unbound_standalone_modifier_observation(cx: &mut TestAppContext) { + let (cx, _, _) = setup_pending_input_test(cx, []); + let terminal_context = terminal_context(); + let (observed_keystrokes, _observer) = capture_observed_keystrokes(cx); + + for (modifiers, key) in [ + (Modifiers::shift(), "shift"), + (Modifiers::control(), "ctrl"), + (Modifiers::alt(), "alt"), + (Modifiers::command(), "cmd"), + (Modifiers::function(), "fn"), + ] { + observed_keystrokes.borrow_mut().clear(); + cx.simulate_modifiers_change(modifiers); + assert!( + observed_keystrokes.borrow().is_empty(), + "modifier press must not notify observers" + ); + cx.simulate_modifiers_change(Modifiers::none()); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: Keystroke::parse(key).expect("valid modifier"), + action_name: None, + context_stack: vec![terminal_context.clone()], + }] + ); + } + } + + #[crate::test] + fn test_raw_modifier_handler_can_suppress_observation(cx: &mut TestAppContext) { + struct ModifierListenerTestView { + focus_handle: FocusHandle, + consume: Rc>, + releases: Rc>, + } + + impl Render for ModifierListenerTestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + use crate::{InteractiveElement as _, Styled as _}; + let consume = self.consume.clone(); + let releases = self.releases.clone(); + crate::div() + .key_context("Terminal") + .track_focus(&self.focus_handle) + .size_full() + .on_action(|_: &TestAction, _, cx| cx.propagate()) + .on_modifiers_changed(move |event, _, cx| { + if !event.modifiers.modified() { + releases.set(releases.get() + 1); + if consume.get() { + cx.stop_propagation(); + } + } + }) + } + } + + cx.update(|cx| { + cx.bind_keys([KeyBinding::new("shift", TestAction, Some("Terminal"))]); + }); + let consume = Rc::new(Cell::new(true)); + let releases = Rc::new(Cell::new(0)); + let (view, cx) = cx.add_window_view(|_, cx| ModifierListenerTestView { + focus_handle: cx.focus_handle(), + consume: consume.clone(), + releases: releases.clone(), + }); + cx.update(|window, cx| { + let focus_handle = view.read(cx).focus_handle.clone(); + window.focus(&focus_handle, cx); + window.activate_window(); + }); + let (observed_keystrokes, _observer) = capture_observed_keystrokes(cx); + + simulate_modifier_tap(cx, Modifiers::shift()); + assert_eq!(releases.get(), 1); + assert!(observed_keystrokes.borrow().is_empty()); + + consume.set(false); + simulate_modifier_tap(cx, Modifiers::shift()); + assert_eq!(releases.get(), 2); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: Keystroke::parse("shift").expect("valid modifier"), + action_name: None, + context_stack: vec![terminal_context()], + }] + ); + } + + #[crate::test] + fn test_pending_modifier_observed_when_binding_resolves(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_test( + cx, + [ + KeyBinding::new("shift", TestAction, Some("Terminal")), + KeyBinding::new("shift f1", SecondaryTestAction, Some("Terminal")), + ], + ); + let (observed_keystrokes, _observer) = capture_observed_keystrokes(cx); + + simulate_modifier_tap(cx, Modifiers::shift()); + assert!(observed_keystrokes.borrow().is_empty()); + assert_eq!(action_count.get(), 0); + + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + assert_eq!(action_count.get(), 1); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: Keystroke::parse("shift").expect("valid modifier"), + action_name: Some(TestAction.name()), + context_stack: Vec::new(), + }] + ); + + observed_keystrokes.borrow_mut().clear(); + simulate_modifier_tap(cx, Modifiers::shift()); + assert!(observed_keystrokes.borrow().is_empty()); + cx.simulate_keystrokes("f1"); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 1); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: Keystroke::parse("f1").expect("valid key"), + action_name: Some(SecondaryTestAction.name()), + context_stack: vec![terminal_context()], + }] + ); + } + + #[crate::test] + fn test_combined_shortcut_has_no_standalone_modifier(cx: &mut TestAppContext) { + let (cx, action_count, _) = setup_pending_input_test( + cx, + [ + KeyBinding::new("shift", TestAction, Some("Terminal")), + KeyBinding::new("shift-f1", TestAction, Some("Terminal")), + ], + ); + let intercepted_keystrokes = Rc::new(RefCell::new(Vec::new())); + let (observed_keystrokes, _observer) = capture_observed_keystrokes(cx); + let _interceptor = cx.update(|_, cx| { + cx.intercept_keystrokes({ + let intercepted_keystrokes = intercepted_keystrokes.clone(); + move |event, _, _| { + intercepted_keystrokes + .borrow_mut() + .push(event.keystroke.clone()); + } + }) + }); + + // Shift-F1 is the only keystroke. Releasing Shift must not emit a second one. + cx.simulate_modifiers_change(Modifiers::shift()); + assert!(intercepted_keystrokes.borrow().is_empty()); + cx.simulate_keystrokes("shift-f1"); + cx.simulate_modifiers_change(Modifiers::none()); + + let shift_f1 = Keystroke::parse("shift-f1").expect("valid keystroke"); + assert_eq!( + intercepted_keystrokes.borrow().as_slice(), + std::slice::from_ref(&shift_f1) + ); + assert_eq!( + observed_keystrokes.borrow().as_slice(), + &[ObservedKeystroke { + keystroke: shift_f1, + action_name: Some(TestAction.name()), + context_stack: vec![terminal_context()], + }] + ); + assert_eq!(action_count.get(), 1); + } + + #[crate::test] + fn test_keystroke_input_preference(cx: &mut TestAppContext) { + let (test, cx) = setup_altgr_test(cx); + let intercepted_preferences = Rc::new(RefCell::new(Vec::new())); + let observed_preferences = Rc::new(RefCell::new(Vec::new())); + let _interceptor = cx.update(|_, cx| { + cx.intercept_keystrokes({ + let intercepted_preferences = intercepted_preferences.clone(); + move |event, _, _| { + intercepted_preferences + .borrow_mut() + .push(event.input_preference); + } + }) + }); + let _observer = cx.update(|_, cx| { + cx.observe_keystrokes({ + let observed_preferences = observed_preferences.clone(); + move |event, _, _| { + observed_preferences + .borrow_mut() + .push(event.input_preference); + } + }) + }); + + for (prefer_character_input, accepts_text_input, input_preference) in [ + (true, true, InputPreference::CharacterInput), + (false, true, InputPreference::KeyBindings), + (true, false, InputPreference::KeyBindings), + (false, false, InputPreference::KeyBindings), + ] { + test.update(cx, |test, _| { + test.accepts_text_input.set(accepts_text_input); + test.action_count.set(0); + }); + intercepted_preferences.borrow_mut().clear(); + observed_preferences.borrow_mut().clear(); + let result = dispatch_altgr_key_down(cx, prefer_character_input); + assert_eq!( + result.propagate, + input_preference == InputPreference::CharacterInput + ); + assert_eq!( + intercepted_preferences.borrow().as_slice(), + &[input_preference] + ); + assert_eq!( + observed_preferences.borrow().as_slice(), + &[input_preference] + ); + test.read_with(cx, |test, _| { + assert_eq!( + test.action_count.get(), + usize::from(input_preference == InputPreference::KeyBindings) + ); + }); + } + } + + #[crate::test] + fn test_input_preference_rechecked_after_interception(cx: &mut TestAppContext) { + let (test, cx) = setup_altgr_test(cx); + let accepts_text_input = test.read_with(cx, |test, _| test.accepts_text_input.clone()); + let _interceptor = cx.update(|_, cx| { + cx.intercept_keystrokes({ + let accepts_text_input = accepts_text_input.clone(); + move |event, _, _| { + assert_eq!( + event.input_preference == InputPreference::CharacterInput, + accepts_text_input.get() + ); + accepts_text_input.set(!accepts_text_input.get()); + } + }) + }); + let observed_preferences = Rc::new(RefCell::new(Vec::new())); + let _observer = cx.update(|_, cx| { + cx.observe_keystrokes({ + let observed_preferences = observed_preferences.clone(); + move |event, _, _| { + observed_preferences + .borrow_mut() + .push(event.input_preference); + } + }) + }); + + for (initially_accepts_text_input, observed_preference) in [ + (true, InputPreference::KeyBindings), + (false, InputPreference::CharacterInput), + ] { + accepts_text_input.set(initially_accepts_text_input); + test.update(cx, |test, _| test.action_count.set(0)); + observed_preferences.borrow_mut().clear(); + let result = dispatch_altgr_key_down(cx, true); + assert_eq!(result.propagate, !initially_accepts_text_input); + assert_eq!( + observed_preferences.borrow().as_slice(), + &[observed_preference] + ); + test.read_with(cx, |test, _| { + assert_eq!( + test.action_count.get(), + usize::from(initially_accepts_text_input) + ); + }); + } + } + + #[crate::test] + fn test_keystroke_interceptors_can_consume_preferred_character_input(cx: &mut TestAppContext) { + let (test, cx) = setup_altgr_test(cx); + let intercepted = Rc::new(Cell::new(false)); + let _interceptor = cx.update(|_, cx| { + cx.intercept_keystrokes({ + let intercepted = intercepted.clone(); + move |event, _, cx| { + assert_eq!(event.input_preference, InputPreference::CharacterInput); + intercepted.set(true); + cx.stop_propagation(); + } + }) + }); + + let result = dispatch_altgr_key_down(cx, true); + assert!(intercepted.get()); + assert!(!result.propagate); + test.read_with(cx, |test, _| assert_eq!(test.action_count.get(), 0)); + } + + #[crate::test] + fn test_consumed_modifier_preserves_pending_input(cx: &mut TestAppContext) { + let (test, cx) = cx.add_window_view(|_, cx| PendingTextInputTestView::new(cx)); + test.update_in(cx, |test, window, cx| { + window.focus(&test.focus_handle, cx); + window.activate_window(); + }); + let _subscription = cx.update(|_, cx| { + cx.intercept_keystrokes(|event, _, cx| { + if event.keystroke.key == "shift" { + cx.stop_propagation(); + } + }) + }); + + // Exercise both paths that processing Shift would take: completing `j shift`, and + // replaying `j` when `j k` no longer matches. + for binding in ["j shift", "j k"] { + cx.update(|_, cx| { + cx.clear_key_bindings(); + cx.bind_keys([KeyBinding::new(binding, TestAction, Some("Terminal"))]); + }); + test.update(cx, |test, _| test.text.borrow_mut().clear()); + cx.simulate_keystrokes("j"); + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT / 2); + cx.run_until_parked(); + let pending_keystrokes = cx.update(|window, _| { + window + .pending_input() + .expect("pending input") + .keystrokes() + .to_vec() + }); + + // Consuming Shift must not complete or replay the pending `j`. + cx.simulate_modifiers_change(Modifiers::shift()); + cx.simulate_modifiers_change(Modifiers::none()); + cx.update(|window, _| { + let pending_input = window.pending_input().expect("pending input"); + assert_eq!(pending_input.keystrokes(), pending_keystrokes); + assert!(pending_input.timeout().is_some()); + }); + test.update(cx, |test, _| { + assert_eq!(test.action_count.get(), 0); + assert_eq!(test.text.borrow().as_str(), ""); + }); + + // The unchanged timeout should replay `j` after its remaining half. + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT / 2); + cx.run_until_parked(); + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + test.update(cx, |test, _| { + assert_eq!(test.action_count.get(), 0); + assert_eq!(test.text.borrow().as_str(), "j"); + }); + } + } + + #[crate::test] + fn test_printable_pending_input_replays_on_timeout(cx: &mut TestAppContext) { + cx.update(|cx| { + cx.bind_keys([KeyBinding::new("j k", TestAction, Some("Terminal"))]); + }); + let (test, cx) = cx.add_window_view(|_, cx| PendingTextInputTestView::new(cx)); + let focus_handle = test.update(cx, |test, _| test.focus_handle.clone()); + cx.update(|window, cx| { + window.focus(&focus_handle, cx); + window.activate_window(); + }); + + cx.simulate_keystrokes("j"); + + cx.update(|window, _| { + let pending_input = window.pending_input().expect("pending input"); + assert_eq!(pending_input.keystrokes().len(), 1); + assert!(pending_input.timeout().is_some()); + }); + test.update(cx, |test, _| { + assert_eq!(test.action_count.get(), 0); + assert_eq!(test.text.borrow().as_str(), ""); + }); + + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + test.update(cx, |test, _| { + assert_eq!(test.action_count.get(), 0); + assert_eq!(test.text.borrow().as_str(), "j"); + }); + } + + #[crate::test] + fn test_pending_input_timeout_dispatches_shorter_binding(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + cx.update(|window, _| { + assert_eq!( + window + .pending_input() + .map(|pending_input| pending_input.keystrokes().len()), + Some(1) + ); + assert_eq!( + window + .pending_input() + .and_then(|pending_input| pending_input.timeout()) + .map(|timeout| timeout.duration()), + Some(crate::PENDING_INPUT_TIMEOUT) + ); + }); + assert_eq!(action_count.get(), 0); + + // Emulate a countdown indicator re-rendering the window while waiting for the timeout. + for _ in 0..10 { + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT / 10); + cx.update(|window, _| window.refresh()); + cx.run_until_parked(); + } + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 0); + } + + #[crate::test] + fn test_running_pending_input_timeout_resets_when_binding_advances(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 4 / 5); + cx.run_until_parked(); + cx.simulate_keystrokes("h"); + cx.run_until_parked(); + + cx.update(|window, cx| { + let pending_input = window.pending_input().expect("pending input"); + let timeout = pending_input.timeout().expect("pending input timeout"); + assert_eq!(pending_input.keystrokes().len(), 2); + assert!(!timeout.is_paused()); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT); + }); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT / 5); + cx.run_until_parked(); + cx.update(|window, _| assert!(window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 0); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 4 / 5); + cx.run_until_parked(); + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 1); + } + + #[crate::test] + fn test_pending_input_timeout_starts_when_binding_becomes_ambiguous(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_test( + cx, + [ + KeyBinding::new("ctrl-b h", SecondaryTestAction, Some("Terminal")), + KeyBinding::new("ctrl-b h j", TestAction, Some("Terminal")), + ], + ); + simulate_pending_binding(cx); + + cx.update(|window, _| { + let pending_input = window.pending_input().expect("pending input"); + assert_eq!(pending_input.keystrokes().len(), 1); + assert!(pending_input.timeout().is_none()); + }); + + cx.simulate_keystrokes("h"); + cx.run_until_parked(); + cx.update(|window, cx| { + let pending_input = window.pending_input().expect("pending input"); + let timeout = pending_input.timeout().expect("pending input timeout"); + assert_eq!(pending_input.keystrokes().len(), 2); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT); + }); + + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 1); + } + + #[crate::test] + fn test_invalid_continuation_while_timeout_paused_replays_pending_input( + cx: &mut TestAppContext, + ) { + let (cx, action_count, secondary_action_count) = setup_pending_input_test( + cx, + [ + KeyBinding::new("ctrl-b", TestAction, Some("Terminal")), + KeyBinding::new("ctrl-b h", SecondaryTestAction, Some("Terminal")), + KeyBinding::new("x", SecondaryTestAction, Some("Terminal")), + ], + ); + simulate_pending_binding(cx); + let pause_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + }); + cx.run_until_parked(); + + cx.simulate_keystrokes("x"); + cx.run_until_parked(); + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 1); + + drop(pause_owner); + cx.update(|_, _| {}); + cx.run_until_parked(); + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + + cx.update(|window, _| assert!(window.pending_input_is_none())); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 1); + } + + #[crate::test] + fn test_pending_input_timeout_pauses_and_resumes(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 7 / 10); + cx.run_until_parked(); + + let pause_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + let other_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + assert!(!window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + assert!(!window.set_pending_input_timeout_paused(&other_owner, false, cx)); + }); + cx.run_until_parked(); + cx.update(|window, cx| { + let timeout = window + .pending_input() + .and_then(|pending_input| pending_input.timeout()) + .expect("pending input timeout"); + assert!(timeout.is_paused()); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT * 3 / 10); + }); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 2); + cx.run_until_parked(); + cx.update(|window, _| assert!(window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, false, cx)); + }); + cx.run_until_parked(); + cx.update(|window, cx| { + let timeout = window + .pending_input() + .and_then(|pending_input| pending_input.timeout()) + .expect("pending input timeout"); + assert!(!timeout.is_paused()); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT * 3 / 10); + }); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 3 / 10); + cx.run_until_parked(); + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 0); + } + + #[crate::test] + fn test_pending_input_timeout_resumes_when_owner_is_released(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 7 / 10); + cx.run_until_parked(); + + let pause_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + }); + cx.run_until_parked(); + + drop(pause_owner); + cx.update(|_, _| {}); + cx.run_until_parked(); + cx.update(|window, cx| { + let timeout = window + .pending_input() + .and_then(|pending_input| pending_input.timeout()) + .expect("pending input timeout"); + assert!(!timeout.is_paused()); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT * 3 / 10); + }); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 3 / 10); + cx.run_until_parked(); + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 1); + assert_eq!(secondary_action_count.get(), 0); + } + + #[crate::test] + fn test_pending_input_timeout_resets_when_binding_advances(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT / 2); + cx.run_until_parked(); + let pause_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + }); + cx.run_until_parked(); + cx.update(|window, cx| { + let timeout = window + .pending_input() + .and_then(|pending_input| pending_input.timeout()) + .expect("pending input timeout"); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT / 2); + }); + + cx.simulate_keystrokes("h"); + cx.run_until_parked(); + cx.update(|window, cx| { + let pending_input = window.pending_input().expect("pending input"); + let timeout = pending_input.timeout().expect("pending input timeout"); + assert_eq!(pending_input.keystrokes().len(), 2); + assert!(timeout.is_paused()); + assert_eq!(timeout.remaining(cx), crate::PENDING_INPUT_TIMEOUT); + }); + + cx.executor() + .advance_clock(crate::PENDING_INPUT_TIMEOUT * 2); + cx.run_until_parked(); + cx.update(|window, _| assert!(window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 0); + + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, false, cx)); + }); + cx.run_until_parked(); + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 1); + } + + #[crate::test] + fn test_clearing_pending_input_invalidates_timeout_pause(cx: &mut TestAppContext) { + let (cx, action_count, secondary_action_count) = setup_pending_input_timeout_test(cx); + simulate_pending_binding(cx); + let pause_owner = cx.update(|_, cx| cx.new(|_| PendingInputTimeoutPauseOwner)); + cx.update(|window, cx| { + assert!(window.set_pending_input_timeout_paused(&pause_owner, true, cx)); + window.focus(&cx.focus_handle(), cx); + assert!(!window.has_pending_keystrokes()); + }); + + drop(pause_owner); + cx.update(|_, _| {}); + cx.run_until_parked(); + cx.executor().advance_clock(crate::PENDING_INPUT_TIMEOUT); + cx.run_until_parked(); + + cx.update(|window, _| assert!(window.pending_input_is_none())); + assert_eq!(action_count.get(), 0); + assert_eq!(secondary_action_count.get(), 0); + } + + #[crate::test] + fn test_input_handler_pending(cx: &mut TestAppContext) { + cx.update(|cx| { + cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]); + cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]); + cx.bind_keys([KeyBinding::new("ctrl-x k", TestAction, Some("Terminal"))]); + }); + let (test, cx) = cx.add_window_view(|_, cx| PendingTextInputTestView::new(cx)); + let focus_handle = test.update(cx, |test, _| test.focus_handle.clone()); + cx.update(|window, cx| { + window.focus(&focus_handle, cx); + window.activate_window(); + }); + + assert_eq!(query_prefers_ime_for_printable_keys(cx), Some(true)); + cx.simulate_keystrokes("ctrl-x"); + cx.update(|window, _| assert!(window.has_pending_keystrokes())); + assert_eq!(query_prefers_ime_for_printable_keys(cx), Some(false)); + + let prefers_ime_after_blur = { + let mut platform_window = cx.test_window(cx.window_handle()); + let mut input_handler = platform_window.take_input_handler(); + cx.update(|window, cx| { + window.blur(cx); + assert!(!window.has_pending_keystrokes()); + assert!(window.pending_input_is_none()); + }); + let prefers_ime = input_handler + .as_mut() + .map(|input_handler| input_handler.query_prefers_ime_for_printable_keys()); + if let Some(input_handler) = input_handler { + platform_window.set_input_handler(input_handler); + } + prefers_ime + }; + assert_eq!(prefers_ime_after_blur, Some(true)); + cx.update(|window, cx| window.focus(&focus_handle, cx)); + + cx.simulate_keystrokes("ctrl-x"); + assert_eq!(query_prefers_ime_for_printable_keys(cx), Some(false)); + cx.simulate_keystrokes("k"); + cx.update(|window, _| assert!(!window.has_pending_keystrokes())); + assert_eq!(query_prefers_ime_for_printable_keys(cx), Some(true)); + test.update(cx, |test, _| { + assert_eq!(test.action_count.get(), 1); + assert_eq!(test.text.borrow().as_str(), ""); + }); + + cx.simulate_keystrokes("ctrl-b ["); + test.update(cx, |test, _| assert_eq!(test.text.borrow().as_str(), "[")) + } +} diff --git a/vendor/gpui-pre/src/keymap.rs b/vendor/gpui-pre/src/keymap.rs new file mode 100644 index 00000000..477c5a0a --- /dev/null +++ b/vendor/gpui-pre/src/keymap.rs @@ -0,0 +1,1135 @@ +mod binding; +mod context; + +pub use binding::*; +pub use context::*; + +use crate::{Action, AsKeystroke, Keystroke, Unbind, is_no_action, is_unbind}; +use collections::{HashSet, TypeIdHashMap}; +use smallvec::SmallVec; + +/// An opaque identifier of which version of the keymap is currently active. +/// The keymap's version is changed whenever bindings are added or removed. +#[derive(Copy, Clone, Eq, PartialEq, Default)] +pub struct KeymapVersion(usize); + +/// A collection of key bindings for the user's application. +#[derive(Default)] +pub struct Keymap { + bindings: Vec, + binding_indices_by_action_id: TypeIdHashMap>, + disabled_binding_indices: Vec, + version: KeymapVersion, +} + +/// Index of a binding within a keymap. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct BindingIndex(usize); + +fn disabled_binding_matches_context(disabled_binding: &KeyBinding, binding: &KeyBinding) -> bool { + match ( + &disabled_binding.context_predicate, + &binding.context_predicate, + ) { + (None, _) => true, + (Some(_), None) => false, + (Some(disabled_predicate), Some(predicate)) => disabled_predicate.is_superset(predicate), + } +} + +fn binding_is_unbound(disabled_binding: &KeyBinding, binding: &KeyBinding) -> bool { + disabled_binding.keystrokes == binding.keystrokes + && disabled_binding + .action() + .as_any() + .downcast_ref::() + .is_some_and(|unbind| unbind.0.as_ref() == binding.action.name()) +} + +impl Keymap { + /// Create a new keymap with the given bindings. + pub fn new(bindings: Vec) -> Self { + let mut this = Self::default(); + this.add_bindings(bindings); + this + } + + /// Get the current version of the keymap. + pub fn version(&self) -> KeymapVersion { + self.version + } + + /// Add more bindings to the keymap. + pub fn add_bindings>(&mut self, bindings: T) { + for binding in bindings { + let action_id = binding.action().as_any().type_id(); + if is_no_action(&*binding.action) || is_unbind(&*binding.action) { + self.disabled_binding_indices.push(self.bindings.len()); + } else { + self.binding_indices_by_action_id + .entry(action_id) + .or_default() + .push(self.bindings.len()); + } + self.bindings.push(binding); + } + + self.version.0 += 1; + } + + /// Reset this keymap to its initial state. + pub fn clear(&mut self) { + self.bindings.clear(); + self.binding_indices_by_action_id.clear(); + self.disabled_binding_indices.clear(); + self.version.0 += 1; + } + + /// Iterate over all bindings, in the order they were added. + pub fn bindings(&self) -> impl DoubleEndedIterator + ExactSizeIterator { + self.bindings.iter() + } + + /// Iterate over all bindings for the given action, in the order they were added. For display, + /// the last binding should take precedence. + pub fn bindings_for_action<'a>( + &'a self, + action: &'a dyn Action, + ) -> impl 'a + DoubleEndedIterator { + let action_id = action.type_id(); + let binding_indices = self + .binding_indices_by_action_id + .get(&action_id) + .map_or(&[] as _, SmallVec::as_slice) + .iter(); + + binding_indices.filter_map(|ix| { + let binding = &self.bindings[*ix]; + if !binding.action().partial_eq(action) { + return None; + } + + for disabled_ix in &self.disabled_binding_indices { + if disabled_ix > ix { + let disabled_binding = &self.bindings[*disabled_ix]; + if disabled_binding.keystrokes != binding.keystrokes { + continue; + } + + if is_no_action(&*disabled_binding.action) { + if disabled_binding_matches_context(disabled_binding, binding) { + return None; + } + } else if is_unbind(&*disabled_binding.action) + && disabled_binding_matches_context(disabled_binding, binding) + && binding_is_unbound(disabled_binding, binding) + { + return None; + } + } + } + + Some(binding) + }) + } + + /// Returns all bindings that might match the input without checking context. The bindings + /// returned in precedence order (reverse of the order they were added to the keymap). + pub fn all_bindings_for_input(&self, input: &[Keystroke]) -> Vec { + self.bindings() + .rev() + .filter(|binding| { + binding + .match_keystrokes(input) + .is_some_and(|pending| !pending) + }) + .cloned() + .collect() + } + + /// Returns a list of bindings that match the given input, and a boolean indicating whether or + /// not more bindings might match if the input was longer. Bindings are returned in precedence + /// order (higher precedence first, reverse of the order they were added to the keymap). + /// + /// Precedence is defined by the depth in the tree (matches on the Editor take precedence over + /// matches on the Pane, then the Workspace, etc.). Bindings with no context are treated as the + /// same as the deepest context. + /// + /// In the case of multiple bindings at the same depth, the ones added to the keymap later take + /// precedence. User bindings are added after built-in bindings so that they take precedence. + /// + /// If a binding has been disabled with `"x": null` it will not be returned. Disabled bindings + /// are evaluated with the same precedence rules so you can disable a rule in a given context + /// only. A disabled binding only suppresses bindings from sources with equal or weaker + /// precedence: a base keymap null hides default bindings, but user bindings still apply. + pub fn bindings_for_input( + &self, + input: &[impl AsKeystroke], + context_stack: &[KeyContext], + ) -> (SmallVec<[KeyBinding; 1]>, bool) { + let (bindings, pending) = self.resolve_bindings_for_input( + input, + context_stack, + self.bindings().enumerate().rev(), + ); + ( + bindings + .into_iter() + .map(|(_, binding)| binding.clone()) + .collect(), + pending, + ) + } + + /// Same as `bindings_for_input`, but only looks at `keymap_bindings` instead of the whole + /// keymap, and returns each binding with its keymap index. + /// + /// `keymap_bindings` must be in reverse keymap order and include every binding that could + /// match `input`. For example, leaving out a `null` binding would make the binding it disables + /// look like it wins. `bindings_for_input` passes the whole keymap, which always meets this but + /// goes through every binding on every call. Passing a pre-filtered list is cheaper when + /// resolving many inputs against it. + fn resolve_bindings_for_input<'a>( + &self, + input: &[impl AsKeystroke], + context_stack: &[KeyContext], + keymap_bindings: impl IntoIterator, + ) -> (SmallVec<[(BindingIndex, &'a KeyBinding); 1]>, bool) { + let mut matched_bindings = SmallVec::<[(usize, BindingIndex, &KeyBinding); 1]>::new(); + let mut pending_bindings = SmallVec::<[(BindingIndex, &KeyBinding); 1]>::new(); + + for (ix, binding) in keymap_bindings { + let Some(depth) = self.binding_enabled(binding, context_stack) else { + continue; + }; + let Some(pending) = binding.match_keystrokes(input) else { + continue; + }; + + if !pending { + matched_bindings.push((depth, BindingIndex(ix), binding)); + } else { + pending_bindings.push((BindingIndex(ix), binding)); + } + } + + matched_bindings.sort_by(|(depth_a, ix_a, _), (depth_b, ix_b, _)| { + depth_b.cmp(depth_a).then(ix_b.cmp(ix_a)) + }); + + let mut bindings: SmallVec<[_; 1]> = SmallVec::new(); + let mut first_binding_index = None; + let mut unbound_bindings: Vec<&KeyBinding> = Vec::new(); + // A `NoAction` binding suppresses out-ranked bindings from sources with + // equal or weaker precedence, while bindings from stronger sources (a + // smaller meta, e.g. a user binding vs a base keymap null) still apply. + // Bindings without a meta are treated as user bindings. + let mut no_action_meta: Option = None; + + for (_, ix, binding) in matched_bindings { + let meta = binding.meta.map_or(0, |meta| meta.0); + if is_no_action(&*binding.action) { + no_action_meta = Some(no_action_meta.map_or(meta, |existing| existing.min(meta))); + continue; + } + + if no_action_meta.is_some_and(|no_action_meta| meta >= no_action_meta) { + continue; + } + + if is_unbind(&*binding.action) { + unbound_bindings.push(binding); + continue; + } + + if unbound_bindings + .iter() + .any(|disabled_binding| binding_is_unbound(disabled_binding, binding)) + { + continue; + } + + bindings.push((ix, binding)); + first_binding_index.get_or_insert(ix); + } + + let mut pending = HashSet::default(); + for (ix, binding) in pending_bindings.into_iter().rev() { + if let Some(binding_ix) = first_binding_index + && binding_ix > ix + { + continue; + } + if is_no_action(&*binding.action) || is_unbind(&*binding.action) { + pending.remove(&&binding.keystrokes); + continue; + } + pending.insert(&binding.keystrokes); + } + + (bindings, !pending.is_empty()) + } + /// Check if the given binding is enabled, given a certain key context. + /// Returns the deepest depth at which the binding matches, or None if it doesn't match. + fn binding_enabled(&self, binding: &KeyBinding, contexts: &[KeyContext]) -> Option { + if let Some(predicate) = &binding.context_predicate { + predicate.depth_of(contexts) + } else { + Some(contexts.len()) + } + } + + /// Find the bindings that can follow the current input sequence, in precedence order. Only + /// includes bindings that dispatch would run for their full keystrokes, so bindings disabled + /// with `null` or `Unbind` are left out. + pub fn possible_next_bindings_for_input( + &self, + input: &[Keystroke], + context_stack: &[KeyContext], + ) -> Vec { + // Keeps `null` and `Unbind` bindings, which can disable candidates. + let bindings_extending_input = self + .bindings() + .enumerate() + .rev() + .filter(|(_, binding)| { + binding + .match_keystrokes(input) + .is_some_and(|pending| pending) + }) + .collect::>(); + + let mut full_input = SmallVec::<[&Keystroke; 4]>::new(); + let mut candidates = bindings_extending_input + .iter() + .filter(|(_, binding)| !is_no_action(&*binding.action) && !is_unbind(&*binding.action)) + .filter_map(|&(ix, binding)| { + let depth = self.binding_enabled(binding, context_stack)?; + // Use the typed input rather than the binding's own keystrokes. A typed keystroke + // can match through its physical key, like `alt-s`, or the character it produced, + // like `ß`. + full_input.clear(); + full_input.extend(input.iter()); + full_input.extend( + binding.keystrokes[input.len()..] + .iter() + .map(AsKeystroke::as_keystroke), + ); + let (dispatched, _) = self.resolve_bindings_for_input( + &full_input, + context_stack, + bindings_extending_input.iter().copied(), + ); + dispatched + .iter() + .any(|(dispatched_ix, _)| *dispatched_ix == BindingIndex(ix)) + .then_some((depth, ix, binding)) + }) + .collect::>(); + candidates.sort_unstable_by(|(depth_a, ix_a, _), (depth_b, ix_b, _)| { + depth_b.cmp(depth_a).then(ix_b.cmp(ix_a)) + }); + + candidates + .into_iter() + .map(|(_, _, binding)| binding.clone()) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate as gpui; + use gpui::{NoAction, Unbind}; + + actions!( + test_only, + [ActionAlpha, ActionBeta, ActionGamma, ActionDelta,] + ); + + #[test] + fn test_keymap() { + let bindings = [ + KeyBinding::new("ctrl-a", ActionAlpha {}, None), + KeyBinding::new("ctrl-a", ActionBeta {}, Some("pane")), + KeyBinding::new("ctrl-a", ActionGamma {}, Some("editor && mode==full")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings.clone()); + + // global bindings are enabled in all contexts + assert_eq!(keymap.binding_enabled(&bindings[0], &[]), Some(0)); + assert_eq!( + keymap.binding_enabled(&bindings[0], &[KeyContext::parse("terminal").unwrap()]), + Some(1) + ); + + // contextual bindings are enabled in contexts that match their predicate + assert_eq!( + keymap.binding_enabled(&bindings[1], &[KeyContext::parse("barf x=y").unwrap()]), + None + ); + assert_eq!( + keymap.binding_enabled(&bindings[1], &[KeyContext::parse("pane x=y").unwrap()]), + Some(1) + ); + + assert_eq!( + keymap.binding_enabled(&bindings[2], &[KeyContext::parse("editor").unwrap()]), + None + ); + assert_eq!( + keymap.binding_enabled( + &bindings[2], + &[KeyContext::parse("editor mode=full").unwrap()] + ), + Some(1) + ); + } + + #[test] + fn test_depth_precedence() { + let bindings = [ + KeyBinding::new("ctrl-a", ActionBeta {}, Some("pane")), + KeyBinding::new("ctrl-a", ActionGamma {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-a").unwrap()], + &[ + KeyContext::parse("pane").unwrap(), + KeyContext::parse("editor").unwrap(), + ], + ); + + assert!(!pending); + assert_eq!(result.len(), 2); + assert!(result[0].action.partial_eq(&ActionGamma {})); + assert!(result[1].action.partial_eq(&ActionBeta {})); + } + + #[test] + fn test_keymap_disabled() { + let bindings = [ + KeyBinding::new("ctrl-a", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-b", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-a", NoAction {}, Some("editor && mode==full")), + KeyBinding::new("ctrl-b", NoAction {}, None), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // binding is only enabled in a specific context + assert!( + keymap + .bindings_for_input( + &[Keystroke::parse("ctrl-a").unwrap()], + &[KeyContext::parse("barf").unwrap()], + ) + .0 + .is_empty() + ); + assert!( + !keymap + .bindings_for_input( + &[Keystroke::parse("ctrl-a").unwrap()], + &[KeyContext::parse("editor").unwrap()], + ) + .0 + .is_empty() + ); + + // binding is disabled in a more specific context + assert!( + keymap + .bindings_for_input( + &[Keystroke::parse("ctrl-a").unwrap()], + &[KeyContext::parse("editor mode=full").unwrap()], + ) + .0 + .is_empty() + ); + + // binding is globally disabled + assert!( + keymap + .bindings_for_input( + &[Keystroke::parse("ctrl-b").unwrap()], + &[KeyContext::parse("barf").unwrap()], + ) + .0 + .is_empty() + ); + } + + #[test] + /// Tests for https://github.com/zed-industries/zed/issues/30259 + fn test_multiple_keystroke_binding_disabled() { + let bindings = [ + KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")), + KeyBinding::new("space w w", NoAction {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let space = || Keystroke::parse("space").unwrap(); + let w = || Keystroke::parse("w").unwrap(); + + let space_w = [space(), w()]; + let space_w_w = [space(), w(), w()]; + + let workspace_context = || [KeyContext::parse("workspace").unwrap()]; + + let editor_workspace_context = || { + [ + KeyContext::parse("workspace").unwrap(), + KeyContext::parse("editor").unwrap(), + ] + }; + + // Ensure `space` results in pending input on the workspace, but not editor + let space_workspace = keymap.bindings_for_input(&[space()], &workspace_context()); + assert!(space_workspace.0.is_empty()); + assert!(space_workspace.1); + + let space_editor = keymap.bindings_for_input(&[space()], &editor_workspace_context()); + assert!(space_editor.0.is_empty()); + assert!(!space_editor.1); + + // Ensure `space w` results in pending input on the workspace, but not editor + let space_w_workspace = keymap.bindings_for_input(&space_w, &workspace_context()); + assert!(space_w_workspace.0.is_empty()); + assert!(space_w_workspace.1); + + let space_w_editor = keymap.bindings_for_input(&space_w, &editor_workspace_context()); + assert!(space_w_editor.0.is_empty()); + assert!(!space_w_editor.1); + + // Ensure `space w w` results in the binding in the workspace, but not in the editor + let space_w_w_workspace = keymap.bindings_for_input(&space_w_w, &workspace_context()); + assert!(!space_w_w_workspace.0.is_empty()); + assert!(!space_w_w_workspace.1); + + let space_w_w_editor = keymap.bindings_for_input(&space_w_w, &editor_workspace_context()); + assert!(space_w_w_editor.0.is_empty()); + assert!(!space_w_w_editor.1); + + // Now test what happens if we have another binding defined AFTER the NoAction + // that should result in pending + let bindings = [ + KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")), + KeyBinding::new("space w w", NoAction {}, Some("editor")), + KeyBinding::new("space w x", ActionAlpha {}, Some("editor")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let space_editor = keymap.bindings_for_input(&[space()], &editor_workspace_context()); + assert!(space_editor.0.is_empty()); + assert!(space_editor.1); + + // Now test what happens if we have another binding defined BEFORE the NoAction + // that should result in pending + let bindings = [ + KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")), + KeyBinding::new("space w x", ActionAlpha {}, Some("editor")), + KeyBinding::new("space w w", NoAction {}, Some("editor")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let space_editor = keymap.bindings_for_input(&[space()], &editor_workspace_context()); + assert!(space_editor.0.is_empty()); + assert!(space_editor.1); + + // Now test what happens if we have another binding defined at a higher context + // that should result in pending + let bindings = [ + KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")), + KeyBinding::new("space w x", ActionAlpha {}, Some("workspace")), + KeyBinding::new("space w w", NoAction {}, Some("editor")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let space_editor = keymap.bindings_for_input(&[space()], &editor_workspace_context()); + assert!(space_editor.0.is_empty()); + assert!(space_editor.1); + } + + #[test] + fn test_override_multikey() { + let bindings = [ + KeyBinding::new("ctrl-w left", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-w", NoAction {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Ensure `space` results in pending input on the workspace, but not editor + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-w").unwrap()], + &[KeyContext::parse("editor").unwrap()], + ); + assert!(result.is_empty()); + assert!(pending); + + let bindings = [ + KeyBinding::new("ctrl-w left", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-w", ActionBeta {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Ensure `space` results in pending input on the workspace, but not editor + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-w").unwrap()], + &[KeyContext::parse("editor").unwrap()], + ); + assert_eq!(result.len(), 1); + assert!(!pending); + } + + #[test] + fn test_simple_disable() { + let bindings = [ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Ensure `space` results in pending input on the workspace, but not editor + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x").unwrap()], + &[KeyContext::parse("editor").unwrap()], + ); + assert!(result.is_empty()); + assert!(!pending); + } + + #[test] + fn test_disable_weaker_sources_only() { + const USER: KeyBindingMetaIndex = KeyBindingMetaIndex(0); + const VIM: KeyBindingMetaIndex = KeyBindingMetaIndex(1); + const BASE: KeyBindingMetaIndex = KeyBindingMetaIndex(2); + const DEFAULT: KeyBindingMetaIndex = KeyBindingMetaIndex(3); + + let editor_context = || [KeyContext::parse("editor").unwrap()]; + let ctrl_x = || [Keystroke::parse("ctrl-x").unwrap()]; + + // A base keymap null disables a default binding in the same context. + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")).with_meta(DEFAULT), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(BASE), + ]); + let (result, _) = keymap.bindings_for_input(&ctrl_x(), &editor_context()); + assert!(result.is_empty()); + + // A user binding is not affected by base keymap or default nulls. + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(DEFAULT), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(BASE), + KeyBinding::new("ctrl-x", ActionBeta {}, None).with_meta(USER), + ]); + let (result, _) = keymap.bindings_for_input(&ctrl_x(), &editor_context()); + assert_eq!(result.len(), 1); + assert!(result[0].action.partial_eq(&ActionBeta {})); + + // A user binding at a shallower context is not disabled by a deeper + // base keymap null. + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(BASE), + KeyBinding::new("ctrl-x", ActionBeta {}, Some("workspace")).with_meta(USER), + ]); + let (result, _) = keymap.bindings_for_input( + &ctrl_x(), + &[ + KeyContext::parse("workspace").unwrap(), + KeyContext::parse("editor").unwrap(), + ], + ); + assert_eq!(result.len(), 1); + assert!(result[0].action.partial_eq(&ActionBeta {})); + + // A vim binding survives a base keymap null, and a user null disables + // everything. + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")).with_meta(DEFAULT), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(BASE), + KeyBinding::new("ctrl-x", ActionGamma {}, Some("editor")).with_meta(VIM), + ]); + let (result, _) = keymap.bindings_for_input(&ctrl_x(), &editor_context()); + assert_eq!(result.len(), 1); + assert!(result[0].action.partial_eq(&ActionGamma {})); + + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")).with_meta(DEFAULT), + KeyBinding::new("ctrl-x", ActionGamma {}, Some("editor")).with_meta(VIM), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")).with_meta(USER), + ]); + let (result, _) = keymap.bindings_for_input(&ctrl_x(), &editor_context()); + assert!(result.is_empty()); + } + + #[test] + fn test_fail_to_disable() { + // disabled at the wrong level + let bindings = [ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")), + KeyBinding::new("ctrl-x", NoAction {}, Some("workspace")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Ensure `space` results in pending input on the workspace, but not editor + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x").unwrap()], + &[ + KeyContext::parse("workspace").unwrap(), + KeyContext::parse("editor").unwrap(), + ], + ); + assert_eq!(result.len(), 1); + assert!(!pending); + } + + #[test] + fn test_disable_deeper() { + let bindings = [ + KeyBinding::new("ctrl-x", ActionAlpha {}, Some("workspace")), + KeyBinding::new("ctrl-x", NoAction {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Ensure `space` results in pending input on the workspace, but not editor + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x").unwrap()], + &[ + KeyContext::parse("workspace").unwrap(), + KeyContext::parse("editor").unwrap(), + ], + ); + assert_eq!(result.len(), 0); + assert!(!pending); + } + + #[test] + fn test_pending_match_enabled() { + let bindings = [ + KeyBinding::new("ctrl-x", ActionBeta, Some("vim_mode == normal")), + KeyBinding::new("ctrl-x 0", ActionAlpha, Some("Workspace")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let matched = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x")].map(Result::unwrap), + &[ + KeyContext::parse("Workspace"), + KeyContext::parse("Pane"), + KeyContext::parse("Editor vim_mode=normal"), + ] + .map(Result::unwrap), + ); + assert_eq!(matched.0.len(), 1); + assert!(matched.0[0].action.partial_eq(&ActionBeta)); + assert!(matched.1); + } + + #[test] + fn test_pending_match_enabled_extended() { + let bindings = [ + KeyBinding::new("ctrl-x", ActionBeta, Some("vim_mode == normal")), + KeyBinding::new("ctrl-x 0", NoAction, Some("Workspace")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let matched = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x")].map(Result::unwrap), + &[ + KeyContext::parse("Workspace"), + KeyContext::parse("Pane"), + KeyContext::parse("Editor vim_mode=normal"), + ] + .map(Result::unwrap), + ); + assert_eq!(matched.0.len(), 1); + assert!(matched.0[0].action.partial_eq(&ActionBeta)); + assert!(!matched.1); + let bindings = [ + KeyBinding::new("ctrl-x", ActionBeta, Some("Workspace")), + KeyBinding::new("ctrl-x 0", NoAction, Some("vim_mode == normal")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let matched = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x")].map(Result::unwrap), + &[ + KeyContext::parse("Workspace"), + KeyContext::parse("Pane"), + KeyContext::parse("Editor vim_mode=normal"), + ] + .map(Result::unwrap), + ); + assert_eq!(matched.0.len(), 1); + assert!(matched.0[0].action.partial_eq(&ActionBeta)); + assert!(!matched.1); + } + + #[test] + fn test_overriding_prefix() { + let bindings = [ + KeyBinding::new("ctrl-x 0", ActionAlpha, Some("Workspace")), + KeyBinding::new("ctrl-x", ActionBeta, Some("vim_mode == normal")), + ]; + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let matched = keymap.bindings_for_input( + &[Keystroke::parse("ctrl-x")].map(Result::unwrap), + &[ + KeyContext::parse("Workspace"), + KeyContext::parse("Pane"), + KeyContext::parse("Editor vim_mode=normal"), + ] + .map(Result::unwrap), + ); + assert_eq!(matched.0.len(), 1); + assert!(matched.0[0].action.partial_eq(&ActionBeta)); + assert!(!matched.1); + } + + #[test] + fn test_context_precedence_with_same_source() { + // Test case: User has both Workspace and Editor bindings for the same key + // Editor binding should take precedence over Workspace binding + let bindings = [ + KeyBinding::new("cmd-r", ActionAlpha {}, Some("Workspace")), + KeyBinding::new("cmd-r", ActionBeta {}, Some("Editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + // Test with context stack: [Workspace, Editor] (Editor is deeper) + let (result, _) = keymap.bindings_for_input( + &[Keystroke::parse("cmd-r").unwrap()], + &[ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("Editor").unwrap(), + ], + ); + + // Both bindings should be returned, but Editor binding should be first (highest precedence) + assert_eq!(result.len(), 2); + assert!(result[0].action.partial_eq(&ActionBeta {})); // Editor binding first + assert!(result[1].action.partial_eq(&ActionAlpha {})); // Workspace binding second + } + + #[test] + fn test_bindings_for_action() { + let bindings = [ + KeyBinding::new("ctrl-a", ActionAlpha {}, Some("pane")), + KeyBinding::new("ctrl-b", ActionBeta {}, Some("editor && mode == full")), + KeyBinding::new("ctrl-c", ActionGamma {}, Some("workspace")), + KeyBinding::new("ctrl-a", NoAction {}, Some("pane && active")), + KeyBinding::new("ctrl-b", NoAction {}, Some("editor")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + assert_bindings(&keymap, &ActionAlpha {}, &["ctrl-a"]); + assert_bindings(&keymap, &ActionBeta {}, &[]); + assert_bindings(&keymap, &ActionGamma {}, &["ctrl-c"]); + + #[track_caller] + fn assert_bindings(keymap: &Keymap, action: &dyn Action, expected: &[&str]) { + let actual = keymap + .bindings_for_action(action) + .map(|binding| binding.keystrokes[0].inner().unparse()) + .collect::>(); + assert_eq!(actual, expected, "{:?}", action); + } + } + + #[test] + fn test_targeted_unbind_ignores_target_context() { + let bindings = [ + KeyBinding::new("tab", ActionAlpha {}, Some("Editor")), + KeyBinding::new("tab", ActionBeta {}, Some("Editor && showing_completions")), + KeyBinding::new( + "tab", + Unbind("test_only::ActionAlpha".into()), + Some("Editor && edit_prediction"), + ), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + let (result, pending) = keymap.bindings_for_input( + &[Keystroke::parse("tab").unwrap()], + &[KeyContext::parse("Editor showing_completions edit_prediction").unwrap()], + ); + + assert!(!pending); + assert_eq!(result.len(), 1); + assert!(result[0].action.partial_eq(&ActionBeta {})); + } + + #[test] + fn test_bindings_for_action_keeps_binding_for_narrower_targeted_unbind() { + let bindings = [ + KeyBinding::new("tab", ActionAlpha {}, Some("Editor")), + KeyBinding::new( + "tab", + Unbind("test_only::ActionAlpha".into()), + Some("Editor && edit_prediction"), + ), + KeyBinding::new("tab", ActionBeta {}, Some("Editor && showing_completions")), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + assert_bindings(&keymap, &ActionAlpha {}, &["tab"]); + assert_bindings(&keymap, &ActionBeta {}, &["tab"]); + + #[track_caller] + fn assert_bindings(keymap: &Keymap, action: &dyn Action, expected: &[&str]) { + let actual = keymap + .bindings_for_action(action) + .map(|binding| binding.keystrokes[0].inner().unparse()) + .collect::>(); + assert_eq!(actual, expected, "{:?}", action); + } + } + + #[test] + fn test_bindings_for_action_removes_binding_for_broader_targeted_unbind() { + let bindings = [ + KeyBinding::new("tab", ActionAlpha {}, Some("Editor && edit_prediction")), + KeyBinding::new( + "tab", + Unbind("test_only::ActionAlpha".into()), + Some("Editor"), + ), + ]; + + let mut keymap = Keymap::default(); + keymap.add_bindings(bindings); + + assert!(keymap.bindings_for_action(&ActionAlpha {}).next().is_none()); + } + + #[test] + fn test_source_precedence_sorting() { + // KeybindSource precedence: User (0) > Vim (1) > Base (2) > Default (3) + // Test that user keymaps take precedence over default keymaps at the same context depth + let mut keymap = Keymap::default(); + + // Add a default keymap binding first + let mut default_binding = KeyBinding::new("cmd-r", ActionAlpha {}, Some("Editor")); + default_binding.set_meta(KeyBindingMetaIndex(3)); // Default source + keymap.add_bindings([default_binding]); + + // Add a user keymap binding + let mut user_binding = KeyBinding::new("cmd-r", ActionBeta {}, Some("Editor")); + user_binding.set_meta(KeyBindingMetaIndex(0)); // User source + keymap.add_bindings([user_binding]); + + // Test with Editor context stack + let (result, _) = keymap.bindings_for_input( + &[Keystroke::parse("cmd-r").unwrap()], + &[KeyContext::parse("Editor").unwrap()], + ); + + // User binding should take precedence over default binding + assert_eq!(result.len(), 2); + assert!(result[0].action.partial_eq(&ActionBeta {})); + assert!(result[1].action.partial_eq(&ActionAlpha {})); + } + + #[test] + fn test_possible_next_bindings_exclude_null_bindings() { + let keymap = Keymap::new(vec![ + KeyBinding::new("ctrl-k a", ActionAlpha {}, Some("Editor")), + KeyBinding::new("ctrl-k b", ActionBeta {}, Some("Editor")), + KeyBinding::new("ctrl-k a", NoAction {}, Some("Editor")), + ]); + + let bindings = keymap.possible_next_bindings_for_input( + &[Keystroke::parse("ctrl-k").unwrap()], + &[KeyContext::parse("Editor").unwrap()], + ); + assert_eq!( + describe_bindings(&bindings), + vec![("ctrl-k b".to_string(), "test_only::ActionBeta")] + ); + } + + #[test] + fn test_possible_next_bindings_exclude_unbound_bindings() { + let keymap = Keymap::new(vec![ + KeyBinding::new("ctrl-k a", ActionAlpha {}, Some("Editor")), + KeyBinding::new("ctrl-k b", ActionBeta {}, Some("Editor")), + KeyBinding::new( + "ctrl-k a", + Unbind("test_only::ActionAlpha".into()), + Some("Editor"), + ), + ]); + + let bindings = keymap.possible_next_bindings_for_input( + &[Keystroke::parse("ctrl-k").unwrap()], + &[KeyContext::parse("Editor").unwrap()], + ); + assert_eq!( + describe_bindings(&bindings), + vec![("ctrl-k b".to_string(), "test_only::ActionBeta")] + ); + } + + #[test] + fn test_possible_next_bindings_keep_user_binding_over_base_keymap_null() { + const USER: KeyBindingMetaIndex = KeyBindingMetaIndex(0); + const BASE: KeyBindingMetaIndex = KeyBindingMetaIndex(2); + const DEFAULT: KeyBindingMetaIndex = KeyBindingMetaIndex(3); + + let mut keymap = Keymap::default(); + keymap.add_bindings([ + KeyBinding::new("ctrl-k a", ActionAlpha {}, Some("Editor")).with_meta(DEFAULT), + KeyBinding::new("ctrl-k a", NoAction {}, Some("Editor")).with_meta(BASE), + KeyBinding::new("ctrl-k a", ActionBeta {}, Some("Editor")).with_meta(USER), + ]); + + let bindings = keymap.possible_next_bindings_for_input( + &[Keystroke::parse("ctrl-k").unwrap()], + &[KeyContext::parse("Editor").unwrap()], + ); + assert_eq!( + describe_bindings(&bindings), + vec![("ctrl-k a".to_string(), "test_only::ActionBeta")] + ); + } + + #[test] + fn test_possible_next_bindings_apply_disabling_by_context() { + let keymap = Keymap::new(vec![ + KeyBinding::new("ctrl-k a", ActionAlpha {}, Some("Workspace")), + KeyBinding::new("ctrl-k a", ActionBeta {}, Some("Editor")), + KeyBinding::new("ctrl-k b", ActionGamma {}, Some("Editor")), + // Only removes the editor binding, so the workspace binding still dispatches. + KeyBinding::new( + "ctrl-k a", + Unbind("test_only::ActionBeta".into()), + Some("Editor"), + ), + // Doesn't apply because `Terminal` isn't in the context stack. + KeyBinding::new("ctrl-k b", NoAction {}, Some("Terminal")), + ]); + + let bindings = keymap.possible_next_bindings_for_input( + &[Keystroke::parse("ctrl-k").unwrap()], + &[ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("Editor").unwrap(), + ], + ); + assert_eq!( + describe_bindings(&bindings), + vec![ + ("ctrl-k b".to_string(), "test_only::ActionGamma"), + ("ctrl-k a".to_string(), "test_only::ActionAlpha"), + ] + ); + } + + #[test] + fn test_possible_next_bindings_exclude_longer_chord_disabled_in_deeper_context() { + let keymap = Keymap::new(vec![ + KeyBinding::new("space w w", ActionAlpha {}, Some("Workspace")), + KeyBinding::new("space w x", ActionBeta {}, Some("Workspace")), + KeyBinding::new("space w w", NoAction {}, Some("AgentPanel")), + ]); + let context_stack = [ + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("AgentPanel").unwrap(), + ]; + + for input in ["space", "space w"] { + let input = input + .split(' ') + .map(|keystroke| Keystroke::parse(keystroke).unwrap()) + .collect::>(); + let bindings = keymap.possible_next_bindings_for_input(&input, &context_stack); + assert_eq!( + describe_bindings(&bindings), + vec![("space w x".to_string(), "test_only::ActionBeta")] + ); + } + } + + #[test] + fn test_possible_next_bindings_exclude_disabled_bindings_with_typed_input() { + // Option-S reports both its physical key and the character it produced, so typed input + // matches bindings written with either. + let typed_input = [Keystroke::parse("alt-s->ß").unwrap()]; + let keymap = Keymap::new(vec![ + KeyBinding::new("ß a", ActionAlpha {}, None), + KeyBinding::new("alt-s a", NoAction {}, None), + ]); + assert!( + keymap + .possible_next_bindings_for_input(&typed_input, &[]) + .is_empty() + ); + + // Cross-check against dispatch of the same typed input. + let typed_then_a = [ + Keystroke::parse("alt-s->ß").unwrap(), + Keystroke::parse("a").unwrap(), + ]; + let (dispatched, _) = keymap.bindings_for_input(&typed_then_a, &[]); + assert!(dispatched.is_empty()); + } + + fn describe_bindings(bindings: &[KeyBinding]) -> Vec<(String, &'static str)> { + bindings + .iter() + .map(|binding| { + ( + binding + .keystrokes() + .iter() + .map(|keystroke| keystroke.inner().unparse()) + .collect::>() + .join(" "), + binding.action().name(), + ) + }) + .collect() + } +} diff --git a/vendor/gpui-pre/src/keymap/binding.rs b/vendor/gpui-pre/src/keymap/binding.rs new file mode 100644 index 00000000..fc4b3294 --- /dev/null +++ b/vendor/gpui-pre/src/keymap/binding.rs @@ -0,0 +1,143 @@ +use std::rc::Rc; + +use crate::{ + Action, AsKeystroke, DummyKeyboardMapper, InvalidKeystrokeError, KeyBindingContextPredicate, + KeybindingKeystroke, Keystroke, PlatformKeyboardMapper, SharedString, +}; +use smallvec::SmallVec; + +/// A keybinding and its associated metadata, from the keymap. +pub struct KeyBinding { + pub(crate) action: Box, + pub(crate) keystrokes: SmallVec<[KeybindingKeystroke; 2]>, + pub(crate) context_predicate: Option>, + pub(crate) meta: Option, + /// The json input string used when building the keybinding, if any + pub(crate) action_input: Option, +} + +impl Clone for KeyBinding { + fn clone(&self) -> Self { + KeyBinding { + action: self.action.boxed_clone(), + keystrokes: self.keystrokes.clone(), + context_predicate: self.context_predicate.clone(), + meta: self.meta, + action_input: self.action_input.clone(), + } + } +} + +impl KeyBinding { + /// Construct a new keybinding from the given data. Panics on parse error. + pub fn new(keystrokes: &str, action: A, context: Option<&str>) -> Self { + let context_predicate = + context.map(|context| KeyBindingContextPredicate::parse(context).unwrap().into()); + Self::load( + keystrokes, + Box::new(action), + context_predicate, + false, + None, + &DummyKeyboardMapper, + ) + .unwrap() + } + + /// Load a keybinding from the given raw data. + pub fn load( + keystrokes: &str, + action: Box, + context_predicate: Option>, + use_key_equivalents: bool, + action_input: Option, + keyboard_mapper: &dyn PlatformKeyboardMapper, + ) -> std::result::Result { + let keystrokes: SmallVec<[KeybindingKeystroke; 2]> = keystrokes + .split_whitespace() + .map(|source| { + let keystroke = Keystroke::parse(source)?; + Ok(KeybindingKeystroke::new_with_mapper( + keystroke, + use_key_equivalents, + keyboard_mapper, + )) + }) + .collect::>()?; + + Ok(Self { + keystrokes, + action, + context_predicate, + meta: None, + action_input, + }) + } + + /// Set the metadata for this binding. + pub fn with_meta(mut self, meta: KeyBindingMetaIndex) -> Self { + self.meta = Some(meta); + self + } + + /// Set the metadata for this binding. + pub fn set_meta(&mut self, meta: KeyBindingMetaIndex) { + self.meta = Some(meta); + } + + /// Check if the given keystrokes match this binding. + pub fn match_keystrokes(&self, typed: &[impl AsKeystroke]) -> Option { + if self.keystrokes.len() < typed.len() { + return None; + } + + for (target, typed) in self.keystrokes.iter().zip(typed.iter()) { + if !typed.as_keystroke().should_match(target) { + return None; + } + } + + Some(self.keystrokes.len() > typed.len()) + } + + /// Get the keystrokes associated with this binding + pub fn keystrokes(&self) -> &[KeybindingKeystroke] { + self.keystrokes.as_slice() + } + + /// Get the action associated with this binding + pub fn action(&self) -> &dyn Action { + self.action.as_ref() + } + + /// Get the predicate used to match this binding + pub fn predicate(&self) -> Option> { + self.context_predicate.as_ref().map(|rc| rc.clone()) + } + + /// Get the metadata for this binding + pub fn meta(&self) -> Option { + self.meta + } + + /// Get the action input associated with the action for this binding + pub fn action_input(&self) -> Option { + self.action_input.clone() + } +} + +impl std::fmt::Debug for KeyBinding { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("KeyBinding") + .field("keystrokes", &self.keystrokes) + .field("context_predicate", &self.context_predicate) + .field("action", &self.action.name()) + .finish() + } +} + +/// A unique identifier for retrieval of metadata associated with a key binding. +/// Intended to be used as an index or key into a user-defined store of metadata +/// associated with the binding, such as the source of the binding. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct KeyBindingMetaIndex(pub u32); diff --git a/vendor/gpui-pre/src/keymap/context.rs b/vendor/gpui-pre/src/keymap/context.rs new file mode 100644 index 00000000..27f361bb --- /dev/null +++ b/vendor/gpui-pre/src/keymap/context.rs @@ -0,0 +1,891 @@ +use crate::SharedString; +use anyhow::{Context as _, Result}; +use std::fmt; + +/// A datastructure for resolving whether an action should be dispatched +/// at this point in the element tree. Contains a set of identifiers +/// and/or key value pairs representing the current context for the +/// keymap. +#[derive(Clone, Default, Eq, PartialEq, Hash)] +pub struct KeyContext(Vec); + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +/// An entry in a KeyContext +pub struct ContextEntry { + /// The key (or name if no value) + pub key: SharedString, + /// The value + pub value: Option, +} + +impl<'a> TryFrom<&'a str> for KeyContext { + type Error = anyhow::Error; + + fn try_from(value: &'a str) -> Result { + Self::parse(value) + } +} + +impl KeyContext { + /// Initialize a new [`KeyContext`] that contains an `os` key set to either `macos`, `linux`, `windows` or `unknown`. + pub fn new_with_defaults() -> Self { + let mut context = Self::default(); + #[cfg(target_os = "macos")] + context.set("os", "macos"); + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + context.set("os", "linux"); + #[cfg(target_os = "windows")] + context.set("os", "windows"); + #[cfg(not(any( + target_os = "macos", + target_os = "linux", + target_os = "freebsd", + target_os = "windows" + )))] + context.set("os", "unknown"); + context + } + + /// Returns the primary context entry (usually the name of the component) + pub fn primary(&self) -> Option<&ContextEntry> { + self.0.iter().find(|p| p.value.is_none()) + } + + /// Returns everything except the primary context entry. + pub fn secondary(&self) -> impl Iterator { + let primary = self.primary(); + self.0.iter().filter(move |&p| Some(p) != primary) + } + + /// Parse a key context from a string. + /// The key context format is very simple: + /// - either a single identifier, such as `StatusBar` + /// - or a key value pair, such as `mode = visible` + /// - separated by whitespace, such as `StatusBar mode = visible` + pub fn parse(source: &str) -> Result { + let mut context = Self::default(); + let source = skip_whitespace(source); + Self::parse_expr(source, &mut context)?; + Ok(context) + } + + fn parse_expr(mut source: &str, context: &mut Self) -> Result<()> { + if source.is_empty() { + return Ok(()); + } + + let key = source + .chars() + .take_while(|c| is_identifier_char(*c)) + .collect::(); + source = skip_whitespace(&source[key.len()..]); + if let Some(suffix) = source.strip_prefix('=') { + source = skip_whitespace(suffix); + let value = source + .chars() + .take_while(|c| is_identifier_char(*c)) + .collect::(); + source = skip_whitespace(&source[value.len()..]); + context.set(key, value); + } else { + context.add(key); + } + + Self::parse_expr(source, context) + } + + /// Check if this context is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Clear this context. + pub fn clear(&mut self) { + self.0.clear(); + } + + /// Extend this context with another context. + pub fn extend(&mut self, other: &Self) { + for entry in &other.0 { + if !self.contains(&entry.key) { + self.0.push(entry.clone()); + } + } + } + + /// Add an identifier to this context, if it's not already in this context. + pub fn add>(&mut self, identifier: I) { + let key = identifier.into(); + + if !self.contains(&key) { + self.0.push(ContextEntry { key, value: None }) + } + } + + /// Set a key value pair in this context, if it's not already set. + pub fn set, S2: Into>(&mut self, key: S1, value: S2) { + let key = key.into(); + if !self.contains(&key) { + self.0.push(ContextEntry { + key, + value: Some(value.into()), + }) + } + } + + /// Check if this context contains a given identifier or key. + pub fn contains(&self, key: &str) -> bool { + self.0.iter().any(|entry| entry.key.as_ref() == key) + } + + /// Get the associated value for a given identifier or key. + pub fn get(&self, key: &str) -> Option<&SharedString> { + self.0 + .iter() + .find(|entry| entry.key.as_ref() == key)? + .value + .as_ref() + } +} + +impl fmt::Debug for KeyContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut entries = self.0.iter().peekable(); + while let Some(entry) = entries.next() { + if let Some(ref value) = entry.value { + write!(f, "{}={}", entry.key, value)?; + } else { + write!(f, "{}", entry.key)?; + } + if entries.peek().is_some() { + write!(f, " ")?; + } + } + Ok(()) + } +} + +/// A datastructure for resolving whether an action should be dispatched +/// Representing a small language for describing which contexts correspond +/// to which actions. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum KeyBindingContextPredicate { + /// A predicate that will match a given identifier. + Identifier(SharedString), + /// A predicate that will match a given key-value pair. + Equal(SharedString, SharedString), + /// A predicate that will match a given key-value pair not being present. + NotEqual(SharedString, SharedString), + /// A predicate that will match a given predicate appearing below another predicate. + /// in the element tree + Descendant( + Box, + Box, + ), + /// Predicate that will invert another predicate. + Not(Box), + /// A predicate that will match if both of its children match. + And( + Box, + Box, + ), + /// A predicate that will match if either of its children match. + Or( + Box, + Box, + ), +} + +impl fmt::Display for KeyBindingContextPredicate { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Identifier(name) => write!(f, "{name}"), + Self::Equal(left, right) => write!(f, "{left} == {right}"), + Self::NotEqual(left, right) => write!(f, "{left} != {right}"), + Self::Descendant(parent, child) => write!(f, "{parent} > {child}"), + Self::Not(pred) => match pred.as_ref() { + Self::Identifier(name) => write!(f, "!{name}"), + _ => write!(f, "!({pred})"), + }, + Self::And(..) => self.fmt_joined(f, " && ", LogicalOperator::And, |node| { + matches!(node, Self::Or(..)) + }), + Self::Or(..) => self.fmt_joined(f, " || ", LogicalOperator::Or, |node| { + matches!(node, Self::And(..)) + }), + } + } +} + +impl KeyBindingContextPredicate { + /// Parse a string in the same format as the keymap's context field. + /// + /// A basic equivalence check against a set of identifiers can performed by + /// simply writing a string: + /// + /// `StatusBar` -> A predicate that will match a context with the identifier `StatusBar` + /// + /// You can also specify a key-value pair: + /// + /// `mode == visible` -> A predicate that will match a context with the key `mode` + /// with the value `visible` + /// + /// And a logical operations combining these two checks: + /// + /// `StatusBar && mode == visible` -> A predicate that will match a context with the + /// identifier `StatusBar` and the key `mode` + /// with the value `visible` + /// + /// + /// There is also a special child `>` operator that will match a predicate that is + /// below another predicate: + /// + /// `StatusBar > mode == visible` -> A predicate that will match a context identifier `StatusBar` + /// and a child context that has the key `mode` with the + /// value `visible` + /// + /// This syntax supports `!=`, `||` and `&&` as logical operators. + /// You can also preface an operation or check with a `!` to negate it. + pub fn parse(source: &str) -> Result { + let source = skip_whitespace(source); + let (predicate, rest) = Self::parse_expr(source, 0)?; + if let Some(next) = rest.chars().next() { + anyhow::bail!("unexpected character '{next:?}'"); + } else { + Ok(predicate) + } + } + + /// Find the deepest depth at which the predicate matches. + pub fn depth_of(&self, contexts: &[KeyContext]) -> Option { + for depth in (0..=contexts.len()).rev() { + let context_slice = &contexts[0..depth]; + if self.eval_inner(context_slice, contexts) { + return Some(depth); + } + } + None + } + + /// Eval a predicate against a set of contexts, arranged from lowest to highest. + #[allow(unused)] + pub fn eval(&self, contexts: &[KeyContext]) -> bool { + self.eval_inner(contexts, contexts) + } + + /// Eval a predicate against a set of contexts, arranged from lowest to highest. + pub fn eval_inner(&self, contexts: &[KeyContext], all_contexts: &[KeyContext]) -> bool { + let Some(context) = contexts.last() else { + return false; + }; + match self { + Self::Identifier(name) => context.contains(name), + Self::Equal(left, right) => context + .get(left) + .map(|value| value == right) + .unwrap_or(false), + Self::NotEqual(left, right) => context + .get(left) + .map(|value| value != right) + .unwrap_or(true), + Self::Not(pred) => { + for i in 0..all_contexts.len() { + if pred.eval_inner(&all_contexts[..=i], all_contexts) { + return false; + } + } + true + } + // Workspace > Pane > Editor + // + // Pane > (Pane > Editor) // should match? + // (Pane > Pane) > Editor // should not match? + // Pane > !Workspace <-- should match? + // !Workspace <-- shouldn't match? + Self::Descendant(parent, child) => { + for i in 0..contexts.len() - 1 { + // [Workspace > Pane], [Editor] + if parent.eval_inner(&contexts[..=i], all_contexts) { + if !child.eval_inner(&contexts[i + 1..], &contexts[i + 1..]) { + return false; + } + return true; + } + } + false + } + Self::And(left, right) => { + left.eval_inner(contexts, all_contexts) && right.eval_inner(contexts, all_contexts) + } + Self::Or(left, right) => { + left.eval_inner(contexts, all_contexts) || right.eval_inner(contexts, all_contexts) + } + } + } + + /// Returns whether or not this predicate matches all possible contexts matched by + /// the other predicate. + pub fn is_superset(&self, other: &Self) -> bool { + if self == other { + return true; + } + + if let KeyBindingContextPredicate::Or(left, right) = self { + return left.is_superset(other) || right.is_superset(other); + } + + match other { + KeyBindingContextPredicate::Descendant(_, child) => self.is_superset(child), + KeyBindingContextPredicate::And(left, right) => { + self.is_superset(left) || self.is_superset(right) + } + KeyBindingContextPredicate::Identifier(_) => false, + KeyBindingContextPredicate::Equal(_, _) => false, + KeyBindingContextPredicate::NotEqual(_, _) => false, + KeyBindingContextPredicate::Not(_) => false, + KeyBindingContextPredicate::Or(_, _) => false, + } + } + + fn parse_expr(mut source: &str, min_precedence: u32) -> anyhow::Result<(Self, &str)> { + type Op = fn( + KeyBindingContextPredicate, + KeyBindingContextPredicate, + ) -> Result; + + let (mut predicate, rest) = Self::parse_primary(source)?; + source = rest; + + 'parse: loop { + for (operator, precedence, constructor) in [ + (">", PRECEDENCE_CHILD, Self::new_child as Op), + ("&&", PRECEDENCE_AND, Self::new_and as Op), + ("||", PRECEDENCE_OR, Self::new_or as Op), + ("==", PRECEDENCE_EQ, Self::new_eq as Op), + ("!=", PRECEDENCE_EQ, Self::new_neq as Op), + ] { + if source.starts_with(operator) && precedence >= min_precedence { + source = skip_whitespace(&source[operator.len()..]); + let (right, rest) = Self::parse_expr(source, precedence + 1)?; + predicate = constructor(predicate, right)?; + source = rest; + continue 'parse; + } + } + break; + } + + Ok((predicate, source)) + } + + fn parse_primary(mut source: &str) -> anyhow::Result<(Self, &str)> { + let next = source.chars().next().context("unexpected end")?; + match next { + '(' => { + source = skip_whitespace(&source[1..]); + let (predicate, rest) = Self::parse_expr(source, 0)?; + let stripped = rest.strip_prefix(')').context("expected a ')'")?; + source = skip_whitespace(stripped); + Ok((predicate, source)) + } + '!' => { + let source = skip_whitespace(&source[1..]); + let (predicate, source) = Self::parse_expr(source, PRECEDENCE_NOT)?; + Ok((KeyBindingContextPredicate::Not(Box::new(predicate)), source)) + } + _ if is_identifier_char(next) => { + let len = source + .find(|c: char| !is_identifier_char(c) && !is_vim_operator_char(c)) + .unwrap_or(source.len()); + let (identifier, rest) = source.split_at(len); + source = skip_whitespace(rest); + Ok(( + KeyBindingContextPredicate::Identifier(identifier.to_string().into()), + source, + )) + } + _ if is_vim_operator_char(next) => { + let (operator, rest) = source.split_at(1); + source = skip_whitespace(rest); + Ok(( + KeyBindingContextPredicate::Identifier(operator.to_string().into()), + source, + )) + } + _ => anyhow::bail!("unexpected character '{next:?}'"), + } + } + + fn new_or(self, other: Self) -> Result { + Ok(Self::Or(Box::new(self), Box::new(other))) + } + + fn new_and(self, other: Self) -> Result { + Ok(Self::And(Box::new(self), Box::new(other))) + } + + fn new_child(self, other: Self) -> Result { + Ok(Self::Descendant(Box::new(self), Box::new(other))) + } + + fn new_eq(self, other: Self) -> Result { + if let (Self::Identifier(left), Self::Identifier(right)) = (self, other) { + Ok(Self::Equal(left, right)) + } else { + anyhow::bail!("operands of == must be identifiers"); + } + } + + fn new_neq(self, other: Self) -> Result { + if let (Self::Identifier(left), Self::Identifier(right)) = (self, other) { + Ok(Self::NotEqual(left, right)) + } else { + anyhow::bail!("operands of != must be identifiers"); + } + } + + fn fmt_joined( + &self, + f: &mut fmt::Formatter<'_>, + separator: &str, + operator: LogicalOperator, + needs_parens: impl Fn(&Self) -> bool + Copy, + ) -> fmt::Result { + let mut first = true; + self.fmt_joined_inner(f, separator, operator, needs_parens, &mut first) + } + + fn fmt_joined_inner( + &self, + f: &mut fmt::Formatter<'_>, + separator: &str, + operator: LogicalOperator, + needs_parens: impl Fn(&Self) -> bool + Copy, + first: &mut bool, + ) -> fmt::Result { + match (operator, self) { + (LogicalOperator::And, Self::And(left, right)) + | (LogicalOperator::Or, Self::Or(left, right)) => { + left.fmt_joined_inner(f, separator, operator, needs_parens, first)?; + right.fmt_joined_inner(f, separator, operator, needs_parens, first) + } + (_, node) => { + if !*first { + f.write_str(separator)?; + } + *first = false; + + if needs_parens(node) { + write!(f, "({node})") + } else { + write!(f, "{node}") + } + } + } + } +} + +#[derive(Clone, Copy)] +enum LogicalOperator { + And, + Or, +} + +const PRECEDENCE_CHILD: u32 = 1; +const PRECEDENCE_OR: u32 = 2; +const PRECEDENCE_AND: u32 = 3; +const PRECEDENCE_EQ: u32 = 4; +const PRECEDENCE_NOT: u32 = 5; + +fn is_identifier_char(c: char) -> bool { + c.is_alphanumeric() || c == '_' || c == '-' +} + +fn is_vim_operator_char(c: char) -> bool { + c == '>' || c == '<' || c == '~' || c == '"' || c == '?' +} + +fn skip_whitespace(source: &str) -> &str { + let len = source + .find(|c: char| !c.is_whitespace()) + .unwrap_or(source.len()); + &source[len..] +} + +#[cfg(test)] +mod tests { + use core::slice; + + use super::*; + use crate as gpui; + use KeyBindingContextPredicate::*; + + #[test] + fn test_actions_definition() { + { + actions!(test_only, [A, B, C, D, E, F, G]); + } + + { + actions!( + test_only, + [ + H, I, J, K, L, M, N, // Don't wrap, test the trailing comma + ] + ); + } + } + + #[test] + fn test_parse_context() { + let mut expected = KeyContext::default(); + expected.add("baz"); + expected.set("foo", "bar"); + assert_eq!(KeyContext::parse("baz foo=bar").unwrap(), expected); + assert_eq!(KeyContext::parse("baz foo = bar").unwrap(), expected); + assert_eq!( + KeyContext::parse(" baz foo = bar baz").unwrap(), + expected + ); + assert_eq!(KeyContext::parse(" baz foo = bar").unwrap(), expected); + } + + #[test] + fn test_parse_identifiers() { + // Identifiers + assert_eq!( + KeyBindingContextPredicate::parse("abc12").unwrap(), + Identifier("abc12".into()) + ); + assert_eq!( + KeyBindingContextPredicate::parse("_1a").unwrap(), + Identifier("_1a".into()) + ); + } + + #[test] + fn test_parse_negations() { + assert_eq!( + KeyBindingContextPredicate::parse("!abc").unwrap(), + Not(Box::new(Identifier("abc".into()))) + ); + assert_eq!( + KeyBindingContextPredicate::parse(" ! ! abc").unwrap(), + Not(Box::new(Not(Box::new(Identifier("abc".into()))))) + ); + } + + #[test] + fn test_parse_equality_operators() { + assert_eq!( + KeyBindingContextPredicate::parse("a == b").unwrap(), + Equal("a".into(), "b".into()) + ); + assert_eq!( + KeyBindingContextPredicate::parse("c!=d").unwrap(), + NotEqual("c".into(), "d".into()) + ); + assert_eq!( + KeyBindingContextPredicate::parse("c == !d") + .unwrap_err() + .to_string(), + "operands of == must be identifiers" + ); + } + + #[test] + fn test_parse_boolean_operators() { + assert_eq!( + KeyBindingContextPredicate::parse("a || b").unwrap(), + Or( + Box::new(Identifier("a".into())), + Box::new(Identifier("b".into())) + ) + ); + assert_eq!( + KeyBindingContextPredicate::parse("a || !b && c").unwrap(), + Or( + Box::new(Identifier("a".into())), + Box::new(And( + Box::new(Not(Box::new(Identifier("b".into())))), + Box::new(Identifier("c".into())) + )) + ) + ); + assert_eq!( + KeyBindingContextPredicate::parse("a && b || c&&d").unwrap(), + Or( + Box::new(And( + Box::new(Identifier("a".into())), + Box::new(Identifier("b".into())) + )), + Box::new(And( + Box::new(Identifier("c".into())), + Box::new(Identifier("d".into())) + )) + ) + ); + assert_eq!( + KeyBindingContextPredicate::parse("a == b && c || d == e && f").unwrap(), + Or( + Box::new(And( + Box::new(Equal("a".into(), "b".into())), + Box::new(Identifier("c".into())) + )), + Box::new(And( + Box::new(Equal("d".into(), "e".into())), + Box::new(Identifier("f".into())) + )) + ) + ); + assert_eq!( + KeyBindingContextPredicate::parse("a && b && c && d").unwrap(), + And( + Box::new(And( + Box::new(And( + Box::new(Identifier("a".into())), + Box::new(Identifier("b".into())) + )), + Box::new(Identifier("c".into())), + )), + Box::new(Identifier("d".into())) + ), + ); + } + + #[test] + fn test_parse_parenthesized_expressions() { + assert_eq!( + KeyBindingContextPredicate::parse("a && (b == c || d != e)").unwrap(), + And( + Box::new(Identifier("a".into())), + Box::new(Or( + Box::new(Equal("b".into(), "c".into())), + Box::new(NotEqual("d".into(), "e".into())), + )), + ), + ); + assert_eq!( + KeyBindingContextPredicate::parse(" ( a || b ) ").unwrap(), + Or( + Box::new(Identifier("a".into())), + Box::new(Identifier("b".into())), + ) + ); + } + + #[test] + fn test_is_superset() { + assert_is_superset("editor", "editor", true); + assert_is_superset("editor", "workspace", false); + + assert_is_superset("editor", "editor && vim_mode", true); + assert_is_superset("editor", "mode == full && editor", true); + assert_is_superset("editor && mode == full", "editor", false); + + assert_is_superset("editor", "something > editor", true); + assert_is_superset("editor", "editor > menu", false); + + assert_is_superset("foo || bar || baz", "bar", true); + assert_is_superset("foo || bar || baz", "quux", false); + + #[track_caller] + fn assert_is_superset(a: &str, b: &str, result: bool) { + let a = KeyBindingContextPredicate::parse(a).unwrap(); + let b = KeyBindingContextPredicate::parse(b).unwrap(); + assert_eq!(a.is_superset(&b), result, "({a:?}).is_superset({b:?})"); + } + } + + #[test] + fn test_child_operator() { + let predicate = KeyBindingContextPredicate::parse("parent > child").unwrap(); + + let parent_context = KeyContext::try_from("parent").unwrap(); + let child_context = KeyContext::try_from("child").unwrap(); + + let contexts = vec![parent_context.clone(), child_context.clone()]; + assert!(predicate.eval(&contexts)); + + let grandparent_context = KeyContext::try_from("grandparent").unwrap(); + + let contexts = vec![ + grandparent_context, + parent_context.clone(), + child_context.clone(), + ]; + assert!(predicate.eval(&contexts)); + + let other_context = KeyContext::try_from("other").unwrap(); + + let contexts = vec![other_context.clone(), child_context.clone()]; + assert!(!predicate.eval(&contexts)); + + let contexts = vec![parent_context.clone(), other_context, child_context.clone()]; + assert!(predicate.eval(&contexts)); + + assert!(!predicate.eval(&[])); + assert!(!predicate.eval(slice::from_ref(&child_context))); + assert!(!predicate.eval(&[parent_context])); + + let zany_predicate = KeyBindingContextPredicate::parse("child > child").unwrap(); + assert!(!zany_predicate.eval(slice::from_ref(&child_context))); + assert!(zany_predicate.eval(&[child_context.clone(), child_context])); + } + + #[test] + fn test_not_operator() { + let not_predicate = KeyBindingContextPredicate::parse("!editor").unwrap(); + let editor_context = KeyContext::try_from("editor").unwrap(); + let workspace_context = KeyContext::try_from("workspace").unwrap(); + let parent_context = KeyContext::try_from("parent").unwrap(); + let child_context = KeyContext::try_from("child").unwrap(); + + assert!(not_predicate.eval(slice::from_ref(&workspace_context))); + assert!(!not_predicate.eval(slice::from_ref(&editor_context))); + assert!(!not_predicate.eval(&[editor_context.clone(), workspace_context.clone()])); + assert!(!not_predicate.eval(&[workspace_context.clone(), editor_context.clone()])); + + let complex_not = KeyBindingContextPredicate::parse("!editor && workspace").unwrap(); + assert!(complex_not.eval(slice::from_ref(&workspace_context))); + assert!(!complex_not.eval(&[editor_context.clone(), workspace_context.clone()])); + + let not_mode_predicate = KeyBindingContextPredicate::parse("!(mode == full)").unwrap(); + let mut mode_context = KeyContext::default(); + mode_context.set("mode", "full"); + assert!(!not_mode_predicate.eval(&[mode_context.clone()])); + + let mut other_mode_context = KeyContext::default(); + other_mode_context.set("mode", "partial"); + assert!(not_mode_predicate.eval(&[other_mode_context])); + + let not_descendant = KeyBindingContextPredicate::parse("!(parent > child)").unwrap(); + assert!(not_descendant.eval(slice::from_ref(&parent_context))); + assert!(not_descendant.eval(slice::from_ref(&child_context))); + assert!(!not_descendant.eval(&[parent_context.clone(), child_context.clone()])); + + let not_descendant = KeyBindingContextPredicate::parse("parent > !child").unwrap(); + assert!(!not_descendant.eval(slice::from_ref(&parent_context))); + assert!(!not_descendant.eval(slice::from_ref(&child_context))); + assert!(!not_descendant.eval(&[parent_context, child_context])); + + let double_not = KeyBindingContextPredicate::parse("!!editor").unwrap(); + assert!(double_not.eval(slice::from_ref(&editor_context))); + assert!(!double_not.eval(slice::from_ref(&workspace_context))); + + // Test complex descendant cases + let workspace_context = KeyContext::try_from("Workspace").unwrap(); + let pane_context = KeyContext::try_from("Pane").unwrap(); + let editor_context = KeyContext::try_from("Editor").unwrap(); + + // Workspace > Pane > Editor + let workspace_pane_editor = vec![ + workspace_context.clone(), + pane_context.clone(), + editor_context.clone(), + ]; + + // Pane > (Pane > Editor) - should not match + let pane_pane_editor = KeyBindingContextPredicate::parse("Pane > (Pane > Editor)").unwrap(); + assert!(!pane_pane_editor.eval(&workspace_pane_editor)); + + let workspace_pane_editor_predicate = + KeyBindingContextPredicate::parse("Workspace > Pane > Editor").unwrap(); + assert!(workspace_pane_editor_predicate.eval(&workspace_pane_editor)); + + // (Pane > Pane) > Editor - should not match + let pane_pane_then_editor = + KeyBindingContextPredicate::parse("(Pane > Pane) > Editor").unwrap(); + assert!(!pane_pane_then_editor.eval(&workspace_pane_editor)); + + // Pane > !Workspace - should match + let pane_not_workspace = KeyBindingContextPredicate::parse("Pane > !Workspace").unwrap(); + assert!(pane_not_workspace.eval(&[pane_context.clone(), editor_context.clone()])); + assert!(!pane_not_workspace.eval(&[pane_context.clone(), workspace_context.clone()])); + + // !Workspace - shouldn't match when Workspace is in the context + let not_workspace = KeyBindingContextPredicate::parse("!Workspace").unwrap(); + assert!(!not_workspace.eval(slice::from_ref(&workspace_context))); + assert!(not_workspace.eval(slice::from_ref(&pane_context))); + assert!(not_workspace.eval(slice::from_ref(&editor_context))); + assert!(!not_workspace.eval(&workspace_pane_editor)); + } + + // MARK: - Display + + #[test] + fn test_context_display() { + fn ident(s: &str) -> Box { + Box::new(Identifier(SharedString::new(s))) + } + fn eq(a: &str, b: &str) -> Box { + Box::new(Equal(SharedString::new(a), SharedString::new(b))) + } + fn not_eq(a: &str, b: &str) -> Box { + Box::new(NotEqual(SharedString::new(a), SharedString::new(b))) + } + fn and( + a: Box, + b: Box, + ) -> Box { + Box::new(And(a, b)) + } + fn or( + a: Box, + b: Box, + ) -> Box { + Box::new(Or(a, b)) + } + fn descendant( + a: Box, + b: Box, + ) -> Box { + Box::new(Descendant(a, b)) + } + fn not(a: Box) -> Box { + Box::new(Not(a)) + } + + let test_cases = [ + (ident("a"), "a"), + (eq("a", "b"), "a == b"), + (not_eq("a", "b"), "a != b"), + (descendant(ident("a"), ident("b")), "a > b"), + (not(ident("a")), "!a"), + (not_eq("a", "b"), "a != b"), + (descendant(ident("a"), ident("b")), "a > b"), + (not(and(ident("a"), ident("b"))), "!(a && b)"), + (not(or(ident("a"), ident("b"))), "!(a || b)"), + (and(ident("a"), ident("b")), "a && b"), + (and(and(ident("a"), ident("b")), ident("c")), "a && b && c"), + (or(ident("a"), ident("b")), "a || b"), + (or(or(ident("a"), ident("b")), ident("c")), "a || b || c"), + (or(ident("a"), and(ident("b"), ident("c"))), "a || (b && c)"), + ( + and( + and( + and(ident("a"), eq("b", "c")), + not(descendant(ident("d"), ident("e"))), + ), + eq("f", "g"), + ), + "a && b == c && !(d > e) && f == g", + ), + ( + and(and(ident("a"), or(ident("b"), ident("c"))), ident("d")), + "a && (b || c) && d", + ), + ( + or(or(ident("a"), and(ident("b"), ident("c"))), ident("d")), + "a || (b && c) || d", + ), + ]; + + for (predicate, expected) in test_cases { + let actual = predicate.to_string(); + assert_eq!(actual, expected); + let parsed = KeyBindingContextPredicate::parse(&actual).unwrap(); + assert_eq!(parsed, *predicate); + } + } +} diff --git a/vendor/gpui-pre/src/path_builder.rs b/vendor/gpui-pre/src/path_builder.rs new file mode 100644 index 00000000..40a6e71e --- /dev/null +++ b/vendor/gpui-pre/src/path_builder.rs @@ -0,0 +1,347 @@ +use anyhow::Error; +use etagere::euclid::{Point2D, Vector2D}; +use lyon::geom::Angle; +use lyon::math::{Vector, vector}; +use lyon::path::traits::SvgPathBuilder; +use lyon::path::{ArcFlags, Polygon}; +use lyon::tessellation::{ + BuffersBuilder, FillTessellator, FillVertex, StrokeTessellator, StrokeVertex, VertexBuffers, +}; + +pub use lyon::math::Transform; +pub use lyon::tessellation::{FillOptions, FillRule, StrokeOptions}; + +use crate::{Path, Pixels, Point, point, px}; + +/// Style of the PathBuilder +pub enum PathStyle { + /// Stroke style + Stroke(StrokeOptions), + /// Fill style + Fill(FillOptions), +} + +/// A [`Path`] builder. +pub struct PathBuilder { + raw: lyon::path::builder::WithSvg, + transform: Option, + /// PathStyle of the PathBuilder + pub style: PathStyle, + dash_array: Option>, +} + +impl From for PathBuilder { + fn from(builder: lyon::path::Builder) -> Self { + Self { + raw: builder.with_svg(), + ..Default::default() + } + } +} + +impl From> for PathBuilder { + fn from(raw: lyon::path::builder::WithSvg) -> Self { + Self { + raw, + ..Default::default() + } + } +} + +impl From for Point { + fn from(p: lyon::math::Point) -> Self { + point(px(p.x), px(p.y)) + } +} + +impl From> for lyon::math::Point { + fn from(p: Point) -> Self { + lyon::math::point(p.x.0, p.y.0) + } +} + +impl From> for Vector { + fn from(p: Point) -> Self { + vector(p.x.0, p.y.0) + } +} + +impl From> for Point2D { + fn from(p: Point) -> Self { + Point2D::new(p.x.0, p.y.0) + } +} + +impl Default for PathBuilder { + fn default() -> Self { + Self { + raw: lyon::path::Path::builder().with_svg(), + style: PathStyle::Fill(FillOptions::default()), + transform: None, + dash_array: None, + } + } +} + +impl PathBuilder { + /// Creates a new [`PathBuilder`] to build a Stroke path. + pub fn stroke(width: Pixels) -> Self { + Self { + style: PathStyle::Stroke(StrokeOptions::default().with_line_width(width.0)), + ..Self::default() + } + } + + /// Creates a new [`PathBuilder`] to build a Fill path. + pub fn fill() -> Self { + Self::default() + } + + /// Sets the style of the [`PathBuilder`]. + pub fn with_style(self, style: PathStyle) -> Self { + Self { style, ..self } + } + + /// Sets the dash array of the [`PathBuilder`]. + /// + /// [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/stroke-dasharray) + pub fn dash_array(mut self, dash_array: &[Pixels]) -> Self { + // If an odd number of values is provided, then the list of values is repeated to yield an even number of values. + // Thus, 5,3,2 is equivalent to 5,3,2,5,3,2. + let array = if dash_array.len() % 2 == 1 { + let mut new_dash_array = dash_array.to_vec(); + new_dash_array.extend_from_slice(dash_array); + new_dash_array + } else { + dash_array.to_vec() + }; + + self.dash_array = Some(array); + self + } + + /// Move the current point to the given point. + #[inline] + pub fn move_to(&mut self, to: Point) { + self.raw.move_to(to.into()); + } + + /// Draw a straight line from the current point to the given point. + #[inline] + pub fn line_to(&mut self, to: Point) { + self.raw.line_to(to.into()); + } + + /// Draw a curve from the current point to the given point, using the given control point. + #[inline] + pub fn curve_to(&mut self, to: Point, ctrl: Point) { + self.raw.quadratic_bezier_to(ctrl.into(), to.into()); + } + + /// Adds a cubic Bézier to the [`Path`] given its two control points + /// and its end point. + #[inline] + pub fn cubic_bezier_to( + &mut self, + to: Point, + control_a: Point, + control_b: Point, + ) { + self.raw + .cubic_bezier_to(control_a.into(), control_b.into(), to.into()); + } + + /// Adds an elliptical arc. + pub fn arc_to( + &mut self, + radii: Point, + x_rotation: Pixels, + large_arc: bool, + sweep: bool, + to: Point, + ) { + self.raw.arc_to( + radii.into(), + Angle::degrees(x_rotation.into()), + ArcFlags { large_arc, sweep }, + to.into(), + ); + } + + /// Equivalent to `arc_to` in relative coordinates. + pub fn relative_arc_to( + &mut self, + radii: Point, + x_rotation: Pixels, + large_arc: bool, + sweep: bool, + to: Point, + ) { + self.raw.relative_arc_to( + radii.into(), + Angle::degrees(x_rotation.into()), + ArcFlags { large_arc, sweep }, + to.into(), + ); + } + + /// Adds a polygon. + pub fn add_polygon(&mut self, points: &[Point], closed: bool) { + let points = points.iter().copied().map(|p| p.into()).collect::>(); + self.raw.add_polygon(Polygon { + points: points.as_ref(), + closed, + }); + } + + /// Close the current sub-path. + #[inline] + pub fn close(&mut self) { + self.raw.close(); + } + + /// Applies a transform to the path. + #[inline] + pub fn transform(&mut self, transform: Transform) { + self.transform = Some(transform); + } + + /// Applies a translation to the path. + #[inline] + pub fn translate(&mut self, to: Point) { + if let Some(transform) = self.transform { + self.transform = Some(transform.then_translate(Vector2D::new(to.x.0, to.y.0))); + } else { + self.transform = Some(Transform::translation(to.x.0, to.y.0)) + } + } + + /// Applies a scale to the path. + #[inline] + pub fn scale(&mut self, scale: f32) { + if let Some(transform) = self.transform { + self.transform = Some(transform.then_scale(scale, scale)); + } else { + self.transform = Some(Transform::scale(scale, scale)); + } + } + + /// Applies a rotation to the path. + /// + /// The `angle` is in degrees value in the range 0.0 to 360.0. + #[inline] + pub fn rotate(&mut self, angle: f32) { + let radians = angle.to_radians(); + if let Some(transform) = self.transform { + self.transform = Some(transform.then_rotate(Angle::radians(radians))); + } else { + self.transform = Some(Transform::rotation(Angle::radians(radians))); + } + } + + /// Builds into a [`Path`]. + #[inline] + pub fn build(self) -> Result, Error> { + let path = if let Some(transform) = self.transform { + self.raw.build().transformed(&transform) + } else { + self.raw.build() + }; + + match self.style { + PathStyle::Stroke(options) => Self::tessellate_stroke(self.dash_array, &path, &options), + PathStyle::Fill(options) => Self::tessellate_fill(&path, &options), + } + } + + fn tessellate_fill( + path: &lyon::path::Path, + options: &FillOptions, + ) -> Result, Error> { + // Will contain the result of the tessellation. + let mut buf: VertexBuffers = VertexBuffers::new(); + let mut tessellator = FillTessellator::new(); + + // Compute the tessellation. + tessellator.tessellate_path( + path, + options, + &mut BuffersBuilder::new(&mut buf, |vertex: FillVertex| vertex.position()), + )?; + + Ok(Self::build_path(buf)) + } + + fn tessellate_stroke( + dash_array: Option>, + path: &lyon::path::Path, + options: &StrokeOptions, + ) -> Result, Error> { + let path = if let Some(dash_array) = dash_array { + let measurements = lyon::algorithms::measure::PathMeasurements::from_path(path, 0.01); + let mut sampler = measurements + .create_sampler(path, lyon::algorithms::measure::SampleType::Normalized); + let mut builder = lyon::path::Path::builder(); + + let total_length = sampler.length(); + let dash_array_len = dash_array.len(); + let mut pos = 0.; + let mut dash_index = 0; + while pos < total_length { + let dash_length = dash_array[dash_index % dash_array_len].0; + let next_pos = (pos + dash_length).min(total_length); + if dash_index % 2 == 0 { + let start = pos / total_length; + let end = next_pos / total_length; + sampler.split_range(start..end, &mut builder); + } + pos = next_pos; + dash_index += 1; + } + + &builder.build() + } else { + path + }; + + // Will contain the result of the tessellation. + let mut buf: VertexBuffers = VertexBuffers::new(); + let mut tessellator = StrokeTessellator::new(); + + // Compute the tessellation. + tessellator.tessellate_path( + path, + options, + &mut BuffersBuilder::new(&mut buf, |vertex: StrokeVertex| vertex.position()), + )?; + + Ok(Self::build_path(buf)) + } + + /// Builds a [`Path`] from a [`lyon::tessellation::VertexBuffers`]. + pub fn build_path(buf: VertexBuffers) -> Path { + if buf.vertices.is_empty() { + return Path::new(Point::default()); + } + + let first_point = buf.vertices[0]; + + let mut path = Path::new(first_point.into()); + for i in 0..buf.indices.len() / 3 { + let i0 = buf.indices[i * 3] as usize; + let i1 = buf.indices[i * 3 + 1] as usize; + let i2 = buf.indices[i * 3 + 2] as usize; + + let v0 = buf.vertices[i0]; + let v1 = buf.vertices[i1]; + let v2 = buf.vertices[i2]; + + path.push_triangle( + (v0.into(), v1.into(), v2.into()), + (point(0., 1.), point(0., 1.), point(0., 1.)), + ); + } + + path + } +} diff --git a/vendor/gpui-pre/src/platform.rs b/vendor/gpui-pre/src/platform.rs new file mode 100644 index 00000000..36e79c63 --- /dev/null +++ b/vendor/gpui-pre/src/platform.rs @@ -0,0 +1,3786 @@ +mod app_menu; +mod keyboard; +mod keystroke; + +#[cfg(all(target_os = "linux", feature = "wayland"))] +#[expect(missing_docs)] +pub mod layer_shell; + +/// Types for configuring parent-anchored popup windows such as menus, dropdowns and tooltips. +pub mod popup; + +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +mod threaded_dispatcher; + +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +mod test; + +#[cfg(all(target_os = "macos", any(test, feature = "test-support")))] +mod visual_test; + +#[cfg(all( + feature = "screen-capture", + any(target_os = "windows", target_os = "linux", target_os = "freebsd",) +))] +pub mod scap_screen_capture; + +#[cfg(all( + any(target_os = "windows", target_os = "linux"), + feature = "screen-capture" +))] +pub(crate) type PlatformScreenCaptureFrame = scap::frame::Frame; +#[cfg(not(feature = "screen-capture"))] +pub(crate) type PlatformScreenCaptureFrame = (); +#[cfg(all(target_os = "macos", feature = "screen-capture"))] +pub(crate) type PlatformScreenCaptureFrame = + objc2_core_foundation::CFRetained; + +use crate::{ + Action, AnyWindowHandle, App, AsyncWindowContext, BackgroundExecutor, Bounds, + DEFAULT_WINDOW_SIZE, DevicePixels, DispatchEventResult, Edges, ExternalDragPayload, Font, + FontId, FontMetrics, FontRun, ForegroundExecutor, GlyphId, GpuSpecs, Hsla, ImageSource, Keymap, + LineLayout, MissingGlyphSink, Pixels, PlatformGestures, PlatformInput, Point, Priority, + RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Scene, ShapedGlyph, + ShapedRun, SharedString, Size, SvgRenderer, SystemWindowTab, Task, Window, WindowControlArea, + hash, point, px, size, +}; +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +use anyhow::bail; +use anyhow::{Context as _, Result}; +use async_task::Runnable; +use collections::FxHashMap; +use futures::channel::oneshot; +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +use image::RgbaImage; +use image::codecs::gif::GifDecoder; +use image::{AnimationDecoder as _, DynamicImage, Frame}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; +use scheduler::Instant; +pub use scheduler::RunnableMeta; +use schemars::JsonSchema; +use seahash::SeaHasher; +use serde::{Deserialize, Serialize}; +use smallvec::SmallVec; +use std::borrow::Cow; +use std::collections::hash_map::Entry; +use std::hash::{Hash, Hasher}; +use std::io::Cursor; +use std::ops; +use std::time::Duration; +use std::{ + ffi::OsString, + fmt::{self, Debug}, + ops::Range, + path::{Path, PathBuf}, + rc::Rc, + sync::Arc, +}; +use strum::EnumIter; +use uuid::Uuid; + +pub use app_menu::*; +pub use keyboard::*; +pub use keystroke::*; + +/// Whether the platform is presenting a window's frames. +/// +/// This is about presentation, not the window's shown/hidden state: a shown +/// window that is fully covered by other windows, minimized, on another +/// Space or virtual desktop, or on a display that is asleep is `Hidden`. A +/// window only partly covered by other windows is `Visible`. +/// +/// Each platform reports from a single source, and what that source can see +/// differs: +/// +/// * macOS: `NSWindow.occlusionState`. Covers all of the cases above. +/// * Windows: `WS_VISIBLE` and the minimized state. Windows keeps compositing +/// covered windows for thumbnails and Alt-Tab and offers no occlusion +/// notification, so a fully covered window stays `Visible`. Display sleep is +/// not reported either. +/// * Wayland: the `xdg_toplevel` `suspended` state (xdg-shell v6). Compositors +/// that don't support it never report `Hidden`. +/// * X11: mapped state plus `VisibilityNotify`. Compositing window managers +/// generally never report a window as fully obscured, so covering is only +/// detected without compositing. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WindowVisibility { + /// At least part of the window is being presented; frames drawn for it + /// will be shown. + Visible, + /// No part of the window is being presented. The platform will not + /// request frames for it until it becomes visible again. + Hidden, +} + +impl WindowVisibility { + /// Whether frames drawn for the window will be shown. + pub fn is_visible(self) -> bool { + self == Self::Visible + } +} + +/// Controls whether the application participates in the system's foreground UI. +/// +/// Only has an effect on macOS; other platforms ignore this setting. There, +/// [`App::request_windowing`] sets it: `Accessory` while headless and `Regular` while windowed. +/// Set it directly with [`App::set_activation_policy`] for the one case that doesn't cover: an +/// accessory app that shows windows, such as a menu bar utility. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum ActivationPolicy { + /// Participate in foreground application UI, such as the Dock and menu bar on macOS. + #[default] + Regular, + /// Run without foreground application UI while retaining the ability to open windows. + Accessory, +} + +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +pub(crate) use test::*; + +#[cfg(any(test, feature = "test-support"))] +pub use test::{TestDispatcher, TestScreenCaptureSource, TestScreenCaptureStream}; + +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +pub use threaded_dispatcher::ThreadedDispatcher; + +#[cfg(all(target_os = "macos", any(test, feature = "test-support")))] +pub use visual_test::VisualTestPlatform; + +/// Keeps an operating system activity, such as an idle sleep inhibitor, alive until dropped. +pub struct ActivityGuard { + _release: gpui_util::Deferred>, +} + +impl ActivityGuard { + /// Runs `release` when the guard is dropped. + pub fn new(release: impl FnOnce() + Send + 'static) -> Self { + Self { + _release: gpui_util::defer(Box::new(release)), + } + } + + /// A guard for platforms without a corresponding activity. + pub fn noop() -> Self { + Self::new(|| {}) + } +} + +// TODO(jk): return an enum instead of a string +/// Return which compositor we're guessing we'll use. +/// Does not attempt to connect to the given compositor. +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[inline] +pub fn guess_compositor() -> &'static str { + if std::env::var_os("ZED_HEADLESS").is_some() { + return "Headless"; + } + GraphicalEnvironment::detect().guess_compositor() +} + +/// The graphical session to connect to: the variables that locate its display server, as some +/// process sees them. +/// +/// A long-running process can outlive the graphical session it was started in, so a platform +/// that attaches to a display server later can be given a fresher environment than its own. +/// While connected, programs the platform launches (for example to open a URL) get these +/// variables instead of the ones this process started with. Apply +/// [`App::graphical_environment`] to the programs an app launches, for the same reason. +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[derive(Clone, Debug, Default)] +pub struct GraphicalEnvironment { + /// `WAYLAND_DISPLAY`: a socket name relative to `xdg_runtime_dir`, or an absolute path. + pub wayland_display: Option, + /// `DISPLAY`: the X11 display name. + pub x11_display: Option, + /// `XDG_RUNTIME_DIR`: the directory containing Wayland sockets. + pub xdg_runtime_dir: Option, + /// `XDG_ACTIVATION_TOKEN`: lets the first window take focus on Wayland. + /// + /// A platform takes this process's token from its environment when it's created, and uses + /// it if it starts windowed. Pass one here to switch to windowed mode later, for example + /// the token of the process that asked for a window. + pub activation_token: Option, +} + +/// The graphical session to connect to: the Windows session whose desktop windows appear on. +/// +/// A process can only show windows in its own session, so switching to windowed mode fails if +/// this names another one, for example when a process started over SSH is asked to show a +/// window on the desktop. +#[cfg(target_os = "windows")] +#[derive(Clone, Debug, Default)] +pub struct GraphicalEnvironment { + /// The session ID, as `ProcessIdToSessionId` reports it. `None` means this process's own + /// session. + pub session_id: Option, +} + +#[cfg(target_os = "windows")] +impl GraphicalEnvironment { + /// Returns the environment of this process's session. + pub fn detect() -> Self { + let mut session_id = 0; + // SAFETY: `session_id` is a valid pointer for the call's duration. + let result = unsafe { + windows::Win32::System::RemoteDesktop::ProcessIdToSessionId( + windows::Win32::System::Threading::GetCurrentProcessId(), + &mut session_id, + ) + }; + Self { + session_id: result.is_ok().then_some(session_id), + } + } + + /// Does nothing on this platform: programs inherit the session of the process that + /// starts them. + pub fn apply_to(&self, _command: &mut std::process::Command) {} +} + +/// The graphical session to connect to. Carries nothing yet on this platform. +#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "windows")))] +#[derive(Clone, Debug, Default)] +pub struct GraphicalEnvironment; + +#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "windows")))] +impl GraphicalEnvironment { + /// Returns the environment of this process's graphical session. + pub fn detect() -> Self { + Self + } + + /// Does nothing on this platform. + pub fn apply_to(&self, _command: &mut std::process::Command) {} +} + +/// A display mode for [`App::request_windowing`] to switch to. +#[derive(Clone, Debug)] +pub enum WindowingRequest { + /// No display server. Windows lay out and handle input but draw nothing. + Headless, + /// Connected to the display server that the environment names. + Windowed(GraphicalEnvironment), +} + +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +impl GraphicalEnvironment { + /// Reads the display variables from this process's environment. + /// + /// This only reads environment variables: whether they name a reachable display server is + /// checked when a platform connects. Leaves `activation_token` unset: see its documentation. + pub fn detect() -> Self { + Self { + wayland_display: std::env::var_os("WAYLAND_DISPLAY"), + x11_display: std::env::var_os("DISPLAY"), + xdg_runtime_dir: std::env::var_os("XDG_RUNTIME_DIR"), + activation_token: None, + } + } + + /// Sets this environment's display variables on `command`, and removes the ones it doesn't + /// set, so the program connects to this graphical session rather than the one this process + /// started in. Leaves `XDG_ACTIVATION_TOKEN` alone. + pub fn apply_to(&self, command: &mut std::process::Command) { + for (name, value) in [ + ("WAYLAND_DISPLAY", &self.wayland_display), + ("DISPLAY", &self.x11_display), + ("XDG_RUNTIME_DIR", &self.xdg_runtime_dir), + ] { + match value { + Some(value) => command.env(name, value), + None => command.env_remove(name), + }; + } + } + + /// Returns the compositor this environment selects: Wayland, then X11, then headless. + /// + /// Does not attempt to connect to the compositor. + pub fn guess_compositor(&self) -> &'static str { + let is_set = + |value: &Option| value.as_ref().is_some_and(|value| !value.is_empty()); + if cfg!(feature = "wayland") && is_set(&self.wayland_display) { + "Wayland" + } else if cfg!(feature = "x11") && is_set(&self.x11_display) { + "X11" + } else { + "Headless" + } + } +} + +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +bitflags::bitflags! { + /// The windowing modes a platform may start in or switch to. + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub struct WindowingModes: u8 { + /// Connected to a Wayland compositor. + const WAYLAND = 1 << 0; + /// Connected to an X server. + const X11 = 1 << 1; + /// No display server. Windows lay out and handle input but draw nothing. + const HEADLESS = 1 << 2; + } +} + +#[expect(missing_docs)] +pub trait Platform: 'static { + fn background_executor(&self) -> BackgroundExecutor; + fn foreground_executor(&self) -> ForegroundExecutor; + fn text_system(&self) -> Arc; + + fn run(&self, on_finish_launching: Box); + fn quit(&self); + /// Switches a capable platform between headless and windowed modes. See + /// [`App::request_windowing`]. + /// Sets the windowing mode the platform starts in. Called before `run`. See + /// [`Application::with_windowing`]. + fn set_initial_windowing(&self, _request: WindowingRequest) {} + fn request_windowing(&self, _request: WindowingRequest) -> Task> { + Task::ready(Err(anyhow::anyhow!( + "this platform cannot switch between headless and windowed modes" + ))) + } + fn restart(&self, binary_path: Option, arguments: Vec); + fn activate(&self, ignoring_other_apps: bool); + /// Sets the initial or current activation policy. Has no effect outside macOS. + fn set_activation_policy(&self, _policy: ActivationPolicy) {} + fn hide(&self); + fn hide_other_apps(&self); + fn unhide_other_apps(&self); + + fn displays(&self) -> Vec>; + fn primary_display(&self) -> Option>; + fn active_window(&self) -> Option; + fn window_stack(&self) -> Option> { + None + } + + fn is_screen_capture_supported(&self) -> bool { + false + } + + fn screen_capture_sources( + &self, + ) -> oneshot::Receiver>>> { + let (sources_tx, sources_rx) = oneshot::channel(); + sources_tx + .send(Err(anyhow::anyhow!( + "gpui was compiled without the screen-capture feature" + ))) + .ok(); + sources_rx + } + + fn open_window( + &self, + handle: AnyWindowHandle, + options: WindowParams, + ) -> anyhow::Result>; + + /// Returns the appearance of the application's windows. + fn window_appearance(&self) -> WindowAppearance; + + /// Overrides the appearance (light/dark) applied to the app's windows, independent + /// of the OS-wide setting. Pass `None` to clear the override and follow the system + /// again. The override is reflected by [`Platform::window_appearance`]. + /// + /// Currently only implemented on macOS, where it sets `NSApplication.appearance` so + /// the native window chrome (the window border and titlebar) of every window matches + /// a dark app theme even when the system is in light mode (or vice versa). A no-op on + /// other platforms. + fn set_window_appearance(&self, _appearance: Option) {} + + /// Returns the window button layout configuration when supported. + fn button_layout(&self) -> Option { + None + } + + fn open_url(&self, url: &str); + fn on_open_urls(&self, callback: Box)>); + fn register_url_scheme(&self, url: &str) -> Task>; + + fn prompt_for_paths( + &self, + options: PathPromptOptions, + ) -> oneshot::Receiver>>>; + fn prompt_for_new_path( + &self, + directory: &Path, + suggested_name: Option<&str>, + ) -> oneshot::Receiver>>; + fn can_select_mixed_files_and_dirs(&self) -> bool; + fn reveal_path(&self, path: &Path); + fn open_with_system(&self, path: &Path); + + fn on_quit(&self, callback: Box bool>); + fn on_reopen(&self, callback: Box); + /// Registers the callback invoked when the system is about to sleep. + fn on_system_sleep(&self, callback: Box); + /// Registers the callback invoked when the system resumes from sleep. + fn on_system_wake(&self, callback: Box); + + // Mobile platform methods. On mobile the OS owns the application + // lifecycle: apps are backgrounded, foregrounded, and killed at the + // system's discretion, and must react rather than decide. + + /// Registers a callback invoked whenever the application's lifecycle + /// phase changes. See [`AppLifecyclePhase`] for the phase vocabulary and + /// its mapping onto iOS and Android. + /// + /// Desktop platforms never invoke this. + fn on_app_lifecycle(&self, _callback: Box) {} + + /// Registers a callback invoked when the OS signals memory pressure + /// (iOS `didReceiveMemoryWarning`, Android `onTrimMemory`). + /// + /// Desktop platforms never invoke this. + fn on_memory_warning(&self, _callback: Box) {} + + /// The platform's gesture recognition services, if it provides any + /// beyond gpui's portable recognizers. See + /// [`PlatformGestures`](crate::PlatformGestures). + fn gestures(&self) -> Option> { + None + } + + fn set_menus(&self, menus: Vec, keymap: &Keymap); + fn get_menus(&self) -> Option> { + None + } + + fn set_dock_menu(&self, menu: Vec, keymap: &Keymap); + fn perform_dock_menu_action(&self, _action: usize) {} + fn add_recent_document(&self, _path: &Path) {} + fn update_jump_list( + &self, + _menus: Vec, + _entries: Vec>, + ) -> Task>> { + Task::ready(Vec::new()) + } + fn on_app_menu_action(&self, callback: Box); + fn on_will_open_app_menu(&self, callback: Box); + fn on_validate_app_menu_command(&self, callback: Box bool>); + + fn thermal_state(&self) -> ThermalState; + fn on_thermal_state_change(&self, callback: Box); + fn prevent_idle_sleep(&self, reason: &str) -> Task>; + + /// Sets the application's process-wide identity and user-visible name. + /// + /// The identifier is used for platform identity mechanisms such as the + /// Windows AppUserModelID. The name is used wherever the operating system + /// presents the application to the user. Call this once, early in startup, + /// before opening windows or posting notifications. + fn set_app_identity(&self, identifier: &str, name: &str) { + _ = (identifier, name); + } + + /// Posts a notification to the operating system's notification center. + /// + /// Posting a notification whose [`SystemNotification::tag`] matches an + /// earlier one replaces that notification where the platform supports it. + /// No-op on platforms without notification support, or when delivery is + /// unavailable (e.g. authorization was denied). + fn show_system_notification(&self, notification: SystemNotification) { + _ = notification; + } + + /// Removes the delivered or pending notification with this tag. + /// + /// Best-effort: some platforms cannot retract a notification once shown, + /// in which case it ages out of the notification center on its own. + fn dismiss_system_notification(&self, tag: &str) { + _ = tag; + } + + /// Registers the callback invoked when the user activates a system + /// notification, either by clicking its body or one of its action + /// buttons. + /// + /// Implementations must invoke the callback on the main thread. + fn on_system_notification_response( + &self, + callback: Box, + ) { + _ = callback; + } + + fn compositor_name(&self) -> &'static str { + "" + } + /// The environment of the display server a platform that can switch windowing modes is + /// connected to. See [`App::graphical_environment`]. + fn graphical_environment(&self) -> Option { + None + } + fn app_path(&self) -> Result; + fn path_for_auxiliary_executable(&self, name: &str) -> Result; + + fn set_cursor_style(&self, style: CursorStyle); + + /// Hides the mouse cursor until the user moves the mouse over one of + /// this application's windows. + fn hide_cursor_until_mouse_moves(&self); + + /// Returns whether the mouse cursor is currently visible. + fn is_cursor_visible(&self) -> bool; + + fn should_auto_hide_scrollbars(&self) -> bool; + + fn read_from_clipboard(&self) -> Option; + fn write_to_clipboard(&self, item: ClipboardItem); + + /// Reads the clipboard, resolving once its contents are available. + /// + /// Most platforms read synchronously and return a ready task. Platforms + /// whose clipboard access is inherently asynchronous and permission-gated + /// (e.g. the browser's async clipboard API) override this method; on those + /// platforms [`Platform::read_from_clipboard`] cannot return the clipboard + /// contents, so callers that can await should prefer this method. + fn read_from_clipboard_async(&self) -> Task, ClipboardReadError>> { + Task::ready(Ok(self.read_from_clipboard())) + } + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + fn read_from_primary(&self) -> Option; + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + fn write_to_primary(&self, item: ClipboardItem); + + #[cfg(target_os = "macos")] + fn read_from_find_pasteboard(&self) -> Option; + #[cfg(target_os = "macos")] + fn write_to_find_pasteboard(&self, item: ClipboardItem); + + fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task>; + fn read_credentials(&self, url: &str) -> Task)>>>; + fn delete_credentials(&self, url: &str) -> Task>; + + fn keyboard_layout(&self) -> Box; + fn keyboard_mapper(&self) -> Rc; + fn on_keyboard_layout_change(&self, callback: Box); +} + +/// A handle to a platform's display, e.g. a monitor or laptop screen. +pub trait PlatformDisplay: Debug { + /// Get the ID for this display + fn id(&self) -> DisplayId; + + /// Returns a stable identifier for this display that can be persisted and used + /// across system restarts. + fn uuid(&self) -> Result; + + /// Get the bounds for this display + fn bounds(&self) -> Bounds; + + /// Get the visible bounds for this display, excluding taskbar/dock areas. + /// This is the usable area where windows can be placed without being obscured. + /// Defaults to the full display bounds if not overridden. + fn visible_bounds(&self) -> Bounds { + self.bounds() + } + + /// Get the default bounds for this display to place a window + fn default_bounds(&self) -> Bounds { + let bounds = self.bounds(); + let center = bounds.center(); + let clipped_window_size = DEFAULT_WINDOW_SIZE.min(&bounds.size); + + let offset = clipped_window_size / 2.0; + let origin = point(center.x - offset.width, center.y - offset.height); + Bounds::new(origin, clipped_window_size) + } +} + +/// A notification posted to the operating system's notification center, +/// rather than rendered as in-app UI. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SystemNotification { + /// Stable identity for the notification. Posting a new notification with + /// the same tag replaces the previous one where the platform supports it, + /// and responses carry the tag back to the application. + pub tag: SharedString, + /// The notification's headline. + pub title: SharedString, + /// Additional text displayed below the title. + pub body: SharedString, + /// Buttons offered on the notification. Platforms that cannot display + /// action buttons show the notification without them. + pub actions: Vec, +} + +/// A button offered on a [`SystemNotification`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct SystemNotificationAction { + /// Identifies the action in [`SystemNotificationResponse::action_id`] + /// when the user presses this button. + pub id: SharedString, + /// The button's user-visible label. + pub label: SharedString, +} + +/// The user's activation of a [`SystemNotification`]. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SystemNotificationResponse { + /// The [`SystemNotification::tag`] of the activated notification. + pub tag: SharedString, + /// The pressed action button's [`SystemNotificationAction::id`], or + /// `None` when the user activated the notification body itself. + pub action_id: Option, +} + +/// Thermal state of the system +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ThermalState { + /// System has no thermal constraints + Nominal, + /// System is slightly constrained, reduce discretionary work + Fair, + /// System is moderately constrained, reduce CPU/GPU intensive work + Serious, + /// System is critically constrained, minimize all resource usage + Critical, +} + +/// Metadata for a given [ScreenCaptureSource] +#[derive(Clone)] +pub struct SourceMetadata { + /// Opaque identifier of this screen. + pub id: u64, + /// Human-readable label for this source. + pub label: Option, + /// Whether this source is the main display. + pub is_main: Option, + /// Video resolution of this source. + pub resolution: Size, +} + +/// A source of on-screen video content that can be captured. +pub trait ScreenCaptureSource { + /// Returns metadata for this source. + fn metadata(&self) -> Result; + + /// Start capture video from this source, invoking the given callback + /// with each frame. + fn stream( + &self, + foreground_executor: &ForegroundExecutor, + frame_callback: Box, + ) -> oneshot::Receiver>>; +} + +/// A video stream captured from a screen. +pub trait ScreenCaptureStream { + /// Returns metadata for this source. + fn metadata(&self) -> Result; +} + +/// A frame of video captured from a screen. +pub struct ScreenCaptureFrame(pub PlatformScreenCaptureFrame); + +/// An opaque identifier for a hardware display +#[derive(PartialEq, Eq, Hash, Copy, Clone)] +pub struct DisplayId(pub(crate) u64); + +impl DisplayId { + /// Create a new `DisplayId` from a raw platform display identifier. + pub fn new(id: u64) -> Self { + Self(id) + } +} + +impl From for DisplayId { + fn from(id: u64) -> Self { + Self(id) + } +} + +impl From for u64 { + fn from(id: DisplayId) -> Self { + id.0 + } +} + +impl Debug for DisplayId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "DisplayId({})", self.0) + } +} + +/// Which part of the window to resize +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ResizeEdge { + /// The top edge + Top, + /// The top right corner + TopRight, + /// The right edge + Right, + /// The bottom right corner + BottomRight, + /// The bottom edge + Bottom, + /// The bottom left corner + BottomLeft, + /// The left edge + Left, + /// The top left corner + TopLeft, +} + +/// A type to describe the appearance of a window +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] +pub enum WindowDecorations { + #[default] + /// Server side decorations + Server, + /// Client side decorations + Client, +} + +/// A type to describe how this window is currently configured +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] +pub enum Decorations { + /// The window is configured to use server side decorations + #[default] + Server, + /// The window is configured to use client side decorations + Client { + /// The edge tiling state + tiling: Tiling, + }, +} + +/// What window controls this platform supports +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct WindowControls { + /// Whether this platform supports fullscreen + pub fullscreen: bool, + /// Whether this platform supports maximize + pub maximize: bool, + /// Whether this platform supports minimize + pub minimize: bool, + /// Whether this platform supports a window menu + pub window_menu: bool, +} + +impl Default for WindowControls { + fn default() -> Self { + // Assume that we can do anything, unless told otherwise + Self { + fullscreen: true, + maximize: true, + minimize: true, + window_menu: true, + } + } +} + +/// A window control button type used in [`WindowButtonLayout`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum WindowButton { + /// The minimize button + Minimize, + /// The maximize button + Maximize, + /// The close button + Close, +} + +impl WindowButton { + /// Returns a stable element ID for rendering this button. + pub fn id(&self) -> &'static str { + match self { + WindowButton::Minimize => "minimize", + WindowButton::Maximize => "maximize", + WindowButton::Close => "close", + } + } + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + fn index(&self) -> usize { + match self { + WindowButton::Minimize => 0, + WindowButton::Maximize => 1, + WindowButton::Close => 2, + } + } +} + +/// Maximum number of [`WindowButton`]s per side in the titlebar. +pub const MAX_BUTTONS_PER_SIDE: usize = 3; + +/// Describes which [`WindowButton`]s appear on each side of the titlebar. +/// +/// On Linux, this is read from the desktop environment's configuration +/// (e.g. GNOME's `gtk-decoration-layout` gsetting) via [`WindowButtonLayout::parse`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct WindowButtonLayout { + /// Buttons on the left side of the titlebar. + pub left: [Option; MAX_BUTTONS_PER_SIDE], + /// Buttons on the right side of the titlebar. + pub right: [Option; MAX_BUTTONS_PER_SIDE], +} + +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +impl WindowButtonLayout { + /// Returns Zed's built-in fallback button layout for Linux titlebars. + pub fn linux_default() -> Self { + Self { + left: [None; MAX_BUTTONS_PER_SIDE], + right: [ + Some(WindowButton::Minimize), + Some(WindowButton::Maximize), + Some(WindowButton::Close), + ], + } + } + + /// Parses a GNOME-style `button-layout` string (e.g. `"close,minimize:maximize"`). + pub fn parse(layout_string: &str) -> Result { + fn parse_side( + s: &str, + seen_buttons: &mut [bool; MAX_BUTTONS_PER_SIDE], + unrecognized: &mut Vec, + ) -> [Option; MAX_BUTTONS_PER_SIDE] { + let mut result = [None; MAX_BUTTONS_PER_SIDE]; + let mut i = 0; + for name in s.split(',') { + let trimmed = name.trim(); + if trimmed.is_empty() { + continue; + } + let button = match trimmed { + "minimize" => Some(WindowButton::Minimize), + "maximize" => Some(WindowButton::Maximize), + "close" => Some(WindowButton::Close), + other => { + unrecognized.push(other.to_string()); + None + } + }; + if let Some(button) = button { + if seen_buttons[button.index()] { + continue; + } + if let Some(slot) = result.get_mut(i) { + *slot = Some(button); + seen_buttons[button.index()] = true; + i += 1; + } + } + } + result + } + + let (left_str, right_str) = layout_string.split_once(':').unwrap_or(("", layout_string)); + let mut unrecognized = Vec::new(); + let mut seen_buttons = [false; MAX_BUTTONS_PER_SIDE]; + let layout = Self { + left: parse_side(left_str, &mut seen_buttons, &mut unrecognized), + right: parse_side(right_str, &mut seen_buttons, &mut unrecognized), + }; + + if !unrecognized.is_empty() + && layout.left.iter().all(Option::is_none) + && layout.right.iter().all(Option::is_none) + { + bail!( + "button layout string {:?} contains no valid buttons (unrecognized: {})", + layout_string, + unrecognized.join(", ") + ); + } + + Ok(layout) + } + + /// Formats the layout back into a GNOME-style `button-layout` string. + #[cfg(test)] + pub fn format(&self) -> String { + fn format_side(buttons: &[Option; MAX_BUTTONS_PER_SIDE]) -> String { + buttons + .iter() + .flatten() + .map(|button| match button { + WindowButton::Minimize => "minimize", + WindowButton::Maximize => "maximize", + WindowButton::Close => "close", + }) + .collect::>() + .join(",") + } + + format!("{}:{}", format_side(&self.left), format_side(&self.right)) + } +} + +/// A type to describe which sides of the window are currently tiled in some way +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] +pub struct Tiling { + /// Whether the top edge is tiled + pub top: bool, + /// Whether the left edge is tiled + pub left: bool, + /// Whether the right edge is tiled + pub right: bool, + /// Whether the bottom edge is tiled + pub bottom: bool, +} + +impl Tiling { + /// Initializes a [`Tiling`] type with all sides tiled + pub fn tiled() -> Self { + Self { + top: true, + left: true, + right: true, + bottom: true, + } + } + + /// Whether any edge is tiled + pub fn is_tiled(&self) -> bool { + self.top || self.left || self.right || self.bottom + } +} + +/// Callbacks for the accessibility adapter. +pub struct A11yCallbacks { + /// Called when the adapter is activated (a screen reader connects). + pub activation: Box Option + Send + 'static>, + /// Called when an action is requested by the screen reader. + pub action: Box, + /// Called when the adapter is deactivated (screen reader disconnects). + pub deactivation: Box, +} + +/// The source of a platform frame request's timestamp. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] +pub enum FrameRequestSource { + /// An OS callback or compositor-paced frame request. + #[default] + NativeCallback, + /// A refresh timer, retry, queued wakeup, or fallback sleep paced by the app. + LocalSchedule, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] +#[expect(missing_docs)] +pub struct RequestFrameOptions { + /// Whether a presentation is required. + pub require_presentation: bool, + /// Force refresh of all rendering states when true. + pub force_render: bool, + /// When the platform first requested this frame, before main-thread dispatch. + /// + /// `None` means the captured request time is unavailable. + /// Coalesced requests carry their first request time, not their delivery time. + /// Built-in backends collect timestamps only with the `profiler` feature. + pub signal_at: Option, + /// Distinguishes native callbacks from local scheduling requests. + pub signal_source: FrameRequestSource, +} + +/// Preserves the first platform frame request time across coalesced notifications. +/// +/// Producers may record from a platform thread without waiting for the UI thread. +/// The consumer drains the timestamp before dispatching the request on the UI thread. +/// The timestamp offset and source share one atomic word so coalescing cannot +/// mix a request's time with another request's source. The low bit encodes the +/// source; the remaining bits encode nanoseconds from `origin`. `u64::MAX` is empty. +/// Without the `profiler` feature, this accumulator has no timestamp storage. +pub struct PlatformFrameSignal { + #[cfg(feature = "profiler")] + origin: Instant, + #[cfg(feature = "profiler")] + first_signal: std::sync::atomic::AtomicU64, +} + +impl Default for PlatformFrameSignal { + fn default() -> Self { + Self::new() + } +} + +impl PlatformFrameSignal { + /// Creates an empty signal accumulator. + pub fn new() -> Self { + Self { + #[cfg(feature = "profiler")] + origin: Instant::now(), + #[cfg(feature = "profiler")] + first_signal: std::sync::atomic::AtomicU64::new(u64::MAX), + } + } + + /// Captures a platform request timestamp only when profiling is enabled. + /// + /// The closure is not invoked in profiler-disabled builds. + #[inline] + pub fn capture(capture: impl FnOnce() -> Instant) -> Option { + if cfg!(feature = "profiler") { + Some(capture()) + } else { + None + } + } + + /// Records a platform frame request, retaining the first undrained timestamp. + #[inline] + #[cfg_attr(not(feature = "profiler"), expect(unused_variables))] + pub fn record(&self, at: Instant, source: FrameRequestSource) { + #[cfg(feature = "profiler")] + { + let nanoseconds = at + .saturating_duration_since(self.origin) + .as_nanos() + .min(u128::from((u64::MAX >> 1) - 1)) as u64; + let source_bit = match source { + FrameRequestSource::NativeCallback => 0, + FrameRequestSource::LocalSchedule => 1, + }; + self.first_signal.fetch_min( + (nanoseconds << 1) | source_bit, + std::sync::atomic::Ordering::Relaxed, + ); + } + } + + /// Drains the first platform frame request time and source, leaving the accumulator empty. + #[inline] + pub fn take(&self) -> Option<(Instant, FrameRequestSource)> { + #[cfg(feature = "profiler")] + { + let signal = self + .first_signal + .swap(u64::MAX, std::sync::atomic::Ordering::Relaxed); + (signal != u64::MAX).then(|| { + let source = match signal & 1 { + 0 => FrameRequestSource::NativeCallback, + _ => FrameRequestSource::LocalSchedule, + }; + (self.origin + Duration::from_nanos(signal >> 1), source) + }) + } + #[cfg(not(feature = "profiler"))] + { + None + } + } +} + +/// The application's lifecycle phase, as owned and reported by a mobile OS. +/// +/// `Inactive` means visible but not receiving input (a system dialog on +/// top), while `Background` means not visible at all, with process death +/// possible at any time thereafter. +/// +/// | Phase | iOS | Android | +/// |--------------|------------------------------|--------------| +/// | `Active` | `didBecomeActive` | `onResume` | +/// | `Inactive` | `willResignActive` | `onPause` | +/// | `Background` | `didEnterBackground` | `onStop` | +/// | `Foreground` | `willEnterForeground` | `onStart` | +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum AppLifecyclePhase { + /// Foreground and receiving input. + Active, + /// Foreground (visible) but not receiving input. + Inactive, + /// Not visible. The GPU surface may be destroyed while backgrounded and + /// the process may be killed without further notice. + Background, + /// Becoming visible again, before input is restored. + Foreground, +} + +/// Regions of a window that are obscured or reserved by the system. +/// +/// Mobile applications often share space in their window with system-specific +/// geometry, from keyboards to camera notches. In GPUI, all this is abstracted +/// into a single "inset" which should be overlaid on the window's bounds. +/// It is up to the application develop to determine how to handle these cases. +#[derive(Debug, Clone, Default, PartialEq)] +pub struct WindowInsets { + /// Regions covered by system UI or hardware: status bar, display + /// cutouts/notch, home indicator, navigation bars. + /// (iOS: `safeAreaInsets`. Android: `WindowInsets` of types + /// `systemBars() | displayCutout()`.) + pub safe_area: Edges, + /// The region covered by the keyboard, when present. + /// (iOS: derived from `keyboardWillShow`/frame-change notifications. + /// Android: `WindowInsets.Type.ime()`.) + pub ime: Edges, +} + +impl WindowInsets { + /// The combined inset content should avoid. + pub fn effective(&self) -> Edges { + Edges { + top: self.safe_area.top.max(self.ime.top), + right: self.safe_area.right.max(self.ime.right), + bottom: self.safe_area.bottom.max(self.ime.bottom), + left: self.safe_area.left.max(self.ime.left), + } + } +} + +/// A change in the state of the focused text input. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum TextInputStateChange { + /// The window changed from having no active text input to having one. + FocusGained, + /// The window no longer has an active text input. + FocusLost, + /// The selection or caret moved + SelectionChanged, + /// The document content changed outside of platform-initiated edits. + ContentChanged, +} + +#[expect(missing_docs)] +pub trait PlatformWindow: HasWindowHandle + HasDisplayHandle { + fn bounds(&self) -> Bounds; + fn is_maximized(&self) -> bool; + fn window_bounds(&self) -> WindowBounds; + fn content_size(&self) -> Size; + /// Returns the visible viewport in logical pixels relative to the content origin. + /// + /// This may be smaller or offset when a keyboard or zoom obscures content; + /// it must not change the full layout size returned by `content_size`. + /// Implementations should return a frame snapshot, not query platform layout here. + fn visual_viewport_bounds(&self) -> Bounds { + Bounds::new(Point::default(), self.content_size()) + } + /// Registers a callback when visible geometry may have changed. + /// + /// This requests a frame; backends can sample the new viewport and safe-area + /// geometry in `prepare_frame` rather than updating it inside the callback. + fn on_visual_viewport_changed(&self, _callback: Box) {} + /// Samples platform geometry before a draw, returning whether view caches must be invalidated. + /// + /// Geometry getters must remain consistent throughout the ensuing draw. + /// Do not invoke callbacks here: GPUI is already updating this window. + fn prepare_frame(&self) -> bool { + false + } + fn resize(&mut self, size: Size); + fn scale_factor(&self) -> f32; + fn appearance(&self) -> WindowAppearance; + fn display(&self) -> Option>; + fn mouse_position(&self) -> Point; + fn modifiers(&self) -> Modifiers; + fn capslock(&self) -> Capslock; + fn set_input_handler(&mut self, input_handler: PlatformInputHandler); + fn take_input_handler(&mut self) -> Option; + /// Apply the focused text region's [`TextInputConfiguration`] to the + /// platform's text input session (e.g. attributes of the hidden editable + /// element on web). Called only when the configuration changes, because + /// reconfiguring a live input session can restart the IME connection. + fn set_text_input_configuration(&mut self, _configuration: TextInputConfiguration) {} + fn prompt( + &self, + level: PromptLevel, + msg: &str, + detail: Option<&str>, + answers: &[PromptButton], + ) -> Option>; + fn activate(&self); + /// Requests that the operating system draw attention to this window. + fn request_attention(&self) {} + fn is_active(&self) -> bool; + /// The current [`WindowVisibility`]. Read once when the window is created; + /// afterwards changes arrive through [`Self::on_visibility_change`]. + fn visibility(&self) -> WindowVisibility; + fn is_hovered(&self) -> bool; + fn background_appearance(&self) -> WindowBackgroundAppearance; + fn set_title(&mut self, title: &str); + fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance); + fn minimize(&self); + fn zoom(&self); + fn toggle_fullscreen(&self); + fn is_fullscreen(&self) -> bool; + fn frame_waker(&self) -> Option> { + None + } + fn on_request_frame(&self, callback: Box); + fn on_input(&self, callback: Box DispatchEventResult>); + fn on_active_status_change(&self, callback: Box); + /// Registers the callback invoked when [`Self::visibility`] changes. Only + /// transitions are reported; the callback runs on the main thread outside + /// of any window update. + fn on_visibility_change(&self, callback: Box); + fn on_hover_status_change(&self, callback: Box); + fn on_resize(&self, callback: Box, f32)>); + fn on_moved(&self, callback: Box); + fn on_should_close(&self, callback: Box bool>); + fn on_hit_test_window_control(&self, callback: Box Option>); + fn on_close(&self, callback: Box); + fn on_appearance_changed(&self, callback: Box); + fn on_button_layout_changed(&self, _callback: Box) {} + fn draw(&self, scene: &Scene); + fn schedule_frame(&self) {} + fn sprite_atlas(&self) -> Arc; + fn is_subpixel_rendering_supported(&self) -> bool; + + // macOS specific methods + fn get_title(&self) -> String { + String::new() + } + fn tabbed_windows(&self) -> Option> { + None + } + fn tab_bar_visible(&self) -> bool { + false + } + fn set_edited(&mut self, _edited: bool) {} + fn set_document_path(&self, _path: Option<&std::path::Path>) {} + fn toggle_simple_fullscreen(&self) {} + fn is_simple_fullscreen(&self) -> bool { + false + } + #[cfg(target_os = "macos")] + fn set_traffic_light_position(&self, _position: Point) {} + fn show_character_palette(&self) {} + fn titlebar_double_click(&self, _is_resizable: bool, _is_minimizable: bool) {} + fn on_move_tab_to_new_window(&self, _callback: Box) {} + fn on_merge_all_windows(&self, _callback: Box) {} + fn on_select_previous_tab(&self, _callback: Box) {} + fn on_select_next_tab(&self, _callback: Box) {} + fn on_toggle_tab_bar(&self, _callback: Box) {} + fn merge_all_windows(&self) {} + fn move_tab_to_new_window(&self) {} + fn toggle_window_tab_overview(&self) {} + fn set_tabbing_identifier(&self, _identifier: Option) {} + + fn native_window_state(&self) -> Option> { + None + } + fn restore_native_window_state(&self, _state: &[u8]) {} + + #[cfg(target_os = "windows")] + fn get_raw_handle(&self) -> windows::Win32::Foundation::HWND; + + // Linux specific methods + fn inner_window_bounds(&self) -> WindowBounds { + self.window_bounds() + } + fn request_decorations(&self, _decorations: WindowDecorations) {} + fn show_window_menu(&self, _position: Point) {} + fn start_window_move(&self) {} + fn can_start_external_drag(&self) -> bool { + false + } + fn start_external_drag(&self, _payload: &ExternalDragPayload) -> bool { + false + } + fn start_window_resize(&self, _edge: ResizeEdge) {} + fn set_exclusive_zone(&self, _zone: Pixels) {} + #[cfg(all(target_os = "linux", feature = "wayland"))] + fn set_exclusive_edge(&self, _edge: layer_shell::Anchor) {} + fn set_input_region(&self, _region: Option<&[Bounds]>) {} + fn window_decorations(&self) -> Decorations { + Decorations::Server + } + fn set_app_id(&mut self, _app_id: &str) {} + fn map_window(&mut self) -> anyhow::Result<()> { + Ok(()) + } + fn window_controls(&self) -> WindowControls { + WindowControls::default() + } + fn set_client_inset(&self, _inset: Pixels) {} + fn gpu_specs(&self) -> Option; + + fn update_ime_position(&self, _bounds: Bounds); + + // Mobile platform methods. + + /// The regions of this window currently obscured or reserved by the + /// system. Zero on platforms without such regions. + fn insets(&self) -> WindowInsets { + WindowInsets::default() + } + + /// Registers a callback invoked whenever [`Self::insets`] change. + /// + /// Contract: fires continuously during animated transitions (Android + /// `WindowInsetsAnimation` progress; on iOS the platform interpolates + /// the keyboard animation curve on frame ticks) and is exact at rest. + fn on_insets_changed(&self, _callback: Box) {} + + /// Sets the handler for the system back action (Android back + /// button/gesture; no source on iOS or desktop). + fn set_back_handler(&self, _callback: Box) {} + + /// Declares whether the application would currently handle the system + /// back action (e.g. navigation depth > 0). + fn set_back_enabled(&self, _enabled: bool) {} + + /// Requests that the soft keyboard be shown. + fn show_soft_keyboard(&self) {} + + /// Requests that the soft keyboard be hidden. + fn hide_soft_keyboard(&self) {} + + /// Inform the operating system that the text input state has changed + fn text_input_state_changed(&self, _change: TextInputStateChange) {} + + fn play_system_bell(&self) {} + + /// Initialize the accessibility adapter with callbacks. + fn a11y_init(&self, _callbacks: A11yCallbacks) {} + + /// Provide a TreeUpdate to the accessibility adapter. + fn a11y_tree_update(&self, _tree_update: accesskit::TreeUpdate) {} + + /// Inform the adapter of updated window bounds. + fn a11y_update_window_bounds(&self) {} + + #[cfg(any(test, feature = "test-support", feature = "bench-support"))] + fn as_test(&mut self) -> Option<&mut TestWindow> { + None + } + + /// Renders the given scene to a texture and returns the pixel data as an RGBA image. + /// This does not present the frame to screen - useful for visual testing where we want + /// to capture what would be rendered without displaying it or requiring the window to be visible. + #[cfg(any(test, feature = "test-support"))] + fn render_to_image(&self, _scene: &Scene) -> Result { + anyhow::bail!("render_to_image not implemented for this platform") + } +} + +/// A renderer for headless windows that can produce real rendered output. +#[cfg(any(test, feature = "test-support", feature = "bench-support"))] +pub trait PlatformHeadlessRenderer { + /// Render a scene and return the result as an RGBA image. + fn render_scene_to_image( + &mut self, + scene: &Scene, + size: Size, + ) -> Result; + + /// Render a scene to an offscreen target without reading the result back. + /// + /// This is the headless analogue of presenting a frame: it performs the + /// same CPU-side scene encoding and GPU submission as drawing to a real + /// window, but doesn't block on GPU completion or copy pixels back. + fn render_scene(&mut self, scene: &Scene, size: Size) -> Result<()>; + + /// Returns the sprite atlas used by this renderer. + fn sprite_atlas(&self) -> Arc; +} + +/// Type alias for runnables with metadata. +/// Previously an enum with a single variant, now simplified to a direct type alias. +#[doc(hidden)] +pub type RunnableVariant = Runnable; + +#[doc(hidden)] +pub type TimerResolutionGuard = gpui_util::Deferred>; + +#[doc(hidden)] +pub enum TasksIncluded { + OnlyCompleted, + CompletedAndRunning, +} + +/// This type is public so that our test macro can generate and use it, but it should not +/// be considered part of our public API. +#[doc(hidden)] +pub trait PlatformDispatcher: Send + Sync { + fn is_main_thread(&self) -> bool; + fn dispatch(&self, runnable: RunnableVariant, priority: Priority); + fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority); + fn dispatch_after(&self, duration: Duration, runnable: RunnableVariant); + + fn dispatch_on_main_thread_when_idle( + &self, + runnable: RunnableVariant, + timeout: Option, + ) { + let _ = timeout; + self.dispatch_on_main_thread(runnable, Priority::Low); + } + + fn idle_time_remaining(&self) -> Option { + None + } + + fn spawn_realtime(&self, f: Box); + + fn now(&self) -> Instant { + Instant::now() + } + + fn increase_timer_resolution(&self) -> TimerResolutionGuard { + gpui_util::defer(Box::new(|| {})) + } + + fn prevent_app_nap(&self, _reason: &str) -> ActivityGuard { + ActivityGuard::noop() + } + + #[cfg(any(test, feature = "test-support", feature = "bench-support"))] + fn as_test(&self) -> Option<&TestDispatcher> { + None + } + + // This cfg must match the `threaded_dispatcher` module's, which implements + // this method whenever it compiles. + #[cfg(any(test, feature = "test-support", feature = "bench-support"))] + fn as_threaded(&self) -> Option<&ThreadedDispatcher> { + None + } +} + +#[expect(missing_docs)] +pub trait PlatformTextSystem: Send + Sync { + fn add_fonts(&self, fonts: Vec>) -> Result<()>; + /// Installs a nonblocking sink for unresolved grapheme clusters. + fn set_missing_glyph_sink(&self, _sink: Option>) {} + /// Get all available font names. + fn all_font_names(&self) -> Vec; + /// The weights a family ships as its own faces, ascending and without repeats. + /// + /// A platform that cannot tell answers none, and the caller shows its own list. + fn weights_for_family(&self, _family: &str) -> Vec { + Vec::new() + } + /// Whether `family` is monospaced, as the platform's own metadata says. + /// + /// A platform that cannot tell answers true, so every font stays offered. + fn is_monospaced(&self, _family: &str) -> bool { + true + } + /// Get the font ID for a font descriptor. + fn font_id(&self, descriptor: &Font) -> Result; + /// Prewarm any system font caches needed to shape text. + fn prewarm_fonts(&self, _font_ids: &[FontId]) {} + /// Get metrics for a font. + fn font_metrics(&self, font_id: FontId) -> FontMetrics; + /// Get typographic bounds for a glyph. + fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result>; + /// Get the advance width for a glyph. + fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result>; + /// Get the glyph ID for a character. + fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option; + /// Get raster bounds for a glyph. + fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result>; + /// Rasterize a glyph. + fn rasterize_glyph( + &self, + params: &RenderGlyphParams, + raster_bounds: Bounds, + ) -> Result<(Size, Vec)>; + /// Layout a line of text with the given font runs. + fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout; + /// Returns the recommended text rendering mode for the given font and size. + fn recommended_rendering_mode(&self, _font_id: FontId, _font_size: Pixels) + -> TextRenderingMode; + /// Returns the dilation level to use for a glyph painted in the given color. + fn glyph_dilation_for_color(&self, _color: Hsla) -> u8 { + 0 + } +} + +#[expect(missing_docs)] +pub struct NoopTextSystem; + +#[expect(missing_docs)] +impl NoopTextSystem { + #[allow(dead_code)] + pub fn new() -> Self { + Self + } +} + +impl PlatformTextSystem for NoopTextSystem { + fn add_fonts(&self, _fonts: Vec>) -> Result<()> { + Ok(()) + } + + fn all_font_names(&self) -> Vec { + Vec::new() + } + + fn weights_for_family(&self, _family: &str) -> Vec { + Vec::new() + } + + fn is_monospaced(&self, _family: &str) -> bool { + true + } + + fn font_id(&self, _descriptor: &Font) -> Result { + Ok(FontId(1)) + } + + fn font_metrics(&self, _font_id: FontId) -> FontMetrics { + FontMetrics { + units_per_em: 1000, + ascent: 1025.0, + descent: -275.0, + line_gap: 0.0, + underline_position: -95.0, + underline_thickness: 60.0, + cap_height: 698.0, + x_height: 516.0, + bounding_box: Bounds { + origin: Point { + x: -260.0, + y: -245.0, + }, + size: Size { + width: 1501.0, + height: 1364.0, + }, + }, + } + } + + fn typographic_bounds(&self, _font_id: FontId, _glyph_id: GlyphId) -> Result> { + Ok(Bounds { + origin: Point { x: 54.0, y: 0.0 }, + size: size(392.0, 528.0), + }) + } + + fn advance(&self, _font_id: FontId, glyph_id: GlyphId) -> Result> { + Ok(size(600.0 * glyph_id.0 as f32, 0.0)) + } + + fn glyph_for_char(&self, _font_id: FontId, ch: char) -> Option { + Some(GlyphId(ch.len_utf16() as u32)) + } + + fn glyph_raster_bounds(&self, _params: &RenderGlyphParams) -> Result> { + Ok(Default::default()) + } + + fn rasterize_glyph( + &self, + _params: &RenderGlyphParams, + raster_bounds: Bounds, + ) -> Result<(Size, Vec)> { + Ok((raster_bounds.size, Vec::new())) + } + + fn layout_line(&self, text: &str, font_size: Pixels, _runs: &[FontRun]) -> LineLayout { + let mut position = px(0.); + let metrics = self.font_metrics(FontId(0)); + let em_width = font_size + * self + .advance(FontId(0), self.glyph_for_char(FontId(0), 'm').unwrap()) + .unwrap() + .width + / metrics.units_per_em as f32; + let mut glyphs = Vec::new(); + for (ix, c) in text.char_indices() { + if let Some(glyph) = self.glyph_for_char(FontId(0), c) { + glyphs.push(ShapedGlyph { + id: glyph, + position: point(position, px(0.)), + index: ix, + is_emoji: glyph.0 == 2, + }); + if glyph.0 == 2 { + position += em_width * 2.0; + } else { + position += em_width; + } + } else { + position += em_width + } + } + let mut runs = Vec::default(); + if !glyphs.is_empty() { + runs.push(ShapedRun { + font_id: FontId(0), + glyphs, + }); + } else { + position = px(0.); + } + + LineLayout { + font_size, + width: position, + ascent: font_size * (metrics.ascent / metrics.units_per_em as f32), + descent: font_size * (metrics.descent / metrics.units_per_em as f32), + runs, + len: text.len(), + } + } + + fn recommended_rendering_mode( + &self, + _font_id: FontId, + _font_size: Pixels, + ) -> TextRenderingMode { + TextRenderingMode::Grayscale + } +} + +// Adapted from https://github.com/microsoft/terminal/blob/1283c0f5b99a2961673249fa77c6b986efb5086c/src/renderer/atlas/dwrite.cpp +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/// Compute gamma correction ratios for subpixel text rendering. +#[allow(dead_code)] +pub fn get_gamma_correction_ratios(gamma: f32) -> [f32; 4] { + const GAMMA_INCORRECT_TARGET_RATIOS: [[f32; 4]; 13] = [ + [0.0000 / 4.0, 0.0000 / 4.0, 0.0000 / 4.0, 0.0000 / 4.0], // gamma = 1.0 + [0.0166 / 4.0, -0.0807 / 4.0, 0.2227 / 4.0, -0.0751 / 4.0], // gamma = 1.1 + [0.0350 / 4.0, -0.1760 / 4.0, 0.4325 / 4.0, -0.1370 / 4.0], // gamma = 1.2 + [0.0543 / 4.0, -0.2821 / 4.0, 0.6302 / 4.0, -0.1876 / 4.0], // gamma = 1.3 + [0.0739 / 4.0, -0.3963 / 4.0, 0.8167 / 4.0, -0.2287 / 4.0], // gamma = 1.4 + [0.0933 / 4.0, -0.5161 / 4.0, 0.9926 / 4.0, -0.2616 / 4.0], // gamma = 1.5 + [0.1121 / 4.0, -0.6395 / 4.0, 1.1588 / 4.0, -0.2877 / 4.0], // gamma = 1.6 + [0.1300 / 4.0, -0.7649 / 4.0, 1.3159 / 4.0, -0.3080 / 4.0], // gamma = 1.7 + [0.1469 / 4.0, -0.8911 / 4.0, 1.4644 / 4.0, -0.3234 / 4.0], // gamma = 1.8 + [0.1627 / 4.0, -1.0170 / 4.0, 1.6051 / 4.0, -0.3347 / 4.0], // gamma = 1.9 + [0.1773 / 4.0, -1.1420 / 4.0, 1.7385 / 4.0, -0.3426 / 4.0], // gamma = 2.0 + [0.1908 / 4.0, -1.2652 / 4.0, 1.8650 / 4.0, -0.3476 / 4.0], // gamma = 2.1 + [0.2031 / 4.0, -1.3864 / 4.0, 1.9851 / 4.0, -0.3501 / 4.0], // gamma = 2.2 + ]; + + const NORM13: f32 = ((0x10000 as f64) / (255.0 * 255.0) * 4.0) as f32; + const NORM24: f32 = ((0x100 as f64) / (255.0) * 4.0) as f32; + + let index = ((gamma * 10.0).round() as usize).clamp(10, 22) - 10; + let ratios = GAMMA_INCORRECT_TARGET_RATIOS[index]; + + [ + ratios[0] * NORM13, + ratios[1] * NORM24, + ratios[2] * NORM13, + ratios[3] * NORM24, + ] +} + +#[derive(PartialEq, Eq, Hash, Clone)] +#[expect(missing_docs)] +pub enum AtlasKey { + Glyph(RenderGlyphParams), + Svg(RenderSvgParams), + Image(RenderImageParams), +} + +impl AtlasKey { + /// Returns the texture kind for this atlas key. + pub fn texture_kind(&self) -> AtlasTextureKind { + match self { + AtlasKey::Glyph(params) => { + if params.is_emoji { + AtlasTextureKind::Polychrome + } else if params.subpixel_rendering { + AtlasTextureKind::Subpixel + } else { + AtlasTextureKind::Monochrome + } + } + AtlasKey::Svg(_) => AtlasTextureKind::Monochrome, + AtlasKey::Image(_) => AtlasTextureKind::Polychrome, + } + } +} + +impl From for AtlasKey { + fn from(params: RenderGlyphParams) -> Self { + Self::Glyph(params) + } +} + +impl From for AtlasKey { + fn from(params: RenderSvgParams) -> Self { + Self::Svg(params) + } +} + +impl From for AtlasKey { + fn from(params: RenderImageParams) -> Self { + Self::Image(params) + } +} + +#[expect(missing_docs)] +pub trait PlatformAtlas { + /// The builder runs with the atlas locked and must not re-enter the same atlas. + fn get_or_insert_with<'a>( + &self, + key: AtlasKey, + build: &mut dyn FnMut() -> Result, Cow<'a, [u8]>)>>, + ) -> Result>; + fn remove(&self, key: &AtlasKey); + + #[cfg(any(test, feature = "test-support", feature = "bench-support"))] + fn contains(&self, _key: &AtlasKey) -> bool { + false + } +} + +#[doc(hidden)] +pub trait AtlasBackend { + fn insert( + &mut self, + kind: AtlasTextureKind, + size: Size, + bytes: &[u8], + ) -> Result; + + fn remove(&mut self, tile: AtlasTile); +} + +#[doc(hidden)] +pub struct AtlasState { + tiles_by_key: FxHashMap, + pub backend: Backend, +} + +impl AtlasState { + pub fn new(backend: Backend) -> Self { + Self { + tiles_by_key: FxHashMap::default(), + backend, + } + } + + pub fn contains(&self, key: &AtlasKey) -> bool { + self.tiles_by_key.contains_key(key) + } + + pub fn clear(&mut self, reset_backend: impl FnOnce(&mut Backend)) { + self.tiles_by_key.clear(); + reset_backend(&mut self.backend); + } +} + +impl Default for AtlasState { + fn default() -> Self { + Self::new(Backend::default()) + } +} + +impl AtlasState { + pub fn get_or_insert_with<'a>( + &mut self, + key: AtlasKey, + build: &mut dyn FnMut() -> Result, Cow<'a, [u8]>)>>, + ) -> Result> { + match self.tiles_by_key.entry(key) { + Entry::Occupied(entry) => Ok(Some(*entry.get())), + Entry::Vacant(entry) => { + profiling::scope!("new tile"); + let Some((size, bytes)) = build()? else { + return Ok(None); + }; + let tile = self + .backend + .insert(entry.key().texture_kind(), size, &bytes)?; + entry.insert(tile); + Ok(Some(tile)) + } + } + } + + pub fn remove(&mut self, key: &AtlasKey) { + if let Some(tile) = self.tiles_by_key.remove(key) { + self.backend.remove(tile); + } + } +} + +/// A sprite atlas for windows without a GPU. It hands out uniquely identified +/// tiles without uploading any pixels, so glyph, SVG, and image painting can +/// run to completion in tests and headless platforms. +#[derive(Default)] +pub struct HeadlessAtlas(parking_lot::Mutex>); + +#[doc(hidden)] +#[derive(Default)] +pub struct HeadlessAtlasBackend { + next_id: u32, +} + +impl AtlasBackend for HeadlessAtlasBackend { + fn insert( + &mut self, + kind: AtlasTextureKind, + size: Size, + _bytes: &[u8], + ) -> Result { + self.next_id += 1; + let texture_id = self.next_id; + self.next_id += 1; + let tile_id = self.next_id; + Ok(AtlasTile { + texture_id: AtlasTextureId { + index: texture_id, + kind, + }, + tile_id: TileId(tile_id), + padding: 0, + bounds: Bounds { + origin: Point::default(), + size, + }, + }) + } + + fn remove(&mut self, _tile: AtlasTile) {} +} + +impl PlatformAtlas for HeadlessAtlas { + fn get_or_insert_with<'a>( + &self, + key: AtlasKey, + build: &mut dyn FnMut() -> Result, Cow<'a, [u8]>)>>, + ) -> Result> { + self.0.lock().get_or_insert_with(key, build) + } + + fn remove(&self, key: &AtlasKey) { + self.0.lock().remove(key); + } + + #[cfg(any(test, feature = "test-support", feature = "bench-support"))] + fn contains(&self, key: &AtlasKey) -> bool { + self.0.lock().contains(key) + } +} + +#[doc(hidden)] +pub struct AtlasTextureList { + pub textures: Vec>, + pub free_list: Vec, +} + +impl Default for AtlasTextureList { + fn default() -> Self { + Self { + textures: Vec::default(), + free_list: Vec::default(), + } + } +} + +impl ops::Index for AtlasTextureList { + type Output = Option; + + fn index(&self, index: usize) -> &Self::Output { + &self.textures[index] + } +} + +impl AtlasTextureList { + #[allow(unused)] + pub fn drain(&mut self) -> std::vec::Drain<'_, Option> { + self.free_list.clear(); + self.textures.drain(..) + } + + #[allow(dead_code)] + pub fn iter_mut(&mut self) -> impl DoubleEndedIterator { + self.textures.iter_mut().flatten() + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(C)] +#[expect(missing_docs)] +pub struct AtlasTile { + /// The texture this tile belongs to. + pub texture_id: AtlasTextureId, + /// The unique ID of this tile within its texture. + pub tile_id: TileId, + /// Padding around the tile content in pixels. + pub padding: u32, + /// The bounds of this tile within the texture. + pub bounds: Bounds, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(C)] +#[expect(missing_docs)] +pub struct AtlasTextureId { + // We use u32 instead of usize for Metal Shader Language compatibility + /// The index of this texture in the atlas. + pub index: u32, + /// The kind of content stored in this texture. + pub kind: AtlasTextureKind, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(C)] +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +#[expect(missing_docs)] +pub enum AtlasTextureKind { + Monochrome = 0, + Polychrome = 1, + Subpixel = 2, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[repr(C)] +#[expect(missing_docs)] +pub struct TileId(pub u32); + +impl From for TileId { + fn from(id: etagere::AllocId) -> Self { + Self(id.serialize()) + } +} + +impl From for etagere::AllocId { + fn from(id: TileId) -> Self { + Self::deserialize(id.0) + } +} + +#[expect(missing_docs)] +pub struct PlatformInputHandler { + cx: AsyncWindowContext, + handler: Box, +} + +#[expect(missing_docs)] +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +impl PlatformInputHandler { + pub fn new(cx: AsyncWindowContext, handler: Box) -> Self { + Self { cx, handler } + } + + pub fn selected_text_range(&mut self, ignore_disabled_input: bool) -> Option { + self.cx + .update(|window, cx| { + self.handler + .selected_text_range(ignore_disabled_input, window, cx) + }) + .ok() + .flatten() + } + + #[cfg_attr(target_os = "windows", allow(dead_code))] + pub fn marked_text_range(&mut self) -> Option> { + self.cx + .update(|window, cx| self.handler.marked_text_range(window, cx)) + .ok() + .flatten() + } + + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "windows"), + allow(dead_code) + )] + pub fn text_for_range( + &mut self, + range_utf16: Range, + adjusted: &mut Option>, + ) -> Option { + self.cx + .update(|window, cx| { + self.handler + .text_for_range(range_utf16, adjusted, window, cx) + }) + .ok() + .flatten() + } + + pub fn replace_text_in_range(&mut self, replacement_range: Option>, text: &str) { + self.cx + .update(|window, cx| { + self.handler + .replace_text_in_range(replacement_range, text, window, cx); + }) + .ok(); + } + + pub fn replace_and_mark_text_in_range( + &mut self, + range_utf16: Option>, + new_text: &str, + new_selected_range: Option>, + ) { + self.cx + .update(|window, cx| { + self.handler.replace_and_mark_text_in_range( + range_utf16, + new_text, + new_selected_range, + window, + cx, + ) + }) + .ok(); + } + + #[cfg_attr(target_os = "windows", allow(dead_code))] + pub fn unmark_text(&mut self) { + self.cx + .update(|window, cx| self.handler.unmark_text(window, cx)) + .ok(); + } + + pub fn paste(&mut self, item: ClipboardItem) { + self.cx + .update(|window, cx| self.handler.paste(item, window, cx)) + .ok(); + } + + pub fn bounds_for_range(&mut self, range_utf16: Range) -> Option> { + self.cx + .update(|window, cx| self.handler.bounds_for_range(range_utf16, window, cx)) + .ok() + .flatten() + } + + #[allow(dead_code)] + pub fn apple_press_and_hold_enabled(&mut self) -> bool { + self.handler.apple_press_and_hold_enabled() + } + + pub fn dispatch_input(&mut self, input: &str, window: &mut Window, cx: &mut App) { + self.handler.replace_text_in_range(None, input, window, cx); + } + + pub fn compute_ime_candidate_bounds( + marked_range: Option>, + selection: &UTF16Selection, + mut bounds_for_range: impl FnMut(Range) -> Option>, + ) -> Option> { + if let Some(marked_range) = marked_range { + // Default to the start of the marked (composing) range. + let mut line_start = marked_range.start; + + // Walk backward from the caret looking for a line break. A change in + // the Y coordinate means we crossed into the previous visual line, so + // the line start is one position after the break point. + let caret = selection.range.end; + if let Some(caret_bounds) = bounds_for_range(caret..caret) { + for i in (marked_range.start..caret).rev() { + if let Some(b) = bounds_for_range(i..i) { + if (b.origin.y - caret_bounds.origin.y).abs() > px(0.1) { + line_start = i + 1; + break; + } + } + } + } + bounds_for_range(line_start..line_start) + } else { + // No active composition — use the selection endpoint. + let offset = if selection.reversed { + selection.range.start + } else { + selection.range.end + }; + bounds_for_range(offset..offset) + } + } + + pub fn selected_bounds(&mut self, window: &mut Window, cx: &mut App) -> Option> { + let marked_range = self.handler.marked_text_range(window, cx); + let selection = self.handler.selected_text_range(true, window, cx)?; + Self::compute_ime_candidate_bounds(marked_range, &selection, |range| { + self.handler.bounds_for_range(range, window, cx) + }) + } + + pub fn ime_candidate_bounds(&mut self) -> Option> { + let marked_range = self.marked_text_range(); + let selection = self.selected_text_range(true)?; + Self::compute_ime_candidate_bounds(marked_range, &selection, |range| { + self.bounds_for_range(range) + }) + } + + #[allow(unused)] + pub fn character_index_for_point(&mut self, point: Point) -> Option { + self.cx + .update(|window, cx| self.handler.character_index_for_point(point, window, cx)) + .ok() + .flatten() + } + + /// See [`InputHandler::set_selected_text_range`]. + pub fn set_selected_text_range(&mut self, range_utf16: Range) { + self.cx + .update(|window, cx| { + self.handler + .set_selected_text_range(range_utf16, window, cx) + }) + .ok(); + } + + /// See [`InputHandler::element_bounds`]. + pub fn element_bounds(&mut self) -> Option> { + self.cx + .update(|window, cx| self.handler.element_bounds(window, cx)) + .ok() + .flatten() + } + + /// See [`InputHandler::text_length_utf16`]. + pub fn text_length_utf16(&mut self) -> Option { + self.cx + .update(|window, cx| self.handler.text_length_utf16(window, cx)) + .ok() + .flatten() + } + + #[allow(dead_code)] + pub fn accepts_text_input(&mut self, window: &mut Window, cx: &mut App) -> bool { + self.handler.accepts_text_input(window, cx) + } + + #[allow(dead_code)] + pub fn query_accepts_text_input(&mut self) -> bool { + self.cx + .update(|window, cx| self.handler.accepts_text_input(window, cx)) + .unwrap_or(true) + } + + /// See [`InputHandler::prefers_ime_for_printable_keys`]. + /// + /// This is not a pure delegation to the handler: while a multi-stroke binding is pending this + /// returns `false` regardless of the handler's preference, because the next printable key may + /// complete a binding whose prefix already bypassed the IME. + pub fn query_prefers_ime_for_printable_keys(&mut self) -> bool { + self.cx + .update(|window, cx| { + // The next printable key may complete a chord whose prefix bypassed the IME. + !window.has_pending_keystrokes() + && self.handler.prefers_ime_for_printable_keys(window, cx) + }) + .unwrap_or(false) + } + + /// See [`InputHandler::text_input_configuration`]. + pub fn text_input_configuration( + &mut self, + window: &mut Window, + cx: &mut App, + ) -> TextInputConfiguration { + self.handler.text_input_configuration(window, cx) + } + + /// See [`InputHandler::text_input_editable_range`]. + pub fn text_input_editable_range(&mut self) -> Option> { + self.cx + .update(|window, cx| self.handler.text_input_editable_range(window, cx)) + .ok() + .flatten() + } +} + +/// A struct representing a selection in a text buffer, in UTF16 characters. +/// This is different from a range because the head may be before the tail. +#[derive(Debug)] +pub struct UTF16Selection { + /// The range of text in the document this selection corresponds to + /// in UTF16 characters. + pub range: Range, + /// Whether the head of this selection is at the start (true), or end (false) + /// of the range + pub reversed: bool, +} + +/// Zed's interface for handling text input from the platform's IME system +/// This is currently a 1:1 exposure of the NSTextInputClient API: +/// +/// +pub trait InputHandler: 'static { + /// Get the range of the user's currently selected text, if any + /// Corresponds to [selectedRange()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438242-selectedrange) + /// + /// Return value is in terms of UTF-16 characters, from 0 to the length of the document + fn selected_text_range( + &mut self, + ignore_disabled_input: bool, + window: &mut Window, + cx: &mut App, + ) -> Option; + + /// Get the range of the currently marked text, if any + /// Corresponds to [markedRange()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438250-markedrange) + /// + /// Return value is in terms of UTF-16 characters, from 0 to the length of the document + fn marked_text_range(&mut self, window: &mut Window, cx: &mut App) -> Option>; + + /// Get the text for the given document range in UTF-16 characters + /// Corresponds to [attributedSubstring(forProposedRange: actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438238-attributedsubstring) + /// + /// range_utf16 is in terms of UTF-16 characters + fn text_for_range( + &mut self, + range_utf16: Range, + adjusted_range: &mut Option>, + window: &mut Window, + cx: &mut App, + ) -> Option; + + /// Replace the text in the given document range with the given text + /// Corresponds to [insertText(_:replacementRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438258-inserttext) + /// + /// replacement_range is in terms of UTF-16 characters + fn replace_text_in_range( + &mut self, + replacement_range: Option>, + text: &str, + window: &mut Window, + cx: &mut App, + ); + + /// Replace the text in the given document range with the given text, + /// and mark the given text as part of an IME 'composing' state + /// Corresponds to [setMarkedText(_:selectedRange:replacementRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438246-setmarkedtext) + /// + /// range_utf16 is in terms of UTF-16 characters + /// new_selected_range is in terms of UTF-16 characters + fn replace_and_mark_text_in_range( + &mut self, + range_utf16: Option>, + new_text: &str, + new_selected_range: Option>, + window: &mut Window, + cx: &mut App, + ); + + /// Remove the IME 'composing' state from the document + /// Corresponds to [unmarkText()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438239-unmarktext) + fn unmark_text(&mut self, window: &mut Window, cx: &mut App); + + /// Insert a platform-initiated paste at the current selection. + /// + /// Platforms that deliver paste as an input event rather than through an + /// application-defined action (e.g. the DOM `paste` event on web) call + /// this with the full clipboard contents. The default implementation + /// inserts only the plain-text portion of the item. + fn paste(&mut self, item: ClipboardItem, window: &mut Window, cx: &mut App) { + if let Some(text) = item.text() { + self.replace_text_in_range(None, &text, window, cx); + } + } + + /// Get the bounds of the given document range in screen coordinates + /// Corresponds to [firstRect(forCharacterRange:actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438240-firstrect) + /// + /// This is used for positioning the IME candidate window + fn bounds_for_range( + &mut self, + range_utf16: Range, + window: &mut Window, + cx: &mut App, + ) -> Option>; + + /// Get the character offset for the given point in terms of UTF16 characters + /// + /// Corresponds to [characterIndexForPoint:](https://developer.apple.com/documentation/appkit/nstextinputclient/characterindex(for:)) + fn character_index_for_point( + &mut self, + point: Point, + window: &mut Window, + cx: &mut App, + ) -> Option; + + /// Set the range of the user's currently selected text. + /// + /// This is the reverse data-flow direction from [`Self::selected_text_range`]: + /// platforms call it when the system text machinery moves the selection on the + /// application's behalf — e.g. the user drags a system selection handle or + /// invokes Select All from system UI (iOS `UITextInput setSelectedTextRange:`, + /// Android `InputConnection.setSelection`). + /// + /// range_utf16 is in terms of UTF-16 characters, from 0 to the length of the document + fn set_selected_text_range( + &mut self, + _range_utf16: Range, + _window: &mut Window, + _cx: &mut App, + ) { + } + + /// Get the bounds of the focused text element in window coordinates, if known. + /// + /// This is the pull counterpart to the [`PlatformWindow::update_ime_position`] + /// push: mobile platforms ask for the focused element's geometry when they + /// need it (e.g. to frame system text-interaction UI overlaid on the focused + /// element). + fn element_bounds(&mut self, _window: &mut Window, _cx: &mut App) -> Option> { + None + } + + /// Get the length of the document in UTF-16 characters, if known. + fn text_length_utf16(&mut self, _window: &mut Window, _cx: &mut App) -> Option { + None + } + + /// Allows a given input context to opt into getting raw key repeats instead of + /// sending these to the platform. + /// TODO: Ideally we should be able to set ApplePressAndHoldEnabled in NSUserDefaults + /// (which is how iTerm does it) but it doesn't seem to work for me. + #[allow(dead_code)] + fn apple_press_and_hold_enabled(&mut self) -> bool { + true + } + + /// Returns whether this handler is accepting text input to be inserted. + fn accepts_text_input(&mut self, _window: &mut Window, _cx: &mut App) -> bool { + true + } + + /// The contiguous range of text, in UTF-16 code units, that platform text + /// input may read and edit around the current selection. + /// + /// Platforms that mirror document text into an IME-editable buffer clamp + /// the mirrored window to this range, so multi-step IME edit gestures + /// (word deletion, autocorrect rewrites, suggestion picks) cannot reach + /// content outside it. The range should contain the current selection; + /// when it cannot (a selection spanning a region boundary), platforms + /// degrade the mirrored IME context rather than widening the range. + /// `None` places no bound. + fn text_input_editable_range( + &mut self, + _window: &mut Window, + _cx: &mut App, + ) -> Option> { + None + } + + /// Returns whether printable keys should be routed to the IME before keybinding + /// matching when a non-ASCII input source (e.g. Japanese, Korean, Chinese IME) + /// is active. This prevents multi-stroke keybindings like `jj` from intercepting + /// keys that the IME should compose. + /// + /// Defaults to `false`. The editor overrides this based on whether it expects + /// character input (e.g. Vim insert mode returns `true`, normal mode returns `false`). + /// The terminal keeps the default `false` so that raw keys reach the terminal process. + fn prefers_ime_for_printable_keys(&mut self, _window: &mut Window, _cx: &mut App) -> bool { + false + } + + /// Get this handler's preferences for platform text assistance. + /// + /// GPUI re-queries this every frame and forwards it to the platform window + /// only when it changes, so implementations must be cheap and may vary the + /// result with application state (e.g. with the cursor's position). + fn text_input_configuration( + &mut self, + _window: &mut Window, + _cx: &mut App, + ) -> TextInputConfiguration { + TextInputConfiguration::default() + } +} + +/// Platform text-assistance preferences for the focused text region. +/// +/// Returned by [`InputHandler::text_input_configuration`] and forwarded to the +/// platform whenever it changes; the platform maps the fields onto its native +/// input-session attributes (on web, DOM attributes of the hidden editable +/// element such as `autocorrect` and `enterkeyhint`). +/// +/// The default disables all text assistance and requests no particular action +/// key presentation. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct TextInputConfiguration { + /// Whether the platform may automatically correct entered text. + pub autocorrect: bool, + /// How software keyboards automatically capitalize entered text. + pub autocapitalize: Autocapitalize, + /// Whether software keyboards may offer word suggestions and spellcheck. + pub suggestions: bool, + /// The action advertised on a software keyboard's confirm ("enter") key. + pub input_action: TextInputAction, +} + +/// Automatic capitalization applied by software keyboards. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum Autocapitalize { + /// No automatic capitalization. + #[default] + None, + /// Capitalize the first letter of each word. + Words, + /// Capitalize the first letter of each sentence. + Sentences, + /// Capitalize every letter. + Characters, +} + +/// The action a software keyboard advertises on its confirm ("enter") key. +/// +/// This affects only how the key is presented (icon or label); pressing it is +/// still delivered as ordinary input. +/// +/// The variants are the HTML `enterkeyhint` attribute's value set +/// (), +/// which also maps onto Android's `IME_ACTION_*` constants and iOS's +/// `UIReturnKeyType`; [`TextInputAction::Unspecified`] means "emit no hint". +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum TextInputAction { + /// Let the platform choose its default presentation. + #[default] + Unspecified, + /// Inserting a line break. + Enter, + /// Committing the field's value. + Done, + /// Navigating to the typed target. + Go, + /// Moving to the next field. + Next, + /// Moving to the previous field. + Previous, + /// Executing a search. + Search, + /// Sending a message. + Send, +} + +/// The variables that can be configured when creating a new window +#[derive(Debug)] +pub struct WindowOptions { + /// Specifies the state and bounds of the window in screen coordinates. + /// - `None`: Inherit the bounds. + /// - `Some(WindowBounds)`: Open a window with corresponding state and its restore size. + pub window_bounds: Option, + + /// The titlebar configuration of the window + pub titlebar: Option, + + /// Whether the window should be focused when created + pub focus: bool, + + /// Whether the window should be shown when created + pub show: bool, + + /// The kind of window to create + pub kind: WindowKind, + + /// Whether the window can be moved by the user. When `false`, the user cannot drag + /// the window (on macOS this sets `NSWindow.isMovable`, which also disables the + /// Window-menu tiling items); programmatic moves are still allowed. + pub is_movable: bool, + + /// Whether the application owns dragging of the (custom) titlebar, rather than + /// AppKit. Only has an effect on macOS. + /// + /// Set this to `true` for windows that draw their own titlebar and move the window + /// themselves via [`Window::start_window_move`]. It marks the whole content view as + /// app-owned titlebar content, so AppKit neither drags the window from the titlebar + /// nor delays titlebar clicks while disambiguating double-clicks (a delay first + /// observed on macOS 27). It is independent of `is_movable`, so such windows stay + /// user-movable (via their own drag) and keep the Window-menu tiling items enabled. + /// + /// Leave this `false` for windows that rely on AppKit's native titlebar dragging. + pub app_owns_titlebar_drag: bool, + + /// The minimum interval between animation frames while the window is inactive. + /// + /// Set to `None` to disable inactive-window animation frame throttling. + pub inactive_frame_interval: Option, + + /// Whether the window should be resizable by the user + pub is_resizable: bool, + + /// Whether the window should be minimized by the user + pub is_minimizable: bool, + + /// The display to create the window on, if this is None, + /// the window will be created on the main display + pub display_id: Option, + + /// The appearance of the window background. + pub window_background: WindowBackgroundAppearance, + + /// Application identifier of the window. Can by used by desktop environments to group applications together. + pub app_id: Option, + + /// Window minimum size + pub window_min_size: Option>, + + /// Whether to use client or server-side decorations on X11 and Wayland. + /// The platform may ignore requests it cannot satisfy. + pub window_decorations: Option, + + /// Icon image (X11 only) + pub icon: Option>, + + /// Tab group name, allows opening the window as a native tab on macOS 10.12+. Windows with the same tabbing identifier will be grouped together. + pub tabbing_identifier: Option, +} + +/// The variables that can be configured when creating a new window +#[derive(Debug)] +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +#[allow(missing_docs)] +pub struct WindowParams { + pub bounds: Bounds, + + /// The titlebar configuration of the window + #[cfg_attr(feature = "wayland", allow(dead_code))] + pub titlebar: Option, + + /// The kind of window to create + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + pub kind: WindowKind, + + /// Whether the window should be movable by the user + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + pub is_movable: bool, + + /// Whether the application owns dragging of the (custom) titlebar (macOS only) + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "windows"), + allow(dead_code) + )] + pub app_owns_titlebar_drag: bool, + + /// Whether the window should be resizable by the user + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + pub is_resizable: bool, + + /// Whether the window should be minimized by the user + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + pub is_minimizable: bool, + + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "windows"), + allow(dead_code) + )] + pub focus: bool, + + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + pub show: bool, + + /// An image to set as the window icon (x11 only) + #[cfg_attr(feature = "wayland", allow(dead_code))] + pub icon: Option>, + + #[cfg_attr(feature = "wayland", allow(dead_code))] + pub display_id: Option, + + #[cfg_attr(feature = "wayland", allow(dead_code))] + pub app_id: Option, + + pub window_min_size: Option>, + + #[cfg(target_os = "macos")] + pub tabbing_identifier: Option, +} + +/// Represents the status of how a window should be opened. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum WindowBounds { + /// Indicates that the window should open in a windowed state with the given bounds. + Windowed(Bounds), + /// Indicates that the window should open in a maximized state. + /// The bounds provided here represent the restore size of the window. + Maximized(Bounds), + /// Indicates that the window should open in fullscreen mode. + /// The bounds provided here represent the restore size of the window. + Fullscreen(Bounds), +} + +impl Default for WindowBounds { + fn default() -> Self { + WindowBounds::Windowed(Bounds::default()) + } +} + +impl WindowBounds { + /// Retrieve the inner bounds + pub fn get_bounds(&self) -> Bounds { + match self { + WindowBounds::Windowed(bounds) => *bounds, + WindowBounds::Maximized(bounds) => *bounds, + WindowBounds::Fullscreen(bounds) => *bounds, + } + } + + /// Creates a new window bounds that centers the window on the screen. + pub fn centered(size: Size, cx: &App) -> Self { + WindowBounds::Windowed(Bounds::centered(None, size, cx)) + } +} + +impl Default for WindowOptions { + fn default() -> Self { + Self { + window_bounds: None, + titlebar: Some(TitlebarOptions { + title: Default::default(), + appears_transparent: Default::default(), + traffic_light_position: Default::default(), + }), + focus: true, + show: true, + kind: WindowKind::Normal, + is_movable: true, + app_owns_titlebar_drag: false, + inactive_frame_interval: Some(Duration::from_micros(33_333)), + is_resizable: true, + is_minimizable: true, + display_id: None, + window_background: WindowBackgroundAppearance::default(), + icon: None, + app_id: None, + window_min_size: None, + window_decorations: None, + tabbing_identifier: None, + } + } +} + +/// The options that can be configured for a window's titlebar +#[derive(Debug, Default)] +pub struct TitlebarOptions { + /// The initial title of the window + pub title: Option, + + /// Should the default system titlebar be hidden to allow for a custom-drawn titlebar? (macOS and Windows only) + /// Refer to [`WindowOptions::window_decorations`] on Linux + pub appears_transparent: bool, + + /// The position of the macOS traffic light buttons + pub traffic_light_position: Option>, +} + +/// The kind of window to create +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum WindowKind { + /// A normal application window + Normal, + + /// A window that appears above all other windows, usually used for alerts or popups + /// use sparingly! + PopUp, + + /// A parent-anchored, platform-native popup window for menus, comboboxes, context menus and + /// tooltips. Unlike [`WindowKind::PopUp`], it is positioned relative to a parent window. + /// + /// The popup's size comes from [`WindowOptions::window_bounds`], whose origin is ignored. + /// See [`popup::PopupOptions`] for the placement options. Platforms without a native + /// implementation reject it with [`popup::PopupNotSupportedError`]. + AnchoredPopup(popup::PopupOptions), + + /// A floating window that appears on top of its parent window + Floating, + + /// A Wayland LayerShell window, used to draw overlays or backgrounds for applications such as + /// docks, notifications or wallpapers. + #[cfg(all(target_os = "linux", feature = "wayland"))] + LayerShell(layer_shell::LayerShellOptions), + + /// A window that appears on top of its parent window and blocks interaction with it + /// until the modal window is closed + Dialog, +} + +/// The appearance of the window, as defined by the operating system. +/// +/// On macOS, this corresponds to named [`NSAppearance`](https://developer.apple.com/documentation/appkit/nsappearance) +/// values. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum WindowAppearance { + /// A light appearance. + /// + /// On macOS, this corresponds to the `aqua` appearance. + #[default] + Light, + + /// A light appearance with vibrant colors. + /// + /// On macOS, this corresponds to the `NSAppearanceNameVibrantLight` appearance. + VibrantLight, + + /// A dark appearance. + /// + /// On macOS, this corresponds to the `darkAqua` appearance. + Dark, + + /// A dark appearance with vibrant colors. + /// + /// On macOS, this corresponds to the `NSAppearanceNameVibrantDark` appearance. + VibrantDark, +} + +/// The appearance of the background of the window itself, when there is +/// no content or the content is transparent. +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub enum WindowBackgroundAppearance { + /// Opaque. + /// + /// This lets the window manager know that content behind this + /// window does not need to be drawn. + /// + /// Actual color depends on the system and themes should define a fully + /// opaque background color instead. + #[default] + Opaque, + /// Plain alpha transparency. + Transparent, + /// Transparency, but the contents behind the window are blurred. + /// + /// Not always supported. + Blurred, + /// The Mica backdrop material, supported on Windows 11. + MicaBackdrop, + /// The Mica Alt backdrop material, supported on Windows 11. + MicaAltBackdrop, +} + +/// The text rendering mode to use for drawing glyphs. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum TextRenderingMode { + /// Use the platform's default text rendering mode. + #[default] + PlatformDefault, + /// Use subpixel (ClearType-style) text rendering. + Subpixel, + /// Use grayscale text rendering. + Grayscale, +} + +/// The options that can be configured for a file dialog prompt +#[derive(Clone, Debug)] +pub struct PathPromptOptions { + /// Should the prompt allow files to be selected? + pub files: bool, + /// Should the prompt allow directories to be selected? + pub directories: bool, + /// Should the prompt allow multiple files to be selected? + pub multiple: bool, + /// The prompt to show to a user when selecting a path + pub prompt: Option, +} + +/// What kind of prompt styling to show +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum PromptLevel { + /// A prompt that is shown when the user should be notified of something + Info, + + /// A prompt that is shown when the user needs to be warned of a potential problem + Warning, + + /// A prompt that is shown when a critical problem has occurred + Critical, +} + +/// Prompt Button +#[derive(Clone, Debug, PartialEq)] +pub enum PromptButton { + /// Ok button + Ok(SharedString), + /// Cancel button + Cancel(SharedString), + /// Other button + Other(SharedString), +} + +impl PromptButton { + /// Create a button with label + pub fn new(label: impl Into) -> Self { + PromptButton::Other(label.into()) + } + + /// Create an Ok button + pub fn ok(label: impl Into) -> Self { + PromptButton::Ok(label.into()) + } + + /// Create a Cancel button + pub fn cancel(label: impl Into) -> Self { + PromptButton::Cancel(label.into()) + } + + /// Returns true if this button is a cancel button. + #[allow(dead_code)] + pub fn is_cancel(&self) -> bool { + matches!(self, PromptButton::Cancel(_)) + } + + /// Returns the label of the button + pub fn label(&self) -> &SharedString { + match self { + PromptButton::Ok(label) => label, + PromptButton::Cancel(label) => label, + PromptButton::Other(label) => label, + } + } +} + +impl From<&str> for PromptButton { + fn from(value: &str) -> Self { + match value.to_lowercase().as_str() { + "ok" => PromptButton::Ok("OK".into()), + "cancel" => PromptButton::Cancel("Cancel".into()), + _ => PromptButton::Other(SharedString::from(value.to_owned())), + } + } +} + +/// The style of the cursor (pointer) +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum CursorStyle { + /// The default cursor + #[default] + Arrow, + + /// A text input cursor + /// corresponds to the CSS cursor value `text` + IBeam, + + /// A crosshair cursor + /// corresponds to the CSS cursor value `crosshair` + Crosshair, + + /// A closed hand cursor + /// corresponds to the CSS cursor value `grabbing` + ClosedHand, + + /// An open hand cursor + /// corresponds to the CSS cursor value `grab` + OpenHand, + + /// A pointing hand cursor + /// corresponds to the CSS cursor value `pointer` + PointingHand, + + /// A resize left cursor + /// corresponds to the CSS cursor value `w-resize` + ResizeLeft, + + /// A resize right cursor + /// corresponds to the CSS cursor value `e-resize` + ResizeRight, + + /// A resize cursor to the left and right + /// corresponds to the CSS cursor value `ew-resize` + ResizeLeftRight, + + /// A resize up cursor + /// corresponds to the CSS cursor value `n-resize` + ResizeUp, + + /// A resize down cursor + /// corresponds to the CSS cursor value `s-resize` + ResizeDown, + + /// A resize cursor directing up and down + /// corresponds to the CSS cursor value `ns-resize` + ResizeUpDown, + + /// A resize cursor directing up-left and down-right + /// corresponds to the CSS cursor value `nesw-resize` + ResizeUpLeftDownRight, + + /// A resize cursor directing up-right and down-left + /// corresponds to the CSS cursor value `nwse-resize` + ResizeUpRightDownLeft, + + /// A cursor indicating that the item/column can be resized horizontally. + /// corresponds to the CSS cursor value `col-resize` + ResizeColumn, + + /// A cursor indicating that the item/row can be resized vertically. + /// corresponds to the CSS cursor value `row-resize` + ResizeRow, + + /// A text input cursor for vertical layout + /// corresponds to the CSS cursor value `vertical-text` + IBeamCursorForVerticalLayout, + + /// A cursor indicating that the operation is not allowed + /// corresponds to the CSS cursor value `not-allowed` + OperationNotAllowed, + + /// A cursor indicating that the operation will result in a link + /// corresponds to the CSS cursor value `alias` + DragLink, + + /// A cursor indicating that the operation will result in a copy + /// corresponds to the CSS cursor value `copy` + DragCopy, + + /// A cursor indicating that the operation will result in a context menu + /// corresponds to the CSS cursor value `context-menu` + ContextualMenu, +} + +/// A clipboard item that should be copied to the clipboard +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ClipboardItem { + /// The entries in this clipboard item. + pub entries: Vec, +} + +/// An error produced by [`Platform::read_from_clipboard_async`]. +/// +/// Callers surface these failures to users, so the variants distinguish +/// conditions that call for different user-facing guidance. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ClipboardReadError { + /// The platform clipboard is not available in this context, e.g. the + /// browser does not expose the async clipboard API or the page is not a + /// secure context. + Unavailable, + /// The platform refused access, e.g. the user declined the browser's + /// clipboard permission prompt or paste confirmation. + Denied(String), + /// The clipboard contents could not be converted into a + /// [`ClipboardItem`]. + UnsupportedContent, +} + +impl std::fmt::Display for ClipboardReadError { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Unavailable => formatter.write_str("the clipboard is unavailable"), + Self::Denied(message) => { + write!(formatter, "clipboard access was denied: {message}") + } + Self::UnsupportedContent => { + formatter.write_str("the clipboard contents are unsupported") + } + } + } +} + +impl std::error::Error for ClipboardReadError {} + +/// Either a ClipboardString or a ClipboardImage +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ClipboardEntry { + /// A string entry + String(ClipboardString), + /// An image entry + Image(Image), + /// A file entry + ExternalPaths(crate::ExternalPaths), +} + +impl ClipboardItem { + /// Create a new ClipboardItem::String with no associated metadata + pub fn new_string(text: String) -> Self { + Self { + entries: vec![ClipboardEntry::String(ClipboardString::new(text))], + } + } + + /// Create a new ClipboardItem::String with the given text and associated metadata + pub fn new_string_with_metadata(text: String, metadata: String) -> Self { + Self { + entries: vec![ClipboardEntry::String(ClipboardString { + text, + metadata: Some(metadata), + })], + } + } + + /// Create a new ClipboardItem::String with the given text and associated metadata + pub fn new_string_with_json_metadata(text: String, metadata: T) -> Self { + Self { + entries: vec![ClipboardEntry::String( + ClipboardString::new(text).with_json_metadata(metadata), + )], + } + } + + /// Create a new ClipboardItem::Image with the given image with no associated metadata + pub fn new_image(image: &Image) -> Self { + Self { + entries: vec![ClipboardEntry::Image(image.clone())], + } + } + + /// Concatenates together all the ClipboardString entries in the item. + /// Returns None if there were no ClipboardString entries. + pub fn text(&self) -> Option { + let mut answer = String::new(); + + for entry in self.entries.iter() { + if let ClipboardEntry::String(ClipboardString { text, metadata: _ }) = entry { + answer.push_str(text); + } + } + + if answer.is_empty() { + for entry in self.entries.iter() { + if let ClipboardEntry::ExternalPaths(paths) = entry { + for path in &paths.0 { + use std::fmt::Write as _; + _ = write!(answer, "{}", path.display()); + } + } + } + } + + if !answer.is_empty() { + Some(answer) + } else { + None + } + } + + /// If this item is one ClipboardEntry::String, returns its metadata. + #[cfg_attr(not(target_os = "windows"), allow(dead_code))] + pub fn metadata(&self) -> Option<&String> { + match self.entries().first() { + Some(ClipboardEntry::String(clipboard_string)) if self.entries.len() == 1 => { + clipboard_string.metadata.as_ref() + } + _ => None, + } + } + + /// Get the item's entries + pub fn entries(&self) -> &[ClipboardEntry] { + &self.entries + } + + /// Get owned versions of the item's entries + pub fn into_entries(self) -> impl Iterator { + self.entries.into_iter() + } +} + +impl From for ClipboardEntry { + fn from(value: ClipboardString) -> Self { + Self::String(value) + } +} + +impl From for ClipboardEntry { + fn from(value: String) -> Self { + Self::from(ClipboardString::from(value)) + } +} + +impl From for ClipboardEntry { + fn from(value: Image) -> Self { + Self::Image(value) + } +} + +impl From for ClipboardItem { + fn from(value: ClipboardEntry) -> Self { + Self { + entries: vec![value], + } + } +} + +impl From for ClipboardItem { + fn from(value: String) -> Self { + Self::from(ClipboardEntry::from(value)) + } +} + +impl From for ClipboardItem { + fn from(value: Image) -> Self { + Self::from(ClipboardEntry::from(value)) + } +} + +/// One of the editor's supported image formats (e.g. PNG, JPEG) - used when dealing with images in the clipboard +#[derive(Clone, Copy, Debug, Eq, PartialEq, EnumIter, Hash)] +pub enum ImageFormat { + // Sorted from most to least likely to be pasted into an editor, + // which matters when we iterate through them trying to see if + // clipboard content matches them. + /// .png + Png, + /// .jpeg or .jpg + Jpeg, + /// .webp + Webp, + /// .gif + Gif, + /// .svg + Svg, + /// .bmp + Bmp, + /// .tif or .tiff + Tiff, + /// .ico + Ico, + /// Netpbm image formats (.pbm, .ppm, .pgm). + Pnm, +} + +impl ImageFormat { + /// Returns the mime type for the ImageFormat + pub const fn mime_type(self) -> &'static str { + match self { + ImageFormat::Png => "image/png", + ImageFormat::Jpeg => "image/jpeg", + ImageFormat::Webp => "image/webp", + ImageFormat::Gif => "image/gif", + ImageFormat::Svg => "image/svg+xml", + ImageFormat::Bmp => "image/bmp", + ImageFormat::Tiff => "image/tiff", + ImageFormat::Ico => "image/ico", + ImageFormat::Pnm => "image/x-portable-anymap", + } + } + + /// Returns the file extension for this image format (without leading dot). + pub const fn extension(self) -> &'static str { + match self { + ImageFormat::Png => "png", + ImageFormat::Jpeg => "jpg", + ImageFormat::Webp => "webp", + ImageFormat::Gif => "gif", + ImageFormat::Svg => "svg", + ImageFormat::Bmp => "bmp", + ImageFormat::Tiff => "tiff", + ImageFormat::Ico => "ico", + ImageFormat::Pnm => "pnm", + } + } + + /// Returns the ImageFormat for the given mime type, including known aliases. + pub fn from_mime_type(mime_type: &str) -> Option { + use strum::IntoEnumIterator; + Self::iter() + .find(|format| format.mime_type() == mime_type) + .or_else(|| Self::from_mime_type_alias(mime_type)) + } + + /// Non-canonical mime types that some producers use in the wild. + /// Unlike `mime_type()` which returns the single canonical form, + /// these are legacy or shortened variants we still need to recognize. + fn from_mime_type_alias(mime_type: &str) -> Option { + match mime_type { + "image/jpg" => Some(Self::Jpeg), + "image/tif" => Some(Self::Tiff), + _ => None, + } + } +} + +/// An image, with a format and certain bytes +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Image { + /// The image format the bytes represent (e.g. PNG) + pub format: ImageFormat, + /// The raw image bytes + pub bytes: Vec, + /// The unique ID for the image + pub id: u64, +} + +pub(crate) fn decode_static_image( + bytes: &[u8], + format: image::ImageFormat, +) -> Result> { + let decoder = image::ImageReader::with_format(Cursor::new(bytes), format) + .into_decoder() + .context("creating image decoder")?; + decode_static_image_from_decoder(decoder) +} + +pub(crate) fn decode_static_image_from_decoder( + mut decoder: impl image::ImageDecoder, +) -> Result> { + let orientation = decoder + .orientation() + .context("reading decoder's orientation")?; + let mut image = DynamicImage::from_decoder(decoder).context("decoding image")?; + image.apply_orientation(orientation); + + let mut data = image.into_rgba8(); + for pixel in data.chunks_exact_mut(4) { + pixel.swap(0, 2); + } + + Ok(SmallVec::from_elem(Frame::new(data), 1)) +} + +impl Hash for Image { + fn hash(&self, state: &mut H) { + state.write_u64(self.id); + } +} + +impl Image { + /// An empty image containing no data + pub fn empty() -> Self { + Self::from_bytes(ImageFormat::Png, Vec::new()) + } + + /// Create an image from a format and bytes + pub fn from_bytes(format: ImageFormat, bytes: Vec) -> Self { + Self { + id: hash(&bytes), + format, + bytes, + } + } + + /// Get this image's ID + pub fn id(&self) -> u64 { + self.id + } + + /// Use the GPUI `use_asset` API to make this image renderable + pub fn use_render_image( + self: Arc, + window: &mut Window, + cx: &mut App, + ) -> Option> { + ImageSource::Image(self) + .use_data(None, window, cx) + .and_then(|result| result.ok()) + } + + /// Use the GPUI `get_asset` API to make this image renderable + pub fn get_render_image( + self: Arc, + window: &mut Window, + cx: &mut App, + ) -> Option> { + ImageSource::Image(self) + .get_data(None, window, cx) + .and_then(|result| result.ok()) + } + + /// Use the GPUI `remove_asset` API to drop this image, if possible. + pub fn remove_asset(self: Arc, cx: &mut App) { + ImageSource::Image(self).remove_asset(cx); + } + + /// Check whether this image is present in GPUI's asset cache (loading or + /// loaded), without fetching it. + #[cfg(any(test, feature = "test-support"))] + pub fn is_asset_cached(self: &Arc, cx: &App) -> bool { + ImageSource::Image(self.clone()).is_asset_cached(cx) + } + + /// Convert the clipboard image to an `ImageData` object. + pub fn to_image_data(&self, svg_renderer: SvgRenderer) -> Result> { + let frames = match self.format { + ImageFormat::Gif => { + let decoder = GifDecoder::new(Cursor::new(&self.bytes))?; + let mut frames = SmallVec::new(); + + for frame in decoder.into_frames() { + match frame { + Ok(mut frame) => { + // Convert from RGBA to BGRA. + for pixel in frame.buffer_mut().chunks_exact_mut(4) { + pixel.swap(0, 2); + } + frames.push(frame); + } + Err(err) => { + log::debug!("Skipping GIF frame due to decode error: {err}"); + } + } + } + + if frames.is_empty() { + anyhow::bail!("GIF could not be decoded: all frames failed"); + } + + frames + } + ImageFormat::Png => decode_static_image(&self.bytes, image::ImageFormat::Png)?, + ImageFormat::Jpeg => decode_static_image(&self.bytes, image::ImageFormat::Jpeg)?, + ImageFormat::Webp => decode_static_image(&self.bytes, image::ImageFormat::WebP)?, + ImageFormat::Bmp => decode_static_image(&self.bytes, image::ImageFormat::Bmp)?, + ImageFormat::Tiff => decode_static_image(&self.bytes, image::ImageFormat::Tiff)?, + ImageFormat::Ico => decode_static_image(&self.bytes, image::ImageFormat::Ico)?, + ImageFormat::Svg => { + return svg_renderer + .render_single_frame(&self.bytes, 1.0) + .map_err(Into::into); + } + ImageFormat::Pnm => decode_static_image(&self.bytes, image::ImageFormat::Pnm)?, + }; + + Ok(Arc::new(RenderImage::new(frames))) + } + + /// Get the format of the clipboard image + pub fn format(&self) -> ImageFormat { + self.format + } + + /// Get the raw bytes of the clipboard image + pub fn bytes(&self) -> &[u8] { + self.bytes.as_slice() + } +} + +/// A clipboard item that should be copied to the clipboard +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ClipboardString { + /// The text content. + pub text: String, + /// Optional metadata associated with this clipboard string. + pub metadata: Option, +} + +impl ClipboardString { + /// Create a new clipboard string with the given text + pub fn new(text: String) -> Self { + Self { + text, + metadata: None, + } + } + + /// Return a new clipboard item with the metadata replaced by the given metadata, + /// after serializing it as JSON. + pub fn with_json_metadata(mut self, metadata: T) -> Self { + self.metadata = Some(serde_json::to_string(&metadata).unwrap()); + self + } + + /// Get the text of the clipboard string + pub fn text(&self) -> &String { + &self.text + } + + /// Get the owned text of the clipboard string + pub fn into_text(self) -> String { + self.text + } + + /// Get the metadata of the clipboard string, formatted as JSON + pub fn metadata_json(&self) -> Option + where + T: for<'a> Deserialize<'a>, + { + self.metadata + .as_ref() + .and_then(|m| serde_json::from_str(m).ok()) + } + + #[cfg_attr(any(target_os = "linux", target_os = "freebsd"), allow(dead_code))] + /// Compute a hash of the given text for clipboard change detection. + pub fn text_hash(text: &str) -> u64 { + let mut hasher = SeaHasher::new(); + text.hash(&mut hasher); + hasher.finish() + } +} + +impl From for ClipboardString { + fn from(value: String) -> Self { + Self { + text: value, + metadata: None, + } + } +} + +#[cfg(test)] +mod image_tests { + use super::*; + use std::sync::Arc; + + #[test] + fn test_image_to_image_data_applies_exif_orientation() { + let image = Image::from_bytes( + ImageFormat::Jpeg, + include_bytes!("../examples/image/exif-orientation-rotate-180.jpg").to_vec(), + ); + + let render_image = image.to_image_data(SvgRenderer::new(Arc::new(()))).unwrap(); + + assert_eq!(render_image.size(0), size(16.into(), 32.into())); + + let bytes = render_image.as_bytes(0).unwrap(); + assert_eq!(&bytes[..4], &[255, 255, 255, 255]); + assert_eq!(&bytes[(16 * 32 - 1) * 4..], &[0, 0, 0, 255]); + } + + #[test] + fn test_svg_image_to_image_data_converts_to_bgra() { + let image = Image::from_bytes( + ImageFormat::Svg, + br##" + +"## + .to_vec(), + ); + + let render_image = image.to_image_data(SvgRenderer::new(Arc::new(()))).unwrap(); + let bytes = render_image.as_bytes(0).unwrap(); + + for pixel in bytes.chunks_exact(4) { + assert_eq!(pixel, &[0xF8, 0xBD, 0x38, 0xFF]); + } + } +} + +#[cfg(test)] +mod atlas_tests { + use super::*; + + const TILE_SIZE: Size = Size { + width: DevicePixels(1), + height: DevicePixels(1), + }; + + #[derive(Default)] + struct RecordingAtlasBackend { + insert_calls: u32, + fail_next_insert: bool, + removed_tiles: Vec, + } + + impl AtlasBackend for RecordingAtlasBackend { + fn insert( + &mut self, + kind: AtlasTextureKind, + size: Size, + _bytes: &[u8], + ) -> Result { + self.insert_calls += 1; + if std::mem::take(&mut self.fail_next_insert) { + anyhow::bail!("backend failed"); + } + Ok(AtlasTile { + texture_id: AtlasTextureId { index: 0, kind }, + tile_id: TileId(self.insert_calls), + padding: 0, + bounds: Bounds { + origin: Point::default(), + size, + }, + }) + } + + fn remove(&mut self, tile: AtlasTile) { + self.removed_tiles.push(tile); + } + } + + fn image_key(image_id: usize) -> AtlasKey { + AtlasKey::Image(RenderImageParams { + image_id: crate::ImageId(image_id), + frame_index: 0, + }) + } + + fn build_tile() -> Result, Cow<'static, [u8]>)>> { + Ok(Some((TILE_SIZE, Cow::Borrowed(&[0, 0, 0, 255])))) + } + + #[test] + fn only_successful_inserts_are_cached() -> Result<()> { + let mut state = AtlasState::new(RecordingAtlasBackend::default()); + let key = image_key(1); + + assert_eq!( + state.get_or_insert_with(key.clone(), &mut || Ok(None))?, + None + ); + state + .get_or_insert_with(key.clone(), &mut || anyhow::bail!("builder failed")) + .expect_err("builder error should propagate"); + assert!(!state.contains(&key)); + assert_eq!(state.backend.insert_calls, 0); + + state.backend.fail_next_insert = true; + state + .get_or_insert_with(key.clone(), &mut build_tile) + .expect_err("backend error should propagate"); + assert!(!state.contains(&key)); + assert_eq!(state.backend.insert_calls, 1); + + let tile = state + .get_or_insert_with(key.clone(), &mut build_tile)? + .context("builder should produce a tile")?; + assert_eq!(tile.texture_id.kind, key.texture_kind()); + assert_eq!( + state.get_or_insert_with(key.clone(), &mut || { + anyhow::bail!("cache hit must not call the builder") + })?, + Some(tile) + ); + assert!(state.contains(&key)); + assert_eq!(state.backend.insert_calls, 2); + Ok(()) + } + + #[test] + fn remove_and_clear_invalidate_keys() -> Result<()> { + let mut state = AtlasState::new(RecordingAtlasBackend::default()); + let key = image_key(1); + let other_key = image_key(2); + let tile = state + .get_or_insert_with(key.clone(), &mut build_tile)? + .context("builder should produce a tile")?; + state + .get_or_insert_with(other_key.clone(), &mut build_tile)? + .context("builder should produce another tile")?; + + state.remove(&key); + state.remove(&key); + assert!(!state.contains(&key)); + assert!(state.contains(&other_key)); + assert_eq!(state.backend.removed_tiles, vec![tile]); + + let mut reset_calls = 0; + state.clear(|_| reset_calls += 1); + assert_eq!(reset_calls, 1); + assert!(!state.contains(&other_key)); + assert_eq!(state.backend.removed_tiles, vec![tile]); + Ok(()) + } +} + +#[cfg(test)] +mod frame_signal_tests { + use super::*; + + #[cfg(feature = "profiler")] + #[test] + fn coalesced_signals_retain_the_earliest_until_drained() { + for (first_source, later_source) in [ + ( + FrameRequestSource::NativeCallback, + FrameRequestSource::LocalSchedule, + ), + ( + FrameRequestSource::LocalSchedule, + FrameRequestSource::NativeCallback, + ), + ] { + let signal = PlatformFrameSignal::new(); + let first = + PlatformFrameSignal::capture(Instant::now).expect("profiling captures requests"); + assert_eq!(signal.take(), None); + signal.record(first + Duration::from_millis(16), later_source); + signal.record(first, first_source); + signal.record(first + Duration::from_millis(32), later_source); + assert_eq!(signal.take(), Some((first, first_source))); + assert_eq!(signal.take(), None); + let next = first + Duration::from_millis(48); + signal.record(next, later_source); + assert_eq!(signal.take(), Some((next, later_source))); + } + } + + #[cfg(not(feature = "profiler"))] + #[test] + fn disabled_profiling_does_not_capture_or_store_timestamps() { + let captured = PlatformFrameSignal::capture(|| { + panic!("profiler-disabled builds must not evaluate the capture closure"); + }); + assert_eq!(captured, None); + let signal = PlatformFrameSignal::new(); + signal.record(Instant::now(), FrameRequestSource::LocalSchedule); + assert_eq!(signal.take(), None); + } +} + +#[cfg(all(test, any(target_os = "linux", target_os = "freebsd")))] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn test_window_button_layout_parse_standard() { + let layout = WindowButtonLayout::parse("close,minimize:maximize").unwrap(); + assert_eq!( + layout.left, + [ + Some(WindowButton::Close), + Some(WindowButton::Minimize), + None + ] + ); + assert_eq!(layout.right, [Some(WindowButton::Maximize), None, None]); + } + + #[test] + fn test_window_button_layout_parse_right_only() { + let layout = WindowButtonLayout::parse("minimize,maximize,close").unwrap(); + assert_eq!(layout.left, [None, None, None]); + assert_eq!( + layout.right, + [ + Some(WindowButton::Minimize), + Some(WindowButton::Maximize), + Some(WindowButton::Close) + ] + ); + } + + #[test] + fn test_window_button_layout_parse_left_only() { + let layout = WindowButtonLayout::parse("close,minimize,maximize:").unwrap(); + assert_eq!( + layout.left, + [ + Some(WindowButton::Close), + Some(WindowButton::Minimize), + Some(WindowButton::Maximize) + ] + ); + assert_eq!(layout.right, [None, None, None]); + } + + #[test] + fn test_window_button_layout_parse_with_whitespace() { + let layout = WindowButtonLayout::parse(" close , minimize : maximize ").unwrap(); + assert_eq!( + layout.left, + [ + Some(WindowButton::Close), + Some(WindowButton::Minimize), + None + ] + ); + assert_eq!(layout.right, [Some(WindowButton::Maximize), None, None]); + } + + #[test] + fn test_window_button_layout_parse_empty() { + let layout = WindowButtonLayout::parse("").unwrap(); + assert_eq!(layout.left, [None, None, None]); + assert_eq!(layout.right, [None, None, None]); + } + + #[test] + fn test_window_button_layout_parse_intentionally_empty() { + let layout = WindowButtonLayout::parse(":").unwrap(); + assert_eq!(layout.left, [None, None, None]); + assert_eq!(layout.right, [None, None, None]); + } + + #[test] + fn test_window_button_layout_parse_invalid_buttons() { + let layout = WindowButtonLayout::parse("close,invalid,minimize:maximize,foo").unwrap(); + assert_eq!( + layout.left, + [ + Some(WindowButton::Close), + Some(WindowButton::Minimize), + None + ] + ); + assert_eq!(layout.right, [Some(WindowButton::Maximize), None, None]); + } + + #[test] + fn test_window_button_layout_parse_deduplicates_same_side_buttons() { + let layout = WindowButtonLayout::parse("close,close,minimize").unwrap(); + assert_eq!( + layout.right, + [ + Some(WindowButton::Close), + Some(WindowButton::Minimize), + None + ] + ); + assert_eq!(layout.format(), ":close,minimize"); + } + + #[test] + fn test_window_button_layout_parse_deduplicates_buttons_across_sides() { + let layout = WindowButtonLayout::parse("close:maximize,close,minimize").unwrap(); + assert_eq!(layout.left, [Some(WindowButton::Close), None, None]); + assert_eq!( + layout.right, + [ + Some(WindowButton::Maximize), + Some(WindowButton::Minimize), + None + ] + ); + + let button_ids: Vec<_> = layout + .left + .iter() + .chain(layout.right.iter()) + .flatten() + .map(WindowButton::id) + .collect(); + let unique_button_ids = button_ids.iter().copied().collect::>(); + assert_eq!(unique_button_ids.len(), button_ids.len()); + assert_eq!(layout.format(), "close:maximize,minimize"); + } + + #[test] + fn test_window_button_layout_parse_gnome_style() { + let layout = WindowButtonLayout::parse("close").unwrap(); + assert_eq!(layout.left, [None, None, None]); + assert_eq!(layout.right, [Some(WindowButton::Close), None, None]); + } + + #[test] + fn test_window_button_layout_parse_elementary_style() { + let layout = WindowButtonLayout::parse("close:maximize").unwrap(); + assert_eq!(layout.left, [Some(WindowButton::Close), None, None]); + assert_eq!(layout.right, [Some(WindowButton::Maximize), None, None]); + } + + #[test] + fn test_window_button_layout_round_trip() { + let cases = [ + "close:minimize,maximize", + "minimize,maximize,close:", + ":close", + "close:", + "close:maximize", + ":", + ]; + + for case in cases { + let layout = WindowButtonLayout::parse(case).unwrap(); + assert_eq!(layout.format(), case, "Round-trip failed for: {}", case); + } + } + + #[test] + fn test_window_button_layout_linux_default() { + let layout = WindowButtonLayout::linux_default(); + assert_eq!(layout.left, [None, None, None]); + assert_eq!( + layout.right, + [ + Some(WindowButton::Minimize), + Some(WindowButton::Maximize), + Some(WindowButton::Close) + ] + ); + + let round_tripped = WindowButtonLayout::parse(&layout.format()).unwrap(); + assert_eq!(round_tripped, layout); + } + + #[test] + fn test_window_button_layout_parse_all_invalid() { + assert!(WindowButtonLayout::parse("asdfghjkl").is_err()); + } +} diff --git a/vendor/gpui-pre/src/platform/app_menu.rs b/vendor/gpui-pre/src/platform/app_menu.rs new file mode 100644 index 00000000..27c20c00 --- /dev/null +++ b/vendor/gpui-pre/src/platform/app_menu.rs @@ -0,0 +1,426 @@ +use crate::{Action, App, Platform, SharedString}; + +/// A menu of the application, either a main menu or a submenu +pub struct Menu { + /// The name of the menu + pub name: SharedString, + + /// The items in the menu + pub items: Vec, + + /// Whether this menu is disabled + pub disabled: bool, +} + +impl Menu { + /// Create a new Menu with the given name + pub fn new(name: impl Into) -> Self { + Self { + name: name.into(), + items: vec![], + disabled: false, + } + } + + /// Set items to be in this menu + pub fn items(mut self, items: impl IntoIterator) -> Self { + self.items = items.into_iter().collect(); + self + } + + /// Set whether this menu is disabled + pub fn disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } + + /// Create an OwnedMenu from this Menu + pub fn owned(self) -> OwnedMenu { + OwnedMenu { + name: self.name.to_string().into(), + items: self.items.into_iter().map(|item| item.owned()).collect(), + disabled: self.disabled, + } + } +} + +/// OS menus are menus that are recognized by the operating system +/// This allows the operating system to provide specialized items for +/// these menus +pub struct OsMenu { + /// The name of the menu + pub name: SharedString, + + /// The type of menu + pub menu_type: SystemMenuType, +} + +impl OsMenu { + /// Create an OwnedOsMenu from this OsMenu + pub fn owned(self) -> OwnedOsMenu { + OwnedOsMenu { + name: self.name.to_string().into(), + menu_type: self.menu_type, + } + } +} + +/// The type of system menu +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum SystemMenuType { + /// The 'Services' menu in the Application menu on macOS + Services, +} + +/// The different kinds of items that can be in a menu +pub enum MenuItem { + /// A separator between items + Separator, + + /// A submenu + Submenu(Menu), + + /// A menu, managed by the system (for example, the Services menu on macOS) + SystemMenu(OsMenu), + + /// An action that can be performed + Action { + /// The name of this menu item + name: SharedString, + + /// The action to perform when this menu item is selected + action: Box, + + /// The OS Action that corresponds to this action, if any + /// See [`OsAction`] for more information + os_action: Option, + + /// Whether this action is checked + checked: bool, + + /// Whether this action is disabled + disabled: bool, + }, +} + +impl MenuItem { + /// Creates a new menu item that is a separator + pub fn separator() -> Self { + Self::Separator + } + + /// Creates a new menu item that is a submenu + pub fn submenu(menu: Menu) -> Self { + Self::Submenu(menu) + } + + /// Creates a new submenu that is populated by the OS + pub fn os_submenu(name: impl Into, menu_type: SystemMenuType) -> Self { + Self::SystemMenu(OsMenu { + name: name.into(), + menu_type, + }) + } + + /// Creates a new menu item that invokes an action + pub fn action(name: impl Into, action: impl Action) -> Self { + Self::Action { + name: name.into(), + action: Box::new(action), + os_action: None, + checked: false, + disabled: false, + } + } + + /// Creates a new menu item that invokes an action and has an OS action + pub fn os_action( + name: impl Into, + action: impl Action, + os_action: OsAction, + ) -> Self { + Self::Action { + name: name.into(), + action: Box::new(action), + os_action: Some(os_action), + checked: false, + disabled: false, + } + } + + /// Create an OwnedMenuItem from this MenuItem + pub fn owned(self) -> OwnedMenuItem { + match self { + MenuItem::Separator => OwnedMenuItem::Separator, + MenuItem::Submenu(submenu) => OwnedMenuItem::Submenu(submenu.owned()), + MenuItem::Action { + name, + action, + os_action, + checked, + disabled, + } => OwnedMenuItem::Action { + name: name.into(), + action, + os_action, + checked, + disabled, + }, + MenuItem::SystemMenu(os_menu) => OwnedMenuItem::SystemMenu(os_menu.owned()), + } + } + + /// Set whether this menu item is checked + /// + /// Only for [`MenuItem::Action`], otherwise, will be ignored + pub fn checked(mut self, checked: bool) -> Self { + match &mut self { + MenuItem::Action { checked: old, .. } => { + *old = checked; + } + _ => {} + } + self + } + + /// Returns whether this menu item is checked + /// + /// Only for [`MenuItem::Action`], otherwise, returns false + #[inline] + pub fn is_checked(&self) -> bool { + match self { + MenuItem::Action { checked, .. } => *checked, + _ => false, + } + } + + /// Set whether this menu item is disabled + pub fn disabled(mut self, disabled: bool) -> Self { + match &mut self { + MenuItem::Action { disabled: old, .. } => { + *old = disabled; + } + MenuItem::Submenu(submenu) => { + submenu.disabled = disabled; + } + _ => {} + } + self + } + + /// Returns whether this menu item is disabled + /// + /// Only for [`MenuItem::Action`] and [`MenuItem::Submenu`], otherwise, returns false + #[inline] + pub fn is_disabled(&self) -> bool { + match self { + MenuItem::Action { disabled, .. } => *disabled, + MenuItem::Submenu(submenu) => submenu.disabled, + _ => false, + } + } +} + +/// OS menus are menus that are recognized by the operating system +/// This allows the operating system to provide specialized items for +/// these menus +#[derive(Clone)] +pub struct OwnedOsMenu { + /// The name of the menu + pub name: SharedString, + + /// The type of menu + pub menu_type: SystemMenuType, +} + +/// A menu of the application, either a main menu or a submenu +#[derive(Clone)] +pub struct OwnedMenu { + /// The name of the menu + pub name: SharedString, + + /// The items in the menu + pub items: Vec, + + /// Whether this menu is disabled + pub disabled: bool, +} + +/// The different kinds of items that can be in a menu +pub enum OwnedMenuItem { + /// A separator between items + Separator, + + /// A submenu + Submenu(OwnedMenu), + + /// A menu, managed by the system (for example, the Services menu on macOS) + SystemMenu(OwnedOsMenu), + + /// An action that can be performed + Action { + /// The name of this menu item + name: String, + + /// The action to perform when this menu item is selected + action: Box, + + /// The OS Action that corresponds to this action, if any + /// See [`OsAction`] for more information + os_action: Option, + + /// Whether this action is checked + checked: bool, + + /// Whether this action is disabled + disabled: bool, + }, +} + +impl Clone for OwnedMenuItem { + fn clone(&self) -> Self { + match self { + OwnedMenuItem::Separator => OwnedMenuItem::Separator, + OwnedMenuItem::Submenu(submenu) => OwnedMenuItem::Submenu(submenu.clone()), + OwnedMenuItem::Action { + name, + action, + os_action, + checked, + disabled, + } => OwnedMenuItem::Action { + name: name.clone(), + action: action.boxed_clone(), + os_action: *os_action, + checked: *checked, + disabled: *disabled, + }, + OwnedMenuItem::SystemMenu(os_menu) => OwnedMenuItem::SystemMenu(os_menu.clone()), + } + } +} + +// TODO: As part of the global selections refactor, these should +// be moved to GPUI-provided actions that make this association +// without leaking the platform details to GPUI users + +/// OS actions are actions that are recognized by the operating system +/// This allows the operating system to provide specialized behavior for +/// these actions +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum OsAction { + /// The 'cut' action + Cut, + + /// The 'copy' action + Copy, + + /// The 'paste' action + Paste, + + /// The 'select all' action + SelectAll, + + /// The 'undo' action + Undo, + + /// The 'redo' action + Redo, +} + +pub(crate) fn init_app_menus(platform: &dyn Platform, cx: &App) { + platform.on_will_open_app_menu(Box::new({ + let cx = cx.to_async(); + move || { + if let Some(app) = cx.app.upgrade() { + app.borrow_mut().update(|cx| cx.clear_pending_keystrokes()); + } + } + })); + + platform.on_validate_app_menu_command(Box::new({ + let cx = cx.to_async(); + move |action| { + cx.app + .upgrade() + .map(|app| app.borrow_mut().update(|cx| cx.is_action_available(action))) + .unwrap_or(false) + } + })); + + platform.on_app_menu_action(Box::new({ + let cx = cx.to_async(); + move |action| { + if let Some(app) = cx.app.upgrade() { + app.borrow_mut().update(|cx| cx.dispatch_action(action)); + } + } + })); +} + +#[cfg(test)] +mod tests { + use crate::Menu; + + #[test] + fn test_menu() { + let menu = Menu::new("App") + .items(vec![ + crate::MenuItem::action("Action 1", gpui::NoAction), + crate::MenuItem::separator(), + ]) + .disabled(true); + + assert_eq!(menu.name.as_ref(), "App"); + assert_eq!(menu.items.len(), 2); + assert!(menu.disabled); + } + + #[test] + fn test_menu_item_builder() { + use super::MenuItem; + + let item = MenuItem::action("Test Action", gpui::NoAction); + assert_eq!( + match &item { + MenuItem::Action { name, .. } => name.as_ref(), + _ => unreachable!(), + }, + "Test Action" + ); + assert!(matches!( + item, + MenuItem::Action { + checked: false, + disabled: false, + .. + } + )); + + assert!( + MenuItem::action("Test Action", gpui::NoAction) + .checked(true) + .is_checked() + ); + assert!( + MenuItem::action("Test Action", gpui::NoAction) + .disabled(true) + .is_disabled() + ); + + let submenu = MenuItem::submenu(super::Menu { + name: "Submenu".into(), + items: vec![], + disabled: true, + }); + assert_eq!( + match &submenu { + MenuItem::Submenu(menu) => menu.name.as_ref(), + _ => unreachable!(), + }, + "Submenu" + ); + assert!(!submenu.is_checked()); + assert!(submenu.is_disabled()); + } +} diff --git a/vendor/gpui-pre/src/platform/keyboard.rs b/vendor/gpui-pre/src/platform/keyboard.rs new file mode 100644 index 00000000..10b86202 --- /dev/null +++ b/vendor/gpui-pre/src/platform/keyboard.rs @@ -0,0 +1,41 @@ +use collections::HashMap; + +use crate::{KeybindingKeystroke, Keystroke}; + +/// A trait for platform-specific keyboard layouts +pub trait PlatformKeyboardLayout { + /// Get the keyboard layout ID, which should be unique to the layout + fn id(&self) -> &str; + /// Get the keyboard layout display name + fn name(&self) -> &str; +} + +/// A trait for platform-specific keyboard mappings +pub trait PlatformKeyboardMapper { + /// Map a key equivalent to its platform-specific representation + fn map_key_equivalent( + &self, + keystroke: Keystroke, + use_key_equivalents: bool, + ) -> KeybindingKeystroke; + /// Get the key equivalents for the current keyboard layout, + /// only used on macOS + fn get_key_equivalents(&self) -> Option<&HashMap>; +} + +/// A dummy implementation of the platform keyboard mapper +pub struct DummyKeyboardMapper; + +impl PlatformKeyboardMapper for DummyKeyboardMapper { + fn map_key_equivalent( + &self, + keystroke: Keystroke, + _use_key_equivalents: bool, + ) -> KeybindingKeystroke { + KeybindingKeystroke::from_keystroke(keystroke) + } + + fn get_key_equivalents(&self) -> Option<&HashMap> { + None + } +} diff --git a/vendor/gpui-pre/src/platform/keystroke.rs b/vendor/gpui-pre/src/platform/keystroke.rs new file mode 100644 index 00000000..c24433d0 --- /dev/null +++ b/vendor/gpui-pre/src/platform/keystroke.rs @@ -0,0 +1,782 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::{ + error::Error, + fmt::{Display, Write}, +}; + +use crate::PlatformKeyboardMapper; + +/// This is a helper trait so that we can simplify the implementation of some functions +pub trait AsKeystroke { + /// Returns the GPUI representation of the keystroke. + fn as_keystroke(&self) -> &Keystroke; +} + +/// A keystroke and associated metadata generated by the platform +#[derive(Clone, Debug, Eq, PartialEq, Default, Deserialize, Hash)] +pub struct Keystroke { + /// the state of the modifier keys at the time the keystroke was generated + pub modifiers: Modifiers, + + /// key is the character printed on the key that was pressed + /// e.g. for option-s, key is "s" + /// On layouts that do not have ascii keys (e.g. Thai) + /// this will be the ASCII-equivalent character (q instead of ๆ), + /// and the typed character will be present in key_char. + pub key: String, + + /// key_char is the character that could have been typed when + /// this binding was pressed. + /// e.g. for s this is "s", for option-s "ß", and cmd-s None + pub key_char: Option, +} + +/// Represents a keystroke that can be used in keybindings and displayed to the user. +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct KeybindingKeystroke { + /// The GPUI representation of the keystroke. + inner: Keystroke, + /// The modifiers to display. + #[cfg(target_os = "windows")] + display_modifiers: Modifiers, + /// The key to display. + #[cfg(target_os = "windows")] + display_key: String, +} + +/// Error type for `Keystroke::parse`. This is used instead of `anyhow::Error` so that Zed can use +/// markdown to display it. +#[derive(Debug)] +pub struct InvalidKeystrokeError { + /// The invalid keystroke. + pub keystroke: String, +} + +impl Error for InvalidKeystrokeError {} + +impl Display for InvalidKeystrokeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Invalid keystroke \"{}\". {}", + self.keystroke, KEYSTROKE_PARSE_EXPECTED_MESSAGE + ) + } +} + +/// Sentence explaining what keystroke parser expects, starting with "Expected ..." +pub const KEYSTROKE_PARSE_EXPECTED_MESSAGE: &str = "Expected a sequence of modifiers \ + (`ctrl`, `alt`, `shift`, `fn`, `cmd`, `super`, or `win`) \ + followed by a key, separated by `-`."; + +impl Keystroke { + /// When matching a key we cannot know whether the user intended to type + /// the key_char or the key itself. On some non-US keyboards keys we use in our + /// bindings are behind option (for example `$` is typed `alt-ç` on a Czech keyboard), + /// and on some keyboards the IME handler converts a sequence of keys into a + /// specific character (for example `"` is typed as `" space` on a brazilian keyboard). + /// + /// This method assumes that `self` was typed and `target' is in the keymap, and checks + /// both possibilities for self against the target. + pub fn should_match(&self, target: &KeybindingKeystroke) -> bool { + #[cfg(not(target_os = "windows"))] + if let Some(key_char) = self + .key_char + .as_ref() + .filter(|key_char| key_char != &&self.key) + { + let ime_modifiers = Modifiers { + control: self.modifiers.control, + platform: self.modifiers.platform, + ..Default::default() + }; + + if &target.inner.key == key_char && target.inner.modifiers == ime_modifiers { + return true; + } + } + + #[cfg(target_os = "windows")] + if let Some(key_char) = self + .key_char + .as_ref() + .filter(|key_char| key_char != &&self.key) + { + // On Windows, if key_char is set, then the typed keystroke produced the key_char + if &target.inner.key == key_char && target.inner.modifiers == Modifiers::none() { + return true; + } + } + + target.inner.modifiers == self.modifiers && target.inner.key == self.key + } + + /// key syntax is: + /// [secondary-][ctrl-][alt-][shift-][cmd-][fn-]key[->key_char] + /// key_char syntax is only used for generating test events, + /// secondary means "cmd" on macOS and "ctrl" on other platforms + /// when matching a key with an key_char set will be matched without it. + pub fn parse(source: &str) -> std::result::Result { + let mut modifiers = Modifiers::none(); + let mut key = None; + let mut key_char = None; + + let mut components = source.split('-').peekable(); + while let Some(component) = components.next() { + if component.eq_ignore_ascii_case("ctrl") { + modifiers.control = true; + continue; + } + if component.eq_ignore_ascii_case("alt") { + modifiers.alt = true; + continue; + } + if component.eq_ignore_ascii_case("shift") { + modifiers.shift = true; + continue; + } + if component.eq_ignore_ascii_case("fn") { + modifiers.function = true; + continue; + } + if component.eq_ignore_ascii_case("secondary") { + if cfg!(target_os = "macos") { + modifiers.platform = true; + } else { + modifiers.control = true; + }; + continue; + } + + let is_platform = component.eq_ignore_ascii_case("cmd") + || component.eq_ignore_ascii_case("super") + || component.eq_ignore_ascii_case("win"); + + if is_platform { + modifiers.platform = true; + continue; + } + + let mut key_str = component.to_string(); + + if let Some(next) = components.peek() { + if next.is_empty() && source.ends_with('-') { + key = Some(String::from("-")); + break; + } else if next.len() > 1 && next.starts_with('>') { + key = Some(key_str); + key_char = Some(String::from(&next[1..])); + components.next(); + } else { + return Err(InvalidKeystrokeError { + keystroke: source.to_owned(), + }); + } + continue; + } + + if component.len() == 1 && component.as_bytes()[0].is_ascii_uppercase() { + // Convert to shift + lowercase char + modifiers.shift = true; + key_str.make_ascii_lowercase(); + } else { + // convert ascii chars to lowercase so that named keys like "tab" and "enter" + // are accepted case insensitively and stored how we expect so they are matched properly + key_str.make_ascii_lowercase() + } + key = Some(key_str); + } + + // Allow for the user to specify a keystroke modifier as the key itself + // This sets the `key` to the modifier, and disables the modifier + key = key.or_else(|| { + use std::mem; + // std::mem::take clears bool incase its true + if mem::take(&mut modifiers.shift) { + Some("shift".to_string()) + } else if mem::take(&mut modifiers.control) { + Some("control".to_string()) + } else if mem::take(&mut modifiers.alt) { + Some("alt".to_string()) + } else if mem::take(&mut modifiers.platform) { + Some("platform".to_string()) + } else if mem::take(&mut modifiers.function) { + Some("function".to_string()) + } else { + None + } + }); + + let key = key.ok_or_else(|| InvalidKeystrokeError { + keystroke: source.to_owned(), + })?; + + Ok(Keystroke { + modifiers, + key, + key_char, + }) + } + + /// Produces a representation of this key that Parse can understand. + pub fn unparse(&self) -> String { + unparse(&self.modifiers, &self.key) + } + + /// Returns true if this keystroke left + /// the ime system in an incomplete state. + pub fn is_ime_in_progress(&self) -> bool { + self.key_char.is_none() + && (is_printable_key(&self.key) || self.key.is_empty()) + && !(self.modifiers.platform + || self.modifiers.control + || self.modifiers.function + || self.modifiers.alt) + } + + /// Returns a new keystroke with the key_char filled. + /// This is used for dispatch_keystroke where we want users to + /// be able to simulate typing "space", etc. + pub fn with_simulated_ime(mut self) -> Self { + if self.key_char.is_none() + && !self.modifiers.platform + && !self.modifiers.control + && !self.modifiers.function + && !self.modifiers.alt + { + self.key_char = match self.key.as_str() { + "space" => Some(" ".into()), + "tab" => Some("\t".into()), + "enter" => Some("\n".into()), + key if !is_printable_key(key) || key.is_empty() => None, + key => { + if self.modifiers.shift { + Some(key.to_uppercase()) + } else { + Some(key.into()) + } + } + } + } + self + } +} + +impl KeybindingKeystroke { + #[cfg(target_os = "windows")] + #[expect(missing_docs)] + pub fn new(inner: Keystroke, display_modifiers: Modifiers, display_key: String) -> Self { + KeybindingKeystroke { + inner, + display_modifiers, + display_key, + } + } + + /// Create a new keybinding keystroke from the given keystroke using the given keyboard mapper. + pub fn new_with_mapper( + inner: Keystroke, + use_key_equivalents: bool, + keyboard_mapper: &dyn PlatformKeyboardMapper, + ) -> Self { + keyboard_mapper.map_key_equivalent(inner, use_key_equivalents) + } + + /// Create a new keybinding keystroke from the given keystroke, without any platform-specific mapping. + pub fn from_keystroke(keystroke: Keystroke) -> Self { + #[cfg(target_os = "windows")] + { + let key = keystroke.key.clone(); + let modifiers = keystroke.modifiers; + KeybindingKeystroke { + inner: keystroke, + display_modifiers: modifiers, + display_key: key, + } + } + #[cfg(not(target_os = "windows"))] + { + KeybindingKeystroke { inner: keystroke } + } + } + + /// Returns the GPUI representation of the keystroke. + pub fn inner(&self) -> &Keystroke { + &self.inner + } + + /// Returns the modifiers. + /// + /// Platform-specific behavior: + /// - On macOS and Linux, this modifiers is the same as `inner.modifiers`, which is the GPUI representation of the keystroke. + /// - On Windows, this modifiers is the display modifiers, for example, a `ctrl-@` keystroke will have `inner.modifiers` as + /// `Modifiers::control()` and `display_modifiers` as `Modifiers::control_shift()`. + pub fn modifiers(&self) -> &Modifiers { + #[cfg(target_os = "windows")] + { + &self.display_modifiers + } + #[cfg(not(target_os = "windows"))] + { + &self.inner.modifiers + } + } + + /// Returns the key. + /// + /// Platform-specific behavior: + /// - On macOS and Linux, this key is the same as `inner.key`, which is the GPUI representation of the keystroke. + /// - On Windows, this key is the display key, for example, a `ctrl-@` keystroke will have `inner.key` as `@` and `display_key` as `2`. + pub fn key(&self) -> &str { + #[cfg(target_os = "windows")] + { + &self.display_key + } + #[cfg(not(target_os = "windows"))] + { + &self.inner.key + } + } + + /// Sets the modifiers. On Windows this modifies both `inner.modifiers` and `display_modifiers`. + pub fn set_modifiers(&mut self, modifiers: Modifiers) { + self.inner.modifiers = modifiers; + #[cfg(target_os = "windows")] + { + self.display_modifiers = modifiers; + } + } + + /// Sets the key. On Windows this modifies both `inner.key` and `display_key`. + pub fn set_key(&mut self, key: String) { + #[cfg(target_os = "windows")] + { + self.display_key = key.clone(); + } + self.inner.key = key; + } + + /// Produces a representation of this key that Parse can understand. + pub fn unparse(&self) -> String { + #[cfg(target_os = "windows")] + { + unparse(&self.display_modifiers, &self.display_key) + } + #[cfg(not(target_os = "windows"))] + { + unparse(&self.inner.modifiers, &self.inner.key) + } + } + + /// Removes the key_char + pub fn remove_key_char(&mut self) { + self.inner.key_char = None; + } +} + +fn is_printable_key(key: &str) -> bool { + !matches!( + key, + "f1" | "f2" + | "f3" + | "f4" + | "f5" + | "f6" + | "f7" + | "f8" + | "f9" + | "f10" + | "f11" + | "f12" + | "f13" + | "f14" + | "f15" + | "f16" + | "f17" + | "f18" + | "f19" + | "f20" + | "f21" + | "f22" + | "f23" + | "f24" + | "f25" + | "f26" + | "f27" + | "f28" + | "f29" + | "f30" + | "f31" + | "f32" + | "f33" + | "f34" + | "f35" + | "backspace" + | "delete" + | "left" + | "right" + | "up" + | "down" + | "pageup" + | "pagedown" + | "insert" + | "home" + | "end" + | "back" + | "forward" + | "escape" + ) +} + +impl std::fmt::Display for Keystroke { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_modifiers(&self.modifiers, f)?; + display_key(&self.key, f) + } +} + +impl std::fmt::Display for KeybindingKeystroke { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_modifiers(self.modifiers(), f)?; + display_key(self.key(), f) + } +} + +/// The state of the modifier keys at some point in time +#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize, Hash, JsonSchema)] +pub struct Modifiers { + /// The control key + #[serde(default)] + pub control: bool, + + /// The alt key + /// Sometimes also known as the 'meta' key + #[serde(default)] + pub alt: bool, + + /// The shift key + #[serde(default)] + pub shift: bool, + + /// The command key, on macos + /// the windows key, on windows + /// the super key, on linux + #[serde(default)] + pub platform: bool, + + /// The function key + #[serde(default)] + pub function: bool, +} + +impl Modifiers { + /// Returns whether any modifier key is pressed. + pub fn modified(&self) -> bool { + self.control || self.alt || self.shift || self.platform || self.function + } + + /// Whether the semantically 'secondary' modifier key is pressed. + /// + /// On macOS, this is the command key. + /// On Linux and Windows, this is the control key. + pub fn secondary(&self) -> bool { + #[cfg(target_os = "macos")] + { + self.platform + } + + #[cfg(not(target_os = "macos"))] + { + self.control + } + } + + /// Returns how many modifier keys are pressed. + pub fn number_of_modifiers(&self) -> u8 { + self.control as u8 + + self.alt as u8 + + self.shift as u8 + + self.platform as u8 + + self.function as u8 + } + + /// Returns [`Modifiers`] with no modifiers. + pub fn none() -> Modifiers { + Default::default() + } + + /// Returns [`Modifiers`] with just the command key. + pub fn command() -> Modifiers { + Modifiers { + platform: true, + ..Default::default() + } + } + + /// A Returns [`Modifiers`] with just the secondary key pressed. + pub fn secondary_key() -> Modifiers { + #[cfg(target_os = "macos")] + { + Modifiers { + platform: true, + ..Default::default() + } + } + + #[cfg(not(target_os = "macos"))] + { + Modifiers { + control: true, + ..Default::default() + } + } + } + + /// Returns [`Modifiers`] with just the windows key. + pub fn windows() -> Modifiers { + Modifiers { + platform: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with just the super key. + pub fn super_key() -> Modifiers { + Modifiers { + platform: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with just control. + pub fn control() -> Modifiers { + Modifiers { + control: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with just alt. + pub fn alt() -> Modifiers { + Modifiers { + alt: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with just shift. + pub fn shift() -> Modifiers { + Modifiers { + shift: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with just function. + pub fn function() -> Modifiers { + Modifiers { + function: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with command + shift. + pub fn command_shift() -> Modifiers { + Modifiers { + shift: true, + platform: true, + ..Default::default() + } + } + + /// Returns [`Modifiers`] with command + shift. + pub fn control_shift() -> Modifiers { + Modifiers { + shift: true, + control: true, + ..Default::default() + } + } + + /// Checks if this [`Modifiers`] is a subset of another [`Modifiers`]. + pub fn is_subset_of(&self, other: &Modifiers) -> bool { + (*other & *self) == *self + } +} + +impl std::ops::BitOr for Modifiers { + type Output = Self; + + fn bitor(mut self, other: Self) -> Self::Output { + self |= other; + self + } +} + +impl std::ops::BitOrAssign for Modifiers { + fn bitor_assign(&mut self, other: Self) { + self.control |= other.control; + self.alt |= other.alt; + self.shift |= other.shift; + self.platform |= other.platform; + self.function |= other.function; + } +} + +impl std::ops::BitXor for Modifiers { + type Output = Self; + fn bitxor(mut self, rhs: Self) -> Self::Output { + self ^= rhs; + self + } +} + +impl std::ops::BitXorAssign for Modifiers { + fn bitxor_assign(&mut self, other: Self) { + self.control ^= other.control; + self.alt ^= other.alt; + self.shift ^= other.shift; + self.platform ^= other.platform; + self.function ^= other.function; + } +} + +impl std::ops::BitAnd for Modifiers { + type Output = Self; + fn bitand(mut self, rhs: Self) -> Self::Output { + self &= rhs; + self + } +} + +impl std::ops::BitAndAssign for Modifiers { + fn bitand_assign(&mut self, other: Self) { + self.control &= other.control; + self.alt &= other.alt; + self.shift &= other.shift; + self.platform &= other.platform; + self.function &= other.function; + } +} + +/// The state of the capslock key at some point in time +#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize, Hash, JsonSchema)] +pub struct Capslock { + /// The capslock key is on + #[serde(default)] + pub on: bool, +} + +impl AsKeystroke for Keystroke { + fn as_keystroke(&self) -> &Keystroke { + self + } +} + +impl AsKeystroke for KeybindingKeystroke { + fn as_keystroke(&self) -> &Keystroke { + &self.inner + } +} + +impl AsKeystroke for &T { + fn as_keystroke(&self) -> &Keystroke { + (**self).as_keystroke() + } +} + +fn display_modifiers(modifiers: &Modifiers, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if modifiers.control { + #[cfg(target_os = "macos")] + f.write_char('^')?; + + #[cfg(not(target_os = "macos"))] + write!(f, "ctrl-")?; + } + if modifiers.alt { + #[cfg(target_os = "macos")] + f.write_char('⌥')?; + + #[cfg(not(target_os = "macos"))] + write!(f, "alt-")?; + } + if modifiers.platform { + #[cfg(target_os = "macos")] + f.write_char('⌘')?; + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + f.write_char('❖')?; + + #[cfg(target_os = "windows")] + f.write_char('⊞')?; + } + if modifiers.shift { + #[cfg(target_os = "macos")] + f.write_char('⇧')?; + + #[cfg(not(target_os = "macos"))] + write!(f, "shift-")?; + } + Ok(()) +} + +fn display_key(key: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let key = match key { + #[cfg(target_os = "macos")] + "backspace" => '⌫', + #[cfg(target_os = "macos")] + "up" => '↑', + #[cfg(target_os = "macos")] + "down" => '↓', + #[cfg(target_os = "macos")] + "left" => '←', + #[cfg(target_os = "macos")] + "right" => '→', + #[cfg(target_os = "macos")] + "tab" => '⇥', + #[cfg(target_os = "macos")] + "escape" => '⎋', + #[cfg(target_os = "macos")] + "shift" => '⇧', + #[cfg(target_os = "macos")] + "control" => '⌃', + #[cfg(target_os = "macos")] + "alt" => '⌥', + #[cfg(target_os = "macos")] + "platform" => '⌘', + + key if key.len() == 1 => key.chars().next().unwrap().to_ascii_uppercase(), + key => return f.write_str(key), + }; + f.write_char(key) +} + +#[inline] +fn unparse(modifiers: &Modifiers, key: &str) -> String { + let mut result = String::new(); + if modifiers.function { + result.push_str("fn-"); + } + if modifiers.control { + result.push_str("ctrl-"); + } + if modifiers.alt { + result.push_str("alt-"); + } + if modifiers.platform { + #[cfg(target_os = "macos")] + result.push_str("cmd-"); + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + result.push_str("super-"); + + #[cfg(target_os = "windows")] + result.push_str("win-"); + } + if modifiers.shift { + result.push_str("shift-"); + } + result.push_str(&key); + result +} diff --git a/vendor/gpui-pre/src/platform/layer_shell.rs b/vendor/gpui-pre/src/platform/layer_shell.rs new file mode 100644 index 00000000..8be1b5fc --- /dev/null +++ b/vendor/gpui-pre/src/platform/layer_shell.rs @@ -0,0 +1,83 @@ +use bitflags::bitflags; +use thiserror::Error; + +use crate::Pixels; + +/// The layer the surface is rendered on. Multiple surfaces can share a layer, and ordering within +/// a single layer is undefined. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum Layer { + /// The background layer, typically used for wallpapers. + Background, + + /// The bottom layer. + Bottom, + + /// The top layer, typically used for fullscreen windows. + Top, + + /// The overlay layer, used for surfaces that should always be on top. + #[default] + Overlay, +} + +bitflags! { + /// Screen anchor point for layer_shell surfaces. These can be used in any combination, e.g. + /// specifying `Anchor::LEFT | Anchor::RIGHT` will stretch the surface across the width of the + /// screen. + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] + pub struct Anchor: u32 { + /// Anchor to the top edge of the screen. + const TOP = 1; + /// Anchor to the bottom edge of the screen. + const BOTTOM = 2; + /// Anchor to the left edge of the screen. + const LEFT = 4; + /// Anchor to the right edge of the screen. + const RIGHT = 8; + } +} + +/// Keyboard interactivity mode for the layer_shell surfaces. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum KeyboardInteractivity { + /// No keyboard inputs will be delivered to the surface and it won't be able to receive + /// keyboard focus. + None, + + /// The surface will receive exclusive keyboard focus as long as it is above the shell surface + /// layer, and no other layer_shell surfaces are above it. + Exclusive, + + /// The surface can be focused similarly to a normal window. + #[default] + OnDemand, +} + +/// Options for creating a layer_shell window. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct LayerShellOptions { + /// The namespace for the surface, mostly used by compositors to apply rules, can not be + /// changed after the surface is created. + pub namespace: String, + /// The layer the surface is rendered on. + pub layer: Layer, + /// The anchor point of the surface. + pub anchor: Anchor, + /// Requests that the compositor avoids occluding an area with other surfaces. + pub exclusive_zone: Option, + /// The anchor point of the exclusive zone, will be determined using the anchor if left + /// unspecified. + pub exclusive_edge: Option, + /// Margins between the surface and its anchor point(s). + /// Specified in CSS order: top, right, bottom, left. + pub margin: Option<(Pixels, Pixels, Pixels, Pixels)>, + /// How keyboard events should be delivered to the surface. + pub keyboard_interactivity: KeyboardInteractivity, +} + +/// An error indicating that an action failed because the compositor doesn't support the required +/// layer_shell protocol. +#[derive(Debug, Error)] +#[error("Compositor doesn't support zwlr_layer_shell_v1")] +pub struct LayerShellNotSupportedError; diff --git a/vendor/gpui-pre/src/platform/popup.rs b/vendor/gpui-pre/src/platform/popup.rs new file mode 100644 index 00000000..a1f8d7ea --- /dev/null +++ b/vendor/gpui-pre/src/platform/popup.rs @@ -0,0 +1,134 @@ +use bitflags::bitflags; +use thiserror::Error; + +use crate::{AnyWindowHandle, Bounds, Pixels, Point}; + +/// Options for a parent-anchored popup window such as a menu, dropdown, context menu or tooltip. +/// +/// A popup is placed relative to an anchor rectangle on its parent window rather than at an +/// absolute screen position. The platform resolves the final position, so this works both on +/// systems where the compositor owns window placement (Wayland) and on platforms with absolute +/// coordinates. +/// +/// The popup's size comes from [`WindowOptions::window_bounds`](crate::WindowOptions), whose +/// origin is ignored. All coordinates are in logical pixels. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PopupOptions { + /// The window the popup is anchored to. + pub parent: AnyWindowHandle, + + /// The rectangle the popup is positioned relative to, in the parent window's coordinate + /// space (the same space element bounds are in). For example, a dropdown menu uses the + /// bounds of the button that opened it. + pub anchor_rect: Bounds, + + /// Which point of [`Self::anchor_rect`] the popup is anchored to. + pub anchor: PopupAnchor, + + /// The direction in which the popup extends away from the anchor point. A dropdown that + /// drops below its button anchors to [`PopupAnchor::BottomLeft`] with a gravity of + /// [`PopupGravity::BottomRight`] so it grows down and to the right. + pub gravity: PopupGravity, + + /// How the platform may adjust the popup if the requested placement would put it off-screen. + pub constraint_adjustment: PopupConstraintAdjustment, + + /// An additional offset applied to the popup after anchoring. + pub offset: Point, + + /// Whether the popup should take an explicit input grab. + /// + /// Grabbing popups behave like menus: they take keyboard focus and are dismissed when the + /// user clicks outside of them or presses a dismissing key. Use it for menus and comboboxes, + /// not for tooltips or other passive popups. + /// + /// A grab must be requested while the triggering input is still active, in practice the + /// press of the mouse button that opens the popup. Open grabbing popups from a mouse-down + /// handler rather than a click handler, otherwise the grab is refused. + /// + /// Automatic dismissal only covers input aimed at other applications. A click elsewhere in + /// your own application still reaches it as usual, so closing the popup in that case is up + /// to you. Nested grabbing popups must be closed in the reverse order they were opened. + pub grab: bool, +} + +/// The point of the anchor rectangle that a popup is anchored to. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum PopupAnchor { + /// Anchor to the center of the anchor rectangle. + #[default] + Center, + /// Anchor to the center of the top edge. + Top, + /// Anchor to the center of the bottom edge. + Bottom, + /// Anchor to the center of the left edge. + Left, + /// Anchor to the center of the right edge. + Right, + /// Anchor to the top-left corner. + TopLeft, + /// Anchor to the bottom-left corner. + BottomLeft, + /// Anchor to the top-right corner. + TopRight, + /// Anchor to the bottom-right corner. + BottomRight, +} + +/// The direction in which a popup extends away from its anchor point. +/// +/// For instance, a gravity of [`PopupGravity::BottomRight`] places the popup below and to the +/// right of the anchor point. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum PopupGravity { + /// The popup is centered over the anchor point. + #[default] + Center, + /// The popup extends upwards from the anchor point. + Top, + /// The popup extends downwards from the anchor point. + Bottom, + /// The popup extends to the left of the anchor point. + Left, + /// The popup extends to the right of the anchor point. + Right, + /// The popup extends up and to the left of the anchor point. + TopLeft, + /// The popup extends down and to the left of the anchor point. + BottomLeft, + /// The popup extends up and to the right of the anchor point. + TopRight, + /// The popup extends down and to the right of the anchor point. + BottomRight, +} + +bitflags! { + /// How a popup may be adjusted by the platform if the requested placement would put it + /// off-screen. If no flags are set, the popup is placed exactly as requested and may be + /// clipped. + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] + pub struct PopupConstraintAdjustment: u32 { + /// The popup may be slid horizontally to stay on-screen. + const SLIDE_X = 1; + /// The popup may be slid vertically to stay on-screen. + const SLIDE_Y = 2; + /// The popup's anchor and gravity may be flipped horizontally to stay on-screen. + const FLIP_X = 4; + /// The popup's anchor and gravity may be flipped vertically to stay on-screen. + const FLIP_Y = 8; + /// The popup may be shrunk horizontally to stay on-screen. + const RESIZE_X = 16; + /// The popup may be shrunk vertically to stay on-screen. + const RESIZE_Y = 32; + } +} + +/// Returned when the current platform has no native popup implementation yet. +/// +/// Native popups are separate from gpui's in-window popovers, which are drawn as elements inside +/// an existing window. A caller that wants a popup on every platform should treat this error as +/// a cue to fall back to that in-window rendering. +#[derive(Debug, Error)] +#[error("popups are not supported on this platform")] +pub struct PopupNotSupportedError; diff --git a/vendor/gpui-pre/src/platform/scap_screen_capture.rs b/vendor/gpui-pre/src/platform/scap_screen_capture.rs new file mode 100644 index 00000000..797e19ba --- /dev/null +++ b/vendor/gpui-pre/src/platform/scap_screen_capture.rs @@ -0,0 +1,325 @@ +//! Screen capture for Linux and Windows +use crate::{ + DevicePixels, ForegroundExecutor, ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream, + Size, SourceMetadata, size, +}; +use anyhow::{Context as _, Result, anyhow}; +use futures::channel::oneshot; +use scap::Target; +use std::rc::Rc; +use std::sync::Arc; +use std::sync::atomic::{self, AtomicBool}; + +/// Populates the receiver with the screens that can be captured. +/// +/// `scap_default_target_source` should be used instead on Wayland, since `scap_screen_sources` +/// won't return any results. +#[allow(dead_code)] +pub fn scap_screen_sources( + foreground_executor: &ForegroundExecutor, +) -> oneshot::Receiver>>> { + let (sources_tx, sources_rx) = oneshot::channel(); + get_screen_targets(sources_tx); + to_dyn_screen_capture_sources(sources_rx, foreground_executor) +} + +/// Starts screen capture for the default target, and populates the receiver with a single source +/// for it. The first frame of the screen capture is used to determine the size of the stream. +/// +/// On Wayland (Linux), prompts the user to select a target, and populates the receiver with a +/// single screen capture source for their selection. +#[allow(dead_code)] +pub(crate) fn start_scap_default_target_source( + foreground_executor: &ForegroundExecutor, +) -> oneshot::Receiver>>> { + let (sources_tx, sources_rx) = oneshot::channel(); + start_default_target_screen_capture(sources_tx); + to_dyn_screen_capture_sources(sources_rx, foreground_executor) +} + +struct ScapCaptureSource { + target: scap::Display, + size: Size, +} + +/// Populates the sender with the screens available for capture. +fn get_screen_targets(sources_tx: oneshot::Sender>>) { + // Due to use of blocking APIs, a new thread is used. + std::thread::spawn(|| { + let targets = match scap::get_all_targets() { + Ok(targets) => targets, + Err(err) => { + sources_tx.send(Err(err)).ok(); + return; + } + }; + let sources = targets + .into_iter() + .filter_map(|target| match target { + scap::Target::Display(display) => { + let size = Size { + width: DevicePixels(display.width as i32), + height: DevicePixels(display.height as i32), + }; + Some(ScapCaptureSource { + target: display, + size, + }) + } + scap::Target::Window(_) => None, + }) + .collect::>(); + sources_tx.send(Ok(sources)).ok(); + }); +} + +impl ScreenCaptureSource for ScapCaptureSource { + fn metadata(&self) -> Result { + Ok(SourceMetadata { + resolution: self.size, + label: Some(self.target.title.clone().into()), + is_main: None, + id: self.target.id as u64, + }) + } + + fn stream( + &self, + foreground_executor: &ForegroundExecutor, + frame_callback: Box, + ) -> oneshot::Receiver>> { + let (stream_tx, stream_rx) = oneshot::channel(); + let target = self.target.clone(); + + // Due to use of blocking APIs, a dedicated thread is used. + std::thread::spawn(move || { + match new_scap_capturer(Some(scap::Target::Display(target.clone()))) { + Ok(mut capturer) => { + capturer.start_capture(); + run_capture(capturer, target.clone(), frame_callback, stream_tx); + } + Err(e) => { + stream_tx.send(Err(e)).ok(); + } + } + }); + + to_dyn_screen_capture_stream(stream_rx, foreground_executor) + } +} + +struct ScapDefaultTargetCaptureSource { + // Sender populated by single call to `ScreenCaptureSource::stream`. + stream_call_tx: std::sync::mpsc::SyncSender<( + // Provides the result of `ScreenCaptureSource::stream`. + oneshot::Sender>, + // Callback for frames. + Box, + )>, + target: scap::Display, + size: Size, +} + +/// Starts screen capture on the default capture target, and populates the sender with the source. +fn start_default_target_screen_capture( + sources_tx: oneshot::Sender>>, +) { + // Due to use of blocking APIs, a dedicated thread is used. + std::thread::spawn(|| { + let start_result = gpui_util::maybe!({ + let mut capturer = new_scap_capturer(None)?; + capturer.start_capture(); + let first_frame = capturer + .get_next_frame() + .context("Failed to get first frame of screenshare to get the size.")?; + let size = frame_size(&first_frame); + let target = capturer + .target() + .context("Unable to determine the target display.")?; + let target = target.clone(); + Ok((capturer, size, target)) + }); + + match start_result { + Ok((capturer, size, Target::Display(display))) => { + let (stream_call_tx, stream_rx) = std::sync::mpsc::sync_channel(1); + sources_tx + .send(Ok(vec![ScapDefaultTargetCaptureSource { + stream_call_tx, + size, + target: display.clone(), + }])) + .ok(); + let Ok((stream_tx, frame_callback)) = stream_rx.recv() else { + return; + }; + run_capture(capturer, display, frame_callback, stream_tx); + } + Err(e) => { + sources_tx.send(Err(e)).ok(); + } + _ => { + sources_tx + .send(Err(anyhow!("The screen capture source is not a display"))) + .ok(); + } + } + }); +} + +impl ScreenCaptureSource for ScapDefaultTargetCaptureSource { + fn metadata(&self) -> Result { + Ok(SourceMetadata { + resolution: self.size, + label: None, + is_main: None, + id: self.target.id as u64, + }) + } + + fn stream( + &self, + foreground_executor: &ForegroundExecutor, + frame_callback: Box, + ) -> oneshot::Receiver>> { + let (tx, rx) = oneshot::channel(); + match self.stream_call_tx.try_send((tx, frame_callback)) { + Ok(()) => {} + Err(std::sync::mpsc::TrySendError::Full((tx, _))) + | Err(std::sync::mpsc::TrySendError::Disconnected((tx, _))) => { + // Note: support could be added for being called again after end of prior stream. + tx.send(Err(anyhow!( + "Can't call ScapDefaultTargetCaptureSource::stream multiple times." + ))) + .ok(); + } + } + to_dyn_screen_capture_stream(rx, foreground_executor) + } +} + +fn new_scap_capturer(target: Option) -> Result { + scap::capturer::Capturer::build(scap::capturer::Options { + fps: 60, + show_cursor: true, + show_highlight: true, + // Note that the actual frame output type may differ. + output_type: scap::frame::FrameType::YUVFrame, + output_resolution: scap::capturer::Resolution::Captured, + crop_area: None, + target, + excluded_targets: None, + }) +} + +fn run_capture( + mut capturer: scap::capturer::Capturer, + display: scap::Display, + frame_callback: Box, + stream_tx: oneshot::Sender>, +) { + let cancel_stream = Arc::new(AtomicBool::new(false)); + let size = Size { + width: DevicePixels(display.width as i32), + height: DevicePixels(display.height as i32), + }; + let stream_send_result = stream_tx.send(Ok(ScapStream { + cancel_stream: cancel_stream.clone(), + display, + size, + })); + if stream_send_result.is_err() { + return; + } + while !cancel_stream.load(std::sync::atomic::Ordering::SeqCst) { + match capturer.get_next_frame() { + Ok(frame) => frame_callback(ScreenCaptureFrame(frame)), + Err(err) => { + log::error!("Halting screen capture due to error: {err}"); + break; + } + } + } + capturer.stop_capture(); +} + +struct ScapStream { + cancel_stream: Arc, + display: scap::Display, + size: Size, +} + +impl ScreenCaptureStream for ScapStream { + fn metadata(&self) -> Result { + Ok(SourceMetadata { + resolution: self.size, + label: Some(self.display.title.clone().into()), + is_main: None, + id: self.display.id as u64, + }) + } +} + +impl Drop for ScapStream { + fn drop(&mut self) { + self.cancel_stream.store(true, atomic::Ordering::SeqCst); + } +} + +fn frame_size(frame: &scap::frame::Frame) -> Size { + let (width, height) = match frame { + scap::frame::Frame::YUVFrame(frame) => (frame.width, frame.height), + scap::frame::Frame::RGB(frame) => (frame.width, frame.height), + scap::frame::Frame::RGBx(frame) => (frame.width, frame.height), + scap::frame::Frame::XBGR(frame) => (frame.width, frame.height), + scap::frame::Frame::BGRx(frame) => (frame.width, frame.height), + scap::frame::Frame::BGR0(frame) => (frame.width, frame.height), + scap::frame::Frame::BGRA(frame) => (frame.width, frame.height), + }; + size(DevicePixels(width), DevicePixels(height)) +} + +/// This is used by `get_screen_targets` and `start_default_target_screen_capture` to turn their +/// results into `Rc`. They need to `Send` their capture source, and so +/// the capture source structs are used as `Rc` is not `Send`. +fn to_dyn_screen_capture_sources( + sources_rx: oneshot::Receiver>>, + foreground_executor: &ForegroundExecutor, +) -> oneshot::Receiver>>> { + let (dyn_sources_tx, dyn_sources_rx) = oneshot::channel(); + foreground_executor + .spawn(async move { + match sources_rx.await { + Ok(Ok(results)) => dyn_sources_tx + .send(Ok(results + .into_iter() + .map(|source| Rc::new(source) as Rc) + .collect::>())) + .ok(), + Ok(Err(err)) => dyn_sources_tx.send(Err(err)).ok(), + Err(oneshot::Canceled) => None, + } + }) + .detach(); + dyn_sources_rx +} + +/// Same motivation as `to_dyn_screen_capture_sources` above. +fn to_dyn_screen_capture_stream( + sources_rx: oneshot::Receiver>, + foreground_executor: &ForegroundExecutor, +) -> oneshot::Receiver>> { + let (dyn_sources_tx, dyn_sources_rx) = oneshot::channel(); + foreground_executor + .spawn(async move { + match sources_rx.await { + Ok(Ok(stream)) => dyn_sources_tx + .send(Ok(Box::new(stream) as Box)) + .ok(), + Ok(Err(err)) => dyn_sources_tx.send(Err(err)).ok(), + Err(oneshot::Canceled) => None, + } + }) + .detach(); + dyn_sources_rx +} diff --git a/vendor/gpui-pre/src/platform/test.rs b/vendor/gpui-pre/src/platform/test.rs new file mode 100644 index 00000000..a327d8fe --- /dev/null +++ b/vendor/gpui-pre/src/platform/test.rs @@ -0,0 +1,12 @@ +mod dispatcher; +mod display; +mod platform; +mod window; + +pub use dispatcher::*; +pub(crate) use display::*; +pub(crate) use platform::*; +pub(crate) use window::*; + +#[cfg(any(test, feature = "test-support"))] +pub use platform::{TestScreenCaptureSource, TestScreenCaptureStream}; diff --git a/vendor/gpui-pre/src/platform/test/dispatcher.rs b/vendor/gpui-pre/src/platform/test/dispatcher.rs new file mode 100644 index 00000000..c48e4913 --- /dev/null +++ b/vendor/gpui-pre/src/platform/test/dispatcher.rs @@ -0,0 +1,148 @@ +use crate::{PlatformDispatcher, Priority, RunnableVariant}; +use scheduler::Instant; +use scheduler::{Clock, Scheduler, SessionId, TestScheduler, TestSchedulerConfig, Yield}; +use std::{ + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +/// TestDispatcher provides deterministic async execution for tests. +/// +/// This implementation delegates task scheduling to the scheduler crate's `TestScheduler`. +/// Access the scheduler directly via `scheduler()` for clock, rng, and parking control. +#[doc(hidden)] +pub struct TestDispatcher { + session_id: SessionId, + scheduler: Arc, + num_cpus_override: Arc, +} + +impl TestDispatcher { + pub fn new(seed: u64) -> Self { + let scheduler = Arc::new(TestScheduler::new(TestSchedulerConfig { + seed, + randomize_order: true, + allow_parking: false, + capture_pending_traces: std::env::var("PENDING_TRACES") + .map_or(false, |var| var == "1" || var == "true"), + timeout_ticks: 0..=1000, + })); + Self::from_scheduler(scheduler) + } + + pub fn from_scheduler(scheduler: Arc) -> Self { + TestDispatcher { + session_id: scheduler.allocate_session_id(), + scheduler, + num_cpus_override: Arc::new(AtomicUsize::new(0)), + } + } + + pub fn scheduler(&self) -> &Arc { + &self.scheduler + } + + pub fn session_id(&self) -> SessionId { + self.session_id + } + + pub fn drain_tasks(&self) { + self.scheduler.drain_tasks(); + } + + pub fn advance_clock(&self, by: Duration) { + self.scheduler.advance_clock(by); + } + + pub fn advance_clock_to_next_timer(&self) -> bool { + self.scheduler.advance_clock_to_next_timer() + } + + pub fn simulate_random_delay(&self) -> Yield { + self.scheduler.yield_random() + } + + pub fn tick(&self, background_only: bool) -> bool { + if background_only { + self.scheduler.tick_background_only() + } else { + self.scheduler.tick() + } + } + + pub fn run_until_parked(&self) { + while self.tick(false) {} + } + + pub fn allow_parking(&self) { + self.scheduler.allow_parking(); + } + + pub fn forbid_parking(&self) { + self.scheduler.forbid_parking(); + } + + /// Override the value returned by `BackgroundExecutor::num_cpus()` in tests. + /// A value of 0 means no override (the default of 4 is used). + pub fn set_num_cpus(&self, count: usize) { + self.num_cpus_override.store(count, Ordering::SeqCst); + } + + /// Returns the overridden CPU count, or `None` if no override is set. + pub fn num_cpus_override(&self) -> Option { + match self.num_cpus_override.load(Ordering::SeqCst) { + 0 => None, + n => Some(n), + } + } +} + +impl Clone for TestDispatcher { + fn clone(&self) -> Self { + let session_id = self.scheduler.allocate_session_id(); + Self { + session_id, + scheduler: self.scheduler.clone(), + num_cpus_override: self.num_cpus_override.clone(), + } + } +} + +impl PlatformDispatcher for TestDispatcher { + fn is_main_thread(&self) -> bool { + self.scheduler.is_main_thread() + } + + fn now(&self) -> Instant { + self.scheduler.clock().now() + } + + fn dispatch(&self, runnable: RunnableVariant, priority: Priority) { + self.scheduler + .schedule_background_with_priority(runnable, priority); + } + + fn dispatch_on_main_thread(&self, runnable: RunnableVariant, _priority: Priority) { + self.scheduler.schedule_local(self.session_id, runnable); + } + + fn dispatch_after(&self, _duration: Duration, _runnable: RunnableVariant) { + panic!( + "dispatch_after should not be called in tests. \ + Use BackgroundExecutor::timer() which uses the scheduler's native timer." + ); + } + + fn as_test(&self) -> Option<&TestDispatcher> { + Some(self) + } + + fn spawn_realtime(&self, f: Box) { + std::thread::spawn(move || { + f(); + }); + } +} diff --git a/vendor/gpui-pre/src/platform/test/display.rs b/vendor/gpui-pre/src/platform/test/display.rs new file mode 100644 index 00000000..c4adb014 --- /dev/null +++ b/vendor/gpui-pre/src/platform/test/display.rs @@ -0,0 +1,33 @@ +use crate::{Bounds, DisplayId, Pixels, PlatformDisplay, Point, px}; +use anyhow::{Ok, Result}; + +#[derive(Debug)] +pub(crate) struct TestDisplay { + id: DisplayId, + uuid: uuid::Uuid, + bounds: Bounds, +} + +impl TestDisplay { + pub fn new() -> Self { + TestDisplay { + id: DisplayId(1), + uuid: uuid::Uuid::new_v4(), + bounds: Bounds::from_corners(Point::default(), Point::new(px(1920.), px(1080.))), + } + } +} + +impl PlatformDisplay for TestDisplay { + fn id(&self) -> crate::DisplayId { + self.id + } + + fn uuid(&self) -> Result { + Ok(self.uuid) + } + + fn bounds(&self) -> crate::Bounds { + self.bounds + } +} diff --git a/vendor/gpui-pre/src/platform/test/platform.rs b/vendor/gpui-pre/src/platform/test/platform.rs new file mode 100644 index 00000000..4bf08387 --- /dev/null +++ b/vendor/gpui-pre/src/platform/test/platform.rs @@ -0,0 +1,742 @@ +#[cfg(any(test, feature = "test-support"))] +use crate::NoopTextSystem; +#[cfg(any(test, feature = "test-support"))] +use crate::PathPromptOptions; +use crate::{ + ActivityGuard, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DevicePixels, + DummyKeyboardMapper, ForegroundExecutor, Keymap, OwnedMenu, Platform, PlatformDisplay, + PlatformHeadlessRenderer, PlatformKeyboardLayout, PlatformKeyboardMapper, PlatformTextSystem, + PromptButton, ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream, SharedString, + SourceMetadata, SystemNotification, SystemNotificationResponse, Task, TestDisplay, TestWindow, + ThermalState, WindowAppearance, WindowParams, size, +}; +use anyhow::Result; +#[cfg(any(test, feature = "test-support"))] +use collections::VecDeque; +use futures::channel::oneshot; +use parking_lot::Mutex; +use std::{ + cell::{Cell, RefCell}, + path::{Path, PathBuf}, + rc::{Rc, Weak}, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +/// TestPlatform implements the Platform trait for use in tests. +pub(crate) struct TestPlatform { + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + + pub(crate) active_window: RefCell>, + active_display: Rc, + active_cursor: Mutex, + current_clipboard_item: Mutex>, + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + current_primary_item: Mutex>, + #[cfg(target_os = "macos")] + current_find_pasteboard_item: Mutex>, + #[cfg(any(test, feature = "test-support"))] + pub(crate) prompts: RefCell, + screen_capture_sources: RefCell>, + pub opened_url: RefCell>, + pub(crate) system_notifications: RefCell, + pub text_system: Arc, + pub expect_restart: + RefCell, Vec)>>>, + idle_sleep_prevention_count: Arc, + idle_sleep_prevention_delay: Cell, + idle_sleep_prevention_fails: Cell, + headless_renderer_factory: + Option anyhow::Result>>>>, + weak: Weak, + menus: RefCell>, +} + +#[derive(Clone)] +/// A fake screen capture source, used for testing. +pub struct TestScreenCaptureSource {} + +/// A fake screen capture stream, used for testing. +pub struct TestScreenCaptureStream {} + +impl ScreenCaptureSource for TestScreenCaptureSource { + fn metadata(&self) -> Result { + Ok(SourceMetadata { + id: 0, + is_main: None, + label: None, + resolution: size(DevicePixels(1), DevicePixels(1)), + }) + } + + fn stream( + &self, + _foreground_executor: &ForegroundExecutor, + _frame_callback: Box, + ) -> oneshot::Receiver>> { + let (mut tx, rx) = oneshot::channel(); + let stream = TestScreenCaptureStream {}; + tx.send(Ok(Box::new(stream) as Box)) + .ok(); + rx + } +} + +impl ScreenCaptureStream for TestScreenCaptureStream { + fn metadata(&self) -> Result { + TestScreenCaptureSource {}.metadata() + } +} + +#[cfg(any(test, feature = "test-support"))] +struct TestPrompt { + msg: String, + detail: Option, + answers: Vec, + tx: oneshot::Sender, +} + +#[derive(Default)] +pub(crate) struct TestSystemNotifications { + pub(crate) app_identity: Option<(SharedString, SharedString)>, + pub(crate) shown: Vec, + pub(crate) delivered: Vec, + pub(crate) dismissed: Vec, + response_callback: Option>, +} + +#[cfg(any(test, feature = "test-support"))] +#[derive(Default)] +pub(crate) struct TestPrompts { + multiple_choice: VecDeque, + new_path: VecDeque<(PathBuf, oneshot::Sender>>)>, + paths: VecDeque<( + PathPromptOptions, + oneshot::Sender>>>, + )>, +} + +impl TestPlatform { + #[cfg(any(test, feature = "test-support"))] + pub fn new(executor: BackgroundExecutor, foreground_executor: ForegroundExecutor) -> Rc { + Self::with_platform( + executor, + foreground_executor, + Arc::new(NoopTextSystem), + None, + ) + } + + #[cfg(any(test, feature = "test-support"))] + pub fn with_text_system( + executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + text_system: Arc, + ) -> Rc { + Self::with_platform(executor, foreground_executor, text_system, None) + } + + pub fn with_platform( + executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + text_system: Arc, + headless_renderer_factory: Option< + Box anyhow::Result>>>, + >, + ) -> Rc { + Rc::new_cyclic(|weak| TestPlatform { + background_executor: executor, + foreground_executor, + #[cfg(any(test, feature = "test-support"))] + prompts: Default::default(), + screen_capture_sources: Default::default(), + active_cursor: Default::default(), + active_display: Rc::new(TestDisplay::new()), + active_window: Default::default(), + expect_restart: Default::default(), + current_clipboard_item: Mutex::new(None), + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + current_primary_item: Mutex::new(None), + #[cfg(target_os = "macos")] + current_find_pasteboard_item: Mutex::new(None), + idle_sleep_prevention_count: Arc::new(AtomicUsize::new(0)), + idle_sleep_prevention_delay: Cell::new(Duration::ZERO), + idle_sleep_prevention_fails: Cell::new(false), + weak: weak.clone(), + opened_url: Default::default(), + system_notifications: Default::default(), + text_system, + headless_renderer_factory, + menus: Default::default(), + }) + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn simulate_new_path_selection( + &self, + select_path: impl FnOnce(&std::path::Path) -> Option, + ) { + let (path, tx) = self + .prompts + .borrow_mut() + .new_path + .pop_front() + .expect("no pending new path prompt"); + tx.send(Ok(select_path(&path))).ok(); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn simulate_path_prompt_response( + &self, + select_paths: impl FnOnce(&PathPromptOptions) -> Option>, + ) { + let (options, tx) = self + .prompts + .borrow_mut() + .paths + .pop_front() + .expect("no pending paths prompt"); + let selection = select_paths(&options); + if let Some(paths) = &selection + && !options.multiple + && paths.len() > 1 + { + panic!( + "selected {} paths for a prompt that does not allow multiple selection", + paths.len() + ); + } + tx.send(Ok(selection)).ok(); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn did_prompt_for_paths(&self) -> bool { + !self.prompts.borrow().paths.is_empty() + } + + #[cfg(any(test, feature = "test-support"))] + #[track_caller] + pub(crate) fn simulate_prompt_answer(&self, response: &str) { + let prompt = self + .prompts + .borrow_mut() + .multiple_choice + .pop_front() + .expect("no pending multiple choice prompt"); + let Some(ix) = prompt.answers.iter().position(|a| a == response) else { + panic!( + "PROMPT: {}\n{:?}\n{:?}\nCannot respond with {}", + prompt.msg, prompt.detail, prompt.answers, response + ) + }; + prompt.tx.send(ix).ok(); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn has_pending_prompt(&self) -> bool { + !self.prompts.borrow().multiple_choice.is_empty() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn pending_prompt(&self) -> Option<(String, String)> { + let prompts = self.prompts.borrow(); + let prompt = prompts.multiple_choice.front()?; + Some(( + prompt.msg.clone(), + prompt.detail.clone().unwrap_or_default(), + )) + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn set_screen_capture_sources(&self, sources: Vec) { + *self.screen_capture_sources.borrow_mut() = sources; + } + + /// Queues the prompt so a test can later inspect or answer it through + /// [`Self::pending_prompt`] and [`Self::simulate_prompt_answer`]. + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn prompt( + &self, + msg: &str, + detail: Option<&str>, + answers: &[PromptButton], + ) -> oneshot::Receiver { + let (tx, rx) = oneshot::channel(); + let answers: Vec = answers.iter().map(|s| s.label().to_string()).collect(); + self.prompts + .borrow_mut() + .multiple_choice + .push_back(TestPrompt { + msg: msg.to_string(), + detail: detail.map(|s| s.to_string()), + answers, + tx, + }); + rx + } + + /// Benchmarks have no API to answer a prompt, so this doesn't retain it + /// for later inspection; dropping the sender immediately cancels the + /// returned receiver instead of leaving it pending indefinitely. + #[cfg(not(any(test, feature = "test-support")))] + pub(crate) fn prompt( + &self, + _msg: &str, + _detail: Option<&str>, + _answers: &[PromptButton], + ) -> oneshot::Receiver { + oneshot::channel().1 + } + + pub(crate) fn set_active_window(&self, window: Option) { + let executor = self.foreground_executor(); + let previous_window = self.active_window.borrow_mut().take(); + self.active_window.borrow_mut().clone_from(&window); + + executor + .spawn(async move { + if let Some(previous_window) = previous_window { + if let Some(window) = window.as_ref() + && Rc::ptr_eq(&previous_window.0, &window.0) + { + return; + } + previous_window.simulate_active_status_change(false); + } + if let Some(window) = window { + window.simulate_active_status_change(true); + } + }) + .detach(); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn did_prompt_for_new_path(&self) -> bool { + !self.prompts.borrow().new_path.is_empty() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn active_idle_sleep_preventions(&self) -> usize { + self.idle_sleep_prevention_count.load(Ordering::SeqCst) + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn set_idle_sleep_prevention_delay(&self, delay: Duration) { + self.idle_sleep_prevention_delay.set(delay); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn set_idle_sleep_prevention_fails(&self, fails: bool) { + self.idle_sleep_prevention_fails.set(fails); + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn app_identity(&self) -> Option<(SharedString, SharedString)> { + self.system_notifications.borrow().app_identity.clone() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn shown_system_notifications(&self) -> Vec { + self.system_notifications.borrow().shown.clone() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn delivered_system_notifications(&self) -> Vec { + self.system_notifications.borrow().delivered.clone() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn dismissed_system_notifications(&self) -> Vec { + self.system_notifications.borrow().dismissed.clone() + } + + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn simulate_system_notification_response( + &self, + response: SystemNotificationResponse, + ) { + let callback = self + .system_notifications + .borrow_mut() + .response_callback + .take(); + if let Some(mut callback) = callback { + callback(response); + self.system_notifications + .borrow_mut() + .response_callback + .get_or_insert(callback); + } + } +} + +impl Platform for TestPlatform { + fn background_executor(&self) -> BackgroundExecutor { + self.background_executor.clone() + } + + fn foreground_executor(&self) -> ForegroundExecutor { + self.foreground_executor.clone() + } + + fn text_system(&self) -> Arc { + self.text_system.clone() + } + + fn keyboard_layout(&self) -> Box { + Box::new(TestKeyboardLayout) + } + + fn keyboard_mapper(&self) -> Rc { + Rc::new(DummyKeyboardMapper) + } + + fn on_keyboard_layout_change(&self, _: Box) {} + + fn on_thermal_state_change(&self, _: Box) {} + + fn thermal_state(&self) -> ThermalState { + ThermalState::Nominal + } + + fn prevent_idle_sleep(&self, reason: &str) -> Task> { + let count = self.idle_sleep_prevention_count.clone(); + let fails = self.idle_sleep_prevention_fails.get(); + let reason = reason.to_owned(); + let acquire = move || { + if fails { + anyhow::bail!("Idle sleep prevention for {reason:?} is set to fail in this test"); + } + count.fetch_add(1, Ordering::SeqCst); + Ok(ActivityGuard::new(move || { + count.fetch_sub(1, Ordering::SeqCst); + })) + }; + + let delay = self.idle_sleep_prevention_delay.get(); + if delay.is_zero() { + Task::ready(acquire()) + } else { + let delay = self.background_executor.timer(delay); + self.foreground_executor.spawn(async move { + delay.await; + acquire() + }) + } + } + + fn run(&self, _on_finish_launching: Box) { + unimplemented!() + } + + fn quit(&self) {} + + fn restart(&self, path: Option, arguments: Vec) { + if let Some(tx) = self.expect_restart.take() { + tx.send((path, arguments)).unwrap(); + } + } + + fn activate(&self, _ignoring_other_apps: bool) { + // + } + + fn hide(&self) { + unimplemented!() + } + + fn hide_other_apps(&self) { + unimplemented!() + } + + fn unhide_other_apps(&self) { + unimplemented!() + } + + fn displays(&self) -> Vec> { + vec![self.active_display.clone()] + } + + fn primary_display(&self) -> Option> { + Some(self.active_display.clone()) + } + + fn is_screen_capture_supported(&self) -> bool { + true + } + + fn screen_capture_sources( + &self, + ) -> oneshot::Receiver>>> { + let (mut tx, rx) = oneshot::channel(); + tx.send(Ok(self + .screen_capture_sources + .borrow() + .iter() + .map(|source| Rc::new(source.clone()) as Rc) + .collect())) + .ok(); + rx + } + + fn active_window(&self) -> Option { + self.active_window + .borrow() + .as_ref() + .map(|window| window.0.lock().handle) + } + + fn open_window( + &self, + handle: AnyWindowHandle, + params: WindowParams, + ) -> anyhow::Result> { + let renderer = match self.headless_renderer_factory.as_ref() { + Some(factory) => factory()?, + None => None, + }; + let window = TestWindow::new( + handle, + params, + self.weak.clone(), + self.active_display.clone(), + renderer, + ); + Ok(Box::new(window)) + } + + fn window_appearance(&self) -> WindowAppearance { + WindowAppearance::Light + } + + fn open_url(&self, url: &str) { + *self.opened_url.borrow_mut() = Some(url.to_string()) + } + + fn on_open_urls(&self, _callback: Box)>) { + unimplemented!() + } + + /// Queues the prompt so a test can later answer it through + /// [`Self::simulate_path_prompt_response`]. + #[cfg(any(test, feature = "test-support"))] + fn prompt_for_paths( + &self, + options: crate::PathPromptOptions, + ) -> oneshot::Receiver>>> { + let (tx, rx) = oneshot::channel(); + self.prompts.borrow_mut().paths.push_back((options, tx)); + rx + } + + /// Benchmarks have no API to answer a path prompt, so this doesn't + /// retain it for later inspection; dropping the sender immediately + /// cancels the returned receiver instead of leaving it pending + /// indefinitely. + #[cfg(not(any(test, feature = "test-support")))] + fn prompt_for_paths( + &self, + _options: crate::PathPromptOptions, + ) -> oneshot::Receiver>>> { + oneshot::channel().1 + } + + /// Queues the prompt so a test can later answer it through + /// [`Self::simulate_new_path_selection`]. + #[cfg(any(test, feature = "test-support"))] + fn prompt_for_new_path( + &self, + directory: &std::path::Path, + _suggested_name: Option<&str>, + ) -> oneshot::Receiver>> { + let (tx, rx) = oneshot::channel(); + self.prompts + .borrow_mut() + .new_path + .push_back((directory.to_path_buf(), tx)); + rx + } + + /// Benchmarks have no API to answer a new-path prompt, so this doesn't + /// retain it for later inspection; dropping the sender immediately + /// cancels the returned receiver instead of leaving it pending + /// indefinitely. + #[cfg(not(any(test, feature = "test-support")))] + fn prompt_for_new_path( + &self, + _directory: &std::path::Path, + _suggested_name: Option<&str>, + ) -> oneshot::Receiver>> { + oneshot::channel().1 + } + + fn can_select_mixed_files_and_dirs(&self) -> bool { + true + } + + fn reveal_path(&self, _path: &std::path::Path) { + unimplemented!() + } + + fn on_quit(&self, _callback: Box bool>) {} + + fn on_reopen(&self, _callback: Box) { + unimplemented!() + } + + fn on_system_sleep(&self, _callback: Box) {} + + fn on_system_wake(&self, _callback: Box) {} + + fn set_app_identity(&self, identifier: &str, name: &str) { + self.system_notifications.borrow_mut().app_identity = + Some((identifier.to_string().into(), name.to_string().into())); + } + + fn show_system_notification(&self, notification: SystemNotification) { + let mut system_notifications = self.system_notifications.borrow_mut(); + if system_notifications.app_identity.is_none() { + return; + } + + let delivered = system_notifications + .delivered + .iter_mut() + .find(|delivered| delivered.tag == notification.tag); + if let Some(delivered) = delivered { + *delivered = notification.clone(); + } else { + system_notifications.delivered.push(notification.clone()); + } + system_notifications.shown.push(notification); + } + + fn dismiss_system_notification(&self, tag: &str) { + let mut system_notifications = self.system_notifications.borrow_mut(); + system_notifications + .delivered + .retain(|notification| notification.tag != tag); + system_notifications + .dismissed + .push(SharedString::from(tag.to_string())); + } + + fn on_system_notification_response( + &self, + callback: Box, + ) { + self.system_notifications.borrow_mut().response_callback = Some(callback); + } + + fn set_menus(&self, menus: Vec, _keymap: &Keymap) { + *self.menus.borrow_mut() = menus.into_iter().map(|menu| menu.owned()).collect() + } + + fn get_menus(&self) -> Option> { + Some(self.menus.borrow().clone()) + } + + fn set_dock_menu(&self, _menu: Vec, _keymap: &Keymap) {} + + fn add_recent_document(&self, _paths: &Path) {} + + fn on_app_menu_action(&self, _callback: Box) {} + + fn on_will_open_app_menu(&self, _callback: Box) {} + + fn on_validate_app_menu_command(&self, _callback: Box bool>) {} + + fn app_path(&self) -> Result { + unimplemented!() + } + + fn path_for_auxiliary_executable(&self, _name: &str) -> Result { + unimplemented!() + } + + fn set_cursor_style(&self, style: crate::CursorStyle) { + *self.active_cursor.lock() = style; + } + + fn hide_cursor_until_mouse_moves(&self) {} + + fn is_cursor_visible(&self) -> bool { + true + } + + fn should_auto_hide_scrollbars(&self) -> bool { + false + } + + fn read_from_clipboard(&self) -> Option { + self.current_clipboard_item.lock().clone() + } + + fn write_to_clipboard(&self, item: ClipboardItem) { + *self.current_clipboard_item.lock() = Some(item); + } + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + fn read_from_primary(&self) -> Option { + self.current_primary_item.lock().clone() + } + + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + fn write_to_primary(&self, item: ClipboardItem) { + *self.current_primary_item.lock() = Some(item); + } + + #[cfg(target_os = "macos")] + fn read_from_find_pasteboard(&self) -> Option { + self.current_find_pasteboard_item.lock().clone() + } + + #[cfg(target_os = "macos")] + fn write_to_find_pasteboard(&self, item: ClipboardItem) { + *self.current_find_pasteboard_item.lock() = Some(item); + } + + fn write_credentials(&self, _url: &str, _username: &str, _password: &[u8]) -> Task> { + Task::ready(Ok(())) + } + + fn read_credentials(&self, _url: &str) -> Task)>>> { + Task::ready(Ok(None)) + } + + fn delete_credentials(&self, _url: &str) -> Task> { + Task::ready(Ok(())) + } + + fn register_url_scheme(&self, _: &str) -> Task> { + unimplemented!() + } + + fn open_with_system(&self, _path: &Path) { + unimplemented!() + } +} + +impl TestScreenCaptureSource { + /// Create a fake screen capture source, for testing. + #[cfg(any(test, feature = "test-support"))] + pub fn new() -> Self { + Self {} + } +} + +struct TestKeyboardLayout; + +impl PlatformKeyboardLayout for TestKeyboardLayout { + fn id(&self) -> &str { + "zed.keyboard.example" + } + + fn name(&self) -> &str { + "zed.keyboard.example" + } +} diff --git a/vendor/gpui-pre/src/platform/test/window.rs b/vendor/gpui-pre/src/platform/test/window.rs new file mode 100644 index 00000000..14fb8896 --- /dev/null +++ b/vendor/gpui-pre/src/platform/test/window.rs @@ -0,0 +1,591 @@ +use crate::{ + AnyWindowHandle, Bounds, DevicePixels, DispatchEventResult, GpuSpecs, HeadlessAtlas, Pixels, + PlatformAtlas, PlatformDisplay, PlatformHeadlessRenderer, PlatformInput, PlatformInputHandler, + PlatformWindow, Point, PromptButton, RequestFrameOptions, Scene, Size, TestPlatform, + TextInputConfiguration, TextInputStateChange, WindowAppearance, WindowBackgroundAppearance, + WindowBounds, WindowControlArea, WindowInsets, WindowParams, WindowVisibility, +}; +use gpui_util::ResultExt as _; +#[cfg(any(test, feature = "test-support"))] +use image::RgbaImage; +use parking_lot::Mutex; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; +use std::{ + cell::Cell, + path::PathBuf, + rc::{Rc, Weak}, + sync::{self, Arc}, +}; + +pub(crate) struct TestWindowState { + pub(crate) bounds: Bounds, + pub(crate) handle: AnyWindowHandle, + display: Rc, + pub(crate) title: Option, + pub(crate) edited: bool, + pub(crate) document_path: Option, + platform: Weak, + // TODO: Replace with `Rc` + sprite_atlas: Arc, + renderer: Option>, + pub(crate) should_close_handler: Option bool>>, + hit_test_window_control_callback: Option Option>>, + input_callback: Option DispatchEventResult>>, + active_status_change_callback: Option>, + visibility: WindowVisibility, + visibility_callback: Option>, + hover_status_change_callback: Option>, + resize_callback: Option, f32)>>, + visual_viewport: Option>, + visual_viewport_callback: Option>, + insets: WindowInsets, + insets_callback: Option>, + virtual_keyboard_requests: usize, + virtual_keyboard_dismissals: usize, + moved_callback: Option>, + appearance_change_callback: Option>, + request_frame_callback: Option>, + frame_wake_count: Rc>, + frame_scheduled: bool, + frame_callback_pending: bool, + input_handler: Option, + text_input_configurations: Vec, + text_input_state_changes: Vec, + is_fullscreen: bool, + scale_factor: f32, + appearance: WindowAppearance, + external_drag_files: Vec<(PathBuf, bool)>, + start_external_drag_result: bool, +} + +#[derive(Clone)] +pub struct TestWindow(pub(crate) Rc>); + +// Test windows are not backed by a real platform window, so there is no raw +// handle to report; `NotSupported` is `raw_window_handle`'s variant for exactly this. +impl HasWindowHandle for TestWindow { + fn window_handle( + &self, + ) -> Result, raw_window_handle::HandleError> { + Err(raw_window_handle::HandleError::NotSupported) + } +} + +impl HasDisplayHandle for TestWindow { + fn display_handle( + &self, + ) -> Result, raw_window_handle::HandleError> { + Err(raw_window_handle::HandleError::NotSupported) + } +} + +impl TestWindow { + pub(crate) fn new( + handle: AnyWindowHandle, + params: WindowParams, + platform: Weak, + display: Rc, + renderer: Option>, + ) -> Self { + let sprite_atlas: Arc = match &renderer { + Some(r) => r.sprite_atlas(), + None => Arc::new(HeadlessAtlas::default()), + }; + Self(Rc::new(Mutex::new(TestWindowState { + bounds: params.bounds, + display, + platform, + handle, + sprite_atlas, + renderer, + title: Default::default(), + edited: false, + document_path: None, + should_close_handler: None, + hit_test_window_control_callback: None, + input_callback: None, + active_status_change_callback: None, + visibility: WindowVisibility::Visible, + visibility_callback: None, + hover_status_change_callback: None, + resize_callback: None, + visual_viewport: None, + visual_viewport_callback: None, + insets: WindowInsets::default(), + insets_callback: None, + virtual_keyboard_requests: 0, + virtual_keyboard_dismissals: 0, + moved_callback: None, + appearance_change_callback: None, + request_frame_callback: None, + frame_wake_count: Rc::new(Cell::new(0)), + frame_scheduled: false, + frame_callback_pending: false, + input_handler: None, + text_input_configurations: Vec::new(), + text_input_state_changes: Vec::new(), + is_fullscreen: false, + // Preserve the test platform's historical 2x default. + scale_factor: 2.0, + appearance: WindowAppearance::Light, + external_drag_files: Vec::new(), + start_external_drag_result: false, + }))) + } + pub fn simulate_scheduled_frame(&self) -> bool { + let callback = { + let mut state = self.0.lock(); + if !std::mem::take(&mut state.frame_scheduled) { + return false; + } + state.frame_callback_pending = false; + state.request_frame_callback.take() + }; + let Some(mut callback) = callback else { + self.0.lock().frame_scheduled = true; + return false; + }; + + callback(RequestFrameOptions::default()); + self.0.lock().request_frame_callback = Some(callback); + true + } + + pub fn frame_scheduled(&self) -> bool { + self.0.lock().frame_scheduled + } + + pub fn simulate_visibility_change(&self, visibility: WindowVisibility) { + let callback = { + let mut state = self.0.lock(); + state.visibility = visibility; + state.visibility_callback.take() + }; + if let Some(mut callback) = callback { + callback(visibility); + self.0.lock().visibility_callback = Some(callback); + } + } + + pub fn simulate_visual_viewport_change(&self, bounds: Bounds) { + let callback = { + let mut state = self.0.lock(); + state.visual_viewport = Some(bounds); + state.visual_viewport_callback.take() + }; + if let Some(mut callback) = callback { + callback(); + self.0.lock().visual_viewport_callback = Some(callback); + } + } + + pub fn simulate_insets_change(&self, insets: WindowInsets) { + let callback = { + let mut state = self.0.lock(); + state.insets = insets.clone(); + state.insets_callback.take() + }; + if let Some(mut callback) = callback { + callback(insets); + self.0.lock().insets_callback = Some(callback); + } + } + + pub fn virtual_keyboard_requests(&self) -> usize { + self.0.lock().virtual_keyboard_requests + } + + pub fn virtual_keyboard_dismissals(&self) -> usize { + self.0.lock().virtual_keyboard_dismissals + } + + /// Every [`TextInputConfiguration`] forwarded to this window, in order. + pub fn text_input_configurations(&self) -> Vec { + self.0.lock().text_input_configurations.clone() + } + + pub fn text_input_state_changes(&self) -> Vec { + self.0.lock().text_input_state_changes.clone() + } + + pub fn simulate_resize(&mut self, size: Size) { + let scale_factor = self.scale_factor(); + let mut lock = self.0.lock(); + // Always update bounds, even if no callback is registered + lock.bounds.size = size; + let Some(mut callback) = lock.resize_callback.take() else { + return; + }; + drop(lock); + callback(size, scale_factor); + self.0.lock().resize_callback = Some(callback); + } + + /// Simulates a display scale change through the resize callback, preserving logical bounds. + pub fn simulate_scale_factor_change(&mut self, scale_factor: f32) { + let size = { + let mut lock = self.0.lock(); + lock.scale_factor = scale_factor; + lock.bounds.size + }; + self.simulate_resize(size); + } + + pub(crate) fn simulate_active_status_change(&self, active: bool) { + let mut lock = self.0.lock(); + let Some(mut callback) = lock.active_status_change_callback.take() else { + return; + }; + drop(lock); + callback(active); + self.0.lock().active_status_change_callback = Some(callback); + } + + pub fn simulate_appearance_change(&self, appearance: WindowAppearance) { + let mut lock = self.0.lock(); + lock.appearance = appearance; + let Some(mut callback) = lock.appearance_change_callback.take() else { + return; + }; + drop(lock); + callback(); + self.0.lock().appearance_change_callback = Some(callback); + } + + /// Returns how many times this window's frame waker has been invoked. + pub fn frame_wake_count(&self) -> usize { + self.0.lock().frame_wake_count.get() + } + + /// Delivers a frame request to the window, as the platform's frame source + /// would. + pub fn simulate_frame_request(&self, options: RequestFrameOptions) { + let mut lock = self.0.lock(); + let Some(mut callback) = lock.request_frame_callback.take() else { + return; + }; + drop(lock); + callback(options); + self.0.lock().request_frame_callback = Some(callback); + } + + pub fn simulate_input(&mut self, event: PlatformInput) -> bool { + let mut lock = self.0.lock(); + let Some(mut callback) = lock.input_callback.take() else { + return false; + }; + drop(lock); + let result = callback(event); + self.0.lock().input_callback = Some(callback); + !result.propagate + } + + pub fn external_drag_files(&self) -> Vec<(PathBuf, bool)> { + self.0.lock().external_drag_files.clone() + } + + pub fn set_start_external_drag_result(&self, result: bool) { + self.0.lock().start_external_drag_result = result; + } +} + +impl PlatformWindow for TestWindow { + fn visual_viewport_bounds(&self) -> Bounds { + let state = self.0.lock(); + state + .visual_viewport + .unwrap_or_else(|| Bounds::new(Point::default(), state.bounds.size)) + } + + fn on_visual_viewport_changed(&self, callback: Box) { + self.0.lock().visual_viewport_callback = Some(callback); + } + + fn insets(&self) -> WindowInsets { + self.0.lock().insets.clone() + } + + fn on_insets_changed(&self, callback: Box) { + self.0.lock().insets_callback = Some(callback); + } + + fn show_soft_keyboard(&self) { + self.0.lock().virtual_keyboard_requests += 1; + } + + fn hide_soft_keyboard(&self) { + self.0.lock().virtual_keyboard_dismissals += 1; + } + + fn bounds(&self) -> Bounds { + self.0.lock().bounds + } + + fn window_bounds(&self) -> WindowBounds { + WindowBounds::Windowed(self.bounds()) + } + + fn is_maximized(&self) -> bool { + false + } + + fn content_size(&self) -> Size { + self.bounds().size + } + + fn resize(&mut self, size: Size) { + let mut lock = self.0.lock(); + lock.bounds.size = size; + } + + fn scale_factor(&self) -> f32 { + self.0.lock().scale_factor + } + + fn appearance(&self) -> WindowAppearance { + self.0.lock().appearance + } + + fn display(&self) -> Option> { + Some(self.0.lock().display.clone()) + } + + fn mouse_position(&self) -> Point { + Point::default() + } + + fn modifiers(&self) -> crate::Modifiers { + crate::Modifiers::default() + } + + fn capslock(&self) -> crate::Capslock { + crate::Capslock::default() + } + + fn set_input_handler(&mut self, input_handler: PlatformInputHandler) { + self.0.lock().input_handler = Some(input_handler); + } + + fn take_input_handler(&mut self) -> Option { + self.0.lock().input_handler.take() + } + + fn set_text_input_configuration(&mut self, configuration: TextInputConfiguration) { + self.0.lock().text_input_configurations.push(configuration); + } + + fn text_input_state_changed(&self, change: TextInputStateChange) { + self.0.lock().text_input_state_changes.push(change); + } + + fn prompt( + &self, + _level: crate::PromptLevel, + msg: &str, + detail: Option<&str>, + answers: &[PromptButton], + ) -> Option> { + Some( + self.0 + .lock() + .platform + .upgrade() + .expect("platform dropped") + .prompt(msg, detail, answers), + ) + } + + fn activate(&self) { + self.0 + .lock() + .platform + .upgrade() + .unwrap() + .set_active_window(Some(self.clone())) + } + + fn is_active(&self) -> bool { + false + } + + fn visibility(&self) -> WindowVisibility { + self.0.lock().visibility + } + + fn is_hovered(&self) -> bool { + false + } + + fn background_appearance(&self) -> WindowBackgroundAppearance { + WindowBackgroundAppearance::Opaque + } + + fn is_subpixel_rendering_supported(&self) -> bool { + false + } + + fn set_title(&mut self, title: &str) { + self.0.lock().title = Some(title.to_owned()); + } + + fn set_app_id(&mut self, _app_id: &str) {} + + fn set_background_appearance(&self, _background: WindowBackgroundAppearance) {} + + fn set_edited(&mut self, edited: bool) { + self.0.lock().edited = edited; + } + + fn set_document_path(&self, path: Option<&std::path::Path>) { + self.0.lock().document_path = path.map(|p| p.to_path_buf()); + } + + fn show_character_palette(&self) { + unimplemented!() + } + + fn minimize(&self) { + unimplemented!() + } + + fn zoom(&self) { + unimplemented!() + } + + fn toggle_fullscreen(&self) { + let mut lock = self.0.lock(); + lock.is_fullscreen = !lock.is_fullscreen; + } + + fn is_fullscreen(&self) -> bool { + self.0.lock().is_fullscreen + } + + fn frame_waker(&self) -> Option> { + // Tests can inspect wakes without delivering a frame synchronously. + let frame_wake_count = self.0.lock().frame_wake_count.clone(); + #[cfg(feature = "bench-support")] + let window = Rc::downgrade(&self.0); + Some(Rc::new(move || { + frame_wake_count.set(frame_wake_count.get() + 1); + #[cfg(feature = "bench-support")] + if let Some(window) = window.upgrade() { + TestWindow(window).schedule_frame(); + } + })) + } + + fn on_request_frame(&self, callback: Box) { + self.0.lock().request_frame_callback = Some(callback); + } + + fn schedule_frame(&self) { + let mut state = self.0.lock(); + if !state.frame_callback_pending { + state.frame_scheduled = true; + } + } + + fn on_input(&self, callback: Box DispatchEventResult>) { + self.0.lock().input_callback = Some(callback) + } + + fn on_active_status_change(&self, callback: Box) { + self.0.lock().active_status_change_callback = Some(callback) + } + + fn on_visibility_change(&self, callback: Box) { + self.0.lock().visibility_callback = Some(callback); + } + + fn on_hover_status_change(&self, callback: Box) { + self.0.lock().hover_status_change_callback = Some(callback) + } + + fn on_resize(&self, callback: Box, f32)>) { + self.0.lock().resize_callback = Some(callback) + } + + fn on_moved(&self, callback: Box) { + self.0.lock().moved_callback = Some(callback) + } + + fn on_should_close(&self, callback: Box bool>) { + self.0.lock().should_close_handler = Some(callback); + } + + fn on_close(&self, _callback: Box) {} + + fn on_hit_test_window_control(&self, callback: Box Option>) { + self.0.lock().hit_test_window_control_callback = Some(callback); + } + + fn on_appearance_changed(&self, callback: Box) { + self.0.lock().appearance_change_callback = Some(callback); + } + + fn draw(&self, scene: &Scene) { + let scale_factor = self.scale_factor(); + let mut state = self.0.lock(); + state.frame_callback_pending = true; + state.frame_scheduled = true; + let device_size: Size = state.bounds.size.to_device_pixels(scale_factor); + if let Some(renderer) = &mut state.renderer { + renderer.render_scene(scene, device_size).warn_on_err(); + } + } + + fn sprite_atlas(&self) -> sync::Arc { + self.0.lock().sprite_atlas.clone() + } + + #[cfg(any(test, feature = "test-support"))] + fn render_to_image(&self, scene: &Scene) -> anyhow::Result { + let scale_factor = self.scale_factor(); + let mut state = self.0.lock(); + let size = state.bounds.size; + if let Some(renderer) = &mut state.renderer { + let device_size: Size = size.to_device_pixels(scale_factor); + renderer.render_scene_to_image(scene, device_size) + } else { + anyhow::bail!("render_to_image not available: no HeadlessRenderer configured") + } + } + + fn as_test(&mut self) -> Option<&mut TestWindow> { + Some(self) + } + + #[cfg(target_os = "windows")] + fn get_raw_handle(&self) -> windows::Win32::Foundation::HWND { + unimplemented!() + } + + fn show_window_menu(&self, _position: Point) { + unimplemented!() + } + + fn start_window_move(&self) { + unimplemented!() + } + + fn can_start_external_drag(&self) -> bool { + true + } + + fn start_external_drag(&self, payload: &crate::ExternalDragPayload) -> bool { + let mut state = self.0.lock(); + match payload { + crate::ExternalDragPayload::Files(paths) => { + state.external_drag_files.extend_from_slice(paths.entries()); + } + } + state.start_external_drag_result + } + + fn update_ime_position(&self, _bounds: Bounds) {} + + fn gpu_specs(&self) -> Option { + None + } +} diff --git a/vendor/gpui-pre/src/platform/threaded_dispatcher.rs b/vendor/gpui-pre/src/platform/threaded_dispatcher.rs new file mode 100644 index 00000000..b1fb4974 --- /dev/null +++ b/vendor/gpui-pre/src/platform/threaded_dispatcher.rs @@ -0,0 +1,744 @@ +use std::{ + collections::BinaryHeap, + sync::Arc, + thread, + time::{Duration, Instant}, +}; + +use parking_lot::{Condvar, Mutex}; + +use crate::{ + PlatformDispatcher, Priority, RunnableVariant, profiler, + queue::{PriorityQueueReceiver, PriorityQueueSender}, +}; + +const MIN_THREADS: usize = 2; + +/// A multithreaded [`PlatformDispatcher`] for tests and benchmarks. +/// +/// Background tasks run in parallel on a pool of worker threads and timers fire +/// in real time on a dedicated timer thread, mirroring the production +/// dispatchers (see `LinuxDispatcher`). Main-thread tasks are queued until the +/// creating thread drains them via [`Self::run_until_idle`], since there is no +/// platform run loop pumping them. +/// +/// Unlike [`TestDispatcher`](crate::TestDispatcher), which runs everything on a +/// single thread with a virtual clock, work dispatched through this dispatcher +/// executes with production concurrency. +pub struct ThreadedDispatcher { + background_sender: PriorityQueueSender, + main_sender: PriorityQueueSender, + main_receiver: Mutex>, + timers: Arc, + idle: Arc, + main_thread_id: thread::ThreadId, +} + +/// Tracks how many background and timer runnables are queued or running so +/// [`ThreadedDispatcher::run_until_idle`] knows when to stop waiting. +#[derive(Default)] +struct IdleTracker { + inflight: Mutex, + condvar: Condvar, +} + +impl IdleTracker { + fn increment(&self) { + *self.inflight.lock() += 1; + } + + fn decrement(&self) { + let mut inflight = self.inflight.lock(); + *inflight -= 1; + if *inflight == 0 { + self.condvar.notify_all(); + } + } + + /// Returns a guard that decrements the in-flight count when dropped, so + /// the count stays correct even if the runnable being executed panics. + fn decrement_on_drop(&self) -> impl Drop + '_ { + gpui_util::defer(|| self.decrement()) + } + + /// Notifies waiters while holding the in-flight lock. `run_until_idle` + /// re-checks its wake conditions under this lock before waiting, so the + /// notification can't slip between its check and its wait and be lost. + fn notify_under_lock(&self) { + let _inflight = self.inflight.lock(); + self.condvar.notify_all(); + } +} + +struct TimerQueue { + state: Mutex, + condvar: Condvar, +} + +struct TimerQueueState { + heap: BinaryHeap, + next_seq: u64, +} + +struct TimerEntry { + due: Instant, + seq: u64, + runnable: RunnableVariant, +} + +impl PartialEq for TimerEntry { + fn eq(&self, other: &Self) -> bool { + self.due == other.due && self.seq == other.seq + } +} + +impl Eq for TimerEntry {} + +impl PartialOrd for TimerEntry { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for TimerEntry { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + // Reversed so that the entry with the earliest due time (breaking ties + // by insertion order) is at the top of the max-heap. + other + .due + .cmp(&self.due) + .then_with(|| other.seq.cmp(&self.seq)) + } +} + +impl Default for ThreadedDispatcher { + fn default() -> Self { + Self::new() + } +} + +impl ThreadedDispatcher { + /// Creates a dispatcher whose main thread is the calling thread. + /// + /// Worker and timer threads live for the lifetime of the process; the + /// dispatcher is expected to be created once and reused. + pub fn new() -> Self { + let (background_sender, background_receiver) = PriorityQueueReceiver::new(); + let (main_sender, main_receiver) = PriorityQueueReceiver::new(); + let idle = Arc::new(IdleTracker::default()); + + let thread_count = + thread::available_parallelism().map_or(MIN_THREADS, |i| i.get().max(MIN_THREADS)); + for i in 0..thread_count { + let mut receiver: PriorityQueueReceiver = background_receiver.clone(); + let idle = idle.clone(); + thread::Builder::new() + .name(format!("ThreadedDispatcherWorker-{i}")) + .spawn(move || { + while let Ok(runnable) = receiver.pop() { + let _decrement = idle.decrement_on_drop(); + let location = runnable.metadata().location; + let spawned = runnable.metadata().spawned; + profiler::update_running_task(spawned, location); + runnable.run(); + profiler::save_task_timing(); + } + }) + .expect("failed to spawn threaded dispatcher worker"); + } + drop(background_receiver); + + let timers = Arc::new(TimerQueue { + state: Mutex::new(TimerQueueState { + heap: BinaryHeap::new(), + next_seq: 0, + }), + condvar: Condvar::new(), + }); + { + let timers = timers.clone(); + let idle = idle.clone(); + thread::Builder::new() + .name("ThreadedDispatcherTimer".to_owned()) + .spawn(move || { + let mut state = timers.state.lock(); + loop { + let Some(entry) = state.heap.peek() else { + timers.condvar.wait(&mut state); + continue; + }; + let due = entry.due; + if due > Instant::now() { + timers.condvar.wait_until(&mut state, due); + continue; + } + let Some(entry) = state.heap.pop() else { + continue; + }; + // Count the firing timer as in-flight before releasing + // the lock so it can spawn follow-up work that + // `run_until_idle` will wait for. Lock order is always + // timer state, then in-flight count; `run_until_idle` + // never takes them in the opposite order. + idle.increment(); + drop(state); + + { + let _decrement = idle.decrement_on_drop(); + let location = entry.runnable.metadata().location; + let spawned = entry.runnable.metadata().spawned; + profiler::update_running_task(spawned, location); + entry.runnable.run(); + profiler::save_task_timing(); + } + + state = timers.state.lock(); + } + }) + .expect("failed to spawn threaded dispatcher timer"); + } + + Self { + background_sender, + main_sender, + main_receiver: Mutex::new(main_receiver), + timers, + idle, + main_thread_id: thread::current().id(), + } + } + + /// Runs queued main thread tasks and waits until no background or timer + /// work is queued, running, or already due. + /// + /// Timers that haven't reached their due time yet are *not* waited for: + /// the dispatcher runs in real time and cannot skip ahead like the + /// `TestDispatcher`'s virtual clock, so waiting on a future timer would + /// block for its full real duration. Tasks sleeping on such timers are + /// considered idle. Must be called on the thread that created this + /// dispatcher. + pub fn run_until_idle(&self) { + self.run_until_idle_with(|| self.drain_main_queue()); + } + + pub(crate) fn run_until_idle_with(&self, mut run_turn: impl FnMut() -> bool) { + assert!( + self.is_main_thread(), + "run_until_idle must be called on the threaded dispatcher's main thread" + ); + loop { + if run_turn() { + continue; + } + + // Checked before taking the in-flight lock; the timer thread + // locks them in the opposite order, so nesting would deadlock. + if self.has_due_timer() { + // Poll briefly: a firing timer leaves the heap just before it + // registers as in-flight. + let mut inflight = self.idle.inflight.lock(); + self.idle + .condvar + .wait_for(&mut inflight, Duration::from_millis(1)); + continue; + } + + let mut inflight = self.idle.inflight.lock(); + // Re-checked under the lock that `dispatch_on_main_thread` + // notifies under, so the notification can't be lost. + if self.main_queue_has_work() { + continue; + } + if *inflight == 0 { + // Main-thread sends happen before in-flight decrements, and + // decrements happen under this lock, so the check above + // observed all completed work. + return; + } + // Woken when main-thread work arrives or the in-flight count + // reaches zero; both notify under this lock. + self.idle.condvar.wait(&mut inflight); + } + } + + /// Drives main-thread work until `ready` returns a value. + /// + /// Unlike [`Self::run_until_idle`], this waits across temporary quiescence. + /// This is required when completion can arrive from an external worker that + /// is not represented in the dispatcher's in-flight count. + /// + /// Readiness is checked before every main-thread runnable, so this returns + /// as soon as `ready` observes completion rather than after the queue + /// drains — deferred work that re-queues itself (idle sweeps, pollers) + /// must not extend a benchmark's measured interval past the completion it + /// awaits. + #[cfg(test)] + pub(crate) fn run_until(&self, ready: impl FnMut() -> Option) -> R { + self.run_until_with_frames(ready, || false) + } + + /// Runs at most one queued main-thread task, returning whether one ran. + /// + /// Stepping tasks individually lets callers check completion between polls + /// even when work continually re-queues itself. + fn run_one_main_task(&self) -> bool { + assert!( + self.is_main_thread(), + "main tasks must run on the main thread" + ); + let runnable = self.main_receiver.lock().try_pop(); + match runnable { + Ok(Some(runnable)) => { + let location = runnable.metadata().location; + let spawned = runnable.metadata().spawned; + profiler::update_running_task(spawned, location); + runnable.run(); + profiler::save_task_timing(); + true + } + Ok(None) | Err(_) => false, + } + } + + /// Runs up to the initial queue length of main-thread tasks. + /// + /// Returns whether any ran. This snapshots the count, not task identities: + /// newly dispatched higher-priority tasks can overtake the original tasks. + pub fn run_ready_main_tasks(&self) -> bool { + self.run_ready_main_tasks_with(|| true, || {}) + } + + /// Runs a count-bounded ready turn, checking `should_continue` before every poll. + /// Calls `after_poll` after each runnable returns, outside the queue lock. + pub(crate) fn run_ready_main_tasks_with( + &self, + mut should_continue: impl FnMut() -> bool, + mut after_poll: impl FnMut(), + ) -> bool { + assert!( + self.is_main_thread(), + "run_ready_main_tasks must be called on the threaded dispatcher's main thread" + ); + let pending = self.main_receiver.lock().len(); + let mut ran_any = false; + for _ in 0..pending { + if !should_continue() || !self.run_one_main_task() { + break; + } + ran_any = true; + after_poll(); + } + ran_any + } + + #[cfg(any(test, feature = "bench-support"))] + pub(crate) fn run_until_with_frames( + &self, + mut ready: impl FnMut() -> Option, + mut dispatch_frames: impl FnMut() -> bool, + ) -> R { + assert!( + self.is_main_thread(), + "main tasks must run on the main thread" + ); + loop { + if let Some(result) = ready() { + return result; + } + let ran_task = self.run_one_main_task(); + // A completion poll must not pull an unrelated animation frame + // into the measured operation. + if let Some(result) = ready() { + return result; + } + let dispatched_frames = dispatch_frames(); + if ran_task || dispatched_frames { + continue; + } + + let mut inflight = self.idle.inflight.lock(); + if self.main_queue_has_work() { + continue; + } + self.idle.condvar.wait(&mut inflight); + } + } + + /// Cancels all pending timers so timers armed by one workload can't fire + /// during a later workload sharing this process-lifetime dispatcher. + /// + /// Dropping a timer runnable drops its completion sender, waking the task + /// awaiting the timer. Call [`Self::run_until_idle`] after this method to + /// drain any work that cancellation unblocks. + pub fn cancel_pending_timers(&self) -> usize { + let timers = { + let mut state = self.timers.state.lock(); + let timers: Vec<_> = state.heap.drain().collect(); + self.timers.condvar.notify_all(); + timers + }; + let canceled = timers.len(); + drop(timers); + canceled + } + + /// Describes the dispatcher's idle-tracking state, for diagnosing + /// workloads that fail to reach quiescence. + pub fn debug_state(&self) -> String { + let inflight = *self.idle.inflight.lock(); + let timers = self.timers.state.lock().heap.len(); + let main_queue_has_work = self.main_queue_has_work(); + format!( + "ThreadedDispatcher {{ inflight: {inflight}, pending_timers: {timers}, \ + main_queue_has_work: {main_queue_has_work} }}" + ) + } + + /// Whether no main-thread work is queued, no background or timer + /// runnables are queued or running, and no armed timer is due. Timers + /// that aren't due yet are ignored, as in [`Self::run_until_idle`]. + #[cfg(any(test, feature = "bench-support"))] + pub(crate) fn is_idle(&self) -> bool { + !self.main_queue_has_work() && !self.has_due_timer() && *self.idle.inflight.lock() == 0 + } + + fn has_due_timer(&self) -> bool { + let state = self.timers.state.lock(); + state + .heap + .peek() + .is_some_and(|entry| entry.due <= Instant::now()) + } + + fn main_queue_has_work(&self) -> bool { + !self.main_receiver.lock().is_empty() + } + + fn drain_main_queue(&self) -> bool { + let mut ran_any = false; + loop { + // Lock only around the pop so runnables can re-entrantly dispatch + // more main-thread work through the sender while they run. + let runnable = self.main_receiver.lock().try_pop(); + match runnable { + Ok(Some(runnable)) => { + let location = runnable.metadata().location; + let spawned = runnable.metadata().spawned; + profiler::update_running_task(spawned, location); + runnable.run(); + profiler::save_task_timing(); + ran_any = true; + } + Ok(None) | Err(_) => return ran_any, + } + } + } +} + +impl PlatformDispatcher for ThreadedDispatcher { + fn is_main_thread(&self) -> bool { + thread::current().id() == self.main_thread_id + } + + fn dispatch(&self, runnable: RunnableVariant, priority: Priority) { + self.idle.increment(); + self.background_sender + .send(priority, runnable) + .unwrap_or_else(|_| panic!("threaded dispatcher workers are no longer running")); + } + + fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority) { + if let Err(error) = self.main_sender.send(priority, runnable) { + // The main receiver lives as long as this dispatcher, so a failed + // send means we're mid-teardown. The runnable may wrap a !Send + // future, so forget it rather than dropping it on this thread + // (mirrors LinuxDispatcher). + std::mem::forget(error); + return; + } + // Wake `run_until_idle` if it's waiting for main-thread work. + self.idle.notify_under_lock(); + } + + fn dispatch_after(&self, duration: Duration, runnable: RunnableVariant) { + let mut state = self.timers.state.lock(); + let seq = state.next_seq; + state.next_seq += 1; + state.heap.push(TimerEntry { + due: Instant::now() + duration, + seq, + runnable, + }); + self.timers.condvar.notify_one(); + } + + fn spawn_realtime(&self, f: Box) { + // This dispatcher does not need realtime scheduling priority; a plain + // thread keeps it portable. + thread::Builder::new() + .name("ThreadedDispatcherRealtime".to_owned()) + .spawn(f) + .expect("failed to spawn threaded dispatcher realtime thread"); + } + + fn as_threaded(&self) -> Option<&ThreadedDispatcher> { + Some(self) + } +} + +#[cfg(test)] +mod tests { + use std::future::Future; + use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + + use super::*; + use crate::{BackgroundExecutor, ForegroundExecutor}; + + #[test] + fn is_idle_tracks_queued_work_but_ignores_undue_timers() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + assert!(dispatcher.is_idle()); + + foreground.spawn(async {}).detach(); + assert!(!dispatcher.is_idle()); + dispatcher.run_until_idle(); + assert!(dispatcher.is_idle()); + + let background = BackgroundExecutor::new(dispatcher.clone()); + let timer = background.timer(Duration::from_secs(60)); + // The timer future's initial poll runs on a worker thread; wait for + // it so only the armed, not-yet-due timer remains. + dispatcher.run_until_idle(); + assert!( + dispatcher.is_idle(), + "a timer that is not due yet should not count as pending work" + ); + drop(timer); + dispatcher.cancel_pending_timers(); + dispatcher.run_until_idle(); + assert!(dispatcher.is_idle()); + } + + #[test] + fn run_ready_main_tasks_does_not_wait_for_background_handoffs() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let background = BackgroundExecutor::new(dispatcher.clone()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + + let (sender, receiver) = futures::channel::oneshot::channel(); + background + .spawn(async move { + thread::sleep(Duration::from_millis(10)); + sender.send(()).ok(); + }) + .detach(); + + let completed = Arc::new(AtomicBool::new(false)); + foreground + .spawn({ + let completed = completed.clone(); + async move { + receiver.await.ok(); + completed.store(true, Ordering::SeqCst); + } + }) + .detach(); + + assert!(dispatcher.run_ready_main_tasks()); + assert!(!completed.load(Ordering::SeqCst)); + + dispatcher.run_until_idle(); + assert!(completed.load(Ordering::SeqCst)); + } + + #[test] + fn run_until_idle_completes_background_to_main_handoffs() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let background = BackgroundExecutor::new(dispatcher.clone()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + + let (sender, receiver) = futures::channel::oneshot::channel(); + background + .spawn(async move { + thread::sleep(Duration::from_millis(10)); + sender.send(()).ok(); + }) + .detach(); + + let completed = Arc::new(AtomicBool::new(false)); + foreground + .spawn({ + let completed = completed.clone(); + async move { + receiver.await.ok(); + completed.store(true, Ordering::SeqCst); + } + }) + .detach(); + + dispatcher.run_until_idle(); + assert!(completed.load(Ordering::SeqCst)); + } + + #[test] + fn run_until_waits_for_untracked_external_wakes() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + let (sender, receiver) = futures::channel::oneshot::channel(); + let sender_thread = thread::spawn(move || { + thread::sleep(Duration::from_millis(10)); + sender + .send(()) + .expect("foreground receiver should remain alive"); + }); + + let completed = Arc::new(AtomicBool::new(false)); + foreground + .spawn({ + let completed = completed.clone(); + async move { + receiver + .await + .expect("external sender should deliver its wake"); + completed.store(true, Ordering::SeqCst); + } + }) + .detach(); + + dispatcher.run_until(|| completed.load(Ordering::SeqCst).then_some(())); + sender_thread.join().expect("sender thread should finish"); + assert!(completed.load(Ordering::SeqCst)); + } + + #[test] + fn run_until_returns_at_readiness_despite_requeuing_main_work() { + const REQUEUE_LIMIT: usize = 10_000; + + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + + // Mirrors main-thread work that yields and immediately re-queues + // itself (e.g. an idle-time sweep): the main queue never drains until + // such work finishes every iteration, so readiness must be observed + // between runnables rather than only at quiescence. + let iterations = Arc::new(AtomicUsize::new(0)); + foreground + .spawn({ + let iterations = iterations.clone(); + async move { + for _ in 0..REQUEUE_LIMIT { + iterations.fetch_add(1, Ordering::SeqCst); + yield_once().await; + } + } + }) + .detach(); + + let completed = Arc::new(AtomicBool::new(false)); + foreground + .spawn({ + let completed = completed.clone(); + async move { + completed.store(true, Ordering::SeqCst); + } + }) + .detach(); + + dispatcher.run_until(|| completed.load(Ordering::SeqCst).then_some(())); + assert!( + iterations.load(Ordering::SeqCst) < REQUEUE_LIMIT, + "run_until should return at readiness instead of draining re-queued main work" + ); + } + + /// Completes after one re-schedule: the poll returns `Pending` and wakes + /// immediately, so the runnable re-enters the main queue. + fn yield_once() -> impl Future { + let mut yielded = false; + std::future::poll_fn(move |poll_context| { + if yielded { + std::task::Poll::Ready(()) + } else { + yielded = true; + poll_context.waker().wake_by_ref(); + std::task::Poll::Pending + } + }) + } + + #[test] + fn run_ready_main_tasks_advances_requeuing_work_one_batch_per_call() { + const REQUEUE_LIMIT: usize = 10_000; + + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let foreground = ForegroundExecutor::new(dispatcher.clone()); + + let iterations = Arc::new(AtomicUsize::new(0)); + foreground + .spawn({ + let iterations = iterations.clone(); + async move { + for _ in 0..REQUEUE_LIMIT { + iterations.fetch_add(1, Ordering::SeqCst); + yield_once().await; + } + } + }) + .detach(); + + assert!(dispatcher.run_ready_main_tasks()); + assert_eq!(iterations.load(Ordering::SeqCst), 1); + assert!(dispatcher.run_ready_main_tasks()); + assert_eq!(iterations.load(Ordering::SeqCst), 2); + } + + #[test] + fn timers_fire_in_real_time() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let background = BackgroundExecutor::new(dispatcher); + + let fired = Arc::new(AtomicBool::new(false)); + let timer = background.timer(Duration::from_millis(10)); + background + .spawn({ + let fired = fired.clone(); + async move { + timer.await; + fired.store(true, Ordering::SeqCst); + } + }) + .detach(); + + let deadline = Instant::now() + Duration::from_secs(10); + while !fired.load(Ordering::SeqCst) && Instant::now() < deadline { + thread::sleep(Duration::from_millis(1)); + } + assert!(fired.load(Ordering::SeqCst)); + } + + #[test] + fn cancel_pending_timers_wakes_waiters_without_waiting_for_deadline() { + let dispatcher = Arc::new(ThreadedDispatcher::new()); + let background = BackgroundExecutor::new(dispatcher.clone()); + + let fired = Arc::new(AtomicBool::new(false)); + let timer = background.timer(Duration::from_secs(10)); + background + .spawn({ + let fired = fired.clone(); + async move { + timer.await; + fired.store(true, Ordering::SeqCst); + } + }) + .detach(); + + dispatcher.run_until_idle(); + assert_eq!(dispatcher.cancel_pending_timers(), 1); + dispatcher.run_until_idle(); + + assert!(fired.load(Ordering::SeqCst)); + assert_eq!(dispatcher.cancel_pending_timers(), 0); + } +} diff --git a/vendor/gpui-pre/src/platform/visual_test.rs b/vendor/gpui-pre/src/platform/visual_test.rs new file mode 100644 index 00000000..0454c310 --- /dev/null +++ b/vendor/gpui-pre/src/platform/visual_test.rs @@ -0,0 +1,272 @@ +//! Visual test platform that combines real rendering (macOs-only for now) with controllable TestDispatcher. +//! +//! This platform is used for visual tests that need: +//! - Real rendering (e.g. Metal/compositor) for accurate screenshots +//! - Deterministic task scheduling via TestDispatcher +//! - Controllable time via `advance_clock` + +use crate::ScreenCaptureSource; +use crate::{ + ActivityGuard, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, + ForegroundExecutor, Keymap, Menu, MenuItem, OwnedMenu, PathPromptOptions, Platform, + PlatformDisplay, PlatformKeyboardLayout, PlatformKeyboardMapper, PlatformTextSystem, + PlatformWindow, Task, TestDispatcher, WindowAppearance, WindowParams, +}; +use anyhow::Result; +use futures::channel::oneshot; +use parking_lot::Mutex; + +use std::{ + path::{Path, PathBuf}, + rc::Rc, + sync::Arc, +}; + +/// A platform that combines real Mac rendering with controllable TestDispatcher. +/// +/// This allows visual tests to: +/// - Render real UI via Metal for accurate screenshots +/// - Control task scheduling deterministically via TestDispatcher +/// - Advance simulated time for testing time-based behaviors (tooltips, animations, etc.) +pub struct VisualTestPlatform { + dispatcher: TestDispatcher, + background_executor: BackgroundExecutor, + foreground_executor: ForegroundExecutor, + platform: Rc, + clipboard: Mutex>, + find_pasteboard: Mutex>, +} + +impl VisualTestPlatform { + /// Creates a new VisualTestPlatform with the given random seed. + /// + /// The seed is used for deterministic random number generation in the TestDispatcher. + pub fn new(platform: Rc, seed: u64) -> Self { + let dispatcher = TestDispatcher::new(seed); + let arc_dispatcher = Arc::new(dispatcher.clone()); + + let background_executor = BackgroundExecutor::new(arc_dispatcher.clone()); + let foreground_executor = ForegroundExecutor::new(arc_dispatcher); + + Self { + dispatcher, + background_executor, + foreground_executor, + platform, + clipboard: Mutex::new(None), + find_pasteboard: Mutex::new(None), + } + } + + /// Returns a reference to the TestDispatcher for controlling task scheduling and time. + pub fn dispatcher(&self) -> &TestDispatcher { + &self.dispatcher + } +} + +impl Platform for VisualTestPlatform { + fn background_executor(&self) -> BackgroundExecutor { + self.background_executor.clone() + } + + fn foreground_executor(&self) -> ForegroundExecutor { + self.foreground_executor.clone() + } + + fn text_system(&self) -> Arc { + self.platform.text_system() + } + + fn run(&self, _on_finish_launching: Box) { + panic!("VisualTestPlatform::run should not be called in tests") + } + + fn quit(&self) {} + + fn restart(&self, _binary_path: Option, _arguments: Vec) {} + + fn activate(&self, _ignoring_other_apps: bool) {} + + fn hide(&self) {} + + fn hide_other_apps(&self) {} + + fn unhide_other_apps(&self) {} + + fn displays(&self) -> Vec> { + self.platform.displays() + } + + fn primary_display(&self) -> Option> { + self.platform.primary_display() + } + + fn active_window(&self) -> Option { + self.platform.active_window() + } + + fn window_stack(&self) -> Option> { + self.platform.window_stack() + } + + fn is_screen_capture_supported(&self) -> bool { + self.platform.is_screen_capture_supported() + } + + fn screen_capture_sources( + &self, + ) -> oneshot::Receiver>>> { + self.platform.screen_capture_sources() + } + + fn open_window( + &self, + handle: AnyWindowHandle, + options: WindowParams, + ) -> Result> { + self.platform.open_window(handle, options) + } + + fn window_appearance(&self) -> WindowAppearance { + self.platform.window_appearance() + } + + fn open_url(&self, url: &str) { + self.platform.open_url(url) + } + + fn on_open_urls(&self, _callback: Box)>) {} + + fn register_url_scheme(&self, _url: &str) -> Task> { + Task::ready(Ok(())) + } + + fn prompt_for_paths( + &self, + _options: PathPromptOptions, + ) -> oneshot::Receiver>>> { + let (tx, rx) = oneshot::channel(); + tx.send(Ok(None)).ok(); + rx + } + + fn prompt_for_new_path( + &self, + _directory: &Path, + _suggested_name: Option<&str>, + ) -> oneshot::Receiver>> { + let (tx, rx) = oneshot::channel(); + tx.send(Ok(None)).ok(); + rx + } + + fn can_select_mixed_files_and_dirs(&self) -> bool { + true + } + + fn reveal_path(&self, path: &Path) { + self.platform.reveal_path(path) + } + + fn open_with_system(&self, path: &Path) { + self.platform.open_with_system(path) + } + + fn on_quit(&self, _callback: Box bool>) {} + + fn on_reopen(&self, _callback: Box) {} + + fn on_system_sleep(&self, _callback: Box) {} + + fn on_system_wake(&self, _callback: Box) {} + + fn set_menus(&self, _menus: Vec, _keymap: &Keymap) {} + + fn get_menus(&self) -> Option> { + None + } + + fn set_dock_menu(&self, _menu: Vec, _keymap: &Keymap) {} + + fn on_app_menu_action(&self, _callback: Box) {} + + fn on_will_open_app_menu(&self, _callback: Box) {} + + fn on_validate_app_menu_command(&self, _callback: Box bool>) {} + + fn app_path(&self) -> Result { + self.platform.app_path() + } + + fn path_for_auxiliary_executable(&self, name: &str) -> Result { + self.platform.path_for_auxiliary_executable(name) + } + + fn set_cursor_style(&self, style: CursorStyle) { + self.platform.set_cursor_style(style) + } + + fn hide_cursor_until_mouse_moves(&self) { + self.platform.hide_cursor_until_mouse_moves(); + } + + fn is_cursor_visible(&self) -> bool { + self.platform.is_cursor_visible() + } + + fn should_auto_hide_scrollbars(&self) -> bool { + self.platform.should_auto_hide_scrollbars() + } + + fn read_from_clipboard(&self) -> Option { + self.clipboard.lock().clone() + } + + fn write_to_clipboard(&self, item: ClipboardItem) { + *self.clipboard.lock() = Some(item); + } + + #[cfg(target_os = "macos")] + fn read_from_find_pasteboard(&self) -> Option { + self.find_pasteboard.lock().clone() + } + + #[cfg(target_os = "macos")] + fn write_to_find_pasteboard(&self, item: ClipboardItem) { + *self.find_pasteboard.lock() = Some(item); + } + + fn write_credentials(&self, _url: &str, _username: &str, _password: &[u8]) -> Task> { + Task::ready(Ok(())) + } + + fn read_credentials(&self, _url: &str) -> Task)>>> { + Task::ready(Ok(None)) + } + + fn delete_credentials(&self, _url: &str) -> Task> { + Task::ready(Ok(())) + } + + fn keyboard_layout(&self) -> Box { + self.platform.keyboard_layout() + } + + fn keyboard_mapper(&self) -> Rc { + self.platform.keyboard_mapper() + } + + fn on_keyboard_layout_change(&self, _callback: Box) {} + + fn thermal_state(&self) -> super::ThermalState { + super::ThermalState::Nominal + } + + fn on_thermal_state_change(&self, _callback: Box) {} + + fn prevent_idle_sleep(&self, reason: &str) -> Task> { + Task::ready(Err(anyhow::anyhow!( + "Idle sleep prevention for {reason:?} is not supported in visual tests" + ))) + } +} diff --git a/vendor/gpui-pre/src/platform_scheduler.rs b/vendor/gpui-pre/src/platform_scheduler.rs new file mode 100644 index 00000000..a555a5a3 --- /dev/null +++ b/vendor/gpui-pre/src/platform_scheduler.rs @@ -0,0 +1,457 @@ +use crate::{PlatformDispatcher, RunnableMeta}; +use async_task::Runnable; +use chrono::{DateTime, Utc}; +use futures::channel::oneshot; +use scheduler::Instant; +use scheduler::{ + Clock, LocalExecutor, Priority, Scheduler, SessionId, Task, TestScheduler, Timer, + spawn_dedicated_thread, +}; +#[cfg(not(target_family = "wasm"))] +use std::task::{Context, Poll}; +use std::{ + any::Any, + future::Future, + pin::Pin, + sync::{ + Arc, + atomic::{AtomicU16, Ordering}, + }, + time::Duration, +}; + +/// A production implementation of [`Scheduler`] that wraps a [`PlatformDispatcher`]. +/// +/// This allows GPUI to use the scheduler crate's executor types with the platform's +/// native dispatch mechanisms (e.g., Grand Central Dispatch on macOS). +pub struct PlatformScheduler { + dispatcher: Arc, + clock: Arc, + next_session_id: AtomicU16, + #[cfg(feature = "profiler")] + foreground_runnables: crate::profiler::journal::ForegroundRunnableCounter, +} + +impl PlatformScheduler { + pub fn new(dispatcher: Arc) -> Self { + Self { + dispatcher: dispatcher.clone(), + clock: Arc::new(PlatformClock { dispatcher }), + next_session_id: AtomicU16::new(0), + #[cfg(feature = "profiler")] + foreground_runnables: crate::profiler::journal::foreground_runnable_counter(), + } + } + + pub fn foreground_executor(self: &Arc) -> LocalExecutor { + let session_id = self.next_session_id(); + let scheduler = Arc::downgrade(self); + LocalExecutor::new(session_id, self.clone(), move |runnable| { + if let Some(scheduler) = scheduler.upgrade() { + scheduler.schedule_local(session_id, runnable); + } + }) + } + + fn next_session_id(&self) -> SessionId { + SessionId::new(self.next_session_id.fetch_add(1, Ordering::SeqCst)) + } + + #[cfg(feature = "profiler")] + pub(crate) fn foreground_runnable_counter( + &self, + ) -> crate::profiler::journal::ForegroundRunnableCounter { + self.foreground_runnables.clone() + } +} + +impl Scheduler for PlatformScheduler { + #[cfg(not(target_family = "wasm"))] + fn block( + &self, + _session_id: Option, + mut future: Pin<&mut dyn Future>, + timeout: Option, + ) -> bool { + use waker_fn::waker_fn; + let deadline = timeout.map(|t| Instant::now() + t); + let parker = parking::Parker::new(); + let unparker = parker.unparker(); + let waker = waker_fn(move || { + unparker.unpark(); + }); + let mut cx = Context::from_waker(&waker); + if let Poll::Ready(()) = future.as_mut().poll(&mut cx) { + return true; + } + + let park_deadline = |deadline: Instant| { + // Timer expirations are only delivered every ~15.6 milliseconds by default on Windows. + // We increase the resolution during this wait so that short timeouts stay reasonably short. + let _timer_guard = self.dispatcher.increase_timer_resolution(); + parker.park_deadline(deadline) + }; + + loop { + match deadline { + Some(deadline) if !park_deadline(deadline) && deadline <= Instant::now() => { + return false; + } + Some(_) => (), + None => parker.park(), + } + if let Poll::Ready(()) = future.as_mut().poll(&mut cx) { + break true; + } + } + } + + fn schedule_local(&self, _session_id: SessionId, runnable: Runnable) { + #[cfg(feature = "profiler")] + self.foreground_runnables.queued(); + self.dispatcher + .dispatch_on_main_thread(runnable, Priority::default()); + } + + fn schedule_background_with_priority( + &self, + runnable: Runnable, + priority: Priority, + ) { + self.dispatcher.dispatch(runnable, priority); + } + + fn spawn_realtime(&self, f: Box) { + self.dispatcher.spawn_realtime(f); + } + + #[track_caller] + fn timer(&self, duration: Duration) -> Timer { + let (tx, rx) = oneshot::channel(); + let dispatcher = self.dispatcher.clone(); + + // Create a runnable that will send the completion signal + let location = std::panic::Location::caller(); + let (runnable, _task) = async_task::Builder::new() + .metadata(RunnableMeta { + location, + spawned: scheduler::SpawnTime(Instant::now()), + }) + .spawn( + move |_| async move { + let _ = tx.send(()); + }, + move |runnable| { + dispatcher.dispatch_after(duration, runnable); + }, + ); + runnable.schedule(); + + Timer::new(rx) + } + + fn clock(&self) -> Arc { + self.clock.clone() + } + + fn spawn_dedicated( + self: Arc, + f: Box< + dyn FnOnce( + LocalExecutor, + ) + -> Pin> + 'static>> + + Send + + 'static, + >, + ) -> Task> { + let session_id = self.next_session_id(); + spawn_dedicated_thread(session_id, self, move |executor| f(executor)) + } + + fn as_test(&self) -> Option<&TestScheduler> { + None + } +} + +/// A production clock that uses the platform dispatcher's time. +struct PlatformClock { + dispatcher: Arc, +} + +impl Clock for PlatformClock { + fn utc_now(&self) -> DateTime { + Utc::now() + } + + fn now(&self) -> Instant { + self.dispatcher.now() + } +} + +#[cfg(all(test, not(target_family = "wasm")))] +mod tests { + use super::*; + use crate::RunnableVariant; + use scheduler::BackgroundExecutor; + use std::time::Instant as StdInstant; + + // `spawn_dedicated` shouldn't touch the platform dispatcher at all; + // panicking on every method ensures the test catches it if it does. + struct SmokeDispatcher; + + impl PlatformDispatcher for SmokeDispatcher { + fn is_main_thread(&self) -> bool { + false + } + fn dispatch(&self, _runnable: RunnableVariant, _priority: Priority) { + panic!("SmokeDispatcher should not be asked to dispatch in this test"); + } + fn dispatch_on_main_thread(&self, _runnable: RunnableVariant, _priority: Priority) { + panic!("SmokeDispatcher does not implement a main thread"); + } + fn dispatch_after(&self, _duration: Duration, _runnable: RunnableVariant) { + panic!("SmokeDispatcher does not implement timers"); + } + fn spawn_realtime(&self, _f: Box) { + panic!("SmokeDispatcher does not implement realtime"); + } + } + + #[test] + fn dedicated_executor_tasks_share_one_thread() { + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + let dedicated = scheduler::DedicatedExecutor::new(&background); + + let first = dedicated.spawn(async { std::thread::current().id() }); + let second = dedicated.spawn(async { std::thread::current().id() }); + + let first = futures::executor::block_on(first); + let second = futures::executor::block_on(second); + + assert_eq!(first, second, "tasks must share the dedicated thread"); + assert_ne!( + first, + std::thread::current().id(), + "dedicated tasks must not run on the spawning thread" + ); + } + + #[test] + fn spawn_dedicated_runs_on_a_real_separate_thread() { + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + let started = StdInstant::now(); + let task = background.spawn_dedicated(|_executor| async move { + // A genuine blocking syscall on the dedicated thread. If + // `spawn_dedicated` were running the future on any shared + // executor, this would stall that executor. + let thread_id_before = std::thread::current().id(); + std::thread::sleep(Duration::from_millis(50)); + let thread_id_after = std::thread::current().id(); + assert_eq!(thread_id_before, thread_id_after); + (thread_id_before, "slept") + }); + let (dedicated_thread_id, message) = futures::executor::block_on(task); + let elapsed = started.elapsed(); + assert_eq!(message, "slept"); + assert_ne!( + dedicated_thread_id, + std::thread::current().id(), + "dedicated future ran on the test thread" + ); + assert!( + elapsed >= Duration::from_millis(40), + "expected the dedicated thread to genuinely sleep, elapsed = {:?}", + elapsed + ); + } + + #[test] + fn spawn_dedicated_returns_not_send_future_output() { + // The whole point of `spawn_dedicated` is that the future can be + // `!Send`. Constructing one with `Rc>` ensures the + // signature actually permits it. + use std::cell::RefCell; + use std::rc::Rc; + + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + let task = background.spawn_dedicated(|_executor| async move { + let state = Rc::new(RefCell::new(0_i32)); + for _ in 0..3 { + *state.borrow_mut() += 1; + } + *state.borrow() + }); + let output = futures::executor::block_on(task); + assert_eq!(output, 3); + } + + #[test] + fn spawn_dedicated_dropping_task_cancels_future() { + use parking_lot::Mutex; + use std::sync::mpsc; + + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + + let (started_tx, started_rx) = mpsc::channel::<()>(); + let (after_park_tx, after_park_rx) = mpsc::channel::<()>(); + let observed_post_await_write = Arc::new(Mutex::new(false)); + + let task = { + let observed_post_await_write = observed_post_await_write.clone(); + background.spawn_dedicated(move |_executor| async move { + // Announce that the future is live on the dedicated thread. + started_tx + .send(()) + .expect("started signal must be received"); + // Park forever. Dropping the `Task` must cancel us here so + // the code below this `await` never runs. + futures::future::pending::<()>().await; + *observed_post_await_write.lock() = true; + after_park_tx + .send(()) + .expect("after-park signal must be received"); + }) + }; + + // Wait until the dedicated future is actually parked at the await. + started_rx + .recv_timeout(Duration::from_secs(2)) + .expect("dedicated future failed to start"); + + // Drop the root Task: this must cancel the future. + drop(task); + + // If cancellation works, the future never advances past `pending`, + // so this recv must time out. + assert!( + after_park_rx + .recv_timeout(Duration::from_millis(100)) + .is_err(), + "dedicated future advanced past the await after its Task was dropped" + ); + assert!( + !*observed_post_await_write.lock(), + "dedicated future ran code past the cancellation point" + ); + } + + #[test] + fn spawn_dedicated_thread_tears_down_after_work_completes() { + use std::sync::mpsc; + + // Fires from `Drop` so we observe teardown of the dedicated future's + // captured state on whichever thread runs its destructor. + struct DropSignal { + tx: Option>, + } + impl Drop for DropSignal { + fn drop(&mut self) { + if let Some(tx) = self.tx.take() { + let _ = tx.send(std::thread::current().id()); + } + } + } + + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + let (started_tx, started_rx) = mpsc::channel::(); + let (drop_tx, drop_rx) = mpsc::channel::(); + + let task = background.spawn_dedicated(move |_executor| async move { + // Captured by the future's state. When the future completes and + // its state is dropped on the dedicated thread, this guard's + // `Drop` fires and reports the thread id it ran on. + let _guard = DropSignal { tx: Some(drop_tx) }; + started_tx + .send(std::thread::current().id()) + .expect("started signal must be received"); + // Future returns immediately. The dedicated thread should then + // drop the future (firing _guard), exit the recv loop, and exit. + }); + + let dedicated_thread_id = started_rx + .recv_timeout(Duration::from_secs(2)) + .expect("dedicated future failed to start"); + assert_ne!( + dedicated_thread_id, + std::thread::current().id(), + "dedicated future ran on the test thread" + ); + + // Drive the root task to completion so its body finishes. + futures::executor::block_on(task); + + // The guard's drop runs from the dedicated thread as it tears down + // the future's captured state. If the executor/recv-loop were + // keeping the future alive past task completion, this would hang. + let drop_thread_id = drop_rx + .recv_timeout(Duration::from_secs(2)) + .expect("dedicated future's captured state was not dropped after task completion"); + assert_eq!( + drop_thread_id, dedicated_thread_id, + "dedicated future's captured state must be dropped on the dedicated thread, not elsewhere" + ); + } + + #[test] + fn spawn_dedicated_detached_child_outlives_root() { + use std::sync::mpsc; + + let background = + BackgroundExecutor::new(Arc::new(PlatformScheduler::new(Arc::new(SmokeDispatcher)))); + + // `gate_rx` lets the detached child park until the test explicitly + // releases it — after we've already observed the root completing. + let (gate_tx, gate_rx) = mpsc::channel::<()>(); + let (child_done_tx, child_done_rx) = mpsc::channel::(); + + let task = background.spawn_dedicated(move |executor| async move { + executor + .spawn(async move { + // Blocking on `recv` is normally wrong inside an + // executor, but the dedicated thread is exclusive to + // this session, so blocking the only future on it is + // fine — this is the property `spawn_dedicated` is + // designed to provide. + gate_rx + .recv() + .expect("gate sender dropped before child resumed"); + child_done_tx + .send(std::thread::current().id()) + .expect("child_done receiver dropped"); + }) + .detach(); + // Root finishes here. The detached child must keep the + // dedicated thread alive until it completes. + }); + + futures::executor::block_on(task); + + // Negative assertion: the child has not finished, because the gate + // hasn't been released yet. + assert!( + child_done_rx + .recv_timeout(Duration::from_millis(50)) + .is_err(), + "detached child finished before being released" + ); + + // Release the gate. The detached child should now complete on the + // dedicated thread. + gate_tx.send(()).expect("gate receiver dropped"); + + let child_thread_id = child_done_rx + .recv_timeout(Duration::from_secs(2)) + .expect("detached child failed to complete after gate was released"); + assert_ne!( + child_thread_id, + std::thread::current().id(), + "detached child ran on the test thread instead of the dedicated thread" + ); + } +} diff --git a/vendor/gpui-pre/src/prelude.rs b/vendor/gpui-pre/src/prelude.rs new file mode 100644 index 00000000..b5185a25 --- /dev/null +++ b/vendor/gpui-pre/src/prelude.rs @@ -0,0 +1,9 @@ +//! The GPUI prelude is a collection of traits and types that are widely used +//! throughout the library. It is recommended to import this prelude into your +//! application to avoid having to import each trait individually. + +pub use crate::{ + AppContext as _, BorrowAppContext, Context, Element, InteractiveElement, IntoElement, + ParentElement, Refineable, Render, RenderOnce, StatefulInteractiveElement, Styled, StyledImage, + TaskExt as _, VisualContext, util::FluentBuilder, +}; diff --git a/vendor/gpui-pre/src/profiler.rs b/vendor/gpui-pre/src/profiler.rs new file mode 100644 index 00000000..e8108c10 --- /dev/null +++ b/vendor/gpui-pre/src/profiler.rs @@ -0,0 +1,1644 @@ +#[cfg(feature = "profiler")] +use hdrhistogram::Histogram; +use itertools::Itertools; +use scheduler::{Instant, SpawnTime}; +#[cfg(feature = "profiler")] +use smallvec::SmallVec; +use std::{ + cell::LazyCell, + collections::{HashMap, VecDeque}, + hash::{DefaultHasher, Hash, Hasher}, + sync::{ + Arc, + atomic::{AtomicU64, Ordering}, + }, + thread::ThreadId, + time::Duration, +}; + +mod actions; +#[cfg(feature = "profiler")] +pub mod hang; +#[cfg(feature = "profiler")] +pub mod journal; +pub use actions::{ActionStatistics, ActionTiming, take_action_stats}; + +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "profiler")] +use crate::{Action, App, WindowId}; +use crate::{SharedString, TasksIncluded}; + +#[cfg(feature = "profiler")] +#[doc(hidden)] +pub fn get_all_timings(included: gpui::TasksIncluded) -> Vec { + ThreadTaskTimings::collect(upgraded_thread_timings(), included) +} + +#[cfg(feature = "profiler")] +#[doc(hidden)] +pub fn get_current_thread_timings(included: TasksIncluded) -> gpui::ThreadTaskTimings { + gpui::profiler::get_current_thread_task_timings(included) +} + +#[cfg(feature = "profiler")] +#[doc(hidden)] +pub fn take_all_stats(included: TasksIncluded) -> Vec { + ThreadTaskStatistics::collect_and_reset(upgraded_thread_timings(), included) +} + +#[cfg(not(feature = "profiler"))] +#[doc(hidden)] +pub fn get_all_timings(_included: gpui::TasksIncluded) -> Vec { + Vec::new() +} +#[cfg(not(feature = "profiler"))] +#[doc(hidden)] +pub fn get_current_thread_timings(_included: TasksIncluded) -> gpui::ThreadTaskTimings { + gpui::ThreadTaskTimings { + thread_name: None, + thread_id: std::thread::current().id(), + timings: Vec::new(), + stats: TaskStatistics::default(), + total_pushed: 0, + } +} +#[cfg(not(feature = "profiler"))] +#[doc(hidden)] +pub fn take_all_stats(_included: TasksIncluded) -> Vec { + Vec::new() +} + +#[doc(hidden)] +#[derive(Debug, Copy, Clone)] +pub struct YieldTime(pub Instant); + +#[doc(hidden)] +#[derive(Copy, Clone)] +pub struct TaskTiming { + pub location: &'static core::panic::Location<'static>, + pub spawned: SpawnTime, + pub start: Instant, + pub end: YieldTime, +} + +impl std::fmt::Debug for TaskTiming { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TaskTiming") + .field("location", &self.location) + .field("since_spawned", &self.spawned.0.elapsed()) + .field("last_poll_duration", &self.poll_duration()) + .field("total_runtime", &self.since_spawn()) + .finish() + } +} + +#[doc(hidden)] +#[derive(Debug, Copy, Clone)] +pub struct ActiveTiming { + pub location: &'static core::panic::Location<'static>, + pub spawned: SpawnTime, + pub start: Instant, +} + +impl TaskTiming { + /// A task timing with a duration of zero. Any task will replace this in history. + pub fn placeholder() -> Self { + let now = Instant::now(); + Self { + location: std::panic::Location::caller(), + spawned: SpawnTime(now), + start: now, + end: YieldTime(now), + } + } + + #[inline(always)] + pub fn poll_duration(&self) -> Duration { + self.end.0 - self.start + } + + #[inline(always)] + fn since_spawn(&self) -> Duration { + self.end.0 - self.spawned.0 + } +} + +#[doc(hidden)] +#[derive(Debug, Clone)] +pub struct ThreadTaskTimings { + pub thread_name: Option, + pub thread_id: ThreadId, + pub timings: Vec, + pub stats: TaskStatistics, + pub total_pushed: u64, +} + +impl ThreadTaskTimings { + /// Convert upgraded per-thread timings into their structured format. + pub fn collect( + timings: Vec<(ThreadId, Arc)>, + included: TasksIncluded, + ) -> Vec { + timings + .into_iter() + .map(|(thread_id, timings)| { + let timings = timings.lock(); + let thread_name = timings.thread_name.clone(); + let total_pushed = timings.total_pushed; + let completed = &timings.timings; + + let mut vec = Vec::with_capacity(completed.len() + 1); // +1 for running task + let (s1, s2) = completed.as_slices(); + vec.extend_from_slice(s1); + vec.extend_from_slice(s2); + if let TasksIncluded::CompletedAndRunning = included + && let Some(running) = timings.running + { + vec.push(TaskTiming { + location: running.location, + spawned: running.spawned, + start: running.start, + end: YieldTime(Instant::now()), + }) + } + + ThreadTaskTimings { + thread_name, + thread_id, + timings: vec, + stats: timings.stats.clone(), + total_pushed, + } + }) + .collect() + } +} + +#[doc(hidden)] +#[derive(Debug)] +pub struct ThreadTaskStatistics { + pub thread_name: Option, + pub thread_id: ThreadId, + pub stats: TaskStatistics, +} + +impl ThreadTaskStatistics { + pub fn collect_and_reset( + timings: Vec<(ThreadId, Arc)>, + include_running: TasksIncluded, + ) -> Vec { + timings + .into_iter() + .map(|(thread_id, timings)| { + let mut timings = timings.lock(); + let thread_name = timings.thread_name.clone(); + + let mut stats = std::mem::take(&mut timings.stats); + if let TasksIncluded::CompletedAndRunning = include_running + && let Some(ActiveTiming { + location, + spawned, + start, + }) = timings.running + { + let end = YieldTime(Instant::now()); + let timing = TaskTiming { + location, + spawned, + start, + end, + }; + stats.add_runtime(timing); + stats.add_yield_timing(timing); + } + + Self { + thread_name, + thread_id, + stats, + } + }) + .collect() + } +} + +/// Serializable variant of [`core::panic::Location`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SerializedLocation { + /// Name of the source file + pub file: SharedString, + /// Line in the source file + pub line: u32, + /// Column in the source file + pub column: u32, +} + +impl From<&core::panic::Location<'static>> for SerializedLocation { + fn from(value: &core::panic::Location<'static>) -> Self { + SerializedLocation { + file: value.file().into(), + line: value.line(), + column: value.column(), + } + } +} + +/// Serializable variant of [`TaskTiming`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SerializedTaskTiming { + /// Location of the timing + pub location: SerializedLocation, + /// Time at which the measurement was reported in nanoseconds + pub start: u128, + /// Duration of the measurement in nanoseconds + pub duration: u128, +} + +impl SerializedTaskTiming { + /// Convert an array of [`TaskTiming`] into their serializable format + /// + /// # Params + /// + /// `anchor` - [`Instant`] that should be earlier than all timings to use as base anchor + pub fn convert(anchor: Instant, timings: &[TaskTiming]) -> Vec { + let serialized = timings + .iter() + .map(|timing| { + let start = timing.start.duration_since(anchor).as_nanos(); + let duration = timing.end.0.duration_since(timing.start).as_nanos(); + SerializedTaskTiming { + location: timing.location.into(), + start, + duration, + } + }) + .collect::>(); + + serialized + } + + /// `anchor` - [`Instant`] that should be earlier than all timings to use as base anchor + pub fn from(anchor: Instant, timing: TaskTiming) -> SerializedTaskTiming { + let start = timing.start.duration_since(anchor).as_nanos(); + let duration = timing.end.0.duration_since(timing.start).as_nanos(); + SerializedTaskTiming { + location: timing.location.into(), + start, + duration, + } + } +} + +/// Serializable variant of [`ThreadTaskTimings`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SerializedThreadTaskTimings { + /// Thread name + pub thread_name: Option, + /// Hash of the thread id + pub thread_id: u64, + /// Timing records for this thread + pub timings: Vec, +} + +impl SerializedThreadTaskTimings { + /// Convert [`ThreadTaskTimings`] into their serializable format + /// + /// # Params + /// + /// `anchor` - [`Instant`] that should be earlier than all timings to use as base anchor + pub fn convert(anchor: Instant, timings: ThreadTaskTimings) -> SerializedThreadTaskTimings { + let serialized_timings = SerializedTaskTiming::convert(anchor, &timings.timings); + + let mut hasher = DefaultHasher::new(); + timings.thread_id.hash(&mut hasher); + let thread_id = hasher.finish(); + + SerializedThreadTaskTimings { + thread_name: timings.thread_name, + thread_id, + timings: serialized_timings, + } + } +} + +#[doc(hidden)] +#[derive(Debug, Clone)] +pub struct ThreadTimingsDelta { + /// Hashed thread id + pub thread_id: u64, + /// Thread name, if known + pub thread_name: Option, + /// New timings since the last call. If the circular buffer wrapped around + /// since the previous poll, some entries may have been lost. + pub new_timings: Vec, +} + +/// Tracks which timing events have already been seen so that callers can request only unseen events. +#[doc(hidden)] +pub struct ProfilingCollector { + startup_time: Instant, + cursors: HashMap, +} + +impl ProfilingCollector { + pub fn new(startup_time: Instant) -> Self { + Self { + startup_time, + cursors: HashMap::default(), + } + } + + pub fn startup_time(&self) -> Instant { + self.startup_time + } + + pub fn collect_unseen( + &mut self, + all_timings: Vec, + ) -> Vec { + let mut deltas = Vec::with_capacity(all_timings.len()); + + for thread in all_timings { + let mut hasher = DefaultHasher::new(); + thread.thread_id.hash(&mut hasher); + let hashed_id = hasher.finish(); + + let prev_cursor = self.cursors.get(&thread.thread_id).copied().unwrap_or(0); + let buffer_len = thread.timings.len() as u64; + let buffer_start = thread.total_pushed.saturating_sub(buffer_len); + + let mut slice = if prev_cursor < buffer_start { + // Cursor fell behind the buffer — some entries were evicted. + // Return everything still in the buffer. + thread.timings.as_slice() + } else { + let skip = (prev_cursor - buffer_start) as usize; + &thread.timings[skip.min(thread.timings.len())..] + }; + + let cursor_advance = thread.total_pushed; + self.cursors.insert(thread.thread_id, cursor_advance); + + if slice.is_empty() { + continue; + } + + let new_timings = SerializedTaskTiming::convert(self.startup_time, slice); + + deltas.push(ThreadTimingsDelta { + thread_id: hashed_id, + thread_name: thread.thread_name, + new_timings, + }); + } + + deltas + } + + pub fn reset(&mut self) { + self.cursors.clear(); + } +} + +// Allow 16MiB of task timing entries. +// VecDeque grows by doubling its capacity when full, so keep this a power of 2 to avoid wasting +// memory. +#[cfg(feature = "profiler")] +const MAX_TASK_TIMINGS: usize = (16 * 1024 * 1024) / core::mem::size_of::(); + +#[doc(hidden)] +pub(crate) type TaskTimings = VecDeque; + +#[doc(hidden)] +pub type GuardedTaskTimings = spin::Mutex; + +#[doc(hidden)] +pub struct GlobalThreadTimings { + pub thread_id: ThreadId, + pub timings: std::sync::Weak, +} + +#[doc(hidden)] +#[derive(Debug, Clone)] +pub struct TaskStatistics { + pub poll_time_to_beat: Duration, + pub runtime_to_beat: Duration, + pub longest_poll_times: [TaskTiming; 5], + pub longest_runtimes: [TaskTiming; 5], +} + +impl std::fmt::Display for TaskStatistics { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("Tasks that blocked the longest before yielding\n")?; + for timing in self.longest_poll_times { + f.write_fmt(format_args!( + "{:<20} - {}:{}\n", + format!("{:?}", timing.poll_duration()), + timing.location.file(), + timing.location.column() + ))?; + } + f.write_str("Tasks that ran the longest\n")?; + for timing in self.longest_runtimes { + f.write_fmt(format_args!( + "{:<20} - {}:{}\n", + format!("{:?}", timing.since_spawn()), + timing.location.file(), + timing.location.column() + ))?; + } + Ok(()) + } +} + +impl Default for TaskStatistics { + fn default() -> Self { + Self { + // Do not track polls that are not problematic + // this keeps more calls on the fast path + poll_time_to_beat: Duration::from_micros(100), + runtime_to_beat: Duration::from_micros(100), + longest_poll_times: [TaskTiming::placeholder(); 5], + longest_runtimes: [TaskTiming::placeholder(); 5], + } + } +} + +impl TaskStatistics { + #[inline(always)] + fn add_yield_timing(&mut self, task: TaskTiming) { + let yielded_after = task.poll_duration(); + if yielded_after >= self.poll_time_to_beat { + std::hint::cold_path(); // most tasks are not the worst, optimize for that + let to_replace = self + .longest_poll_times + .iter() + .position_min_by_key(|task| task.since_spawn()) + .expect("guarded by the comparison with nth_longest_yield_time"); + self.longest_poll_times[to_replace] = task; + + self.poll_time_to_beat = self + .longest_poll_times + .iter() + .map(|task| task.since_spawn()) + .min() + .expect("never empty"); + } + } + + #[inline(always)] + fn add_runtime(&mut self, task: TaskTiming) { + let runtime = task.since_spawn(); + if runtime >= self.runtime_to_beat { + std::hint::cold_path(); // most tasks are not the worst, optimize for that + let to_replace = self + .longest_runtimes + .iter() + .position_min_by_key(|task| task.since_spawn()) + .expect("guarded by the comparison with nth_longest_yield_time"); + self.longest_runtimes[to_replace] = task; + + self.runtime_to_beat = self + .longest_runtimes + .iter() + .map(|task| task.since_spawn()) + .min() + .expect("never empty"); + } + } +} + +#[doc(hidden)] +pub static GLOBAL_THREAD_TIMINGS: spin::Mutex> = + spin::Mutex::new(Vec::new()); + +/// Upgrades all live per-thread timing handles, holding the global registry +/// lock only for the duration of the upgrades. +/// +/// The upgraded `Arc`s must never be dropped while `GLOBAL_THREAD_TIMINGS` is +/// locked: dropping the last strong reference runs [`ThreadTimings::drop`], +/// which locks `GLOBAL_THREAD_TIMINGS` again and would deadlock the +/// non-reentrant spinlock. A thread exiting concurrently can hand off its last +/// reference to us at any time, so callers of this function process (lock, +/// read, drop) the returned handles only after the global lock is released. +fn upgraded_thread_timings() -> Vec<(ThreadId, Arc)> { + let global_thread_timings = GLOBAL_THREAD_TIMINGS.lock(); + global_thread_timings + .iter() + .filter_map(|t| Some((t.thread_id, t.timings.upgrade()?))) + .collect() +} + +thread_local! { + #[doc(hidden)] + pub static THREAD_TIMINGS: LazyCell> = LazyCell::new(|| { + let current_thread = std::thread::current(); + let thread_name = current_thread.name(); + let thread_id = current_thread.id(); + let timings = ThreadTimings::new(thread_name.map(|e| e.to_string()), thread_id); + let timings = Arc::new(spin::Mutex::new(timings)); + + { + let timings = Arc::downgrade(&timings); + let global_timings = GlobalThreadTimings { + thread_id: std::thread::current().id(), + timings, + }; + GLOBAL_THREAD_TIMINGS.lock().push(global_timings); + } + + timings + }); +} + +#[doc(hidden)] +pub struct ThreadTimings { + pub thread_name: Option, + pub thread_id: ThreadId, + pub timings: TaskTimings, + pub running: Option, + pub stats: TaskStatistics, + pub total_pushed: u64, +} + +impl ThreadTimings { + pub fn new(thread_name: Option, thread_id: ThreadId) -> Self { + ThreadTimings { + thread_name, + thread_id, + timings: TaskTimings::new(), + stats: TaskStatistics::default(), + total_pushed: 0, + running: None, + } + } + + #[cfg(feature = "profiler")] + pub fn update_running_task( + &mut self, + spawned: SpawnTime, + location: &'static std::panic::Location<'_>, + ) { + let start = Instant::now(); + self.running = Some(ActiveTiming { + spawned, + location, + start, + }); + } + #[cfg(not(feature = "profiler"))] + pub fn update_running_task(&mut self, _: SpawnTime, _: &'static std::panic::Location<'_>) {} + + #[cfg(feature = "profiler")] + pub fn save_task_timing(&mut self, ended: YieldTime) -> TaskTiming { + let ActiveTiming { + location, + start, + spawned, + } = self + .running + .take() + .expect("this function is only ever called after register_task_start"); + + let timing = TaskTiming { + location, + spawned, + start, + end: ended, + }; + self.stats.add_yield_timing(timing); + self.stats.add_runtime(timing); + + if trace_enabled() { + std::hint::cold_path(); // optimize for when the profiling is off + if self.timings.len() >= MAX_TASK_TIMINGS { + self.timings.pop_front(); + } + self.timings.push_back(timing); + self.total_pushed += 1; + } + timing + } + #[cfg(not(feature = "profiler"))] + pub fn save_task_timing(&mut self, _: YieldTime) {} + + // Running tasks are included in the reliability trace, which is written + // whenever the foreground executor makes no progress for > n seconds + pub fn get_thread_task_timings(&self, includes: TasksIncluded) -> ThreadTaskTimings { + ThreadTaskTimings { + thread_name: self.thread_name.clone(), + thread_id: self.thread_id, + timings: self + .timings + .iter() + .cloned() + .chain( + self.running + .filter(|_| matches!(includes, TasksIncluded::CompletedAndRunning)) + .map(|running| TaskTiming { + spawned: running.spawned, + location: running.location, + start: running.start, + end: YieldTime(Instant::now()), + }), + ) + .collect(), + stats: self.stats.clone(), + total_pushed: self.total_pushed, + } + } +} + +impl Drop for ThreadTimings { + fn drop(&mut self) { + let mut thread_timings = GLOBAL_THREAD_TIMINGS.lock(); + + let Some((index, _)) = thread_timings + .iter() + .enumerate() + .find(|(_, t)| t.thread_id == self.thread_id) + else { + return; + }; + thread_timings.swap_remove(index); + } +} + +#[doc(hidden)] +pub fn update_running_task(spawned: SpawnTime, location: &'static std::panic::Location<'_>) { + #[cfg(feature = "profiler")] + journal::begin_foreground_turn(); + THREAD_TIMINGS.with(|timings| { + timings.lock().update_running_task(spawned, location); + }); +} + +#[doc(hidden)] +pub fn save_task_timing() { + let yielded_at = YieldTime(Instant::now()); + #[cfg(feature = "profiler")] + { + let timing = THREAD_TIMINGS.with(|timings| timings.lock().save_task_timing(yielded_at)); + journal::record_task_poll(timing); + } + #[cfg(not(feature = "profiler"))] + THREAD_TIMINGS.with(|timings| { + timings.lock().save_task_timing(yielded_at); + }); +} + +#[doc(hidden)] +pub fn get_current_thread_task_timings(include_running: TasksIncluded) -> ThreadTaskTimings { + THREAD_TIMINGS.with(|timings| timings.lock().get_thread_task_timings(include_running)) +} + +const TRACE_SETTING_ENABLED: u64 = 1 << 63; +const TRACE_SCOPE_COUNT_MASK: u64 = TRACE_SETTING_ENABLED - 1; +static TRACE_STATE: AtomicU64 = AtomicU64::new(0); + +/// Enables or disables profiler trace collection at runtime. +/// +/// When transitioning from enabled to disabled, `add_task_timing` becomes +/// cheaper since only cheap statistics are gathered. The existing per-thread +/// task buffers and the frame-event buffer are cleared so stale data isn't +/// reported after a later re-enable. Active trace scopes keep collection enabled +/// until the last scope ends. Calls with the current setting are a no-op. +pub fn set_trace_enabled(enabled: bool) -> bool { + let mut state = TRACE_STATE.load(Ordering::Acquire); + loop { + let was_enabled = state & TRACE_SETTING_ENABLED != 0; + if was_enabled == enabled { + return false; + } + + let next_state = if enabled { + state | TRACE_SETTING_ENABLED + } else { + state & TRACE_SCOPE_COUNT_MASK + }; + match TRACE_STATE.compare_exchange_weak( + state, + next_state, + Ordering::AcqRel, + Ordering::Acquire, + ) { + Ok(_) => { + if next_state == 0 { + clear_trace_buffers(); + } + return true; + } + Err(updated_state) => state = updated_state, + } + } +} + +#[cfg(any(feature = "bench-support", all(test, feature = "profiler")))] +pub(crate) struct TraceGuard; + +#[cfg(any(feature = "bench-support", all(test, feature = "profiler")))] +pub(crate) fn trace_scope() -> TraceGuard { + let incremented = TRACE_STATE.fetch_update(Ordering::AcqRel, Ordering::Acquire, |state| { + (state & TRACE_SCOPE_COUNT_MASK < TRACE_SCOPE_COUNT_MASK).then_some(state + 1) + }); + assert!(incremented.is_ok(), "too many active profiler trace scopes"); + TraceGuard +} + +#[cfg(any(feature = "bench-support", all(test, feature = "profiler")))] +impl Drop for TraceGuard { + fn drop(&mut self) { + let previous_state = + TRACE_STATE.fetch_update(Ordering::AcqRel, Ordering::Acquire, |state| { + (state & TRACE_SCOPE_COUNT_MASK > 0).then_some(state - 1) + }); + match previous_state { + Ok(1) => clear_trace_buffers(), + Ok(_) => {} + Err(_) => debug_assert!(false, "profiler trace scope count underflowed"), + } + } +} + +/// Returns whether profiler trace collection is enabled. +pub fn trace_enabled() -> bool { + TRACE_STATE.load(Ordering::Relaxed) != 0 +} + +fn clear_trace_buffers() { + for (_, timings) in upgraded_thread_timings() { + let mut timings = timings.lock(); + timings.timings.clear(); + timings.timings.shrink_to_fit(); + timings.total_pushed = 0; + } + #[cfg(feature = "profiler")] + { + let mut frames = FRAME_TIMINGS.lock(); + frames.timings.clear(); + frames.timings.shrink_to_fit(); + frames.total_pushed = 0; + } +} + +/// Timing for a single drawn window frame. +#[cfg(feature = "profiler")] +#[derive(Debug, Copy, Clone)] +pub struct FrameTiming { + /// The window that was drawn. + pub window_id: WindowId, + /// When the frame first became dirty (its first invalidation). `None` if + /// profiler tracing was not yet enabled when the invalidation occurred. + pub dirty_at: Option, + /// Number of invalidations coalesced into this frame. + pub invalidations: u64, + /// When `Window::draw` started. + pub draw_start: Instant, + /// When `Window::draw` finished. + pub draw_end: Instant, +} + +#[cfg(feature = "profiler")] +impl FrameTiming { + /// Time spent inside `Window::draw`. + pub fn draw_duration(&self) -> Duration { + self.draw_end.duration_since(self.draw_start) + } + + /// Time from the frame's first invalidation to the end of its draw, if the + /// first invalidation was observed. + pub fn dirty_to_draw_duration(&self) -> Option { + self.dirty_at + .map(|dirty_at| self.draw_end.duration_since(dirty_at)) + } +} + +/// Work spent submitting a window frame to the platform. +#[cfg(feature = "profiler")] +#[derive(Debug, Copy, Clone)] +pub struct PresentTiming { + /// The window whose frame was submitted. + pub window_id: WindowId, + /// When the platform submission began. + pub present_start: Instant, + /// When the platform submission completed. + pub present_end: Instant, + /// The interval since the previous newly drawn frame was submitted, when + /// both frames belong to an active animation. + pub animation_interval: Option, +} + +#[cfg(feature = "profiler")] +impl PresentTiming { + /// Time spent submitting the frame to the platform. + pub fn present_duration(&self) -> Duration { + self.present_end.duration_since(self.present_start) + } +} + +/// A frame event observed by the profiler. +#[cfg(feature = "profiler")] +#[derive(Debug, Copy, Clone)] +pub enum FrameEvent { + /// A window frame was drawn. + Draw(FrameTiming), + /// A newly drawn window frame was presented. + Present(PresentTiming), +} + +/// A point-in-time snapshot of the frame-duration histograms for a window, +/// suitable for external formatting. +#[cfg(feature = "profiler")] +#[derive(Clone)] +pub struct FrameDurationSnapshot { + /// Histogram of durations from the first invalidation through presentation, in nanoseconds. + pub dirty_to_present_histogram: Histogram, + /// Histogram of `Window::draw` durations, in nanoseconds. + pub draw_duration_histogram: Histogram, + /// Histogram of intervals between consecutively presented frames while the + /// window was animating, in nanoseconds. + pub present_interval_histogram: Histogram, +} + +/// A point-in-time snapshot of the input-latency histograms for a window, +/// suitable for external formatting. +#[cfg(feature = "profiler")] +#[derive(Clone)] +pub struct InputLatencySnapshot { + /// Histogram of input-to-frame latency samples, in nanoseconds. + pub latency_histogram: Histogram, + /// Histogram of input events coalesced per rendered frame. + pub events_per_frame_histogram: Histogram, + /// Count of input events that arrived mid-draw and were excluded from + /// latency recording. + pub mid_draw_events_dropped: u64, +} + +#[cfg(feature = "profiler")] +enum WindowActivity { + Input { + started_at: Instant, + kind: &'static str, + }, + Draw { + started_at: Instant, + }, +} + +/// Collects profiling information for one window. +/// +/// Aggregate histograms are always populated when the `profiler` feature is +/// compiled in. Individual draw and present events are added to the global +/// profiler buffer only while tracing is enabled. +#[cfg(feature = "profiler")] +pub struct WindowProfiler { + window_id: WindowId, + active_activities: SmallVec<[WindowActivity; 4]>, + active_actions: SmallVec<[(&'static str, Instant); 2]>, + dirty_to_present_histogram: Histogram, + draw_duration_histogram: Histogram, + present_interval_histogram: Histogram, + first_input_at: Option, + pending_input_count: u64, + input_latency_histogram: Histogram, + events_per_frame_histogram: Histogram, + mid_draw_events_dropped: u64, + last_present_at: Option, + animating_at_last_present: bool, + pending_frame: Option, +} + +#[cfg(feature = "profiler")] +impl WindowProfiler { + /// Creates a profiler for a window. + pub fn new(window_id: WindowId) -> anyhow::Result { + let profiler = Self { + window_id, + active_activities: SmallVec::new(), + active_actions: SmallVec::new(), + dirty_to_present_histogram: Histogram::new(3).map_err(|error| { + anyhow::anyhow!("Failed to create dirty-to-present histogram: {error}") + })?, + draw_duration_histogram: Histogram::new(3).map_err(|error| { + anyhow::anyhow!("Failed to create draw duration histogram: {error}") + })?, + present_interval_histogram: Histogram::new(3).map_err(|error| { + anyhow::anyhow!("Failed to create present interval histogram: {error}") + })?, + first_input_at: None, + pending_input_count: 0, + input_latency_histogram: Histogram::new(3).map_err(|error| { + anyhow::anyhow!("Failed to create input latency histogram: {error}") + })?, + events_per_frame_histogram: Histogram::new(3).map_err(|error| { + anyhow::anyhow!("Failed to create events per frame histogram: {error}") + })?, + mid_draw_events_dropped: 0, + last_present_at: None, + animating_at_last_present: false, + pending_frame: None, + }; + journal::record_frame_pending(window_id, Instant::now()); + Ok(profiler) + } + + /// Records the beginning of an input dispatch. `kind` names the platform + /// input variant being dispatched (see [`crate::PlatformInput::kind_name`]). + pub fn begin_input(&mut self, kind: &'static str) { + journal::begin_foreground_turn(); + self.active_activities.push(WindowActivity::Input { + started_at: Instant::now(), + kind, + }); + } + + /// Records the end of an input dispatch. + pub fn end_input(&mut self, caused_invalidation: bool) { + let Some(WindowActivity::Input { started_at, kind }) = self.active_activities.pop() else { + debug_assert!(false, "input activity must be the current window activity"); + journal::end_foreground_turn(); + return; + }; + + if !journal::power_interrupted_since(started_at) { + journal::record_input(journal::InputTiming { + kind, + start: started_at, + end: Instant::now(), + caused_invalidation, + }); + } + journal::end_foreground_turn(); + + if !caused_invalidation || !journal::frame_sample_is_valid(self.window_id, started_at) { + return; + } + if self + .first_input_at + .is_some_and(|at| !journal::frame_sample_is_valid(self.window_id, at)) + { + self.first_input_at = None; + self.pending_input_count = 0; + } + + let arrived_during_draw = self + .active_activities + .iter() + .any(|activity| matches!(activity, WindowActivity::Draw { .. })); + if arrived_during_draw { + self.mid_draw_events_dropped += 1; + } else { + self.first_input_at.get_or_insert(started_at); + self.pending_input_count += 1; + } + } + + /// Records the beginning of an action handler. + pub fn begin_action_handler(&mut self, action: &(dyn Action + 'static), cx: &mut App) { + journal::begin_foreground_turn(); + let name = actions::update_running_action(action, cx); + self.active_actions.push((name, Instant::now())); + } + + /// Records the end of the current action handler. + pub fn end_action_handler(&mut self) { + // Dual-write to the legacy aggregate store; its single global running + // slot misbehaves when tests run actions concurrently, which is why + // the journal entry is tracked here on the window instead. + actions::save_action_timing(); + let Some((name, start)) = self.active_actions.pop() else { + debug_assert!(false, "action handler must be begun before it ends"); + journal::end_foreground_turn(); + return; + }; + if !journal::power_interrupted_since(start) { + journal::record_action(ActionTiming { + name, + start, + end: Instant::now(), + }); + } + journal::end_foreground_turn(); + } + + /// Records the beginning of a window draw. + pub fn begin_draw(&mut self) { + journal::begin_foreground_turn(); + let started_at = Instant::now(); + journal::record_frame_pending(self.window_id, started_at); + self.active_activities + .push(WindowActivity::Draw { started_at }); + } + + /// Records the end of a window draw and returns the draw duration. + pub fn end_draw(&mut self, dirty_at: Option, invalidations: u64) -> Duration { + let Some(WindowActivity::Draw { + started_at: draw_start, + }) = self.active_activities.pop() + else { + debug_assert!(false, "draw activity must be the current window activity"); + journal::end_foreground_turn(); + return Duration::ZERO; + }; + + let draw_end = Instant::now(); + let frame_timing = FrameTiming { + window_id: self.window_id, + dirty_at: dirty_at.filter(|at| journal::frame_sample_is_valid(self.window_id, *at)), + invalidations, + draw_start, + draw_end, + }; + let draw_duration = frame_timing.draw_duration(); + if !journal::power_interrupted_since(draw_start) { + self.record_draw_timing(frame_timing); + } + journal::end_foreground_turn(); + draw_duration + } + + /// Records that a frame was presented. + /// + /// `next_frame_scheduled` marks the animation state for the interval ending + /// at the next newly drawn frame's presentation. + pub fn record_present( + &mut self, + present_start: Instant, + present_end: Instant, + window_active: bool, + next_frame_scheduled: bool, + ) { + self.record_present_at( + present_start, + present_end, + window_active, + next_frame_scheduled, + ); + } + + /// Returns a snapshot of the current input-latency histograms. + pub fn input_latency_snapshot(&self) -> InputLatencySnapshot { + InputLatencySnapshot { + latency_histogram: self.input_latency_histogram.clone(), + events_per_frame_histogram: self.events_per_frame_histogram.clone(), + mid_draw_events_dropped: self.mid_draw_events_dropped, + } + } + + /// Returns a snapshot of the current frame-duration histograms. + pub fn frame_duration_snapshot(&self) -> FrameDurationSnapshot { + FrameDurationSnapshot { + dirty_to_present_histogram: self.dirty_to_present_histogram.clone(), + draw_duration_histogram: self.draw_duration_histogram.clone(), + present_interval_histogram: self.present_interval_histogram.clone(), + } + } + + fn record_present_at( + &mut self, + present_start: Instant, + present_end: Instant, + window_active: bool, + next_frame_scheduled: bool, + ) { + if let Some(first_input_at) = self.first_input_at.take() + && journal::frame_sample_is_valid(self.window_id, first_input_at) + { + let latency_nanos = present_end.duration_since(first_input_at).as_nanos() as u64; + self.input_latency_histogram.record(latency_nanos).ok(); + if self.pending_input_count > 0 { + self.events_per_frame_histogram + .record(self.pending_input_count) + .ok(); + } + } + self.pending_input_count = 0; + + let frame = self + .pending_frame + .take() + .filter(|frame| journal::frame_sample_is_valid(self.window_id, frame.draw_start)) + .map(|mut frame| { + frame.dirty_at = frame + .dirty_at + .filter(|at| journal::frame_sample_is_valid(self.window_id, *at)); + frame + }); + let animation_interval = + if frame.is_some() && self.animating_at_last_present && window_active { + self.last_present_at + .filter(|at| journal::frame_sample_is_valid(self.window_id, *at)) + .map(|last_present_at| present_end.duration_since(last_present_at)) + } else { + None + }; + let present_timing = PresentTiming { + window_id: self.window_id, + present_start, + present_end, + animation_interval, + }; + journal::record_present(present_timing, frame); + + let Some(frame) = frame else { + return; + }; + + if let Some(dirty_at) = frame.dirty_at + && let Err(error) = self + .dirty_to_present_histogram + .record(present_end.duration_since(dirty_at).as_nanos() as u64) + { + log::error!("failed to record dirty-to-present frame timing: {error}"); + } + + if let Some(animation_interval) = animation_interval { + self.present_interval_histogram + .record(animation_interval.as_nanos() as u64) + .ok(); + } + record_frame_event(FrameEvent::Present(present_timing)); + + self.last_present_at = Some(present_end); + self.animating_at_last_present = next_frame_scheduled && window_active; + } + + fn record_draw_timing(&mut self, timing: FrameTiming) { + self.record_draw_duration(timing.draw_duration()); + self.pending_frame = Some(timing); + record_frame_event(FrameEvent::Draw(timing)); + journal::record_draw(timing); + } + + fn record_draw_duration(&mut self, duration: Duration) { + self.draw_duration_histogram + .record(duration.as_nanos() as u64) + .ok(); + } +} + +#[cfg(feature = "profiler")] +impl Drop for WindowProfiler { + fn drop(&mut self) { + journal::record_window_closed(self.window_id); + } +} + +// Allow 16MiB of frame event entries. +#[cfg(feature = "profiler")] +const MAX_FRAME_TIMINGS: usize = (16 * 1024 * 1024) / core::mem::size_of::(); + +#[cfg(feature = "profiler")] +struct FrameTimings { + timings: VecDeque, + total_pushed: u64, +} + +#[cfg(feature = "profiler")] +static FRAME_TIMINGS: spin::Mutex = spin::Mutex::new(FrameTimings { + timings: VecDeque::new(), + total_pushed: 0, +}); + +/// Records a frame event. +/// +/// No-op unless profiler tracing is enabled via [`set_trace_enabled`]. +#[cfg(feature = "profiler")] +pub fn record_frame_event(event: FrameEvent) { + if !trace_enabled() { + return; + } + std::hint::cold_path(); // optimize for when profiling is off + + let mut frames = FRAME_TIMINGS.lock(); + if frames.timings.len() >= MAX_FRAME_TIMINGS { + frames.timings.pop_front(); + } + frames.timings.push_back(event); + frames.total_pushed += 1; +} + +/// Drains frame events recorded after this collector was created, tracking a +/// cursor so each call to [`Self::collect_unseen`] returns only new entries. +#[cfg(feature = "profiler")] +pub struct FrameTimingCollector { + cursor: u64, +} + +#[cfg(feature = "profiler")] +impl Default for FrameTimingCollector { + fn default() -> Self { + Self::new() + } +} + +#[cfg(feature = "profiler")] +impl FrameTimingCollector { + /// Creates a collector that only sees frame events recorded from this point on. + pub fn new() -> Self { + Self { + cursor: FRAME_TIMINGS.lock().total_pushed, + } + } + + /// Returns frame events recorded since the previous call (or since the + /// collector was created). If the ring buffer wrapped around since the + /// previous poll, the evicted entries are lost. + pub fn collect_unseen(&mut self) -> Vec { + let frames = FRAME_TIMINGS.lock(); + let buffer_len = frames.timings.len() as u64; + let buffer_start = frames.total_pushed.saturating_sub(buffer_len); + let skip = self.cursor.saturating_sub(buffer_start) as usize; + let unseen = frames + .timings + .iter() + .skip(skip.min(frames.timings.len())) + .copied() + .collect(); + self.cursor = frames.total_pushed; + unseen + } +} + +#[cfg(all(test, feature = "profiler"))] +mod tests { + use super::*; + use std::sync::{Mutex, MutexGuard}; + + #[test] + fn interruptions_drop_latency_samples_but_hiding_keeps_draw_work() { + for sleep in [false, true] { + let (_journal, _guard) = journal::install_test_foreground_journal(64, 4); + let id = WindowId::from(1); + let mut profiler = WindowProfiler::new(id).expect("valid histograms"); + let old = Instant::now() - Duration::from_secs(1); + record_test_draw(&mut profiler, old); + profiler.record_present_at(old, old, true, true); + profiler.first_input_at = Some(old); + profiler.pending_input_count = 1; + profiler.begin_draw(); + if sleep { + journal::record_power_transition(journal::PowerState::Suspended); + journal::record_power_transition(journal::PowerState::Awake); + } else { + journal::record_window_visibility(id, crate::WindowVisibility::Hidden); + journal::record_window_visibility(id, crate::WindowVisibility::Visible); + } + profiler.end_draw(Some(old), 1); + let now = Instant::now(); + profiler.record_present_at(now, now, true, true); + assert_eq!( + profiler.draw_duration_histogram.len(), + if sleep { 1 } else { 2 } + ); + assert_eq!(profiler.input_latency_histogram.len(), 0); + assert_eq!(profiler.dirty_to_present_histogram.len(), 1); + assert_eq!(profiler.present_interval_histogram.len(), 0); + profiler.begin_draw(); + profiler.end_draw(Some(Instant::now()), 1); + let now = Instant::now(); + profiler.record_present_at(now, now, true, true); + assert_eq!(profiler.dirty_to_present_histogram.len(), 2); + } + } + + #[test] + fn records_draw_events_only_while_tracing() { + let _trace_test_guard = TraceTestGuard::new(); + let window_id = WindowId::from(0xD0A0); + let mut window_profiler = + WindowProfiler::new(window_id).expect("window profiler should initialize"); + let dirty_at = Instant::now(); + let mut collector = FrameTimingCollector::new(); + + window_profiler.begin_draw(); + window_profiler.end_draw(Some(dirty_at), 3); + assert!( + collector + .collect_unseen() + .iter() + .all(|event| !event_matches_window(*event, window_id)) + ); + + set_trace_enabled(true); + let mut collector = FrameTimingCollector::new(); + window_profiler.begin_draw(); + window_profiler.end_draw(Some(dirty_at), 3); + + let timing = collector + .collect_unseen() + .into_iter() + .find_map(|event| match event { + FrameEvent::Draw(timing) if timing.window_id == window_id => Some(timing), + _ => None, + }) + .expect("draw event should be recorded while tracing"); + assert_eq!(timing.dirty_at, Some(dirty_at)); + assert_eq!(timing.invalidations, 3); + assert!(timing.draw_start >= dirty_at); + } + + #[test] + fn records_present_events_for_newly_drawn_frames() { + let _trace_test_guard = TraceTestGuard::new(); + set_trace_enabled(true); + let window_id = WindowId::from(0xA11E); + let mut window_profiler = + WindowProfiler::new(window_id).expect("window profiler should initialize"); + let start = Instant::now(); + let mut collector = FrameTimingCollector::new(); + + record_test_draw(&mut window_profiler, start); + window_profiler.record_present_at(start, start, true, true); + record_test_draw(&mut window_profiler, start + FRAME); + window_profiler.record_present_at(start + FRAME, start + FRAME, true, true); + window_profiler.record_present_at( + start + FRAME + FRAME / 2, + start + FRAME + FRAME / 2, + true, + true, + ); + + let present_timings = collector + .collect_unseen() + .into_iter() + .filter_map(|event| match event { + FrameEvent::Present(timing) if timing.window_id == window_id => Some(timing), + _ => None, + }) + .collect::>(); + let [first_present, second_present] = present_timings.as_slice() else { + panic!("expected exactly two present events, got {present_timings:?}"); + }; + assert_eq!(first_present.animation_interval, None); + assert_eq!(second_present.animation_interval, Some(FRAME)); + + #[cfg(feature = "profiler")] + { + assert_eq!(window_profiler.present_interval_histogram.len(), 1); + assert!( + window_profiler.present_interval_histogram.max() + >= second_present + .animation_interval + .expect("second present should have an animation interval") + .as_nanos() as u64 + ); + } + } + + #[test] + fn disabling_tracing_clears_frame_events() { + let _trace_test_guard = TraceTestGuard::new(); + set_trace_enabled(true); + let window_id = WindowId::from(0xC1EA); + let mut window_profiler = + WindowProfiler::new(window_id).expect("window profiler should initialize"); + let mut collector = FrameTimingCollector::new(); + + window_profiler.begin_draw(); + window_profiler.end_draw(None, 0); + assert!( + FRAME_TIMINGS + .lock() + .timings + .iter() + .copied() + .any(|event| event_matches_window(event, window_id)) + ); + + set_trace_enabled(false); + assert!( + collector + .collect_unseen() + .iter() + .all(|event| !event_matches_window(*event, window_id)) + ); + } + + #[cfg(feature = "profiler")] + #[test] + fn records_intervals_only_between_animation_frames() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(1)).expect("window profiler should initialize"); + let start = Instant::now(); + + draw_and_present(&mut window_profiler, start, true, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 0); + + draw_and_present(&mut window_profiler, start + FRAME, true, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 1); + + draw_and_present(&mut window_profiler, start + FRAME * 2, true, false); + assert_eq!(window_profiler.present_interval_histogram.len(), 2); + + draw_and_present(&mut window_profiler, start + FRAME * 100, true, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 2); + } + + #[cfg(feature = "profiler")] + #[test] + fn missed_frames_stretch_the_recorded_interval() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(2)).expect("window profiler should initialize"); + let start = Instant::now(); + + draw_and_present(&mut window_profiler, start, true, true); + draw_and_present(&mut window_profiler, start + FRAME * 5, true, true); + + let recorded = window_profiler.present_interval_histogram.max(); + assert!(recorded >= (FRAME * 4).as_nanos() as u64); + } + + #[cfg(feature = "profiler")] + #[test] + fn ignores_re_presents_of_unchanged_frames() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(3)).expect("window profiler should initialize"); + let start = Instant::now(); + + draw_and_present(&mut window_profiler, start, true, true); + window_profiler.record_present_at(start + FRAME / 2, start + FRAME / 2, true, true); + draw_and_present(&mut window_profiler, start + FRAME, true, true); + + assert_eq!(window_profiler.present_interval_histogram.len(), 1); + assert!( + window_profiler.present_interval_histogram.max() >= (FRAME * 3 / 4).as_nanos() as u64 + ); + } + + #[cfg(feature = "profiler")] + #[test] + fn skips_intervals_for_inactive_windows() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(4)).expect("window profiler should initialize"); + let start = Instant::now(); + + draw_and_present(&mut window_profiler, start, false, true); + draw_and_present(&mut window_profiler, start + FRAME, false, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 0); + + draw_and_present(&mut window_profiler, start + FRAME * 2, true, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 0); + + draw_and_present(&mut window_profiler, start + FRAME * 3, true, true); + assert_eq!(window_profiler.present_interval_histogram.len(), 1); + } + + #[test] + fn records_dirty_to_present_durations() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(8)).expect("window profiler should initialize"); + let draw_end = Instant::now(); + let present_end = draw_end + Duration::from_millis(6); + + record_test_draw(&mut window_profiler, draw_end); + window_profiler.record_present_at(present_end, present_end, true, false); + + let snapshot = window_profiler.frame_duration_snapshot(); + let histogram = snapshot.dirty_to_present_histogram; + assert_eq!(histogram.len(), 1); + assert!(histogram.max() >= Duration::from_millis(10).as_nanos() as u64); + } + + #[cfg(feature = "profiler")] + #[test] + fn records_every_draw_duration() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(5)).expect("window profiler should initialize"); + + window_profiler.record_draw_duration(Duration::from_millis(2)); + window_profiler.record_draw_duration(Duration::from_millis(40)); + + let snapshot = window_profiler.frame_duration_snapshot(); + assert_eq!(snapshot.draw_duration_histogram.len(), 2); + assert!(snapshot.draw_duration_histogram.max() >= 39_000_000); + } + + #[test] + fn records_input_latency_at_the_frame_presentation_timestamp() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(6)).expect("window profiler should initialize"); + let first_input_at = Instant::now(); + let presented_at = first_input_at + Duration::from_millis(12); + + begin_input_at(&mut window_profiler, first_input_at); + window_profiler.end_input(true); + begin_input_at( + &mut window_profiler, + first_input_at + Duration::from_millis(2), + ); + window_profiler.end_input(true); + record_test_draw(&mut window_profiler, presented_at); + window_profiler.record_present_at(presented_at, presented_at, true, false); + + let snapshot = window_profiler.input_latency_snapshot(); + assert_eq!(snapshot.latency_histogram.len(), 1); + assert!(snapshot.latency_histogram.max() >= Duration::from_millis(12).as_nanos() as u64); + assert_eq!(snapshot.events_per_frame_histogram.len(), 1); + assert_eq!(snapshot.events_per_frame_histogram.max(), 2); + assert_eq!(snapshot.mid_draw_events_dropped, 0); + } + + #[test] + fn excludes_input_that_arrives_during_a_draw() { + let mut window_profiler = + WindowProfiler::new(WindowId::from(7)).expect("window profiler should initialize"); + + window_profiler.begin_draw(); + begin_input_at(&mut window_profiler, Instant::now()); + window_profiler.end_input(true); + window_profiler.end_draw(None, 0); + + let snapshot = window_profiler.input_latency_snapshot(); + assert!(snapshot.latency_histogram.is_empty()); + assert!(snapshot.events_per_frame_histogram.is_empty()); + assert_eq!(snapshot.mid_draw_events_dropped, 1); + } + + #[test] + fn overlapping_trace_scopes_keep_tracing_enabled() { + let _trace_test_guard = TraceTestGuard::new(); + let first_scope = trace_scope(); + let second_scope = trace_scope(); + + assert!(trace_enabled()); + drop(first_scope); + assert!(trace_enabled()); + drop(second_scope); + assert!(!trace_enabled()); + } + + const FRAME: Duration = Duration::from_millis(16); + static TRACE_TEST_LOCK: Mutex<()> = Mutex::new(()); + + struct TraceTestGuard { + was_enabled: bool, + _lock: MutexGuard<'static, ()>, + } + + impl TraceTestGuard { + fn new() -> Self { + let lock = TRACE_TEST_LOCK + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + let was_enabled = trace_enabled(); + set_trace_enabled(false); + Self { + was_enabled, + _lock: lock, + } + } + } + + impl Drop for TraceTestGuard { + fn drop(&mut self) { + set_trace_enabled(false); + if self.was_enabled { + set_trace_enabled(true); + } + } + } + + fn event_matches_window(event: FrameEvent, window_id: WindowId) -> bool { + match event { + FrameEvent::Draw(timing) => timing.window_id == window_id, + FrameEvent::Present(timing) => timing.window_id == window_id, + } + } + + fn begin_input_at(window_profiler: &mut WindowProfiler, started_at: Instant) { + window_profiler + .active_activities + .push(WindowActivity::Input { + started_at, + kind: "test", + }); + } + + #[cfg(feature = "profiler")] + fn draw_and_present( + window_profiler: &mut WindowProfiler, + presented_at: Instant, + window_active: bool, + next_frame_scheduled: bool, + ) { + record_test_draw(window_profiler, presented_at); + window_profiler.record_present_at( + presented_at, + presented_at, + window_active, + next_frame_scheduled, + ); + } + + fn record_test_draw(window_profiler: &mut WindowProfiler, draw_end: Instant) { + window_profiler.record_draw_timing(FrameTiming { + window_id: window_profiler.window_id, + dirty_at: Some(draw_end - Duration::from_millis(4)), + invalidations: 1, + draw_start: draw_end - Duration::from_millis(2), + draw_end, + }); + } +} diff --git a/vendor/gpui-pre/src/profiler/actions.rs b/vendor/gpui-pre/src/profiler/actions.rs new file mode 100644 index 00000000..a4892f8a --- /dev/null +++ b/vendor/gpui-pre/src/profiler/actions.rs @@ -0,0 +1,213 @@ +use std::time::Duration; + +use itertools::Itertools; +use scheduler::Instant; + +#[cfg(feature = "profiler")] +use crate::action::Action; + +#[doc(hidden)] +#[derive(Clone)] +pub struct ActionStatistics { + runtime_to_beat: Duration, + + longest_runtimes: heapless::Vec, + running: Option<(&'static str, Instant)>, +} + +impl std::fmt::Debug for ActionStatistics { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ActionStatistics") + .field("runtime_to_beat", &self.runtime_to_beat) + .field("longest_runtimes", &self.longest_runtimes) + .field( + "running", + &self.running.map(|(id, started)| (id, started.elapsed())), + ) + .finish() + } +} + +impl std::fmt::Display for ActionStatistics { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("Actions that blocked the longest\n")?; + for action in self + .longest_runtimes(true) + .sorted_by_key(|action| action.runtime()) + .rev() + { + f.write_fmt(format_args!( + "{:<20} - {}", + format!("{:?}", action.runtime()), // impl dbg does not support alignment + action.name + ))?; + writeln!(f)?; + } + Ok(()) + } +} + +impl Default for ActionStatistics { + fn default() -> Self { + Self::new() + } +} + +impl ActionStatistics { + const fn new() -> Self { + Self { + // This keeps more calls on the fast path by only tracking + // problematic polls + runtime_to_beat: Duration::from_micros(100), + longest_runtimes: heapless::Vec::new(), + running: None, + } + } + + pub fn take(&mut self) -> Self { + let taken = std::mem::take(self); + self.running = taken.running; + taken + } + + pub fn is_empty(&self) -> bool { + self.longest_runtimes.is_empty() + } + + #[cfg(feature = "profiler")] + pub fn update_running_action(&mut self, action: &'static str, started: Instant) { + self.running = Some((action, started)); + } + #[cfg(not(feature = "profiler"))] + pub fn update_running_action(&mut self, _action: &'static str, _started: Instant) {} + + #[cfg(feature = "profiler")] + pub fn save_action_timing(&mut self) { + let now = Instant::now(); + + let Some((action, started)) = self.running.take() else { + // Actions are ran only on the foreground executor and therefore + // sequentially _except_ in tests where they can run concurrently. + // + // When ran sequentially self.running will always be Some. When ran + // concurrently that is no longer true. But that is fine, we do not + // need to track action timings in tests. + std::hint::cold_path(); + return; + }; + + let timing = ActionTiming { + name: action, + start: started, + end: now, + }; + + let runtime = now.duration_since(started); + if runtime >= self.runtime_to_beat { + std::hint::cold_path(); // most actions are not the worst, optimize for that + + if self.longest_runtimes.is_full() + && let Some(to_replace) = self + .longest_runtimes + .iter_mut() + .min_by_key(|action| runtime >= action.runtime()) + { + *to_replace = timing; + } else { + self.longest_runtimes + .push(timing) + .expect("just checked it is not full"); + }; + + self.runtime_to_beat = self + .longest_runtimes + .iter() + .map(|action| action.runtime()) + .min() + .expect("never empty"); + } + } + #[cfg(not(feature = "profiler"))] + pub fn save_action_timing(&mut self) {} + + pub fn longest_runtimes(&self, include_running: bool) -> impl Iterator { + self.longest_runtimes.iter().copied().chain( + self.running + .into_iter() + .filter(move |_| include_running) + .map(|(name, start)| ActionTiming { + name, + start, + end: Instant::now(), + }), + ) + } +} + +#[doc(hidden)] +/// UNSTABLE only for use in the profiler and zed-reliability +#[derive(Copy, Clone)] +pub struct ActionTiming { + pub name: &'static str, + pub start: Instant, + pub end: Instant, +} + +impl core::fmt::Debug for ActionTiming { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ActionTiming") + .field("name", &self.name) + .field("runtime", &self.runtime()) + .finish() + } +} + +impl ActionTiming { + pub fn duration(&self) -> Duration { + self.end.saturating_duration_since(self.start) + } +} + +impl ActionTiming { + #[doc(hidden)] + pub fn runtime(&self) -> Duration { + self.end - self.start + } +} + +// The profiler is careful to never block when the lock is held, therefore a +// spinlock is optimal. +#[cfg(feature = "profiler")] +static ACTION_STATISTICS: spin::Mutex = + const { spin::Mutex::new(ActionStatistics::new()) }; + +#[doc(hidden)] +#[cfg(feature = "profiler")] +pub(crate) fn update_running_action( + action: &(dyn Action + 'static), + cx: &mut crate::App, +) -> &'static str { + let now = Instant::now(); + let action = action.type_id(); + let action = cx.actions.try_resolve_action(&action).unwrap_or("un-named"); + ACTION_STATISTICS.lock().update_running_action(action, now); + action +} + +#[doc(hidden)] +#[cfg(feature = "profiler")] +pub(crate) fn save_action_timing() { + ACTION_STATISTICS.lock().save_action_timing(); +} + +#[doc(hidden)] +#[cfg(feature = "profiler")] +pub fn take_action_stats() -> ActionStatistics { + ACTION_STATISTICS.lock().take() +} + +#[doc(hidden)] +#[cfg(not(feature = "profiler"))] +pub fn take_action_stats() -> ActionStatistics { + ActionStatistics::default() +} diff --git a/vendor/gpui-pre/src/profiler/hang.rs b/vendor/gpui-pre/src/profiler/hang.rs new file mode 100644 index 00000000..fbd52341 --- /dev/null +++ b/vendor/gpui-pre/src/profiler/hang.rs @@ -0,0 +1,1506 @@ +//! Post-hoc detection of foreground hangs from the journal's event stream. +//! +//! A hang is any single piece of foreground work — a task poll, an action +//! handler, an input dispatch, a window draw, or platform presentation — that +//! blocked the foreground thread for at least a threshold duration. An +//! interval whose total foreground spend reached the frame budget also +//! counts, even when no single event crossed the threshold: many small +//! pieces of work can drop a frame — or starve a headless app — as +//! thoroughly as one long stall. [`HangDetector`] drains the journal and +//! reports each completed activity interval containing hangs as a +//! [`HangIncident`]. + +use std::time::Duration; + +use scheduler::Instant; +use serde::Serialize; + +#[cfg(not(target_family = "wasm"))] +mod monitor; +#[cfg(not(target_family = "wasm"))] +pub(crate) use monitor::HangMonitor; +#[cfg(not(target_family = "wasm"))] +pub use monitor::{HangMonitorConfig, HangMonitorError, HangMonitorPoll, HangMonitorPollReason}; + +/// Version of the power/visibility-aware measurement rules. +pub const MEASUREMENT_VERSION: u32 = 2; + +use super::SerializedLocation; +use super::journal::{ + ForegroundEvent, ForegroundJournal, ForegroundJournalCollector, ForegroundJournalEntry, + FrameSnapshot, IntervalBoundary, IntervalSealer, +}; + +/// Detects foreground hangs by polling the journal. +/// +/// Detection is post-hoc: a hang is reported once an explicit presentation, +/// completed frame skip, or foreground-idle boundary completes its interval. +/// Work that never yields back to the foreground is not observed until it does. +pub struct HangDetector { + collector: ForegroundJournalCollector, + sealer: IntervalSealer, + threshold: Duration, + frame_budget: Duration, + first_present_at: Option, +} + +/// One sealed interval that contained at least one hang. +#[derive(Debug, Clone)] +pub struct HangIncident { + /// The interval the hangs occurred in, including all non-hang foreground + /// work recorded alongside them. + pub snapshot: FrameSnapshot, + /// Which detection rule qualified the interval. + pub trigger: HangTrigger, + /// For [`HangTrigger::Threshold`], the events that blocked the foreground + /// for at least the detector's threshold, longest first. For + /// [`HangTrigger::Budget`], no event crossed the threshold and this instead + /// holds every event in the interval, longest first. + pub contributors: Vec, +} + +/// The detection rule that qualified an interval as a [`HangIncident`]. +/// +/// Recorded explicitly so consumers can separate the two classes without +/// re-deriving them from `stall_ms`, which stops working whenever the +/// detector's thresholds change. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum HangTrigger { + /// A single event blocked the foreground for at least the hang threshold. + Threshold, + /// No single event crossed the threshold, but the interval's total + /// foreground spend reached the frame budget. + Budget, +} + +impl HangDetector { + /// Creates a detector reporting single events at or above `threshold` + /// and intervals whose total foreground spend reached `frame_budget`. + /// Only events recorded from this point on are observed. + pub fn new(journal: ForegroundJournal, threshold: Duration, frame_budget: Duration) -> Self { + Self { + collector: journal.collector(), + sealer: IntervalSealer::new(Instant::now()), + threshold, + frame_budget, + first_present_at: None, + } + } + + /// When the first newly drawn frame observed by this detector finished + /// platform submission. `None` until a presentation boundary is observed. + pub fn first_present_at(&self) -> Option { + self.first_present_at + } + + /// Drains newly recorded events and returns the incidents sealed since + /// the previous poll. + pub fn poll(&mut self) -> Vec { + let drained = self.collector.collect_unseen(); + if self.first_present_at.is_none() { + self.first_present_at = drained.entries.iter().find_map(|entry| match entry { + ForegroundJournalEntry::Boundary(IntervalBoundary::Presented(presented)) => { + Some(presented.presentation.present_end) + } + _ => None, + }); + } + self.sealer + .push_entries(drained.entries) + .into_iter() + .filter_map(|snapshot| { + HangIncident::detect(snapshot, self.threshold, self.frame_budget) + }) + .collect() + } +} + +/// A [`HangIncident`] in a telemetry-friendly form: timestamps and durations +/// in fractional milliseconds since app startup (microsecond precision), +/// locations as plain data, contributor count capped by the converter. +#[derive(Debug, Clone, Serialize)] +pub struct SerializedHangIncident { + /// Identifies the rules used to exclude interrupted measurements. + pub measurement_version: u32, + /// `"startup"` when the active window began before the first observed + /// newly drawn frame finished platform submission (see + /// [`HangDetector::first_present_at`]), otherwise `"steady"`. + pub phase: &'static str, + /// `"threshold"` or `"budget"` (see [`HangTrigger`]). + pub trigger: HangTrigger, + /// When the incident's active window started, in milliseconds since app + /// startup: the sealing frame's first invalidation, or the earliest + /// contributor's start when nothing was pending a repaint. Foreground + /// idle time between the previous frame and the cause is excluded. + pub start_ms: f64, + /// Length of the active window in milliseconds: from the cause to the + /// seal. Exceeds `stall_ms` when several stalls piled up on one frame. + pub active_ms: f64, + /// The longest single block of foreground work, in milliseconds: the + /// best estimate of the freeze a user perceived. Below the hang + /// threshold (possibly zero) when the frame budget alone triggered the + /// incident. + pub stall_ms: f64, + /// For presentation-sealed incidents, how long the submitted frame had + /// been dirty, in milliseconds. + pub dirty_to_present_ms: Option, + /// What closed the incident: `"present"`, `"frame_skipped"`, `"idle"`, or + /// `"power_transition"`. This labels the boundary, not the hang's cause — + /// the cause is the first contributor. + pub sealed_by: &'static str, + /// Fraction of the active window the foreground spent working, + /// `0.0..=1.0`. Low values with a high `dirty_to_present_ms` indicate + /// throttling or scheduling delay rather than application work. + pub busy_fraction: f64, + /// Total events recorded in the interval (before the contributor cap). + pub event_count: usize, + /// Count of task polls below the journal's floor. + pub small_poll_count: u64, + /// Total duration of task polls below the journal's floor, in milliseconds. + pub small_poll_total_ms: f64, + /// Events lost to caps or ring overwrites. + pub dropped_events: u64, + /// Whether one or more journal entries were unavailable in the interval. + /// Threshold-qualified contributors remain valid, but cumulative budget + /// conclusions and boundary attribution are not trusted across the gap. + pub journal_discontinuous: bool, + /// The incident's contributors (see [`HangIncident::contributors`]) in + /// start order. The cap keeps the longest ones; `stall_ms` is always + /// among them. + pub contributors: Vec, + /// Contributors elided by the cap. + pub contributors_elided: usize, +} + +/// One hang contributor in serialized form. +/// +/// Foreground work nests: an input dispatch can synchronously draw a window, +/// a draw can poll a task. `depth` expresses that containment — a depth-1 +/// event's time is already inside some depth-0 event's duration, so summing +/// sibling durations across depths double-counts. +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "kind", rename_all = "snake_case")] +pub enum SerializedHangContributor { + /// A foreground task poll. + TaskPoll { + /// Where the task was spawned. + location: SerializedLocation, + /// When the poll started, in milliseconds since app startup. + start_ms: f64, + /// How long the poll blocked the foreground, in milliseconds. + duration_ms: f64, + /// How many other events in the interval contain this one. + depth: usize, + }, + /// An action handler. + Action { + /// The action's name. + name: &'static str, + /// When the handler started, in milliseconds since app startup. + start_ms: f64, + /// How long the handler ran, in milliseconds. + duration_ms: f64, + /// How many other events in the interval contain this one. + depth: usize, + }, + /// A platform input dispatch. + Input { + /// The platform input variant dispatched, e.g. `"key_down"`. + /// Named `input_kind` because `kind` is this enum's serde tag. + input_kind: &'static str, + /// When the dispatch started, in milliseconds since app startup. + start_ms: f64, + /// How long the dispatch ran, in milliseconds. + duration_ms: f64, + /// Whether handling the input invalidated a window. + caused_invalidation: bool, + /// How many other events in the interval contain this one. + depth: usize, + }, + /// A window draw. + Draw { + /// The window that was drawn. + window_id: u64, + /// When the draw started, in milliseconds since app startup. + start_ms: f64, + /// How long the draw took, in milliseconds. + duration_ms: f64, + /// Time from the frame's first invalidation to the end of its draw, + /// in milliseconds. + dirty_to_draw_ms: Option, + /// Invalidations coalesced into the frame. + invalidations: u64, + /// How many other events in the interval contain this one. + depth: usize, + }, + /// Work spent submitting a frame to the platform. + Present { + /// The window whose frame was submitted. + window_id: u64, + /// When submission began, in milliseconds since app startup. + start_ms: f64, + /// How long platform submission took, in milliseconds. + duration_ms: f64, + /// How many other events in the interval contain this one. + depth: usize, + }, +} + +/// Milliseconds with microsecond precision: keeps `dbg!`/JSON output short +/// (`115.954` rather than `115.95400000000001` or `115954`). +fn as_millis(duration: Duration) -> f64 { + duration.as_micros() as f64 / 1000.0 +} + +impl SerializedHangIncident { + /// Converts an incident, keeping at most `max_contributors` contributors. + /// `first_present_at` is the end of the first observed newly drawn frame's + /// platform submission (typically [`HangDetector::first_present_at`]); + /// incidents whose active window begins before it are tagged `"startup"`. + pub fn convert( + startup: Instant, + incident: &HangIncident, + max_contributors: usize, + first_present_at: Option, + ) -> Self { + let since_startup = + |instant: Instant| as_millis(instant.saturating_duration_since(startup)); + let snapshot = &incident.snapshot; + let (active_start, active_end) = incident.active_window(); + let active = active_end.duration_since(active_start); + let busy_fraction = if active.is_zero() { + 1.0 + } else { + snapshot + .occupancy_within(active_start, active_end) + .div_duration_f64(active) + .min(1.0) + }; + Self { + phase: match first_present_at { + Some(first_present_at) if active_start >= first_present_at => "steady", + _ => "startup", + }, + measurement_version: MEASUREMENT_VERSION, + trigger: incident.trigger, + start_ms: since_startup(active_start), + active_ms: as_millis(active), + stall_ms: incident + .contributors + .first() + .map(|event| as_millis(event.duration())) + .unwrap_or(0.0), + dirty_to_present_ms: match snapshot.boundary { + IntervalBoundary::Presented(presented) => { + presented.dirty_to_present_duration().map(as_millis) + } + IntervalBoundary::FrameSkipped(_) + | IntervalBoundary::Idle { .. } + | IntervalBoundary::PowerTransition { .. } => None, + }, + sealed_by: match snapshot.boundary { + IntervalBoundary::Presented(_) => "present", + IntervalBoundary::FrameSkipped(_) => "frame_skipped", + IntervalBoundary::Idle { .. } => "idle", + IntervalBoundary::PowerTransition { .. } => "power_transition", + }, + busy_fraction: (busy_fraction * 1000.0).round() / 1000.0, + event_count: snapshot.events.len(), + small_poll_count: snapshot.small_poll_summary().count, + small_poll_total_ms: as_millis(snapshot.small_poll_summary().total), + dropped_events: snapshot.dropped_events, + journal_discontinuous: snapshot.journal_discontinuous, + contributors: { + let mut kept: Vec<&ForegroundEvent> = incident + .contributors + .iter() + .take(max_contributors) + .collect(); + kept.sort_by_key(|event| event.start_time()); + kept.into_iter() + .map(|event| { + SerializedHangContributor::convert( + startup, + event, + nesting_depth(event, &snapshot.events), + ) + }) + .collect() + }, + contributors_elided: incident.contributors.len().saturating_sub(max_contributors), + } + } +} + +/// How many events in `events` strictly contain `event`'s span. Events with +/// identical spans don't count as containing each other, so `event`'s own +/// presence in `events` contributes nothing. +fn nesting_depth(event: &ForegroundEvent, events: &[ForegroundEvent]) -> usize { + let (start, end) = (event.start_time(), event.end_time()); + events + .iter() + .filter(|other| { + let (other_start, other_end) = (other.start_time(), other.end_time()); + other_start <= start && end <= other_end && (other_start < start || end < other_end) + }) + .count() +} + +impl SerializedHangContributor { + fn convert(startup: Instant, event: &ForegroundEvent, depth: usize) -> Self { + let since_startup = + |instant: Instant| as_millis(instant.saturating_duration_since(startup)); + let duration_ms = as_millis(event.duration()); + match event { + ForegroundEvent::TaskPoll(timing) => Self::TaskPoll { + location: timing.location.into(), + start_ms: since_startup(timing.start), + duration_ms, + depth, + }, + ForegroundEvent::Action(timing) => Self::Action { + name: timing.name, + start_ms: since_startup(timing.start), + duration_ms, + depth, + }, + ForegroundEvent::Input(timing) => Self::Input { + input_kind: timing.kind, + start_ms: since_startup(timing.start), + duration_ms, + caused_invalidation: timing.caused_invalidation, + depth, + }, + ForegroundEvent::Draw(timing) => Self::Draw { + window_id: timing.window_id.as_u64(), + start_ms: since_startup(timing.draw_start), + duration_ms, + dirty_to_draw_ms: timing.dirty_to_draw_duration().map(as_millis), + invalidations: timing.invalidations, + depth, + }, + ForegroundEvent::Present(timing) => Self::Present { + window_id: timing.window_id.as_u64(), + start_ms: since_startup(timing.present_start), + duration_ms, + depth, + }, + ForegroundEvent::SmallPolls(flush) => { + // The sealer folds these out of snapshot events; a contributor + // can therefore never be one, but serialize defensively as an + // unnamed poll spanning the flush rather than panicking. + Self::TaskPoll { + location: SerializedLocation { + file: "".into(), + line: 0, + column: 0, + }, + start_ms: since_startup(flush.since), + duration_ms, + depth, + } + } + } + } +} + +impl HangIncident { + /// The incident's reporting window: from its earliest cause — the + /// sealing frame's first invalidation, or the earliest contributor's + /// start when no repaint was pending — to the seal. This trims + /// foreground-idle time between the previous frame and the cause, and + /// may begin before the underlying snapshot when a contributor was + /// already running at the previous seal. + pub fn active_window(&self) -> (Instant, Instant) { + let snapshot = &self.snapshot; + let dirty_at = snapshot.boundary.dirty_at(); + let earliest_contributor = self + .contributors + .iter() + .map(|event| event.start_time()) + .min(); + let start = [dirty_at, earliest_contributor] + .into_iter() + .flatten() + .min() + .unwrap_or(snapshot.interval_start); + (start, snapshot.interval_end()) + } + + /// Returns an incident when the snapshot contains at least one event + /// that blocked the foreground for `threshold` or longer, or when the + /// interval's total foreground spend — event time plus folded + /// small-poll time — reached `frame_budget` even though no single event + /// did. In the latter case every event in the interval becomes a + /// contributor, since no single stall explains the busy interval. + pub fn detect( + snapshot: FrameSnapshot, + threshold: Duration, + frame_budget: Duration, + ) -> Option { + let mut contributors: Vec = snapshot + .events + .iter() + .filter(|event| event.duration() >= threshold) + .copied() + .collect(); + let trigger = if contributors.is_empty() { + if snapshot.journal_discontinuous { + return None; + } + let spend = snapshot.occupancy_within(snapshot.interval_start, snapshot.interval_end()); + if spend < frame_budget { + return None; + } + contributors = snapshot.events.clone(); + HangTrigger::Budget + } else { + HangTrigger::Threshold + }; + contributors.sort_by_key(|event| std::cmp::Reverse(event.duration())); + Some(Self { + snapshot, + trigger, + contributors, + }) + } +} + +#[cfg(test)] +mod tests { + use std::cell::Cell; + use std::rc::Rc; + use std::thread; + use std::time::Duration; + + use proptest::prelude::*; + use rand::prelude::*; + use scheduler::SpawnTime; + + use crate::{ + self as gpui, Context, FocusHandle, InteractiveElement, IntoElement, Modifiers, + MouseButton, Render, Styled, TestAppContext, VisualTestContext, Window, WindowId, div, + point, px, + }; + + use crate::profiler::{ActionTiming, FrameTiming, PresentTiming, TaskTiming, YieldTime}; + + use super::super::journal::{ + FRAME_DEADLINE, ForegroundEvent, ForegroundJournalEntry, FrameSkipReason, FrameSkipped, + FrameSnapshot, FrameStateChange, InputTiming, IntervalBoundary, IntervalSealer, + PlatformSignal, PollSummary, PresentedFrame, SmallPollFlush, + install_test_foreground_journal, record_present, + }; + use super::{ + HangDetector, HangIncident, HangTrigger, SerializedHangContributor, SerializedHangIncident, + }; + + actions!(hang_test, [HangyAction]); + + // Well above legitimate per-event work in a test app (layout of one div, + // empty polls), well below the injected hangs. + const HANG_THRESHOLD: Duration = Duration::from_millis(10); + // Equal to the threshold, mirroring how production wires the detector + // today. + const FRAME_BUDGET: Duration = HANG_THRESHOLD; + + #[test] + fn completed_skips_preserve_real_hangs_and_serialize_their_boundary() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(1); + for discontinuous in [false, true] { + for trigger in [HangTrigger::Threshold, HangTrigger::Budget] { + let mut sealer = IntervalSealer::new(startup); + let mut entries = Vec::new(); + match trigger { + HangTrigger::Threshold => entries.push(ForegroundJournalEntry::Event( + task_poll_event(at(10), at(30)), + )), + HangTrigger::Budget => entries.extend([ + ForegroundJournalEntry::Event(task_poll_event(at(10), at(16))), + ForegroundJournalEntry::Event(task_poll_event(at(20), at(26))), + ]), + } + if discontinuous { + entries.push(ForegroundJournalEntry::Discontinuity { lost: 1 }); + } + entries.push(ForegroundJournalEntry::Boundary( + IntervalBoundary::FrameSkipped(FrameSkipped { + window_id, + at: at(60), + reason: FrameSkipReason::NoRenderNeeded, + }), + )); + let snapshots = sealer.push_entries(entries); + let [snapshot] = snapshots.as_slice() else { + panic!("expected one snapshot, got {snapshots:?}"); + }; + let incident = HangIncident::detect(snapshot.clone(), HANG_THRESHOLD, FRAME_BUDGET); + if discontinuous && trigger == HangTrigger::Budget { + assert!(incident.is_none(), "skips must not exempt journal gaps"); + continue; + } + let incident = incident.expect("real work still qualifies across a skip"); + assert_eq!(incident.trigger, trigger); + let serialized = SerializedHangIncident::convert(startup, &incident, 10, None); + assert_eq!(serialized.sealed_by, "frame_skipped"); + assert_eq!(serialized.dirty_to_present_ms, None); + assert_eq!(serialized.start_ms, 10.0); + assert_eq!(serialized.active_ms, 50.0); + assert_eq!(serialized.journal_discontinuous, discontinuous); + assert_eq!(serialized.event_count, incident.contributors.len()); + let json = serde_json::to_value(&serialized).expect("serialize incident"); + assert_eq!(json["sealed_by"], "frame_skipped"); + assert!(json["dirty_to_present_ms"].is_null()); + } + } + } + + #[test] + fn delayed_platform_signals_without_work_are_not_hangs() { + let start = scheduler::Instant::now(); + let window_id = WindowId::from(1); + let mut sealer = IntervalSealer::new(start); + let snapshots = sealer.push_entries([ + ForegroundJournalEntry::PlatformSignal(PlatformSignal { + window_id, + signal_at: Some(start), + handled_at: start + Duration::from_secs(5), + source: crate::FrameRequestSource::NativeCallback, + }), + ForegroundJournalEntry::Boundary(IntervalBoundary::FrameSkipped(FrameSkipped { + window_id, + at: start + Duration::from_secs(6), + reason: FrameSkipReason::NoRenderNeeded, + })), + ]); + assert!( + snapshots.is_empty(), + "a late signal without work seals nothing, got {snapshots:?}" + ); + } + + /// A hang that outlives the frame deadline stays in one incident with + /// the frame it starved: the deadline only unblocks idle boundaries, so + /// the eventual presentation seals the hang together with its + /// dirty-to-present association. + #[test] + fn a_hang_outliving_the_frame_deadline_keeps_its_frame_association() { + let start = scheduler::Instant::now(); + let window_id = WindowId::from(0x51E17); + let hang_end = start + FRAME_DEADLINE * 5; + let presented_at = hang_end + Duration::from_millis(16); + let (journal, _journal_guard) = install_test_foreground_journal(64, 8); + let mut detector = HangDetector::new(journal, HANG_THRESHOLD, FRAME_BUDGET); + + let snapshots = detector.sealer.push_entries([ + ForegroundJournalEntry::FrameState(FrameStateChange::Pending { + window_id, + dirty_at: start, + }), + ForegroundJournalEntry::Event(task_poll_event(start, hang_end)), + ]); + assert!(snapshots.is_empty(), "nothing seals mid-hang"); + + let snapshots = detector + .sealer + .push_entries([ForegroundJournalEntry::Boundary( + IntervalBoundary::Presented(PresentedFrame { + frame: frame(window_id, presented_at), + presentation: PresentTiming { + window_id, + present_start: presented_at - Duration::from_millis(1), + present_end: presented_at, + animation_interval: None, + }, + }), + )]); + let [snapshot] = snapshots.as_slice() else { + panic!("expected one presented snapshot, got {snapshots:?}"); + }; + let incident = HangIncident::detect(snapshot.clone(), HANG_THRESHOLD, FRAME_BUDGET) + .expect("the hang qualifies"); + assert!(matches!( + incident.contributors[0], + ForegroundEvent::TaskPoll(timing) if timing.end.0 == hang_end + )); + assert!(matches!( + incident.snapshot.boundary, + IntervalBoundary::Presented(_) + )); + } + + #[test] + fn serialized_incident_reports_presented_seal_fields() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(0xF1E1D); + + let presentation = PresentTiming { + window_id, + present_start: at(380), + present_end: at(400), + animation_interval: None, + }; + let frame = FrameTiming { + window_id, + dirty_at: Some(at(100)), + invalidations: 3, + draw_start: at(350), + draw_end: at(380), + }; + let snapshot = FrameSnapshot { + interval_start: at(150), + boundary: IntervalBoundary::Presented(PresentedFrame { + frame, + presentation, + }), + events: vec![ + task_poll_event(at(150), at(300)), + ForegroundEvent::Action(ActionTiming { + name: "test::SlowAction", + start: at(300), + end: at(340), + }), + ForegroundEvent::Input(InputTiming { + kind: "test", + start: at(340), + end: at(345), + caused_invalidation: false, + }), + ForegroundEvent::Present(presentation), + ], + small_polls: vec![SmallPollFlush { + summary: PollSummary { + count: 2, + total: Duration::from_millis(1), + }, + since: at(105), + until: at(145), + }], + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = + HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET).expect("has contributors"); + let serialized = SerializedHangIncident::convert(startup, &incident, 1, Some(at(50))); + + assert_eq!(serialized.phase, "steady"); + assert_eq!(serialized.trigger, HangTrigger::Threshold); + // The frame's first invalidation anchors the active window, not the + // interval start or the first contributor. + assert_eq!(serialized.start_ms, 100.0); + assert_eq!(serialized.active_ms, 300.0); + assert_eq!(serialized.stall_ms, 150.0); + assert_eq!(serialized.dirty_to_present_ms, Some(300.0)); + assert_eq!(serialized.sealed_by, "present"); + // Occupancy: poll 150ms + action 40ms + input 5ms + present 20ms + + // folded polls 1ms = 216ms of the 300ms window. + assert_eq!(serialized.busy_fraction, 0.72); + assert_eq!(serialized.event_count, 4); + assert_eq!(serialized.small_poll_count, 2); + assert_eq!(serialized.small_poll_total_ms, 1.0); + assert_eq!(serialized.dropped_events, 0); + // Three contributors qualify (poll, action, present); the cap keeps + // the longest and counts the rest. + assert_eq!(serialized.contributors.len(), 1); + assert_eq!(serialized.contributors_elided, 2); + assert!(matches!( + serialized.contributors[0], + SerializedHangContributor::TaskPoll { + start_ms, + duration_ms, + .. + } if start_ms == 150.0 && duration_ms == 150.0 + )); + } + + #[test] + fn hang_monitor_polls_on_its_interval_and_on_flush() { + use super::{HangMonitor, HangMonitorPollReason}; + + let (journal, _guard) = install_test_foreground_journal(64, 4); + // Each monitor reports on its own channel, which disconnects once the + // monitor's thread has exited and dropped its callback. + let spawn_monitor = |journal, interval| { + let (sender, receiver) = std::sync::mpsc::channel(); + let monitor = HangMonitor::spawn( + HangDetector::new(journal, HANG_THRESHOLD, FRAME_BUDGET), + interval, + move |poll| { + if !poll.incidents.is_empty() { + sender.send((poll.reason, poll.incidents.len())).ok(); + } + }, + ) + .expect("spawn monitor thread"); + (monitor, receiver) + }; + + let (monitor, receiver) = spawn_monitor(journal.clone(), Duration::from_millis(10)); + simulate_blocked_foreground_poll(HANG_THRESHOLD * 2); + assert_eq!( + receiver.recv_timeout(Duration::from_secs(10)).ok(), + Some((HangMonitorPollReason::Interval, 1)), + ); + drop(monitor); + assert_eq!( + receiver.recv_timeout(Duration::from_secs(10)), + Err(std::sync::mpsc::RecvTimeoutError::Disconnected), + ); + + // An interval longer than the test isolates the flush path. + let (monitor, receiver) = spawn_monitor(journal, Duration::from_secs(3600)); + simulate_blocked_foreground_poll(HANG_THRESHOLD * 2); + let flushed = monitor.request_flush().expect("monitor thread is running"); + futures::executor::block_on(flushed).expect("flush completes"); + assert_eq!( + receiver.try_recv().ok(), + Some((HangMonitorPollReason::Flush, 1)), + ); + + drop(monitor); + assert_eq!( + receiver.recv_timeout(Duration::from_secs(10)), + Err(std::sync::mpsc::RecvTimeoutError::Disconnected), + ); + } + + #[gpui::test] + fn app_flushes_its_hang_monitor_on_shutdown(cx: &mut TestAppContext) { + use super::{HangMonitorConfig, HangMonitorPollReason}; + + // The monitor runs on a real OS thread, so shutdown has to park until it + // finishes the flush, and its completion wakes the scheduler from that thread. + cx.executor().allow_parking(); + + let (sender, receiver) = std::sync::mpsc::channel(); + cx.update(|cx| { + cx.start_hang_monitor( + HangMonitorConfig { + threshold: HANG_THRESHOLD, + frame_budget: FRAME_BUDGET, + // Longer than the test, so only shutdown can poll. + interval: Duration::from_secs(3600), + }, + move |poll| { + sender.send(poll.reason).ok(); + }, + ) + .expect("start hang monitor"); + }); + assert!(receiver.try_recv().is_err()); + + cx.update(|cx| cx.shutdown()); + assert_eq!(receiver.try_recv().ok(), Some(HangMonitorPollReason::Flush)); + } + + #[gpui::test] + fn starting_the_hang_monitor_twice_is_rejected(cx: &mut TestAppContext) { + use super::{HangMonitorConfig, HangMonitorError}; + + let config = HangMonitorConfig { + threshold: HANG_THRESHOLD, + frame_budget: FRAME_BUDGET, + interval: Duration::from_secs(3600), + }; + cx.update(|cx| { + cx.start_hang_monitor(config, |_| {}) + .expect("start hang monitor"); + let second = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + cx.start_hang_monitor(config, |_| {}) + })); + // Debug builds also assert, so misuse is caught during development. + if cfg!(debug_assertions) { + assert!(second.is_err()); + } else { + assert!(matches!(second, Ok(Err(HangMonitorError::AlreadyStarted)))); + } + }); + } + + #[test] + fn serialized_incident_reports_idle_seal_fields() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + + let idle = FrameSnapshot { + interval_start: at(200), + boundary: IntervalBoundary::Idle { ended_at: at(260) }, + events: vec![task_poll_event(at(200), at(260))], + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + let incident = + HangIncident::detect(idle, HANG_THRESHOLD, FRAME_BUDGET).expect("has contributors"); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, None); + assert_eq!(serialized.phase, "startup"); + assert_eq!(serialized.sealed_by, "idle"); + assert_eq!(serialized.dirty_to_present_ms, None); + // With no frame, the earliest contributor anchors the active window. + assert_eq!(serialized.start_ms, 200.0); + assert_eq!(serialized.active_ms, 60.0); + assert_eq!(serialized.stall_ms, 60.0); + assert_eq!(serialized.busy_fraction, 1.0); + } + + #[test] + fn phase_is_startup_until_the_first_present() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let snapshot = FrameSnapshot { + interval_start: at(500), + boundary: IntervalBoundary::Idle { ended_at: at(600) }, + events: vec![task_poll_event(at(500), at(600))], + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + let incident = + HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET).expect("has contributors"); + + let phase = |first_present_at| { + SerializedHangIncident::convert(startup, &incident, 8, first_present_at).phase + }; + assert_eq!(phase(None), "startup", "nothing has been presented yet"); + assert_eq!( + phase(Some(at(700))), + "startup", + "the incident began before the first presentation" + ); + assert_eq!( + phase(Some(at(500))), + "steady", + "an incident beginning exactly at first presentation is steady" + ); + assert_eq!(phase(Some(at(100))), "steady"); + } + + /// The detector must latch the first presentation it observes and never + /// move it. + #[test] + fn first_present_at_latches_on_the_first_observed_presentation() { + let (journal, _journal_guard) = install_test_foreground_journal(64, 8); + let mut detector = HangDetector::new(journal, HANG_THRESHOLD, FRAME_BUDGET); + let window_id = WindowId::from(0x1A7C4); + + let first_present_end = scheduler::Instant::now(); + record_present( + presentation(window_id, first_present_end), + Some(frame(window_id, first_present_end)), + ); + detector.poll(); + let latched = detector + .first_present_at() + .expect("a presentation was recorded"); + assert_eq!(latched, first_present_end); + + record_present( + presentation(window_id, first_present_end + Duration::from_millis(16)), + Some(frame( + window_id, + first_present_end + Duration::from_millis(16), + )), + ); + detector.poll(); + assert_eq!(detector.first_present_at(), Some(latched)); + } + + /// The only work inside the 100ms active window here is the 50ms poll, + /// so the busy fraction is 0.5: the folded polls' flush span lies + /// entirely before the window and must contribute nothing to it + /// (PR #62779 review finding 5). + #[test] + fn busy_fraction_excludes_small_polls_outside_the_active_window() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Idle { ended_at: at(1000) }, + events: vec![task_poll_event(at(900), at(950))], + // Folded polls that ran during at(0)..at(800), long before the + // active window opens at the contributor's start. + small_polls: vec![SmallPollFlush { + summary: PollSummary { + count: 500, + total: Duration::from_millis(400), + }, + since: at(0), + until: at(800), + }], + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = + HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET).expect("has contributors"); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, None); + + assert_eq!(serialized.busy_fraction, 0.5); + } + + /// Many sub-threshold pieces of work can drop a frame as thoroughly as + /// one long stall: an interval whose total foreground spend reaches the + /// budget is an incident even when no single event crosses the hang + /// threshold, and every event becomes a contributor so the report shows + /// what filled the interval. + #[test] + fn an_interval_of_small_work_over_budget_is_an_incident() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(0xB0D6E7); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Presented(PresentedFrame { + frame: FrameTiming { + window_id, + dirty_at: Some(at(0)), + invalidations: 1, + draw_start: at(140), + draw_end: at(145), + }, + presentation: PresentTiming { + window_id, + present_start: at(145), + present_end: at(150), + animation_interval: None, + }, + }), + events: vec![ + task_poll_event(at(0), at(5)), + task_poll_event(at(5), at(13)), + task_poll_event(at(13), at(18)), + ], + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET) + .expect("foreground spend exceeded the frame budget"); + assert_eq!(incident.trigger, HangTrigger::Budget); + assert_eq!(incident.contributors.len(), 3); + assert_eq!( + incident.contributors[0].duration(), + Duration::from_millis(8) + ); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, Some(startup)); + assert_eq!(serialized.trigger, HangTrigger::Budget); + assert_eq!(serialized.stall_ms, 8.0); + assert_eq!(serialized.dirty_to_present_ms, Some(150.0)); + assert_eq!(serialized.sealed_by, "present"); + } + + #[test] + fn a_journal_gap_suppresses_budget_inference_but_retains_observed_hangs() { + let start = scheduler::Instant::now(); + let at = |ms: u64| start + Duration::from_millis(ms); + let mut sealer = super::super::journal::IntervalSealer::new(start); + let snapshots = sealer.push_entries([ + ForegroundJournalEntry::Event(task_poll_event(at(0), at(5))), + ForegroundJournalEntry::Discontinuity { lost: 1 }, + ForegroundJournalEntry::Event(task_poll_event(at(10), at(15))), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at: at(15) }), + ForegroundJournalEntry::Discontinuity { lost: 1 }, + ForegroundJournalEntry::Event(task_poll_event(at(20), at(32))), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at: at(32) }), + ForegroundJournalEntry::Event(task_poll_event(at(40), at(52))), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at: at(52) }), + ]); + let [budget_only, observed_hang, clean] = snapshots.as_slice() else { + panic!("expected two discontinuous snapshots followed by a clean one"); + }; + + assert!(budget_only.journal_discontinuous); + assert_eq!(budget_only.dropped_events, 1); + assert!(HangIncident::detect(budget_only.clone(), HANG_THRESHOLD, FRAME_BUDGET).is_none()); + + let observed_hang = + HangIncident::detect(observed_hang.clone(), HANG_THRESHOLD, FRAME_BUDGET) + .expect("the directly observed threshold-qualified hang remains valid"); + assert!(observed_hang.snapshot.journal_discontinuous); + assert_eq!(observed_hang.contributors.len(), 1); + let serialized = SerializedHangIncident::convert(start, &observed_hang, 8, None); + assert!(serialized.journal_discontinuous); + + assert!(!clean.journal_discontinuous); + assert!(HangIncident::detect(clean.clone(), HANG_THRESHOLD, FRAME_BUDGET).is_some()); + } + + /// A frame that reaches the screen late with almost no foreground work + /// behind it — pure scheduling or presentation delay — is not a hang: + /// the budget measures foreground spend, not dirty-to-present time. + #[test] + fn a_slow_frame_with_little_foreground_spend_is_not_an_incident() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(0xFA57); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Presented(PresentedFrame { + frame: FrameTiming { + window_id, + dirty_at: Some(at(0)), + invalidations: 1, + draw_start: at(145), + draw_end: at(147), + }, + presentation: PresentTiming { + window_id, + present_start: at(149), + present_end: at(150), + animation_interval: None, + }, + }), + events: vec![task_poll_event(at(0), at(5))], + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + + assert!(HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET).is_none()); + } + + /// The budget applies to idle-sealed intervals too: a headless app (or + /// a stretch with no repaint pending) can still starve the foreground + /// with accumulated sub-threshold work. + #[test] + fn an_idle_sealed_interval_over_budget_is_an_incident() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Idle { ended_at: at(200) }, + events: (0..10) + .map(|i| task_poll_event(at(i * 20), at(i * 20 + 5))) + .collect(), + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET) + .expect("foreground spend exceeded the frame budget"); + assert_eq!(incident.contributors.len(), 10); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, Some(startup)); + assert_eq!(serialized.sealed_by, "idle"); + assert_eq!(serialized.dirty_to_present_ms, None); + assert_eq!(serialized.stall_ms, 5.0); + assert_eq!(serialized.contributors_elided, 2); + } + + /// Contributors serialize in start order with their nesting depth: an + /// input dispatch that synchronously drew a window reads as the input at + /// depth 0 followed by the draw at depth 1, rather than two unrelated + /// blocks of equal wall time. + #[test] + fn serialized_contributors_are_chronological_with_nesting_depths() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(0x2E57ED); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Idle { ended_at: at(80) }, + events: vec![ + task_poll_event(at(50), at(70)), + ForegroundEvent::Input(InputTiming { + kind: "mouse_move", + start: at(0), + end: at(40), + caused_invalidation: true, + }), + ForegroundEvent::Draw(FrameTiming { + window_id, + dirty_at: Some(at(0)), + invalidations: 1, + draw_start: at(1), + draw_end: at(39), + }), + ], + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = + HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET).expect("has contributors"); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, Some(startup)); + + assert_eq!(serialized.stall_ms, 40.0); + assert!(matches!( + serialized.contributors.as_slice(), + [ + SerializedHangContributor::Input { + input_kind: "mouse_move", + depth: 0, + .. + }, + SerializedHangContributor::Draw { depth: 1, .. }, + SerializedHangContributor::TaskPoll { depth: 0, .. }, + ] + )); + } + + /// Folded small polls count toward foreground spend, so an interval can + /// reach the budget with no retained events at all. The incident then + /// has no contributors and the small-poll summary carries the story. + #[test] + fn small_poll_spend_alone_can_reach_the_budget() { + let startup = scheduler::Instant::now(); + let at = |ms: u64| startup + Duration::from_millis(ms); + let window_id = WindowId::from(0xDE1A7); + let snapshot = FrameSnapshot { + interval_start: at(0), + boundary: IntervalBoundary::Presented(PresentedFrame { + frame: FrameTiming { + window_id, + dirty_at: Some(at(0)), + invalidations: 1, + draw_start: at(148), + draw_end: at(149), + }, + presentation: PresentTiming { + window_id, + present_start: at(149), + present_end: at(150), + animation_interval: None, + }, + }), + events: Vec::new(), + small_polls: vec![SmallPollFlush { + summary: PollSummary { + count: 40, + total: Duration::from_millis(12), + }, + since: at(0), + until: at(150), + }], + dropped_events: 0, + journal_discontinuous: false, + }; + + let incident = HangIncident::detect(snapshot, HANG_THRESHOLD, FRAME_BUDGET) + .expect("small-poll spend exceeded the frame budget"); + assert!(incident.contributors.is_empty()); + let serialized = SerializedHangIncident::convert(startup, &incident, 8, Some(startup)); + assert_eq!(serialized.stall_ms, 0.0); + assert_eq!(serialized.event_count, 0); + assert_eq!(serialized.small_poll_count, 40); + assert_eq!(serialized.dirty_to_present_ms, Some(150.0)); + assert_eq!(serialized.busy_fraction, 0.08); + } + + proptest! { + #![proptest_config(ProptestConfig { + failure_persistence: None, + ..ProptestConfig::default() + })] + + #[test] + fn detection_matches_threshold_and_budget_model_at_boundaries( + durations_ms in prop::collection::vec(0u16..=50, 0..=16), + threshold_ms in 0u16..=60, + frame_budget_ms in 0u16..=500, + small_poll_total_ms in 0u16..=100, + ) { + let origin = scheduler::Instant::now(); + let mut cursor_ms = 0u64; + let events = durations_ms + .iter() + .map(|duration_ms| { + let start = origin + Duration::from_millis(cursor_ms); + cursor_ms += u64::from(*duration_ms); + let end = origin + Duration::from_millis(cursor_ms); + cursor_ms += 1; + ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end, + caused_invalidation: false, + }) + }) + .collect::>(); + let interval_end_ms = cursor_ms.max(1); + let snapshot = FrameSnapshot { + interval_start: origin, + boundary: IntervalBoundary::Idle { + ended_at: origin + Duration::from_millis(interval_end_ms), + }, + events, + small_polls: vec![SmallPollFlush { + summary: PollSummary { + count: u64::from(small_poll_total_ms > 0), + total: Duration::from_millis(u64::from(small_poll_total_ms)), + }, + since: origin, + until: origin + Duration::from_millis(interval_end_ms), + }], + dropped_events: 0, + journal_discontinuous: false, + }; + let qualifying_durations = durations_ms + .iter() + .copied() + .filter(|duration| *duration >= threshold_ms) + .collect::>(); + let occupancy_ms = durations_ms + .iter() + .map(|duration| u64::from(*duration)) + .sum::() + + u64::from(small_poll_total_ms); + let expected_incident = + !qualifying_durations.is_empty() || occupancy_ms >= u64::from(frame_budget_ms); + + let incident = HangIncident::detect( + snapshot, + Duration::from_millis(u64::from(threshold_ms)), + Duration::from_millis(u64::from(frame_budget_ms)), + ); + prop_assert_eq!(incident.is_some(), expected_incident); + + if let Some(incident) = incident { + let mut expected_contributors = if qualifying_durations.is_empty() { + durations_ms + } else { + qualifying_durations + }; + expected_contributors.sort_unstable_by(|first, second| second.cmp(first)); + let observed_contributors = incident + .contributors + .iter() + .map(|event| event.duration().as_millis() as u16) + .collect::>(); + prop_assert_eq!(observed_contributors, expected_contributors); + } + } + } + + #[derive(Clone, Default)] + struct HangControls { + render: Rc>>, + input: Rc>>, + action: Rc>>, + } + + struct HangyView { + controls: HangControls, + focus_handle: FocusHandle, + } + + impl Render for HangyView { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + if let Some(duration) = self.controls.render.take() { + thread::sleep(duration); + } + let action_controls = self.controls.clone(); + let input_controls = self.controls.clone(); + div() + .size_full() + .track_focus(&self.focus_handle) + .on_action(cx.listener(move |_, _: &HangyAction, _, _| { + if let Some(duration) = action_controls.action.take() { + thread::sleep(duration); + } + })) + .on_mouse_down(MouseButton::Left, move |_, _, _| { + if let Some(duration) = input_controls.input.take() { + thread::sleep(duration); + } + }) + } + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + enum HangKind { + Render, + Input, + Action, + Poll, + } + + /// Renders a real element tree and injects randomly ordered, randomly + /// sized hangs through the production dispatch paths: view rendering + /// (window draw), platform input dispatch, action dispatch, and a + /// foreground task poll. Asserts the detector reports every one of them. + #[gpui::test(iterations = 5)] + fn detects_randomly_placed_foreground_hangs(mut rng: StdRng, cx: &mut TestAppContext) { + let (journal, _journal_guard) = install_test_foreground_journal(1024, 16); + let mut detector = HangDetector::new(journal, HANG_THRESHOLD, FRAME_BUDGET); + + let controls = HangControls::default(); + let (view, cx) = cx.add_window_view(|_, cx| HangyView { + controls: controls.clone(), + focus_handle: cx.focus_handle(), + }); + view.update_in(cx, |view, window, cx| { + window.focus(&view.focus_handle, cx); + }); + draw_window(cx); + + let mut injections: Vec = Vec::new(); + for _ in 0..rng.random_range(1..=4) { + let duration = HANG_THRESHOLD + Duration::from_millis(rng.random_range(5..25)); + let started = scheduler::Instant::now(); + let kind = match rng.random_range(0..4) { + 0 => { + controls.render.set(Some(duration)); + view.update_in(cx, |_, _, cx| cx.notify()); + draw_window(cx); + HangKind::Render + } + 1 => { + controls.input.set(Some(duration)); + cx.simulate_mouse_down( + point(px(5.), px(5.)), + MouseButton::Left, + Modifiers::none(), + ); + HangKind::Input + } + 2 => { + controls.action.set(Some(duration)); + cx.dispatch_action(HangyAction); + HangKind::Action + } + _ => { + simulate_blocked_foreground_poll(duration); + HangKind::Poll + } + }; + injections.push(Injection { + kind, + duration, + window: started..scheduler::Instant::now(), + }); + + // Innocent interleaved activity that must not confuse detection. + if rng.random_bool(0.5) { + draw_window(cx); + } + if rng.random_bool(0.5) { + cx.simulate_mouse_up(point(px(5.), px(5.)), MouseButton::Left, Modifiers::none()); + } + } + + // A final presentation seals whatever interval is still open. + draw_window(cx); + + let incidents = detector.poll(); + let contributors: Vec = incidents + .iter() + .flat_map(|incident| incident.contributors.iter().copied()) + .collect(); + + for injection in &injections { + assert_detected_once(injection, &contributors); + } + } + + struct Injection { + kind: HangKind, + duration: Duration, + window: std::ops::Range, + } + + /// Exactly one contributor of the injected kind must fall inside the + /// injection's window, and it must be at least as long as the injected + /// sleep (sleeps never wake early). Contributors outside every window are + /// ignored: on a loaded machine, uninjected work can legitimately exceed + /// the threshold, and reporting it is correct. + fn assert_detected_once(injection: &Injection, contributors: &[ForegroundEvent]) { + let Injection { + kind, + duration, + window, + } = injection; + let matches: Vec<&ForegroundEvent> = contributors + .iter() + .filter(|event| { + matches_kind(event, *kind) + && window.start <= event.start_time() + && event.end_time() <= window.end + }) + .collect(); + assert_eq!( + matches.len(), + 1, + "expected injected {kind:?} hang of {duration:?} to be reported exactly once; \ + observed {:?}", + matches + .iter() + .map(|event| event.duration()) + .collect::>(), + ); + if let Some(event) = matches.first() { + assert!( + event.duration() >= *duration, + "injected {kind:?} hang of {duration:?} was reported as {:?}", + event.duration(), + ); + } + } + + fn matches_kind(event: &ForegroundEvent, kind: HangKind) -> bool { + match (event, kind) { + (ForegroundEvent::Draw(_), HangKind::Render) => true, + (ForegroundEvent::Input(_), HangKind::Input) => true, + (ForegroundEvent::Action(timing), HangKind::Action) => { + timing.name.ends_with("HangyAction") + } + (ForegroundEvent::TaskPoll(timing), HangKind::Poll) => { + timing.location.file() == file!() + } + _ => false, + } + } + + fn draw_window(cx: &mut VisualTestContext) { + cx.update(|window, cx| { + let arena_clear = window.draw(cx); + window.present_if_needed(); + arena_clear.clear(cx); + }); + } + + /// The deterministic test scheduler does not bracket runnables with the + /// profiler hooks, so drive the same public hooks the platform + /// dispatchers call around a poll that blocks the foreground. + fn simulate_blocked_foreground_poll(duration: Duration) { + let location = std::panic::Location::caller(); + crate::profiler::update_running_task(SpawnTime(scheduler::Instant::now()), location); + thread::sleep(duration); + crate::profiler::save_task_timing(); + } + + fn task_poll_event(start: scheduler::Instant, end: scheduler::Instant) -> ForegroundEvent { + ForegroundEvent::TaskPoll(TaskTiming { + location: std::panic::Location::caller(), + spawned: SpawnTime(start), + start, + end: YieldTime(end), + }) + } + + fn presentation(window_id: WindowId, present_end: scheduler::Instant) -> PresentTiming { + PresentTiming { + window_id, + present_start: present_end - Duration::from_millis(1), + present_end, + animation_interval: None, + } + } + + fn frame(window_id: WindowId, draw_end: scheduler::Instant) -> FrameTiming { + FrameTiming { + window_id, + dirty_at: Some(draw_end - Duration::from_millis(2)), + invalidations: 1, + draw_start: draw_end - Duration::from_millis(1), + draw_end, + } + } +} diff --git a/vendor/gpui-pre/src/profiler/hang/monitor.rs b/vendor/gpui-pre/src/profiler/hang/monitor.rs new file mode 100644 index 00000000..566b32d3 --- /dev/null +++ b/vendor/gpui-pre/src/profiler/hang/monitor.rs @@ -0,0 +1,113 @@ +use std::sync::mpsc::{self, RecvTimeoutError}; +use std::time::Duration; + +use futures::channel::oneshot; +use scheduler::Instant; + +use super::{HangDetector, HangIncident}; + +/// Detection thresholds and polling cadence for +/// [`crate::App::start_hang_monitor`]. +#[derive(Debug, Clone, Copy)] +pub struct HangMonitorConfig { + /// Duration at which a single piece of foreground work counts as a hang. + pub threshold: Duration, + /// Total foreground spend within one interval that counts as a hang. + pub frame_budget: Duration, + /// How often the monitor thread drains the journal. + pub interval: Duration, +} + +/// Why [`crate::App::start_hang_monitor`] failed. +#[derive(Debug, thiserror::Error)] +pub enum HangMonitorError { + /// The monitor was already started for this app. + #[error("the hang monitor was already started")] + AlreadyStarted, + /// The monitor thread couldn't be spawned. + #[error("failed to spawn the hang monitor thread: {0}")] + Spawn(#[source] std::io::Error), +} + +/// Why a [`HangMonitor`] polled its detector. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum HangMonitorPollReason { + /// The monitor's regular interval elapsed. + Interval, + /// A poll was requested before the application quits. Consumers should + /// deliver any batched results now. + Flush, +} + +/// The incidents a [`HangMonitor`] collected in one poll. +pub struct HangMonitorPoll { + /// Incidents sealed since the previous poll, possibly none. + pub incidents: Vec, + /// See [`HangDetector::first_present_at`]. + pub first_present_at: Option, + /// Why this poll happened. + pub reason: HangMonitorPollReason, +} + +enum Request { + Flush { done: oneshot::Sender<()> }, +} + +/// Polls a [`HangDetector`] on a dedicated OS thread. +/// +/// Detection runs off the foreground thread so incidents are still collected +/// and reported while GPUI's executors are stalled. The thread owns the +/// detector and the callback; other threads only send it requests. Dropping +/// the monitor stops the thread. +pub(crate) struct HangMonitor { + requests: mpsc::Sender, +} + +impl HangMonitor { + /// Starts a thread that polls `detector` every `interval` and passes each + /// poll's result, including empty ones, to `on_poll` on that thread. + /// + /// # Errors + /// + /// Returns an error when the thread can't be spawned. + pub(crate) fn spawn( + mut detector: HangDetector, + interval: Duration, + mut on_poll: F, + ) -> std::io::Result + where + F: FnMut(HangMonitorPoll) + Send + 'static, + { + let (requests, receiver) = mpsc::channel(); + std::thread::Builder::new() + .name("HangDetection".to_string()) + .spawn(move || { + loop { + let (reason, done) = match receiver.recv_timeout(interval) { + Ok(Request::Flush { done }) => (HangMonitorPollReason::Flush, Some(done)), + Err(RecvTimeoutError::Timeout) => (HangMonitorPollReason::Interval, None), + Err(RecvTimeoutError::Disconnected) => break, + }; + let incidents = detector.poll(); + on_poll(HangMonitorPoll { + incidents, + first_present_at: detector.first_present_at(), + reason, + }); + if let Some(done) = done { + done.send(()).ok(); + } + } + })?; + Ok(Self { requests }) + } + + /// Asks the monitor thread to poll now with [`HangMonitorPollReason::Flush`] + /// without waiting for it. The returned receiver completes once the + /// callback has returned. Returns `None` if the thread has exited. + pub(crate) fn request_flush(&self) -> Option> { + let (done, finished) = oneshot::channel(); + self.requests.send(Request::Flush { done }).ok()?; + Some(finished) + } +} diff --git a/vendor/gpui-pre/src/profiler/journal.rs b/vendor/gpui-pre/src/profiler/journal.rs new file mode 100644 index 00000000..fba75ae7 --- /dev/null +++ b/vendor/gpui-pre/src/profiler/journal.rs @@ -0,0 +1,3522 @@ +//! A journal of foreground work and the semantic boundaries between activity intervals. +//! +//! The foreground thread records task polls, action handlers, input dispatches, +//! draws, and presentations as [`ForegroundEvent`]s in a bounded journal ring. +//! Task polls shorter than [`TASK_POLL_FLOOR`] are folded into summaries, which +//! bound the stream by the number of slow polls while preserving their exact +//! count and total duration. +//! +//! Presentation, completed frame skips, and foreground idle are explicit +//! [`IntervalBoundary`] entries in the same stream. Independent [`ForegroundJournalCollector`]s +//! feed entries to [`IntervalSealer`], a pure state machine that groups all work +//! preceding each boundary into a [`FrameSnapshot`]. The sealer does not infer +//! boundaries from elapsed time or from incidental event kinds such as draws. + +use std::cell::{RefCell, UnsafeCell}; +use std::collections::{HashMap, VecDeque}; +use std::mem::MaybeUninit; +use std::sync::{ + Arc, + atomic::{AtomicU64, AtomicUsize, Ordering}, +}; +use std::time::Duration; + +use gpui_util::ResultExt; +use scheduler::Instant; + +use super::{ActionTiming, FrameTiming, PresentTiming, TaskTiming}; +use crate::{App, WindowId, WindowVisibility}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(crate) enum PowerState { + Awake, + Suspended, +} + +/// Task polls shorter than this are folded into a [`PollSummary`] instead of +/// being recorded individually. This keeps the stream bounded by the number +/// of *slow* polls while preserving their exact count and total duration. +pub const TASK_POLL_FLOOR: Duration = Duration::from_micros(100); + +/// A dirty frame that has not been presented by this deadline stops blocking +/// foreground-idle boundaries, so a window that never presents (hidden or +/// occluded windows receive no frame callbacks) cannot suppress boundaries +/// indefinitely. Expiry only unblocks: the open interval still seals at a +/// presentation, completed frame skip, or idle boundary, keeping a starving +/// hang and the callback it starved in one interval. +pub const FRAME_DEADLINE: Duration = Duration::from_secs(1); + +/// Growth in [`system_suspended_time`] below this is attributed to reading +/// its two clocks separately (on Windows both advance only on the system +/// tick, up to 15.6 ms), not to a suspend. A real suspend, including freezing +/// and thawing processes around it, takes far longer. +const MIN_DETECTED_SUSPEND: Duration = Duration::from_millis(50); + +// Backstop against pathological event storms within a single interval. At the +// 100us floor, a fully hung second can produce at most ~10k recordable polls, +// so this bound is only reachable when something is already deeply wrong. +const MAX_INTERVAL_EVENTS: usize = 16 * 1024; + +// Allow 4MiB for the fixed ring allocation, including each slot's atomic +// metadata. The poll floor and frame cadence bound the event rate to roughly +// 10k per second in the worst case, so this holds several seconds of +// worst-case traffic between consumer drains. +const MAX_JOURNAL_ENTRIES: usize = (4 * 1024 * 1024) / core::mem::size_of::(); + +// Absorbs brief collisions with a collector reading the exact slot being +// wrapped. The foreground never waits for a reader; queued entries are retried +// in order on the next publication. +const MAX_PENDING_JOURNAL_ENTRIES: usize = 64; + +/// One entry in the foreground stream. +/// +/// Events are recorded in completion order (ordered by their end time). An +/// event that was in progress across a frame boundary (e.g. the task poll +/// enclosing a draw) is recorded when it *ends*, with timestamps that may +/// precede events recorded before it. +#[derive(Debug, Copy, Clone)] +pub enum ForegroundEvent { + /// A foreground task poll at least [`TASK_POLL_FLOOR`] long. + TaskPoll(TaskTiming), + /// A completed action handler. + Action(ActionTiming), + /// A dispatched platform input event. + Input(InputTiming), + /// A completed window draw. + Draw(FrameTiming), + /// Work spent submitting a frame to the platform. + Present(PresentTiming), + /// Aggregate of task polls below [`TASK_POLL_FLOOR`], flushed before the + /// next individually retained event or interval boundary. + SmallPolls(SmallPollFlush), +} + +impl ForegroundEvent { + /// When the work described by this event began. For draws this is the + /// start of the draw itself, not the frame's first invalidation. + pub fn start_time(&self) -> Instant { + match self { + Self::TaskPoll(timing) => timing.start, + Self::Action(timing) => timing.start, + Self::Input(timing) => timing.start, + Self::Draw(timing) => timing.draw_start, + Self::Present(timing) => timing.present_start, + Self::SmallPolls(flush) => flush.since, + } + } + + /// When the work described by this event ended. + pub fn end_time(&self) -> Instant { + match self { + Self::TaskPoll(timing) => timing.end.0, + Self::Action(timing) => timing.end, + Self::Input(timing) => timing.end, + Self::Draw(timing) => timing.draw_end, + Self::Present(timing) => timing.present_end, + Self::SmallPolls(flush) => flush.until, + } + } + + /// How long the work described by this event took. For + /// [`Self::SmallPolls`] this is the span the summary covers, not time + /// spent polling; use the summary's `total` for occupancy. + pub fn duration(&self) -> Duration { + self.end_time().duration_since(self.start_time()) + } +} + +/// Timing of one platform input dispatch on a window. +#[derive(Debug, Copy, Clone)] +pub struct InputTiming { + /// The platform input variant dispatched (see + /// [`crate::PlatformInput::kind_name`]). + pub kind: &'static str, + /// When the input dispatch started. + pub start: Instant, + /// When the input dispatch finished. + pub end: Instant, + /// Whether handling the input invalidated a window. + pub caused_invalidation: bool, +} + +/// A frame callback entering the foreground, without implying foreground work. +#[derive(Debug, Copy, Clone)] +pub struct PlatformSignal { + /// The window receiving the callback. + pub window_id: WindowId, + /// When the platform requested the callback, if its clock is supported. + pub signal_at: Option, + /// When foreground handling began. + pub handled_at: Instant, + /// Whether the callback came from the platform or local scheduling. + pub source: crate::FrameRequestSource, +} + +/// Why a completed frame request did not draw a new frame. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum FrameSkipReason { + /// The callback completed without needing a new render. + NoRenderNeeded, + /// An inactive window deferred drawing. + InactiveFrameRateLimit, + /// Thermal throttling deferred drawing. + ThermalFrameRateLimit, +} + +/// A completed frame request that returned without drawing a new frame. +#[derive(Debug, Copy, Clone)] +pub struct FrameSkipped { + /// The window whose callback returned. + pub window_id: WindowId, + /// When the foreground completed this callback. + pub at: Instant, + /// Why no new frame was drawn. + pub reason: FrameSkipReason, +} + +/// Exact count and total duration of task polls below [`TASK_POLL_FLOOR`]. +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] +pub struct PollSummary { + /// Number of polls below the floor. + pub count: u64, + /// Total duration of polls below the floor. + pub total: Duration, +} + +impl PollSummary { + fn add(&mut self, other: Self) { + self.count += other.count; + self.total += other.total; + } +} + +/// A flushed [`PollSummary`] and the tightest span containing its folded polls. +#[derive(Debug, Copy, Clone)] +pub struct SmallPollFlush { + /// The folded polls. + pub summary: PollSummary, + /// When the first folded poll began. + pub since: Instant, + /// When the last folded poll ended. + pub until: Instant, +} + +/// A newly drawn frame and the platform submission that completed its interval. +#[derive(Debug, Copy, Clone)] +pub struct PresentedFrame { + /// The draw whose rendered scene was submitted. + pub frame: FrameTiming, + /// Work spent submitting that scene to the platform. + pub presentation: PresentTiming, +} + +impl PresentedFrame { + /// Time from the frame's first invalidation through platform submission. + pub fn dirty_to_present_duration(&self) -> Option { + self.frame + .dirty_at + .map(|dirty_at| self.presentation.present_end.duration_since(dirty_at)) + } +} + +/// The semantic event that completed a foreground activity interval. +#[derive(Debug, Copy, Clone)] +pub enum IntervalBoundary { + /// A newly drawn frame was submitted to the platform. + Presented(PresentedFrame), + /// A callback completed without drawing, excluding reentrant callbacks. + FrameSkipped(FrameSkipped), + /// The foreground returned to an idle platform loop with no unexpired + /// frame pending. + Idle { + /// When the foreground went idle. + ended_at: Instant, + }, + /// A system suspend interrupted the measurement interval, observed either + /// through a power notification or through the suspend clock. + PowerTransition { + /// When the foreground noticed the suspend, through a notification or + /// the suspend clock. + ended_at: Instant, + }, +} + +impl IntervalBoundary { + /// When the interval ended. + pub fn end_time(&self) -> Instant { + match self { + Self::Presented(presented) => presented.presentation.present_end, + Self::FrameSkipped(skipped) => skipped.at, + Self::Idle { ended_at } | Self::PowerTransition { ended_at } => *ended_at, + } + } + + /// The first invalidation of the frame satisfied by this boundary, if any. + pub fn dirty_at(&self) -> Option { + match self { + Self::Presented(presented) => presented.frame.dirty_at, + Self::FrameSkipped(_) | Self::Idle { .. } | Self::PowerTransition { .. } => None, + } + } +} + +/// A control-plane change to one window's pending-frame state. +#[derive(Debug, Copy, Clone)] +pub enum FrameStateChange { + /// The window has a frame waiting to be presented. + Pending { + /// The window waiting for presentation. + window_id: WindowId, + /// When this frame generation first became dirty. + dirty_at: Instant, + }, + /// The window closed, so any pending frame no longer blocks idle + /// boundaries. + Closed { + /// The window that closed. + window_id: WindowId, + /// When the window closed. + at: Instant, + }, +} + +/// One item retained in the foreground journal. +#[derive(Debug, Copy, Clone)] +pub enum ForegroundJournalEntry { + /// A completed piece of foreground work. + Event(ForegroundEvent), + /// A semantic interval boundary. + Boundary(IntervalBoundary), + /// A change to pending-frame state. This is metadata, not foreground work. + FrameState(FrameStateChange), + /// A callback entering the foreground; not work or an interval boundary. + PlatformSignal(PlatformSignal), + /// A nested frame request deferred while an enclosing draw was still running. + ReentrantFrameSkipped { + /// The window whose nested frame request was deferred. + window_id: WindowId, + /// When the nested frame request was deferred. + at: Instant, + }, + /// One or more logical entries were unavailable at this point in the + /// stream. Consumers must not infer interval boundaries across this gap. + Discontinuity { + /// Number of unavailable logical entries. + lost: u64, + }, +} + +/// An immutable view of one sealed foreground interval, produced by +/// [`IntervalSealer`]. +#[derive(Debug, Clone)] +pub struct FrameSnapshot { + /// When the interval started (the previous seal, or the end of the idle + /// stretch preceding the interval's first event). + pub interval_start: Instant, + /// The semantic event that completed the interval, including its metadata. + pub boundary: IntervalBoundary, + /// Foreground work recorded during the interval, in completion order. + /// [`ForegroundEvent::SmallPolls`] entries are collected into + /// `small_polls` instead of appearing here. + pub events: Vec, + /// Span-tagged aggregates of task polls below [`TASK_POLL_FLOOR`]. Spans + /// are retained so occupancy can apportion folded poll time to reporting + /// windows narrower than the interval. + pub small_polls: Vec, + /// Events lost to the interval's event cap, plus ring losses reported + /// via [`IntervalSealer::note_lost`]. + pub dropped_events: u64, + /// Whether the journal had an unobserved gap during this interval. + pub journal_discontinuous: bool, +} + +impl FrameSnapshot { + /// When the interval ended. + pub fn interval_end(&self) -> Instant { + self.boundary.end_time() + } + + /// The combined count and total of all folded sub-floor polls in the + /// interval. + pub fn small_poll_summary(&self) -> PollSummary { + let mut summary = PollSummary::default(); + for flush in &self.small_polls { + summary.add(flush.summary); + } + summary + } + + /// Total foreground time occupied within the interval: the union of the + /// recorded events' spans (clamped to the interval, so nested work like an + /// action inside an input dispatch is not double counted) plus the folded + /// small polls. Folded polls cannot be unioned with nested individually + /// timed work, so this remains a close approximation. + pub fn occupancy(&self) -> Duration { + self.occupancy_within(self.interval_start, self.interval_end()) + } + + /// Like [`Self::occupancy`], but measured against an arbitrary window + /// (e.g. a reporting window anchored at a frame's first invalidation). + /// Event spans are clamped to the window. Folded polls carry no + /// individual timestamps, so each flush's total is apportioned by how + /// much of its span overlaps the window — assuming the folded time is + /// spread uniformly across the span. + pub fn occupancy_within(&self, window_start: Instant, window_end: Instant) -> Duration { + let mut spans: Vec<(Instant, Instant)> = self + .events + .iter() + .map(|event| { + let start = event.start_time().max(window_start); + let end = event.end_time().min(window_end).max(start); + (start, end) + }) + .collect(); + spans.sort_by_key(|(start, _)| *start); + + let mut occupied = Duration::ZERO; + let mut merged_until: Option = None; + for (start, end) in spans { + let start = match merged_until { + Some(merged_until) => start.max(merged_until), + None => start, + }; + occupied += end.duration_since(start); + merged_until = Some(match merged_until { + Some(merged_until) => merged_until.max(end), + None => end, + }); + } + + let apportioned_small_polls: Duration = self + .small_polls + .iter() + .map(|flush| { + let span = flush.until.duration_since(flush.since); + if span.is_zero() { + // A point-like flush lies either inside or outside the + // window. + if flush.since >= window_start && flush.since <= window_end { + flush.summary.total + } else { + Duration::ZERO + } + } else { + let overlap_start = flush.since.max(window_start); + let overlap_end = flush.until.min(window_end).max(overlap_start); + let overlap = overlap_end.duration_since(overlap_start); + flush.summary.total.mul_f64(overlap.div_duration_f64(span)) + } + }) + .sum(); + occupied + apportioned_small_polls + } + + /// The fraction of the interval the foreground spent working, in `0.0..=1.0`. + pub fn busy_fraction(&self) -> f64 { + let interval = self.interval_end().duration_since(self.interval_start); + if interval.is_zero() { + return 1.0; + } + (self.occupancy().div_duration_f64(interval)).min(1.0) + } +} + +#[derive(Clone)] +pub(crate) struct ForegroundRunnableCounter(Arc); + +impl ForegroundRunnableCounter { + fn new() -> Self { + Self(Arc::new(AtomicUsize::new(0))) + } + + pub(crate) fn queued(&self) { + self.0.fetch_add(1, Ordering::Release); + } + + fn finished(&self) { + let _ = self + .0 + .fetch_update(Ordering::AcqRel, Ordering::Acquire, |count| { + count.checked_sub(1) + }); + } + + fn has_runnables(&self) -> bool { + self.0.load(Ordering::Acquire) > 0 + } +} + +// Visibility and power changes clear `dirty_at`; `Window::refresh_visibility` +// re-records the frame from the window's actual dirty state afterwards. +struct WindowFrameState { + visibility: WindowVisibility, + dirty_at: Option, + visibility_changed_at: Option, +} + +impl WindowFrameState { + fn new(visibility: WindowVisibility) -> Self { + Self { + visibility, + dirty_at: None, + visibility_changed_at: None, + } + } +} + +struct ForegroundJournalWriter { + foreground_runnables: ForegroundRunnableCounter, + publisher: JournalPublisher, + turn_depth: usize, + windows: HashMap, + power: PowerState, + power_changed_at: Option, + read_suspended_time: fn() -> Option, + suspended_time: Option, + retained_since_boundary: bool, + small_polls: Option, +} + +impl ForegroundJournalWriter { + fn new(foreground_runnables: ForegroundRunnableCounter, publisher: JournalPublisher) -> Self { + Self { + foreground_runnables, + publisher, + turn_depth: 0, + windows: HashMap::new(), + power: PowerState::Awake, + power_changed_at: None, + read_suspended_time: system_suspended_time, + suspended_time: system_suspended_time(), + retained_since_boundary: false, + small_polls: None, + } + } + + fn begin_turn(&mut self) { + self.turn_depth += 1; + } + + // Idle boundaries require a retained event since the last boundary, not + // merely folded sub-floor polls. Sporadic wake-ups (timers, file + // watchers) leave the foreground idle after every tiny poll; a boundary + // for each would re-admit to the ring the very polls the fold keeps out + // of it, wrapping the ring within seconds. Folded-only work is discarded + // at true idle so unrelated wake-ups cannot accumulate toward a later + // frame budget. Polls remain folded while a frame or runnable is pending. + fn end_turn(&mut self, ended_at: Instant) { + let Some(turn_depth) = self.turn_depth.checked_sub(1) else { + debug_assert!(false, "foreground turn must be begun before it ends"); + return; + }; + self.turn_depth = turn_depth; + if self.turn_depth > 0 + || self.foreground_runnables.has_runnables() + || self.has_unexpired_pending_frame(ended_at) + { + return; + } + if !self.retained_since_boundary { + self.small_polls = None; + return; + } + + self.record_entry(ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { + ended_at, + })); + } + + fn has_unexpired_pending_frame(&mut self, now: Instant) -> bool { + for window in self.windows.values_mut() { + if window + .dirty_at + .is_some_and(|at| now.saturating_duration_since(at) >= FRAME_DEADLINE) + { + window.dirty_at = None; + } + } + self.power == PowerState::Awake + && self + .windows + .values() + .any(|window| window.dirty_at.is_some()) + } + + fn power_transition(&mut self, power: PowerState, at: Instant) { + if self.power == power { + return; + } + self.power = power; + // A suspend that was notified after it happened must not be reported + // again by the suspend clock. A notification that precedes its + // suspend (macOS posts will-sleep up to 30 s early) leaves the clock + // to fire once more after wake, which only seals an empty interval. + self.suspended_time = (self.read_suspended_time)(); + self.interrupt_measurements(at); + } + + /// Interrupts measurements, as a power notification would, if the system + /// suspended since the previous check. Measurements that end call this + /// before deciding whether to keep themselves, so a suspend during them + /// is detected even if its notification hasn't been handled yet. + // + // Power notifications arrive on the foreground thread, so work that was + // running when the system suspended finishes before its notification is + // handled (and on Windows the notification may never arrive). + fn detect_suspend(&mut self, at: Instant) { + let Some(suspended_time) = (self.read_suspended_time)() else { + return; + }; + let previous = self.suspended_time.replace(suspended_time); + if previous + .is_some_and(|previous| suspended_time.saturating_sub(previous) >= MIN_DETECTED_SUSPEND) + { + self.interrupt_measurements(at); + } + } + + /// Seals the open interval and invalidates all measurements in progress + /// at `at`, since they may span a suspend. + fn interrupt_measurements(&mut self, at: Instant) { + self.record_entry(ForegroundJournalEntry::Boundary( + IntervalBoundary::PowerTransition { ended_at: at }, + )); + self.power_changed_at = Some(at); + for window in self.windows.values_mut() { + window.dirty_at = None; + } + } + + /// Whether work that started at `start` spans a sleep or a wake, and so + /// must not be measured as uninterrupted foreground work. + fn power_interrupted_since(&self, start: Instant) -> bool { + self.power == PowerState::Suspended || self.power_changed_at.is_some_and(|at| start <= at) + } + + fn set_visibility(&mut self, id: WindowId, visibility: WindowVisibility, at: Instant) { + let window = self + .windows + .entry(id) + .or_insert_with(|| WindowFrameState::new(visibility)); + if window.visibility != visibility { + window.visibility = visibility; + window.visibility_changed_at = Some(at); + window.dirty_at = None; + } + } + + fn fold_small_poll(&mut self, timing: TaskTiming) { + let flush = self.small_polls.get_or_insert(SmallPollFlush { + summary: PollSummary::default(), + since: timing.start, + until: timing.end.0, + }); + flush.summary.count += 1; + flush.summary.total += timing.poll_duration(); + flush.since = flush.since.min(timing.start); + flush.until = flush.until.max(timing.end.0); + } + + fn take_small_polls(&mut self) -> Option { + self.small_polls.take() + } + + fn record_event(&mut self, event: ForegroundEvent) { + self.retained_since_boundary = true; + self.record_entry(ForegroundJournalEntry::Event(event)); + } + + fn record_entry(&mut self, entry: ForegroundJournalEntry) { + let small_polls = self + .take_small_polls() + .map(ForegroundEvent::SmallPolls) + .map(ForegroundJournalEntry::Event); + self.publisher + .publish([small_polls, Some(entry)].into_iter().flatten()); + if matches!(entry, ForegroundJournalEntry::Boundary(_)) { + self.retained_since_boundary = false; + } + } + + /// Publishes a point record that is neither work nor a boundary. Folded + /// polls stay folded: publishing them here would let them reach the + /// sealer even when [`Self::end_turn`] later discards folded-only work. + fn record_marker(&mut self, entry: ForegroundJournalEntry) { + self.publisher.publish([entry]); + } + + fn record_frame_state(&mut self, change: FrameStateChange) { + self.record_entry(ForegroundJournalEntry::FrameState(change)); + } + + fn record_platform_signal(&mut self, signal: PlatformSignal) { + self.record_marker(ForegroundJournalEntry::PlatformSignal(signal)); + } + + /// Seals retained work at a frame request that didn't draw. Like idle + /// boundaries, skips require a retained event since the last boundary: + /// platforms that request a frame every refresh would otherwise seal an + /// empty interval, and flush folded polls, on every idle refresh. + fn record_frame_skipped(&mut self, skipped: FrameSkipped) { + if !self.retained_since_boundary { + return; + } + // Even a no-render callback can schedule or invalidate the next frame. + // Skipping does not establish that the window's pending demand is met. + self.record_entry(ForegroundJournalEntry::Boundary( + IntervalBoundary::FrameSkipped(skipped), + )); + } + + fn record_frame_pending(&mut self, window_id: WindowId, dirty_at: Instant) { + let window = self + .windows + .entry(window_id) + .or_insert_with(|| WindowFrameState::new(WindowVisibility::Visible)); + if self.power == PowerState::Suspended + || !window.visibility.is_visible() + || window + .dirty_at + .is_some_and(|at| dirty_at.saturating_duration_since(at) < FRAME_DEADLINE) + { + return; + } + + window.dirty_at = Some(dirty_at); + self.record_frame_state(FrameStateChange::Pending { + window_id, + dirty_at, + }); + } + + fn record_window_closed(&mut self, window_id: WindowId, at: Instant) { + self.windows.remove(&window_id); + self.record_frame_state(FrameStateChange::Closed { window_id, at }); + } + + fn record_present(&mut self, timing: PresentTiming, frame: Option) { + if let Some(window) = self.windows.get_mut(&timing.window_id) { + window.dirty_at = None; + } + if self.power_interrupted_since(timing.present_start) { + return; + } + match frame { + Some(frame) => { + self.record_entry(ForegroundJournalEntry::Boundary( + IntervalBoundary::Presented(PresentedFrame { + frame, + presentation: timing, + }), + )); + } + None => { + self.record_event(ForegroundEvent::Present(timing)); + } + } + } +} + +thread_local! { + static FOREGROUND_RUNNABLES: ForegroundRunnableCounter = ForegroundRunnableCounter::new(); + static FOREGROUND_JOURNAL: RefCell> = const { RefCell::new(None) }; +} + +pub(crate) fn foreground_runnable_counter() -> ForegroundRunnableCounter { + FOREGROUND_RUNNABLES.with(Clone::clone) +} + +/// Starts journaling on the calling thread. Called once by `App` construction +/// on the main thread; every other thread's recording calls are no-ops. +/// Idempotent so that multiple `App`s on one thread (tests) share one journal. +pub(crate) fn install_foreground_journal() -> ForegroundJournal { + let foreground_runnables = foreground_runnable_counter(); + FOREGROUND_JOURNAL.with(|journal| { + let mut journal = journal.borrow_mut(); + if let Some(journal) = journal.as_ref() { + return ForegroundJournal { + ring: Arc::clone(&journal.publisher.ring), + }; + } + + let (handle, publisher) = + ForegroundJournal::new(MAX_JOURNAL_ENTRIES, MAX_PENDING_JOURNAL_ENTRIES); + *journal = Some(ForegroundJournalWriter::new( + foreground_runnables, + publisher, + )); + handle + }) +} + +/// Restores the previous foreground journal on drop, so a test's writer +/// (turn depth, pending frames, retained-since-boundary state) never leaks +/// into a later test that happens to reuse the same test-harness thread. +#[cfg(test)] +pub(crate) struct TestForegroundJournalGuard { + previous: Option, + _not_send: std::marker::PhantomData>, +} + +#[cfg(test)] +impl Drop for TestForegroundJournalGuard { + fn drop(&mut self) { + FOREGROUND_JOURNAL.with(|journal| { + *journal.borrow_mut() = self.previous.take(); + }); + } +} + +/// Installs a fresh journal for the duration of a test, isolated from +/// whatever a previous test left on this thread. Used by tests outside this +/// module (e.g. `bench_context`) that need to observe journal entries +/// without interference from the shared per-thread journal. +#[cfg(test)] +pub(crate) fn install_test_foreground_journal( + capacity: usize, + pending_capacity: usize, +) -> (ForegroundJournal, TestForegroundJournalGuard) { + let foreground_runnables = foreground_runnable_counter(); + let (handle, publisher) = ForegroundJournal::new(capacity, pending_capacity); + let previous = FOREGROUND_JOURNAL.with(|journal| { + journal.borrow_mut().replace( + ForegroundJournalWriter::new(foreground_runnables, publisher).with_test_suspend_clock(), + ) + }); + ( + handle, + TestForegroundJournalGuard { + previous, + _not_send: std::marker::PhantomData, + }, + ) +} + +#[cfg(test)] +thread_local! { + static TEST_SUSPENDED_TIME: std::cell::Cell = const { std::cell::Cell::new(Duration::ZERO) }; +} + +#[cfg(test)] +fn test_suspended_time() -> Option { + Some(TEST_SUSPENDED_TIME.get()) +} + +/// Simulates the system spending `duration` suspended, as observed through +/// the suspend clock of journals using [`ForegroundJournalWriter::with_test_suspend_clock`]. +#[cfg(test)] +pub(crate) fn advance_test_suspended_time(duration: Duration) { + TEST_SUSPENDED_TIME.set(TEST_SUSPENDED_TIME.get() + duration); +} + +#[cfg(test)] +impl ForegroundJournalWriter { + /// Replaces the system suspend clock, so a real suspend during a test + /// can't interrupt its measurements. + fn with_test_suspend_clock(mut self) -> Self { + TEST_SUSPENDED_TIME.set(Duration::ZERO); + self.read_suspended_time = test_suspended_time; + self.suspended_time = test_suspended_time(); + self + } +} + +fn with_journal(f: impl FnOnce(&mut ForegroundJournalWriter)) { + FOREGROUND_JOURNAL.with(|journal| { + if let Some(journal) = journal.borrow_mut().as_mut() { + f(journal); + } + }); +} + +pub(crate) fn observe_power(cx: &App) { + cx.on_system_sleep(|_| { + record_power_transition(PowerState::Suspended); + }) + .detach(); + // Visibility notifications delivered during sleep may have been missed. + cx.on_system_wake(|cx| { + record_power_transition(PowerState::Awake); + cx.spawn(async |cx| { + cx.update(|cx| { + for handle in cx.windows() { + handle + .update(cx, |_, window, cx| window.refresh_visibility(cx)) + .log_err(); + } + }); + }) + .detach(); + }) + .detach(); +} + +/// Total time the system has spent suspended since boot, or `None` where no +/// clock provides it: the difference between a clock that counts suspended +/// time and one that doesn't. The suspend-excluding clock is read first so +/// read latency can't make the difference negative. Every read is served from +/// memory the kernel maps into the process, without a syscall. +#[cfg(any(target_os = "linux", target_os = "android"))] +fn system_suspended_time() -> Option { + // CLOCK_BOOTTIME is CLOCK_MONOTONIC plus time spent suspended: + // https://man7.org/linux/man-pages/man2/clock_gettime.2.html + let awake = read_clock(libc::CLOCK_MONOTONIC)?; + let total = read_clock(libc::CLOCK_BOOTTIME)?; + Some(total.saturating_sub(awake)) +} + +#[cfg(target_os = "macos")] +fn system_suspended_time() -> Option { + use std::sync::OnceLock; + + // Declared here because libc deprecates its mach bindings, and these + // three functions don't justify a `mach2` dependency. `` + // documents `mach_continuous_time` as "like mach_absolute_time, but + // advances during sleep", so both count the same ticks: + // https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/mach/mach_time.h + #[repr(C)] + struct MachTimebaseInfo { + numer: u32, + denom: u32, + } + unsafe extern "C" { + fn mach_absolute_time() -> u64; + fn mach_continuous_time() -> u64; + fn mach_timebase_info(info: *mut MachTimebaseInfo) -> i32; + } + + static TIMEBASE: OnceLock> = OnceLock::new(); + let (numer, denom) = (*TIMEBASE.get_or_init(|| { + let mut info = MachTimebaseInfo { numer: 0, denom: 0 }; + // SAFETY: `info` is a valid, writable mach_timebase_info. + let succeeded = unsafe { mach_timebase_info(&mut info) } == 0; + (succeeded && info.denom != 0).then_some((info.numer, info.denom)) + }))?; + // SAFETY: neither function has preconditions. + let awake = unsafe { mach_absolute_time() }; + // SAFETY: as above. + let total = unsafe { mach_continuous_time() }; + let nanos = u128::from(total.saturating_sub(awake)) * u128::from(numer) / u128::from(denom); + Some(Duration::from_nanos(u64::try_from(nanos).ok()?)) +} + +#[cfg(any(target_os = "linux", target_os = "android"))] +fn read_clock(clock: libc::clockid_t) -> Option { + let mut time = libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }; + // SAFETY: `time` is a valid, writable timespec. + if unsafe { libc::clock_gettime(clock, &mut time) } != 0 { + return None; + } + Some(Duration::new( + u64::try_from(time.tv_sec).ok()?, + u32::try_from(time.tv_nsec).ok()?, + )) +} + +#[cfg(target_os = "windows")] +fn system_suspended_time() -> Option { + use windows::Win32::System::WindowsProgramming::{ + QueryInterruptTime, QueryUnbiasedInterruptTime, + }; + let mut awake = 0; + // SAFETY: `awake` is a valid, writable u64. + if !unsafe { QueryUnbiasedInterruptTime(&mut awake) }.as_bool() { + return None; + } + // SAFETY: no preconditions. + let total = unsafe { QueryInterruptTime() }; + // Both count 100 ns units; unbiased interrupt time excludes sleep and + // hibernation: + // https://learn.microsoft.com/en-us/windows/win32/sysinfo/interrupt-time + Some(Duration::from_nanos( + total.saturating_sub(awake).saturating_mul(100), + )) +} + +#[cfg(not(any( + target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "windows" +)))] +fn system_suspended_time() -> Option { + None +} + +pub(crate) fn record_power_transition(state: PowerState) { + with_journal(|journal| journal.power_transition(state, Instant::now())); +} + +/// Whether work that started at `start` spans a sleep or a wake. Such work +/// is dropped rather than measured. +pub(crate) fn power_interrupted_since(start: Instant) -> bool { + let mut interrupted = false; + with_journal(|journal| { + journal.detect_suspend(Instant::now()); + interrupted = journal.power_interrupted_since(start); + }); + interrupted +} + +pub(crate) fn record_window_visibility(id: WindowId, visibility: WindowVisibility) { + with_journal(|journal| journal.set_visibility(id, visibility, Instant::now())); +} + +/// Whether a frame sample that started at `start` was measured while the +/// window stayed visible and the system stayed awake. +pub(crate) fn frame_sample_is_valid(id: WindowId, start: Instant) -> bool { + let mut valid = true; + with_journal(|journal| { + journal.detect_suspend(Instant::now()); + valid = !journal.power_interrupted_since(start) + && journal.windows.get(&id).is_none_or(|window| { + window.visibility.is_visible() + && window.visibility_changed_at.is_none_or(|at| start > at) + }); + }); + valid +} + +// TODO(gpui-profiler): the turn brackets in the dispatchers and +// WindowProfiler are bare begin/end call pairs rather than uses of this +// guard. A caught unwind between a pair leaves `turn_depth` (and potentially +// the runnable counter) permanently unbalanced, which silently disables +// idle boundaries for the rest of the process. Zed aborts on panics so +// this is latent today, but gpui-as-a-library callers may catch unwinds; +// route all bracketing through this guard. +pub(crate) struct ForegroundTurnGuard; + +impl Drop for ForegroundTurnGuard { + fn drop(&mut self) { + end_foreground_turn(); + } +} + +pub(crate) fn foreground_turn() -> ForegroundTurnGuard { + begin_foreground_turn(); + ForegroundTurnGuard +} + +pub(crate) fn begin_foreground_turn() { + // Observing before the turn's work takes its start time means a suspend + // detected here never invalidates the work that follows it. + with_journal(|journal| { + journal.detect_suspend(Instant::now()); + journal.begin_turn(); + }); +} + +pub(crate) fn end_foreground_turn() { + with_journal(|journal| journal.end_turn(Instant::now())); +} + +pub(crate) fn record_task_poll(timing: TaskTiming) { + FOREGROUND_RUNNABLES.with(ForegroundRunnableCounter::finished); + with_journal(|journal| { + journal.detect_suspend(timing.end.0); + if journal.power_interrupted_since(timing.start) { + journal.end_turn(timing.end.0); + return; + } + if timing.poll_duration() >= TASK_POLL_FLOOR { + journal.record_event(ForegroundEvent::TaskPoll(timing)); + } else { + journal.fold_small_poll(timing); + } + journal.end_turn(timing.end.0); + }); +} + +pub(crate) fn record_action(timing: ActionTiming) { + with_journal(|journal| journal.record_event(ForegroundEvent::Action(timing))); +} + +pub(crate) fn record_input(timing: InputTiming) { + with_journal(|journal| journal.record_event(ForegroundEvent::Input(timing))); +} + +pub(crate) fn record_draw(timing: FrameTiming) { + with_journal(|journal| journal.record_event(ForegroundEvent::Draw(timing))); +} + +pub(crate) fn record_present(timing: PresentTiming, frame: Option) { + with_journal(|journal| journal.record_present(timing, frame)); +} + +pub(crate) fn record_platform_signal(signal: PlatformSignal) { + with_journal(|journal| journal.record_platform_signal(signal)); +} + +pub(crate) fn record_reentrant_frame_skipped(window_id: WindowId, at: Instant) { + with_journal(|journal| { + journal.record_marker(ForegroundJournalEntry::ReentrantFrameSkipped { window_id, at }); + }); +} + +pub(crate) fn record_frame_skipped(window_id: WindowId, at: Instant, reason: FrameSkipReason) { + with_journal(|journal| { + journal.record_frame_skipped(FrameSkipped { + window_id, + at, + reason, + }) + }); +} + +pub(crate) fn record_frame_pending(window_id: WindowId, dirty_at: Instant) { + with_journal(|journal| journal.record_frame_pending(window_id, dirty_at)); +} + +pub(crate) fn record_window_closed(window_id: WindowId) { + let at = Instant::now(); + with_journal(|journal| journal.record_window_closed(window_id, at)); +} + +const SLOT_WRITER: usize = 1 << (usize::BITS - 1); +const SLOT_READER_MASK: usize = !SLOT_WRITER; +const EMPTY_SEQUENCE: u64 = u64::MAX; + +struct JournalSlot { + users: AtomicUsize, + sequence: AtomicU64, + entry: UnsafeCell>, +} + +// `users` ensures the entry is only read while no writer owns the slot and is +// only written while no readers own it. +unsafe impl Sync for JournalSlot {} + +impl JournalSlot { + fn new() -> Self { + Self { + users: AtomicUsize::new(0), + sequence: AtomicU64::new(EMPTY_SEQUENCE), + entry: UnsafeCell::new(MaybeUninit::uninit()), + } + } + + fn try_publish(&self, sequence: u64, entry: ForegroundJournalEntry) -> bool { + if self + .users + .compare_exchange(0, SLOT_WRITER, Ordering::Acquire, Ordering::Relaxed) + .is_err() + { + return false; + } + + // SAFETY: setting SLOT_WRITER from zero gives this writer exclusive + // access to the slot until the Release store below. + unsafe { + (*self.entry.get()).write(entry); + } + self.sequence.store(sequence, Ordering::Relaxed); + self.users.store(0, Ordering::Release); + true + } + + fn try_read(&self, expected_sequence: u64) -> Option { + let _guard = JournalSlotReadGuard::try_new(self)?; + if self.sequence.load(Ordering::Relaxed) != expected_sequence { + return None; + } + + // SAFETY: a matching sequence means the slot was initialized for this + // logical entry, and `guard` prevents the writer from overwriting it + // until after the Copy. + Some(unsafe { *(*self.entry.get()).assume_init_ref() }) + } + + fn try_add_reader(&self) -> bool { + let mut users = self.users.load(Ordering::Relaxed); + loop { + if users & SLOT_WRITER != 0 || users == SLOT_READER_MASK { + return false; + } + match self.users.compare_exchange_weak( + users, + users + 1, + Ordering::Acquire, + Ordering::Relaxed, + ) { + Ok(_) => return true, + Err(updated_users) => users = updated_users, + } + } + } + + fn remove_reader(&self) { + let previous = self.users.fetch_sub(1, Ordering::Release); + debug_assert!( + previous > 0 && previous & SLOT_WRITER == 0, + "invalid slot reader state: {previous:#x}" + ); + } +} + +struct JournalSlotReadGuard<'a> { + slot: &'a JournalSlot, +} + +impl<'a> JournalSlotReadGuard<'a> { + fn try_new(slot: &'a JournalSlot) -> Option { + if slot.try_add_reader() { + Some(Self { slot }) + } else { + None + } + } +} + +impl Drop for JournalSlotReadGuard<'_> { + fn drop(&mut self) { + self.slot.remove_reader(); + } +} + +struct JournalRing { + slots: Box<[JournalSlot]>, + finalized: AtomicU64, + offered: AtomicU64, +} + +impl JournalRing { + fn new(capacity: usize) -> Self { + let capacity = capacity.max(1); + Self { + slots: (0..capacity).map(|_| JournalSlot::new()).collect(), + finalized: AtomicU64::new(0), + offered: AtomicU64::new(0), + } + } + + fn capacity(&self) -> usize { + self.slots.len() + } + + fn try_publish(&self, sequence: u64, entry: ForegroundJournalEntry) -> bool { + let index = (sequence % self.slots.len() as u64) as usize; + self.slots[index].try_publish(sequence, entry) + } + + fn read(&self, sequence: u64) -> Option { + let index = (sequence % self.slots.len() as u64) as usize; + self.slots[index].try_read(sequence) + } +} + +struct PendingJournalEntry { + sequence: u64, + entry: ForegroundJournalEntry, +} + +struct JournalPublisher { + ring: Arc, + next_sequence: u64, + pending: VecDeque, + dropped_after_pending: u64, + pending_capacity: usize, +} + +impl JournalPublisher { + fn new(ring: Arc, pending_capacity: usize) -> Self { + Self { + ring, + next_sequence: 0, + pending: VecDeque::with_capacity(pending_capacity), + dropped_after_pending: 0, + pending_capacity, + } + } + + fn publish(&mut self, entries: impl IntoIterator) { + for entry in entries { + self.flush_pending(); + self.publish_one(entry); + } + self.flush_pending(); + } + + fn publish_one(&mut self, entry: ForegroundJournalEntry) { + let sequence = self.next_sequence; + self.next_sequence += 1; + self.ring + .offered + .store(self.next_sequence, Ordering::Release); + + if !self.pending.is_empty() || self.dropped_after_pending > 0 { + if self.dropped_after_pending == 0 && self.pending.len() < self.pending_capacity { + self.pending + .push_back(PendingJournalEntry { sequence, entry }); + } else { + self.dropped_after_pending += 1; + } + return; + } + + if self.ring.try_publish(sequence, entry) { + self.ring.finalized.store(sequence + 1, Ordering::Release); + } else if self.pending_capacity > 0 { + self.pending + .push_back(PendingJournalEntry { sequence, entry }); + } else { + self.dropped_after_pending = 1; + } + } + + fn flush_pending(&mut self) { + while let Some(pending) = self.pending.front() { + if !self.ring.try_publish(pending.sequence, pending.entry) { + return; + } + let sequence = pending.sequence; + self.pending.pop_front(); + self.ring.finalized.store(sequence + 1, Ordering::Release); + } + + if self.dropped_after_pending > 0 { + self.ring + .finalized + .store(self.next_sequence, Ordering::Release); + self.dropped_after_pending = 0; + } + } +} + +/// A cloneable handle to one foreground journal stream. +/// +/// Each collector has an independent cursor. Collectors briefly pin one slot +/// at a time and never block recording; entries they could not observe are +/// reported as discontinuities. Apps on the same foreground thread share the +/// stream. +#[derive(Clone)] +pub struct ForegroundJournal { + ring: Arc, +} + +impl ForegroundJournal { + fn new(capacity: usize, pending_capacity: usize) -> (Self, JournalPublisher) { + let ring = Arc::new(JournalRing::new(capacity)); + ( + Self { + ring: Arc::clone(&ring), + }, + JournalPublisher::new(ring, pending_capacity), + ) + } + + /// Creates an independent collector that observes entries offered after + /// this call. + pub fn collector(&self) -> ForegroundJournalCollector { + ForegroundJournalCollector { + cursor: self.ring.offered.load(Ordering::Acquire), + ring: Arc::clone(&self.ring), + } + } +} + +/// Entries returned by one [`ForegroundJournalCollector::collect_unseen`] call. +#[derive(Debug, Default)] +pub struct DrainedEntries { + /// Journal entries recorded since the previous drain, in recording order, + /// including synthetic [`ForegroundJournalEntry::Discontinuity`] markers at + /// unavailable logical positions. + pub entries: Vec, + /// Entries unavailable to this collector because they were overwritten or + /// could not be published after the fixed pending queue filled. This is the + /// aggregate of the discontinuity markers in `entries`. + pub lost: u64, +} + +/// Reads the foreground stream, tracking a cursor so each call to +/// [`Self::collect_unseen`] returns only entries recorded since the previous +/// call. Independent collectors do not affect each other. +pub struct ForegroundJournalCollector { + cursor: u64, + ring: Arc, +} + +impl ForegroundJournalCollector { + /// Returns entries recorded since the previous call (or since the + /// collector was created), reporting how many were unavailable before this + /// drain observed them. + pub fn collect_unseen(&mut self) -> DrainedEntries { + let end = self.ring.finalized.load(Ordering::Acquire); + if self.cursor >= end { + return DrainedEntries::default(); + } + let retained_start = end.saturating_sub(self.ring.capacity() as u64); + let mut lost = retained_start.saturating_sub(self.cursor); + self.cursor = self.cursor.max(retained_start); + let mut entries = Vec::with_capacity((end - self.cursor) as usize + usize::from(lost > 0)); + if lost > 0 { + entries.push(ForegroundJournalEntry::Discontinuity { lost }); + } + + while self.cursor < end { + if let Some(entry) = self.ring.read(self.cursor) { + entries.push(entry); + } else { + lost += 1; + match entries.last_mut() { + Some(ForegroundJournalEntry::Discontinuity { lost }) => *lost += 1, + _ => entries.push(ForegroundJournalEntry::Discontinuity { lost: 1 }), + } + } + self.cursor += 1; + } + + DrainedEntries { entries, lost } + } +} + +/// A pure state machine that groups foreground journal entries into +/// [`FrameSnapshot`]s. +/// +/// Feed it drained entries in recording order. Work is carried across calls +/// until an explicit [`IntervalBoundary`] arrives. Idle time before an +/// interval's first event is excluded without relying on an elapsed-time +/// heuristic. +#[derive(Debug)] +pub struct IntervalSealer { + interval_start: Instant, + events: Vec, + small_polls: Vec, + dropped_events: u64, + journal_discontinuous: bool, +} + +impl IntervalSealer { + /// Creates a sealer whose first interval starts at `start` (typically + /// the moment the consumer's collector was created). + pub fn new(start: Instant) -> Self { + Self { + interval_start: start, + events: Vec::new(), + small_polls: Vec::new(), + dropped_events: 0, + journal_discontinuous: false, + } + } + + /// Accounts for a loss supplied outside a collector drain. Collector losses + /// are already represented by ordered discontinuity entries. + pub fn note_lost(&mut self, lost: u64) { + self.dropped_events += lost; + self.journal_discontinuous |= lost > 0; + } + + /// Processes a batch of drained entries, returning the snapshots completed + /// by explicit boundaries. Work without a following boundary is carried + /// over to subsequent calls. + pub fn push_entries( + &mut self, + entries: impl IntoIterator, + ) -> Vec { + let mut snapshots = Vec::new(); + for entry in entries { + match entry { + ForegroundJournalEntry::Event(event) => { + if self.is_empty() { + self.interval_start = self.interval_start.max(event.start_time()); + } + match event { + ForegroundEvent::SmallPolls(flush) => self.push_small_polls(flush), + event => self.push_event(event), + } + } + ForegroundJournalEntry::Boundary(boundary) => { + if let IntervalBoundary::Presented(presented) = boundary { + if self.is_empty() { + self.interval_start = self + .interval_start + .max(presented.presentation.present_start); + } + self.push_event(ForegroundEvent::Present(presented.presentation)); + } + if self.is_empty() { + self.interval_start = self.interval_start.max(boundary.end_time()); + } else { + snapshots.push(self.seal(boundary)); + } + } + // Pending-frame state gates boundaries on the writer side; + // the entries remain in the stream for consumers that want + // dirty timing, but the sealer has no use for them. + ForegroundJournalEntry::FrameState(_) + | ForegroundJournalEntry::PlatformSignal(_) + | ForegroundJournalEntry::ReentrantFrameSkipped { .. } => {} + ForegroundJournalEntry::Discontinuity { lost } => self.note_lost(lost), + } + } + snapshots + } + + fn is_empty(&self) -> bool { + self.events.is_empty() + && self.small_polls.is_empty() + && self.dropped_events == 0 + && !self.journal_discontinuous + } + + fn push_event(&mut self, event: ForegroundEvent) { + if self.events.len() >= MAX_INTERVAL_EVENTS { + self.dropped_events += 1; + } else { + self.events.push(event); + } + } + + fn push_small_polls(&mut self, flush: SmallPollFlush) { + if self.small_polls.len() >= MAX_INTERVAL_EVENTS + && let Some(last) = self.small_polls.last_mut() + { + // Degrade gracefully at the cap: widen the last flush's span + // instead of dropping poll time, at the cost of coarser + // apportioning. + last.summary.add(flush.summary); + last.since = last.since.min(flush.since); + last.until = last.until.max(flush.until); + } else { + self.small_polls.push(flush); + } + } + + fn seal(&mut self, boundary: IntervalBoundary) -> FrameSnapshot { + let ended = boundary.end_time(); + let snapshot = FrameSnapshot { + interval_start: self.interval_start, + boundary, + events: std::mem::take(&mut self.events), + small_polls: std::mem::take(&mut self.small_polls), + dropped_events: std::mem::take(&mut self.dropped_events), + journal_discontinuous: std::mem::take(&mut self.journal_discontinuous), + }; + self.interval_start = ended; + snapshot + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + use scheduler::SpawnTime; + + use super::*; + use crate::{WindowId, profiler::YieldTime}; + + #[test] + fn platform_signals_are_journaled_without_sealing_or_occupying_time() { + let (journal, _guard) = install_test_foreground_journal(32, 4); + let mut collector = journal.collector(); + let start = Instant::now(); + let mut sealer = IntervalSealer::new(start); + let window_id = WindowId::from(1); + for source in [ + crate::FrameRequestSource::NativeCallback, + crate::FrameRequestSource::LocalSchedule, + ] { + for signal_at in [None, Some(start + Duration::from_secs(5))] { + record_platform_signal(PlatformSignal { + window_id, + signal_at, + handled_at: start + Duration::from_millis(5), + source, + }); + let entries = collector.collect_unseen().entries; + let [ForegroundJournalEntry::PlatformSignal(signal)] = entries.as_slice() else { + panic!("expected a raw platform signal, got {entries:?}"); + }; + assert_eq!(signal.window_id, window_id); + assert_eq!(signal.signal_at, signal_at); + assert_eq!(signal.handled_at, start + Duration::from_millis(5)); + assert_eq!(signal.source, source); + assert!(sealer.push_entries(entries).is_empty()); + } + } + let ended_at = start + Duration::from_millis(10); + // An enclosing work span may complete after the callback metadata. + let snapshots = sealer.push_entries([ + input_entry(start, ended_at), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at }), + ]); + let [snapshot] = snapshots.as_slice() else { + panic!("expected one snapshot, got {snapshots:?}"); + }; + assert_eq!(snapshot.interval_start, start); + assert_eq!(snapshot.interval_end(), ended_at); + assert_eq!(snapshot.occupancy(), Duration::from_millis(10)); + assert_eq!(snapshot.events.len(), 1); + } + + #[test] + fn completed_skips_seal_without_retiring_pending_demand() { + let start = Instant::now(); + let at = start + Duration::from_millis(10); + let window_id = WindowId::from(1); + for reason in [ + FrameSkipReason::NoRenderNeeded, + FrameSkipReason::InactiveFrameRateLimit, + FrameSkipReason::ThermalFrameRateLimit, + ] { + let (mut writer, mut collector) = test_journal(ForegroundRunnableCounter::new()); + writer.begin_turn(); + writer.record_frame_pending(window_id, start); + writer.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end: start + Duration::from_millis(2), + caused_invalidation: false, + })); + writer.record_frame_skipped(FrameSkipped { + window_id, + at, + reason, + }); + + let mut sealer = IntervalSealer::new(start); + let snapshots = sealer.push_entries(collector.collect_unseen().entries); + let [snapshot] = snapshots.as_slice() else { + panic!("expected a completed skip, got {snapshots:?}"); + }; + assert!( + matches!(snapshot.boundary, IntervalBoundary::FrameSkipped(skipped) + if skipped.window_id == window_id && skipped.at == at && skipped.reason == reason) + ); + assert_eq!(snapshot.interval_end(), at); + assert_eq!(snapshot.boundary.dirty_at(), None); + assert_eq!(snapshot.occupancy(), Duration::from_millis(2)); + + writer.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start: at, + end: at + Duration::from_millis(1), + caused_invalidation: false, + })); + writer.end_turn(at + Duration::from_millis(1)); + assert!( + !collector + .collect_unseen() + .entries + .iter() + .any(|entry| matches!(entry, ForegroundJournalEntry::Boundary(_))), + "pending demand must still block idle boundaries" + ); + } + } + + /// Platforms that request a frame every refresh skip most of them while + /// idle. Those skips seal nothing and leave folded polls folded, so + /// end-of-turn idle handling can still discard folded-only work. + #[test] + fn idle_refreshes_seal_nothing_and_keep_polls_folded() { + let start = Instant::now(); + let window_id = WindowId::from(1); + let (mut writer, mut collector) = test_journal(ForegroundRunnableCounter::new()); + for refresh in 0..3u32 { + let at = start + Duration::from_millis(16) * refresh; + writer.begin_turn(); + writer.fold_small_poll(task_timing(at, at + Duration::from_micros(50))); + writer.record_platform_signal(PlatformSignal { + window_id, + signal_at: Some(at), + handled_at: at, + source: crate::FrameRequestSource::NativeCallback, + }); + writer.record_frame_skipped(FrameSkipped { + window_id, + at, + reason: FrameSkipReason::NoRenderNeeded, + }); + writer.end_turn(at + Duration::from_micros(60)); + } + + let entries = collector.collect_unseen().entries; + assert!( + entries + .iter() + .all(|entry| matches!(entry, ForegroundJournalEntry::PlatformSignal(_))), + "expected only platform signals, got {entries:?}" + ); + assert!(IntervalSealer::new(start).push_entries(entries).is_empty()); + } + + #[test] + fn reentrant_skip_does_not_seal_the_enclosing_draw() { + let (journal, _guard) = install_test_foreground_journal(32, 4); + let mut collector = journal.collector(); + let start = Instant::now(); + let window_id = WindowId::from(1); + let mut sealer = IntervalSealer::new(start); + record_platform_signal(PlatformSignal { + window_id, + signal_at: None, + handled_at: start + Duration::from_millis(5), + source: crate::FrameRequestSource::LocalSchedule, + }); + record_reentrant_frame_skipped(window_id, start + Duration::from_millis(6)); + let entries = collector.collect_unseen().entries; + assert!(matches!( + entries.as_slice(), + [ + ForegroundJournalEntry::PlatformSignal(_), + ForegroundJournalEntry::ReentrantFrameSkipped { + window_id: skipped_window_id, + at, + } + ] + if *skipped_window_id == window_id && *at == start + Duration::from_millis(6) + )); + assert!(sealer.push_entries(entries).is_empty()); + + let frame = FrameTiming { + window_id, + dirty_at: Some(start), + invalidations: 1, + draw_start: start, + draw_end: start + Duration::from_millis(20), + }; + record_draw(frame); + record_present(presentation_timing(window_id, frame.draw_end), Some(frame)); + let snapshots = sealer.push_entries(collector.collect_unseen().entries); + let [snapshot] = snapshots.as_slice() else { + panic!("expected the enclosing presentation, got {snapshots:?}"); + }; + assert!(matches!(snapshot.boundary, IntervalBoundary::Presented(_))); + assert_eq!(snapshot.occupancy(), Duration::from_millis(20)); + } + + #[gpui::test] + fn wake_rechecks_native_visibility(cx: &mut crate::TestAppContext) { + use crate::PlatformWindow as _; + let handle = cx.add_window(|_, _| crate::Empty); + let platform = cx.test_window(handle.into()); + platform.on_visibility_change(Box::new(|_| {})); + platform.simulate_visibility_change(WindowVisibility::Hidden); + handle + .update(cx, |_, window, _| assert!(window.is_visible())) + .expect("window"); + cx.update(|cx| { + cx.system_wake_observers + .clone() + .retain(&(), |callback| callback(cx)) + }); + cx.run_until_parked(); + handle + .update(cx, |_, window, _| assert!(!window.is_visible())) + .expect("window"); + } + + #[test] + fn power_interruption_drops_the_poll_before_small_poll_folding() { + let (journal, _guard) = install_test_foreground_journal(32, 4); + let mut collector = journal.collector(); + let start = Instant::now(); + begin_foreground_turn(); + record_power_transition(PowerState::Suspended); + record_power_transition(PowerState::Awake); + assert!(power_interrupted_since(start)); + record_task_poll(task_timing(start, start + Duration::from_micros(10))); + assert!( + collector + .collect_unseen() + .entries + .iter() + .all(|entry| matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::PowerTransition { .. }) + )) + ); + with_journal(|writer| assert!(writer.small_polls.is_none())); + begin_foreground_turn(); + let start = Instant::now(); + assert!(!power_interrupted_since(start)); + record_task_poll(task_timing(start, start + TASK_POLL_FLOOR)); + assert!( + collector + .collect_unseen() + .entries + .iter() + .any(|entry| matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::TaskPoll(_)) + )) + ); + } + + #[test] + fn a_poll_spanning_an_unnotified_suspend_is_dropped() { + let (journal, _guard) = install_test_foreground_journal(32, 4); + let mut collector = journal.collector(); + let window = WindowId::from(1); + record_frame_pending(window, Instant::now()); + begin_foreground_turn(); + let start = Instant::now(); + advance_test_suspended_time(Duration::from_secs(2)); + record_task_poll(task_timing(start, Instant::now())); + let entries = collector.collect_unseen().entries; + assert!(entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::PowerTransition { .. }) + ))); + assert!(!entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::TaskPoll(_)) + ))); + with_journal(|writer| assert_eq!(writer.windows[&window].dirty_at, None)); + + begin_foreground_turn(); + let start = Instant::now(); + record_task_poll(task_timing(start, start + TASK_POLL_FLOOR)); + let entries = collector.collect_unseen().entries; + assert!(entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::TaskPoll(_)) + ))); + assert!(!entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::PowerTransition { .. }) + ))); + } + + #[test] + fn suspend_clock_ignores_jitter_and_notified_suspends() { + let (journal, _guard) = install_test_foreground_journal(32, 4); + let mut collector = journal.collector(); + record_power_transition(PowerState::Suspended); + advance_test_suspended_time(Duration::from_secs(60)); + record_power_transition(PowerState::Awake); + advance_test_suspended_time(MIN_DETECTED_SUSPEND - Duration::from_millis(1)); + begin_foreground_turn(); + let start = Instant::now(); + record_task_poll(task_timing(start, start + TASK_POLL_FLOOR)); + let entries = collector.collect_unseen().entries; + let power_transitions = entries + .iter() + .filter(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::PowerTransition { .. }) + ) + }) + .count(); + assert_eq!(power_transitions, 2, "only the two notifications"); + assert!(entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::TaskPoll(_)) + ))); + } + + #[test] + fn visibility_and_power_changes_clear_pending_frames() { + let (mut writer, _) = test_journal(ForegroundRunnableCounter::new()); + let start = Instant::now(); + let first = WindowId::from(1); + let second = WindowId::from(2); + writer.set_visibility(first, WindowVisibility::Hidden, start); + writer.record_frame_pending(first, start); + assert!(!writer.has_unexpired_pending_frame(start)); + writer.record_frame_pending(second, start); + assert!(writer.has_unexpired_pending_frame(start)); + writer.set_visibility(second, WindowVisibility::Hidden, start); + assert!(!writer.has_unexpired_pending_frame(start)); + writer.set_visibility(first, WindowVisibility::Visible, start); + writer.record_frame_pending(first, start); + assert!(writer.has_unexpired_pending_frame(start)); + writer.power_transition(PowerState::Suspended, start); + assert_eq!(writer.windows[&first].dirty_at, None); + writer.record_frame_pending(first, start); + assert!(!writer.has_unexpired_pending_frame(start)); + // A repeated notification is not a transition. + writer.power_transition(PowerState::Suspended, start + FRAME_DEADLINE); + assert_eq!(writer.power_changed_at, Some(start)); + writer.power_transition(PowerState::Awake, start); + writer.record_frame_pending(first, start); + assert!(writer.has_unexpired_pending_frame(start)); + writer.record_present(presentation_timing(first, start + FRAME_DEADLINE), None); + assert_eq!(writer.windows[&first].dirty_at, None); + writer.record_window_closed(first, start); + assert!(!writer.windows.contains_key(&first)); + } + + #[test] + fn draw_waits_for_its_presentation_boundary() { + let start = Instant::now(); + let input = InputTiming { + kind: "test", + start: start + Duration::from_millis(1), + end: start + Duration::from_millis(2), + caused_invalidation: true, + }; + let frame = FrameTiming { + window_id: WindowId::from(1), + dirty_at: Some(input.start), + invalidations: 1, + draw_start: start + Duration::from_millis(3), + draw_end: start + Duration::from_millis(4), + }; + let presentation = PresentTiming { + window_id: frame.window_id, + present_start: start + Duration::from_millis(5), + present_end: start + Duration::from_millis(6), + animation_interval: None, + }; + let mut sealer = IntervalSealer::new(start); + + let snapshots = sealer.push_entries([ + ForegroundJournalEntry::Event(ForegroundEvent::Input(input)), + ForegroundJournalEntry::Event(ForegroundEvent::Draw(frame)), + ]); + assert!(snapshots.is_empty()); + + let snapshots = sealer.push_entries([ForegroundJournalEntry::Boundary( + IntervalBoundary::Presented(PresentedFrame { + frame, + presentation, + }), + )]); + let [snapshot] = snapshots.as_slice() else { + panic!("expected one presentation-sealed snapshot, got {snapshots:?}"); + }; + assert_eq!(snapshot.interval_start, input.start); + assert_eq!(snapshot.interval_end(), presentation.present_end); + assert_eq!(snapshot.events.len(), 3); + assert!(matches!( + snapshot.events.last(), + Some(ForegroundEvent::Present(timing)) + if timing.present_duration() == Duration::from_millis(1) + )); + assert_eq!( + match snapshot.boundary { + IntervalBoundary::Presented(presented) => { + presented.dirty_to_present_duration() + } + IntervalBoundary::FrameSkipped(_) + | IntervalBoundary::Idle { .. } + | IntervalBoundary::PowerTransition { .. } => None, + }, + Some(Duration::from_millis(5)) + ); + } + + #[test] + fn outermost_turn_seals_no_frame_work_when_idle() { + let start = Instant::now(); + let counter = ForegroundRunnableCounter::new(); + let (mut journal, mut collector) = test_journal(counter); + let events = [ + ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end: start + Duration::from_millis(1), + caused_invalidation: false, + }), + ForegroundEvent::Action(ActionTiming { + name: "test.action", + start: start + Duration::from_millis(2), + end: start + Duration::from_millis(3), + }), + ForegroundEvent::TaskPoll(task_timing( + start + Duration::from_millis(4), + start + Duration::from_millis(5), + )), + ]; + + for event in events { + journal.begin_turn(); + journal.record_event(event); + journal.end_turn(event.end_time()); + } + + let entries = collector.collect_unseen().entries; + for event in events { + assert!(entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at }) + if *ended_at == event.end_time() + ) + })); + } + } + + #[test] + fn nested_turns_only_seal_after_the_outermost_turn() { + let start = Instant::now(); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + let action = ForegroundEvent::Action(ActionTiming { + name: "test.action", + start, + end: start + Duration::from_millis(1), + }); + let input = ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end: start + Duration::from_millis(2), + caused_invalidation: false, + }); + + journal.begin_turn(); + journal.begin_turn(); + journal.record_event(action); + journal.end_turn(action.end_time()); + assert!(!has_boundary_at( + &collector.collect_unseen().entries, + action.end_time() + )); + + journal.record_event(input); + journal.end_turn(input.end_time()); + assert!(collector.collect_unseen().entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at }) + if *ended_at == input.end_time() + ) + })); + } + + #[test] + fn an_immediately_ready_runnable_prevents_an_idle_boundary_between_polls() { + let start = Instant::now(); + let counter = ForegroundRunnableCounter::new(); + let (mut journal, mut collector) = test_journal(counter.clone()); + counter.queued(); + counter.queued(); + + let first = ForegroundEvent::TaskPoll(task_timing(start, start + Duration::from_millis(1))); + journal.begin_turn(); + journal.record_event(first); + counter.finished(); + journal.end_turn(first.end_time()); + assert!(!has_boundary_at( + &collector.collect_unseen().entries, + first.end_time() + )); + + let second = ForegroundEvent::TaskPoll(task_timing( + start + Duration::from_millis(2), + start + Duration::from_millis(3), + )); + journal.begin_turn(); + journal.record_event(second); + counter.finished(); + journal.end_turn(second.end_time()); + assert!(collector.collect_unseen().entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at }) + if *ended_at == second.end_time() + ) + })); + } + + #[test] + fn a_pending_frame_prevents_idle_until_presentation() { + let start = Instant::now(); + let window_id = WindowId::from(0xD17A); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.record_frame_pending(window_id, start); + journal.begin_turn(); + journal.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end: start + Duration::from_millis(1), + caused_invalidation: true, + })); + let input_end = start + Duration::from_millis(1); + journal.end_turn(input_end); + assert!(!has_boundary_at( + &collector.collect_unseen().entries, + input_end + )); + + let frame = frame_timing(window_id, start, start + Duration::from_millis(2)); + let presentation = presentation_timing(window_id, start + Duration::from_millis(3)); + journal.record_present(presentation, Some(frame)); + assert!(collector.collect_unseen().entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::Presented(presented)) + if presented.frame.window_id == window_id + ) + })); + } + + #[test] + fn a_present_without_a_draw_clears_the_window_pending_state() { + let start = Instant::now(); + let presented_at = start + Duration::from_millis(1); + let window_id = WindowId::from(0xD17B); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.record_frame_pending(window_id, start); + journal.begin_turn(); + journal.record_present(presentation_timing(window_id, presented_at), None); + journal.end_turn(presented_at); + + let entries = collector.collect_unseen().entries; + assert!(entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::Present(timing)) + if timing.window_id == window_id + ) + })); + assert!(has_boundary_at(&entries, presented_at)); + } + + /// A frame that outlives [`FRAME_DEADLINE`] no longer seals an interval + /// of its own: the work that starved it and its eventual presentation + /// stay in one interval, preserving the dirty-to-present association. + #[test] + fn a_presentation_after_the_deadline_seals_the_whole_interval() { + let start = Instant::now(); + let window_id = WindowId::from(0xDEA1); + let presented_at = start + FRAME_DEADLINE + Duration::from_millis(250); + let mut sealer = IntervalSealer::new(start); + let snapshots = sealer.push_entries([ + pending_frame(window_id, start), + input_entry(start, start + Duration::from_millis(20)), + ForegroundJournalEntry::Boundary(presented_boundary(window_id, start, presented_at)), + ]); + let [snapshot] = snapshots.as_slice() else { + panic!("expected one presented snapshot, got {snapshots:?}"); + }; + assert!(matches!( + snapshot.boundary, + IntervalBoundary::Presented(presented) + if presented.frame.window_id == window_id + && presented.dirty_to_present_duration() + == Some(presented_at.duration_since(start)) + )); + assert_eq!(snapshot.interval_end(), presented_at); + assert_eq!(snapshot.events.len(), 2); + } + + /// Frame expiry unblocks idle boundaries on the writer side: retained + /// work after the deadline seals at its turn's end even though the window + /// never presented. + #[test] + fn an_expired_frame_no_longer_blocks_idle_boundaries() { + let start = Instant::now(); + let window_id = WindowId::from(0xDEA2); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.record_frame_pending(window_id, start); + + let blocked_end = start + Duration::from_millis(20); + journal.begin_turn(); + journal.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end: blocked_end, + caused_invalidation: true, + })); + journal.end_turn(blocked_end); + assert!(!has_boundary_at( + &collector.collect_unseen().entries, + blocked_end + )); + + let unblocked_end = start + FRAME_DEADLINE + Duration::from_millis(1); + journal.begin_turn(); + journal.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start: start + FRAME_DEADLINE, + end: unblocked_end, + caused_invalidation: false, + })); + journal.end_turn(unblocked_end); + assert!(has_boundary_at( + &collector.collect_unseen().entries, + unblocked_end + )); + } + + /// Closing a window clears its pending frame, so idle boundaries resume + /// without waiting for the deadline. + #[test] + fn closing_a_window_unblocks_idle_boundaries() { + let start = Instant::now(); + let window_id = WindowId::from(0xDEA7); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.record_frame_pending(window_id, start); + journal.record_window_closed(window_id, start + Duration::from_millis(1)); + + let event_end = start + Duration::from_millis(2); + journal.begin_turn(); + journal.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start: start + Duration::from_millis(1), + end: event_end, + caused_invalidation: false, + })); + journal.end_turn(event_end); + assert!(has_boundary_at( + &collector.collect_unseen().entries, + event_end + )); + } + + /// One window presenting must not unblock idle boundaries while another + /// window's unexpired frame is still pending. + #[test] + fn presenting_one_window_does_not_clear_another_pending_window() { + let start = Instant::now(); + let first_window = WindowId::from(0xDEA5); + let second_window = WindowId::from(0xDEA6); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.record_frame_pending(first_window, start); + journal.record_frame_pending(second_window, start + Duration::from_millis(100)); + journal.record_present( + presentation_timing(first_window, start + Duration::from_millis(500)), + Some(frame_timing( + first_window, + start, + start + Duration::from_millis(500), + )), + ); + + let event_end = start + Duration::from_millis(620); + journal.begin_turn(); + journal.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start: start + Duration::from_millis(600), + end: event_end, + caused_invalidation: false, + })); + journal.end_turn(event_end); + + let entries = collector.collect_unseen().entries; + assert!(entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::Presented(presented)) + if presented.frame.window_id == first_window + ) + })); + assert!(!has_boundary_at(&entries, event_end)); + } + + #[test] + fn small_polls_are_flushed_immediately_before_a_retained_event() { + let start = Instant::now(); + let first = task_timing( + start + Duration::from_millis(1), + start + Duration::from_millis(1) + Duration::from_micros(20), + ); + let second = task_timing( + start + Duration::from_millis(3), + start + Duration::from_millis(3) + Duration::from_micros(30), + ); + let input = InputTiming { + kind: "test", + start: start + Duration::from_millis(5), + end: start + Duration::from_millis(6), + caused_invalidation: false, + }; + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + + journal.fold_small_poll(first); + journal.fold_small_poll(second); + journal.record_event(ForegroundEvent::Input(input)); + + let drained = collector.collect_unseen(); + let input_index = drained + .entries + .iter() + .position(|entry| { + matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::Input(timing)) + if timing.start == input.start + ) + }) + .expect("input event should be retained"); + let Some(ForegroundJournalEntry::Event(ForegroundEvent::SmallPolls(flush))) = input_index + .checked_sub(1) + .and_then(|index| drained.entries.get(index)) + else { + panic!("small-poll summary should immediately precede the input event"); + }; + assert_eq!(flush.summary.count, 2); + assert_eq!(flush.summary.total, Duration::from_micros(50)); + assert_eq!(flush.since, first.start); + assert_eq!(flush.until, second.end.0); + } + + #[test] + fn small_polls_are_flushed_before_frame_state_changes() { + let start = Instant::now(); + let window_id = WindowId::from(0xDEA9); + let poll = task_timing(start, start + Duration::from_micros(50)); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + journal.fold_small_poll(poll); + journal.record_frame_pending(window_id, poll.end.0); + + let entries = collector.collect_unseen().entries; + let pending_index = entries + .iter() + .position(|entry| { + matches!( + entry, + ForegroundJournalEntry::FrameState(FrameStateChange::Pending { + window_id: pending_window, + .. + }) if *pending_window == window_id + ) + }) + .expect("pending frame should be retained"); + assert!(matches!( + pending_index + .checked_sub(1) + .and_then(|index| entries.get(index)), + Some(ForegroundJournalEntry::Event(ForegroundEvent::SmallPolls(flush))) + if flush.since == poll.start && flush.until == poll.end.0 + )); + } + + /// Sporadic wake-ups (a tiny folded poll after which the foreground goes + /// idle, repeatedly) must write nothing to the ring and must not accumulate + /// toward a later retained interval. + #[test] + fn sparse_small_polls_are_discarded_when_the_foreground_returns_to_idle() { + let start = Instant::now(); + let (mut journal, mut collector) = test_journal(ForegroundRunnableCounter::new()); + let mut tiny_wake = |ended_at: Instant| { + journal.begin_turn(); + journal.fold_small_poll(task_timing(ended_at - Duration::from_micros(50), ended_at)); + journal.end_turn(ended_at); + }; + + for second in 1..=160 { + tiny_wake(start + Duration::from_secs(second)); + } + let quiet = collector.collect_unseen().entries; + assert!(quiet.is_empty()); + + // A later retained event seals normally without inheriting the earlier + // folded-only wake-ups. + let retained = ForegroundEvent::TaskPoll(task_timing( + start + Duration::from_secs(161), + start + Duration::from_secs(161) + Duration::from_millis(1), + )); + journal.begin_turn(); + journal.record_event(retained); + journal.end_turn(retained.end_time()); + let entries = collector.collect_unseen().entries; + assert!(has_boundary_at(&entries, retained.end_time())); + assert!(!entries.iter().any(|entry| matches!( + entry, + ForegroundJournalEntry::Event(ForegroundEvent::SmallPolls(_)) + ))); + } + + #[test] + fn note_lost_is_reported_on_the_next_snapshot_only() { + let start = Instant::now(); + let mut sealer = IntervalSealer::new(start); + sealer.note_lost(7); + + let snapshots = sealer.push_entries([ + input_entry(start, start + Duration::from_millis(1)), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { + ended_at: start + Duration::from_millis(1), + }), + input_entry( + start + Duration::from_millis(2), + start + Duration::from_millis(3), + ), + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { + ended_at: start + Duration::from_millis(3), + }), + ]); + + assert_eq!(snapshots.len(), 2); + assert_eq!(snapshots[0].dropped_events, 7); + assert_eq!(snapshots[1].dropped_events, 0); + } + + /// Ring losses must be able to surface even when every retained entry was + /// among the losses: a loss-only interval still seals at the next + /// boundary rather than sliding away as empty. + #[test] + fn losses_alone_seal_a_snapshot_at_the_next_boundary() { + let start = Instant::now(); + let mut sealer = IntervalSealer::new(start); + sealer.note_lost(3); + + let snapshots = + sealer.push_entries([ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { + ended_at: start + Duration::from_millis(1), + })]); + + assert_eq!(snapshots.len(), 1); + assert_eq!(snapshots[0].dropped_events, 3); + assert!(snapshots[0].events.is_empty()); + } + + #[test] + fn interval_event_cap_counts_overflowing_events() { + let start = Instant::now(); + let mut sealer = IntervalSealer::new(start); + let overflow = 5; + let mut entries: Vec = (0..(MAX_INTERVAL_EVENTS + overflow) as u64) + .map(|i| { + input_entry( + start + Duration::from_micros(i), + start + Duration::from_micros(i + 1), + ) + }) + .collect(); + entries.push(ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { + ended_at: start + Duration::from_micros((MAX_INTERVAL_EVENTS + overflow) as u64 + 1), + })); + + let snapshots = sealer.push_entries(entries); + + assert_eq!(snapshots.len(), 1); + assert_eq!(snapshots[0].events.len(), MAX_INTERVAL_EVENTS); + assert_eq!(snapshots[0].dropped_events, overflow as u64); + } + + #[test] + fn collect_unseen_returns_each_entry_once_in_order() { + let start = Instant::now(); + let (journal, mut publisher) = ForegroundJournal::new(32, 4); + let mut collector = journal.collector(); + let timestamps: Vec = (0..19) + .map(|i| start + Duration::from_micros(i as u64 + 1)) + .collect(); + publisher.publish(timestamps.iter().map(|&at| input_entry(at, at))); + + let ours = |entries: &[ForegroundJournalEntry]| -> Vec { + entries + .iter() + .filter_map(|entry| match entry { + ForegroundJournalEntry::Event(ForegroundEvent::Input(timing)) + if timestamps.contains(&timing.end) => + { + Some(timing.end) + } + _ => None, + }) + .collect() + }; + + let drained = collector.collect_unseen(); + assert_eq!(ours(&drained.entries), timestamps); + + // The cursor advanced past everything: a second drain sees none of + // our entries again. + let drained = collector.collect_unseen(); + assert!(ours(&drained.entries).is_empty()); + } + + #[test] + fn concurrent_collection_preserves_the_complete_logical_sequence() { + const ENTRY_COUNT: u64 = 20_000; + + let origin = Instant::now(); + let (journal, mut publisher) = ForegroundJournal::new(8, 4); + let mut collector = journal.collector(); + let done = Arc::new(std::sync::atomic::AtomicBool::new(false)); + let collector_done = Arc::clone(&done); + let collector_task = std::thread::spawn(move || { + let mut observed = Vec::new(); + loop { + let drained = collector.collect_unseen(); + observed.extend(normalize_ring_drain(origin, drained.entries)); + if collector_done.load(Ordering::Acquire) { + let drained = collector.collect_unseen(); + observed.extend(normalize_ring_drain(origin, drained.entries)); + return (collector, observed); + } + std::thread::yield_now(); + } + }); + + for sequence in 0..ENTRY_COUNT { + publisher.publish([ring_entry(origin, sequence)]); + } + done.store(true, Ordering::Release); + + let (mut collector, mut observed) = collector_task + .join() + .expect("collector thread should not panic"); + publisher.flush_pending(); + observed.extend(normalize_ring_drain( + origin, + collector.collect_unseen().entries, + )); + + let mut expected_sequence = 0; + for entry in observed { + match entry { + ModelDrainEntry::Entry(sequence) => { + assert_eq!(sequence, expected_sequence); + expected_sequence += 1; + } + ModelDrainEntry::Discontinuity(lost) => expected_sequence += lost, + } + } + assert_eq!(expected_sequence, ENTRY_COUNT); + assert_eq!( + publisher.ring.finalized.load(Ordering::Acquire), + ENTRY_COUNT + ); + } + + #[derive(Clone, Debug)] + enum RingOperation { + Publish, + Collect(u8), + NewCollector, + Pin(u8), + Unpin(u8), + } + + #[derive(Clone, Debug, PartialEq, Eq)] + enum ModelDrainEntry { + Entry(u64), + Discontinuity(u64), + } + + struct ModelRing { + capacity: usize, + pending_capacity: usize, + next_sequence: u64, + finalized: u64, + offered: u64, + slots: Vec>, + pinned: Vec, + pending: VecDeque<(u64, u64)>, + dropped_after_pending: u64, + } + + impl ModelRing { + fn new(capacity: usize, pending_capacity: usize) -> Self { + Self { + capacity, + pending_capacity, + next_sequence: 0, + finalized: 0, + offered: 0, + slots: vec![None; capacity], + pinned: vec![false; capacity], + pending: VecDeque::new(), + dropped_after_pending: 0, + } + } + + fn publish(&mut self) { + self.flush_pending(); + let sequence = self.next_sequence; + self.next_sequence += 1; + self.offered = self.next_sequence; + + if !self.pending.is_empty() || self.dropped_after_pending > 0 { + if self.dropped_after_pending == 0 && self.pending.len() < self.pending_capacity { + self.pending.push_back((sequence, sequence)); + } else { + self.dropped_after_pending += 1; + } + } else { + let index = sequence as usize % self.capacity; + if self.pinned[index] { + if self.pending_capacity > 0 { + self.pending.push_back((sequence, sequence)); + } else { + self.dropped_after_pending = 1; + } + } else { + self.slots[index] = Some((sequence, sequence)); + self.finalized = sequence + 1; + } + } + self.flush_pending(); + } + + fn flush_pending(&mut self) { + while let Some(&(sequence, value)) = self.pending.front() { + let index = sequence as usize % self.capacity; + if self.pinned[index] { + return; + } + self.slots[index] = Some((sequence, value)); + self.pending.pop_front(); + self.finalized = sequence + 1; + } + + if self.dropped_after_pending > 0 { + self.finalized = self.next_sequence; + self.dropped_after_pending = 0; + } + } + + fn collect(&self, cursor: &mut u64) -> (Vec, u64) { + let end = self.finalized; + if *cursor >= end { + return (Vec::new(), 0); + } + + let retained_start = end.saturating_sub(self.capacity as u64); + let mut lost = retained_start.saturating_sub(*cursor); + *cursor = (*cursor).max(retained_start); + let mut entries = Vec::new(); + if lost > 0 { + entries.push(ModelDrainEntry::Discontinuity(lost)); + } + while *cursor < end { + let index = *cursor as usize % self.capacity; + match self.slots[index] { + Some((sequence, value)) if sequence == *cursor => { + entries.push(ModelDrainEntry::Entry(value)); + } + _ => { + lost += 1; + match entries.last_mut() { + Some(ModelDrainEntry::Discontinuity(lost)) => *lost += 1, + _ => entries.push(ModelDrainEntry::Discontinuity(1)), + } + } + } + *cursor += 1; + } + (entries, lost) + } + } + + fn ring_entry(origin: Instant, sequence: u64) -> ForegroundJournalEntry { + let at = origin + Duration::from_micros(sequence); + input_entry(at, at) + } + + fn normalize_ring_drain( + origin: Instant, + entries: Vec, + ) -> Vec { + entries + .into_iter() + .map(|entry| match entry { + ForegroundJournalEntry::Event(ForegroundEvent::Input(timing)) => { + ModelDrainEntry::Entry(timing.start.duration_since(origin).as_micros() as u64) + } + ForegroundJournalEntry::Discontinuity { lost } => { + ModelDrainEntry::Discontinuity(lost) + } + other => panic!("ring property observed an unexpected entry: {other:?}"), + }) + .collect() + } + + #[derive(Debug, Clone, PartialEq, Eq)] + struct NormalizedEvent { + kind: u8, + start: u64, + end: u64, + } + + #[derive(Debug, Clone, PartialEq, Eq)] + struct NormalizedSmallPolls { + count: u64, + total_micros: u64, + since: u64, + until: u64, + } + + #[derive(Debug, Clone, PartialEq, Eq)] + struct NormalizedSnapshot { + interval_start: u64, + boundary_kind: u8, + interval_end: u64, + events: Vec, + small_polls: Vec, + dropped_events: u64, + journal_discontinuous: bool, + } + + #[derive(Debug, Clone, PartialEq, Eq)] + struct NormalizedSealerTail { + interval_start: u64, + events: Vec, + small_polls: Vec, + dropped_events: u64, + journal_discontinuous: bool, + } + + fn completion_order_entries( + origin: Instant, + specifications: &[(u8, u8, u8)], + ) -> Vec { + let mut completed_at_micros = 1u64; + specifications + .iter() + .map(|(advance, span, kind)| { + completed_at_micros += u64::from(*advance) + 1; + let started_at_micros = completed_at_micros.saturating_sub(u64::from(*span)); + let start = origin + Duration::from_micros(started_at_micros); + let end = origin + Duration::from_micros(completed_at_micros); + match kind % 7 { + 0 => input_entry(start, end), + 1 => ForegroundJournalEntry::Event(ForegroundEvent::Action(ActionTiming { + name: "test.action", + start, + end, + })), + 2 => ForegroundJournalEntry::Event(ForegroundEvent::TaskPoll(task_timing( + start, end, + ))), + 3 => { + ForegroundJournalEntry::Event(ForegroundEvent::SmallPolls(SmallPollFlush { + summary: PollSummary { + count: u64::from(*span % 5) + 1, + total: Duration::from_micros(u64::from(*span)), + }, + since: start, + until: end, + })) + } + 4 => pending_frame(WindowId::from(completed_at_micros), start), + 5 => ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at: end }), + _ => ForegroundJournalEntry::Boundary(presented_boundary( + WindowId::from(completed_at_micros), + start, + end, + )), + } + }) + .collect() + } + + fn normalize_event(origin: Instant, event: ForegroundEvent) -> NormalizedEvent { + let kind = match event { + ForegroundEvent::TaskPoll(_) => 0, + ForegroundEvent::Action(_) => 1, + ForegroundEvent::Input(_) => 2, + ForegroundEvent::Draw(_) => 3, + ForegroundEvent::Present(_) => 4, + ForegroundEvent::SmallPolls(_) => 5, + }; + NormalizedEvent { + kind, + start: event.start_time().duration_since(origin).as_micros() as u64, + end: event.end_time().duration_since(origin).as_micros() as u64, + } + } + + fn normalize_small_polls(origin: Instant, flush: SmallPollFlush) -> NormalizedSmallPolls { + NormalizedSmallPolls { + count: flush.summary.count, + total_micros: flush.summary.total.as_micros() as u64, + since: flush.since.duration_since(origin).as_micros() as u64, + until: flush.until.duration_since(origin).as_micros() as u64, + } + } + + fn normalize_snapshot(origin: Instant, snapshot: &FrameSnapshot) -> NormalizedSnapshot { + NormalizedSnapshot { + interval_start: snapshot.interval_start.duration_since(origin).as_micros() as u64, + boundary_kind: match snapshot.boundary { + IntervalBoundary::Idle { .. } => 0, + IntervalBoundary::Presented(_) => 1, + IntervalBoundary::PowerTransition { .. } => 2, + IntervalBoundary::FrameSkipped(_) => 3, + }, + interval_end: snapshot.interval_end().duration_since(origin).as_micros() as u64, + events: snapshot + .events + .iter() + .copied() + .map(|event| normalize_event(origin, event)) + .collect(), + small_polls: snapshot + .small_polls + .iter() + .copied() + .map(|flush| normalize_small_polls(origin, flush)) + .collect(), + dropped_events: snapshot.dropped_events, + journal_discontinuous: snapshot.journal_discontinuous, + } + } + + fn normalize_tail(origin: Instant, sealer: &IntervalSealer) -> NormalizedSealerTail { + NormalizedSealerTail { + interval_start: sealer.interval_start.duration_since(origin).as_micros() as u64, + events: sealer + .events + .iter() + .copied() + .map(|event| normalize_event(origin, event)) + .collect(), + small_polls: sealer + .small_polls + .iter() + .copied() + .map(|flush| normalize_small_polls(origin, flush)) + .collect(), + dropped_events: sealer.dropped_events, + journal_discontinuous: sealer.journal_discontinuous, + } + } + + fn reference_seal( + origin: Instant, + entries: &[ForegroundJournalEntry], + ) -> (Vec, NormalizedSealerTail) { + let mut interval_start = 0; + let mut events = Vec::new(); + let mut small_polls = Vec::new(); + let mut snapshots = Vec::new(); + let mut dropped_events = 0; + let mut journal_discontinuous = false; + + for entry in entries { + match *entry { + ForegroundJournalEntry::Event(event) => { + let event_start = event.start_time().duration_since(origin).as_micros() as u64; + if events.is_empty() + && small_polls.is_empty() + && dropped_events == 0 + && !journal_discontinuous + { + interval_start = interval_start.max(event_start); + } + match event { + ForegroundEvent::SmallPolls(flush) => { + small_polls.push(normalize_small_polls(origin, flush)); + } + event => events.push(normalize_event(origin, event)), + } + } + ForegroundJournalEntry::Boundary(boundary) => { + if let IntervalBoundary::Presented(presented) = boundary { + let present = ForegroundEvent::Present(presented.presentation); + if events.is_empty() + && small_polls.is_empty() + && dropped_events == 0 + && !journal_discontinuous + { + interval_start = + interval_start + .max(present.start_time().duration_since(origin).as_micros() + as u64); + } + events.push(normalize_event(origin, present)); + } + + let interval_end = + boundary.end_time().duration_since(origin).as_micros() as u64; + if events.is_empty() + && small_polls.is_empty() + && dropped_events == 0 + && !journal_discontinuous + { + interval_start = interval_start.max(interval_end); + } else { + snapshots.push(NormalizedSnapshot { + interval_start, + boundary_kind: match boundary { + IntervalBoundary::Idle { .. } => 0, + IntervalBoundary::Presented(_) => 1, + IntervalBoundary::PowerTransition { .. } => 2, + IntervalBoundary::FrameSkipped(_) => 3, + }, + interval_end, + events: std::mem::take(&mut events), + small_polls: std::mem::take(&mut small_polls), + dropped_events: std::mem::take(&mut dropped_events), + journal_discontinuous: std::mem::take(&mut journal_discontinuous), + }); + interval_start = interval_end; + } + } + ForegroundJournalEntry::FrameState(_) + | ForegroundJournalEntry::PlatformSignal(_) + | ForegroundJournalEntry::ReentrantFrameSkipped { .. } => {} + ForegroundJournalEntry::Discontinuity { lost } => { + dropped_events += lost; + journal_discontinuous = true; + } + } + } + + ( + snapshots, + NormalizedSealerTail { + interval_start, + events, + small_polls, + dropped_events, + journal_discontinuous, + }, + ) + } + + fn reference_occupancy_micros( + event_spans: &[(u8, u8)], + small_poll_spans: &[(u8, u8, u8)], + window_start: u8, + window_end: u8, + ) -> u64 { + let mut clamped_spans = event_spans + .iter() + .map(|&(first, second)| { + let start = first.min(second).max(window_start); + let end = first.max(second).min(window_end).max(start); + (start, end) + }) + .collect::>(); + clamped_spans.sort_unstable(); + + let mut occupied = 0u64; + let mut merged_until = None; + for (start, end) in clamped_spans { + let start = merged_until.map_or(start, |until| start.max(until)); + occupied += u64::from(end.saturating_sub(start)); + merged_until = Some(merged_until.map_or(end, |until| until.max(end))); + } + + occupied + + small_poll_spans + .iter() + .map(|&(first, second, factor)| { + let since = first.min(second); + let until = first.max(second); + if since == until { + if since >= window_start && since <= window_end { + u64::from(factor) + } else { + 0 + } + } else { + let overlap_start = since.max(window_start); + let overlap_end = until.min(window_end).max(overlap_start); + u64::from(overlap_end - overlap_start) * u64::from(factor) + } + }) + .sum::() + } + + #[derive(Debug, Clone)] + struct WriterOperation { + kind: u8, + advance: u16, + argument: u8, + } + + #[derive(Debug, Clone, PartialEq, Eq)] + enum WriterEntry { + Input(u64), + SmallPolls { + count: u64, + total_micros: u64, + since: u64, + until: u64, + }, + Pending { + window: u64, + at: u64, + }, + Closed { + window: u64, + at: u64, + }, + Present { + window: u64, + at: u64, + }, + Presented { + window: u64, + at: u64, + }, + Idle(u64), + } + + #[derive(Default)] + struct ModelSmallPolls { + count: u64, + total_micros: u64, + since: u64, + until: u64, + } + + #[derive(Default)] + struct ModelWriter { + turn_depth: usize, + runnables: usize, + pending_frames: HashMap, + retained_since_boundary: bool, + small_polls: Option, + entries: Vec, + } + + impl ModelWriter { + fn record_entry(&mut self, entry: WriterEntry) { + if let Some(small_polls) = self.small_polls.take() { + self.entries.push(WriterEntry::SmallPolls { + count: small_polls.count, + total_micros: small_polls.total_micros, + since: small_polls.since, + until: small_polls.until, + }); + } + let boundary = matches!(entry, WriterEntry::Presented { .. } | WriterEntry::Idle(_)); + self.entries.push(entry); + if boundary { + self.retained_since_boundary = false; + } + } + + fn record_input(&mut self, at: u64) { + self.retained_since_boundary = true; + self.record_entry(WriterEntry::Input(at)); + } + + fn fold_small_poll(&mut self, since: u64, until: u64) { + let small_polls = self.small_polls.get_or_insert(ModelSmallPolls { + since, + until, + ..ModelSmallPolls::default() + }); + small_polls.count += 1; + small_polls.total_micros += until - since; + small_polls.since = small_polls.since.min(since); + small_polls.until = small_polls.until.max(until); + } + + fn record_pending(&mut self, window: u64, at: u64) { + let should_record = self + .pending_frames + .get(&window) + .is_none_or(|previous| at.saturating_sub(*previous) >= 1_000_000); + if should_record { + self.pending_frames.insert(window, at); + self.record_entry(WriterEntry::Pending { window, at }); + } + } + + fn record_closed(&mut self, window: u64, at: u64) { + self.pending_frames.remove(&window); + self.record_entry(WriterEntry::Closed { window, at }); + } + + fn record_present(&mut self, window: u64, at: u64, has_frame: bool) { + if has_frame { + self.pending_frames.remove(&window); + self.record_entry(WriterEntry::Presented { window, at }); + } else { + self.pending_frames.remove(&window); + self.retained_since_boundary = true; + self.record_entry(WriterEntry::Present { window, at }); + } + } + + fn end_turn(&mut self, at: u64) { + if self.turn_depth == 0 { + return; + } + self.turn_depth -= 1; + if self.turn_depth > 0 || self.runnables > 0 { + return; + } + self.pending_frames + .retain(|_, dirty_at| at.saturating_sub(*dirty_at) < 1_000_000); + if !self.pending_frames.is_empty() { + return; + } + if !self.retained_since_boundary { + self.small_polls = None; + return; + } + self.record_entry(WriterEntry::Idle(at)); + } + } + + fn normalize_writer_entries( + origin: Instant, + entries: Vec, + ) -> Vec { + let at = |instant: Instant| instant.duration_since(origin).as_micros() as u64; + entries + .into_iter() + .map(|entry| match entry { + ForegroundJournalEntry::Event(ForegroundEvent::Input(timing)) => { + WriterEntry::Input(at(timing.end)) + } + ForegroundJournalEntry::Event(ForegroundEvent::SmallPolls(flush)) => { + WriterEntry::SmallPolls { + count: flush.summary.count, + total_micros: flush.summary.total.as_micros() as u64, + since: at(flush.since), + until: at(flush.until), + } + } + ForegroundJournalEntry::Event(ForegroundEvent::Present(timing)) => { + WriterEntry::Present { + window: timing.window_id.as_u64(), + at: at(timing.present_end), + } + } + ForegroundJournalEntry::FrameState(FrameStateChange::Pending { + window_id, + dirty_at, + }) => WriterEntry::Pending { + window: window_id.as_u64(), + at: at(dirty_at), + }, + ForegroundJournalEntry::FrameState(FrameStateChange::Closed { + window_id, + at: closed_at, + }) => WriterEntry::Closed { + window: window_id.as_u64(), + at: at(closed_at), + }, + ForegroundJournalEntry::Boundary(IntervalBoundary::Presented(presented)) => { + WriterEntry::Presented { + window: presented.frame.window_id.as_u64(), + at: at(presented.presentation.present_end), + } + } + ForegroundJournalEntry::Boundary(IntervalBoundary::Idle { ended_at }) => { + WriterEntry::Idle(at(ended_at)) + } + other => panic!("writer property emitted an unexpected entry: {other:?}"), + }) + .collect() + } + + proptest! { + #![proptest_config(ProptestConfig { + failure_persistence: None, + ..ProptestConfig::default() + })] + + #[test] + fn ring_matches_reference_model_under_wrap_collisions_and_independent_cursors( + capacity in 1usize..=8, + pending_capacity in 0usize..=4, + operations in prop::collection::vec( + prop_oneof![ + 5 => Just(RingOperation::Publish), + 3 => any::().prop_map(RingOperation::Collect), + 1 => Just(RingOperation::NewCollector), + 2 => any::().prop_map(RingOperation::Pin), + 2 => any::().prop_map(RingOperation::Unpin), + ], + 1..=128, + ), + ) { + let origin = Instant::now(); + let (journal, mut publisher) = ForegroundJournal::new(capacity, pending_capacity); + let mut collectors = vec![journal.collector()]; + let mut model_collectors = vec![0]; + let mut model = ModelRing::new(capacity, pending_capacity); + let mut pins: Vec>> = + (0..capacity).map(|_| None).collect(); + + for operation in operations { + match operation { + RingOperation::Publish => { + let sequence = model.next_sequence; + publisher.publish([ring_entry(origin, sequence)]); + model.publish(); + } + RingOperation::Collect(collector) => { + let index = usize::from(collector) % collectors.len(); + let drained = collectors[index].collect_unseen(); + let (expected_entries, expected_lost) = + model.collect(&mut model_collectors[index]); + let observed_entries = normalize_ring_drain(origin, drained.entries); + prop_assert_eq!(observed_entries, expected_entries); + prop_assert_eq!(drained.lost, expected_lost); + } + RingOperation::NewCollector if collectors.len() < 4 => { + collectors.push(journal.collector()); + model_collectors.push(model.offered); + } + RingOperation::NewCollector => {} + RingOperation::Pin(slot) => { + let index = usize::from(slot) % capacity; + if pins[index].is_none() { + pins[index] = JournalSlotReadGuard::try_new(&journal.ring.slots[index]); + prop_assert!(pins[index].is_some()); + model.pinned[index] = true; + } + } + RingOperation::Unpin(slot) => { + let index = usize::from(slot) % capacity; + pins[index].take(); + model.pinned[index] = false; + } + } + + prop_assert_eq!(publisher.next_sequence, model.next_sequence); + prop_assert_eq!( + publisher.ring.offered.load(Ordering::Acquire), + model.offered + ); + prop_assert_eq!( + publisher.ring.finalized.load(Ordering::Acquire), + model.finalized + ); + prop_assert_eq!( + publisher + .pending + .iter() + .map(|entry| entry.sequence) + .collect::>(), + model + .pending + .iter() + .map(|(sequence, _)| *sequence) + .collect::>() + ); + prop_assert_eq!( + publisher.dropped_after_pending, + model.dropped_after_pending + ); + } + + for pin in &mut pins { + pin.take(); + } + model.pinned.fill(false); + publisher.flush_pending(); + model.flush_pending(); + + for (collector, model_cursor) in collectors.iter_mut().zip(&mut model_collectors) { + let drained = collector.collect_unseen(); + let (expected_entries, expected_lost) = model.collect(model_cursor); + let observed_entries = normalize_ring_drain(origin, drained.entries); + prop_assert_eq!(observed_entries, expected_entries); + prop_assert_eq!(drained.lost, expected_lost); + } + } + + #[test] + fn a_presentation_seals_exactly_once_regardless_of_delay( + present_delay_micros in 1u64..=2_000_000 + ) { + let start = Instant::now(); + let window_id = WindowId::from(0xDEA8); + let presented_at = start + Duration::from_micros(present_delay_micros); + let mut sealer = IntervalSealer::new(start); + let snapshots = sealer.push_entries([ + pending_frame(window_id, start), + input_entry(start, start + Duration::from_micros(1)), + ForegroundJournalEntry::Boundary(presented_boundary( + window_id, + start, + presented_at, + )), + ]); + + prop_assert_eq!(snapshots.len(), 1); + prop_assert!(matches!( + snapshots[0].boundary, + IntervalBoundary::Presented(_) + )); + prop_assert_eq!(snapshots[0].interval_end(), presented_at); + } + + #[test] + fn completion_order_sealer_matches_reference_under_arbitrary_batching( + specifications in prop::collection::vec((0u8..16, 0u8..128, any::()), 1..=96), + batch_sizes in prop::collection::vec(1usize..=12, 1..=24), + ) { + let origin = Instant::now(); + let entries = completion_order_entries(origin, &specifications); + let (expected_snapshots, expected_tail) = reference_seal(origin, &entries); + + let mut one_batch_sealer = IntervalSealer::new(origin); + let one_batch_snapshots = one_batch_sealer + .push_entries(entries.iter().copied()) + .iter() + .map(|snapshot| normalize_snapshot(origin, snapshot)) + .collect::>(); + prop_assert_eq!(&one_batch_snapshots, &expected_snapshots); + prop_assert_eq!(&normalize_tail(origin, &one_batch_sealer), &expected_tail); + + let mut batched_sealer = IntervalSealer::new(origin); + let mut batched_snapshots = Vec::new(); + let mut offset = 0; + let mut batch_index = 0; + while offset < entries.len() { + let batch_size = batch_sizes[batch_index % batch_sizes.len()]; + let batch_end = (offset + batch_size).min(entries.len()); + batched_snapshots.extend( + batched_sealer + .push_entries(entries[offset..batch_end].iter().copied()) + .iter() + .map(|snapshot| normalize_snapshot(origin, snapshot)), + ); + offset = batch_end; + batch_index += 1; + } + prop_assert_eq!(batched_snapshots, expected_snapshots); + prop_assert_eq!(normalize_tail(origin, &batched_sealer), expected_tail); + } + + #[test] + fn occupancy_matches_interval_union_and_fold_apportionment( + event_spans in prop::collection::vec((0u8..=128, 0u8..=128), 0..=16), + small_poll_spans in prop::collection::vec( + (0u8..=128, 0u8..=128, 0u8..=4), + 0..=12, + ), + window in (0u8..=128, 0u8..=128), + ) { + let origin = Instant::now(); + let window_start_micros = window.0.min(window.1); + let window_end_micros = window.0.max(window.1); + let events = event_spans + .iter() + .map(|&(first, second)| { + let start = origin + Duration::from_micros(u64::from(first.min(second))); + let end = origin + Duration::from_micros(u64::from(first.max(second))); + ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end, + caused_invalidation: false, + }) + }) + .collect(); + let small_polls = small_poll_spans + .iter() + .map(|&(first, second, factor)| { + let since_micros = first.min(second); + let until_micros = first.max(second); + let span_micros = u64::from(until_micros - since_micros); + let total_micros = if span_micros == 0 { + u64::from(factor) + } else { + span_micros * u64::from(factor) + }; + SmallPollFlush { + summary: PollSummary { + count: 1, + total: Duration::from_micros(total_micros), + }, + since: origin + Duration::from_micros(u64::from(since_micros)), + until: origin + Duration::from_micros(u64::from(until_micros)), + } + }) + .collect(); + let snapshot = FrameSnapshot { + interval_start: origin, + boundary: IntervalBoundary::Idle { + ended_at: origin + Duration::from_micros(128), + }, + events, + small_polls, + dropped_events: 0, + journal_discontinuous: false, + }; + let expected_micros = reference_occupancy_micros( + &event_spans, + &small_poll_spans, + window_start_micros, + window_end_micros, + ); + let observed = snapshot.occupancy_within( + origin + Duration::from_micros(u64::from(window_start_micros)), + origin + Duration::from_micros(u64::from(window_end_micros)), + ); + + prop_assert_eq!(observed, Duration::from_micros(expected_micros)); + + let full_expected = + reference_occupancy_micros(&event_spans, &small_poll_spans, 0, 128); + prop_assert_eq!(snapshot.occupancy(), Duration::from_micros(full_expected)); + prop_assert!((0.0..=1.0).contains(&snapshot.busy_fraction())); + prop_assert_eq!( + snapshot.busy_fraction(), + (full_expected as f64 / 128.0).min(1.0) + ); + } + + #[test] + fn writer_matches_state_model_across_turn_frame_and_runnable_transitions( + operations in prop::collection::vec( + (any::(), any::(), any::()).prop_map( + |(kind, advance, argument)| WriterOperation { + kind, + advance, + argument, + }, + ), + 1..=128, + ), + ) { + let origin = Instant::now(); + let counter = ForegroundRunnableCounter::new(); + let (mut writer, mut collector) = test_journal(counter.clone()); + let mut model = ModelWriter::default(); + let mut at_micros = 100u64; + + for operation in operations { + if operation.advance % 16 == 0 { + at_micros += FRAME_DEADLINE.as_micros() as u64; + } else { + at_micros += u64::from(operation.advance) + 1; + } + let at = origin + Duration::from_micros(at_micros); + let window_id = WindowId::from(u64::from(operation.argument % 4)); + let window = window_id.as_u64(); + + match operation.kind % 10 { + 0 => { + writer.begin_turn(); + model.turn_depth += 1; + } + 1 if model.turn_depth > 0 => { + writer.end_turn(at); + model.end_turn(at_micros); + } + 1 => {} + 2 => { + writer.record_event(ForegroundEvent::Input(InputTiming { + kind: "test", + start: at, + end: at, + caused_invalidation: false, + })); + model.record_input(at_micros); + } + 3 => { + let duration_micros = u64::from(operation.argument % 100); + writer.fold_small_poll(task_timing( + at - Duration::from_micros(duration_micros), + at, + )); + model.fold_small_poll( + at_micros - duration_micros, + at_micros, + ); + } + 4 => { + counter.queued(); + model.runnables += 1; + } + 5 if model.runnables > 0 => { + counter.finished(); + model.runnables -= 1; + } + 5 => {} + 6 => { + writer.record_frame_pending(window_id, at); + model.record_pending(window, at_micros); + } + 7 => { + writer.record_window_closed(window_id, at); + model.record_closed(window, at_micros); + } + 8 => { + writer.record_present( + presentation_timing(window_id, at), + Some(frame_timing(window_id, at, at)), + ); + model.record_present(window, at_micros, true); + } + _ => { + writer.record_present(presentation_timing(window_id, at), None); + model.record_present(window, at_micros, false); + } + } + + let drained = collector.collect_unseen(); + prop_assert_eq!(drained.lost, 0); + prop_assert_eq!( + normalize_writer_entries(origin, drained.entries), + std::mem::take(&mut model.entries) + ); + prop_assert_eq!(writer.turn_depth, model.turn_depth); + prop_assert_eq!(writer.retained_since_boundary, model.retained_since_boundary); + prop_assert_eq!( + writer + .windows + .values() + .filter(|window| window.dirty_at.is_some()) + .count(), + model.pending_frames.len() + ); + } + } + } + + fn test_journal( + foreground_runnables: ForegroundRunnableCounter, + ) -> (ForegroundJournalWriter, ForegroundJournalCollector) { + let (journal, publisher) = ForegroundJournal::new(256, 8); + let collector = journal.collector(); + ( + ForegroundJournalWriter::new(foreground_runnables, publisher).with_test_suspend_clock(), + collector, + ) + } + + fn has_boundary_at(entries: &[ForegroundJournalEntry], at: Instant) -> bool { + entries.iter().any(|entry| { + matches!(entry, ForegroundJournalEntry::Boundary(boundary) if boundary.end_time() == at) + }) + } + + fn input_entry(start: Instant, end: Instant) -> ForegroundJournalEntry { + ForegroundJournalEntry::Event(ForegroundEvent::Input(InputTiming { + kind: "test", + start, + end, + caused_invalidation: false, + })) + } + + fn pending_frame(window_id: WindowId, dirty_at: Instant) -> ForegroundJournalEntry { + ForegroundJournalEntry::FrameState(FrameStateChange::Pending { + window_id, + dirty_at, + }) + } + + fn frame_timing(window_id: WindowId, dirty_at: Instant, draw_end: Instant) -> FrameTiming { + FrameTiming { + window_id, + dirty_at: Some(dirty_at), + invalidations: 1, + draw_start: draw_end, + draw_end, + } + } + + fn presentation_timing(window_id: WindowId, present_end: Instant) -> PresentTiming { + PresentTiming { + window_id, + present_start: present_end, + present_end, + animation_interval: None, + } + } + + fn presented_boundary( + window_id: WindowId, + dirty_at: Instant, + present_end: Instant, + ) -> IntervalBoundary { + IntervalBoundary::Presented(PresentedFrame { + frame: frame_timing(window_id, dirty_at, present_end), + presentation: presentation_timing(window_id, present_end), + }) + } + + fn task_timing(start: Instant, end: Instant) -> TaskTiming { + TaskTiming { + location: std::panic::Location::caller(), + spawned: SpawnTime(start), + start, + end: YieldTime(end), + } + } +} diff --git a/vendor/gpui-pre/src/queue.rs b/vendor/gpui-pre/src/queue.rs new file mode 100644 index 00000000..6d921309 --- /dev/null +++ b/vendor/gpui-pre/src/queue.rs @@ -0,0 +1,499 @@ +use std::{ + collections::VecDeque, + fmt, + iter::FusedIterator, + sync::{Arc, Condvar, Mutex, MutexGuard, PoisonError, TryLockError, atomic::AtomicUsize}, +}; + +use rand::{Rng, SeedableRng, rngs::SmallRng}; + +use crate::Priority; + +struct PriorityQueues { + high_priority: VecDeque, + medium_priority: VecDeque, + low_priority: VecDeque, +} + +impl PriorityQueues { + fn is_empty(&self) -> bool { + self.high_priority.is_empty() + && self.medium_priority.is_empty() + && self.low_priority.is_empty() + } +} + +struct PriorityQueueState { + // std's Wasm atomic backend unlocks and notifies without acquiring another + // lock. parking_lot can park during those operations, even after try_lock. + queues: Mutex>, + condvar: Condvar, + receiver_count: AtomicUsize, + sender_count: AtomicUsize, +} + +impl PriorityQueueState { + fn send(&self, priority: Priority, item: T) -> Result<(), SendError> { + if self + .receiver_count + .load(std::sync::atomic::Ordering::Relaxed) + == 0 + { + return Err(SendError(item)); + } + + let mut queues = self.queues.lock().unwrap_or_else(PoisonError::into_inner); + Self::push(&mut queues, priority, item); + self.condvar.notify_one(); + Ok(()) + } + + fn spin_send(&self, priority: Priority, item: T) -> Result<(), SendError> { + if self + .receiver_count + .load(std::sync::atomic::Ordering::Relaxed) + == 0 + { + return Err(SendError(item)); + } + + let mut queues = loop { + match self.queues.try_lock() { + Ok(guard) => break guard, + Err(TryLockError::Poisoned(error)) => break error.into_inner(), + Err(TryLockError::WouldBlock) => std::hint::spin_loop(), + } + }; + Self::push(&mut queues, priority, item); + self.condvar.notify_one(); + Ok(()) + } + + fn push(queues: &mut PriorityQueues, priority: Priority, item: T) { + match priority { + Priority::RealtimeAudio => unreachable!( + "Realtime audio priority runs on a dedicated thread and is never queued" + ), + Priority::High => queues.high_priority.push_back(item), + Priority::Medium => queues.medium_priority.push_back(item), + Priority::Low => queues.low_priority.push_back(item), + }; + } + + fn recv<'a>(&'a self) -> Result>, RecvError> { + let mut queues = self.queues.lock().unwrap_or_else(PoisonError::into_inner); + + // Re-checked after every wake: dropping the last sender wakes waiting receivers + // so they can end instead of blocking forever on a queue nothing can fill. + while queues.is_empty() { + if self.sender_count.load(std::sync::atomic::Ordering::Acquire) == 0 { + return Err(crate::queue::RecvError); + } + queues = self + .condvar + .wait(queues) + .unwrap_or_else(PoisonError::into_inner); + } + + Ok(queues) + } + + fn try_recv<'a>(&'a self) -> Result>>, RecvError> { + let queues = self.queues.lock().unwrap_or_else(PoisonError::into_inner); + + let sender_count = self.sender_count.load(std::sync::atomic::Ordering::Relaxed); + if queues.is_empty() && sender_count == 0 { + return Err(crate::queue::RecvError); + } + + if queues.is_empty() { + Ok(None) + } else { + Ok(Some(queues)) + } + } + + fn spin_try_recv<'a>(&'a self) -> Result>>, RecvError> { + let queues = loop { + match self.queues.try_lock() { + Ok(guard) => break guard, + Err(TryLockError::Poisoned(error)) => break error.into_inner(), + Err(TryLockError::WouldBlock) => std::hint::spin_loop(), + } + }; + + let sender_count = self.sender_count.load(std::sync::atomic::Ordering::Relaxed); + if queues.is_empty() && sender_count == 0 { + return Err(crate::queue::RecvError); + } + + if queues.is_empty() { + Ok(None) + } else { + Ok(Some(queues)) + } + } +} + +#[doc(hidden)] +pub struct PriorityQueueSender { + state: Arc>, +} + +impl PriorityQueueSender { + fn new(state: Arc>) -> Self { + Self { state } + } + + pub fn send(&self, priority: Priority, item: T) -> Result<(), SendError> { + self.state.send(priority, item)?; + Ok(()) + } + + pub fn spin_send(&self, priority: Priority, item: T) -> Result<(), SendError> { + self.state.spin_send(priority, item)?; + Ok(()) + } +} + +impl Drop for PriorityQueueSender { + fn drop(&mut self) { + let previous = self + .state + .sender_count + .fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + if previous == 1 { + // A receiver checks the sender count and starts waiting under the queue lock, + // atomically. Acquiring that lock once, even with nothing to do under it, + // means any receiver that saw a live sender is already waiting, so the + // notification below reaches it; without this, a receiver between its check + // and its wait would miss the wake-up and block forever. + drop( + self.state + .queues + .lock() + .unwrap_or_else(PoisonError::into_inner), + ); + self.state.condvar.notify_all(); + } + } +} + +#[doc(hidden)] +pub struct PriorityQueueReceiver { + state: Arc>, + rand: SmallRng, + disconnected: bool, +} + +impl Clone for PriorityQueueReceiver { + fn clone(&self) -> Self { + self.state + .receiver_count + .fetch_add(1, std::sync::atomic::Ordering::AcqRel); + Self { + state: Arc::clone(&self.state), + rand: SmallRng::seed_from_u64(0), + disconnected: self.disconnected, + } + } +} + +#[doc(hidden)] +pub struct SendError(pub T); + +impl fmt::Debug for SendError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SendError").field(&self.0).finish() + } +} + +#[derive(Debug)] +#[doc(hidden)] +pub struct RecvError; + +#[allow(dead_code)] +impl PriorityQueueReceiver { + pub fn new() -> (PriorityQueueSender, Self) { + let state = PriorityQueueState { + queues: Mutex::new(PriorityQueues { + high_priority: VecDeque::new(), + medium_priority: VecDeque::new(), + low_priority: VecDeque::new(), + }), + condvar: Condvar::new(), + receiver_count: AtomicUsize::new(1), + sender_count: AtomicUsize::new(1), + }; + let state = Arc::new(state); + + let sender = PriorityQueueSender::new(Arc::clone(&state)); + + let receiver = PriorityQueueReceiver { + state, + rand: SmallRng::seed_from_u64(0), + disconnected: false, + }; + + (sender, receiver) + } + + /// Returns whether the queue currently contains no elements. + pub fn is_empty(&self) -> bool { + self.state + .queues + .lock() + .unwrap_or_else(PoisonError::into_inner) + .is_empty() + } + + /// Returns the number of queued elements across all priorities. + pub(crate) fn len(&self) -> usize { + let queues = self + .state + .queues + .lock() + .unwrap_or_else(PoisonError::into_inner); + queues.high_priority.len() + queues.medium_priority.len() + queues.low_priority.len() + } + + /// Tries to pop one element from the priority queue without blocking. + /// + /// This will early return if there are no elements in the queue. + /// + /// This method is best suited if you only intend to pop one element, for better performance + /// on large queues see [`Self::try_iter`] + /// + /// # Errors + /// + /// If the sender was dropped + pub fn try_pop(&mut self) -> Result, RecvError> { + self.pop_inner(false) + } + + pub fn spin_try_pop(&mut self) -> Result, RecvError> { + use Priority as P; + + let Some(mut queues) = self.state.spin_try_recv()? else { + return Ok(None); + }; + + let high = P::High.weight() * !queues.high_priority.is_empty() as u32; + let medium = P::Medium.weight() * !queues.medium_priority.is_empty() as u32; + let low = P::Low.weight() * !queues.low_priority.is_empty() as u32; + let mut mass = high + medium + low; + + if !queues.high_priority.is_empty() { + let flip = self.rand.random_ratio(P::High.weight(), mass); + if flip { + return Ok(queues.high_priority.pop_front()); + } + mass -= P::High.weight(); + } + + if !queues.medium_priority.is_empty() { + let flip = self.rand.random_ratio(P::Medium.weight(), mass); + if flip { + return Ok(queues.medium_priority.pop_front()); + } + mass -= P::Medium.weight(); + } + + if !queues.low_priority.is_empty() { + let flip = self.rand.random_ratio(P::Low.weight(), mass); + if flip { + return Ok(queues.low_priority.pop_front()); + } + } + + Ok(None) + } + + /// Pops an element from the priority queue blocking if necessary. + /// + /// This method is best suited if you only intend to pop one element, for better performance + /// on large queues see [`Self::iter``] + /// + /// # Errors + /// + /// If the sender was dropped + pub fn pop(&mut self) -> Result { + self.pop_inner(true).map(|e| e.unwrap()) + } + + /// Returns an iterator over the elements of the queue + /// this iterator will end when all elements have been consumed and will not wait for new ones. + pub fn try_iter(self) -> TryIter { + TryIter { + receiver: self, + ended: false, + } + } + + /// Returns an iterator over the elements of the queue + /// this iterator will wait for new elements if the queue is empty. + pub fn iter(self) -> Iter { + Iter(self) + } + + #[inline(always)] + // algorithm is the loaded die from biased coin from + // https://www.keithschwarz.com/darts-dice-coins/ + fn pop_inner(&mut self, block: bool) -> Result, RecvError> { + use Priority as P; + + let mut queues = if !block { + let Some(queues) = self.state.try_recv()? else { + return Ok(None); + }; + queues + } else { + self.state.recv()? + }; + + let high = P::High.weight() * !queues.high_priority.is_empty() as u32; + let medium = P::Medium.weight() * !queues.medium_priority.is_empty() as u32; + let low = P::Low.weight() * !queues.low_priority.is_empty() as u32; + let mut mass = high + medium + low; //% + + if !queues.high_priority.is_empty() { + let flip = self.rand.random_ratio(P::High.weight(), mass); + if flip { + return Ok(queues.high_priority.pop_front()); + } + mass -= P::High.weight(); + } + + if !queues.medium_priority.is_empty() { + let flip = self.rand.random_ratio(P::Medium.weight(), mass); + if flip { + return Ok(queues.medium_priority.pop_front()); + } + mass -= P::Medium.weight(); + } + + if !queues.low_priority.is_empty() { + let flip = self.rand.random_ratio(P::Low.weight(), mass); + if flip { + return Ok(queues.low_priority.pop_front()); + } + } + + Ok(None) + } +} + +impl Drop for PriorityQueueReceiver { + fn drop(&mut self) { + self.state + .receiver_count + .fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + } +} + +#[doc(hidden)] +pub struct Iter(PriorityQueueReceiver); +impl Iterator for Iter { + type Item = T; + + fn next(&mut self) -> Option { + self.0.pop().ok() + } +} +impl FusedIterator for Iter {} + +#[doc(hidden)] +pub struct TryIter { + receiver: PriorityQueueReceiver, + ended: bool, +} +impl Iterator for TryIter { + type Item = Result; + + fn next(&mut self) -> Option { + if self.ended { + return None; + } + + let res = self.receiver.try_pop(); + self.ended = res.is_err(); + + res.transpose() + } +} +impl FusedIterator for TryIter {} + +#[cfg(test)] +mod tests { + use collections::HashSet; + + use super::*; + + #[test] + fn blocked_receivers_end_when_the_sender_drops() { + let (sender, receiver) = PriorityQueueReceiver::::new(); + let (done_sender, done_receiver) = std::sync::mpsc::channel(); + let workers = (0..2) + .map(|_| { + let receiver = receiver.clone(); + let done_sender = done_sender.clone(); + std::thread::spawn(move || { + let received: Vec = receiver.iter().collect(); + done_sender.send(received).ok(); + }) + }) + .collect::>(); + drop(receiver); + + sender.send(Priority::Medium, 7).unwrap(); + std::thread::sleep(std::time::Duration::from_millis(50)); + assert!( + done_receiver.try_recv().is_err(), + "receivers keep waiting while the sender is alive" + ); + + drop(sender); + let mut received = Vec::new(); + for _ in 0..2 { + received.extend( + done_receiver + .recv_timeout(std::time::Duration::from_secs(5)) + .expect("a waiting receiver should end once the sender is dropped"), + ); + } + assert_eq!(received, [7]); + for worker in workers { + worker.join().expect("worker should exit cleanly"); + } + } + + #[test] + fn all_tasks_get_yielded() { + let (tx, mut rx) = PriorityQueueReceiver::new(); + tx.send(Priority::Medium, 20).unwrap(); + tx.send(Priority::High, 30).unwrap(); + tx.send(Priority::Low, 10).unwrap(); + tx.send(Priority::Medium, 21).unwrap(); + tx.send(Priority::High, 31).unwrap(); + + drop(tx); + + assert_eq!( + rx.iter().collect::>(), + [30, 31, 20, 21, 10].into_iter().collect::>() + ) + } + + #[test] + fn new_high_prio_task_get_scheduled_quickly() { + let (tx, mut rx) = PriorityQueueReceiver::new(); + for _ in 0..100 { + tx.send(Priority::Low, 1).unwrap(); + } + + assert_eq!(rx.pop().unwrap(), 1); + tx.send(Priority::High, 3).unwrap(); + assert_eq!(rx.pop().unwrap(), 3); + assert_eq!(rx.pop().unwrap(), 1); + } +} diff --git a/vendor/gpui-pre/src/randomized_element_tree.rs b/vendor/gpui-pre/src/randomized_element_tree.rs new file mode 100644 index 00000000..1366317b --- /dev/null +++ b/vendor/gpui-pre/src/randomized_element_tree.rs @@ -0,0 +1,1745 @@ +use crate::{ + AnyElement, AppContext as _, Context, ElementId, Entity, Hsla, InteractiveElement, IntoElement, + ParentElement, Render, StatefulInteractiveElement, Styled, Window, div, px, + util::FluentBuilder, +}; +use collections::{HashMap, HashSet}; +use rand::{Rng as _, SeedableRng as _, rngs::StdRng}; +use std::{ + cell::RefCell, + ops::RangeInclusive, + rc::{Rc, Weak}, +}; + +/// Dispatched to no one: the action generated elements register handlers for. Not +/// registered, so builds that enable `bench-support` through feature unification (such as +/// the workspace's tests) don't gain an action namespace. +#[derive(Clone, Default, PartialEq, crate::Action)] +#[action(namespace = randomized_element_tree, no_json, no_register)] +pub struct RandomizedElementTreeAction; + +/// The initial shape generated for a randomized element tree. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum RandomizedElementTreeTopology { + /// Every generated element is a direct child of the root. + Wide, + /// Every generated element is the child of the previous element. + Deep, + /// Generated elements choose parents throughout the existing tree. + Mixed, + /// Generated elements usually extend one deep branch, with occasional root children. + Narrow, +} + +impl RandomizedElementTreeTopology { + /// Every topology. + pub const ALL: [Self; 4] = [Self::Wide, Self::Deep, Self::Mixed, Self::Narrow]; + + /// Whether the tree's depth grows with its element count. `Deep` nests every element + /// under the previous one and `Narrow` nests four in five, so both recurse once per + /// element through layout and paint; without gpui's `stacker` feature that overflows + /// a 2 MB thread stack somewhere between 384 and 512 elements in a release build. + pub fn is_tall(self) -> bool { + matches!(self, Self::Deep | Self::Narrow) + } + + fn from_seed(seed: u64) -> Self { + match seed % 4 { + 0 => Self::Wide, + 1 => Self::Deep, + 2 => Self::Mixed, + _ => Self::Narrow, + } + } +} + +/// Configuration for a reproducible randomized element-tree workload. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct RandomizedElementTreeConfig { + seed: u64, + element_count: usize, + topology: RandomizedElementTreeTopology, + entity_density: f64, + handler_density: f64, +} + +impl RandomizedElementTreeConfig { + /// Creates an element-only workload whose topology is selected by `seed`. + pub fn new(seed: u64, element_count: usize) -> Self { + Self { + seed, + element_count, + topology: RandomizedElementTreeTopology::from_seed(seed), + entity_density: 0.0, + handler_density: 0.0, + } + } + + /// Selects the initial tree topology independently of the RNG seed. + pub fn with_topology(mut self, topology: RandomizedElementTreeTopology) -> Self { + self.topology = topology; + self + } + + /// Sets the probability that each generated element is backed by a persistent entity. + pub fn with_entity_density(mut self, density: f64) -> Self { + self.entity_density = normalized_density(density); + self + } + + /// Sets the probability of each generated interaction feature on an element. + pub fn with_handler_density(mut self, density: f64) -> Self { + self.handler_density = normalized_density(density); + self + } + + /// Returns the seed used for generation and subsequent random mutations. + pub fn seed(&self) -> u64 { + self.seed + } + + /// Returns the requested number of initial descendants. + pub fn element_count(&self) -> usize { + self.element_count + } + + /// Returns the selected initial topology. + pub fn topology(&self) -> RandomizedElementTreeTopology { + self.topology + } + + /// Returns the probability that a generated element is backed by an entity. + pub fn entity_density(&self) -> f64 { + self.entity_density + } + + /// Returns the probability of each generated interaction feature. + pub fn handler_density(&self) -> f64 { + self.handler_density + } +} + +/// Bounds an RNG is drawn against to produce a [`RandomizedElementTreeConfig`]: a family +/// of trees, such as "tall trees of 32 to 256 elements with up to half of them entities", +/// from which one draw picks one member. Every field of the resulting config, and the +/// tree built from it, follows from the RNG's state, so an RNG seeded by `#[gpui::bench]` +/// or `#[gpui::test]` samples the family across seeds and any one seed reproduces exactly. +#[derive(Clone, Debug, PartialEq)] +pub struct RandomizedElementTreeBounds { + topologies: Vec, + element_count: RangeInclusive, + entity_density: RangeInclusive, + handler_density: RangeInclusive, +} + +impl RandomizedElementTreeBounds { + /// Trees of any topology with `element_count` elements, no entities and no handlers. + pub fn new(element_count: RangeInclusive) -> Self { + Self { + topologies: RandomizedElementTreeTopology::ALL.to_vec(), + element_count, + entity_density: 0.0..=0.0, + handler_density: 0.0..=0.0, + } + } + + /// Restricts the topologies a seed may pick. An empty list keeps them all. + pub fn with_topologies( + mut self, + topologies: impl IntoIterator, + ) -> Self { + let topologies: Vec<_> = topologies.into_iter().collect(); + if !topologies.is_empty() { + self.topologies = topologies; + } + self + } + + /// The range a seed draws the share of entity-backed elements from. + pub fn with_entity_density(mut self, density: RangeInclusive) -> Self { + self.entity_density = + normalized_density(*density.start())..=normalized_density(*density.end()); + self + } + + /// The range a seed draws the per-feature handler probability from. + pub fn with_handler_density(mut self, density: RangeInclusive) -> Self { + self.handler_density = + normalized_density(*density.start())..=normalized_density(*density.end()); + self + } + + /// Draws one config from these bounds. The config's own seed, which drives the tree's + /// contents and mutation stream, is drawn from `rng` too, so all of it reproduces from + /// the seed `rng` started from. + pub fn sample(&self, rng: &mut StdRng) -> RandomizedElementTreeConfig { + let topology = self.topologies[rng.random_range(0..self.topologies.len())]; + let element_count = rng.random_range(self.element_count.clone()); + RandomizedElementTreeConfig::new(rng.random(), element_count) + .with_topology(topology) + .with_entity_density(sample_range(&self.entity_density, rng)) + .with_handler_density(sample_range(&self.handler_density, rng)) + } +} + +fn sample_range(range: &RangeInclusive, rng: &mut StdRng) -> f64 { + if range.start() >= range.end() { + *range.start() + } else { + rng.random_range(range.clone()) + } +} + +/// Work performed while converting randomized entities and elements into an element tree. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct RandomizedElementTreeWorkCounters { + root_render_count: usize, + entity_render_count: usize, + element_render_count: usize, + handler_registration_count: usize, + rendered_entity_ids: Vec, +} + +impl RandomizedElementTreeWorkCounters { + /// Returns how many times the persistent root's `Render` implementation ran. + pub fn root_render_count(&self) -> usize { + self.root_render_count + } + + /// Returns how many randomized child entities rendered. + pub fn entity_render_count(&self) -> usize { + self.entity_render_count + } + + /// Returns how many randomized descendant elements were reconstructed. + pub fn element_render_count(&self) -> usize { + self.element_render_count + } + + /// Returns how many interaction handlers were registered while rendering. + pub fn handler_registration_count(&self) -> usize { + self.handler_registration_count + } + + /// Returns stable IDs for the randomized child entities that rendered, in render order. + pub fn rendered_entity_ids(&self) -> &[u64] { + &self.rendered_entity_ids + } + + fn reset(&mut self) { + self.root_render_count = 0; + self.entity_render_count = 0; + self.element_render_count = 0; + self.handler_registration_count = 0; + self.rendered_entity_ids.clear(); + } +} + +/// A cloneable description of a randomized element tree's renderable state. +#[derive(Clone, Debug, PartialEq)] +pub struct RandomizedElementTreeSnapshot { + root: RandomizedElementStyle, + children: Vec, + next_element_id: u64, + paths_by_element_id: HashMap>, +} + +impl RandomizedElementTreeSnapshot { + /// Returns the number of randomized elements below the persistent root. + pub fn descendant_count(&self) -> usize { + let mut count = 0; + let mut stack = self.children.iter().collect::>(); + while let Some(node) = stack.pop() { + count += 1; + stack.extend(node.children.iter()); + } + count + } + + /// Returns the deepest randomized element below the persistent root. + /// + /// A snapshot with no descendants has depth zero. + pub fn max_depth(&self) -> usize { + let mut max_depth = 0; + let mut stack = self + .children + .iter() + .map(|node| (node, 1)) + .collect::>(); + while let Some((node, depth)) = stack.pop() { + max_depth = max_depth.max(depth); + stack.extend(node.children.iter().map(|child| (child, depth + 1))); + } + max_depth + } + + /// Returns the stable element IDs in depth-first order. + pub fn element_ids(&self) -> Vec { + node_paths(&self.children) + .iter() + .filter_map(|path| node_at_path(&self.children, path).map(|node| node.id)) + .collect() + } + + /// Returns the number of descendants backed by persistent child entities. + pub fn entity_count(&self) -> usize { + let mut count = 0; + let mut stack = self.children.iter().collect::>(); + while let Some(node) = stack.pop() { + count += usize::from(node.is_entity); + stack.extend(node.children.iter()); + } + count + } + + /// Returns the number of interaction handlers in the generated tree. + pub fn handler_count(&self) -> usize { + let mut count = 0; + let mut stack = self.children.iter().collect::>(); + while let Some(node) = stack.pop() { + count += node.features.handler_count(); + stack.extend(node.children.iter()); + } + count + } + + fn rebuild_element_paths(&mut self) { + self.paths_by_element_id = node_paths(&self.children) + .into_iter() + .filter_map(|path| node_at_path(&self.children, &path).map(|node| (node.id, path))) + .collect(); + } + + fn node(&self, element_id: u64) -> Option<&RandomizedElementNode> { + node_at_path(&self.children, self.paths_by_element_id.get(&element_id)?) + } +} + +/// A requested class of deterministic randomized-tree mutation. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum RandomizedElementTreeMutationKind { + /// Change the root background color. + RootColor, + /// Change the root opacity. + RootOpacity, + /// Change the root border. + RootBorder, + /// Change the root width and height. + RootBounds, + /// Toggle clipping on the root. + RootClipping, + /// Toggle root visibility. + RootVisibility, + /// Change a seeded random descendant's colors. + ChildColor, + /// Change a seeded random descendant's opacity. + ChildOpacity, + /// Change a seeded random descendant's border. + ChildBorder, + /// Change a seeded random descendant's width and height. + ChildBounds, + /// Toggle clipping on a seeded random descendant. + ChildClipping, + /// Toggle visibility on a seeded random descendant. + ChildVisibility, + /// Reorder a seeded random descendant among its siblings. + Reorder, + /// Insert a generated descendant below a seeded random parent. + Insert, + /// Remove a seeded random descendant and its subtree. + Remove, + /// Remove a seeded random childless descendant. Unlike [`Self::Remove`] this changes + /// the element count by exactly one, so it can alternate with [`Self::Insert`] in a + /// long benchmark loop without the tree collapsing or growing. + RemoveLeaf, +} + +impl RandomizedElementTreeMutationKind { + /// Every supported mutation kind, suitable for parameterized tests and benchmarks. + pub const ALL: [Self; 16] = [ + Self::RootColor, + Self::RootOpacity, + Self::RootBorder, + Self::RootBounds, + Self::RootClipping, + Self::RootVisibility, + Self::ChildColor, + Self::ChildOpacity, + Self::ChildBorder, + Self::ChildBounds, + Self::ChildClipping, + Self::ChildVisibility, + Self::Reorder, + Self::Insert, + Self::Remove, + Self::RemoveLeaf, + ]; +} + +/// A deterministic mutation applied to a [`RandomizedElementTree`]. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum RandomizedElementTreeMutation { + /// Changed the root background color. + RootColor, + /// Changed the root opacity. + RootOpacity, + /// Changed the root border. + RootBorder, + /// Changed the root width and height. + RootBounds, + /// Toggled clipping on the root. + RootClipping, + /// Toggled root visibility. + RootVisibility, + /// Changed a descendant's colors. + ChildColor { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Changed a descendant's opacity. + ChildOpacity { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Changed a descendant's border. + ChildBorder { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Changed a descendant's width and height. + ChildBounds { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Toggled clipping on a descendant. + ChildClipping { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Toggled a descendant's visibility. + ChildVisibility { + /// The stable ID of the mutated element. + element_id: u64, + }, + /// Moved an element to a different position among its siblings. + Reordered { + /// The stable ID of the moved element. + element_id: u64, + /// The stable ID of its parent, or `None` for the persistent root. + parent_id: Option, + /// The element's previous position. + old_index: usize, + /// The element's new position. + new_index: usize, + }, + /// Inserted a newly generated element. + Inserted { + /// The stable ID of the inserted element. + element_id: u64, + /// The stable ID of its parent, or `None` for the persistent root. + parent_id: Option, + /// The position of the inserted element. + index: usize, + }, + /// Removed an element and all of its descendants. + Removed { + /// The stable ID of the removed element. + element_id: u64, + /// The stable ID of its parent, or `None` for the persistent root. + parent_id: Option, + /// The former position of the removed element. + index: usize, + /// The total number of elements removed with the subtree. + removed_element_count: usize, + }, +} + +/// Where the elements changed by one frame sit relative to each other. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ChangeLocality { + /// Inside one random entity's subtree, as a user action or one component's state + /// change would be; the change reaches the rest of the tree only if the subtree has + /// fewer elements than are changing (a common ancestor changing). + Localized, + /// Anywhere in the tree, uniformly: the worst case for a renderer that reuses clean + /// subtrees, since every changed element may sit in a different one. + Spread, +} + +/// What [`RandomizedElementTree::recolor_children`] changed. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct RecoloredChildren { + /// Descendants whose background changed. + pub recolored: usize, + /// Entity boundaries (or the root) notified, each once. + pub notified: usize, +} + +/// A persistent root view for randomized GPUI element-tree tests and benchmarks. +pub struct RandomizedElementTree { + snapshot: Rc>, + entities: Rc>, + work_counters: Rc>, + config: RandomizedElementTreeConfig, + rng: StdRng, +} + +impl RandomizedElementTree { + /// Generates a tree with `element_count` descendants and a mutation stream from `seed`. + /// + /// Different seeds deliberately produce wide, deep, mixed, and narrow initial topologies. + pub fn new(seed: u64, element_count: usize) -> Self { + Self::from_config(RandomizedElementTreeConfig::new(seed, element_count)) + } + + /// Generates a configured tree and creates its persistent child entities. + pub fn new_with_config(config: RandomizedElementTreeConfig, cx: &mut Context) -> Self { + let mut tree = Self::from_config(config); + tree.synchronize_entities(cx); + tree + } + + fn from_config(config: RandomizedElementTreeConfig) -> Self { + let mut rng = StdRng::seed_from_u64(config.seed); + let mut children = Vec::new(); + let mut deepest_path = Vec::new(); + + for element_index in 0..config.element_count { + let mut parent_path = match config.topology { + RandomizedElementTreeTopology::Wide => Vec::new(), + RandomizedElementTreeTopology::Deep => deepest_path.clone(), + RandomizedElementTreeTopology::Mixed => random_parent_path(&children, &mut rng), + RandomizedElementTreeTopology::Narrow => { + if rng.random_bool(0.8) { + deepest_path.clone() + } else { + Vec::new() + } + } + }; + let node = RandomizedElementNode::random( + element_index as u64, + config.entity_density, + config.handler_density, + &mut rng, + ); + let (_, inserted_path) = insert_node(&mut children, &mut parent_path, node); + deepest_path = inserted_path; + } + + let mut snapshot = RandomizedElementTreeSnapshot { + root: RandomizedElementStyle::random_root(&mut rng), + children, + next_element_id: config.element_count as u64, + paths_by_element_id: HashMap::default(), + }; + snapshot.rebuild_element_paths(); + + Self { + snapshot: Rc::new(RefCell::new(snapshot)), + entities: Rc::new(RefCell::new(HashMap::default())), + work_counters: Rc::new(RefCell::new(RandomizedElementTreeWorkCounters::default())), + config, + rng, + } + } + + /// Reconstructs a tree from renderable state captured by [`Self::snapshot`]. + pub fn from_snapshot(snapshot: RandomizedElementTreeSnapshot) -> Self { + Self { + config: RandomizedElementTreeConfig::new(0, snapshot.descendant_count()), + snapshot: Rc::new(RefCell::new(snapshot)), + entities: Rc::new(RefCell::new(HashMap::default())), + work_counters: Rc::new(RefCell::new(RandomizedElementTreeWorkCounters::default())), + rng: StdRng::seed_from_u64(0), + } + } + + /// Reconstructs a snapshot while preserving its randomized entity boundaries. + pub fn from_snapshot_with_entities( + snapshot: RandomizedElementTreeSnapshot, + cx: &mut Context, + ) -> Self { + let mut tree = Self::from_snapshot(snapshot); + tree.synchronize_entities(cx); + tree + } + + /// Captures all state that affects rendering and future element IDs. + pub fn snapshot(&self) -> RandomizedElementTreeSnapshot { + self.snapshot.borrow().clone() + } + + /// Clears render work accumulated since construction or the previous reset. + pub fn reset_work_counters(&mut self) { + self.work_counters.borrow_mut().reset(); + } + + /// Returns work accumulated since construction or the previous reset. + pub fn work_counters(&self) -> RandomizedElementTreeWorkCounters { + self.work_counters.borrow().clone() + } + + /// Applies one seeded random style or structural mutation. + /// + /// This does not notify persistent child entities. Entity-aware callers should use + /// [`Self::apply_random_mutation`] from an entity update instead. + pub fn mutate(&mut self) -> RandomizedElementTreeMutation { + let kind = RandomizedElementTreeMutationKind::ALL[self + .rng + .random_range(0..RandomizedElementTreeMutationKind::ALL.len())]; + self.apply_mutation_without_notification(kind).mutation + } + + /// Applies one seeded random mutation and notifies its nearest persistent entity boundary. + pub fn apply_random_mutation( + &mut self, + cx: &mut Context, + ) -> RandomizedElementTreeMutation { + let kind = RandomizedElementTreeMutationKind::ALL[self + .rng + .random_range(0..RandomizedElementTreeMutationKind::ALL.len())]; + self.apply_mutation(kind, cx) + } + + /// Applies a selected mutation kind and notifies its nearest persistent entity boundary. + pub fn apply_mutation( + &mut self, + kind: RandomizedElementTreeMutationKind, + cx: &mut Context, + ) -> RandomizedElementTreeMutation { + let applied = self.apply_mutation_without_notification(kind); + if applied.synchronize_entities { + self.synchronize_entities(cx); + } + self.notify_owner(applied.owner_entity_id, cx); + applied.mutation + } + + /// Generates and inserts an element below a seeded random parent. + /// + /// This does not synchronize or notify persistent child entities. Entity-aware callers should + /// use [`Self::apply_mutation`] with [`RandomizedElementTreeMutationKind::Insert`]. + pub fn insert_child(&mut self) -> RandomizedElementTreeMutation { + self.insert_child_internal().mutation + } + + /// Removes a seeded random element and its subtree. + /// + /// This does not synchronize or notify persistent child entities. Entity-aware callers should + /// use [`Self::apply_mutation`] with [`RandomizedElementTreeMutationKind::Remove`]. + pub fn remove_child(&mut self) -> Option { + self.remove_child_internal(false) + .map(|applied| applied.mutation) + } + + fn apply_mutation_without_notification( + &mut self, + kind: RandomizedElementTreeMutationKind, + ) -> AppliedRandomizedElementTreeMutation { + match kind { + RandomizedElementTreeMutationKind::RootColor => { + self.snapshot.borrow_mut().root.background = random_color(&mut self.rng); + AppliedRandomizedElementTreeMutation::root(RandomizedElementTreeMutation::RootColor) + } + RandomizedElementTreeMutationKind::RootOpacity => { + self.snapshot.borrow_mut().root.opacity = random_opacity(&mut self.rng); + AppliedRandomizedElementTreeMutation::root( + RandomizedElementTreeMutation::RootOpacity, + ) + } + RandomizedElementTreeMutationKind::RootBorder => { + self.snapshot + .borrow_mut() + .root + .randomize_border(&mut self.rng); + AppliedRandomizedElementTreeMutation::root( + RandomizedElementTreeMutation::RootBorder, + ) + } + RandomizedElementTreeMutationKind::RootBounds => { + let mut snapshot = self.snapshot.borrow_mut(); + snapshot.root.width = self.rng.random_range(520.0..980.0); + snapshot.root.height = self.rng.random_range(360.0..760.0); + AppliedRandomizedElementTreeMutation::root( + RandomizedElementTreeMutation::RootBounds, + ) + } + RandomizedElementTreeMutationKind::RootClipping => { + let mut snapshot = self.snapshot.borrow_mut(); + snapshot.root.clipped = !snapshot.root.clipped; + AppliedRandomizedElementTreeMutation::root( + RandomizedElementTreeMutation::RootClipping, + ) + } + RandomizedElementTreeMutationKind::RootVisibility => { + let mut snapshot = self.snapshot.borrow_mut(); + snapshot.root.visible = !snapshot.root.visible; + AppliedRandomizedElementTreeMutation::root( + RandomizedElementTreeMutation::RootVisibility, + ) + } + RandomizedElementTreeMutationKind::ChildColor => { + self.mutate_random_child(RandomizedChildMutation::Color) + } + RandomizedElementTreeMutationKind::ChildOpacity => { + self.mutate_random_child(RandomizedChildMutation::Opacity) + } + RandomizedElementTreeMutationKind::ChildBorder => { + self.mutate_random_child(RandomizedChildMutation::Border) + } + RandomizedElementTreeMutationKind::ChildBounds => { + self.mutate_random_child(RandomizedChildMutation::Bounds) + } + RandomizedElementTreeMutationKind::ChildClipping => { + self.mutate_random_child(RandomizedChildMutation::Clipping) + } + RandomizedElementTreeMutationKind::ChildVisibility => { + self.mutate_random_child(RandomizedChildMutation::Visibility) + } + RandomizedElementTreeMutationKind::Reorder => self.reorder_child(), + RandomizedElementTreeMutationKind::Insert => self.insert_child_internal(), + RandomizedElementTreeMutationKind::Remove => self + .remove_child_internal(false) + .unwrap_or_else(|| self.insert_child_internal()), + RandomizedElementTreeMutationKind::RemoveLeaf => self + .remove_child_internal(true) + .unwrap_or_else(|| self.insert_child_internal()), + } + } + + fn insert_child_internal(&mut self) -> AppliedRandomizedElementTreeMutation { + let mut snapshot = self.snapshot.borrow_mut(); + let element_id = snapshot.next_element_id; + snapshot.next_element_id += 1; + let mut parent_path = random_parent_path(&snapshot.children, &mut self.rng); + let parent_id = node_at_path(&snapshot.children, &parent_path).map(|node| node.id); + let owner_entity_id = nearest_entity_id(&snapshot.children, &parent_path); + let node = RandomizedElementNode::random( + element_id, + self.config.entity_density, + self.config.handler_density, + &mut self.rng, + ); + let (index, _) = insert_node(&mut snapshot.children, &mut parent_path, node); + snapshot.rebuild_element_paths(); + + AppliedRandomizedElementTreeMutation { + mutation: RandomizedElementTreeMutation::Inserted { + element_id, + parent_id, + index, + }, + owner_entity_id, + synchronize_entities: true, + } + } + + fn remove_child_internal( + &mut self, + leaves_only: bool, + ) -> Option { + let mut snapshot = self.snapshot.borrow_mut(); + let path = if leaves_only { + random_leaf_path(&snapshot.children, &mut self.rng)? + } else { + random_node_path(&snapshot.children, &mut self.rng)? + }; + let (index, parent_path) = path.split_last()?; + let parent_id = node_at_path(&snapshot.children, parent_path).map(|node| node.id); + let owner_entity_id = nearest_entity_id(&snapshot.children, parent_path); + let siblings = children_at_path_mut(&mut snapshot.children, parent_path)?; + if *index >= siblings.len() { + return None; + } + + let removed = siblings.remove(*index); + let removed_element_count = removed.element_count(); + let element_id = removed.id; + snapshot.rebuild_element_paths(); + Some(AppliedRandomizedElementTreeMutation { + mutation: RandomizedElementTreeMutation::Removed { + element_id, + parent_id, + index: *index, + removed_element_count, + }, + owner_entity_id, + synchronize_entities: true, + }) + } + + /// Recolors `count` distinct seeded random descendants in one pass and notifies each + /// affected entity boundary once (the root, for descendants owned by no entity). + /// Returns how many descendants changed and how many boundaries were notified. + /// + /// This is the "share of the scene changing per frame" knob: `count` calls to + /// [`Self::apply_mutation`] would each walk the tree and notify separately, costing + /// more than the frame being measured once `count` is a fair share of the tree. + pub fn recolor_children( + &mut self, + count: usize, + locality: ChangeLocality, + cx: &mut Context, + ) -> RecoloredChildren { + let owners = { + let mut snapshot = self.snapshot.borrow_mut(); + let mut paths = node_paths(&snapshot.children); + let count = count.min(paths.len()); + if locality == ChangeLocality::Localized { + // Order the paths so one random entity's subtree comes first: the change + // stays inside that entity unless there is more of it than the subtree. + let entity_paths: Vec<_> = paths + .iter() + .filter(|path| { + node_at_path(&snapshot.children, path).is_some_and(|node| node.is_entity) + }) + .cloned() + .collect(); + if let Some(entity_path) = entity_paths + .get(self.rng.random_range(0..entity_paths.len().max(1))) + .cloned() + { + let (inside, outside): (Vec<_>, Vec<_>) = paths + .into_iter() + .partition(|path| path.starts_with(&entity_path)); + paths = inside; + paths.extend(outside); + } + } + // A partial Fisher–Yates shuffle over the first `count` slots: for `Spread`, a + // uniform sample of the tree; for `Localized`, a uniform sample of the chosen + // subtree, spilling into the rest only once the subtree is exhausted. + let sample_from = match locality { + ChangeLocality::Spread => paths.len(), + ChangeLocality::Localized => count, + }; + for index in 0..count { + let other = self.rng.random_range(index..sample_from.max(index + 1)); + paths.swap(index, other); + } + let mut owners = HashSet::default(); + for path in &paths[..count] { + owners.insert(nearest_entity_id(&snapshot.children, path)); + if let Some(node) = node_at_path_mut(&mut snapshot.children, path) { + node.style.background = random_color(&mut self.rng); + } + } + owners + }; + let notified = owners.len(); + let recolored = count.min(self.snapshot.borrow().descendant_count()); + for owner in owners { + self.notify_owner(owner, cx); + } + RecoloredChildren { + recolored, + notified, + } + } + + fn mutate_random_child( + &mut self, + mutation: RandomizedChildMutation, + ) -> AppliedRandomizedElementTreeMutation { + let mut snapshot = self.snapshot.borrow_mut(); + let Some(path) = random_node_path(&snapshot.children, &mut self.rng) else { + drop(snapshot); + return self.insert_child_internal(); + }; + let owner_entity_id = nearest_entity_id(&snapshot.children, &path); + let Some(node) = node_at_path_mut(&mut snapshot.children, &path) else { + drop(snapshot); + return self.insert_child_internal(); + }; + let element_id = node.id; + + let mutation = match mutation { + RandomizedChildMutation::Color => { + node.style.background = random_color(&mut self.rng); + RandomizedElementTreeMutation::ChildColor { element_id } + } + RandomizedChildMutation::Opacity => { + node.style.opacity = random_opacity(&mut self.rng); + RandomizedElementTreeMutation::ChildOpacity { element_id } + } + RandomizedChildMutation::Border => { + node.style.randomize_border(&mut self.rng); + RandomizedElementTreeMutation::ChildBorder { element_id } + } + RandomizedChildMutation::Bounds => { + node.style.width = self.rng.random_range(36.0..220.0); + node.style.height = self.rng.random_range(28.0..180.0); + RandomizedElementTreeMutation::ChildBounds { element_id } + } + RandomizedChildMutation::Clipping => { + node.style.clipped = !node.style.clipped; + RandomizedElementTreeMutation::ChildClipping { element_id } + } + RandomizedChildMutation::Visibility => { + node.style.visible = !node.style.visible; + RandomizedElementTreeMutation::ChildVisibility { element_id } + } + }; + AppliedRandomizedElementTreeMutation { + mutation, + owner_entity_id, + synchronize_entities: false, + } + } + + fn reorder_child(&mut self) -> AppliedRandomizedElementTreeMutation { + let mut snapshot = self.snapshot.borrow_mut(); + let parent_paths = parent_paths_with_multiple_children(&snapshot.children); + if parent_paths.is_empty() { + drop(snapshot); + return self.insert_child_internal(); + } + + let parent_path_index = self.rng.random_range(0..parent_paths.len()); + let Some(parent_path) = parent_paths.get(parent_path_index) else { + drop(snapshot); + return self.insert_child_internal(); + }; + let parent_id = node_at_path(&snapshot.children, parent_path).map(|node| node.id); + let owner_entity_id = nearest_entity_id(&snapshot.children, parent_path); + let Some(child_count) = + children_at_path(&snapshot.children, parent_path).map(<[RandomizedElementNode]>::len) + else { + drop(snapshot); + return self.insert_child_internal(); + }; + if child_count < 2 { + drop(snapshot); + return self.insert_child_internal(); + } + + let old_index = self.rng.random_range(0..child_count); + let mut new_index = self.rng.random_range(0..child_count - 1); + if new_index >= old_index { + new_index += 1; + } + + let Some(siblings) = children_at_path_mut(&mut snapshot.children, parent_path) else { + drop(snapshot); + return self.insert_child_internal(); + }; + let child = siblings.remove(old_index); + let element_id = child.id; + siblings.insert(new_index, child); + snapshot.rebuild_element_paths(); + AppliedRandomizedElementTreeMutation { + mutation: RandomizedElementTreeMutation::Reordered { + element_id, + parent_id, + old_index, + new_index, + }, + owner_entity_id, + synchronize_entities: false, + } + } + + fn synchronize_entities(&mut self, cx: &mut Context) { + let entity_ids = { + let snapshot = self.snapshot.borrow(); + snapshot + .element_ids() + .into_iter() + .filter(|element_id| { + snapshot + .node(*element_id) + .is_some_and(|node| node.is_entity) + }) + .collect::>() + }; + let entity_id_set = entity_ids.iter().copied().collect::>(); + + self.entities + .borrow_mut() + .retain(|element_id, _| entity_id_set.contains(element_id)); + + let missing_entity_ids = { + let entities = self.entities.borrow(); + entity_ids + .into_iter() + .filter(|element_id| !entities.contains_key(element_id)) + .collect::>() + }; + + let weak_entities = Rc::downgrade(&self.entities); + for element_id in missing_entity_ids { + let entity = cx.new(|_| RandomizedElementEntity { + element_id, + snapshot: self.snapshot.clone(), + entities: weak_entities.clone(), + work_counters: self.work_counters.clone(), + }); + self.entities.borrow_mut().insert(element_id, entity); + } + + let entity_count = self.entities.borrow().len(); + let mut work_counters = self.work_counters.borrow_mut(); + let additional_capacity = + entity_count.saturating_sub(work_counters.rendered_entity_ids.len()); + work_counters + .rendered_entity_ids + .reserve(additional_capacity); + } + + fn notify_owner(&self, owner_entity_id: Option, cx: &mut Context) { + let owner = + owner_entity_id.and_then(|element_id| self.entities.borrow().get(&element_id).cloned()); + if let Some(owner) = owner { + owner.update(cx, |_, cx| cx.notify()); + } else { + cx.notify(); + } + } +} + +impl Render for RandomizedElementTree { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let snapshot = self.snapshot.borrow(); + let root = &snapshot.root; + let entities = self.entities.borrow(); + let mut work_counters = self.work_counters.borrow_mut(); + work_counters.root_render_count += 1; + + div() + .flex() + .when(root.vertical, |element| element.flex_col()) + .when(root.wrap, |element| element.flex_wrap()) + .gap(px(root.gap)) + .p(px(root.padding)) + .w(px(root.width)) + .h(px(root.height)) + .bg(root.background) + .border(px(root.border_width)) + .border_color(root.border_color) + .rounded(px(root.corner_radius)) + .opacity(root.opacity) + .when(root.clipped, |element| element.overflow_hidden()) + .when(!root.visible, |element| element.invisible()) + .children( + snapshot + .children + .iter() + .map(|node| render_node(node, &entities, &mut work_counters)), + ) + } +} + +type RandomizedElementEntities = HashMap>; + +struct RandomizedElementEntity { + element_id: u64, + snapshot: Rc>, + entities: Weak>, + work_counters: Rc>, +} + +impl Render for RandomizedElementEntity { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let snapshot = self.snapshot.borrow(); + let entities = self.entities.upgrade(); + let entities = entities.as_ref().map(|entities| entities.borrow()); + let mut work_counters = self.work_counters.borrow_mut(); + work_counters.entity_render_count += 1; + work_counters.rendered_entity_ids.push(self.element_id); + + snapshot + .node(self.element_id) + .map(|node| render_node_body(node, entities.as_deref(), &mut work_counters)) + .unwrap_or_else(|| div().into_any_element()) + } +} + +struct AppliedRandomizedElementTreeMutation { + mutation: RandomizedElementTreeMutation, + owner_entity_id: Option, + synchronize_entities: bool, +} + +impl AppliedRandomizedElementTreeMutation { + fn root(mutation: RandomizedElementTreeMutation) -> Self { + Self { + mutation, + owner_entity_id: None, + synchronize_entities: false, + } + } +} + +#[derive(Clone, Debug, PartialEq)] +struct RandomizedElementNode { + id: u64, + style: RandomizedElementStyle, + is_entity: bool, + features: RandomizedElementFeatures, + children: Vec, +} + +impl RandomizedElementNode { + fn random(id: u64, entity_density: f64, handler_density: f64, rng: &mut StdRng) -> Self { + Self { + id, + style: RandomizedElementStyle::random_child(rng), + is_entity: rng.random_bool(entity_density), + features: RandomizedElementFeatures::random(handler_density, rng), + children: Vec::new(), + } + } + + fn element_count(&self) -> usize { + let mut count = 0; + let mut stack = vec![self]; + while let Some(node) = stack.pop() { + count += 1; + stack.extend(node.children.iter()); + } + count + } +} + +#[derive(Clone, Debug, PartialEq)] +struct RandomizedElementFeatures { + action_handler: bool, + click_handler: bool, + key_context: bool, +} + +impl RandomizedElementFeatures { + fn random(handler_density: f64, rng: &mut StdRng) -> Self { + Self { + action_handler: rng.random_bool(handler_density), + click_handler: rng.random_bool(handler_density), + key_context: rng.random_bool(handler_density), + } + } + + fn handler_count(&self) -> usize { + usize::from(self.action_handler) + usize::from(self.click_handler) + } +} + +#[derive(Clone, Debug, PartialEq)] +struct RandomizedElementStyle { + background: Hsla, + border_color: Hsla, + opacity: f32, + border_width: f32, + corner_radius: f32, + width: f32, + height: f32, + padding: f32, + gap: f32, + clipped: bool, + visible: bool, + vertical: bool, + wrap: bool, +} + +impl RandomizedElementStyle { + fn random_root(rng: &mut StdRng) -> Self { + Self { + background: random_color(rng), + border_color: random_color(rng), + opacity: random_opacity(rng), + border_width: rng.random_range(0.0..4.0), + corner_radius: rng.random_range(0.0..18.0), + width: rng.random_range(520.0..980.0), + height: rng.random_range(360.0..760.0), + padding: rng.random_range(4.0..18.0), + gap: rng.random_range(2.0..14.0), + clipped: rng.random_bool(0.5), + visible: true, + vertical: rng.random_bool(0.5), + wrap: rng.random_bool(0.7), + } + } + + fn random_child(rng: &mut StdRng) -> Self { + Self { + background: random_color(rng), + border_color: random_color(rng), + opacity: random_opacity(rng), + border_width: rng.random_range(0.0..4.0), + corner_radius: rng.random_range(0.0..14.0), + width: rng.random_range(36.0..220.0), + height: rng.random_range(28.0..180.0), + padding: rng.random_range(1.0..10.0), + gap: rng.random_range(1.0..8.0), + clipped: rng.random_bool(0.3), + visible: rng.random_bool(0.9), + vertical: rng.random_bool(0.5), + wrap: rng.random_bool(0.4), + } + } + + fn randomize_border(&mut self, rng: &mut StdRng) { + self.border_color = random_color(rng); + self.border_width = rng.random_range(0.0..5.0); + self.corner_radius = rng.random_range(0.0..18.0); + } +} + +#[derive(Clone, Copy)] +enum RandomizedChildMutation { + Color, + Opacity, + Border, + Bounds, + Clipping, + Visibility, +} + +#[cfg_attr(feature = "stacker", stacksafe::stacksafe)] +fn render_node( + node: &RandomizedElementNode, + entities: &RandomizedElementEntities, + work_counters: &mut RandomizedElementTreeWorkCounters, +) -> AnyElement { + if node.is_entity + && let Some(entity) = entities.get(&node.id) + { + return entity.clone().into_any_element(); + } + + render_node_body(node, Some(entities), work_counters) +} + +#[cfg_attr(feature = "stacker", stacksafe::stacksafe)] +fn render_node_body( + node: &RandomizedElementNode, + entities: Option<&RandomizedElementEntities>, + work_counters: &mut RandomizedElementTreeWorkCounters, +) -> AnyElement { + work_counters.element_render_count += 1; + work_counters.handler_registration_count += node.features.handler_count(); + let style = &node.style; + div() + .id(ElementId::NamedInteger( + "randomized-element".into(), + node.id, + )) + .flex() + .when(style.vertical, |element| element.flex_col()) + .when(style.wrap, |element| element.flex_wrap()) + .gap(px(style.gap)) + .p(px(style.padding)) + .w(px(style.width)) + .h(px(style.height)) + .bg(style.background) + .border(px(style.border_width)) + .border_color(style.border_color) + .rounded(px(style.corner_radius)) + .opacity(style.opacity) + .when(style.clipped, |element| element.overflow_hidden()) + .when(!style.visible, |element| element.invisible()) + .when(node.features.action_handler, |element| { + element.on_action(|_: &RandomizedElementTreeAction, _window, _cx| {}) + }) + .when(node.features.click_handler, |element| { + element.on_click(|_event, _window, _cx| {}) + }) + .when(node.features.key_context, |element| { + element.key_context("RandomizedElementTree") + }) + .children(node.children.iter().map(|child| { + if let Some(entities) = entities { + render_node(child, entities, work_counters) + } else { + render_node_body(child, None, work_counters) + } + })) + .into_any_element() +} + +fn insert_node( + root_children: &mut Vec, + parent_path: &mut Vec, + node: RandomizedElementNode, +) -> (usize, Vec) { + let Some(children) = children_at_path_mut(root_children, parent_path) else { + parent_path.clear(); + let index = root_children.len(); + root_children.push(node); + return (index, vec![index]); + }; + + let index = children.len(); + children.push(node); + let mut inserted_path = parent_path.clone(); + inserted_path.push(index); + (index, inserted_path) +} + +fn random_parent_path(root_children: &[RandomizedElementNode], rng: &mut StdRng) -> Vec { + let paths = node_paths(root_children); + let index = rng.random_range(0..=paths.len()); + paths.get(index).cloned().unwrap_or_default() +} + +fn random_node_path( + root_children: &[RandomizedElementNode], + rng: &mut StdRng, +) -> Option> { + let paths = node_paths(root_children); + if paths.is_empty() { + None + } else { + paths.get(rng.random_range(0..paths.len())).cloned() + } +} + +fn random_leaf_path( + root_children: &[RandomizedElementNode], + rng: &mut StdRng, +) -> Option> { + let leaves = node_paths(root_children) + .into_iter() + .filter(|path| { + node_at_path(root_children, path).is_some_and(|node| node.children.is_empty()) + }) + .collect::>(); + if leaves.is_empty() { + None + } else { + leaves.get(rng.random_range(0..leaves.len())).cloned() + } +} + +fn parent_paths_with_multiple_children(root_children: &[RandomizedElementNode]) -> Vec> { + let mut parent_paths = Vec::new(); + if root_children.len() >= 2 { + parent_paths.push(Vec::new()); + } + parent_paths.extend(node_paths(root_children).into_iter().filter(|path| { + node_at_path(root_children, path).is_some_and(|node| node.children.len() >= 2) + })); + parent_paths +} + +fn node_paths(root_children: &[RandomizedElementNode]) -> Vec> { + let mut paths = Vec::new(); + let mut stack = root_children + .iter() + .enumerate() + .rev() + .map(|(index, node)| (vec![index], node)) + .collect::>(); + + while let Some((path, node)) = stack.pop() { + for (index, child) in node.children.iter().enumerate().rev() { + let mut child_path = path.clone(); + child_path.push(index); + stack.push((child_path, child)); + } + paths.push(path); + } + paths +} + +fn node_at_path<'a>( + root_children: &'a [RandomizedElementNode], + path: &[usize], +) -> Option<&'a RandomizedElementNode> { + let (index, parent_path) = path.split_last()?; + children_at_path(root_children, parent_path)?.get(*index) +} + +fn node_at_path_mut<'a>( + root_children: &'a mut Vec, + path: &[usize], +) -> Option<&'a mut RandomizedElementNode> { + let (index, parent_path) = path.split_last()?; + children_at_path_mut(root_children, parent_path)?.get_mut(*index) +} + +fn children_at_path<'a>( + mut children: &'a [RandomizedElementNode], + path: &[usize], +) -> Option<&'a [RandomizedElementNode]> { + for index in path { + children = &children.get(*index)?.children; + } + Some(children) +} + +fn children_at_path_mut<'a>( + mut children: &'a mut Vec, + path: &[usize], +) -> Option<&'a mut Vec> { + for index in path { + children = &mut children.get_mut(*index)?.children; + } + Some(children) +} + +fn nearest_entity_id(root_children: &[RandomizedElementNode], path: &[usize]) -> Option { + let mut children = root_children; + let mut nearest_entity_id = None; + for index in path { + let node = children.get(*index)?; + if node.is_entity { + nearest_entity_id = Some(node.id); + } + children = &node.children; + } + nearest_entity_id +} + +fn normalized_density(density: f64) -> f64 { + if density.is_nan() { + 0.0 + } else { + density.clamp(0.0, 1.0) + } +} + +fn random_color(rng: &mut StdRng) -> Hsla { + Hsla { + h: rng.random_range(0.0..1.0), + s: rng.random_range(0.25..0.9), + l: rng.random_range(0.18..0.82), + a: 1.0, + } +} + +fn random_opacity(rng: &mut StdRng) -> f32 { + rng.random_range(0.25..1.0) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AnyWindowHandle, Background, BorderStyle, Bounds, ContentMask, Corners, Edges, Pixels, + ScaledPixels, Size, TestAppContext, size, + }; + use proptest::prelude::*; + use std::collections::BTreeSet; + + const ELEMENT_COUNT: usize = 64; + const MUTATION_COUNT: usize = 32; + const WINDOW_SIZE: Size = size(px(1200.0), px(900.0)); + + #[derive(Debug, PartialEq)] + struct SceneSnapshot { + quads: Vec, + element_ids: BTreeSet, + } + + impl SceneSnapshot { + fn from_window(window: &Window) -> Self { + Self { + quads: window + .rendered_frame + .scene + .quads + .iter() + .map(QuadSnapshot::from) + .collect(), + element_ids: window + .rendered_frame + .element_states + .keys() + .filter_map(|(global_id, _)| { + let ElementId::NamedInteger(name, element_id) = global_id.0.last()? else { + return None; + }; + (name.as_ref() == "randomized-element").then_some(*element_id) + }) + .collect(), + } + } + } + + #[derive(Debug, PartialEq)] + struct QuadSnapshot { + order: u32, + border_style: BorderStyle, + bounds: Bounds, + content_mask: ContentMask, + background: Background, + border_color: Hsla, + corner_radii: Corners, + border_widths: Edges, + } + + impl From<&crate::Quad> for QuadSnapshot { + fn from(quad: &crate::Quad) -> Self { + Self { + order: quad.order, + border_style: quad.border_style, + bounds: quad.bounds, + content_mask: quad.content_mask, + background: quad.background, + border_color: quad.border_color, + corner_radii: quad.corner_radii, + border_widths: quad.border_widths, + } + } + } + + #[gpui::test] + fn localized_recoloring_notifies_one_entity_until_its_subtree_is_exhausted( + cx: &mut TestAppContext, + ) { + // Wide: every element is a root child, so every entity's subtree is exactly one + // element and localized change of k elements must touch k boundaries only when it + // spills; a mixed tree has larger subtrees to stay inside. + let config = RandomizedElementTreeConfig::new(11, 200) + .with_topology(RandomizedElementTreeTopology::Mixed) + .with_entity_density(0.1); + let window = cx.open_window(WINDOW_SIZE, move |_, cx| { + RandomizedElementTree::new_with_config(config, cx) + }); + let root = window.root(cx).expect("window has a root"); + let (localized, spread) = root.update(cx, |tree, cx| { + let localized = tree.recolor_children(20, ChangeLocality::Localized, cx); + let spread = tree.recolor_children(20, ChangeLocality::Spread, cx); + (localized, spread) + }); + assert_eq!(localized.recolored, 20); + assert_eq!(spread.recolored, 20); + assert!( + localized.notified <= spread.notified, + "localized change touches no more boundaries than spread change: {localized:?} vs {spread:?}" + ); + assert!(localized.notified >= 1); + } + + #[test] + fn bounds_sample_within_range_and_reproduce_from_the_seed() { + let bounds = RandomizedElementTreeBounds::new(32..=256) + .with_topologies([ + RandomizedElementTreeTopology::Deep, + RandomizedElementTreeTopology::Narrow, + ]) + .with_entity_density(0.1..=0.5) + .with_handler_density(0.25..=0.25); + let mut topologies = BTreeSet::new(); + let sample = |seed| bounds.sample(&mut StdRng::seed_from_u64(seed)); + for seed in 0..64 { + let config = sample(seed); + assert!((32..=256).contains(&config.element_count()), "{config:?}"); + assert!(config.topology().is_tall(), "{config:?}"); + assert!((0.1..=0.5).contains(&config.entity_density()), "{config:?}"); + assert_eq!(config.handler_density(), 0.25); + assert_eq!(sample(seed), config, "a seed draws the same config twice"); + topologies.insert(format!("{:?}", config.topology())); + } + assert_eq!(topologies.len(), 2, "64 seeds pick both allowed topologies"); + assert_ne!(sample(0), sample(1)); + } + + #[test] + fn generated_topologies_include_wide_deep_narrow_and_empty_trees() { + let wide = RandomizedElementTree::new(0, ELEMENT_COUNT).snapshot(); + assert_eq!(wide.children.len(), ELEMENT_COUNT); + assert_eq!(wide.max_depth(), 1); + + let deep = RandomizedElementTree::new(1, ELEMENT_COUNT).snapshot(); + assert_eq!(deep.children.len(), 1); + assert_eq!(deep.max_depth(), ELEMENT_COUNT); + + let narrow = RandomizedElementTree::new(3, ELEMENT_COUNT).snapshot(); + assert_eq!(narrow.descendant_count(), ELEMENT_COUNT); + assert!(narrow.max_depth() > 1); + + let empty = RandomizedElementTree::new(2, 0).snapshot(); + assert_eq!(empty.descendant_count(), 0); + assert_eq!(empty.max_depth(), 0); + } + + #[test] + fn randomized_element_ids_are_unique_and_stable() { + let mut tree = RandomizedElementTree::new(0, ELEMENT_COUNT); + let initial_ids = tree.snapshot().element_ids(); + assert_eq!(initial_ids.len(), ELEMENT_COUNT); + assert_eq!( + initial_ids.iter().copied().collect::>().len(), + ELEMENT_COUNT + ); + + for mutation in [ + RandomizedChildMutation::Color, + RandomizedChildMutation::Opacity, + RandomizedChildMutation::Border, + RandomizedChildMutation::Bounds, + RandomizedChildMutation::Clipping, + RandomizedChildMutation::Visibility, + ] { + tree.mutate_random_child(mutation); + assert_eq!(tree.snapshot().element_ids(), initial_ids); + } + + tree.reorder_child(); + let reordered_ids = tree.snapshot().element_ids(); + assert_eq!( + reordered_ids.iter().copied().collect::>(), + initial_ids.iter().copied().collect() + ); + + tree.insert_child(); + let inserted_ids = tree.snapshot().element_ids(); + let inserted_id_set = inserted_ids.iter().copied().collect::>(); + assert_eq!(inserted_ids.len(), ELEMENT_COUNT + 1); + assert!(initial_ids.iter().all(|id| inserted_id_set.contains(id))); + + tree.remove_child(); + let remaining_ids = tree.snapshot().element_ids(); + assert_eq!( + remaining_ids.iter().copied().collect::>().len(), + remaining_ids.len() + ); + assert!(remaining_ids.iter().all(|id| inserted_id_set.contains(id))); + } + + #[gpui::test] + fn randomized_entities_and_work_counters_support_incremental_benchmarks( + cx: &mut TestAppContext, + ) { + let config = RandomizedElementTreeConfig::new(0, 16) + .with_topology(RandomizedElementTreeTopology::Wide) + .with_entity_density(1.0) + .with_handler_density(1.0); + let window = cx.open_window(WINDOW_SIZE, move |_, cx| { + RandomizedElementTree::new_with_config(config, cx) + }); + let root = window + .root(cx) + .expect("randomized tree window should have a root"); + let window = AnyWindowHandle::from(window); + + draw_window(window, cx); + let initial_counters = root.read_with(cx, |tree, _| tree.work_counters()); + assert!(initial_counters.root_render_count() >= 1); + assert!(initial_counters.entity_render_count() >= 16); + assert!(initial_counters.element_render_count() >= 16); + assert!(initial_counters.handler_registration_count() >= 32); + + let mutation = root.update(cx, |tree, cx| { + tree.reset_work_counters(); + tree.apply_mutation(RandomizedElementTreeMutationKind::ChildColor, cx) + }); + let RandomizedElementTreeMutation::ChildColor { element_id } = mutation else { + panic!("a nonempty tree should apply the requested child-color mutation"); + }; + draw_window(window, cx); + + let incremental_counters = root.read_with(cx, |tree, _| tree.work_counters()); + assert!(incremental_counters.root_render_count() >= 1); + assert!(incremental_counters.entity_render_count() >= 1); + assert!(incremental_counters.element_render_count() >= 1); + assert!(incremental_counters.handler_registration_count() >= 2); + assert!( + incremental_counters + .rendered_entity_ids() + .contains(&element_id) + ); + + cx.update_window(window, |_, window, _| window.remove_window()) + .expect("randomized tree window should remain open until the case completes"); + } + + #[gpui::property_test(config = ProptestConfig { + cases: 4, + ..Default::default() + })] + fn randomized_element_tree_matches_full_render(cx: &mut TestAppContext, seed: u64) { + for topology in 0..4 { + let topology_seed = (seed & !3) | topology; + let config = RandomizedElementTreeConfig::new(topology_seed, ELEMENT_COUNT) + .with_entity_density(0.2) + .with_handler_density(0.2); + run_render_equivalence_case(cx, config); + } + run_render_equivalence_case( + cx, + RandomizedElementTreeConfig::new(seed, 0) + .with_entity_density(0.2) + .with_handler_density(0.2), + ); + } + + fn run_render_equivalence_case(cx: &mut TestAppContext, config: RandomizedElementTreeConfig) { + let persistent_window = cx.open_window(WINDOW_SIZE, move |_, cx| { + RandomizedElementTree::new_with_config(config, cx) + }); + let persistent_root = persistent_window + .root(cx) + .expect("randomized tree window should have a root"); + let persistent_window = AnyWindowHandle::from(persistent_window); + + assert_matches_reference(&persistent_root, persistent_window, cx, config, None); + + for mutation_index in 0..MUTATION_COUNT { + let mutation = persistent_root.update(cx, |tree, cx| match mutation_index { + 0 => tree.apply_mutation(RandomizedElementTreeMutationKind::Insert, cx), + 1 => tree.apply_mutation(RandomizedElementTreeMutationKind::Remove, cx), + _ => tree.apply_random_mutation(cx), + }); + + assert_matches_reference( + &persistent_root, + persistent_window, + cx, + config, + Some((mutation_index, mutation)), + ); + } + + cx.update_window(persistent_window, |_, window, _| window.remove_window()) + .expect("persistent window should remain open until the case completes"); + } + + fn assert_matches_reference( + persistent_root: &crate::Entity, + persistent_window: AnyWindowHandle, + cx: &mut TestAppContext, + config: RandomizedElementTreeConfig, + mutation: Option<(usize, RandomizedElementTreeMutation)>, + ) { + let snapshot = persistent_root.read_with(cx, |tree, _| tree.snapshot()); + let expected_element_ids = snapshot.element_ids().into_iter().collect::>(); + let persistent_scene = draw_window(persistent_window, cx); + assert_eq!( + persistent_scene.element_ids, expected_element_ids, + "persistent frame element IDs diverged from the model for config {config:?}, after \ + mutation {mutation:?}" + ); + let reference_scene = draw_fresh_reference(snapshot, cx); + + assert_eq!( + persistent_scene, reference_scene, + "rendered scene diverged for config {config:?}, after mutation {mutation:?}" + ); + } + + fn draw_fresh_reference( + snapshot: RandomizedElementTreeSnapshot, + cx: &mut TestAppContext, + ) -> SceneSnapshot { + let reference_window = cx.open_window(WINDOW_SIZE, move |_, cx| { + RandomizedElementTree::from_snapshot_with_entities(snapshot, cx) + }); + let reference_window = AnyWindowHandle::from(reference_window); + let scene = draw_window(reference_window, cx); + cx.update_window(reference_window, |_, window, _| window.remove_window()) + .expect("reference window should remain open until its frame is captured"); + scene + } + + fn draw_window(window: AnyWindowHandle, cx: &mut TestAppContext) -> SceneSnapshot { + cx.update_window(window, |_, window, cx| { + let arena_clear_needed = window.draw(cx); + let scene = SceneSnapshot::from_window(window); + arena_clear_needed.clear(cx); + scene + }) + .expect("randomized element tree window should remain open while drawing") + } +} diff --git a/vendor/gpui-pre/src/scene.rs b/vendor/gpui-pre/src/scene.rs new file mode 100644 index 00000000..160587a4 --- /dev/null +++ b/vendor/gpui-pre/src/scene.rs @@ -0,0 +1,949 @@ +// todo("windows"): remove +#![cfg_attr(windows, allow(dead_code))] + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + AtlasTextureId, AtlasTile, Background, Bounds, ContentMask, Corners, Edges, Hsla, Pixels, + Point, Radians, ScaledPixels, Size, bounds_tree::BoundsTree, point, +}; +use std::{ + fmt::Debug, + iter::Peekable, + ops::{Add, Range, Sub}, + slice, +}; + +#[allow(non_camel_case_types, unused)] +#[expect(missing_docs)] +pub type PathVertex_ScaledPixels = PathVertex; + +#[expect(missing_docs)] +pub type DrawOrder = u32; + +/// A boolean stored as a `u32` so that GPU-facing structs contain no +/// compiler-inserted padding bytes, which would be undefined behavior to +/// reinterpret as `&[u8]` when writing instance buffers. Guaranteed to be +/// `0` or `1` by construction; shaders read it as a `u32`/`uint`. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +#[repr(transparent)] +pub struct PaddedBool32(u32); + +impl From for PaddedBool32 { + fn from(value: bool) -> Self { + PaddedBool32(value as u32) + } +} + +#[derive(Default)] +#[expect(missing_docs)] +pub struct Scene { + pub(crate) paint_operations: Vec, + primitive_bounds: BoundsTree, + layer_stack: Vec, + pub shadows: Vec, + pub quads: Vec, + pub paths: Vec>, + pub underlines: Vec, + pub monochrome_sprites: Vec, + pub subpixel_sprites: Vec, + pub polychrome_sprites: Vec, + pub surfaces: Vec, +} + +#[expect(missing_docs)] +impl Scene { + pub fn clear(&mut self) { + self.paint_operations.clear(); + self.primitive_bounds.clear(); + self.layer_stack.clear(); + self.paths.clear(); + self.shadows.clear(); + self.quads.clear(); + self.underlines.clear(); + self.monochrome_sprites.clear(); + self.subpixel_sprites.clear(); + self.polychrome_sprites.clear(); + self.surfaces.clear(); + } + + pub fn len(&self) -> usize { + self.paint_operations.len() + } + + pub fn push_layer(&mut self, bounds: Bounds) { + let order = self.primitive_bounds.insert(bounds); + self.layer_stack.push(order); + self.paint_operations + .push(PaintOperation::StartLayer(bounds)); + } + + pub fn pop_layer(&mut self) { + self.layer_stack.pop(); + self.paint_operations.push(PaintOperation::EndLayer); + } + + pub fn insert_primitive(&mut self, primitive: impl Into) { + let mut primitive = primitive.into(); + let clipped_bounds = primitive + .bounds() + .intersect(&primitive.content_mask().bounds); + + if clipped_bounds.is_empty() { + return; + } + + let order = self + .layer_stack + .last() + .copied() + .unwrap_or_else(|| self.primitive_bounds.insert(clipped_bounds)); + match &mut primitive { + Primitive::Shadow(shadow) => { + shadow.order = order; + self.shadows.push(*shadow); + } + Primitive::Quad(quad) => { + quad.order = order; + self.quads.push(*quad); + } + Primitive::Path(path) => { + path.order = order; + path.id = PathId(self.paths.len()); + self.paths.push(path.clone()); + } + Primitive::Underline(underline) => { + underline.order = order; + self.underlines.push(*underline); + } + Primitive::MonochromeSprite(sprite) => { + sprite.order = order; + self.monochrome_sprites.push(*sprite); + } + Primitive::SubpixelSprite(sprite) => { + sprite.order = order; + self.subpixel_sprites.push(*sprite); + } + Primitive::PolychromeSprite(sprite) => { + sprite.order = order; + self.polychrome_sprites.push(*sprite); + } + Primitive::Surface(surface) => { + surface.order = order; + self.surfaces.push(surface.clone()); + } + } + self.paint_operations + .push(PaintOperation::Primitive(primitive)); + } + + pub fn replay(&mut self, range: Range, prev_scene: &Scene) { + for operation in &prev_scene.paint_operations[range] { + match operation { + PaintOperation::Primitive(primitive) => self.insert_primitive(primitive.clone()), + PaintOperation::StartLayer(bounds) => self.push_layer(*bounds), + PaintOperation::EndLayer => self.pop_layer(), + } + } + } + + pub fn finish(&mut self) { + self.shadows.sort_by_key(|shadow| shadow.order); + self.quads.sort_by_key(|quad| quad.order); + self.paths.sort_by_key(|path| path.order); + self.underlines.sort_by_key(|underline| underline.order); + self.monochrome_sprites + .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id)); + self.subpixel_sprites + .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id)); + self.polychrome_sprites + .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id)); + self.surfaces.sort_by_key(|surface| surface.order); + } + + #[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) + )] + pub fn batches(&self) -> impl Iterator + '_ { + BatchIterator { + shadows_start: 0, + shadows_iter: self.shadows.iter().peekable(), + quads_start: 0, + quads_iter: self.quads.iter().peekable(), + paths_start: 0, + paths_iter: self.paths.iter().peekable(), + underlines_start: 0, + underlines_iter: self.underlines.iter().peekable(), + monochrome_sprites_start: 0, + monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(), + subpixel_sprites_start: 0, + subpixel_sprites_iter: self.subpixel_sprites.iter().peekable(), + polychrome_sprites_start: 0, + polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(), + surfaces_start: 0, + surfaces_iter: self.surfaces.iter().peekable(), + } + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)] +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +pub(crate) enum PrimitiveKind { + Shadow, + #[default] + Quad, + Path, + Underline, + MonochromeSprite, + SubpixelSprite, + PolychromeSprite, + Surface, +} + +pub(crate) enum PaintOperation { + Primitive(Primitive), + StartLayer(Bounds), + EndLayer, +} + +#[derive(Clone)] +#[expect(missing_docs)] +pub enum Primitive { + Shadow(Shadow), + Quad(Quad), + Path(Path), + Underline(Underline), + MonochromeSprite(MonochromeSprite), + SubpixelSprite(SubpixelSprite), + PolychromeSprite(PolychromeSprite), + Surface(PaintSurface), +} + +#[expect(missing_docs)] +impl Primitive { + pub fn bounds(&self) -> &Bounds { + match self { + Primitive::Shadow(shadow) => &shadow.bounds, + Primitive::Quad(quad) => &quad.bounds, + Primitive::Path(path) => &path.bounds, + Primitive::Underline(underline) => &underline.bounds, + Primitive::MonochromeSprite(sprite) => &sprite.bounds, + Primitive::SubpixelSprite(sprite) => &sprite.bounds, + Primitive::PolychromeSprite(sprite) => &sprite.bounds, + Primitive::Surface(surface) => &surface.bounds, + } + } + + pub fn content_mask(&self) -> &ContentMask { + match self { + Primitive::Shadow(shadow) => &shadow.content_mask, + Primitive::Quad(quad) => &quad.content_mask, + Primitive::Path(path) => &path.content_mask, + Primitive::Underline(underline) => &underline.content_mask, + Primitive::MonochromeSprite(sprite) => &sprite.content_mask, + Primitive::SubpixelSprite(sprite) => &sprite.content_mask, + Primitive::PolychromeSprite(sprite) => &sprite.content_mask, + Primitive::Surface(surface) => &surface.content_mask, + } + } +} + +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +struct BatchIterator<'a> { + shadows_start: usize, + shadows_iter: Peekable>, + quads_start: usize, + quads_iter: Peekable>, + paths_start: usize, + paths_iter: Peekable>>, + underlines_start: usize, + underlines_iter: Peekable>, + monochrome_sprites_start: usize, + monochrome_sprites_iter: Peekable>, + subpixel_sprites_start: usize, + subpixel_sprites_iter: Peekable>, + polychrome_sprites_start: usize, + polychrome_sprites_iter: Peekable>, + surfaces_start: usize, + surfaces_iter: Peekable>, +} + +impl<'a> Iterator for BatchIterator<'a> { + type Item = PrimitiveBatch; + + fn next(&mut self) -> Option { + let mut orders_and_kinds = [ + ( + self.shadows_iter.peek().map(|s| s.order), + PrimitiveKind::Shadow, + ), + (self.quads_iter.peek().map(|q| q.order), PrimitiveKind::Quad), + (self.paths_iter.peek().map(|q| q.order), PrimitiveKind::Path), + ( + self.underlines_iter.peek().map(|u| u.order), + PrimitiveKind::Underline, + ), + ( + self.monochrome_sprites_iter.peek().map(|s| s.order), + PrimitiveKind::MonochromeSprite, + ), + ( + self.subpixel_sprites_iter.peek().map(|s| s.order), + PrimitiveKind::SubpixelSprite, + ), + ( + self.polychrome_sprites_iter.peek().map(|s| s.order), + PrimitiveKind::PolychromeSprite, + ), + ( + self.surfaces_iter.peek().map(|s| s.order), + PrimitiveKind::Surface, + ), + ]; + orders_and_kinds.sort_by_key(|(order, kind)| (order.unwrap_or(u32::MAX), *kind)); + + let first = orders_and_kinds[0]; + let second = orders_and_kinds[1]; + let (batch_kind, max_order_and_kind) = if first.0.is_some() { + (first.1, (second.0.unwrap_or(u32::MAX), second.1)) + } else { + return None; + }; + + match batch_kind { + PrimitiveKind::Shadow => { + let shadows_start = self.shadows_start; + let mut shadows_end = shadows_start + 1; + self.shadows_iter.next(); + while self + .shadows_iter + .next_if(|shadow| (shadow.order, batch_kind) < max_order_and_kind) + .is_some() + { + shadows_end += 1; + } + self.shadows_start = shadows_end; + Some(PrimitiveBatch::Shadows(shadows_start..shadows_end)) + } + PrimitiveKind::Quad => { + let quads_start = self.quads_start; + let mut quads_end = quads_start + 1; + self.quads_iter.next(); + while self + .quads_iter + .next_if(|quad| (quad.order, batch_kind) < max_order_and_kind) + .is_some() + { + quads_end += 1; + } + self.quads_start = quads_end; + Some(PrimitiveBatch::Quads(quads_start..quads_end)) + } + PrimitiveKind::Path => { + let paths_start = self.paths_start; + let mut paths_end = paths_start + 1; + self.paths_iter.next(); + while self + .paths_iter + .next_if(|path| (path.order, batch_kind) < max_order_and_kind) + .is_some() + { + paths_end += 1; + } + self.paths_start = paths_end; + Some(PrimitiveBatch::Paths(paths_start..paths_end)) + } + PrimitiveKind::Underline => { + let underlines_start = self.underlines_start; + let mut underlines_end = underlines_start + 1; + self.underlines_iter.next(); + while self + .underlines_iter + .next_if(|underline| (underline.order, batch_kind) < max_order_and_kind) + .is_some() + { + underlines_end += 1; + } + self.underlines_start = underlines_end; + Some(PrimitiveBatch::Underlines(underlines_start..underlines_end)) + } + PrimitiveKind::MonochromeSprite => { + let texture_id = self.monochrome_sprites_iter.peek().unwrap().tile.texture_id; + let sprites_start = self.monochrome_sprites_start; + let mut sprites_end = sprites_start + 1; + self.monochrome_sprites_iter.next(); + while self + .monochrome_sprites_iter + .next_if(|sprite| { + (sprite.order, batch_kind) < max_order_and_kind + && sprite.tile.texture_id == texture_id + }) + .is_some() + { + sprites_end += 1; + } + self.monochrome_sprites_start = sprites_end; + Some(PrimitiveBatch::MonochromeSprites { + texture_id, + range: sprites_start..sprites_end, + }) + } + PrimitiveKind::SubpixelSprite => { + let texture_id = self.subpixel_sprites_iter.peek().unwrap().tile.texture_id; + let sprites_start = self.subpixel_sprites_start; + let mut sprites_end = sprites_start + 1; + self.subpixel_sprites_iter.next(); + while self + .subpixel_sprites_iter + .next_if(|sprite| { + (sprite.order, batch_kind) < max_order_and_kind + && sprite.tile.texture_id == texture_id + }) + .is_some() + { + sprites_end += 1; + } + self.subpixel_sprites_start = sprites_end; + Some(PrimitiveBatch::SubpixelSprites { + texture_id, + range: sprites_start..sprites_end, + }) + } + PrimitiveKind::PolychromeSprite => { + let texture_id = self.polychrome_sprites_iter.peek().unwrap().tile.texture_id; + let sprites_start = self.polychrome_sprites_start; + let mut sprites_end = sprites_start + 1; + self.polychrome_sprites_iter.next(); + while self + .polychrome_sprites_iter + .next_if(|sprite| { + (sprite.order, batch_kind) < max_order_and_kind + && sprite.tile.texture_id == texture_id + }) + .is_some() + { + sprites_end += 1; + } + self.polychrome_sprites_start = sprites_end; + Some(PrimitiveBatch::PolychromeSprites { + texture_id, + range: sprites_start..sprites_end, + }) + } + PrimitiveKind::Surface => { + let surfaces_start = self.surfaces_start; + let mut surfaces_end = surfaces_start + 1; + self.surfaces_iter.next(); + while self + .surfaces_iter + .next_if(|surface| (surface.order, batch_kind) < max_order_and_kind) + .is_some() + { + surfaces_end += 1; + } + self.surfaces_start = surfaces_end; + Some(PrimitiveBatch::Surfaces(surfaces_start..surfaces_end)) + } + } + } +} + +#[derive(Debug)] +#[cfg_attr( + all( + any(target_os = "linux", target_os = "freebsd"), + not(any(feature = "x11", feature = "wayland")) + ), + allow(dead_code) +)] +#[allow(missing_docs)] +pub enum PrimitiveBatch { + Shadows(Range), + Quads(Range), + Paths(Range), + Underlines(Range), + MonochromeSprites { + texture_id: AtlasTextureId, + range: Range, + }, + #[cfg_attr(target_os = "macos", allow(dead_code))] + SubpixelSprites { + texture_id: AtlasTextureId, + range: Range, + }, + PolychromeSprites { + texture_id: AtlasTextureId, + range: Range, + }, + Surfaces(Range), +} + +impl PrimitiveBatch { + #[expect(missing_docs)] + pub fn label(&self) -> String { + match self { + Self::Shadows(range) => format!("shadows ({})", range.len()), + Self::Quads(range) => format!("quads ({})", range.len()), + Self::Paths(range) => format!("paths ({})", range.len()), + Self::Underlines(range) => format!("underlines ({})", range.len()), + Self::MonochromeSprites { texture_id, range } => { + format!( + "monochrome sprites ({}) on atlas {}", + range.len(), + texture_id.index + ) + } + Self::SubpixelSprites { texture_id, range } => { + format!( + "subpixel sprites ({}) on atlas {}", + range.len(), + texture_id.index + ) + } + Self::PolychromeSprites { texture_id, range } => { + format!( + "polychrome sprites ({}) on atlas {}", + range.len(), + texture_id.index + ) + } + Self::Surfaces(range) => format!("surfaces ({})", range.len()), + } + } +} + +#[derive(Default, Debug, Copy, Clone)] +#[repr(C)] +#[expect(missing_docs)] +pub struct Quad { + pub order: DrawOrder, + pub border_style: BorderStyle, + pub bounds: Bounds, + pub content_mask: ContentMask, + pub background: Background, + pub border_color: Hsla, + pub corner_radii: Corners, + pub border_widths: Edges, +} + +impl From for Primitive { + fn from(quad: Quad) -> Self { + Primitive::Quad(quad) + } +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +#[expect(missing_docs)] +pub struct Underline { + pub order: DrawOrder, + pub pad: u32, // align to 8 bytes + pub bounds: Bounds, + pub content_mask: ContentMask, + pub color: Hsla, + pub thickness: ScaledPixels, + pub wavy: PaddedBool32, +} + +impl From for Primitive { + fn from(underline: Underline) -> Self { + Primitive::Underline(underline) + } +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +#[expect(missing_docs)] +pub struct Shadow { + pub order: DrawOrder, + pub blur_radius: ScaledPixels, + pub bounds: Bounds, + pub corner_radii: Corners, + pub content_mask: ContentMask, + pub color: Hsla, + pub element_bounds: Bounds, + pub element_corner_radii: Corners, + /// 0 = drop shadow (rendered outside the element), 1 = inset shadow (rendered inside). + pub inset: u32, + pub pad: u32, // align to 8 bytes +} + +impl From for Primitive { + fn from(shadow: Shadow) -> Self { + Primitive::Shadow(shadow) + } +} + +/// The style of a border. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[repr(C)] +pub enum BorderStyle { + /// A solid border. + #[default] + Solid = 0, + /// A dashed border. + Dashed = 1, +} + +/// A data type representing a 2 dimensional transformation that can be applied to an element. +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub struct TransformationMatrix { + /// 2x2 matrix containing rotation and scale, + /// stored row-major + pub rotation_scale: [[f32; 2]; 2], + /// translation vector + pub translation: [f32; 2], +} + +impl Eq for TransformationMatrix {} + +impl TransformationMatrix { + /// The unit matrix, has no effect. + pub fn unit() -> Self { + Self { + rotation_scale: [[1.0, 0.0], [0.0, 1.0]], + translation: [0.0, 0.0], + } + } + + /// Move the origin by a given point + pub fn translate(mut self, point: Point) -> Self { + self.compose(Self { + rotation_scale: [[1.0, 0.0], [0.0, 1.0]], + translation: [point.x.0, point.y.0], + }) + } + + /// Clockwise rotation in radians around the origin + pub fn rotate(self, angle: Radians) -> Self { + self.compose(Self { + rotation_scale: [ + [angle.0.cos(), -angle.0.sin()], + [angle.0.sin(), angle.0.cos()], + ], + translation: [0.0, 0.0], + }) + } + + /// Scale around the origin + pub fn scale(self, size: Size) -> Self { + self.compose(Self { + rotation_scale: [[size.width, 0.0], [0.0, size.height]], + translation: [0.0, 0.0], + }) + } + + /// Perform matrix multiplication with another transformation + /// to produce a new transformation that is the result of + /// applying both transformations: first, `other`, then `self`. + #[inline] + pub fn compose(self, other: TransformationMatrix) -> TransformationMatrix { + if other == Self::unit() { + return self; + } + // Perform matrix multiplication + TransformationMatrix { + rotation_scale: [ + [ + self.rotation_scale[0][0] * other.rotation_scale[0][0] + + self.rotation_scale[0][1] * other.rotation_scale[1][0], + self.rotation_scale[0][0] * other.rotation_scale[0][1] + + self.rotation_scale[0][1] * other.rotation_scale[1][1], + ], + [ + self.rotation_scale[1][0] * other.rotation_scale[0][0] + + self.rotation_scale[1][1] * other.rotation_scale[1][0], + self.rotation_scale[1][0] * other.rotation_scale[0][1] + + self.rotation_scale[1][1] * other.rotation_scale[1][1], + ], + ], + translation: [ + self.translation[0] + + self.rotation_scale[0][0] * other.translation[0] + + self.rotation_scale[0][1] * other.translation[1], + self.translation[1] + + self.rotation_scale[1][0] * other.translation[0] + + self.rotation_scale[1][1] * other.translation[1], + ], + } + } + + /// Apply transformation to a point, mainly useful for debugging + pub fn apply(&self, point: Point) -> Point { + let input = [point.x.0, point.y.0]; + let mut output = self.translation; + for (i, output_cell) in output.iter_mut().enumerate() { + for (k, input_cell) in input.iter().enumerate() { + *output_cell += self.rotation_scale[i][k] * *input_cell; + } + } + Point::new(output[0].into(), output[1].into()) + } +} + +impl Default for TransformationMatrix { + fn default() -> Self { + Self::unit() + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +#[expect(missing_docs)] +pub struct MonochromeSprite { + pub order: DrawOrder, + pub pad: u32, + pub bounds: Bounds, + pub content_mask: ContentMask, + pub color: Hsla, + pub tile: AtlasTile, + pub transformation: TransformationMatrix, +} + +impl From for Primitive { + fn from(sprite: MonochromeSprite) -> Self { + Primitive::MonochromeSprite(sprite) + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +#[expect(missing_docs)] +pub struct SubpixelSprite { + pub order: DrawOrder, + pub pad: u32, // align to 8 bytes + pub bounds: Bounds, + pub content_mask: ContentMask, + pub color: Hsla, + pub tile: AtlasTile, + pub transformation: TransformationMatrix, +} + +impl From for Primitive { + fn from(sprite: SubpixelSprite) -> Self { + Primitive::SubpixelSprite(sprite) + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +#[expect(missing_docs)] +pub struct PolychromeSprite { + pub order: DrawOrder, + pub pad: u32, + pub grayscale: PaddedBool32, + pub opacity: f32, + pub bounds: Bounds, + pub content_mask: ContentMask, + pub corner_radii: Corners, + pub tile: AtlasTile, +} + +impl From for Primitive { + fn from(sprite: PolychromeSprite) -> Self { + Primitive::PolychromeSprite(sprite) + } +} + +#[derive(Clone, Debug)] +#[allow(missing_docs)] +pub struct PaintSurface { + pub order: DrawOrder, + pub bounds: Bounds, + pub content_mask: ContentMask, + #[cfg(any(target_os = "macos", target_os = "ios"))] + pub image_buffer: core_video::pixel_buffer::CVPixelBuffer, +} + +impl From for Primitive { + fn from(surface: PaintSurface) -> Self { + Primitive::Surface(surface) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[expect(missing_docs)] +pub struct PathId(pub usize); + +/// A line made up of a series of vertices and control points. +#[derive(Clone, Debug)] +#[expect(missing_docs)] +pub struct Path { + pub id: PathId, + pub order: DrawOrder, + pub bounds: Bounds

    , + pub content_mask: ContentMask

    , + pub vertices: Vec>, + pub color: Background, + start: Point

    , + current: Point

    , + contour_count: usize, +} + +impl Path { + /// Create a new path with the given starting point. + pub fn new(start: Point) -> Self { + Self { + id: PathId(0), + order: DrawOrder::default(), + vertices: Vec::new(), + start, + current: start, + bounds: Bounds { + origin: start, + size: Default::default(), + }, + content_mask: Default::default(), + color: Default::default(), + contour_count: 0, + } + } + + /// Scale this path by the given factor. + pub fn scale(&self, factor: f32) -> Path { + Path { + id: self.id, + order: self.order, + bounds: self.bounds.scale(factor), + content_mask: self.content_mask.scale(factor), + vertices: self + .vertices + .iter() + .map(|vertex| vertex.scale(factor)) + .collect(), + start: self.start.map(|start| start.scale(factor)), + current: self.current.scale(factor), + contour_count: self.contour_count, + color: self.color, + } + } + + /// Move the start, current point to the given point. + pub fn move_to(&mut self, to: Point) { + self.contour_count += 1; + self.start = to; + self.current = to; + } + + /// Draw a straight line from the current point to the given point. + pub fn line_to(&mut self, to: Point) { + self.contour_count += 1; + if self.contour_count > 1 { + self.push_triangle( + (self.start, self.current, to), + (point(0., 1.), point(0., 1.), point(0., 1.)), + ); + } + self.current = to; + } + + /// Draw a curve from the current point to the given point, using the given control point. + pub fn curve_to(&mut self, to: Point, ctrl: Point) { + self.contour_count += 1; + if self.contour_count > 1 { + self.push_triangle( + (self.start, self.current, to), + (point(0., 1.), point(0., 1.), point(0., 1.)), + ); + } + + self.push_triangle( + (self.current, ctrl, to), + (point(0., 0.), point(0.5, 0.), point(1., 1.)), + ); + self.current = to; + } + + /// Push a triangle to the Path. + pub fn push_triangle( + &mut self, + xy: (Point, Point, Point), + st: (Point, Point, Point), + ) { + self.bounds = self + .bounds + .union(&Bounds { + origin: xy.0, + size: Default::default(), + }) + .union(&Bounds { + origin: xy.1, + size: Default::default(), + }) + .union(&Bounds { + origin: xy.2, + size: Default::default(), + }); + + self.vertices.push(PathVertex { + xy_position: xy.0, + st_position: st.0, + content_mask: Default::default(), + }); + self.vertices.push(PathVertex { + xy_position: xy.1, + st_position: st.1, + content_mask: Default::default(), + }); + self.vertices.push(PathVertex { + xy_position: xy.2, + st_position: st.2, + content_mask: Default::default(), + }); + } +} + +impl Path +where + T: Clone + Debug + Default + PartialEq + PartialOrd + Add + Sub, +{ + #[allow(unused)] + #[expect(missing_docs)] + pub fn clipped_bounds(&self) -> Bounds { + self.bounds.intersect(&self.content_mask.bounds) + } +} + +impl From> for Primitive { + fn from(path: Path) -> Self { + Primitive::Path(path) + } +} + +#[derive(Clone, Debug)] +#[repr(C)] +#[expect(missing_docs)] +pub struct PathVertex { + pub xy_position: Point

    , + pub st_position: Point, + pub content_mask: ContentMask

    , +} + +#[expect(missing_docs)] +impl PathVertex { + pub fn scale(&self, factor: f32) -> PathVertex { + PathVertex { + xy_position: self.xy_position.scale(factor), + st_position: self.st_position, + content_mask: self.content_mask.scale(factor), + } + } +} diff --git a/vendor/gpui-pre/src/seeds.rs b/vendor/gpui-pre/src/seeds.rs new file mode 100644 index 00000000..e90784d7 --- /dev/null +++ b/vendor/gpui-pre/src/seeds.rs @@ -0,0 +1,67 @@ +use std::env; + +/// Returns the seeds a randomized `#[gpui::test]` or `#[gpui::bench]` runs with, in +/// order, and whether there is more than one. +/// +/// With `$SEED` set, runs `$SEED..$SEED + iterations` and ignores `explicit_seeds`. +/// Otherwise runs `0..iterations` followed by `explicit_seeds`, except that the +/// default single iteration is dropped when explicit seeds are given. +/// `$ITERATIONS` overrides `iterations`. +/// Tests and benchmarks share this so that one `SEED` reproduces either. +/// +/// This is intended for use by the `gpui::test` and `gpui::bench` macros and generally +/// should not be used directly. +#[doc(hidden)] +pub fn calculate_seeds( + iterations: u64, + explicit_seeds: &[u64], +) -> (impl Iterator + '_, bool) { + let iterations = env::var("ITERATIONS") + .ok() + .map(|var| var.parse().expect("invalid ITERATIONS variable")) + .unwrap_or(iterations); + + let env_seed = env::var("SEED") + .map(|seed| seed.parse().expect("invalid SEED variable as integer")) + .ok(); + + let iter = seeds(iterations, explicit_seeds, env_seed); + let is_multiple_runs = iter.clone().nth(1).is_some(); + (iter, is_multiple_runs) +} + +fn seeds( + iterations: u64, + explicit_seeds: &[u64], + env_seed: Option, +) -> impl Iterator + Clone + '_ { + let (iterations_range, explicit_seeds) = match env_seed { + Some(env_seed) => (env_seed..env_seed + iterations, &[][..]), + None if iterations == 1 && !explicit_seeds.is_empty() => (0..0, explicit_seeds), + None => (0..iterations, explicit_seeds), + }; + iterations_range.chain(explicit_seeds.iter().copied()) +} + +#[cfg(test)] +mod tests { + use super::seeds; + + fn collect(iterations: u64, explicit_seeds: &[u64], env_seed: Option) -> Vec { + seeds(iterations, explicit_seeds, env_seed).collect() + } + + #[test] + fn seeds_follow_iterations_explicit_seeds_and_seed_variable() { + assert_eq!(collect(1, &[], None), [0]); + assert_eq!(collect(3, &[], None), [0, 1, 2]); + assert_eq!(collect(1, &[10, 20], None), [10, 20]); + assert_eq!(collect(2, &[10], None), [0, 1, 10]); + assert_eq!(collect(1, &[10], Some(7)), [7]); + assert_eq!( + collect(2, &[10], Some(7)), + [7, 8], + "`SEED` starts the iterations once, without repeating itself" + ); + } +} diff --git a/vendor/gpui-pre/src/shared_uri.rs b/vendor/gpui-pre/src/shared_uri.rs new file mode 100644 index 00000000..e257aaf0 --- /dev/null +++ b/vendor/gpui-pre/src/shared_uri.rs @@ -0,0 +1,25 @@ +use derive_more::{Deref, DerefMut}; + +use crate::SharedString; + +/// A [`SharedString`] containing a URI. +#[derive(Deref, DerefMut, Default, PartialEq, Eq, Hash, Clone)] +pub struct SharedUri(SharedString); + +impl std::fmt::Debug for SharedUri { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::fmt::Display for SharedUri { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0.as_ref()) + } +} + +impl> From for SharedUri { + fn from(value: T) -> Self { + Self(value.into()) + } +} diff --git a/vendor/gpui-pre/src/spring.rs b/vendor/gpui-pre/src/spring.rs new file mode 100644 index 00000000..efc87806 --- /dev/null +++ b/vendor/gpui-pre/src/spring.rs @@ -0,0 +1,830 @@ +use std::{ops::RangeInclusive, time::Duration}; + +use crate::{Hsla, Pixels, Rems, Rgba}; + +const CRITICAL_DAMPING_TOLERANCE: f32 = 1e-4; +const DEFAULT_SPRING_EPSILON: f32 = 0.001; + +/// The physical parameters of a damped harmonic oscillator. +/// +/// `stiffness` and `mass` must be finite and positive. `damping` must be finite +/// and non-negative. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct SpringConfig { + /// The spring stiffness, conventionally written as $k$. + pub stiffness: f32, + /// The viscous damping coefficient, conventionally written as $c$. + pub damping: f32, + /// The moving mass, conventionally written as $m$. + pub mass: f32, +} + +impl SpringConfig { + /// Creates a spring from its physical parameters. + pub const fn new(stiffness: f32, damping: f32, mass: f32) -> Self { + Self { + stiffness, + damping, + mass, + } + } + + /// Returns the natural angular frequency and damping ratio $(\omega_0, \zeta)$. + pub fn canonical(&self) -> (f32, f32) { + let natural_frequency = (self.stiffness / self.mass).sqrt(); + let damping_ratio = self.damping / (2.0 * (self.stiffness * self.mass).sqrt()); + (natural_frequency, damping_ratio) + } + + /// Advances a spring toward a target that remains fixed for `delta_time`. + /// + /// This analytic step is independent of frame rate and preserves velocity, + /// allowing an interrupted spring to be retargeted without restarting it. + pub fn step(&self, state: SpringState, target: f32, delta_time: f32) -> SpringState { + let propagator = self.propagator(delta_time); + let displacement = state.position - target; + + SpringState { + position: target + propagator[0][0] * displacement + propagator[0][1] * state.velocity, + velocity: propagator[1][0] * displacement + propagator[1][1] * state.velocity, + } + } + + /// Advances a spring toward a target moving at a constant velocity. + /// + /// A first-order hold avoids the frame-rate-dependent lag introduced by + /// treating a dragged target as stationary between frames. + pub fn step_ramp( + &self, + state: SpringState, + target: f32, + target_velocity: f32, + delta_time: f32, + ) -> SpringState { + let (natural_frequency, damping_ratio) = self.canonical(); + let steady_state_lag = -2.0 * damping_ratio * target_velocity / natural_frequency; + let displacement = state.position - target - steady_state_lag; + let velocity = state.velocity - target_velocity; + let propagator = self.propagator(delta_time); + let target = target + target_velocity * delta_time; + + SpringState { + position: target + + steady_state_lag + + propagator[0][0] * displacement + + propagator[0][1] * velocity, + velocity: target_velocity + + propagator[1][0] * displacement + + propagator[1][1] * velocity, + } + } + + /// Returns the exact state-transition matrix for a constant target. + /// + /// Materializing this matrix is useful when many springs share the same + /// configuration and frame delta. A matrix must not be reused when the + /// frame delta changes. + pub fn propagator(&self, delta_time: f32) -> [[f32; 2]; 2] { + let (natural_frequency, damping_ratio) = self.canonical(); + + if damping_ratio < 1.0 - CRITICAL_DAMPING_TOLERANCE { + let decay = damping_ratio * natural_frequency; + let damped_frequency = natural_frequency * (1.0 - damping_ratio * damping_ratio).sqrt(); + let exponential = (-decay * delta_time).exp(); + let (sine, cosine) = (damped_frequency * delta_time).sin_cos(); + let sine_over_frequency = sine / damped_frequency; + + [ + [ + exponential * (cosine + decay * sine_over_frequency), + exponential * sine_over_frequency, + ], + [ + -exponential * natural_frequency * natural_frequency * sine_over_frequency, + exponential * (cosine - decay * sine_over_frequency), + ], + ] + } else if damping_ratio > 1.0 + CRITICAL_DAMPING_TOLERANCE { + let root = (damping_ratio * damping_ratio - 1.0).sqrt(); + let root_sum = damping_ratio + root; + let slow_root = -natural_frequency / root_sum; + let fast_root = -natural_frequency * root_sum; + let denominator = slow_root - fast_root; + let slow_exponential = (slow_root * delta_time).exp(); + let fast_exponential = (fast_root * delta_time).exp(); + + [ + [ + (-fast_root * slow_exponential + slow_root * fast_exponential) / denominator, + (slow_exponential - fast_exponential) / denominator, + ], + [ + slow_root * fast_root * (fast_exponential - slow_exponential) / denominator, + (slow_root * slow_exponential - fast_root * fast_exponential) / denominator, + ], + ] + } else { + let exponential = (-natural_frequency * delta_time).exp(); + + [ + [ + exponential * (1.0 + natural_frequency * delta_time), + exponential * delta_time, + ], + [ + -exponential * natural_frequency * natural_frequency * delta_time, + exponential * (1.0 - natural_frequency * delta_time), + ], + ] + } + } + + /// Tests both displacement and velocity against a positional tolerance. + /// + /// Velocity is compared with `epsilon * natural_frequency`, giving it the + /// corresponding animated-units-per-second scale. + pub fn is_settled(&self, state: SpringState, target: f32, epsilon: f32) -> bool { + let (natural_frequency, _) = self.canonical(); + epsilon.is_finite() + && epsilon >= 0.0 + && (state.position - target).abs() <= epsilon + && state.velocity.abs() <= epsilon * natural_frequency + } + + /// Returns a conservative time after which the spring remains settled. + /// + /// An undamped spring has no finite settling time and returns + /// [`Duration::MAX`]. + pub fn settle_time(&self, state: SpringState, target: f32, epsilon: f32) -> Duration { + let displacement = state.position - target; + if displacement == 0.0 && state.velocity == 0.0 { + return Duration::ZERO; + } + + let (natural_frequency, damping_ratio) = self.canonical(); + if !natural_frequency.is_finite() + || natural_frequency <= 0.0 + || !damping_ratio.is_finite() + || damping_ratio <= 0.0 + || !epsilon.is_finite() + || epsilon <= 0.0 + { + return Duration::MAX; + } + + let velocity_threshold = epsilon * natural_frequency; + + if damping_ratio < 1.0 - CRITICAL_DAMPING_TOLERANCE { + let decay = damping_ratio * natural_frequency; + let damped_frequency = natural_frequency * (1.0 - damping_ratio * damping_ratio).sqrt(); + let sine_coefficient = (state.velocity + decay * displacement) / damped_frequency; + let position_envelope = displacement.hypot(sine_coefficient); + let velocity_cosine = damped_frequency * sine_coefficient - decay * displacement; + let velocity_sine = -damped_frequency * displacement - decay * sine_coefficient; + let velocity_envelope = velocity_cosine.hypot(velocity_sine); + + find_settle_time( + epsilon, + velocity_threshold, + 0.0, + natural_frequency, + move |time| { + let exponential = (-decay * time).exp(); + ( + position_envelope * exponential, + velocity_envelope * exponential, + ) + }, + ) + } else if damping_ratio > 1.0 + CRITICAL_DAMPING_TOLERANCE { + let root = (damping_ratio * damping_ratio - 1.0).sqrt(); + let root_sum = damping_ratio + root; + let slow_root = -natural_frequency / root_sum; + let fast_root = -natural_frequency * root_sum; + let denominator = slow_root - fast_root; + let slow_coefficient = (state.velocity - fast_root * displacement) / denominator; + let fast_coefficient = (slow_root * displacement - state.velocity) / denominator; + + find_settle_time( + epsilon, + velocity_threshold, + 0.0, + natural_frequency, + move |time| { + let slow_term = slow_coefficient.abs() * (slow_root * time).exp(); + let fast_term = fast_coefficient.abs() * (fast_root * time).exp(); + ( + slow_term + fast_term, + slow_root.abs() * slow_term + fast_root.abs() * fast_term, + ) + }, + ) + } else { + let linear_coefficient = state.velocity + natural_frequency * displacement; + let position_constant = displacement.abs(); + let position_linear = linear_coefficient.abs(); + let velocity_constant = (linear_coefficient - natural_frequency * displacement).abs(); + let velocity_linear = natural_frequency * linear_coefficient.abs(); + let position_decay_start = + envelope_decay_start(position_constant, position_linear, natural_frequency); + let velocity_decay_start = + envelope_decay_start(velocity_constant, velocity_linear, natural_frequency); + + find_settle_time( + epsilon, + velocity_threshold, + position_decay_start.max(velocity_decay_start), + natural_frequency, + move |time| { + let exponential = (-natural_frequency * time).exp(); + ( + (position_constant + position_linear * time) * exponential, + (velocity_constant + velocity_linear * time) * exponential, + ) + }, + ) + } + } +} + +/// The instantaneous position and velocity of a spring. +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct SpringState { + /// The current value in the animated unit. + pub position: f32, + /// The current value's change per second. + pub velocity: f32, +} + +/// A value that can be targeted by a one-dimensional spring. +/// +/// Implementations may project the spring coordinate into a richer output, +/// allowing a discrete state or a path through a multidimensional value to be +/// driven by one spring. +pub trait SpringTarget: 'static { + /// The value supplied to the spring animator. + type Output; + + /// Returns the target in the spring's coordinate space. + fn target(&self) -> f32; + + /// Projects a spring coordinate into the animated output. + fn resolve(&self, value: f32) -> Self::Output; +} + +impl SpringTarget for f32 { + type Output = f32; + + fn target(&self) -> f32 { + *self + } + + fn resolve(&self, value: f32) -> Self::Output { + value + } +} + +impl SpringTarget for Pixels { + type Output = Pixels; + + fn target(&self) -> f32 { + self.as_f32() + } + + fn resolve(&self, value: f32) -> Self::Output { + Pixels::from(value) + } +} + +impl SpringTarget for Rems { + type Output = Rems; + + fn target(&self) -> f32 { + self.0 + } + + fn resolve(&self, value: f32) -> Self::Output { + Rems(value) + } +} + +impl SpringTarget for bool { + type Output = AnimationPhase; + + fn target(&self) -> f32 { + if *self { 1.0 } else { 0.0 } + } + + fn resolve(&self, value: f32) -> Self::Output { + AnimationPhase(value) + } +} + +/// A potentially overshooting coordinate within an animation. +/// +/// Phases are not restricted to 0..1. Multi-stage animations can assign each +/// stage its own coordinate and interpolate over ranges such as 1..=2. +#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] +pub struct AnimationPhase( + /// The unbounded phase coordinate. + pub f32, +); + +impl AnimationPhase { + /// Restricts this phase to the bounds of a range. + pub fn clamp(self, range: RangeInclusive) -> Self { + let (first, second) = range.into_inner(); + Self(self.0.clamp(first.min(second), first.max(second))) + } + + /// Interpolates between values using 0 and 1 as their phase coordinates. + pub fn interpolate(self, from: T, to: T) -> T { + T::interpolate(from, to, self.0) + } + + /// Interpolates between values without extrapolating beyond 0 and 1. + pub fn interpolate_clamped(self, from: T, to: T) -> T { + T::interpolate(from, to, self.0.clamp(0.0, 1.0)) + } + + /// Interpolates between values assigned to arbitrary phase coordinates. + pub fn interpolate_between( + self, + range: RangeInclusive, + from: T, + to: T, + ) -> T { + let (start, end) = range.into_inner(); + let phase = if start == end { + if self.0 < start { 0.0 } else { 1.0 } + } else { + (self.0 - start) / (end - start) + }; + T::interpolate(from, to, phase) + } + + /// Interpolates over arbitrary phase coordinates without extrapolating. + pub fn interpolate_between_clamped( + self, + range: RangeInclusive, + from: T, + to: T, + ) -> T { + let (start, end) = range.into_inner(); + let phase = if start == end { + if self.0 < start { 0.0 } else { 1.0 } + } else { + ((self.0 - start) / (end - start)).clamp(0.0, 1.0) + }; + T::interpolate(from, to, phase) + } +} + +impl From for AnimationPhase { + fn from(value: f32) -> Self { + Self(value) + } +} + +impl From for AnimationPhase { + fn from(value: bool) -> Self { + Self(if value { 1.0 } else { 0.0 }) + } +} + +impl SpringTarget for AnimationPhase { + type Output = AnimationPhase; + + fn target(&self) -> f32 { + self.0 + } + + fn resolve(&self, value: f32) -> Self::Output { + Self(value) + } +} + +/// A value that supports linear interpolation and extrapolation. +pub trait Interpolate: Sized { + /// Resolves the value at `phase`, where 0 is `from` and 1 is `to`. + fn interpolate(from: Self, to: Self, phase: f32) -> Self; +} + +impl Interpolate for f32 { + fn interpolate(from: Self, to: Self, phase: f32) -> Self { + from + (to - from) * phase + } +} + +impl Interpolate for Pixels { + fn interpolate(from: Self, to: Self, phase: f32) -> Self { + from + (to - from) * phase + } +} + +impl Interpolate for Rems { + fn interpolate(from: Self, to: Self, phase: f32) -> Self { + from + (to - from) * phase + } +} + +impl Interpolate for Rgba { + fn interpolate(from: Self, to: Self, phase: f32) -> Self { + Self { + r: f32::interpolate(from.r, to.r, phase), + g: f32::interpolate(from.g, to.g, phase), + b: f32::interpolate(from.b, to.b, phase), + a: f32::interpolate(from.a, to.a, phase), + } + } +} + +impl Interpolate for Hsla { + fn interpolate(from: Self, to: Self, phase: f32) -> Self { + let hue_delta = (to.h - from.h + 0.5).rem_euclid(1.0) - 0.5; + Self { + h: (from.h + hue_delta * phase).rem_euclid(1.0), + s: f32::interpolate(from.s, to.s, phase), + l: f32::interpolate(from.l, to.l, phase), + a: f32::interpolate(from.a, to.a, phase), + } + } +} + +/// Controls how a spring advances and resolves its presentation value. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum SpringPlayback { + /// Advances toward the latest target, preserving velocity across retargets. + #[default] + Running, + /// Holds the current position and velocity until playback resumes. + Paused, + /// Holds the current position and discards velocity. + Stopped, + /// Snaps to the latest target and discards velocity. + Completed, + /// Returns to the initial value and discards velocity. + Cancelled, +} + +/// A stateful spring animation targeting a value or projected path. +#[derive(Clone, Debug)] +pub struct SpringAnimation { + pub(crate) config: SpringConfig, + pub(crate) target: T, + pub(crate) epsilon: f32, + pub(crate) initial: Option, + pub(crate) playback: SpringPlayback, +} + +impl SpringAnimation<()> { + /// Creates a spring animation builder. + pub fn new(config: SpringConfig) -> Self { + Self { + config, + target: (), + epsilon: DEFAULT_SPRING_EPSILON, + initial: None, + playback: SpringPlayback::Running, + } + } + + /// Sets the value or path targeted by this spring. + pub fn to(self, target: T) -> SpringAnimation { + let SpringAnimation { + config, + target: (), + epsilon, + initial, + playback, + } = self; + SpringAnimation { + config, + target, + epsilon, + initial, + playback, + } + } +} + +impl SpringAnimation { + /// Sets the settling tolerance in the target's scalar coordinate space. + pub fn with_epsilon(mut self, epsilon: f32) -> Self { + self.epsilon = epsilon; + self + } + + /// Sets how the spring advances or resolves its current value. + pub fn playback(mut self, playback: SpringPlayback) -> Self { + self.playback = playback; + self + } +} + +impl SpringAnimation { + /// Sets the coordinate used when this element has no prior spring state. + pub fn from(mut self, initial: T) -> Self { + self.initial = Some(initial.target()); + self + } +} + +/// Adapts a spring starting at zero with no velocity to GPUI's duration-based easing API. +/// +/// The returned easing can overshoot the normalized 0..1 output range. Retargeting +/// this duration-based form restarts the spring; use [`SpringConfig::step`] when +/// preserving velocity matters. +pub fn sampled_easing(config: SpringConfig, epsilon: f32) -> (Duration, impl Fn(f32) -> f32) { + let initial_state = SpringState { + position: 0.0, + velocity: 0.0, + }; + let duration = config.settle_time(initial_state, 1.0, epsilon); + let duration_seconds = duration.as_secs_f32(); + + (duration, move |progress| { + if progress <= 0.0 { + 0.0 + } else if progress >= 1.0 { + 1.0 + } else { + config + .step(initial_state, 1.0, progress * duration_seconds) + .position + } + }) +} + +fn envelope_decay_start(constant: f32, linear: f32, decay: f32) -> f32 { + if linear == 0.0 { + 0.0 + } else { + (1.0 / decay - constant / linear).max(0.0) + } +} + +fn find_settle_time( + position_threshold: f32, + velocity_threshold: f32, + decay_start: f32, + natural_frequency: f32, + envelope: impl Fn(f32) -> (f32, f32), +) -> Duration { + let is_below_threshold = |time| { + let (position, velocity) = envelope(time); + position <= position_threshold && velocity <= velocity_threshold + }; + + if is_below_threshold(decay_start) { + return duration_from_secs(decay_start); + } + + let mut lower_bound = decay_start; + let mut upper_bound = decay_start.max(natural_frequency.recip()); + while !is_below_threshold(upper_bound) { + lower_bound = upper_bound; + upper_bound *= 2.0; + if !upper_bound.is_finite() { + return Duration::MAX; + } + } + + for _ in 0..32 { + let midpoint = (lower_bound + upper_bound) / 2.0; + if is_below_threshold(midpoint) { + upper_bound = midpoint; + } else { + lower_bound = midpoint; + } + } + + duration_from_secs(upper_bound) +} + +fn duration_from_secs(seconds: f32) -> Duration { + if !seconds.is_finite() || seconds >= Duration::MAX.as_secs_f32() { + Duration::MAX + } else if seconds <= 0.0 { + Duration::ZERO + } else { + Duration::from_secs_f32(seconds) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const EPSILON: f32 = 1e-4; + + #[test] + fn spring_targets_resolve_typed_outputs() { + assert_eq!(12.0_f32.target(), 12.0); + assert_eq!(12.0_f32.resolve(14.0), 14.0); + assert_eq!(Pixels::from(12.0).target(), 12.0); + assert_eq!(Pixels::from(12.0).resolve(14.0), Pixels::from(14.0)); + assert_eq!(false.target(), 0.0); + assert_eq!(true.target(), 1.0); + assert_eq!(true.resolve(1.25), AnimationPhase(1.25)); + } + + #[test] + fn animation_phases_interpolate_over_arbitrary_ranges() { + let phase = AnimationPhase(1.5); + assert_eq!(phase.interpolate_between(1.0..=2.0, 10.0, 20.0), 15.0); + assert_eq!( + phase.interpolate_between_clamped(2.0..=3.0, 10.0, 20.0), + 10.0 + ); + assert_eq!( + AnimationPhase(3.5).interpolate_between(2.0..=3.0, 10.0, 20.0), + 25.0 + ); + } + + #[test] + fn hsla_interpolation_takes_the_shortest_hue_path() { + let from = Hsla { + h: 0.9, + s: 0.5, + l: 0.5, + a: 1.0, + }; + let to = Hsla { + h: 0.1, + s: 1.0, + l: 0.75, + a: 0.5, + }; + let result = AnimationPhase(0.5).interpolate(from, to); + + assert!(result.h < EPSILON || (1.0 - result.h) < EPSILON); + assert!((result.s - 0.75).abs() < EPSILON); + assert!((result.l - 0.625).abs() < EPSILON); + assert!((result.a - 0.75).abs() < EPSILON); + } + + #[test] + fn propagators_compose_and_have_expected_determinant() { + for damping_ratio in [0.4, 1.0, 1.5] { + let natural_frequency = 12.0; + let config = SpringConfig::new( + natural_frequency * natural_frequency, + 2.0 * damping_ratio * natural_frequency, + 1.0, + ); + let first = config.propagator(0.013); + let second = config.propagator(0.021); + let combined = multiply(second, first); + let direct = config.propagator(0.034); + + for row in 0..2 { + for column in 0..2 { + assert!( + (combined[row][column] - direct[row][column]).abs() < 2e-4, + "{damping_ratio}: {combined:?} != {direct:?}" + ); + } + } + + let determinant = direct[0][0] * direct[1][1] - direct[0][1] * direct[1][0]; + let expected = (-2.0 * damping_ratio * natural_frequency * 0.034).exp(); + assert!((determinant - expected).abs() < 2e-4); + } + } + + #[test] + fn step_preserves_semigroup_for_every_damping_regime() { + let state = SpringState { + position: -3.0, + velocity: 5.0, + }; + for damping in [4.0, 20.0, 40.0] { + let config = SpringConfig::new(100.0, damping, 1.0); + let stepped = config.step(config.step(state, 7.0, 0.013), 7.0, 0.021); + let direct = config.step(state, 7.0, 0.034); + + assert!((stepped.position - direct.position).abs() < 2e-4); + assert!((stepped.velocity - direct.velocity).abs() < 2e-4); + } + } + + #[test] + fn ramp_tracks_steady_state_lag() { + let natural_frequency = 10.0; + let damping_ratio = 0.8; + let target_velocity = 3.0; + let config = SpringConfig::new( + natural_frequency * natural_frequency, + 2.0 * damping_ratio * natural_frequency, + 1.0, + ); + let lag = -2.0 * damping_ratio * target_velocity / natural_frequency; + let state = SpringState { + position: lag, + velocity: target_velocity, + }; + let next = config.step_ramp(state, 0.0, target_velocity, 0.25); + + assert!((next.position - (target_velocity * 0.25 + lag)).abs() < EPSILON); + assert!((next.velocity - target_velocity).abs() < EPSILON); + } + + #[test] + fn settling_requires_low_velocity() { + let config = SpringConfig::new(100.0, 10.0, 1.0); + assert!(!config.is_settled( + SpringState { + position: 1.0, + velocity: 1.0, + }, + 1.0, + 0.01, + )); + assert!(config.is_settled( + SpringState { + position: 1.005, + velocity: 0.05, + }, + 1.0, + 0.01, + )); + } + + #[test] + fn settle_time_is_conservative_for_every_damping_regime() { + let initial_state = SpringState { + position: -2.0, + velocity: 4.0, + }; + for damping in [4.0, 20.0, 40.0] { + let config = SpringConfig::new(100.0, damping, 1.0); + let duration = config.settle_time(initial_state, 3.0, 0.001); + assert_ne!(duration, Duration::MAX); + + for additional_time in [0.0, 0.1, 1.0] { + let state = + config.step(initial_state, 3.0, duration.as_secs_f32() + additional_time); + assert!( + config.is_settled(state, 3.0, 0.001), + "{damping}: {duration:?} produced {state:?}" + ); + } + } + } + + #[test] + fn settle_time_accounts_for_motion_outside_an_instantaneous_tolerance() { + let config = SpringConfig::new(100.0, 2.0, 1.0); + let state = SpringState { + position: 1.125, + velocity: 1.25, + }; + assert!(config.is_settled(state, 1.0, 0.125)); + + let duration = config.settle_time(state, 1.0, 0.125); + assert!(duration > Duration::ZERO); + assert!(config.is_settled(config.step(state, 1.0, duration.as_secs_f32()), 1.0, 0.125,)); + } + + #[test] + fn undamped_spring_never_settles() { + let config = SpringConfig::new(100.0, 0.0, 1.0); + assert_eq!( + config.settle_time( + SpringState { + position: 0.0, + velocity: 0.0, + }, + 1.0, + 0.001, + ), + Duration::MAX + ); + } + + #[test] + fn sampled_easing_has_exact_endpoints_and_can_overshoot() { + let config = SpringConfig::new(100.0, 6.0, 1.0); + let (duration, easing) = sampled_easing(config, 0.001); + + assert_ne!(duration, Duration::MAX); + assert_eq!(easing(0.0), 0.0); + assert_eq!(easing(1.0), 1.0); + assert!((1..100).any(|step| easing(step as f32 / 100.0) > 1.0)); + } + + fn multiply(left: [[f32; 2]; 2], right: [[f32; 2]; 2]) -> [[f32; 2]; 2] { + [ + [ + left[0][0] * right[0][0] + left[0][1] * right[1][0], + left[0][0] * right[0][1] + left[0][1] * right[1][1], + ], + [ + left[1][0] * right[0][0] + left[1][1] * right[1][0], + left[1][0] * right[0][1] + left[1][1] * right[1][1], + ], + ] + } +} diff --git a/vendor/gpui-pre/src/style.rs b/vendor/gpui-pre/src/style.rs new file mode 100644 index 00000000..9150fdde --- /dev/null +++ b/vendor/gpui-pre/src/style.rs @@ -0,0 +1,1529 @@ +use std::{ + hash::{Hash, Hasher}, + iter, mem, + ops::Range, +}; + +use crate::{ + AbsoluteLength, App, Background, BackgroundTag, BorderStyle, Bounds, ContentMask, Corners, + CornersRefinement, CursorStyle, DefiniteLength, DevicePixels, Edges, EdgesRefinement, Font, + FontFallbacks, FontFeatures, FontStyle, FontWeight, GridLocation, Hsla, Length, Pixels, Point, + PointRefinement, Rgba, SharedString, Size, SizeRefinement, Styled, TextRun, Window, black, phi, + point, px, quad, rems, size, +}; +use collections::HashSet; +use refineable::Refineable; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// Use this struct for interfacing with the 'debug_below' styling from your own elements. +/// If a parent element has this style set on it, then this struct will be set as a global in +/// GPUI. +#[cfg(debug_assertions)] +pub struct DebugBelow; + +#[cfg(debug_assertions)] +impl crate::Global for DebugBelow {} + +/// How to fit the image into the bounds of the element. +pub enum ObjectFit { + /// The image will be stretched to fill the bounds of the element. + Fill, + /// The image will be scaled to fit within the bounds of the element. + Contain, + /// The image will be scaled to cover the bounds of the element. + Cover, + /// The image will be scaled down to fit within the bounds of the element. + ScaleDown, + /// The image will maintain its original size. + None, +} + +impl ObjectFit { + /// Get the bounds of the image within the given bounds. + pub fn get_bounds( + &self, + bounds: Bounds, + image_size: Size, + ) -> Bounds { + let image_size = image_size.map(|dimension| Pixels::from(u32::from(dimension))); + let image_ratio = image_size.width / image_size.height; + let bounds_ratio = bounds.size.width / bounds.size.height; + + match self { + ObjectFit::Fill => bounds, + ObjectFit::Contain => { + let new_size = if bounds_ratio > image_ratio { + size( + image_size.width * (bounds.size.height / image_size.height), + bounds.size.height, + ) + } else { + size( + bounds.size.width, + image_size.height * (bounds.size.width / image_size.width), + ) + }; + + Bounds { + origin: point( + bounds.origin.x + (bounds.size.width - new_size.width) / 2.0, + bounds.origin.y + (bounds.size.height - new_size.height) / 2.0, + ), + size: new_size, + } + } + ObjectFit::ScaleDown => { + // Check if the image is larger than the bounds in either dimension. + if image_size.width > bounds.size.width || image_size.height > bounds.size.height { + // If the image is larger, use the same logic as Contain to scale it down. + let new_size = if bounds_ratio > image_ratio { + size( + image_size.width * (bounds.size.height / image_size.height), + bounds.size.height, + ) + } else { + size( + bounds.size.width, + image_size.height * (bounds.size.width / image_size.width), + ) + }; + + Bounds { + origin: point( + bounds.origin.x + (bounds.size.width - new_size.width) / 2.0, + bounds.origin.y + (bounds.size.height - new_size.height) / 2.0, + ), + size: new_size, + } + } else { + // If the image is smaller than or equal to the container, display it at its original size, + // centered within the container. + let original_size = size(image_size.width, image_size.height); + Bounds { + origin: point( + bounds.origin.x + (bounds.size.width - original_size.width) / 2.0, + bounds.origin.y + (bounds.size.height - original_size.height) / 2.0, + ), + size: original_size, + } + } + } + ObjectFit::Cover => { + let new_size = if bounds_ratio > image_ratio { + size( + bounds.size.width, + image_size.height * (bounds.size.width / image_size.width), + ) + } else { + size( + image_size.width * (bounds.size.height / image_size.height), + bounds.size.height, + ) + }; + + Bounds { + origin: point( + bounds.origin.x + (bounds.size.width - new_size.width) / 2.0, + bounds.origin.y + (bounds.size.height - new_size.height) / 2.0, + ), + size: new_size, + } + } + ObjectFit::None => Bounds { + origin: bounds.origin, + size: image_size, + }, + } + } +} + +/// The minimum size of a column or row in a grid layout +#[derive( + Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, JsonSchema, Serialize, Deserialize, +)] +pub enum GridTemplateMinSize { + /// The column or row size may be 0 + #[default] + Zero, + /// The column or row size can be determined by the min content + MinContent, + /// The column or row size can be determined by the max content + MaxContent, +} + +/// A simplified representation of the grid-template-* value +#[derive( + Copy, + Clone, + Refineable, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + Default, + JsonSchema, + Serialize, + Deserialize, +)] +pub struct GridTemplate { + /// How this template directive should be repeated + pub repeat: u16, + /// The minimum size in the repeat(<>, minmax(_, 1fr)) equation + pub min_size: GridTemplateMinSize, +} + +/// The CSS styling that can be applied to an element via the `Styled` trait +#[derive(Clone, Refineable, Debug)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct Style { + /// What layout strategy should be used? + pub display: Display, + + /// Should the element be painted on screen? + pub visibility: Visibility, + + // Overflow properties + /// How children overflowing their container should affect layout + #[refineable] + pub overflow: Point, + /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes. + pub scrollbar_width: AbsoluteLength, + /// Whether both x and y axis should be scrollable at the same time. + pub allow_concurrent_scroll: bool, + /// Whether scrolling should be restricted to the input gesture's axis. + /// + /// Pixel-based scroll gestures are locked to their initially dominant axis. The lock may be + /// released when the gesture changes direction strongly. Touch phases delimit gestures when + /// available, with a timeout fallback for platforms that only emit moved events. + /// + /// This also prevents input from being remapped to another axis. For example, horizontal input + /// will not scroll a container that only has vertical overflow enabled. Mouse wheel platforms + /// typically report ordinary wheel input on the Y axis and Shift-modified input on the X axis. + /// + /// ## Motivation + /// + /// On the web when scrolling with the mouse wheel, scrolling up and down will always scroll the Y axis, even when + /// the mouse is over a horizontally-scrollable element. + /// + /// The only way to scroll horizontally is to hold down `Shift` while scrolling, which then changes the scroll axis + /// to the X axis. + /// + /// Currently, GPUI operates differently from the web in that it will scroll an element in either the X or Y axis + /// when scrolling with just the mouse wheel. This causes problems when scrolling in a vertical list that contains + /// horizontally-scrollable elements, as when you get to the horizontally-scrollable elements the scroll will be + /// hijacked. + /// + /// Ideally we would match the web's behavior and not have a need for this, but right now we're adding this opt-in + /// style property to limit the potential blast radius. + pub restrict_scroll_to_axis: bool, + + // Position properties + /// What should the `position` value of this struct use as a base offset? + pub position: Position, + /// How should the position of this element be tweaked relative to the layout defined? + #[refineable] + pub inset: Edges, + + // Size properties + /// Sets the initial size of the item + #[refineable] + pub size: Size, + /// Controls the minimum size of the item + #[refineable] + pub min_size: Size, + /// Controls the maximum size of the item + #[refineable] + pub max_size: Size, + /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height. + pub aspect_ratio: Option, + + // Spacing Properties + /// How large should the margin be on each side? + #[refineable] + pub margin: Edges, + /// How large should the padding be on each side? + #[refineable] + pub padding: Edges, + /// How large should the border be on each side? + #[refineable] + pub border_widths: Edges, + + // Alignment properties + /// How this node's children aligned in the cross/block axis? + pub align_items: Option, + /// How this node should be aligned in the cross/block axis. Falls back to the parents [`AlignItems`] if not set + pub align_self: Option, + /// How should content contained within this item be aligned in the cross/block axis + pub align_content: Option, + /// How should contained within this item be aligned in the main/inline axis + pub justify_content: Option, + /// How large should the gaps between items in a flex container be? + #[refineable] + pub gap: Size, + + // Flexbox properties + /// Which direction does the main axis flow in? + pub flex_direction: FlexDirection, + /// Should elements wrap, or stay in a single line? + pub flex_wrap: FlexWrap, + /// Sets the initial main axis size of the item + pub flex_basis: Length, + /// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive. + pub flex_grow: f32, + /// The relative rate at which this item shrinks when it is contracting to fit into space, 1.0 is the default value, and this value must be positive. + pub flex_shrink: f32, + + /// The fill color of this element + pub background: Option, + + /// The border color of this element + pub border_color: Option, + + /// The border style of this element + pub border_style: BorderStyle, + + /// The radius of the corners of this element + #[refineable] + pub corner_radii: Corners, + + /// Box shadow of the element + pub box_shadow: Vec, + + /// The text style of this element + #[refineable] + pub text: TextStyleRefinement, + + /// The mouse cursor style shown when the mouse pointer is over an element. + pub mouse_cursor: Option, + + /// The opacity of this element + pub opacity: Option, + + /// The grid columns of this element + /// Roughly equivalent to the Tailwind `grid-cols-` + pub grid_cols: Option, + + /// The row span of this element + /// Equivalent to the Tailwind `grid-rows-` + pub grid_rows: Option, + + /// The grid location of this element + pub grid_location: Option, + + /// Whether to draw a red debugging outline around this element + #[cfg(debug_assertions)] + pub debug: bool, + + /// Whether to draw a red debugging outline around this element and all of its conforming children + #[cfg(debug_assertions)] + pub debug_below: bool, +} + +impl Styled for StyleRefinement { + fn style(&mut self) -> &mut StyleRefinement { + self + } +} + +impl StyleRefinement { + /// The grid location of this element + pub fn grid_location_mut(&mut self) -> &mut GridLocation { + self.grid_location.get_or_insert_default() + } +} + +/// The value of the visibility property, similar to the CSS property `visibility` +#[derive(Default, Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] +pub enum Visibility { + /// The element should be drawn as normal. + #[default] + Visible, + /// The element should not be drawn, but should still take up space in the layout. + Hidden, +} + +/// The possible values of the box-shadow property +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct BoxShadow { + /// What color should the shadow have? + pub color: Hsla, + /// How should it be offset from its element? + pub offset: Point, + /// How much should the shadow be blurred? + pub blur_radius: Pixels, + /// How much should the shadow spread? + pub spread_radius: Pixels, + /// Whether this is an inset shadow (drawn inside the element's bounds). + pub inset: bool, +} + +impl BoxShadow { + /// Creates a new [`BoxShadow`] with the given offset and color, matching the order + /// of the CSS `box-shadow` property. Use the builder methods to set blur radius, + /// spread radius, and inset. + pub fn new(offset_x: Pixels, offset_y: Pixels, color: Hsla) -> Self { + Self { + color, + offset: point(offset_x, offset_y), + blur_radius: px(0.), + spread_radius: px(0.), + inset: false, + } + } + + /// Sets the shadow blur radius. + pub fn blur_radius(mut self, blur_radius: Pixels) -> Self { + self.blur_radius = blur_radius; + self + } + + /// Sets the shadow spread radius. + pub fn spread_radius(mut self, spread_radius: Pixels) -> Self { + self.spread_radius = spread_radius; + self + } + + /// Marks the shadow as inset (drawn inside the element's bounds). + pub fn inset(mut self) -> Self { + self.inset = true; + self + } +} + +/// How to handle whitespace in text +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub enum WhiteSpace { + /// Normal line wrapping when text overflows the width of the element + #[default] + Normal, + /// No line wrapping, text will overflow the width of the element + Nowrap, +} + +/// How to truncate text that overflows the width of the element +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub enum TextOverflow { + /// Truncate the text at the end when it doesn't fit, and represent this truncation by + /// displaying the provided string (e.g., "very long te…"). + Truncate(SharedString), + /// Truncate the text at the start when it doesn't fit, and represent this truncation by + /// displaying the provided string at the beginning (e.g., "…ong text here"). + /// Typically more adequate for file paths where the end is more important than the beginning. + TruncateStart(SharedString), + /// Truncate the text in the middle when it doesn't fit, preserving both the start and end + /// of the string (e.g., "long fi…name.rs"). Useful for filenames where both the prefix + /// and the extension are important context. + TruncateMiddle(SharedString), +} + +/// How to align text within the element +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub enum TextAlign { + /// Align the text to the left of the element + #[default] + Left, + + /// Center the text within the element + Center, + + /// Align the text to the right of the element + Right, +} + +/// The properties that can be used to style text in GPUI +#[derive(Refineable, Clone, Debug, PartialEq)] +#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct TextStyle { + /// The color of the text + pub color: Hsla, + + /// The font family to use + pub font_family: SharedString, + + /// The font features to use + pub font_features: FontFeatures, + + /// The fallback fonts to use + pub font_fallbacks: Option, + + /// The font size to use, in pixels or rems. + pub font_size: AbsoluteLength, + + /// The line height to use, in pixels or fractions + pub line_height: DefiniteLength, + + /// The font weight, e.g. bold + pub font_weight: FontWeight, + + /// The font style, e.g. italic + pub font_style: FontStyle, + + /// The background color of the text + pub background_color: Option, + + /// The underline style of the text + pub underline: Option, + + /// The strikethrough style of the text + pub strikethrough: Option, + + /// How to handle whitespace in the text + pub white_space: WhiteSpace, + + /// The text should be truncated if it overflows the width of the element + pub text_overflow: Option, + + /// How the text should be aligned within the element + pub text_align: TextAlign, + + /// The number of lines to display before truncating the text + pub line_clamp: Option, +} + +impl Default for TextStyle { + fn default() -> Self { + TextStyle { + color: black(), + // todo(linux) make this configurable or choose better default + font_family: ".SystemUIFont".into(), + font_features: FontFeatures::default(), + font_fallbacks: None, + font_size: rems(1.).into(), + line_height: phi(), + font_weight: FontWeight::default(), + font_style: FontStyle::default(), + background_color: None, + underline: None, + strikethrough: None, + white_space: WhiteSpace::Normal, + text_overflow: None, + text_align: TextAlign::default(), + line_clamp: None, + } + } +} + +impl TextStyle { + /// Create a new text style with the given highlighting applied. + pub fn highlight(mut self, style: impl Into) -> Self { + let style = style.into(); + if let Some(weight) = style.font_weight { + self.font_weight = weight; + } + if let Some(style) = style.font_style { + self.font_style = style; + } + + if let Some(color) = style.color { + self.color = self.color.blend(color); + } + + if let Some(factor) = style.fade_out { + self.color.fade_out(factor); + } + + if let Some(background_color) = style.background_color { + self.background_color = Some(background_color); + } + + if let Some(underline) = style.underline { + self.underline = Some(underline); + } + + if let Some(strikethrough) = style.strikethrough { + self.strikethrough = Some(strikethrough); + } + + self + } + + /// Get the font configured for this text style. + pub fn font(&self) -> Font { + Font { + family: self.font_family.clone(), + features: self.font_features.clone(), + fallbacks: self.font_fallbacks.clone(), + weight: self.font_weight, + style: self.font_style, + } + } + + /// Returns the rounded line height in pixels. + pub fn line_height_in_pixels(&self, rem_size: Pixels) -> Pixels { + self.line_height.to_pixels(self.font_size, rem_size).round() + } + + /// Convert this text style into a [`TextRun`], for the given length of the text. + pub fn to_run(&self, len: usize) -> TextRun { + TextRun { + len, + font: Font { + family: self.font_family.clone(), + features: self.font_features.clone(), + fallbacks: self.font_fallbacks.clone(), + weight: self.font_weight, + style: self.font_style, + }, + color: self.color, + background_color: self.background_color, + underline: self.underline, + strikethrough: self.strikethrough, + } + } +} + +/// A highlight style to apply, similar to a `TextStyle` except +/// for a single font, uniformly sized and spaced text. +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct HighlightStyle { + /// The color of the text + pub color: Option, + + /// The font weight, e.g. bold + pub font_weight: Option, + + /// The font style, e.g. italic + pub font_style: Option, + + /// The background color of the text + pub background_color: Option, + + /// The underline style of the text + pub underline: Option, + + /// The underline style of the text + pub strikethrough: Option, + + /// Similar to the CSS `opacity` property, this will cause the text to be less vibrant. + pub fade_out: Option, +} + +impl Eq for HighlightStyle {} + +impl Hash for HighlightStyle { + fn hash(&self, state: &mut H) { + self.color.hash(state); + self.font_weight.hash(state); + self.font_style.hash(state); + self.background_color.hash(state); + self.underline.hash(state); + self.strikethrough.hash(state); + state.write_u32(u32::from_be_bytes( + self.fade_out.map(|f| f.to_be_bytes()).unwrap_or_default(), + )); + } +} + +impl Style { + /// Returns true if the style is visible and the background is opaque. + pub fn has_opaque_background(&self) -> bool { + self.background + .as_ref() + .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) + } + + /// Get the text style in this element style. + pub fn text_style(&self) -> Option<&TextStyleRefinement> { + if self.text.is_some() { + Some(&self.text) + } else { + None + } + } + + /// Get the content mask for this element style, based on the given bounds. + /// If the element does not hide its overflow, this will return `None`. + pub fn overflow_mask( + &self, + bounds: Bounds, + rem_size: Pixels, + ) -> Option> { + match self.overflow { + Point { + x: Overflow::Visible, + y: Overflow::Visible, + } => None, + _ => { + let mut min = bounds.origin; + let mut max = bounds.bottom_right(); + + if self + .border_color + .is_some_and(|color| !color.is_transparent()) + { + min.x += self.border_widths.left.to_pixels(rem_size); + max.x -= self.border_widths.right.to_pixels(rem_size); + min.y += self.border_widths.top.to_pixels(rem_size); + max.y -= self.border_widths.bottom.to_pixels(rem_size); + } + + let bounds = match ( + self.overflow.x == Overflow::Visible, + self.overflow.y == Overflow::Visible, + ) { + // x and y both visible + (true, true) => return None, + // x visible, y hidden + (true, false) => Bounds::from_corners( + point(min.x, bounds.origin.y), + point(max.x, bounds.bottom_right().y), + ), + // x hidden, y visible + (false, true) => Bounds::from_corners( + point(bounds.origin.x, min.y), + point(bounds.bottom_right().x, max.y), + ), + // both hidden + (false, false) => Bounds::from_corners(min, max), + }; + + Some(ContentMask { bounds }) + } + } + } + + /// Paints the background of an element styled with this style. + pub fn paint( + &self, + bounds: Bounds, + window: &mut Window, + cx: &mut App, + continuation: impl FnOnce(&mut Window, &mut App), + ) { + #[cfg(debug_assertions)] + if self.debug_below { + cx.set_global(DebugBelow) + } + + #[cfg(debug_assertions)] + if self.debug || cx.has_global::() { + window.paint_quad(crate::outline(bounds, crate::red(), BorderStyle::default())); + } + + let rem_size = window.rem_size(); + let corner_radii = self + .corner_radii + .to_pixels(rem_size) + .clamp_radii_for_quad_size(bounds.size); + + window.paint_drop_shadows(bounds, corner_radii, &self.box_shadow); + + let background_color = self.background.as_ref().and_then(Fill::color); + if background_color.is_some_and(|color| !color.is_transparent()) { + let mut border_color = match background_color { + Some(color) => match color.tag { + BackgroundTag::Solid + | BackgroundTag::PatternSlash + | BackgroundTag::Checkerboard => color.solid, + + BackgroundTag::LinearGradient => color + .colors + .first() + .map(|stop| stop.color) + .unwrap_or_default(), + }, + None => Hsla::default(), + }; + border_color.a = 0.; + window.paint_quad(quad( + bounds, + corner_radii, + background_color.unwrap_or_default(), + Edges::default(), + border_color, + self.border_style, + )); + } + + window.paint_inset_shadows(bounds, corner_radii, &self.box_shadow); + + continuation(window, cx); + + if self.is_border_visible() { + let border_widths = self.border_widths.to_pixels(rem_size); + let mut background = self.border_color.unwrap_or_default(); + background.a = 0.; + window.paint_quad(quad( + bounds, + corner_radii, + background, + border_widths, + self.border_color.unwrap_or_default(), + self.border_style, + )); + } + + #[cfg(debug_assertions)] + if self.debug_below { + cx.remove_global::(); + } + } + + fn is_border_visible(&self) -> bool { + self.border_color + .is_some_and(|color| !color.is_transparent()) + && self.border_widths.any(|length| !length.is_zero()) + } +} + +impl Default for Style { + fn default() -> Self { + Style { + display: Display::Block, + visibility: Visibility::Visible, + overflow: Point { + x: Overflow::Visible, + y: Overflow::Visible, + }, + allow_concurrent_scroll: false, + restrict_scroll_to_axis: false, + scrollbar_width: AbsoluteLength::default(), + position: Position::Relative, + inset: Edges::auto(), + margin: Edges::::zero(), + padding: Edges::::zero(), + border_widths: Edges::::zero(), + size: Size::auto(), + min_size: Size::auto(), + max_size: Size::auto(), + aspect_ratio: None, + gap: Size::default(), + // Alignment + align_items: None, + align_self: None, + align_content: None, + justify_content: None, + // Flexbox + flex_direction: FlexDirection::Row, + flex_wrap: FlexWrap::NoWrap, + flex_grow: 0.0, + flex_shrink: 1.0, + flex_basis: Length::Auto, + background: None, + border_color: None, + border_style: BorderStyle::default(), + corner_radii: Corners::default(), + box_shadow: Default::default(), + text: TextStyleRefinement::default(), + mouse_cursor: None, + opacity: None, + grid_rows: None, + grid_cols: None, + grid_location: None, + + #[cfg(debug_assertions)] + debug: false, + #[cfg(debug_assertions)] + debug_below: false, + } + } +} + +/// The properties that can be applied to an underline. +#[derive( + Refineable, Copy, Clone, Default, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, +)] +pub struct UnderlineStyle { + /// The thickness of the underline. + pub thickness: Pixels, + + /// The color of the underline. + pub color: Option, + + /// Whether the underline should be wavy, like in a spell checker. + pub wavy: bool, +} + +/// The properties that can be applied to a strikethrough. +#[derive( + Refineable, Copy, Clone, Default, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, +)] +pub struct StrikethroughStyle { + /// The thickness of the strikethrough. + pub thickness: Pixels, + + /// The color of the strikethrough. + pub color: Option, +} + +/// The kinds of fill that can be applied to a shape. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)] +pub enum Fill { + /// A solid color fill. + Color(Background), +} + +impl Fill { + /// Unwrap this fill into a solid color, if it is one. + /// + /// If the fill is not a solid color, this method returns `None`. + pub fn color(&self) -> Option { + match self { + Fill::Color(color) => Some(*color), + } + } +} + +impl Default for Fill { + fn default() -> Self { + Self::Color(Background::default()) + } +} + +impl From for Fill { + fn from(color: Hsla) -> Self { + Self::Color(color.into()) + } +} + +impl From for Fill { + fn from(color: Rgba) -> Self { + Self::Color(color.into()) + } +} + +impl From for Fill { + fn from(background: Background) -> Self { + Self::Color(background) + } +} + +impl From for HighlightStyle { + fn from(other: TextStyle) -> Self { + Self::from(&other) + } +} + +impl From<&TextStyle> for HighlightStyle { + fn from(other: &TextStyle) -> Self { + Self { + color: Some(other.color), + font_weight: Some(other.font_weight), + font_style: Some(other.font_style), + background_color: other.background_color, + underline: other.underline, + strikethrough: other.strikethrough, + fade_out: None, + } + } +} + +impl HighlightStyle { + /// Create a highlight style with just a color + pub fn color(color: Hsla) -> Self { + Self { + color: Some(color), + ..Default::default() + } + } + /// Blend this highlight style with another. + /// Non-continuous properties, like font_weight and font_style, are overwritten. + #[must_use] + pub fn highlight(self, other: HighlightStyle) -> Self { + Self { + color: other + .color + .map(|other_color| { + if let Some(color) = self.color { + color.blend(other_color) + } else { + other_color + } + }) + .or(self.color), + font_weight: other.font_weight.or(self.font_weight), + font_style: other.font_style.or(self.font_style), + background_color: other.background_color.or(self.background_color), + underline: other.underline.or(self.underline), + strikethrough: other.strikethrough.or(self.strikethrough), + fade_out: other + .fade_out + .map(|source_fade| { + self.fade_out + .map(|dest_fade| (dest_fade * (1. + source_fade)).clamp(0., 1.)) + .unwrap_or(source_fade) + }) + .or(self.fade_out), + } + } +} + +impl From for HighlightStyle { + fn from(color: Hsla) -> Self { + Self { + color: Some(color), + ..Default::default() + } + } +} + +impl From for HighlightStyle { + fn from(font_weight: FontWeight) -> Self { + Self { + font_weight: Some(font_weight), + ..Default::default() + } + } +} + +impl From for HighlightStyle { + fn from(font_style: FontStyle) -> Self { + Self { + font_style: Some(font_style), + ..Default::default() + } + } +} + +impl From for HighlightStyle { + fn from(color: Rgba) -> Self { + Self { + color: Some(color.into()), + ..Default::default() + } + } +} + +/// Combine and merge the highlights and ranges in the two iterators. +pub fn combine_highlights( + a: impl IntoIterator, HighlightStyle)>, + b: impl IntoIterator, HighlightStyle)>, +) -> impl Iterator, HighlightStyle)> { + let mut endpoints = Vec::new(); + let mut highlights = Vec::new(); + for (range, highlight) in a.into_iter().chain(b) { + if !range.is_empty() { + let highlight_id = highlights.len(); + endpoints.push((range.start, highlight_id, true)); + endpoints.push((range.end, highlight_id, false)); + highlights.push(highlight); + } + } + endpoints.sort_unstable_by_key(|(position, _, _)| *position); + let mut endpoints = endpoints.into_iter().peekable(); + + let mut active_styles = HashSet::default(); + let mut ix = 0; + iter::from_fn(move || { + while let Some((endpoint_ix, highlight_id, is_start)) = endpoints.peek() { + let prev_index = mem::replace(&mut ix, *endpoint_ix); + if ix > prev_index && !active_styles.is_empty() { + let current_style = active_styles + .iter() + .fold(HighlightStyle::default(), |acc, highlight_id| { + acc.highlight(highlights[*highlight_id]) + }); + return Some((prev_index..ix, current_style)); + } + + if *is_start { + active_styles.insert(*highlight_id); + } else { + active_styles.remove(highlight_id); + } + endpoints.next(); + } + None + }) +} + +/// Used to control how child nodes are aligned. +/// For Flexbox it controls alignment in the cross axis +/// For Grid it controls alignment in the block axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items) +#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum AlignItems { + /// Items are packed toward the start of the axis + Start, + /// Items are packed toward the end of the axis + End, + /// Items are packed towards the flex-relative start of the axis. + /// + /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent + /// to End. In all other cases it is equivalent to Start. + FlexStart, + /// Items are packed towards the flex-relative end of the axis. + /// + /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent + /// to Start. In all other cases it is equivalent to End. + FlexEnd, + /// Items are packed along the center of the cross axis + Center, + /// Items are aligned such as their baselines align + Baseline, + /// Stretch to fill the container + Stretch, +} +/// Used to control how child nodes are aligned. +/// Does not apply to Flexbox, and will be ignored if specified on a flex container +/// For Grid it controls alignment in the inline axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items) +pub type JustifyItems = AlignItems; +/// Used to control how the specified nodes is aligned. +/// Overrides the parent Node's `AlignItems` property. +/// For Flexbox it controls alignment in the cross axis +/// For Grid it controls alignment in the block axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self) +pub type AlignSelf = AlignItems; +/// Used to control how the specified nodes is aligned. +/// Overrides the parent Node's `JustifyItems` property. +/// Does not apply to Flexbox, and will be ignored if specified on a flex child +/// For Grid it controls alignment in the inline axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self) +pub type JustifySelf = AlignItems; + +/// Sets the distribution of space between and around content items +/// For Flexbox it controls alignment in the cross axis +/// For Grid it controls alignment in the block axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content) +#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum AlignContent { + /// Items are packed toward the start of the axis + Start, + /// Items are packed toward the end of the axis + End, + /// Items are packed towards the flex-relative start of the axis. + /// + /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent + /// to End. In all other cases it is equivalent to Start. + FlexStart, + /// Items are packed towards the flex-relative end of the axis. + /// + /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent + /// to Start. In all other cases it is equivalent to End. + FlexEnd, + /// Items are centered around the middle of the axis + Center, + /// Items are stretched to fill the container + Stretch, + /// The first and last items are aligned flush with the edges of the container (no gap) + /// The gap between items is distributed evenly. + SpaceBetween, + /// The gap between the first and last items is exactly THE SAME as the gap between items. + /// The gaps are distributed evenly + SpaceEvenly, + /// The gap between the first and last items is exactly HALF the gap between items. + /// The gaps are distributed evenly in proportion to these ratios. + SpaceAround, +} + +/// Sets the distribution of space between and around content items +/// For Flexbox it controls alignment in the main axis +/// For Grid it controls alignment in the inline axis +/// +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content) +pub type JustifyContent = AlignContent; + +/// Sets the layout used for the children of this node +/// +/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum Display { + /// The children will follow the block layout algorithm + Block, + /// The children will follow the flexbox layout algorithm + #[default] + Flex, + /// The children will follow the CSS Grid layout algorithm + Grid, + /// The children will not be laid out, and will follow absolute positioning + None, +} + +/// Controls whether flex items are forced onto one line or can wrap onto multiple lines. +/// +/// Defaults to [`FlexWrap::NoWrap`] +/// +/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-wrap-property) +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum FlexWrap { + /// Items will not wrap and stay on a single line + #[default] + NoWrap, + /// Items will wrap according to this item's [`FlexDirection`] + Wrap, + /// Items will wrap in the opposite direction to this item's [`FlexDirection`] + WrapReverse, +} + +/// The direction of the flexbox layout main axis. +/// +/// There are always two perpendicular layout axes: main (or primary) and cross (or secondary). +/// Adding items will cause them to be positioned adjacent to each other along the main axis. +/// By varying this value throughout your tree, you can create complex axis-aligned layouts. +/// +/// Items are always aligned relative to the cross axis, and justified relative to the main axis. +/// +/// The default behavior is [`FlexDirection::Row`]. +/// +/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-direction-property) +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum FlexDirection { + /// Defines +x as the main axis + /// + /// Items will be added from left to right in a row. + #[default] + Row, + /// Defines +y as the main axis + /// + /// Items will be added from top to bottom in a column. + Column, + /// Defines -x as the main axis + /// + /// Items will be added from right to left in a row. + RowReverse, + /// Defines -y as the main axis + /// + /// Items will be added from bottom to top in a column. + ColumnReverse, +} + +/// How children overflowing their container should affect layout +/// +/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should +/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout, +/// the main ones being: +/// +/// - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based +/// - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property) +/// +/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for +/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`. +/// +/// +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum Overflow { + /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content. + /// Content that overflows this node *should* contribute to the scroll region of its parent. + #[default] + Visible, + /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content. + /// Content that overflows this node should *not* contribute to the scroll region of its parent. + Clip, + /// The automatic minimum size of this node as a flexbox/grid item should be `0`. + /// Content that overflows this node should *not* contribute to the scroll region of its parent. + Hidden, + /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved + /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property. + /// Content that overflows this node should *not* contribute to the scroll region of its parent. + Scroll, +} + +/// The positioning strategy for this item. +/// +/// This controls both how the origin is determined for the [`Style::position`] field, +/// and whether or not the item will be controlled by flexbox's layout algorithm. +/// +/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position), +/// which can be unintuitive. +/// +/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)] +// Copy of taffy::style type of the same name, to derive JsonSchema. +pub enum Position { + /// The offset is computed relative to the final position given by the layout algorithm. + /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end. + #[default] + Relative, + /// The offset is computed relative to this item's closest positioned ancestor, if any. + /// Otherwise, it is placed relative to the origin. + /// No space is created for the item in the page layout, and its size will not be altered. + /// + /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object. + Absolute, +} + +impl From for taffy::style::AlignItems { + fn from(value: AlignItems) -> Self { + match value { + AlignItems::Start => Self::START, + AlignItems::End => Self::END, + AlignItems::FlexStart => Self::FLEX_START, + AlignItems::FlexEnd => Self::FLEX_END, + AlignItems::Center => Self::CENTER, + AlignItems::Baseline => Self::BASELINE, + AlignItems::Stretch => Self::STRETCH, + } + } +} + +impl From for taffy::style::AlignContent { + fn from(value: AlignContent) -> Self { + match value { + AlignContent::Start => Self::START, + AlignContent::End => Self::END, + AlignContent::FlexStart => Self::FLEX_START, + AlignContent::FlexEnd => Self::FLEX_END, + AlignContent::Center => Self::CENTER, + AlignContent::Stretch => Self::STRETCH, + AlignContent::SpaceBetween => Self::SPACE_BETWEEN, + AlignContent::SpaceEvenly => Self::SPACE_EVENLY, + AlignContent::SpaceAround => Self::SPACE_AROUND, + } + } +} + +impl From for taffy::style::Display { + fn from(value: Display) -> Self { + match value { + Display::Block => Self::Block, + Display::Flex => Self::Flex, + Display::Grid => Self::Grid, + Display::None => Self::None, + } + } +} + +impl From for taffy::style::FlexWrap { + fn from(value: FlexWrap) -> Self { + match value { + FlexWrap::NoWrap => Self::NoWrap, + FlexWrap::Wrap => Self::Wrap, + FlexWrap::WrapReverse => Self::WrapReverse, + } + } +} + +impl From for taffy::style::FlexDirection { + fn from(value: FlexDirection) -> Self { + match value { + FlexDirection::Row => Self::Row, + FlexDirection::Column => Self::Column, + FlexDirection::RowReverse => Self::RowReverse, + FlexDirection::ColumnReverse => Self::ColumnReverse, + } + } +} + +impl From for taffy::style::Overflow { + fn from(value: Overflow) -> Self { + match value { + Overflow::Visible => Self::Visible, + Overflow::Clip => Self::Clip, + Overflow::Hidden => Self::Hidden, + Overflow::Scroll => Self::Scroll, + } + } +} + +impl From for taffy::style::Position { + fn from(value: Position) -> Self { + match value { + Position::Relative => Self::Relative, + Position::Absolute => Self::Absolute, + } + } +} + +#[cfg(test)] +mod tests { + use crate::{blue, green, px, red, yellow}; + + use super::*; + + use util_macros::perf; + + #[perf] + fn test_basic_highlight_style_combination() { + let style_a = HighlightStyle::default(); + let style_b = HighlightStyle::default(); + let style_a = style_a.highlight(style_b); + assert_eq!( + style_a, + HighlightStyle::default(), + "Combining empty styles should not produce a non-empty style." + ); + + let mut style_b = HighlightStyle { + color: Some(red()), + strikethrough: Some(StrikethroughStyle { + thickness: px(2.), + color: Some(blue()), + }), + fade_out: Some(0.), + font_style: Some(FontStyle::Italic), + font_weight: Some(FontWeight(300.)), + background_color: Some(yellow()), + underline: Some(UnderlineStyle { + thickness: px(2.), + color: Some(red()), + wavy: true, + }), + }; + let expected_style = style_b; + + let style_a = style_a.highlight(style_b); + assert_eq!( + style_a, expected_style, + "Blending an empty style with another style should return the other style" + ); + + let style_b = style_b.highlight(Default::default()); + assert_eq!( + style_b, expected_style, + "Blending a style with an empty style should not change the style." + ); + + let mut style_c = expected_style; + + let style_d = HighlightStyle { + color: Some(blue().alpha(0.7)), + strikethrough: Some(StrikethroughStyle { + thickness: px(4.), + color: Some(crate::red()), + }), + fade_out: Some(0.), + font_style: Some(FontStyle::Oblique), + font_weight: Some(FontWeight(800.)), + background_color: Some(green()), + underline: Some(UnderlineStyle { + thickness: px(4.), + color: None, + wavy: false, + }), + }; + + let expected_style = HighlightStyle { + color: Some(red().blend(blue().alpha(0.7))), + strikethrough: Some(StrikethroughStyle { + thickness: px(4.), + color: Some(red()), + }), + // TODO this does not seem right + fade_out: Some(0.), + font_style: Some(FontStyle::Oblique), + font_weight: Some(FontWeight(800.)), + background_color: Some(green()), + underline: Some(UnderlineStyle { + thickness: px(4.), + color: None, + wavy: false, + }), + }; + + let style_c = style_c.highlight(style_d); + assert_eq!( + style_c, expected_style, + "Blending styles should blend properties where possible and override all others" + ); + } + + #[perf] + fn test_combine_highlights() { + assert_eq!( + combine_highlights( + [ + (0..5, green().into()), + (4..10, FontWeight::BOLD.into()), + (15..20, yellow().into()), + ], + [ + (2..6, FontStyle::Italic.into()), + (1..3, blue().into()), + (21..23, red().into()), + ] + ) + .collect::>(), + [ + ( + 0..1, + HighlightStyle { + color: Some(green()), + ..Default::default() + } + ), + ( + 1..2, + HighlightStyle { + color: Some(blue()), + ..Default::default() + } + ), + ( + 2..3, + HighlightStyle { + color: Some(blue()), + font_style: Some(FontStyle::Italic), + ..Default::default() + } + ), + ( + 3..4, + HighlightStyle { + color: Some(green()), + font_style: Some(FontStyle::Italic), + ..Default::default() + } + ), + ( + 4..5, + HighlightStyle { + color: Some(green()), + font_weight: Some(FontWeight::BOLD), + font_style: Some(FontStyle::Italic), + ..Default::default() + } + ), + ( + 5..6, + HighlightStyle { + font_weight: Some(FontWeight::BOLD), + font_style: Some(FontStyle::Italic), + ..Default::default() + } + ), + ( + 6..10, + HighlightStyle { + font_weight: Some(FontWeight::BOLD), + ..Default::default() + } + ), + ( + 15..20, + HighlightStyle { + color: Some(yellow()), + ..Default::default() + } + ), + ( + 21..23, + HighlightStyle { + color: Some(red()), + ..Default::default() + } + ) + ] + ); + } + + #[perf] + fn test_text_style_refinement() { + let mut style = Style::default(); + style.refine(&StyleRefinement::default().text_size(px(20.0))); + style.refine(&StyleRefinement::default().font_weight(FontWeight::SEMIBOLD)); + + assert_eq!( + Some(AbsoluteLength::from(px(20.0))), + style.text_style().unwrap().font_size + ); + + assert_eq!( + Some(FontWeight::SEMIBOLD), + style.text_style().unwrap().font_weight + ); + } +} diff --git a/vendor/gpui-pre/src/styled.rs b/vendor/gpui-pre/src/styled.rs new file mode 100644 index 00000000..a24982a6 --- /dev/null +++ b/vendor/gpui-pre/src/styled.rs @@ -0,0 +1,904 @@ +use crate::{ + self as gpui, AbsoluteLength, AlignContent, AlignItems, AlignSelf, BorderStyle, CursorStyle, + DefiniteLength, Display, Fill, FlexDirection, FlexWrap, Font, FontFeatures, FontStyle, + FontWeight, GridPlacement, GridTemplate, GridTemplateMinSize, Hsla, JustifyContent, Length, + SharedString, StrikethroughStyle, StyleRefinement, TextAlign, TextOverflow, + TextStyleRefinement, UnderlineStyle, WhiteSpace, px, relative, rems, +}; +pub use gpui_macros::{ + border_style_methods, box_shadow_style_methods, cursor_style_methods, margin_style_methods, + overflow_style_methods, padding_style_methods, position_style_methods, + visibility_style_methods, +}; +const ELLIPSIS: SharedString = SharedString::new_static("…"); + +/// A trait for elements that can be styled. +/// Use this to opt-in to a utility CSS-like styling API. +// gate on rust-analyzer so rust-analyzer never needs to expand this macro, it takes up to 10 seconds to expand due to inefficiencies in rust-analyzers proc-macro srv +#[cfg_attr( + all(any(feature = "inspector", debug_assertions), not(rust_analyzer)), + gpui_macros::derive_inspector_reflection +)] +pub trait Styled: Sized { + /// Returns a reference to the style memory of this element. + fn style(&mut self) -> &mut StyleRefinement; + + gpui_macros::style_helpers!(); + gpui_macros::visibility_style_methods!(); + gpui_macros::margin_style_methods!(); + gpui_macros::padding_style_methods!(); + gpui_macros::position_style_methods!(); + gpui_macros::overflow_style_methods!(); + gpui_macros::cursor_style_methods!(); + gpui_macros::border_style_methods!(); + gpui_macros::box_shadow_style_methods!(); + + /// Sets the display type of the element to `block`. + /// [Docs](https://tailwindcss.com/docs/display) + fn block(mut self) -> Self { + self.style().display = Some(Display::Block); + self + } + + /// Sets the display type of the element to `flex`. + /// [Docs](https://tailwindcss.com/docs/display) + fn flex(mut self) -> Self { + self.style().display = Some(Display::Flex); + self + } + + /// Sets the display type of the element to `grid`. + /// [Docs](https://tailwindcss.com/docs/display) + fn grid(mut self) -> Self { + self.style().display = Some(Display::Grid); + self + } + + /// Sets the display type of the element to `none`. + /// [Docs](https://tailwindcss.com/docs/display) + fn hidden(mut self) -> Self { + self.style().display = Some(Display::None); + self + } + + /// Set the space to be reserved for rendering the scrollbar. + /// + /// This will only affect the layout of the element when overflow for this element is set to + /// `Overflow::Scroll`. + fn scrollbar_width(mut self, width: impl Into) -> Self { + self.style().scrollbar_width = Some(width.into()); + self + } + + /// Sets the whitespace of the element to `normal`. + /// [Docs](https://tailwindcss.com/docs/whitespace#normal) + fn whitespace_normal(mut self) -> Self { + self.text_style().white_space = Some(WhiteSpace::Normal); + self + } + + /// Sets the whitespace of the element to `nowrap`. + /// [Docs](https://tailwindcss.com/docs/whitespace#nowrap) + fn whitespace_nowrap(mut self) -> Self { + self.text_style().white_space = Some(WhiteSpace::Nowrap); + self + } + + /// Sets the truncate overflowing text with an ellipsis (…) at the end if needed. + /// [Docs](https://tailwindcss.com/docs/text-overflow#ellipsis) + fn text_ellipsis(mut self) -> Self { + self.text_style().text_overflow = Some(TextOverflow::Truncate(ELLIPSIS)); + self + } + + /// Sets the truncate overflowing text with an ellipsis (…) at the start if needed. + /// Typically more adequate for file paths where the end is more important than the beginning. + /// Note: This doesn't exist in Tailwind CSS. + fn text_ellipsis_start(mut self) -> Self { + self.text_style().text_overflow = Some(TextOverflow::TruncateStart(ELLIPSIS)); + self + } + + /// Sets the truncate overflowing text with an ellipsis (…) in the middle if needed. + /// Preserves the beginning and end of the text. Useful for filenames. + /// Note: This doesn't exist in Tailwind CSS. + fn text_ellipsis_middle(mut self) -> Self { + self.text_style().text_overflow = Some(TextOverflow::TruncateMiddle(ELLIPSIS)); + self + } + + /// Sets the text overflow behavior of the element. + fn text_overflow(mut self, overflow: TextOverflow) -> Self { + self.text_style().text_overflow = Some(overflow); + self + } + + /// Set the text alignment of the element. + fn text_align(mut self, align: TextAlign) -> Self { + self.text_style().text_align = Some(align); + self + } + + /// Sets the text alignment to left + fn text_left(mut self) -> Self { + self.text_align(TextAlign::Left) + } + + /// Sets the text alignment to center + fn text_center(mut self) -> Self { + self.text_align(TextAlign::Center) + } + + /// Sets the text alignment to right + fn text_right(mut self) -> Self { + self.text_align(TextAlign::Right) + } + + /// Sets the truncate to prevent text from wrapping and truncate overflowing text with an ellipsis (…) if needed. + /// [Docs](https://tailwindcss.com/docs/text-overflow#truncate) + fn truncate(mut self) -> Self { + self.overflow_hidden().whitespace_nowrap().text_ellipsis() + } + + /// Sets number of lines to show before truncating the text. + /// [Docs](https://tailwindcss.com/docs/line-clamp) + fn line_clamp(mut self, lines: usize) -> Self { + let mut text_style = self.text_style(); + text_style.line_clamp = Some(lines); + self.overflow_hidden() + } + + /// Sets the flex direction of the element to `column`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#column) + fn flex_col(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::Column); + self + } + + /// Sets the flex direction of the element to `column-reverse`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#column-reverse) + fn flex_col_reverse(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::ColumnReverse); + self + } + + /// Sets the flex direction of the element to `row`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#row) + fn flex_row(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::Row); + self + } + + /// Sets the flex direction of the element to `row-reverse`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#row-reverse) + fn flex_row_reverse(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::RowReverse); + self + } + + /// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size. + /// [Docs](https://tailwindcss.com/docs/flex#flex-1) + fn flex_1(mut self) -> Self { + self.style().flex_grow = Some(1.); + self.style().flex_shrink = Some(1.); + self.style().flex_basis = Some(relative(0.).into()); + self + } + + /// Sets the element to allow a flex item to grow and shrink, taking into account its initial size. + /// [Docs](https://tailwindcss.com/docs/flex#auto) + fn flex_auto(mut self) -> Self { + self.style().flex_grow = Some(1.); + self.style().flex_shrink = Some(1.); + self.style().flex_basis = Some(Length::Auto); + self + } + + /// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size. + /// [Docs](https://tailwindcss.com/docs/flex#initial) + fn flex_initial(mut self) -> Self { + self.style().flex_grow = Some(0.); + self.style().flex_shrink = Some(1.); + self.style().flex_basis = Some(Length::Auto); + self + } + + /// Sets the element to prevent a flex item from growing or shrinking. + /// [Docs](https://tailwindcss.com/docs/flex#none) + fn flex_none(mut self) -> Self { + self.style().flex_grow = Some(0.); + self.style().flex_shrink = Some(0.); + self.style().flex_basis = Some(Length::Auto); + self + } + + /// Sets the initial size of flex items for this element. + /// [Docs](https://tailwindcss.com/docs/flex-basis) + fn flex_basis(mut self, basis: impl Into) -> Self { + self.style().flex_basis = Some(basis.into()); + self + } + + /// Sets the flex item's grow factor. + /// [Docs](https://tailwindcss.com/docs/flex-grow) + fn flex_grow(mut self, grow: f32) -> Self { + self.style().flex_grow = Some(grow); + self + } + + /// Disables flex item growth (flex-grow: 0). + /// [Docs](https://tailwindcss.com/docs/flex-grow#dont-grow) + fn flex_grow_0(mut self) -> Self { + self.style().flex_grow = Some(0.); + self + } + + /// Enables flex item growth (flex-grow: 1). + /// [Docs](https://tailwindcss.com/docs/flex-grow#grow-1) + fn flex_grow_1(mut self) -> Self { + self.style().flex_grow = Some(1.); + self + } + + /// Sets the flex item's shrink factor. + /// [Docs](https://tailwindcss.com/docs/flex-shrink) + fn flex_shrink(mut self, shrink: f32) -> Self { + self.style().flex_shrink = Some(shrink); + self + } + + /// Disables flex item shrinking (flex-shrink: 0). + /// [Docs](https://tailwindcss.com/docs/flex-shrink#dont-shrink) + fn flex_shrink_0(mut self) -> Self { + self.style().flex_shrink = Some(0.); + self + } + + /// Enables flex item shrinking (flex-shrink: 1). + /// [Docs](https://tailwindcss.com/docs/flex-shrink#shrink-1) + fn flex_shrink_1(mut self) -> Self { + self.style().flex_shrink = Some(1.); + self + } + + /// Sets the element to allow flex items to wrap. + /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-normally) + fn flex_wrap(mut self) -> Self { + self.style().flex_wrap = Some(FlexWrap::Wrap); + self + } + + /// Sets the element wrap flex items in the reverse direction. + /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-reversed) + fn flex_wrap_reverse(mut self) -> Self { + self.style().flex_wrap = Some(FlexWrap::WrapReverse); + self + } + + /// Sets the element to prevent flex items from wrapping, causing inflexible items to overflow the container if necessary. + /// [Docs](https://tailwindcss.com/docs/flex-wrap#dont-wrap) + fn flex_nowrap(mut self) -> Self { + self.style().flex_wrap = Some(FlexWrap::NoWrap); + self + } + + /// Sets the element to align flex items to the start of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-items#start) + fn items_start(mut self) -> Self { + self.style().align_items = Some(AlignItems::FlexStart); + self + } + + /// Sets the element to align flex items to the end of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-items#end) + fn items_end(mut self) -> Self { + self.style().align_items = Some(AlignItems::FlexEnd); + self + } + + /// Sets the element to align flex items along the center of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-items#center) + fn items_center(mut self) -> Self { + self.style().align_items = Some(AlignItems::Center); + self + } + + /// Sets the element to align flex items along the baseline of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-items#baseline) + fn items_baseline(mut self) -> Self { + self.style().align_items = Some(AlignItems::Baseline); + self + } + + /// Sets the element to stretch flex items to fill the available space along the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-items#stretch) + fn items_stretch(mut self) -> Self { + self.style().align_items = Some(AlignItems::Stretch); + self + } + + /// Sets how this specific element is aligned along the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#start) + fn self_start(mut self) -> Self { + self.style().align_self = Some(AlignSelf::Start); + self + } + + /// Sets this element to align against the end of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#end) + fn self_end(mut self) -> Self { + self.style().align_self = Some(AlignSelf::End); + self + } + + /// Sets this element to align against the start of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#start) + fn self_flex_start(mut self) -> Self { + self.style().align_self = Some(AlignSelf::FlexStart); + self + } + + /// Sets this element to align against the end of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#end) + fn self_flex_end(mut self) -> Self { + self.style().align_self = Some(AlignSelf::FlexEnd); + self + } + + /// Sets this element to align along the center of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#center) + fn self_center(mut self) -> Self { + self.style().align_self = Some(AlignSelf::Center); + self + } + + /// Sets this element to align along the baseline of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#baseline) + fn self_baseline(mut self) -> Self { + self.style().align_self = Some(AlignSelf::Baseline); + self + } + + /// Sets this element to stretch to fill the available space along the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-self#stretch) + fn self_stretch(mut self) -> Self { + self.style().align_self = Some(AlignSelf::Stretch); + self + } + + /// Sets the element to justify flex items against the start of the container's main axis. + /// [Docs](https://tailwindcss.com/docs/justify-content#start) + fn justify_start(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::Start); + self + } + + /// Sets the element to justify flex items against the end of the container's main axis. + /// [Docs](https://tailwindcss.com/docs/justify-content#end) + fn justify_end(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::End); + self + } + + /// Sets the element to justify flex items along the center of the container's main axis. + /// [Docs](https://tailwindcss.com/docs/justify-content#center) + fn justify_center(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::Center); + self + } + + /// Sets the element to justify flex items along the container's main axis + /// such that there is an equal amount of space between each item. + /// [Docs](https://tailwindcss.com/docs/justify-content#space-between) + fn justify_between(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::SpaceBetween); + self + } + + /// Sets the element to justify items along the container's main axis such + /// that there is an equal amount of space on each side of each item. + /// [Docs](https://tailwindcss.com/docs/justify-content#space-around) + fn justify_around(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::SpaceAround); + self + } + + /// Sets the element to justify items along the container's main axis such + /// that there is an equal amount of space around each item, but also + /// accounting for the doubling of space you would normally see between + /// each item when using justify-around. + /// [Docs](https://tailwindcss.com/docs/justify-content#space-evenly) + fn justify_evenly(mut self) -> Self { + self.style().justify_content = Some(JustifyContent::SpaceEvenly); + self + } + + /// Sets the element to pack content items in their default position as if no align-content value was set. + /// [Docs](https://tailwindcss.com/docs/align-content#normal) + fn content_normal(mut self) -> Self { + self.style().align_content = None; + self + } + + /// Sets the element to pack content items in the center of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-content#center) + fn content_center(mut self) -> Self { + self.style().align_content = Some(AlignContent::Center); + self + } + + /// Sets the element to pack content items against the start of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-content#start) + fn content_start(mut self) -> Self { + self.style().align_content = Some(AlignContent::FlexStart); + self + } + + /// Sets the element to pack content items against the end of the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-content#end) + fn content_end(mut self) -> Self { + self.style().align_content = Some(AlignContent::FlexEnd); + self + } + + /// Sets the element to pack content items along the container's cross axis + /// such that there is an equal amount of space between each item. + /// [Docs](https://tailwindcss.com/docs/align-content#space-between) + fn content_between(mut self) -> Self { + self.style().align_content = Some(AlignContent::SpaceBetween); + self + } + + /// Sets the element to pack content items along the container's cross axis + /// such that there is an equal amount of space on each side of each item. + /// [Docs](https://tailwindcss.com/docs/align-content#space-around) + fn content_around(mut self) -> Self { + self.style().align_content = Some(AlignContent::SpaceAround); + self + } + + /// Sets the element to pack content items along the container's cross axis + /// such that there is an equal amount of space between each item. + /// [Docs](https://tailwindcss.com/docs/align-content#space-evenly) + fn content_evenly(mut self) -> Self { + self.style().align_content = Some(AlignContent::SpaceEvenly); + self + } + + /// Sets the element to allow content items to fill the available space along the container's cross axis. + /// [Docs](https://tailwindcss.com/docs/align-content#stretch) + fn content_stretch(mut self) -> Self { + self.style().align_content = Some(AlignContent::Stretch); + self + } + + /// Sets the aspect ratio of the element. + /// [Docs](https://tailwindcss.com/docs/aspect-ratio) + fn aspect_ratio(mut self, ratio: f32) -> Self { + self.style().aspect_ratio = Some(ratio); + self + } + + /// Sets the aspect ratio of the element to 1/1 – equal width and height. + /// [Docs](https://tailwindcss.com/docs/aspect-ratio) + fn aspect_square(mut self) -> Self { + self.style().aspect_ratio = Some(1.0); + self + } + + /// Sets the background color of the element. + fn bg(mut self, fill: F) -> Self + where + F: Into, + Self: Sized, + { + self.style().background = Some(fill.into()); + self + } + + /// Sets the border style of the element. + fn border_dashed(mut self) -> Self { + self.style().border_style = Some(BorderStyle::Dashed); + self + } + + /// Returns a mutable reference to the text style that has been configured on this element. + fn text_style(&mut self) -> &mut TextStyleRefinement { + let style: &mut StyleRefinement = self.style(); + &mut style.text + } + + /// Sets the text color of this element. + /// + /// This value cascades to its child elements. + fn text_color(mut self, color: impl Into) -> Self { + self.text_style().color = Some(color.into()); + self + } + + /// Sets the font weight of this element + /// + /// This value cascades to its child elements. + fn font_weight(mut self, weight: FontWeight) -> Self { + self.text_style().font_weight = Some(weight); + self + } + + /// Sets the background color of this element. + /// + /// This value cascades to its child elements. + fn text_bg(mut self, bg: impl Into) -> Self { + self.text_style().background_color = Some(bg.into()); + self + } + + /// Sets the text size of this element. + /// + /// This value cascades to its child elements. + fn text_size(mut self, size: impl Into) -> Self { + self.text_style().font_size = Some(size.into()); + self + } + + /// Sets the text size to 'extra small'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_xs(mut self) -> Self { + self.text_style().font_size = Some(rems(0.75).into()); + self + } + + /// Sets the text size to 'small'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_sm(mut self) -> Self { + self.text_style().font_size = Some(rems(0.875).into()); + self + } + + /// Sets the text size to 'base'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_base(mut self) -> Self { + self.text_style().font_size = Some(rems(1.0).into()); + self + } + + /// Sets the text size to 'large'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_lg(mut self) -> Self { + self.text_style().font_size = Some(rems(1.125).into()); + self + } + + /// Sets the text size to 'extra large'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_xl(mut self) -> Self { + self.text_style().font_size = Some(rems(1.25).into()); + self + } + + /// Sets the text size to 'extra extra large'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_2xl(mut self) -> Self { + self.text_style().font_size = Some(rems(1.5).into()); + self + } + + /// Sets the text size to 'extra extra extra large'. + /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size) + fn text_3xl(mut self) -> Self { + self.text_style().font_size = Some(rems(1.875).into()); + self + } + + /// Sets the font style of the element to italic. + /// [Docs](https://tailwindcss.com/docs/font-style#italicizing-text) + fn italic(mut self) -> Self { + self.text_style().font_style = Some(FontStyle::Italic); + self + } + + /// Sets the font style of the element to normal (not italic). + /// [Docs](https://tailwindcss.com/docs/font-style#displaying-text-normally) + fn not_italic(mut self) -> Self { + self.text_style().font_style = Some(FontStyle::Normal); + self + } + + /// Sets the text decoration to underline. + /// [Docs](https://tailwindcss.com/docs/text-decoration-line#underling-text) + fn underline(mut self) -> Self { + let style = self.text_style(); + style.underline = Some(UnderlineStyle { + thickness: px(1.), + ..Default::default() + }); + self + } + + /// Sets the decoration of the text to have a line through it. + /// [Docs](https://tailwindcss.com/docs/text-decoration-line#adding-a-line-through-text) + fn line_through(mut self) -> Self { + let style = self.text_style(); + style.strikethrough = Some(StrikethroughStyle { + thickness: px(1.), + ..Default::default() + }); + self + } + + /// Removes the text decoration on this element. + /// + /// This value cascades to its child elements. + fn text_decoration_none(mut self) -> Self { + self.text_style().underline = None; + self + } + + /// Sets the color for the underline on this element + fn text_decoration_color(mut self, color: impl Into) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.color = Some(color.into()); + self + } + + /// Sets the text decoration style to a solid line. + /// [Docs](https://tailwindcss.com/docs/text-decoration-style) + fn text_decoration_solid(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.wavy = false; + self + } + + /// Sets the text decoration style to a wavy line. + /// [Docs](https://tailwindcss.com/docs/text-decoration-style) + fn text_decoration_wavy(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.wavy = true; + self + } + + /// Sets the text decoration to be 0px thick. + /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness) + fn text_decoration_0(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.thickness = px(0.); + self + } + + /// Sets the text decoration to be 1px thick. + /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness) + fn text_decoration_1(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.thickness = px(1.); + self + } + + /// Sets the text decoration to be 2px thick. + /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness) + fn text_decoration_2(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.thickness = px(2.); + self + } + + /// Sets the text decoration to be 4px thick. + /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness) + fn text_decoration_4(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.thickness = px(4.); + self + } + + /// Sets the text decoration to be 8px thick. + /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness) + fn text_decoration_8(mut self) -> Self { + let style = self.text_style(); + let underline = style.underline.get_or_insert_with(Default::default); + underline.thickness = px(8.); + self + } + + /// Sets the font family of this element and its children. + fn font_family(mut self, family_name: impl Into) -> Self { + self.text_style().font_family = Some(family_name.into()); + self + } + + /// Sets the font features of this element and its children. + fn font_features(mut self, features: FontFeatures) -> Self { + self.text_style().font_features = Some(features); + self + } + + /// Sets the font of this element and its children. + fn font(mut self, font: Font) -> Self { + let Font { + family, + features, + fallbacks, + weight, + style, + } = font; + + let text_style = self.text_style(); + text_style.font_family = Some(family); + text_style.font_features = Some(features); + text_style.font_weight = Some(weight); + text_style.font_style = Some(style); + text_style.font_fallbacks = fallbacks; + + self + } + + /// Sets the line height of this element and its children. + fn line_height(mut self, line_height: impl Into) -> Self { + self.text_style().line_height = Some(line_height.into()); + self + } + + /// Sets the opacity of this element and its children. + fn opacity(mut self, opacity: f32) -> Self { + self.style().opacity = Some(opacity); + self + } + + /// Sets the grid columns of this element. + fn grid_cols(mut self, cols: u16) -> Self { + self.style().grid_cols = Some(GridTemplate { + repeat: cols, + min_size: GridTemplateMinSize::Zero, + }); + self + } + + /// Sets the grid columns with min-content minimum sizing. + /// Unlike grid_cols, it won't shrink to width 0 in AvailableSpace::MinContent constraints. + fn grid_cols_min_content(mut self, cols: u16) -> Self { + self.style().grid_cols = Some(GridTemplate { + repeat: cols, + min_size: GridTemplateMinSize::MinContent, + }); + self + } + + /// Sets the grid columns with max-content maximum sizing for content-based column widths. + fn grid_cols_max_content(mut self, cols: u16) -> Self { + self.style().grid_cols = Some(GridTemplate { + repeat: cols, + min_size: GridTemplateMinSize::MaxContent, + }); + self + } + + /// Sets the grid rows of this element. + fn grid_rows(mut self, rows: u16) -> Self { + self.style().grid_rows = Some(GridTemplate { + repeat: rows, + min_size: GridTemplateMinSize::Zero, + }); + self + } + + /// Sets the grid rows with min-content minimum sizing. + /// Unlike grid_rows, it won't shrink to height 0 in AvailableSpace::MinContent constraints. + fn grid_rows_min_content(mut self, rows: u16) -> Self { + self.style().grid_rows = Some(GridTemplate { + repeat: rows, + min_size: GridTemplateMinSize::MinContent, + }); + self + } + + /// Sets the grid rows with max-content maximum sizing for content-based row heights. + fn grid_rows_max_content(mut self, rows: u16) -> Self { + self.style().grid_rows = Some(GridTemplate { + repeat: rows, + min_size: GridTemplateMinSize::MaxContent, + }); + self + } + + /// Sets the column start of this element. + fn col_start(mut self, start: i16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column.start = GridPlacement::Line(start); + self + } + + /// Sets the column start of this element to auto. + fn col_start_auto(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column.start = GridPlacement::Auto; + self + } + + /// Sets the column end of this element. + fn col_end(mut self, end: i16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column.end = GridPlacement::Line(end); + self + } + + /// Sets the column end of this element to auto. + fn col_end_auto(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column.end = GridPlacement::Auto; + self + } + + /// Sets the column span of this element. + fn col_span(mut self, span: u16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column = GridPlacement::Span(span)..GridPlacement::Span(span); + self + } + + /// Sets the row span of this element. + fn col_span_full(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.column = GridPlacement::Line(1)..GridPlacement::Line(-1); + self + } + + /// Sets the row start of this element. + fn row_start(mut self, start: i16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row.start = GridPlacement::Line(start); + self + } + + /// Sets the row start of this element to "auto" + fn row_start_auto(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row.start = GridPlacement::Auto; + self + } + + /// Sets the row end of this element. + fn row_end(mut self, end: i16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row.end = GridPlacement::Line(end); + self + } + + /// Sets the row end of this element to "auto" + fn row_end_auto(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row.end = GridPlacement::Auto; + self + } + + /// Sets the row span of this element. + fn row_span(mut self, span: u16) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row = GridPlacement::Span(span)..GridPlacement::Span(span); + self + } + + /// Sets the row span of this element. + fn row_span_full(mut self) -> Self { + let grid_location = self.style().grid_location_mut(); + grid_location.row = GridPlacement::Line(1)..GridPlacement::Line(-1); + self + } + + /// Draws a debug border around this element. + #[cfg(debug_assertions)] + fn debug(mut self) -> Self { + self.style().debug = Some(true); + self + } + + /// Draws a debug border on all conforming elements below this element. + #[cfg(debug_assertions)] + fn debug_below(mut self) -> Self { + self.style().debug_below = Some(true); + self + } +} diff --git a/vendor/gpui-pre/src/subscription.rs b/vendor/gpui-pre/src/subscription.rs new file mode 100644 index 00000000..b0c55a39 --- /dev/null +++ b/vendor/gpui-pre/src/subscription.rs @@ -0,0 +1,351 @@ +use collections::BTreeMap; +use gpui_util::post_inc; +use std::{ + cell::{Cell, RefCell}, + fmt::Debug, + rc::Rc, +}; + +pub(crate) struct SubscriberSet( + Rc>>, +); + +impl Clone for SubscriberSet { + fn clone(&self) -> Self { + SubscriberSet(self.0.clone()) + } +} + +struct SubscriberSetState { + subscribers: BTreeMap>>>, + next_subscriber_id: usize, +} + +struct Subscriber { + active: Rc>, + dropped: Rc>, + callback: Callback, +} + +impl SubscriberSet +where + EmitterKey: 'static + Ord + Clone + Debug, + Callback: 'static, +{ + pub fn new() -> Self { + Self(Rc::new(RefCell::new(SubscriberSetState { + subscribers: Default::default(), + next_subscriber_id: 0, + }))) + } + + /// Inserts a new [`Subscription`] for the given `emitter_key`. By default, subscriptions + /// are inert, meaning that they won't be listed when calling `[SubscriberSet::remove]` or `[SubscriberSet::retain]`. + /// This method returns a tuple of a [`Subscription`] and an `impl FnOnce`, and you can use the latter + /// to activate the [`Subscription`]. + pub fn insert( + &self, + emitter_key: EmitterKey, + callback: Callback, + ) -> (Subscription, impl FnOnce() + use) { + let active = Rc::new(Cell::new(false)); + let dropped = Rc::new(Cell::new(false)); + let mut lock = self.0.borrow_mut(); + let subscriber_id = post_inc(&mut lock.next_subscriber_id); + lock.subscribers + .entry(emitter_key.clone()) + .or_default() + .get_or_insert_with(Default::default) + .insert( + subscriber_id, + Subscriber { + active: active.clone(), + dropped: dropped.clone(), + callback, + }, + ); + let this = self.0.clone(); + + let subscription = Subscription { + unsubscribe: Some(Box::new(move || { + dropped.set(true); + + let mut lock = this.borrow_mut(); + let Some(subscribers) = lock.subscribers.get_mut(&emitter_key) else { + return; + }; + + if let Some(subscribers) = subscribers { + subscribers.remove(&subscriber_id); + if subscribers.is_empty() { + lock.subscribers.remove(&emitter_key); + } + } + })), + }; + (subscription, move || active.set(true)) + } + + pub fn remove( + &self, + emitter: &EmitterKey, + ) -> impl IntoIterator + use { + let subscribers = self.0.borrow_mut().subscribers.remove(emitter); + subscribers + .unwrap_or_default() + .map(|s| s.into_values()) + .into_iter() + .flatten() + .filter_map(|subscriber| { + if subscriber.active.get() { + Some(subscriber.callback) + } else { + None + } + }) + } + + /// Call the given callback for each subscriber to the given emitter. + /// If the callback returns false, the subscriber is removed. + pub fn retain(&self, emitter: &EmitterKey, mut f: F) + where + F: FnMut(&mut Callback) -> bool, + { + let Some(mut subscribers) = self + .0 + .borrow_mut() + .subscribers + .get_mut(emitter) + .and_then(|s| s.take()) + else { + return; + }; + + subscribers.retain(|_, subscriber| { + if !subscriber.active.get() { + return true; + } + if subscriber.dropped.get() { + return false; + } + let keep = f(&mut subscriber.callback); + keep && !subscriber.dropped.get() + }); + let mut lock = self.0.borrow_mut(); + + // Add any new subscribers that were added while invoking the callback. + if let Some(Some(new_subscribers)) = lock.subscribers.remove(emitter) { + subscribers.extend(new_subscribers); + } + + if !subscribers.is_empty() { + lock.subscribers.insert(emitter.clone(), Some(subscribers)); + } + } +} + +/// A handle to a subscription created by GPUI. When dropped, the subscription +/// is cancelled and the callback will no longer be invoked. +#[must_use] +pub struct Subscription { + unsubscribe: Option>, +} + +impl Subscription { + /// Creates a new subscription with a callback that gets invoked when + /// this subscription is dropped. + pub fn new(unsubscribe: impl 'static + FnOnce()) -> Self { + Self { + unsubscribe: Some(Box::new(unsubscribe)), + } + } + + /// Detaches the subscription from this handle. The callback will + /// continue to be invoked until the entities it has been + /// subscribed to are dropped + pub fn detach(mut self) { + self.unsubscribe.take(); + } + + /// Joins two subscriptions into a single subscription. Detach will + /// detach both interior subscriptions. + pub fn join(mut subscription_a: Self, mut subscription_b: Self) -> Self { + let a_unsubscribe = subscription_a.unsubscribe.take(); + let b_unsubscribe = subscription_b.unsubscribe.take(); + Self { + unsubscribe: Some(Box::new(move || { + if let Some(self_unsubscribe) = a_unsubscribe { + self_unsubscribe(); + } + if let Some(other_unsubscribe) = b_unsubscribe { + other_unsubscribe(); + } + })), + } + } +} + +impl Drop for Subscription { + fn drop(&mut self) { + if let Some(unsubscribe) = self.unsubscribe.take() { + unsubscribe(); + } + } +} + +impl std::fmt::Debug for Subscription { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Subscription").finish() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Global, TestApp}; + + #[test] + fn test_unsubscribe_during_callback_with_insert() { + struct TestGlobal; + impl Global for TestGlobal {} + + let mut app = TestApp::new(); + app.set_global(TestGlobal); + + let observer_a_count = Rc::new(Cell::new(0usize)); + let observer_b_count = Rc::new(Cell::new(0usize)); + + let sub_a: Rc>> = Default::default(); + let sub_b: Rc>> = Default::default(); + + // Observer A fires first (lower subscriber_id). It drops itself and + // inserts a new observer for the same global. + *sub_a.borrow_mut() = Some(app.update({ + let count = observer_a_count.clone(); + let sub_a = sub_a.clone(); + move |cx| { + cx.observe_global::(move |cx| { + count.set(count.get() + 1); + sub_a.borrow_mut().take(); + cx.observe_global::(|_| {}).detach(); + }) + } + })); + + // Observer B fires second. It just drops itself. + *sub_b.borrow_mut() = Some(app.update({ + let count = observer_b_count.clone(); + let sub_b = sub_b.clone(); + move |cx| { + cx.observe_global::(move |_cx| { + count.set(count.get() + 1); + sub_b.borrow_mut().take(); + }) + } + })); + + // Both fire once. + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!(observer_a_count.get(), 1); + assert_eq!(observer_b_count.get(), 1); + + // Neither should fire again — both dropped their subscriptions. + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!(observer_a_count.get(), 1); + assert_eq!(observer_b_count.get(), 1, "orphaned subscriber fired again"); + } + + #[test] + fn test_callback_dropped_by_earlier_callback_does_not_fire() { + struct TestGlobal; + impl Global for TestGlobal {} + + let mut app = TestApp::new(); + app.set_global(TestGlobal); + + let observer_b_count = Rc::new(Cell::new(0usize)); + let sub_b: Rc>> = Default::default(); + + // Observer A fires first and drops B's subscription. + app.update({ + let sub_b = sub_b.clone(); + move |cx| { + cx.observe_global::(move |_cx| { + sub_b.borrow_mut().take(); + }) + .detach(); + } + }); + + // Observer B fires second — but A already dropped it. + *sub_b.borrow_mut() = Some(app.update({ + let count = observer_b_count.clone(); + move |cx| { + cx.observe_global::(move |_cx| { + count.set(count.get() + 1); + }) + } + })); + + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!( + observer_b_count.get(), + 0, + "B should not fire — A dropped its subscription" + ); + } + + #[test] + fn test_self_drop_during_callback() { + struct TestGlobal; + impl Global for TestGlobal {} + + let mut app = TestApp::new(); + app.set_global(TestGlobal); + + let count = Rc::new(Cell::new(0usize)); + let sub: Rc>> = Default::default(); + + *sub.borrow_mut() = Some(app.update({ + let count = count.clone(); + let sub = sub.clone(); + move |cx| { + cx.observe_global::(move |_cx| { + count.set(count.get() + 1); + sub.borrow_mut().take(); + }) + } + })); + + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!(count.get(), 1); + + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!(count.get(), 1, "should not fire after self-drop"); + } + + #[test] + fn test_subscription_drop() { + struct TestGlobal; + impl Global for TestGlobal {} + + let mut app = TestApp::new(); + app.set_global(TestGlobal); + + let count = Rc::new(Cell::new(0usize)); + + let subscription = app.update({ + let count = count.clone(); + move |cx| { + cx.observe_global::(move |_cx| { + count.set(count.get() + 1); + }) + } + }); + + drop(subscription); + + app.update(|cx| cx.set_global(TestGlobal)); + assert_eq!(count.get(), 0, "should not fire after drop"); + } +} diff --git a/vendor/gpui-pre/src/svg_renderer.rs b/vendor/gpui-pre/src/svg_renderer.rs new file mode 100644 index 00000000..798fb2a9 --- /dev/null +++ b/vendor/gpui-pre/src/svg_renderer.rs @@ -0,0 +1,525 @@ +use crate::{ + AssetSource, DevicePixels, IsZero, RenderImage, Result, SharedString, Size, + swap_rgba_pa_to_bgra, +}; +use image::Frame; +use resvg::tiny_skia::Pixmap; +use smallvec::SmallVec; +use std::{ + hash::Hash, + sync::{Arc, LazyLock, OnceLock}, +}; + +#[cfg(target_os = "macos")] +const EMOJI_FONT_FAMILIES: &[&str] = &["Apple Color Emoji", ".AppleColorEmojiUI"]; + +#[cfg(target_os = "windows")] +const EMOJI_FONT_FAMILIES: &[&str] = &["Segoe UI Emoji", "Segoe UI Symbol"]; + +#[cfg(any(target_os = "linux", target_os = "freebsd"))] +const EMOJI_FONT_FAMILIES: &[&str] = &[ + "Noto Color Emoji", + "Emoji One", + "Twitter Color Emoji", + "JoyPixels", +]; + +#[cfg(not(any( + target_os = "macos", + target_os = "windows", + target_os = "linux", + target_os = "freebsd", +)))] +const EMOJI_FONT_FAMILIES: &[&str] = &[]; + +fn is_emoji_presentation(c: char) -> bool { + static EMOJI_PRESENTATION_REGEX: LazyLock = + LazyLock::new(|| regex::Regex::new("\\p{Emoji_Presentation}").unwrap()); + let mut buf = [0u8; 4]; + EMOJI_PRESENTATION_REGEX.is_match(c.encode_utf8(&mut buf)) +} + +fn font_has_char(db: &usvg::fontdb::Database, id: usvg::fontdb::ID, ch: char) -> bool { + db.with_face_data(id, |font_data, face_index| { + ttf_parser::Face::parse(font_data, face_index) + .ok() + .and_then(|face| face.glyph_index(ch)) + .is_some() + }) + .unwrap_or(false) +} + +fn select_emoji_font( + ch: char, + fonts: &[usvg::fontdb::ID], + db: &usvg::fontdb::Database, + families: &[&str], +) -> Option { + for family_name in families { + let query = usvg::fontdb::Query { + families: &[usvg::fontdb::Family::Name(family_name)], + weight: usvg::fontdb::Weight(400), + stretch: usvg::fontdb::Stretch::Normal, + style: usvg::fontdb::Style::Normal, + }; + + let Some(id) = db.query(&query) else { + continue; + }; + + if fonts.contains(&id) || !font_has_char(db, id, ch) { + continue; + } + + return Some(id); + } + + None +} + +/// When rendering SVGs, we render them at twice the size to get a higher-quality result. +pub const SMOOTH_SVG_SCALE_FACTOR: f32 = 2.; + +#[derive(Clone, PartialEq, Hash, Eq)] +#[expect(missing_docs)] +pub struct RenderSvgParams { + pub path: SharedString, + pub size: Size, +} + +#[derive(Clone)] +/// A struct holding everything necessary to render SVGs. +pub struct SvgRenderer { + asset_source: Arc, + usvg_options: Arc>, +} + +/// A parsed SVG document that can be rasterized at any scale. +/// +/// Produced by [`SvgRenderer::parse_svg`] and rasterized by +/// [`SvgRenderer::render_parsed`]. Parsing resolves fonts and converts text +/// to paths, so callers that need to rasterize the same SVG at multiple +/// scales should retain this value to avoid re-paying the parse cost. +pub struct ParsedSvg(usvg::Tree); + +/// The size in which to rasterize the SVG. +#[derive(Clone, Copy)] +pub enum SvgSize { + /// A width in device pixels. The SVG retains its aspect ratio. + Size(Size), + /// An exact width and height in device pixels. + ExactSize(Size), + /// A logical scaling factor to apply to the size provided by the SVG. + ScaleFactor(f32), +} + +impl From for SvgSize { + fn from(scale_factor: f32) -> Self { + Self::ScaleFactor(scale_factor) + } +} + +impl SvgRenderer { + /// Creates a new SVG renderer with the provided asset source. + pub fn new(asset_source: Arc) -> Self { + static SYSTEM_FONT_DB: LazyLock> = LazyLock::new(|| { + let mut db = usvg::fontdb::Database::new(); + db.load_system_fonts(); + Arc::new(db) + }); + + // Build the enriched font DB lazily on first SVG render rather than + // eagerly at construction time. This avoids the expensive deep-clone + // of the system font database for code paths that never render SVGs + // (e.g. tests). + let enriched_fontdb: Arc>> = Arc::new(OnceLock::new()); + + let default_font_resolver = usvg::FontResolver::default_font_selector(); + let font_resolver = Box::new({ + let asset_source = asset_source.clone(); + move |font: &usvg::Font, db: &mut Arc| { + if db.is_empty() { + let fontdb = enriched_fontdb.get_or_init(|| { + let mut db = (**SYSTEM_FONT_DB).clone(); + load_bundled_fonts(&*asset_source, &mut db); + fix_generic_font_families(&mut db); + Arc::new(db) + }); + *db = fontdb.clone(); + } + if let Some(id) = default_font_resolver(font, db) { + return Some(id); + } + // fontdb doesn't recognize CSS system font keywords like "system-ui" + // or "ui-sans-serif", so fall back to sans-serif before any face. + let sans_query = usvg::fontdb::Query { + families: &[usvg::fontdb::Family::SansSerif], + ..Default::default() + }; + db.query(&sans_query) + .or_else(|| db.faces().next().map(|f| f.id)) + } + }); + let default_fallback_selection = usvg::FontResolver::default_fallback_selector(); + let fallback_selection = Box::new( + move |ch: char, fonts: &[usvg::fontdb::ID], db: &mut Arc| { + if is_emoji_presentation(ch) { + if let Some(id) = select_emoji_font(ch, fonts, db.as_ref(), EMOJI_FONT_FAMILIES) + { + return Some(id); + } + } + + default_fallback_selection(ch, fonts, db) + }, + ); + let options = usvg::Options { + font_resolver: usvg::FontResolver { + select_font: font_resolver, + select_fallback: fallback_selection, + }, + ..Default::default() + }; + Self { + asset_source, + usvg_options: Arc::new(options), + } + } + + /// Parses SVG data into a [`ParsedSvg`] that can be rasterized at any scale. + pub fn parse_svg(&self, bytes: &[u8]) -> Result { + usvg::Tree::from_data(bytes, &self.usvg_options).map(ParsedSvg) + } + + /// Rasterizes a previously parsed SVG into an image buffer. + pub fn render_parsed( + &self, + svg: &ParsedSvg, + size: impl Into, + ) -> Result, usvg::Error> { + let (size, image_scale_factor) = match size.into() { + SvgSize::Size(size) => (SvgSize::Size(size), 1.0), + SvgSize::ExactSize(size) => (SvgSize::ExactSize(size), 1.0), + SvgSize::ScaleFactor(scale_factor) => ( + SvgSize::ScaleFactor(scale_factor * SMOOTH_SVG_SCALE_FACTOR), + SMOOTH_SVG_SCALE_FACTOR, + ), + }; + let pixmap = rasterize_tree(&svg.0, size)?; + let mut buffer = + image::ImageBuffer::from_raw(pixmap.width(), pixmap.height(), pixmap.take()).unwrap(); + + for pixel in buffer.chunks_exact_mut(4) { + swap_rgba_pa_to_bgra(pixel); + } + + let mut image = RenderImage::new(SmallVec::from_const([Frame::new(buffer)])); + image.scale_factor = image_scale_factor; + Ok(Arc::new(image)) + } + + /// Renders the given bytes into an image buffer. + pub fn render_single_frame( + &self, + bytes: &[u8], + scale_factor: f32, + ) -> Result, usvg::Error> { + let svg = self.parse_svg(bytes)?; + self.render_parsed(&svg, scale_factor) + } + + pub(crate) fn render_alpha_mask( + &self, + params: &RenderSvgParams, + bytes: Option<&[u8]>, + ) -> Result, Vec)>> { + anyhow::ensure!(!params.size.is_zero(), "can't render at a zero size"); + + let render_pixmap = |bytes| { + let pixmap = self.render_pixmap(bytes, SvgSize::Size(params.size))?; + + // Convert the pixmap's pixels into an alpha mask. + let size = Size::new( + DevicePixels(pixmap.width() as i32), + DevicePixels(pixmap.height() as i32), + ); + let alpha_mask = pixmap + .pixels() + .iter() + .map(|p| p.alpha()) + .collect::>(); + + Ok(Some((size, alpha_mask))) + }; + + if let Some(bytes) = bytes { + render_pixmap(bytes) + } else if let Some(bytes) = self.asset_source.load(¶ms.path)? { + render_pixmap(&bytes) + } else { + Ok(None) + } + } + + fn render_pixmap(&self, bytes: &[u8], size: SvgSize) -> Result { + let tree = usvg::Tree::from_data(bytes, &self.usvg_options)?; + rasterize_tree(&tree, size) + } +} + +fn rasterize_tree(tree: &usvg::Tree, size: SvgSize) -> Result { + // Cap the size of the rendered pixmap to avoid texture allocation panics + // Related issue: #56466 + const MAX_SIZE: f32 = 8192.0; + + let svg_size = tree.size(); + let (mut width, mut height) = match size { + SvgSize::Size(size) => { + let scale = i32::from(size.width) as f32 / svg_size.width(); + (svg_size.width() * scale, svg_size.height() * scale) + } + SvgSize::ExactSize(size) => (i32::from(size.width) as f32, i32::from(size.height) as f32), + SvgSize::ScaleFactor(scale) => (svg_size.width() * scale, svg_size.height() * scale), + }; + + if width > MAX_SIZE { + log::warn!("Attempted to render pixmap where width ({width}) > MAX_SIZE ({MAX_SIZE})"); + } + if height > MAX_SIZE { + log::warn!("Attempted to render pixmap where height ({height}) > MAX_SIZE ({MAX_SIZE})"); + } + let scale = (MAX_SIZE / width).min(MAX_SIZE / height).min(1.0); + width *= scale; + height *= scale; + + // Render the SVG to a pixmap with the specified width and height. + let mut pixmap = resvg::tiny_skia::Pixmap::new(width as u32, height as u32) + .ok_or(usvg::Error::InvalidSize)?; + + let transform = resvg::tiny_skia::Transform::from_scale( + width / svg_size.width(), + height / svg_size.height(), + ); + + resvg::render(tree, transform, &mut pixmap.as_mut()); + + Ok(pixmap) +} + +fn load_bundled_fonts(asset_source: &dyn AssetSource, db: &mut usvg::fontdb::Database) { + let font_paths = [ + "fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf", + "fonts/lilex/Lilex-Regular.ttf", + ]; + for path in font_paths { + match asset_source.load(path) { + Ok(Some(data)) => db.load_font_data(data.into_owned()), + Ok(None) => log::warn!("Bundled font not found: {path}"), + Err(error) => log::warn!("Failed to load bundled font {path}: {error}"), + } + } +} + +// fontdb defaults generic families to Microsoft fonts ("Arial", "Times New Roman") +// which aren't installed on most Linux systems. fontconfig normally overrides these, +// but when it fails the defaults remain and all generic family queries return None. +fn fix_generic_font_families(db: &mut usvg::fontdb::Database) { + use usvg::fontdb::{Family, Query}; + + let families_and_fallbacks: &[(Family<'_>, &str)] = &[ + (Family::SansSerif, "IBM Plex Sans"), + // No serif font bundled; use sans-serif as best available fallback. + (Family::Serif, "IBM Plex Sans"), + (Family::Monospace, "Lilex"), + (Family::Cursive, "IBM Plex Sans"), + (Family::Fantasy, "IBM Plex Sans"), + ]; + + for (family, fallback_name) in families_and_fallbacks { + let query = Query { + families: &[*family], + ..Default::default() + }; + if db.query(&query).is_none() { + match family { + Family::SansSerif => db.set_sans_serif_family(*fallback_name), + Family::Serif => db.set_serif_family(*fallback_name), + Family::Monospace => db.set_monospace_family(*fallback_name), + Family::Cursive => db.set_cursive_family(*fallback_name), + Family::Fantasy => db.set_fantasy_family(*fallback_name), + _ => {} + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use usvg::fontdb::{Database, Family, Query}; + + const IBM_PLEX_REGULAR: &[u8] = + include_bytes!("../../../assets/fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf"); + const LILEX_REGULAR: &[u8] = include_bytes!("../../../assets/fonts/lilex/Lilex-Regular.ttf"); + + #[test] + fn renders_parsed_svg_at_requested_size() -> Result<()> { + let renderer = SvgRenderer::new(Arc::new(())); + let svg = renderer.parse_svg( + br#""#, + )?; + let requested_size = Size::new(DevicePixels(24), DevicePixels(12)); + let image = renderer.render_parsed(&svg, SvgSize::ExactSize(requested_size))?; + + assert_eq!(image.size(0), requested_size); + Ok(()) + } + + #[test] + fn preserves_aspect_ratio_for_width_constrained_size() -> Result<()> { + let renderer = SvgRenderer::new(Arc::new(())); + let svg = renderer.parse_svg( + br#""#, + )?; + let image = renderer.render_parsed( + &svg, + SvgSize::Size(Size::new(DevicePixels(24), DevicePixels(24))), + )?; + + assert_eq!(image.size(0), Size::new(DevicePixels(24), DevicePixels(12))); + Ok(()) + } + + fn db_with_bundled_fonts() -> Database { + let mut db = Database::new(); + db.load_font_data(IBM_PLEX_REGULAR.to_vec()); + db.load_font_data(LILEX_REGULAR.to_vec()); + db + } + + #[test] + fn text_with_split_glyph_clusters_in_mixed_fonts_does_not_panic() { + let mut db = Database::new(); + db.load_font_data(IBM_PLEX_REGULAR.to_vec()); + db.load_font_data(LILEX_REGULAR.to_vec()); + let options = usvg::Options { + fontdb: std::sync::Arc::new(db), + ..Default::default() + }; + + // A base letter followed by a stack of combining marks. Under HarfBuzz's + // default cluster merging every mark glyph shares the base's byte index, + // which is the "glyph splitting" condition that triggered the panic. The + // chunk must use two different fonts so the buggy merge path runs. + let zalgo = "e\u{0301}\u{0302}\u{0303}\u{0304}\u{0306}\u{0307}\u{0308}\u{030a}"; + let svg = format!( + r#"{zalgo}{zalgo}"# + ); + + // Before the fix this aborts via panic with a message like + // "removal index (is 5) should be < len (is 5)". + usvg::Tree::from_data(svg.as_bytes(), &options) + .expect("SVG with mixed-font text should parse"); + } + + #[test] + fn test_is_emoji_presentation() { + let cases = [ + ("a", false), + ("Z", false), + ("1", false), + ("#", false), + ("*", false), + ("漢", false), + ("中", false), + ("カ", false), + ("©", false), + ("♥", false), + ("😀", true), + ("✅", true), + ("🇺🇸", true), + // SVG fallback is not cluster-aware yet + ("©️", false), + ("♥️", false), + ("1️⃣", false), + ]; + for (s, expected) in cases { + assert_eq!( + is_emoji_presentation(s.chars().next().unwrap()), + expected, + "for char {:?}", + s + ); + } + } + + #[test] + fn fix_generic_font_families_sets_all_families() { + let mut db = db_with_bundled_fonts(); + fix_generic_font_families(&mut db); + + let families = [ + Family::SansSerif, + Family::Serif, + Family::Monospace, + Family::Cursive, + Family::Fantasy, + ]; + + for family in families { + let query = Query { + families: &[family], + ..Default::default() + }; + assert!( + db.query(&query).is_some(), + "Expected generic family {family:?} to resolve after fix_generic_font_families" + ); + } + } + + #[test] + fn test_select_emoji_font_skips_family_without_glyph() { + let mut db = db_with_bundled_fonts(); + + let ibm_plex_sans = db + .query(&usvg::fontdb::Query { + families: &[usvg::fontdb::Family::Name("IBM Plex Sans")], + weight: usvg::fontdb::Weight(400), + stretch: usvg::fontdb::Stretch::Normal, + style: usvg::fontdb::Style::Normal, + }) + .unwrap(); + let lilex = db + .query(&usvg::fontdb::Query { + families: &[usvg::fontdb::Family::Name("Lilex")], + weight: usvg::fontdb::Weight(400), + stretch: usvg::fontdb::Stretch::Normal, + style: usvg::fontdb::Style::Normal, + }) + .unwrap(); + let selected = select_emoji_font('│', &[], &db, &["IBM Plex Sans", "Lilex"]).unwrap(); + + assert_eq!(selected, lilex); + assert!(!font_has_char(&db, ibm_plex_sans, '│')); + assert!(font_has_char(&db, selected, '│')); + } + + #[test] + fn fix_generic_font_families_monospace_resolves_to_lilex() { + let mut db = db_with_bundled_fonts(); + fix_generic_font_families(&mut db); + + let query = Query { + families: &[Family::Monospace], + ..Default::default() + }; + let id = db.query(&query).expect("Monospace should resolve"); + let face = db.face(id).expect("Face should exist"); + assert!( + face.families.iter().any(|(name, _)| name.contains("Lilex")), + "Monospace should map to Lilex, got {:?}", + face.families + ); + } +} diff --git a/vendor/gpui-pre/src/tab_stop.rs b/vendor/gpui-pre/src/tab_stop.rs new file mode 100644 index 00000000..bde651ae --- /dev/null +++ b/vendor/gpui-pre/src/tab_stop.rs @@ -0,0 +1,615 @@ +use std::fmt::Debug; + +use ::sum_tree::SumTree; +use collections::FxHashMap; +use sum_tree::Bias; + +use crate::{FocusHandle, FocusId}; + +/// Represents a collection of focus handles using the tab-index APIs. +#[derive(Debug)] +pub(crate) struct TabStopMap { + current_path: TabStopPath, + pub(crate) insertion_history: Vec, + by_id: FxHashMap, + order: SumTree, +} + +#[derive(Debug, Clone)] +pub enum TabStopOperation { + Insert(FocusHandle), + Group(TabIndex), + GroupEnd, +} + +impl TabStopOperation { + fn focus_handle(&self) -> Option<&FocusHandle> { + match self { + TabStopOperation::Insert(focus_handle) => Some(focus_handle), + _ => None, + } + } +} + +type TabIndex = isize; + +#[derive(Debug, Default, PartialEq, Eq, Clone, Ord, PartialOrd)] +struct TabStopPath(smallvec::SmallVec<[TabIndex; 6]>); + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +struct TabStopNode { + /// Path to access the node in the tree + /// The final node in the list is a leaf node corresponding to an actual focus handle, + /// all other nodes are group nodes + path: TabStopPath, + /// index into the backing array of nodes. Corresponds to insertion order + node_insertion_index: usize, + + /// Whether this node is a tab stop + tab_stop: bool, +} + +impl Ord for TabStopNode { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.path + .cmp(&other.path) + .then(self.node_insertion_index.cmp(&other.node_insertion_index)) + } +} + +impl PartialOrd for TabStopNode { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + +impl Default for TabStopMap { + fn default() -> Self { + Self { + current_path: TabStopPath::default(), + insertion_history: Vec::new(), + by_id: FxHashMap::default(), + order: SumTree::new(()), + } + } +} + +impl TabStopMap { + pub fn insert(&mut self, focus_handle: &FocusHandle) { + self.insertion_history + .push(TabStopOperation::Insert(focus_handle.clone())); + let mut path = self.current_path.clone(); + path.0.push(focus_handle.tab_index); + let order = TabStopNode { + node_insertion_index: self.insertion_history.len() - 1, + tab_stop: focus_handle.tab_stop, + path, + }; + self.by_id.insert(focus_handle.id, order.clone()); + self.order.insert_or_replace(order, ()); + } + + pub fn begin_group(&mut self, tab_index: isize) { + self.insertion_history + .push(TabStopOperation::Group(tab_index)); + self.current_path.0.push(tab_index); + } + + pub fn end_group(&mut self) { + self.insertion_history.push(TabStopOperation::GroupEnd); + self.current_path.0.pop(); + } + + pub fn clear(&mut self) { + *self = Self::default(); + self.current_path.0.clear(); + self.insertion_history.clear(); + self.by_id.clear(); + self.order = SumTree::new(()); + } + + pub fn next(&self, focused_id: Option<&FocusId>) -> Option { + let Some(focused_id) = focused_id else { + let first = self.order.first()?; + if first.tab_stop { + return self.focus_handle_for_order(first); + } else { + return self + .next_inner(first) + .and_then(|order| self.focus_handle_for_order(order)); + } + }; + + let Some(node) = self.tab_node_for_focus_id(focused_id) else { + return self.next(None); + }; + let item = self.next_inner(node); + + if let Some(item) = item { + self.focus_handle_for_order(&item) + } else { + self.next(None) + } + } + + fn next_inner(&self, node: &TabStopNode) -> Option<&TabStopNode> { + let mut cursor = self.order.cursor::(()); + cursor.seek(&node, Bias::Left); + cursor.next(); + while let Some(item) = cursor.item() + && !item.tab_stop + { + cursor.next(); + } + + cursor.item() + } + + pub fn prev(&self, focused_id: Option<&FocusId>) -> Option { + let Some(focused_id) = focused_id else { + let last = self.order.last()?; + if last.tab_stop { + return self.focus_handle_for_order(last); + } else { + return self + .prev_inner(last) + .and_then(|order| self.focus_handle_for_order(order)); + } + }; + + let Some(node) = self.tab_node_for_focus_id(focused_id) else { + return self.prev(None); + }; + let item = self.prev_inner(node); + + if let Some(item) = item { + self.focus_handle_for_order(&item) + } else { + self.prev(None) + } + } + + fn prev_inner(&self, node: &TabStopNode) -> Option<&TabStopNode> { + let mut cursor = self.order.cursor::(()); + cursor.seek(&node, Bias::Left); + cursor.prev(); + while let Some(item) = cursor.item() + && !item.tab_stop + { + cursor.prev(); + } + + cursor.item() + } + + pub fn replay(&mut self, nodes: &[TabStopOperation]) { + for node in nodes { + match node { + TabStopOperation::Insert(focus_handle) => self.insert(focus_handle), + TabStopOperation::Group(tab_index) => self.begin_group(*tab_index), + TabStopOperation::GroupEnd => self.end_group(), + } + } + } + + pub fn paint_index(&self) -> usize { + self.insertion_history.len() + } + + pub(crate) fn tab_stop_count(&self) -> usize { + self.by_id.values().filter(|node| node.tab_stop).count() + } + + fn focus_handle_for_order(&self, order: &TabStopNode) -> Option { + let handle = self.insertion_history[order.node_insertion_index].focus_handle(); + debug_assert!( + handle.is_some(), + "The order node did not correspond to an element, this is a GPUI bug" + ); + handle.cloned() + } + + fn tab_node_for_focus_id(&self, focused_id: &FocusId) -> Option<&TabStopNode> { + let Some(order) = self.by_id.get(focused_id) else { + return None; + }; + Some(order) + } +} + +mod sum_tree_impl { + use sum_tree::SeekTarget; + + use crate::tab_stop::{TabStopNode, TabStopPath}; + + #[derive(Clone, Debug)] + pub struct TabStopOrderNodeSummary { + max_index: usize, + max_path: TabStopPath, + pub tab_stops: usize, + } + + pub type TabStopCount = usize; + + impl sum_tree::ContextLessSummary for TabStopOrderNodeSummary { + fn zero() -> Self { + TabStopOrderNodeSummary { + max_index: 0, + max_path: TabStopPath::default(), + tab_stops: 0, + } + } + + fn add_summary(&mut self, summary: &Self) { + self.max_index = summary.max_index; + self.max_path = summary.max_path.clone(); + self.tab_stops += summary.tab_stops; + } + } + + impl sum_tree::KeyedItem for TabStopNode { + type Key = Self; + + fn key(&self) -> Self::Key { + self.clone() + } + } + + impl sum_tree::Item for TabStopNode { + type Summary = TabStopOrderNodeSummary; + + fn summary(&self, _cx: ::Context<'_>) -> Self::Summary { + TabStopOrderNodeSummary { + max_index: self.node_insertion_index, + max_path: self.path.clone(), + tab_stops: if self.tab_stop { 1 } else { 0 }, + } + } + } + + impl<'a> sum_tree::Dimension<'a, TabStopOrderNodeSummary> for TabStopCount { + fn zero(_: ::Context<'_>) -> Self { + 0 + } + + fn add_summary( + &mut self, + summary: &'a TabStopOrderNodeSummary, + _: ::Context<'_>, + ) { + *self += summary.tab_stops; + } + } + + impl<'a> sum_tree::Dimension<'a, TabStopOrderNodeSummary> for TabStopNode { + fn zero(_: ::Context<'_>) -> Self { + TabStopNode::default() + } + + fn add_summary( + &mut self, + summary: &'a TabStopOrderNodeSummary, + _: ::Context<'_>, + ) { + self.node_insertion_index = summary.max_index; + self.path = summary.max_path.clone(); + } + } + + impl<'a, 'b> SeekTarget<'a, TabStopOrderNodeSummary, TabStopNode> for &'b TabStopNode { + fn cmp( + &self, + cursor_location: &TabStopNode, + _: ::Context<'_>, + ) -> std::cmp::Ordering { + Iterator::cmp(self.path.0.iter(), cursor_location.path.0.iter()).then( + ::cmp( + &self.node_insertion_index, + &cursor_location.node_insertion_index, + ), + ) + } + } +} + +#[cfg(test)] +mod tests { + use itertools::Itertools as _; + + use crate::{FocusHandle, FocusId, FocusMap, TabStopMap}; + use std::sync::Arc; + + #[test] + fn test_tab_handles() { + let focus_map = Arc::new(FocusMap::default()); + let mut tab_index_map = TabStopMap::default(); + + let focus_handles = [ + FocusHandle::new(&focus_map).tab_stop(true).tab_index(0), + FocusHandle::new(&focus_map).tab_stop(true).tab_index(1), + FocusHandle::new(&focus_map).tab_stop(true).tab_index(1), + FocusHandle::new(&focus_map), + FocusHandle::new(&focus_map).tab_index(2), + FocusHandle::new(&focus_map).tab_stop(true).tab_index(0), + FocusHandle::new(&focus_map).tab_stop(true).tab_index(2), + ]; + + for handle in focus_handles.iter() { + tab_index_map.insert(handle); + } + let expected = [ + focus_handles[0].clone(), + focus_handles[5].clone(), + focus_handles[1].clone(), + focus_handles[2].clone(), + focus_handles[6].clone(), + ]; + + let mut prev = None; + let mut found = vec![]; + for _ in 0..expected.len() { + let handle = tab_index_map.next(prev.as_ref()).unwrap(); + prev = Some(handle.id); + found.push(handle.id); + } + + assert_eq!( + found, + expected.iter().map(|handle| handle.id).collect::>() + ); + + // Select first tab index if no handle is currently focused. + assert_eq!(tab_index_map.next(None), Some(expected[0].clone())); + // Select last tab index if no handle is currently focused. + assert_eq!(tab_index_map.prev(None), expected.last().cloned(),); + + assert_eq!( + tab_index_map.next(Some(&expected[0].id)), + Some(expected[1].clone()) + ); + assert_eq!( + tab_index_map.next(Some(&expected[1].id)), + Some(expected[2].clone()) + ); + assert_eq!( + tab_index_map.next(Some(&expected[2].id)), + Some(expected[3].clone()) + ); + assert_eq!( + tab_index_map.next(Some(&expected[3].id)), + Some(expected[4].clone()) + ); + assert_eq!( + tab_index_map.next(Some(&expected[4].id)), + Some(expected[0].clone()) + ); + + // prev + assert_eq!(tab_index_map.prev(None), Some(expected[4].clone())); + assert_eq!( + tab_index_map.prev(Some(&expected[0].id)), + Some(expected[4].clone()) + ); + assert_eq!( + tab_index_map.prev(Some(&expected[1].id)), + Some(expected[0].clone()) + ); + assert_eq!( + tab_index_map.prev(Some(&expected[2].id)), + Some(expected[1].clone()) + ); + assert_eq!( + tab_index_map.prev(Some(&expected[3].id)), + Some(expected[2].clone()) + ); + assert_eq!( + tab_index_map.prev(Some(&expected[4].id)), + Some(expected[3].clone()) + ); + } + + #[test] + fn test_tab_non_stop_filtering() { + let focus_map = Arc::new(FocusMap::default()); + let mut tab_index_map = TabStopMap::default(); + + // Check that we can query next from a non-stop tab + let tab_non_stop_1 = FocusHandle::new(&focus_map).tab_stop(false).tab_index(1); + let tab_stop_2 = FocusHandle::new(&focus_map).tab_stop(true).tab_index(2); + tab_index_map.insert(&tab_non_stop_1); + tab_index_map.insert(&tab_stop_2); + let result = tab_index_map.next(Some(&tab_non_stop_1.id)).unwrap(); + assert_eq!(result.id, tab_stop_2.id); + + // Check that we skip over non-stop tabs + let tab_stop_0 = FocusHandle::new(&focus_map).tab_stop(true).tab_index(0); + let tab_non_stop_0 = FocusHandle::new(&focus_map).tab_stop(false).tab_index(0); + tab_index_map.insert(&tab_stop_0); + tab_index_map.insert(&tab_non_stop_0); + let result = tab_index_map.next(Some(&tab_stop_0.id)).unwrap(); + assert_eq!(result.id, tab_stop_2.id); + } + + #[must_use] + struct TabStopMapTest { + tab_map: TabStopMap, + focus_map: Arc, + expected: Vec<(usize, FocusId)>, + } + + impl TabStopMapTest { + #[must_use] + fn new() -> Self { + Self { + tab_map: TabStopMap::default(), + focus_map: Arc::new(FocusMap::default()), + expected: Vec::default(), + } + } + + #[must_use] + fn tab_non_stop(mut self, index: isize) -> Self { + let handle = FocusHandle::new(&self.focus_map) + .tab_stop(false) + .tab_index(index); + self.tab_map.insert(&handle); + self + } + + #[must_use] + fn tab_stop(mut self, index: isize, expected: usize) -> Self { + let handle = FocusHandle::new(&self.focus_map) + .tab_stop(true) + .tab_index(index); + self.tab_map.insert(&handle); + self.expected.push((expected, handle.id)); + self.expected.sort_by_key(|(expected, _)| *expected); + self + } + + #[must_use] + fn tab_group(mut self, tab_index: isize, children: impl FnOnce(Self) -> Self) -> Self { + self.tab_map.begin_group(tab_index); + self = children(self); + self.tab_map.end_group(); + self + } + + fn traverse_tab_map( + &self, + traverse: impl Fn(&TabStopMap, Option<&FocusId>) -> Option, + ) -> Vec { + let mut last_focus_id = None; + let mut found = vec![]; + for _ in 0..self.expected.len() { + let handle = traverse(&self.tab_map, last_focus_id.as_ref()).unwrap(); + last_focus_id = Some(handle.id); + found.push(handle.id); + } + found + } + + fn assert(self) { + let mut expected = self.expected.iter().map(|(_, id)| *id).collect_vec(); + + // Check next order + let forward_found = self.traverse_tab_map(|tab_map, prev| tab_map.next(prev)); + assert_eq!(forward_found, expected); + + // Test overflow. Last to first + assert_eq!( + self.tab_map + .next(forward_found.last()) + .map(|handle| handle.id), + expected.first().cloned() + ); + + // Check previous order + let reversed_found = self.traverse_tab_map(|tab_map, prev| tab_map.prev(prev)); + expected.reverse(); + assert_eq!(reversed_found, expected); + + // Test overflow. First to last + assert_eq!( + self.tab_map + .prev(reversed_found.last()) + .map(|handle| handle.id), + expected.first().cloned(), + ); + } + } + + #[test] + fn test_with_disabled_tab_stop() { + TabStopMapTest::new() + .tab_stop(0, 0) + .tab_non_stop(1) + .tab_stop(2, 1) + .tab_stop(3, 2) + .assert(); + } + + #[test] + fn test_with_multiple_disabled_tab_stops() { + TabStopMapTest::new() + .tab_non_stop(0) + .tab_stop(1, 0) + .tab_non_stop(3) + .tab_stop(3, 1) + .tab_non_stop(4) + .assert(); + } + + #[test] + fn test_tab_group_functionality() { + TabStopMapTest::new() + .tab_stop(0, 0) + .tab_stop(0, 1) + .tab_group(2, |t| t.tab_stop(0, 2).tab_stop(1, 3)) + .tab_stop(3, 4) + .tab_stop(4, 5) + .assert() + } + + #[test] + fn test_sibling_groups() { + TabStopMapTest::new() + .tab_stop(0, 0) + .tab_stop(1, 1) + .tab_group(2, |test| test.tab_stop(0, 2).tab_stop(1, 3)) + .tab_stop(3, 4) + .tab_stop(4, 5) + .tab_group(6, |test| test.tab_stop(0, 6).tab_stop(1, 7)) + .tab_stop(7, 8) + .tab_stop(8, 9) + .assert(); + } + + #[test] + fn test_nested_group() { + TabStopMapTest::new() + .tab_stop(0, 0) + .tab_stop(1, 1) + .tab_group(2, |t| { + t.tab_group(0, |t| t.tab_stop(0, 2).tab_stop(1, 3)) + .tab_stop(1, 4) + }) + .tab_stop(3, 5) + .tab_stop(4, 6) + .assert(); + } + + #[test] + fn test_sibling_nested_groups() { + TabStopMapTest::new() + .tab_stop(0, 0) + .tab_stop(1, 1) + .tab_group(2, |builder| { + builder + .tab_stop(0, 2) + .tab_stop(2, 5) + .tab_group(1, |builder| builder.tab_stop(0, 3).tab_stop(1, 4)) + .tab_group(3, |builder| builder.tab_stop(0, 6).tab_stop(1, 7)) + }) + .tab_stop(3, 8) + .tab_stop(4, 9) + .assert(); + } + + #[test] + fn test_sibling_nested_groups_out_of_order() { + TabStopMapTest::new() + .tab_stop(9, 9) + .tab_stop(8, 8) + .tab_group(7, |builder| { + builder + .tab_stop(0, 2) + .tab_stop(2, 5) + .tab_group(3, |builder| builder.tab_stop(1, 7).tab_stop(0, 6)) + .tab_group(1, |builder| builder.tab_stop(0, 3).tab_stop(1, 4)) + }) + .tab_stop(3, 0) + .tab_stop(4, 1) + .assert(); + } +} diff --git a/vendor/gpui-pre/src/taffy.rs b/vendor/gpui-pre/src/taffy.rs new file mode 100644 index 00000000..b9e583a8 --- /dev/null +++ b/vendor/gpui-pre/src/taffy.rs @@ -0,0 +1,776 @@ +use crate::{ + AbsoluteLength, App, Bounds, DefiniteLength, Edges, GridTemplate, Length, Pixels, Point, Size, + Style, Window, size, + util::{ + ceil_to_device_pixel, round_half_toward_zero, round_stroke_to_device_pixel, + round_to_device_pixel, + }, +}; +use collections::{FxHashMap, FxHashSet}; +use std::{fmt::Debug, ops::Range}; +use taffy::{ + TaffyTree, TraversePartialTree as _, + geometry::{Point as TaffyPoint, Rect as TaffyRect, Size as TaffySize}, + prelude::{max_content, min_content}, + style::AvailableSpace as TaffyAvailableSpace, + tree::NodeId, +}; + +#[cfg(feature = "stacker")] +type StackSafe = stacksafe::StackSafe; +#[cfg(not(feature = "stacker"))] +type StackSafe = T; + +type MeasureFn = + dyn FnMut(Size>, Size, &mut Window, &mut App) -> Size; +type NodeMeasureFn = StackSafe>; + +struct NodeContext { + measure: NodeMeasureFn, +} +pub struct TaffyLayoutEngine { + taffy: TaffyTree, + absolute_layout_bounds: FxHashMap>, + /// Unrounded absolute border-box top-left per-node coordinate in device pixels. + absolute_outer_origins: FxHashMap>, + computed_layouts: FxHashSet, + layout_bounds_scratch_space: Vec, +} + +const EXPECT_MESSAGE: &str = "we should avoid taffy layout errors by construction if possible"; + +impl TaffyLayoutEngine { + pub fn new() -> Self { + let mut taffy = TaffyTree::new(); + taffy.disable_rounding(); + TaffyLayoutEngine { + taffy, + absolute_layout_bounds: FxHashMap::default(), + absolute_outer_origins: FxHashMap::default(), + computed_layouts: FxHashSet::default(), + layout_bounds_scratch_space: Vec::new(), + } + } + + pub fn clear(&mut self) { + self.taffy.clear(); + self.absolute_layout_bounds.clear(); + self.absolute_outer_origins.clear(); + self.computed_layouts.clear(); + } + + pub fn request_layout( + &mut self, + style: Style, + rem_size: Pixels, + scale_factor: f32, + children: &[LayoutId], + ) -> LayoutId { + let taffy_style = style.to_taffy(rem_size, scale_factor); + + if children.is_empty() { + self.taffy + .new_leaf(taffy_style) + .expect(EXPECT_MESSAGE) + .into() + } else { + self.taffy + // This is safe because LayoutId is repr(transparent) to taffy::tree::NodeId. + .new_with_children(taffy_style, LayoutId::to_taffy_slice(children)) + .expect(EXPECT_MESSAGE) + .into() + } + } + + pub fn request_measured_layout( + &mut self, + style: Style, + rem_size: Pixels, + scale_factor: f32, + measure: impl FnMut( + Size>, + Size, + &mut Window, + &mut App, + ) -> Size + + 'static, + ) -> LayoutId { + let taffy_style = style.to_taffy(rem_size, scale_factor); + let measure = Box::new(measure) as Box; + #[cfg(feature = "stacker")] + let measure = StackSafe::new(measure); + + self.taffy + .new_leaf_with_context(taffy_style, NodeContext { measure }) + .expect(EXPECT_MESSAGE) + .into() + } + + /// Treats any `auto` dimension of the given node's style as filling `size`. + /// + /// This is applied to window roots before layout so they behave like the + /// root element on the web, which stretches to fill the initial containing + /// block (the viewport) unless given an explicit size. Explicitly styled + /// dimensions are preserved. + pub fn stretch_auto_size_to_fill( + &mut self, + id: LayoutId, + size: Size, + scale_factor: f32, + ) { + let style = self.taffy.style(id.0).expect(EXPECT_MESSAGE); + let stretch_width = style.size.width.is_auto(); + let stretch_height = style.size.height.is_auto(); + if !stretch_width && !stretch_height { + return; + } + let mut style = style.clone(); + if stretch_width { + style.size.width = + taffy::style::Dimension::length(round_to_device_pixel(size.width.0, scale_factor)); + } + if stretch_height { + style.size.height = + taffy::style::Dimension::length(round_to_device_pixel(size.height.0, scale_factor)); + } + self.taffy.set_style(id.0, style).expect(EXPECT_MESSAGE); + } + + // Used to understand performance + #[allow(dead_code)] + fn count_all_children(&self, parent: LayoutId) -> anyhow::Result { + let mut count = 0; + + for child in self.taffy.children(parent.0)? { + // Count this child. + count += 1; + + // Count all of this child's children. + count += self.count_all_children(LayoutId(child))? + } + + Ok(count) + } + + // Used to understand performance + #[allow(dead_code)] + fn max_depth(&self, depth: u32, parent: LayoutId) -> anyhow::Result { + println!( + "{parent:?} at depth {depth} has {} children", + self.taffy.child_count(parent.0) + ); + + let mut max_child_depth = 0; + + for child in self.taffy.children(parent.0)? { + max_child_depth = std::cmp::max(max_child_depth, self.max_depth(0, LayoutId(child))?); + } + + Ok(depth + 1 + max_child_depth) + } + + // Used to understand performance + #[allow(dead_code)] + fn get_edges(&self, parent: LayoutId) -> anyhow::Result> { + let mut edges = Vec::new(); + + for child in self.taffy.children(parent.0)? { + edges.push((parent, LayoutId(child))); + + edges.extend(self.get_edges(LayoutId(child))?); + } + + Ok(edges) + } + + #[cfg_attr(feature = "stacker", stacksafe::stacksafe)] + pub fn compute_layout( + &mut self, + id: LayoutId, + available_space: Size, + window: &mut Window, + cx: &mut App, + ) { + // Leaving this here until we have a better instrumentation approach. + // println!("Laying out {} children", self.count_all_children(id)?); + // println!("Max layout depth: {}", self.max_depth(0, id)?); + + // Output the edges (branches) of the tree in Mermaid format for visualization. + // println!("Edges:"); + // for (a, b) in self.get_edges(id)? { + // println!("N{} --> N{}", u64::from(a), u64::from(b)); + // } + // + + if !self.computed_layouts.insert(id) { + let stack = &mut self.layout_bounds_scratch_space; + stack.push(id); + while let Some(id) = stack.pop() { + self.absolute_layout_bounds.remove(&id); + self.absolute_outer_origins.remove(&id); + stack.extend( + self.taffy + .children(id.into()) + .expect(EXPECT_MESSAGE) + .into_iter() + .map(LayoutId::from), + ); + } + } + + let scale_factor = window.scale_factor(); + + let transform = |v: AvailableSpace| match v { + AvailableSpace::Definite(pixels) => { + AvailableSpace::Definite(Pixels(pixels.0 * scale_factor)) + } + AvailableSpace::MinContent => AvailableSpace::MinContent, + AvailableSpace::MaxContent => AvailableSpace::MaxContent, + }; + let available_space = size( + transform(available_space.width), + transform(available_space.height), + ); + + self.taffy + .compute_layout_with_measure( + id.into(), + available_space.into(), + |known_dimensions, available_space, _id, node_context, _style| { + let Some(node_context) = node_context else { + return taffy::geometry::Size::default(); + }; + + let known_dimensions = Size { + width: known_dimensions.width.map(|e| Pixels(e / scale_factor)), + height: known_dimensions.height.map(|e| Pixels(e / scale_factor)), + }; + + let available_space: Size = available_space.into(); + let untransform = |ev: AvailableSpace| match ev { + AvailableSpace::Definite(pixels) => { + AvailableSpace::Definite(Pixels(pixels.0 / scale_factor)) + } + AvailableSpace::MinContent => AvailableSpace::MinContent, + AvailableSpace::MaxContent => AvailableSpace::MaxContent, + }; + let available_space = size( + untransform(available_space.width), + untransform(available_space.height), + ); + + let measured_size: Size = + (node_context.measure)(known_dimensions, available_space, window, cx); + snap_measured_size_to_device_pixels(measured_size, scale_factor).into() + }, + ) + .expect(EXPECT_MESSAGE); + } + + // Pixel snapping + // + // Painting primitives at non-integer pixel coordinates produces blurry + // output. Pixel snapping converts layout coordinates into integer + // device-pixel coordinates so painted edges land exactly on physical + // pixel boundaries. + // + // Non-integer coordinates can arise for several reasons, including: + // - flex distribution, percentages, centering, and text measurement + // can produce fractional element sizes and positions; + // - at fractional scale factors (for example 125% or 150%), integer + // logical-pixel values can map to non-integer device-pixel values. + // + // We pixel-snap by rounding in device-pixel space, after multiplying + // by `scale_factor`, so that snapping targets physical pixels. Bounds + // are divided by `scale_factor` before being returned to GPUI. + // + // Midpoints are rounded toward zero. This is a stylistic choice: a + // 1-logical-pixel line at 150% scale should render as 1 dp rather than + // 2 dp. + // + // Pixel snapping is done in two phases: + // + // 1. Pre-layout metric snapping. Before Taffy computes layout, all + // authored absolute lengths are rounded in `to_taffy`. This + // includes borders, padding, gaps, and explicit sizes. + // Custom-measured leaf nodes have their measured sizes rounded up + // to integer device-pixel lengths. + // + // 2. Post-layout edge snapping. After Taffy resolves the tree, layout + // relationships such as flex shares, grid tracks, percentages, and + // centering can produce new fractional edge positions. Boxes now + // have edges in absolute coordinates, and snapping must decide + // where those edges land on the device-pixel grid. + // + // Ideally, post-layout snapping would satisfy: + // + // - Edge closure. Two raw layout edges at the same absolute position + // should snap to the same pixel column. + // - Translation stability. A component's internal geometry should not + // change when it moves to a new absolute position. + // + // These goals are in tension because rounding is not associative. + // The simple local schemes make different tradeoffs: + // + // - Absolute edge rounding gives each window coordinate one answer, + // so coincident edges always close globally. But a span's snapped + // length is `round(far) - round(near)`, which may change by 1 dp + // as its absolute origin moves. + // + // - Parent-relative edge rounding rounds each child inside its + // parent's coordinate space. This guarantees translation stability, + // but a shared edge reached through different parents can + // accumulate different rounding, causing non-closure between + // cousins. + // + // - Length rounding rounds each width, height, and thickness + // independently and then places boxes from those rounded lengths. + // Sizes stay stable under translation, but neighboring boxes derive + // their shared boundary from different sources, so closure is not + // guaranteed. + // + // We apply absolute edge rounding for each element's outer box in + // post-layout rounding to preserve closure. Border and padding widths + // are not touched by post-layout rounding; they keep their pre-layout + // rounded value so that they remain stable under translation. + // + // This gives both closure and translation stability in the case that + // all local metrics are integer device-pixel lengths. Pre-layout + // rounding covers that in most cases. The exception is metrics + // resolved by layout relationships, such as percentages. Outer box + // edges will still close globally, and painted border widths are still + // snapped independently, but the raw content-box origin can carry a + // 1dp residual into descendants. + + pub fn layout_bounds(&mut self, id: LayoutId, scale_factor: f32) -> Bounds { + if let Some(layout) = self.absolute_layout_bounds.get(&id).cloned() { + return layout; + } + + let layout = self.taffy.layout(id.into()).expect(EXPECT_MESSAGE); + let layout_location = layout.location; + let layout_size = layout.size; + let parent = self.taffy.parent(id.0); + + let absolute_outer_origin = match parent { + Some(parent_id) => { + let parent_id = LayoutId::from(parent_id); + self.layout_bounds(parent_id, scale_factor); + let parent_origin = *self + .absolute_outer_origins + .get(&parent_id) + .expect("parent absolute outer origin should be cached"); + parent_origin + Point::from(layout_location) + } + None => Point::from(layout_location), + }; + self.absolute_outer_origins + .insert(id, absolute_outer_origin); + + let absolute_far = absolute_outer_origin + Point::from(Size::from(layout_size)); + let snapped_bounds = Bounds::from_corners( + absolute_outer_origin.map(round_half_toward_zero), + absolute_far.map(round_half_toward_zero), + ); + + let bounds = (snapped_bounds / scale_factor).map(Pixels); + self.absolute_layout_bounds.insert(id, bounds); + bounds + } +} + +/// A unique identifier for a layout node, generated when requesting a layout from Taffy +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[repr(transparent)] +pub struct LayoutId(NodeId); + +impl LayoutId { + fn to_taffy_slice(node_ids: &[Self]) -> &[taffy::NodeId] { + // SAFETY: LayoutId is repr(transparent) to taffy::tree::NodeId. + unsafe { std::mem::transmute::<&[LayoutId], &[taffy::NodeId]>(node_ids) } + } +} + +impl std::hash::Hash for LayoutId { + fn hash(&self, state: &mut H) { + u64::from(self.0).hash(state); + } +} + +impl From for LayoutId { + fn from(node_id: NodeId) -> Self { + Self(node_id) + } +} + +impl From for NodeId { + fn from(layout_id: LayoutId) -> NodeId { + layout_id.0 + } +} + +fn snap_measured_size_to_device_pixels(size: Size, scale_factor: f32) -> Size { + size.map(|d| ceil_to_device_pixel(d.0.max(0.0), scale_factor)) +} + +fn border_widths_to_taffy( + widths: &Edges, + rem_size: Pixels, + scale_factor: f32, +) -> TaffyRect { + let snap = |w: &AbsoluteLength| { + taffy::style::LengthPercentage::length(round_stroke_to_device_pixel( + w.to_pixels(rem_size).0, + scale_factor, + )) + }; + TaffyRect { + top: snap(&widths.top), + right: snap(&widths.right), + bottom: snap(&widths.bottom), + left: snap(&widths.left), + } +} + +trait ToTaffy { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> Output; +} + +impl ToTaffy for Style { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::Style { + use taffy::style_helpers::{fr, length, minmax, repeat}; + + fn to_grid_line( + placement: &Range, + ) -> taffy::Line { + taffy::Line { + start: placement.start.into(), + end: placement.end.into(), + } + } + + fn to_grid_repeat( + unit: &Option, + ) -> Vec> { + unit.map(|template| { + match template.min_size { + // grid-template-*: repeat(, minmax(0, 1fr)); + crate::GridTemplateMinSize::Zero => { + vec![repeat( + template.repeat, + vec![minmax(length(0.0_f32), fr(1.0_f32))], + )] + } + // grid-template-*: repeat(, minmax(min-content, 1fr)); + crate::GridTemplateMinSize::MinContent => { + vec![repeat( + template.repeat, + vec![minmax(min_content(), fr(1.0_f32))], + )] + } + // grid-template-*: repeat(, minmax(0, max-content)) + crate::GridTemplateMinSize::MaxContent => { + vec![repeat( + template.repeat, + vec![minmax(length(0.0_f32), max_content())], + )] + } + } + }) + .unwrap_or_default() + } + + taffy::style::Style { + display: self.display.into(), + overflow: self.overflow.into(), + scrollbar_width: self.scrollbar_width.to_taffy(rem_size, scale_factor), + position: self.position.into(), + inset: self.inset.to_taffy(rem_size, scale_factor), + size: self.size.to_taffy(rem_size, scale_factor), + min_size: self.min_size.to_taffy(rem_size, scale_factor), + max_size: self.max_size.to_taffy(rem_size, scale_factor), + aspect_ratio: self.aspect_ratio, + margin: self.margin.to_taffy(rem_size, scale_factor), + padding: self.padding.to_taffy(rem_size, scale_factor), + border: border_widths_to_taffy(&self.border_widths, rem_size, scale_factor), + align_items: self.align_items.map(|x| x.into()), + align_self: self.align_self.map(|x| x.into()), + align_content: self.align_content.map(|x| x.into()), + justify_content: self.justify_content.map(|x| x.into()), + gap: self.gap.to_taffy(rem_size, scale_factor), + flex_direction: self.flex_direction.into(), + flex_wrap: self.flex_wrap.into(), + flex_basis: self.flex_basis.to_taffy(rem_size, scale_factor), + flex_grow: self.flex_grow, + flex_shrink: self.flex_shrink, + grid_template_rows: to_grid_repeat(&self.grid_rows), + grid_template_columns: to_grid_repeat(&self.grid_cols), + grid_row: self + .grid_location + .as_ref() + .map(|location| to_grid_line(&location.row)) + .unwrap_or_default(), + grid_column: self + .grid_location + .as_ref() + .map(|location| to_grid_line(&location.column)) + .unwrap_or_default(), + ..Default::default() + } + } +} + +impl ToTaffy for AbsoluteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> f32 { + round_to_device_pixel(self.to_pixels(rem_size).0, scale_factor) + } +} + +impl ToTaffy for Length { + fn to_taffy( + &self, + rem_size: Pixels, + scale_factor: f32, + ) -> taffy::prelude::LengthPercentageAuto { + match self { + Length::Definite(length) => length.to_taffy(rem_size, scale_factor), + Length::Auto => taffy::prelude::LengthPercentageAuto::auto(), + } + } +} + +impl ToTaffy for Length { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::prelude::Dimension { + match self { + Length::Definite(length) => length.to_taffy(rem_size, scale_factor), + Length::Auto => taffy::prelude::Dimension::auto(), + } + } +} + +impl ToTaffy for DefiniteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentage { + match self { + DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor), + DefiniteLength::Fraction(fraction) => { + taffy::style::LengthPercentage::percent(*fraction) + } + } + } +} + +impl ToTaffy for DefiniteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentageAuto { + match self { + DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor), + DefiniteLength::Fraction(fraction) => { + taffy::style::LengthPercentageAuto::percent(*fraction) + } + } + } +} + +impl ToTaffy for DefiniteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::Dimension { + match self { + DefiniteLength::Absolute(length) => length.to_taffy(rem_size, scale_factor), + DefiniteLength::Fraction(fraction) => taffy::style::Dimension::percent(*fraction), + } + } +} + +impl ToTaffy for AbsoluteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentage { + taffy::style::LengthPercentage::length(self.to_taffy(rem_size, scale_factor)) + } +} + +impl ToTaffy for AbsoluteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::LengthPercentageAuto { + taffy::style::LengthPercentageAuto::length(self.to_taffy(rem_size, scale_factor)) + } +} + +impl ToTaffy for AbsoluteLength { + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> taffy::style::Dimension { + taffy::style::Dimension::length(self.to_taffy(rem_size, scale_factor)) + } +} + +impl From> for Point +where + T: Into, + T2: Clone + Debug + Default + PartialEq, +{ + fn from(point: TaffyPoint) -> Point { + Point { + x: point.x.into(), + y: point.y.into(), + } + } +} + +impl From> for TaffyPoint +where + T: Into + Clone + Debug + Default + PartialEq, +{ + fn from(val: Point) -> Self { + TaffyPoint { + x: val.x.into(), + y: val.y.into(), + } + } +} + +impl ToTaffy> for Size +where + T: ToTaffy + Clone + Debug + Default + PartialEq, +{ + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> TaffySize { + TaffySize { + width: self.width.to_taffy(rem_size, scale_factor), + height: self.height.to_taffy(rem_size, scale_factor), + } + } +} + +impl ToTaffy> for Edges +where + T: ToTaffy + Clone + Debug + Default + PartialEq, +{ + fn to_taffy(&self, rem_size: Pixels, scale_factor: f32) -> TaffyRect { + TaffyRect { + top: self.top.to_taffy(rem_size, scale_factor), + right: self.right.to_taffy(rem_size, scale_factor), + bottom: self.bottom.to_taffy(rem_size, scale_factor), + left: self.left.to_taffy(rem_size, scale_factor), + } + } +} + +impl From> for Size +where + T: Into, + U: Clone + Debug + Default + PartialEq, +{ + fn from(taffy_size: TaffySize) -> Self { + Size { + width: taffy_size.width.into(), + height: taffy_size.height.into(), + } + } +} + +impl From> for TaffySize +where + T: Into + Clone + Debug + Default + PartialEq, +{ + fn from(size: Size) -> Self { + TaffySize { + width: size.width.into(), + height: size.height.into(), + } + } +} + +/// The space available for an element to be laid out in +#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)] +pub enum AvailableSpace { + /// The amount of space available is the specified number of pixels + Definite(Pixels), + /// The amount of space available is indefinite and the node should be laid out under a min-content constraint + #[default] + MinContent, + /// The amount of space available is indefinite and the node should be laid out under a max-content constraint + MaxContent, +} + +impl AvailableSpace { + /// Returns a `Size` with both width and height set to `AvailableSpace::MinContent`. + /// + /// This function is useful when you want to create a `Size` with the minimum content constraints + /// for both dimensions. + /// + /// # Examples + /// + /// ``` + /// use gpui::AvailableSpace; + /// let min_content_size = AvailableSpace::min_size(); + /// assert_eq!(min_content_size.width, AvailableSpace::MinContent); + /// assert_eq!(min_content_size.height, AvailableSpace::MinContent); + /// ``` + pub const fn min_size() -> Size { + Size { + width: Self::MinContent, + height: Self::MinContent, + } + } +} + +impl From for TaffyAvailableSpace { + fn from(space: AvailableSpace) -> TaffyAvailableSpace { + match space { + AvailableSpace::Definite(Pixels(value)) => TaffyAvailableSpace::Definite(value), + AvailableSpace::MinContent => TaffyAvailableSpace::MinContent, + AvailableSpace::MaxContent => TaffyAvailableSpace::MaxContent, + } + } +} + +impl From for AvailableSpace { + fn from(space: TaffyAvailableSpace) -> AvailableSpace { + match space { + TaffyAvailableSpace::Definite(value) => AvailableSpace::Definite(Pixels(value)), + TaffyAvailableSpace::MinContent => AvailableSpace::MinContent, + TaffyAvailableSpace::MaxContent => AvailableSpace::MaxContent, + } + } +} + +impl From for AvailableSpace { + fn from(pixels: Pixels) -> Self { + AvailableSpace::Definite(pixels) + } +} + +impl From> for Size { + fn from(size: Size) -> Self { + Size { + width: AvailableSpace::Definite(size.width), + height: AvailableSpace::Definite(size.height), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn border_widths_to_taffy_use_stroke_snapping() { + let border_widths = Edges { + top: Pixels(0.0).into(), + right: Pixels(0.4).into(), + bottom: Pixels(0.5).into(), + left: Pixels(1.6).into(), + }; + let taffy_border = border_widths_to_taffy(&border_widths, Pixels(16.0), 1.0); + + assert_eq!( + taffy_border.top, + taffy::style::LengthPercentage::length(0.0) + ); + assert_eq!( + taffy_border.right, + taffy::style::LengthPercentage::length(1.0) + ); + assert_eq!( + taffy_border.bottom, + taffy::style::LengthPercentage::length(1.0) + ); + assert_eq!( + taffy_border.left, + taffy::style::LengthPercentage::length(2.0) + ); + } +} diff --git a/vendor/gpui-pre/src/test.rs b/vendor/gpui-pre/src/test.rs new file mode 100644 index 00000000..c1c8e666 --- /dev/null +++ b/vendor/gpui-pre/src/test.rs @@ -0,0 +1,172 @@ +//! Test support for GPUI. +//! +//! GPUI provides first-class support for testing, which includes a macro to run test that rely on having a context, +//! and a test implementation of the `ForegroundExecutor` and `BackgroundExecutor` which ensure that your tests run +//! deterministically even in the face of arbitrary parallelism. +//! +//! The output of the `gpui::test` macro is understood by other rust test runners, so you can use it with `cargo test` +//! or `cargo-nextest`, or another runner of your choice. +//! +//! To make it possible to test collaborative user interfaces (like Zed) you can ask for as many different contexts +//! as you need. +//! +//! ## Example +//! +//! ``` +//! use gpui; +//! +//! #[gpui::test] +//! async fn test_example(cx: &TestAppContext) { +//! assert!(true) +//! } +//! +//! #[gpui::test] +//! async fn test_collaboration_example(cx_a: &TestAppContext, cx_b: &TestAppContext) { +//! assert!(true) +//! } +//! ``` +use crate::{Entity, Subscription, TestAppContext, TestDispatcher, calculate_seeds}; +use futures::StreamExt as _; +use proptest::prelude::{Just, Strategy, any}; +use std::{ + env, + panic::{self, RefUnwindSafe, UnwindSafe}, + pin::Pin, +}; + +/// Strategy injected into `#[gpui::property_test]` tests to control the seed +/// given to the scheduler. Doesn't shrink, since all scheduler seeds are +/// equivalent in complexity. If `$SEED` is set, it always uses that value. +/// +/// Note: this function is not intended to be used directly. Rather, it is +/// public so that it can be used from the `property_test` macro. +pub fn seed_strategy() -> impl Strategy { + match std::env::var("SEED") { + Ok(val) => Just(val.parse().unwrap()).boxed(), + Err(_) => any::().no_shrink().boxed(), + } +} + +/// Applies a fixed RNG seed to a proptest config so that case generation +/// is deterministic. Uses `$SEED` if set, otherwise defaults to `0`. +/// This bridges the GPUI `SEED` env var to proptest's RNG seed, so that +/// a single variable controls both the scheduler seed and case generation. +/// +/// Note: this function is not intended to be used directly. Rather, it is +/// public so that it can be used from the `property_test` macro. +pub fn apply_seed_to_proptest_config( + mut config: proptest::test_runner::Config, +) -> proptest::test_runner::Config { + let seed = env::var("SEED") + .ok() + .and_then(|val| val.parse::().ok()) + .unwrap_or(0); + config.rng_seed = proptest::test_runner::RngSeed::Fixed(seed); + config +} + +/// Similar to [`run_test`], but only runs the callback once, allowing +/// [`FnOnce`] callbacks. This is intended for use with the +/// `gpui::property_test` macro and generally should not be used directly. +/// +/// Doesn't support many features of [`run_test`], since these are provided by +/// proptest. +pub fn run_test_once( + seed: u64, + test_fn: Box R>, +) -> R { + let result = panic::catch_unwind(|| { + let dispatcher = TestDispatcher::new(seed); + let scheduler = dispatcher.scheduler().clone(); + let res = test_fn(dispatcher); + scheduler.end_test(); + res + }); + + match result { + Ok(r) => r, + Err(e) => panic::resume_unwind(e), + } +} + +/// Run the given test function with the configured parameters. +/// This is intended for use with the `gpui::test` macro +/// and generally should not be used directly. +pub fn run_test( + num_iterations: usize, + explicit_seeds: &[u64], + max_retries: usize, + test_fn: &mut (dyn RefUnwindSafe + Fn(TestDispatcher, u64)), + on_fail_fn: Option, +) { + let (seeds, is_multiple_runs) = calculate_seeds(num_iterations as u64, explicit_seeds); + + for seed in seeds { + let mut attempt = 0; + loop { + if is_multiple_runs { + eprintln!("seed = {seed}"); + } + let result = panic::catch_unwind(|| { + let dispatcher = TestDispatcher::new(seed); + let scheduler = dispatcher.scheduler().clone(); + test_fn(dispatcher, seed); + scheduler.end_test(); + }); + + match result { + Ok(_) => break, + Err(error) => { + if attempt < max_retries { + println!("attempt {} failed, retrying", attempt); + attempt += 1; + // The panic payload might itself trigger an unwind on drop: + // https://doc.rust-lang.org/std/panic/fn.catch_unwind.html#notes + std::mem::forget(error); + } else { + if is_multiple_runs { + eprintln!("failing seed: {seed}"); + eprintln!( + "You can rerun from this seed by setting the environmental variable SEED to {seed}" + ); + } + if let Some(on_fail_fn) = on_fail_fn { + on_fail_fn() + } + panic::resume_unwind(error); + } + } + } + } + } +} + +/// A test struct for converting an observation callback into a stream. +pub struct Observation { + rx: Pin>>, + _subscription: Subscription, +} + +impl futures::Stream for Observation { + type Item = T; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.rx.poll_next_unpin(cx) + } +} + +/// observe returns a stream of the change events from the given `Entity` +pub fn observe(entity: &Entity, cx: &mut TestAppContext) -> Observation<()> { + let (tx, rx) = async_channel::unbounded(); + let _subscription = cx.update(|cx| { + cx.observe(entity, move |_, _| { + let _ = gpui::block_on(tx.send(())); + }) + }); + let rx = Box::pin(rx); + + Observation { rx, _subscription } +} diff --git a/vendor/gpui-pre/src/text_system.rs b/vendor/gpui-pre/src/text_system.rs new file mode 100644 index 00000000..564abdbe --- /dev/null +++ b/vendor/gpui-pre/src/text_system.rs @@ -0,0 +1,1521 @@ +mod font_fallbacks; +mod font_features; +mod line; +mod line_layout; +mod line_wrapper; + +pub use font_fallbacks::*; +pub use font_features::*; +pub use line::*; +pub use line_layout::*; +pub use line_wrapper::*; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + Bounds, DevicePixels, Hsla, Pixels, PlatformTextSystem, Point, Result, SharedString, Size, + StrikethroughStyle, TextRenderingMode, UnderlineStyle, px, +}; +use anyhow::{Context as _, anyhow}; +use collections::{FxHashMap, FxHashSet}; +use core::fmt; +use derive_more::{Add, Deref, FromStr, Sub}; +use itertools::Itertools; +use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; +use smallvec::{SmallVec, smallvec}; +use std::{ + borrow::Cow, + cmp, + collections::VecDeque, + fmt::{Debug, Display, Formatter}, + hash::{Hash, Hasher}, + ops::{Deref, DerefMut, Range}, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, +}; + +/// An opaque identifier for a specific font. +#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)] +#[repr(C)] +pub struct FontId(pub usize); + +/// An opaque identifier for a specific font family. +#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)] +pub struct FontFamilyId(pub usize); + +/// Number of subpixel glyph variants along the X axis. +pub const SUBPIXEL_VARIANTS_X: u8 = 4; + +/// Number of subpixel glyph variants along the Y axis. +pub const SUBPIXEL_VARIANTS_Y: u8 = 1; + +// Leave enough room below the underline for its stroke while keeping it below the baseline. +const UNDERLINE_DESCENT_OFFSET_FACTOR: f32 = 0.618; + +/// Returns the vertical offset used to paint an underline within a line. +pub fn underline_y_offset(line_height: Pixels, ascent: Pixels, descent: Pixels) -> Pixels { + let padding_top = (line_height - ascent - descent) / 2.; + padding_top + ascent + descent * UNDERLINE_DESCENT_OFFSET_FACTOR +} + +const MAX_REPORTED_MISSING_GLYPHS: usize = 1024; + +/// The spacing behavior required of a fallback font. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum FallbackFontClass { + /// A proportionally spaced fallback font. + Proportional, + /// A fixed-width fallback font. + Monospace, +} + +/// A grapheme cluster that could not be represented by any available font. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct MissingGlyph { + grapheme: SharedString, + font_class: FallbackFontClass, +} + +impl MissingGlyph { + /// Creates a missing-glyph report. + pub fn new(grapheme: SharedString, font_class: FallbackFontClass) -> Self { + Self { + grapheme, + font_class, + } + } + + /// Returns the unresolved grapheme cluster. + pub fn grapheme(&self) -> &str { + &self.grapheme + } + + /// Returns the spacing behavior required of a fallback font. + pub fn font_class(&self) -> FallbackFontClass { + self.font_class + } +} + +/// Accepts missing glyphs detected by a platform text system. +pub trait MissingGlyphSink: Send + Sync { + /// Reports grapheme clusters that exhausted font fallback. + fn report(&self, missing_glyphs: Vec); +} + +#[derive(Default)] +struct MissingGlyphState { + reported: FxHashSet, + reported_order: VecDeque, + generation: usize, +} + +impl MissingGlyphState { + fn reset(&mut self, generation: usize) { + self.reported.clear(); + self.reported_order.clear(); + self.generation = generation; + } +} + +struct QueuedMissingGlyph { + generation: usize, + missing_glyph: MissingGlyph, +} + +/// Collects missing-glyph reports without invoking application code during layout. +struct MissingGlyphReporter { + generation: Arc, + sender: async_channel::Sender, +} + +impl MissingGlyphSink for MissingGlyphReporter { + fn report(&self, missing_glyphs: Vec) { + if self.sender.is_closed() { + return; + } + + let generation = self.generation.load(Ordering::Acquire); + // Repetitions within a line must not fill the queue before its other + // missing glyphs. Cross-report deduplication belongs to the receiver. + for missing_glyph in missing_glyphs.into_iter().unique() { + let queued = QueuedMissingGlyph { + generation, + missing_glyph, + }; + if self.sender.try_send(queued).is_err() { + break; + } + } + } +} + +impl MissingGlyphReporter { + fn reset(&self) { + self.generation.fetch_add(1, Ordering::AcqRel); + } +} + +/// Receives batches of grapheme clusters that exhausted font fallback. +pub(crate) struct MissingGlyphReceiver { + state: MissingGlyphState, + generation: Arc, + receiver: async_channel::Receiver, +} + +impl MissingGlyphReceiver { + /// Waits until at least one new missing glyph has been observed. + /// + /// # Errors + /// + /// Returns [`async_channel::RecvError`] if the reporting channel is closed. + pub(crate) async fn recv( + &mut self, + ) -> std::result::Result, async_channel::RecvError> { + loop { + let queued = self.receiver.recv().await?; + let mut missing_glyphs = Vec::new(); + for queued in std::iter::once(queued) + .chain(std::iter::from_fn(|| self.receiver.try_recv().ok())) + .take(MAX_REPORTED_MISSING_GLYPHS) + { + let generation = self.generation.load(Ordering::Acquire); + if self.state.generation != generation { + self.state.reset(generation); + missing_glyphs.clear(); + } + if queued.generation != generation + || !self.state.reported.insert(queued.missing_glyph.clone()) + { + continue; + } + self.state + .reported_order + .push_back(queued.missing_glyph.clone()); + missing_glyphs.push(queued.missing_glyph); + if self.state.reported.len() > MAX_REPORTED_MISSING_GLYPHS + && let Some(expired) = self.state.reported_order.pop_front() + { + self.state.reported.remove(&expired); + } + } + if !missing_glyphs.is_empty() { + return Ok(missing_glyphs); + } + // A producer can keep refilling the queue with already-reported + // glyphs. Bound work per poll even when every report is filtered out. + let mut yielded = false; + std::future::poll_fn(|cx| { + if std::mem::replace(&mut yielded, true) { + std::task::Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + std::task::Poll::Pending + } + }) + .await; + } + } +} + +impl Drop for MissingGlyphReceiver { + fn drop(&mut self) { + self.receiver.close(); + while self.receiver.try_recv().is_ok() {} + } +} + +/// The GPUI text rendering sub system. +pub struct TextSystem { + platform_text_system: Arc, + font_ids_by_font: RwLock>>, + font_metrics: RwLock>, + raster_bounds: RwLock>>, + wrapper_pool: Mutex>>, + font_runs_pool: Mutex>>, + fallback_font_stack: SmallVec<[Font; 2]>, + font_generation: Arc, + missing_glyph_reporter: Arc, + missing_glyph_receiver: Mutex>, +} + +impl TextSystem { + /// Create a new TextSystem with the given platform text system. + pub fn new(platform_text_system: Arc) -> Self { + let (sender, receiver) = async_channel::bounded(MAX_REPORTED_MISSING_GLYPHS); + let missing_glyph_generation = Arc::::default(); + TextSystem { + platform_text_system, + font_metrics: RwLock::default(), + raster_bounds: RwLock::default(), + font_ids_by_font: RwLock::default(), + wrapper_pool: Mutex::default(), + font_runs_pool: Mutex::default(), + fallback_font_stack: smallvec![ + // TODO: Remove this when Linux have implemented setting fallbacks. + font(".ZedMono"), + font(".ZedSans"), + font("Helvetica"), + font("Segoe UI"), // Windows + font("Ubuntu"), // Gnome (Ubuntu) + font("Adwaita Sans"), // Gnome 47 + font("Cantarell"), // Gnome + font("Noto Sans"), // KDE + font("DejaVu Sans"), + font("Arial"), // macOS, Windows + ], + font_generation: Arc::default(), + missing_glyph_reporter: Arc::new(MissingGlyphReporter { + generation: missing_glyph_generation.clone(), + sender, + }), + missing_glyph_receiver: Mutex::new(Some(MissingGlyphReceiver { + state: MissingGlyphState::default(), + generation: missing_glyph_generation, + receiver, + })), + } + } + + /// Get sorted, unique font family names available to the platform text system. + /// + /// Includes fonts registered with [`Self::add_fonts`]. + pub fn all_font_names(&self) -> Vec { + let mut names = self.platform_text_system.all_font_names(); + names.sort_unstable(); + names.dedup(); + names + } + + /// The weights `family` ships as its own faces, ascending and without repeats. + /// + /// A family that ships one face answers that one alone, and a platform that + /// cannot tell answers none, so a caller shows only what the family draws. + pub fn weights_for_family(&self, family: &str) -> Vec { + let mut weights = self.platform_text_system.weights_for_family(family); + weights.sort_unstable(); + weights.dedup(); + weights + } + + /// Whether `family` is monospaced, as the platform's own metadata says. + pub fn is_monospaced(&self, family: &str) -> bool { + self.platform_text_system.is_monospaced(family) + } + + /// Add a font's data to the text system. + /// + /// Cached font resolution and line layouts are invalidated after installation. + /// Layouts already in progress may complete against the previous font set. + pub fn add_fonts(&self, fonts: Vec>) -> Result<()> { + self.platform_text_system.add_fonts(fonts)?; + self.font_ids_by_font.write().clear(); + self.missing_glyph_reporter.reset(); + self.font_generation.fetch_add(1, Ordering::Release); + Ok(()) + } + + /// Takes the receiver for missing-glyph reports. + /// + /// Only one receiver is available for each text system. Returns `None` when + /// the receiver was already taken or another caller is taking it. + pub(crate) fn take_missing_glyph_receiver(&self) -> Option { + self.missing_glyph_receiver + .try_lock() + .and_then(|mut receiver| receiver.take()) + } + + pub(crate) fn enable_missing_glyph_reporting(&self) { + self.platform_text_system + .set_missing_glyph_sink(Some(self.missing_glyph_reporter.clone())); + } + + pub(crate) fn disable_missing_glyph_reporting(&self) { + self.platform_text_system.set_missing_glyph_sink(None); + self.missing_glyph_reporter.reset(); + } + + #[cfg(test)] + pub(crate) fn report_missing_glyphs_in_test(&self, missing_glyphs: Vec) { + self.missing_glyph_reporter.report(missing_glyphs); + } + + /// Get the FontId for the configure font family and style. + fn font_id(&self, font: &Font) -> Result { + fn clone_font_id_result(font_id: &Result) -> Result { + match font_id { + Ok(font_id) => Ok(*font_id), + Err(err) => Err(anyhow!("{err}")), + } + } + + let font_id = self + .font_ids_by_font + .read() + .get(font) + .map(clone_font_id_result); + if let Some(font_id) = font_id { + font_id + } else { + let font_id = self.platform_text_system.font_id(font); + self.font_ids_by_font + .write() + .insert(font.clone(), clone_font_id_result(&font_id)); + font_id + } + } + + /// Get the Font for the Font Id. + pub fn get_font_for_id(&self, id: FontId) -> Option { + let lock = self.font_ids_by_font.read(); + lock.iter() + .filter_map(|(font, result)| match result { + Ok(font_id) if *font_id == id => Some(font.clone()), + _ => None, + }) + .next() + } + + /// Resolves the specified font, falling back to the default font stack if + /// the font fails to load. + /// + /// # Panics + /// + /// Panics if the font and none of the fallbacks can be resolved. + pub fn resolve_font(&self, font: &Font) -> FontId { + if let Ok(font_id) = self.font_id(font) { + return font_id; + } + for fallback in &self.fallback_font_stack { + if let Ok(font_id) = self.font_id(fallback) { + return font_id; + } + } + + panic!( + "failed to resolve font '{}' or any of the fallbacks: {}", + font.family, + self.fallback_font_stack + .iter() + .map(|fallback| &fallback.family) + .join(", ") + ); + } + + /// Prewarm any system font caches needed to shape text. + /// + /// This may be expensive, so callers should generally invoke it on a + /// background executor. Missing entries are still populated on demand by + /// the normal shaping path. + pub fn prewarm_fonts(&self, fonts: &[Font]) { + let mut font_ids = SmallVec::<[FontId; 8]>::new(); + for font in fonts { + let font_id = self.resolve_font(font); + if !font_ids.contains(&font_id) { + font_ids.push(font_id); + } + } + self.platform_text_system.prewarm_fonts(&font_ids); + } + + /// Get the bounding box for the given font and font size. + /// A font's bounding box is the smallest rectangle that could enclose all glyphs + /// in the font. superimposed over one another. + pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Bounds { + self.read_metrics(font_id, |metrics| metrics.bounding_box(font_size)) + } + + /// Get the typographic bounds for the given character, in the given font and size. + pub fn typographic_bounds( + &self, + font_id: FontId, + font_size: Pixels, + character: char, + ) -> Result> { + let glyph_id = self + .platform_text_system + .glyph_for_char(font_id, character) + .with_context(|| format!("glyph not found for character '{character}'"))?; + let bounds = self + .platform_text_system + .typographic_bounds(font_id, glyph_id)?; + Ok(self.read_metrics(font_id, |metrics| { + (bounds / metrics.units_per_em as f32 * font_size.0).map(px) + })) + } + + /// Get the advance width for the given character, in the given font and size. + pub fn advance(&self, font_id: FontId, font_size: Pixels, ch: char) -> Result> { + let glyph_id = self + .platform_text_system + .glyph_for_char(font_id, ch) + .with_context(|| format!("glyph not found for character '{ch}'"))?; + let result = self.platform_text_system.advance(font_id, glyph_id)? + / self.units_per_em(font_id) as f32; + + Ok(result * font_size) + } + + // Consider removing this? + /// Returns the shaped layout width of for the given character, in the given font and size. + pub fn layout_width(&self, font_id: FontId, font_size: Pixels, ch: char) -> Pixels { + let mut buffer = [0; 4]; + let buffer = ch.encode_utf8(&mut buffer); + self.platform_text_system + .layout_line( + buffer, + font_size, + &[FontRun { + len: buffer.len(), + font_id, + }], + ) + .width + } + + /// Returns the width of an `em`. + /// + /// Uses the width of the `m` character in the given font and size. + pub fn em_width(&self, font_id: FontId, font_size: Pixels) -> Result { + Ok(self.typographic_bounds(font_id, font_size, 'm')?.size.width) + } + + /// Returns the advance width of an `em`. + /// + /// Uses the advance width of the `m` character in the given font and size. + pub fn em_advance(&self, font_id: FontId, font_size: Pixels) -> Result { + Ok(self.advance(font_id, font_size, 'm')?.width) + } + + /// Returns the width of an `ch`. + /// + /// Uses the width of the `0` character in the given font and size. + pub fn ch_width(&self, font_id: FontId, font_size: Pixels) -> Result { + Ok(self.typographic_bounds(font_id, font_size, '0')?.size.width) + } + + /// Returns the advance width of an `ch`. + /// + /// Uses the advance width of the `0` character in the given font and size. + pub fn ch_advance(&self, font_id: FontId, font_size: Pixels) -> Result { + Ok(self.advance(font_id, font_size, '0')?.width) + } + + /// Get the number of font size units per 'em square', + /// Per MDN: "an abstract square whose height is the intended distance between + /// lines of type in the same type size" + pub fn units_per_em(&self, font_id: FontId) -> u32 { + self.read_metrics(font_id, |metrics| metrics.units_per_em) + } + + /// Get the height of a capital letter in the given font and size. + pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels { + self.read_metrics(font_id, |metrics| metrics.cap_height(font_size)) + } + + /// Get the height of the x character in the given font and size. + pub fn x_height(&self, font_id: FontId, font_size: Pixels) -> Pixels { + self.read_metrics(font_id, |metrics| metrics.x_height(font_size)) + } + + /// Get the recommended distance from the baseline for the given font + pub fn ascent(&self, font_id: FontId, font_size: Pixels) -> Pixels { + self.read_metrics(font_id, |metrics| metrics.ascent(font_size)) + } + + /// Get the recommended distance below the baseline for the given font, + /// in single spaced text. + pub fn descent(&self, font_id: FontId, font_size: Pixels) -> Pixels { + self.read_metrics(font_id, |metrics| metrics.descent(font_size)) + } + + /// Get the recommended baseline offset for the given font and line height. + pub fn baseline_offset( + &self, + font_id: FontId, + font_size: Pixels, + line_height: Pixels, + ) -> Pixels { + let ascent = self.ascent(font_id, font_size); + let descent = self.descent(font_id, font_size); + let padding_top = (line_height - ascent - descent) / 2.; + padding_top + ascent + } + + fn read_metrics(&self, font_id: FontId, read: impl FnOnce(&FontMetrics) -> T) -> T { + let lock = self.font_metrics.upgradable_read(); + + if let Some(metrics) = lock.get(&font_id) { + read(metrics) + } else { + let mut lock = RwLockUpgradableReadGuard::upgrade(lock); + let metrics = lock + .entry(font_id) + .or_insert_with(|| self.platform_text_system.font_metrics(font_id)); + read(metrics) + } + } + + /// Returns a handle to a line wrapper, for the given font and font size. + pub fn line_wrapper(self: &Arc, font: Font, font_size: Pixels) -> LineWrapperHandle { + let lock = &mut self.wrapper_pool.lock(); + let font_id = self.resolve_font(&font); + let wrappers = lock + .entry(FontIdWithSize { font_id, font_size }) + .or_default(); + let wrapper = wrappers + .pop() + .unwrap_or_else(|| LineWrapper::new(font_id, font_size, self.clone())); + + LineWrapperHandle { + wrapper: Some(wrapper), + text_system: self.clone(), + } + } + + /// Get the rasterized size and location of a specific, rendered glyph. + pub(crate) fn raster_bounds(&self, params: &RenderGlyphParams) -> Result> { + let raster_bounds = self.raster_bounds.upgradable_read(); + if let Some(bounds) = raster_bounds.get(params) { + Ok(*bounds) + } else { + let mut raster_bounds = RwLockUpgradableReadGuard::upgrade(raster_bounds); + let bounds = self.platform_text_system.glyph_raster_bounds(params)?; + raster_bounds.insert(params.clone(), bounds); + Ok(bounds) + } + } + + pub(crate) fn rasterize_glyph( + &self, + params: &RenderGlyphParams, + ) -> Result<(Size, Vec)> { + let raster_bounds = self.raster_bounds(params)?; + self.platform_text_system + .rasterize_glyph(params, raster_bounds) + } + + /// Returns the dilation level to use for a glyph painted in the given color. + pub(crate) fn glyph_dilation_for_color(&self, color: Hsla) -> u8 { + self.platform_text_system.glyph_dilation_for_color(color) + } + + /// Returns the text rendering mode recommended by the platform for the given font and size. + /// The return value will never be [`TextRenderingMode::PlatformDefault`]. + pub(crate) fn recommended_rendering_mode( + &self, + font_id: FontId, + font_size: Pixels, + ) -> TextRenderingMode { + self.platform_text_system + .recommended_rendering_mode(font_id, font_size) + } +} + +/// The GPUI text layout subsystem. +#[derive(Deref)] +pub struct WindowTextSystem { + line_layout_cache: LineLayoutCache, + #[deref] + text_system: Arc, +} + +impl WindowTextSystem { + /// Create a new WindowTextSystem with the given TextSystem. + pub fn new(text_system: Arc) -> Self { + Self { + line_layout_cache: LineLayoutCache::new( + text_system.platform_text_system.clone(), + text_system.font_generation.clone(), + ), + text_system, + } + } + + pub(crate) fn layout_index(&self) -> LineLayoutIndex { + self.line_layout_cache.layout_index() + } + + pub(crate) fn reuse_layouts(&self, index: Range) { + self.line_layout_cache.reuse_layouts(index) + } + + pub(crate) fn truncate_layouts(&self, index: LineLayoutIndex) { + self.line_layout_cache.truncate_layouts(index) + } + + /// Shape the given line, at the given font_size, for painting to the screen. + /// Subsets of the line can be styled independently with the `runs` parameter. + /// + /// Note that this method can only shape a single line of text. It will panic + /// if the text contains newlines. If you need to shape multiple lines of text, + /// use [`Self::shape_text`] instead. + pub fn shape_line( + &self, + text: SharedString, + font_size: Pixels, + runs: &[TextRun], + force_width: Option, + ) -> ShapedLine { + debug_assert!( + text.find('\n').is_none(), + "text argument should not contain newlines" + ); + + let mut decoration_runs = SmallVec::<[DecorationRun; 32]>::new(); + for run in runs { + if let Some(last_run) = decoration_runs.last_mut() + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + && last_run.background_color == run.background_color + { + last_run.len += run.len as u32; + continue; + } + decoration_runs.push(DecorationRun { + len: run.len as u32, + color: run.color, + background_color: run.background_color, + underline: run.underline, + strikethrough: run.strikethrough, + }); + } + + let layout = self.layout_line(&text, font_size, runs, force_width); + + ShapedLine { + layout, + text, + decoration_runs, + } + } + + /// Shape the given line using a caller-provided content hash as the cache key. + /// + /// This enables cache hits without materializing a contiguous `SharedString` for the text. + /// If the cache misses, `materialize_text` is invoked to produce the `SharedString` for shaping. + /// + /// Contract (caller enforced): + /// - Same `text_hash` implies identical text content (collision risk accepted by caller). + /// - `text_len` should be the UTF-8 byte length of the text (helps reduce accidental collisions). + /// + /// Like [`Self::shape_line`], this must be used only for single-line text (no `\n`). + pub fn shape_line_by_hash( + &self, + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &[TextRun], + force_width: Option, + materialize_text: impl FnOnce() -> SharedString, + ) -> ShapedLine { + let mut decoration_runs = SmallVec::<[DecorationRun; 32]>::new(); + for run in runs { + if let Some(last_run) = decoration_runs.last_mut() + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + && last_run.background_color == run.background_color + { + last_run.len += run.len as u32; + continue; + } + decoration_runs.push(DecorationRun { + len: run.len as u32, + color: run.color, + background_color: run.background_color, + underline: run.underline, + strikethrough: run.strikethrough, + }); + } + + let mut used_force_width = force_width; + let layout = self.layout_line_by_hash( + text_hash, + text_len, + font_size, + runs, + used_force_width, + || { + let text = materialize_text(); + debug_assert!( + text.find('\n').is_none(), + "text argument should not contain newlines" + ); + text + }, + ); + + // We only materialize actual text on cache miss; on hit we avoid allocations. + // Since `ShapedLine` carries a `SharedString`, use an empty placeholder for hits. + // NOTE: Callers must not rely on `ShapedLine.text` for content when using this API. + let text: SharedString = SharedString::new_static(""); + + ShapedLine { + layout, + text, + decoration_runs, + } + } + + /// Shape a multi line string of text, at the given font_size, for painting to the screen. + /// Subsets of the text can be styled independently with the `runs` parameter. + /// If `wrap_width` is provided, the line breaks will be adjusted to fit within the given width. + pub fn shape_text( + &self, + text: SharedString, + font_size: Pixels, + runs: &[TextRun], + wrap_width: Option, + line_clamp: Option, + ) -> Result> { + let mut runs = runs.iter().filter(|run| run.len > 0).cloned().peekable(); + let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default(); + + let mut lines = SmallVec::new(); + let mut max_wrap_lines = line_clamp; + let mut wrapped_lines = 0; + + let mut process_line = |line_text: SharedString, line_start, line_end| { + font_runs.clear(); + + let mut decoration_runs = >::with_capacity(32); + let mut run_start = line_start; + while run_start < line_end { + let Some(run) = runs.peek_mut() else { + log::warn!("`TextRun`s do not cover the entire to be shaped text"); + break; + }; + + let run_len_within_line = cmp::min(line_end - run_start, run.len); + + let decoration_changed = if let Some(last_run) = decoration_runs.last_mut() + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + && last_run.background_color == run.background_color + { + last_run.len += run_len_within_line as u32; + false + } else { + decoration_runs.push(DecorationRun { + len: run_len_within_line as u32, + color: run.color, + background_color: run.background_color, + underline: run.underline, + strikethrough: run.strikethrough, + }); + true + }; + + let font_id = self.resolve_font(&run.font); + if let Some(font_run) = font_runs.last_mut() + && font_id == font_run.font_id + && !decoration_changed + { + font_run.len += run_len_within_line; + } else { + font_runs.push(FontRun { + len: run_len_within_line, + font_id, + }); + } + + // Preserve the remainder of the run for the next line + run.len -= run_len_within_line; + if run.len == 0 { + runs.next(); + } + run_start += run_len_within_line; + } + + let layout = self.line_layout_cache.layout_wrapped_line( + &line_text, + font_size, + &font_runs, + wrap_width, + max_wrap_lines.map(|max| max.saturating_sub(wrapped_lines)), + ); + wrapped_lines += layout.wrap_boundaries.len(); + + lines.push(WrappedLine { + layout, + decoration_runs, + text: line_text, + }); + + // Skip `\n` character. + if let Some(run) = runs.peek_mut() { + run.len -= 1; + if run.len == 0 { + runs.next(); + } + } + }; + + let mut split_lines = text.split('\n'); + + // Special case single lines to prevent allocating a sharedstring + if let Some(first_line) = split_lines.next() + && let Some(second_line) = split_lines.next() + { + let mut line_start = 0; + process_line( + SharedString::new(first_line), + line_start, + line_start + first_line.len(), + ); + line_start += first_line.len() + '\n'.len_utf8(); + process_line( + SharedString::new(second_line), + line_start, + line_start + second_line.len(), + ); + for line_text in split_lines { + line_start += line_text.len() + '\n'.len_utf8(); + process_line( + SharedString::new(line_text), + line_start, + line_start + line_text.len(), + ); + } + } else { + let end = text.len(); + process_line(text, 0, end); + } + + self.font_runs_pool.lock().push(font_runs); + + Ok(lines) + } + + pub(crate) fn finish_frame(&self) { + self.line_layout_cache.finish_frame() + } + + /// Layout the given line of text, at the given font_size. + /// Subsets of the line can be styled independently with the `runs` parameter. + /// Generally, you should prefer to use [`Self::shape_line`] instead, which + /// can be painted directly. + pub fn layout_line( + &self, + text: &str, + font_size: Pixels, + runs: &[TextRun], + force_width: Option, + ) -> Arc { + let mut last_run = None::<&TextRun>; + let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default(); + font_runs.clear(); + + for run in runs.iter() { + let decoration_changed = if let Some(last_run) = last_run + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + // we do not consider differing background color relevant, as it does not affect glyphs + // && last_run.background_color == run.background_color + { + false + } else { + last_run = Some(run); + true + }; + + let font_id = self.resolve_font(&run.font); + if let Some(font_run) = font_runs.last_mut() + && font_id == font_run.font_id + && !decoration_changed + { + font_run.len += run.len; + } else { + font_runs.push(FontRun { + len: run.len, + font_id, + }); + } + } + + let layout = self.line_layout_cache.layout_line( + &SharedString::new(text), + font_size, + &font_runs, + force_width, + ); + + self.font_runs_pool.lock().push(font_runs); + + layout + } + + /// Returns the shaped layout width of for the given character, in the given font and size. + pub fn layout_width(&self, font_id: FontId, font_size: Pixels, ch: char) -> Pixels { + let mut buffer = [0; 4]; + let buffer: &_ = ch.encode_utf8(&mut buffer); + self.line_layout_cache + .layout_line( + buffer, + font_size, + &[FontRun { + len: buffer.len(), + font_id, + }], + None, + ) + .width + } + + /// Returns the shaped layout width of an `em`. + pub fn em_layout_width(&self, font_id: FontId, font_size: Pixels) -> Pixels { + self.layout_width(font_id, font_size, 'm') + } + + /// Probe the line layout cache using a caller-provided content hash, without allocating. + /// + /// Returns `Some(layout)` if the layout is already cached in either the current frame + /// or the previous frame. Returns `None` if it is not cached. + /// + /// Contract (caller enforced): + /// - Same `text_hash` implies identical text content (collision risk accepted by caller). + /// - `text_len` should be the UTF-8 byte length of the text (helps reduce accidental collisions). + pub fn try_layout_line_by_hash( + &self, + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &[TextRun], + force_width: Option, + ) -> Option> { + let mut last_run = None::<&TextRun>; + let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default(); + font_runs.clear(); + + for run in runs.iter() { + let decoration_changed = if let Some(last_run) = last_run + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + // we do not consider differing background color relevant, as it does not affect glyphs + // && last_run.background_color == run.background_color + { + false + } else { + last_run = Some(run); + true + }; + + let font_id = self.resolve_font(&run.font); + if let Some(font_run) = font_runs.last_mut() + && font_id == font_run.font_id + && !decoration_changed + { + font_run.len += run.len; + } else { + font_runs.push(FontRun { + len: run.len, + font_id, + }); + } + } + + let layout = self.line_layout_cache.try_layout_line_by_hash( + text_hash, + text_len, + font_size, + &font_runs, + force_width, + ); + + self.font_runs_pool.lock().push(font_runs); + + layout + } + + /// Layout the given line of text using a caller-provided content hash as the cache key. + /// + /// This enables cache hits without materializing a contiguous `SharedString` for the text. + /// If the cache misses, `materialize_text` is invoked to produce the `SharedString` for shaping. + /// + /// Contract (caller enforced): + /// - Same `text_hash` implies identical text content (collision risk accepted by caller). + /// - `text_len` should be the UTF-8 byte length of the text (helps reduce accidental collisions). + pub fn layout_line_by_hash( + &self, + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &[TextRun], + force_width: Option, + materialize_text: impl FnOnce() -> SharedString, + ) -> Arc { + let mut last_run = None::<&TextRun>; + let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default(); + font_runs.clear(); + + for run in runs.iter() { + let decoration_changed = if let Some(last_run) = last_run + && last_run.color == run.color + && last_run.underline == run.underline + && last_run.strikethrough == run.strikethrough + // we do not consider differing background color relevant, as it does not affect glyphs + // && last_run.background_color == run.background_color + { + false + } else { + last_run = Some(run); + true + }; + + let font_id = self.resolve_font(&run.font); + if let Some(font_run) = font_runs.last_mut() + && font_id == font_run.font_id + && !decoration_changed + { + font_run.len += run.len; + } else { + font_runs.push(FontRun { + len: run.len, + font_id, + }); + } + } + + let layout = self.line_layout_cache.layout_line_by_hash( + text_hash, + text_len, + font_size, + &font_runs, + force_width, + materialize_text, + ); + + self.font_runs_pool.lock().push(font_runs); + + layout + } +} + +#[derive(Hash, Eq, PartialEq)] +struct FontIdWithSize { + font_id: FontId, + font_size: Pixels, +} + +/// A handle into the text system, which can be used to compute the wrapped layout of text +pub struct LineWrapperHandle { + wrapper: Option, + text_system: Arc, +} + +impl Drop for LineWrapperHandle { + fn drop(&mut self) { + let mut state = self.text_system.wrapper_pool.lock(); + let wrapper = self.wrapper.take().unwrap(); + state + .get_mut(&FontIdWithSize { + font_id: wrapper.font_id, + font_size: wrapper.font_size, + }) + .unwrap() + .push(wrapper); + } +} + +impl Deref for LineWrapperHandle { + type Target = LineWrapper; + + fn deref(&self) -> &Self::Target { + self.wrapper.as_ref().unwrap() + } +} + +impl DerefMut for LineWrapperHandle { + fn deref_mut(&mut self) -> &mut Self::Target { + self.wrapper.as_mut().unwrap() + } +} + +/// The degree of blackness or stroke thickness of a font. This value ranges from 100.0 to 900.0, +/// with 400.0 as normal. +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize, Add, Sub, FromStr)] +#[serde(transparent)] +pub struct FontWeight(pub f32); + +impl Display for FontWeight { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for FontWeight { + fn from(weight: f32) -> Self { + FontWeight(weight) + } +} + +impl Default for FontWeight { + #[inline] + fn default() -> FontWeight { + FontWeight::NORMAL + } +} + +impl Hash for FontWeight { + fn hash(&self, state: &mut H) { + state.write_u32(u32::from_be_bytes(self.0.to_be_bytes())); + } +} + +impl Eq for FontWeight {} + +impl FontWeight { + /// Thin weight (100), the thinnest value. + pub const THIN: FontWeight = FontWeight(100.0); + /// Extra light weight (200). + pub const EXTRA_LIGHT: FontWeight = FontWeight(200.0); + /// Light weight (300). + pub const LIGHT: FontWeight = FontWeight(300.0); + /// Normal (400). + pub const NORMAL: FontWeight = FontWeight(400.0); + /// Medium weight (500, higher than normal). + pub const MEDIUM: FontWeight = FontWeight(500.0); + /// Semibold weight (600). + pub const SEMIBOLD: FontWeight = FontWeight(600.0); + /// Bold weight (700). + pub const BOLD: FontWeight = FontWeight(700.0); + /// Extra-bold weight (800). + pub const EXTRA_BOLD: FontWeight = FontWeight(800.0); + /// Black weight (900), the thickest value. + pub const BLACK: FontWeight = FontWeight(900.0); + + /// All of the font weights, in order from thinnest to thickest. + pub const ALL: [FontWeight; 9] = [ + Self::THIN, + Self::EXTRA_LIGHT, + Self::LIGHT, + Self::NORMAL, + Self::MEDIUM, + Self::SEMIBOLD, + Self::BOLD, + Self::EXTRA_BOLD, + Self::BLACK, + ]; +} + +impl schemars::JsonSchema for FontWeight { + fn schema_name() -> std::borrow::Cow<'static, str> { + "FontWeight".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + use schemars::json_schema; + json_schema!({ + "type": "number", + "minimum": Self::THIN, + "maximum": Self::BLACK, + "default": Self::default(), + "description": "Font weight value between 100 (thin) and 900 (black)" + }) + } +} + +/// Allows italic or oblique faces to be selected. +#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash, Default, Serialize, Deserialize, JsonSchema)] +pub enum FontStyle { + /// A face that is neither italic not obliqued. + #[default] + Normal, + /// A form that is generally cursive in nature. + Italic, + /// A typically-sloped version of the regular face. + Oblique, +} + +impl Display for FontStyle { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + Debug::fmt(self, f) + } +} + +/// A styled run of text, for use in [`crate::TextLayout`]. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct TextRun { + /// A number of utf8 bytes + pub len: usize, + /// The font to use for this run. + pub font: Font, + /// The color + pub color: Hsla, + /// The background color (if any) + pub background_color: Option, + /// The underline style (if any) + pub underline: Option, + /// The strikethrough style (if any) + pub strikethrough: Option, +} + +#[cfg(all(target_os = "macos", test))] +impl TextRun { + fn with_len(&self, len: usize) -> Self { + let mut this = self.clone(); + this.len = len; + this + } +} + +/// An identifier for a specific glyph, as returned by [`WindowTextSystem::layout_line`]. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[repr(C)] +pub struct GlyphId(pub u32); + +/// Parameters for rendering a glyph, used as cache keys for raster bounds. +/// +/// This struct identifies a specific glyph rendering configuration including +/// font, size, subpixel positioning, and scale factor. It's used to look up +/// cached raster bounds and sprite atlas entries. +#[derive(Clone, Debug, PartialEq)] +#[expect(missing_docs)] +pub struct RenderGlyphParams { + pub font_id: FontId, + pub glyph_id: GlyphId, + pub font_size: Pixels, + pub subpixel_variant: Point, + pub scale_factor: f32, + pub is_emoji: bool, + pub subpixel_rendering: bool, + pub dilation: u8, +} + +impl Eq for RenderGlyphParams {} + +impl Hash for RenderGlyphParams { + fn hash(&self, state: &mut H) { + self.font_id.0.hash(state); + self.glyph_id.0.hash(state); + self.font_size.0.to_bits().hash(state); + self.subpixel_variant.hash(state); + self.scale_factor.to_bits().hash(state); + self.is_emoji.hash(state); + self.subpixel_rendering.hash(state); + self.dilation.hash(state); + } +} + +/// The configuration details for identifying a specific font. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct Font { + /// The font family name. + /// + /// The special name ".SystemUIFont" is used to identify the system UI font, which varies based on platform. + pub family: SharedString, + + /// The font features to use. + pub features: FontFeatures, + + /// The fallbacks fonts to use. + pub fallbacks: Option, + + /// The font weight. + pub weight: FontWeight, + + /// The font style. + pub style: FontStyle, +} + +impl Default for Font { + fn default() -> Self { + font(".SystemUIFont") + } +} + +/// Get a [`Font`] for a given name. +pub fn font(family: impl Into) -> Font { + Font { + family: family.into(), + features: FontFeatures::default(), + weight: FontWeight::default(), + style: FontStyle::default(), + fallbacks: None, + } +} + +impl Font { + /// Set this Font to be bold + pub fn bold(mut self) -> Self { + self.weight = FontWeight::BOLD; + self + } + + /// Set this Font to be italic + pub fn italic(mut self) -> Self { + self.style = FontStyle::Italic; + self + } +} + +/// A struct for storing font metrics. +/// It is used to define the measurements of a typeface. +#[derive(Clone, Copy, Debug)] +pub struct FontMetrics { + /// The number of font units that make up the "em square", + /// a scalable grid for determining the size of a typeface. + pub units_per_em: u32, + + /// The vertical distance from the baseline of the font to the top of the glyph covers. + pub ascent: f32, + + /// The vertical distance from the baseline of the font to the bottom of the glyph covers. + pub descent: f32, + + /// The recommended additional space to add between lines of type. + pub line_gap: f32, + + /// The suggested position of the underline. + pub underline_position: f32, + + /// The suggested thickness of the underline. + pub underline_thickness: f32, + + /// The height of a capital letter measured from the baseline of the font. + pub cap_height: f32, + + /// The height of a lowercase x. + pub x_height: f32, + + /// The outer limits of the area that the font covers. + /// Corresponds to the xMin / xMax / yMin / yMax values in the OpenType `head` table + pub bounding_box: Bounds, +} + +impl FontMetrics { + /// Returns the vertical distance from the baseline of the font to the top of the glyph covers in pixels. + pub fn ascent(&self, font_size: Pixels) -> Pixels { + Pixels((self.ascent / self.units_per_em as f32) * font_size.0) + } + + /// Returns the vertical distance from the baseline of the font to the bottom of the glyph covers in pixels. + pub fn descent(&self, font_size: Pixels) -> Pixels { + Pixels((self.descent / self.units_per_em as f32) * font_size.0) + } + + /// Returns the recommended additional space to add between lines of type in pixels. + pub fn line_gap(&self, font_size: Pixels) -> Pixels { + Pixels((self.line_gap / self.units_per_em as f32) * font_size.0) + } + + /// Returns the suggested position of the underline in pixels. + pub fn underline_position(&self, font_size: Pixels) -> Pixels { + Pixels((self.underline_position / self.units_per_em as f32) * font_size.0) + } + + /// Returns the suggested thickness of the underline in pixels. + pub fn underline_thickness(&self, font_size: Pixels) -> Pixels { + Pixels((self.underline_thickness / self.units_per_em as f32) * font_size.0) + } + + /// Returns the height of a capital letter measured from the baseline of the font in pixels. + pub fn cap_height(&self, font_size: Pixels) -> Pixels { + Pixels((self.cap_height / self.units_per_em as f32) * font_size.0) + } + + /// Returns the height of a lowercase x in pixels. + pub fn x_height(&self, font_size: Pixels) -> Pixels { + Pixels((self.x_height / self.units_per_em as f32) * font_size.0) + } + + /// Returns the outer limits of the area that the font covers in pixels. + pub fn bounding_box(&self, font_size: Pixels) -> Bounds { + (self.bounding_box / self.units_per_em as f32 * font_size.0).map(px) + } +} + +/// Maps well-known virtual font names to their concrete equivalents. +#[allow(unused)] +pub fn font_name_with_fallbacks<'a>(name: &'a str, system: &'a str) -> &'a str { + // Note: the "Zed Plex" fonts were deprecated as we are not allowed to use "Plex" + // in a derived font name. They are essentially indistinguishable from IBM Plex/Lilex, + // and so retained here for backward compatibility. + match name { + ".SystemUIFont" => system, + ".ZedSans" | "Zed Plex Sans" => "IBM Plex Sans", + ".ZedMono" | "Zed Plex Mono" => "Lilex", + _ => name, + } +} + +/// Like [`font_name_with_fallbacks`] but accepts and returns [`SharedString`] references. +#[allow(unused)] +pub fn font_name_with_fallbacks_shared<'a>( + name: &'a SharedString, + system: &'a SharedString, +) -> &'a SharedString { + // Note: the "Zed Plex" fonts were deprecated as we are not allowed to use "Plex" + // in a derived font name. They are essentially indistinguishable from IBM Plex/Lilex, + // and so retained here for backward compatibility. + match name.as_str() { + ".SystemUIFont" => system, + ".ZedSans" | "Zed Plex Sans" => const { &SharedString::new_static("IBM Plex Sans") }, + ".ZedMono" | "Zed Plex Mono" => const { &SharedString::new_static("Lilex") }, + _ => name, + } +} + +#[cfg(test)] +mod missing_glyph_tests { + use super::*; + use futures::FutureExt as _; + + #[test] + fn bounds_retained_missing_glyphs() { + let (reporter, mut receiver) = missing_glyph_channel(); + reporter.report( + (0..MAX_REPORTED_MISSING_GLYPHS) + .map(|index| { + MissingGlyph::new(index.to_string().into(), FallbackFontClass::Proportional) + }) + .collect(), + ); + assert!(receiver.recv().now_or_never().unwrap().is_ok()); + + let newest = MissingGlyph::new("newest".into(), FallbackFontClass::Monospace); + reporter.report(vec![newest.clone()]); + assert!(receiver.recv().now_or_never().unwrap().is_ok()); + + let state = &receiver.state; + assert_eq!(state.reported.len(), MAX_REPORTED_MISSING_GLYPHS); + assert_eq!(state.reported_order.len(), MAX_REPORTED_MISSING_GLYPHS); + assert!(state.reported.contains(&newest)); + } + + #[test] + fn dropping_receiver_closes_and_clears_reports() { + let (reporter, receiver) = missing_glyph_channel(); + reporter.report(vec![missing_glyph("missing")]); + + drop(receiver); + + assert!(reporter.sender.is_closed()); + assert!(reporter.sender.is_empty()); + } + + fn missing_glyph_channel() -> (MissingGlyphReporter, MissingGlyphReceiver) { + let (sender, receiver) = async_channel::bounded(MAX_REPORTED_MISSING_GLYPHS); + let generation = Arc::::default(); + let reporter = MissingGlyphReporter { + generation: generation.clone(), + sender, + }; + let receiver = MissingGlyphReceiver { + state: MissingGlyphState::default(), + generation, + receiver, + }; + (reporter, receiver) + } + + fn missing_glyph(grapheme: &'static str) -> MissingGlyph { + MissingGlyph::new(grapheme.into(), FallbackFontClass::Proportional) + } +} diff --git a/vendor/gpui-pre/src/text_system/font_fallbacks.rs b/vendor/gpui-pre/src/text_system/font_fallbacks.rs new file mode 100644 index 00000000..63dc89ba --- /dev/null +++ b/vendor/gpui-pre/src/text_system/font_fallbacks.rs @@ -0,0 +1,21 @@ +use std::sync::Arc; + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// The fallback fonts that can be configured for a given font. +/// Fallback fonts family names are stored here. +#[derive(Default, Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize, JsonSchema)] +pub struct FontFallbacks(pub Arc>); + +impl FontFallbacks { + /// Get the fallback fonts family names + pub fn fallback_list(&self) -> &[String] { + self.0.as_slice() + } + + /// Create a font fallback from a list of strings + pub fn from_fonts(fonts: Vec) -> Self { + FontFallbacks(Arc::new(fonts)) + } +} diff --git a/vendor/gpui-pre/src/text_system/font_features.rs b/vendor/gpui-pre/src/text_system/font_features.rs new file mode 100644 index 00000000..c1ab72b4 --- /dev/null +++ b/vendor/gpui-pre/src/text_system/font_features.rs @@ -0,0 +1,154 @@ +use std::borrow::Cow; +use std::sync::Arc; + +use schemars::{JsonSchema, json_schema}; + +/// The OpenType features that can be configured for a given font. +#[derive(Default, Clone, Eq, PartialEq, Hash)] +pub struct FontFeatures(pub Arc>); + +impl FontFeatures { + /// Disables `calt`. + pub fn disable_ligatures() -> Self { + Self(Arc::new(vec![("calt".into(), 0)])) + } + + /// Get the tag name list of the font OpenType features + /// only enabled or disabled features are returned + pub fn tag_value_list(&self) -> &[(String, u32)] { + self.0.as_slice() + } + + /// Returns whether the `calt` feature is enabled. + /// + /// Returns `None` if the feature is not present. + pub fn is_calt_enabled(&self) -> Option { + self.0 + .iter() + .find(|(feature, _)| feature == "calt") + .map(|(_, value)| *value == 1) + } +} + +impl std::fmt::Debug for FontFeatures { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut debug = f.debug_struct("FontFeatures"); + for (tag, value) in self.tag_value_list() { + debug.field(tag, value); + } + + debug.finish() + } +} + +#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[serde(untagged)] +enum FeatureValue { + Bool(bool), + Number(serde_json::Number), +} + +impl<'de> serde::Deserialize<'de> for FontFeatures { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::{MapAccess, Visitor}; + use std::fmt; + + struct FontFeaturesVisitor; + + impl<'de> Visitor<'de> for FontFeaturesVisitor { + type Value = FontFeatures; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a map of font features") + } + + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut feature_list = Vec::new(); + + while let Some((key, value)) = + access.next_entry::>()? + { + if !is_valid_feature_tag(&key) { + log::error!("Incorrect font feature tag: {}", key); + continue; + } + if let Some(value) = value { + match value { + FeatureValue::Bool(enable) => { + if enable { + feature_list.push((key, 1)); + } else { + feature_list.push((key, 0)); + } + } + FeatureValue::Number(value) => { + if value.is_u64() { + feature_list.push((key, value.as_u64().unwrap() as u32)); + } else { + log::error!( + "Incorrect font feature value {} for feature tag {}", + value, + key + ); + continue; + } + } + } + } + } + + Ok(FontFeatures(Arc::new(feature_list))) + } + } + + let features = deserializer.deserialize_map(FontFeaturesVisitor)?; + Ok(features) + } +} + +impl serde::Serialize for FontFeatures { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeMap; + + let mut map = serializer.serialize_map(None)?; + + for (tag, value) in self.tag_value_list() { + map.serialize_entry(tag, value)?; + } + + map.end() + } +} + +impl JsonSchema for FontFeatures { + fn schema_name() -> Cow<'static, str> { + "FontFeatures".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + json_schema!({ + "type": "object", + "patternProperties": { + "[0-9a-zA-Z]{4}$": { + "type": ["boolean", "integer"], + "minimum": 0, + "multipleOf": 1 + } + }, + "additionalProperties": false + }) + } +} + +fn is_valid_feature_tag(tag: &str) -> bool { + tag.len() == 4 && tag.chars().all(|c| c.is_ascii_alphanumeric()) +} diff --git a/vendor/gpui-pre/src/text_system/line.rs b/vendor/gpui-pre/src/text_system/line.rs new file mode 100644 index 00000000..f5210052 --- /dev/null +++ b/vendor/gpui-pre/src/text_system/line.rs @@ -0,0 +1,1979 @@ +use crate::{ + App, Bounds, DevicePixels, Half, Hsla, LineLayout, Pixels, Point, RenderGlyphParams, Result, + SharedString, StrikethroughStyle, TextAlign, UnderlineStyle, Window, WrapBoundary, + WrappedLineLayout, black, fill, point, px, size, underline_y_offset, +}; +use derive_more::{Deref, DerefMut}; +use smallvec::SmallVec; +use std::{ops::Range, sync::Arc}; + +/// Pre-computed glyph data for efficient painting without per-glyph cache lookups. +/// +/// This is produced by `ShapedLine::compute_glyph_raster_data` during prepaint +/// and consumed by `ShapedLine::paint_with_raster_data` during paint. +#[derive(Clone, Debug)] +pub struct GlyphRasterData { + /// The raster bounds for each glyph, in paint order. + pub bounds: Vec>, + /// The render params for each glyph (needed for sprite atlas lookup). + pub params: Vec, +} + +/// Set the text decoration for a run of text. +#[derive(Debug, Clone)] +pub struct DecorationRun { + /// The length of the run in utf-8 bytes. + pub len: u32, + + /// The color for this run + pub color: Hsla, + + /// The background color for this run + pub background_color: Option, + + /// The underline style for this run + pub underline: Option, + + /// The strikethrough style for this run + pub strikethrough: Option, +} + +/// A line of text that has been shaped and decorated. +#[derive(Clone, Default, Debug, Deref, DerefMut)] +pub struct ShapedLine { + #[deref] + #[deref_mut] + pub(crate) layout: Arc, + /// The text that was shaped for this line. + pub text: SharedString, + pub(crate) decoration_runs: SmallVec<[DecorationRun; 32]>, +} + +impl ShapedLine { + /// Returns a forward-only cursor for this shaped line. + pub fn cursor(&self) -> ShapedLineCursor<'_> { + assert_eq!( + self.len(), + self.text.len(), + "cannot split a shaped line with an adjusted length" + ); + let byte_ordered = self + .layout + .runs + .iter() + .flat_map(|run| run.glyphs.iter().map(|glyph| glyph.index)) + .is_sorted(); + ShapedLineCursor { + line: self, + unordered_remainder: (!byte_ordered).then(|| self.clone()), + byte_index: 0, + run_index: 0, + glyph_index: 0, + decoration_index: 0, + decoration_offset: 0, + x_offset: px(0.), + } + } + + /// The length of the line in utf-8 bytes. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { + self.layout.len + } + + /// The width of the shaped line in pixels. + /// + /// This is the glyph advance width computed by the text shaping system and is useful for + /// incrementally advancing a "pen" when painting multiple fragments on the same row. + pub fn width(&self) -> Pixels { + self.layout.width + } + + /// Override the len, useful if you're rendering text a + /// as text b (e.g. rendering invisibles). + pub fn with_len(mut self, len: usize) -> Self { + let layout = self.layout.as_ref(); + self.layout = Arc::new(LineLayout { + font_size: layout.font_size, + width: layout.width, + ascent: layout.ascent, + descent: layout.descent, + runs: layout.runs.clone(), + len, + }); + self + } + + /// Paint the line of text to the window. + pub fn paint( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + align_width: Option, + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + self.paint_with_underline_handler( + origin, + line_height, + align, + align_width, + window, + cx, + |_, origin, width, style, window| window.paint_underline(origin, width, style), + ) + } + + /// Paint the line with a handler for each underline. + pub fn paint_with_underline_handler( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + align_width: Option, + window: &mut Window, + cx: &mut App, + mut paint_underline: impl FnMut( + Range, + Point, + Pixels, + &UnderlineStyle, + &mut Window, + ), + ) -> Result<()> { + paint_line( + origin, + &self.layout, + line_height, + align, + align_width, + &self.decoration_runs, + &[], + window, + cx, + &mut paint_underline, + ) + } + + /// Paint the background of the line to the window. + pub fn paint_background( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + align_width: Option, + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + paint_line_background( + origin, + &self.layout, + line_height, + align, + align_width, + &self.decoration_runs, + &[], + window, + cx, + )?; + + Ok(()) + } + + /// Split this shaped line at a byte index, returning `(prefix, suffix)`. + /// + /// - `prefix` contains glyphs for bytes `[0, byte_index)` with original positions. + /// Its width equals the x-advance up to the split point. + /// - `suffix` contains glyphs for bytes `[byte_index, len)` with positions + /// shifted left so the first glyph starts at x=0, and byte indices rebased to 0. + /// - Decoration runs are partitioned at the boundary; a run that straddles it is + /// split into two with adjusted lengths. + /// - `font_size`, `ascent`, and `descent` are copied to both halves. + pub fn split_at(&self, byte_index: usize) -> (ShapedLine, ShapedLine) { + let (left_layout, right_layout) = self.layout.split_at(byte_index); + + // Partition decoration runs. A run straddling the boundary is split into two. + let mut left_decorations = SmallVec::new(); + let mut right_decorations = SmallVec::new(); + let mut decoration_offset = 0u32; + let split_point = byte_index as u32; + + for decoration in &self.decoration_runs { + let run_end = decoration_offset + decoration.len; + + if run_end <= split_point { + left_decorations.push(decoration.clone()); + } else if decoration_offset >= split_point { + right_decorations.push(decoration.clone()); + } else { + let left_len = split_point - decoration_offset; + let right_len = run_end - split_point; + left_decorations.push(DecorationRun { + len: left_len, + color: decoration.color, + background_color: decoration.background_color, + underline: decoration.underline, + strikethrough: decoration.strikethrough, + }); + right_decorations.push(DecorationRun { + len: right_len, + color: decoration.color, + background_color: decoration.background_color, + underline: decoration.underline, + strikethrough: decoration.strikethrough, + }); + } + + decoration_offset = run_end; + } + + // Split text + let left_text = if byte_index == self.text.len() { + self.text.clone() + } else { + SharedString::new(&self.text[..byte_index]) + }; + let right_text = if byte_index == 0 { + self.text.clone() + } else { + SharedString::new(&self.text[byte_index..]) + }; + + let left = ShapedLine { + layout: Arc::new(left_layout), + text: left_text, + decoration_runs: left_decorations, + }; + + let right = ShapedLine { + layout: Arc::new(right_layout), + text: right_text, + decoration_runs: right_decorations, + }; + + (left, right) + } +} + +/// Incrementally splits a [`ShapedLine`] at increasing UTF-8 byte boundaries. +/// +/// Each piece preserves the original glyphs and decorations, rebased as in +/// [`ShapedLine::split_at`]. Byte-ordered glyphs are advanced in linear time, +/// copying each glyph and byte at most once; visually reordered glyphs fall +/// back to the existing split operation. +pub struct ShapedLineCursor<'a> { + line: &'a ShapedLine, + /// Bidirectional shaping can put glyphs out of byte order. + unordered_remainder: Option, + byte_index: usize, + run_index: usize, + glyph_index: usize, + decoration_index: usize, + decoration_offset: u32, + x_offset: Pixels, +} + +impl<'a> ShapedLineCursor<'a> { + /// Takes the bytes since the previous boundary. + /// + /// Panics if the boundary precedes the previous one, exceeds the line's + /// length, or falls inside a UTF-8 character. + pub fn take_until(&mut self, byte_index: usize) -> ShapedLine { + assert!( + byte_index >= self.byte_index, + "split boundary moved backwards" + ); + assert!( + byte_index <= self.line.len(), + "split boundary exceeds line length" + ); + assert!( + self.line.text.is_char_boundary(byte_index), + "split boundary is not a UTF-8 character boundary" + ); + let previous_index = self.byte_index; + let previous_x = self.x_offset; + if let Some(remainder) = &mut self.unordered_remainder { + let (piece, rest) = remainder.split_at(byte_index - previous_index); + *remainder = rest; + self.byte_index = byte_index; + self.x_offset = self.line.layout.x_for_index(byte_index); + return piece; + } + let mut runs = Vec::new(); + let mut next_x = self.line.layout.width; + while let Some(run) = self.line.layout.runs.get(self.run_index) { + let start = self.glyph_index; + while let Some(glyph) = run.glyphs.get(self.glyph_index) { + if glyph.index >= byte_index { + break; + } + self.glyph_index += 1; + } + let end = self.glyph_index; + if start < end { + runs.push(crate::ShapedRun { + font_id: run.font_id, + glyphs: run.glyphs[start..end] + .iter() + .map(|glyph| crate::ShapedGlyph { + id: glyph.id, + position: point(glyph.position.x - previous_x, glyph.position.y), + index: glyph.index - previous_index, + is_emoji: glyph.is_emoji, + }) + .collect(), + }); + } + if let Some(glyph) = run.glyphs.get(self.glyph_index) { + next_x = glyph.position.x; + break; + } + self.run_index += 1; + self.glyph_index = 0; + } + let mut decorations = SmallVec::new(); + while let Some(decoration) = self.line.decoration_runs.get(self.decoration_index) + && (self.decoration_offset < byte_index as u32 + || (decoration.len == 0 && self.decoration_offset == byte_index as u32)) + { + let end = self.decoration_offset + decoration.len; + let start = self.decoration_offset.max(previous_index as u32); + let len = end.min(byte_index as u32) - start; + if len > 0 || decoration.len == 0 { + decorations.push(DecorationRun { + len, + color: decoration.color, + background_color: decoration.background_color, + underline: decoration.underline, + strikethrough: decoration.strikethrough, + }); + } + if end <= byte_index as u32 { + self.decoration_index += 1; + self.decoration_offset = end; + } else { + break; + } + } + self.byte_index = byte_index; + self.x_offset = next_x; + ShapedLine { + layout: Arc::new(LineLayout { + font_size: self.line.layout.font_size, + width: next_x - previous_x, + ascent: self.line.layout.ascent, + descent: self.line.layout.descent, + runs, + len: byte_index - previous_index, + }), + text: SharedString::new(&self.line.text[previous_index..byte_index]), + decoration_runs: decorations, + } + } + + /// Returns the original line's x position at the current boundary. + pub fn x_offset(&self) -> Pixels { + self.x_offset + } +} + +impl LineLayout { + /// Paint this layout to the window, using the given decoration runs to color + /// glyphs and draw underlines and strikethroughs. + /// + /// This is a lower-level alternative to [`ShapedLine::paint`] for callers that + /// hold a bare layout and track decorations themselves. + pub fn paint( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + align_width: Option, + decoration_runs: &[DecorationRun], + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + paint_line( + origin, + self, + line_height, + align, + align_width, + decoration_runs, + &[], + window, + cx, + &mut |_, origin, width, style, window| window.paint_underline(origin, width, style), + ) + } + + /// Paint the background of this layout to the window, using the given + /// decoration runs to determine background colors. + /// + /// This is a lower-level alternative to [`ShapedLine::paint_background`] for + /// callers that hold a bare layout and track decorations themselves. + pub fn paint_background( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + align_width: Option, + decoration_runs: &[DecorationRun], + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + paint_line_background( + origin, + self, + line_height, + align, + align_width, + decoration_runs, + &[], + window, + cx, + ) + } +} + +/// A line of text that has been shaped, decorated, and wrapped by the text layout system. +#[derive(Default, Debug, Deref, DerefMut)] +pub struct WrappedLine { + #[deref] + #[deref_mut] + pub(crate) layout: Arc, + /// The text that was shaped for this line. + pub text: SharedString, + pub(crate) decoration_runs: Vec, +} + +impl WrappedLine { + /// The length of the underlying, unwrapped layout, in utf-8 bytes. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { + self.layout.len() + } + + /// Paint this line of text to the window. + pub fn paint( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + bounds: Option>, + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + let align_width = match bounds { + Some(bounds) => Some(bounds.size.width), + None => self.layout.wrap_width, + }; + + paint_line( + origin, + &self.layout.unwrapped_layout, + line_height, + align, + align_width, + &self.decoration_runs, + &self.wrap_boundaries, + window, + cx, + &mut |_, origin, width, style, window| window.paint_underline(origin, width, style), + )?; + + Ok(()) + } + + /// Paint the background of line of text to the window. + pub fn paint_background( + &self, + origin: Point, + line_height: Pixels, + align: TextAlign, + bounds: Option>, + window: &mut Window, + cx: &mut App, + ) -> Result<()> { + let align_width = match bounds { + Some(bounds) => Some(bounds.size.width), + None => self.layout.wrap_width, + }; + + paint_line_background( + origin, + &self.layout.unwrapped_layout, + line_height, + align, + align_width, + &self.decoration_runs, + &self.wrap_boundaries, + window, + cx, + )?; + + Ok(()) + } +} + +fn paint_line( + origin: Point, + layout: &LineLayout, + line_height: Pixels, + align: TextAlign, + align_width: Option, + decoration_runs: &[DecorationRun], + wrap_boundaries: &[WrapBoundary], + window: &mut Window, + cx: &mut App, + paint_underline: &mut dyn FnMut( + Range, + Point, + Pixels, + &UnderlineStyle, + &mut Window, + ), +) -> Result<()> { + let line_bounds = line_paint_bounds( + origin, + layout, + line_height, + align, + align_width, + wrap_boundaries, + ); + window.paint_layer(line_bounds, |window| { + let padding_top = (line_height - layout.ascent - layout.descent) / 2.; + let baseline_offset = point(px(0.), padding_top + layout.ascent); + let underline_y_offset = underline_y_offset(line_height, layout.ascent, layout.descent); + let mut decoration_runs = decoration_runs.iter(); + let mut wraps = wrap_boundaries.iter().peekable(); + let mut run_end = 0; + let mut color = black(); + let mut current_underline: Option<(Point, UnderlineStyle, Range)> = None; + let mut current_strikethrough: Option<(Point, StrikethroughStyle)> = None; + let text_system = cx.text_system().clone(); + let mut glyph_origin = point( + aligned_origin_x( + origin, + align_width.unwrap_or(layout.width), + px(0.0), + &align, + layout, + wraps.peek(), + ), + origin.y, + ); + let mut prev_glyph_position = Point::default(); + let mut max_glyph_size = size(px(0.), px(0.)); + let mut first_glyph_x = origin.x; + for (run_ix, run) in layout.runs.iter().enumerate() { + max_glyph_size = text_system.bounding_box(run.font_id, layout.font_size).size; + + for (glyph_ix, glyph) in run.glyphs.iter().enumerate() { + glyph_origin.x += glyph.position.x - prev_glyph_position.x; + if glyph_ix == 0 && run_ix == 0 { + first_glyph_x = glyph_origin.x; + } + + if wraps.peek() == Some(&&WrapBoundary { run_ix, glyph_ix }) { + wraps.next(); + if let Some((underline_origin, underline_style, underline_range)) = + current_underline.as_mut() + { + if glyph_origin.x == underline_origin.x { + underline_origin.x -= max_glyph_size.width.half(); + }; + paint_underline( + underline_range.clone(), + *underline_origin, + glyph_origin.x - underline_origin.x, + underline_style, + window, + ); + if glyph.index < run_end { + underline_origin.x = origin.x; + underline_origin.y += line_height; + } else { + current_underline = None; + } + } + if let Some((strikethrough_origin, strikethrough_style)) = + current_strikethrough.as_mut() + { + if glyph_origin.x == strikethrough_origin.x { + strikethrough_origin.x -= max_glyph_size.width.half(); + }; + window.paint_strikethrough( + *strikethrough_origin, + glyph_origin.x - strikethrough_origin.x, + strikethrough_style, + ); + if glyph.index < run_end { + strikethrough_origin.x = origin.x; + strikethrough_origin.y += line_height; + } else { + current_strikethrough = None; + } + } + + glyph_origin.x = aligned_origin_x( + origin, + align_width.unwrap_or(layout.width), + glyph.position.x, + &align, + layout, + wraps.peek(), + ); + glyph_origin.y += line_height; + } + prev_glyph_position = glyph.position; + + let mut finished_underline: Option<(Point, UnderlineStyle, Range)> = + None; + let mut finished_strikethrough: Option<(Point, StrikethroughStyle)> = None; + if glyph.index >= run_end { + let mut style_run = decoration_runs.next(); + + // ignore style runs that apply to a partial glyph + while let Some(run) = style_run { + if glyph.index < run_end + (run.len as usize) { + break; + } + run_end += run.len as usize; + style_run = decoration_runs.next(); + } + + if let Some(style_run) = style_run { + let style_run_start = run_end; + if let Some((_, underline_style, underline_range)) = &mut current_underline + { + if style_run.underline.as_ref() != Some(underline_style) { + finished_underline = current_underline.take(); + } else { + underline_range.end = style_run_start + style_run.len as usize; + } + } + if let Some(run_underline) = style_run.underline.as_ref() { + current_underline.get_or_insert(( + point(glyph_origin.x, glyph_origin.y + underline_y_offset), + UnderlineStyle { + color: Some(run_underline.color.unwrap_or(style_run.color)), + thickness: run_underline.thickness, + wavy: run_underline.wavy, + }, + style_run_start..style_run_start + style_run.len as usize, + )); + } + if let Some((_, strikethrough_style)) = &mut current_strikethrough + && style_run.strikethrough.as_ref() != Some(strikethrough_style) + { + finished_strikethrough = current_strikethrough.take(); + } + if let Some(run_strikethrough) = style_run.strikethrough.as_ref() { + current_strikethrough.get_or_insert(( + point( + glyph_origin.x, + glyph_origin.y + + (((layout.ascent * 0.5) + baseline_offset.y) * 0.5), + ), + StrikethroughStyle { + color: Some(run_strikethrough.color.unwrap_or(style_run.color)), + thickness: run_strikethrough.thickness, + }, + )); + } + + run_end += style_run.len as usize; + color = style_run.color; + } else { + run_end = layout.len; + finished_underline = current_underline.take(); + finished_strikethrough = current_strikethrough.take(); + } + } + + if let Some((mut underline_origin, underline_style, underline_range)) = + finished_underline + { + if underline_origin.x == glyph_origin.x { + underline_origin.x -= max_glyph_size.width.half(); + }; + paint_underline( + underline_range, + underline_origin, + glyph_origin.x - underline_origin.x, + &underline_style, + window, + ); + } + + if let Some((mut strikethrough_origin, strikethrough_style)) = + finished_strikethrough + { + if strikethrough_origin.x == glyph_origin.x { + strikethrough_origin.x -= max_glyph_size.width.half(); + }; + window.paint_strikethrough( + strikethrough_origin, + glyph_origin.x - strikethrough_origin.x, + &strikethrough_style, + ); + } + + let max_glyph_bounds = Bounds { + origin: glyph_origin, + size: max_glyph_size, + }; + + let content_mask = window.content_mask(); + if max_glyph_bounds.intersects(&content_mask.bounds) { + let vertical_offset = point(px(0.0), glyph.position.y); + if glyph.is_emoji { + window.paint_emoji( + glyph_origin + baseline_offset + vertical_offset, + run.font_id, + glyph.id, + layout.font_size, + )?; + } else { + window.paint_glyph( + glyph_origin + baseline_offset + vertical_offset, + run.font_id, + glyph.id, + layout.font_size, + color, + )?; + } + } + } + } + + let mut last_line_end_x = first_glyph_x + layout.width; + if let Some(boundary) = wrap_boundaries.last() { + let run = &layout.runs[boundary.run_ix]; + let glyph = &run.glyphs[boundary.glyph_ix]; + last_line_end_x -= glyph.position.x; + } + + if let Some((mut underline_start, underline_style, underline_range)) = + current_underline.take() + { + if last_line_end_x == underline_start.x { + underline_start.x -= max_glyph_size.width.half() + }; + paint_underline( + underline_range, + underline_start, + last_line_end_x - underline_start.x, + &underline_style, + window, + ); + } + + if let Some((mut strikethrough_start, strikethrough_style)) = current_strikethrough.take() { + if last_line_end_x == strikethrough_start.x { + strikethrough_start.x -= max_glyph_size.width.half() + }; + window.paint_strikethrough( + strikethrough_start, + last_line_end_x - strikethrough_start.x, + &strikethrough_style, + ); + } + + Ok(()) + }) +} + +fn paint_line_background( + origin: Point, + layout: &LineLayout, + line_height: Pixels, + align: TextAlign, + align_width: Option, + decoration_runs: &[DecorationRun], + wrap_boundaries: &[WrapBoundary], + window: &mut Window, + cx: &mut App, +) -> Result<()> { + let line_bounds = line_paint_bounds( + origin, + layout, + line_height, + align, + align_width, + wrap_boundaries, + ); + window.paint_layer(line_bounds, |window| { + let mut decoration_runs = decoration_runs.iter(); + let mut wraps = wrap_boundaries.iter().peekable(); + let mut run_end = 0; + let mut current_background: Option<(Point, Hsla)> = None; + let text_system = cx.text_system().clone(); + let mut glyph_origin = point( + aligned_origin_x( + origin, + align_width.unwrap_or(layout.width), + px(0.0), + &align, + layout, + wraps.peek(), + ), + origin.y, + ); + let mut prev_glyph_position = Point::default(); + let mut max_glyph_size = size(px(0.), px(0.)); + for (run_ix, run) in layout.runs.iter().enumerate() { + max_glyph_size = text_system.bounding_box(run.font_id, layout.font_size).size; + + for (glyph_ix, glyph) in run.glyphs.iter().enumerate() { + glyph_origin.x += glyph.position.x - prev_glyph_position.x; + + if wraps.peek() == Some(&&WrapBoundary { run_ix, glyph_ix }) { + wraps.next(); + if let Some((background_origin, background_color)) = current_background.as_mut() + { + if glyph_origin.x == background_origin.x { + background_origin.x -= max_glyph_size.width.half() + } + window.paint_quad(fill( + Bounds { + origin: *background_origin, + size: size(glyph_origin.x - background_origin.x, line_height), + }, + *background_color, + )); + if glyph.index < run_end { + background_origin.x = origin.x; + background_origin.y += line_height; + } else { + current_background = None; + } + } + + glyph_origin.x = aligned_origin_x( + origin, + align_width.unwrap_or(layout.width), + glyph.position.x, + &align, + layout, + wraps.peek(), + ); + glyph_origin.y += line_height; + } + prev_glyph_position = glyph.position; + + let mut finished_background: Option<(Point, Hsla)> = None; + if glyph.index >= run_end { + let mut style_run = decoration_runs.next(); + + // ignore style runs that apply to a partial glyph + while let Some(run) = style_run { + if glyph.index < run_end + (run.len as usize) { + break; + } + run_end += run.len as usize; + style_run = decoration_runs.next(); + } + + if let Some(style_run) = style_run { + if let Some((_, background_color)) = &mut current_background + && style_run.background_color.as_ref() != Some(background_color) + { + finished_background = current_background.take(); + } + if let Some(run_background) = style_run.background_color { + current_background.get_or_insert(( + point(glyph_origin.x, glyph_origin.y), + run_background, + )); + } + run_end += style_run.len as usize; + } else { + run_end = layout.len; + finished_background = current_background.take(); + } + } + + if let Some((mut background_origin, background_color)) = finished_background { + let mut width = glyph_origin.x - background_origin.x; + if background_origin.x == glyph_origin.x { + background_origin.x -= max_glyph_size.width.half(); + }; + window.paint_quad(fill( + Bounds { + origin: background_origin, + size: size(width, line_height), + }, + background_color, + )); + } + } + } + + let mut last_line_end_x = origin.x + layout.width; + if let Some(boundary) = wrap_boundaries.last() { + let run = &layout.runs[boundary.run_ix]; + let glyph = &run.glyphs[boundary.glyph_ix]; + last_line_end_x -= glyph.position.x; + } + + if let Some((mut background_origin, background_color)) = current_background.take() { + if last_line_end_x == background_origin.x { + background_origin.x -= max_glyph_size.width.half() + }; + window.paint_quad(fill( + Bounds { + origin: background_origin, + size: size(last_line_end_x - background_origin.x, line_height), + }, + background_color, + )); + } + + Ok(()) + }) +} + +fn line_paint_bounds( + origin: Point, + layout: &LineLayout, + line_height: Pixels, + align: TextAlign, + align_width: Option, + wrap_boundaries: &[WrapBoundary], +) -> Bounds { + let mut bounds = Bounds::new( + origin, + size( + layout.width, + line_height * (wrap_boundaries.len() as f32 + 1.), + ), + ); + if align == TextAlign::Left || layout.len == 0 { + return bounds; + } + + let align_width = align_width.unwrap_or(layout.width); + let mut row_start = Pixels::ZERO; + let row_ends = wrap_boundaries + .iter() + .map(|boundary| { + layout.runs[boundary.run_ix].glyphs[boundary.glyph_ix] + .position + .x + }) + .chain([layout.width]); + for (row, row_end) in row_ends.enumerate() { + let width = row_end - row_start; + let offset = match align { + TextAlign::Left => Pixels::ZERO, + TextAlign::Center => (align_width - width) / 2., + TextAlign::Right => align_width - width, + }; + bounds = bounds.union(&Bounds::new( + point(origin.x + offset, origin.y + line_height * row as f32), + size(width, line_height), + )); + row_start = row_end; + } + bounds +} + +fn aligned_origin_x( + origin: Point, + align_width: Pixels, + last_glyph_x: Pixels, + align: &TextAlign, + layout: &LineLayout, + wrap_boundary: Option<&&WrapBoundary>, +) -> Pixels { + let end_of_line = if let Some(WrapBoundary { run_ix, glyph_ix }) = wrap_boundary { + layout.runs[*run_ix].glyphs[*glyph_ix].position.x + } else { + layout.width + }; + + let line_width = end_of_line - last_glyph_x; + + match align { + TextAlign::Left => origin.x, + TextAlign::Center => (origin.x * 2.0 + align_width - line_width) / 2.0, + TextAlign::Right => origin.x + align_width - line_width, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AppContext as _, Context, FontId, GlyphId, IntoElement, Render, ShapedGlyph, ShapedRun, + Styled, TestAppContext, TextRun, Underline, canvas, font, hsla, + }; + use std::rc::Rc; + + /// Helper: build a ShapedLine from glyph descriptors without the platform text system. + /// Each glyph is described as (byte_index, x_position). + fn make_shaped_line( + text: &str, + glyphs: &[(usize, f32)], + width: f32, + decorations: &[DecorationRun], + ) -> ShapedLine { + let shaped_glyphs: Vec = glyphs + .iter() + .map(|&(index, x)| ShapedGlyph { + id: GlyphId(0), + position: point(px(x), px(0.0)), + index, + is_emoji: false, + }) + .collect(); + + ShapedLine { + layout: Arc::new(LineLayout { + font_size: px(16.0), + width: px(width), + ascent: px(12.0), + descent: px(4.0), + runs: vec![ShapedRun { + font_id: FontId(0), + glyphs: shaped_glyphs, + }], + len: text.len(), + }), + text: SharedString::new(text), + decoration_runs: SmallVec::from(decorations.to_vec()), + } + } + + #[test] + fn test_aligned_line_paint_bounds() { + let line = make_shaped_line("abcd", &[(0, 0.), (1, 10.), (2, 20.), (3, 30.)], 40., &[]); + let origin = point(px(10.), px(20.)); + let line_height = px(16.); + for (wrapped, align_width, expected_edges) in [ + (false, None, [(10., 50.), (10., 50.), (10., 50.)]), + (true, None, [(10., 50.), (10., 50.), (10., 50.)]), + (false, Some(40.), [(10., 50.), (10., 50.), (10., 50.)]), + (true, Some(40.), [(10., 50.), (10., 50.), (10., 50.)]), + (false, Some(100.), [(10., 50.), (10., 80.), (10., 110.)]), + (true, Some(100.), [(10., 50.), (10., 70.), (10., 110.)]), + (false, Some(10.), [(10., 50.), (-5., 50.), (-20., 50.)]), + (true, Some(10.), [(10., 50.), (5., 50.), (0., 50.)]), + (false, Some(0.), [(10., 50.), (-10., 50.), (-30., 50.)]), + (true, Some(0.), [(10., 50.), (0., 50.), (-10., 50.)]), + ] { + let boundaries = if wrapped { + vec![WrapBoundary { + run_ix: 0, + glyph_ix: 2, + }] + } else { + Vec::new() + }; + for (align, (left, right)) in [TextAlign::Left, TextAlign::Center, TextAlign::Right] + .into_iter() + .zip(expected_edges) + { + assert_eq!( + line_paint_bounds( + origin, + &line.layout, + line_height, + align, + align_width.map(px), + &boundaries, + ), + Bounds::new( + point(px(left), origin.y), + size(px(right - left), px(if wrapped { 32. } else { 16. })), + ), + "wrapped={wrapped}, align={align:?}, align_width={align_width:?}", + ); + } + } + let empty = make_shaped_line("", &[], 0., &[]); + for align in [TextAlign::Left, TextAlign::Center, TextAlign::Right] { + assert_eq!( + line_paint_bounds( + origin, + &empty.layout, + line_height, + align, + Some(px(100.)), + &[] + ), + Bounds::new(origin, size(Pixels::ZERO, line_height)), + ); + } + } + + #[gpui::test] + fn test_underline_handler_matches_default_paint(cx: &mut TestAppContext) { + test_underline_handler_at_scales(cx, |window, cx| { + let first_style = UnderlineStyle { + thickness: px(1.), + color: Some(hsla(0., 1., 0.5, 1.)), + wavy: true, + }; + let last_style = UnderlineStyle { + color: Some(hsla(0.5, 1., 0.5, 1.)), + wavy: false, + ..first_style + }; + let fallback_style = UnderlineStyle { + color: Some(black()), + ..first_style + }; + let decoration = DecorationRun { + len: 1, + color: black(), + background_color: None, + underline: Some(first_style), + strikethrough: None, + }; + let line = underline_test_line( + "aébcde", + &[ + decoration.clone(), + DecorationRun { + len: 2, + ..decoration.clone() + }, + DecorationRun { + underline: None, + ..decoration.clone() + }, + DecorationRun { + underline: Some(UnderlineStyle { + color: None, + ..first_style + }), + ..decoration.clone() + }, + DecorationRun { + underline: Some(last_style), + ..decoration.clone() + }, + DecorationRun { + underline: Some(last_style), + ..decoration + }, + ], + false, + window, + ); + assert_eq!(line.width(), px(48.)); + for origin_x in [-3.25, 0., 4.25] { + for (align, align_width, offset) in [ + (TextAlign::Left, None, 0.), + (TextAlign::Center, None, 0.), + (TextAlign::Right, None, 0.), + (TextAlign::Left, Some(px(96.)), 0.), + (TextAlign::Center, Some(px(96.)), 24.), + (TextAlign::Right, Some(px(96.)), 48.), + ] { + let origin = point(px(origin_x), px(12.25)); + let line_height = px(20.); + window.next_frame.scene.clear(); + line.paint(origin, line_height, align, align_width, window, cx) + .unwrap(); + let original = window.next_frame.scene.underlines.clone(); + window.next_frame.scene.clear(); + line.layout + .paint( + origin, + line_height, + align, + align_width, + &line.decoration_runs, + window, + cx, + ) + .unwrap(); + assert_underline_primitives_eq(&window.next_frame.scene.underlines, &original); + + window.next_frame.scene.clear(); + let mut strokes = Vec::new(); + line.paint_with_underline_handler( + origin, + line_height, + align, + align_width, + window, + cx, + |range, origin, width, style, window| { + strokes.push((range, origin, width, *style)); + window.paint_underline(origin, width, style); + }, + ) + .unwrap(); + let start = px(origin_x + offset); + let y = origin.y + underline_y_offset(line_height, line.ascent, line.descent); + assert_eq!( + strokes, + [ + (0..3, point(start, y), px(16.), first_style), + (4..5, point(start + px(24.), y), px(8.), fallback_style), + (5..7, point(start + px(32.), y), px(16.), last_style), + ] + ); + assert_underline_primitives_eq(&window.next_frame.scene.underlines, &original); + + window.next_frame.scene.clear(); + let mut captured = Vec::new(); + line.paint_with_underline_handler( + origin, + line_height, + align, + align_width, + window, + cx, + |range, origin, width, style, _| { + captured.push((range, origin, width, *style)) + }, + ) + .unwrap(); + assert_eq!(captured, strokes); + assert_eq!(window.next_frame.scene.underlines.len(), 0); + } + } + for text in ["", "abc"] { + let line = underline_test_line(text, &[], false, window); + let mut calls = 0; + line.paint_with_underline_handler( + point(px(4.), px(10.)), + px(20.), + TextAlign::Left, + None, + window, + cx, + |_, _, _, _, _| calls += 1, + ) + .unwrap(); + assert_eq!(calls, 0); + } + }); + } + + #[gpui::test] + fn test_underline_handler_reports_zero_advance_geometry(cx: &mut TestAppContext) { + test_underline_handler_at_scales(cx, |window, cx| { + let first_style = UnderlineStyle { + thickness: px(1.), + color: Some(black()), + wavy: true, + }; + let last_style = UnderlineStyle { + wavy: false, + ..first_style + }; + let decoration = DecorationRun { + len: 1, + color: black(), + background_color: None, + underline: Some(first_style), + strikethrough: None, + }; + let line = underline_test_line( + "ab", + &[ + decoration.clone(), + DecorationRun { + underline: Some(last_style), + ..decoration + }, + ], + true, + window, + ); + let half_width = cx + .text_system() + .bounding_box(line.runs[0].font_id, line.font_size) + .size + .width + / 2.; + let origin = point(px(40.25), px(10.25)); + let line_height = px(20.); + let y = origin.y + underline_y_offset(line_height, line.ascent, line.descent); + for (align, offset) in [ + (TextAlign::Left, 0.), + (TextAlign::Center, 16.), + (TextAlign::Right, 32.), + ] { + window.next_frame.scene.clear(); + line.paint(origin, line_height, align, Some(px(32.)), window, cx) + .unwrap(); + let original = window.next_frame.scene.underlines.clone(); + window.next_frame.scene.clear(); + let mut strokes = Vec::new(); + line.paint_with_underline_handler( + origin, + line_height, + align, + Some(px(32.)), + window, + cx, + |range, origin, width, style, window| { + strokes.push((range, origin, width, *style)); + window.paint_underline(origin, width, style); + }, + ) + .unwrap(); + let end = origin.x + px(offset); + let start = point(end - half_width, y); + let width = end - start.x; + assert_eq!( + strokes, + [ + (0..1, start, width, first_style), + (1..2, start, width, last_style), + ] + ); + assert_underline_primitives_eq(&window.next_frame.scene.underlines, &original); + } + }); + } + + #[gpui::test] + fn test_underline_handler_matches_wrapped_paint(cx: &mut TestAppContext) { + test_underline_handler_at_scales(cx, |window, cx| { + let style = UnderlineStyle { + thickness: px(1.), + color: Some(black()), + wavy: true, + }; + for zero_advance in [false, true] { + let line = underline_test_line( + "abcd", + &[DecorationRun { + len: 4, + color: black(), + background_color: None, + underline: Some(style), + strikethrough: None, + }], + zero_advance, + window, + ); + let half_width = cx + .text_system() + .bounding_box(line.runs[0].font_id, line.font_size) + .size + .width + / 2.; + let origin = point(px(40.25), px(10.25)); + let line_height = px(20.); + let y = origin.y + underline_y_offset(line_height, line.ascent, line.descent); + let wrapped = WrappedLine { + layout: Arc::new(WrappedLineLayout { + unwrapped_layout: line.layout, + wrap_boundaries: SmallVec::from_buf([WrapBoundary { + run_ix: 0, + glyph_ix: 2, + }]), + wrap_width: Some(px(16.)), + }), + text: line.text, + decoration_runs: line.decoration_runs.into_vec(), + }; + window.next_frame.scene.clear(); + wrapped + .paint(origin, line_height, TextAlign::Left, None, window, cx) + .unwrap(); + let original = window.next_frame.scene.underlines.clone(); + window.next_frame.scene.clear(); + let mut strokes = Vec::new(); + paint_line( + origin, + &wrapped.unwrapped_layout, + line_height, + TextAlign::Left, + Some(px(16.)), + &wrapped.decoration_runs, + &wrapped.wrap_boundaries, + window, + cx, + &mut |range, origin, width, style, window| { + strokes.push((range, origin, width, *style)); + window.paint_underline(origin, width, style); + }, + ) + .unwrap(); + let (start, width) = if zero_advance { + let start = origin.x - half_width; + (start, origin.x - start) + } else { + (origin.x, px(16.)) + }; + assert_eq!( + strokes, + [ + (0..4, point(start, y), width, style), + (0..4, point(start, y + line_height), width, style), + ] + ); + assert_underline_primitives_eq(&window.next_frame.scene.underlines, &original); + } + }); + } + + #[test] + fn test_split_at_invariants() { + // Split "abcdef" at every possible byte index and verify structural invariants. + let line = make_shaped_line( + "abcdef", + &[ + (0, 0.0), + (1, 10.0), + (2, 20.0), + (3, 30.0), + (4, 40.0), + (5, 50.0), + ], + 60.0, + &[], + ); + + for i in 0..=6 { + let (left, right) = line.split_at(i); + + assert_eq!( + left.width() + right.width(), + line.width(), + "widths must sum at split={i}" + ); + assert_eq!( + left.len() + right.len(), + line.len(), + "lengths must sum at split={i}" + ); + assert_eq!( + format!("{}{}", left.text.as_ref(), right.text.as_ref()), + "abcdef", + "text must concatenate at split={i}" + ); + assert_eq!(left.font_size, line.font_size, "font_size at split={i}"); + assert_eq!(right.ascent, line.ascent, "ascent at split={i}"); + assert_eq!(right.descent, line.descent, "descent at split={i}"); + } + + // Edge: split at 0 produces no left runs, full content on right + let (left, right) = line.split_at(0); + assert_eq!(left.runs.len(), 0); + assert_eq!(right.runs[0].glyphs.len(), 6); + + // Edge: split at end produces full content on left, no right runs + let (left, right) = line.split_at(6); + assert_eq!(left.runs[0].glyphs.len(), 6); + assert_eq!(right.runs.len(), 0); + } + + #[test] + fn test_split_at_glyph_rebasing() { + // Two font runs (simulating a font fallback boundary at byte 3): + // run A (FontId 0): glyphs at bytes 0,1,2 positions 0,10,20 + // run B (FontId 1): glyphs at bytes 3,4,5 positions 30,40,50 + // Successive splits simulate the incremental splitting done during wrap. + let line = ShapedLine { + layout: Arc::new(LineLayout { + font_size: px(16.0), + width: px(60.0), + ascent: px(12.0), + descent: px(4.0), + runs: vec![ + ShapedRun { + font_id: FontId(0), + glyphs: vec![ + ShapedGlyph { + id: GlyphId(0), + position: point(px(0.0), px(0.0)), + index: 0, + is_emoji: false, + }, + ShapedGlyph { + id: GlyphId(0), + position: point(px(10.0), px(0.0)), + index: 1, + is_emoji: false, + }, + ShapedGlyph { + id: GlyphId(0), + position: point(px(20.0), px(0.0)), + index: 2, + is_emoji: false, + }, + ], + }, + ShapedRun { + font_id: FontId(1), + glyphs: vec![ + ShapedGlyph { + id: GlyphId(0), + position: point(px(30.0), px(0.0)), + index: 3, + is_emoji: false, + }, + ShapedGlyph { + id: GlyphId(0), + position: point(px(40.0), px(0.0)), + index: 4, + is_emoji: false, + }, + ShapedGlyph { + id: GlyphId(0), + position: point(px(50.0), px(0.0)), + index: 5, + is_emoji: false, + }, + ], + }, + ], + len: 6, + }), + text: "abcdef".into(), + decoration_runs: SmallVec::new(), + }; + + // First split at byte 2 — mid-run in run A + let (first, remainder) = line.split_at(2); + assert_eq!(first.text.as_ref(), "ab"); + assert_eq!(first.runs.len(), 1); + assert_eq!(first.runs[0].font_id, FontId(0)); + + // Remainder "cdef" should have two runs: tail of A (1 glyph) + all of B (3 glyphs) + assert_eq!(remainder.text.as_ref(), "cdef"); + assert_eq!(remainder.runs.len(), 2); + assert_eq!(remainder.runs[0].font_id, FontId(0)); + assert_eq!(remainder.runs[0].glyphs.len(), 1); + assert_eq!(remainder.runs[0].glyphs[0].index, 0); + assert_eq!(remainder.runs[0].glyphs[0].position.x, px(0.0)); + assert_eq!(remainder.runs[1].font_id, FontId(1)); + assert_eq!(remainder.runs[1].glyphs[0].index, 1); + assert_eq!(remainder.runs[1].glyphs[0].position.x, px(10.0)); + + // Second split at byte 2 within remainder — crosses the run boundary + let (second, final_part) = remainder.split_at(2); + assert_eq!(second.text.as_ref(), "cd"); + assert_eq!(final_part.text.as_ref(), "ef"); + assert_eq!(final_part.runs[0].glyphs[0].index, 0); + assert_eq!(final_part.runs[0].glyphs[0].position.x, px(0.0)); + + // Widths must sum across all three pieces + assert_eq!( + first.width() + second.width() + final_part.width(), + line.width() + ); + } + + #[test] + fn test_split_at_decorations() { + // Three decoration runs: red [0..2), green [2..5), blue [5..6). + // Split at byte 3 — red goes entirely left, green straddles, blue goes entirely right. + let red = Hsla { + h: 0.0, + s: 1.0, + l: 0.5, + a: 1.0, + }; + let green = Hsla { + h: 0.3, + s: 1.0, + l: 0.5, + a: 1.0, + }; + let blue = Hsla { + h: 0.6, + s: 1.0, + l: 0.5, + a: 1.0, + }; + + let line = make_shaped_line( + "abcdef", + &[ + (0, 0.0), + (1, 10.0), + (2, 20.0), + (3, 30.0), + (4, 40.0), + (5, 50.0), + ], + 60.0, + &[ + DecorationRun { + len: 2, + color: red, + background_color: None, + underline: None, + strikethrough: None, + }, + DecorationRun { + len: 3, + color: green, + background_color: None, + underline: None, + strikethrough: None, + }, + DecorationRun { + len: 1, + color: blue, + background_color: None, + underline: None, + strikethrough: None, + }, + ], + ); + + let (left, right) = line.split_at(3); + + // Left: red(2) + green(1) — green straddled, left portion has len 1 + assert_eq!(left.decoration_runs.len(), 2); + assert_eq!(left.decoration_runs[0].len, 2); + assert_eq!(left.decoration_runs[0].color, red); + assert_eq!(left.decoration_runs[1].len, 1); + assert_eq!(left.decoration_runs[1].color, green); + + // Right: green(2) + blue(1) — green straddled, right portion has len 2 + assert_eq!(right.decoration_runs.len(), 2); + assert_eq!(right.decoration_runs[0].len, 2); + assert_eq!(right.decoration_runs[0].color, green); + assert_eq!(right.decoration_runs[1].len, 1); + assert_eq!(right.decoration_runs[1].color, blue); + } + + struct UnderlineHandlerTestView(Rc); + + impl Render for UnderlineHandlerTestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let paint = self.0.clone(); + canvas( + |_, _, _| {}, + move |_, _, window, cx| { + window.with_element_opacity(Some(0.5), |window| paint(window, cx)); + }, + ) + .size_full() + } + } + + fn test_underline_handler_at_scales( + cx: &mut TestAppContext, + paint: impl Fn(&mut Window, &mut App) + 'static, + ) { + let window = cx.add_window(move |_, _| UnderlineHandlerTestView(Rc::new(paint))); + for scale in [1., 1.25, 1.5, 2., 3.] { + cx.simulate_window_scale_factor_change(window.into(), scale); + cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + } + } + + fn underline_test_line( + text: &str, + decorations: &[DecorationRun], + zero_advance: bool, + window: &Window, + ) -> ShapedLine { + let mut line = window.text_system().shape_line( + SharedString::new(text), + px(16.), + &[TextRun { + len: text.len(), + font: font(".ZedMono"), + color: black(), + ..TextRun::default() + }], + None, + ); + line.decoration_runs = SmallVec::from(decorations.to_vec()); + let layout = &line.layout; + let mut runs = layout.runs.clone(); + let advance = if zero_advance { px(0.) } else { px(8.) }; + let mut width = px(0.); + for glyph in runs.iter_mut().flat_map(|run| &mut run.glyphs) { + glyph.position.x = width; + width += advance; + } + line.layout = Arc::new(LineLayout { + font_size: layout.font_size, + width, + ascent: layout.ascent, + descent: layout.descent, + runs, + len: layout.len, + }); + line + } + + fn assert_underline_primitives_eq(actual: &[Underline], expected: &[Underline]) { + assert_eq!(actual.len(), expected.len()); + for (actual, expected) in actual.iter().zip(expected) { + assert_eq!(actual.bounds, expected.bounds); + assert_eq!(actual.content_mask, expected.content_mask); + assert_eq!(actual.color, expected.color); + assert_eq!(actual.thickness, expected.thickness); + assert_eq!(actual.wavy, expected.wavy); + assert_eq!(actual.order, expected.order); + assert_eq!(actual.pad, expected.pad); + } + } + + #[test] + fn test_cursor_preserves_shaping_metadata_across_runs() { + let line = ShapedLine { + layout: Arc::new(LineLayout { + font_size: px(16.0), + width: px(50.0), + ascent: px(12.0), + descent: px(4.0), + runs: vec![ + ShapedRun { + font_id: FontId(3), + glyphs: vec![ + ShapedGlyph { + id: GlyphId(11), + position: point(px(0.0), px(1.0)), + index: 0, + is_emoji: true, + }, + ShapedGlyph { + id: GlyphId(12), + position: point(px(17.0), px(1.0)), + index: 1, + is_emoji: false, + }, + ShapedGlyph { + id: GlyphId(13), + position: point(px(19.0), px(-1.0)), + index: 1, + is_emoji: false, + }, + ], + }, + ShapedRun { + font_id: FontId(8), + glyphs: vec![ + ShapedGlyph { + id: GlyphId(21), + position: point(px(25.0), px(1.0)), + index: 5, + is_emoji: true, + }, + ShapedGlyph { + id: GlyphId(22), + position: point(px(41.0), px(1.0)), + index: 7, + is_emoji: false, + }, + ], + }, + ], + len: 10, + }), + text: "a😀bcdef".into(), + decoration_runs: SmallVec::new(), + }; + let mut cursor = line.cursor(); + let first = cursor.take_until(5); + assert_eq!(first.text.as_ref(), "a😀"); + assert_eq!(first.runs[0].font_id, FontId(3)); + assert_eq!(first.runs[0].glyphs[0].id, GlyphId(11)); + assert!(first.runs[0].glyphs[0].is_emoji); + assert_eq!(first.runs[0].glyphs[1].index, 1); + assert_eq!(first.runs[0].glyphs[1].position, point(px(17.0), px(1.0))); + assert_eq!(first.runs[0].glyphs.len(), 3); + assert_eq!(first.runs[0].glyphs[2].index, 1); + assert_eq!(first.runs[0].glyphs[2].position, point(px(19.0), px(-1.0))); + assert_eq!(cursor.x_offset(), px(25.0)); + + let second = cursor.take_until(7); + assert_eq!(second.text.as_ref(), "bc"); + assert_eq!(second.runs[0].font_id, FontId(8)); + assert_eq!(second.runs[0].glyphs[0].id, GlyphId(21)); + assert_eq!(second.runs[0].glyphs[0].index, 0); + assert_eq!(second.runs[0].glyphs[0].position, point(px(0.0), px(1.0))); + assert_eq!(cursor.x_offset(), px(41.0)); + + let final_part = cursor.take_until(10); + assert_eq!(final_part.text.as_ref(), "def"); + assert_eq!(final_part.runs[0].font_id, FontId(8)); + assert_eq!(final_part.runs[0].glyphs[0].id, GlyphId(22)); + assert_eq!(final_part.runs[0].glyphs[0].index, 0); + assert_eq!( + final_part.runs[0].glyphs[0].position, + point(px(0.0), px(1.0)) + ); + } + + #[test] + fn test_cursor_preserves_existing_visual_order_splitting() { + let line = make_shaped_line("abc", &[(0, 0.0), (2, 10.0), (1, 20.0)], 30.0, &[]); + let mut cursor = line.cursor(); + let mut remainder = line.clone(); + let mut previous_boundary = 0; + for boundary in [0, 1, 2, 3] { + let (expected, rest) = remainder.split_at(boundary - previous_boundary); + let actual = cursor.take_until(boundary); + assert_eq!(actual.text, expected.text); + assert_eq!(actual.width(), expected.width()); + assert_eq!(actual.runs.len(), expected.runs.len()); + for (actual, expected) in actual.runs.iter().zip(&expected.runs) { + assert_eq!(actual.font_id, expected.font_id); + assert_eq!(actual.glyphs.len(), expected.glyphs.len()); + for (actual, expected) in actual.glyphs.iter().zip(&expected.glyphs) { + assert_eq!(actual.id, expected.id); + assert_eq!(actual.index, expected.index); + assert_eq!(actual.position, expected.position); + } + } + assert_eq!(cursor.x_offset(), line.x_for_index(boundary)); + remainder = rest; + previous_boundary = boundary; + } + } + + #[test] + fn test_cursor_partitions_one_decoration_across_three_chunks() { + let line = make_shaped_line( + "abcdef", + &[ + (0, 0.0), + (1, 10.0), + (2, 20.0), + (3, 30.0), + (4, 40.0), + (5, 50.0), + ], + 60.0, + &[DecorationRun { + len: 6, + color: Hsla { + h: 0.2, + s: 0.4, + l: 0.6, + a: 1.0, + }, + background_color: None, + underline: None, + strikethrough: None, + }], + ); + let mut cursor = line.cursor(); + assert_eq!(cursor.take_until(2).decoration_runs[0].len, 2); + assert_eq!(cursor.take_until(4).decoration_runs[0].len, 2); + assert_eq!(cursor.take_until(6).decoration_runs[0].len, 2); + } + + #[test] + fn test_cursor_matches_successive_splits_at_ordered_boundaries() { + let decorations: Vec<_> = [2, 0, 3, 1] + .into_iter() + .map(|len| DecorationRun { + len, + color: Hsla { + h: len as f32 / 10.0, + s: 0.5, + l: 0.5, + a: 1.0, + }, + background_color: Some(black()), + underline: None, + strikethrough: None, + }) + .collect(); + let line = make_shaped_line( + "abcdef", + &[(0, 5.0), (0, 5.0), (2, 15.0), (4, 25.0), (5, 35.0)], + 45.0, + &decorations, + ); + for first in 0..=line.len() { + for second in first..=line.len() { + let mut cursor = line.cursor(); + let mut remainder = line.clone(); + let mut previous_boundary = 0; + let mut total_width = px(0.0); + let mut text = String::new(); + for boundary in [first, second, line.len(), line.len()] { + let (expected, rest) = remainder.split_at(boundary - previous_boundary); + let actual = cursor.take_until(boundary); + assert_eq!(actual.text, expected.text); + assert_eq!(actual.len(), expected.len()); + assert_eq!(actual.width(), expected.width()); + assert_eq!(actual.runs.len(), expected.runs.len()); + for (actual, expected) in actual.runs.iter().zip(&expected.runs) { + assert_eq!(actual.font_id, expected.font_id); + assert_eq!(actual.glyphs.len(), expected.glyphs.len()); + for (actual, expected) in actual.glyphs.iter().zip(&expected.glyphs) { + assert_eq!(actual.id, expected.id); + assert_eq!(actual.index, expected.index); + assert_eq!(actual.position, expected.position); + } + } + assert_eq!(actual.decoration_runs.len(), expected.decoration_runs.len()); + for (actual, expected) in + actual.decoration_runs.iter().zip(&expected.decoration_runs) + { + assert_eq!(actual.len, expected.len); + assert_eq!(actual.color, expected.color); + assert_eq!(actual.background_color, expected.background_color); + } + total_width += actual.width(); + text.push_str(&actual.text); + remainder = rest; + previous_boundary = boundary; + } + assert_eq!(total_width, line.width()); + assert_eq!(text, line.text.as_ref()); + } + } + } + + #[test] + fn test_cursor_empty_chunks_and_repeated_boundaries() { + let line = make_shaped_line("ab", &[(0, 5.0), (1, 15.0)], 20.0, &[]); + let mut cursor = line.cursor(); + assert_eq!(cursor.take_until(0).text.as_ref(), ""); + assert_eq!(cursor.take_until(0).text.as_ref(), ""); + assert_eq!(cursor.take_until(1).text.as_ref(), "a"); + assert_eq!(cursor.take_until(2).text.as_ref(), "b"); + assert_eq!(cursor.take_until(2).text.as_ref(), ""); + let empty = make_shaped_line("", &[], 0.0, &[]); + let piece = empty.cursor().take_until(0); + assert!(piece.text.is_empty()); + assert!(piece.runs.is_empty()); + assert_eq!(piece.width(), px(0.0)); + } + + #[test] + fn test_cursor_rejects_invalid_boundaries() { + let line = make_shaped_line("é", &[(0, 0.0)], 10.0, &[]); + let mut cursor = line.cursor(); + assert!( + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + cursor.take_until(1); + })) + .is_err() + ); + let mut cursor = line.cursor(); + cursor.take_until(2); + assert!( + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + cursor.take_until(0); + })) + .is_err() + ); + let mut cursor = line.cursor(); + assert!( + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + cursor.take_until(3); + })) + .is_err() + ); + } +} diff --git a/vendor/gpui-pre/src/text_system/line_layout.rs b/vendor/gpui-pre/src/text_system/line_layout.rs new file mode 100644 index 00000000..f0bf1211 --- /dev/null +++ b/vendor/gpui-pre/src/text_system/line_layout.rs @@ -0,0 +1,1190 @@ +use crate::{FontId, GlyphId, Pixels, PlatformTextSystem, Point, SharedString, Size, point, px}; +use collections::FxHashMap; +use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; +use smallvec::SmallVec; +use std::{ + borrow::Borrow, + hash::{Hash, Hasher}, + ops::Range, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, +}; + +use super::LineWrapper; + +/// A laid out and styled line of text +#[derive(Default, Debug)] +pub struct LineLayout { + /// The font size for this line + pub font_size: Pixels, + /// The width of the line + pub width: Pixels, + /// The ascent of the line + pub ascent: Pixels, + /// The descent of the line + pub descent: Pixels, + /// The shaped runs that make up this line + pub runs: Vec, + /// The length of the line in utf-8 bytes + pub len: usize, +} + +/// A run of text that has been shaped . +#[derive(Debug, Clone)] +pub struct ShapedRun { + /// The font id for this run + pub font_id: FontId, + /// The glyphs that make up this run + pub glyphs: Vec, +} + +/// A single glyph, ready to paint. +#[derive(Clone, Debug)] +pub struct ShapedGlyph { + /// The ID for this glyph, as determined by the text system. + pub id: GlyphId, + + /// The position of this glyph in its containing line. + pub position: Point, + + /// The index of this glyph in the original text. + pub index: usize, + + /// Whether this glyph is an emoji + pub is_emoji: bool, +} + +impl LineLayout { + /// The index for the character at the given x coordinate + pub fn index_for_x(&self, x: Pixels) -> Option { + if x >= self.width { + None + } else { + for run in self.runs.iter().rev() { + for glyph in run.glyphs.iter().rev() { + if glyph.position.x <= x { + return Some(glyph.index); + } + } + } + Some(0) + } + } + + /// closest_index_for_x returns the character boundary closest to the given x coordinate + /// (e.g. to handle aligning up/down arrow keys) + pub fn closest_index_for_x(&self, x: Pixels) -> usize { + let mut prev_index = 0; + let mut prev_x = px(0.); + + for run in self.runs.iter() { + for glyph in run.glyphs.iter() { + if glyph.position.x >= x { + if glyph.position.x - x < x - prev_x { + return glyph.index; + } else { + return prev_index; + } + } + prev_index = glyph.index; + prev_x = glyph.position.x; + } + } + + if self.len == 1 { + if x > self.width / 2. { + return 1; + } else { + return 0; + } + } + + self.len + } + + /// The x position of the character at the given index + pub fn x_for_index(&self, index: usize) -> Pixels { + for run in &self.runs { + for glyph in &run.glyphs { + if glyph.index >= index { + return glyph.position.x; + } + } + } + self.width + } + + /// The corresponding Font at the given index + pub fn font_id_for_index(&self, index: usize) -> Option { + for run in &self.runs { + for glyph in &run.glyphs { + if glyph.index >= index { + return Some(run.font_id); + } + } + } + None + } + + /// Split this layout at a byte index, returning `(prefix, suffix)`. + /// + /// - `prefix` contains glyphs for bytes `[0, byte_index)` with original positions. + /// Its width equals the x-advance up to the split point. + /// - `suffix` contains glyphs for bytes `[byte_index, len)` with positions + /// shifted left so the first glyph starts at x=0, and byte indices rebased to 0. + /// - `font_size`, `ascent`, and `descent` are copied to both halves. + pub fn split_at(&self, byte_index: usize) -> (LineLayout, LineLayout) { + let x_offset = self.x_for_index(byte_index); + + // Partition glyph runs. A single run may contribute glyphs to both halves. + let mut left_runs = Vec::new(); + let mut right_runs = Vec::new(); + + for run in &self.runs { + let split_pos = run.glyphs.partition_point(|g| g.index < byte_index); + + if split_pos > 0 { + left_runs.push(ShapedRun { + font_id: run.font_id, + glyphs: run.glyphs[..split_pos].to_vec(), + }); + } + + if split_pos < run.glyphs.len() { + let right_glyphs = run.glyphs[split_pos..] + .iter() + .map(|g| ShapedGlyph { + id: g.id, + position: point(g.position.x - x_offset, g.position.y), + index: g.index - byte_index, + is_emoji: g.is_emoji, + }) + .collect(); + right_runs.push(ShapedRun { + font_id: run.font_id, + glyphs: right_glyphs, + }); + } + } + + let left = LineLayout { + font_size: self.font_size, + width: x_offset, + ascent: self.ascent, + descent: self.descent, + runs: left_runs, + len: byte_index, + }; + + let right = LineLayout { + font_size: self.font_size, + width: self.width - x_offset, + ascent: self.ascent, + descent: self.descent, + runs: right_runs, + len: self.len - byte_index, + }; + + (left, right) + } + + fn compute_wrap_boundaries( + &self, + text: &str, + wrap_width: Pixels, + max_lines: Option, + ) -> SmallVec<[WrapBoundary; 1]> { + let mut boundaries = SmallVec::new(); + let mut first_non_whitespace_ix = None; + let mut last_candidate_ix = None; + let mut last_candidate_x = px(0.); + let mut last_boundary = WrapBoundary { + run_ix: 0, + glyph_ix: 0, + }; + let mut last_boundary_x = px(0.); + let mut prev_ch = '\0'; + let mut glyphs = self + .runs + .iter() + .enumerate() + .flat_map(move |(run_ix, run)| { + run.glyphs.iter().enumerate().map(move |(glyph_ix, glyph)| { + let character = text[glyph.index..].chars().next().unwrap(); + ( + WrapBoundary { run_ix, glyph_ix }, + character, + glyph.position.x, + ) + }) + }) + .peekable(); + + while let Some((boundary, ch, x)) = glyphs.next() { + if ch == '\n' { + continue; + } + + // Here is very similar to `LineWrapper::wrap_line` to determine text wrapping, + // but there are some differences, so we have to duplicate the code here. + if LineWrapper::is_word_char(ch) { + if prev_ch == ' ' && ch != ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = Some(boundary); + last_candidate_x = x; + } + } else { + if ch != ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = Some(boundary); + last_candidate_x = x; + } + } + + if ch != ' ' && first_non_whitespace_ix.is_none() { + first_non_whitespace_ix = Some(boundary); + } + + let next_x = glyphs.peek().map_or(self.width, |(_, _, x)| *x); + let width = next_x - last_boundary_x; + + if width > wrap_width && boundary > last_boundary { + // When used line_clamp, we should limit the number of lines. + if let Some(max_lines) = max_lines + && boundaries.len() >= max_lines.saturating_sub(1) + { + break; + } + + if let Some(last_candidate_ix) = last_candidate_ix.take() { + last_boundary = last_candidate_ix; + last_boundary_x = last_candidate_x; + } else { + last_boundary = boundary; + last_boundary_x = x; + } + boundaries.push(last_boundary); + } + prev_ch = ch; + } + + boundaries + } +} + +/// A line of text that has been wrapped to fit a given width +#[derive(Default, Debug)] +pub struct WrappedLineLayout { + /// The line layout, pre-wrapping. + pub unwrapped_layout: Arc, + + /// The boundaries at which the line was wrapped + pub wrap_boundaries: SmallVec<[WrapBoundary; 1]>, + + /// The width of the line, if it was wrapped + pub wrap_width: Option, +} + +/// A boundary at which a line was wrapped +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct WrapBoundary { + /// The index in the run just before the line was wrapped + pub run_ix: usize, + /// The index of the glyph just before the line was wrapped + pub glyph_ix: usize, +} + +impl WrappedLineLayout { + /// The length of the underlying text, in utf8 bytes. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { + self.unwrapped_layout.len + } + + /// The width of this line, in pixels, whether or not it was wrapped. + pub fn width(&self) -> Pixels { + self.wrap_width + .unwrap_or(Pixels::MAX) + .min(self.unwrapped_layout.width) + } + + /// The size of the whole wrapped text, for the given line_height. + /// can span multiple lines if there are multiple wrap boundaries. + pub fn size(&self, line_height: Pixels) -> Size { + Size { + width: self.width(), + height: line_height * (self.wrap_boundaries.len() + 1), + } + } + + /// The ascent of a line in this layout + pub fn ascent(&self) -> Pixels { + self.unwrapped_layout.ascent + } + + /// The descent of a line in this layout + pub fn descent(&self) -> Pixels { + self.unwrapped_layout.descent + } + + /// The wrap boundaries in this layout + pub fn wrap_boundaries(&self) -> &[WrapBoundary] { + &self.wrap_boundaries + } + + /// The font size of this layout + pub fn font_size(&self) -> Pixels { + self.unwrapped_layout.font_size + } + + /// The runs in this layout, sans wrapping + pub fn runs(&self) -> &[ShapedRun] { + &self.unwrapped_layout.runs + } + + /// The index corresponding to a given position in this layout for the given line height. + /// + /// See also [`Self::closest_index_for_position`]. + pub fn index_for_position( + &self, + position: Point, + line_height: Pixels, + ) -> Result { + self._index_for_position(position, line_height, false) + } + + /// The closest index to a given position in this layout for the given line height. + /// + /// Closest means the character boundary closest to the given position. + /// + /// See also [`LineLayout::closest_index_for_x`]. + pub fn closest_index_for_position( + &self, + position: Point, + line_height: Pixels, + ) -> Result { + self._index_for_position(position, line_height, true) + } + + fn _index_for_position( + &self, + mut position: Point, + line_height: Pixels, + closest: bool, + ) -> Result { + let wrapped_line_ix = (position.y / line_height) as usize; + + let wrapped_line_start_index; + let wrapped_line_start_x; + if wrapped_line_ix > 0 { + let Some(line_start_boundary) = self.wrap_boundaries.get(wrapped_line_ix - 1) else { + return Err(0); + }; + let run = &self.unwrapped_layout.runs[line_start_boundary.run_ix]; + let glyph = &run.glyphs[line_start_boundary.glyph_ix]; + wrapped_line_start_index = glyph.index; + wrapped_line_start_x = glyph.position.x; + } else { + wrapped_line_start_index = 0; + wrapped_line_start_x = Pixels::ZERO; + }; + + let wrapped_line_end_index; + let wrapped_line_end_x; + if wrapped_line_ix < self.wrap_boundaries.len() { + let next_wrap_boundary_ix = wrapped_line_ix; + let next_wrap_boundary = self.wrap_boundaries[next_wrap_boundary_ix]; + let run = &self.unwrapped_layout.runs[next_wrap_boundary.run_ix]; + let glyph = &run.glyphs[next_wrap_boundary.glyph_ix]; + wrapped_line_end_index = glyph.index; + wrapped_line_end_x = glyph.position.x; + } else { + wrapped_line_end_index = self.unwrapped_layout.len; + wrapped_line_end_x = self.unwrapped_layout.width; + }; + + let mut position_in_unwrapped_line = position; + position_in_unwrapped_line.x += wrapped_line_start_x; + if position_in_unwrapped_line.x < wrapped_line_start_x { + Err(wrapped_line_start_index) + } else if position_in_unwrapped_line.x >= wrapped_line_end_x { + Err(wrapped_line_end_index) + } else { + if closest { + Ok(self + .unwrapped_layout + .closest_index_for_x(position_in_unwrapped_line.x)) + } else { + // The shaper can place a trailing zero-width wrap boundary glyph slightly past + // the line's width, so the row can extend past where `index_for_x` has glyphs. + self.unwrapped_layout + .index_for_x(position_in_unwrapped_line.x) + .ok_or(wrapped_line_end_index) + } + } + } + + /// Returns the pixel position for the given byte index. + pub fn position_for_index(&self, index: usize, line_height: Pixels) -> Option> { + let mut line_start_ix = 0; + let mut line_end_indices = self + .wrap_boundaries + .iter() + .map(|wrap_boundary| { + let run = &self.unwrapped_layout.runs[wrap_boundary.run_ix]; + let glyph = &run.glyphs[wrap_boundary.glyph_ix]; + glyph.index + }) + .chain([self.len()]) + .enumerate(); + for (ix, line_end_ix) in line_end_indices { + let line_y = ix as f32 * line_height; + if index < line_start_ix { + break; + } else if index > line_end_ix { + line_start_ix = line_end_ix; + continue; + } else { + let line_start_x = self.unwrapped_layout.x_for_index(line_start_ix); + let x = self.unwrapped_layout.x_for_index(index) - line_start_x; + return Some(point(x, line_y)); + } + } + + None + } +} + +pub(crate) struct LineLayoutCache { + previous_frame: Mutex, + current_frame: RwLock, + platform_text_system: Arc, + /// Advances when [`TextSystem::add_fonts`] successfully changes the font database. + font_generation: Arc, + /// Records the generation represented by both frame caches. + cached_font_generation: AtomicUsize, +} + +#[derive(Default)] +struct FrameCache { + lines: FxHashMap, Arc>, + wrapped_lines: FxHashMap, Arc>, + used_lines: Vec>, + used_wrapped_lines: Vec>, + + // Content-addressable caches keyed by caller-provided text hash + layout params. + // These allow cache hits without materializing a contiguous `SharedString`. + // + // IMPORTANT: To support allocation-free lookups, we store these maps using a key type + // (`HashedCacheKeyRef`) that can be computed without building a contiguous `&str`/`SharedString`. + // On miss, we allocate once and store under an owned `HashedCacheKey`. + lines_by_hash: FxHashMap, Arc>, + wrapped_lines_by_hash: FxHashMap, Arc>, + used_lines_by_hash: Vec>, + used_wrapped_lines_by_hash: Vec>, +} + +#[derive(Clone, Default)] +pub(crate) struct LineLayoutIndex { + font_generation: usize, + lines_index: usize, + wrapped_lines_index: usize, + lines_by_hash_index: usize, + wrapped_lines_by_hash_index: usize, +} + +impl LineLayoutCache { + pub fn new( + platform_text_system: Arc, + font_generation: Arc, + ) -> Self { + let cached_font_generation = font_generation.load(Ordering::Acquire); + Self { + previous_frame: Mutex::default(), + current_frame: RwLock::default(), + platform_text_system, + font_generation, + cached_font_generation: AtomicUsize::new(cached_font_generation), + } + } + + pub fn layout_index(&self) -> LineLayoutIndex { + let font_generation = self.clear_if_font_generation_changed(); + let frame = self.current_frame.read(); + LineLayoutIndex { + font_generation, + lines_index: frame.used_lines.len(), + wrapped_lines_index: frame.used_wrapped_lines.len(), + lines_by_hash_index: frame.used_lines_by_hash.len(), + wrapped_lines_by_hash_index: frame.used_wrapped_lines_by_hash.len(), + } + } + + pub fn reuse_layouts(&self, range: Range) { + let font_generation = self.clear_if_font_generation_changed(); + if range.start.font_generation != font_generation + || range.end.font_generation != font_generation + { + return; + } + let mut current_frame = &mut *self.current_frame.write(); + let mut previous_frame = &mut *self.previous_frame.lock(); + + for key in &previous_frame.used_lines[range.start.lines_index..range.end.lines_index] { + if let Some((key, line)) = previous_frame.lines.remove_entry(key) { + current_frame.lines.insert(key, line); + } + current_frame.used_lines.push(key.clone()); + } + + for key in &previous_frame.used_wrapped_lines + [range.start.wrapped_lines_index..range.end.wrapped_lines_index] + { + if let Some((key, line)) = previous_frame.wrapped_lines.remove_entry(key) { + current_frame.wrapped_lines.insert(key, line); + } + current_frame.used_wrapped_lines.push(key.clone()); + } + + for key in &previous_frame.used_lines_by_hash + [range.start.lines_by_hash_index..range.end.lines_by_hash_index] + { + if let Some((key, line)) = previous_frame.lines_by_hash.remove_entry(key) { + current_frame.lines_by_hash.insert(key, line); + } + current_frame.used_lines_by_hash.push(key.clone()); + } + + for key in &previous_frame.used_wrapped_lines_by_hash + [range.start.wrapped_lines_by_hash_index..range.end.wrapped_lines_by_hash_index] + { + if let Some((key, line)) = previous_frame.wrapped_lines_by_hash.remove_entry(key) { + current_frame.wrapped_lines_by_hash.insert(key, line); + } + current_frame.used_wrapped_lines_by_hash.push(key.clone()); + } + } + + pub fn truncate_layouts(&self, index: LineLayoutIndex) { + let font_generation = self.clear_if_font_generation_changed(); + if index.font_generation != font_generation { + return; + } + let mut current_frame = &mut *self.current_frame.write(); + current_frame.used_lines.truncate(index.lines_index); + current_frame + .used_wrapped_lines + .truncate(index.wrapped_lines_index); + current_frame + .used_lines_by_hash + .truncate(index.lines_by_hash_index); + current_frame + .used_wrapped_lines_by_hash + .truncate(index.wrapped_lines_by_hash_index); + } + + pub fn finish_frame(&self) { + let _font_generation = self.clear_if_font_generation_changed(); + let mut curr_frame = self.current_frame.write(); + let mut prev_frame = self.previous_frame.lock(); + std::mem::swap(&mut *prev_frame, &mut *curr_frame); + curr_frame.lines.clear(); + curr_frame.wrapped_lines.clear(); + curr_frame.used_lines.clear(); + curr_frame.used_wrapped_lines.clear(); + + curr_frame.lines_by_hash.clear(); + curr_frame.wrapped_lines_by_hash.clear(); + curr_frame.used_lines_by_hash.clear(); + curr_frame.used_wrapped_lines_by_hash.clear(); + } + + pub fn layout_wrapped_line( + &self, + text: Text, + font_size: Pixels, + runs: &[FontRun], + wrap_width: Option, + max_lines: Option, + ) -> Arc + where + Text: AsRef, + SharedString: From, + { + let _font_generation = self.clear_if_font_generation_changed(); + let key = &CacheKeyRef { + text: text.as_ref(), + font_size, + runs, + wrap_width, + force_width: None, + } as &dyn AsCacheKeyRef; + + let current_frame = self.current_frame.upgradable_read(); + if let Some(layout) = current_frame.wrapped_lines.get(key) { + return layout.clone(); + } + + let previous_frame_entry = self.previous_frame.lock().wrapped_lines.remove_entry(key); + if let Some((key, layout)) = previous_frame_entry { + let mut current_frame = RwLockUpgradableReadGuard::upgrade(current_frame); + current_frame + .wrapped_lines + .insert(key.clone(), layout.clone()); + current_frame.used_wrapped_lines.push(key); + layout + } else { + drop(current_frame); + let text = SharedString::from(text); + let unwrapped_layout = self.layout_line::<&SharedString>(&text, font_size, runs, None); + let wrap_boundaries = if let Some(wrap_width) = wrap_width { + unwrapped_layout.compute_wrap_boundaries(text.as_ref(), wrap_width, max_lines) + } else { + SmallVec::new() + }; + let layout = Arc::new(WrappedLineLayout { + unwrapped_layout, + wrap_boundaries, + wrap_width, + }); + let key = Arc::new(CacheKey { + text, + font_size, + runs: SmallVec::from(runs), + wrap_width, + force_width: None, + }); + + let mut current_frame = self.current_frame.write(); + current_frame + .wrapped_lines + .insert(key.clone(), layout.clone()); + current_frame.used_wrapped_lines.push(key); + + layout + } + } + + pub fn layout_line( + &self, + text: Text, + font_size: Pixels, + runs: &[FontRun], + force_width: Option, + ) -> Arc + where + Text: AsRef, + SharedString: From, + { + let _font_generation = self.clear_if_font_generation_changed(); + let key = &CacheKeyRef { + text: text.as_ref(), + font_size, + runs, + wrap_width: None, + force_width, + } as &dyn AsCacheKeyRef; + + let current_frame = self.current_frame.upgradable_read(); + if let Some(layout) = current_frame.lines.get(key) { + return layout.clone(); + } + + let mut current_frame = RwLockUpgradableReadGuard::upgrade(current_frame); + if let Some((key, layout)) = self.previous_frame.lock().lines.remove_entry(key) { + current_frame.lines.insert(key.clone(), layout.clone()); + current_frame.used_lines.push(key); + layout + } else { + let text = SharedString::from(text); + let mut layout = self + .platform_text_system + .layout_line(&text, font_size, runs); + + if let Some(force_width) = force_width { + apply_force_width_to_layout(&mut layout, force_width); + } + + let key = Arc::new(CacheKey { + text, + font_size, + runs: SmallVec::from(runs), + wrap_width: None, + force_width, + }); + let layout = Arc::new(layout); + current_frame.lines.insert(key.clone(), layout.clone()); + current_frame.used_lines.push(key); + layout + } + } + + /// Try to retrieve a previously-shaped line layout using a caller-provided content hash. + /// + /// This is a *non-allocating* cache probe: it does not materialize any text. If the layout + /// is not already cached in either the current frame or previous frame, returns `None`. + /// + /// Contract (caller enforced): + /// - Same `text_hash` implies identical text content (collision risk accepted by caller). + /// - `text_len` should be the UTF-8 byte length of the text (helps reduce accidental collisions). + pub fn try_layout_line_by_hash( + &self, + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &[FontRun], + force_width: Option, + ) -> Option> { + let _font_generation = self.clear_if_font_generation_changed(); + let key_ref = HashedCacheKeyRef { + text_hash, + text_len, + font_size, + runs, + wrap_width: None, + force_width, + }; + + let current_frame = self.current_frame.read(); + if let Some((_, layout)) = current_frame.lines_by_hash.iter().find(|(key, _)| { + HashedCacheKeyRef { + text_hash: key.text_hash, + text_len: key.text_len, + font_size: key.font_size, + runs: key.runs.as_slice(), + wrap_width: key.wrap_width, + force_width: key.force_width, + } == key_ref + }) { + return Some(layout.clone()); + } + + let previous_frame = self.previous_frame.lock(); + if let Some((_, layout)) = previous_frame.lines_by_hash.iter().find(|(key, _)| { + HashedCacheKeyRef { + text_hash: key.text_hash, + text_len: key.text_len, + font_size: key.font_size, + runs: key.runs.as_slice(), + wrap_width: key.wrap_width, + force_width: key.force_width, + } == key_ref + }) { + return Some(layout.clone()); + } + + None + } + + /// Layout a line of text using a caller-provided content hash as the cache key. + /// + /// This enables cache hits without materializing a contiguous `SharedString` for `text`. + /// If the cache misses, `materialize_text` is invoked to produce the `SharedString` for shaping. + /// + /// Contract (caller enforced): + /// - Same `text_hash` implies identical text content (collision risk accepted by caller). + /// - `text_len` should be the UTF-8 byte length of the text (helps reduce accidental collisions). + pub fn layout_line_by_hash( + &self, + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &[FontRun], + force_width: Option, + materialize_text: impl FnOnce() -> SharedString, + ) -> Arc { + let _font_generation = self.clear_if_font_generation_changed(); + let key_ref = HashedCacheKeyRef { + text_hash, + text_len, + font_size, + runs, + wrap_width: None, + force_width, + }; + + // Fast path: already cached (no allocation). + let current_frame = self.current_frame.upgradable_read(); + if let Some((_, layout)) = current_frame.lines_by_hash.iter().find(|(key, _)| { + HashedCacheKeyRef { + text_hash: key.text_hash, + text_len: key.text_len, + font_size: key.font_size, + runs: key.runs.as_slice(), + wrap_width: key.wrap_width, + force_width: key.force_width, + } == key_ref + }) { + return layout.clone(); + } + + let mut current_frame = RwLockUpgradableReadGuard::upgrade(current_frame); + + // Try to reuse from previous frame without allocating; do a linear scan to find a matching key. + // (We avoid `drain()` here because it would eagerly move all entries.) + let mut previous_frame = self.previous_frame.lock(); + if let Some(existing_key) = previous_frame + .used_lines_by_hash + .iter() + .find(|key| { + HashedCacheKeyRef { + text_hash: key.text_hash, + text_len: key.text_len, + font_size: key.font_size, + runs: key.runs.as_slice(), + wrap_width: key.wrap_width, + force_width: key.force_width, + } == key_ref + }) + .cloned() + { + if let Some((key, layout)) = previous_frame.lines_by_hash.remove_entry(&existing_key) { + current_frame + .lines_by_hash + .insert(key.clone(), layout.clone()); + current_frame.used_lines_by_hash.push(key); + return layout; + } + } + + let text = materialize_text(); + let mut layout = self + .platform_text_system + .layout_line(&text, font_size, runs); + + if let Some(force_width) = force_width { + apply_force_width_to_layout(&mut layout, force_width); + } + + let key = Arc::new(HashedCacheKey { + text_hash, + text_len, + font_size, + runs: SmallVec::from(runs), + wrap_width: None, + force_width, + }); + let layout = Arc::new(layout); + current_frame + .lines_by_hash + .insert(key.clone(), layout.clone()); + current_frame.used_lines_by_hash.push(key); + layout + } + + fn clear_if_font_generation_changed(&self) -> usize { + let font_generation = self.font_generation.load(Ordering::Acquire); + if self.cached_font_generation.load(Ordering::Acquire) == font_generation { + return font_generation; + } + + let mut current_frame = self.current_frame.write(); + if self.cached_font_generation.load(Ordering::Acquire) == font_generation { + return font_generation; + } + + *current_frame = FrameCache::default(); + *self.previous_frame.lock() = FrameCache::default(); + self.cached_font_generation + .store(font_generation, Ordering::Release); + font_generation + } +} + +// Combining marks (e.g. Thai vowel signs, Arabic diacritics) are shaped by +// HarfBuzz at the same x position as their base character. The force-width +// loop must not advance the cell counter for these zero-advance glyphs, +// otherwise they get displaced into the next cell. We detect them by checking +// whether shaped x has advanced by at least half a cell beyond the last base. +fn apply_force_width_to_layout(layout: &mut LineLayout, force_width: Pixels) { + let mut glyph_pos: usize = 0; + // NEG_INFINITY ensures the first glyph is always classified as a base. + let mut last_base_shaped_x = px(f32::NEG_INFINITY); + let mut last_base_actual_x = px(0.); + + for run in layout.runs.iter_mut() { + for glyph in run.glyphs.iter_mut() { + let shaped_x = glyph.position.x; + + if shaped_x > last_base_shaped_x + force_width * 0.5 { + let forced_x = glyph_pos * force_width; + if (shaped_x - forced_x).abs() > px(1.) { + glyph.position.x = forced_x; + } + last_base_shaped_x = shaped_x; + last_base_actual_x = glyph.position.x; + glyph_pos += 1; + } else { + glyph.position.x = last_base_actual_x + (shaped_x - last_base_shaped_x); + } + } + } +} + +/// A run of text with a single font. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[expect(missing_docs)] +pub struct FontRun { + pub len: usize, + pub font_id: FontId, +} + +trait AsCacheKeyRef { + fn as_cache_key_ref(&self) -> CacheKeyRef<'_>; +} + +#[derive(Clone, Debug, Eq)] +struct CacheKey { + text: SharedString, + font_size: Pixels, + runs: SmallVec<[FontRun; 1]>, + wrap_width: Option, + force_width: Option, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct CacheKeyRef<'a> { + text: &'a str, + font_size: Pixels, + runs: &'a [FontRun], + wrap_width: Option, + force_width: Option, +} + +#[derive(Clone, Debug)] +struct HashedCacheKey { + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: SmallVec<[FontRun; 1]>, + wrap_width: Option, + force_width: Option, +} + +#[derive(Copy, Clone)] +struct HashedCacheKeyRef<'a> { + text_hash: u64, + text_len: usize, + font_size: Pixels, + runs: &'a [FontRun], + wrap_width: Option, + force_width: Option, +} + +impl PartialEq for dyn AsCacheKeyRef + '_ { + fn eq(&self, other: &dyn AsCacheKeyRef) -> bool { + self.as_cache_key_ref() == other.as_cache_key_ref() + } +} + +impl PartialEq for HashedCacheKey { + fn eq(&self, other: &Self) -> bool { + self.text_hash == other.text_hash + && self.text_len == other.text_len + && self.font_size == other.font_size + && self.runs.as_slice() == other.runs.as_slice() + && self.wrap_width == other.wrap_width + && self.force_width == other.force_width + } +} + +impl Eq for HashedCacheKey {} + +impl Hash for HashedCacheKey { + fn hash(&self, state: &mut H) { + self.text_hash.hash(state); + self.text_len.hash(state); + self.font_size.hash(state); + self.runs.as_slice().hash(state); + self.wrap_width.hash(state); + self.force_width.hash(state); + } +} + +impl PartialEq for HashedCacheKeyRef<'_> { + fn eq(&self, other: &Self) -> bool { + self.text_hash == other.text_hash + && self.text_len == other.text_len + && self.font_size == other.font_size + && self.runs == other.runs + && self.wrap_width == other.wrap_width + && self.force_width == other.force_width + } +} + +impl Eq for HashedCacheKeyRef<'_> {} + +impl Hash for HashedCacheKeyRef<'_> { + fn hash(&self, state: &mut H) { + self.text_hash.hash(state); + self.text_len.hash(state); + self.font_size.hash(state); + self.runs.hash(state); + self.wrap_width.hash(state); + self.force_width.hash(state); + } +} + +impl Eq for dyn AsCacheKeyRef + '_ {} + +impl Hash for dyn AsCacheKeyRef + '_ { + fn hash(&self, state: &mut H) { + self.as_cache_key_ref().hash(state) + } +} + +impl AsCacheKeyRef for CacheKey { + fn as_cache_key_ref(&self) -> CacheKeyRef<'_> { + CacheKeyRef { + text: &self.text, + font_size: self.font_size, + runs: self.runs.as_slice(), + wrap_width: self.wrap_width, + force_width: self.force_width, + } + } +} + +impl PartialEq for CacheKey { + fn eq(&self, other: &Self) -> bool { + self.as_cache_key_ref().eq(&other.as_cache_key_ref()) + } +} + +impl Hash for CacheKey { + fn hash(&self, state: &mut H) { + self.as_cache_key_ref().hash(state); + } +} + +impl<'a> Borrow for Arc { + fn borrow(&self) -> &(dyn AsCacheKeyRef + 'a) { + self.as_ref() as &dyn AsCacheKeyRef + } +} + +impl AsCacheKeyRef for CacheKeyRef<'_> { + fn as_cache_key_ref(&self) -> CacheKeyRef<'_> { + *self + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::GlyphId; + + fn glyph_at(x: f32, index: usize) -> ShapedGlyph { + ShapedGlyph { + id: GlyphId(0), + position: point(px(x), px(0.)), + index, + is_emoji: false, + } + } + + fn make_layout(glyphs: Vec) -> LineLayout { + LineLayout { + font_size: px(16.), + width: px(100.), + ascent: px(12.), + descent: px(4.), + runs: vec![ShapedRun { + font_id: FontId(0), + glyphs, + }], + len: 0, + } + } + + fn glyph_x_positions(layout: &LineLayout) -> Vec { + layout.runs[0] + .glyphs + .iter() + .map(|g| f32::from(g.position.x)) + .collect() + } + + #[test] + fn test_force_width_latin_unchanged() { + let cell_width = px(8.); + let mut layout = make_layout(vec![glyph_at(0., 0), glyph_at(8., 1), glyph_at(16., 2)]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0., 8., 16.]); + } + + #[test] + fn test_force_width_combining_marks_not_advanced() { + let cell_width = px(8.); + // Simulates Thai "กี" — base consonant at x=0, combining vowel also at x=0 + let mut layout = make_layout(vec![ + glyph_at(0., 0), // ก (base) + glyph_at(0., 3), // ี (combining mark, same x) + ]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0., 0.]); + } + + #[test] + fn test_force_width_base_after_combining_mark() { + let cell_width = px(8.); + let mut layout = make_layout(vec![glyph_at(0., 0), glyph_at(0., 3), glyph_at(8., 6)]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0., 0., 8.]); + } + + #[test] + fn test_force_width_multiple_combining_marks() { + let cell_width = px(8.); + // Simulates "ก้" — base + vowel + tone mark (two combining marks stacked) + let mut layout = make_layout(vec![ + glyph_at(0., 0), // ก (base) + glyph_at(0., 3), // vowel (combining) + glyph_at(0., 6), // tone mark (combining) + glyph_at(8., 9), // next base + ]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0., 0., 0., 8.]); + } + + #[test] + fn test_force_width_corrects_drifted_base_positions() { + let cell_width = px(8.); + // Font metrics don't perfectly match cell grid — glyphs drift >1px from cell boundary + let mut layout = make_layout(vec![ + glyph_at(0.5, 0), // within 1px tolerance, kept as-is + glyph_at(10.2, 1), // >1px off from 8.0, corrected + glyph_at(19.8, 2), // >1px off from 16.0, corrected + ]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0.5, 8., 16.]); + } + + #[test] + fn test_force_width_combining_mark_after_within_tolerance_base() { + let cell_width = px(8.); + // Base glyph is within 1px of grid so it keeps its shaped position. + // The combining mark must align to the base's actual position, not the grid slot. + let mut layout = make_layout(vec![glyph_at(0.5, 0), glyph_at(0.5, 3)]); + + apply_force_width_to_layout(&mut layout, cell_width); + + let positions = glyph_x_positions(&layout); + assert_eq!(positions, vec![0.5, 0.5]); + } +} diff --git a/vendor/gpui-pre/src/text_system/line_wrapper.rs b/vendor/gpui-pre/src/text_system/line_wrapper.rs new file mode 100644 index 00000000..ca821bbb --- /dev/null +++ b/vendor/gpui-pre/src/text_system/line_wrapper.rs @@ -0,0 +1,1921 @@ +use crate::{FontId, Pixels, SharedString, TextRun, TextSystem, px}; +use collections::HashMap; +use std::{borrow::Cow, iter, sync::Arc}; + +/// Determines whether to truncate text from the start or end. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TruncateFrom { + /// Truncate text from the start. + Start, + /// Truncate text from the end. + End, + /// Truncate text from the middle, preserving the start and end. + Middle, +} + +/// Controls how soft-wrapped continuation lines are indented. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum IndentAdjustment { + /// No indent - continuation lines start at column 0. + NoIndent, + /// Match the original line's leading whitespace. + #[default] + SameIndent, + /// Add N extra columns of indent (in space-character widths). + ExtraColumns(u32), +} + +/// The GPUI line wrapper, used to wrap lines of text to a given width. +pub struct LineWrapper { + text_system: Arc, + pub(crate) font_id: FontId, + pub(crate) font_size: Pixels, + cached_ascii_char_widths: [Option; 128], + cached_other_char_widths: HashMap, +} + +impl LineWrapper { + /// The maximum indent that can be applied to a line. + pub const MAX_INDENT: u32 = 256; + + pub(crate) fn new(font_id: FontId, font_size: Pixels, text_system: Arc) -> Self { + Self { + text_system, + font_id, + font_size, + cached_ascii_char_widths: [None; 128], + cached_other_char_widths: HashMap::default(), + } + } + + /// Wrap a line of text to the given width with this wrapper's font and font size. + pub fn wrap_line<'a>( + &'a mut self, + fragments: &'a [LineFragment], + wrap_width: Pixels, + indent_adjustment: IndentAdjustment, + ) -> impl Iterator + 'a { + let mut width = px(0.); + let mut first_non_whitespace_ix = None; + let mut base_indent = None; + let mut last_candidate_ix = 0; + let mut last_candidate_width = px(0.); + let mut last_wrap_ix = 0; + let mut prev_c = '\0'; + let mut index = 0; + let mut candidates = fragments + .iter() + .flat_map(move |fragment| fragment.wrap_boundary_candidates()) + .peekable(); + iter::from_fn(move || { + for candidate in candidates.by_ref() { + let ix = index; + index += candidate.len_utf8(); + let mut new_prev_c = prev_c; + let item_width = match candidate { + WrapBoundaryCandidate::Char { character: c } => { + if c == '\n' { + continue; + } + + if Self::is_word_char(c) { + if prev_c == ' ' && c != ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = ix; + last_candidate_width = width; + } + } else { + // CJK may not be space separated, e.g.: `Hello world你好世界` + if c != ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = ix; + last_candidate_width = width; + } + } + + if c != ' ' && first_non_whitespace_ix.is_none() { + first_non_whitespace_ix = Some(ix); + } + + new_prev_c = c; + + self.width_for_char(c) + } + WrapBoundaryCandidate::Element { + width: element_width, + .. + } => { + if prev_c == ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = ix; + last_candidate_width = width; + } + + if first_non_whitespace_ix.is_none() { + first_non_whitespace_ix = Some(ix); + } + + element_width + } + }; + + width += item_width; + if width > wrap_width && ix > last_wrap_ix { + let wrap_at_candidate = + last_candidate_ix > 0 && width - last_candidate_width <= wrap_width; + + let carried_width = if wrap_at_candidate { + width - last_candidate_width + } else { + item_width + }; + + // Compute base indentation from the first non-whitespace character on the line + // and retain it for all subsequent wrap rows. If the line begins with leading + // whitespace that wraps before any non-whitespace character (or is all whitespace), + // base_indent remains None so continuation rows within the leading whitespace + // do not receive ExtraColumns indentation and degrade into cascading short rows. + if base_indent.is_none() { + if let Some(first_non_whitespace_ix) = first_non_whitespace_ix { + base_indent = + Some(Self::MAX_INDENT.min( + first_non_whitespace_ix.saturating_sub(last_wrap_ix) as u32, + )); + } + } + + let next_indent = match indent_adjustment { + IndentAdjustment::NoIndent => 0, + IndentAdjustment::SameIndent => base_indent.unwrap_or(0), + IndentAdjustment::ExtraColumns(extra) => { + if let Some(base_indent) = base_indent { + let candidate = base_indent.saturating_add(extra); + let candidate_indent_width = + self.width_for_char(' ') * candidate as f32; + // Reserve headroom for any carried suffix from an earlier word boundary + // (and at least 2 columns for a full-width character) so the continuation + // line does not immediately exceed wrap width. + let min_headroom = + carried_width.max(self.width_for_char(' ') * 2.0); + if candidate_indent_width + min_headroom > wrap_width { + 0 + } else { + Self::MAX_INDENT.min(candidate) + } + } else { + 0 + } + } + }; + + if wrap_at_candidate { + last_wrap_ix = last_candidate_ix; + width -= last_candidate_width; + } else { + last_wrap_ix = ix; + width = item_width; + } + last_candidate_ix = 0; + + width += self.width_for_char(' ') * next_indent as f32; + + return Some(Boundary::new(last_wrap_ix, next_indent)); + } + + prev_c = new_prev_c; + } + + None + }) + } + + /// Determines if a line should be truncated based on its width. + /// + /// Returns the truncation index in `line`. + pub fn should_truncate_line( + &mut self, + line: &str, + truncate_width: Pixels, + truncation_affix: &str, + truncate_from: TruncateFrom, + ) -> Option { + let mut width = px(0.); + let suffix_width = truncation_affix + .chars() + .map(|c| self.width_for_char(c)) + .fold(px(0.0), |a, x| a + x); + let mut truncate_ix = 0; + + match truncate_from { + TruncateFrom::Start => { + for (ix, c) in line.char_indices().rev() { + if width + suffix_width < truncate_width { + truncate_ix = ix; + } + + let char_width = self.width_for_char(c); + width += char_width; + + if width.floor() > truncate_width { + return Some(truncate_ix); + } + } + } + TruncateFrom::End => { + for (ix, c) in line.char_indices() { + if width + suffix_width < truncate_width { + truncate_ix = ix; + } + + let char_width = self.width_for_char(c); + width += char_width; + + if width.floor() > truncate_width { + return Some(truncate_ix); + } + } + } + TruncateFrom::Middle => {} + } + + None + } + + fn should_truncate_line_middle( + &mut self, + line: &str, + truncate_width: Pixels, + truncation_affix: &str, + ) -> Option<(usize, usize)> { + let suffix_width = truncation_affix + .chars() + .map(|c| self.width_for_char(c)) + .fold(px(0.0), |a, x| a + x); + + let total_width: Pixels = line + .chars() + .map(|c| self.width_for_char(c)) + .fold(px(0.0), |a, x| a + x); + + if total_width <= truncate_width { + return None; + } + + let content_budget = truncate_width - suffix_width; + if content_budget <= px(0.) { + return Some((0, line.len())); + } + + let front_budget = content_budget * (2.0 / 3.0); + let back_budget = content_budget - front_budget; + + let mut front_width = px(0.); + let mut front_end_ix = 0usize; + for (ix, c) in line.char_indices() { + let char_width = self.width_for_char(c); + if front_width + char_width > front_budget { + break; + } + front_width += char_width; + front_end_ix = ix + c.len_utf8(); + } + + let mut back_width = px(0.); + let mut back_start_ix = line.len(); + for (ix, c) in line.char_indices().rev() { + let char_width = self.width_for_char(c); + if back_width + char_width > back_budget { + break; + } + back_width += char_width; + back_start_ix = ix; + } + + if front_end_ix >= back_start_ix { + return Some((0, line.len())); + } + + Some((front_end_ix, back_start_ix)) + } + + /// Truncate a line of text to the given width with this wrapper's font and font size. + pub fn truncate_line<'a>( + &mut self, + line: SharedString, + truncate_width: Pixels, + truncation_affix: &str, + runs: &'a [TextRun], + truncate_from: TruncateFrom, + ) -> (SharedString, Cow<'a, [TextRun]>) { + if truncate_from == TruncateFrom::Middle { + if let Some((front_end_ix, back_start_ix)) = + self.should_truncate_line_middle(&line, truncate_width, truncation_affix) + { + let result = SharedString::from(format!( + "{}{truncation_affix}{}", + &line[..front_end_ix], + &line[back_start_ix..] + )); + let mut runs = runs.to_vec(); + update_runs_after_middle_truncation( + truncation_affix, + &mut runs, + front_end_ix, + back_start_ix, + ); + return (result, Cow::Owned(runs)); + } else { + return (line, Cow::Borrowed(runs)); + } + } + + if let Some(truncate_ix) = + self.should_truncate_line(&line, truncate_width, truncation_affix, truncate_from) + { + let result = match truncate_from { + TruncateFrom::Start => SharedString::from(format!( + "{truncation_affix}{}", + &line[line.ceil_char_boundary(truncate_ix + 1)..] + )), + TruncateFrom::End => SharedString::from(format!( + "{}{truncation_affix}", + line[..truncate_ix] + .trim_end_matches(|c: char| c.is_whitespace() || c.is_ascii_punctuation()) + )), + TruncateFrom::Middle => unreachable!("Middle truncation is handled above"), + }; + let mut runs = runs.to_vec(); + update_runs_after_truncation(&result, truncation_affix, &mut runs, truncate_from); + (result, Cow::Owned(runs)) + } else { + (line, Cow::Borrowed(runs)) + } + } + + /// Truncate text to fit within a given number of wrapped lines. + /// + /// Unlike `truncate_line` which treats the text as a flat width budget + /// (`width * max_lines`), this method accounts for word-boundary wrapping: + /// it walks through characters once, tracking wrap boundaries and the + /// truncation point simultaneously. When text overflows on the last + /// allowed line, it truncates there and appends the affix. + /// + /// For `max_lines == 1`, this delegates to `truncate_line`. + pub fn truncate_wrapped_line<'a>( + &mut self, + text: SharedString, + wrap_width: Pixels, + max_lines: usize, + truncation_affix: &str, + runs: &'a [TextRun], + truncate_from: TruncateFrom, + ) -> (SharedString, Cow<'a, [TextRun]>) { + if max_lines <= 1 || truncate_from == TruncateFrom::Start { + return self.truncate_line( + text, + wrap_width * max_lines, + truncation_affix, + runs, + truncate_from, + ); + } + if truncate_from == TruncateFrom::Middle { + return self.truncate_line(text, wrap_width, truncation_affix, runs, truncate_from); + } + + let affix_width: Pixels = truncation_affix + .chars() + .map(|c| self.width_for_char(c)) + .sum(); + + let mut width = px(0.); + let mut line = 0usize; + let mut first_non_whitespace_ix = None; + let mut last_candidate_ix = 0usize; + let mut last_candidate_width = px(0.); + let mut last_wrap_ix = 0usize; + let mut prev_c = '\0'; + let mut indent: Option = None; + let mut truncate_ix = 0usize; + + for (ix, c) in text.char_indices() { + if c == '\n' { + if line >= max_lines - 1 && !text[ix + 1..].trim().is_empty() { + // Newline on the last allowed line with real content + // below. Truncate here. + let truncated = text[..truncate_ix] + .trim_end_matches(|c: char| c.is_whitespace() || c.is_ascii_punctuation()); + let result = SharedString::from(format!("{truncated}{truncation_affix}")); + let mut runs = runs.to_vec(); + update_runs_after_truncation( + &result, + truncation_affix, + &mut runs, + TruncateFrom::End, + ); + return (result, Cow::Owned(runs)); + } + + // Newline before the last line: it consumes a line. + line += 1; + width = px(0.); + first_non_whitespace_ix = None; + last_candidate_ix = 0; + last_candidate_width = px(0.); + last_wrap_ix = ix + 1; + prev_c = '\0'; + indent = None; + truncate_ix = ix + 1; + continue; + } + + let char_width = self.width_for_char(c); + + if Self::is_word_char(c) { + if prev_c == ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = ix; + last_candidate_width = width; + } + } else if c != ' ' && first_non_whitespace_ix.is_some() { + last_candidate_ix = ix; + last_candidate_width = width; + } + + if c != ' ' && first_non_whitespace_ix.is_none() { + first_non_whitespace_ix = Some(ix); + } + + width += char_width; + + if line < max_lines - 1 { + // Before the last line: replicate wrap_line's boundary logic. + if width > wrap_width && ix > last_wrap_ix { + if let (None, Some(first_nw)) = (indent, first_non_whitespace_ix) { + indent = Some(Self::MAX_INDENT.min((first_nw - last_wrap_ix) as u32)); + } + + if last_candidate_ix > last_wrap_ix { + last_wrap_ix = last_candidate_ix; + width -= last_candidate_width; + last_candidate_ix = 0; + } else { + last_wrap_ix = ix; + width = char_width; + } + + if let Some(ind) = indent { + width += self.width_for_char(' ') * ind as f32; + } + + line += 1; + truncate_ix = last_wrap_ix; + } + } else { + // On the last line: track the furthest point where the affix + // still fits, and stop as soon as the line overflows. + if width + affix_width <= wrap_width { + truncate_ix = ix + c.len_utf8(); + } + + if width > wrap_width { + let truncated = text[..truncate_ix] + .trim_end_matches(|c: char| c.is_whitespace() || c.is_ascii_punctuation()); + let result = SharedString::from(format!("{truncated}{truncation_affix}")); + let mut runs = runs.to_vec(); + update_runs_after_truncation( + &result, + truncation_affix, + &mut runs, + TruncateFrom::End, + ); + return (result, Cow::Owned(runs)); + } + } + + prev_c = c; + } + + // Text fits within max_lines without truncation. + (text, Cow::Borrowed(runs)) + } + + /// Any character in this list should be treated as a word character, + /// meaning it can be part of a word that should not be wrapped. + pub(crate) fn is_word_char(c: char) -> bool { + // ASCII alphanumeric characters, for English, numbers: `Hello123`, etc. + c.is_ascii_alphanumeric() || + // Latin script in Unicode for French, German, Spanish, etc. + // Latin-1 Supplement + // https://en.wikipedia.org/wiki/Latin-1_Supplement + matches!(c, '\u{00C0}'..='\u{00FF}') || + // Latin Extended-A + // https://en.wikipedia.org/wiki/Latin_Extended-A + matches!(c, '\u{0100}'..='\u{017F}') || + // Latin Extended-B + // https://en.wikipedia.org/wiki/Latin_Extended-B + matches!(c, '\u{0180}'..='\u{024F}') || + // Cyrillic for Russian, Ukrainian, etc. + // https://en.wikipedia.org/wiki/Cyrillic_script_in_Unicode + matches!(c, '\u{0400}'..='\u{04FF}') || + + // Vietnamese (https://vietunicode.sourceforge.net/charset/) + matches!(c, '\u{1E00}'..='\u{1EFF}') || // Latin Extended Additional + matches!(c, '\u{0300}'..='\u{036F}') || // Combining Diacritical Marks + + // Bengali (https://en.wikipedia.org/wiki/Bengali_(Unicode_block)) + matches!(c, '\u{0980}'..='\u{09FF}') || + + // Some other known special characters that should be treated as word characters, + // e.g. `a-b`, `var_name`, `I'm`/`won’t`, '@mention`, `#hashtag`, `100%`, `3.1415`, + // `2^3`, `a~b`, `a=1`, `Self::new`, etc. Trailing punctuation like `,`, `.`, `:`, `;` + // is included so it stays attached to the preceding word when wrapping. + matches!(c, '-' | '_' | '.' | '\'' | '’' | '‘' | '$' | '%' | '@' | '#' | '^' | '~' | ',' | '=' | ':' | ';') || + // Closing punctuation never starts a line (UAX #14 LB13: no break + // before `!`, `)`, `]`, `}`, closing quotes or an ellipsis) — `plz!`, + // `see)`, `quoted”` wrap as one word instead of orphaning the mark on + // the next line. `/` and `?` stay break opportunities so long paths + // and URLs (`a/b`, `foo?b=2`) can wrap. + matches!(c, '!' | ')' | ']' | '}' | '"' | '”' | '»' | '…') || + // `⋯` character is special used in Zed, to keep this at the end of the line. + matches!(c, '⋯') || + + // Non-breaking glue characters + matches!(c, '\u{202F}' | '\u{00A0}' | '\u{2011}') + } + + #[inline(always)] + fn width_for_char(&mut self, c: char) -> Pixels { + if (c as u32) < 128 { + if let Some(cached_width) = self.cached_ascii_char_widths[c as usize] { + cached_width + } else { + let width = self + .text_system + .layout_width(self.font_id, self.font_size, c); + self.cached_ascii_char_widths[c as usize] = Some(width); + width + } + } else if let Some(cached_width) = self.cached_other_char_widths.get(&c) { + *cached_width + } else { + let width = self + .text_system + .layout_width(self.font_id, self.font_size, c); + self.cached_other_char_widths.insert(c, width); + width + } + } +} + +fn update_runs_after_truncation( + result: &str, + ellipsis: &str, + runs: &mut Vec, + truncate_from: TruncateFrom, +) { + let mut truncate_at = result.len() - ellipsis.len(); + match truncate_from { + TruncateFrom::Start => { + for (run_index, run) in runs.iter_mut().enumerate().rev() { + if run.len <= truncate_at { + truncate_at -= run.len; + } else { + run.len = truncate_at + ellipsis.len(); + runs.splice(..run_index, std::iter::empty()); + break; + } + } + } + TruncateFrom::End => { + for (run_index, run) in runs.iter_mut().enumerate() { + if run.len <= truncate_at { + truncate_at -= run.len; + } else { + run.len = truncate_at + ellipsis.len(); + runs.truncate(run_index + 1); + break; + } + } + } + TruncateFrom::Middle => { + unreachable!("Middle truncation calls this function with TruncateFrom::End directly") + } + } +} + +fn update_runs_after_middle_truncation( + ellipsis: &str, + runs: &mut Vec, + front_end_ix: usize, + back_start_ix: usize, +) { + let original_runs = std::mem::take(runs); + let mut result_runs: Vec = Vec::with_capacity(original_runs.len()); + + // Front segment [0, front_end_ix) + ellipsis: walk forward until the run + // that straddles or ends at front_end_ix, then extend that run's length + // to include the ellipsis. + let mut front_remaining = front_end_ix; + let mut front_done = false; + for run in &original_runs { + if front_done { + break; + } + if run.len <= front_remaining { + result_runs.push(run.clone()); + front_remaining -= run.len; + } else { + let mut partial = run.clone(); + partial.len = front_remaining + ellipsis.len(); + result_runs.push(partial); + front_done = true; + } + } + if !front_done { + // front_end_ix landed exactly on a run boundary; append ellipsis to + // the last front run (or, if the front is empty, to the first back run). + if let Some(last) = result_runs.last_mut() { + last.len += ellipsis.len(); + } else if let Some(first) = original_runs.first() { + let mut affix_run = first.clone(); + affix_run.len = ellipsis.len(); + result_runs.push(affix_run); + } + } + + // Back segment [back_start_ix, original.len()): skip runs entirely in the + // removed middle, keep the rest. + let mut byte_pos = 0usize; + for run in &original_runs { + let run_end = byte_pos + run.len; + if run_end > back_start_ix { + if byte_pos < back_start_ix { + // Run straddles back_start_ix; keep only the tail. + let mut partial = run.clone(); + partial.len = run_end - back_start_ix; + result_runs.push(partial); + } else { + result_runs.push(run.clone()); + } + } + byte_pos = run_end; + } + + *runs = result_runs; +} + +/// A fragment of a line that can be wrapped. +pub enum LineFragment<'a> { + /// A text fragment consisting of characters. + Text { + /// The text content of the fragment. + text: &'a str, + }, + /// A non-text element with a fixed width. + Element { + /// The width of the element in pixels. + width: Pixels, + /// The UTF-8 encoded length of the element. + len_utf8: usize, + }, +} + +impl<'a> LineFragment<'a> { + /// Creates a new text fragment from the given text. + pub fn text(text: &'a str) -> Self { + LineFragment::Text { text } + } + + /// Creates a new non-text element with the given width and UTF-8 encoded length. + pub fn element(width: Pixels, len_utf8: usize) -> Self { + LineFragment::Element { width, len_utf8 } + } + + fn wrap_boundary_candidates(&self) -> impl Iterator { + let text = match self { + LineFragment::Text { text } => text, + LineFragment::Element { .. } => "\0", + }; + text.chars().map(move |character| { + if let LineFragment::Element { width, len_utf8 } = self { + WrapBoundaryCandidate::Element { + width: *width, + len_utf8: *len_utf8, + } + } else { + WrapBoundaryCandidate::Char { character } + } + }) + } +} + +enum WrapBoundaryCandidate { + Char { character: char }, + Element { width: Pixels, len_utf8: usize }, +} + +impl WrapBoundaryCandidate { + pub fn len_utf8(&self) -> usize { + match self { + WrapBoundaryCandidate::Char { character } => character.len_utf8(), + WrapBoundaryCandidate::Element { len_utf8: len, .. } => *len, + } + } +} + +/// A boundary between two lines of text. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Boundary { + /// The index of the last character in a line + pub ix: usize, + /// The indent of the next line. + pub next_indent: u32, +} + +impl Boundary { + fn new(ix: usize, next_indent: u32) -> Self { + Self { ix, next_indent } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Font, FontFeatures, FontStyle, FontWeight, TestAppContext, TestDispatcher, font}; + #[cfg(target_os = "macos")] + use crate::{TextRun, WindowTextSystem, WrapBoundary}; + + fn build_wrapper() -> LineWrapper { + let dispatcher = TestDispatcher::new(0); + let cx = TestAppContext::build(dispatcher, None); + let id = cx.text_system().resolve_font(&font(".ZedMono")); + LineWrapper::new(id, px(16.), cx.text_system().clone()) + } + + fn generate_test_runs(input_run_len: &[usize]) -> Vec { + input_run_len + .iter() + .map(|run_len| TextRun { + len: *run_len, + font: Font { + family: "Dummy".into(), + features: FontFeatures::default(), + fallbacks: None, + weight: FontWeight::default(), + style: FontStyle::Normal, + }, + ..Default::default() + }) + .collect() + } + + #[test] + fn test_wrap_line() { + let mut wrapper = build_wrapper(); + + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text("aa bbb cccc ddddd eeee")], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(7, 0), + Boundary::new(12, 0), + Boundary::new(18, 0) + ], + ); + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text("aaa aaaaaaaaaaaaaaaaaa")], + px(72.0), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(4, 0), + Boundary::new(11, 0), + Boundary::new(18, 0) + ], + ); + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(" aaaaaaa")], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(7, 5), + Boundary::new(9, 5), + Boundary::new(11, 5), + ] + ); + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(" ")], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(7, 0), + Boundary::new(14, 0), + Boundary::new(21, 0) + ] + ); + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(" aaaaaaaaaaaaaa")], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(7, 0), + Boundary::new(14, 3), + Boundary::new(18, 3), + Boundary::new(22, 3), + ] + ); + + // Test wrapping multiple text fragments + assert_eq!( + wrapper + .wrap_line( + &[ + LineFragment::text("aa bbb "), + LineFragment::text("cccc ddddd eeee") + ], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(7, 0), + Boundary::new(12, 0), + Boundary::new(18, 0) + ], + ); + + // Test wrapping with a mix of text and element fragments + assert_eq!( + wrapper + .wrap_line( + &[ + LineFragment::text("aa "), + LineFragment::element(px(20.), 1), + LineFragment::text(" bbb "), + LineFragment::element(px(30.), 1), + LineFragment::text(" cccc") + ], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(5, 0), + Boundary::new(9, 0), + Boundary::new(11, 0) + ], + ); + + // Test with element at the beginning and text afterward + assert_eq!( + wrapper + .wrap_line( + &[ + LineFragment::element(px(50.), 1), + LineFragment::text(" aaaa bbbb cccc dddd") + ], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(2, 0), + Boundary::new(7, 0), + Boundary::new(12, 0), + Boundary::new(17, 0) + ], + ); + + // Test with a large element that forces wrapping by itself + assert_eq!( + wrapper + .wrap_line( + &[ + LineFragment::text("short text "), + LineFragment::element(px(100.), 1), + LineFragment::text(" more text") + ], + px(72.), + IndentAdjustment::default() + ) + .collect::>(), + &[ + Boundary::new(6, 0), + Boundary::new(11, 0), + Boundary::new(12, 0), + Boundary::new(18, 0) + ], + ); + + // Test with non-breaking glue characters + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text("a\u{202F}b\u{00A0}c\u{2011}d e")], + px(72.0), + IndentAdjustment::default() + ) + .collect::>(), + &[Boundary::new(12, 0),], // special chars above take up 3, 2 and 3 bytes, so boundary ends up at 12 + ); + } + + #[test] + fn test_truncate_line_end() { + let mut wrapper = build_wrapper(); + + fn perform_test( + wrapper: &mut LineWrapper, + text: &'static str, + expected: &'static str, + ellipsis: &str, + ) { + let dummy_run_lens = vec![text.len()]; + let dummy_runs = generate_test_runs(&dummy_run_lens); + let (result, dummy_runs) = wrapper.truncate_line( + text.into(), + px(220.), + ellipsis, + &dummy_runs, + TruncateFrom::End, + ); + assert_eq!(result, expected); + assert_eq!(dummy_runs.first().unwrap().len, result.len()); + } + + perform_test( + &mut wrapper, + "aa bbb cccc ddddd eeee ffff gggg", + "aa bbb cccc ddddd eeee", + "", + ); + perform_test( + &mut wrapper, + "aa bbb cccc ddddd eeee ffff gggg", + "aa bbb cccc ddddd eee…", + "…", + ); + perform_test( + &mut wrapper, + "aa bbb cccc ddddd eeee ffff gggg", + "aa bbb cccc dddd......", + "......", + ); + perform_test( + &mut wrapper, + "aa bbb cccc 🦀🦀🦀🦀🦀 eeee ffff gggg", + "aa bbb cccc 🦀🦀🦀🦀…", + "…", + ); + } + + #[test] + fn test_truncate_line_start() { + let mut wrapper = build_wrapper(); + + #[track_caller] + fn perform_test( + wrapper: &mut LineWrapper, + text: &'static str, + expected: &'static str, + ellipsis: &str, + ) { + let dummy_run_lens = vec![text.len()]; + let dummy_runs = generate_test_runs(&dummy_run_lens); + let (result, dummy_runs) = wrapper.truncate_line( + text.into(), + px(220.), + ellipsis, + &dummy_runs, + TruncateFrom::Start, + ); + assert_eq!(result, expected); + assert_eq!(dummy_runs.first().unwrap().len, result.len()); + } + + perform_test( + &mut wrapper, + "aaaa bbbb cccc ddddd eeee fff gg", + "cccc ddddd eeee fff gg", + "", + ); + perform_test( + &mut wrapper, + "aaaa bbbb cccc ddddd eeee fff gg", + "…ccc ddddd eeee fff gg", + "…", + ); + perform_test( + &mut wrapper, + "aaaa bbbb cccc ddddd eeee fff gg", + "......dddd eeee fff gg", + "......", + ); + perform_test( + &mut wrapper, + "aaaa bbbb cccc 🦀🦀🦀🦀🦀 eeee fff gg", + "…🦀🦀🦀🦀 eeee fff gg", + "…", + ); + } + + #[test] + fn test_truncate_multiple_runs_end() { + let mut wrapper = build_wrapper(); + + fn perform_test( + wrapper: &mut LineWrapper, + text: &'static str, + expected: &str, + run_lens: &[usize], + result_run_len: &[usize], + line_width: Pixels, + ) { + let dummy_runs = generate_test_runs(run_lens); + let (result, dummy_runs) = + wrapper.truncate_line(text.into(), line_width, "…", &dummy_runs, TruncateFrom::End); + assert_eq!(result, expected); + for (run, result_len) in dummy_runs.iter().zip(result_run_len) { + assert_eq!(run.len, *result_len); + } + } + // Case 0: Normal + // Text: abcdefghijkl + // Runs: Run0 { len: 12, ... } + // + // Truncate res: abcd… (truncate_at = 4) + // Run res: Run0 { string: abcd…, len: 7, ... } + perform_test(&mut wrapper, "abcdefghijkl", "abcd…", &[12], &[7], px(50.)); + // Case 1: Drop some runs + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: abcdef… (truncate_at = 6) + // Runs res: Run0 { string: abcd, len: 4, ... }, Run1 { string: ef…, len: + // 5, ... } + perform_test( + &mut wrapper, + "abcdefghijkl", + "abcdef…", + &[4, 4, 4], + &[4, 5], + px(70.), + ); + // Case 2: Truncate at start of some run + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: abcdefgh… (truncate_at = 8) + // Runs res: Run0 { string: abcd, len: 4, ... }, Run1 { string: efgh, len: + // 4, ... }, Run2 { string: …, len: 3, ... } + perform_test( + &mut wrapper, + "abcdefghijkl", + "abcdefgh…", + &[4, 4, 4], + &[4, 4, 3], + px(90.), + ); + } + + #[test] + fn test_truncate_multiple_runs_start() { + let mut wrapper = build_wrapper(); + + #[track_caller] + fn perform_test( + wrapper: &mut LineWrapper, + text: &'static str, + expected: &str, + run_lens: &[usize], + result_run_len: &[usize], + line_width: Pixels, + ) { + let dummy_runs = generate_test_runs(run_lens); + let (result, dummy_runs) = wrapper.truncate_line( + text.into(), + line_width, + "…", + &dummy_runs, + TruncateFrom::Start, + ); + assert_eq!(result, expected); + for (run, result_len) in dummy_runs.iter().zip(result_run_len) { + assert_eq!(run.len, *result_len); + } + } + // Case 0: Normal + // Text: abcdefghijkl + // Runs: Run0 { len: 12, ... } + // + // Truncate res: …ijkl (truncate_at = 9) + // Run res: Run0 { string: …ijkl, len: 7, ... } + perform_test(&mut wrapper, "abcdefghijkl", "…ijkl", &[12], &[7], px(50.)); + // Case 1: Drop some runs + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: …ghijkl (truncate_at = 7) + // Runs res: Run0 { string: …gh, len: 5, ... }, Run1 { string: ijkl, len: + // 4, ... } + perform_test( + &mut wrapper, + "abcdefghijkl", + "…ghijkl", + &[4, 4, 4], + &[5, 4], + px(70.), + ); + // Case 2: Truncate at start of some run + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: abcdefgh… (truncate_at = 3) + // Runs res: Run0 { string: …, len: 3, ... }, Run1 { string: efgh, len: + // 4, ... }, Run2 { string: ijkl, len: 4, ... } + perform_test( + &mut wrapper, + "abcdefghijkl", + "…efghijkl", + &[4, 4, 4], + &[3, 4, 4], + px(90.), + ); + } + + #[test] + fn test_update_run_after_truncation_end() { + fn perform_test(result: &str, run_lens: &[usize], result_run_lens: &[usize]) { + let mut dummy_runs = generate_test_runs(run_lens); + update_runs_after_truncation(result, "…", &mut dummy_runs, TruncateFrom::End); + for (run, result_len) in dummy_runs.iter().zip(result_run_lens) { + assert_eq!(run.len, *result_len); + } + } + // Case 0: Normal + // Text: abcdefghijkl + // Runs: Run0 { len: 12, ... } + // + // Truncate res: abcd… (truncate_at = 4) + // Run res: Run0 { string: abcd…, len: 7, ... } + perform_test("abcd…", &[12], &[7]); + // Case 1: Drop some runs + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: abcdef… (truncate_at = 6) + // Runs res: Run0 { string: abcd, len: 4, ... }, Run1 { string: ef…, len: + // 5, ... } + perform_test("abcdef…", &[4, 4, 4], &[4, 5]); + // Case 2: Truncate at start of some run + // Text: abcdefghijkl + // Runs: Run0 { len: 4, ... }, Run1 { len: 4, ... }, Run2 { len: 4, ... } + // + // Truncate res: abcdefgh… (truncate_at = 8) + // Runs res: Run0 { string: abcd, len: 4, ... }, Run1 { string: efgh, len: + // 4, ... }, Run2 { string: …, len: 3, ... } + perform_test("abcdefgh…", &[4, 4, 4], &[4, 4, 3]); + } + + #[test] + fn test_is_word_char() { + #[track_caller] + fn assert_word(word: &str) { + for c in word.chars() { + assert!( + LineWrapper::is_word_char(c), + "assertion failed for '{}' (unicode 0x{:x})", + c, + c as u32 + ); + } + } + + #[track_caller] + fn assert_not_word(word: &str) { + let found = word.chars().any(|c| !LineWrapper::is_word_char(c)); + assert!(found, "assertion failed for '{}'", word); + } + + assert_word("Hello123"); + assert_word("non-English"); + assert_word("var_name"); + assert_word("123456"); + assert_word("3.1415"); + assert_word("10^2"); + assert_word("1~2"); + assert_word("100%"); + assert_word("@mention"); + assert_word("#hashtag"); + assert_word("$variable"); + assert_word("a=1"); + assert_word("Self::is_word_char"); + assert_word("on;"); + assert_word("more⋯"); + assert_word("won’t"); + assert_word("‘twas"); + assert_word("plz!"); + assert_word("see)"); + assert_word("quoted”"); + assert_word("well…"); + + // Space + assert_not_word("foo bar"); + + // URL case + assert_word("github.com"); + assert_not_word("zed-industries/zed"); + assert_not_word("zed-industries\\zed"); + assert_not_word("a=1&b=2"); + assert_not_word("foo?b=2"); + + // Latin-1 Supplement + assert_word("ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ"); + // Latin Extended-A + assert_word("ĀāĂ㥹ĆćĈĉĊċČčĎď"); + // Latin Extended-B + assert_word("ƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏ"); + // Cyrillic + assert_word("АБВГДЕЖЗИЙКЛМНОП"); + // Vietnamese (https://github.com/zed-industries/zed/issues/23245) + assert_word("ThậmchíđếnkhithuachạychúngcònnhẫntâmgiếtnốtsốđôngtùchínhtrịởYênBáivàCaoBằng"); + // Bengali + assert_word("গিয়েছিলেন"); + assert_word("ছেলে"); + assert_word("হচ্ছিল"); + + // non-word characters + assert_not_word("你好"); + assert_not_word("안녕하세요"); + assert_not_word("こんにちは"); + assert_not_word("😀😁😂"); + assert_not_word("()[]{}<>"); + + // Non-breaking ("Glue") characters, see https://www.unicode.org/reports/tr14/ + // (https://github.com/zed-industries/zed/issues/59664) + assert_word("\u{202F}"); // NNBSP " " + assert_word("\u{00A0}"); // NBSP " " + assert_word("\u{2011}"); // NBH "‑" + } + + // For compatibility with the test macro + #[cfg(target_os = "macos")] + use crate as gpui; + + // These seem to vary wildly based on the text system. + #[cfg(target_os = "macos")] + #[crate::test] + fn test_wrap_shaped_line(cx: &mut TestAppContext) { + cx.update(|cx| { + let text_system = WindowTextSystem::new(cx.text_system().clone()); + + let normal = TextRun { + len: 0, + font: font("Helvetica"), + color: Default::default(), + underline: Default::default(), + ..Default::default() + }; + let bold = TextRun { + len: 0, + font: font("Helvetica").bold(), + ..Default::default() + }; + + let text = "aa bbb cccc ddddd eeee".into(); + let lines = text_system + .shape_text( + text, + px(16.), + &[ + normal.with_len(4), + bold.with_len(5), + normal.with_len(6), + bold.with_len(1), + normal.with_len(7), + ], + Some(px(72.)), + None, + ) + .unwrap(); + + assert_eq!( + lines[0].layout.wrap_boundaries(), + &[ + WrapBoundary { + run_ix: 0, + glyph_ix: 7 + }, + WrapBoundary { + run_ix: 0, + glyph_ix: 12 + }, + WrapBoundary { + run_ix: 0, + glyph_ix: 18 + } + ], + ); + }); + } + + #[test] + fn test_multiline_truncation_fits_within_wrapped_lines() { + let mut wrapper = build_wrapper(); + + // With .ZedMono at 16px, each char is 9.6px wide. + // wrap_width = 72px fits ~7 chars per line. + // + // "aa bbbbbb cccccc dddddd eeee ffff" with wrap_width=72px wraps as: + // Line 1: "aa " (28.8px, wraps because "bbbbbb" won't fit) + // Line 2: "bbbbbb " (67.2px) + // Line 3: "cccccc " (67.2px) + // ... + // + // truncate_wrapped_line should wrap first to find line 2 starts at + // "bbbbbb...", then truncate only that line to fit with ellipsis. + let text: &str = "aa bbbbbb cccccc dddddd eeee ffff"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (truncated, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + // The truncated text, when wrapped, must fit within max_lines lines. + let wrap_count = wrapper + .wrap_line( + &[LineFragment::text(&truncated)], + wrap_width, + IndentAdjustment::default(), + ) + .count(); + + assert!( + wrap_count < max_lines, + "Truncated text '{}' wraps into {} visual lines, expected at most {}", + truncated, + wrap_count + 1, + max_lines + ); + + // The truncated text should end with the ellipsis. + assert!( + truncated.ends_with('\u{2026}'), + "Truncated text '{}' should end with ellipsis", + truncated + ); + } + + #[test] + fn test_multiline_truncation_no_truncation_needed() { + let mut wrapper = build_wrapper(); + + // Text that fits in 2 lines shouldn't be truncated. + // Line 1: "aa bbb " (67.2px), Line 2: "cccccc" (57.6px) + let text: &str = "aa bbb cccccc"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (result, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + assert_eq!( + result.as_ref(), + text, + "Text that fits should not be modified" + ); + } + + #[test] + fn test_multiline_truncation_three_lines() { + let mut wrapper = build_wrapper(); + + let text: &str = "aa bbb cccc ddddd eeee ffff gggg hhhh iiii jjjj"; + let wrap_width = px(72.); + let max_lines: usize = 3; + + let runs = generate_test_runs(&[text.len()]); + let (truncated, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + let wrap_count = wrapper + .wrap_line( + &[LineFragment::text(&truncated)], + wrap_width, + IndentAdjustment::default(), + ) + .count(); + + assert!( + wrap_count < max_lines, + "Truncated text '{}' wraps into {} visual lines, expected at most {}", + truncated, + wrap_count + 1, + max_lines + ); + + assert!( + truncated.ends_with('\u{2026}'), + "Truncated text '{}' should end with ellipsis", + truncated + ); + } + + #[test] + fn test_multiline_truncation_with_newlines() { + let mut wrapper = build_wrapper(); + + // "hello\nworld foo bar baz" with line_clamp(2): + // shape_text splits on \n, giving physical lines "hello" and + // "world foo bar baz". The newline consumes line 1, so the + // second physical line should be truncated on line 2. + let text: &str = "hello\nworld foo bar baz"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (truncated, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + // The newline should be preserved. + let parts: Vec<&str> = truncated.splitn(2, '\n').collect(); + assert_eq!( + parts.len(), + 2, + "Newline should be preserved: '{}'", + truncated + ); + assert_eq!(parts[0], "hello"); + + // The second line should fit within wrap_width and end with ellipsis. + let second_line_width: Pixels = parts[1].chars().map(|c| wrapper.width_for_char(c)).sum(); + assert!( + second_line_width <= wrap_width, + "Second line '{}' ({}px) exceeds wrap_width ({}px)", + parts[1], + second_line_width, + wrap_width + ); + assert!( + truncated.ends_with('\u{2026}'), + "Should end with ellipsis: '{}'", + truncated + ); + } + + #[test] + fn test_multiline_truncation_newline_on_last_line() { + let mut wrapper = build_wrapper(); + + // "hello\nworld\nmore" with line_clamp(2): + // Line 1: "hello", Line 2: "world" — but there's a third line, + // so line 2 should be truncated with ellipsis. + let text: &str = "hello\nworld\nmore"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (truncated, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + let parts: Vec<&str> = truncated.splitn(2, '\n').collect(); + assert_eq!(parts[0], "hello"); + assert!( + truncated.ends_with('\u{2026}'), + "Should end with ellipsis since there's more content: '{}'", + truncated + ); + } + + #[test] + fn test_truncate_line_middle() { + let mut wrapper = build_wrapper(); + + // No truncation when text fits within a very wide budget. + let short_text = "hello world"; + let runs = generate_test_runs(&[short_text.len()]); + let (result, result_runs) = wrapper.truncate_line( + short_text.into(), + px(10000.), + "…", + &runs, + TruncateFrom::Middle, + ); + assert_eq!(result.as_ref(), short_text); + assert_eq!(result_runs.len(), 1); + assert_eq!(result_runs[0].len, short_text.len()); + + // Basic middle truncation: long string with px(100.) budget. + let long_text = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"; + let runs = generate_test_runs(&[long_text.len()]); + let (result, _result_runs) = + wrapper.truncate_line(long_text.into(), px(100.), "…", &runs, TruncateFrom::Middle); + assert!( + result.contains('…'), + "Middle-truncated result should contain '…', got: '{}'", + result + ); + assert!( + result.chars().count() < long_text.chars().count(), + "Middle-truncated result should be shorter than original" + ); + assert_eq!( + result.chars().next(), + long_text.chars().next(), + "Result should start with the same first character as original" + ); + assert_eq!( + result.chars().last(), + long_text.chars().last(), + "Result should end with the same last character as original" + ); + + // Degenerate case: budget so narrow that middle truncation cannot find a valid split. + // Still show the truncation affix instead of returning the original overflowing text. + let text = "abcdef"; + let runs = generate_test_runs(&[text.len()]); + let (result, result_runs) = + wrapper.truncate_line(text.into(), px(1.), "…", &runs, TruncateFrom::Middle); + assert_eq!(result.as_ref(), "…"); + assert_eq!(result_runs.len(), 1); + assert_eq!(result_runs[0].len, "…".len()); + + // Run adjustment correctness: multiple runs across the string. + // Verify that the returned runs' lengths sum to result.len(). + let multi_run_text = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"; + let run_lens = [20, 20, multi_run_text.len() - 40]; + let runs = generate_test_runs(&run_lens); + let (result, result_runs) = wrapper.truncate_line( + multi_run_text.into(), + px(100.), + "…", + &runs, + TruncateFrom::Middle, + ); + let total_run_len: usize = result_runs.iter().map(|r| r.len).sum(); + assert_eq!( + total_run_len, + result.len(), + "Sum of run lengths ({}) should equal result byte length ({})", + total_run_len, + result.len() + ); + } + + #[test] + fn test_multiline_truncation_trailing_newline() { + let mut wrapper = build_wrapper(); + + // "hello\nworld\n" with line_clamp(2): + // The trailing newline has no content after it, so no ellipsis. + let text: &str = "hello\nworld\n"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (result, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + assert!( + !result.ends_with('\u{2026}'), + "Trailing newline with no content should not add ellipsis: '{}'", + result + ); + } + + #[test] + fn test_multiline_truncation_newline_fits_exactly() { + let mut wrapper = build_wrapper(); + + // "hello\nworld" with line_clamp(2): + // Exactly 2 lines, no truncation needed. + let text: &str = "hello\nworld"; + let wrap_width = px(72.); + let max_lines: usize = 2; + + let runs = generate_test_runs(&[text.len()]); + let (result, _) = wrapper.truncate_wrapped_line( + text.into(), + wrap_width, + max_lines, + "\u{2026}", + &runs, + TruncateFrom::End, + ); + + assert_eq!( + result.as_ref(), + text, + "Text that fits exactly should not be modified: '{}'", + result + ); + } + + #[test] + fn test_extra_columns_overflow_guard() { + let mut wrapper = build_wrapper(); + let space_width = wrapper.width_for_char(' '); + + // 6 spaces indent, wrap width 10 columns. + let text = " ab cd ef gh"; + let wrap_width = space_width * 10.0; + + // When base_indent + extra overflows wrap width (6 + 8 + 2 > 10), + // indent must fall back to 0 instead of degrading to one character per row. + // + // Expected wrapped lines (10 columns): + // | ab | (row 0: 6 spaces + "ab ", len 9) + // |cd ef gh | (row 1: 0 indent + "cd ef gh", len 8) + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(text)], + wrap_width, + IndentAdjustment::ExtraColumns(8), + ) + .collect::>(), + &[Boundary::new(9, 0)] + ); + + // When base_indent + extra fits within wrap width (6 + 2 + 2 <= 10), + // the extra indent is applied and not clamped. + // + // Expected wrapped lines (10 columns): + // | ab | (row 0: 6 spaces + "ab ", len 9) + // | cd| (row 1: 8 spaces + "cd", len 10) + // | ef| (row 2: 8 spaces + "ef", len 10) + // | gh| (row 3: 8 spaces + "gh", len 10) + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(text)], + wrap_width, + IndentAdjustment::ExtraColumns(2), + ) + .collect::>(), + &[ + Boundary::new(9, 8), + Boundary::new(11, 8), + Boundary::new(13, 8), + Boundary::new(15, 8), + ] + ); + + // When text contains full-width (two-column) glyphs, reserving headroom for a + // two-column character (candidate + 2 > wrap_width) ensures that candidate + // indents leaving only 1 column cannot accept the indent and overflow. + // + // 1 space indent, wrap width 10 columns. + // " 🦀🦀🦀🦀🦀🦀🦀🦀" with extra=8 (extra_two with tab_size=4): + // candidate = 1 + 8 = 9. + // With +2 headroom (9 + 2 > 10), indent falls back to 0. + // + // Expected wrapped lines (10 columns): + // | 🦀🦀🦀🦀 | (row 0: 1 space + 4 two-column glyphs, 9 cols) + // |🦀🦀🦀🦀 | (row 1: 0 indent + 4 two-column glyphs, 8 cols) + let full_width_text = " 🦀🦀🦀🦀🦀🦀🦀🦀"; + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(full_width_text)], + wrap_width, + IndentAdjustment::ExtraColumns(8), + ) + .collect::>(), + &[Boundary::new(17, 0)] + ); + + // When the carried suffix fits within wrap width alongside extra indent + // (1 indent + 9 carried suffix = 10 <= 10), the extra indent is applied. + // + // Expected wrapped lines (10 columns): + // |a | (row 0: "a ", len 2) + // | abcdefghi| (row 1: 1 indent + "abcdefghi", len 10) + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text("a abcdefghi")], + wrap_width, + IndentAdjustment::ExtraColumns(1), + ) + .collect::>(), + &[Boundary::new(2, 1)] + ); + + // When extra indent exceeds wrap width by even 1 column + // (2 indent + 9 carried suffix = 11 > 10), indent falls back to 0. + // + // Expected wrapped lines (10 columns): + // |a | (row 0: "a ", len 2) + // |abcdefghi | (row 1: 0 indent + "abcdefghi", len 9) + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text("a abcdefghi")], + wrap_width, + IndentAdjustment::ExtraColumns(2), + ) + .collect::>(), + &[Boundary::new(2, 0)] + ); + + // When text wraps at an earlier word boundary, the carried suffix + // must be accounted for so indent + carried_suffix <= wrap_width. + // + // "a abcdefghij" with wrap_width 10 columns, ExtraColumns(8): + // candidate = 0 + 8 = 8. + // carried suffix = "abcdefghi" (9 columns). + // 8 indent + 9 carried suffix = 17 > 10, so indent falls back to 0. + // + // Expected wrapped lines (10 columns): + // |a | (row 0: "a ", len 2) + // |abcdefghij| (row 1: 0 indent + "abcdefghij", len 10) + let carried_text = "a abcdefghij"; + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(carried_text)], + wrap_width, + IndentAdjustment::ExtraColumns(8), + ) + .collect::>(), + &[Boundary::new(2, 0)] + ); + + // When a wider inline element is encountered after the first wrap, + // the overflow guard must evaluate whether the element fits with the extra indent. + // If text continues after the element row and wraps again, subsequent continuation + // lines resume the extra indent if their carried content fits. + // + // "abcdefghijk " followed by an 8-column element and "z 12": + // Row 0: "abcdefghij" (len 10) + // Row 1: "k " (2 cols) with 8 indent (len 10) + // Row 2: element (8 cols) cannot fit with 8 indent (8 + 8 = 16 > 10), + // so indent falls back to 0. Element (8 cols) + "z " (2 cols) = len 10. + // Row 3: "12" (2 cols) fits with 8 indent (8 + 2 = 10 <= 10). + // + // Expected wrapped lines (10 columns): + // |abcdefghij| (row 0: 10 cols) + // | k | (row 1: 8 indent + "k ", len 10) + // |[ELEMENT]z| (row 2: 0 indent + [ELEMENT (8)] + "z ", len 10) + // | 12| (row 3: 8 indent + "12", len 10) + let element_fragments = [ + LineFragment::text("abcdefghijk "), + LineFragment::element(space_width * 8.0, 1), + LineFragment::text("z 12"), + ]; + assert_eq!( + wrapper + .wrap_line( + &element_fragments, + wrap_width, + IndentAdjustment::ExtraColumns(8), + ) + .collect::>(), + &[ + Boundary::new(10, 8), + Boundary::new(12, 0), + Boundary::new(15, 8), + ] + ); + + // A line of only whitespace wrapping before any non-whitespace character + // must not have extra columns added to subsequent rows. + let spaces = " "; // 20 spaces + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(spaces)], + wrap_width, + IndentAdjustment::ExtraColumns(8), + ) + .collect::>(), + &[Boundary::new(10, 0)] + ); + + // When leading whitespace wraps before the first non-whitespace character, + // base_indent should reflect the leading whitespace on the row where non-whitespace begins. + // 14 spaces followed by "ab cd ef gh", wrap width 10: + // Row 0: 10 spaces (len 10) -> wraps at ix 10 with indent 0 + // Row 1: 4 spaces + "ab cd" (len 9) -> wraps at ix 20 + // base_indent is 14 - 10 = 4. + // With ExtraColumns(2), candidate = 4 + 2 = 6. 6 + 2 (headroom) = 8 <= 10. + // Row 2 and subsequent rows get indent 6. + let multiline_indent_text = " ab cd ef gh"; + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(multiline_indent_text)], + wrap_width, + IndentAdjustment::ExtraColumns(2), + ) + .collect::>(), + &[ + Boundary::new(10, 0), + Boundary::new(20, 6), + Boundary::new(23, 6), + ] + ); + + // When a word boundary precedes an oversized carried suffix that itself + // exceeds wrap_width (e.g. text followed by an inline element), wrapping + // at the earlier candidate would force the continuation row to immediately + // overflow even with 0 indent. The wrapper must reject the candidate and + // break before the overflowing item instead. + // + // "aaaaaaaaaaaaaaaaaaa a" (21 chars: 19 'a's, space, 'a') followed by 10-column element: + // Row 0: "aaaaaaaaaa" (10 chars, len 10) -> wraps at ix 10 + // Row 1: "aaaaaaaa" (8 chars) with 2 indent (len 10) -> wraps at ix 18 + // Row 2: "a a" (3 chars) with 2 indent (len 5) + // candidate boundary at ix 20 (space) + // Then element (10 cols): width becomes 5 + 10 = 15 > wrap_width (10). + // Candidate would carry 'a' (1 col) + element (10 cols) = 11 cols > 10. + // Because carried suffix (11) > wrap_width (10), candidate is rejected. + // Wrapper breaks at ix 21 (before element) with indent 0. + // Row 3: element (10 cols, len 10) + let oversized_suffix_fragments = [ + LineFragment::text("aaaaaaaaaaaaaaaaaaa a"), + LineFragment::element(space_width * 10.0, 1), + ]; + assert_eq!( + wrapper + .wrap_line( + &oversized_suffix_fragments, + wrap_width, + IndentAdjustment::ExtraColumns(2), + ) + .collect::>(), + &[ + Boundary::new(10, 2), + Boundary::new(18, 2), + Boundary::new(21, 0), + ] + ); + + assert_eq!( + wrapper + .wrap_line( + &[LineFragment::text(" aaaaaaaa")], + space_width * 4.0, + IndentAdjustment::ExtraColumns(u32::MAX), + ) + .collect::>(), + &[Boundary::new(4, 0), Boundary::new(8, 0)] + ); + } +} diff --git a/vendor/gpui-pre/src/util.rs b/vendor/gpui-pre/src/util.rs new file mode 100644 index 00000000..13ee752d --- /dev/null +++ b/vendor/gpui-pre/src/util.rs @@ -0,0 +1,252 @@ +use crate::{BackgroundExecutor, Task}; +use std::{ + future::Future, + pin::Pin, + sync::atomic::{AtomicUsize, Ordering::SeqCst}, + task, + time::Duration, +}; + +/// A helper trait for building complex objects with imperative conditionals in a fluent style. +pub trait FluentBuilder { + /// Imperatively modify self with the given closure. + fn map(self, f: impl FnOnce(Self) -> U) -> U + where + Self: Sized, + { + f(self) + } + + /// Conditionally modify self with the given closure. + fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self + where + Self: Sized, + { + self.map(|this| if condition { then(this) } else { this }) + } + + /// Conditionally modify self with the given closure. + fn when_else( + self, + condition: bool, + then: impl FnOnce(Self) -> Self, + else_fn: impl FnOnce(Self) -> Self, + ) -> Self + where + Self: Sized, + { + self.map(|this| if condition { then(this) } else { else_fn(this) }) + } + + /// Conditionally unwrap and modify self with the given closure, if the given option is Some. + fn when_some(self, option: Option, then: impl FnOnce(Self, T) -> Self) -> Self + where + Self: Sized, + { + self.map(|this| { + if let Some(value) = option { + then(this, value) + } else { + this + } + }) + } + /// Conditionally unwrap and modify self with the given closure, if the given option is None. + fn when_none(self, option: &Option, then: impl FnOnce(Self) -> Self) -> Self + where + Self: Sized, + { + self.map(|this| if option.is_some() { this } else { then(this) }) + } +} + +/// Extensions for Future types that provide additional combinators and utilities. +pub trait FutureExt { + /// Requires a Future to complete before the specified duration has elapsed. + /// Similar to tokio::timeout. + fn with_timeout(self, timeout: Duration, executor: &BackgroundExecutor) -> WithTimeout + where + Self: Sized; +} + +impl FutureExt for T { + fn with_timeout(self, timeout: Duration, executor: &BackgroundExecutor) -> WithTimeout + where + Self: Sized, + { + WithTimeout { + future: self, + timer: executor.timer(timeout), + } + } +} + +#[pin_project::pin_project] +pub struct WithTimeout { + #[pin] + future: T, + #[pin] + timer: Task<()>, +} + +#[derive(Debug, thiserror::Error)] +#[error("Timed out before future resolved")] +/// Error returned by with_timeout when the timeout duration elapsed before the future resolved +pub struct Timeout; + +impl Future for WithTimeout { + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> task::Poll { + let this = self.project(); + + if let task::Poll::Ready(output) = this.future.poll(cx) { + task::Poll::Ready(Ok(output)) + } else if this.timer.poll(cx).is_ready() { + task::Poll::Ready(Err(Timeout)) + } else { + task::Poll::Pending + } + } +} + +/// Increment the given atomic counter if it is not zero. +/// Return the new value of the counter. +pub(crate) fn atomic_incr_if_not_zero(counter: &AtomicUsize) -> usize { + let mut loaded = counter.load(SeqCst); + loop { + if loaded == 0 { + return 0; + } + match counter.compare_exchange_weak(loaded, loaded + 1, SeqCst, SeqCst) { + Ok(x) => return x + 1, + Err(actual) => loaded = actual, + } + } +} + +/// Rounds to the nearest integer with 0.5 ties toward zero. +#[inline] +pub(crate) fn round_half_toward_zero(value: f32) -> f32 { + (value.abs() - 0.5).ceil().copysign(value) +} + +#[inline] +pub(crate) fn round_half_toward_zero_f64(value: f64) -> f64 { + (value.abs() - 0.5).ceil().copysign(value) +} + +#[inline] +pub(crate) fn round_to_device_pixel(logical: f32, scale_factor: f32) -> f32 { + round_half_toward_zero(logical * scale_factor) +} + +#[inline] +pub(crate) fn round_stroke_to_device_pixel(logical: f32, scale_factor: f32) -> f32 { + if logical == 0.0 { + 0.0 + } else { + round_to_device_pixel(logical.max(0.0), scale_factor).max(1.0) + } +} + +#[inline] +pub(crate) fn floor_to_device_pixel(logical: f32, scale_factor: f32) -> f32 { + (logical * scale_factor).floor() +} + +#[inline] +pub(crate) fn ceil_to_device_pixel(logical: f32, scale_factor: f32) -> f32 { + (logical * scale_factor).ceil() +} + +#[cfg(test)] +mod tests { + use crate::TestAppContext; + + use super::*; + + #[test] + fn test_round_half_toward_zero() { + // Midpoint ties go toward zero + assert_eq!(round_half_toward_zero(0.5), 0.0); + assert_eq!(round_half_toward_zero(1.5), 1.0); + assert_eq!(round_half_toward_zero(2.5), 2.0); + assert_eq!(round_half_toward_zero(-0.5), 0.0); + assert_eq!(round_half_toward_zero(-1.5), -1.0); + assert_eq!(round_half_toward_zero(-2.5), -2.0); + + // Non-midpoint values round to nearest + assert_eq!(round_half_toward_zero(1.5001), 2.0); + assert_eq!(round_half_toward_zero(1.4999), 1.0); + assert_eq!(round_half_toward_zero(-1.5001), -2.0); + assert_eq!(round_half_toward_zero(-1.4999), -1.0); + + // Integers are unchanged + assert_eq!(round_half_toward_zero(0.0), 0.0); + assert_eq!(round_half_toward_zero(3.0), 3.0); + assert_eq!(round_half_toward_zero(-3.0), -3.0); + } + + #[test] + fn test_device_pixel_helpers() { + // Snap uses half-toward-zero: 1.0 * 1.5 = 1.5 ties toward 1.0. + assert_eq!(round_to_device_pixel(1.0, 1.5), 1.0); + // Below the tie rounds down, above rounds up. + assert_eq!(round_to_device_pixel(0.3, 2.0), 1.0); + assert_eq!(round_to_device_pixel(1.4, 1.0), 1.0); + assert_eq!(round_to_device_pixel(1.6, 1.0), 2.0); + + // Stroke uses snap, but clamps non-zero input up to at least 1dp. + assert_eq!(round_stroke_to_device_pixel(0.0, 1.0), 0.0); + assert_eq!(round_stroke_to_device_pixel(0.4, 1.0), 1.0); + assert_eq!(round_stroke_to_device_pixel(0.5, 1.0), 1.0); + assert_eq!(round_stroke_to_device_pixel(1.0, 1.5), 1.0); + assert_eq!(round_stroke_to_device_pixel(1.6, 1.0), 2.0); + + // Cover's near edge floors, far edge ceils. Together they form a strict superset. + assert_eq!(floor_to_device_pixel(0.3, 2.0), 0.0); + assert_eq!(ceil_to_device_pixel(0.3, 2.0), 1.0); + assert_eq!(floor_to_device_pixel(2.1, 1.0), 2.0); + assert_eq!(ceil_to_device_pixel(2.1, 1.0), 3.0); + + // Integer device-pixel inputs are stable under all three. + assert_eq!(round_to_device_pixel(2.0, 2.0), 4.0); + assert_eq!(floor_to_device_pixel(2.0, 2.0), 4.0); + assert_eq!(ceil_to_device_pixel(2.0, 2.0), 4.0); + } + + #[test] + fn test_round_half_toward_zero_f64() { + assert_eq!(round_half_toward_zero_f64(0.5), 0.0); + assert_eq!(round_half_toward_zero_f64(-0.5), 0.0); + assert_eq!(round_half_toward_zero_f64(1.5), 1.0); + assert_eq!(round_half_toward_zero_f64(-1.5), -1.0); + assert_eq!(round_half_toward_zero_f64(2.5001), 3.0); + } + + #[gpui::test] + async fn test_with_timeout(cx: &mut TestAppContext) { + Task::ready(()) + .with_timeout(Duration::from_secs(1), &cx.executor()) + .await + .expect("Timeout should be noop"); + + let long_duration = Duration::from_secs(6000); + let short_duration = Duration::from_secs(1); + cx.executor() + .timer(long_duration) + .with_timeout(short_duration, &cx.executor()) + .await + .expect_err("timeout should have triggered"); + + let fut = cx + .executor() + .timer(long_duration) + .with_timeout(short_duration, &cx.executor()); + cx.executor().advance_clock(short_duration * 2); + futures::FutureExt::now_or_never(fut) + .unwrap_or_else(|| panic!("timeout should have triggered")) + .expect_err("timeout"); + } +} diff --git a/vendor/gpui-pre/src/view.rs b/vendor/gpui-pre/src/view.rs new file mode 100644 index 00000000..f24a4da9 --- /dev/null +++ b/vendor/gpui-pre/src/view.rs @@ -0,0 +1,593 @@ +use crate::{ + AnyElement, AnyEntity, AnyWeakEntity, App, AvailableSpace, Bounds, ContentMask, Context, + Element, ElementId, Entity, EntityId, GlobalElementId, InspectorElementId, IntoElement, + LayoutId, PaintIndex, Pixels, PrepaintStateIndex, Render, RenderOnce, Size, Style, + StyleRefinement, TextStyle, WeakEntity, +}; +use crate::{Empty, Window}; +use anyhow::Result; +use collections::FxHashSet; +use refineable::Refineable; +use std::mem; +use std::{ + any::{TypeId, type_name}, + fmt, + ops::Range, +}; + +/// A dynamically-typed view handle that can be downcast to a specific `Entity`. +/// +/// This is the type-erased counterpart to [`ViewElement`]: it holds an entity plus +/// a function pointer to its render, and is itself a [`View`], so embedding it as an +/// element goes through the same [`ViewElement`] machinery as any other view. +#[derive(Clone, Debug)] +pub struct AnyView { + entity: AnyEntity, + render: fn(&AnyView, &mut Window, &mut App) -> AnyElement, +} + +impl From> for AnyView { + fn from(value: Entity) -> Self { + AnyView { + entity: value.into_any(), + render: any_view::render::, + } + } +} + +impl AnyView { + /// Embed this view as a cached [`ViewElement`] laid out at `style`. + /// + /// The rendered subtree is recycled from the previous frame unless + /// [Context::notify] was called on the backing entity since it was rendered + /// (or [Window::refresh] is called, which ignores caching). + pub fn cached(self, style: StyleRefinement) -> ViewElement { + ViewElement::new(self).cached(style) + } + + /// Convert this to a weak handle. + pub fn downgrade(&self) -> AnyWeakView { + AnyWeakView { + entity: self.entity.downgrade(), + render: self.render, + } + } + + /// Convert this to a [Entity] of a specific type. + /// If this handle does not contain a view of the specified type, returns itself in an `Err` variant. + pub fn downcast(self) -> Result, Self> { + match self.entity.downcast() { + Ok(entity) => Ok(entity), + Err(entity) => Err(Self { + entity, + render: self.render, + }), + } + } + + /// Gets the [TypeId] of the underlying view. + pub fn entity_type(&self) -> TypeId { + self.entity.entity_type + } + + /// The [`EntityId`] of this view. + pub fn entity_id(&self) -> EntityId { + self.entity.entity_id() + } +} + +impl PartialEq for AnyView { + fn eq(&self, other: &Self) -> bool { + self.entity == other.entity + } +} + +impl Eq for AnyView {} + +/// `AnyView` is the type-erased [`View`]: its `render` is a function pointer rather +/// than a concrete type, but it participates in the reactive graph exactly like any +/// other view via [`ViewElement`]. +impl View for AnyView { + fn entity_id(&self) -> Option { + Some(self.entity.entity_id()) + } + + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + (self.render)(&self, window, cx) + } +} + +impl IntoElement for Entity { + type Element = ViewElement>; + + fn into_element(self) -> Self::Element { + ViewElement::new(self) + } + + #[inline(never)] + fn into_any_element(self) -> AnyElement { + self.into_element().into_any() + } +} + +impl IntoElement for AnyView { + type Element = ViewElement; + + fn into_element(self) -> Self::Element { + ViewElement::new(self) + } +} + +/// A weak, dynamically-typed view handle. +pub struct AnyWeakView { + entity: AnyWeakEntity, + render: fn(&AnyView, &mut Window, &mut App) -> AnyElement, +} + +impl AnyWeakView { + /// Upgrade to a strong `AnyView` handle, if the view is still alive. + pub fn upgrade(&self) -> Option { + let entity = self.entity.upgrade()?; + Some(AnyView { + entity, + render: self.render, + }) + } +} + +impl From> for AnyWeakView { + fn from(view: WeakEntity) -> Self { + AnyWeakView { + entity: view.into(), + render: any_view::render::, + } + } +} + +impl PartialEq for AnyWeakView { + fn eq(&self, other: &Self) -> bool { + self.entity == other.entity + } +} + +impl std::fmt::Debug for AnyWeakView { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyWeakView") + .field("entity_id", &self.entity.entity_id) + .finish_non_exhaustive() + } +} + +mod any_view { + use crate::{AnyElement, AnyView, App, IntoElement, Render, Window}; + + pub(crate) fn render( + view: &AnyView, + window: &mut Window, + cx: &mut App, + ) -> AnyElement { + let view = view.clone().downcast::().unwrap(); + // Record the view's Render type name so the accessibility debug dump can + // attribute nodes to the view that produced them. + #[cfg(debug_assertions)] + window + .a11y + .view_type_names + .insert(view.entity_id(), std::any::type_name::()); + view.update(cx, |view, cx| view.render(window, cx).into_any_element()) + } +} + +/// A renderable that participates in GPUI's reactive graph — the unifying model +/// behind [`Render`] and [`RenderOnce`]. +/// +/// When `entity_id()` returns `Some`, that id becomes the view's identity: it gets +/// a unique element-id space (so internal `use_state` / `.id(..)` never collide +/// across siblings) and `cx.notify()` on that entity re-renders only this view's +/// subtree. `None` behaves like a stateless component. +/// +/// You rarely implement `View` directly. `Entity` and any `T: RenderOnce` +/// get a blanket impl below; implement it by hand only when a component needs both +/// parent-supplied props *and* a backing entity for identity. +pub trait View: 'static + Sized { + /// This view's identity, if it has one. A view typically holds the backing + /// entity as a field and returns its [`EntityId`] here. + /// + /// The id becomes this view's [`ElementId`], so two views keyed on the same + /// entity must not be rendered at the same position in the element tree + /// (e.g. as siblings under the same parent): their internal element state + /// (`use_state`, scroll offsets, etc.) would silently collide. Nesting is + /// fine — the id is scoped by the parent path. + fn entity_id(&self) -> Option; + + /// Render this view into an element tree, consuming `self`. + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement; +} + +/// A stateless component (`RenderOnce`) is a `View` with no identity. +impl View for T { + fn entity_id(&self) -> Option { + None + } + + #[inline] + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + RenderOnce::render(self, window, cx) + } +} + +/// An entity that renders itself (`Render`) is a `View` keyed on its own id. +impl View for Entity { + fn entity_id(&self) -> Option { + Some(Entity::entity_id(self)) + } + + #[inline] + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + self.update(cx, |this, cx| { + Render::render(this, window, cx).into_any_element() + }) + } +} + +impl Entity { + /// Embed this entity as a cached [`ViewElement`] laid out at `style`. + /// + /// The rendered subtree is reused until the entity is notified (or the + /// cached bounds / text style change). Caching requires a definite size: + /// a cached view is laid out from `style` and is *not* measured from its + /// contents. Use [`ViewElement::new`] (or `.child(entity)`) for the + /// uncached case. + #[track_caller] + pub fn cached(self, style: StyleRefinement) -> ViewElement> { + ViewElement::new(self).cached(style) + } +} + +/// The element type for [`View`] implementations. Wraps a `View` and hooks it +/// into layout, prepaint, and paint. Constructed via [`ViewElement::new`]. +#[doc(hidden)] +pub struct ViewElement { + view: Option, + entity_id: Option, + cached_style: Option, + #[cfg(debug_assertions)] + source: &'static core::panic::Location<'static>, +} + +impl ViewElement { + /// Wrap a [`View`] as an element. + #[track_caller] + pub fn new(view: V) -> Self { + let entity_id = view.entity_id(); + ViewElement { + entity_id, + cached_style: None, + view: Some(view), + #[cfg(debug_assertions)] + source: core::panic::Location::caller(), + } + } + + /// Enable caching of this view's rendered subtree, laid out at `style`. + /// The composer supplies the layout style because caching skips rendering + /// the contents to measure them. + /// + /// Crate-private on purpose: caching is only sound for entity-backed views, + /// where [`Context::notify`] is the contract that busts the cache. A stateless + /// view has no such contract, so a frozen subtree could never be invalidated. + /// Reach this through [`Entity::cached`] or [`AnyView::cached`], which are + /// entity-backed by construction. + pub(crate) fn cached(mut self, style: StyleRefinement) -> Self { + self.cached_style = Some(style); + self + } +} + +impl IntoElement for ViewElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +struct ViewElementState { + prepaint_range: Range, + paint_range: Range, + cache_key: ViewElementCacheKey, + accessed_entities: FxHashSet, +} + +struct ViewElementCacheKey { + bounds: Bounds, + content_mask: ContentMask, + text_style: TextStyle, +} + +impl Element for ViewElement { + type RequestLayoutState = Option; + type PrepaintState = Option; + + fn id(&self) -> Option { + self.entity_id.map(ElementId::View) + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + #[cfg(debug_assertions)] + return Some(self.source); + + #[cfg(not(debug_assertions))] + return None; + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + if let Some(entity_id) = self.entity_id { + // Stateful path: create a reactive boundary. + let view = &mut self.view; + request_layout_view( + entity_id, + self.cached_style.as_ref(), + window, + cx, + &mut |window, cx| view.take().unwrap().render(window, cx).into_any_element(), + ) + } else { + // Stateless path: isolate subtree via type name (no entity identity). + request_layout_component(type_name::(), window, cx, &mut |window, cx| { + self.view + .take() + .unwrap() + .render(window, cx) + .into_any_element() + }) + } + } + + fn prepaint( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + bounds: Bounds, + element: &mut Self::RequestLayoutState, + window: &mut Window, + cx: &mut App, + ) -> Option { + if let Some(entity_id) = self.entity_id { + // Stateful path. + prepaint_view( + entity_id, + global_id, + bounds, + element, + window, + cx, + &mut |window, cx| { + self.view + .take() + .unwrap() + .render(window, cx) + .into_any_element() + }, + ) + } else { + // Stateless path: just prepaint the element. + prepaint_component(type_name::(), element, window, cx) + } + } + + fn paint( + &mut self, + global_id: Option<&GlobalElementId>, + _inspector_id: Option<&InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + element: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + if let Some(entity_id) = self.entity_id { + // Stateful path. + paint_view( + entity_id, + self.cached_style.is_some(), + global_id, + element, + window, + cx, + ); + } else { + // Stateless path: just paint the element. + paint_component(std::any::type_name::(), element, window, cx); + } + } +} + +/// A view that renders nothing +pub struct EmptyView; + +impl Render for EmptyView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + Empty + } +} + +#[inline(never)] +fn request_layout_view( + entity_id: EntityId, + cached_style: Option<&StyleRefinement>, + window: &mut Window, + cx: &mut App, + render: &mut dyn FnMut(&mut Window, &mut App) -> AnyElement, +) -> (LayoutId, Option) { + window.with_rendered_view(entity_id, |window| { + let caching_disabled = window.is_inspector_picking(cx); + match cached_style { + Some(style) if !caching_disabled => { + let mut root_style = Style::default(); + root_style.refine(style); + let layout_id = window.request_layout(root_style, None, cx); + (layout_id, None) + } + _ => { + let mut element = render(window, cx); + let layout_id = element.request_layout(window, cx); + (layout_id, Some(element)) + } + } + }) +} + +#[inline(never)] +fn request_layout_component( + name: &'static str, + window: &mut Window, + cx: &mut App, + render: &mut dyn FnMut(&mut Window, &mut App) -> AnyElement, +) -> (LayoutId, Option) { + window.with_id(ElementId::from(name), |window| { + let mut element = render(window, cx); + let layout_id = element.request_layout(window, cx); + (layout_id, Some(element)) + }) +} + +#[inline(never)] +fn prepaint_view( + entity_id: EntityId, + global_id: Option<&GlobalElementId>, + bounds: Bounds, + element: &mut Option, + window: &mut Window, + cx: &mut App, + render: &mut dyn FnMut(&mut Window, &mut App) -> AnyElement, +) -> Option { + window.set_view_id(entity_id); + window.with_rendered_view(entity_id, |window| { + if let Some(mut element) = element.take() { + element.prepaint(window, cx); + return Some(element); + } + + window.with_element_state::( + global_id.unwrap(), + |element_state, window| { + let content_mask = window.content_mask(); + let text_style = window.text_style(); + + if let Some(mut element_state) = element_state + && element_state.cache_key.bounds == bounds + && element_state.cache_key.content_mask == content_mask + && element_state.cache_key.text_style == text_style + && !window.dirty_views.contains(&entity_id) + && !window.refreshing + { + let prepaint_start = window.prepaint_index(); + window.reuse_prepaint(element_state.prepaint_range.clone()); + cx.entities + .extend_accessed(&element_state.accessed_entities); + let prepaint_end = window.prepaint_index(); + element_state.prepaint_range = prepaint_start..prepaint_end; + + return (None, element_state); + } + + let refreshing = mem::replace(&mut window.refreshing, true); + let prepaint_start = window.prepaint_index(); + let (element, accessed_entities) = cx.detect_accessed_entities(|cx| { + let mut element = render(window, cx); + element.layout_as_root(Size::::from(bounds.size), window, cx); + element.prepaint_at(bounds.origin, window, cx); + element + }); + + let prepaint_end = window.prepaint_index(); + window.refreshing = refreshing; + + ( + Some(element), + ViewElementState { + accessed_entities, + prepaint_range: prepaint_start..prepaint_end, + paint_range: PaintIndex::default()..PaintIndex::default(), + cache_key: ViewElementCacheKey { + bounds, + content_mask, + text_style, + }, + }, + ) + }, + ) + }) +} + +#[inline(never)] +fn prepaint_component( + name: &'static str, + element: &mut Option, + window: &mut Window, + cx: &mut App, +) -> Option { + window.with_id(ElementId::from(name), |window| { + element.as_mut().unwrap().prepaint(window, cx); + }); + Some(element.take().unwrap()) +} + +#[inline(never)] +fn paint_view( + entity_id: EntityId, + cached: bool, + global_id: Option<&GlobalElementId>, + element: &mut Option, + window: &mut Window, + cx: &mut App, +) { + window.with_rendered_view(entity_id, |window| { + let caching_disabled = window.is_inspector_picking(cx); + if cached && !caching_disabled { + window.with_element_state::( + global_id.unwrap(), + |element_state, window| { + let mut element_state = element_state.unwrap(); + + let paint_start = window.paint_index(); + + if let Some(element) = element { + let refreshing = mem::replace(&mut window.refreshing, true); + element.paint(window, cx); + window.refreshing = refreshing; + } else { + window.reuse_paint(element_state.paint_range.clone()); + } + + let paint_end = window.paint_index(); + element_state.paint_range = paint_start..paint_end; + + ((), element_state) + }, + ) + } else { + element.as_mut().unwrap().paint(window, cx); + } + }); +} + +#[inline(never)] +fn paint_component( + name: &'static str, + element: &mut Option, + window: &mut Window, + cx: &mut App, +) { + window.with_id(ElementId::Name(name.into()), |window| { + element.as_mut().unwrap().paint(window, cx); + }); +} diff --git a/vendor/gpui-pre/src/window.rs b/vendor/gpui-pre/src/window.rs new file mode 100644 index 00000000..259a451a --- /dev/null +++ b/vendor/gpui-pre/src/window.rs @@ -0,0 +1,9528 @@ +#[cfg(feature = "profiler")] +use crate::DebugFrameOverlayMode; +#[cfg(any(feature = "inspector", debug_assertions))] +use crate::Inspector; +#[cfg(feature = "profiler")] +use crate::profiler; +use crate::{ + Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset, + AsyncWindowContext, AtlasTile, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, + Capslock, Context, Corners, CursorHideMode, CursorStyle, Decorations, DevicePixels, + DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, + EntityId, EventEmitter, FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, + Hsla, InputHandler, InputPreference, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, + Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers, ModifiersChangedEvent, + MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, + PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, + PolychromeSprite, Priority, PromptButton, PromptLevel, Quad, Render, RenderGlyphParams, + RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR, + SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y, ScaledPixels, Scene, Shadow, SharedString, Size, + StrikethroughStyle, Style, SubpixelSprite, SubscriberSet, Subscription, SystemWindowTab, + SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextInputConfiguration, + TextInputStateChange, TextRenderingMode, TextStyle, TextStyleRefinement, ThermalState, + TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance, + WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem, + WindowVisibility, point, prelude::*, px, rems, size, transparent_black, +}; + +use crate::gestures::{GestureTuning, RecognizedTouchGesture, TouchGestureRecognizer}; +use crate::interactive::TouchEvent; +use anyhow::{Context as _, Result, anyhow}; +use collections::{FxHashMap, FxHashSet}; +#[cfg(any(target_os = "macos", target_os = "ios"))] +use core_video::pixel_buffer::CVPixelBuffer; +use derive_more::{Deref, DerefMut}; +use futures::channel::oneshot; +use gpui_util::post_inc; +use gpui_util::{ResultExt, measure}; +use itertools::FoldWhile::{Continue, Done}; +use itertools::Itertools; +use parking_lot::RwLock; +use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle}; +use refineable::Refineable; +use scheduler::Instant; +use slotmap::SlotMap; +use smallvec::SmallVec; +use std::{ + any::{Any, TypeId}, + borrow::Cow, + cell::{Cell, RefCell}, + cmp, + fmt::{Debug, Display}, + hash::{Hash, Hasher}, + marker::PhantomData, + mem, + ops::{DerefMut, Range}, + rc::Rc, + sync::{ + Arc, Weak, + atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst}, + }, + thread::AccessError, + time::Duration, +}; +use uuid::Uuid; + +pub(crate) mod a11y; +mod prompts; + +pub use a11y::A11ySubtreeBuilder; + +use self::a11y::A11y; +#[cfg(not(target_family = "wasm"))] +use self::a11y::ROOT_NODE_ID; +use crate::util::{ + atomic_incr_if_not_zero, ceil_to_device_pixel, floor_to_device_pixel, round_half_toward_zero, + round_half_toward_zero_f64, round_stroke_to_device_pixel, round_to_device_pixel, +}; +pub use prompts::*; + +/// Default window size used when no explicit size is provided. +pub const DEFAULT_WINDOW_SIZE: Size = size(px(1536.), px(1095.)); + +/// A 6:5 aspect ratio minimum window size to be used for functional, +/// additional-to-main-Zed windows, like the settings and rules library windows. +pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size = Size { + width: Pixels(900.), + height: Pixels(750.), +}; + +/// Represents the two different phases when dispatching events. +#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] +pub enum DispatchPhase { + /// After the capture phase comes the bubble phase, in which mouse event listeners are + /// invoked front to back and keyboard event listeners are invoked from the focused element + /// to the root of the element tree. This is the phase you'll most commonly want to use when + /// registering event listeners. + #[default] + Bubble, + /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard + /// listeners are invoked from the root of the tree downward toward the focused element. This phase + /// is used for special purposes such as clearing the "pressed" state for click events. If + /// you stop event propagation during this phase, you need to know what you're doing. Handlers + /// outside of the immediate region may rely on detecting non-local events during this phase. + Capture, +} + +impl DispatchPhase { + /// Returns true if this represents the "bubble" phase. + #[inline] + pub fn bubble(self) -> bool { + self == DispatchPhase::Bubble + } + + /// Returns true if this represents the "capture" phase. + #[inline] + pub fn capture(self) -> bool { + self == DispatchPhase::Capture + } +} + +struct WindowInvalidatorInner { + #[cfg(feature = "profiler")] + pub window_id: WindowId, + pub dirty: bool, + pub draw_phase: DrawPhase, + pub dirty_views: FxHashSet, + pub update_count: usize, + #[cfg(feature = "profiler")] + pub frame_dirty: FrameDirtyAccumulator, + pub platform_waker: Option>, +} + +/// Per-frame invalidation bookkeeping, drained at draw time and emitted to the +/// frame profiler. Tracks when the current frame first became dirty and how +/// many invalidations were coalesced into it, whenever the profiler is +/// compiled in. Retention of the resulting per-frame records is what +/// `profiler::trace_enabled()` controls, not this measurement. +#[cfg(feature = "profiler")] +#[derive(Default)] +struct FrameDirtyAccumulator { + dirty_at: Option, + invalidations: u64, +} + +/// Why GPUI capped a window's frame rate. +#[derive(Clone, Copy)] +enum FrameRateLimit { + /// The window isn't focused. + Inactive, + /// The system is under thermal pressure. + Thermal, +} + +#[derive(Clone)] +pub(crate) struct WindowInvalidator { + inner: Rc>, +} + +impl WindowInvalidator { + pub fn new(#[allow(unused_variables)] window_id: WindowId) -> Self { + WindowInvalidator { + inner: Rc::new(RefCell::new(WindowInvalidatorInner { + #[cfg(feature = "profiler")] + window_id, + dirty: true, + draw_phase: DrawPhase::None, + dirty_views: FxHashSet::default(), + update_count: 0, + #[cfg(feature = "profiler")] + frame_dirty: FrameDirtyAccumulator::default(), + platform_waker: None, + })), + } + } + + pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool { + let mut inner = self.inner.borrow_mut(); + inner.update_count += 1; + inner.dirty_views.insert(entity); + if inner.draw_phase == DrawPhase::None { + #[cfg(feature = "profiler")] + let dirty_at = Self::record_frame_dirty(&mut inner); + let became_dirty = !inner.dirty; + inner.dirty = true; + let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten(); + #[cfg(feature = "profiler")] + let window_id = inner.window_id; + drop(inner); + #[cfg(feature = "profiler")] + if became_dirty { + profiler::journal::record_frame_pending(window_id, dirty_at); + } + cx.push_effect(Effect::Notify { emitter: entity }); + if let Some(waker) = waker { + waker(); + } + true + } else { + false + } + } + + pub fn is_dirty(&self) -> bool { + self.inner.borrow().dirty + } + + pub fn set_dirty(&self, dirty: bool) { + let mut inner = self.inner.borrow_mut(); + let became_dirty = dirty && !inner.dirty; + inner.dirty = dirty; + if dirty { + inner.update_count += 1; + } + #[cfg(feature = "profiler")] + let dirty_at = dirty.then(|| Self::record_frame_dirty(&mut inner)); + let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten(); + #[cfg(feature = "profiler")] + let window_id = inner.window_id; + drop(inner); + #[cfg(feature = "profiler")] + if became_dirty && let Some(dirty_at) = dirty_at { + profiler::journal::record_frame_pending(window_id, dirty_at); + } + if let Some(waker) = waker { + waker(); + } + } + + pub fn set_platform_waker(&self, waker: Option>) { + let mut inner = self.inner.borrow_mut(); + inner.platform_waker = waker; + let waker = inner.dirty.then(|| inner.platform_waker.clone()).flatten(); + drop(inner); + if let Some(waker) = waker { + waker(); + } + } + + /// Wakes the platform's frame-request source so a frame request is + /// delivered even if the platform stops requesting frames for idle + /// windows. No-op on platforms without a frame waker. + pub fn wake_platform(&self) { + let waker = self.inner.borrow().platform_waker.clone(); + if let Some(waker) = waker { + waker(); + } + } + + pub fn set_phase(&self, phase: DrawPhase) { + self.inner.borrow_mut().draw_phase = phase + } + + pub fn update_count(&self) -> usize { + self.inner.borrow().update_count + } + + #[cfg(feature = "profiler")] + fn record_frame_dirty(inner: &mut WindowInvalidatorInner) -> Instant { + let dirty_at = *inner.frame_dirty.dirty_at.get_or_insert_with(Instant::now); + inner.frame_dirty.invalidations += 1; + dirty_at + } + + #[cfg(feature = "profiler")] + fn take_frame_dirty(&self) -> FrameDirtyAccumulator { + mem::take(&mut self.inner.borrow_mut().frame_dirty) + } + + pub fn take_views(&self) -> FxHashSet { + mem::take(&mut self.inner.borrow_mut().dirty_views) + } + + pub fn replace_views(&self, views: FxHashSet) { + self.inner.borrow_mut().dirty_views = views; + } + + pub fn not_drawing(&self) -> bool { + self.inner.borrow().draw_phase == DrawPhase::None + } + + #[track_caller] + pub fn debug_assert_paint(&self) { + debug_assert!( + matches!(self.inner.borrow().draw_phase, DrawPhase::Paint), + "this method can only be called during paint" + ); + } + + #[track_caller] + pub fn debug_assert_prepaint(&self) { + debug_assert!( + matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint), + "this method can only be called during request_layout, or prepaint" + ); + } + + #[track_caller] + pub fn debug_assert_paint_or_prepaint(&self) { + debug_assert!( + matches!( + self.inner.borrow().draw_phase, + DrawPhase::Paint | DrawPhase::Prepaint + ), + "this method can only be called during request_layout, prepaint, or paint" + ); + } +} + +type AnyObserver = Box bool + 'static>; + +pub(crate) type AnyWindowFocusListener = + Box bool + 'static>; + +pub(crate) struct WindowFocusEvent { + pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>, + pub(crate) current_focus_path: SmallVec<[FocusId; 8]>, +} + +impl WindowFocusEvent { + pub fn is_focus_in(&self, focus_id: FocusId) -> bool { + !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id) + } + + pub fn is_focus_out(&self, focus_id: FocusId) -> bool { + self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id) + } +} + +/// This is provided when subscribing for `Context::on_focus_out` events. +pub struct FocusOutEvent { + /// A weak focus handle representing what was blurred. + pub blurred: WeakFocusHandle, +} + +slotmap::new_key_type! { + /// A globally unique identifier for a focusable element. + pub struct FocusId; +} + +thread_local! { + /// Fallback arena used when no app-specific arena is active. + /// In production, each window draw sets CURRENT_ELEMENT_ARENA to the app's arena. + pub(crate) static ELEMENT_ARENA: RefCell = RefCell::new(Arena::new(1024 * 1024)); + + /// Points to the current App's element arena during draw operations. + /// This allows multiple test Apps to have isolated arenas, preventing + /// cross-session corruption when the scheduler interleaves their tasks. + static CURRENT_ELEMENT_ARENA: Cell>> = const { Cell::new(None) }; +} + +/// Whether a window draw is currently in progress on this thread. +/// +/// This holds exactly while an `ElementArenaScope` is active: nested scopes +/// restore the previous (still set) arena pointer, so `CURRENT_ELEMENT_ARENA` +/// is `Some` from the outermost draw's start to its end. +/// +/// The `on_request_frame` callback uses this to defer draw requests that +/// arrive re-entrantly while a draw is already on the stack (e.g. via nested +/// message pumping in the Windows window procedure), instead of running a +/// nested draw or panicking on the already-borrowed App. +fn draw_in_progress() -> bool { + CURRENT_ELEMENT_ARENA.with(|current| current.get().is_some()) +} + +/// Allocates an element in the current arena. Uses the app-specific arena if one +/// is active (during draw), otherwise falls back to the thread-local ELEMENT_ARENA. +#[inline(always)] +pub(crate) fn with_element_arena(callback: impl FnOnce(&mut Arena) -> R) -> R { + let mut callback = Some(callback); + let mut result = None; + let access = with_element_arena_erased(&mut |arena| { + result = Some(callback.take().expect("arena callback runs once")(arena)); + }); + drop(callback); + access.expect("cannot access a Thread Local Storage value during or after destruction"); + result.expect("arena callback produces a result") +} + +/// Scope guard that sets CURRENT_ELEMENT_ARENA for the duration of a draw +/// operation and tracks the arena's scope depth, so that a nested draw's +/// `ArenaClearNeeded::clear` is deferred rather than freeing memory the outer +/// draw still references (see `Arena::clear`). +/// +/// Call [`ElementArenaScope::exit`] with the same arena that was entered to +/// obtain the [`ArenaClearNeeded`] token the draw now owes; requiring `exit` +/// makes it impossible to request a clear before the scope has ended. The +/// scope's teardown — restoring the thread-local and balancing `begin_scope` +/// with `end_scope` — happens in `Drop`, so the arena's scope depth stays +/// balanced on every path, including when a panic unwinds a draw before `exit` +/// is reached. (If teardown lived only in `exit`, such a panic would leave the +/// scope depth permanently elevated and defer every future clear, leaking +/// memory unboundedly.) +pub(crate) struct ElementArenaScope { + /// The entered arena: compared against the argument in `exit`, and + /// dereferenced in `Drop` to end its scope (see the SAFETY note there). + entered: *const RefCell, + previous: Option<*const RefCell>, + exited: bool, +} + +impl ElementArenaScope { + /// Enter a scope where element allocations use the given arena. + pub(crate) fn enter(arena: &RefCell) -> Self { + arena.borrow_mut().begin_scope(); + let previous = CURRENT_ELEMENT_ARENA.with(|current| { + let prev = current.get(); + current.set(Some(arena as *const RefCell)); + prev + }); + Self { + entered: arena as *const RefCell, + previous, + exited: false, + } + } + + /// End the scope: restores the previously-current arena and ends the + /// arena's clear-deferral scope. Returns the token for the arena clear the + /// draw now owes; producing it here makes it impossible to request a clear + /// before the scope has ended (which would be silently deferred forever). + /// + /// Panics if passed a different arena than was entered: ending the scope + /// of the wrong arena would unbalance two arenas' scope depths, allowing + /// one of them to clear while a draw still references its memory. + pub(crate) fn exit(mut self, arena: &RefCell) -> ArenaClearNeeded { + assert!( + std::ptr::eq(self.entered, arena), + "ElementArenaScope::exit called with a different arena than was entered" + ); + self.exited = true; + // Teardown (restoring the thread-local and ending the arena's + // clear-deferral scope) runs in `Drop`, which fires both here — `self` + // is dropped as `exit` returns, before the token reaches the caller — + // and when a panic unwinds the draw before `exit` is reached. + ArenaClearNeeded::new(arena) + } +} + +impl Drop for ElementArenaScope { + fn drop(&mut self) { + // Teardown lives here (rather than in `exit`) so it runs exactly once on + // every path: `exit` consumes and drops the guard on the normal path, + // and unwinding drops it on the panic path. Balancing `begin_scope` here + // keeps the arena's scope depth correct even when a draw panics; if this + // only happened in `exit`, a panic between `enter` and `exit` would leave + // the depth elevated and defer every future clear. + CURRENT_ELEMENT_ARENA.with(|current| { + current.set(self.previous); + }); + // SAFETY: `entered` came from a `&RefCell` in `enter`, and the + // arena (owned by the `App` being drawn) outlives this guard on both the + // normal and unwinding paths, since the guard is a local of the draw. + unsafe { &*self.entered }.borrow_mut().end_scope(); + if !self.exited && !std::thread::panicking() { + debug_assert!(false, "ElementArenaScope dropped without calling exit()"); + log::error!( + "ElementArenaScope dropped without calling exit(); \ + the arena clear for this draw was never requested" + ); + } + } +} + +/// Returned when the element arena has been used and so must be cleared before the next draw. +#[must_use] +pub struct ArenaClearNeeded { + /// Identity of the arena that was drawn into. Only ever compared against + /// another pointer in `clear`; never dereferenced. + arena: *const RefCell, +} + +impl ArenaClearNeeded { + /// Create a new ArenaClearNeeded token for the App whose arena was drawn + /// into. Private: the only way to obtain one is [`ElementArenaScope::exit`]. + fn new(arena: &RefCell) -> Self { + Self { + arena: arena as *const RefCell, + } + } + + /// Clear the element arena of the App the draw ran against. If an enclosing + /// draw is still in progress (this draw was nested inside it), the clear is + /// deferred to the enclosing draw's own `ArenaClearNeeded` so that its live + /// allocations aren't freed. + /// + /// Panics if passed a different App than the draw ran against, since + /// clearing another App's arena could free memory its draws still + /// reference. + pub fn clear(self, cx: &mut App) { + assert!( + std::ptr::eq(self.arena, &cx.element_arena), + "ArenaClearNeeded::clear called with a different App than the draw ran against" + ); + cx.element_arena.borrow_mut().clear(); + } +} + +pub(crate) type FocusMap = RwLock>; +pub(crate) struct FocusRef { + pub(crate) ref_count: AtomicUsize, + pub(crate) tab_index: isize, + pub(crate) tab_stop: bool, +} + +impl FocusId { + /// Obtains whether the element associated with this handle is currently focused. + pub fn is_focused(&self, window: &Window) -> bool { + window.focus == Some(*self) + } + + /// Obtains whether the element associated with this handle contains the focused + /// element or is itself focused. + pub fn contains_focused(&self, window: &Window, cx: &App) -> bool { + window + .focused(cx) + .is_some_and(|focused| self.contains(focused.id, window)) + } + + /// Obtains whether the element associated with this handle is contained within the + /// focused element or is itself focused. + pub fn within_focused(&self, window: &Window, cx: &App) -> bool { + let focused = window.focused(cx); + focused.is_some_and(|focused| focused.id.contains(*self, window)) + } + + /// Obtains whether this handle contains the given handle in the most recently rendered frame. + pub(crate) fn contains(&self, other: Self, window: &Window) -> bool { + window + .rendered_frame + .dispatch_tree + .focus_contains(*self, other) + } +} + +/// A handle which can be used to track and manipulate the focused element in a window. +pub struct FocusHandle { + pub(crate) id: FocusId, + handles: Arc, + /// The index of this element in the tab order. + pub tab_index: isize, + /// Whether this element can be focused by tab navigation. + pub tab_stop: bool, +} + +impl std::fmt::Debug for FocusHandle { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("FocusHandle({:?})", self.id)) + } +} + +impl FocusHandle { + pub(crate) fn new(handles: &Arc) -> Self { + let id = handles.write().insert(FocusRef { + ref_count: AtomicUsize::new(1), + tab_index: 0, + tab_stop: false, + }); + + Self { + id, + tab_index: 0, + tab_stop: false, + handles: handles.clone(), + } + } + + pub(crate) fn for_id(id: FocusId, handles: &Arc) -> Option { + let lock = handles.read(); + let focus = lock.get(id)?; + if atomic_incr_if_not_zero(&focus.ref_count) == 0 { + return None; + } + Some(Self { + id, + tab_index: focus.tab_index, + tab_stop: focus.tab_stop, + handles: handles.clone(), + }) + } + + /// Sets the tab index of the element associated with this handle. + pub fn tab_index(mut self, index: isize) -> Self { + self.tab_index = index; + if let Some(focus) = self.handles.write().get_mut(self.id) { + focus.tab_index = index; + } + self + } + + /// Sets whether the element associated with this handle is a tab stop. + /// + /// When `false`, the element will not be included in the tab order. + pub fn tab_stop(mut self, tab_stop: bool) -> Self { + self.tab_stop = tab_stop; + if let Some(focus) = self.handles.write().get_mut(self.id) { + focus.tab_stop = tab_stop; + } + self + } + + /// Converts this focus handle into a weak variant, which does not prevent it from being released. + pub fn downgrade(&self) -> WeakFocusHandle { + WeakFocusHandle { + id: self.id, + handles: Arc::downgrade(&self.handles), + } + } + + /// Moves the focus to the element associated with this handle. + pub fn focus(&self, window: &mut Window, cx: &mut App) { + window.focus(self, cx) + } + + /// Obtains whether the element associated with this handle is currently focused. + pub fn is_focused(&self, window: &Window) -> bool { + self.id.is_focused(window) + } + + /// Obtains whether the element associated with this handle contains the focused + /// element or is itself focused. + pub fn contains_focused(&self, window: &Window, cx: &App) -> bool { + self.id.contains_focused(window, cx) + } + + /// Obtains whether the element associated with this handle is contained within the + /// focused element or is itself focused. + pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool { + self.id.within_focused(window, cx) + } + + /// Obtains whether this handle contains the given handle in the most recently rendered frame. + pub fn contains(&self, other: &Self, window: &Window) -> bool { + self.id.contains(other.id, window) + } + + /// Dispatch an action on the element that rendered this focus handle + pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) { + if let Some(node_id) = window + .rendered_frame + .dispatch_tree + .focusable_node_id(self.id) + { + window.dispatch_action_on_node(node_id, action, cx) + } + } +} + +impl Clone for FocusHandle { + fn clone(&self) -> Self { + Self::for_id(self.id, &self.handles).unwrap() + } +} + +impl PartialEq for FocusHandle { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + +impl Eq for FocusHandle {} + +impl Drop for FocusHandle { + fn drop(&mut self) { + self.handles + .read() + .get(self.id) + .unwrap() + .ref_count + .fetch_sub(1, SeqCst); + } +} + +/// A weak reference to a focus handle. +#[derive(Clone, Debug)] +pub struct WeakFocusHandle { + pub(crate) id: FocusId, + pub(crate) handles: Weak, +} + +impl WeakFocusHandle { + /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle]. + pub fn upgrade(&self) -> Option { + let handles = self.handles.upgrade()?; + FocusHandle::for_id(self.id, &handles) + } +} + +impl PartialEq for WeakFocusHandle { + fn eq(&self, other: &WeakFocusHandle) -> bool { + self.id == other.id + } +} + +impl Eq for WeakFocusHandle {} + +impl PartialEq for WeakFocusHandle { + fn eq(&self, other: &FocusHandle) -> bool { + self.id == other.id + } +} + +impl PartialEq for FocusHandle { + fn eq(&self, other: &WeakFocusHandle) -> bool { + self.id == other.id + } +} + +/// Focusable allows users of your view to easily +/// focus it (using window.focus_view(cx, view)) +pub trait Focusable: 'static { + /// Returns the focus handle associated with this view. + fn focus_handle(&self, cx: &App) -> FocusHandle; +} + +impl Focusable for Entity { + fn focus_handle(&self, cx: &App) -> FocusHandle { + self.read(cx).focus_handle(cx) + } +} + +/// ManagedView is a view (like a Modal, Popover, Menu, etc.) +/// where the lifecycle of the view is handled by another view. +pub trait ManagedView: Focusable + EventEmitter + Render {} + +impl + Render> ManagedView for M {} + +/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal. +pub struct DismissEvent; + +type FrameCallback = Box; + +pub(crate) type AnyMouseListener = + Box; + +#[derive(Clone)] +pub(crate) struct CursorStyleRequest { + pub(crate) hitbox_id: Option, + pub(crate) style: CursorStyle, +} + +#[derive(Default, Eq, PartialEq)] +pub(crate) struct HitTest { + pub(crate) ids: SmallVec<[HitboxId; 8]>, + pub(crate) hover_hitbox_count: usize, +} + +/// A type of window control area that corresponds to the platform window. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum WindowControlArea { + /// An area that allows dragging of the platform window. + Drag, + /// An area that allows closing of the platform window. + Close, + /// An area that allows maximizing of the platform window. + Max, + /// An area that allows minimizing of the platform window. + Min, +} + +/// An identifier for a [Hitbox] which also includes [HitboxBehavior]. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct HitboxId(u64); + +#[cfg(feature = "test-support")] +impl HitboxId { + /// A placeholder HitboxId exclusively for integration testing API's that + /// need a hitbox but where the value of the hitbox does not matter. The + /// alternative is to make the Hitbox optional but that complicates the + /// implementation. + pub const fn placeholder() -> Self { + Self(0) + } +} + +impl HitboxId { + /// Checks if the hitbox with this ID is currently hovered. Returns `false` during keyboard + /// input modality so that keyboard navigation suppresses hover highlights. Except when handling + /// `ScrollWheelEvent`, this is typically what you want when determining whether to handle mouse + /// events or paint hover styles. + /// + /// See [`Hitbox::is_hovered`] for details. + pub fn is_hovered(self, window: &Window) -> bool { + // If this hitbox has captured the pointer, it's always considered hovered + if window.captured_hitbox == Some(self) { + return true; + } + if window.last_input_was_keyboard() { + return false; + } + self.hit_test(window) + } + + /// Checks if the hitbox with this ID is currently hovered, regardless of the last + /// input modality used. + /// + /// See [`HitboxId::is_hovered`] for more details. + pub(crate) fn is_hovered_ignoring_last_input(self, window: &Window) -> bool { + // If this hitbox has captured the pointer, it's always considered hovered + if window.captured_hitbox == Some(self) { + return true; + } + self.hit_test(window) + } + + fn hit_test(self, window: &Window) -> bool { + let hit_test = &window.mouse_hit_test; + for id in hit_test.ids.iter().take(hit_test.hover_hitbox_count) { + if self == *id { + return true; + } + } + false + } + + /// Checks if the hitbox with this ID contains the mouse and should handle scroll events. + /// Typically this should only be used when handling `ScrollWheelEvent`, and otherwise + /// `is_hovered` should be used. See the documentation of `Hitbox::is_hovered` for details about + /// this distinction. + pub fn should_handle_scroll(self, window: &Window) -> bool { + window.mouse_hit_test.ids.contains(&self) + } + + fn next(mut self) -> HitboxId { + HitboxId(self.0.wrapping_add(1)) + } +} + +/// A rectangular region that potentially blocks hitboxes inserted prior. +/// See [Window::insert_hitbox] for more details. +#[derive(Clone, Debug, Deref)] +pub struct Hitbox { + /// A unique identifier for the hitbox. + pub id: HitboxId, + /// The bounds of the hitbox. + #[deref] + pub bounds: Bounds, + /// The content mask when the hitbox was inserted. + pub content_mask: ContentMask, + /// Flags that specify hitbox behavior. + pub behavior: HitboxBehavior, +} + +impl Hitbox { + /// Checks if the hitbox is currently hovered. Returns `false` during keyboard input modality + /// so that keyboard navigation suppresses hover highlights. Except when handling + /// `ScrollWheelEvent`, this is typically what you want when determining whether to handle mouse + /// events or paint hover styles. + /// + /// This can return `false` even when the hitbox contains the mouse, if a hitbox in front of + /// this sets `HitboxBehavior::BlockMouse` (`InteractiveElement::occlude`) or + /// `HitboxBehavior::BlockMouseExceptScroll` (`InteractiveElement::block_mouse_except_scroll`), + /// or if the current input modality is keyboard (see [`Window::last_input_was_keyboard`]). + /// + /// Handling of `ScrollWheelEvent` should typically use `should_handle_scroll` instead. + /// Concretely, this is due to use-cases like overlays that cause the elements under to be + /// non-interactive while still allowing scrolling. More abstractly, this is because + /// `is_hovered` is about element interactions directly under the mouse - mouse moves, clicks, + /// hover styling, etc. In contrast, scrolling is about finding the current outer scrollable + /// container. + pub fn is_hovered(&self, window: &Window) -> bool { + self.id.is_hovered(window) + } + + /// Checks whether this hitbox would be hovered at `position`, regardless of the current input + /// modality or mouse position. + pub fn is_hovered_at(&self, position: Point, window: &Window) -> bool { + let hit_test = window.rendered_frame.hit_test(position); + hit_test + .ids + .iter() + .take(hit_test.hover_hitbox_count) + .any(|id| self.id == *id) + } + + /// Checks if the hitbox contains the mouse and should handle scroll events. Typically this + /// should only be used when handling `ScrollWheelEvent`, and otherwise `is_hovered` should be + /// used. See the documentation of `Hitbox::is_hovered` for details about this distinction. + /// + /// This can return `false` even when the hitbox contains the mouse, if a hitbox in front of + /// this sets `HitboxBehavior::BlockMouse` (`InteractiveElement::occlude`). + pub fn should_handle_scroll(&self, window: &Window) -> bool { + self.id.should_handle_scroll(window) + } +} + +/// How the hitbox affects mouse behavior. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum HitboxBehavior { + /// Normal hitbox mouse behavior, doesn't affect mouse handling for other hitboxes. + #[default] + Normal, + + /// All hitboxes behind this hitbox will be ignored and so will have `hitbox.is_hovered() == + /// false` and `hitbox.should_handle_scroll() == false`. Typically for elements this causes + /// skipping of all mouse events, hover styles, and tooltips. This flag is set by + /// [`InteractiveElement::occlude`]. + /// + /// For mouse handlers that check those hitboxes, this behaves the same as registering a + /// bubble-phase handler for every mouse event type: + /// + /// ```ignore + /// window.on_mouse_event(move |_: &EveryMouseEventTypeHere, phase, window, cx| { + /// if phase == DispatchPhase::Capture && hitbox.is_hovered(window) { + /// cx.stop_propagation(); + /// } + /// }) + /// ``` + /// + /// This has effects beyond event handling - any use of hitbox checking, such as hover + /// styles and tooltips. These other behaviors are the main point of this mechanism. An + /// alternative might be to not affect mouse event handling - but this would allow + /// inconsistent UI where clicks and moves interact with elements that are not considered to + /// be hovered. + BlockMouse, + + /// All hitboxes behind this hitbox will have `hitbox.is_hovered() == false`, even when + /// `hitbox.should_handle_scroll() == true`. Typically for elements this causes all mouse + /// interaction except scroll events to be ignored - see the documentation of + /// [`Hitbox::is_hovered`] for details. This flag is set by + /// [`InteractiveElement::block_mouse_except_scroll`]. + /// + /// For mouse handlers that check those hitboxes, this behaves the same as registering a + /// bubble-phase handler for every mouse event type **except** `ScrollWheelEvent`: + /// + /// ```ignore + /// window.on_mouse_event(move |_: &EveryMouseEventTypeExceptScroll, phase, window, cx| { + /// if phase == DispatchPhase::Bubble && hitbox.should_handle_scroll(window) { + /// cx.stop_propagation(); + /// } + /// }) + /// ``` + /// + /// See the documentation of [`Hitbox::is_hovered`] for details of why `ScrollWheelEvent` is + /// handled differently than other mouse events. If also blocking these scroll events is + /// desired, then a `cx.stop_propagation()` handler like the one above can be used. + /// + /// This has effects beyond event handling - this affects any use of `is_hovered`, such as + /// hover styles and tooltips. These other behaviors are the main point of this mechanism. + /// An alternative might be to not affect mouse event handling - but this would allow + /// inconsistent UI where clicks and moves interact with elements that are not considered to + /// be hovered. + BlockMouseExceptScroll, +} + +/// An identifier for a tooltip. +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +pub struct TooltipId(usize); + +impl TooltipId { + /// Checks if the tooltip is currently hovered. + pub fn is_hovered(&self, window: &Window) -> bool { + window + .tooltip_bounds + .as_ref() + .is_some_and(|tooltip_bounds| { + tooltip_bounds.id == *self + && tooltip_bounds.bounds.contains(&window.mouse_position()) + }) + } +} + +pub(crate) struct TooltipBounds { + id: TooltipId, + bounds: Bounds, +} + +#[derive(Clone)] +pub(crate) struct TooltipRequest { + id: TooltipId, + tooltip: AnyTooltip, +} + +pub(crate) struct DeferredDraw { + current_view: EntityId, + priority: usize, + parent_node: DispatchNodeId, + element_id_stack: SmallVec<[ElementId; 32]>, + text_style_stack: Vec, + content_mask: Option>, + rem_size: Pixels, + element: Option, + absolute_offset: Point, + prepaint_range: Range, + paint_range: Range, +} + +pub(crate) struct Frame { + pub(crate) focus: Option, + pub(crate) window_active: bool, + pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>, + accessed_element_states: Vec<(GlobalElementId, TypeId)>, + pub(crate) mouse_listeners: Vec>, + pub(crate) dispatch_tree: DispatchTree, + pub(crate) scene: Scene, + pub(crate) hitboxes: Vec, + pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>, + pub(crate) deferred_draws: Vec, + pub(crate) input_handlers: Vec>, + pub(crate) tooltip_requests: Vec>, + pub(crate) cursor_styles: Vec, + #[cfg(any(test, feature = "test-support"))] + pub(crate) debug_bounds: FxHashMap>, + #[cfg(any(test, feature = "test-support"))] + debug_bounds_records: Vec<(String, Bounds)>, + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) next_inspector_instance_ids: FxHashMap, usize>, + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) inspector_hitboxes: FxHashMap, + pub(crate) tab_stops: TabStopMap, +} + +#[derive(Clone, Default)] +pub(crate) struct PrepaintStateIndex { + hitboxes_index: usize, + tooltips_index: usize, + deferred_draws_index: usize, + dispatch_tree_index: usize, + accessed_element_states_index: usize, + line_layout_index: LineLayoutIndex, +} + +#[derive(Clone, Default)] +pub(crate) struct PaintIndex { + scene_index: usize, + #[cfg(any(test, feature = "test-support"))] + debug_bounds_index: usize, + mouse_listeners_index: usize, + input_handlers_index: usize, + cursor_styles_index: usize, + accessed_element_states_index: usize, + tab_handle_index: usize, + line_layout_index: LineLayoutIndex, +} + +impl Frame { + #[cfg(any(test, feature = "test-support"))] + pub(crate) fn record_debug_bounds(&mut self, selector: String, bounds: Bounds) { + self.debug_bounds.insert(selector.clone(), bounds); + self.debug_bounds_records.push((selector, bounds)); + } + + pub(crate) fn new(dispatch_tree: DispatchTree) -> Self { + Frame { + focus: None, + window_active: false, + element_states: FxHashMap::default(), + accessed_element_states: Vec::new(), + mouse_listeners: Vec::new(), + dispatch_tree, + scene: Scene::default(), + hitboxes: Vec::new(), + window_control_hitboxes: Vec::new(), + deferred_draws: Vec::new(), + input_handlers: Vec::new(), + tooltip_requests: Vec::new(), + cursor_styles: Vec::new(), + + #[cfg(any(test, feature = "test-support"))] + debug_bounds: FxHashMap::default(), + #[cfg(any(test, feature = "test-support"))] + debug_bounds_records: Vec::new(), + + #[cfg(any(feature = "inspector", debug_assertions))] + next_inspector_instance_ids: FxHashMap::default(), + + #[cfg(any(feature = "inspector", debug_assertions))] + inspector_hitboxes: FxHashMap::default(), + tab_stops: TabStopMap::default(), + } + } + + pub(crate) fn clear(&mut self) { + self.element_states.clear(); + self.accessed_element_states.clear(); + self.mouse_listeners.clear(); + self.dispatch_tree.clear(); + self.scene.clear(); + self.input_handlers.clear(); + self.tooltip_requests.clear(); + self.cursor_styles.clear(); + self.hitboxes.clear(); + self.window_control_hitboxes.clear(); + self.deferred_draws.clear(); + self.tab_stops.clear(); + self.focus = None; + + #[cfg(any(test, feature = "test-support"))] + { + self.debug_bounds.clear(); + self.debug_bounds_records.clear(); + } + + #[cfg(any(feature = "inspector", debug_assertions))] + { + self.next_inspector_instance_ids.clear(); + self.inspector_hitboxes.clear(); + } + } + + pub(crate) fn cursor_style(&self, window: &Window) -> Option { + self.cursor_styles + .iter() + .rev() + .fold_while(None, |style, request| match request.hitbox_id { + None => Done(Some(request.style)), + Some(hitbox_id) => Continue(style.or_else(|| { + hitbox_id + .is_hovered_ignoring_last_input(window) + .then_some(request.style) + })), + }) + .into_inner() + } + + pub(crate) fn hit_test(&self, position: Point) -> HitTest { + let mut set_hover_hitbox_count = false; + let mut hit_test = HitTest::default(); + for hitbox in self.hitboxes.iter().rev() { + let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds); + if bounds.contains(&position) { + hit_test.ids.push(hitbox.id); + if !set_hover_hitbox_count + && hitbox.behavior == HitboxBehavior::BlockMouseExceptScroll + { + hit_test.hover_hitbox_count = hit_test.ids.len(); + set_hover_hitbox_count = true; + } + if hitbox.behavior == HitboxBehavior::BlockMouse { + break; + } + } + } + if !set_hover_hitbox_count { + hit_test.hover_hitbox_count = hit_test.ids.len(); + } + hit_test + } + + pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> { + self.focus + .map(|focus_id| self.dispatch_tree.focus_path(focus_id)) + .unwrap_or_default() + } + + pub(crate) fn finish(&mut self, prev_frame: &mut Self) { + for element_state_key in &self.accessed_element_states { + if let Some((element_state_key, element_state)) = + prev_frame.element_states.remove_entry(element_state_key) + { + self.element_states.insert(element_state_key, element_state); + } + } + + self.scene.finish(); + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +enum InputModality { + Mouse, + Keyboard, + Touch, +} + +/// Holds the state for a specific window. +pub struct Window { + pub(crate) handle: AnyWindowHandle, + pub(crate) invalidator: WindowInvalidator, + pub(crate) removed: bool, + pub(crate) platform_window: Box, + display_id: Option, + is_resizable: bool, + is_minimizable: bool, + sprite_atlas: Arc, + text_system: Arc, + text_rendering_mode: Rc>, + rem_size: Pixels, + /// The stack of override values for the window's rem size. + /// + /// This is used by `with_rem_size` to allow rendering an element tree with + /// a given rem size. + rem_size_override_stack: SmallVec<[Pixels; 8]>, + pub(crate) viewport_size: Size, + layout_engine: Option, + pub(crate) root: Option, + pub(crate) element_id_stack: SmallVec<[ElementId; 32]>, + pub(crate) text_style_stack: Vec, + pub(crate) rendered_entity_stack: Vec, + pub(crate) element_offset_stack: Vec>, + pub(crate) element_opacity: f32, + pub(crate) content_mask_stack: Vec>, + pub(crate) requested_autoscroll: Option>, + /// The [`TextInputConfiguration`] most recently forwarded to the platform + /// window, so that only actual changes are forwarded (reconfiguring a live + /// input session can restart the IME connection). + last_text_input_configuration: Option, + focused_text_input_active: bool, + pub(crate) image_cache_stack: Vec, + pub(crate) rendered_frame: Frame, + pub(crate) next_frame: Frame, + next_hitbox_id: HitboxId, + pub(crate) next_tooltip_id: TooltipId, + pub(crate) tooltip_bounds: Option, + pub(crate) next_frame_callbacks: Rc>>, + pub(crate) dirty_views: FxHashSet, + focus_listeners: SubscriberSet<(), AnyWindowFocusListener>, + pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>, + focus_lost_path: SmallVec<[FocusId; 8]>, + default_prevented: bool, + mouse_position: Point, + mouse_hit_test: HitTest, + modifiers: Modifiers, + capslock: Capslock, + scale_factor: f32, + pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>, + appearance: WindowAppearance, + pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>, + pub(crate) button_layout_observers: SubscriberSet<(), AnyObserver>, + active: Rc>, + visibility: WindowVisibility, + pub(crate) visibility_observers: + SubscriberSet<(), Box bool>>, + hovered: Rc>, + pub(crate) needs_present: Rc>, + /// Tracks recent input event timestamps to determine if input is arriving at a high rate. + /// Used to selectively enable VRR optimization only when input rate exceeds 60fps. + pub(crate) input_rate_tracker: Rc>, + #[cfg(feature = "profiler")] + window_profiler: profiler::WindowProfiler, + last_input_modality: InputModality, + touch_gestures: TouchGestureRecognizer, + touch_prediction_enabled: bool, + long_press_timer: Option>, + long_press_capture: Option, + pub(crate) refreshing: bool, + pub(crate) activation_observers: SubscriberSet<(), AnyObserver>, + pub(crate) focus: Option, + focus_enabled: bool, + /// Incremented every time focus moves. Used to invalidate a + /// pending keyboard activation state when focus changes. + pub(crate) focus_generation: u64, + pending_input: Option, + pending_modifier: ModifierState, + pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>, + prompt: Option, + pub(crate) client_inset: Option, + /// The hitbox that has captured the pointer, if any. + /// While captured, mouse events route to this hitbox regardless of hit testing. + captured_hitbox: Option, + #[cfg(any(feature = "inspector", debug_assertions))] + inspector: Option>, + #[cfg(feature = "profiler")] + debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay, + pub(crate) a11y: A11y, +} + +#[derive(Clone, Debug, Default)] +struct ModifierState { + modifiers: Modifiers, + saw_other_input: bool, +} + +/// Tracks input event timestamps to determine if input is arriving at a high rate. +/// Used for selective VRR (Variable Refresh Rate) optimization. +#[derive(Clone, Debug)] +pub(crate) struct InputRateTracker { + timestamps: Vec, + window: Duration, + inputs_per_second: u32, + sustain_until: Instant, + sustain_duration: Duration, +} + +impl Default for InputRateTracker { + fn default() -> Self { + Self { + timestamps: Vec::new(), + window: Duration::from_millis(100), + inputs_per_second: 60, + sustain_until: Instant::now(), + sustain_duration: Duration::from_secs(1), + } + } +} + +impl InputRateTracker { + pub fn record_input(&mut self) { + let now = Instant::now(); + self.timestamps.push(now); + self.prune_old_timestamps(now); + + let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000; + if self.timestamps.len() as u128 >= min_events { + self.sustain_until = now + self.sustain_duration; + } + } + + pub fn is_high_rate(&self) -> bool { + Instant::now() < self.sustain_until + } + + fn prune_old_timestamps(&mut self, now: Instant) { + self.timestamps + .retain(|&t| now.duration_since(t) <= self.window); + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(crate) enum DrawPhase { + None, + Prepaint, + Paint, + Focus, +} + +pub(crate) const PENDING_INPUT_TIMEOUT: Duration = Duration::from_secs(1); + +/// Pending input for a potential multi-stroke key binding. +pub struct PendingInputStatus<'a> { + keystrokes: &'a [Keystroke], + timeout: Option, +} + +impl<'a> PendingInputStatus<'a> { + /// Returns the keystrokes entered so far. + pub fn keystrokes(&self) -> &'a [Keystroke] { + self.keystrokes + } + + /// Returns the timeout state for flushing this input, if it needs a timeout. + pub fn timeout(&self) -> Option { + self.timeout + } +} + +/// The timeout state for pending input. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct PendingInputTimeoutStatus { + duration: Duration, + remaining: Duration, + started_at: Option, + paused: bool, +} + +impl PendingInputTimeoutStatus { + /// Returns the full timeout duration. + pub fn duration(&self) -> Duration { + self.duration + } + + /// Returns the duration remaining before pending input is flushed. + pub fn remaining(&self, cx: &App) -> Duration { + self.started_at + .map(|started_at| { + self.remaining + .saturating_sub(cx.background_executor().now() - started_at) + }) + .unwrap_or(self.remaining) + } + + /// Returns whether the timeout is paused. + pub fn is_paused(&self) -> bool { + self.paused + } +} + +#[derive(Debug)] +struct PendingInputTimeout { + duration: Duration, + remaining: Duration, + state: PendingInputTimeoutState, +} + +#[derive(Debug)] +enum PendingInputTimeoutState { + Running { started_at: Instant, task: Task<()> }, + Paused { pause: PendingInputTimeoutPause }, +} + +#[derive(Debug)] +struct PendingInputTimeoutPause { + owner_id: EntityId, + _release_subscription: Subscription, +} + +impl PendingInputTimeout { + fn is_paused(&self) -> bool { + matches!(&self.state, PendingInputTimeoutState::Paused { .. }) + } + + fn pause(&mut self, pause: PendingInputTimeoutPause, now: Instant) -> bool { + match std::mem::replace(&mut self.state, PendingInputTimeoutState::Paused { pause }) { + PendingInputTimeoutState::Running { started_at, task } => { + self.remaining = self.remaining.saturating_sub(now - started_at); + drop(task); + true + } + previous_state @ PendingInputTimeoutState::Paused { .. } => { + self.state = previous_state; + false + } + } + } + + fn pause_owner_id(&self) -> Option { + match &self.state { + PendingInputTimeoutState::Running { .. } => None, + PendingInputTimeoutState::Paused { pause } => Some(pause.owner_id), + } + } + + fn resume(&mut self, owner_id: EntityId, started_at: Instant, task: Task<()>) -> bool { + match std::mem::replace( + &mut self.state, + PendingInputTimeoutState::Running { started_at, task }, + ) { + PendingInputTimeoutState::Paused { pause } if pause.owner_id == owner_id => true, + previous_state => { + self.state = previous_state; + false + } + } + } + + fn reset_duration(&mut self, duration: Duration) { + self.duration = duration; + self.remaining = duration; + } + + fn status(&self) -> PendingInputTimeoutStatus { + let (started_at, paused) = match &self.state { + PendingInputTimeoutState::Running { started_at, .. } => (Some(*started_at), false), + PendingInputTimeoutState::Paused { .. } => (None, true), + }; + PendingInputTimeoutStatus { + duration: self.duration, + remaining: self.remaining, + started_at, + paused, + } + } +} + +#[derive(Default, Debug)] +struct PendingInput { + keystrokes: SmallVec<[Keystroke; 1]>, + focus: Option, + timeout: Option, +} + +pub(crate) struct ElementStateBox { + pub(crate) inner: Box, + #[cfg(debug_assertions)] + pub(crate) type_name: &'static str, +} + +fn default_bounds(display_id: Option, cx: &mut App) -> WindowBounds { + // TODO, BUG: if you open a window with the currently active window + // on the stack, this will erroneously fallback to `None` + // + // TODO these should be the initial window bounds not considering maximized/fullscreen + let active_window_bounds = cx + .active_window() + .and_then(|w| w.update(cx, |_, window, _| window.window_bounds()).ok()); + + const CASCADE_OFFSET: f32 = 25.0; + + let display = display_id + .map(|id| cx.find_display(id)) + .unwrap_or_else(|| cx.primary_display()); + + let default_placement = || Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE); + + // Use visible_bounds to exclude taskbar/dock areas + let display_bounds = display + .as_ref() + .map(|d| d.visible_bounds()) + .unwrap_or_else(default_placement); + + let ( + Bounds { + origin: base_origin, + size: base_size, + }, + window_bounds_ctor, + ): (_, fn(Bounds) -> WindowBounds) = match active_window_bounds { + Some(bounds) => match bounds { + WindowBounds::Windowed(bounds) => (bounds, WindowBounds::Windowed), + WindowBounds::Maximized(bounds) => (bounds, WindowBounds::Maximized), + WindowBounds::Fullscreen(bounds) => (bounds, WindowBounds::Fullscreen), + }, + None => ( + display + .as_ref() + .map(|d| d.default_bounds()) + .unwrap_or_else(default_placement), + WindowBounds::Windowed, + ), + }; + + let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET)); + let proposed_origin = base_origin + cascade_offset; + let proposed_bounds = Bounds::new(proposed_origin, base_size); + + let display_right = display_bounds.origin.x + display_bounds.size.width; + let display_bottom = display_bounds.origin.y + display_bounds.size.height; + let window_right = proposed_bounds.origin.x + proposed_bounds.size.width; + let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height; + + let fits_horizontally = window_right <= display_right; + let fits_vertically = window_bottom <= display_bottom; + + let final_origin = match (fits_horizontally, fits_vertically) { + (true, true) => proposed_origin, + (false, true) => point(display_bounds.origin.x, base_origin.y), + (true, false) => point(base_origin.x, display_bounds.origin.y), + (false, false) => display_bounds.origin, + }; + window_bounds_ctor(Bounds::new(final_origin, base_size)) +} + +impl Window { + pub(crate) fn new( + handle: AnyWindowHandle, + options: WindowOptions, + cx: &mut App, + ) -> Result { + let WindowOptions { + window_bounds, + titlebar, + focus, + show, + kind, + is_movable, + app_owns_titlebar_drag, + inactive_frame_interval, + is_resizable, + is_minimizable, + display_id, + window_background, + app_id, + window_min_size, + window_decorations, + #[cfg_attr( + not(any(target_os = "linux", target_os = "freebsd")), + allow(unused_variables) + )] + icon, + #[cfg_attr(not(target_os = "macos"), allow(unused_variables))] + tabbing_identifier, + } = options; + + let initial_window_title = titlebar + .as_ref() + .and_then(|titlebar| titlebar.title.clone()); + + let window_bounds = window_bounds.unwrap_or_else(|| default_bounds(display_id, cx)); + let mut platform_window = cx.platform.open_window( + handle, + WindowParams { + bounds: window_bounds.get_bounds(), + titlebar, + kind, + is_movable, + app_owns_titlebar_drag, + is_resizable, + is_minimizable, + focus, + show, + display_id, + window_min_size, + app_id: app_id.clone(), + icon, + #[cfg(target_os = "macos")] + tabbing_identifier, + }, + )?; + + let tab_bar_visible = platform_window.tab_bar_visible(); + SystemWindowTabController::init_visible(cx, tab_bar_visible); + if let Some(tabs) = platform_window.tabbed_windows() { + SystemWindowTabController::add_tab(cx, handle.window_id(), tabs); + } + + let display_id = platform_window.display().map(|display| display.id()); + let sprite_atlas = platform_window.sprite_atlas(); + let mouse_position = platform_window.mouse_position(); + let modifiers = platform_window.modifiers(); + let capslock = platform_window.capslock(); + let content_size = platform_window.content_size(); + let scale_factor = platform_window.scale_factor(); + let appearance = platform_window.appearance(); + let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone())); + let invalidator = WindowInvalidator::new(handle.window_id()); + let active = Rc::new(Cell::new(platform_window.is_active())); + let visibility = platform_window.visibility(); + #[cfg(feature = "profiler")] + profiler::journal::record_window_visibility(handle.window_id(), visibility); + let hovered = Rc::new(Cell::new(platform_window.is_hovered())); + let needs_present = Rc::new(Cell::new(false)); + let next_frame_callbacks: Rc>> = Default::default(); + let input_rate_tracker = Rc::new(RefCell::new(InputRateTracker::default())); + let last_frame_time = Rc::new(Cell::new(None)); + + platform_window + .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server)); + platform_window.set_background_appearance(window_background); + + match window_bounds { + WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(), + WindowBounds::Maximized(_) => platform_window.zoom(), + WindowBounds::Windowed(_) => {} + } + + let accessibility_force_disabled = cx.accessibility_force_disabled; + let a11y_active_flag = Arc::new(AtomicBool::new(false)); + + #[cfg(not(target_family = "wasm"))] + if !accessibility_force_disabled { + let mut initial_root_node = accesskit::Node::new(accesskit::Role::Window); + if let Some(title) = &initial_window_title { + initial_root_node.set_label(title.to_string()); + } + let initial_tree = accesskit::TreeUpdate { + nodes: vec![(ROOT_NODE_ID, initial_root_node)], + tree: Some(accesskit::Tree::new(ROOT_NODE_ID)), + tree_id: accesskit::TreeId::ROOT, + focus: ROOT_NODE_ID, + }; + let (activation_sender, activation_receiver) = async_channel::unbounded::<()>(); + let (deactivation_sender, deactivation_receiver) = async_channel::unbounded::<()>(); + let (action_sender, action_receiver) = + async_channel::unbounded::(); + + platform_window.a11y_init(crate::A11yCallbacks { + activation: { + let active_flag = a11y_active_flag.clone(); + Box::new(move || { + log::info!("Accessibility activated"); + active_flag.store(true, SeqCst); + activation_sender.send_blocking(()).log_err(); + Some(initial_tree.clone()) + }) + }, + action: Box::new(move |request| { + action_sender.send_blocking(request).log_err(); + }), + deactivation: { + let active_flag = a11y_active_flag.clone(); + Box::new(move || { + log::info!("Accessibility deactivated"); + active_flag.store(false, SeqCst); + deactivation_sender.send_blocking(()).log_err(); + }) + }, + }); + + // A11y can be activated at any time, and so we cannot compute a + // correct `TreeUpdate` on-demand. When this happens, we return a + // default empty `TreeUpdate`. + // + // So we force a new frame, which will then send a correct `TreeUpdate`. + let mut async_cx = cx.to_async(); + cx.foreground_executor() + .spawn(async move { + while activation_receiver.recv().await.is_ok() { + handle + .update(&mut async_cx, |_, window, _| window.refresh()) + .log_err(); + } + }) + .detach(); + + let mut async_cx = cx.to_async(); + cx.foreground_executor() + .spawn(async move { + while deactivation_receiver.recv().await.is_ok() { + handle + .update(&mut async_cx, |_, window, _| window.refresh()) + .log_err(); + } + }) + .detach(); + + let mut async_cx = cx.to_async(); + cx.foreground_executor() + .spawn(async move { + while let Ok(request) = action_receiver.recv().await { + handle + .update(&mut async_cx, |_, window, cx| { + window.handle_a11y_action(request, cx); + }) + .log_err(); + } + }) + .detach(); + } + + platform_window.on_close(Box::new({ + let window_id = handle.window_id(); + let mut cx = cx.to_async(); + move || { + let _ = handle.update(&mut cx, |_, window, _| window.remove_window()); + let _ = cx.update(|cx| { + SystemWindowTabController::remove_tab(cx, window_id); + }); + } + })); + platform_window.on_request_frame(Box::new({ + let mut cx = cx.to_async(); + let invalidator = invalidator.clone(); + let active = active.clone(); + let needs_present = needs_present.clone(); + let next_frame_callbacks = next_frame_callbacks.clone(); + let input_rate_tracker = input_rate_tracker.clone(); + let mut deferred_force_render = false; + move |request_frame_options| { + #[cfg(feature = "profiler")] + let (_foreground_turn, window_id) = { + let foreground_turn = profiler::journal::foreground_turn(); + let window_id = handle.window_id(); + profiler::journal::record_platform_signal(profiler::journal::PlatformSignal { + window_id, + signal_at: request_frame_options.signal_at, + handled_at: Instant::now(), + source: request_frame_options.signal_source, + }); + (foreground_turn, window_id) + }; + // This must be checked before accessing App: if this request + // arrived re-entrantly while a draw is on this thread's stack + // (e.g. via a nested message pump in the Windows window + // procedure), drawing would nest draws, and even touching the + // App would panic on its already-mutable borrow. Skip instead; + // the platform leaves the window invalidated (or re-invalidates + // it), so a fresh request arrives once the in-progress draw + // unwinds. Remember force_render so the deferred frame still + // bypasses the view cache. + // + // Returning here skips `complete_frame`, which on Wayland would + // stall the window's frame callbacks (no `surface.commit()`) — + // but calling it would hit the App borrow panic above, and this + // branch is unreachable there in practice: only Windows pumps + // platform events (and thus requests frames) mid-draw. + if draw_in_progress() { + log::debug!("deferring re-entrant window draw request"); + deferred_force_render |= request_frame_options.force_render; + #[cfg(feature = "profiler")] + profiler::journal::record_reentrant_frame_skipped(window_id, Instant::now()); + return; + } + // Take the deferred flag first: `||` short-circuits, and leaving + // the flag set when this request already forces a render would + // force a second, redundant render on the next frame. + let force_render = + mem::take(&mut deferred_force_render) || request_frame_options.force_render; + + let thermal_state = handle + .update(&mut cx, |_, _, cx| cx.thermal_state()) + .log_err(); + + // Throttle frame rate based on conditions: + // - Thermal pressure (Serious/Critical): cap to ~60fps + // - Inactive window (not focused): cap to ~30fps to save energy + let min_frame_interval = if request_frame_options.require_presentation + || (!request_frame_options.force_render + && next_frame_callbacks.borrow().is_empty()) + { + None + } else if !active.get() && !input_rate_tracker.borrow_mut().is_high_rate() { + inactive_frame_interval.map(|interval| (interval, FrameRateLimit::Inactive)) + } else if let Some(ThermalState::Critical | ThermalState::Serious) = thermal_state { + Some((Duration::from_micros(16667), FrameRateLimit::Thermal)) + } else { + None + }; + + let now = Instant::now(); + #[cfg_attr(not(feature = "profiler"), expect(unused_variables))] + if let Some((min_interval, limit)) = min_frame_interval { + if let Some(last_frame) = last_frame_time.get() + && now.duration_since(last_frame) < min_interval + { + // Don't lose a pending forced render to throttling. + deferred_force_render |= force_render; + // Deferred by throttling: ask demand-driven platforms to retry. + handle + .update(&mut cx, |_, window, _| { + window.platform_window.schedule_frame(); + }) + .log_err(); + // The demand that entered this branch (a deferred forced + // render or pending next-frame callbacks) is still + // unserved; platforms that stop requesting frames for + // idle windows need a wakeup to deliver the retry. + invalidator.wake_platform(); + #[cfg(feature = "profiler")] + profiler::journal::record_frame_skipped( + window_id, + Instant::now(), + match limit { + FrameRateLimit::Inactive => { + profiler::journal::FrameSkipReason::InactiveFrameRateLimit + } + FrameRateLimit::Thermal => { + profiler::journal::FrameSkipReason::ThermalFrameRateLimit + } + }, + ); + return; + } + } + last_frame_time.set(Some(now)); + + let pending_next_frame_callbacks = next_frame_callbacks.take(); + if !pending_next_frame_callbacks.is_empty() { + handle + .update(&mut cx, |_, window, cx| { + for callback in pending_next_frame_callbacks { + callback(window, cx); + } + }) + .log_err(); + } + + // Keep presenting if input was recently arriving at a high rate (>= 60fps). + // Once high-rate input is detected, we sustain presentation for 1 second + // to prevent display underclocking during active input. + let needs_present = request_frame_options.require_presentation + || needs_present.get() + || input_rate_tracker.borrow_mut().is_high_rate(); + + let should_draw = invalidator.is_dirty() || force_render; + if should_draw { + measure("frame duration", || { + handle + .update(&mut cx, |_, window, cx| { + if force_render { + // Bypass cached view reuse so we don't replay stale + // atlas tile references after a GPU device recovery. + window.refresh(); + } + let arena_clear_needed = window.draw(cx); + window.present(); + arena_clear_needed.clear(cx); + }) + .log_err(); + }) + } else if needs_present { + handle + .update(&mut cx, |_, window, _| window.present()) + .log_err(); + } + + handle + .update(&mut cx, |_, window, _| { + if window.invalidator.is_dirty() + || !window.next_frame_callbacks.borrow().is_empty() + { + window.platform_window.schedule_frame(); + } + }) + .log_err(); + + // Platforms that stop requesting frames for idle windows only + // deliver another request after a wakeup. If demand remains + // after this frame (the window was re-invalidated mid-draw, or + // animations scheduled next-frame callbacks), re-arm the frame + // source explicitly. + if invalidator.is_dirty() || !next_frame_callbacks.borrow().is_empty() { + invalidator.wake_platform(); + } + #[cfg(feature = "profiler")] + if !should_draw { + profiler::journal::record_frame_skipped( + window_id, + Instant::now(), + profiler::journal::FrameSkipReason::NoRenderNeeded, + ); + } + } + })); + invalidator.set_platform_waker(platform_window.frame_waker()); + platform_window.on_visual_viewport_changed(Box::new({ + let mut cx = cx.to_async(); + move || { + handle + .update(&mut cx, |_, window, _| window.refresh()) + .log_err(); + } + })); + platform_window.on_insets_changed(Box::new({ + let mut cx = cx.to_async(); + move |_| { + handle + .update(&mut cx, |_, window, _| window.refresh()) + .log_err(); + } + })); + platform_window.on_resize(Box::new({ + let mut cx = cx.to_async(); + move |_, _| { + handle + .update(&mut cx, |_, window, cx| window.bounds_changed(cx)) + .log_err(); + } + })); + platform_window.on_moved(Box::new({ + let mut cx = cx.to_async(); + move || { + handle + .update(&mut cx, |_, window, cx| window.bounds_changed(cx)) + .log_err(); + } + })); + platform_window.on_appearance_changed(Box::new({ + let cx = cx.to_async(); + let foreground_executor = cx.foreground_executor().clone(); + move || { + let mut cx = cx.clone(); + // Defer the update because changing the AppKit appearance may + // synchronously invoke this callback while App is already borrowed. + foreground_executor + .spawn(async move { + handle + .update(&mut cx, |_, window, cx| window.appearance_changed(cx)) + .log_err(); + }) + .detach(); + } + })); + platform_window.on_button_layout_changed(Box::new({ + let mut cx = cx.to_async(); + move || { + handle + .update(&mut cx, |_, window, cx| window.button_layout_changed(cx)) + .log_err(); + } + })); + platform_window.on_active_status_change(Box::new({ + let mut cx = cx.to_async(); + move |active| { + handle + .update(&mut cx, |_, window, cx| { + window.active.set(active); + window.modifiers = window.platform_window.modifiers(); + window.capslock = window.platform_window.capslock(); + window + .activation_observers + .clone() + .retain(&(), |callback| callback(window, cx)); + + window.bounds_changed(cx); + window.refresh(); + + SystemWindowTabController::update_last_active(cx, window.handle.id); + }) + .log_err(); + } + })); + platform_window.on_visibility_change(Box::new({ + let mut cx = cx.to_async(); + move |_| { + handle + .update(&mut cx, |_, window, cx| { + window.refresh_visibility(cx); + }) + .log_err(); + } + })); + platform_window.on_hover_status_change(Box::new({ + let mut cx = cx.to_async(); + move |active| { + handle + .update(&mut cx, |_, window, _| { + window.hovered.set(active); + window.refresh(); + }) + .log_err(); + } + })); + platform_window.on_input({ + let mut cx = cx.to_async(); + Box::new(move |event| { + handle + .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx)) + .log_err() + .unwrap_or(DispatchEventResult::default()) + }) + }); + platform_window.on_hit_test_window_control({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, window, _cx| { + for (area, hitbox) in &window.rendered_frame.window_control_hitboxes { + if window.mouse_hit_test.ids.contains(&hitbox.id) { + return Some(*area); + } + } + None + }) + .log_err() + .unwrap_or(None) + }) + }); + platform_window.on_move_tab_to_new_window({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, _window, cx| { + SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id()); + }) + .log_err(); + }) + }); + platform_window.on_merge_all_windows({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, _window, cx| { + SystemWindowTabController::merge_all_windows(cx, handle.window_id()); + }) + .log_err(); + }) + }); + platform_window.on_select_next_tab({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, _window, cx| { + SystemWindowTabController::select_next_tab(cx, handle.window_id()); + }) + .log_err(); + }) + }); + platform_window.on_select_previous_tab({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, _window, cx| { + SystemWindowTabController::select_previous_tab(cx, handle.window_id()) + }) + .log_err(); + }) + }); + platform_window.on_toggle_tab_bar({ + let mut cx = cx.to_async(); + Box::new(move || { + handle + .update(&mut cx, |_, window, cx| { + let tab_bar_visible = window.platform_window.tab_bar_visible(); + SystemWindowTabController::set_visible(cx, tab_bar_visible); + }) + .log_err(); + }) + }); + + if let Some(app_id) = app_id { + platform_window.set_app_id(&app_id); + } + + platform_window.map_window().unwrap(); + + Ok(Window { + handle, + invalidator, + removed: false, + platform_window, + display_id, + is_resizable, + is_minimizable, + sprite_atlas, + text_system, + text_rendering_mode: cx.text_rendering_mode.clone(), + rem_size: px(16.), + rem_size_override_stack: SmallVec::new(), + viewport_size: content_size, + layout_engine: Some(TaffyLayoutEngine::new()), + root: None, + element_id_stack: SmallVec::default(), + text_style_stack: Vec::new(), + rendered_entity_stack: Vec::new(), + element_offset_stack: Vec::new(), + content_mask_stack: Vec::new(), + element_opacity: 1.0, + requested_autoscroll: None, + last_text_input_configuration: None, + focused_text_input_active: false, + rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), + next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), + next_frame_callbacks, + next_hitbox_id: HitboxId(0), + next_tooltip_id: TooltipId::default(), + tooltip_bounds: None, + dirty_views: FxHashSet::default(), + focus_listeners: SubscriberSet::new(), + focus_lost_listeners: SubscriberSet::new(), + focus_lost_path: SmallVec::new(), + default_prevented: true, + mouse_position, + mouse_hit_test: HitTest::default(), + modifiers, + capslock, + scale_factor, + bounds_observers: SubscriberSet::new(), + appearance, + appearance_observers: SubscriberSet::new(), + button_layout_observers: SubscriberSet::new(), + active, + visibility, + visibility_observers: SubscriberSet::new(), + hovered, + needs_present, + input_rate_tracker, + #[cfg(feature = "profiler")] + window_profiler: profiler::WindowProfiler::new(handle.window_id())?, + last_input_modality: InputModality::Mouse, + touch_gestures: TouchGestureRecognizer::new( + cx.platform + .gestures() + .map_or_else(GestureTuning::default, |gestures| gestures.tuning()), + ), + touch_prediction_enabled: true, + long_press_timer: None, + long_press_capture: None, + refreshing: false, + activation_observers: SubscriberSet::new(), + focus: None, + focus_enabled: true, + focus_generation: 0, + pending_input: None, + pending_modifier: ModifierState::default(), + pending_input_observers: SubscriberSet::new(), + prompt: None, + client_inset: None, + image_cache_stack: Vec::new(), + captured_hitbox: None, + #[cfg(any(feature = "inspector", debug_assertions))] + inspector: None, + #[cfg(feature = "profiler")] + debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay::new(), + a11y: A11y::new( + a11y_active_flag, + accessibility_force_disabled, + initial_window_title, + ), + }) + } + + pub(crate) fn new_focus_listener( + &self, + value: AnyWindowFocusListener, + ) -> (Subscription, impl FnOnce() + use<>) { + self.focus_listeners.insert((), value) + } +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[expect(missing_docs)] +pub struct DispatchEventResult { + pub propagate: bool, + pub default_prevented: bool, +} + +/// Indicates which region of the window is visible. Content falling outside of this mask will not be +/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type +/// to leave room to support more complex shapes in the future. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +#[repr(C)] +pub struct ContentMask { + /// The bounds + pub bounds: Bounds

    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 literal 0 HcmV?d00001 diff --git a/vendor/ely/assets/fonts/JetBrainsMono-Regular.ttf b/vendor/ely/assets/fonts/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dff66cc50702c75abd025dcf49f62a4dcc2d72de GIT binary patch literal 273900 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 z

    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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/vendor/ely/assets/icons/LICENSE b/vendor/ely/assets/icons/LICENSE new file mode 100644 index 00000000..718bb3f0 --- /dev/null +++ b/vendor/ely/assets/icons/LICENSE @@ -0,0 +1,43 @@ +ISC License + +Copyright (c) 2026 Lucide Icons and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--- + +The following Lucide icons are derived from the Feather project: + +airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out + +The MIT License (MIT) (for the icons listed above) + +Copyright (c) 2013-present Cole Bemis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/ely/assets/icons/a-arrow-down.svg b/vendor/ely/assets/icons/a-arrow-down.svg new file mode 100644 index 00000000..dbbfb1f1 --- /dev/null +++ b/vendor/ely/assets/icons/a-arrow-down.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/a-arrow-up.svg b/vendor/ely/assets/icons/a-arrow-up.svg new file mode 100644 index 00000000..450de2f0 --- /dev/null +++ b/vendor/ely/assets/icons/a-arrow-up.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/accessibility.svg b/vendor/ely/assets/icons/accessibility.svg new file mode 100644 index 00000000..397b14c1 --- /dev/null +++ b/vendor/ely/assets/icons/accessibility.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/activity.svg b/vendor/ely/assets/icons/activity.svg new file mode 100644 index 00000000..40c92a8d --- /dev/null +++ b/vendor/ely/assets/icons/activity.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/alarm-clock.svg b/vendor/ely/assets/icons/alarm-clock.svg new file mode 100644 index 00000000..cc2e8c71 --- /dev/null +++ b/vendor/ely/assets/icons/alarm-clock.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/align-center-horizontal.svg b/vendor/ely/assets/icons/align-center-horizontal.svg new file mode 100644 index 00000000..91af229f --- /dev/null +++ b/vendor/ely/assets/icons/align-center-horizontal.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/align-center-vertical.svg b/vendor/ely/assets/icons/align-center-vertical.svg new file mode 100644 index 00000000..5363c767 --- /dev/null +++ b/vendor/ely/assets/icons/align-center-vertical.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/align-center.svg b/vendor/ely/assets/icons/align-center.svg new file mode 100644 index 00000000..0e10220e --- /dev/null +++ b/vendor/ely/assets/icons/align-center.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-end-horizontal.svg b/vendor/ely/assets/icons/align-end-horizontal.svg new file mode 100644 index 00000000..c41e712b --- /dev/null +++ b/vendor/ely/assets/icons/align-end-horizontal.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-end-vertical.svg b/vendor/ely/assets/icons/align-end-vertical.svg new file mode 100644 index 00000000..e0496713 --- /dev/null +++ b/vendor/ely/assets/icons/align-end-vertical.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-horizontal-distribute-center.svg b/vendor/ely/assets/icons/align-horizontal-distribute-center.svg new file mode 100644 index 00000000..7fb870d3 --- /dev/null +++ b/vendor/ely/assets/icons/align-horizontal-distribute-center.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/align-justify.svg b/vendor/ely/assets/icons/align-justify.svg new file mode 100644 index 00000000..ed9caa39 --- /dev/null +++ b/vendor/ely/assets/icons/align-justify.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-left.svg b/vendor/ely/assets/icons/align-left.svg new file mode 100644 index 00000000..a1eae4d3 --- /dev/null +++ b/vendor/ely/assets/icons/align-left.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-right.svg b/vendor/ely/assets/icons/align-right.svg new file mode 100644 index 00000000..4f3b86a1 --- /dev/null +++ b/vendor/ely/assets/icons/align-right.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-start-horizontal.svg b/vendor/ely/assets/icons/align-start-horizontal.svg new file mode 100644 index 00000000..28466733 --- /dev/null +++ b/vendor/ely/assets/icons/align-start-horizontal.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-start-vertical.svg b/vendor/ely/assets/icons/align-start-vertical.svg new file mode 100644 index 00000000..040b3380 --- /dev/null +++ b/vendor/ely/assets/icons/align-start-vertical.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/align-vertical-distribute-center.svg b/vendor/ely/assets/icons/align-vertical-distribute-center.svg new file mode 100644 index 00000000..a646479e --- /dev/null +++ b/vendor/ely/assets/icons/align-vertical-distribute-center.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/app-window.svg b/vendor/ely/assets/icons/app-window.svg new file mode 100644 index 00000000..b28c6000 --- /dev/null +++ b/vendor/ely/assets/icons/app-window.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/archive.svg b/vendor/ely/assets/icons/archive.svg new file mode 100644 index 00000000..3d6608e5 --- /dev/null +++ b/vendor/ely/assets/icons/archive.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/arrow-down-left.svg b/vendor/ely/assets/icons/arrow-down-left.svg new file mode 100644 index 00000000..8a321bb2 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down-left.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/arrow-down-to-dot.svg b/vendor/ely/assets/icons/arrow-down-to-dot.svg new file mode 100644 index 00000000..9c900cf7 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down-to-dot.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/arrow-down-to-line.svg b/vendor/ely/assets/icons/arrow-down-to-line.svg new file mode 100644 index 00000000..d08fa738 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down-to-line.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/arrow-down-up.svg b/vendor/ely/assets/icons/arrow-down-up.svg new file mode 100644 index 00000000..9403e3e5 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down-up.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/arrow-down-wide-narrow.svg b/vendor/ely/assets/icons/arrow-down-wide-narrow.svg new file mode 100644 index 00000000..17eda4eb --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down-wide-narrow.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/arrow-down.svg b/vendor/ely/assets/icons/arrow-down.svg new file mode 100644 index 00000000..5445d76b --- /dev/null +++ b/vendor/ely/assets/icons/arrow-down.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/arrow-left.svg b/vendor/ely/assets/icons/arrow-left.svg new file mode 100644 index 00000000..6e2984d1 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-left.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/arrow-right.svg b/vendor/ely/assets/icons/arrow-right.svg new file mode 100644 index 00000000..55e55646 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/arrow-up-from-dot.svg b/vendor/ely/assets/icons/arrow-up-from-dot.svg new file mode 100644 index 00000000..1c34a4ce --- /dev/null +++ b/vendor/ely/assets/icons/arrow-up-from-dot.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/arrow-up-narrow-wide.svg b/vendor/ely/assets/icons/arrow-up-narrow-wide.svg new file mode 100644 index 00000000..5c741588 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-up-narrow-wide.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/arrow-up-right.svg b/vendor/ely/assets/icons/arrow-up-right.svg new file mode 100644 index 00000000..a0b9c298 --- /dev/null +++ b/vendor/ely/assets/icons/arrow-up-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/arrow-up.svg b/vendor/ely/assets/icons/arrow-up.svg new file mode 100644 index 00000000..82e0740d --- /dev/null +++ b/vendor/ely/assets/icons/arrow-up.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/at-sign.svg b/vendor/ely/assets/icons/at-sign.svg new file mode 100644 index 00000000..76bda430 --- /dev/null +++ b/vendor/ely/assets/icons/at-sign.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/audio-lines.svg b/vendor/ely/assets/icons/audio-lines.svg new file mode 100644 index 00000000..4188d22a --- /dev/null +++ b/vendor/ely/assets/icons/audio-lines.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/ban.svg b/vendor/ely/assets/icons/ban.svg new file mode 100644 index 00000000..08cbfa96 --- /dev/null +++ b/vendor/ely/assets/icons/ban.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/battery.svg b/vendor/ely/assets/icons/battery.svg new file mode 100644 index 00000000..c97d2609 --- /dev/null +++ b/vendor/ely/assets/icons/battery.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/bell.svg b/vendor/ely/assets/icons/bell.svg new file mode 100644 index 00000000..a58ca127 --- /dev/null +++ b/vendor/ely/assets/icons/bell.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/bold.svg b/vendor/ely/assets/icons/bold.svg new file mode 100644 index 00000000..45042cf2 --- /dev/null +++ b/vendor/ely/assets/icons/bold.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/book-open.svg b/vendor/ely/assets/icons/book-open.svg new file mode 100644 index 00000000..06fcc64b --- /dev/null +++ b/vendor/ely/assets/icons/book-open.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/bookmark.svg b/vendor/ely/assets/icons/bookmark.svg new file mode 100644 index 00000000..3ecf52e4 --- /dev/null +++ b/vendor/ely/assets/icons/bookmark.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/bot.svg b/vendor/ely/assets/icons/bot.svg new file mode 100644 index 00000000..39826271 --- /dev/null +++ b/vendor/ely/assets/icons/bot.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/box.svg b/vendor/ely/assets/icons/box.svg new file mode 100644 index 00000000..1f739899 --- /dev/null +++ b/vendor/ely/assets/icons/box.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/braces.svg b/vendor/ely/assets/icons/braces.svg new file mode 100644 index 00000000..8ce78705 --- /dev/null +++ b/vendor/ely/assets/icons/braces.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/brush.svg b/vendor/ely/assets/icons/brush.svg new file mode 100644 index 00000000..ba9b72a8 --- /dev/null +++ b/vendor/ely/assets/icons/brush.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/bug.svg b/vendor/ely/assets/icons/bug.svg new file mode 100644 index 00000000..734c9045 --- /dev/null +++ b/vendor/ely/assets/icons/bug.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/calendar-days.svg b/vendor/ely/assets/icons/calendar-days.svg new file mode 100644 index 00000000..ce7fb8ea --- /dev/null +++ b/vendor/ely/assets/icons/calendar-days.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/calendar-range.svg b/vendor/ely/assets/icons/calendar-range.svg new file mode 100644 index 00000000..be432565 --- /dev/null +++ b/vendor/ely/assets/icons/calendar-range.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/calendar.svg b/vendor/ely/assets/icons/calendar.svg new file mode 100644 index 00000000..11d94b95 --- /dev/null +++ b/vendor/ely/assets/icons/calendar.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/camera.svg b/vendor/ely/assets/icons/camera.svg new file mode 100644 index 00000000..1f6df0d4 --- /dev/null +++ b/vendor/ely/assets/icons/camera.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/captions-off.svg b/vendor/ely/assets/icons/captions-off.svg new file mode 100644 index 00000000..8d72e112 --- /dev/null +++ b/vendor/ely/assets/icons/captions-off.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/captions.svg b/vendor/ely/assets/icons/captions.svg new file mode 100644 index 00000000..90d00f9c --- /dev/null +++ b/vendor/ely/assets/icons/captions.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/case-sensitive.svg b/vendor/ely/assets/icons/case-sensitive.svg new file mode 100644 index 00000000..981c2c1a --- /dev/null +++ b/vendor/ely/assets/icons/case-sensitive.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/chart-area.svg b/vendor/ely/assets/icons/chart-area.svg new file mode 100644 index 00000000..c06957ca --- /dev/null +++ b/vendor/ely/assets/icons/chart-area.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/chart-bar.svg b/vendor/ely/assets/icons/chart-bar.svg new file mode 100644 index 00000000..620e3a82 --- /dev/null +++ b/vendor/ely/assets/icons/chart-bar.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/chart-candlestick.svg b/vendor/ely/assets/icons/chart-candlestick.svg new file mode 100644 index 00000000..60dfc88f --- /dev/null +++ b/vendor/ely/assets/icons/chart-candlestick.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/vendor/ely/assets/icons/chart-column.svg b/vendor/ely/assets/icons/chart-column.svg new file mode 100644 index 00000000..fdf27dde --- /dev/null +++ b/vendor/ely/assets/icons/chart-column.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/chart-gantt.svg b/vendor/ely/assets/icons/chart-gantt.svg new file mode 100644 index 00000000..1b0dd640 --- /dev/null +++ b/vendor/ely/assets/icons/chart-gantt.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/chart-line.svg b/vendor/ely/assets/icons/chart-line.svg new file mode 100644 index 00000000..ef0b6021 --- /dev/null +++ b/vendor/ely/assets/icons/chart-line.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/chart-pie.svg b/vendor/ely/assets/icons/chart-pie.svg new file mode 100644 index 00000000..0bb5b123 --- /dev/null +++ b/vendor/ely/assets/icons/chart-pie.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/check-check.svg b/vendor/ely/assets/icons/check-check.svg new file mode 100644 index 00000000..68c96cc7 --- /dev/null +++ b/vendor/ely/assets/icons/check-check.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/check.svg b/vendor/ely/assets/icons/check.svg new file mode 100644 index 00000000..9c50c69e --- /dev/null +++ b/vendor/ely/assets/icons/check.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/chevron-down.svg b/vendor/ely/assets/icons/chevron-down.svg new file mode 100644 index 00000000..a5f35453 --- /dev/null +++ b/vendor/ely/assets/icons/chevron-down.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/chevron-left.svg b/vendor/ely/assets/icons/chevron-left.svg new file mode 100644 index 00000000..f7d5355d --- /dev/null +++ b/vendor/ely/assets/icons/chevron-left.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/chevron-right.svg b/vendor/ely/assets/icons/chevron-right.svg new file mode 100644 index 00000000..fcc78d5f --- /dev/null +++ b/vendor/ely/assets/icons/chevron-right.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/chevron-up.svg b/vendor/ely/assets/icons/chevron-up.svg new file mode 100644 index 00000000..3f66b33b --- /dev/null +++ b/vendor/ely/assets/icons/chevron-up.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/chevrons-left-right.svg b/vendor/ely/assets/icons/chevrons-left-right.svg new file mode 100644 index 00000000..2025a3b3 --- /dev/null +++ b/vendor/ely/assets/icons/chevrons-left-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/chevrons-left.svg b/vendor/ely/assets/icons/chevrons-left.svg new file mode 100644 index 00000000..369b6430 --- /dev/null +++ b/vendor/ely/assets/icons/chevrons-left.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/chevrons-right.svg b/vendor/ely/assets/icons/chevrons-right.svg new file mode 100644 index 00000000..588a390f --- /dev/null +++ b/vendor/ely/assets/icons/chevrons-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/chevrons-up-down.svg b/vendor/ely/assets/icons/chevrons-up-down.svg new file mode 100644 index 00000000..25784268 --- /dev/null +++ b/vendor/ely/assets/icons/chevrons-up-down.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/circle-alert.svg b/vendor/ely/assets/icons/circle-alert.svg new file mode 100644 index 00000000..3f59b642 --- /dev/null +++ b/vendor/ely/assets/icons/circle-alert.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/circle-check.svg b/vendor/ely/assets/icons/circle-check.svg new file mode 100644 index 00000000..94eaf2b6 --- /dev/null +++ b/vendor/ely/assets/icons/circle-check.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/circle-dashed.svg b/vendor/ely/assets/icons/circle-dashed.svg new file mode 100644 index 00000000..177376dc --- /dev/null +++ b/vendor/ely/assets/icons/circle-dashed.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/circle-dot-dashed.svg b/vendor/ely/assets/icons/circle-dot-dashed.svg new file mode 100644 index 00000000..85ae29a2 --- /dev/null +++ b/vendor/ely/assets/icons/circle-dot-dashed.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/circle-dot.svg b/vendor/ely/assets/icons/circle-dot.svg new file mode 100644 index 00000000..574a826a --- /dev/null +++ b/vendor/ely/assets/icons/circle-dot.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/circle-help.svg b/vendor/ely/assets/icons/circle-help.svg new file mode 100644 index 00000000..23e854ae --- /dev/null +++ b/vendor/ely/assets/icons/circle-help.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/circle-pause.svg b/vendor/ely/assets/icons/circle-pause.svg new file mode 100644 index 00000000..d28faa06 --- /dev/null +++ b/vendor/ely/assets/icons/circle-pause.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/circle-stop.svg b/vendor/ely/assets/icons/circle-stop.svg new file mode 100644 index 00000000..01330981 --- /dev/null +++ b/vendor/ely/assets/icons/circle-stop.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/circle-x.svg b/vendor/ely/assets/icons/circle-x.svg new file mode 100644 index 00000000..8544386a --- /dev/null +++ b/vendor/ely/assets/icons/circle-x.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/circle.svg b/vendor/ely/assets/icons/circle.svg new file mode 100644 index 00000000..c2ac8895 --- /dev/null +++ b/vendor/ely/assets/icons/circle.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/clipboard-check.svg b/vendor/ely/assets/icons/clipboard-check.svg new file mode 100644 index 00000000..b75133c3 --- /dev/null +++ b/vendor/ely/assets/icons/clipboard-check.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/clipboard.svg b/vendor/ely/assets/icons/clipboard.svg new file mode 100644 index 00000000..c2d3e6e8 --- /dev/null +++ b/vendor/ely/assets/icons/clipboard.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/clock.svg b/vendor/ely/assets/icons/clock.svg new file mode 100644 index 00000000..8d583d95 --- /dev/null +++ b/vendor/ely/assets/icons/clock.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/cloud-alert.svg b/vendor/ely/assets/icons/cloud-alert.svg new file mode 100644 index 00000000..189592a5 --- /dev/null +++ b/vendor/ely/assets/icons/cloud-alert.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/cloud-check.svg b/vendor/ely/assets/icons/cloud-check.svg new file mode 100644 index 00000000..0f7945ec --- /dev/null +++ b/vendor/ely/assets/icons/cloud-check.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/cloud-off.svg b/vendor/ely/assets/icons/cloud-off.svg new file mode 100644 index 00000000..d003f895 --- /dev/null +++ b/vendor/ely/assets/icons/cloud-off.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/cloud-upload.svg b/vendor/ely/assets/icons/cloud-upload.svg new file mode 100644 index 00000000..8eb8a3a7 --- /dev/null +++ b/vendor/ely/assets/icons/cloud-upload.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/cloud.svg b/vendor/ely/assets/icons/cloud.svg new file mode 100644 index 00000000..356bf997 --- /dev/null +++ b/vendor/ely/assets/icons/cloud.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/code.svg b/vendor/ely/assets/icons/code.svg new file mode 100644 index 00000000..2b7e4ffc --- /dev/null +++ b/vendor/ely/assets/icons/code.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/columns-2.svg b/vendor/ely/assets/icons/columns-2.svg new file mode 100644 index 00000000..658ac751 --- /dev/null +++ b/vendor/ely/assets/icons/columns-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/columns-3.svg b/vendor/ely/assets/icons/columns-3.svg new file mode 100644 index 00000000..45cd5870 --- /dev/null +++ b/vendor/ely/assets/icons/columns-3.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/command.svg b/vendor/ely/assets/icons/command.svg new file mode 100644 index 00000000..4c999aa3 --- /dev/null +++ b/vendor/ely/assets/icons/command.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/compass.svg b/vendor/ely/assets/icons/compass.svg new file mode 100644 index 00000000..7b4a86a4 --- /dev/null +++ b/vendor/ely/assets/icons/compass.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/contrast.svg b/vendor/ely/assets/icons/contrast.svg new file mode 100644 index 00000000..f7b93d55 --- /dev/null +++ b/vendor/ely/assets/icons/contrast.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/copy.svg b/vendor/ely/assets/icons/copy.svg new file mode 100644 index 00000000..4aa1bd22 --- /dev/null +++ b/vendor/ely/assets/icons/copy.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/corner-down-right.svg b/vendor/ely/assets/icons/corner-down-right.svg new file mode 100644 index 00000000..3fdd007c --- /dev/null +++ b/vendor/ely/assets/icons/corner-down-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/cpu.svg b/vendor/ely/assets/icons/cpu.svg new file mode 100644 index 00000000..ce585fad --- /dev/null +++ b/vendor/ely/assets/icons/cpu.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/credit-card.svg b/vendor/ely/assets/icons/credit-card.svg new file mode 100644 index 00000000..a57bba54 --- /dev/null +++ b/vendor/ely/assets/icons/credit-card.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/crop.svg b/vendor/ely/assets/icons/crop.svg new file mode 100644 index 00000000..39e18e5f --- /dev/null +++ b/vendor/ely/assets/icons/crop.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/crosshair.svg b/vendor/ely/assets/icons/crosshair.svg new file mode 100644 index 00000000..c2728387 --- /dev/null +++ b/vendor/ely/assets/icons/crosshair.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/database.svg b/vendor/ely/assets/icons/database.svg new file mode 100644 index 00000000..61c65a21 --- /dev/null +++ b/vendor/ely/assets/icons/database.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/delete.svg b/vendor/ely/assets/icons/delete.svg new file mode 100644 index 00000000..02187284 --- /dev/null +++ b/vendor/ely/assets/icons/delete.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/dices.svg b/vendor/ely/assets/icons/dices.svg new file mode 100644 index 00000000..1da7d19c --- /dev/null +++ b/vendor/ely/assets/icons/dices.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/dollar-sign.svg b/vendor/ely/assets/icons/dollar-sign.svg new file mode 100644 index 00000000..fbad50f5 --- /dev/null +++ b/vendor/ely/assets/icons/dollar-sign.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/dot.svg b/vendor/ely/assets/icons/dot.svg new file mode 100644 index 00000000..963f7896 --- /dev/null +++ b/vendor/ely/assets/icons/dot.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/download.svg b/vendor/ely/assets/icons/download.svg new file mode 100644 index 00000000..0db23894 --- /dev/null +++ b/vendor/ely/assets/icons/download.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/ellipsis-vertical.svg b/vendor/ely/assets/icons/ellipsis-vertical.svg new file mode 100644 index 00000000..2a7bafe1 --- /dev/null +++ b/vendor/ely/assets/icons/ellipsis-vertical.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/ellipsis.svg b/vendor/ely/assets/icons/ellipsis.svg new file mode 100644 index 00000000..6b61d7f1 --- /dev/null +++ b/vendor/ely/assets/icons/ellipsis.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/eraser.svg b/vendor/ely/assets/icons/eraser.svg new file mode 100644 index 00000000..3310a089 --- /dev/null +++ b/vendor/ely/assets/icons/eraser.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/external-link.svg b/vendor/ely/assets/icons/external-link.svg new file mode 100644 index 00000000..78af062c --- /dev/null +++ b/vendor/ely/assets/icons/external-link.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/eye-off.svg b/vendor/ely/assets/icons/eye-off.svg new file mode 100644 index 00000000..faa83a8c --- /dev/null +++ b/vendor/ely/assets/icons/eye-off.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/eye.svg b/vendor/ely/assets/icons/eye.svg new file mode 100644 index 00000000..4d16d9d2 --- /dev/null +++ b/vendor/ely/assets/icons/eye.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/file-archive.svg b/vendor/ely/assets/icons/file-archive.svg new file mode 100644 index 00000000..06f0b3f7 --- /dev/null +++ b/vendor/ely/assets/icons/file-archive.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/file-audio.svg b/vendor/ely/assets/icons/file-audio.svg new file mode 100644 index 00000000..81083d71 --- /dev/null +++ b/vendor/ely/assets/icons/file-audio.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/file-code.svg b/vendor/ely/assets/icons/file-code.svg new file mode 100644 index 00000000..d9788f3d --- /dev/null +++ b/vendor/ely/assets/icons/file-code.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file-cog.svg b/vendor/ely/assets/icons/file-cog.svg new file mode 100644 index 00000000..16ce1c89 --- /dev/null +++ b/vendor/ely/assets/icons/file-cog.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/file-image.svg b/vendor/ely/assets/icons/file-image.svg new file mode 100644 index 00000000..ec87e2b8 --- /dev/null +++ b/vendor/ely/assets/icons/file-image.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file-json.svg b/vendor/ely/assets/icons/file-json.svg new file mode 100644 index 00000000..5e4df554 --- /dev/null +++ b/vendor/ely/assets/icons/file-json.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file-plus.svg b/vendor/ely/assets/icons/file-plus.svg new file mode 100644 index 00000000..4ba74680 --- /dev/null +++ b/vendor/ely/assets/icons/file-plus.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file-spreadsheet.svg b/vendor/ely/assets/icons/file-spreadsheet.svg new file mode 100644 index 00000000..4b35eeae --- /dev/null +++ b/vendor/ely/assets/icons/file-spreadsheet.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/file-terminal.svg b/vendor/ely/assets/icons/file-terminal.svg new file mode 100644 index 00000000..6ae8e6a3 --- /dev/null +++ b/vendor/ely/assets/icons/file-terminal.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file-text.svg b/vendor/ely/assets/icons/file-text.svg new file mode 100644 index 00000000..e3efa62d --- /dev/null +++ b/vendor/ely/assets/icons/file-text.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/file-type.svg b/vendor/ely/assets/icons/file-type.svg new file mode 100644 index 00000000..3e84b1c5 --- /dev/null +++ b/vendor/ely/assets/icons/file-type.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/file-video-camera.svg b/vendor/ely/assets/icons/file-video-camera.svg new file mode 100644 index 00000000..fecffa65 --- /dev/null +++ b/vendor/ely/assets/icons/file-video-camera.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/file.svg b/vendor/ely/assets/icons/file.svg new file mode 100644 index 00000000..5d91e41b --- /dev/null +++ b/vendor/ely/assets/icons/file.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/filter.svg b/vendor/ely/assets/icons/filter.svg new file mode 100644 index 00000000..07ec25ca --- /dev/null +++ b/vendor/ely/assets/icons/filter.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/fingerprint.svg b/vendor/ely/assets/icons/fingerprint.svg new file mode 100644 index 00000000..47959b53 --- /dev/null +++ b/vendor/ely/assets/icons/fingerprint.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/flag.svg b/vendor/ely/assets/icons/flag.svg new file mode 100644 index 00000000..09b415cc --- /dev/null +++ b/vendor/ely/assets/icons/flag.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/folder-open.svg b/vendor/ely/assets/icons/folder-open.svg new file mode 100644 index 00000000..b4543027 --- /dev/null +++ b/vendor/ely/assets/icons/folder-open.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/folder-plus.svg b/vendor/ely/assets/icons/folder-plus.svg new file mode 100644 index 00000000..a28ff621 --- /dev/null +++ b/vendor/ely/assets/icons/folder-plus.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/folder.svg b/vendor/ely/assets/icons/folder.svg new file mode 100644 index 00000000..3ac458d5 --- /dev/null +++ b/vendor/ely/assets/icons/folder.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/forward.svg b/vendor/ely/assets/icons/forward.svg new file mode 100644 index 00000000..efa038ce --- /dev/null +++ b/vendor/ely/assets/icons/forward.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/frame.svg b/vendor/ely/assets/icons/frame.svg new file mode 100644 index 00000000..66babc73 --- /dev/null +++ b/vendor/ely/assets/icons/frame.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/frown.svg b/vendor/ely/assets/icons/frown.svg new file mode 100644 index 00000000..ae624b2f --- /dev/null +++ b/vendor/ely/assets/icons/frown.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/fullscreen.svg b/vendor/ely/assets/icons/fullscreen.svg new file mode 100644 index 00000000..0de1e042 --- /dev/null +++ b/vendor/ely/assets/icons/fullscreen.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/gauge.svg b/vendor/ely/assets/icons/gauge.svg new file mode 100644 index 00000000..b373fd67 --- /dev/null +++ b/vendor/ely/assets/icons/gauge.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/git-branch.svg b/vendor/ely/assets/icons/git-branch.svg new file mode 100644 index 00000000..0229c0d9 --- /dev/null +++ b/vendor/ely/assets/icons/git-branch.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/git-commit-horizontal.svg b/vendor/ely/assets/icons/git-commit-horizontal.svg new file mode 100644 index 00000000..48d72b9e --- /dev/null +++ b/vendor/ely/assets/icons/git-commit-horizontal.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/git-merge.svg b/vendor/ely/assets/icons/git-merge.svg new file mode 100644 index 00000000..38435d05 --- /dev/null +++ b/vendor/ely/assets/icons/git-merge.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/git-pull-request-closed.svg b/vendor/ely/assets/icons/git-pull-request-closed.svg new file mode 100644 index 00000000..1b347631 --- /dev/null +++ b/vendor/ely/assets/icons/git-pull-request-closed.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/git-pull-request-draft.svg b/vendor/ely/assets/icons/git-pull-request-draft.svg new file mode 100644 index 00000000..94ffe9f6 --- /dev/null +++ b/vendor/ely/assets/icons/git-pull-request-draft.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/git-pull-request.svg b/vendor/ely/assets/icons/git-pull-request.svg new file mode 100644 index 00000000..dec747fe --- /dev/null +++ b/vendor/ely/assets/icons/git-pull-request.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/globe.svg b/vendor/ely/assets/icons/globe.svg new file mode 100644 index 00000000..88e764f1 --- /dev/null +++ b/vendor/ely/assets/icons/globe.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/grip-horizontal.svg b/vendor/ely/assets/icons/grip-horizontal.svg new file mode 100644 index 00000000..be78fe2b --- /dev/null +++ b/vendor/ely/assets/icons/grip-horizontal.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/grip-vertical.svg b/vendor/ely/assets/icons/grip-vertical.svg new file mode 100644 index 00000000..5fcf574c --- /dev/null +++ b/vendor/ely/assets/icons/grip-vertical.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/hand.svg b/vendor/ely/assets/icons/hand.svg new file mode 100644 index 00000000..46212f9d --- /dev/null +++ b/vendor/ely/assets/icons/hand.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/hard-drive.svg b/vendor/ely/assets/icons/hard-drive.svg new file mode 100644 index 00000000..99c24bfa --- /dev/null +++ b/vendor/ely/assets/icons/hard-drive.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/hash.svg b/vendor/ely/assets/icons/hash.svg new file mode 100644 index 00000000..8587430e --- /dev/null +++ b/vendor/ely/assets/icons/hash.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/heading-1.svg b/vendor/ely/assets/icons/heading-1.svg new file mode 100644 index 00000000..f96e6a4c --- /dev/null +++ b/vendor/ely/assets/icons/heading-1.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/heading-2.svg b/vendor/ely/assets/icons/heading-2.svg new file mode 100644 index 00000000..4c4cfecb --- /dev/null +++ b/vendor/ely/assets/icons/heading-2.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/heading-3.svg b/vendor/ely/assets/icons/heading-3.svg new file mode 100644 index 00000000..53539bd0 --- /dev/null +++ b/vendor/ely/assets/icons/heading-3.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/heading.svg b/vendor/ely/assets/icons/heading.svg new file mode 100644 index 00000000..050bc316 --- /dev/null +++ b/vendor/ely/assets/icons/heading.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/headphones.svg b/vendor/ely/assets/icons/headphones.svg new file mode 100644 index 00000000..6414f472 --- /dev/null +++ b/vendor/ely/assets/icons/headphones.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/heart.svg b/vendor/ely/assets/icons/heart.svg new file mode 100644 index 00000000..60534cbd --- /dev/null +++ b/vendor/ely/assets/icons/heart.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/hexagon.svg b/vendor/ely/assets/icons/hexagon.svg new file mode 100644 index 00000000..576b930a --- /dev/null +++ b/vendor/ely/assets/icons/hexagon.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/history.svg b/vendor/ely/assets/icons/history.svg new file mode 100644 index 00000000..e85090b9 --- /dev/null +++ b/vendor/ely/assets/icons/history.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/hourglass.svg b/vendor/ely/assets/icons/hourglass.svg new file mode 100644 index 00000000..63695b46 --- /dev/null +++ b/vendor/ely/assets/icons/hourglass.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/house.svg b/vendor/ely/assets/icons/house.svg new file mode 100644 index 00000000..4ec24cba --- /dev/null +++ b/vendor/ely/assets/icons/house.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/image-off.svg b/vendor/ely/assets/icons/image-off.svg new file mode 100644 index 00000000..0aeeeb53 --- /dev/null +++ b/vendor/ely/assets/icons/image-off.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/image.svg b/vendor/ely/assets/icons/image.svg new file mode 100644 index 00000000..8b733895 --- /dev/null +++ b/vendor/ely/assets/icons/image.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/inbox.svg b/vendor/ely/assets/icons/inbox.svg new file mode 100644 index 00000000..cc49bd64 --- /dev/null +++ b/vendor/ely/assets/icons/inbox.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/info.svg b/vendor/ely/assets/icons/info.svg new file mode 100644 index 00000000..c158e137 --- /dev/null +++ b/vendor/ely/assets/icons/info.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/italic.svg b/vendor/ely/assets/icons/italic.svg new file mode 100644 index 00000000..61d76d5d --- /dev/null +++ b/vendor/ely/assets/icons/italic.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/kanban.svg b/vendor/ely/assets/icons/kanban.svg new file mode 100644 index 00000000..76e94d14 --- /dev/null +++ b/vendor/ely/assets/icons/kanban.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/key.svg b/vendor/ely/assets/icons/key.svg new file mode 100644 index 00000000..2e9c2b8b --- /dev/null +++ b/vendor/ely/assets/icons/key.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/keyboard.svg b/vendor/ely/assets/icons/keyboard.svg new file mode 100644 index 00000000..c38c84ec --- /dev/null +++ b/vendor/ely/assets/icons/keyboard.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/languages.svg b/vendor/ely/assets/icons/languages.svg new file mode 100644 index 00000000..6397512d --- /dev/null +++ b/vendor/ely/assets/icons/languages.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/laugh.svg b/vendor/ely/assets/icons/laugh.svg new file mode 100644 index 00000000..f6818324 --- /dev/null +++ b/vendor/ely/assets/icons/laugh.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/layers.svg b/vendor/ely/assets/icons/layers.svg new file mode 100644 index 00000000..667affee --- /dev/null +++ b/vendor/ely/assets/icons/layers.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/layout-dashboard.svg b/vendor/ely/assets/icons/layout-dashboard.svg new file mode 100644 index 00000000..17620aa4 --- /dev/null +++ b/vendor/ely/assets/icons/layout-dashboard.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/layout-grid.svg b/vendor/ely/assets/icons/layout-grid.svg new file mode 100644 index 00000000..5ce0c7c1 --- /dev/null +++ b/vendor/ely/assets/icons/layout-grid.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/library.svg b/vendor/ely/assets/icons/library.svg new file mode 100644 index 00000000..47995665 --- /dev/null +++ b/vendor/ely/assets/icons/library.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/lightbulb.svg b/vendor/ely/assets/icons/lightbulb.svg new file mode 100644 index 00000000..ffe63b4c --- /dev/null +++ b/vendor/ely/assets/icons/lightbulb.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/link.svg b/vendor/ely/assets/icons/link.svg new file mode 100644 index 00000000..91b35736 --- /dev/null +++ b/vendor/ely/assets/icons/link.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/list-checks.svg b/vendor/ely/assets/icons/list-checks.svg new file mode 100644 index 00000000..92d9c581 --- /dev/null +++ b/vendor/ely/assets/icons/list-checks.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/list-ordered.svg b/vendor/ely/assets/icons/list-ordered.svg new file mode 100644 index 00000000..ae3570dc --- /dev/null +++ b/vendor/ely/assets/icons/list-ordered.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/list-todo.svg b/vendor/ely/assets/icons/list-todo.svg new file mode 100644 index 00000000..9ef7fda8 --- /dev/null +++ b/vendor/ely/assets/icons/list-todo.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/list.svg b/vendor/ely/assets/icons/list.svg new file mode 100644 index 00000000..559888b5 --- /dev/null +++ b/vendor/ely/assets/icons/list.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/loader-circle.svg b/vendor/ely/assets/icons/loader-circle.svg new file mode 100644 index 00000000..e9573235 --- /dev/null +++ b/vendor/ely/assets/icons/loader-circle.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/lock-open.svg b/vendor/ely/assets/icons/lock-open.svg new file mode 100644 index 00000000..46c368ec --- /dev/null +++ b/vendor/ely/assets/icons/lock-open.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/lock.svg b/vendor/ely/assets/icons/lock.svg new file mode 100644 index 00000000..e3303b91 --- /dev/null +++ b/vendor/ely/assets/icons/lock.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/log-in.svg b/vendor/ely/assets/icons/log-in.svg new file mode 100644 index 00000000..eb003f3a --- /dev/null +++ b/vendor/ely/assets/icons/log-in.svg @@ -0,0 +1,17 @@ + + diff --git a/vendor/ely/assets/icons/log-out.svg b/vendor/ely/assets/icons/log-out.svg new file mode 100644 index 00000000..7796c51d --- /dev/null +++ b/vendor/ely/assets/icons/log-out.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/mail.svg b/vendor/ely/assets/icons/mail.svg new file mode 100644 index 00000000..0bf0558b --- /dev/null +++ b/vendor/ely/assets/icons/mail.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/map-pin.svg b/vendor/ely/assets/icons/map-pin.svg new file mode 100644 index 00000000..b2f7b66d --- /dev/null +++ b/vendor/ely/assets/icons/map-pin.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/map.svg b/vendor/ely/assets/icons/map.svg new file mode 100644 index 00000000..f363059f --- /dev/null +++ b/vendor/ely/assets/icons/map.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/maximize-2.svg b/vendor/ely/assets/icons/maximize-2.svg new file mode 100644 index 00000000..f9c5a658 --- /dev/null +++ b/vendor/ely/assets/icons/maximize-2.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/meh.svg b/vendor/ely/assets/icons/meh.svg new file mode 100644 index 00000000..c622cfcb --- /dev/null +++ b/vendor/ely/assets/icons/meh.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/memory-stick.svg b/vendor/ely/assets/icons/memory-stick.svg new file mode 100644 index 00000000..32c9e6a7 --- /dev/null +++ b/vendor/ely/assets/icons/memory-stick.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/menu.svg b/vendor/ely/assets/icons/menu.svg new file mode 100644 index 00000000..96b27f32 --- /dev/null +++ b/vendor/ely/assets/icons/menu.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/merge.svg b/vendor/ely/assets/icons/merge.svg new file mode 100644 index 00000000..e6b9f171 --- /dev/null +++ b/vendor/ely/assets/icons/merge.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/message-square-diff.svg b/vendor/ely/assets/icons/message-square-diff.svg new file mode 100644 index 00000000..611914c3 --- /dev/null +++ b/vendor/ely/assets/icons/message-square-diff.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/message-square-warning.svg b/vendor/ely/assets/icons/message-square-warning.svg new file mode 100644 index 00000000..b360ede2 --- /dev/null +++ b/vendor/ely/assets/icons/message-square-warning.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/message-square.svg b/vendor/ely/assets/icons/message-square.svg new file mode 100644 index 00000000..b4778730 --- /dev/null +++ b/vendor/ely/assets/icons/message-square.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/mic-off.svg b/vendor/ely/assets/icons/mic-off.svg new file mode 100644 index 00000000..02fd7d37 --- /dev/null +++ b/vendor/ely/assets/icons/mic-off.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/mic.svg b/vendor/ely/assets/icons/mic.svg new file mode 100644 index 00000000..472ca06f --- /dev/null +++ b/vendor/ely/assets/icons/mic.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/minimize-2.svg b/vendor/ely/assets/icons/minimize-2.svg new file mode 100644 index 00000000..81140c95 --- /dev/null +++ b/vendor/ely/assets/icons/minimize-2.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/minus.svg b/vendor/ely/assets/icons/minus.svg new file mode 100644 index 00000000..c59db619 --- /dev/null +++ b/vendor/ely/assets/icons/minus.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/monitor.svg b/vendor/ely/assets/icons/monitor.svg new file mode 100644 index 00000000..da4c9245 --- /dev/null +++ b/vendor/ely/assets/icons/monitor.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/moon.svg b/vendor/ely/assets/icons/moon.svg new file mode 100644 index 00000000..c0f8e8cc --- /dev/null +++ b/vendor/ely/assets/icons/moon.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/mouse-pointer-2.svg b/vendor/ely/assets/icons/mouse-pointer-2.svg new file mode 100644 index 00000000..28e54461 --- /dev/null +++ b/vendor/ely/assets/icons/mouse-pointer-2.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/move-up-right.svg b/vendor/ely/assets/icons/move-up-right.svg new file mode 100644 index 00000000..ce85e98f --- /dev/null +++ b/vendor/ely/assets/icons/move-up-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/move.svg b/vendor/ely/assets/icons/move.svg new file mode 100644 index 00000000..5c31d17d --- /dev/null +++ b/vendor/ely/assets/icons/move.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/music.svg b/vendor/ely/assets/icons/music.svg new file mode 100644 index 00000000..95d1b5d6 --- /dev/null +++ b/vendor/ely/assets/icons/music.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/network.svg b/vendor/ely/assets/icons/network.svg new file mode 100644 index 00000000..0f152069 --- /dev/null +++ b/vendor/ely/assets/icons/network.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/notebook-pen.svg b/vendor/ely/assets/icons/notebook-pen.svg new file mode 100644 index 00000000..d6874539 --- /dev/null +++ b/vendor/ely/assets/icons/notebook-pen.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/octagon-alert.svg b/vendor/ely/assets/icons/octagon-alert.svg new file mode 100644 index 00000000..17593993 --- /dev/null +++ b/vendor/ely/assets/icons/octagon-alert.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/package.svg b/vendor/ely/assets/icons/package.svg new file mode 100644 index 00000000..6c8abeff --- /dev/null +++ b/vendor/ely/assets/icons/package.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/palette.svg b/vendor/ely/assets/icons/palette.svg new file mode 100644 index 00000000..4044dcbf --- /dev/null +++ b/vendor/ely/assets/icons/palette.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/panel-bottom.svg b/vendor/ely/assets/icons/panel-bottom.svg new file mode 100644 index 00000000..d0947ea7 --- /dev/null +++ b/vendor/ely/assets/icons/panel-bottom.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/panel-left.svg b/vendor/ely/assets/icons/panel-left.svg new file mode 100644 index 00000000..90e50734 --- /dev/null +++ b/vendor/ely/assets/icons/panel-left.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/panel-right.svg b/vendor/ely/assets/icons/panel-right.svg new file mode 100644 index 00000000..41cb2d63 --- /dev/null +++ b/vendor/ely/assets/icons/panel-right.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/paperclip.svg b/vendor/ely/assets/icons/paperclip.svg new file mode 100644 index 00000000..e867ae84 --- /dev/null +++ b/vendor/ely/assets/icons/paperclip.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/pause.svg b/vendor/ely/assets/icons/pause.svg new file mode 100644 index 00000000..2ad3d959 --- /dev/null +++ b/vendor/ely/assets/icons/pause.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/pen-line.svg b/vendor/ely/assets/icons/pen-line.svg new file mode 100644 index 00000000..656c6a42 --- /dev/null +++ b/vendor/ely/assets/icons/pen-line.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/pen-tool.svg b/vendor/ely/assets/icons/pen-tool.svg new file mode 100644 index 00000000..6d056a02 --- /dev/null +++ b/vendor/ely/assets/icons/pen-tool.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/pencil.svg b/vendor/ely/assets/icons/pencil.svg new file mode 100644 index 00000000..ccfea639 --- /dev/null +++ b/vendor/ely/assets/icons/pencil.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/phone-off.svg b/vendor/ely/assets/icons/phone-off.svg new file mode 100644 index 00000000..0a94ac2d --- /dev/null +++ b/vendor/ely/assets/icons/phone-off.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/phone.svg b/vendor/ely/assets/icons/phone.svg new file mode 100644 index 00000000..83e22db6 --- /dev/null +++ b/vendor/ely/assets/icons/phone.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/picture-in-picture-2.svg b/vendor/ely/assets/icons/picture-in-picture-2.svg new file mode 100644 index 00000000..3bac41c8 --- /dev/null +++ b/vendor/ely/assets/icons/picture-in-picture-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/pin-off.svg b/vendor/ely/assets/icons/pin-off.svg new file mode 100644 index 00000000..95705815 --- /dev/null +++ b/vendor/ely/assets/icons/pin-off.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/pin.svg b/vendor/ely/assets/icons/pin.svg new file mode 100644 index 00000000..97b7130f --- /dev/null +++ b/vendor/ely/assets/icons/pin.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/pipette.svg b/vendor/ely/assets/icons/pipette.svg new file mode 100644 index 00000000..dbf7c727 --- /dev/null +++ b/vendor/ely/assets/icons/pipette.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/play.svg b/vendor/ely/assets/icons/play.svg new file mode 100644 index 00000000..c2ef3e2d --- /dev/null +++ b/vendor/ely/assets/icons/play.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/plus.svg b/vendor/ely/assets/icons/plus.svg new file mode 100644 index 00000000..d3cd0a3a --- /dev/null +++ b/vendor/ely/assets/icons/plus.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/power.svg b/vendor/ely/assets/icons/power.svg new file mode 100644 index 00000000..f12f8eee --- /dev/null +++ b/vendor/ely/assets/icons/power.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/printer.svg b/vendor/ely/assets/icons/printer.svg new file mode 100644 index 00000000..4ea72f59 --- /dev/null +++ b/vendor/ely/assets/icons/printer.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/puzzle.svg b/vendor/ely/assets/icons/puzzle.svg new file mode 100644 index 00000000..51a2b287 --- /dev/null +++ b/vendor/ely/assets/icons/puzzle.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/quote.svg b/vendor/ely/assets/icons/quote.svg new file mode 100644 index 00000000..d463663d --- /dev/null +++ b/vendor/ely/assets/icons/quote.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/redo-2.svg b/vendor/ely/assets/icons/redo-2.svg new file mode 100644 index 00000000..f8c1fe33 --- /dev/null +++ b/vendor/ely/assets/icons/redo-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/redo-dot.svg b/vendor/ely/assets/icons/redo-dot.svg new file mode 100644 index 00000000..f40b7815 --- /dev/null +++ b/vendor/ely/assets/icons/redo-dot.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/refresh-cw.svg b/vendor/ely/assets/icons/refresh-cw.svg new file mode 100644 index 00000000..c0830476 --- /dev/null +++ b/vendor/ely/assets/icons/refresh-cw.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/regex.svg b/vendor/ely/assets/icons/regex.svg new file mode 100644 index 00000000..07a3b42e --- /dev/null +++ b/vendor/ely/assets/icons/regex.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/repeat-1.svg b/vendor/ely/assets/icons/repeat-1.svg new file mode 100644 index 00000000..8ecc4cdf --- /dev/null +++ b/vendor/ely/assets/icons/repeat-1.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/repeat.svg b/vendor/ely/assets/icons/repeat.svg new file mode 100644 index 00000000..bbea6696 --- /dev/null +++ b/vendor/ely/assets/icons/repeat.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/reply-all.svg b/vendor/ely/assets/icons/reply-all.svg new file mode 100644 index 00000000..99ca6896 --- /dev/null +++ b/vendor/ely/assets/icons/reply-all.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/reply.svg b/vendor/ely/assets/icons/reply.svg new file mode 100644 index 00000000..aa2eada6 --- /dev/null +++ b/vendor/ely/assets/icons/reply.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/rocket.svg b/vendor/ely/assets/icons/rocket.svg new file mode 100644 index 00000000..db440481 --- /dev/null +++ b/vendor/ely/assets/icons/rocket.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/rotate-ccw.svg b/vendor/ely/assets/icons/rotate-ccw.svg new file mode 100644 index 00000000..90a1d339 --- /dev/null +++ b/vendor/ely/assets/icons/rotate-ccw.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/rotate-cw.svg b/vendor/ely/assets/icons/rotate-cw.svg new file mode 100644 index 00000000..afa57c55 --- /dev/null +++ b/vendor/ely/assets/icons/rotate-cw.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/rows-2.svg b/vendor/ely/assets/icons/rows-2.svg new file mode 100644 index 00000000..f0593652 --- /dev/null +++ b/vendor/ely/assets/icons/rows-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/save.svg b/vendor/ely/assets/icons/save.svg new file mode 100644 index 00000000..d67d9de5 --- /dev/null +++ b/vendor/ely/assets/icons/save.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/scissors.svg b/vendor/ely/assets/icons/scissors.svg new file mode 100644 index 00000000..810404cb --- /dev/null +++ b/vendor/ely/assets/icons/scissors.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/screen-share-off.svg b/vendor/ely/assets/icons/screen-share-off.svg new file mode 100644 index 00000000..a2c13cd1 --- /dev/null +++ b/vendor/ely/assets/icons/screen-share-off.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/screen-share.svg b/vendor/ely/assets/icons/screen-share.svg new file mode 100644 index 00000000..45529e6c --- /dev/null +++ b/vendor/ely/assets/icons/screen-share.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/search-x.svg b/vendor/ely/assets/icons/search-x.svg new file mode 100644 index 00000000..27028039 --- /dev/null +++ b/vendor/ely/assets/icons/search-x.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/search.svg b/vendor/ely/assets/icons/search.svg new file mode 100644 index 00000000..ba16b998 --- /dev/null +++ b/vendor/ely/assets/icons/search.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/send.svg b/vendor/ely/assets/icons/send.svg new file mode 100644 index 00000000..bfdb69c0 --- /dev/null +++ b/vendor/ely/assets/icons/send.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/server.svg b/vendor/ely/assets/icons/server.svg new file mode 100644 index 00000000..db7f2cc0 --- /dev/null +++ b/vendor/ely/assets/icons/server.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/settings.svg b/vendor/ely/assets/icons/settings.svg new file mode 100644 index 00000000..e23730e7 --- /dev/null +++ b/vendor/ely/assets/icons/settings.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/shapes.svg b/vendor/ely/assets/icons/shapes.svg new file mode 100644 index 00000000..c0dc3374 --- /dev/null +++ b/vendor/ely/assets/icons/shapes.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/share-2.svg b/vendor/ely/assets/icons/share-2.svg new file mode 100644 index 00000000..2ef0696e --- /dev/null +++ b/vendor/ely/assets/icons/share-2.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/shield.svg b/vendor/ely/assets/icons/shield.svg new file mode 100644 index 00000000..4d256a3e --- /dev/null +++ b/vendor/ely/assets/icons/shield.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/shuffle.svg b/vendor/ely/assets/icons/shuffle.svg new file mode 100644 index 00000000..93d272a7 --- /dev/null +++ b/vendor/ely/assets/icons/shuffle.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/skip-back.svg b/vendor/ely/assets/icons/skip-back.svg new file mode 100644 index 00000000..118f6776 --- /dev/null +++ b/vendor/ely/assets/icons/skip-back.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/skip-forward.svg b/vendor/ely/assets/icons/skip-forward.svg new file mode 100644 index 00000000..b8f9147b --- /dev/null +++ b/vendor/ely/assets/icons/skip-forward.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/slash.svg b/vendor/ely/assets/icons/slash.svg new file mode 100644 index 00000000..63e5a38b --- /dev/null +++ b/vendor/ely/assets/icons/slash.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/sliders-horizontal.svg b/vendor/ely/assets/icons/sliders-horizontal.svg new file mode 100644 index 00000000..8241295a --- /dev/null +++ b/vendor/ely/assets/icons/sliders-horizontal.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/smartphone.svg b/vendor/ely/assets/icons/smartphone.svg new file mode 100644 index 00000000..3aa94114 --- /dev/null +++ b/vendor/ely/assets/icons/smartphone.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/smile-plus.svg b/vendor/ely/assets/icons/smile-plus.svg new file mode 100644 index 00000000..2bf9238b --- /dev/null +++ b/vendor/ely/assets/icons/smile-plus.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/vendor/ely/assets/icons/smile.svg b/vendor/ely/assets/icons/smile.svg new file mode 100644 index 00000000..f61140db --- /dev/null +++ b/vendor/ely/assets/icons/smile.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/sparkles.svg b/vendor/ely/assets/icons/sparkles.svg new file mode 100644 index 00000000..e13154bd --- /dev/null +++ b/vendor/ely/assets/icons/sparkles.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/spline.svg b/vendor/ely/assets/icons/spline.svg new file mode 100644 index 00000000..3e7994e2 --- /dev/null +++ b/vendor/ely/assets/icons/spline.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/square-check.svg b/vendor/ely/assets/icons/square-check.svg new file mode 100644 index 00000000..9a9e08f8 --- /dev/null +++ b/vendor/ely/assets/icons/square-check.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/square-function.svg b/vendor/ely/assets/icons/square-function.svg new file mode 100644 index 00000000..621ee4d6 --- /dev/null +++ b/vendor/ely/assets/icons/square-function.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/square-pen.svg b/vendor/ely/assets/icons/square-pen.svg new file mode 100644 index 00000000..9580d9bb --- /dev/null +++ b/vendor/ely/assets/icons/square-pen.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/square-round-corner.svg b/vendor/ely/assets/icons/square-round-corner.svg new file mode 100644 index 00000000..313be689 --- /dev/null +++ b/vendor/ely/assets/icons/square-round-corner.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/square.svg b/vendor/ely/assets/icons/square.svg new file mode 100644 index 00000000..8df41cd0 --- /dev/null +++ b/vendor/ely/assets/icons/square.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/star.svg b/vendor/ely/assets/icons/star.svg new file mode 100644 index 00000000..3f05f7b5 --- /dev/null +++ b/vendor/ely/assets/icons/star.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/step-forward.svg b/vendor/ely/assets/icons/step-forward.svg new file mode 100644 index 00000000..efc3b388 --- /dev/null +++ b/vendor/ely/assets/icons/step-forward.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/sticky-note.svg b/vendor/ely/assets/icons/sticky-note.svg new file mode 100644 index 00000000..f3390428 --- /dev/null +++ b/vendor/ely/assets/icons/sticky-note.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/strikethrough.svg b/vendor/ely/assets/icons/strikethrough.svg new file mode 100644 index 00000000..9bef2ef9 --- /dev/null +++ b/vendor/ely/assets/icons/strikethrough.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/sun.svg b/vendor/ely/assets/icons/sun.svg new file mode 100644 index 00000000..5644b618 --- /dev/null +++ b/vendor/ely/assets/icons/sun.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/table.svg b/vendor/ely/assets/icons/table.svg new file mode 100644 index 00000000..57a8bb92 --- /dev/null +++ b/vendor/ely/assets/icons/table.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/tag.svg b/vendor/ely/assets/icons/tag.svg new file mode 100644 index 00000000..34e20b3c --- /dev/null +++ b/vendor/ely/assets/icons/tag.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/target.svg b/vendor/ely/assets/icons/target.svg new file mode 100644 index 00000000..7dea02e4 --- /dev/null +++ b/vendor/ely/assets/icons/target.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/terminal.svg b/vendor/ely/assets/icons/terminal.svg new file mode 100644 index 00000000..cc21fae3 --- /dev/null +++ b/vendor/ely/assets/icons/terminal.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/thumbs-down.svg b/vendor/ely/assets/icons/thumbs-down.svg new file mode 100644 index 00000000..c8266cf1 --- /dev/null +++ b/vendor/ely/assets/icons/thumbs-down.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/thumbs-up.svg b/vendor/ely/assets/icons/thumbs-up.svg new file mode 100644 index 00000000..1a824b56 --- /dev/null +++ b/vendor/ely/assets/icons/thumbs-up.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/timer.svg b/vendor/ely/assets/icons/timer.svg new file mode 100644 index 00000000..4c8c2521 --- /dev/null +++ b/vendor/ely/assets/icons/timer.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/trash-2.svg b/vendor/ely/assets/icons/trash-2.svg new file mode 100644 index 00000000..a276e0b7 --- /dev/null +++ b/vendor/ely/assets/icons/trash-2.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/trending-down.svg b/vendor/ely/assets/icons/trending-down.svg new file mode 100644 index 00000000..774e6360 --- /dev/null +++ b/vendor/ely/assets/icons/trending-down.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/trending-up.svg b/vendor/ely/assets/icons/trending-up.svg new file mode 100644 index 00000000..c5664b11 --- /dev/null +++ b/vendor/ely/assets/icons/trending-up.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/triangle-alert.svg b/vendor/ely/assets/icons/triangle-alert.svg new file mode 100644 index 00000000..18af8cdb --- /dev/null +++ b/vendor/ely/assets/icons/triangle-alert.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/type.svg b/vendor/ely/assets/icons/type.svg new file mode 100644 index 00000000..eaf86aa6 --- /dev/null +++ b/vendor/ely/assets/icons/type.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/underline.svg b/vendor/ely/assets/icons/underline.svg new file mode 100644 index 00000000..f34b4980 --- /dev/null +++ b/vendor/ely/assets/icons/underline.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/undo-2.svg b/vendor/ely/assets/icons/undo-2.svg new file mode 100644 index 00000000..d4e9ca5d --- /dev/null +++ b/vendor/ely/assets/icons/undo-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/upload.svg b/vendor/ely/assets/icons/upload.svg new file mode 100644 index 00000000..cd69186c --- /dev/null +++ b/vendor/ely/assets/icons/upload.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/user-plus.svg b/vendor/ely/assets/icons/user-plus.svg new file mode 100644 index 00000000..f2007a2c --- /dev/null +++ b/vendor/ely/assets/icons/user-plus.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/user.svg b/vendor/ely/assets/icons/user.svg new file mode 100644 index 00000000..b0209539 --- /dev/null +++ b/vendor/ely/assets/icons/user.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/users.svg b/vendor/ely/assets/icons/users.svg new file mode 100644 index 00000000..9d8738d4 --- /dev/null +++ b/vendor/ely/assets/icons/users.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/variable.svg b/vendor/ely/assets/icons/variable.svg new file mode 100644 index 00000000..fc4d5ffe --- /dev/null +++ b/vendor/ely/assets/icons/variable.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/video-off.svg b/vendor/ely/assets/icons/video-off.svg new file mode 100644 index 00000000..9ef415e3 --- /dev/null +++ b/vendor/ely/assets/icons/video-off.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/video.svg b/vendor/ely/assets/icons/video.svg new file mode 100644 index 00000000..2b21175a --- /dev/null +++ b/vendor/ely/assets/icons/video.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/volume-1.svg b/vendor/ely/assets/icons/volume-1.svg new file mode 100644 index 00000000..62126431 --- /dev/null +++ b/vendor/ely/assets/icons/volume-1.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/volume-2.svg b/vendor/ely/assets/icons/volume-2.svg new file mode 100644 index 00000000..d5299e45 --- /dev/null +++ b/vendor/ely/assets/icons/volume-2.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/volume-x.svg b/vendor/ely/assets/icons/volume-x.svg new file mode 100644 index 00000000..3fe57ce1 --- /dev/null +++ b/vendor/ely/assets/icons/volume-x.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/volume.svg b/vendor/ely/assets/icons/volume.svg new file mode 100644 index 00000000..c1663d4d --- /dev/null +++ b/vendor/ely/assets/icons/volume.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/wallet.svg b/vendor/ely/assets/icons/wallet.svg new file mode 100644 index 00000000..97782f93 --- /dev/null +++ b/vendor/ely/assets/icons/wallet.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/wand-sparkles.svg b/vendor/ely/assets/icons/wand-sparkles.svg new file mode 100644 index 00000000..053a168c --- /dev/null +++ b/vendor/ely/assets/icons/wand-sparkles.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/vendor/ely/assets/icons/whole-word.svg b/vendor/ely/assets/icons/whole-word.svg new file mode 100644 index 00000000..acb0b737 --- /dev/null +++ b/vendor/ely/assets/icons/whole-word.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vendor/ely/assets/icons/wifi-off.svg b/vendor/ely/assets/icons/wifi-off.svg new file mode 100644 index 00000000..1c18dd33 --- /dev/null +++ b/vendor/ely/assets/icons/wifi-off.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/vendor/ely/assets/icons/wifi.svg b/vendor/ely/assets/icons/wifi.svg new file mode 100644 index 00000000..60085486 --- /dev/null +++ b/vendor/ely/assets/icons/wifi.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/workflow.svg b/vendor/ely/assets/icons/workflow.svg new file mode 100644 index 00000000..368df4ef --- /dev/null +++ b/vendor/ely/assets/icons/workflow.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/icons/wrench.svg b/vendor/ely/assets/icons/wrench.svg new file mode 100644 index 00000000..2da7fbe4 --- /dev/null +++ b/vendor/ely/assets/icons/wrench.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/x.svg b/vendor/ely/assets/icons/x.svg new file mode 100644 index 00000000..7b9f74b0 --- /dev/null +++ b/vendor/ely/assets/icons/x.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/vendor/ely/assets/icons/zap.svg b/vendor/ely/assets/icons/zap.svg new file mode 100644 index 00000000..d983b507 --- /dev/null +++ b/vendor/ely/assets/icons/zap.svg @@ -0,0 +1,15 @@ + + + + diff --git a/vendor/ely/assets/icons/zoom-in.svg b/vendor/ely/assets/icons/zoom-in.svg new file mode 100644 index 00000000..1d43681d --- /dev/null +++ b/vendor/ely/assets/icons/zoom-in.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/vendor/ely/assets/icons/zoom-out.svg b/vendor/ely/assets/icons/zoom-out.svg new file mode 100644 index 00000000..7eb78a16 --- /dev/null +++ b/vendor/ely/assets/icons/zoom-out.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/vendor/ely/assets/maps/countries.geojson b/vendor/ely/assets/maps/countries.geojson new file mode 100644 index 00000000..2decfa01 --- /dev/null +++ b/vendor/ely/assets/maps/countries.geojson @@ -0,0 +1 @@ +{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"name":"Fiji","iso":"FJ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[180,-16.07],[180,-16.56],[179.36,-16.8],[178.73,-17.01],[178.6,-16.64],[179.1,-16.43],[179.41,-16.38],[180,-16.07]]],[[[178.13,-17.5],[178.37,-17.34],[178.72,-17.63],[178.55,-18.15],[177.93,-18.29],[177.38,-18.16],[177.29,-17.72],[177.67,-17.38],[178.13,-17.5]]],[[[-179.79,-16.02],[-179.92,-16.5],[-180,-16.56],[-180,-16.07],[-179.79,-16.02]]]]}},{"type":"Feature","properties":{"name":"Tanzania","iso":"TZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[33.9,-0.95],[34.07,-1.06],[37.7,-3.1],[37.77,-3.68],[39.2,-4.68],[38.74,-5.91],[38.8,-6.48],[39.44,-6.84],[39.47,-7.1],[39.19,-7.7],[39.25,-8.01],[39.19,-8.49],[39.54,-9.11],[39.95,-10.1],[40.32,-10.32],[39.52,-10.9],[38.43,-11.29],[37.83,-11.27],[37.47,-11.57],[36.78,-11.59],[36.51,-11.72],[35.31,-11.44],[34.56,-11.52],[34.28,-10.16],[33.94,-9.69],[33.74,-9.42],[32.76,-9.23],[32.19,-8.93],[31.56,-8.76],[31.16,-8.59],[30.74,-8.34],[30.2,-7.08],[29.62,-6.52],[29.42,-5.94],[29.52,-5.42],[29.34,-4.5],[29.75,-4.45],[30.12,-4.09],[30.51,-3.57],[30.75,-3.36],[30.74,-3.03],[30.53,-2.81],[30.47,-2.41],[30.76,-2.29],[30.82,-1.7],[30.42,-1.13],[30.77,-1.01],[31.87,-1.03],[33.9,-0.95]]]]}},{"type":"Feature","properties":{"name":"W. Sahara","iso":"EH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.67,27.66],[-8.67,27.59],[-8.68,27.4],[-8.69,25.88],[-11.97,25.93],[-11.94,23.37],[-12.87,23.28],[-13.12,22.77],[-12.93,21.33],[-16.85,21.33],[-17.06,21.0],[-17.02,21.42],[-17.0,21.42],[-14.75,21.5],[-14.63,21.86],[-14.22,22.31],[-13.89,23.69],[-12.5,24.77],[-12.03,26.03],[-11.72,26.1],[-11.39,26.88],[-10.55,26.99],[-10.19,26.86],[-9.74,26.86],[-9.41,27.09],[-8.79,27.12],[-8.82,27.66],[-8.67,27.66]]]]}},{"type":"Feature","properties":{"name":"Canada","iso":"CA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-122.84,49],[-122.97,49.0],[-124.91,49.98],[-125.62,50.42],[-127.44,50.83],[-127.99,51.72],[-127.85,52.33],[-129.13,52.76],[-129.31,53.56],[-130.51,54.29],[-130.54,54.8],[-129.98,55.28],[-130.01,55.92],[-131.71,56.55],[-132.73,57.69],[-133.36,58.41],[-134.27,58.86],[-134.94,59.27],[-135.48,59.79],[-136.48,59.46],[-137.45,58.91],[-138.34,59.56],[-139.04,60],[-140.01,60.28],[-141.0,60.31],[-140.99,66.0],[-140.99,69.71],[-139.12,69.47],[-137.55,68.99],[-136.5,68.9],[-135.63,69.32],[-134.41,69.63],[-132.93,69.51],[-131.43,69.94],[-129.79,70.19],[-129.11,69.78],[-128.36,70.01],[-128.14,70.48],[-127.45,70.38],[-125.76,69.48],[-124.42,70.16],[-124.29,69.4],[-123.06,69.56],[-122.68,69.86],[-121.47,69.8],[-119.94,69.38],[-117.6,69.01],[-116.23,68.84],[-115.25,68.91],[-113.9,68.4],[-115.3,67.9],[-113.5,67.69],[-110.8,67.81],[-109.95,67.98],[-108.88,67.38],[-107.79,67.89],[-108.81,68.31],[-108.17,68.65],[-106.95,68.7],[-106.15,68.8],[-105.34,68.56],[-104.34,68.02],[-103.22,68.1],[-101.45,67.65],[-99.9,67.81],[-98.44,67.78],[-98.56,68.4],[-97.67,68.58],[-96.12,68.24],[-96.13,67.29],[-95.49,68.09],[-94.69,68.06],[-94.23,69.07],[-95.3,69.69],[-96.47,70.09],[-96.39,71.19],[-95.21,71.92],[-93.89,71.76],[-92.88,71.32],[-91.52,70.19],[-92.41,69.7],[-90.55,69.5],[-90.55,68.47],[-89.22,69.26],[-88.02,68.62],[-88.32,67.87],[-87.35,67.2],[-86.31,67.92],[-85.58,68.78],[-85.52,69.88],[-84.1,69.81],[-82.62,69.66],[-81.28,69.16],[-81.22,68.67],[-81.96,68.13],[-81.26,67.6],[-81.39,67.11],[-83.34,66.41],[-84.74,66.26],[-85.77,66.56],[-86.07,66.06],[-87.03,65.21],[-87.32,64.78],[-88.48,64.1],[-89.91,64.03],[-90.7,63.61],[-90.77,62.96],[-91.93,62.84],[-93.16,62.02],[-94.24,60.9],[-94.63,60.11],[-94.68,58.95],[-93.22,58.78],[-92.76,57.85],[-92.3,57.09],[-90.9,57.28],[-89.04,56.85],[-88.04,56.47],[-87.32,56.0],[-86.07,55.72],[-85.01,55.3],[-83.36,55.24],[-82.27,55.15],[-82.44,54.28],[-82.13,53.28],[-81.4,52.16],[-79.91,51.21],[-79.14,51.53],[-78.6,52.56],[-79.12,54.14],[-79.83,54.67],[-78.23,55.14],[-77.1,55.84],[-76.54,56.53],[-76.62,57.2],[-77.3,58.05],[-78.52,58.8],[-77.34,59.85],[-77.77,60.76],[-78.11,62.32],[-77.41,62.55],[-75.7,62.28],[-74.67,62.18],[-73.84,62.44],[-72.91,62.11],[-71.68,61.53],[-71.37,61.14],[-69.59,61.06],[-69.62,60.22],[-69.29,58.96],[-68.37,58.8],[-67.65,58.21],[-66.2,58.77],[-65.25,59.87],[-64.58,60.34],[-63.8,59.44],[-62.5,58.17],[-61.4,56.97],[-61.8,56.34],[-60.47,55.78],[-59.57,55.2],[-57.98,54.95],[-57.33,54.63],[-56.94,53.78],[-56.16,53.65],[-55.76,53.27],[-55.68,52.15],[-56.41,51.77],[-57.13,51.42],[-58.77,51.06],[-60.03,50.24],[-61.72,50.08],[-63.86,50.29],[-65.36,50.3],[-66.4,50.23],[-67.24,49.51],[-68.51,49.07],[-69.95,47.74],[-71.1,46.82],[-70.26,46.99],[-68.65,48.3],[-66.55,49.13],[-65.06,49.23],[-64.17,48.74],[-65.12,48.07],[-64.8,46.99],[-64.47,46.24],[-63.17,45.74],[-61.52,45.88],[-60.52,47.01],[-60.45,46.28],[-59.8,45.92],[-61.04,45.27],[-63.25,44.67],[-64.25,44.27],[-65.36,43.55],[-66.12,43.62],[-66.16,44.47],[-64.43,45.29],[-66.03,45.26],[-67.14,45.14],[-67.79,45.7],[-67.79,47.07],[-68.23,47.35],[-68.91,47.19],[-69.24,47.45],[-70.0,46.69],[-70.31,45.91],[-70.66,45.46],[-71.08,45.31],[-71.41,45.26],[-71.51,45.01],[-73.35,45.01],[-74.87,45.0],[-75.32,44.82],[-76.38,44.1],[-76.5,44.02],[-76.82,43.63],[-77.74,43.63],[-78.72,43.63],[-79.17,43.47],[-79.01,43.27],[-78.92,42.97],[-78.94,42.86],[-80.25,42.37],[-81.28,42.21],[-82.44,41.68],[-82.69,41.68],[-83.03,41.83],[-83.14,41.98],[-83.12,42.08],[-82.9,42.43],[-82.43,42.98],[-82.14,43.57],[-82.34,44.44],[-82.55,45.35],[-83.59,45.82],[-83.47,45.99],[-83.62,46.12],[-83.89,46.12],[-84.09,46.28],[-84.14,46.51],[-84.34,46.41],[-84.6,46.44],[-84.54,46.54],[-84.78,46.64],[-84.88,46.9],[-85.65,47.22],[-86.46,47.55],[-87.44,47.94],[-88.38,48.3],[-89.27,48.02],[-89.6,48.01],[-90.83,48.27],[-91.64,48.14],[-92.61,48.45],[-93.63,48.61],[-94.33,48.67],[-94.64,48.84],[-94.82,49.39],[-95.16,49.38],[-95.16,49],[-97.23,49.0],[-100.65,49],[-104.05,49.0],[-107.05,49],[-110.05,49],[-113,49],[-116.05,49],[-117.03,49],[-120,49],[-122.84,49]]],[[[-83.99,62.45],[-83.25,62.91],[-81.88,62.9],[-81.9,62.71],[-83.07,62.16],[-83.77,62.18],[-83.99,62.45]]],[[[-79.78,72.8],[-80.88,73.33],[-80.83,73.69],[-80.35,73.76],[-78.06,73.65],[-76.34,73.1],[-76.25,72.83],[-77.31,72.86],[-78.39,72.88],[-79.49,72.74],[-79.78,72.8]]],[[[-80.32,62.09],[-79.93,62.39],[-79.52,62.36],[-79.27,62.16],[-79.66,61.63],[-80.1,61.72],[-80.36,62.02],[-80.32,62.09]]],[[[-93.61,74.98],[-94.16,74.59],[-95.61,74.67],[-96.82,74.93],[-96.29,75.38],[-94.85,75.65],[-93.98,75.3],[-93.61,74.98]]],[[[-93.84,77.52],[-94.3,77.49],[-96.17,77.56],[-96.44,77.83],[-94.42,77.82],[-93.72,77.63],[-93.84,77.52]]],[[[-96.75,78.77],[-95.56,78.42],[-95.83,78.06],[-97.31,77.85],[-98.12,78.08],[-98.55,78.46],[-98.63,78.87],[-97.34,78.83],[-96.75,78.77]]],[[[-88.15,74.39],[-89.76,74.52],[-92.42,74.84],[-92.77,75.39],[-92.89,75.88],[-93.89,76.32],[-95.96,76.44],[-97.12,76.75],[-96.75,77.16],[-94.68,77.1],[-93.57,76.78],[-91.61,76.78],[-90.74,76.45],[-90.97,76.07],[-89.82,75.85],[-89.19,75.61],[-87.84,75.57],[-86.38,75.48],[-84.79,75.7],[-82.75,75.78],[-81.13,75.71],[-80.06,75.34],[-79.83,74.92],[-80.46,74.66],[-81.95,74.44],[-83.23,74.56],[-86.1,74.41],[-88.15,74.39]]],[[[-111.26,78.15],[-109.85,78.0],[-110.19,77.7],[-112.05,77.41],[-113.53,77.73],[-112.72,78.05],[-111.26,78.15]]],[[[-110.96,78.8],[-109.66,78.6],[-110.88,78.41],[-112.54,78.41],[-112.53,78.55],[-111.5,78.85],[-110.96,78.8]]],[[[-55.6,51.32],[-56.13,50.69],[-56.8,49.81],[-56.14,50.15],[-55.47,49.94],[-55.82,49.59],[-54.94,49.31],[-54.47,49.56],[-53.48,49.25],[-53.79,48.52],[-53.09,48.69],[-52.96,48.16],[-52.65,47.54],[-53.07,46.66],[-53.52,46.62],[-54.18,46.81],[-53.96,47.63],[-54.24,47.75],[-55.4,46.88],[-56.0,46.92],[-55.29,47.39],[-56.25,47.63],[-57.33,47.57],[-59.27,47.6],[-59.42,47.9],[-58.8,48.25],[-59.23,48.52],[-58.39,49.13],[-57.36,50.72],[-56.74,51.29],[-55.87,51.63],[-55.41,51.59],[-55.6,51.32]]],[[[-83.88,65.11],[-82.79,64.77],[-81.64,64.46],[-81.55,63.98],[-80.82,64.06],[-80.1,63.73],[-80.99,63.41],[-82.55,63.65],[-83.11,64.1],[-84.1,63.57],[-85.52,63.05],[-85.87,63.64],[-87.22,63.54],[-86.35,64.04],[-86.22,64.82],[-85.88,65.74],[-85.16,65.66],[-84.98,65.22],[-84.46,65.37],[-83.88,65.11]]],[[[-78.77,72.35],[-77.82,72.75],[-75.61,72.24],[-74.23,71.77],[-74.1,71.33],[-72.24,71.56],[-71.2,70.92],[-68.79,70.53],[-67.91,70.12],[-66.97,69.19],[-68.81,68.72],[-66.45,68.07],[-64.86,67.85],[-63.42,66.93],[-61.85,66.86],[-62.16,66.16],[-63.92,65.0],[-65.15,65.43],[-66.72,66.39],[-68.02,66.26],[-68.14,65.69],[-67.09,65.11],[-65.73,64.65],[-65.32,64.38],[-64.67,63.39],[-65.01,62.67],[-66.28,62.95],[-68.78,63.75],[-67.37,62.88],[-66.33,62.28],[-66.17,61.93],[-68.88,62.33],[-71.02,62.91],[-72.24,63.4],[-71.89,63.68],[-73.38,64.19],[-74.83,64.68],[-74.82,64.39],[-77.71,64.23],[-78.56,64.57],[-77.9,65.31],[-76.02,65.33],[-73.96,65.45],[-74.29,65.81],[-73.94,66.31],[-72.65,67.28],[-72.93,67.73],[-73.31,68.07],[-74.84,68.55],[-76.87,68.89],[-76.23,69.15],[-77.29,69.77],[-78.17,69.83],[-78.96,70.17],[-79.49,69.87],[-81.31,69.74],[-84.94,69.97],[-87.06,70.26],[-88.68,70.41],[-89.51,70.76],[-88.47,71.22],[-89.89,71.22],[-90.21,72.24],[-89.44,73.13],[-88.41,73.54],[-85.83,73.8],[-86.56,73.16],[-85.77,72.53],[-84.85,73.34],[-82.32,73.75],[-80.6,72.72],[-80.75,72.06],[-78.77,72.35]]],[[[-94.5,74.13],[-92.42,74.1],[-90.51,73.86],[-92.0,72.97],[-93.2,72.77],[-94.27,72.02],[-95.41,72.06],[-96.03,72.94],[-96.02,73.44],[-95.5,73.86],[-94.5,74.13]]],[[[-122.85,76.12],[-121.16,76.86],[-119.1,77.51],[-117.57,77.5],[-116.2,77.65],[-116.34,76.88],[-117.11,76.53],[-118.04,76.48],[-119.9,76.05],[-121.5,75.9],[-122.85,76.12]]],[[[-132.71,54.04],[-131.75,54.12],[-132.05,52.98],[-131.18,52.18],[-131.58,52.18],[-132.18,52.64],[-132.55,53.1],[-133.05,53.41],[-133.24,53.85],[-133.18,54.17],[-132.71,54.04]]],[[[-105.49,79.3],[-103.53,79.17],[-100.83,78.8],[-100.06,78.32],[-99.67,77.91],[-101.3,78.02],[-102.95,78.34],[-105.18,78.38],[-104.21,78.68],[-105.42,78.92],[-105.49,79.3]]],[[[-123.51,48.51],[-124.01,48.37],[-125.66,48.83],[-125.95,49.18],[-126.85,49.53],[-127.03,49.81],[-128.06,49.99],[-128.44,50.54],[-128.36,50.77],[-127.31,50.55],[-126.7,50.4],[-125.76,50.3],[-125.42,49.95],[-124.92,49.48],[-123.92,49.06],[-123.51,48.51]]],[[[-121.54,74.45],[-120.11,74.24],[-117.56,74.19],[-116.58,73.9],[-115.51,73.48],[-116.77,73.22],[-119.22,72.52],[-120.46,71.82],[-120.46,71.38],[-123.09,70.9],[-123.62,71.34],[-125.93,71.87],[-125.5,72.29],[-124.81,73.02],[-123.94,73.68],[-124.92,74.29],[-121.54,74.45]]],[[[-107.82,75.85],[-106.93,76.01],[-105.88,75.97],[-105.7,75.48],[-106.31,75.01],[-109.7,74.85],[-112.22,74.42],[-113.74,74.39],[-113.87,74.72],[-111.79,75.16],[-116.31,75.04],[-117.71,75.22],[-116.35,76.2],[-115.4,76.48],[-112.59,76.14],[-110.81,75.55],[-109.07,75.47],[-110.5,76.43],[-109.58,76.79],[-108.55,76.68],[-108.21,76.2],[-107.82,75.85]]],[[[-106.52,73.08],[-105.4,72.67],[-104.77,71.7],[-104.46,70.99],[-102.79,70.5],[-100.98,70.02],[-101.09,69.58],[-102.73,69.5],[-102.09,69.12],[-102.43,68.75],[-104.24,68.91],[-105.96,69.18],[-107.12,69.12],[-109,68.78],[-111.53,68.63],[-113.31,68.54],[-113.85,69.01],[-115.22,69.28],[-116.11,69.17],[-117.34,69.96],[-116.67,70.07],[-115.13,70.24],[-113.72,70.19],[-112.42,70.37],[-114.35,70.6],[-116.49,70.52],[-117.9,70.54],[-118.43,70.91],[-116.11,71.31],[-117.66,71.3],[-119.4,71.56],[-118.56,72.31],[-117.87,72.71],[-115.19,73.31],[-114.17,73.12],[-114.67,72.65],[-112.44,72.96],[-111.05,72.45],[-109.92,72.96],[-109.01,72.63],[-108.19,71.65],[-107.69,72.07],[-108.4,73.09],[-107.52,73.24],[-106.52,73.08]]],[[[-100.44,72.71],[-101.54,73.36],[-100.36,73.84],[-99.16,73.63],[-97.38,73.76],[-97.12,73.47],[-98.05,72.99],[-96.54,72.56],[-96.72,71.66],[-98.36,71.27],[-99.32,71.36],[-100.01,71.74],[-102.5,72.51],[-102.48,72.83],[-100.44,72.71]]],[[[-106.6,73.6],[-105.26,73.64],[-104.5,73.42],[-105.38,72.76],[-106.94,73.46],[-106.6,73.6]]],[[[-98.5,76.72],[-97.74,76.26],[-97.7,75.74],[-98.16,75],[-99.81,74.9],[-100.88,75.06],[-100.86,75.64],[-102.5,75.56],[-102.57,76.34],[-101.49,76.31],[-99.98,76.65],[-98.58,76.59],[-98.5,76.72]]],[[[-96.02,80.6],[-95.32,80.91],[-94.3,80.98],[-94.74,81.21],[-92.41,81.26],[-91.13,80.72],[-89.45,80.51],[-87.81,80.32],[-87.02,79.66],[-85.81,79.34],[-87.19,79.04],[-89.04,78.29],[-90.8,78.22],[-92.88,78.34],[-93.95,78.75],[-93.94,79.11],[-93.15,79.38],[-94.97,79.37],[-96.08,79.71],[-96.71,80.16],[-96.02,80.6]]],[[[-91.59,81.89],[-90.1,82.08],[-88.93,82.12],[-86.97,82.28],[-85.5,82.65],[-84.26,82.6],[-83.18,82.32],[-82.42,82.86],[-81.1,83.02],[-79.31,83.13],[-76.25,83.17],[-75.72,83.06],[-72.83,83.23],[-70.67,83.17],[-68.5,83.11],[-65.83,83.03],[-63.68,82.9],[-61.85,82.63],[-61.89,82.36],[-64.33,81.93],[-66.75,81.73],[-67.66,81.5],[-65.48,81.51],[-67.84,80.9],[-69.47,80.62],[-71.18,79.8],[-73.24,79.63],[-73.88,79.43],[-76.91,79.32],[-75.53,79.2],[-76.22,79.02],[-75.39,78.53],[-76.34,78.18],[-77.89,77.9],[-78.36,77.51],[-79.76,77.21],[-79.62,76.98],[-77.91,77.02],[-77.89,76.78],[-80.56,76.18],[-83.17,76.45],[-86.11,76.3],[-87.6,76.42],[-89.49,76.47],[-89.62,76.95],[-87.77,77.18],[-88.26,77.9],[-87.65,77.97],[-84.98,77.54],[-86.34,78.18],[-87.96,78.37],[-87.15,78.76],[-85.38,79.0],[-85.09,79.35],[-86.51,79.74],[-86.93,80.25],[-84.2,80.21],[-83.41,80.1],[-81.85,80.46],[-84.1,80.58],[-87.6,80.52],[-89.37,80.86],[-90.2,81.26],[-91.37,81.55],[-91.59,81.89]]],[[[-75.22,67.44],[-75.87,67.15],[-76.99,67.1],[-77.24,67.59],[-76.81,68.15],[-75.9,68.29],[-75.11,68.01],[-75.1,67.58],[-75.22,67.44]]],[[[-96.26,69.49],[-95.65,69.11],[-96.27,68.76],[-97.62,69.06],[-98.43,68.95],[-99.8,69.4],[-98.92,69.71],[-98.22,70.14],[-97.16,69.86],[-96.56,69.68],[-96.26,69.49]]],[[[-64.52,49.87],[-64.17,49.96],[-62.86,49.71],[-61.84,49.29],[-61.81,49.11],[-62.29,49.09],[-63.59,49.4],[-64.52,49.87]]],[[[-64.01,47.04],[-63.66,46.55],[-62.94,46.42],[-62.01,46.44],[-62.5,46.03],[-62.87,45.97],[-64.14,46.39],[-64.39,46.73],[-64.01,47.04]]]]}},{"type":"Feature","properties":{"name":"United States of America","iso":"US"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-122.84,49],[-120,49],[-117.03,49],[-116.05,49],[-113,49],[-110.05,49],[-107.05,49],[-104.05,49.0],[-100.65,49],[-97.23,49.0],[-95.16,49],[-95.16,49.38],[-94.82,49.39],[-94.64,48.84],[-94.33,48.67],[-93.63,48.61],[-92.61,48.45],[-91.64,48.14],[-90.83,48.27],[-89.6,48.01],[-89.27,48.02],[-88.38,48.3],[-87.44,47.94],[-86.46,47.55],[-85.65,47.22],[-84.88,46.9],[-84.78,46.64],[-84.54,46.54],[-84.6,46.44],[-84.34,46.41],[-84.14,46.51],[-84.09,46.28],[-83.89,46.12],[-83.62,46.12],[-83.47,45.99],[-83.59,45.82],[-82.55,45.35],[-82.34,44.44],[-82.14,43.57],[-82.43,42.98],[-82.9,42.43],[-83.12,42.08],[-83.14,41.98],[-83.03,41.83],[-82.69,41.68],[-82.44,41.68],[-81.28,42.21],[-80.25,42.37],[-78.94,42.86],[-78.92,42.97],[-79.01,43.27],[-79.17,43.47],[-78.72,43.63],[-77.74,43.63],[-76.82,43.63],[-76.5,44.02],[-76.38,44.1],[-75.32,44.82],[-74.87,45.0],[-73.35,45.01],[-71.51,45.01],[-71.41,45.26],[-71.08,45.31],[-70.66,45.46],[-70.31,45.91],[-70.0,46.69],[-69.24,47.45],[-68.91,47.19],[-68.23,47.35],[-67.79,47.07],[-67.79,45.7],[-67.14,45.14],[-66.96,44.81],[-68.03,44.33],[-69.06,43.98],[-70.12,43.68],[-70.65,43.09],[-70.81,42.87],[-70.83,42.34],[-70.5,41.8],[-70.08,41.78],[-70.19,42.15],[-69.88,41.92],[-69.97,41.64],[-70.64,41.48],[-71.12,41.49],[-71.86,41.32],[-72.3,41.27],[-72.88,41.22],[-73.71,40.93],[-72.24,41.12],[-71.94,40.93],[-73.34,40.63],[-73.98,40.63],[-73.95,40.75],[-74.26,40.47],[-73.96,40.43],[-74.18,39.71],[-74.91,38.94],[-74.98,39.2],[-75.2,39.25],[-75.53,39.5],[-75.32,38.96],[-75.07,38.78],[-75.06,38.4],[-75.38,38.02],[-75.94,37.22],[-76.03,37.26],[-75.72,37.94],[-76.23,38.32],[-76.35,39.15],[-76.54,38.72],[-76.33,38.08],[-76.99,38.24],[-76.3,37.92],[-76.26,36.97],[-75.97,36.9],[-75.87,36.55],[-75.73,35.55],[-76.36,34.81],[-77.4,34.51],[-78.05,33.93],[-78.55,33.86],[-79.06,33.49],[-79.2,33.16],[-80.3,32.51],[-80.86,32.03],[-81.34,31.44],[-81.49,30.73],[-81.31,30.04],[-80.98,29.18],[-80.54,28.47],[-80.53,28.04],[-80.06,26.88],[-80.09,26.21],[-80.13,25.82],[-80.38,25.21],[-80.68,25.08],[-81.17,25.2],[-81.33,25.64],[-81.71,25.87],[-82.24,26.73],[-82.71,27.5],[-82.86,27.89],[-82.65,28.55],[-82.93,29.1],[-83.71,29.94],[-84.1,30.09],[-85.11,29.64],[-85.29,29.69],[-85.77,30.15],[-86.4,30.4],[-87.53,30.27],[-88.42,30.38],[-89.18,30.32],[-89.59,30.16],[-89.41,29.89],[-89.43,29.49],[-89.22,29.29],[-89.41,29.16],[-89.78,29.31],[-90.15,29.12],[-90.88,29.15],[-91.63,29.68],[-92.5,29.55],[-93.23,29.78],[-93.85,29.71],[-94.69,29.48],[-95.6,28.74],[-96.59,28.31],[-97.14,27.83],[-97.37,27.38],[-97.38,26.69],[-97.33,26.21],[-97.14,25.87],[-97.53,25.84],[-98.24,26.06],[-99.02,26.37],[-99.3,26.84],[-99.52,27.54],[-100.11,28.11],[-100.46,28.7],[-100.96,29.38],[-101.66,29.78],[-102.48,29.76],[-103.11,28.97],[-103.94,29.27],[-104.46,29.57],[-104.71,30.12],[-105.04,30.64],[-105.63,31.08],[-106.14,31.4],[-106.51,31.75],[-108.24,31.75],[-108.24,31.34],[-109.03,31.34],[-111.02,31.33],[-113.3,32.04],[-114.81,32.53],[-114.72,32.72],[-115.99,32.61],[-117.13,32.54],[-117.3,33.05],[-117.94,33.62],[-118.41,33.74],[-118.52,34.03],[-119.08,34.08],[-119.44,34.35],[-120.37,34.45],[-120.62,34.61],[-120.74,35.16],[-121.71,36.16],[-122.55,37.55],[-122.51,37.78],[-122.95,38.11],[-123.73,38.95],[-123.87,39.77],[-124.4,40.31],[-124.18,41.14],[-124.21,42.0],[-124.53,42.77],[-124.14,43.71],[-124.02,44.62],[-123.9,45.52],[-124.08,46.86],[-124.4,47.72],[-124.69,48.18],[-124.57,48.38],[-123.12,48.04],[-122.59,47.1],[-122.34,47.36],[-122.5,48.18],[-122.84,49]]],[[[-155.4,20.08],[-155.22,19.99],[-155.06,19.86],[-154.81,19.51],[-154.83,19.45],[-155.22,19.24],[-155.54,19.08],[-155.69,18.92],[-155.94,19.06],[-155.91,19.34],[-156.07,19.7],[-156.02,19.81],[-155.85,19.98],[-155.92,20.17],[-155.86,20.27],[-155.79,20.25],[-155.4,20.08]]],[[[-156.0,20.76],[-156.08,20.64],[-156.41,20.57],[-156.59,20.78],[-156.7,20.86],[-156.71,20.93],[-156.61,21.01],[-156.26,20.92],[-156.0,20.76]]],[[[-156.76,21.18],[-156.79,21.07],[-157.33,21.1],[-157.25,21.22],[-156.76,21.18]]],[[[-158.03,21.72],[-157.94,21.65],[-157.65,21.32],[-157.71,21.26],[-157.78,21.28],[-158.13,21.31],[-158.25,21.54],[-158.29,21.58],[-158.03,21.72]]],[[[-159.37,22.21],[-159.35,21.98],[-159.46,21.88],[-159.8,22.07],[-159.75,22.14],[-159.6,22.24],[-159.37,22.21]]],[[[-166.47,60.38],[-165.67,60.29],[-165.58,59.91],[-166.19,59.75],[-166.85,59.94],[-167.46,60.21],[-166.47,60.38]]],[[[-153.23,57.97],[-152.56,57.9],[-152.14,57.59],[-153.01,57.12],[-154.01,56.73],[-154.52,56.99],[-154.67,57.46],[-153.76,57.82],[-153.23,57.97]]],[[[-140.99,69.71],[-140.99,66.0],[-141.0,60.31],[-140.01,60.28],[-139.04,60],[-138.34,59.56],[-137.45,58.91],[-136.48,59.46],[-135.48,59.79],[-134.94,59.27],[-134.27,58.86],[-133.36,58.41],[-132.73,57.69],[-131.71,56.55],[-130.01,55.92],[-129.98,55.28],[-130.54,54.8],[-131.09,55.18],[-131.97,55.5],[-132.25,56.37],[-133.54,57.18],[-134.08,58.12],[-135.04,58.19],[-136.63,58.21],[-137.8,58.5],[-139.87,59.54],[-140.83,59.73],[-142.57,60.08],[-143.96,60.0],[-145.93,60.46],[-147.11,60.88],[-148.22,60.67],[-148.02,59.98],[-148.57,59.91],[-149.73,59.71],[-150.61,59.37],[-151.72,59.16],[-151.86,59.74],[-151.41,60.73],[-150.35,61.03],[-150.62,61.28],[-151.9,60.73],[-152.58,60.06],[-154.02,59.35],[-153.29,58.86],[-154.23,58.15],[-155.31,57.73],[-156.31,57.42],[-156.56,56.98],[-158.12,56.46],[-158.43,55.99],[-159.6,55.57],[-160.29,55.64],[-161.22,55.36],[-162.24,55.02],[-163.07,54.69],[-164.79,54.4],[-164.94,54.57],[-163.85,55.04],[-162.87,55.35],[-161.8,55.89],[-160.56,56.01],[-160.07,56.42],[-158.68,57.02],[-158.46,57.22],[-157.72,57.57],[-157.55,58.33],[-157.04,58.92],[-158.19,58.62],[-158.52,58.79],[-159.06,58.42],[-159.71,58.93],[-159.98,58.57],[-160.36,59.07],[-161.36,58.67],[-161.97,58.67],[-162.05,59.27],[-161.87,59.63],[-162.52,59.99],[-163.82,59.8],[-164.66,60.27],[-165.35,60.51],[-165.35,61.07],[-166.12,61.5],[-165.73,62.07],[-164.92,62.63],[-164.56,63.15],[-163.75,63.22],[-163.07,63.06],[-162.26,63.54],[-161.53,63.46],[-160.77,63.77],[-160.96,64.22],[-161.52,64.4],[-160.78,64.79],[-161.39,64.78],[-162.45,64.56],[-162.76,64.34],[-163.55,64.56],[-164.96,64.45],[-166.43,64.69],[-166.85,65.09],[-168.11,65.67],[-166.71,66.09],[-164.47,66.58],[-163.65,66.58],[-163.79,66.08],[-161.68,66.12],[-162.49,66.74],[-163.72,67.12],[-164.43,67.62],[-165.39,68.04],[-166.76,68.36],[-166.2,68.88],[-164.43,68.92],[-163.17,69.37],[-162.93,69.86],[-161.91,70.33],[-160.93,70.45],[-159.04,70.89],[-158.12,70.82],[-156.58,71.36],[-155.07,71.15],[-154.34,70.7],[-153.9,70.89],[-152.21,70.83],[-152.27,70.6],[-150.74,70.43],[-149.72,70.53],[-147.61,70.21],[-145.69,70.12],[-144.92,69.99],[-143.59,70.15],[-142.07,69.85],[-140.99,69.71]]],[[[-171.73,63.78],[-171.11,63.59],[-170.49,63.69],[-169.68,63.43],[-168.69,63.3],[-168.77,63.19],[-169.53,62.98],[-170.29,63.19],[-170.67,63.38],[-171.55,63.32],[-171.79,63.41],[-171.73,63.78]]]]}},{"type":"Feature","properties":{"name":"Kazakhstan","iso":"KZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[87.36,49.21],[86.6,48.55],[85.77,48.46],[85.72,47.45],[85.16,47.0],[83.18,47.33],[82.46,45.54],[81.95,45.32],[79.97,44.92],[80.87,43.18],[80.18,42.92],[80.26,42.35],[79.64,42.5],[79.14,42.86],[77.66,42.96],[76.0,42.99],[75.64,42.88],[74.21,43.3],[73.65,43.09],[73.49,42.5],[71.84,42.85],[71.19,42.7],[70.96,42.27],[70.39,42.08],[69.07,41.38],[68.63,40.67],[68.26,40.66],[67.99,41.14],[66.71,41.17],[66.51,41.99],[66.02,41.99],[66.1,43.0],[64.9,43.73],[63.19,43.65],[62.01,43.5],[61.06,44.41],[60.24,44.78],[58.69,45.5],[58.5,45.59],[55.93,45.0],[55.97,41.31],[55.46,41.26],[54.76,42.04],[54.08,42.32],[52.94,42.12],[52.5,41.78],[52.45,42.03],[52.69,42.44],[52.5,42.79],[51.34,43.13],[50.89,44.03],[50.34,44.28],[50.31,44.61],[51.28,44.51],[51.32,45.25],[52.17,45.41],[53.04,45.26],[53.22,46.23],[53.04,46.85],[52.04,46.8],[51.19,47.05],[50.03,46.61],[49.1,46.4],[48.59,46.56],[48.69,47.08],[48.06,47.74],[47.32,47.72],[46.47,48.39],[47.04,49.15],[46.75,49.36],[47.55,50.45],[48.58,49.87],[48.7,50.61],[50.77,51.69],[52.33,51.72],[54.53,51.03],[55.72,50.62],[56.78,51.04],[58.36,51.06],[59.64,50.55],[59.93,50.84],[61.34,50.8],[61.59,51.27],[59.97,51.96],[60.93,52.45],[60.74,52.72],[61.7,52.98],[60.98,53.66],[61.44,54.01],[65.18,54.35],[65.67,54.6],[68.17,54.97],[69.07,55.39],[70.87,55.17],[71.18,54.13],[72.22,54.38],[73.51,54.04],[73.43,53.49],[74.38,53.55],[76.89,54.49],[76.53,54.18],[77.8,53.4],[80.04,50.86],[80.57,51.39],[81.95,50.81],[83.38,51.07],[83.94,50.89],[84.42,50.31],[85.12,50.12],[85.54,49.69],[86.83,49.83],[87.36,49.21]]]]}},{"type":"Feature","properties":{"name":"Uzbekistan","iso":"UZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[55.97,41.31],[55.93,45.0],[58.5,45.59],[58.69,45.5],[60.24,44.78],[61.06,44.41],[62.01,43.5],[63.19,43.65],[64.9,43.73],[66.1,43.0],[66.02,41.99],[66.51,41.99],[66.71,41.17],[67.99,41.14],[68.26,40.66],[68.63,40.67],[69.07,41.38],[70.39,42.08],[70.96,42.27],[71.26,42.17],[70.42,41.52],[71.16,41.14],[71.87,41.39],[73.06,40.87],[71.77,40.15],[71.01,40.24],[70.6,40.22],[70.46,40.5],[70.67,40.96],[69.33,40.73],[69.01,40.09],[68.54,39.53],[67.7,39.58],[67.44,39.14],[68.18,38.9],[68.39,38.16],[67.83,37.14],[67.08,37.36],[66.52,37.36],[66.55,37.97],[65.22,38.4],[64.17,38.89],[63.52,39.36],[62.37,40.05],[61.88,41.08],[61.55,41.27],[60.47,41.22],[60.08,41.43],[59.98,42.22],[58.63,42.75],[57.79,42.17],[56.93,41.83],[57.1,41.32],[55.97,41.31]]]]}},{"type":"Feature","properties":{"name":"Papua New Guinea","iso":"PG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[141.0,-2.6],[142.74,-3.29],[144.58,-3.86],[145.27,-4.37],[145.83,-4.88],[145.98,-5.47],[147.65,-6.08],[147.89,-6.61],[146.97,-6.72],[147.19,-7.39],[148.08,-8.04],[148.73,-9.1],[149.31,-9.07],[149.27,-9.51],[150.04,-9.68],[149.74,-9.87],[150.8,-10.29],[150.69,-10.58],[150.03,-10.65],[149.78,-10.39],[148.92,-10.28],[147.91,-10.13],[147.14,-9.49],[146.57,-8.94],[146.05,-8.07],[144.74,-7.63],[143.9,-7.92],[143.29,-8.25],[143.41,-8.98],[142.63,-9.33],[142.07,-9.16],[141.03,-9.12],[141.02,-5.86],[141.0,-2.6]]],[[[152.64,-3.66],[153.02,-3.98],[153.14,-4.5],[152.83,-4.77],[152.64,-4.18],[152.41,-3.79],[151.95,-3.46],[151.38,-3.04],[150.66,-2.74],[150.94,-2.5],[151.48,-2.78],[151.82,-3.0],[152.24,-3.24],[152.64,-3.66]]],[[[151.3,-5.84],[150.75,-6.08],[150.24,-6.32],[149.71,-6.32],[148.89,-6.03],[148.32,-5.75],[148.4,-5.44],[149.3,-5.58],[149.85,-5.51],[150.0,-5.03],[150.14,-5.0],[150.24,-5.53],[150.81,-5.46],[151.09,-5.11],[151.65,-4.76],[151.54,-4.17],[152.14,-4.15],[152.34,-4.31],[152.32,-4.87],[151.98,-5.48],[151.46,-5.56],[151.3,-5.84]]],[[[154.76,-5.34],[155.06,-5.57],[155.55,-6.2],[156.02,-6.54],[155.88,-6.82],[155.6,-6.92],[155.17,-6.54],[154.73,-5.9],[154.51,-5.14],[154.65,-5.04],[154.76,-5.34]]]]}},{"type":"Feature","properties":{"name":"Indonesia","iso":"ID"},"geometry":{"type":"MultiPolygon","coordinates":[[[[141.0,-2.6],[141.02,-5.86],[141.03,-9.12],[140.14,-8.3],[139.13,-8.1],[138.88,-8.38],[137.61,-8.41],[138.04,-7.6],[138.67,-7.32],[138.41,-6.23],[137.93,-5.39],[135.99,-4.55],[135.16,-4.46],[133.66,-3.54],[133.37,-4.02],[132.98,-4.11],[132.76,-3.75],[132.75,-3.31],[131.99,-2.82],[133.07,-2.46],[133.78,-2.48],[133.7,-2.21],[132.23,-2.21],[131.84,-1.62],[130.94,-1.43],[130.52,-0.94],[131.87,-0.7],[132.38,-0.37],[133.99,-0.78],[134.14,-1.15],[134.42,-2.77],[135.46,-3.37],[136.29,-2.31],[137.44,-1.7],[138.33,-1.7],[139.18,-2.05],[139.93,-2.41],[141.0,-2.6]]],[[[124.97,-8.89],[125.07,-9.09],[125.09,-9.39],[124.44,-10.14],[123.58,-10.36],[123.46,-10.24],[123.55,-9.9],[123.98,-9.29],[124.97,-8.89]]],[[[134.21,-6.9],[134.11,-6.14],[134.29,-5.78],[134.5,-5.45],[134.73,-5.74],[134.72,-6.21],[134.21,-6.9]]],[[[117.88,4.14],[117.31,3.23],[118.05,2.29],[117.88,1.83],[119.0,0.9],[117.81,0.78],[117.48,0.1],[117.52,-0.8],[116.56,-1.49],[116.53,-2.48],[116.15,-4.01],[116.0,-3.66],[114.86,-4.11],[114.47,-3.5],[113.76,-3.44],[113.26,-3.12],[112.07,-3.48],[111.7,-2.99],[111.05,-3.05],[110.22,-2.93],[110.07,-1.59],[109.57,-1.31],[109.09,-0.46],[108.95,0.42],[109.07,1.34],[109.66,2.01],[109.83,1.34],[110.51,0.77],[111.16,0.98],[111.8,0.9],[112.38,1.41],[112.86,1.5],[113.81,1.22],[114.62,1.43],[115.13,2.82],[115.52,3.17],[115.87,4.31],[117.02,4.31],[117.88,4.14]]],[[[129.37,-2.8],[130.47,-3.09],[130.83,-3.86],[129.99,-3.45],[129.16,-3.36],[128.59,-3.43],[127.9,-3.39],[128.14,-2.84],[129.37,-2.8]]],[[[126.87,-3.79],[126.18,-3.61],[125.99,-3.18],[127.0,-3.13],[127.25,-3.46],[126.87,-3.79]]],[[[127.93,2.17],[128.0,1.63],[128.59,1.54],[128.69,1.13],[128.64,0.26],[128.12,0.36],[127.97,-0.25],[128.38,-0.78],[128.1,-0.9],[127.7,-0.27],[127.4,1.01],[127.6,1.81],[127.93,2.17]]],[[[122.93,0.88],[124.08,0.92],[125.07,1.64],[125.24,1.42],[124.44,0.43],[123.69,0.24],[122.72,0.43],[121.06,0.38],[120.18,0.24],[120.04,-0.52],[120.94,-1.41],[121.48,-0.96],[123.34,-0.62],[123.26,-1.08],[122.82,-0.93],[122.39,-1.52],[121.51,-1.9],[122.45,-3.19],[122.27,-3.53],[123.17,-4.68],[123.16,-5.34],[122.63,-5.63],[122.24,-5.28],[122.72,-4.46],[121.74,-4.85],[121.49,-4.57],[121.62,-4.19],[120.9,-3.6],[120.97,-2.63],[120.31,-2.93],[120.39,-4.1],[120.43,-5.53],[119.8,-5.67],[119.37,-5.38],[119.65,-4.46],[119.5,-3.49],[119.08,-3.49],[118.77,-2.8],[119.18,-2.15],[119.32,-1.35],[119.83,0.15],[120.04,0.57],[120.89,1.31],[121.67,1.01],[122.93,0.88]]],[[[120.3,-10.26],[118.97,-9.56],[119.9,-9.36],[120.43,-9.67],[120.78,-9.97],[120.72,-10.24],[120.3,-10.26]]],[[[121.34,-8.54],[122.01,-8.46],[122.9,-8.09],[122.76,-8.65],[121.25,-8.93],[119.92,-8.81],[119.92,-8.44],[120.72,-8.24],[121.34,-8.54]]],[[[118.26,-8.36],[118.88,-8.28],[119.13,-8.71],[117.97,-8.91],[117.28,-9.04],[116.74,-9.03],[117.08,-8.46],[117.63,-8.45],[117.9,-8.1],[118.26,-8.36]]],[[[108.49,-6.42],[108.62,-6.78],[110.54,-6.88],[110.76,-6.47],[112.61,-6.95],[112.98,-7.59],[114.48,-7.78],[115.71,-8.37],[114.56,-8.75],[113.46,-8.35],[112.56,-8.38],[111.52,-8.3],[110.59,-8.12],[109.43,-7.74],[108.69,-7.64],[108.28,-7.77],[106.45,-7.35],[106.28,-6.92],[105.37,-6.85],[106.05,-5.9],[107.27,-5.95],[108.07,-6.35],[108.49,-6.42]]],[[[104.37,-1.08],[104.54,-1.78],[104.89,-2.34],[105.62,-2.43],[106.11,-3.06],[105.86,-4.31],[105.82,-5.85],[104.71,-5.87],[103.87,-5.04],[102.58,-4.22],[102.16,-3.61],[101.4,-2.8],[100.9,-2.05],[100.14,-0.65],[99.26,0.18],[98.97,1.04],[98.6,1.82],[97.7,2.45],[97.18,3.31],[96.42,3.87],[95.38,4.97],[95.29,5.48],[95.94,5.44],[97.48,5.25],[98.37,4.27],[99.14,3.59],[99.69,3.17],[100.64,2.1],[101.66,2.08],[102.5,1.4],[103.08,0.56],[103.84,0.1],[103.44,-0.71],[104.01,-1.06],[104.37,-1.08]]]]}},{"type":"Feature","properties":{"name":"Argentina","iso":"AR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-68.63,-52.64],[-68.25,-53.1],[-67.75,-53.85],[-66.45,-54.45],[-65.05,-54.7],[-65.5,-55.2],[-66.45,-55.25],[-66.96,-54.9],[-67.56,-54.87],[-68.63,-54.87],[-68.63,-52.64]]],[[[-57.63,-30.22],[-57.87,-31.02],[-58.14,-32.04],[-58.13,-33.04],[-58.35,-33.26],[-58.43,-33.91],[-58.5,-34.43],[-57.23,-35.29],[-57.36,-35.98],[-56.74,-36.41],[-56.79,-36.9],[-57.75,-38.18],[-59.23,-38.72],[-61.24,-38.93],[-62.34,-38.83],[-62.13,-39.42],[-62.33,-40.17],[-62.15,-40.68],[-62.75,-41.03],[-63.77,-41.17],[-64.73,-40.8],[-65.12,-41.06],[-64.98,-42.06],[-64.3,-42.36],[-63.76,-42.04],[-63.46,-42.56],[-64.38,-42.87],[-65.18,-43.5],[-65.33,-44.5],[-65.57,-45.04],[-66.51,-45.04],[-67.29,-45.55],[-67.58,-46.3],[-66.6,-47.03],[-65.64,-47.24],[-65.99,-48.13],[-67.17,-48.7],[-67.82,-49.87],[-68.73,-50.26],[-69.14,-50.73],[-68.82,-51.77],[-68.15,-52.35],[-68.57,-52.3],[-69.5,-52.14],[-71.91,-52.01],[-72.33,-51.43],[-72.31,-50.68],[-72.98,-50.74],[-73.33,-50.38],[-73.42,-49.32],[-72.65,-48.88],[-72.33,-48.24],[-72.45,-47.74],[-71.92,-46.88],[-71.55,-45.56],[-71.66,-44.97],[-71.22,-44.78],[-71.33,-44.41],[-71.79,-44.21],[-71.46,-43.79],[-71.92,-43.41],[-72.15,-42.25],[-71.75,-42.05],[-71.92,-40.83],[-71.68,-39.81],[-71.41,-38.92],[-70.81,-38.55],[-71.12,-37.58],[-71.12,-36.66],[-70.36,-36.01],[-70.39,-35.17],[-69.82,-34.19],[-69.81,-33.27],[-70.07,-33.09],[-70.54,-31.37],[-69.92,-30.34],[-70.01,-29.37],[-69.66,-28.46],[-69.0,-27.52],[-68.3,-26.9],[-68.59,-26.51],[-68.39,-26.19],[-68.42,-24.52],[-67.33,-24.03],[-66.99,-22.99],[-67.11,-22.74],[-66.27,-21.83],[-64.96,-22.08],[-64.38,-22.8],[-63.99,-21.99],[-62.85,-22.03],[-62.69,-22.25],[-60.85,-23.88],[-60.03,-24.03],[-58.81,-24.77],[-57.78,-25.16],[-57.63,-25.6],[-58.62,-27.12],[-57.61,-27.4],[-56.49,-27.55],[-55.7,-27.39],[-54.79,-26.62],[-54.63,-25.74],[-54.13,-25.55],[-53.63,-26.12],[-53.65,-26.92],[-54.49,-27.47],[-55.16,-27.88],[-56.29,-28.85],[-57.63,-30.22]]]]}},{"type":"Feature","properties":{"name":"Chile","iso":"CL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-68.63,-52.64],[-68.63,-54.87],[-67.56,-54.87],[-66.96,-54.9],[-67.29,-55.3],[-68.15,-55.61],[-68.64,-55.58],[-69.23,-55.5],[-69.96,-55.2],[-71.01,-55.05],[-72.26,-54.5],[-73.29,-53.96],[-74.66,-52.84],[-73.84,-53.05],[-72.43,-53.72],[-71.11,-54.07],[-70.59,-53.62],[-70.27,-52.93],[-69.35,-52.52],[-68.63,-52.64]]],[[[-69.59,-17.58],[-69.1,-18.26],[-68.97,-18.98],[-68.44,-19.41],[-68.76,-20.37],[-68.22,-21.49],[-67.83,-22.87],[-67.11,-22.74],[-66.99,-22.99],[-67.33,-24.03],[-68.42,-24.52],[-68.39,-26.19],[-68.59,-26.51],[-68.3,-26.9],[-69.0,-27.52],[-69.66,-28.46],[-70.01,-29.37],[-69.92,-30.34],[-70.54,-31.37],[-70.07,-33.09],[-69.81,-33.27],[-69.82,-34.19],[-70.39,-35.17],[-70.36,-36.01],[-71.12,-36.66],[-71.12,-37.58],[-70.81,-38.55],[-71.41,-38.92],[-71.68,-39.81],[-71.92,-40.83],[-71.75,-42.05],[-72.15,-42.25],[-71.92,-43.41],[-71.46,-43.79],[-71.79,-44.21],[-71.33,-44.41],[-71.22,-44.78],[-71.66,-44.97],[-71.55,-45.56],[-71.92,-46.88],[-72.45,-47.74],[-72.33,-48.24],[-72.65,-48.88],[-73.42,-49.32],[-73.33,-50.38],[-72.98,-50.74],[-72.31,-50.68],[-72.33,-51.43],[-71.91,-52.01],[-69.5,-52.14],[-68.57,-52.3],[-69.46,-52.29],[-69.94,-52.54],[-70.85,-52.9],[-71.01,-53.83],[-71.43,-53.86],[-72.56,-53.53],[-73.7,-52.84],[-74.95,-52.26],[-75.26,-51.63],[-74.98,-51.04],[-75.48,-50.38],[-75.61,-48.67],[-75.18,-47.71],[-74.13,-46.94],[-75.64,-46.65],[-74.69,-45.76],[-74.35,-44.1],[-73.24,-44.45],[-72.72,-42.38],[-73.39,-42.12],[-73.7,-43.37],[-74.33,-43.22],[-74.02,-41.79],[-73.68,-39.94],[-73.22,-39.26],[-73.51,-38.28],[-73.59,-37.16],[-73.17,-37.12],[-72.55,-35.51],[-71.86,-33.91],[-71.44,-32.42],[-71.67,-30.92],[-71.37,-30.1],[-71.49,-28.86],[-70.91,-27.64],[-70.72,-25.71],[-70.4,-23.63],[-70.09,-21.39],[-70.16,-19.76],[-70.37,-18.35],[-69.86,-18.09],[-69.59,-17.58]]]]}},{"type":"Feature","properties":{"name":"Dem. Rep. Congo","iso":"CD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[29.34,-4.5],[29.52,-5.42],[29.42,-5.94],[29.62,-6.52],[30.2,-7.08],[30.74,-8.34],[30.35,-8.24],[29.0,-8.41],[28.73,-8.53],[28.45,-9.16],[28.67,-9.61],[28.5,-10.79],[28.37,-11.79],[28.64,-11.97],[29.34,-12.36],[29.62,-12.18],[29.7,-13.26],[28.93,-13.25],[28.52,-12.7],[28.16,-12.27],[27.39,-12.13],[27.16,-11.61],[26.55,-11.92],[25.75,-11.78],[25.42,-11.33],[24.78,-11.24],[24.31,-11.26],[24.26,-10.95],[23.91,-10.93],[23.46,-10.87],[22.84,-11.02],[22.4,-10.99],[22.16,-11.08],[22.21,-9.89],[21.88,-9.52],[21.8,-8.91],[21.95,-8.31],[21.75,-7.92],[21.73,-7.29],[20.51,-7.3],[20.6,-6.94],[20.09,-6.94],[20.04,-7.12],[19.42,-7.16],[19.17,-7.74],[19.02,-7.99],[18.46,-7.85],[18.13,-7.99],[17.47,-8.07],[17.09,-7.55],[16.86,-7.22],[16.57,-6.62],[16.33,-5.88],[13.38,-5.86],[13.02,-5.98],[12.74,-5.97],[12.32,-6.1],[12.18,-5.79],[12.44,-5.68],[12.47,-5.25],[12.63,-4.99],[13.0,-4.78],[13.26,-4.88],[13.6,-4.5],[14.14,-4.51],[14.21,-4.79],[14.58,-4.97],[15.17,-4.34],[15.75,-3.86],[16.01,-3.54],[15.97,-2.71],[16.41,-1.74],[16.87,-1.23],[17.52,-0.74],[17.64,-0.42],[17.66,-0.06],[17.83,0.29],[17.77,0.86],[17.9,1.74],[18.09,2.37],[18.39,2.9],[18.45,3.5],[18.54,4.2],[18.93,4.71],[19.47,5.03],[20.29,4.69],[20.93,4.32],[21.66,4.22],[22.41,4.03],[22.7,4.63],[22.84,4.71],[23.3,4.61],[24.41,5.11],[24.81,4.9],[25.13,4.93],[25.28,5.17],[25.65,5.26],[26.4,5.15],[27.04,5.13],[27.37,5.23],[27.98,4.41],[28.43,4.29],[28.7,4.46],[29.16,4.39],[29.72,4.6],[29.95,4.17],[30.83,3.51],[30.77,2.34],[31.17,2.2],[30.85,1.85],[30.47,1.58],[30.09,1.06],[29.88,0.6],[29.82,-0.21],[29.59,-0.59],[29.58,-1.34],[29.29,-1.62],[29.25,-2.22],[29.12,-2.29],[29.02,-2.84],[29.28,-3.29],[29.34,-4.5]]]]}},{"type":"Feature","properties":{"name":"Somalia","iso":"SO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[41.59,-1.68],[40.99,-0.86],[40.98,2.78],[41.86,3.92],[42.13,4.23],[42.77,4.25],[43.66,4.96],[44.96,5.0],[47.79,8.0],[48.49,8.84],[48.94,9.45],[48.94,9.97],[48.94,10.98],[48.94,11.39],[48.95,11.41],[49.27,11.43],[49.73,11.58],[50.26,11.68],[50.73,12.02],[51.11,12.02],[51.13,11.75],[51.04,11.17],[51.05,10.64],[50.83,10.28],[50.55,9.2],[50.07,8.08],[49.45,6.8],[48.59,5.34],[47.74,4.22],[46.56,2.86],[45.56,2.05],[44.07,1.05],[43.14,0.29],[42.04,-0.92],[41.81,-1.45],[41.59,-1.68]]]]}},{"type":"Feature","properties":{"name":"Kenya","iso":"KE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[39.2,-4.68],[37.77,-3.68],[37.7,-3.1],[34.07,-1.06],[33.9,-0.95],[33.89,0.11],[34.18,0.52],[34.67,1.18],[35.04,1.91],[34.6,3.05],[34.48,3.56],[34.01,4.25],[34.62,4.85],[35.3,5.51],[35.82,5.34],[35.82,4.78],[36.16,4.45],[36.86,4.45],[38.12,3.6],[38.44,3.59],[38.67,3.62],[38.89,3.5],[39.56,3.42],[39.85,3.84],[40.77,4.26],[41.17,3.92],[41.86,3.92],[40.98,2.78],[40.99,-0.86],[41.59,-1.68],[40.88,-2.08],[40.64,-2.5],[40.26,-2.57],[40.12,-3.28],[39.8,-3.68],[39.6,-4.35],[39.2,-4.68]]]]}},{"type":"Feature","properties":{"name":"Sudan","iso":"SD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[24.57,8.23],[23.81,8.67],[23.46,8.95],[23.39,9.27],[23.56,9.68],[23.55,10.09],[22.98,10.71],[22.86,11.14],[22.88,11.38],[22.51,11.68],[22.5,12.26],[22.29,12.65],[21.94,12.59],[22.04,12.96],[22.3,13.37],[22.18,13.79],[22.51,14.09],[22.3,14.33],[22.57,14.94],[23.02,15.68],[23.89,15.61],[23.84,19.58],[23.85,20],[25,20.0],[25,22],[29.02,22],[32.9,22],[36.87,22],[37.19,21.02],[36.97,20.84],[37.11,19.81],[37.48,18.61],[37.86,18.37],[38.41,18.0],[37.9,17.43],[37.17,17.26],[36.85,16.96],[36.75,16.29],[36.32,14.82],[36.43,14.42],[36.27,13.56],[35.86,12.58],[35.26,12.08],[34.83,11.32],[34.73,10.91],[34.26,10.63],[33.96,9.58],[33.97,8.68],[33.96,9.46],[33.82,9.48],[33.84,9.98],[33.72,10.33],[33.21,10.72],[33.09,11.44],[33.21,12.18],[32.74,12.25],[32.67,12.02],[32.07,11.97],[32.31,11.68],[32.4,11.08],[31.85,10.53],[31.35,9.81],[30.84,9.71],[30.0,10.29],[29.62,10.08],[29.52,9.79],[29.0,9.6],[28.97,9.4],[27.97,9.4],[27.83,9.6],[27.11,9.64],[26.75,9.47],[26.48,9.55],[25.96,10.14],[25.79,10.41],[25.07,10.27],[24.79,9.81],[24.54,8.92],[24.19,8.73],[23.89,8.62],[24.57,8.23]]]]}},{"type":"Feature","properties":{"name":"Chad","iso":"TD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[23.84,19.58],[23.89,15.61],[23.02,15.68],[22.57,14.94],[22.3,14.33],[22.51,14.09],[22.18,13.79],[22.3,13.37],[22.04,12.96],[21.94,12.59],[22.29,12.65],[22.5,12.26],[22.51,11.68],[22.88,11.38],[22.86,11.14],[22.23,10.97],[21.72,10.57],[21.0,9.48],[20.06,9.01],[19.09,9.07],[18.81,8.98],[18.91,8.63],[18.39,8.28],[17.96,7.89],[16.71,7.51],[16.46,7.73],[16.29,7.75],[16.11,7.5],[15.28,7.42],[15.44,7.69],[15.12,8.38],[14.98,8.8],[14.54,8.97],[13.95,9.55],[14.17,10.02],[14.63,9.92],[14.91,9.99],[15.47,9.98],[14.92,10.89],[14.96,11.56],[14.89,12.22],[14.5,12.86],[14.6,13.33],[13.95,13.35],[13.96,14.0],[13.54,14.37],[13.97,15.68],[15.25,16.63],[15.3,17.93],[15.69,19.96],[15.9,20.39],[15.49,20.73],[15.47,21.05],[15.1,21.31],[14.85,22.86],[15.86,23.41],[19.85,21.5],[23.84,19.58]]]]}},{"type":"Feature","properties":{"name":"Haiti","iso":"HT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.71,19.71],[-71.62,19.17],[-71.7,18.79],[-71.95,18.62],[-71.69,18.32],[-71.71,18.04],[-72.37,18.21],[-72.84,18.15],[-73.45,18.22],[-73.92,18.03],[-74.46,18.34],[-74.37,18.66],[-73.45,18.53],[-72.69,18.45],[-72.33,18.67],[-72.79,19.1],[-72.78,19.48],[-73.42,19.64],[-73.19,19.92],[-72.58,19.87],[-71.71,19.71]]]]}},{"type":"Feature","properties":{"name":"Dominican Rep.","iso":"DO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.71,18.04],[-71.69,18.32],[-71.95,18.62],[-71.7,18.79],[-71.62,19.17],[-71.71,19.71],[-71.59,19.88],[-70.81,19.88],[-70.21,19.62],[-69.95,19.65],[-69.77,19.29],[-69.22,19.31],[-69.25,19.02],[-68.81,18.98],[-68.32,18.61],[-68.69,18.21],[-69.16,18.42],[-69.62,18.38],[-69.95,18.43],[-70.13,18.25],[-70.52,18.18],[-70.67,18.43],[-71.0,18.28],[-71.4,17.6],[-71.66,17.76],[-71.71,18.04]]]]}},{"type":"Feature","properties":{"name":"Russia","iso":"RU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[178.73,71.1],[180,71.52],[180,70.83],[178.9,70.78],[178.73,71.1]]],[[[49.1,46.4],[48.65,45.81],[47.68,45.64],[46.68,44.61],[47.59,43.66],[47.49,42.99],[48.58,41.81],[47.99,41.41],[47.82,41.15],[47.37,41.22],[46.69,41.83],[46.4,41.86],[45.78,42.09],[45.47,42.5],[44.54,42.71],[43.93,42.55],[43.76,42.74],[42.39,43.22],[40.92,43.38],[40.08,43.55],[39.96,43.43],[38.68,44.28],[37.54,44.66],[36.68,45.24],[37.4,45.4],[38.23,46.24],[37.67,46.64],[39.15,47.04],[39.12,47.26],[38.22,47.1],[38.26,47.55],[38.77,47.83],[39.74,47.9],[39.9,48.23],[39.67,48.78],[40.08,49.31],[40.07,49.6],[38.59,49.93],[38.01,49.92],[37.39,50.38],[36.63,50.23],[35.36,50.58],[35.38,50.77],[35.02,51.21],[34.22,51.26],[34.14,51.57],[34.39,51.77],[33.75,52.34],[32.72,52.24],[32.41,52.29],[32.16,52.06],[31.79,52.1],[31.54,52.74],[31.31,53.07],[31.5,53.17],[32.3,53.13],[32.69,53.35],[32.41,53.62],[31.73,53.79],[31.79,53.97],[31.38,54.16],[30.76,54.81],[30.97,55.08],[30.87,55.55],[29.9,55.79],[29.37,55.67],[29.23,55.92],[28.18,56.17],[27.86,56.76],[27.77,57.24],[27.29,57.47],[27.72,57.79],[27.42,58.72],[28.13,59.3],[27.98,59.48],[29.12,60.03],[28.07,60.5],[30.21,61.78],[31.14,62.36],[31.52,62.87],[30.04,63.55],[30.44,64.2],[29.54,64.95],[30.22,65.81],[29.05,66.94],[29.98,67.7],[28.45,68.36],[28.59,69.06],[29.4,69.16],[31.1,69.56],[32.13,69.91],[33.78,69.3],[36.51,69.06],[40.29,67.93],[41.06,67.46],[41.13,66.79],[40.02,66.27],[38.38,66.0],[33.92,66.76],[33.18,66.63],[34.81,65.9],[34.88,65.44],[34.94,64.41],[36.23,64.11],[37.01,63.85],[37.14,64.33],[36.54,64.76],[37.18,65.14],[39.59,64.52],[40.44,64.76],[39.76,65.5],[42.09,66.48],[43.02,66.42],[43.95,66.07],[44.53,66.76],[43.7,67.35],[44.19,67.95],[43.45,68.57],[46.25,68.25],[46.82,67.69],[45.56,67.57],[45.56,67.01],[46.35,66.67],[47.89,66.88],[48.14,67.52],[50.23,68.0],[53.72,68.86],[54.47,68.81],[53.49,68.2],[54.73,68.1],[55.44,68.44],[57.32,68.47],[58.8,68.88],[59.94,68.28],[61.08,68.94],[60.03,69.52],[60.55,69.85],[63.5,69.55],[64.89,69.23],[68.51,68.09],[69.18,68.62],[68.16,69.14],[68.14,69.36],[66.93,69.45],[67.26,69.93],[66.72,70.71],[66.69,71.03],[68.54,71.93],[69.2,72.84],[69.94,73.04],[72.59,72.78],[72.8,72.22],[71.85,71.41],[72.47,71.09],[72.79,70.39],[72.56,69.02],[73.67,68.41],[73.24,67.74],[71.28,66.32],[72.42,66.17],[72.82,66.53],[73.92,66.79],[74.19,67.28],[75.05,67.76],[74.47,68.33],[74.94,68.99],[73.84,69.07],[73.6,69.63],[74.4,70.63],[73.1,71.45],[74.89,72.12],[74.66,72.83],[75.16,72.85],[75.68,72.3],[75.29,71.34],[76.36,71.15],[75.9,71.87],[77.58,72.27],[79.65,72.32],[81.5,71.75],[80.61,72.58],[80.51,73.65],[82.25,73.85],[84.66,73.81],[86.82,73.94],[86.01,74.46],[87.17,75.12],[88.32,75.14],[90.26,75.64],[92.9,75.77],[93.23,76.05],[95.86,76.14],[96.68,75.92],[98.92,76.45],[100.76,76.43],[101.04,76.86],[101.99,77.29],[104.35,77.7],[106.07,77.37],[104.7,77.13],[106.97,76.97],[107.24,76.48],[108.15,76.72],[111.08,76.71],[113.33,76.22],[114.13,75.85],[113.89,75.33],[112.78,75.03],[110.15,74.48],[109.4,74.18],[110.64,74.04],[112.12,73.79],[113.02,73.98],[113.53,73.34],[113.97,73.59],[115.57,73.75],[118.78,73.59],[119.02,73.12],[123.2,72.97],[123.26,73.74],[125.38,73.56],[126.98,73.57],[128.59,73.04],[129.05,72.4],[128.46,71.98],[129.72,71.19],[131.29,70.79],[132.25,71.84],[133.86,71.39],[135.56,71.66],[137.5,71.35],[138.23,71.63],[139.87,71.49],[139.15,72.42],[140.47,72.85],[149.5,72.2],[150.35,71.61],[152.97,70.84],[157.01,71.03],[159.0,70.87],[159.83,70.45],[159.71,69.72],[160.94,69.44],[162.28,69.64],[164.05,69.67],[165.94,69.47],[167.84,69.58],[169.58,68.69],[170.82,69.01],[170.01,69.65],[170.45,70.1],[173.64,69.82],[175.72,69.88],[178.6,69.4],[180,68.96],[180,64.98],[179.99,64.97],[178.71,64.53],[177.41,64.61],[178.31,64.08],[178.91,63.25],[179.37,62.98],[179.49,62.57],[179.23,62.3],[177.36,62.52],[174.57,61.77],[173.68,61.65],[172.15,60.95],[170.7,60.34],[170.33,59.88],[168.9,60.57],[166.29,59.79],[165.84,60.16],[164.88,59.73],[163.54,59.87],[163.22,59.21],[162.02,58.24],[162.05,57.84],[163.19,57.62],[163.06,56.16],[162.13,56.12],[161.7,55.29],[162.12,54.86],[160.37,54.34],[160.02,53.2],[158.53,52.96],[158.23,51.94],[156.79,51.01],[156.42,51.7],[155.99,53.16],[155.43,55.38],[155.91,56.77],[156.76,57.36],[156.81,57.83],[158.36,58.06],[160.15,59.31],[161.87,60.34],[163.67,61.14],[164.47,62.55],[163.26,62.47],[162.66,61.64],[160.12,60.54],[159.3,61.77],[156.72,61.43],[154.22,59.76],[155.04,59.14],[152.81,58.88],[151.27,58.78],[151.34,59.5],[149.78,59.66],[148.54,59.16],[145.49,59.34],[142.2,59.04],[138.96,57.09],[135.13,54.73],[136.7,54.6],[137.19,53.98],[138.16,53.76],[138.8,54.25],[139.9,54.19],[141.35,53.09],[141.38,52.24],[140.6,51.24],[140.51,50.05],[140.06,48.45],[138.55,47.0],[138.22,46.31],[136.86,45.14],[135.52,43.99],[134.87,43.4],[133.54,42.81],[132.91,42.8],[132.28,43.28],[130.94,42.55],[130.78,42.22],[130.64,42.4],[130.63,42.9],[131.14,42.93],[131.29,44.11],[131.03,44.97],[131.88,45.32],[133.1,45.14],[133.77,46.12],[134.11,47.21],[134.5,47.58],[135.03,48.48],[133.37,48.18],[132.51,47.79],[130.99,47.79],[130.58,48.73],[129.4,49.44],[127.66,49.76],[127.29,50.74],[126.94,51.35],[126.56,51.78],[125.95,52.79],[125.07,53.16],[123.57,53.46],[122.25,53.43],[121.0,53.25],[120.18,52.75],[120.73,52.52],[120.74,51.96],[120.18,51.64],[119.28,50.58],[119.29,50.14],[117.88,49.51],[116.68,49.89],[115.49,49.81],[114.96,50.14],[114.36,50.25],[112.9,49.54],[111.58,49.38],[110.66,49.13],[109.4,49.29],[108.48,49.28],[107.87,49.79],[106.89,50.27],[105.89,50.41],[104.62,50.28],[103.68,50.09],[102.26,50.51],[102.07,51.26],[100.89,51.52],[99.98,51.63],[98.86,52.05],[97.83,51.01],[98.23,50.42],[97.26,49.73],[95.81,49.98],[94.82,50.01],[94.15,50.48],[93.1,50.5],[92.23,50.8],[90.71,50.33],[88.81,49.47],[87.75,49.3],[87.36,49.21],[86.83,49.83],[85.54,49.69],[85.12,50.12],[84.42,50.31],[83.94,50.89],[83.38,51.07],[81.95,50.81],[80.57,51.39],[80.04,50.86],[77.8,53.4],[76.53,54.18],[76.89,54.49],[74.38,53.55],[73.43,53.49],[73.51,54.04],[72.22,54.38],[71.18,54.13],[70.87,55.17],[69.07,55.39],[68.17,54.97],[65.67,54.6],[65.18,54.35],[61.44,54.01],[60.98,53.66],[61.7,52.98],[60.74,52.72],[60.93,52.45],[59.97,51.96],[61.59,51.27],[61.34,50.8],[59.93,50.84],[59.64,50.55],[58.36,51.06],[56.78,51.04],[55.72,50.62],[54.53,51.03],[52.33,51.72],[50.77,51.69],[48.7,50.61],[48.58,49.87],[47.55,50.45],[46.75,49.36],[47.04,49.15],[46.47,48.39],[47.32,47.72],[48.06,47.74],[48.69,47.08],[48.59,46.56],[49.1,46.4]]],[[[93.78,81.02],[95.94,81.25],[97.88,80.75],[100.19,79.78],[99.94,78.88],[97.76,78.76],[94.97,79.04],[93.31,79.43],[92.55,80.14],[91.18,80.34],[93.78,81.02]]],[[[102.84,79.28],[105.37,78.71],[105.08,78.31],[99.44,77.92],[101.26,79.23],[102.09,79.35],[102.84,79.28]]],[[[138.83,76.14],[141.47,76.09],[145.09,75.56],[144.3,74.82],[140.61,74.85],[138.96,74.61],[136.97,75.26],[137.51,75.95],[138.83,76.14]]],[[[148.22,75.35],[150.73,75.08],[149.58,74.69],[147.98,74.78],[146.12,75.17],[146.36,75.5],[148.22,75.35]]],[[[139.86,73.37],[140.81,73.77],[142.06,73.86],[143.48,73.48],[143.6,73.21],[142.09,73.21],[140.04,73.32],[139.86,73.37]]],[[[44.85,80.59],[46.8,80.77],[48.32,80.78],[48.52,80.51],[49.1,80.75],[50.04,80.92],[51.52,80.7],[51.14,80.55],[49.79,80.42],[48.89,80.34],[48.75,80.18],[47.59,80.01],[46.5,80.25],[47.07,80.56],[44.85,80.59]]],[[[22.73,54.33],[20.89,54.31],[19.66,54.43],[19.89,54.87],[21.27,55.19],[22.32,55.02],[22.76,54.86],[22.65,54.58],[22.73,54.33]]],[[[53.51,73.75],[55.9,74.63],[55.63,75.08],[57.87,75.61],[61.17,76.25],[64.5,76.44],[66.21,76.81],[68.16,76.94],[68.85,76.54],[68.18,76.23],[64.64,75.74],[61.58,75.26],[58.48,74.31],[56.99,73.33],[55.42,72.37],[55.62,71.54],[57.54,70.72],[56.94,70.63],[53.68,70.76],[53.41,71.21],[51.6,71.47],[51.46,72.01],[52.48,72.23],[52.44,72.77],[54.43,73.63],[53.51,73.75]]],[[[142.91,53.7],[143.26,52.74],[143.24,51.76],[143.65,50.75],[144.65,48.98],[143.17,49.31],[142.56,47.86],[143.53,46.84],[143.51,46.14],[142.75,46.74],[142.09,45.97],[141.91,46.81],[142.02,47.78],[141.9,48.86],[142.14,49.62],[142.18,50.95],[141.59,51.94],[141.68,53.3],[142.61,53.76],[142.21,54.23],[142.65,54.37],[142.91,53.7]]],[[[-174.93,67.21],[-175.01,66.58],[-174.34,66.34],[-174.57,67.06],[-171.86,66.91],[-169.9,65.98],[-170.89,65.54],[-172.53,65.44],[-172.56,64.46],[-172.96,64.25],[-173.89,64.28],[-174.65,64.63],[-175.98,64.92],[-176.21,65.36],[-177.22,65.52],[-178.36,65.39],[-178.9,65.74],[-178.69,66.11],[-179.88,65.87],[-179.43,65.4],[-180,64.98],[-180,68.96],[-177.55,68.2],[-174.93,67.21]]],[[[-178.69,70.89],[-180,70.83],[-180,71.52],[-179.87,71.56],[-179.02,71.56],[-177.58,71.27],[-177.66,71.13],[-178.69,70.89]]],[[[33.44,45.97],[33.7,46.22],[34.41,46.01],[34.73,45.97],[34.86,45.77],[35.01,45.74],[35.02,45.65],[35.51,45.41],[36.53,45.47],[36.33,45.11],[35.24,44.94],[33.88,44.36],[33.33,44.56],[33.55,45.03],[32.45,45.33],[32.63,45.52],[33.59,45.85],[33.44,45.97]]]]}},{"type":"Feature","properties":{"name":"Bahamas","iso":"BS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-78.98,26.79],[-78.51,26.87],[-77.85,26.84],[-77.82,26.58],[-78.91,26.42],[-78.98,26.79]]],[[[-77.79,27.04],[-77,26.59],[-77.17,25.88],[-77.36,26.01],[-77.34,26.53],[-77.79,26.93],[-77.79,27.04]]],[[[-78.19,25.21],[-77.89,25.17],[-77.54,24.34],[-77.53,23.76],[-77.78,23.71],[-78.03,24.29],[-78.41,24.58],[-78.19,25.21]]]]}},{"type":"Feature","properties":{"name":"Falkland Is.","iso":"FK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.2,-51.85],[-60,-51.25],[-59.15,-51.5],[-58.55,-51.1],[-57.75,-51.55],[-58.05,-51.9],[-59.4,-52.2],[-59.85,-51.85],[-60.7,-52.3],[-61.2,-51.85]]]]}},{"type":"Feature","properties":{"name":"Norway","iso":"NO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[15.14,79.67],[15.52,80.02],[16.99,80.05],[18.25,79.7],[21.54,78.96],[19.03,78.56],[18.47,77.83],[17.59,77.64],[17.12,76.81],[15.91,76.77],[13.76,77.38],[14.67,77.74],[13.17,78.02],[11.22,78.87],[10.44,79.65],[13.17,80.01],[13.72,79.66],[15.14,79.67]]],[[[31.1,69.56],[29.4,69.16],[28.59,69.06],[29.02,69.77],[27.73,70.16],[26.18,69.83],[25.69,69.09],[24.74,68.65],[23.66,68.89],[22.36,68.84],[21.24,69.37],[20.65,69.11],[20.03,69.07],[19.88,68.41],[17.99,68.57],[17.73,68.01],[16.77,68.01],[16.11,67.3],[15.11,66.19],[13.56,64.79],[13.92,64.45],[13.57,64.05],[12.58,64.07],[11.93,63.13],[11.99,61.8],[12.63,61.29],[12.3,60.12],[11.47,59.43],[11.03,58.86],[10.36,59.47],[8.38,58.31],[7.05,58.08],[5.67,58.59],[5.31,59.66],[4.99,61.97],[5.91,62.61],[8.55,63.45],[10.53,64.49],[12.36,65.88],[14.76,67.81],[16.44,68.56],[19.18,69.82],[21.38,70.26],[23.02,70.2],[24.55,71.03],[26.37,70.99],[28.17,71.19],[31.29,70.45],[30.01,70.19],[31.1,69.56]]],[[[27.41,80.06],[25.92,79.52],[23.02,79.4],[20.08,79.57],[19.9,79.84],[18.46,79.86],[17.37,80.32],[20.46,80.6],[21.91,80.36],[22.92,80.66],[25.45,80.41],[27.41,80.06]]],[[[24.72,77.85],[22.49,77.44],[20.73,77.68],[21.42,77.94],[20.81,78.25],[22.88,78.45],[23.28,78.08],[24.72,77.85]]]]}},{"type":"Feature","properties":{"name":"Greenland","iso":"GL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-46.76,82.63],[-43.41,83.23],[-39.9,83.18],[-38.62,83.55],[-35.09,83.65],[-27.1,83.52],[-20.85,82.73],[-22.69,82.34],[-26.52,82.3],[-31.9,82.2],[-31.4,82.02],[-27.86,82.13],[-24.84,81.79],[-22.9,82.09],[-22.07,81.73],[-23.17,81.15],[-20.62,81.52],[-15.77,81.91],[-12.77,81.72],[-12.21,81.29],[-16.29,80.58],[-16.85,80.35],[-20.05,80.18],[-17.73,80.13],[-18.9,79.4],[-19.7,78.75],[-19.67,77.64],[-18.47,76.99],[-20.04,76.94],[-21.68,76.63],[-19.83,76.1],[-19.6,75.25],[-20.67,75.16],[-19.37,74.3],[-21.59,74.22],[-20.43,73.82],[-20.76,73.46],[-22.17,73.31],[-23.57,73.31],[-22.31,72.63],[-22.3,72.18],[-24.28,72.6],[-24.79,72.33],[-23.44,72.08],[-22.13,71.47],[-21.75,70.66],[-23.54,70.47],[-24.31,70.86],[-25.54,71.43],[-25.2,70.75],[-26.36,70.23],[-23.73,70.18],[-22.35,70.13],[-25.03,69.26],[-27.75,68.47],[-30.67,68.13],[-31.78,68.12],[-32.81,67.74],[-34.2,66.68],[-36.35,65.98],[-37.04,65.94],[-38.38,65.69],[-39.81,65.46],[-40.67,64.84],[-40.68,64.14],[-41.19,63.48],[-42.82,62.68],[-42.42,61.9],[-42.87,61.07],[-43.38,60.1],[-44.79,60.04],[-46.26,60.85],[-48.26,60.86],[-49.23,61.41],[-49.9,62.38],[-51.63,63.63],[-52.14,64.28],[-52.28,65.18],[-53.66,66.1],[-53.3,66.84],[-53.97,67.19],[-52.98,68.36],[-51.48,68.73],[-51.08,69.15],[-50.87,69.93],[-52.01,69.57],[-52.56,69.43],[-53.46,69.28],[-54.68,69.61],[-54.75,70.29],[-54.36,70.82],[-53.43,70.84],[-51.39,70.57],[-53.11,71.2],[-54.0,71.55],[-55,71.41],[-55.83,71.65],[-54.72,72.59],[-55.33,72.96],[-56.12,73.65],[-57.32,74.71],[-58.6,75.1],[-58.59,75.52],[-61.27,76.1],[-63.39,76.18],[-66.06,76.13],[-68.5,76.06],[-69.66,76.38],[-71.4,77.01],[-68.78,77.32],[-66.76,77.38],[-71.04,77.64],[-73.3,78.04],[-73.16,78.43],[-69.37,78.91],[-65.71,79.39],[-65.32,79.76],[-68.02,80.12],[-67.15,80.52],[-63.69,81.21],[-62.23,81.32],[-62.65,81.77],[-60.28,82.03],[-57.21,82.19],[-54.13,82.2],[-53.04,81.89],[-50.39,82.44],[-48.0,82.06],[-46.6,81.99],[-44.52,81.66],[-46.9,82.2],[-46.76,82.63]]]]}},{"type":"Feature","properties":{"name":"Fr. S. Antarctic Lands","iso":"TF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[68.94,-48.62],[69.58,-48.94],[70.53,-49.06],[70.56,-49.26],[70.28,-49.71],[68.75,-49.77],[68.72,-49.24],[68.87,-48.83],[68.94,-48.62]]]]}},{"type":"Feature","properties":{"name":"Timor-Leste","iso":"TL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[124.97,-8.89],[125.09,-8.66],[125.95,-8.43],[126.64,-8.4],[126.96,-8.27],[127.34,-8.4],[126.97,-8.67],[125.93,-9.11],[125.09,-9.39],[125.07,-9.09],[124.97,-8.89]]]]}},{"type":"Feature","properties":{"name":"South Africa","iso":"ZA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[16.34,-28.58],[16.82,-28.08],[17.22,-28.36],[17.39,-28.78],[17.84,-28.86],[18.46,-29.05],[19.0,-28.97],[19.89,-28.46],[19.9,-24.77],[20.17,-24.92],[20.76,-25.87],[20.67,-26.48],[20.89,-26.83],[21.61,-26.73],[22.11,-26.28],[22.58,-25.98],[22.82,-25.5],[23.31,-25.27],[23.73,-25.39],[24.21,-25.67],[25.03,-25.72],[25.66,-25.49],[25.77,-25.17],[25.94,-24.7],[26.49,-24.62],[26.79,-24.24],[27.12,-23.57],[28.02,-22.83],[29.43,-22.09],[29.84,-22.1],[30.32,-22.27],[30.66,-22.15],[31.19,-22.25],[31.67,-23.66],[31.93,-24.37],[31.75,-25.48],[31.84,-25.84],[31.33,-25.66],[31.04,-25.73],[30.95,-26.02],[30.68,-26.4],[30.69,-26.74],[31.28,-27.29],[31.87,-27.18],[32.07,-26.73],[32.83,-26.74],[32.58,-27.47],[32.46,-28.3],[32.2,-28.75],[31.52,-29.26],[31.33,-29.4],[30.9,-29.91],[30.62,-30.42],[30.06,-31.14],[28.93,-32.17],[28.22,-32.77],[27.46,-33.23],[26.42,-33.61],[25.91,-33.67],[25.78,-33.94],[25.17,-33.8],[24.68,-33.99],[23.59,-33.79],[22.99,-33.92],[22.57,-33.86],[21.54,-34.26],[20.69,-34.42],[20.07,-34.8],[19.62,-34.82],[19.19,-34.46],[18.86,-34.44],[18.42,-34.0],[18.38,-34.14],[18.24,-33.87],[18.25,-33.28],[17.93,-32.61],[18.25,-32.43],[18.22,-31.66],[17.57,-30.73],[17.06,-29.88],[16.34,-28.58]],[[28.98,-28.96],[28.54,-28.65],[28.07,-28.85],[27.53,-29.24],[27.0,-29.88],[27.75,-30.65],[28.11,-30.55],[28.29,-30.23],[28.85,-30.07],[29.02,-29.74],[29.33,-29.26],[28.98,-28.96]]]]}},{"type":"Feature","properties":{"name":"Lesotho","iso":"LS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[28.98,-28.96],[29.33,-29.26],[29.02,-29.74],[28.85,-30.07],[28.29,-30.23],[28.11,-30.55],[27.75,-30.65],[27.0,-29.88],[27.53,-29.24],[28.07,-28.85],[28.54,-28.65],[28.98,-28.96]]]]}},{"type":"Feature","properties":{"name":"Mexico","iso":"MX"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-117.13,32.54],[-115.99,32.61],[-114.72,32.72],[-114.81,32.53],[-113.3,32.04],[-111.02,31.33],[-109.03,31.34],[-108.24,31.34],[-108.24,31.75],[-106.51,31.75],[-106.14,31.4],[-105.63,31.08],[-105.04,30.64],[-104.71,30.12],[-104.46,29.57],[-103.94,29.27],[-103.11,28.97],[-102.48,29.76],[-101.66,29.78],[-100.96,29.38],[-100.46,28.7],[-100.11,28.11],[-99.52,27.54],[-99.3,26.84],[-99.02,26.37],[-98.24,26.06],[-97.53,25.84],[-97.14,25.87],[-97.53,24.99],[-97.7,24.27],[-97.78,22.93],[-97.87,22.44],[-97.7,21.9],[-97.39,21.41],[-97.19,20.64],[-96.53,19.89],[-96.29,19.32],[-95.9,18.83],[-94.84,18.56],[-94.43,18.14],[-93.55,18.42],[-92.79,18.52],[-92.04,18.7],[-91.41,18.88],[-90.77,19.28],[-90.53,19.87],[-90.45,20.71],[-90.28,21.0],[-89.6,21.26],[-88.54,21.49],[-87.66,21.46],[-87.05,21.54],[-86.81,21.33],[-86.85,20.85],[-87.38,20.26],[-87.62,19.65],[-87.44,19.47],[-87.59,19.04],[-87.84,18.26],[-88.09,18.52],[-88.3,18.5],[-88.49,18.49],[-88.85,17.88],[-89.03,18.0],[-89.15,17.96],[-89.14,17.81],[-90.07,17.82],[-91.0,17.82],[-91.0,17.25],[-91.45,17.25],[-91.08,16.92],[-90.71,16.69],[-90.6,16.47],[-90.44,16.41],[-90.46,16.07],[-91.75,16.07],[-92.23,15.25],[-92.09,15.06],[-92.2,14.83],[-92.23,14.54],[-93.36,15.62],[-93.88,15.94],[-94.69,16.2],[-95.25,16.13],[-96.05,15.75],[-96.56,15.65],[-97.26,15.92],[-98.01,16.11],[-98.95,16.57],[-99.7,16.71],[-100.83,17.17],[-101.67,17.65],[-101.92,17.92],[-102.48,17.98],[-103.5,18.29],[-103.92,18.75],[-104.99,19.32],[-105.49,19.95],[-105.73,20.43],[-105.4,20.53],[-105.5,20.82],[-105.27,21.08],[-105.27,21.42],[-105.6,21.87],[-105.69,22.27],[-106.03,22.77],[-106.91,23.77],[-107.92,24.55],[-108.4,25.17],[-109.26,25.58],[-109.44,25.82],[-109.29,26.44],[-109.8,26.68],[-110.39,27.16],[-110.64,27.86],[-111.18,27.94],[-111.76,28.47],[-112.23,28.95],[-112.27,29.27],[-112.81,30.02],[-113.16,30.79],[-113.15,31.17],[-113.87,31.57],[-114.21,31.52],[-114.78,31.8],[-114.94,31.39],[-114.77,30.91],[-114.67,30.16],[-114.33,29.75],[-113.59,29.06],[-113.42,28.83],[-113.27,28.75],[-113.14,28.41],[-112.96,28.43],[-112.76,27.78],[-112.46,27.53],[-112.24,27.17],[-111.62,26.66],[-111.28,25.73],[-110.99,25.29],[-110.71,24.83],[-110.66,24.3],[-110.17,24.27],[-109.77,23.81],[-109.41,23.36],[-109.43,23.19],[-109.85,22.82],[-110.03,22.82],[-110.3,23.43],[-110.95,24.0],[-111.67,24.48],[-112.18,24.74],[-112.15,25.47],[-112.3,26.01],[-112.78,26.32],[-113.46,26.77],[-113.6,26.64],[-113.85,26.9],[-114.47,27.14],[-115.06,27.72],[-114.98,27.8],[-114.57,27.74],[-114.2,28.12],[-114.16,28.57],[-114.93,29.28],[-115.52,29.56],[-115.89,30.18],[-116.26,30.84],[-116.72,31.64],[-117.13,32.54]]]]}},{"type":"Feature","properties":{"name":"Uruguay","iso":"UY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-57.63,-30.22],[-56.98,-30.11],[-55.97,-30.88],[-55.6,-30.85],[-54.57,-31.49],[-53.79,-32.05],[-53.21,-32.73],[-53.65,-33.2],[-53.37,-33.77],[-53.81,-34.4],[-54.94,-34.95],[-55.67,-34.75],[-56.22,-34.86],[-57.14,-34.43],[-57.82,-34.46],[-58.43,-33.91],[-58.35,-33.26],[-58.13,-33.04],[-58.14,-32.04],[-57.87,-31.02],[-57.63,-30.22]]]]}},{"type":"Feature","properties":{"name":"Brazil","iso":"BR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.37,-33.77],[-53.65,-33.2],[-53.21,-32.73],[-53.79,-32.05],[-54.57,-31.49],[-55.6,-30.85],[-55.97,-30.88],[-56.98,-30.11],[-57.63,-30.22],[-56.29,-28.85],[-55.16,-27.88],[-54.49,-27.47],[-53.65,-26.92],[-53.63,-26.12],[-54.13,-25.55],[-54.63,-25.74],[-54.43,-25.16],[-54.29,-24.57],[-54.29,-24.02],[-54.65,-23.84],[-55.03,-24.0],[-55.4,-23.96],[-55.52,-23.57],[-55.61,-22.66],[-55.8,-22.36],[-56.47,-22.09],[-56.88,-22.28],[-57.94,-22.09],[-57.87,-20.73],[-58.17,-20.18],[-57.85,-19.97],[-57.95,-19.4],[-57.68,-18.96],[-57.5,-18.17],[-57.73,-17.55],[-58.28,-17.27],[-58.39,-16.88],[-58.24,-16.3],[-60.16,-16.26],[-60.54,-15.09],[-60.25,-15.08],[-60.26,-14.65],[-60.46,-14.35],[-60.5,-13.78],[-61.08,-13.48],[-61.71,-13.49],[-62.13,-13.2],[-62.8,-13.0],[-63.2,-12.63],[-64.32,-12.46],[-65.4,-11.57],[-65.32,-10.9],[-65.44,-10.51],[-65.34,-9.76],[-66.65,-9.93],[-67.17,-10.31],[-68.05,-10.71],[-68.27,-11.01],[-68.79,-11.04],[-69.53,-10.95],[-70.09,-11.12],[-70.55,-11.01],[-70.48,-9.49],[-71.3,-10.08],[-72.18,-10.05],[-72.56,-9.52],[-73.23,-9.46],[-73.02,-9.03],[-73.57,-8.42],[-73.99,-7.52],[-73.72,-7.34],[-73.72,-6.92],[-73.12,-6.63],[-73.22,-6.09],[-72.96,-5.74],[-72.89,-5.27],[-71.75,-4.59],[-70.93,-4.4],[-70.79,-4.25],[-69.89,-4.3],[-69.44,-1.56],[-69.42,-1.12],[-69.58,-0.55],[-70.02,-0.19],[-70.02,0.54],[-69.45,0.71],[-69.25,0.6],[-69.22,0.99],[-69.8,1.09],[-69.82,1.71],[-67.87,1.69],[-67.54,2.04],[-67.26,1.72],[-67.07,1.13],[-66.88,1.25],[-66.33,0.72],[-65.55,0.79],[-65.35,1.1],[-64.61,1.33],[-64.2,1.49],[-64.08,1.92],[-63.37,2.2],[-63.42,2.41],[-64.27,2.5],[-64.41,3.13],[-64.37,3.8],[-64.82,4.06],[-64.63,4.15],[-63.89,4.02],[-63.09,3.77],[-62.8,4.01],[-62.09,4.16],[-60.97,4.54],[-60.6,4.92],[-60.73,5.2],[-60.21,5.24],[-59.98,5.01],[-60.11,4.57],[-59.77,4.42],[-59.54,3.96],[-59.82,3.61],[-59.97,2.76],[-59.72,2.25],[-59.65,1.79],[-59.03,1.32],[-58.54,1.27],[-58.43,1.46],[-58.11,1.51],[-57.66,1.68],[-57.34,1.95],[-56.78,1.86],[-56.54,1.9],[-56.0,1.82],[-55.91,2.02],[-56.07,2.22],[-55.97,2.51],[-55.57,2.42],[-55.1,2.52],[-54.52,2.31],[-54.09,2.11],[-53.78,2.38],[-53.55,2.33],[-53.42,2.05],[-52.94,2.12],[-52.56,2.5],[-52.25,3.24],[-51.66,4.16],[-51.32,4.2],[-51.07,3.65],[-50.51,1.9],[-49.97,1.74],[-49.95,1.05],[-50.7,0.22],[-50.39,-0.08],[-48.62,-0.24],[-48.58,-1.24],[-47.82,-0.58],[-46.57,-0.94],[-44.91,-1.55],[-44.42,-2.14],[-44.58,-2.69],[-43.42,-2.38],[-41.47,-2.91],[-39.98,-2.87],[-38.5,-3.7],[-37.22,-4.82],[-36.45,-5.11],[-35.6,-5.15],[-35.24,-5.46],[-34.9,-6.74],[-34.73,-7.34],[-35.13,-9.0],[-35.64,-9.65],[-37.05,-11.04],[-37.68,-12.17],[-38.42,-13.04],[-38.67,-13.06],[-38.95,-13.79],[-38.88,-15.67],[-39.16,-17.21],[-39.27,-17.87],[-39.58,-18.26],[-39.76,-19.6],[-40.77,-20.9],[-40.94,-21.94],[-41.75,-22.37],[-41.99,-22.97],[-43.07,-22.97],[-44.65,-23.35],[-45.35,-23.8],[-46.47,-24.09],[-47.65,-24.89],[-48.5,-25.88],[-48.64,-26.62],[-48.47,-27.18],[-48.66,-28.19],[-48.89,-28.67],[-49.59,-29.22],[-50.7,-30.98],[-51.58,-31.78],[-52.26,-32.25],[-52.71,-33.2],[-53.37,-33.77]]]]}},{"type":"Feature","properties":{"name":"Bolivia","iso":"BO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-69.53,-10.95],[-68.79,-11.04],[-68.27,-11.01],[-68.05,-10.71],[-67.17,-10.31],[-66.65,-9.93],[-65.34,-9.76],[-65.44,-10.51],[-65.32,-10.9],[-65.4,-11.57],[-64.32,-12.46],[-63.2,-12.63],[-62.8,-13.0],[-62.13,-13.2],[-61.71,-13.49],[-61.08,-13.48],[-60.5,-13.78],[-60.46,-14.35],[-60.26,-14.65],[-60.25,-15.08],[-60.54,-15.09],[-60.16,-16.26],[-58.24,-16.3],[-58.39,-16.88],[-58.28,-17.27],[-57.73,-17.55],[-57.5,-18.17],[-57.68,-18.96],[-57.95,-19.4],[-57.85,-19.97],[-58.17,-20.18],[-58.18,-19.87],[-59.12,-19.36],[-60.04,-19.34],[-61.79,-19.63],[-62.27,-20.51],[-62.29,-21.05],[-62.69,-22.25],[-62.85,-22.03],[-63.99,-21.99],[-64.38,-22.8],[-64.96,-22.08],[-66.27,-21.83],[-67.11,-22.74],[-67.83,-22.87],[-68.22,-21.49],[-68.76,-20.37],[-68.44,-19.41],[-68.97,-18.98],[-69.1,-18.26],[-69.59,-17.58],[-68.96,-16.5],[-69.39,-15.66],[-69.16,-15.32],[-69.34,-14.95],[-68.95,-14.45],[-68.93,-13.6],[-68.88,-12.9],[-68.67,-12.56],[-69.53,-10.95]]]]}},{"type":"Feature","properties":{"name":"Peru","iso":"PE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-69.89,-4.3],[-70.79,-4.25],[-70.93,-4.4],[-71.75,-4.59],[-72.89,-5.27],[-72.96,-5.74],[-73.22,-6.09],[-73.12,-6.63],[-73.72,-6.92],[-73.72,-7.34],[-73.99,-7.52],[-73.57,-8.42],[-73.02,-9.03],[-73.23,-9.46],[-72.56,-9.52],[-72.18,-10.05],[-71.3,-10.08],[-70.48,-9.49],[-70.55,-11.01],[-70.09,-11.12],[-69.53,-10.95],[-68.67,-12.56],[-68.88,-12.9],[-68.93,-13.6],[-68.95,-14.45],[-69.34,-14.95],[-69.16,-15.32],[-69.39,-15.66],[-68.96,-16.5],[-69.59,-17.58],[-69.86,-18.09],[-70.37,-18.35],[-71.38,-17.77],[-71.46,-17.36],[-73.44,-16.36],[-75.24,-15.27],[-76.01,-14.65],[-76.42,-13.82],[-76.26,-13.54],[-77.11,-12.22],[-78.09,-10.38],[-79.04,-8.39],[-79.45,-7.93],[-79.76,-7.19],[-80.54,-6.54],[-81.25,-6.14],[-80.93,-5.69],[-81.41,-4.74],[-81.1,-4.04],[-80.3,-3.4],[-80.18,-3.82],[-80.47,-4.06],[-80.44,-4.43],[-80.03,-4.35],[-79.62,-4.45],[-79.21,-4.96],[-78.64,-4.55],[-78.45,-3.87],[-77.84,-3.0],[-76.64,-2.61],[-75.54,-1.56],[-75.23,-0.91],[-75.37,-0.15],[-75.11,-0.06],[-74.44,-0.53],[-74.12,-1.0],[-73.66,-1.26],[-73.07,-2.31],[-72.33,-2.43],[-71.77,-2.17],[-71.41,-2.34],[-70.81,-2.26],[-70.05,-2.73],[-70.69,-3.74],[-70.39,-3.77],[-69.89,-4.3]]]]}},{"type":"Feature","properties":{"name":"Colombia","iso":"CO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-66.88,1.25],[-67.07,1.13],[-67.26,1.72],[-67.54,2.04],[-67.87,1.69],[-69.82,1.71],[-69.8,1.09],[-69.22,0.99],[-69.25,0.6],[-69.45,0.71],[-70.02,0.54],[-70.02,-0.19],[-69.58,-0.55],[-69.42,-1.12],[-69.44,-1.56],[-69.89,-4.3],[-70.39,-3.77],[-70.69,-3.74],[-70.05,-2.73],[-70.81,-2.26],[-71.41,-2.34],[-71.77,-2.17],[-72.33,-2.43],[-73.07,-2.31],[-73.66,-1.26],[-74.12,-1.0],[-74.44,-0.53],[-75.11,-0.06],[-75.37,-0.15],[-75.8,0.08],[-76.29,0.42],[-76.58,0.26],[-77.42,0.4],[-77.67,0.83],[-77.86,0.81],[-78.86,1.38],[-78.99,1.69],[-78.62,1.77],[-78.66,2.27],[-78.43,2.63],[-77.93,2.7],[-77.51,3.33],[-77.13,3.85],[-77.5,4.09],[-77.31,4.67],[-77.53,5.58],[-77.32,5.85],[-77.48,6.69],[-77.88,7.22],[-77.75,7.71],[-77.43,7.64],[-77.24,7.94],[-77.47,8.52],[-77.35,8.67],[-76.84,8.64],[-76.09,9.34],[-75.67,9.44],[-75.66,9.77],[-75.48,10.62],[-74.91,11.08],[-74.28,11.1],[-74.2,11.31],[-73.41,11.23],[-72.63,11.73],[-72.24,11.96],[-71.75,12.44],[-71.4,12.38],[-71.14,12.11],[-71.33,11.78],[-71.97,11.61],[-72.23,11.11],[-72.61,10.82],[-72.91,10.45],[-73.03,9.74],[-73.3,9.15],[-72.79,9.09],[-72.66,8.63],[-72.44,8.41],[-72.36,8.0],[-72.48,7.63],[-72.44,7.42],[-72.2,7.34],[-71.96,6.99],[-70.67,7.09],[-70.09,6.96],[-69.39,6.1],[-68.99,6.21],[-68.27,6.15],[-67.7,6.27],[-67.34,6.1],[-67.52,5.56],[-67.74,5.22],[-67.82,4.5],[-67.62,3.84],[-67.34,3.54],[-67.3,3.32],[-67.81,2.82],[-67.45,2.6],[-67.18,2.25],[-66.88,1.25]]]]}},{"type":"Feature","properties":{"name":"Panama","iso":"PA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-77.35,8.67],[-77.47,8.52],[-77.24,7.94],[-77.43,7.64],[-77.75,7.71],[-77.88,7.22],[-78.21,7.51],[-78.43,8.05],[-78.18,8.32],[-78.44,8.39],[-78.62,8.72],[-79.12,9.0],[-79.56,8.93],[-79.76,8.58],[-80.16,8.33],[-80.38,8.3],[-80.48,8.09],[-80.0,7.55],[-80.28,7.42],[-80.42,7.27],[-80.89,7.22],[-81.06,7.82],[-81.19,7.65],[-81.52,7.71],[-81.72,8.11],[-82.13,8.18],[-82.39,8.29],[-82.82,8.29],[-82.85,8.07],[-82.97,8.23],[-82.91,8.42],[-82.83,8.63],[-82.87,8.81],[-82.72,8.93],[-82.93,9.07],[-82.93,9.48],[-82.55,9.57],[-82.19,9.21],[-82.21,9.0],[-81.81,8.95],[-81.71,9.03],[-81.44,8.79],[-80.95,8.86],[-80.52,9.11],[-79.91,9.31],[-79.57,9.61],[-79.02,9.55],[-79.06,9.45],[-78.5,9.42],[-78.06,9.25],[-77.73,8.95],[-77.35,8.67]]]]}},{"type":"Feature","properties":{"name":"Costa Rica","iso":"CR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-82.55,9.57],[-82.93,9.48],[-82.93,9.07],[-82.72,8.93],[-82.87,8.81],[-82.83,8.63],[-82.91,8.42],[-82.97,8.23],[-83.51,8.45],[-83.71,8.66],[-83.6,8.83],[-83.63,9.05],[-83.91,9.29],[-84.3,9.49],[-84.65,9.62],[-84.71,9.91],[-84.98,10.09],[-84.91,9.8],[-85.11,9.56],[-85.34,9.83],[-85.66,9.93],[-85.8,10.13],[-85.79,10.44],[-85.66,10.75],[-85.94,10.9],[-85.71,11.09],[-85.56,11.22],[-84.9,10.95],[-84.67,11.08],[-84.36,11.0],[-84.19,10.79],[-83.9,10.73],[-83.66,10.94],[-83.4,10.4],[-83.02,9.99],[-82.55,9.57]]]]}},{"type":"Feature","properties":{"name":"Nicaragua","iso":"NI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-83.66,10.94],[-83.9,10.73],[-84.19,10.79],[-84.36,11.0],[-84.67,11.08],[-84.9,10.95],[-85.56,11.22],[-85.71,11.09],[-86.06,11.4],[-86.53,11.81],[-86.75,12.14],[-87.17,12.46],[-87.67,12.91],[-87.56,13.06],[-87.39,12.91],[-87.32,12.98],[-87.01,13.03],[-86.88,13.25],[-86.73,13.26],[-86.76,13.75],[-86.52,13.78],[-86.31,13.77],[-86.1,14.04],[-85.8,13.84],[-85.7,13.96],[-85.51,14.08],[-85.17,14.35],[-85.15,14.56],[-85.05,14.55],[-84.92,14.79],[-84.82,14.82],[-84.65,14.67],[-84.45,14.62],[-84.23,14.75],[-83.98,14.75],[-83.63,14.88],[-83.49,15.02],[-83.15,15.0],[-83.23,14.9],[-83.28,14.68],[-83.18,14.31],[-83.41,13.97],[-83.52,13.57],[-83.55,13.13],[-83.5,12.87],[-83.47,12.42],[-83.63,12.32],[-83.72,11.89],[-83.65,11.63],[-83.86,11.37],[-83.81,11.1],[-83.66,10.94]]]]}},{"type":"Feature","properties":{"name":"Honduras","iso":"HN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-83.15,15.0],[-83.49,15.02],[-83.63,14.88],[-83.98,14.75],[-84.23,14.75],[-84.45,14.62],[-84.65,14.67],[-84.82,14.82],[-84.92,14.79],[-85.05,14.55],[-85.15,14.56],[-85.17,14.35],[-85.51,14.08],[-85.7,13.96],[-85.8,13.84],[-86.1,14.04],[-86.31,13.77],[-86.52,13.78],[-86.76,13.75],[-86.73,13.26],[-86.88,13.25],[-87.01,13.03],[-87.32,12.98],[-87.49,13.3],[-87.79,13.38],[-87.72,13.79],[-87.86,13.89],[-88.07,13.96],[-88.5,13.85],[-88.54,13.98],[-88.84,14.14],[-89.06,14.34],[-89.35,14.42],[-89.15,14.68],[-89.23,14.87],[-89.15,15.07],[-88.68,15.35],[-88.23,15.73],[-88.12,15.69],[-87.9,15.86],[-87.62,15.88],[-87.52,15.8],[-87.37,15.85],[-86.9,15.76],[-86.44,15.78],[-86.12,15.89],[-86.0,16.01],[-85.68,15.95],[-85.44,15.89],[-85.18,15.91],[-84.98,16.0],[-84.53,15.86],[-84.37,15.84],[-84.06,15.65],[-83.77,15.42],[-83.41,15.27],[-83.15,15.0]]]]}},{"type":"Feature","properties":{"name":"El Salvador","iso":"SV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-89.35,14.42],[-89.06,14.34],[-88.84,14.14],[-88.54,13.98],[-88.5,13.85],[-88.07,13.96],[-87.86,13.89],[-87.72,13.79],[-87.79,13.38],[-87.9,13.15],[-88.48,13.16],[-88.84,13.26],[-89.26,13.46],[-89.81,13.52],[-90.1,13.74],[-90.06,13.88],[-89.72,14.13],[-89.53,14.24],[-89.59,14.36],[-89.35,14.42]]]]}},{"type":"Feature","properties":{"name":"Guatemala","iso":"GT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-92.23,14.54],[-92.2,14.83],[-92.09,15.06],[-92.23,15.25],[-91.75,16.07],[-90.46,16.07],[-90.44,16.41],[-90.6,16.47],[-90.71,16.69],[-91.08,16.92],[-91.45,17.25],[-91.0,17.25],[-91.0,17.82],[-90.07,17.82],[-89.14,17.81],[-89.15,17.02],[-89.23,15.89],[-88.93,15.89],[-88.6,15.71],[-88.52,15.86],[-88.23,15.73],[-88.68,15.35],[-89.15,15.07],[-89.23,14.87],[-89.15,14.68],[-89.35,14.42],[-89.59,14.36],[-89.53,14.24],[-89.72,14.13],[-90.06,13.88],[-90.1,13.74],[-90.61,13.91],[-91.23,13.93],[-91.69,14.13],[-92.23,14.54]]]]}},{"type":"Feature","properties":{"name":"Belize","iso":"BZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-89.14,17.81],[-89.15,17.96],[-89.03,18.0],[-88.85,17.88],[-88.49,18.49],[-88.3,18.5],[-88.3,18.35],[-88.11,18.35],[-88.12,18.08],[-88.29,17.64],[-88.2,17.49],[-88.3,17.13],[-88.24,17.04],[-88.36,16.53],[-88.55,16.27],[-88.73,16.23],[-88.93,15.89],[-89.23,15.89],[-89.15,17.02],[-89.14,17.81]]]]}},{"type":"Feature","properties":{"name":"Venezuela","iso":"VE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-60.73,5.2],[-60.6,4.92],[-60.97,4.54],[-62.09,4.16],[-62.8,4.01],[-63.09,3.77],[-63.89,4.02],[-64.63,4.15],[-64.82,4.06],[-64.37,3.8],[-64.41,3.13],[-64.27,2.5],[-63.42,2.41],[-63.37,2.2],[-64.08,1.92],[-64.2,1.49],[-64.61,1.33],[-65.35,1.1],[-65.55,0.79],[-66.33,0.72],[-66.88,1.25],[-67.18,2.25],[-67.45,2.6],[-67.81,2.82],[-67.3,3.32],[-67.34,3.54],[-67.62,3.84],[-67.82,4.5],[-67.74,5.22],[-67.52,5.56],[-67.34,6.1],[-67.7,6.27],[-68.27,6.15],[-68.99,6.21],[-69.39,6.1],[-70.09,6.96],[-70.67,7.09],[-71.96,6.99],[-72.2,7.34],[-72.44,7.42],[-72.48,7.63],[-72.36,8.0],[-72.44,8.41],[-72.66,8.63],[-72.79,9.09],[-73.3,9.15],[-73.03,9.74],[-72.91,10.45],[-72.61,10.82],[-72.23,11.11],[-71.97,11.61],[-71.33,11.78],[-71.36,11.54],[-71.95,11.42],[-71.62,10.97],[-71.63,10.45],[-72.07,9.87],[-71.7,9.07],[-71.26,9.14],[-71.04,9.86],[-71.35,10.21],[-71.4,10.97],[-70.16,11.38],[-70.29,11.85],[-69.94,12.16],[-69.58,11.46],[-68.88,11.44],[-68.23,10.89],[-68.19,10.55],[-67.3,10.55],[-66.23,10.65],[-65.66,10.2],[-64.89,10.08],[-64.33,10.39],[-64.32,10.64],[-63.08,10.7],[-61.88,10.72],[-62.73,10.42],[-62.39,9.95],[-61.59,9.87],[-60.83,9.38],[-60.67,8.58],[-60.15,8.6],[-59.76,8.37],[-60.55,7.78],[-60.64,7.42],[-60.3,7.04],[-60.54,6.86],[-61.16,6.7],[-61.14,6.23],[-61.41,5.96],[-60.73,5.2]]]]}},{"type":"Feature","properties":{"name":"Guyana","iso":"GY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-56.54,1.9],[-56.78,1.86],[-57.34,1.95],[-57.66,1.68],[-58.11,1.51],[-58.43,1.46],[-58.54,1.27],[-59.03,1.32],[-59.65,1.79],[-59.72,2.25],[-59.97,2.76],[-59.82,3.61],[-59.54,3.96],[-59.77,4.42],[-60.11,4.57],[-59.98,5.01],[-60.21,5.24],[-60.73,5.2],[-61.41,5.96],[-61.14,6.23],[-61.16,6.7],[-60.54,6.86],[-60.3,7.04],[-60.64,7.42],[-60.55,7.78],[-59.76,8.37],[-59.1,8.0],[-58.48,7.35],[-58.45,6.83],[-58.08,6.81],[-57.54,6.32],[-57.15,5.97],[-57.31,5.07],[-57.91,4.81],[-57.86,4.58],[-58.04,4.06],[-57.6,3.33],[-57.28,3.33],[-57.15,2.77],[-56.54,1.9]]]]}},{"type":"Feature","properties":{"name":"Suriname","iso":"SR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-54.52,2.31],[-55.1,2.52],[-55.57,2.42],[-55.97,2.51],[-56.07,2.22],[-55.91,2.02],[-56.0,1.82],[-56.54,1.9],[-57.15,2.77],[-57.28,3.33],[-57.6,3.33],[-58.04,4.06],[-57.86,4.58],[-57.91,4.81],[-57.31,5.07],[-57.15,5.97],[-55.95,5.77],[-55.84,5.95],[-55.03,6.03],[-53.96,5.76],[-54.48,4.9],[-54.4,4.21],[-54.01,3.62],[-54.18,3.19],[-54.27,2.73],[-54.52,2.31]]]]}},{"type":"Feature","properties":{"name":"France","iso":"FR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-51.66,4.16],[-52.25,3.24],[-52.56,2.5],[-52.94,2.12],[-53.42,2.05],[-53.55,2.33],[-53.78,2.38],[-54.09,2.11],[-54.52,2.31],[-54.27,2.73],[-54.18,3.19],[-54.01,3.62],[-54.4,4.21],[-54.48,4.9],[-53.96,5.76],[-53.62,5.65],[-52.88,5.41],[-51.82,4.57],[-51.66,4.16]]],[[[6.19,49.46],[6.66,49.2],[8.1,49.02],[7.59,48.33],[7.47,47.62],[7.19,47.45],[6.74,47.54],[6.77,47.29],[6.04,46.73],[6.02,46.27],[6.5,46.43],[6.84,45.99],[6.8,45.71],[7.1,45.33],[6.75,45.03],[7.01,44.25],[7.55,44.13],[7.44,43.69],[6.53,43.13],[4.56,43.4],[3.1,43.08],[2.99,42.47],[1.83,42.34],[0.7,42.8],[0.34,42.58],[-1.5,43.03],[-1.9,43.42],[-1.38,44.02],[-1.19,46.01],[-2.23,47.06],[-2.96,47.57],[-4.49,47.95],[-4.59,48.68],[-3.3,48.9],[-1.62,48.64],[-1.93,49.78],[-0.99,49.35],[1.34,50.13],[1.64,50.95],[2.51,51.15],[2.66,50.8],[3.12,50.78],[3.59,50.38],[4.29,49.91],[4.8,49.99],[5.67,49.53],[5.9,49.44],[6.19,49.46]]],[[[8.75,42.63],[9.39,43.01],[9.56,42.15],[9.23,41.38],[8.78,41.58],[8.54,42.26],[8.75,42.63]]]]}},{"type":"Feature","properties":{"name":"Ecuador","iso":"EC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.37,-0.15],[-75.23,-0.91],[-75.54,-1.56],[-76.64,-2.61],[-77.84,-3.0],[-78.45,-3.87],[-78.64,-4.55],[-79.21,-4.96],[-79.62,-4.45],[-80.03,-4.35],[-80.44,-4.43],[-80.47,-4.06],[-80.18,-3.82],[-80.3,-3.4],[-79.77,-2.66],[-79.99,-2.22],[-80.37,-2.69],[-80.97,-2.25],[-80.76,-1.97],[-80.93,-1.06],[-80.58,-0.91],[-80.4,-0.28],[-80.02,0.36],[-80.09,0.77],[-79.54,0.98],[-78.86,1.38],[-77.86,0.81],[-77.67,0.83],[-77.42,0.4],[-76.58,0.26],[-76.29,0.42],[-75.8,0.08],[-75.37,-0.15]]]]}},{"type":"Feature","properties":{"name":"Puerto Rico","iso":"PR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-66.28,18.51],[-65.77,18.43],[-65.59,18.23],[-65.85,17.98],[-66.6,17.98],[-67.18,17.95],[-67.24,18.37],[-67.1,18.52],[-66.28,18.51]]]]}},{"type":"Feature","properties":{"name":"Jamaica","iso":"JM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-77.57,18.49],[-76.9,18.4],[-76.37,18.16],[-76.2,17.89],[-76.9,17.87],[-77.21,17.7],[-77.77,17.86],[-78.34,18.23],[-78.22,18.45],[-77.8,18.52],[-77.57,18.49]]]]}},{"type":"Feature","properties":{"name":"Cuba","iso":"CU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-82.27,23.19],[-81.4,23.12],[-80.62,23.11],[-79.68,22.77],[-79.28,22.4],[-78.35,22.51],[-77.99,22.28],[-77.15,21.66],[-76.52,21.21],[-76.19,21.22],[-75.6,21.02],[-75.67,20.74],[-74.93,20.69],[-74.18,20.28],[-74.3,20.05],[-74.96,19.92],[-75.63,19.87],[-76.32,19.95],[-77.76,19.86],[-77.09,20.41],[-77.49,20.67],[-78.14,20.74],[-78.48,21.03],[-78.72,21.6],[-79.28,21.56],[-80.22,21.83],[-80.52,22.04],[-81.82,22.19],[-82.17,22.39],[-81.8,22.64],[-82.78,22.69],[-83.49,22.17],[-83.91,22.15],[-84.05,21.91],[-84.55,21.8],[-84.97,21.9],[-84.45,22.2],[-84.23,22.57],[-83.78,22.79],[-83.27,22.98],[-82.51,23.08],[-82.27,23.19]]]]}},{"type":"Feature","properties":{"name":"Zimbabwe","iso":"ZW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[31.19,-22.25],[30.66,-22.15],[30.32,-22.27],[29.84,-22.1],[29.43,-22.09],[28.79,-21.64],[28.02,-21.49],[27.73,-20.85],[27.72,-20.5],[27.3,-20.39],[26.16,-19.29],[25.85,-18.71],[25.65,-18.54],[25.26,-17.74],[26.38,-17.85],[26.71,-17.96],[27.04,-17.94],[27.6,-17.29],[28.47,-16.47],[28.83,-16.39],[28.95,-16.04],[29.52,-15.64],[30.27,-15.51],[30.34,-15.88],[31.17,-15.86],[31.64,-16.07],[31.85,-16.32],[32.33,-16.39],[32.85,-16.71],[32.85,-17.98],[32.65,-18.67],[32.61,-19.42],[32.77,-19.72],[32.66,-20.3],[32.51,-20.4],[32.24,-21.12],[31.19,-22.25]]]]}},{"type":"Feature","properties":{"name":"Botswana","iso":"BW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[29.43,-22.09],[28.02,-22.83],[27.12,-23.57],[26.79,-24.24],[26.49,-24.62],[25.94,-24.7],[25.77,-25.17],[25.66,-25.49],[25.03,-25.72],[24.21,-25.67],[23.73,-25.39],[23.31,-25.27],[22.82,-25.5],[22.58,-25.98],[22.11,-26.28],[21.61,-26.73],[20.89,-26.83],[20.67,-26.48],[20.76,-25.87],[20.17,-24.92],[19.9,-24.77],[19.9,-21.85],[20.88,-21.81],[20.91,-18.25],[21.66,-18.22],[23.2,-17.87],[23.58,-18.28],[24.22,-17.89],[24.52,-17.89],[25.08,-17.66],[25.26,-17.74],[25.65,-18.54],[25.85,-18.71],[26.16,-19.29],[27.3,-20.39],[27.72,-20.5],[27.73,-20.85],[28.02,-21.49],[28.79,-21.64],[29.43,-22.09]]]]}},{"type":"Feature","properties":{"name":"Namibia","iso":"NA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[19.9,-24.77],[19.89,-28.46],[19.0,-28.97],[18.46,-29.05],[17.84,-28.86],[17.39,-28.78],[17.22,-28.36],[16.82,-28.08],[16.34,-28.58],[15.6,-27.82],[15.21,-27.09],[14.99,-26.12],[14.74,-25.39],[14.41,-23.85],[14.39,-22.66],[14.26,-22.11],[13.87,-21.7],[13.35,-20.87],[12.83,-19.67],[12.61,-19.05],[11.79,-18.07],[11.73,-17.3],[12.22,-17.11],[12.81,-16.94],[13.46,-16.97],[14.06,-17.42],[14.21,-17.35],[18.26,-17.31],[18.96,-17.79],[21.38,-17.93],[23.22,-17.52],[24.03,-17.3],[24.68,-17.35],[25.08,-17.58],[25.08,-17.66],[24.52,-17.89],[24.22,-17.89],[23.58,-18.28],[23.2,-17.87],[21.66,-18.22],[20.91,-18.25],[20.88,-21.81],[19.9,-21.85],[19.9,-24.77]]]]}},{"type":"Feature","properties":{"name":"Senegal","iso":"SN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-16.71,13.59],[-17.13,14.37],[-17.63,14.73],[-17.19,14.92],[-16.7,15.62],[-16.46,16.14],[-16.12,16.46],[-15.62,16.37],[-15.14,16.59],[-14.58,16.6],[-14.1,16.3],[-13.44,16.04],[-12.83,15.3],[-12.17,14.62],[-12.12,13.99],[-11.93,13.42],[-11.55,13.14],[-11.47,12.75],[-11.51,12.44],[-11.66,12.39],[-12.2,12.47],[-12.28,12.35],[-12.5,12.33],[-13.22,12.58],[-13.7,12.59],[-15.55,12.63],[-15.82,12.52],[-16.15,12.55],[-16.68,12.38],[-16.84,13.15],[-15.93,13.13],[-15.69,13.27],[-15.51,13.28],[-15.14,13.51],[-14.71,13.3],[-14.28,13.28],[-13.84,13.51],[-14.05,13.79],[-14.38,13.63],[-14.69,13.63],[-15.08,13.88],[-15.4,13.86],[-15.62,13.62],[-16.71,13.59]]]]}},{"type":"Feature","properties":{"name":"Mali","iso":"ML"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-11.51,12.44],[-11.47,12.75],[-11.55,13.14],[-11.93,13.42],[-12.12,13.99],[-12.17,14.62],[-11.83,14.8],[-11.67,15.39],[-11.35,15.41],[-10.65,15.13],[-10.09,15.33],[-9.7,15.26],[-9.55,15.49],[-5.54,15.5],[-5.32,16.2],[-5.49,16.33],[-5.97,20.64],[-6.45,24.96],[-4.92,24.97],[-1.55,22.79],[1.82,20.61],[2.06,20.14],[2.68,19.86],[3.15,19.69],[3.16,19.06],[4.27,19.16],[4.27,16.85],[3.72,16.18],[3.64,15.57],[2.75,15.41],[1.39,15.32],[1.02,14.97],[0.37,14.93],[-0.27,14.92],[-0.52,15.12],[-1.07,14.97],[-2.0,14.56],[-2.19,14.25],[-2.97,13.8],[-3.1,13.54],[-3.52,13.34],[-4.01,13.47],[-4.28,13.23],[-4.43,12.54],[-5.22,11.71],[-5.2,11.38],[-5.47,10.95],[-5.4,10.37],[-5.82,10.22],[-6.05,10.1],[-6.21,10.52],[-6.49,10.41],[-6.67,10.43],[-6.85,10.14],[-7.62,10.15],[-7.9,10.3],[-8.03,10.21],[-8.34,10.49],[-8.28,10.79],[-8.41,10.91],[-8.62,10.81],[-8.58,11.14],[-8.38,11.39],[-8.79,11.81],[-8.91,12.09],[-9.13,12.31],[-9.33,12.33],[-9.57,12.19],[-9.89,12.06],[-10.17,11.84],[-10.59,11.92],[-10.87,12.18],[-11.04,12.21],[-11.3,12.08],[-11.46,12.08],[-11.51,12.44]]]]}},{"type":"Feature","properties":{"name":"Mauritania","iso":"MR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-17.06,21.0],[-16.85,21.33],[-12.93,21.33],[-13.12,22.77],[-12.87,23.28],[-11.94,23.37],[-11.97,25.93],[-8.69,25.88],[-8.68,27.4],[-4.92,24.97],[-6.45,24.96],[-5.97,20.64],[-5.49,16.33],[-5.32,16.2],[-5.54,15.5],[-9.55,15.49],[-9.7,15.26],[-10.09,15.33],[-10.65,15.13],[-11.35,15.41],[-11.67,15.39],[-11.83,14.8],[-12.17,14.62],[-12.83,15.3],[-13.44,16.04],[-14.1,16.3],[-14.58,16.6],[-15.14,16.59],[-15.62,16.37],[-16.12,16.46],[-16.46,16.14],[-16.55,16.67],[-16.27,17.17],[-16.15,18.11],[-16.26,19.1],[-16.38,19.59],[-16.28,20.09],[-16.54,20.57],[-17.06,21.0]]]]}},{"type":"Feature","properties":{"name":"Benin","iso":"BJ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[2.69,6.26],[1.87,6.14],[1.62,6.83],[1.66,9.13],[1.46,9.33],[1.43,9.83],[1.08,10.18],[0.77,10.47],[0.9,11.0],[1.24,11.11],[1.45,11.55],[1.94,11.64],[2.15,11.94],[2.49,12.23],[2.85,12.24],[3.61,11.66],[3.57,11.33],[3.8,10.73],[3.6,10.33],[3.71,10.06],[3.22,9.44],[2.91,9.14],[2.72,8.51],[2.75,7.87],[2.69,6.26]]]]}},{"type":"Feature","properties":{"name":"Niger","iso":"NE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.85,22.86],[15.1,21.31],[15.47,21.05],[15.49,20.73],[15.9,20.39],[15.69,19.96],[15.3,17.93],[15.25,16.63],[13.97,15.68],[13.54,14.37],[13.96,14.0],[13.95,13.35],[14.6,13.33],[14.5,12.86],[14.21,12.8],[14.18,12.48],[14.0,12.46],[13.32,13.56],[13.08,13.6],[12.3,13.04],[11.53,13.33],[10.99,13.39],[10.7,13.25],[10.11,13.28],[9.52,12.85],[9.01,12.83],[7.8,13.34],[7.33,13.1],[6.82,13.12],[6.45,13.49],[5.44,13.87],[4.37,13.75],[4.11,13.53],[3.97,12.96],[3.68,12.55],[3.61,11.66],[2.85,12.24],[2.49,12.23],[2.15,11.94],[2.18,12.63],[1.02,12.85],[0.99,13.34],[0.43,13.99],[0.3,14.44],[0.37,14.93],[1.02,14.97],[1.39,15.32],[2.75,15.41],[3.64,15.57],[3.72,16.18],[4.27,16.85],[4.27,19.16],[5.68,19.6],[8.57,21.57],[12.0,23.47],[13.58,23.04],[14.14,22.49],[14.85,22.86]]]]}},{"type":"Feature","properties":{"name":"Nigeria","iso":"NG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[2.69,6.26],[2.75,7.87],[2.72,8.51],[2.91,9.14],[3.22,9.44],[3.71,10.06],[3.6,10.33],[3.8,10.73],[3.57,11.33],[3.61,11.66],[3.68,12.55],[3.97,12.96],[4.11,13.53],[4.37,13.75],[5.44,13.87],[6.45,13.49],[6.82,13.12],[7.33,13.1],[7.8,13.34],[9.01,12.83],[9.52,12.85],[10.11,13.28],[10.7,13.25],[10.99,13.39],[11.53,13.33],[12.3,13.04],[13.08,13.6],[13.32,13.56],[14.0,12.46],[14.18,12.48],[14.58,12.09],[14.47,11.9],[14.42,11.57],[13.57,10.8],[13.31,10.16],[13.17,9.64],[12.96,9.42],[12.75,8.72],[12.22,8.31],[12.06,7.8],[11.84,7.4],[11.75,6.98],[11.06,6.64],[10.5,7.06],[10.12,7.04],[9.52,6.45],[9.23,6.44],[8.76,5.48],[8.5,4.77],[7.46,4.41],[7.08,4.46],[6.7,4.24],[5.9,4.26],[5.36,4.89],[5.03,5.61],[4.33,6.27],[3.57,6.26],[2.69,6.26]]]]}},{"type":"Feature","properties":{"name":"Cameroon","iso":"CM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.5,12.86],[14.89,12.22],[14.96,11.56],[14.92,10.89],[15.47,9.98],[14.91,9.99],[14.63,9.92],[14.17,10.02],[13.95,9.55],[14.54,8.97],[14.98,8.8],[15.12,8.38],[15.44,7.69],[15.28,7.42],[14.78,6.41],[14.54,6.23],[14.46,5.45],[14.56,5.03],[14.48,4.73],[14.95,4.21],[15.04,3.85],[15.41,3.34],[15.86,3.01],[15.91,2.56],[16.01,2.27],[15.94,1.73],[15.15,1.96],[14.34,2.23],[13.08,2.27],[12.95,2.32],[12.36,2.19],[11.75,2.33],[11.28,2.26],[9.65,2.28],[9.8,3.07],[9.4,3.73],[8.95,3.9],[8.74,4.35],[8.49,4.5],[8.5,4.77],[8.76,5.48],[9.23,6.44],[9.52,6.45],[10.12,7.04],[10.5,7.06],[11.06,6.64],[11.75,6.98],[11.84,7.4],[12.06,7.8],[12.22,8.31],[12.75,8.72],[12.96,9.42],[13.17,9.64],[13.31,10.16],[13.57,10.8],[14.42,11.57],[14.47,11.9],[14.58,12.09],[14.18,12.48],[14.21,12.8],[14.5,12.86]]]]}},{"type":"Feature","properties":{"name":"Togo","iso":"TG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[0.9,11.0],[0.77,10.47],[1.08,10.18],[1.43,9.83],[1.46,9.33],[1.66,9.13],[1.62,6.83],[1.87,6.14],[1.06,5.93],[0.84,6.28],[0.57,6.91],[0.49,7.41],[0.71,8.31],[0.46,8.68],[0.37,9.47],[0.37,10.19],[-0.05,10.71],[0.02,11.02],[0.9,11.0]]]]}},{"type":"Feature","properties":{"name":"Ghana","iso":"GH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[0.02,11.02],[-0.05,10.71],[0.37,10.19],[0.37,9.47],[0.46,8.68],[0.71,8.31],[0.49,7.41],[0.57,6.91],[0.84,6.28],[1.06,5.93],[-0.51,5.34],[-1.06,5.0],[-1.96,4.71],[-2.86,4.99],[-2.81,5.39],[-3.24,6.25],[-2.98,7.38],[-2.56,8.22],[-2.83,9.64],[-2.96,10.4],[-2.94,10.96],[-1.2,11.01],[-0.76,10.94],[-0.44,11.1],[0.02,11.02]]]]}},{"type":"Feature","properties":{"name":"C\u00f4te d'Ivoire","iso":"CI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.03,10.21],[-7.9,10.3],[-7.62,10.15],[-6.85,10.14],[-6.67,10.43],[-6.49,10.41],[-6.21,10.52],[-6.05,10.1],[-5.82,10.22],[-5.4,10.37],[-4.95,10.15],[-4.78,9.82],[-4.33,9.61],[-3.98,9.86],[-3.51,9.9],[-2.83,9.64],[-2.56,8.22],[-2.98,7.38],[-3.24,6.25],[-2.81,5.39],[-2.86,4.99],[-3.31,4.98],[-4.01,5.18],[-4.65,5.17],[-5.83,4.99],[-6.53,4.71],[-7.52,4.34],[-7.71,4.36],[-7.64,5.19],[-7.54,5.31],[-7.57,5.71],[-7.99,6.13],[-8.31,6.19],[-8.6,6.47],[-8.39,6.91],[-8.49,7.4],[-8.44,7.69],[-8.28,7.69],[-8.22,8.12],[-8.3,8.32],[-8.2,8.46],[-7.83,8.58],[-8.08,9.38],[-8.31,9.79],[-8.23,10.13],[-8.03,10.21]]]]}},{"type":"Feature","properties":{"name":"Guinea","iso":"GN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-13.7,12.59],[-13.22,12.58],[-12.5,12.33],[-12.28,12.35],[-12.2,12.47],[-11.66,12.39],[-11.51,12.44],[-11.46,12.08],[-11.3,12.08],[-11.04,12.21],[-10.87,12.18],[-10.59,11.92],[-10.17,11.84],[-9.89,12.06],[-9.57,12.19],[-9.33,12.33],[-9.13,12.31],[-8.91,12.09],[-8.79,11.81],[-8.38,11.39],[-8.58,11.14],[-8.62,10.81],[-8.41,10.91],[-8.28,10.79],[-8.34,10.49],[-8.03,10.21],[-8.23,10.13],[-8.31,9.79],[-8.08,9.38],[-7.83,8.58],[-8.2,8.46],[-8.3,8.32],[-8.22,8.12],[-8.28,7.69],[-8.44,7.69],[-8.72,7.71],[-8.93,7.31],[-9.21,7.31],[-9.4,7.53],[-9.34,7.93],[-9.76,8.54],[-10.02,8.43],[-10.23,8.41],[-10.51,8.35],[-10.49,8.72],[-10.65,8.98],[-10.62,9.27],[-10.84,9.69],[-11.12,10.05],[-11.92,10.05],[-12.15,9.86],[-12.43,9.84],[-12.6,9.62],[-12.71,9.34],[-13.25,8.9],[-13.69,9.49],[-14.07,9.89],[-14.33,10.02],[-14.58,10.21],[-14.69,10.66],[-14.84,10.88],[-15.13,11.04],[-14.69,11.53],[-14.38,11.51],[-14.12,11.68],[-13.9,11.68],[-13.74,11.81],[-13.83,12.14],[-13.72,12.25],[-13.7,12.59]]]]}},{"type":"Feature","properties":{"name":"Guinea-Bissau","iso":"GW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-16.68,12.38],[-16.15,12.55],[-15.82,12.52],[-15.55,12.63],[-13.7,12.59],[-13.72,12.25],[-13.83,12.14],[-13.74,11.81],[-13.9,11.68],[-14.12,11.68],[-14.38,11.51],[-14.69,11.53],[-15.13,11.04],[-15.66,11.46],[-16.09,11.52],[-16.31,11.81],[-16.31,11.96],[-16.61,12.17],[-16.68,12.38]]]]}},{"type":"Feature","properties":{"name":"Liberia","iso":"LR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.44,7.69],[-8.49,7.4],[-8.39,6.91],[-8.6,6.47],[-8.31,6.19],[-7.99,6.13],[-7.57,5.71],[-7.54,5.31],[-7.64,5.19],[-7.71,4.36],[-7.97,4.36],[-9.0,4.83],[-9.91,5.59],[-10.77,6.14],[-11.44,6.79],[-11.2,7.11],[-11.15,7.4],[-10.7,7.94],[-10.23,8.41],[-10.02,8.43],[-9.76,8.54],[-9.34,7.93],[-9.4,7.53],[-9.21,7.31],[-8.93,7.31],[-8.72,7.71],[-8.44,7.69]]]]}},{"type":"Feature","properties":{"name":"Sierra Leone","iso":"SL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-13.25,8.9],[-12.71,9.34],[-12.6,9.62],[-12.43,9.84],[-12.15,9.86],[-11.92,10.05],[-11.12,10.05],[-10.84,9.69],[-10.62,9.27],[-10.65,8.98],[-10.49,8.72],[-10.51,8.35],[-10.23,8.41],[-10.7,7.94],[-11.15,7.4],[-11.2,7.11],[-11.44,6.79],[-11.71,6.86],[-12.43,7.26],[-12.95,7.8],[-13.12,8.16],[-13.25,8.9]]]]}},{"type":"Feature","properties":{"name":"Burkina Faso","iso":"BF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-5.4,10.37],[-5.47,10.95],[-5.2,11.38],[-5.22,11.71],[-4.43,12.54],[-4.28,13.23],[-4.01,13.47],[-3.52,13.34],[-3.1,13.54],[-2.97,13.8],[-2.19,14.25],[-2.0,14.56],[-1.07,14.97],[-0.52,15.12],[-0.27,14.92],[0.37,14.93],[0.3,14.44],[0.43,13.99],[0.99,13.34],[1.02,12.85],[2.18,12.63],[2.15,11.94],[1.94,11.64],[1.45,11.55],[1.24,11.11],[0.9,11.0],[0.02,11.02],[-0.44,11.1],[-0.76,10.94],[-1.2,11.01],[-2.94,10.96],[-2.96,10.4],[-2.83,9.64],[-3.51,9.9],[-3.98,9.86],[-4.33,9.61],[-4.78,9.82],[-4.95,10.15],[-5.4,10.37]]]]}},{"type":"Feature","properties":{"name":"Central African Rep.","iso":"CF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[27.37,5.23],[27.04,5.13],[26.4,5.15],[25.65,5.26],[25.28,5.17],[25.13,4.93],[24.81,4.9],[24.41,5.11],[23.3,4.61],[22.84,4.71],[22.7,4.63],[22.41,4.03],[21.66,4.22],[20.93,4.32],[20.29,4.69],[19.47,5.03],[18.93,4.71],[18.54,4.2],[18.45,3.5],[17.81,3.56],[17.13,3.73],[16.54,3.2],[16.01,2.27],[15.91,2.56],[15.86,3.01],[15.41,3.34],[15.04,3.85],[14.95,4.21],[14.48,4.73],[14.56,5.03],[14.46,5.45],[14.54,6.23],[14.78,6.41],[15.28,7.42],[16.11,7.5],[16.29,7.75],[16.46,7.73],[16.71,7.51],[17.96,7.89],[18.39,8.28],[18.91,8.63],[18.81,8.98],[19.09,9.07],[20.06,9.01],[21.0,9.48],[21.72,10.57],[22.23,10.97],[22.86,11.14],[22.98,10.71],[23.55,10.09],[23.56,9.68],[23.39,9.27],[23.46,8.95],[23.81,8.67],[24.57,8.23],[25.11,7.83],[25.12,7.5],[25.8,6.98],[26.21,6.55],[26.47,5.95],[27.21,5.55],[27.37,5.23]]]]}},{"type":"Feature","properties":{"name":"Congo","iso":"CG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.45,3.5],[18.39,2.9],[18.09,2.37],[17.9,1.74],[17.77,0.86],[17.83,0.29],[17.66,-0.06],[17.64,-0.42],[17.52,-0.74],[16.87,-1.23],[16.41,-1.74],[15.97,-2.71],[16.01,-3.54],[15.75,-3.86],[15.17,-4.34],[14.58,-4.97],[14.21,-4.79],[14.14,-4.51],[13.6,-4.5],[13.26,-4.88],[13.0,-4.78],[12.62,-4.44],[12.32,-4.61],[11.91,-5.04],[11.09,-3.98],[11.86,-3.43],[11.48,-2.77],[11.82,-2.51],[12.5,-2.39],[12.58,-1.95],[13.11,-2.43],[13.99,-2.47],[14.3,-2.0],[14.43,-1.33],[14.32,-0.55],[13.84,0.04],[14.28,1.2],[14.03,1.4],[13.28,1.31],[13.0,1.83],[13.08,2.27],[14.34,2.23],[15.15,1.96],[15.94,1.73],[16.01,2.27],[16.54,3.2],[17.13,3.73],[17.81,3.56],[18.45,3.5]]]]}},{"type":"Feature","properties":{"name":"Gabon","iso":"GA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[11.28,2.26],[11.75,2.33],[12.36,2.19],[12.95,2.32],[13.08,2.27],[13.0,1.83],[13.28,1.31],[14.03,1.4],[14.28,1.2],[13.84,0.04],[14.32,-0.55],[14.43,-1.33],[14.3,-2.0],[13.99,-2.47],[13.11,-2.43],[12.58,-1.95],[12.5,-2.39],[11.82,-2.51],[11.48,-2.77],[11.86,-3.43],[11.09,-3.98],[10.07,-2.97],[9.41,-2.14],[8.8,-1.11],[8.83,-0.78],[9.05,-0.46],[9.29,0.27],[9.49,1.01],[9.83,1.07],[11.29,1.06],[11.28,2.26]]]]}},{"type":"Feature","properties":{"name":"Eq. Guinea","iso":"GQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.65,2.28],[11.28,2.26],[11.29,1.06],[9.83,1.07],[9.49,1.01],[9.31,1.16],[9.65,2.28]]]]}},{"type":"Feature","properties":{"name":"Zambia","iso":"ZM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[30.74,-8.34],[31.16,-8.59],[31.56,-8.76],[32.19,-8.93],[32.76,-9.23],[33.23,-9.68],[33.49,-10.53],[33.32,-10.8],[33.11,-11.61],[33.31,-12.44],[32.99,-12.78],[32.69,-13.71],[33.21,-13.97],[30.18,-14.8],[30.27,-15.51],[29.52,-15.64],[28.95,-16.04],[28.83,-16.39],[28.47,-16.47],[27.6,-17.29],[27.04,-17.94],[26.71,-17.96],[26.38,-17.85],[25.26,-17.74],[25.08,-17.66],[25.08,-17.58],[24.68,-17.35],[24.03,-17.3],[23.22,-17.52],[22.56,-16.9],[21.89,-16.08],[21.93,-12.9],[24.02,-12.91],[23.93,-12.57],[24.08,-12.19],[23.9,-11.72],[24.02,-11.24],[23.91,-10.93],[24.26,-10.95],[24.31,-11.26],[24.78,-11.24],[25.42,-11.33],[25.75,-11.78],[26.55,-11.92],[27.16,-11.61],[27.39,-12.13],[28.16,-12.27],[28.52,-12.7],[28.93,-13.25],[29.7,-13.26],[29.62,-12.18],[29.34,-12.36],[28.64,-11.97],[28.37,-11.79],[28.5,-10.79],[28.67,-9.61],[28.45,-9.16],[28.73,-8.53],[29.0,-8.41],[30.35,-8.24],[30.74,-8.34]]]]}},{"type":"Feature","properties":{"name":"Malawi","iso":"MW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.76,-9.23],[33.74,-9.42],[33.94,-9.69],[34.28,-10.16],[34.56,-11.52],[34.28,-12.28],[34.56,-13.58],[34.91,-13.57],[35.27,-13.89],[35.69,-14.61],[35.77,-15.9],[35.34,-16.11],[35.03,-16.8],[34.38,-16.18],[34.31,-15.48],[34.52,-15.01],[34.46,-14.61],[34.06,-14.36],[33.79,-14.45],[33.21,-13.97],[32.69,-13.71],[32.99,-12.78],[33.31,-12.44],[33.11,-11.61],[33.32,-10.8],[33.49,-10.53],[33.23,-9.68],[32.76,-9.23]]]]}},{"type":"Feature","properties":{"name":"Mozambique","iso":"MZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.56,-11.52],[35.31,-11.44],[36.51,-11.72],[36.78,-11.59],[37.47,-11.57],[37.83,-11.27],[38.43,-11.29],[39.52,-10.9],[40.32,-10.32],[40.48,-10.77],[40.44,-11.76],[40.56,-12.64],[40.6,-14.2],[40.78,-14.69],[40.48,-15.41],[40.09,-16.1],[39.45,-16.72],[38.54,-17.1],[37.41,-17.59],[36.28,-18.66],[35.9,-18.84],[35.2,-19.55],[34.79,-19.78],[34.7,-20.5],[35.18,-21.25],[35.37,-21.84],[35.39,-22.14],[35.56,-22.09],[35.53,-23.07],[35.37,-23.54],[35.61,-23.71],[35.46,-24.12],[35.04,-24.48],[34.22,-24.82],[33.01,-25.36],[32.57,-25.73],[32.66,-26.15],[32.92,-26.22],[32.83,-26.74],[32.07,-26.73],[31.99,-26.29],[31.84,-25.84],[31.75,-25.48],[31.93,-24.37],[31.67,-23.66],[31.19,-22.25],[32.24,-21.12],[32.51,-20.4],[32.66,-20.3],[32.77,-19.72],[32.61,-19.42],[32.65,-18.67],[32.85,-17.98],[32.85,-16.71],[32.33,-16.39],[31.85,-16.32],[31.64,-16.07],[31.17,-15.86],[30.34,-15.88],[30.27,-15.51],[30.18,-14.8],[33.21,-13.97],[33.79,-14.45],[34.06,-14.36],[34.46,-14.61],[34.52,-15.01],[34.31,-15.48],[34.38,-16.18],[35.03,-16.8],[35.34,-16.11],[35.77,-15.9],[35.69,-14.61],[35.27,-13.89],[34.91,-13.57],[34.56,-13.58],[34.28,-12.28],[34.56,-11.52]]]]}},{"type":"Feature","properties":{"name":"eSwatini","iso":"SZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.07,-26.73],[31.87,-27.18],[31.28,-27.29],[30.69,-26.74],[30.68,-26.4],[30.95,-26.02],[31.04,-25.73],[31.33,-25.66],[31.84,-25.84],[31.99,-26.29],[32.07,-26.73]]]]}},{"type":"Feature","properties":{"name":"Angola","iso":"AO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[13.0,-4.78],[12.63,-4.99],[12.47,-5.25],[12.44,-5.68],[12.18,-5.79],[11.91,-5.04],[12.32,-4.61],[12.62,-4.44],[13.0,-4.78]]],[[[12.32,-6.1],[12.74,-5.97],[13.02,-5.98],[13.38,-5.86],[16.33,-5.88],[16.57,-6.62],[16.86,-7.22],[17.09,-7.55],[17.47,-8.07],[18.13,-7.99],[18.46,-7.85],[19.02,-7.99],[19.17,-7.74],[19.42,-7.16],[20.04,-7.12],[20.09,-6.94],[20.6,-6.94],[20.51,-7.3],[21.73,-7.29],[21.75,-7.92],[21.95,-8.31],[21.8,-8.91],[21.88,-9.52],[22.21,-9.89],[22.16,-11.08],[22.4,-10.99],[22.84,-11.02],[23.46,-10.87],[23.91,-10.93],[24.02,-11.24],[23.9,-11.72],[24.08,-12.19],[23.93,-12.57],[24.02,-12.91],[21.93,-12.9],[21.89,-16.08],[22.56,-16.9],[23.22,-17.52],[21.38,-17.93],[18.96,-17.79],[18.26,-17.31],[14.21,-17.35],[14.06,-17.42],[13.46,-16.97],[12.81,-16.94],[12.22,-17.11],[11.73,-17.3],[11.64,-16.67],[11.78,-15.79],[12.12,-14.88],[12.18,-14.45],[12.5,-13.55],[12.74,-13.14],[13.31,-12.48],[13.63,-12.04],[13.74,-11.3],[13.69,-10.73],[13.39,-10.37],[13.12,-9.77],[12.88,-9.17],[12.93,-8.96],[13.24,-8.56],[12.93,-7.6],[12.73,-6.93],[12.23,-6.29],[12.32,-6.1]]]]}},{"type":"Feature","properties":{"name":"Burundi","iso":"BI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[30.47,-2.41],[30.53,-2.81],[30.74,-3.03],[30.75,-3.36],[30.51,-3.57],[30.12,-4.09],[29.75,-4.45],[29.34,-4.5],[29.28,-3.29],[29.02,-2.84],[29.63,-2.92],[29.94,-2.35],[30.47,-2.41]]]]}},{"type":"Feature","properties":{"name":"Israel","iso":"IL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.72,32.71],[35.55,32.39],[35.18,32.53],[34.97,31.87],[35.23,31.75],[34.97,31.62],[34.93,31.35],[35.4,31.49],[35.42,31.1],[34.92,29.5],[34.82,29.76],[34.27,31.22],[34.56,31.55],[34.49,31.61],[34.75,32.07],[34.96,32.83],[35.1,33.08],[35.13,33.09],[35.46,33.09],[35.55,33.26],[35.82,33.28],[35.84,32.87],[35.7,32.72],[35.72,32.71]]]]}},{"type":"Feature","properties":{"name":"Lebanon","iso":"LB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.82,33.28],[35.55,33.26],[35.46,33.09],[35.13,33.09],[35.48,33.91],[35.98,34.61],[36.0,34.64],[36.45,34.59],[36.61,34.2],[36.07,33.82],[35.82,33.28]]]]}},{"type":"Feature","properties":{"name":"Madagascar","iso":"MG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[49.54,-12.47],[49.81,-12.9],[50.06,-13.56],[50.22,-14.76],[50.48,-15.23],[50.38,-15.71],[50.2,-16.0],[49.86,-15.41],[49.67,-15.71],[49.86,-16.45],[49.77,-16.88],[49.5,-17.11],[49.44,-17.95],[49.04,-19.12],[48.55,-20.5],[47.93,-22.39],[47.55,-23.78],[47.1,-24.94],[46.28,-25.18],[45.41,-25.6],[44.83,-25.35],[44.04,-24.99],[43.76,-24.46],[43.7,-23.57],[43.35,-22.78],[43.25,-22.06],[43.43,-21.34],[43.89,-21.16],[43.9,-20.83],[44.37,-20.07],[44.46,-19.44],[44.23,-18.96],[44.04,-18.33],[43.96,-17.41],[44.31,-16.85],[44.45,-16.22],[44.94,-16.18],[45.5,-15.97],[45.87,-15.79],[46.31,-15.78],[46.88,-15.21],[47.71,-14.59],[48.01,-14.09],[47.87,-13.66],[48.29,-13.78],[48.85,-13.09],[48.86,-12.49],[49.19,-12.04],[49.54,-12.47]]]]}},{"type":"Feature","properties":{"name":"Palestine","iso":"PS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.4,31.49],[34.93,31.35],[34.97,31.62],[35.23,31.75],[34.97,31.87],[35.18,32.53],[35.55,32.39],[35.55,31.78],[35.4,31.49]]]]}},{"type":"Feature","properties":{"name":"Gambia","iso":"GM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-16.71,13.59],[-15.62,13.62],[-15.4,13.86],[-15.08,13.88],[-14.69,13.63],[-14.38,13.63],[-14.05,13.79],[-13.84,13.51],[-14.28,13.28],[-14.71,13.3],[-15.14,13.51],[-15.51,13.28],[-15.69,13.27],[-15.93,13.13],[-16.84,13.15],[-16.71,13.59]]]]}},{"type":"Feature","properties":{"name":"Tunisia","iso":"TN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.48,30.31],[9.06,32.1],[8.44,32.51],[8.43,32.75],[7.61,33.34],[7.52,34.1],[8.14,34.66],[8.38,35.48],[8.22,36.43],[8.42,36.95],[9.51,37.35],[10.21,37.23],[10.18,36.72],[11.03,37.09],[11.1,36.9],[10.6,36.41],[10.59,35.95],[10.94,35.7],[10.81,34.83],[10.15,34.33],[10.34,33.79],[10.86,33.77],[11.11,33.29],[11.49,33.14],[11.43,32.37],[10.94,32.08],[10.64,31.76],[9.95,31.38],[10.06,30.96],[9.97,30.54],[9.48,30.31]]]]}},{"type":"Feature","properties":{"name":"Algeria","iso":"DZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.68,27.4],[-8.67,27.59],[-8.67,27.66],[-8.67,28.84],[-7.06,29.58],[-6.06,29.73],[-5.24,30.0],[-4.86,30.5],[-3.69,30.9],[-3.65,31.64],[-3.07,31.72],[-2.62,32.09],[-1.31,32.26],[-1.12,32.65],[-1.39,32.86],[-1.73,33.92],[-1.79,34.53],[-2.17,35.17],[-1.21,35.71],[-0.13,35.89],[0.5,36.3],[1.47,36.61],[3.16,36.78],[4.82,36.87],[5.32,36.72],[6.26,37.11],[7.33,37.12],[7.74,36.89],[8.42,36.95],[8.22,36.43],[8.38,35.48],[8.14,34.66],[7.52,34.1],[7.61,33.34],[8.43,32.75],[8.44,32.51],[9.06,32.1],[9.48,30.31],[9.81,29.42],[9.86,28.96],[9.68,28.14],[9.76,27.69],[9.63,27.14],[9.72,26.51],[9.32,26.09],[9.91,25.37],[9.95,24.94],[10.3,24.38],[10.77,24.56],[11.56,24.1],[12.0,23.47],[8.57,21.57],[5.68,19.6],[4.27,19.16],[3.16,19.06],[3.15,19.69],[2.68,19.86],[2.06,20.14],[1.82,20.61],[-1.55,22.79],[-4.92,24.97],[-8.68,27.4]]]]}},{"type":"Feature","properties":{"name":"Jordan","iso":"JO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.55,32.39],[35.72,32.71],[36.83,32.31],[38.79,33.38],[39.2,32.16],[39.0,32.01],[37.0,31.51],[38.0,30.51],[37.67,30.34],[37.5,30.0],[36.74,29.87],[36.5,29.51],[36.07,29.2],[34.96,29.36],[34.92,29.5],[35.42,31.1],[35.4,31.49],[35.55,31.78],[35.55,32.39]]]]}},{"type":"Feature","properties":{"name":"United Arab Emirates","iso":"AE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[51.58,24.25],[51.76,24.29],[51.79,24.02],[52.58,24.18],[53.4,24.15],[54.01,24.12],[54.69,24.8],[55.44,25.44],[56.07,26.06],[56.26,25.71],[56.4,24.92],[55.89,24.92],[55.8,24.27],[55.98,24.13],[55.53,23.93],[55.53,23.52],[55.23,23.11],[55.21,22.71],[55.01,22.5],[52.0,23.0],[51.62,24.01],[51.58,24.25]]]]}},{"type":"Feature","properties":{"name":"Qatar","iso":"QA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[50.81,24.75],[50.74,25.48],[51.01,26.01],[51.29,26.11],[51.59,25.8],[51.61,25.22],[51.39,24.63],[51.11,24.56],[50.81,24.75]]]]}},{"type":"Feature","properties":{"name":"Kuwait","iso":"KW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[47.97,29.98],[48.18,29.53],[48.09,29.31],[48.42,28.55],[47.71,28.53],[47.46,29.0],[46.57,29.1],[47.3,30.06],[47.97,29.98]]]]}},{"type":"Feature","properties":{"name":"Iraq","iso":"IQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[39.2,32.16],[38.79,33.38],[41.01,34.42],[41.38,35.63],[41.29,36.36],[41.84,36.61],[42.35,37.23],[42.78,37.39],[43.94,37.26],[44.29,37.0],[44.77,37.17],[45.42,35.98],[46.08,35.68],[46.15,35.09],[45.65,34.75],[45.42,33.97],[46.11,33.02],[47.33,32.47],[47.85,31.71],[47.69,30.98],[48.0,30.99],[48.01,30.45],[48.57,29.93],[47.97,29.98],[47.3,30.06],[46.57,29.1],[44.71,29.18],[41.89,31.19],[40.4,31.89],[39.2,32.16]]]]}},{"type":"Feature","properties":{"name":"Oman","iso":"OM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[55.21,22.71],[55.23,23.11],[55.53,23.52],[55.53,23.93],[55.98,24.13],[55.8,24.27],[55.89,24.92],[56.4,24.92],[56.85,24.24],[57.4,23.88],[58.14,23.75],[58.73,23.57],[59.18,22.99],[59.45,22.66],[59.81,22.53],[59.81,22.31],[59.44,21.71],[59.28,21.43],[58.86,21.11],[58.49,20.43],[58.03,20.48],[57.83,20.24],[57.67,19.74],[57.79,19.07],[57.69,18.94],[57.23,18.95],[56.61,18.57],[56.51,18.09],[56.28,17.88],[55.66,17.88],[55.27,17.63],[55.27,17.23],[54.79,16.95],[54.24,17.04],[53.57,16.71],[53.11,16.65],[52.78,17.35],[52.0,19.0],[55.0,20.0],[55.67,22.0],[55.21,22.71]]],[[[56.26,25.71],[56.07,26.06],[56.36,26.4],[56.49,26.31],[56.39,25.9],[56.26,25.71]]]]}},{"type":"Feature","properties":{"name":"Vanuatu","iso":"VU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[167.22,-15.89],[167.84,-16.47],[167.52,-16.6],[167.18,-16.16],[167.22,-15.89]]],[[[166.79,-15.67],[166.65,-15.39],[166.63,-14.63],[167.11,-14.93],[167.27,-15.74],[167.0,-15.61],[166.79,-15.67]]]]}},{"type":"Feature","properties":{"name":"Cambodia","iso":"KH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[102.58,12.19],[102.35,13.39],[102.99,14.23],[104.28,14.42],[105.22,14.27],[106.04,13.88],[106.5,14.57],[107.38,14.2],[107.61,13.54],[107.49,12.34],[105.81,11.57],[106.25,10.96],[105.2,10.89],[104.33,10.49],[103.5,10.63],[103.09,11.15],[102.58,12.19]]]]}},{"type":"Feature","properties":{"name":"Thailand","iso":"TH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[105.22,14.27],[104.28,14.42],[102.99,14.23],[102.35,13.39],[102.58,12.19],[101.69,12.65],[100.83,12.63],[100.98,13.41],[100.1,13.41],[100.02,12.31],[99.48,10.85],[99.15,9.96],[99.22,9.24],[99.87,9.21],[100.28,8.3],[100.46,7.43],[101.02,6.86],[101.62,6.74],[102.14,6.22],[101.81,5.81],[101.15,5.69],[101.08,6.2],[100.26,6.64],[100.09,6.46],[99.69,6.85],[99.52,7.34],[98.99,7.91],[98.5,8.38],[98.34,7.79],[98.15,8.35],[98.26,8.97],[98.55,9.93],[99.04,10.96],[99.59,11.89],[99.2,12.8],[99.21,13.27],[99.1,13.83],[98.43,14.62],[98.19,15.12],[98.54,15.31],[98.9,16.18],[98.49,16.84],[97.86,17.57],[97.38,18.45],[97.8,18.63],[98.25,19.71],[98.96,19.75],[99.54,20.19],[100.12,20.42],[100.55,20.11],[100.61,19.51],[101.28,19.46],[101.04,18.41],[101.06,17.51],[102.11,18.11],[102.41,17.93],[103.0,17.96],[103.2,18.31],[103.96,18.24],[104.72,17.43],[104.78,16.44],[105.59,15.57],[105.54,14.72],[105.22,14.27]]]]}},{"type":"Feature","properties":{"name":"Laos","iso":"LA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[107.38,14.2],[106.5,14.57],[106.04,13.88],[105.22,14.27],[105.54,14.72],[105.59,15.57],[104.78,16.44],[104.72,17.43],[103.96,18.24],[103.2,18.31],[103.0,17.96],[102.41,17.93],[102.11,18.11],[101.06,17.51],[101.04,18.41],[101.28,19.46],[100.61,19.51],[100.55,20.11],[100.12,20.42],[100.33,20.79],[101.18,21.44],[101.27,21.2],[101.8,21.17],[101.65,22.32],[102.17,22.46],[102.75,21.68],[103.2,20.77],[104.44,20.76],[104.82,19.89],[104.18,19.62],[103.9,19.27],[105.09,18.67],[105.93,17.49],[106.56,16.6],[107.31,15.91],[107.56,15.2],[107.38,14.2]]]]}},{"type":"Feature","properties":{"name":"Myanmar","iso":"MM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[100.12,20.42],[99.54,20.19],[98.96,19.75],[98.25,19.71],[97.8,18.63],[97.38,18.45],[97.86,17.57],[98.49,16.84],[98.9,16.18],[98.54,15.31],[98.19,15.12],[98.43,14.62],[99.1,13.83],[99.21,13.27],[99.2,12.8],[99.59,11.89],[99.04,10.96],[98.55,9.93],[98.46,10.68],[98.76,11.44],[98.43,12.03],[98.51,13.12],[98.1,13.64],[97.78,14.84],[97.6,16.1],[97.16,16.93],[96.51,16.43],[95.37,15.71],[94.81,15.8],[94.19,16.04],[94.53,17.28],[94.32,18.21],[93.54,19.37],[93.66,19.73],[93.08,19.86],[92.37,20.67],[92.3,21.48],[92.65,21.32],[92.67,22.04],[93.17,22.28],[93.06,22.7],[93.29,23.04],[93.33,24.08],[94.11,23.85],[94.55,24.68],[94.6,25.16],[95.16,26.0],[95.12,26.57],[96.42,27.26],[97.13,27.08],[97.05,27.7],[97.4,27.88],[97.33,28.26],[97.91,28.34],[98.25,27.75],[98.68,27.51],[98.71,26.74],[98.67,25.92],[97.72,25.08],[97.6,23.9],[98.66,24.06],[98.9,23.14],[99.53,22.95],[99.24,22.12],[99.98,21.74],[100.42,21.56],[101.15,21.85],[101.18,21.44],[100.33,20.79],[100.12,20.42]]]]}},{"type":"Feature","properties":{"name":"Vietnam","iso":"VN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[104.33,10.49],[105.2,10.89],[106.25,10.96],[105.81,11.57],[107.49,12.34],[107.61,13.54],[107.38,14.2],[107.56,15.2],[107.31,15.91],[106.56,16.6],[105.93,17.49],[105.09,18.67],[103.9,19.27],[104.18,19.62],[104.82,19.89],[104.44,20.76],[103.2,20.77],[102.75,21.68],[102.17,22.46],[102.71,22.71],[103.5,22.7],[104.48,22.82],[105.33,23.35],[105.81,22.98],[106.73,22.79],[106.57,22.22],[107.04,21.81],[108.05,21.55],[106.72,20.7],[105.88,19.75],[105.66,19.06],[106.43,18.0],[107.36,16.7],[108.27,16.08],[108.88,15.28],[109.34,13.43],[109.2,11.67],[108.37,11.01],[107.22,10.36],[106.41,9.53],[105.16,8.6],[104.8,9.24],[105.08,9.92],[104.33,10.49]]]]}},{"type":"Feature","properties":{"name":"North Korea","iso":"KP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[130.64,42.4],[130.78,42.22],[130.4,42.28],[129.97,41.94],[129.67,41.6],[129.71,40.88],[129.19,40.66],[129.01,40.49],[128.63,40.19],[127.97,40.03],[127.53,39.76],[127.5,39.32],[127.39,39.21],[127.78,39.05],[128.35,38.61],[128.21,38.37],[127.78,38.3],[127.07,38.26],[126.68,37.8],[126.24,37.84],[126.17,37.75],[125.69,37.94],[125.57,37.75],[125.28,37.67],[125.24,37.86],[124.98,37.95],[124.71,38.11],[124.99,38.55],[125.22,38.67],[125.13,38.85],[125.39,39.39],[125.32,39.55],[124.74,39.66],[124.27,39.93],[125.08,40.57],[126.18,41.11],[126.87,41.82],[127.34,41.5],[128.21,41.47],[128.05,41.99],[129.6,42.42],[129.99,42.99],[130.64,42.4]]]]}},{"type":"Feature","properties":{"name":"South Korea","iso":"KR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[126.17,37.75],[126.24,37.84],[126.68,37.8],[127.07,38.26],[127.78,38.3],[128.21,38.37],[128.35,38.61],[129.21,37.43],[129.46,36.78],[129.47,35.63],[129.09,35.08],[128.19,34.89],[127.39,34.48],[126.49,34.39],[126.37,34.93],[126.56,35.68],[126.12,36.73],[126.86,36.89],[126.17,37.75]]]]}},{"type":"Feature","properties":{"name":"Mongolia","iso":"MN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[87.75,49.3],[88.81,49.47],[90.71,50.33],[92.23,50.8],[93.1,50.5],[94.15,50.48],[94.82,50.01],[95.81,49.98],[97.26,49.73],[98.23,50.42],[97.83,51.01],[98.86,52.05],[99.98,51.63],[100.89,51.52],[102.07,51.26],[102.26,50.51],[103.68,50.09],[104.62,50.28],[105.89,50.41],[106.89,50.27],[107.87,49.79],[108.48,49.28],[109.4,49.29],[110.66,49.13],[111.58,49.38],[112.9,49.54],[114.36,50.25],[114.96,50.14],[115.49,49.81],[116.68,49.89],[116.19,49.13],[115.49,48.14],[115.74,47.73],[116.31,47.85],[117.3,47.7],[118.06,48.07],[118.87,47.75],[119.77,47.05],[119.66,46.69],[118.87,46.81],[117.42,46.67],[116.72,46.39],[115.99,45.73],[114.46,45.34],[113.46,44.81],[112.44,45.01],[111.87,45.1],[111.35,44.46],[111.67,44.07],[111.83,43.74],[111.13,43.41],[110.41,42.87],[109.24,42.52],[107.74,42.48],[106.13,42.13],[104.96,41.6],[104.52,41.91],[103.31,41.91],[101.83,42.51],[100.85,42.66],[99.52,42.52],[97.45,42.75],[96.35,42.73],[95.76,43.32],[95.31,44.24],[94.69,44.35],[93.48,44.98],[92.13,45.12],[90.95,45.29],[90.59,45.72],[90.97,46.89],[90.28,47.69],[88.85,48.07],[88.01,48.6],[87.75,49.3]]]]}},{"type":"Feature","properties":{"name":"India","iso":"IN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[97.33,28.26],[97.4,27.88],[97.05,27.7],[97.13,27.08],[96.42,27.26],[95.12,26.57],[95.16,26.0],[94.6,25.16],[94.55,24.68],[94.11,23.85],[93.33,24.08],[93.29,23.04],[93.06,22.7],[93.17,22.28],[92.67,22.04],[92.15,23.63],[91.87,23.62],[91.71,22.99],[91.16,23.5],[91.47,24.07],[91.92,24.13],[92.38,24.98],[91.8,25.15],[90.87,25.13],[89.92,25.27],[89.83,25.97],[89.36,26.01],[88.56,26.45],[88.21,25.77],[88.93,25.24],[88.31,24.87],[88.08,24.5],[88.7,24.23],[88.53,23.63],[88.88,22.88],[89.03,22.06],[88.89,21.69],[88.21,21.7],[86.98,21.5],[87.03,20.74],[86.5,20.15],[85.06,19.48],[83.94,18.3],[83.19,17.67],[82.19,17.02],[82.19,16.56],[81.69,16.31],[80.79,15.95],[80.32,15.9],[80.03,15.14],[80.23,13.84],[80.29,13.01],[79.86,12.06],[79.86,10.36],[79.34,10.31],[78.89,9.55],[79.19,9.22],[78.28,8.93],[77.94,8.25],[77.54,7.97],[76.59,8.9],[76.13,10.3],[75.75,11.31],[75.4,11.78],[74.86,12.74],[74.62,13.99],[74.44,14.62],[73.53,15.99],[73.12,17.93],[72.82,19.21],[72.82,20.42],[72.63,21.36],[71.18,20.76],[70.47,20.88],[69.16,22.09],[69.64,22.45],[69.35,22.84],[68.18,23.69],[68.84,24.36],[71.04,24.36],[70.84,25.22],[70.28,25.72],[70.17,26.49],[69.51,26.94],[70.62,27.99],[71.78,27.91],[72.82,28.96],[73.45,29.98],[74.42,30.98],[74.41,31.69],[75.26,32.27],[74.45,32.76],[74.1,33.44],[73.75,34.32],[74.24,34.75],[75.76,34.5],[76.87,34.65],[77.84,35.49],[78.91,34.32],[78.81,33.51],[79.21,32.99],[79.18,32.48],[78.46,32.62],[78.74,31.52],[79.72,30.88],[81.11,30.18],[80.48,29.73],[80.09,28.79],[81.06,28.42],[82.0,27.93],[83.3,27.36],[84.68,27.23],[85.25,26.73],[86.02,26.63],[87.23,26.4],[88.06,26.41],[88.17,26.81],[88.04,27.45],[88.12,27.88],[88.73,28.09],[88.81,27.3],[88.84,27.1],[89.74,26.72],[90.37,26.88],[91.22,26.81],[92.03,26.84],[92.1,27.45],[91.7,27.77],[92.5,27.9],[93.41,28.64],[94.57,29.28],[95.4,29.03],[96.12,29.45],[96.59,28.83],[96.25,28.41],[97.33,28.26]]]]}},{"type":"Feature","properties":{"name":"Bangladesh","iso":"BD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[92.67,22.04],[92.65,21.32],[92.3,21.48],[92.37,20.67],[92.08,21.19],[92.03,21.7],[91.83,22.18],[91.42,22.77],[90.5,22.81],[90.59,22.39],[90.27,21.84],[89.85,22.04],[89.7,21.86],[89.42,21.97],[89.03,22.06],[88.88,22.88],[88.53,23.63],[88.7,24.23],[88.08,24.5],[88.31,24.87],[88.93,25.24],[88.21,25.77],[88.56,26.45],[89.36,26.01],[89.83,25.97],[89.92,25.27],[90.87,25.13],[91.8,25.15],[92.38,24.98],[91.92,24.13],[91.47,24.07],[91.16,23.5],[91.71,22.99],[91.87,23.62],[92.15,23.63],[92.67,22.04]]]]}},{"type":"Feature","properties":{"name":"Bhutan","iso":"BT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[91.7,27.77],[92.1,27.45],[92.03,26.84],[91.22,26.81],[90.37,26.88],[89.74,26.72],[88.84,27.1],[88.81,27.3],[89.48,28.04],[90.02,28.3],[90.73,28.06],[91.26,28.04],[91.7,27.77]]]]}},{"type":"Feature","properties":{"name":"Nepal","iso":"NP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[88.12,27.88],[88.04,27.45],[88.17,26.81],[88.06,26.41],[87.23,26.4],[86.02,26.63],[85.25,26.73],[84.68,27.23],[83.3,27.36],[82.0,27.93],[81.06,28.42],[80.09,28.79],[80.48,29.73],[81.11,30.18],[81.53,30.42],[82.33,30.12],[83.34,29.46],[83.9,29.32],[84.23,28.84],[85.01,28.64],[85.82,28.2],[86.95,27.97],[88.12,27.88]]]]}},{"type":"Feature","properties":{"name":"Pakistan","iso":"PK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[77.84,35.49],[76.87,34.65],[75.76,34.5],[74.24,34.75],[73.75,34.32],[74.1,33.44],[74.45,32.76],[75.26,32.27],[74.41,31.69],[74.42,30.98],[73.45,29.98],[72.82,28.96],[71.78,27.91],[70.62,27.99],[69.51,26.94],[70.17,26.49],[70.28,25.72],[70.84,25.22],[71.04,24.36],[68.84,24.36],[68.18,23.69],[67.44,23.94],[67.15,24.66],[66.37,25.43],[64.53,25.24],[62.91,25.22],[61.5,25.08],[61.87,26.24],[63.32,26.76],[63.23,27.22],[62.76,27.38],[62.73,28.26],[61.77,28.7],[61.37,29.3],[60.87,29.83],[62.55,29.32],[63.55,29.47],[64.15,29.34],[64.35,29.56],[65.05,29.47],[66.35,29.89],[66.38,30.74],[66.94,31.3],[67.68,31.3],[67.79,31.58],[68.56,31.71],[68.93,31.62],[69.32,31.9],[69.26,32.5],[69.69,33.11],[70.32,33.36],[69.93,34.02],[70.88,33.99],[71.16,34.35],[71.12,34.73],[71.61,35.15],[71.5,35.65],[71.26,36.07],[71.85,36.51],[72.92,36.72],[74.07,36.84],[74.58,37.02],[75.16,37.13],[75.9,36.67],[76.19,35.9],[77.84,35.49]]]]}},{"type":"Feature","properties":{"name":"Afghanistan","iso":"AF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[66.52,37.36],[67.08,37.36],[67.83,37.14],[68.14,37.02],[68.86,37.34],[69.2,37.15],[69.52,37.61],[70.12,37.59],[70.27,37.74],[70.38,38.14],[70.81,38.49],[71.35,38.26],[71.24,37.95],[71.54,37.91],[71.45,37.07],[71.84,36.74],[72.19,36.95],[72.64,37.05],[73.26,37.5],[73.95,37.42],[74.98,37.42],[75.16,37.13],[74.58,37.02],[74.07,36.84],[72.92,36.72],[71.85,36.51],[71.26,36.07],[71.5,35.65],[71.61,35.15],[71.12,34.73],[71.16,34.35],[70.88,33.99],[69.93,34.02],[70.32,33.36],[69.69,33.11],[69.26,32.5],[69.32,31.9],[68.93,31.62],[68.56,31.71],[67.79,31.58],[67.68,31.3],[66.94,31.3],[66.38,30.74],[66.35,29.89],[65.05,29.47],[64.35,29.56],[64.15,29.34],[63.55,29.47],[62.55,29.32],[60.87,29.83],[61.78,30.74],[61.7,31.38],[60.94,31.55],[60.86,32.18],[60.54,32.98],[60.96,33.53],[60.53,33.68],[60.8,34.4],[61.21,35.65],[62.23,35.27],[62.98,35.4],[63.19,35.86],[63.98,36.01],[64.55,36.31],[64.75,37.11],[65.59,37.31],[65.75,37.66],[66.22,37.39],[66.52,37.36]]]]}},{"type":"Feature","properties":{"name":"Tajikistan","iso":"TJ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[67.83,37.14],[68.39,38.16],[68.18,38.9],[67.44,39.14],[67.7,39.58],[68.54,39.53],[69.01,40.09],[69.33,40.73],[70.67,40.96],[70.46,40.5],[70.6,40.22],[71.01,40.24],[70.65,39.94],[69.56,40.1],[69.46,39.53],[70.55,39.6],[71.78,39.28],[73.68,39.43],[73.93,38.51],[74.26,38.61],[74.86,38.38],[74.83,37.99],[74.98,37.42],[73.95,37.42],[73.26,37.5],[72.64,37.05],[72.19,36.95],[71.84,36.74],[71.45,37.07],[71.54,37.91],[71.24,37.95],[71.35,38.26],[70.81,38.49],[70.38,38.14],[70.27,37.74],[70.12,37.59],[69.52,37.61],[69.2,37.15],[68.86,37.34],[68.14,37.02],[67.83,37.14]]]]}},{"type":"Feature","properties":{"name":"Kyrgyzstan","iso":"KG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[70.96,42.27],[71.19,42.7],[71.84,42.85],[73.49,42.5],[73.65,43.09],[74.21,43.3],[75.64,42.88],[76.0,42.99],[77.66,42.96],[79.14,42.86],[79.64,42.5],[80.26,42.35],[80.12,42.12],[78.54,41.58],[78.19,41.19],[76.9,41.07],[76.53,40.43],[75.47,40.56],[74.78,40.37],[73.82,39.89],[73.96,39.66],[73.68,39.43],[71.78,39.28],[70.55,39.6],[69.46,39.53],[69.56,40.1],[70.65,39.94],[71.01,40.24],[71.77,40.15],[73.06,40.87],[71.87,41.39],[71.16,41.14],[70.42,41.52],[71.26,42.17],[70.96,42.27]]]]}},{"type":"Feature","properties":{"name":"Turkmenistan","iso":"TM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[52.5,41.78],[52.94,42.12],[54.08,42.32],[54.76,42.04],[55.46,41.26],[55.97,41.31],[57.1,41.32],[56.93,41.83],[57.79,42.17],[58.63,42.75],[59.98,42.22],[60.08,41.43],[60.47,41.22],[61.55,41.27],[61.88,41.08],[62.37,40.05],[63.52,39.36],[64.17,38.89],[65.22,38.4],[66.55,37.97],[66.52,37.36],[66.22,37.39],[65.75,37.66],[65.59,37.31],[64.75,37.11],[64.55,36.31],[63.98,36.01],[63.19,35.86],[62.98,35.4],[62.23,35.27],[61.21,35.65],[61.12,36.49],[60.38,36.53],[59.23,37.41],[58.44,37.52],[57.33,38.03],[56.62,38.12],[56.18,37.94],[55.51,37.96],[54.8,37.39],[53.92,37.2],[53.74,37.91],[53.88,38.95],[53.1,39.29],[53.36,39.98],[52.69,40.03],[52.92,40.88],[53.86,40.63],[54.74,40.95],[54.01,41.55],[53.72,42.12],[52.92,41.87],[52.81,41.14],[52.5,41.78]]]]}},{"type":"Feature","properties":{"name":"Iran","iso":"IR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[48.57,29.93],[48.01,30.45],[48.0,30.99],[47.69,30.98],[47.85,31.71],[47.33,32.47],[46.11,33.02],[45.42,33.97],[45.65,34.75],[46.15,35.09],[46.08,35.68],[45.42,35.98],[44.77,37.17],[44.23,37.97],[44.42,38.28],[44.11,39.43],[44.79,39.71],[44.95,39.34],[45.46,38.87],[46.14,38.74],[46.51,38.77],[47.69,39.51],[48.06,39.58],[48.36,39.29],[48.01,38.79],[48.63,38.27],[48.88,38.32],[49.2,37.58],[50.15,37.37],[50.84,36.87],[52.26,36.7],[53.83,36.97],[53.92,37.2],[54.8,37.39],[55.51,37.96],[56.18,37.94],[56.62,38.12],[57.33,38.03],[58.44,37.52],[59.23,37.41],[60.38,36.53],[61.12,36.49],[61.21,35.65],[60.8,34.4],[60.53,33.68],[60.96,33.53],[60.54,32.98],[60.86,32.18],[60.94,31.55],[61.7,31.38],[61.78,30.74],[60.87,29.83],[61.37,29.3],[61.77,28.7],[62.73,28.26],[62.76,27.38],[63.23,27.22],[63.32,26.76],[61.87,26.24],[61.5,25.08],[59.62,25.38],[58.53,25.61],[57.4,25.74],[56.97,26.97],[56.49,27.14],[55.72,26.96],[54.72,26.48],[53.49,26.81],[52.48,27.58],[51.52,27.87],[50.85,28.81],[50.12,30.15],[49.58,29.99],[48.94,30.32],[48.57,29.93]]]]}},{"type":"Feature","properties":{"name":"Syria","iso":"SY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.72,32.71],[35.7,32.72],[35.84,32.87],[35.82,33.28],[36.07,33.82],[36.61,34.2],[36.45,34.59],[36.0,34.64],[35.91,35.41],[36.15,35.82],[36.42,36.04],[36.69,36.26],[36.74,36.82],[37.07,36.62],[38.17,36.9],[38.7,36.71],[39.52,36.72],[40.67,37.09],[41.21,37.07],[42.35,37.23],[41.84,36.61],[41.29,36.36],[41.38,35.63],[41.01,34.42],[38.79,33.38],[36.83,32.31],[35.72,32.71]]]]}},{"type":"Feature","properties":{"name":"Armenia","iso":"AM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[46.51,38.77],[46.14,38.74],[45.74,39.32],[45.74,39.47],[45.3,39.47],[45.0,39.74],[44.79,39.71],[44.4,40.01],[43.66,40.25],[43.75,40.74],[43.58,41.09],[44.97,41.25],[45.18,40.99],[45.56,40.81],[45.36,40.56],[45.89,40.22],[45.61,39.9],[46.03,39.63],[46.48,39.46],[46.51,38.77]]]]}},{"type":"Feature","properties":{"name":"Sweden","iso":"SE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[11.03,58.86],[11.47,59.43],[12.3,60.12],[12.63,61.29],[11.99,61.8],[11.93,63.13],[12.58,64.07],[13.57,64.05],[13.92,64.45],[13.56,64.79],[15.11,66.19],[16.11,67.3],[16.77,68.01],[17.73,68.01],[17.99,68.57],[19.88,68.41],[20.03,69.07],[20.65,69.11],[21.98,68.62],[23.54,67.94],[23.57,66.4],[23.9,66.01],[22.18,65.72],[21.21,65.03],[21.37,64.41],[19.78,63.61],[17.85,62.75],[17.12,61.34],[17.83,60.64],[18.79,60.08],[17.87,58.95],[16.83,58.72],[16.45,57.04],[15.88,56.1],[14.67,56.2],[14.1,55.41],[12.94,55.36],[12.63,56.31],[11.79,57.44],[11.03,58.86]]]]}},{"type":"Feature","properties":{"name":"Belarus","iso":"BY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[28.18,56.17],[29.23,55.92],[29.37,55.67],[29.9,55.79],[30.87,55.55],[30.97,55.08],[30.76,54.81],[31.38,54.16],[31.79,53.97],[31.73,53.79],[32.41,53.62],[32.69,53.35],[32.3,53.13],[31.5,53.17],[31.31,53.07],[31.54,52.74],[31.79,52.1],[30.93,52.04],[30.62,51.82],[30.56,51.32],[30.16,51.42],[29.25,51.37],[28.99,51.6],[28.62,51.43],[28.24,51.57],[27.45,51.59],[26.34,51.83],[25.33,51.91],[24.55,51.89],[24.01,51.62],[23.53,51.58],[23.51,52.02],[23.2,52.49],[23.8,52.69],[23.8,53.09],[23.53,53.47],[23.48,53.91],[24.45,53.91],[25.54,54.28],[25.77,54.85],[26.59,55.17],[26.49,55.62],[27.1,55.78],[28.18,56.17]]]]}},{"type":"Feature","properties":{"name":"Ukraine","iso":"UA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[31.79,52.1],[32.16,52.06],[32.41,52.29],[32.72,52.24],[33.75,52.34],[34.39,51.77],[34.14,51.57],[34.22,51.26],[35.02,51.21],[35.38,50.77],[35.36,50.58],[36.63,50.23],[37.39,50.38],[38.01,49.92],[38.59,49.93],[40.07,49.6],[40.08,49.31],[39.67,48.78],[39.9,48.23],[39.74,47.9],[38.77,47.83],[38.26,47.55],[38.22,47.1],[37.43,47.02],[36.76,46.7],[35.82,46.65],[34.96,46.27],[35.01,45.74],[34.86,45.77],[34.73,45.97],[34.41,46.01],[33.7,46.22],[33.44,45.97],[33.3,46.08],[31.74,46.33],[31.68,46.71],[30.75,46.58],[30.38,46.03],[29.6,45.29],[29.15,45.46],[28.68,45.3],[28.23,45.49],[28.49,45.6],[28.66,45.94],[28.93,46.26],[28.86,46.44],[29.07,46.52],[29.17,46.38],[29.76,46.35],[30.02,46.42],[29.84,46.53],[29.91,46.67],[29.56,46.93],[29.42,47.35],[29.05,47.51],[29.12,47.85],[28.67,48.12],[28.26,48.16],[27.52,48.47],[26.86,48.37],[26.62,48.22],[26.2,48.22],[25.95,47.99],[25.21,47.89],[24.87,47.74],[24.4,47.98],[23.76,47.99],[23.14,48.1],[22.71,47.88],[22.64,48.15],[22.09,48.42],[22.28,48.83],[22.56,49.09],[22.78,49.03],[22.52,49.48],[23.43,50.31],[23.92,50.42],[24.03,50.71],[23.53,51.58],[24.01,51.62],[24.55,51.89],[25.33,51.91],[26.34,51.83],[27.45,51.59],[28.24,51.57],[28.62,51.43],[28.99,51.6],[29.25,51.37],[30.16,51.42],[30.56,51.32],[30.62,51.82],[30.93,52.04],[31.79,52.1]]]]}},{"type":"Feature","properties":{"name":"Poland","iso":"PL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[23.48,53.91],[23.53,53.47],[23.8,53.09],[23.8,52.69],[23.2,52.49],[23.51,52.02],[23.53,51.58],[24.03,50.71],[23.92,50.42],[23.43,50.31],[22.52,49.48],[22.78,49.03],[22.56,49.09],[21.61,49.47],[20.89,49.33],[20.42,49.43],[19.83,49.22],[19.32,49.57],[18.91,49.44],[18.85,49.5],[18.39,49.99],[17.65,50.05],[17.55,50.36],[16.87,50.47],[16.72,50.22],[16.18,50.42],[16.24,50.7],[15.49,50.78],[15.02,51.11],[14.61,51.75],[14.69,52.09],[14.44,52.62],[14.07,52.98],[14.35,53.25],[14.12,53.76],[14.8,54.05],[16.36,54.51],[17.62,54.85],[18.62,54.68],[18.7,54.44],[19.66,54.43],[20.89,54.31],[22.73,54.33],[23.24,54.22],[23.48,53.91]]]]}},{"type":"Feature","properties":{"name":"Austria","iso":"AT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[16.98,48.12],[16.9,47.71],[16.34,47.71],[16.53,47.5],[16.2,46.85],[16.01,46.68],[15.14,46.66],[14.63,46.43],[13.81,46.51],[12.38,46.77],[12.15,47.12],[11.16,46.94],[11.05,46.75],[10.44,46.89],[9.93,46.92],[9.48,47.1],[9.63,47.35],[9.59,47.53],[9.9,47.58],[10.4,47.3],[10.54,47.57],[11.43,47.52],[12.14,47.7],[12.62,47.67],[12.93,47.47],[13.03,47.64],[12.88,48.29],[13.24,48.42],[13.6,48.88],[14.34,48.56],[14.9,48.96],[15.25,49.04],[16.03,48.73],[16.5,48.79],[16.96,48.6],[16.88,48.47],[16.98,48.12]]]]}},{"type":"Feature","properties":{"name":"Hungary","iso":"HU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[22.09,48.42],[22.64,48.15],[22.71,47.88],[22.1,47.67],[21.63,46.99],[21.02,46.32],[20.22,46.13],[19.6,46.17],[18.83,45.91],[18.46,45.76],[17.63,45.95],[16.88,46.38],[16.56,46.5],[16.37,46.84],[16.2,46.85],[16.53,47.5],[16.34,47.71],[16.9,47.71],[16.98,48.12],[17.49,47.87],[17.86,47.76],[18.7,47.88],[18.78,48.08],[19.17,48.11],[19.66,48.27],[19.77,48.2],[20.24,48.33],[20.47,48.56],[20.8,48.62],[21.87,48.32],[22.09,48.42]]]]}},{"type":"Feature","properties":{"name":"Moldova","iso":"MD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.62,48.22],[26.86,48.37],[27.52,48.47],[28.26,48.16],[28.67,48.12],[29.12,47.85],[29.05,47.51],[29.42,47.35],[29.56,46.93],[29.91,46.67],[29.84,46.53],[30.02,46.42],[29.76,46.35],[29.17,46.38],[29.07,46.52],[28.86,46.44],[28.93,46.26],[28.66,45.94],[28.49,45.6],[28.23,45.49],[28.05,45.94],[28.16,46.37],[28.13,46.81],[27.55,47.41],[27.23,47.83],[26.92,48.12],[26.62,48.22]]]]}},{"type":"Feature","properties":{"name":"Romania","iso":"RO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[28.23,45.49],[28.68,45.3],[29.15,45.46],[29.6,45.29],[29.63,45.04],[29.14,44.82],[28.84,44.91],[28.56,43.71],[27.97,43.81],[27.24,44.18],[26.07,43.94],[25.57,43.69],[24.1,43.74],[23.33,43.9],[22.94,43.82],[22.66,44.23],[22.47,44.41],[22.71,44.58],[22.46,44.7],[22.15,44.48],[21.56,44.77],[21.48,45.18],[20.87,45.42],[20.76,45.73],[20.22,46.13],[21.02,46.32],[21.63,46.99],[22.1,47.67],[22.71,47.88],[23.14,48.1],[23.76,47.99],[24.4,47.98],[24.87,47.74],[25.21,47.89],[25.95,47.99],[26.2,48.22],[26.62,48.22],[26.92,48.12],[27.23,47.83],[27.55,47.41],[28.13,46.81],[28.16,46.37],[28.05,45.94],[28.23,45.49]]]]}},{"type":"Feature","properties":{"name":"Lithuania","iso":"LT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.49,55.62],[26.59,55.17],[25.77,54.85],[25.54,54.28],[24.45,53.91],[23.48,53.91],[23.24,54.22],[22.73,54.33],[22.65,54.58],[22.76,54.86],[22.32,55.02],[21.27,55.19],[21.06,56.03],[22.2,56.34],[23.88,56.27],[24.86,56.37],[25.0,56.16],[25.53,56.1],[26.49,55.62]]]]}},{"type":"Feature","properties":{"name":"Latvia","iso":"LV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[27.29,57.47],[27.77,57.24],[27.86,56.76],[28.18,56.17],[27.1,55.78],[26.49,55.62],[25.53,56.1],[25.0,56.16],[24.86,56.37],[23.88,56.27],[22.2,56.34],[21.06,56.03],[21.09,56.78],[21.58,57.41],[22.52,57.75],[23.32,57.01],[24.12,57.03],[24.31,57.79],[25.16,57.97],[25.6,57.85],[26.46,57.48],[27.29,57.47]]]]}},{"type":"Feature","properties":{"name":"Estonia","iso":"EE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[27.98,59.48],[28.13,59.3],[27.42,58.72],[27.72,57.79],[27.29,57.47],[26.46,57.48],[25.6,57.85],[25.16,57.97],[24.31,57.79],[24.43,58.38],[24.06,58.26],[23.43,58.61],[23.34,59.19],[24.6,59.47],[25.86,59.61],[26.95,59.45],[27.98,59.48]]]]}},{"type":"Feature","properties":{"name":"Germany","iso":"DE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.12,53.76],[14.35,53.25],[14.07,52.98],[14.44,52.62],[14.69,52.09],[14.61,51.75],[15.02,51.11],[14.57,51.0],[14.31,51.12],[14.06,50.93],[13.34,50.73],[12.97,50.48],[12.24,50.27],[12.42,49.97],[12.52,49.55],[13.03,49.31],[13.6,48.88],[13.24,48.42],[12.88,48.29],[13.03,47.64],[12.93,47.47],[12.62,47.67],[12.14,47.7],[11.43,47.52],[10.54,47.57],[10.4,47.3],[9.9,47.58],[9.59,47.53],[8.52,47.83],[8.32,47.61],[7.47,47.62],[7.59,48.33],[8.1,49.02],[6.66,49.2],[6.19,49.46],[6.24,49.9],[6.04,50.13],[6.16,50.8],[5.99,51.85],[6.59,51.85],[6.84,52.23],[7.09,53.14],[6.91,53.48],[7.1,53.69],[7.94,53.75],[8.12,53.53],[8.8,54.02],[8.57,54.4],[8.53,54.96],[9.28,54.83],[9.92,54.98],[9.94,54.6],[10.95,54.36],[10.94,54.01],[11.96,54.2],[12.52,54.47],[13.65,54.08],[14.12,53.76]]]]}},{"type":"Feature","properties":{"name":"Bulgaria","iso":"BG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[22.66,44.23],[22.94,43.82],[23.33,43.9],[24.1,43.74],[25.57,43.69],[26.07,43.94],[27.24,44.18],[27.97,43.81],[28.56,43.71],[28.04,43.29],[27.67,42.58],[28.0,42.01],[27.14,42.14],[26.12,41.83],[26.11,41.33],[25.2,41.23],[24.49,41.58],[23.69,41.31],[22.95,41.34],[22.88,42.0],[22.38,42.32],[22.55,42.46],[22.44,42.58],[22.6,42.9],[22.99,43.21],[22.5,43.64],[22.41,44.01],[22.66,44.23]]]]}},{"type":"Feature","properties":{"name":"Greece","iso":"GR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.29,35.3],[26.16,35.0],[24.72,34.92],[24.74,35.08],[23.51,35.28],[23.7,35.71],[24.25,35.37],[25.03,35.42],[25.77,35.35],[25.75,35.18],[26.29,35.3]]],[[[22.95,41.34],[23.69,41.31],[24.49,41.58],[25.2,41.23],[26.11,41.33],[26.12,41.83],[26.6,41.56],[26.29,40.94],[26.06,40.82],[25.45,40.85],[24.93,40.95],[23.71,40.69],[24.41,40.12],[23.9,39.96],[23.34,39.96],[22.81,40.48],[22.63,40.26],[22.85,39.66],[23.35,39.19],[22.97,38.97],[23.53,38.51],[24.03,38.22],[24.04,37.66],[23.12,37.92],[23.41,37.41],[22.77,37.31],[23.15,36.42],[22.49,36.41],[21.67,36.84],[21.3,37.64],[21.12,38.31],[20.73,38.77],[20.22,39.34],[20.15,39.62],[20.61,40.11],[20.67,40.44],[21.0,40.58],[21.02,40.84],[21.67,40.93],[22.06,41.15],[22.6,41.13],[22.76,41.3],[22.95,41.34]]]]}},{"type":"Feature","properties":{"name":"Turkey","iso":"TR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[44.77,37.17],[44.29,37.0],[43.94,37.26],[42.78,37.39],[42.35,37.23],[41.21,37.07],[40.67,37.09],[39.52,36.72],[38.7,36.71],[38.17,36.9],[37.07,36.62],[36.74,36.82],[36.69,36.26],[36.42,36.04],[36.15,35.82],[35.78,36.27],[36.16,36.65],[35.55,36.57],[34.71,36.8],[34.03,36.22],[32.51,36.11],[31.7,36.64],[30.62,36.68],[30.39,36.26],[29.7,36.14],[28.73,36.68],[27.64,36.66],[27.05,37.65],[26.32,38.21],[26.8,38.99],[26.17,39.46],[27.28,40.42],[28.82,40.46],[29.24,41.22],[31.15,41.09],[32.35,41.74],[33.51,42.02],[35.17,42.04],[36.91,41.34],[38.35,40.95],[39.51,41.1],[40.37,41.01],[41.55,41.54],[42.62,41.58],[43.58,41.09],[43.75,40.74],[43.66,40.25],[44.4,40.01],[44.79,39.71],[44.11,39.43],[44.42,38.28],[44.23,37.97],[44.77,37.17]]],[[[26.12,41.83],[27.14,42.14],[28.0,42.01],[28.12,41.62],[28.99,41.3],[28.81,41.05],[27.62,41.0],[27.19,40.69],[26.36,40.15],[26.04,40.62],[26.06,40.82],[26.29,40.94],[26.6,41.56],[26.12,41.83]]]]}},{"type":"Feature","properties":{"name":"Albania","iso":"AL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[21.02,40.84],[21.0,40.58],[20.67,40.44],[20.61,40.11],[20.15,39.62],[19.98,39.69],[19.96,39.92],[19.41,40.25],[19.32,40.73],[19.4,41.41],[19.54,41.72],[19.37,41.88],[19.3,42.2],[19.74,42.69],[19.8,42.5],[20.07,42.59],[20.28,42.32],[20.52,42.22],[20.59,41.86],[20.46,41.52],[20.61,41.09],[21.02,40.84]]]]}},{"type":"Feature","properties":{"name":"Croatia","iso":"HR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[16.56,46.5],[16.88,46.38],[17.63,45.95],[18.46,45.76],[18.83,45.91],[19.07,45.52],[19.39,45.24],[19.01,44.86],[18.55,45.08],[17.86,45.07],[17.0,45.23],[16.53,45.21],[16.32,45.0],[15.96,45.23],[15.75,44.82],[16.24,44.35],[16.46,44.04],[16.92,43.67],[17.3,43.45],[17.67,43.03],[18.56,42.65],[18.45,42.48],[17.51,42.85],[16.93,43.21],[16.02,43.51],[15.17,44.24],[15.38,44.32],[14.92,44.74],[14.9,45.08],[14.26,45.23],[13.95,44.8],[13.66,45.14],[13.68,45.48],[13.72,45.5],[14.41,45.47],[14.6,45.63],[14.94,45.47],[15.33,45.45],[15.32,45.73],[15.67,45.83],[15.77,46.24],[16.56,46.5]]]]}},{"type":"Feature","properties":{"name":"Switzerland","iso":"CH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.59,47.53],[9.63,47.35],[9.48,47.1],[9.93,46.92],[10.44,46.89],[10.36,46.48],[9.92,46.31],[9.18,46.44],[8.97,46.04],[8.49,46.01],[8.32,46.16],[7.76,45.82],[7.27,45.78],[6.84,45.99],[6.5,46.43],[6.02,46.27],[6.04,46.73],[6.77,47.29],[6.74,47.54],[7.19,47.45],[7.47,47.62],[8.32,47.61],[8.52,47.83],[9.59,47.53]]]]}},{"type":"Feature","properties":{"name":"Luxembourg","iso":"LU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.04,50.13],[6.24,49.9],[6.19,49.46],[5.9,49.44],[5.67,49.53],[5.78,50.09],[6.04,50.13]]]]}},{"type":"Feature","properties":{"name":"Belgium","iso":"BE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.16,50.8],[6.04,50.13],[5.78,50.09],[5.67,49.53],[4.8,49.99],[4.29,49.91],[3.59,50.38],[3.12,50.78],[2.66,50.8],[2.51,51.15],[3.31,51.35],[3.32,51.35],[3.31,51.35],[4.05,51.27],[4.97,51.48],[5.61,51.04],[6.16,50.8]]]]}},{"type":"Feature","properties":{"name":"Netherlands","iso":"NL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.91,53.48],[7.09,53.14],[6.84,52.23],[6.59,51.85],[5.99,51.85],[6.16,50.8],[5.61,51.04],[4.97,51.48],[4.05,51.27],[3.31,51.35],[3.32,51.35],[3.83,51.62],[4.71,53.09],[6.07,53.51],[6.91,53.48]]]]}},{"type":"Feature","properties":{"name":"Portugal","iso":"PT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-9.03,41.88],[-8.67,42.13],[-8.26,42.28],[-8.01,41.79],[-7.42,41.79],[-7.25,41.92],[-6.67,41.88],[-6.39,41.38],[-6.85,41.11],[-6.86,40.33],[-7.03,40.18],[-7.07,39.71],[-7.5,39.63],[-7.1,39.03],[-7.37,38.37],[-7.03,38.08],[-7.17,37.8],[-7.54,37.43],[-7.45,37.1],[-7.86,36.84],[-8.38,36.98],[-8.9,36.87],[-8.75,37.65],[-8.84,38.27],[-9.29,38.36],[-9.53,38.74],[-9.45,39.39],[-9.05,39.76],[-8.98,40.16],[-8.77,40.76],[-8.79,41.18],[-8.99,41.54],[-9.03,41.88]]]]}},{"type":"Feature","properties":{"name":"Spain","iso":"ES"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-7.45,37.1],[-7.54,37.43],[-7.17,37.8],[-7.03,38.08],[-7.37,38.37],[-7.1,39.03],[-7.5,39.63],[-7.07,39.71],[-7.03,40.18],[-6.86,40.33],[-6.85,41.11],[-6.39,41.38],[-6.67,41.88],[-7.25,41.92],[-7.42,41.79],[-8.01,41.79],[-8.26,42.28],[-8.67,42.13],[-9.03,41.88],[-8.98,42.59],[-9.39,43.03],[-7.98,43.75],[-6.75,43.57],[-5.41,43.57],[-4.35,43.4],[-3.52,43.46],[-1.9,43.42],[-1.5,43.03],[0.34,42.58],[0.7,42.8],[1.83,42.34],[2.99,42.47],[3.04,41.89],[2.09,41.23],[0.81,41.01],[0.72,40.68],[0.11,40.12],[-0.28,39.31],[0.11,38.74],[-0.47,38.29],[-0.68,37.64],[-1.44,37.44],[-2.15,36.67],[-3.42,36.66],[-4.37,36.68],[-5.0,36.32],[-5.38,35.95],[-5.87,36.03],[-6.24,36.37],[-6.52,36.94],[-7.45,37.1]]]]}},{"type":"Feature","properties":{"name":"Ireland","iso":"IE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-6.2,53.87],[-6.03,53.15],[-6.79,52.26],[-8.56,51.67],[-9.98,51.82],[-9.17,52.86],[-9.69,53.88],[-8.33,54.66],[-7.57,55.13],[-7.37,54.6],[-7.57,54.06],[-6.95,54.07],[-6.2,53.87]]]]}},{"type":"Feature","properties":{"name":"New Caledonia","iso":"NC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[165.78,-21.08],[166.6,-21.7],[167.12,-22.16],[166.74,-22.4],[166.19,-22.13],[165.47,-21.68],[164.83,-21.15],[164.17,-20.44],[164.03,-20.11],[164.46,-20.12],[165.02,-20.46],[165.46,-20.8],[165.78,-21.08]]]]}},{"type":"Feature","properties":{"name":"Solomon Is.","iso":"SB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[162.12,-10.48],[162.4,-10.83],[161.7,-10.82],[161.32,-10.2],[161.92,-10.45],[162.12,-10.48]]],[[[161.68,-9.6],[161.53,-9.78],[160.79,-8.92],[160.58,-8.32],[160.92,-8.32],[161.28,-9.12],[161.68,-9.6]]],[[[160.85,-9.87],[160.46,-9.9],[159.85,-9.79],[159.64,-9.64],[159.7,-9.24],[160.36,-9.4],[160.69,-9.61],[160.85,-9.87]]],[[[159.64,-8.02],[159.88,-8.34],[159.92,-8.54],[159.13,-8.11],[158.59,-7.75],[158.21,-7.42],[158.36,-7.32],[158.82,-7.56],[159.64,-8.02]]],[[[157.14,-7.02],[157.54,-7.35],[157.34,-7.4],[156.9,-7.18],[156.49,-6.77],[156.54,-6.6],[157.14,-7.02]]]]}},{"type":"Feature","properties":{"name":"New Zealand","iso":"NZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[176.89,-40.07],[176.51,-40.6],[176.01,-41.29],[175.24,-41.69],[175.07,-41.43],[174.65,-41.28],[175.23,-40.46],[174.9,-39.91],[173.82,-39.51],[173.85,-39.15],[174.57,-38.8],[174.74,-38.03],[174.7,-37.38],[174.29,-36.71],[174.32,-36.53],[173.84,-36.12],[173.05,-35.24],[172.64,-34.53],[173.01,-34.45],[173.55,-35.01],[174.33,-35.27],[174.61,-36.16],[175.34,-37.21],[175.36,-36.53],[175.81,-36.8],[175.96,-37.56],[176.76,-37.88],[177.44,-37.96],[178.01,-37.58],[178.52,-37.7],[178.27,-38.58],[177.97,-39.17],[177.21,-39.15],[176.94,-39.45],[177.03,-39.88],[176.89,-40.07]]],[[[169.67,-43.56],[170.52,-43.03],[171.13,-42.51],[171.57,-41.77],[171.95,-41.51],[172.1,-40.96],[172.8,-40.49],[173.02,-40.92],[173.25,-41.33],[173.96,-40.93],[174.25,-41.35],[174.25,-41.77],[173.88,-42.23],[173.22,-42.97],[172.71,-43.37],[173.08,-43.85],[172.31,-43.87],[171.45,-44.24],[171.19,-44.9],[170.62,-45.91],[169.83,-46.36],[169.33,-46.64],[168.41,-46.62],[167.76,-46.29],[166.68,-46.22],[166.51,-45.85],[167.05,-45.11],[168.3,-44.12],[168.95,-43.94],[169.67,-43.56]]]]}},{"type":"Feature","properties":{"name":"Australia","iso":"AU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[147.69,-40.81],[148.29,-40.88],[148.36,-42.06],[148.02,-42.41],[147.91,-43.21],[147.56,-42.94],[146.87,-43.63],[146.66,-43.58],[146.05,-43.55],[145.43,-42.69],[145.3,-42.03],[144.72,-41.16],[144.74,-40.7],[145.4,-40.79],[146.36,-41.14],[146.91,-41.0],[147.69,-40.81]]],[[[126.15,-32.22],[125.09,-32.73],[124.22,-32.96],[124.03,-33.48],[123.66,-33.89],[122.81,-33.91],[122.18,-34.0],[121.3,-33.82],[120.58,-33.93],[119.89,-33.98],[119.3,-34.51],[119.01,-34.46],[118.51,-34.75],[118.02,-35.06],[117.3,-35.03],[116.63,-35.03],[115.56,-34.39],[115.03,-34.2],[115.05,-33.62],[115.55,-33.49],[115.71,-33.26],[115.68,-32.9],[115.8,-32.21],[115.69,-31.61],[115.16,-30.6],[115.0,-30.03],[115.04,-29.46],[114.64,-28.81],[114.62,-28.52],[114.17,-28.12],[114.05,-27.33],[113.48,-26.54],[113.34,-26.12],[113.78,-26.55],[113.44,-25.62],[113.94,-25.91],[114.23,-26.3],[114.22,-25.79],[113.72,-25.0],[113.63,-24.68],[113.39,-24.38],[113.5,-23.81],[113.71,-23.56],[113.84,-23.06],[113.74,-22.48],[114.15,-21.76],[114.23,-22.52],[114.65,-21.83],[115.46,-21.5],[115.95,-21.07],[116.71,-20.7],[117.17,-20.62],[117.44,-20.75],[118.23,-20.37],[118.84,-20.26],[118.99,-20.04],[119.25,-19.95],[119.81,-19.98],[120.86,-19.68],[121.4,-19.24],[121.66,-18.71],[122.24,-18.2],[122.29,-17.8],[122.31,-17.25],[123.01,-16.41],[123.43,-17.27],[123.86,-17.07],[123.5,-16.6],[123.82,-16.11],[124.26,-16.33],[124.38,-15.57],[124.93,-15.08],[125.17,-14.68],[125.67,-14.51],[125.69,-14.23],[126.13,-14.35],[126.14,-14.1],[126.58,-13.95],[127.07,-13.82],[127.8,-14.28],[128.36,-14.87],[128.99,-14.88],[129.62,-14.97],[129.41,-14.42],[129.89,-13.62],[130.34,-13.36],[130.18,-13.11],[130.62,-12.54],[131.22,-12.18],[131.74,-12.3],[132.58,-12.11],[132.56,-11.6],[131.82,-11.27],[132.36,-11.13],[133.02,-11.38],[133.55,-11.79],[134.39,-12.04],[134.68,-11.94],[135.3,-12.25],[135.88,-11.96],[136.26,-12.05],[136.49,-11.86],[136.95,-12.35],[136.69,-12.89],[136.31,-13.29],[135.96,-13.32],[136.08,-13.72],[135.78,-14.22],[135.43,-14.72],[135.5,-15.0],[136.3,-15.55],[137.07,-15.87],[137.58,-16.22],[138.3,-16.81],[138.59,-16.81],[139.11,-17.06],[139.26,-17.37],[140.22,-17.71],[140.88,-17.37],[141.07,-16.83],[141.27,-16.39],[141.4,-15.84],[141.7,-15.04],[141.56,-14.56],[141.64,-14.27],[141.52,-13.7],[141.65,-12.94],[141.84,-12.74],[141.69,-12.41],[141.93,-11.88],[142.12,-11.33],[142.14,-11.04],[142.52,-10.67],[142.8,-11.16],[142.87,-11.78],[143.12,-11.91],[143.16,-12.33],[143.52,-12.83],[143.6,-13.4],[143.56,-13.76],[143.92,-14.55],[144.56,-14.17],[144.89,-14.59],[145.37,-14.98],[145.27,-15.43],[145.49,-16.29],[145.64,-16.78],[145.89,-16.91],[146.16,-17.76],[146.06,-18.28],[146.39,-18.96],[147.47,-19.48],[148.18,-19.96],[148.85,-20.39],[148.72,-20.63],[149.29,-21.26],[149.68,-22.34],[150.08,-22.12],[150.48,-22.56],[150.73,-22.4],[150.9,-23.46],[151.61,-24.08],[152.07,-24.46],[152.86,-25.27],[153.14,-26.07],[153.16,-26.64],[153.09,-27.26],[153.57,-28.11],[153.51,-29.0],[153.34,-29.46],[153.07,-30.35],[153.09,-30.92],[152.89,-31.64],[152.45,-32.55],[151.71,-33.04],[151.34,-33.82],[151.01,-34.31],[150.71,-35.17],[150.33,-35.67],[150.08,-36.42],[149.95,-37.11],[150.0,-37.43],[149.42,-37.77],[148.3,-37.81],[147.38,-38.22],[146.92,-38.61],[146.32,-39.04],[145.49,-38.59],[144.88,-38.42],[145.03,-37.9],[144.49,-38.09],[143.61,-38.81],[142.75,-38.54],[142.18,-38.38],[141.61,-38.31],[140.64,-38.02],[139.99,-37.4],[139.81,-36.64],[139.57,-36.14],[139.08,-35.73],[138.12,-35.61],[138.45,-35.13],[138.21,-34.38],[137.72,-35.08],[136.83,-35.26],[137.35,-34.71],[137.5,-34.13],[137.89,-33.64],[137.81,-32.9],[137.0,-33.75],[136.37,-34.09],[135.99,-34.89],[135.21,-34.48],[135.24,-33.95],[134.61,-33.22],[134.09,-32.85],[134.27,-32.62],[132.99,-32.01],[132.29,-31.98],[131.33,-31.5],[129.54,-31.59],[128.24,-31.95],[127.1,-32.28],[126.15,-32.22]]]]}},{"type":"Feature","properties":{"name":"Sri Lanka","iso":"LK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[81.79,7.52],[81.64,6.48],[81.22,6.2],[80.35,5.97],[79.87,6.76],[79.7,8.2],[80.15,9.82],[80.84,9.27],[81.3,8.56],[81.79,7.52]]]]}},{"type":"Feature","properties":{"name":"China","iso":"CN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[109.48,18.2],[108.66,18.51],[108.63,19.37],[109.12,19.82],[110.21,20.1],[110.79,20.08],[111.01,19.7],[110.57,19.26],[110.34,18.68],[109.48,18.2]]],[[[80.26,42.35],[80.18,42.92],[80.87,43.18],[79.97,44.92],[81.95,45.32],[82.46,45.54],[83.18,47.33],[85.16,47.0],[85.72,47.45],[85.77,48.46],[86.6,48.55],[87.36,49.21],[87.75,49.3],[88.01,48.6],[88.85,48.07],[90.28,47.69],[90.97,46.89],[90.59,45.72],[90.95,45.29],[92.13,45.12],[93.48,44.98],[94.69,44.35],[95.31,44.24],[95.76,43.32],[96.35,42.73],[97.45,42.75],[99.52,42.52],[100.85,42.66],[101.83,42.51],[103.31,41.91],[104.52,41.91],[104.96,41.6],[106.13,42.13],[107.74,42.48],[109.24,42.52],[110.41,42.87],[111.13,43.41],[111.83,43.74],[111.67,44.07],[111.35,44.46],[111.87,45.1],[112.44,45.01],[113.46,44.81],[114.46,45.34],[115.99,45.73],[116.72,46.39],[117.42,46.67],[118.87,46.81],[119.66,46.69],[119.77,47.05],[118.87,47.75],[118.06,48.07],[117.3,47.7],[116.31,47.85],[115.74,47.73],[115.49,48.14],[116.19,49.13],[116.68,49.89],[117.88,49.51],[119.29,50.14],[119.28,50.58],[120.18,51.64],[120.74,51.96],[120.73,52.52],[120.18,52.75],[121.0,53.25],[122.25,53.43],[123.57,53.46],[125.07,53.16],[125.95,52.79],[126.56,51.78],[126.94,51.35],[127.29,50.74],[127.66,49.76],[129.4,49.44],[130.58,48.73],[130.99,47.79],[132.51,47.79],[133.37,48.18],[135.03,48.48],[134.5,47.58],[134.11,47.21],[133.77,46.12],[133.1,45.14],[131.88,45.32],[131.03,44.97],[131.29,44.11],[131.14,42.93],[130.63,42.9],[130.64,42.4],[129.99,42.99],[129.6,42.42],[128.05,41.99],[128.21,41.47],[127.34,41.5],[126.87,41.82],[126.18,41.11],[125.08,40.57],[124.27,39.93],[122.87,39.64],[122.13,39.17],[121.05,38.9],[121.59,39.36],[121.38,39.75],[122.17,40.42],[121.64,40.95],[120.77,40.59],[119.64,39.9],[119.02,39.25],[118.04,39.2],[117.53,38.74],[118.06,38.06],[118.88,37.9],[118.91,37.45],[119.7,37.16],[120.82,37.87],[121.71,37.48],[122.36,37.45],[122.52,36.93],[121.1,36.65],[120.64,36.11],[119.66,35.61],[119.15,34.91],[120.23,34.36],[120.62,33.38],[121.23,32.46],[121.91,31.69],[121.89,30.95],[121.26,30.68],[121.5,30.14],[122.09,29.83],[121.94,29.02],[121.68,28.23],[121.13,28.14],[120.4,27.05],[119.59,25.74],[118.66,24.55],[117.28,23.62],[115.89,22.78],[114.76,22.67],[114.15,22.22],[113.81,22.55],[113.24,22.05],[111.84,21.55],[110.79,21.4],[110.44,20.34],[109.89,20.28],[109.63,21.01],[109.86,21.4],[108.52,21.72],[108.05,21.55],[107.04,21.81],[106.57,22.22],[106.73,22.79],[105.81,22.98],[105.33,23.35],[104.48,22.82],[103.5,22.7],[102.71,22.71],[102.17,22.46],[101.65,22.32],[101.8,21.17],[101.27,21.2],[101.18,21.44],[101.15,21.85],[100.42,21.56],[99.98,21.74],[99.24,22.12],[99.53,22.95],[98.9,23.14],[98.66,24.06],[97.6,23.9],[97.72,25.08],[98.67,25.92],[98.71,26.74],[98.68,27.51],[98.25,27.75],[97.91,28.34],[97.33,28.26],[96.25,28.41],[96.59,28.83],[96.12,29.45],[95.4,29.03],[94.57,29.28],[93.41,28.64],[92.5,27.9],[91.7,27.77],[91.26,28.04],[90.73,28.06],[90.02,28.3],[89.48,28.04],[88.81,27.3],[88.73,28.09],[88.12,27.88],[86.95,27.97],[85.82,28.2],[85.01,28.64],[84.23,28.84],[83.9,29.32],[83.34,29.46],[82.33,30.12],[81.53,30.42],[81.11,30.18],[79.72,30.88],[78.74,31.52],[78.46,32.62],[79.18,32.48],[79.21,32.99],[78.81,33.51],[78.91,34.32],[77.84,35.49],[76.19,35.9],[75.9,36.67],[75.16,37.13],[74.98,37.42],[74.83,37.99],[74.86,38.38],[74.26,38.61],[73.93,38.51],[73.68,39.43],[73.96,39.66],[73.82,39.89],[74.78,40.37],[75.47,40.56],[76.53,40.43],[76.9,41.07],[78.19,41.19],[78.54,41.58],[80.12,42.12],[80.26,42.35]]]]}},{"type":"Feature","properties":{"name":"Taiwan","iso":"TW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[121.78,24.39],[121.18,22.79],[120.75,21.97],[120.22,22.81],[120.11,23.56],[120.69,24.54],[121.5,25.3],[121.95,25.0],[121.78,24.39]]]]}},{"type":"Feature","properties":{"name":"Italy","iso":"IT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[10.44,46.89],[11.05,46.75],[11.16,46.94],[12.15,47.12],[12.38,46.77],[13.81,46.51],[13.7,46.02],[13.94,45.59],[13.14,45.74],[12.33,45.38],[12.38,44.89],[12.26,44.6],[12.59,44.09],[13.53,43.59],[14.03,42.76],[15.14,41.96],[15.93,41.96],[16.17,41.74],[15.89,41.54],[16.79,41.18],[17.52,40.88],[18.38,40.36],[18.48,40.17],[18.29,39.81],[17.74,40.28],[16.87,40.44],[16.45,39.8],[17.17,39.42],[17.05,38.9],[16.64,38.84],[16.1,37.99],[15.68,37.91],[15.69,38.21],[15.89,38.75],[16.11,38.96],[15.72,39.54],[15.41,40.05],[15.0,40.17],[14.7,40.6],[14.06,40.79],[13.63,41.19],[12.89,41.25],[12.11,41.7],[11.19,42.36],[10.51,42.93],[10.2,43.92],[9.7,44.04],[8.89,44.37],[8.43,44.23],[7.85,43.77],[7.44,43.69],[7.55,44.13],[7.01,44.25],[6.75,45.03],[7.1,45.33],[6.8,45.71],[6.84,45.99],[7.27,45.78],[7.76,45.82],[8.32,46.16],[8.49,46.01],[8.97,46.04],[9.18,46.44],[9.92,46.31],[10.36,46.48],[10.44,46.89]]],[[[14.76,38.14],[15.52,38.23],[15.16,37.44],[15.31,37.13],[15.1,36.62],[14.34,37.0],[13.83,37.1],[12.43,37.61],[12.57,38.13],[13.74,38.03],[14.76,38.14]]],[[[8.71,40.9],[9.21,41.21],[9.81,40.5],[9.67,39.18],[9.21,39.24],[8.81,38.91],[8.43,39.17],[8.39,40.38],[8.16,40.95],[8.71,40.9]]]]}},{"type":"Feature","properties":{"name":"Denmark","iso":"DK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.92,54.98],[9.28,54.83],[8.53,54.96],[8.12,55.52],[8.09,56.54],[8.26,56.81],[8.54,57.11],[9.42,57.17],[9.78,57.45],[10.58,57.73],[10.55,57.22],[10.25,56.89],[10.37,56.61],[10.91,56.46],[10.67,56.08],[10.37,56.19],[9.65,55.47],[9.92,54.98]]],[[[12.37,56.11],[12.69,55.61],[12.09,54.8],[11.04,55.36],[10.9,55.78],[12.37,56.11]]]]}},{"type":"Feature","properties":{"name":"United Kingdom","iso":"GB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-6.2,53.87],[-6.95,54.07],[-7.57,54.06],[-7.37,54.6],[-7.57,55.13],[-6.73,55.17],[-5.66,54.55],[-6.2,53.87]]],[[[-3.09,53.4],[-2.95,53.98],[-3.61,54.6],[-3.63,54.62],[-4.84,54.79],[-5.08,55.06],[-4.72,55.51],[-5.05,55.78],[-5.59,55.31],[-5.64,56.28],[-6.15,56.79],[-5.79,57.82],[-5.01,58.63],[-4.21,58.55],[-3.01,58.63],[-4.07,57.55],[-3.06,57.69],[-1.96,57.68],[-2.22,56.87],[-3.12,55.97],[-2.09,55.91],[-2.01,55.8],[-1.11,54.62],[-0.43,54.46],[0.18,53.33],[0.47,52.93],[1.68,52.74],[1.56,52.1],[1.05,51.81],[1.45,51.29],[0.55,50.77],[-0.79,50.77],[-2.49,50.5],[-2.96,50.7],[-3.62,50.23],[-4.54,50.34],[-5.25,49.96],[-5.78,50.16],[-4.31,51.21],[-3.41,51.43],[-3.42,51.43],[-4.98,51.59],[-5.27,51.99],[-4.22,52.3],[-4.77,52.84],[-4.58,53.5],[-3.09,53.4]]]]}},{"type":"Feature","properties":{"name":"Iceland","iso":"IS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-14.51,66.46],[-14.74,65.81],[-13.61,65.13],[-14.91,64.36],[-17.79,63.68],[-18.66,63.5],[-19.97,63.64],[-22.76,63.96],[-21.78,64.4],[-23.96,64.89],[-22.18,65.08],[-22.23,65.38],[-24.33,65.61],[-23.65,66.26],[-22.13,66.41],[-20.58,65.73],[-19.06,66.28],[-17.8,65.99],[-16.17,66.53],[-14.51,66.46]]]]}},{"type":"Feature","properties":{"name":"Azerbaijan","iso":"AZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[46.4,41.86],[46.69,41.83],[47.37,41.22],[47.82,41.15],[47.99,41.41],[48.58,41.81],[49.11,41.28],[49.62,40.57],[50.08,40.53],[50.39,40.26],[49.57,40.18],[49.4,39.4],[49.22,39.05],[48.86,38.82],[48.88,38.32],[48.63,38.27],[48.01,38.79],[48.36,39.29],[48.06,39.58],[47.69,39.51],[46.51,38.77],[46.48,39.46],[46.03,39.63],[45.61,39.9],[45.89,40.22],[45.36,40.56],[45.56,40.81],[45.18,40.99],[44.97,41.25],[45.22,41.41],[45.96,41.12],[46.5,41.06],[46.64,41.18],[46.15,41.72],[46.4,41.86]]],[[[46.14,38.74],[45.46,38.87],[44.95,39.34],[44.79,39.71],[45.0,39.74],[45.3,39.47],[45.74,39.47],[45.74,39.32],[46.14,38.74]]]]}},{"type":"Feature","properties":{"name":"Georgia","iso":"GE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[39.96,43.43],[40.08,43.55],[40.92,43.38],[42.39,43.22],[43.76,42.74],[43.93,42.55],[44.54,42.71],[45.47,42.5],[45.78,42.09],[46.4,41.86],[46.15,41.72],[46.64,41.18],[46.5,41.06],[45.96,41.12],[45.22,41.41],[44.97,41.25],[43.58,41.09],[42.62,41.58],[41.55,41.54],[41.7,41.96],[41.45,42.65],[40.88,43.01],[40.32,43.13],[39.96,43.43]]]]}},{"type":"Feature","properties":{"name":"Philippines","iso":"PH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[120.83,12.7],[120.32,13.47],[121.18,13.43],[121.53,13.07],[121.26,12.21],[120.83,12.7]]],[[[122.59,9.98],[122.84,10.26],[122.95,10.88],[123.5,10.94],[123.34,10.27],[124.08,11.23],[123.98,10.28],[123.62,9.95],[123.31,9.32],[123.0,9.02],[122.38,9.71],[122.59,9.98]]],[[[126.38,8.41],[126.48,7.75],[126.54,7.19],[126.2,6.27],[125.83,7.29],[125.36,6.79],[125.68,6.05],[125.4,5.58],[124.22,6.16],[123.94,6.89],[124.24,7.36],[123.61,7.83],[123.3,7.42],[122.83,7.46],[122.09,6.9],[121.92,7.19],[122.31,8.03],[122.94,8.32],[123.49,8.69],[123.84,8.24],[124.6,8.51],[124.76,8.96],[125.47,8.99],[125.41,9.76],[126.22,9.29],[126.31,8.78],[126.38,8.41]]],[[[118.5,9.32],[117.17,8.37],[117.66,9.07],[118.39,9.68],[118.99,10.38],[119.51,11.37],[119.69,10.55],[119.03,10.0],[118.5,9.32]]],[[[122.34,18.22],[122.17,17.81],[122.52,17.09],[122.25,16.26],[121.66,15.93],[121.51,15.12],[121.73,14.33],[122.26,14.22],[122.7,14.34],[123.95,13.78],[123.86,13.24],[124.18,13.0],[124.08,12.54],[123.3,13.03],[122.93,13.55],[122.67,13.19],[122.03,13.78],[121.13,13.64],[120.63,13.86],[120.68,14.27],[120.99,14.53],[120.69,14.76],[120.56,14.4],[120.07,14.97],[119.92,15.41],[119.88,16.36],[120.29,16.03],[120.39,17.6],[120.72,18.51],[121.32,18.5],[121.94,18.22],[122.25,18.48],[122.34,18.22]]],[[[122.04,11.42],[121.88,11.89],[122.48,11.58],[123.12,11.58],[123.1,11.17],[122.64,10.74],[122.0,10.44],[121.97,10.91],[122.04,11.42]]],[[[125.5,12.16],[125.78,11.05],[125.01,11.31],[125.03,10.98],[125.28,10.36],[124.8,10.13],[124.76,10.84],[124.46,10.89],[124.3,11.5],[124.89,11.42],[124.88,11.79],[124.27,12.56],[125.23,12.54],[125.5,12.16]]]]}},{"type":"Feature","properties":{"name":"Malaysia","iso":"MY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[100.09,6.46],[100.26,6.64],[101.08,6.2],[101.15,5.69],[101.81,5.81],[102.14,6.22],[102.37,6.13],[102.96,5.52],[103.38,4.86],[103.44,4.18],[103.33,3.73],[103.43,3.38],[103.5,2.79],[103.85,2.52],[104.25,1.63],[104.23,1.29],[103.52,1.23],[102.57,1.97],[101.39,2.76],[101.27,3.27],[100.7,3.94],[100.56,4.77],[100.2,5.31],[100.31,6.04],[100.09,6.46]]],[[[117.88,4.14],[117.02,4.31],[115.87,4.31],[115.52,3.17],[115.13,2.82],[114.62,1.43],[113.81,1.22],[112.86,1.5],[112.38,1.41],[111.8,0.9],[111.16,0.98],[110.51,0.77],[109.83,1.34],[109.66,2.01],[110.4,1.66],[111.17,1.85],[111.37,2.7],[111.8,2.89],[113.0,3.1],[113.71,3.89],[114.2,4.53],[114.66,4.01],[114.87,4.35],[115.35,4.32],[115.41,4.96],[115.45,5.45],[116.22,6.14],[116.73,6.92],[117.13,6.93],[117.64,6.42],[117.69,5.99],[118.35,5.71],[119.18,5.41],[119.11,5.02],[118.44,4.97],[118.62,4.48],[117.88,4.14]]]]}},{"type":"Feature","properties":{"name":"Brunei","iso":"BN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[115.45,5.45],[115.41,4.96],[115.35,4.32],[114.87,4.35],[114.66,4.01],[114.2,4.53],[114.6,4.9],[115.45,5.45]]]]}},{"type":"Feature","properties":{"name":"Slovenia","iso":"SI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[13.81,46.51],[14.63,46.43],[15.14,46.66],[16.01,46.68],[16.2,46.85],[16.37,46.84],[16.56,46.5],[15.77,46.24],[15.67,45.83],[15.32,45.73],[15.33,45.45],[14.94,45.47],[14.6,45.63],[14.41,45.47],[13.72,45.5],[13.94,45.59],[13.7,46.02],[13.81,46.51]]]]}},{"type":"Feature","properties":{"name":"Finland","iso":"FI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[28.59,69.06],[28.45,68.36],[29.98,67.7],[29.05,66.94],[30.22,65.81],[29.54,64.95],[30.44,64.2],[30.04,63.55],[31.52,62.87],[31.14,62.36],[30.21,61.78],[28.07,60.5],[26.26,60.42],[24.5,60.06],[22.87,59.85],[22.29,60.39],[21.32,60.72],[21.54,61.71],[21.06,62.61],[21.54,63.19],[22.44,63.82],[24.73,64.9],[25.4,65.11],[25.29,65.53],[23.9,66.01],[23.57,66.4],[23.54,67.94],[21.98,68.62],[20.65,69.11],[21.24,69.37],[22.36,68.84],[23.66,68.89],[24.74,68.65],[25.69,69.09],[26.18,69.83],[27.73,70.16],[29.02,69.77],[28.59,69.06]]]]}},{"type":"Feature","properties":{"name":"Slovakia","iso":"SK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[22.56,49.09],[22.28,48.83],[22.09,48.42],[21.87,48.32],[20.8,48.62],[20.47,48.56],[20.24,48.33],[19.77,48.2],[19.66,48.27],[19.17,48.11],[18.78,48.08],[18.7,47.88],[17.86,47.76],[17.49,47.87],[16.98,48.12],[16.88,48.47],[16.96,48.6],[17.1,48.82],[17.55,48.8],[17.89,48.9],[17.91,49.0],[18.1,49.04],[18.17,49.27],[18.4,49.32],[18.55,49.5],[18.85,49.5],[18.91,49.44],[19.32,49.57],[19.83,49.22],[20.42,49.43],[20.89,49.33],[21.61,49.47],[22.56,49.09]]]]}},{"type":"Feature","properties":{"name":"Czechia","iso":"CZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[15.02,51.11],[15.49,50.78],[16.24,50.7],[16.18,50.42],[16.72,50.22],[16.87,50.47],[17.55,50.36],[17.65,50.05],[18.39,49.99],[18.85,49.5],[18.55,49.5],[18.4,49.32],[18.17,49.27],[18.1,49.04],[17.91,49.0],[17.89,48.9],[17.55,48.8],[17.1,48.82],[16.96,48.6],[16.5,48.79],[16.03,48.73],[15.25,49.04],[14.9,48.96],[14.34,48.56],[13.6,48.88],[13.03,49.31],[12.52,49.55],[12.42,49.97],[12.24,50.27],[12.97,50.48],[13.34,50.73],[14.06,50.93],[14.31,51.12],[14.57,51.0],[15.02,51.11]]]]}},{"type":"Feature","properties":{"name":"Eritrea","iso":"ER"},"geometry":{"type":"MultiPolygon","coordinates":[[[[36.43,14.42],[36.32,14.82],[36.75,16.29],[36.85,16.96],[37.17,17.26],[37.9,17.43],[38.41,18.0],[38.99,16.84],[39.27,15.92],[39.81,15.44],[41.18,14.49],[41.73,13.92],[42.28,13.34],[42.59,13.0],[43.08,12.7],[42.78,12.46],[42.35,12.54],[42.01,12.87],[41.6,13.45],[41.16,13.77],[40.9,14.12],[40.03,14.52],[39.34,14.53],[39.1,14.74],[38.51,14.51],[37.91,14.96],[37.59,14.21],[36.43,14.42]]]]}},{"type":"Feature","properties":{"name":"Japan","iso":"JP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[141.88,39.18],[140.96,38.17],[140.98,37.14],[140.6,36.34],[140.77,35.84],[140.25,35.14],[138.98,34.67],[137.22,34.61],[135.79,33.46],[135.12,33.85],[135.08,34.6],[133.34,34.38],[132.16,33.9],[130.99,33.89],[132.0,33.15],[131.33,31.45],[130.69,31.03],[130.2,31.42],[130.45,32.32],[129.81,32.61],[129.41,33.3],[130.35,33.6],[130.88,34.23],[131.88,34.75],[132.62,35.43],[134.61,35.73],[135.68,35.53],[136.72,37.3],[137.39,36.83],[138.86,37.83],[139.43,38.22],[140.05,39.44],[139.88,40.56],[140.31,41.2],[141.37,41.38],[141.91,39.99],[141.88,39.18]]],[[[144.61,43.96],[145.32,44.38],[145.54,43.26],[144.06,42.99],[143.18,42.0],[141.61,42.68],[141.07,41.58],[139.96,41.57],[139.82,42.56],[140.31,43.33],[141.38,43.39],[141.67,44.77],[141.97,45.55],[143.14,44.51],[143.91,44.17],[144.61,43.96]]],[[[132.37,33.46],[132.92,34.06],[133.49,33.94],[133.9,34.36],[134.64,34.15],[134.77,33.81],[134.2,33.2],[133.79,33.52],[133.28,33.29],[133.01,32.7],[132.36,32.99],[132.37,33.46]]]]}},{"type":"Feature","properties":{"name":"Paraguay","iso":"PY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-58.17,-20.18],[-57.87,-20.73],[-57.94,-22.09],[-56.88,-22.28],[-56.47,-22.09],[-55.8,-22.36],[-55.61,-22.66],[-55.52,-23.57],[-55.4,-23.96],[-55.03,-24.0],[-54.65,-23.84],[-54.29,-24.02],[-54.29,-24.57],[-54.43,-25.16],[-54.63,-25.74],[-54.79,-26.62],[-55.7,-27.39],[-56.49,-27.55],[-57.61,-27.4],[-58.62,-27.12],[-57.63,-25.6],[-57.78,-25.16],[-58.81,-24.77],[-60.03,-24.03],[-60.85,-23.88],[-62.69,-22.25],[-62.29,-21.05],[-62.27,-20.51],[-61.79,-19.63],[-60.04,-19.34],[-59.12,-19.36],[-58.18,-19.87],[-58.17,-20.18]]]]}},{"type":"Feature","properties":{"name":"Yemen","iso":"YE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[52.0,19.0],[52.78,17.35],[53.11,16.65],[52.39,16.38],[52.19,15.94],[52.17,15.6],[51.17,15.18],[49.57,14.71],[48.68,14.0],[48.24,13.95],[47.94,14.01],[47.35,13.59],[46.72,13.4],[45.88,13.35],[45.63,13.29],[45.41,13.03],[45.14,12.95],[44.99,12.7],[44.49,12.72],[44.18,12.59],[43.48,12.64],[43.22,13.22],[43.25,13.77],[43.09,14.06],[42.89,14.8],[42.6,15.21],[42.81,15.26],[42.7,15.72],[42.82,15.91],[42.78,16.35],[43.22,16.67],[43.12,17.09],[43.38,17.58],[43.79,17.32],[44.06,17.41],[45.22,17.43],[45.4,17.33],[46.37,17.23],[46.75,17.28],[47.0,16.95],[47.47,17.12],[48.18,18.17],[49.12,18.62],[52.0,19.0]]]]}},{"type":"Feature","properties":{"name":"Saudi Arabia","iso":"SA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.96,29.36],[36.07,29.2],[36.5,29.51],[36.74,29.87],[37.5,30.0],[37.67,30.34],[38.0,30.51],[37.0,31.51],[39.0,32.01],[39.2,32.16],[40.4,31.89],[41.89,31.19],[44.71,29.18],[46.57,29.1],[47.46,29.0],[47.71,28.53],[48.42,28.55],[48.81,27.69],[49.3,27.46],[49.47,27.11],[50.15,26.69],[50.21,26.28],[50.11,25.94],[50.24,25.61],[50.53,25.33],[50.66,25.0],[50.81,24.75],[51.11,24.56],[51.39,24.63],[51.58,24.25],[51.62,24.01],[52.0,23.0],[55.01,22.5],[55.21,22.71],[55.67,22.0],[55.0,20.0],[52.0,19.0],[49.12,18.62],[48.18,18.17],[47.47,17.12],[47.0,16.95],[46.75,17.28],[46.37,17.23],[45.4,17.33],[45.22,17.43],[44.06,17.41],[43.79,17.32],[43.38,17.58],[43.12,17.09],[43.22,16.67],[42.78,16.35],[42.65,16.77],[42.35,17.08],[42.27,17.47],[41.75,17.83],[41.22,18.67],[40.94,19.49],[40.25,20.17],[39.8,20.34],[39.14,21.29],[39.02,21.99],[39.07,22.58],[38.49,23.69],[38.02,24.08],[37.48,24.29],[37.15,24.86],[37.21,25.08],[36.93,25.6],[36.64,25.83],[36.25,26.57],[35.64,27.38],[35.13,28.06],[34.63,28.06],[34.79,28.61],[34.83,28.96],[34.96,29.36]]]]}},{"type":"Feature","properties":{"name":"Antarctica","iso":"AQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-48.66,-78.05],[-48.15,-78.05],[-46.66,-77.83],[-45.15,-78.05],[-43.92,-78.48],[-43.49,-79.09],[-43.37,-79.52],[-43.33,-80.03],[-44.88,-80.34],[-46.51,-80.59],[-48.39,-80.83],[-50.48,-81.03],[-52.85,-80.97],[-54.16,-80.63],[-53.99,-80.22],[-51.85,-79.95],[-50.99,-79.61],[-50.36,-79.18],[-49.91,-78.81],[-49.31,-78.46],[-48.66,-78.05]]],[[[-66.29,-80.26],[-64.04,-80.29],[-61.88,-80.39],[-61.14,-79.98],[-60.61,-79.63],[-59.57,-80.04],[-59.87,-80.55],[-60.16,-81.0],[-62.26,-80.86],[-64.49,-80.92],[-65.74,-80.59],[-65.74,-80.55],[-66.29,-80.26]]],[[[-73.92,-71.27],[-73.23,-71.15],[-72.07,-71.19],[-71.78,-70.68],[-71.72,-70.31],[-71.74,-69.51],[-71.17,-69.04],[-70.25,-68.88],[-69.72,-69.25],[-69.49,-69.62],[-69.06,-70.07],[-68.73,-70.51],[-68.45,-70.96],[-68.33,-71.41],[-68.51,-71.8],[-68.78,-72.17],[-69.96,-72.31],[-71.08,-72.5],[-72.39,-72.48],[-71.9,-72.09],[-73.07,-72.23],[-74.19,-72.37],[-74.95,-72.07],[-75.01,-71.66],[-73.92,-71.27]]],[[[-102.33,-71.89],[-101.7,-71.72],[-100.43,-71.85],[-98.98,-71.93],[-97.88,-72.07],[-96.79,-71.95],[-96.2,-72.52],[-96.98,-72.44],[-98.2,-72.48],[-99.43,-72.44],[-100.78,-72.5],[-101.8,-72.31],[-102.33,-71.89]]],[[[-122.62,-73.66],[-122.41,-73.32],[-121.21,-73.5],[-119.92,-73.66],[-118.72,-73.48],[-119.29,-73.83],[-120.23,-74.09],[-121.62,-74.01],[-122.62,-73.66]]],[[[-127.28,-73.46],[-126.56,-73.25],[-125.56,-73.48],[-124.03,-73.87],[-124.62,-73.83],[-125.91,-73.74],[-127.28,-73.46]]],[[[-163.71,-78.6],[-163.11,-78.22],[-161.25,-78.38],[-160.25,-78.69],[-159.48,-79.05],[-159.21,-79.5],[-161.13,-79.63],[-162.44,-79.28],[-163.03,-78.93],[-163.07,-78.87],[-163.71,-78.6]]],[[[180,-84.71],[180,-90],[-180,-90],[-180,-84.71],[-179.94,-84.72],[-179.06,-84.14],[-177.26,-84.45],[-177.14,-84.42],[-176.08,-84.1],[-175.95,-84.11],[-175.83,-84.12],[-174.38,-84.53],[-173.12,-84.12],[-172.89,-84.06],[-169.95,-83.88],[-169.0,-84.12],[-168.53,-84.24],[-167.02,-84.57],[-164.18,-84.83],[-161.93,-85.14],[-158.07,-85.37],[-155.19,-85.1],[-150.94,-85.3],[-148.53,-85.61],[-145.89,-85.32],[-143.11,-85.04],[-142.89,-84.57],[-146.83,-84.53],[-150.06,-84.3],[-150.9,-83.9],[-153.59,-83.69],[-153.41,-83.24],[-153.04,-82.83],[-152.67,-82.45],[-152.86,-82.04],[-154.53,-81.77],[-155.29,-81.42],[-156.84,-81.1],[-154.41,-81.16],[-152.1,-81.0],[-150.65,-81.34],[-148.87,-81.04],[-147.22,-80.67],[-146.42,-80.34],[-146.77,-79.93],[-148.06,-79.65],[-149.53,-79.36],[-151.59,-79.3],[-153.39,-79.16],[-155.33,-79.06],[-155.98,-78.69],[-157.27,-78.38],[-158.05,-78.03],[-158.37,-76.89],[-157.88,-76.99],[-156.97,-77.3],[-155.33,-77.2],[-153.74,-77.07],[-152.92,-77.5],[-151.33,-77.4],[-150.0,-77.18],[-148.75,-76.91],[-147.61,-76.58],[-146.1,-76.48],[-146.14,-76.11],[-146.5,-75.73],[-146.2,-75.38],[-144.91,-75.2],[-144.32,-75.54],[-142.79,-75.34],[-141.64,-75.09],[-140.21,-75.07],[-138.86,-74.97],[-137.51,-74.73],[-136.43,-74.52],[-135.21,-74.3],[-134.43,-74.36],[-133.75,-74.44],[-132.26,-74.3],[-130.93,-74.48],[-129.55,-74.46],[-128.24,-74.32],[-126.89,-74.42],[-125.4,-74.52],[-124.01,-74.48],[-122.56,-74.5],[-121.07,-74.52],[-119.7,-74.48],[-118.68,-74.19],[-117.47,-74.03],[-116.22,-74.24],[-115.02,-74.07],[-113.94,-73.71],[-113.3,-74.03],[-112.95,-74.38],[-112.3,-74.71],[-111.26,-74.42],[-110.07,-74.79],[-108.71,-74.91],[-107.56,-75.18],[-106.15,-75.13],[-104.88,-74.95],[-103.37,-74.99],[-102.02,-75.13],[-100.65,-75.3],[-100.12,-74.87],[-100.76,-74.54],[-101.25,-74.19],[-102.55,-74.11],[-103.11,-73.73],[-103.33,-73.36],[-103.68,-72.62],[-102.92,-72.75],[-101.61,-72.81],[-100.31,-72.75],[-99.14,-72.91],[-98.12,-73.21],[-97.69,-73.56],[-96.34,-73.62],[-95.04,-73.48],[-93.67,-73.28],[-92.44,-73.17],[-91.42,-73.4],[-90.09,-73.32],[-89.23,-72.56],[-88.42,-73.01],[-87.27,-73.19],[-86.01,-73.09],[-85.19,-73.48],[-83.88,-73.52],[-82.67,-73.64],[-81.47,-73.85],[-80.69,-73.48],[-80.3,-73.13],[-79.3,-73.52],[-77.93,-73.42],[-76.91,-73.64],[-76.22,-73.97],[-74.89,-73.87],[-73.85,-73.66],[-72.83,-73.4],[-71.62,-73.26],[-70.21,-73.15],[-68.94,-73.01],[-67.96,-72.79],[-67.37,-72.48],[-67.13,-72.05],[-67.25,-71.64],[-67.56,-71.25],[-67.92,-70.85],[-68.23,-70.46],[-68.49,-70.11],[-68.54,-69.72],[-68.45,-69.33],[-67.98,-68.95],[-67.58,-68.54],[-67.43,-68.15],[-67.62,-67.72],[-67.74,-67.33],[-67.25,-66.88],[-66.7,-66.58],[-66.06,-66.21],[-65.37,-65.9],[-64.57,-65.6],[-64.18,-65.17],[-63.63,-64.9],[-63.0,-64.64],[-62.04,-64.58],[-61.41,-64.27],[-60.71,-64.07],[-59.89,-63.96],[-59.16,-63.7],[-58.59,-63.39],[-57.81,-63.27],[-57.22,-63.53],[-57.6,-63.86],[-58.61,-64.15],[-59.05,-64.37],[-59.79,-64.21],[-60.61,-64.31],[-61.3,-64.54],[-62.02,-64.8],[-62.51,-65.09],[-62.65,-65.48],[-62.59,-65.86],[-62.12,-66.19],[-62.81,-66.43],[-63.75,-66.5],[-64.29,-66.84],[-64.88,-67.15],[-65.51,-67.58],[-65.67,-67.95],[-65.31,-68.37],[-64.78,-68.68],[-63.96,-68.91],[-63.2,-69.23],[-62.79,-69.62],[-62.57,-69.99],[-62.28,-70.38],[-61.81,-70.72],[-61.51,-71.09],[-61.38,-72.01],[-61.08,-72.38],[-61.0,-72.77],[-60.69,-73.17],[-60.83,-73.7],[-61.38,-74.11],[-61.96,-74.44],[-63.3,-74.58],[-63.75,-74.93],[-64.35,-75.26],[-65.86,-75.64],[-67.19,-75.79],[-68.45,-76.01],[-69.8,-76.22],[-70.6,-76.63],[-72.21,-76.67],[-73.97,-76.63],[-75.56,-76.71],[-77.24,-76.71],[-76.93,-77.1],[-75.4,-77.28],[-74.28,-77.56],[-73.66,-77.91],[-74.77,-78.22],[-76.5,-78.12],[-77.93,-78.38],[-77.98,-78.79],[-78.02,-79.18],[-76.85,-79.51],[-76.63,-79.89],[-75.36,-80.26],[-73.24,-80.42],[-71.44,-80.69],[-70.01,-81.0],[-68.19,-81.32],[-65.7,-81.47],[-63.26,-81.75],[-61.55,-82.04],[-59.69,-82.38],[-58.71,-82.85],[-58.22,-83.22],[-57.01,-82.87],[-55.36,-82.57],[-53.62,-82.26],[-51.54,-82.0],[-49.76,-81.73],[-47.27,-81.71],[-44.83,-81.85],[-42.81,-82.08],[-42.16,-81.65],[-40.77,-81.36],[-38.24,-81.34],[-36.27,-81.12],[-34.39,-80.91],[-32.31,-80.77],[-30.1,-80.59],[-28.55,-80.34],[-29.25,-79.99],[-29.69,-79.63],[-29.69,-79.26],[-31.62,-79.3],[-33.68,-79.46],[-35.64,-79.46],[-35.91,-79.08],[-35.78,-78.34],[-35.33,-78.12],[-33.9,-77.89],[-32.21,-77.65],[-31.0,-77.36],[-29.78,-77.07],[-28.88,-76.67],[-27.51,-76.5],[-26.16,-76.36],[-25.47,-76.28],[-23.93,-76.24],[-22.46,-76.11],[-21.22,-75.91],[-20.01,-75.67],[-18.91,-75.44],[-17.52,-75.13],[-16.64,-74.79],[-15.7,-74.5],[-15.41,-74.11],[-16.47,-73.87],[-16.11,-73.46],[-15.45,-73.15],[-14.41,-72.95],[-13.31,-72.72],[-12.29,-72.4],[-11.51,-72.01],[-11.02,-71.54],[-10.3,-71.27],[-9.1,-71.32],[-8.61,-71.66],[-7.42,-71.7],[-7.38,-71.32],[-6.87,-70.93],[-5.79,-71.03],[-5.54,-71.4],[-4.34,-71.46],[-3.05,-71.29],[-1.8,-71.17],[-0.66,-71.23],[-0.23,-71.64],[0.87,-71.3],[1.89,-71.13],[3.02,-70.99],[4.14,-70.85],[5.16,-70.62],[6.27,-70.46],[7.14,-70.25],[7.74,-69.89],[8.49,-70.15],[9.53,-70.01],[10.25,-70.48],[10.82,-70.83],[11.95,-70.64],[12.4,-70.25],[13.42,-69.97],[14.73,-70.03],[15.13,-70.4],[15.95,-70.03],[17.03,-69.91],[18.2,-69.87],[19.26,-69.89],[20.38,-70.01],[21.45,-70.07],[21.92,-70.4],[22.57,-70.7],[23.67,-70.52],[24.84,-70.48],[25.98,-70.48],[27.09,-70.46],[28.09,-70.32],[29.15,-70.21],[30.03,-69.93],[30.97,-69.76],[31.99,-69.66],[32.75,-69.38],[33.3,-68.84],[33.87,-68.5],[34.91,-68.66],[35.3,-69.01],[36.16,-69.25],[37.2,-69.17],[37.91,-69.52],[38.65,-69.78],[39.67,-69.54],[40.02,-69.11],[40.92,-68.93],[41.96,-68.6],[42.94,-68.46],[44.11,-68.27],[44.9,-68.05],[45.72,-67.82],[46.5,-67.6],[47.44,-67.72],[48.34,-67.37],[48.99,-67.09],[49.93,-67.11],[50.75,-66.88],[50.95,-66.52],[51.79,-66.25],[52.61,-66.05],[53.61,-65.9],[54.53,-65.82],[55.41,-65.88],[56.36,-65.97],[57.16,-66.25],[57.26,-66.68],[58.14,-67.01],[58.74,-67.29],[59.94,-67.41],[60.61,-67.68],[61.43,-67.95],[62.39,-68.01],[63.19,-67.82],[64.05,-67.41],[64.99,-67.62],[65.97,-67.74],[66.91,-67.86],[67.89,-67.93],[68.89,-67.93],[69.71,-68.97],[69.67,-69.23],[69.56,-69.68],[68.6,-69.93],[67.81,-70.31],[67.95,-70.7],[69.07,-70.68],[68.93,-71.07],[68.42,-71.44],[67.95,-71.85],[68.71,-72.17],[69.87,-72.26],[71.02,-72.09],[71.57,-71.7],[71.91,-71.32],[72.45,-71.01],[73.08,-70.72],[73.34,-70.36],[73.86,-69.87],[74.49,-69.78],[75.63,-69.74],[76.63,-69.62],[77.64,-69.46],[78.13,-69.07],[78.43,-68.7],[79.11,-68.33],[80.09,-68.07],[80.94,-67.88],[81.48,-67.54],[82.05,-67.37],[82.78,-67.21],[83.78,-67.31],[84.68,-67.21],[85.66,-67.09],[86.75,-67.15],[87.48,-66.88],[87.99,-66.21],[88.36,-66.48],[88.83,-66.95],[89.67,-67.15],[90.63,-67.23],[91.59,-67.11],[92.61,-67.19],[93.55,-67.21],[94.18,-67.11],[95.02,-67.17],[95.78,-67.39],[96.68,-67.25],[97.76,-67.25],[98.68,-67.11],[99.72,-67.25],[100.38,-66.92],[100.89,-66.58],[101.58,-66.31],[102.83,-65.56],[103.48,-65.7],[104.24,-65.97],[104.91,-66.33],[106.18,-66.93],[107.16,-66.95],[108.08,-66.95],[109.16,-66.84],[110.24,-66.7],[111.06,-66.43],[111.74,-66.13],[112.86,-66.09],[113.6,-65.88],[114.39,-66.07],[114.9,-66.39],[115.6,-66.7],[116.7,-66.66],[117.38,-66.92],[118.58,-67.17],[119.83,-67.27],[120.87,-67.19],[121.65,-66.88],[122.32,-66.56],[123.22,-66.48],[124.12,-66.62],[125.16,-66.72],[126.1,-66.56],[127.0,-66.56],[127.88,-66.66],[128.8,-66.76],[129.7,-66.58],[130.78,-66.43],[131.8,-66.39],[132.94,-66.39],[133.86,-66.29],[134.76,-66.21],[135.03,-65.72],[135.07,-65.31],[135.7,-65.58],[135.87,-66.03],[136.21,-66.45],[136.62,-66.78],[137.46,-66.95],[138.6,-66.9],[139.91,-66.88],[140.81,-66.82],[142.12,-66.82],[143.06,-66.8],[144.37,-66.84],[145.49,-66.92],[146.2,-67.23],[146.0,-67.6],[146.65,-67.9],[147.72,-68.13],[148.84,-68.39],[150.13,-68.56],[151.48,-68.72],[152.5,-68.87],[153.64,-68.89],[154.28,-68.56],[155.17,-68.84],[155.93,-69.15],[156.81,-69.38],[158.03,-69.48],[159.18,-69.6],[159.67,-69.99],[160.81,-70.23],[161.57,-70.58],[162.69,-70.74],[163.84,-70.72],[164.92,-70.78],[166.11,-70.76],[167.31,-70.83],[168.43,-70.97],[169.46,-71.21],[170.5,-71.4],[171.21,-71.7],[171.09,-72.09],[170.56,-72.44],[170.11,-72.89],[169.76,-73.24],[169.29,-73.66],[167.98,-73.81],[167.39,-74.17],[166.09,-74.38],[165.64,-74.77],[164.96,-75.15],[164.23,-75.46],[163.82,-75.87],[163.57,-76.24],[163.47,-76.69],[163.49,-77.07],[164.06,-77.46],[164.27,-77.83],[164.74,-78.18],[166.6,-78.32],[167.0,-78.75],[165.19,-78.91],[163.67,-79.12],[161.77,-79.16],[160.92,-79.73],[160.75,-80.2],[160.32,-80.57],[159.79,-80.95],[161.12,-81.28],[161.63,-81.69],[162.49,-82.06],[163.71,-82.4],[165.1,-82.71],[166.6,-83.02],[168.9,-83.34],[169.4,-83.83],[172.28,-84.04],[172.48,-84.12],[173.22,-84.41],[175.99,-84.16],[178.28,-84.47],[180,-84.71]]]]}},{"type":"Feature","properties":{"name":"N. Cyprus"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.73,35.14],[32.8,35.15],[32.95,35.39],[33.67,35.37],[34.58,35.67],[33.9,35.25],[33.97,35.06],[33.87,35.09],[33.68,35.02],[33.53,35.04],[33.48,35.0],[33.46,35.1],[33.38,35.16],[33.19,35.17],[32.92,35.09],[32.73,35.14]]]]}},{"type":"Feature","properties":{"name":"Cyprus","iso":"CY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.73,35.14],[32.92,35.09],[33.19,35.17],[33.38,35.16],[33.46,35.1],[33.48,35.0],[33.53,35.04],[33.68,35.02],[33.87,35.09],[33.97,35.06],[34.0,34.98],[32.98,34.57],[32.49,34.7],[32.26,35.1],[32.73,35.14]]]]}},{"type":"Feature","properties":{"name":"Morocco","iso":"MA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-2.17,35.17],[-1.79,34.53],[-1.73,33.92],[-1.39,32.86],[-1.12,32.65],[-1.31,32.26],[-2.62,32.09],[-3.07,31.72],[-3.65,31.64],[-3.69,30.9],[-4.86,30.5],[-5.24,30.0],[-6.06,29.73],[-7.06,29.58],[-8.67,28.84],[-8.67,27.66],[-8.82,27.66],[-8.79,27.12],[-9.41,27.09],[-9.74,26.86],[-10.19,26.86],[-10.55,26.99],[-11.39,26.88],[-11.72,26.1],[-12.03,26.03],[-12.5,24.77],[-13.89,23.69],[-14.22,22.31],[-14.63,21.86],[-14.75,21.5],[-17.0,21.42],[-17.02,21.42],[-16.97,21.89],[-16.59,22.16],[-16.26,22.68],[-16.33,23.02],[-15.98,23.72],[-15.43,24.36],[-15.09,24.52],[-14.82,25.1],[-14.8,25.64],[-14.44,26.25],[-13.77,26.62],[-13.14,27.64],[-13.12,27.65],[-12.62,28.04],[-11.69,28.15],[-10.9,28.83],[-10.4,29.1],[-9.56,29.93],[-9.81,31.18],[-9.43,32.04],[-9.3,32.56],[-8.66,33.24],[-7.65,33.7],[-6.91,34.11],[-6.24,35.15],[-5.93,35.76],[-5.19,35.76],[-4.59,35.33],[-3.64,35.4],[-2.6,35.18],[-2.17,35.17]]]]}},{"type":"Feature","properties":{"name":"Egypt","iso":"EG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[36.87,22],[32.9,22],[29.02,22],[25,22],[25,25.68],[25,29.24],[24.7,30.04],[24.96,30.66],[24.8,31.09],[25.16,31.57],[26.5,31.59],[27.46,31.32],[28.45,31.03],[28.91,30.87],[29.68,31.19],[30.1,31.47],[30.98,31.56],[31.69,31.43],[31.96,30.93],[32.19,31.26],[32.99,31.02],[33.77,30.97],[34.27,31.22],[34.82,29.76],[34.92,29.5],[34.64,29.1],[34.43,28.34],[34.15,27.82],[33.92,27.65],[33.59,27.97],[33.14,28.42],[32.42,29.85],[32.32,29.76],[32.73,28.71],[33.35,27.7],[34.1,26.14],[34.47,25.6],[34.8,25.03],[35.69,23.93],[35.49,23.75],[35.53,23.1],[36.69,22.2],[36.87,22]]]]}},{"type":"Feature","properties":{"name":"Libya","iso":"LY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[25,22],[25,20.0],[23.85,20],[23.84,19.58],[19.85,21.5],[15.86,23.41],[14.85,22.86],[14.14,22.49],[13.58,23.04],[12.0,23.47],[11.56,24.1],[10.77,24.56],[10.3,24.38],[9.95,24.94],[9.91,25.37],[9.32,26.09],[9.72,26.51],[9.63,27.14],[9.76,27.69],[9.68,28.14],[9.86,28.96],[9.81,29.42],[9.48,30.31],[9.97,30.54],[10.06,30.96],[9.95,31.38],[10.64,31.76],[10.94,32.08],[11.43,32.37],[11.49,33.14],[12.66,32.79],[13.08,32.88],[13.92,32.71],[15.25,32.27],[15.71,31.38],[16.61,31.18],[18.02,30.76],[19.09,30.27],[19.57,30.53],[20.05,30.99],[19.82,31.75],[20.13,32.24],[20.85,32.71],[21.54,32.84],[22.9,32.64],[23.24,32.19],[23.61,32.19],[23.93,32.02],[24.92,31.9],[25.16,31.57],[24.8,31.09],[24.96,30.66],[24.7,30.04],[25,29.24],[25,25.68],[25,22]]]]}},{"type":"Feature","properties":{"name":"Ethiopia","iso":"ET"},"geometry":{"type":"MultiPolygon","coordinates":[[[[47.79,8.0],[44.96,5.0],[43.66,4.96],[42.77,4.25],[42.13,4.23],[41.86,3.92],[41.17,3.92],[40.77,4.26],[39.85,3.84],[39.56,3.42],[38.89,3.5],[38.67,3.62],[38.44,3.59],[38.12,3.6],[36.86,4.45],[36.16,4.45],[35.82,4.78],[35.82,5.34],[35.3,5.51],[34.71,6.59],[34.25,6.83],[34.08,7.23],[33.57,7.71],[32.95,7.78],[33.29,8.35],[33.83,8.38],[33.97,8.68],[33.96,9.58],[34.26,10.63],[34.73,10.91],[34.83,11.32],[35.26,12.08],[35.86,12.58],[36.27,13.56],[36.43,14.42],[37.59,14.21],[37.91,14.96],[38.51,14.51],[39.1,14.74],[39.34,14.53],[40.03,14.52],[40.9,14.12],[41.16,13.77],[41.6,13.45],[42.01,12.87],[42.35,12.54],[42,12.1],[41.66,11.63],[41.74,11.36],[41.76,11.05],[42.31,11.03],[42.55,11.11],[42.78,10.93],[42.56,10.57],[42.93,10.02],[43.3,9.54],[43.68,9.18],[46.95,8.0],[47.79,8.0]]]]}},{"type":"Feature","properties":{"name":"Djibouti","iso":"DJ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[42.35,12.54],[42.78,12.46],[43.08,12.7],[43.32,12.39],[43.29,11.97],[42.72,11.74],[43.15,11.46],[42.78,10.93],[42.55,11.11],[42.31,11.03],[41.76,11.05],[41.74,11.36],[41.66,11.63],[42,12.1],[42.35,12.54]]]]}},{"type":"Feature","properties":{"name":"Somaliland"},"geometry":{"type":"MultiPolygon","coordinates":[[[[48.95,11.41],[48.94,11.39],[48.94,10.98],[48.94,9.97],[48.94,9.45],[48.49,8.84],[47.79,8.0],[46.95,8.0],[43.68,9.18],[43.3,9.54],[42.93,10.02],[42.56,10.57],[42.78,10.93],[43.15,11.46],[43.47,11.28],[43.67,10.86],[44.12,10.45],[44.61,10.44],[45.56,10.7],[46.65,10.82],[47.53,11.13],[48.02,11.19],[48.38,11.38],[48.95,11.41]]]]}},{"type":"Feature","properties":{"name":"Uganda","iso":"UG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[33.9,-0.95],[31.87,-1.03],[30.77,-1.01],[30.42,-1.13],[29.82,-1.44],[29.58,-1.34],[29.59,-0.59],[29.82,-0.21],[29.88,0.6],[30.09,1.06],[30.47,1.58],[30.85,1.85],[31.17,2.2],[30.77,2.34],[30.83,3.51],[31.25,3.78],[31.88,3.56],[32.69,3.79],[33.39,3.79],[34.01,4.25],[34.48,3.56],[34.6,3.05],[35.04,1.91],[34.67,1.18],[34.18,0.52],[33.89,0.11],[33.9,-0.95]]]]}},{"type":"Feature","properties":{"name":"Rwanda","iso":"RW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[30.42,-1.13],[30.82,-1.7],[30.76,-2.29],[30.47,-2.41],[29.94,-2.35],[29.63,-2.92],[29.02,-2.84],[29.12,-2.29],[29.25,-2.22],[29.29,-1.62],[29.58,-1.34],[29.82,-1.44],[30.42,-1.13]]]]}},{"type":"Feature","properties":{"name":"Bosnia and Herz.","iso":"BA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.56,42.65],[17.67,43.03],[17.3,43.45],[16.92,43.67],[16.46,44.04],[16.24,44.35],[15.75,44.82],[15.96,45.23],[16.32,45.0],[16.53,45.21],[17.0,45.23],[17.86,45.07],[18.55,45.08],[19.01,44.86],[19.37,44.86],[19.12,44.42],[19.6,44.04],[19.45,43.57],[19.22,43.52],[19.03,43.43],[18.71,43.2],[18.56,42.65]]]]}},{"type":"Feature","properties":{"name":"North Macedonia","iso":"MK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[22.38,42.32],[22.88,42.0],[22.95,41.34],[22.76,41.3],[22.6,41.13],[22.06,41.15],[21.67,40.93],[21.02,40.84],[20.61,41.09],[20.46,41.52],[20.59,41.86],[20.72,41.85],[20.76,42.05],[21.35,42.21],[21.58,42.25],[21.92,42.3],[22.38,42.32]]]]}},{"type":"Feature","properties":{"name":"Serbia","iso":"RS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.83,45.91],[19.6,46.17],[20.22,46.13],[20.76,45.73],[20.87,45.42],[21.48,45.18],[21.56,44.77],[22.15,44.48],[22.46,44.7],[22.71,44.58],[22.47,44.41],[22.66,44.23],[22.41,44.01],[22.5,43.64],[22.99,43.21],[22.6,42.9],[22.44,42.58],[22.55,42.46],[22.38,42.32],[21.92,42.3],[21.58,42.25],[21.54,42.32],[21.66,42.44],[21.78,42.68],[21.63,42.68],[21.44,42.86],[21.27,42.91],[21.14,43.07],[20.96,43.13],[20.81,43.27],[20.64,43.22],[20.5,42.88],[20.26,42.81],[20.34,42.9],[19.96,43.11],[19.63,43.21],[19.48,43.35],[19.22,43.52],[19.45,43.57],[19.6,44.04],[19.12,44.42],[19.37,44.86],[19.01,44.86],[19.39,45.24],[19.07,45.52],[18.83,45.91]]]]}},{"type":"Feature","properties":{"name":"Montenegro","iso":"ME"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.07,42.59],[19.8,42.5],[19.74,42.69],[19.3,42.2],[19.37,41.88],[19.16,41.96],[18.88,42.28],[18.45,42.48],[18.56,42.65],[18.71,43.2],[19.03,43.43],[19.22,43.52],[19.48,43.35],[19.63,43.21],[19.96,43.11],[20.34,42.9],[20.26,42.81],[20.07,42.59]]]]}},{"type":"Feature","properties":{"name":"Kosovo","iso":"XK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.59,41.86],[20.52,42.22],[20.28,42.32],[20.07,42.59],[20.26,42.81],[20.5,42.88],[20.64,43.22],[20.81,43.27],[20.96,43.13],[21.14,43.07],[21.27,42.91],[21.44,42.86],[21.63,42.68],[21.78,42.68],[21.66,42.44],[21.54,42.32],[21.58,42.25],[21.35,42.21],[20.76,42.05],[20.72,41.85],[20.59,41.86]]]]}},{"type":"Feature","properties":{"name":"Trinidad and Tobago","iso":"TT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.68,10.76],[-61.1,10.89],[-60.9,10.86],[-60.94,10.11],[-61.77,10],[-61.95,10.09],[-61.66,10.37],[-61.68,10.76]]]]}},{"type":"Feature","properties":{"name":"S. Sudan","iso":"SS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[30.83,3.51],[29.95,4.17],[29.72,4.6],[29.16,4.39],[28.7,4.46],[28.43,4.29],[27.98,4.41],[27.37,5.23],[27.21,5.55],[26.47,5.95],[26.21,6.55],[25.8,6.98],[25.12,7.5],[25.11,7.83],[24.57,8.23],[23.89,8.62],[24.19,8.73],[24.54,8.92],[24.79,9.81],[25.07,10.27],[25.79,10.41],[25.96,10.14],[26.48,9.55],[26.75,9.47],[27.11,9.64],[27.83,9.6],[27.97,9.4],[28.97,9.4],[29.0,9.6],[29.52,9.79],[29.62,10.08],[30.0,10.29],[30.84,9.71],[31.35,9.81],[31.85,10.53],[32.4,11.08],[32.31,11.68],[32.07,11.97],[32.67,12.02],[32.74,12.25],[33.21,12.18],[33.09,11.44],[33.21,10.72],[33.72,10.33],[33.84,9.98],[33.82,9.48],[33.96,9.46],[33.97,8.68],[33.83,8.38],[33.29,8.35],[32.95,7.78],[33.57,7.71],[34.08,7.23],[34.25,6.83],[34.71,6.59],[35.3,5.51],[34.62,4.85],[34.01,4.25],[33.39,3.79],[32.69,3.79],[31.88,3.56],[31.25,3.78],[30.83,3.51]]]]}}]} \ No newline at end of file diff --git a/vendor/ely/src/account/billing.rs b/vendor/ely/src/account/billing.rs new file mode 100644 index 00000000..f08554d5 --- /dev/null +++ b/vendor/ely/src/account/billing.rs @@ -0,0 +1,425 @@ +use std::rc::Rc; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, prelude::*, +}; + +use super::login::Run; +use crate::{ + buttons::{Button, ButtonVariant, ConfirmButton, ConfirmMode, IconButton}, + data_display::{Badge, Meter, Tone}, + layout::Card, + primitives::IconName, + theme::{ActiveTheme, ControlSize, TextSize}, + typography::{ + Ellipsis, + format::{Separators, currency, number}, + tabular, + }, +}; + +type OnKey = Rc; + +/// Where a subscription stands, each with the date that matters, as words. +#[derive(Clone, Debug, PartialEq)] +pub enum Standing { + Active { renews: SharedString }, + Trial { ends: SharedString }, + Canceled { ends: SharedString }, + PastDue, +} + +impl Standing { + fn badge(&self) -> (&'static str, Tone) { + match self { + Standing::Active { .. } => ("Active", Tone::Success), + Standing::Trial { .. } => ("Trial", Tone::Info), + Standing::Canceled { .. } => ("Canceled", Tone::Neutral), + Standing::PastDue => ("Past due", Tone::Danger), + } + } + + fn line(&self) -> String { + match self { + Standing::Active { renews } => format!("Renews on {renews}."), + Standing::Trial { ends } => format!("The trial ends on {ends}."), + Standing::Canceled { ends } => format!("Ends on {ends}. Nothing more will be charged."), + Standing::PastDue => { + "The last payment failed. Update the card to keep the plan.".into() + } + } + } +} + +/// A plan paid for: its name, its price per period in a currency, and where it stands. +#[derive(Clone, Debug, PartialEq)] +pub struct Subscription { + pub plan: SharedString, + pub price: f64, + pub currency: SharedString, + pub yearly: bool, + pub standing: Standing, +} + +/// A plan at a glance: its name and where it stands, its price, what happens next, and a way to change it, cancel it after a second press, or take it back. +#[derive(IntoElement)] +pub struct SubscriptionCard { + id: ElementId, + subscription: Subscription, + on_change: Option, + on_cancel: Option, + on_resume: Option, +} + +impl SubscriptionCard { + pub fn new(id: impl Into, subscription: Subscription) -> Self { + Self { + id: id.into(), + subscription, + on_change: None, + on_cancel: None, + on_resume: None, + } + } + + /// Shows "Change plan". + pub fn on_change(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_change = Some(Rc::new(handler)); + self + } + + /// Shows "Cancel plan" while the plan runs. + pub fn on_cancel(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_cancel = Some(Rc::new(handler)); + self + } + + /// Shows "Keep plan" once canceled. + pub fn on_resume(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_resume = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for SubscriptionCard { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let (id, plan) = (self.id, self.subscription); + let theme = cx.theme(); + let (state, tone) = plan.standing.badge(); + let canceled = matches!(plan.standing, Standing::Canceled { .. }); + let period = if plan.yearly { "per year" } else { "per month" }; + let change = self.on_change.map(|run| { + Button::new((id.clone(), "change"), "Change plan") + .on_click(move |_, window, cx| run(window, cx)) + .into_any_element() + }); + let end = match canceled { + true => self.on_resume.map(|run| { + Button::new((id.clone(), "resume"), "Keep plan") + .variant(ButtonVariant::Primary) + .on_click(move |_, window, cx| run(window, cx)) + .into_any_element() + }), + false => self.on_cancel.map(|run| { + ConfirmButton::new((id.clone(), "cancel"), "Cancel plan", ConfirmMode::Twice) + .on_confirm(move |window, cx| { + log::info!("subscription card: cancel"); + run(window, cx); + }) + .into_any_element() + }), + }; + let actions: Vec = change.into_iter().chain(end).collect(); + Card::new().child( + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .flex_wrap() + .items_center() + .gap_2() + .child( + div() + .text_size(theme.text_size(TextSize::Md)) + .font_weight(FontWeight::SEMIBOLD) + .child(plan.plan), + ) + .child(Badge::new(state).tone(tone)), + ) + .child( + div() + .flex() + .flex_wrap() + .items_baseline() + .gap_1() + .child(tabular( + div() + .text_size(theme.text_size(TextSize::Xl)) + .font_weight(FontWeight::SEMIBOLD) + .child(currency(plan.price, &plan.currency)), + )) + .child(div().text_color(theme.colors.fg_muted).child(period)), + ) + .child( + div().flex().child( + div() + .flex_1() + .min_w_0() + .text_color(theme.colors.fg_muted) + .child(plan.standing.line()), + ), + ) + .children( + (!actions.is_empty()) + .then(|| div().flex().flex_wrap().gap_2().pt_1().children(actions)), + ), + ) + } +} + +/// A limit on a plan: its key and name, how much is used of how much, and the unit. +#[derive(Clone, Debug, PartialEq)] +pub struct Quota { + pub key: SharedString, + pub name: SharedString, + pub used: f64, + pub limit: f64, + pub unit: SharedString, +} + +/// An amount to a tenth, without a trailing zero: 8, 8.5, 1,200. +fn amount(value: f64) -> String { + let text = number(value, 1, Separators::EN); + text.strip_suffix(".0").map_or(text.clone(), str::to_string) +} + +/// The words under a quota's bar: "8.5 of 10 GB", or how far past its limit. +pub fn quota_line(quota: &Quota) -> String { + assert!(quota.limit > 0.0, "quota {}: no limit", quota.key); + match quota.used > quota.limit { + true => format!( + "{} past the {} {} limit", + amount(quota.used - quota.limit), + amount(quota.limit), + quota.unit + ), + false => format!( + "{} of {} {}", + amount(quota.used), + amount(quota.limit), + quota.unit + ), + } +} + +/// How much of each limit is used, a bar for each that turns amber near it and red at it, and when they start over. +#[derive(IntoElement)] +pub struct UsageQuota { + id: ElementId, + quotas: Vec, + resets: Option, +} + +impl UsageQuota { + pub fn new(id: impl Into, quotas: impl IntoIterator) -> Self { + Self { + id: id.into(), + quotas: quotas.into_iter().collect(), + resets: None, + } + } + + /// When the counts start over, as words. + pub fn resets(mut self, when: impl Into) -> Self { + self.resets = Some(when.into()); + self + } +} + +impl RenderOnce for UsageQuota { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let theme = cx.theme(); + div() + .flex() + .flex_col() + .gap_4() + .children(self.quotas.iter().map(|quota| { + let share = (quota.used / quota.limit).clamp(0.0, 1.0) as f32; + Meter::new( + (id.clone(), format!("quota-{}", quota.key)), + quota.name.clone(), + share, + ) + .detail(quota_line(quota)) + })) + .children(self.resets.map(|when| { + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(format!("Resets on {when}.")) + })) + } +} + +/// Where an invoice stands. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum InvoiceState { + Paid, + Due, + Failed, + Refunded, +} + +/// A bill: its key, date and what it was for as words, its amount in a currency, and where it stands. +#[derive(Clone, Debug, PartialEq)] +pub struct Invoice { + pub key: SharedString, + pub date: SharedString, + pub description: SharedString, + pub amount: f64, + pub currency: SharedString, + pub state: InvoiceState, +} + +/// Past bills, newest first as given: what each was for and its amount, its date and state below, and a way to download it. +#[derive(IntoElement)] +pub struct BillingHistory { + id: ElementId, + invoices: Vec, + on_download: Option, +} + +impl BillingHistory { + pub fn new(id: impl Into, invoices: impl IntoIterator) -> Self { + Self { + id: id.into(), + invoices: invoices.into_iter().collect(), + on_download: None, + } + } + + /// Shows a download button on each. + pub fn on_download( + mut self, + handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_download = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for BillingHistory { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let theme = cx.theme(); + let rows = self.invoices.iter().enumerate().map(|(ix, invoice)| { + let (state, tone) = match invoice.state { + InvoiceState::Paid => ("Paid", Tone::Success), + InvoiceState::Due => ("Due", Tone::Warning), + InvoiceState::Failed => ("Failed", Tone::Danger), + InvoiceState::Refunded => ("Refunded", Tone::Neutral), + }; + let download = self.on_download.clone().map(|run| { + let key = invoice.key.clone(); + div().flex_none().child( + IconButton::new( + (id.clone(), format!("download-{}", invoice.key)), + IconName::Download, + ) + .size(ControlSize::Sm) + .tooltip("Download") + .on_click(move |_, window, cx| { + log::info!("billing history: download {key}"); + run(&key, window, cx); + }), + ) + }); + div() + .flex() + .items_center() + .gap_3() + .py_2p5() + .when(ix > 0, |row| { + row.border_t_1().border_color(theme.colors.border) + }) + .child( + div() + .flex_1() + .min_w_0() + .child( + div() + .flex() + .gap_2() + .child( + div() + .flex_1() + .min_w_0() + .child(Ellipsis::new(invoice.description.clone())), + ) + .child(tabular( + div() + .flex_none() + .font_weight(FontWeight::MEDIUM) + .child(currency(invoice.amount, &invoice.currency)), + )), + ) + .child( + div() + .flex() + .items_center() + .gap_2() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child( + div() + .flex_1() + .min_w_0() + .child(Ellipsis::new(invoice.date.clone())), + ) + .child(div().flex_none().child(Badge::new(state).tone(tone))), + ), + ) + .children(download) + }); + let empty = self.invoices.is_empty().then(|| { + div() + .py_2() + .text_color(theme.colors.fg_muted) + .child("No bills yet.") + }); + div() + .flex() + .flex_col() + .text_size(theme.text_size(TextSize::Sm)) + .children(rows) + .children(empty) + } +} + +#[cfg(test)] +mod tests { + use super::{Quota, quota_line}; + + fn quota(used: f64, limit: f64) -> Quota { + Quota { + key: "storage".into(), + name: "Storage".into(), + used, + limit, + unit: "GB".into(), + } + } + + #[test] + fn a_quota_reads_its_use_or_how_far_past_it_went() { + assert_eq!(quota_line("a(8.5, 10.0)), "8.5 of 10 GB"); + assert_eq!(quota_line("a(1_250.0, 2_000.0)), "1,250 of 2,000 GB"); + assert_eq!(quota_line("a(12.4, 10.0)), "2.4 past the 10 GB limit"); + } +} diff --git a/vendor/ely/src/account/factor.rs b/vendor/ely/src/account/factor.rs new file mode 100644 index 00000000..d676c350 --- /dev/null +++ b/vendor/ely/src/account/factor.rs @@ -0,0 +1,116 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, IntoElement, ParentElement, RenderOnce, SharedString, Styled, Window, div, +}; + +use super::login::Run; +use crate::{ + feedback::InlineMessage, + forms::PinInput, + primitives::Severity, + theme::{ActiveTheme, TextSize}, + typography::Link, +}; + +type OnText = Rc; + +/// Digits in a code from an authenticator app. +const DIGITS: usize = 6; + +/// The code from an authenticator app, in six boxes. A full code goes to the owner at once; after one fails the boxes clear for the next, and a recovery code can stand in. +#[derive(IntoElement)] +pub struct TwoFactorInput { + id: ElementId, + failed: usize, + busy: bool, + on_code: OnText, + on_recovery: Option, +} + +impl TwoFactorInput { + pub fn new( + id: impl Into, + on_code: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + failed: 0, + busy: false, + on_code: Rc::new(on_code), + on_recovery: None, + } + } + + /// How many codes have failed; each new failure clears the boxes and says so. + pub fn failed(mut self, failed: usize) -> Self { + self.failed = failed; + self + } + + /// While the owner checks a code. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } + + /// Shows "Use a recovery code". + pub fn on_recovery(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_recovery = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for TwoFactorInput { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_code = self.on_code; + let theme = cx.theme(); + let note = match (self.busy, self.failed) { + (true, _) => Some( + div() + .text_color(theme.colors.fg_muted) + .child("Checking the code…") + .into_any_element(), + ), + (false, 0) => None, + (false, _) => Some( + InlineMessage::new( + Severity::Danger, + "That code did not work. Try the one showing now.", + ) + .into_any_element(), + ), + }; + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div().flex().child( + div() + .flex_1() + .min_w_0() + .text_color(theme.colors.fg_muted) + .child("Enter the six-digit code from your authenticator app."), + ), + ) + .child( + PinInput::new((id.clone(), "code"), DIGITS) + .attempt(self.failed) + .on_complete(move |code, window, cx| { + log::info!("two-factor input: code entered"); + on_code(&SharedString::from(code.to_string()), window, cx); + }), + ) + .children(note) + .children(self.on_recovery.map(|run| { + div().child(Link::new( + (id.clone(), "recovery"), + "Use a recovery code", + move |_, window, cx| run(window, cx), + )) + })) + } +} diff --git a/vendor/ely/src/account/keys.rs b/vendor/ely/src/account/keys.rs new file mode 100644 index 00000000..f64eac50 --- /dev/null +++ b/vendor/ely/src/account/keys.rs @@ -0,0 +1,209 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, FontWeight, InteractiveElement, IntoElement, ParentElement, RenderOnce, + SharedString, Styled, Window, div, prelude::*, +}; + +use super::login::{Run, field}; +use crate::{ + buttons::{Button, ButtonVariant, ConfirmButton, ConfirmMode, CopyButton}, + feedback::Callout, + forms::{Enter, Input}, + primitives::Severity, + theme::{ActiveTheme, ControlSize, TextSize}, + typography::{Ellipsis, literal}, +}; + +type OnKey = Rc; + +/// An API key as a list shows it: its key, its name, its ends only, and when it was made and last used. +#[derive(Clone, Debug, PartialEq)] +pub struct ApiKey { + pub key: SharedString, + pub name: SharedString, + pub hint: SharedString, + pub created: SharedString, + pub used: SharedString, +} + +/// API keys by name, each with its ends, when it was made and last used, and a Revoke that asks twice. A name makes a new key; its secret, handed back by the owner, shows once with a way to copy it. +#[derive(IntoElement)] +pub struct ApiKeyManager { + id: ElementId, + keys: Vec, + secret: Option, + on_create: OnKey, + on_revoke: OnKey, + on_dismiss: Run, +} + +impl ApiKeyManager { + pub fn new( + id: impl Into, + keys: impl IntoIterator, + on_create: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + on_revoke: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + on_dismiss: impl Fn(&mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + keys: keys.into_iter().collect(), + secret: None, + on_create: Rc::new(on_create), + on_revoke: Rc::new(on_revoke), + on_dismiss: Rc::new(on_dismiss), + } + } + + /// A new key's secret, shown until the owner clears it. + pub fn secret(mut self, secret: impl Into) -> Self { + self.secret = Some(secret.into()); + self + } +} + +impl RenderOnce for ApiKeyManager { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_create = self.on_create; + let on_revoke = self.on_revoke; + let name = field(&id, "name", "A name, such as Deploys", false, window, cx); + let named: SharedString = name.read(cx).text().trim().to_string().into(); + let ready = !named.is_empty(); + let clear = name.clone(); + let create: Run = Rc::new(move |window, cx| { + log::info!("api key manager: create {named}"); + on_create(&named, window, cx); + clear.update(cx, |field, cx| field.set_text("", cx)); + }); + let enter = create.clone(); + let theme = cx.theme(); + let mono = theme.mono_family.clone(); + let secret = self.secret.map(|secret| { + let dismiss = self.on_dismiss.clone(); + Callout::new(Severity::Warning) + .title("Copy this key now. It will not show again.") + .child( + div() + .flex() + .flex_col() + .gap_2() + .child( + div().flex().child( + literal(div()) + .flex_1() + .min_w_0() + .font_family(mono.clone()) + .child(secret.clone()), + ), + ) + .child( + div() + .flex() + .flex_wrap() + .gap_2() + .child(CopyButton::new((id.clone(), "copy"), secret)) + .child( + Button::new((id.clone(), "done"), "Done") + .size(ControlSize::Sm) + .on_click(move |_, window, cx| dismiss(window, cx)), + ), + ), + ) + }); + let rows = self.keys.iter().enumerate().map(|(ix, each)| { + let (key, revoke) = (each.key.clone(), on_revoke.clone()); + div() + .flex() + .flex_wrap() + .items_center() + .gap_3() + .py_2p5() + .when(ix > 0, |row| { + row.border_t_1().border_color(theme.colors.border) + }) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .child( + div() + .flex() + .gap_2() + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .child(Ellipsis::new(each.name.clone())), + ) + .child( + literal(div()) + .flex_none() + .font_family(mono.clone()) + .text_color(theme.colors.fg_muted) + .child(each.hint.clone()), + ), + ) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(Ellipsis::new(format!("{} · {}", each.created, each.used))), + ), + ) + .child( + div().flex_none().child( + ConfirmButton::new( + (id.clone(), format!("revoke-{}", each.key)), + "Revoke", + ConfirmMode::Twice, + ) + .size(ControlSize::Sm) + .on_confirm(move |window, cx| { + log::info!("api key manager: revoke {key}"); + revoke(&key, window, cx); + }), + ), + ) + }); + let empty = self.keys.is_empty().then(|| { + div() + .py_2() + .text_color(theme.colors.fg_muted) + .child("No keys yet. Name one to make it.") + }); + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .children(secret) + .child( + div() + .flex() + .flex_wrap() + .gap_2() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .child(Input::new(&name)), + ) + .child( + Button::new((id.clone(), "create"), "Create key") + .variant(ButtonVariant::Primary) + .disabled(!ready) + .on_click(move |_, window, cx| create(window, cx)), + ), + ) + .child(div().flex().flex_col().children(rows).children(empty)) + } +} diff --git a/vendor/ely/src/account/login.rs b/vendor/ely/src/account/login.rs new file mode 100644 index 00000000..6ec6af28 --- /dev/null +++ b/vendor/ely/src/account/login.rs @@ -0,0 +1,193 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, Entity, InteractiveElement, IntoElement, ParentElement, RenderOnce, + SharedString, Styled, Window, div, +}; + +use crate::{ + buttons::{Button, ButtonVariant}, + feedback::InlineMessage, + forms::{Checkbox, EmailInput, Enter, FormField, PasswordInput, TextInput, is_email}, + primitives::Severity, + theme::{ActiveTheme, TextSize}, + typography::Link, +}; + +pub(super) type Run = Rc; + +/// A form's text field, kept under the form's id; `masked` hides what is typed. +pub(super) fn field( + id: &ElementId, + key: &'static str, + hint: &'static str, + masked: bool, + window: &mut Window, + cx: &mut App, +) -> Entity { + window.use_keyed_state((id.clone(), key), cx, move |window, cx| { + let field = TextInput::new(window, cx).placeholder(hint); + if masked { field.masked() } else { field } + }) +} + +/// Muted words and a link on one line, as under a form: "No account? Sign up". +pub(super) fn aside( + id: impl Into, + words: &'static str, + link: &'static str, + run: Run, + cx: &App, +) -> impl IntoElement { + let theme = cx.theme(); + div() + .flex() + .flex_wrap() + .justify_center() + .gap_1() + .text_size(theme.text_size(TextSize::Sm)) + .text_color(theme.colors.fg_muted) + .child(words) + .child(Link::new(id, link, move |_, window, cx| run(window, cx))) +} + +/// What a sign-in hands its owner. +#[derive(Clone, Debug, PartialEq)] +pub struct Login { + pub email: SharedString, + pub password: SharedString, + pub remember: bool, +} + +type OnLogin = Rc; + +/// An email and a password, a box to stay signed in, and ways to a forgotten password or a new account. Sign in rests until the address reads and a password is typed; Enter in a field signs in. +#[derive(IntoElement)] +pub struct LoginForm { + id: ElementId, + error: Option, + busy: bool, + on_submit: OnLogin, + on_forgot: Option, + on_sign_up: Option, +} + +impl LoginForm { + pub fn new( + id: impl Into, + on_submit: impl Fn(&Login, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + error: None, + busy: false, + on_submit: Rc::new(on_submit), + on_forgot: None, + on_sign_up: None, + } + } + + /// Why the last try failed, shown above Sign in. + pub fn error(mut self, error: impl Into) -> Self { + self.error = Some(error.into()); + self + } + + /// While the owner checks: Sign in spins and rests. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } + + /// Shows "Forgot password?". + pub fn on_forgot(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_forgot = Some(Rc::new(handler)); + self + } + + /// Shows "No account? Sign up". + pub fn on_sign_up(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_sign_up = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for LoginForm { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let email = field(&id, "email", "name@example.com", false, window, cx); + let password = field(&id, "password", "Password", true, window, cx); + let remember = window.use_keyed_state((id.clone(), "remember"), cx, |_, _| false); + let login = Login { + email: email.read(cx).text().trim().to_string().into(), + password: password.read(cx).text().to_string().into(), + remember: *remember.read(cx), + }; + let remembered = login.remember; + let ready = is_email(&login.email) && !login.password.is_empty() && !self.busy; + let on_submit = self.on_submit; + let submit: Run = Rc::new(move |window, cx| { + log::info!("login form: sign in"); + on_submit(&login, window, cx); + }); + let enter = submit.clone(); + div() + .flex() + .flex_col() + .gap_4() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child( + FormField::new((id.clone(), "email-field"), "Email").child(EmailInput::new(&email)), + ) + .child( + FormField::new((id.clone(), "password-field"), "Password") + .child(PasswordInput::new(&password)), + ) + .child( + div() + .flex() + .flex_wrap() + .items_center() + .justify_between() + .gap_2() + .child( + Checkbox::new((id.clone(), "remember"), remembered) + .label("Keep me signed in") + .on_change(move |on, _, cx| { + remember.update(cx, |remember, cx| { + *remember = on; + cx.notify(); + }) + }), + ) + .children(self.on_forgot.map(|run| { + Link::new( + (id.clone(), "forgot"), + "Forgot password?", + move |_, window, cx| run(window, cx), + ) + })), + ) + .children( + self.error + .map(|error| InlineMessage::new(Severity::Danger, error)), + ) + .child( + Button::new((id.clone(), "submit"), "Sign in") + .variant(ButtonVariant::Primary) + .full_width() + .loading(self.busy) + .disabled(!ready) + .on_click(move |_, window, cx| submit(window, cx)), + ) + .children( + self.on_sign_up + .map(|run| aside((id.clone(), "sign-up"), "No account?", "Sign up", run, cx)), + ) + } +} diff --git a/vendor/ely/src/account/mail.rs b/vendor/ely/src/account/mail.rs new file mode 100644 index 00000000..0782dd5a --- /dev/null +++ b/vendor/ely/src/account/mail.rs @@ -0,0 +1,277 @@ +use std::rc::Rc; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, InteractiveElement, IntoElement, ParentElement, + RenderOnce, SharedString, Styled, Window, div, +}; + +use super::login::{Run, field}; +use crate::{ + buttons::{Button, ButtonVariant}, + forms::{EmailInput, Enter, FormField, is_email}, + primitives::{Icon, IconName}, + theme::{ActiveTheme, IconSize, TextSize}, + typography::Link, +}; + +type OnText = Rc; + +/// The words that set one email step apart from another. +struct Words { + intro: &'static str, + send: &'static str, + sent: &'static str, + note: fn(&str) -> String, +} + +/// A way out: its label and what it runs. +type Way = Option<(&'static str, Run)>; + +/// One email step: its words, where it stands, and its ways out. `back` shows in both steps, `other` once sent. +struct Step { + id: ElementId, + words: Words, + sent: bool, + busy: bool, + on_send: OnText, + back: Way, + other: Way, +} + +/// An address to send a link to, then where the link went with a way to send it again. +fn email_step(step: Step, window: &mut Window, cx: &mut App) -> AnyElement { + let Step { + id, + words, + sent, + busy, + on_send, + back, + other, + } = step; + let email = field(&id, "email", "name@example.com", false, window, cx); + let address: SharedString = email.read(cx).text().trim().to_string().into(); + let ready = is_email(&address) && !busy; + let send: Run = { + let address = address.clone(); + Rc::new(move |window, cx| { + log::info!("email step: send"); + on_send(&address, window, cx); + }) + }; + let theme = cx.theme(); + let muted = |text: SharedString| { + div().flex().child( + div() + .flex_1() + .min_w_0() + .text_size(theme.text_size(TextSize::Sm)) + .text_color(theme.colors.fg_muted) + .child(text), + ) + }; + let back = back.map(|(label, run)| { + Link::new((id.clone(), "back"), label, move |_, window, cx| { + run(window, cx) + }) + }); + if sent { + let other = other.map(|(label, run)| { + Button::new((id.clone(), "other"), label) + .variant(ButtonVariant::Ghost) + .on_click(move |_, window, cx| run(window, cx)) + }); + return div() + .flex() + .flex_col() + .gap_4() + .child( + div() + .flex() + .items_start() + .gap_3() + .child( + Icon::new(IconName::CircleCheck) + .size(IconSize::Md) + .color(theme.colors.success), + ) + .child( + div() + .flex_1() + .min_w_0() + .child(div().font_weight(FontWeight::MEDIUM).child(words.sent)) + .child(muted((words.note)(&address).into())), + ), + ) + .child( + div() + .flex() + .flex_wrap() + .gap_2() + .child( + Button::new((id.clone(), "resend"), "Send again") + .loading(busy) + .disabled(busy) + .on_click(move |_, window, cx| send(window, cx)), + ) + .children(other), + ) + .children(back) + .into_any_element(); + } + let enter = send.clone(); + div() + .flex() + .flex_col() + .gap_4() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child(muted(words.intro.into())) + .child(FormField::new((id.clone(), "email-field"), "Email").child(EmailInput::new(&email))) + .child( + Button::new((id.clone(), "send"), words.send) + .variant(ButtonVariant::Primary) + .full_width() + .loading(busy) + .disabled(!ready) + .on_click(move |_, window, cx| send(window, cx)), + ) + .children(back) + .into_any_element() +} + +/// Sign in by a link sent to an address: the address, then where the link went, with a way to send it again or to use another address. +#[derive(IntoElement)] +pub struct MagicLinkForm { + id: ElementId, + sent: bool, + busy: bool, + on_send: OnText, + on_other: Option, +} + +impl MagicLinkForm { + pub fn new( + id: impl Into, + on_send: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + sent: false, + busy: false, + on_send: Rc::new(on_send), + on_other: None, + } + } + + /// Once the owner has sent the link. + pub fn sent(mut self, sent: bool) -> Self { + self.sent = sent; + self + } + + /// While the owner sends. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } + + /// Shows "Use another email" once sent; the owner clears `sent`. + pub fn on_other(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_other = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for MagicLinkForm { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let words = Words { + intro: "We will email you a link that signs you in. No password needed.", + send: "Email me a link", + sent: "Check your email", + note: |address| { + format!("A sign-in link is on its way to {address}. Open it on this device.") + }, + }; + let other = self.on_other.map(|run| ("Use another email", run)); + let step = Step { + id: self.id, + words, + sent: self.sent, + busy: self.busy, + on_send: self.on_send, + back: None, + other, + }; + email_step(step, window, cx) + } +} + +/// A forgotten password: the account's address, then word that a reset link is on its way, with a way to send it again and a way back to sign in. +#[derive(IntoElement)] +pub struct ForgotPassword { + id: ElementId, + sent: bool, + busy: bool, + on_send: OnText, + on_back: Option, +} + +impl ForgotPassword { + pub fn new( + id: impl Into, + on_send: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + sent: false, + busy: false, + on_send: Rc::new(on_send), + on_back: None, + } + } + + /// Once the owner has sent the link. + pub fn sent(mut self, sent: bool) -> Self { + self.sent = sent; + self + } + + /// While the owner sends. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } + + /// Shows "Back to sign in". + pub fn on_back(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_back = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for ForgotPassword { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let words = Words { + intro: "Enter the email you signed up with and we will send a link to set a new password.", + send: "Send reset link", + sent: "Check your email", + note: |address| format!("If an account uses {address}, a reset link is on its way."), + }; + let back = self.on_back.map(|run| ("Back to sign in", run)); + let step = Step { + id: self.id, + words, + sent: self.sent, + busy: self.busy, + on_send: self.on_send, + back, + other: None, + }; + email_step(step, window, cx) + } +} diff --git a/vendor/ely/src/account/mod.rs b/vendor/ely/src/account/mod.rs new file mode 100644 index 00000000..058db5a9 --- /dev/null +++ b/vendor/ely/src/account/mod.rs @@ -0,0 +1,33 @@ +mod billing; +mod factor; +mod keys; +mod login; +mod mail; +mod oauth; +mod payment; +mod profile; +mod sessions; +mod signup; +mod switcher; +mod team; +mod upgrade; + +#[cfg(all(test, feature = "test-support"))] +mod tests; + +pub use billing::{ + BillingHistory, Invoice, InvoiceState, Quota, Standing, Subscription, SubscriptionCard, + UsageQuota, quota_line, +}; +pub use factor::TwoFactorInput; +pub use keys::{ApiKey, ApiKeyManager}; +pub use login::{Login, LoginForm}; +pub use mail::{ForgotPassword, MagicLinkForm}; +pub use oauth::OAuthButtons; +pub use payment::{CardBrand, CardDetails, ExpiryError, PaymentMethodForm, expiry, luhn}; +pub use profile::{Profile, ProfileCard, ProfileEditor}; +pub use sessions::{Session, SessionList}; +pub use signup::{Signup, SignupForm, password_rules}; +pub use switcher::{Account, AccountSwitcher, UserMenu, Workspace, WorkspaceSwitcher}; +pub use team::{Invitation, InvitationList, Member, Role, RoleSelector, TeamMemberTable}; +pub use upgrade::UpgradePrompt; diff --git a/vendor/ely/src/account/oauth.rs b/vendor/ely/src/account/oauth.rs new file mode 100644 index 00000000..603a7009 --- /dev/null +++ b/vendor/ely/src/account/oauth.rs @@ -0,0 +1,80 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, IntoElement, ParentElement, RenderOnce, SharedString, Styled, Window, div, +}; + +use crate::buttons::{Button, ButtonVariant}; + +type OnKey = Rc; + +/// A button for each sign-in provider, stacked full width: "Continue with GitHub". While one is on its way it spins and the others rest. +#[derive(IntoElement)] +pub struct OAuthButtons { + id: ElementId, + providers: Vec<(SharedString, SharedString)>, + busy: Option, + on_pick: OnKey, +} + +impl OAuthButtons { + /// `providers` are each a key and the name shown. + pub fn new( + id: impl Into, + providers: impl IntoIterator, impl Into)>, + on_pick: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let id = id.into(); + let providers: Vec<_> = providers + .into_iter() + .map(|(key, name)| (key.into(), name.into())) + .collect(); + assert!(!providers.is_empty(), "oauth buttons {id:?}: no provider"); + Self { + id, + providers, + busy: None, + on_pick: Rc::new(on_pick), + } + } + + /// The provider on its way. + pub fn busy(mut self, key: impl Into) -> Self { + let key = key.into(); + if !self.providers.iter().any(|(each, _)| *each == key) { + log::error!("oauth buttons: no provider {key}; none busy"); + self.busy = None; + return self; + } + self.busy = Some(key); + self + } +} + +impl RenderOnce for OAuthButtons { + fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement { + let id = self.id; + let on_pick = self.on_pick; + let busy = self.busy; + div() + .flex() + .flex_col() + .gap_2() + .children(self.providers.into_iter().map(|(key, name)| { + let mine = busy.as_ref() == Some(&key); + let pick = on_pick.clone(); + Button::new( + (id.clone(), format!("provider-{key}")), + format!("Continue with {name}"), + ) + .variant(ButtonVariant::Outline) + .full_width() + .loading(mine) + .disabled(busy.is_some() && !mine) + .on_click(move |_, window, cx| { + log::info!("oauth buttons: {key}"); + pick(&key, window, cx); + }) + })) + } +} diff --git a/vendor/ely/src/account/payment.rs b/vendor/ely/src/account/payment.rs new file mode 100644 index 00000000..d8d4a53a --- /dev/null +++ b/vendor/ely/src/account/payment.rs @@ -0,0 +1,344 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, +}; +use jiff::Timestamp; + +use super::login::{Run, field}; +use crate::{ + buttons::{Button, ButtonVariant}, + feedback::InlineMessage, + forms::{Enter, FormField, Input, MaskedInput}, + primitives::{Icon, IconName, Severity}, + theme::{ActiveTheme, IconSize}, + typography::format::system_zone, +}; + +/// A card network, told by a number's first digits. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CardBrand { + Visa, + Mastercard, + Amex, + Discover, + Other, +} + +impl CardBrand { + pub fn of(digits: &str) -> Self { + let lead = |n: usize| digits.get(..n).and_then(|lead| lead.parse::().ok()); + if digits.starts_with('4') { + CardBrand::Visa + } else if lead(2).is_some_and(|lead| (51..=55).contains(&lead)) + || lead(4).is_some_and(|lead| (2221..=2720).contains(&lead)) + { + CardBrand::Mastercard + } else if lead(2).is_some_and(|lead| lead == 34 || lead == 37) { + CardBrand::Amex + } else if digits.starts_with("6011") || digits.starts_with("65") { + CardBrand::Discover + } else { + CardBrand::Other + } + } + + pub fn name(self) -> &'static str { + match self { + CardBrand::Visa => "Visa", + CardBrand::Mastercard => "Mastercard", + CardBrand::Amex => "American Express", + CardBrand::Discover => "Discover", + CardBrand::Other => "Card", + } + } + + /// The number's pattern and its digits, and the digits of its security code. + fn shape(self) -> (&'static str, usize, usize) { + match self { + CardBrand::Amex => ("9999 999999 99999", 15, 4), + _ => ("9999 9999 9999 9999", 16, 3), + } + } +} + +/// Whether `digits` pass the Luhn check that card numbers carry. +pub fn luhn(digits: &str) -> bool { + let mut sum = 0; + for (ix, ch) in digits.chars().rev().enumerate() { + let Some(mut digit) = ch.to_digit(10) else { + return false; + }; + if ix % 2 == 1 { + digit *= 2; + if digit > 9 { + digit -= 9; + } + } + sum += digit; + } + !digits.is_empty() && sum % 10 == 0 +} + +/// Why an expiry cannot be used. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ExpiryError { + /// Not written "MM/YY". + Unread, + NoMonth(i8), + Passed, +} + +/// The month and year of an expiry written "MM/YY", when it reads and has not passed `now`, a year and month. +pub fn expiry(text: &str, now: (i32, i8)) -> Result<(i8, i32), ExpiryError> { + let (month, year) = text.split_once('/').ok_or(ExpiryError::Unread)?; + let month = month + .trim() + .parse::() + .map_err(|_| ExpiryError::Unread)?; + let year = year + .trim() + .parse::() + .ok() + .and_then(|year| year.checked_add(2000)) + .ok_or(ExpiryError::Unread)?; + if !(1..=12).contains(&month) { + return Err(ExpiryError::NoMonth(month)); + } + if (year, month) < now { + return Err(ExpiryError::Passed); + } + Ok((month, year)) +} + +/// What Expires says under a whole date it refuses. +fn expiry_fault(text: &str, now: (i32, i8)) -> Option { + if text.len() != "MM/YY".len() { + return None; + } + match expiry(text, now) { + Err(ExpiryError::NoMonth(month)) => Some(format!("There is no month {month:02}.")), + Err(ExpiryError::Passed) => Some("This date has passed.".into()), + Err(ExpiryError::Unread) | Ok(_) => None, + } +} + +/// A card as its form hands it over. +#[derive(Clone, Debug, PartialEq)] +pub struct CardDetails { + pub brand: CardBrand, + pub number: SharedString, + pub month: i8, + pub year: i32, + pub cvc: SharedString, + pub name: SharedString, +} + +type OnCard = Rc; + +fn digits(text: &str) -> String { + text.chars().filter(char::is_ascii_digit).collect() +} + +/// A card to pay with: its number, spaced as its network writes it and named once told, the month and year it runs out, its security code and the name on it. Save waits for a number that checks out, a month ahead, a full code and a name. +#[derive(IntoElement)] +pub struct PaymentMethodForm { + id: ElementId, + error: Option, + busy: bool, + on_submit: OnCard, +} + +impl PaymentMethodForm { + pub fn new( + id: impl Into, + on_submit: impl Fn(&CardDetails, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + error: None, + busy: false, + on_submit: Rc::new(on_submit), + } + } + + /// Why the card was refused, shown above Save. + pub fn error(mut self, error: impl Into) -> Self { + self.error = Some(error.into()); + self + } + + /// While the owner checks the card. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } +} + +impl RenderOnce for PaymentMethodForm { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_submit = self.on_submit; + let number = field(&id, "number", "", false, window, cx); + let until = field(&id, "expiry", "", false, window, cx); + let code = field(&id, "cvc", "", false, window, cx); + let name = field(&id, "name", "As printed on the card", false, window, cx); + let typed = digits(number.read(cx).text()); + let brand = CardBrand::of(&typed); + let (mask, length, code_length) = brand.shape(); + let complete = typed.len() == length; + let checks = complete && luhn(&typed); + let now = Timestamp::now().to_zoned(system_zone("payment method form")); + let today = (now.year() as i32, now.month()); + let expires = expiry(until.read(cx).text(), today); + let cvc = digits(code.read(cx).text()); + let holder: SharedString = name.read(cx).text().trim().to_string().into(); + let card = expires + .ok() + .filter(|_| checks && cvc.len() == code_length && !holder.is_empty()) + .map(|(month, year)| CardDetails { + brand, + number: typed.clone().into(), + month, + year, + cvc: cvc.clone().into(), + name: holder, + }); + let ready = card.is_some() && !self.busy; + let submit: Run = Rc::new(move |window, cx| { + let card = card.as_ref().expect("Save rests until the card reads"); + log::info!("payment method form: save {}", card.brand.name()); + on_submit(card, window, cx); + }); + let enter = submit.clone(); + let theme = cx.theme(); + let mut number_field = FormField::new((id.clone(), "number-field"), "Card number"); + if complete && !checks { + number_field = number_field.error("This number does not check out."); + } else if brand != CardBrand::Other { + number_field = number_field.description(brand.name()); + } + let mut until_field = FormField::new((id.clone(), "expiry-field"), "Expires"); + if let Some(fault) = expiry_fault(until.read(cx).text(), today) { + until_field = until_field.error(fault); + } + div() + .flex() + .flex_col() + .gap_4() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child( + number_field.child( + MaskedInput::new((id.clone(), "number"), &number, mask).prefix( + Icon::new(IconName::CreditCard) + .size(IconSize::Sm) + .color(theme.colors.fg_subtle), + ), + ), + ) + .child( + div() + .flex() + .flex_wrap() + .gap_3() + .child(div().flex_1().min_w(theme.label_width() * 0.6).child( + until_field.child(MaskedInput::new( + (id.clone(), "expiry"), + &until, + "99/99", + )), + )) + .child(div().flex_1().min_w(theme.label_width() * 0.6).child( + FormField::new((id.clone(), "cvc-field"), "Security code").child( + MaskedInput::new( + (id.clone(), "cvc"), + &code, + if code_length == 4 { "9999" } else { "999" }, + ), + ), + )), + ) + .child( + FormField::new((id.clone(), "name-field"), "Name on card").child(Input::new(&name)), + ) + .children( + self.error + .map(|error| InlineMessage::new(Severity::Danger, error)), + ) + .child( + Button::new((id.clone(), "save"), "Save card") + .variant(ButtonVariant::Primary) + .full_width() + .loading(self.busy) + .disabled(!ready) + .on_click(move |_, window, cx| submit(window, cx)), + ) + } +} + +#[cfg(test)] +mod tests { + use super::{CardBrand, ExpiryError, expiry, expiry_fault, luhn}; + + #[test] + fn a_number_tells_its_network_and_checks_out() { + assert_eq!(CardBrand::of("4242"), CardBrand::Visa); + assert_eq!(CardBrand::of("5555"), CardBrand::Mastercard); + assert_eq!(CardBrand::of("2221"), CardBrand::Mastercard); + assert_eq!(CardBrand::of("3782"), CardBrand::Amex); + assert_eq!(CardBrand::of("6011"), CardBrand::Discover); + assert_eq!(CardBrand::of("9"), CardBrand::Other); + assert!(luhn("4242424242424242")); + assert!(luhn("378282246310005")); + assert!(!luhn("4242424242424241")); + assert!(!luhn("")); + } + + #[test] + fn an_expiry_reads_and_has_not_passed() { + let now = (2026, 9); + assert_eq!( + expiry("09/26", now), + Ok((9, 2026)), + "this month still counts" + ); + assert_eq!(expiry("12/31", now), Ok((12, 2031))); + assert_eq!( + expiry("12/2147483647", now), + Err(ExpiryError::Unread), + "a year past any clock" + ); + assert_eq!(expiry("08/26", now), Err(ExpiryError::Passed)); + assert_eq!(expiry("13/30", now), Err(ExpiryError::NoMonth(13))); + assert_eq!(expiry("1230", now), Err(ExpiryError::Unread)); + } + + #[test] + fn a_whole_expiry_says_why_it_is_refused() { + let now = (2026, 9); + assert_eq!( + expiry_fault("13/30", now).as_deref(), + Some("There is no month 13.") + ); + assert_eq!( + expiry_fault("00/30", now).as_deref(), + Some("There is no month 00.") + ); + assert_eq!( + expiry_fault("08/26", now).as_deref(), + Some("This date has passed.") + ); + assert_eq!(expiry_fault("09/26", now), None); + assert_eq!( + expiry_fault("13/3", now), + None, + "a date still being typed says nothing" + ); + } +} diff --git a/vendor/ely/src/account/profile.rs b/vendor/ely/src/account/profile.rs new file mode 100644 index 00000000..8adc6410 --- /dev/null +++ b/vendor/ely/src/account/profile.rs @@ -0,0 +1,357 @@ +use std::{path::PathBuf, rc::Rc}; + +use gpui::{ + AnyElement, App, AppContext as _, ElementId, Entity, FontWeight, ImageSource, IntoElement, + ParentElement, RenderOnce, SharedString, Styled, Window, div, +}; + +use crate::{ + buttons::{Button, ButtonVariant}, + data_display::{Avatar, Presence}, + forms::{AvatarUpload, EmailInput, FormField, Input, TextInput, is_email}, + layout::Card, + primitives::{Icon, IconName}, + theme::{ActiveTheme, AvatarSize, IconSize, TextSize}, + typography::Ellipsis, +}; + +/// Someone at a glance: their picture or initials, name and title, a line about them, details each with an icon, and the owner's actions. +#[derive(IntoElement)] +pub struct ProfileCard { + id: ElementId, + name: SharedString, + title: Option, + image: Option, + presence: Option, + bio: Option, + details: Vec<(IconName, SharedString)>, + actions: Vec, +} + +impl ProfileCard { + pub fn new(id: impl Into, name: impl Into) -> Self { + Self { + id: id.into(), + name: name.into(), + title: None, + image: None, + presence: None, + bio: None, + details: Vec::new(), + actions: Vec::new(), + } + } + + pub fn title(mut self, title: impl Into) -> Self { + self.title = Some(title.into()); + self + } + + pub fn image(mut self, source: impl Into) -> Self { + self.image = Some(source.into()); + self + } + + pub fn presence(mut self, presence: Presence) -> Self { + self.presence = Some(presence); + self + } + + pub fn bio(mut self, bio: impl Into) -> Self { + self.bio = Some(bio.into()); + self + } + + /// A line such as an email or a place, after its icon. + pub fn detail(mut self, icon: IconName, text: impl Into) -> Self { + self.details.push((icon, text.into())); + self + } + + pub fn action(mut self, action: impl IntoElement) -> Self { + self.actions.push(action.into_any_element()); + self + } +} + +impl RenderOnce for ProfileCard { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let mut avatar = + Avatar::new((self.id.clone(), "avatar"), self.name.clone()).size(AvatarSize::Lg); + if let Some(image) = self.image { + avatar = avatar.image(image); + } + if let Some(presence) = self.presence { + avatar = avatar.presence(presence); + } + let muted = theme.colors.fg_muted; + let details = self.details.into_iter().map(|(icon, text)| { + div() + .flex() + .items_center() + .gap_2() + .child(Icon::new(icon).size(IconSize::Sm).color(muted)) + .child(div().flex_1().min_w_0().child(Ellipsis::new(text))) + }); + Card::new().child( + div() + .flex() + .flex_col() + .gap_4() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_center() + .gap_3() + .child(div().flex_none().child(avatar)) + .child( + div() + .flex_1() + .min_w_0() + .child( + div() + .text_size(theme.text_size(TextSize::Md)) + .font_weight(FontWeight::SEMIBOLD) + .child(Ellipsis::new(self.name)), + ) + .children(self.title.map(|title| { + div().text_color(muted).child(Ellipsis::new(title)) + })), + ), + ) + .children( + self.bio + .map(|bio| div().flex().child(div().flex_1().min_w_0().child(bio))), + ) + .child( + div() + .flex() + .flex_col() + .gap_1p5() + .text_color(muted) + .children(details), + ) + .children( + (!self.actions.is_empty()) + .then(|| div().flex().flex_wrap().gap_2().children(self.actions)), + ), + ) + } +} + +/// What a profile holds. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct Profile { + pub name: SharedString, + pub username: SharedString, + pub email: SharedString, + pub bio: SharedString, + pub location: SharedString, + pub picture: Option, +} + +type OnProfile = Rc; + +/// The editor's own fields, filled from the profile they started as. +struct Fields { + seed: Profile, + name: Entity, + username: Entity, + email: Entity, + bio: Entity, + location: Entity, + picture: Option, +} + +impl Fields { + fn filled(profile: &Profile, window: &mut Window, cx: &mut App) -> Self { + let mut field = |text: &SharedString, lines: bool| { + let text = text.to_string(); + cx.new(|cx| { + let input = TextInput::new(window, cx); + let mut input = if lines { input.multi_line(3, 6) } else { input }; + input.set_text(text, cx); + input + }) + }; + Self { + seed: profile.clone(), + name: field(&profile.name, false), + username: field(&profile.username, false), + email: field(&profile.email, false), + bio: field(&profile.bio, true), + location: field(&profile.location, false), + picture: profile.picture.clone(), + } + } + + fn read(&self, cx: &App) -> Profile { + let text = |input: &Entity| { + SharedString::from(input.read(cx).text().trim().to_string()) + }; + Profile { + name: text(&self.name), + username: text(&self.username), + email: text(&self.email), + bio: text(&self.bio), + location: text(&self.location), + picture: self.picture.clone(), + } + } +} + +/// Whether an edited profile may be saved: it changed, it has a name, and its email reads. +fn savable(edited: &Profile, seed: &Profile) -> bool { + edited != seed && !edited.name.is_empty() && is_email(&edited.email) +} + +/// A profile to edit: the picture, name, username, email, a line about oneself and a place. A new profile from the owner refills it. Save hands the owner the changes and rests while nothing changed, a name is missing or the email does not read; Discard puts the owner's profile back. +#[derive(IntoElement)] +pub struct ProfileEditor { + id: ElementId, + profile: Profile, + on_save: OnProfile, +} + +impl ProfileEditor { + pub fn new( + id: impl Into, + profile: Profile, + on_save: impl Fn(&Profile, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + profile, + on_save: Rc::new(on_save), + } + } +} + +impl RenderOnce for ProfileEditor { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let (id, profile) = (self.id, self.profile); + let on_save = self.on_save; + let fields = window.use_keyed_state((id.clone(), "fields"), cx, |window, cx| { + Fields::filled(&profile, window, cx) + }); + if fields.read(cx).seed != profile { + log::info!("profile editor: filled from the owner's profile"); + let fresh = Fields::filled(&profile, window, cx); + fields.update(cx, |fields, _| *fields = fresh); + } + let now = fields.read(cx); + let edited = now.read(cx); + let ready = savable(&edited, &profile); + let changed = edited != profile; + let (name, username, email, bio, location) = ( + now.name.clone(), + now.username.clone(), + now.email.clone(), + now.bio.clone(), + now.location.clone(), + ); + let mut avatar = + Avatar::new((id.clone(), "avatar"), edited.name.clone()).size(AvatarSize::Xl); + if let Some(picture) = &edited.picture { + avatar = avatar.image(picture.as_path()); + } + let [pictured, discarded] = [(); 2].map(|_| fields.clone()); + let seed = profile.clone(); + div() + .flex() + .flex_col() + .gap_5() + .child( + AvatarUpload::new((id.clone(), "picture"), avatar).on_change(move |path, _, cx| { + log::info!("profile editor: a new picture"); + pictured.update(cx, |fields, cx| { + fields.picture = Some(path); + cx.notify(); + }) + }), + ) + .child( + FormField::new((id.clone(), "name-field"), "Name") + .required() + .child(Input::new(&name)), + ) + .child( + FormField::new((id.clone(), "username-field"), "Username") + .child(Input::new(&username).prefix("@")), + ) + .child( + FormField::new((id.clone(), "email-field"), "Email") + .required() + .child(EmailInput::new(&email)), + ) + .child( + FormField::new((id.clone(), "bio-field"), "About") + .description("A line or two others see.") + .child(Input::new(&bio)), + ) + .child( + FormField::new((id.clone(), "location-field"), "Location") + .child(Input::new(&location)), + ) + .child( + div() + .flex() + .flex_wrap() + .justify_end() + .gap_2() + .child( + Button::new((id.clone(), "discard"), "Discard") + .variant(ButtonVariant::Ghost) + .disabled(!changed) + .on_click(move |_, window, cx| { + log::info!("profile editor: discard"); + let fresh = Fields::filled(&seed, window, cx); + discarded.update(cx, |fields, cx| { + *fields = fresh; + cx.notify(); + }) + }), + ) + .child( + Button::new((id.clone(), "save"), "Save") + .variant(ButtonVariant::Primary) + .disabled(!ready) + .on_click(move |_, window, cx| { + log::info!("profile editor: save"); + on_save(&edited, window, cx); + }), + ), + ) + } +} + +#[cfg(test)] +mod tests { + use super::{Profile, savable}; + + #[test] + fn a_profile_saves_once_changed_named_and_reachable() { + let seed = Profile { + name: "Ada".into(), + email: "ada@example.com".into(), + ..Profile::default() + }; + let with = |edit: fn(&mut Profile)| { + let mut edited = seed.clone(); + edit(&mut edited); + savable(&edited, &seed) + }; + assert!(!with(|_| {}), "nothing changed"); + assert!(with(|profile| profile.location = "London".into())); + assert!( + !with(|profile| profile.name = "".into()), + "a name is needed" + ); + assert!( + !with(|profile| profile.email = "ada".into()), + "the email must read" + ); + } +} diff --git a/vendor/ely/src/account/sessions.rs b/vendor/ely/src/account/sessions.rs new file mode 100644 index 00000000..ea77e83e --- /dev/null +++ b/vendor/ely/src/account/sessions.rs @@ -0,0 +1,145 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, IntoElement, ParentElement, RenderOnce, SharedString, Styled, Window, div, + prelude::*, +}; + +use super::login::Run; +use crate::{ + buttons::{Button, ButtonVariant, ConfirmButton, ConfirmMode}, + data_display::{Badge, Tone}, + primitives::{Icon, IconName}, + theme::{ActiveTheme, ControlSize, IconSize, TextSize}, + typography::Ellipsis, +}; + +type OnKey = Rc; + +/// A place an account is signed in: its key, an icon for the device, the device and the app on it, where it is, when it was last seen, and whether it is this one. +#[derive(Clone, Debug, PartialEq)] +pub struct Session { + pub key: SharedString, + pub icon: IconName, + pub device: SharedString, + pub client: SharedString, + pub place: SharedString, + pub seen: SharedString, + pub current: bool, +} + +/// Where an account is signed in, this device first. Each other one signs out on its own, or all of them at once after a second press. +#[derive(IntoElement)] +pub struct SessionList { + id: ElementId, + sessions: Vec, + on_sign_out: OnKey, + on_sign_out_others: Option, +} + +impl SessionList { + pub fn new( + id: impl Into, + sessions: impl IntoIterator, + on_sign_out: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let mut sessions: Vec<_> = sessions.into_iter().collect(); + assert!( + sessions.iter().filter(|session| session.current).count() <= 1, + "session list: two sessions are this device" + ); + sessions.sort_by_key(|session| !session.current); + Self { + id: id.into(), + sessions, + on_sign_out: Rc::new(on_sign_out), + on_sign_out_others: None, + } + } + + /// Shows "Sign out of all other devices" while there are others. + pub fn on_sign_out_others(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_sign_out_others = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for SessionList { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_sign_out = self.on_sign_out; + let others = self.sessions.iter().any(|session| !session.current); + let theme = cx.theme(); + let rows = self.sessions.into_iter().enumerate().map(|(ix, session)| { + let end = match session.current { + true => Badge::new("This device") + .tone(Tone::Neutral) + .into_any_element(), + false => { + let (key, out) = (session.key.clone(), on_sign_out.clone()); + Button::new((id.clone(), format!("out-{}", session.key)), "Sign out") + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("session list: sign out {key}"); + out(&key, window, cx); + }) + .into_any_element() + } + }; + let tag = format!("session-{}", session.key); + div() + .debug_selector(move || tag) + .flex() + .items_center() + .gap_3() + .py_2p5() + .when(ix > 0, |row| { + row.border_t_1().border_color(theme.colors.border) + }) + .child( + Icon::new(session.icon) + .size(IconSize::Md) + .color(theme.colors.fg_muted), + ) + .child( + div() + .flex_1() + .min_w_0() + .child(Ellipsis::new(format!( + "{} · {}", + session.device, session.client + ))) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(Ellipsis::new(format!( + "{} · {}", + session.place, session.seen + ))), + ), + ) + .child(div().flex_none().child(end)) + }); + let everyone = self.on_sign_out_others.filter(|_| others).map(|run| { + div().pt_2().flex().child( + ConfirmButton::new( + (id.clone(), "others"), + "Sign out of all other devices", + ConfirmMode::Twice, + ) + .on_confirm(move |window, cx| { + log::info!("session list: sign out of the others"); + run(window, cx); + }), + ) + }); + div() + .flex() + .flex_col() + .text_size(theme.text_size(TextSize::Sm)) + .children(rows) + .children(everyone) + } +} diff --git a/vendor/ely/src/account/signup.rs b/vendor/ely/src/account/signup.rs new file mode 100644 index 00000000..c9de8187 --- /dev/null +++ b/vendor/ely/src/account/signup.rs @@ -0,0 +1,207 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, +}; + +use super::login::{Run, aside, field}; +use crate::{ + buttons::{Button, ButtonVariant}, + feedback::InlineMessage, + forms::{Checkbox, EmailInput, Enter, FormField, Input, PasswordInput, is_email}, + primitives::{Icon, IconName, Severity}, + theme::{ActiveTheme, IconSize, TextSize}, +}; + +/// What a sign-up hands its owner. +#[derive(Clone, Debug, PartialEq)] +pub struct Signup { + pub name: SharedString, + pub email: SharedString, + pub password: SharedString, +} + +/// The rules a new password keeps, each with whether `password` keeps it. +pub fn password_rules(password: &str) -> [(&'static str, bool); 3] { + [ + ("At least 8 characters", password.chars().count() >= 8), + ("A letter", password.chars().any(char::is_alphabetic)), + ("A number", password.chars().any(|ch| ch.is_ascii_digit())), + ] +} + +type OnSignup = Rc; + +/// A name, an email and a new password with the rules it keeps, ticked as they hold, and terms to accept when given. Create account rests until all of it holds; Enter in a field sends it. +#[derive(IntoElement)] +pub struct SignupForm { + id: ElementId, + terms: Option, + error: Option, + busy: bool, + on_submit: OnSignup, + on_sign_in: Option, +} + +impl SignupForm { + pub fn new( + id: impl Into, + on_submit: impl Fn(&Signup, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + terms: None, + error: None, + busy: false, + on_submit: Rc::new(on_submit), + on_sign_in: None, + } + } + + /// A box the person ticks to accept, such as "I agree to the terms of service". + pub fn terms(mut self, label: impl Into) -> Self { + self.terms = Some(label.into()); + self + } + + /// Why the last try failed, shown above Create account. + pub fn error(mut self, error: impl Into) -> Self { + self.error = Some(error.into()); + self + } + + /// While the owner works: Create account spins and rests. + pub fn busy(mut self, busy: bool) -> Self { + self.busy = busy; + self + } + + /// Shows "Have an account? Sign in". + pub fn on_sign_in(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_sign_in = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for SignupForm { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let name = field(&id, "name", "Your name", false, window, cx); + let email = field(&id, "email", "name@example.com", false, window, cx); + let password = field(&id, "password", "A new password", true, window, cx); + let accepted = window.use_keyed_state((id.clone(), "terms"), cx, |_, _| false); + let signup = Signup { + name: name.read(cx).text().trim().to_string().into(), + email: email.read(cx).text().trim().to_string().into(), + password: password.read(cx).text().to_string().into(), + }; + let rules = password_rules(&signup.password); + let agreed = *accepted.read(cx); + let ready = !signup.name.is_empty() + && is_email(&signup.email) + && rules.iter().all(|(_, kept)| *kept) + && (self.terms.is_none() || agreed) + && !self.busy; + let on_submit = self.on_submit; + let submit: Run = Rc::new(move |window, cx| { + log::info!("sign-up form: create account"); + on_submit(&signup, window, cx); + }); + let enter = submit.clone(); + let theme = cx.theme(); + let rule = |(rule, kept): (&'static str, bool)| { + let color = if kept { + theme.colors.success + } else { + theme.colors.fg_muted + }; + div() + .flex() + .items_center() + .gap_2() + .text_size(theme.text_size(TextSize::Sm)) + .text_color(color) + .child( + Icon::new(if kept { + IconName::CircleCheck + } else { + IconName::Circle + }) + .size(IconSize::Sm) + .color(color), + ) + .child(rule) + }; + let rules = div().flex().flex_col().gap_1().children(rules.map(rule)); + div() + .flex() + .flex_col() + .gap_4() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child(FormField::new((id.clone(), "name-field"), "Name").child(Input::new(&name))) + .child( + FormField::new((id.clone(), "email-field"), "Email").child(EmailInput::new(&email)), + ) + .child( + FormField::new((id.clone(), "password-field"), "Password") + .child(PasswordInput::new(&password)) + .child(rules), + ) + .children(self.terms.map(|terms| { + Checkbox::new((id.clone(), "terms"), agreed) + .label(terms) + .on_change(move |on, _, cx| { + accepted.update(cx, |accepted, cx| { + *accepted = on; + cx.notify(); + }) + }) + })) + .children( + self.error + .map(|error| InlineMessage::new(Severity::Danger, error)), + ) + .child( + Button::new((id.clone(), "submit"), "Create account") + .variant(ButtonVariant::Primary) + .full_width() + .loading(self.busy) + .disabled(!ready) + .on_click(move |_, window, cx| submit(window, cx)), + ) + .children(self.on_sign_in.map(|run| { + aside( + (id.clone(), "sign-in"), + "Have an account?", + "Sign in", + run, + cx, + ) + })) + } +} + +#[cfg(test)] +mod tests { + use super::password_rules; + + #[test] + fn a_password_keeps_each_rule_on_its_own() { + let kept = |password: &str| password_rules(password).map(|(_, kept)| kept); + assert_eq!(kept(""), [false, false, false]); + assert_eq!(kept("abcdefgh"), [true, true, false]); + assert_eq!(kept("12345678"), [true, false, true]); + assert_eq!( + kept("été2026"), + [false, true, true], + "seven characters, counted as characters" + ); + assert_eq!(kept("été20261"), [true, true, true]); + } +} diff --git a/vendor/ely/src/account/switcher.rs b/vendor/ely/src/account/switcher.rs new file mode 100644 index 00000000..a6be1389 --- /dev/null +++ b/vendor/ely/src/account/switcher.rs @@ -0,0 +1,357 @@ +use std::rc::Rc; + +use gpui::{ + AnyElement, App, Div, ElementId, FontWeight, ImageSource, InteractiveElement, IntoElement, + MouseButton, ParentElement, RenderOnce, SharedString, Stateful, StatefulInteractiveElement, + Styled, Window, div, transparent_black, +}; + +use super::login::Run; +use crate::{ + data_display::{Avatar, Presence}, + menus::{Menu, MenuItem, menu_under}, + primitives::{FocusRing, Icon, IconName}, + theme::{ActiveTheme, AvatarSize, IconSize, Radius, TextSize}, + typography::Ellipsis, +}; + +type OnKey = Rc; + +/// Someone signed in: a key, a name and an email, and a picture when there is one. +#[derive(Clone)] +pub struct Account { + pub key: SharedString, + pub name: SharedString, + pub email: SharedString, + pub image: Option, +} + +/// A workspace or an organization: a key, a name, and a line such as its plan. +#[derive(Clone, Debug, PartialEq)] +pub struct Workspace { + pub key: SharedString, + pub name: SharedString, + pub detail: SharedString, +} + +/// A name over a muted line, each cut to the room there is. +fn named(title: SharedString, detail: SharedString, cx: &App) -> Div { + let theme = cx.theme(); + div() + .flex_1() + .min_w_0() + .child( + div() + .font_weight(FontWeight::MEDIUM) + .child(Ellipsis::new(title)), + ) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(Ellipsis::new(detail)), + ) +} + +/// A row that opens a menu: what it shows, then a chevron. A press leaves focus where it was; Tab reaches it. +fn row(id: impl Into, lead: impl IntoElement, text: Div, cx: &App) -> Stateful

    { + let theme = cx.theme(); + let hover = theme.colors.hover; + div() + .id(id) + .flex() + .items_center() + .gap_2() + .px_2() + .py_1p5() + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(transparent_black()) + .text_size(theme.text_size(TextSize::Sm)) + .tab_index(0) + .focus_ring(cx) + .hover(move |style| style.bg(hover)) + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .child(div().flex_none().child(lead)) + .child(text) + .child( + Icon::new(IconName::ChevronsUpDown) + .size(IconSize::Sm) + .color(theme.colors.fg_subtle), + ) +} + +/// `trigger` opening `menu` under it. +fn opening( + id: ElementId, + menu: &Menu, + trigger: Stateful
    , + window: &mut Window, + cx: &mut App, +) -> AnyElement { + menu_under( + id, + menu, + move |click| { + trigger + .on_click(move |event, window, cx| click(event, window, cx)) + .into_any_element() + }, + window, + cx, + ) + .into_any_element() +} + +/// The accounts signed in, the current one showing; its menu picks another or adds one. +#[derive(IntoElement)] +pub struct AccountSwitcher { + id: ElementId, + accounts: Vec, + current: SharedString, + on_select: OnKey, + on_add: Option, +} + +impl AccountSwitcher { + pub fn new( + id: impl Into, + accounts: impl IntoIterator, + current: impl Into, + on_select: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let (accounts, current): (Vec<_>, SharedString) = + (accounts.into_iter().collect(), current.into()); + Self { + id: id.into(), + accounts, + current, + on_select: Rc::new(on_select), + on_add: None, + } + } + + /// Shows "Add account". + pub fn on_add(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_add = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for AccountSwitcher { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_select = self.on_select; + let items = self.accounts.iter().map(|account| { + let (key, pick) = (account.key.clone(), on_select.clone()); + MenuItem::radio(account.email.clone(), account.key == self.current).on_click( + move |window, cx| { + log::info!("account switcher: {key}"); + pick(&key, window, cx); + }, + ) + }); + let mut menu = Menu::new().group("Accounts", items.collect::>()); + if let Some(add) = self.on_add { + menu = menu.separator().item( + MenuItem::new("Add account") + .icon(IconName::UserPlus) + .on_click(move |window, cx| add(window, cx)), + ); + } + let now = self + .accounts + .into_iter() + .find(|account| account.key == self.current); + if now.is_none() { + log::error!( + "account switcher {id:?}: no account {}; none current", + self.current + ); + } + let name = now + .as_ref() + .map_or_else(|| SharedString::from("No account"), |now| now.name.clone()); + let mut avatar = Avatar::new((id.clone(), "avatar"), name.clone()).size(AvatarSize::Sm); + if let Some(image) = now.as_ref().and_then(|now| now.image.clone()) { + avatar = avatar.image(image); + } + let email = now.map(|now| now.email).unwrap_or_default(); + let trigger = row((id.clone(), "trigger"), avatar, named(name, email, cx), cx); + opening(id, &menu, trigger, window, cx) + } +} + +/// The workspaces one belongs to, the current one showing; its menu picks another or makes one. +#[derive(IntoElement)] +pub struct WorkspaceSwitcher { + id: ElementId, + workspaces: Vec, + current: SharedString, + on_select: OnKey, + on_create: Option, +} + +impl WorkspaceSwitcher { + pub fn new( + id: impl Into, + workspaces: impl IntoIterator, + current: impl Into, + on_select: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let (workspaces, current): (Vec<_>, SharedString) = + (workspaces.into_iter().collect(), current.into()); + Self { + id: id.into(), + workspaces, + current, + on_select: Rc::new(on_select), + on_create: None, + } + } + + /// Shows "Create workspace". + pub fn on_create(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_create = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for WorkspaceSwitcher { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_select = self.on_select; + let items: Vec<_> = self + .workspaces + .iter() + .map(|each| { + let (key, pick) = (each.key.clone(), on_select.clone()); + MenuItem::radio(each.name.clone(), each.key == self.current).on_click( + move |window, cx| { + log::info!("workspace switcher: {key}"); + pick(&key, window, cx); + }, + ) + }) + .collect(); + let mut menu = Menu::new().group("Workspaces", items); + if let Some(create) = self.on_create { + menu = menu.separator().item( + MenuItem::new("Create workspace") + .icon(IconName::Plus) + .on_click(move |window, cx| create(window, cx)), + ); + } + let now = self + .workspaces + .into_iter() + .find(|each| each.key == self.current); + if now.is_none() { + log::error!( + "workspace switcher {id:?}: no workspace {}; none current", + self.current + ); + } + let name = now.as_ref().map_or_else( + || SharedString::from("No workspace"), + |now| now.name.clone(), + ); + let mark = Avatar::new((id.clone(), "mark"), name.clone()) + .square() + .size(AvatarSize::Sm); + let detail = now.map(|now| now.detail).unwrap_or_default(); + let trigger = row((id.clone(), "trigger"), mark, named(name, detail, cx), cx); + opening(id, &menu, trigger, window, cx) + } +} + +/// Someone's avatar that opens their menu: who is signed in over the owner's rows, and Sign out last. +#[derive(IntoElement)] +pub struct UserMenu { + id: ElementId, + name: SharedString, + email: SharedString, + image: Option, + presence: Option, + items: Vec, + on_sign_out: Run, +} + +impl UserMenu { + pub fn new( + id: impl Into, + name: impl Into, + email: impl Into, + on_sign_out: impl Fn(&mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + name: name.into(), + email: email.into(), + image: None, + presence: None, + items: Vec::new(), + on_sign_out: Rc::new(on_sign_out), + } + } + + pub fn image(mut self, source: impl Into) -> Self { + self.image = Some(source.into()); + self + } + + pub fn presence(mut self, presence: Presence) -> Self { + self.presence = Some(presence); + self + } + + /// A row of the owner's, such as Profile or Settings. + pub fn item(mut self, item: MenuItem) -> Self { + self.items.push(item); + self + } +} + +impl RenderOnce for UserMenu { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let sign_out = self.on_sign_out; + let menu = + Menu::new() + .group(format!("Signed in as {}", self.email), self.items) + .separator() + .item(MenuItem::new("Sign out").icon(IconName::LogOut).on_click( + move |window, cx| { + log::info!("user menu: sign out"); + sign_out(window, cx); + }, + )); + let mut avatar = Avatar::new((id.clone(), "avatar"), self.name).size(AvatarSize::Sm); + if let Some(image) = self.image { + avatar = avatar.image(image); + } + if let Some(presence) = self.presence { + avatar = avatar.presence(presence); + } + let trigger = div() + .id((id.clone(), "trigger")) + .rounded_full() + .border_1() + .border_color(transparent_black()) + .tab_index(0) + .focus_ring(cx) + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .child(avatar); + menu_under( + id, + &menu, + move |click| { + trigger + .on_click(move |event, window, cx| click(event, window, cx)) + .into_any_element() + }, + window, + cx, + ) + } +} diff --git a/vendor/ely/src/account/team.rs b/vendor/ely/src/account/team.rs new file mode 100644 index 00000000..6687de78 --- /dev/null +++ b/vendor/ely/src/account/team.rs @@ -0,0 +1,411 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, ImageSource, InteractiveElement, IntoElement, ParentElement, RenderOnce, + SharedString, Styled, Window, div, prelude::*, +}; + +use super::login::field; +use crate::{ + buttons::{Button, ButtonVariant, ConfirmButton, ConfirmMode}, + data_display::{Avatar, Badge, Tone}, + forms::{Choice, EmailInput, Enter, Select, is_email}, + theme::{ActiveTheme, AvatarSize, ControlSize, TextSize}, + typography::Ellipsis, +}; + +type OnKey = Rc; +type OnPair = Rc; + +/// A role: its key, its name and what it may do. +#[derive(Clone, Debug, PartialEq)] +pub struct Role { + pub key: SharedString, + pub name: SharedString, + pub description: SharedString, +} + +/// The role of `key`; none, logged for `owner`, when the roles lost it. +fn role_named<'a>(roles: &'a [Role], key: &SharedString, owner: &str) -> Option<&'a Role> { + let role = roles.iter().find(|role| role.key == *key); + if role.is_none() { + log::error!("{owner}: no role {key}; none shown"); + } + role +} + +/// A role to pick, each with what it may do beneath its name. +#[derive(IntoElement)] +pub struct RoleSelector { + id: ElementId, + roles: Vec, + selected: SharedString, + disabled: bool, + on_change: OnKey, +} + +impl RoleSelector { + pub fn new( + id: impl Into, + roles: impl IntoIterator, + selected: impl Into, + on_change: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let (roles, selected): (Vec<_>, SharedString) = + (roles.into_iter().collect(), selected.into()); + role_named(&roles, &selected, "role selector"); + Self { + id: id.into(), + roles, + selected, + disabled: false, + on_change: Rc::new(on_change), + } + } + + pub fn disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } +} + +impl RenderOnce for RoleSelector { + fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement { + let id = self.id; + let on_change = self.on_change; + let choices = self + .roles + .into_iter() + .map(|role| Choice::new(role.key, role.name).note(role.description)); + Select::new(id, choices) + .selected(self.selected) + .disabled(self.disabled) + .size(ControlSize::Sm) + .on_change(move |key, window, cx| { + log::info!("role selector: {key}"); + on_change(key, window, cx); + }) + } +} + +/// Someone on a team: their key, name and email, their role's key, when they were last seen as words, a picture when there is one, and whether they own the team. +#[derive(Clone)] +pub struct Member { + pub key: SharedString, + pub name: SharedString, + pub email: SharedString, + pub role: SharedString, + pub seen: SharedString, + pub image: Option, + pub owner: bool, +} + +/// A team's members: each with their picture, name and email and when last seen, a role to change and a Remove that asks twice. The owner's role stays, and the owner stays. +#[derive(IntoElement)] +pub struct TeamMemberTable { + id: ElementId, + members: Vec, + roles: Vec, + on_role: OnPair, + on_remove: OnKey, +} + +impl TeamMemberTable { + pub fn new( + id: impl Into, + members: impl IntoIterator, + roles: impl IntoIterator, + on_role: impl Fn(&SharedString, &SharedString, &mut Window, &mut App) + 'static, + on_remove: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let (members, roles): (Vec, Vec) = + (members.into_iter().collect(), roles.into_iter().collect()); + Self { + id: id.into(), + members, + roles, + on_role: Rc::new(on_role), + on_remove: Rc::new(on_remove), + } + } +} + +impl RenderOnce for TeamMemberTable { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_role = self.on_role; + let on_remove = self.on_remove; + let theme = cx.theme(); + let rows = self.members.into_iter().enumerate().map(|(ix, member)| { + let mut avatar = Avatar::new( + (id.clone(), format!("avatar-{}", member.key)), + member.name.clone(), + ) + .size(AvatarSize::Sm); + if let Some(image) = member.image { + avatar = avatar.image(image); + } + let (role, remove) = match member.owner { + true => ( + div() + .text_color(theme.colors.fg_muted) + .child("Owner") + .into_any_element(), + None, + ), + false => { + let [changed, removed] = [(); 2].map(|_| member.key.clone()); + let (set, drop) = (on_role.clone(), on_remove.clone()); + let select = RoleSelector::new( + (id.clone(), format!("role-{}", member.key)), + self.roles.clone(), + member.role.clone(), + move |role, window, cx| set(&changed, role, window, cx), + ); + let button = ConfirmButton::new( + (id.clone(), format!("remove-{}", member.key)), + "Remove", + ConfirmMode::Twice, + ) + .size(ControlSize::Sm) + .on_confirm(move |window, cx| { + log::info!("team member table: remove {removed}"); + drop(&removed, window, cx); + }); + (select.into_any_element(), Some(button)) + } + }; + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_3() + .gap_y_2() + .py_2p5() + .when(ix > 0, |row| { + row.border_t_1().border_color(theme.colors.border) + }) + .child( + div() + .flex() + .items_center() + .gap_3() + .flex_1() + .min_w(theme.label_width()) + .child(div().flex_none().child(avatar)) + .child( + div() + .flex_1() + .min_w_0() + .child(Ellipsis::new(member.name)) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(Ellipsis::new(format!( + "{} · {}", + member.email, member.seen + ))), + ), + ), + ) + .child( + div() + .flex() + .items_center() + .gap_2() + .flex_none() + .child(div().w(theme.label_width()).child(role)) + .children(remove), + ) + }); + div() + .flex() + .flex_col() + .text_size(theme.text_size(TextSize::Sm)) + .children(rows) + } +} + +/// An invitation on its way: its key, the address, the role's key, when it went as words, and whether it has lapsed. +#[derive(Clone, Debug, PartialEq)] +pub struct Invitation { + pub key: SharedString, + pub email: SharedString, + pub role: SharedString, + pub sent: SharedString, + pub expired: bool, +} + +/// Invitations out, each with its role and when it went, and a Resend and a Revoke; above them, an address and a role to invite someone new. Invite waits for an address that reads. +#[derive(IntoElement)] +pub struct InvitationList { + id: ElementId, + invitations: Vec, + roles: Vec, + on_invite: OnPair, + on_resend: OnKey, + on_revoke: OnKey, +} + +impl InvitationList { + pub fn new( + id: impl Into, + invitations: impl IntoIterator, + roles: impl IntoIterator, + on_invite: impl Fn(&SharedString, &SharedString, &mut Window, &mut App) + 'static, + on_resend: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + on_revoke: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + let (invitations, roles): (Vec, Vec) = ( + invitations.into_iter().collect(), + roles.into_iter().collect(), + ); + assert!(!roles.is_empty(), "invitation list: no role to invite as"); + Self { + id: id.into(), + invitations, + roles, + on_invite: Rc::new(on_invite), + on_resend: Rc::new(on_resend), + on_revoke: Rc::new(on_revoke), + } + } +} + +impl RenderOnce for InvitationList { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let on_invite = self.on_invite; + let on_resend = self.on_resend; + let on_revoke = self.on_revoke; + let email = field(&id, "email", "name@example.com", false, window, cx); + let first = self.roles[0].key.clone(); + let role = window.use_keyed_state((id.clone(), "role"), cx, move |_, _| first); + let (address, chosen): (SharedString, SharedString) = ( + email.read(cx).text().trim().to_string().into(), + role.read(cx).clone(), + ); + let offered = self.roles.iter().any(|role| role.key == chosen); + let ready = is_email(&address) && offered; + let clear = email.clone(); + let invite = Rc::new(move |window: &mut Window, cx: &mut App| { + log::info!("invitation list: invite as {chosen}"); + on_invite(&address, &chosen, window, cx); + clear.update(cx, |field, cx| field.set_text("", cx)); + }); + let enter = invite.clone(); + let theme = cx.theme(); + let rows = + self.invitations.iter().map(|invitation| { + let named = role_named(&self.roles, &invitation.role, "invitation list") + .map_or_else(|| SharedString::from("No role"), |role| role.name.clone()); + let [again, gone] = [(); 2].map(|_| invitation.key.clone()); + let (resend, revoke) = (on_resend.clone(), on_revoke.clone()); + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_3() + .gap_y_2() + .py_2p5() + .border_t_1() + .border_color(theme.colors.border) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .child(Ellipsis::new(invitation.email.clone())) + .child( + div() + .flex() + .items_center() + .gap_2() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(theme.colors.fg_muted) + .child(div().flex_1().min_w_0().child(Ellipsis::new(format!( + "{named} · {}", + invitation.sent + )))) + .children(invitation.expired.then(|| { + div() + .flex_none() + .child(Badge::new("Expired").tone(Tone::Warning)) + })), + ), + ) + .child( + div() + .flex() + .flex_none() + .gap_1() + .child( + Button::new( + (id.clone(), format!("resend-{}", invitation.key)), + "Resend", + ) + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("invitation list: resend {again}"); + resend(&again, window, cx); + }), + ) + .child( + Button::new( + (id.clone(), format!("revoke-{}", invitation.key)), + "Revoke", + ) + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("invitation list: revoke {gone}"); + revoke(&gone, window, cx); + }), + ), + ) + }); + let picked = role.clone(); + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .flex_wrap() + .gap_2() + .capture_action(move |_: &Enter, window, cx| { + if ready { + cx.stop_propagation(); + enter(window, cx); + } + }) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .child(EmailInput::new(&email)), + ) + .child(div().w(theme.label_width()).child(RoleSelector::new( + (id.clone(), "invite-role"), + self.roles.clone(), + role.read(cx).clone(), + move |key, _, cx| { + picked.update(cx, |role, cx| { + *role = key.clone(); + cx.notify(); + }) + }, + ))) + .child( + Button::new((id.clone(), "invite"), "Invite") + .variant(ButtonVariant::Primary) + .disabled(!ready) + .on_click(move |_, window, cx| invite(window, cx)), + ), + ) + .child(div().flex().flex_col().children(rows)) + } +} diff --git a/vendor/ely/src/account/tests/access.rs b/vendor/ely/src/account/tests/access.rs new file mode 100644 index 00000000..4727d863 --- /dev/null +++ b/vendor/ely/src/account/tests/access.rs @@ -0,0 +1,259 @@ +use gpui::{AnyElement, Entity, IntoElement, SharedString, TestAppContext}; + +use super::{Bench, bench, said, say, settle, tab, tap, write}; +use crate::account::{ + Account, AccountSwitcher, ApiKey, ApiKeyManager, Profile, ProfileEditor, Session, SessionList, + UserMenu, Workspace, WorkspaceSwitcher, +}; +use crate::{menus::MenuItem, primitives::IconName}; + +fn accounts(_: &Bench, owner: Entity) -> AnyElement { + let account = |key: &str, name: &str, email: &str| Account { + key: key.to_string().into(), + name: name.to_string().into(), + email: email.to_string().into(), + image: None, + }; + AccountSwitcher::new( + "accounts", + [ + account("ada", "Ada", "ada@work.com"), + account("home", "Ada", "ada@home.com"), + ], + "ada", + move |key, _, cx| say(&owner, key.to_string(), cx), + ) + .into_any_element() +} + +/// Stops: the switcher; its menu marks the first row on a keyboard open. +#[gpui::test] +fn the_account_menu_picks_another(cx: &mut TestAppContext) { + let (host, cx) = bench(accounts, cx); + tab(1, cx); + tap("enter", cx); + tap("down", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["home"]); +} + +fn sessions(_: &Bench, owner: Entity) -> AnyElement { + let session = |key: &str, current: bool| Session { + key: key.to_string().into(), + icon: IconName::Monitor, + device: "MacBook".into(), + client: "Safari".into(), + place: "Lisbon".into(), + seen: "Active now".into(), + current, + }; + let everyone = owner.clone(); + SessionList::new( + "sessions", + [session("phone", false), session("mac", true)], + move |key, _, cx| say(&owner, format!("out {key}"), cx), + ) + .on_sign_out_others(move |_, cx| say(&everyone, "others".into(), cx)) + .into_any_element() +} + +/// Stops: the phone's Sign out, then Sign out of all other devices; this device has none. +#[gpui::test] +fn a_session_signs_out_and_the_rest_ask_twice(cx: &mut TestAppContext) { + let (host, cx) = bench(sessions, cx); + tab(1, cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["out phone"], + "this device lists first and has no Sign out" + ); + tab(2, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["out phone"], "the first press only arms"); + tap("space", cx); + assert_eq!(said(&host, cx), ["out phone", "others"]); +} + +fn keys(bench: &Bench, owner: Entity) -> AnyElement { + let key = ApiKey { + key: "ci".into(), + name: "CI".into(), + hint: "sk_…4f2a".into(), + created: "Made 3 Sep".into(), + used: "Never used".into(), + }; + let [made, revoked, done] = [(); 3].map(|_| owner.clone()); + let manager = ApiKeyManager::new( + "keys", + [key], + move |name, _, cx| say(&made, format!("make {name}"), cx), + move |key, _, cx| say(&revoked, format!("revoke {key}"), cx), + move |_, cx| say(&done, "done".into(), cx), + ); + match bench.sent { + true => manager.secret("sk_live_0123456789").into_any_element(), + false => manager.into_any_element(), + } +} + +/// Stops: the name, then Revoke while Create rests; with a secret, Copy and Done lead. +#[gpui::test] +fn a_key_is_made_by_name_revoked_on_the_second_press_and_its_secret_dismissed( + cx: &mut TestAppContext, +) { + let (host, cx) = bench(keys, cx); + tab(2, cx); + tap("space", cx); + tap("space", cx); + tab(1, cx); + write("Deploys", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["revoke ci", "make Deploys"]); + cx.executor() + .advance_clock(std::time::Duration::from_secs(10)); + settle(cx); + tab(2, cx); + tap("space", cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["revoke ci", "make Deploys", "revoke ci"], + "the name field emptied, so Create rests and the second stop is Revoke" + ); + host.update(cx, |bench, cx| { + bench.sent = true; + cx.notify(); + }); + settle(cx); + tab(2, cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["revoke ci", "make Deploys", "revoke ci", "done"] + ); +} + +fn profile() -> Profile { + Profile { + name: "Ada".into(), + username: "ada".into(), + email: "ada@example.com".into(), + ..Profile::default() + } +} + +fn editor(_: &Bench, owner: Entity) -> AnyElement { + ProfileEditor::new("profile", profile(), move |profile, _, cx| { + say(&owner, format!("{} {}", profile.name, profile.email), cx) + }) + .into_any_element() +} + +/// Stops: the picture, name, username, email, about, location; Discard and Save once changed. +#[gpui::test] +fn a_profile_saves_only_what_changed_and_discard_puts_it_back(cx: &mut TestAppContext) { + let (host, cx) = bench(editor, cx); + tab(2, cx); + write(" Lovelace", cx); + tab(8, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["Ada Lovelace ada@example.com"]); + tab(7, cx); + tap("space", cx); + tab(8, cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["Ada Lovelace ada@example.com"], + "after Discard nothing changed, so Save rests" + ); +} + +fn menu(_: &Bench, owner: Entity) -> AnyElement { + let [profile, out] = [(); 2].map(|_| owner.clone()); + UserMenu::new("user", "Ada", "ada@example.com", move |_, cx| { + say(&out, "out".into(), cx) + }) + .item(MenuItem::new("Profile").on_click(move |_, cx| say(&profile, "profile".into(), cx))) + .into_any_element() +} + +/// Stops: the avatar; the menu's rows are Profile, then Sign out. +#[gpui::test] +fn the_user_menu_holds_the_owners_rows_and_sign_out_last(cx: &mut TestAppContext) { + let (host, cx) = bench(menu, cx); + tab(1, cx); + tap("enter", cx); + tap("down", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["out"]); +} + +fn workspaces(_: &Bench, owner: Entity) -> AnyElement { + let space = |key: &str| Workspace { + key: key.to_string().into(), + name: SharedString::from(key.to_string()), + detail: "Pro".into(), + }; + let made = owner.clone(); + WorkspaceSwitcher::new( + "spaces", + [space("north"), space("south")], + "south", + move |key, _, cx| say(&owner, key.to_string(), cx), + ) + .on_create(move |_, cx| say(&made, "create".into(), cx)) + .into_any_element() +} + +/// Stops: the switcher; its rows are north, south, then Create workspace. +#[gpui::test] +fn the_workspace_menu_picks_or_makes_one(cx: &mut TestAppContext) { + let (host, cx) = bench(workspaces, cx); + tab(1, cx); + tap("enter", cx); + tap("enter", cx); + tab(1, cx); + tap("enter", cx); + tap("up", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["north", "create"]); +} + +fn alone(_: &Bench, owner: Entity) -> AnyElement { + let here = Session { + key: "mac".into(), + icon: IconName::Monitor, + device: "MacBook".into(), + client: "Safari".into(), + place: "Lisbon".into(), + seen: "Active now".into(), + current: true, + }; + let everyone = owner.clone(); + SessionList::new("sessions", [here], move |key, _, cx| { + say(&owner, format!("out {key}"), cx) + }) + .on_sign_out_others(move |_, cx| say(&everyone, "others".into(), cx)) + .into_any_element() +} + +/// With this device alone there is nothing to sign out, so the list has no stop. +#[gpui::test] +fn this_device_alone_offers_no_sign_out(cx: &mut TestAppContext) { + let (host, cx) = bench(alone, cx); + tab(1, cx); + tap("space", cx); + tap("space", cx); + assert!(said(&host, cx).is_empty()); +} + +/// The phone comes first in what the owner hands over, this device second; this device lists first. +#[gpui::test] +fn this_device_lists_first(cx: &mut TestAppContext) { + let (_, cx) = bench(sessions, cx); + let here = cx.debug_bounds("session-mac").expect("this device"); + let phone = cx.debug_bounds("session-phone").expect("the phone"); + assert!(here.top() < phone.top(), "{here:?} over {phone:?}"); +} diff --git a/vendor/ely/src/account/tests/billing.rs b/vendor/ely/src/account/tests/billing.rs new file mode 100644 index 00000000..abcf7e5c --- /dev/null +++ b/vendor/ely/src/account/tests/billing.rs @@ -0,0 +1,488 @@ +use gpui::{AnyElement, Entity, IntoElement, ParentElement, Styled, TestAppContext, div, px}; + +use super::{Bench, bench, said, say, settle, tab, tap, write}; +use crate::account::{ + BillingHistory, Invitation, InvitationList, Invoice, InvoiceState, Member, PaymentMethodForm, + Quota, Role, Standing, Subscription, SubscriptionCard, TeamMemberTable, UpgradePrompt, + UsageQuota, +}; + +fn plan(bench: &Bench, owner: Entity) -> AnyElement { + let standing = match bench.sent { + true => Standing::Canceled { + ends: "1 Oct 2026".into(), + }, + false => Standing::Active { + renews: "1 Oct 2026".into(), + }, + }; + let [cancel, resume] = [(); 2].map(|_| owner.clone()); + SubscriptionCard::new( + "plan", + Subscription { + plan: "Pro".into(), + price: 20.0, + currency: "USD".into(), + yearly: false, + standing, + }, + ) + .on_cancel(move |_, cx| say(&cancel, "cancel".into(), cx)) + .on_resume(move |_, cx| say(&resume, "resume".into(), cx)) + .into_any_element() +} + +/// Stops: Cancel plan while it runs; Keep plan once canceled. +#[gpui::test] +fn a_plan_cancels_on_the_second_press_and_comes_back(cx: &mut TestAppContext) { + let (host, cx) = bench(plan, cx); + tab(1, cx); + tap("space", cx); + assert!(said(&host, cx).is_empty(), "the first press only arms"); + tap("space", cx); + host.update(cx, |bench, cx| { + bench.sent = true; + cx.notify(); + }); + settle(cx); + tab(1, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["cancel", "resume"]); +} + +fn card(_: &Bench, owner: Entity) -> AnyElement { + PaymentMethodForm::new("card", move |card, _, cx| { + say( + &owner, + format!( + "{} {} {}/{} {} {}", + card.brand.name(), + card.number, + card.month, + card.year, + card.cvc, + card.name + ), + cx, + ) + }) + .into_any_element() +} + +/// Stops: number, expiry, code, name, then Save once the card reads. +#[gpui::test] +fn a_card_saves_once_its_number_checks_out(cx: &mut TestAppContext) { + let (host, cx) = bench(card, cx); + tab(1, cx); + write("4242424242424241", cx); + tab(2, cx); + write("1240", cx); + tab(3, cx); + write("123", cx); + tab(4, cx); + write("Ada Lovelace", cx); + tap("enter", cx); + assert!( + said(&host, cx).is_empty(), + "a number that fails its check keeps Save at rest" + ); + tab(1, cx); + tap("backspace", cx); + write("2", cx); + tab(4, cx); + tap("enter", cx); + assert_eq!( + said(&host, cx), + ["Visa 4242424242424242 12/2040 123 Ada Lovelace"] + ); +} + +fn roles() -> Vec { + let role = |key: &str, name: &str| Role { + key: key.to_string().into(), + name: name.to_string().into(), + description: "Can do things".into(), + }; + vec![role("member", "Member"), role("admin", "Admin")] +} + +fn invites(_: &Bench, owner: Entity) -> AnyElement { + let sent = Invitation { + key: "bo".into(), + email: "bo@example.com".into(), + role: "admin".into(), + sent: "Sent 2 days ago".into(), + expired: false, + }; + let [invited, again, gone] = [(); 3].map(|_| owner.clone()); + InvitationList::new( + "invites", + [sent], + roles(), + move |email, role, _, cx| say(&invited, format!("invite {email} {role}"), cx), + move |key, _, cx| say(&again, format!("resend {key}"), cx), + move |key, _, cx| say(&gone, format!("revoke {key}"), cx), + ) + .into_any_element() +} + +/// Stops: the address, the role, then Resend and Revoke while Invite rests. +#[gpui::test] +fn an_invitation_goes_as_a_member_and_one_out_resends(cx: &mut TestAppContext) { + let (host, cx) = bench(invites, cx); + tab(3, cx); + tap("space", cx); + tab(1, cx); + write("cy@example.com", cx); + tap("enter", cx); + assert_eq!( + said(&host, cx), + ["resend bo", "invite cy@example.com member"] + ); +} + +fn team(_: &Bench, owner: Entity) -> AnyElement { + let member = |key: &str, owner: bool| Member { + key: key.to_string().into(), + name: key.to_string().into(), + email: format!("{key}@example.com").into(), + role: "member".into(), + seen: "Active today".into(), + image: None, + owner, + }; + let removed = owner.clone(); + TeamMemberTable::new( + "team", + [member("ada", true), member("bo", false)], + roles(), + move |key, role, _, cx| say(&owner, format!("{key} {role}"), cx), + move |key, _, cx| say(&removed, format!("remove {key}"), cx), + ) + .into_any_element() +} + +/// Stops: bo's role, then bo's Remove; the owner has neither. +#[gpui::test] +fn a_member_leaves_on_the_second_press_and_the_owner_stays(cx: &mut TestAppContext) { + let (host, cx) = bench(team, cx); + tab(2, cx); + tap("space", cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["remove bo"]); +} + +fn wall(_: &Bench, owner: Entity) -> AnyElement { + let later = owner.clone(); + UpgradePrompt::new("wall", "Unlock history", move |_, cx| { + say(&owner, "upgrade".into(), cx) + }) + .benefit("Every message, kept") + .on_dismiss(move |_, cx| say(&later, "later".into(), cx)) + .into_any_element() +} + +/// Stops: Upgrade, then Not now. +#[gpui::test] +fn a_paywall_upgrades_or_waits(cx: &mut TestAppContext) { + let (host, cx) = bench(wall, cx); + tab(1, cx); + tap("space", cx); + tab(2, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["upgrade", "later"]); +} + +fn busy_card(_: &Bench, owner: Entity) -> AnyElement { + PaymentMethodForm::new("card", move |card, _, cx| { + say(&owner, card.number.to_string(), cx) + }) + .busy(true) + .into_any_element() +} + +/// Stops: number, expiry, code, name; Save rests while the owner checks the card. +#[gpui::test] +fn a_card_waits_while_the_owner_checks_it(cx: &mut TestAppContext) { + let (host, cx) = bench(busy_card, cx); + tab(1, cx); + write("4242424242424242", cx); + tab(2, cx); + write("1240", cx); + tab(3, cx); + write("123", cx); + tab(4, cx); + write("Ada Lovelace", cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty()); +} + +/// Stops: the address, the role; Invite waits for an address that reads. +#[gpui::test] +fn an_invitation_waits_for_an_address(cx: &mut TestAppContext) { + let (host, cx) = bench(invites, cx); + tab(1, cx); + write("cy@example", cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty()); +} + +/// Stops: bo's role first; Enter opens its list, Down reaches Admin and Enter picks it. +#[gpui::test] +fn a_members_role_changes_from_its_row(cx: &mut TestAppContext) { + let (host, cx) = bench(team, cx); + tab(1, cx); + for key in ["enter", "down", "enter"] { + tap(key, cx); + } + assert_eq!(said(&host, cx), ["bo admin"]); +} + +fn bills(_: &Bench, owner: Entity) -> AnyElement { + let invoice = Invoice { + key: "sep".into(), + date: "1 Sep 2026".into(), + description: "Pro, monthly".into(), + amount: 20.0, + currency: "USD".into(), + state: InvoiceState::Paid, + }; + BillingHistory::new("bills", [invoice]) + .on_download(move |key, _, cx| say(&owner, format!("download {key}"), cx)) + .into_any_element() +} + +/// Stops: the bill's download. +#[gpui::test] +fn a_bill_downloads_from_its_row(cx: &mut TestAppContext) { + let (host, cx) = bench(bills, cx); + tab(1, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["download sep"]); +} + +/// Stops: number, expiry, code, name, then Save once the card reads. +#[gpui::test] +fn a_card_waits_for_a_whole_code_and_a_name(cx: &mut TestAppContext) { + let (host, cx) = bench(card, cx); + tab(1, cx); + write("4242424242424242", cx); + tab(2, cx); + write("1240", cx); + tab(3, cx); + write("12", cx); + tab(4, cx); + write("Ada", cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty(), "a code of two digits"); + tab(3, cx); + write("3", cx); + tab(4, cx); + tap("secondary-a", cx); + tap("backspace", cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty(), "no name on the card"); + write("Ada", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["Visa 4242424242424242 12/2040 123 Ada"]); +} + +/// Stops: number, expiry, code, name; an American Express number takes fifteen digits and a code of four. +#[gpui::test] +fn an_american_express_card_takes_its_own_shape(cx: &mut TestAppContext) { + let (host, cx) = bench(card, cx); + tab(1, cx); + write("378282246310005", cx); + tab(2, cx); + write("1240", cx); + tab(3, cx); + write("1234", cx); + tab(4, cx); + write("Ada", cx); + tap("enter", cx); + assert_eq!( + said(&host, cx), + ["American Express 378282246310005 12/2040 1234 Ada"] + ); +} + +/// Stops: the address, the role, then Invite once the address reads; after it goes, Invite rests and the third stop is Resend. +#[gpui::test] +fn an_invitation_empties_the_address_once_it_goes(cx: &mut TestAppContext) { + let (host, cx) = bench(invites, cx); + tab(1, cx); + write("cy@example.com", cx); + tap("enter", cx); + tab(3, cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["invite cy@example.com member", "resend bo"] + ); +} + +/// One quota in a 280px box. +fn usage(name: &'static str, used: f64, limit: f64) -> AnyElement { + let quota = Quota { + key: "seats".into(), + name: name.into(), + used, + limit, + unit: "seats".into(), + }; + div() + .w(px(280.0)) + .child(UsageQuota::new("usage", [quota])) + .into_any_element() +} + +fn long_name(_: &Bench, _: Entity) -> AnyElement { + usage("Seats across every workspace you own", 9.0, 12.0) +} + +/// A long name gives way, so the count stays whole inside a 280px box. +#[gpui::test] +fn a_long_quota_name_leaves_its_count_inside_the_box(cx: &mut TestAppContext) { + let (_, cx) = bench(long_name, cx); + let count = cx.debug_bounds("meter-detail").expect("the count"); + assert!( + count.right() <= px(280.0), + "the count ends inside the box: {count:?}" + ); +} + +fn past_limit(_: &Bench, _: Entity) -> AnyElement { + usage("Seats", 12.4, 10.0) +} + +/// A quota past its limit draws a full bar and says how far past. +#[gpui::test] +fn a_quota_past_its_limit_draws_full(cx: &mut TestAppContext) { + let (_, cx) = bench(past_limit, cx); + assert!(cx.debug_bounds("meter-detail").is_some(), "the quota drew"); +} + +fn line(_: &Bench, owner: Entity) -> AnyElement { + UpgradePrompt::new("line", "Unlock history", move |_, cx| { + say(&owner, "upgrade".into(), cx) + }) + .into_any_element() +} + +/// With benefits the prompt is a paywall that lists them. +#[gpui::test] +fn a_paywall_lists_its_benefits(cx: &mut TestAppContext) { + let (_, cx) = bench(wall, cx); + assert!(cx.debug_bounds("paywall-benefits").is_some()); +} + +/// Without benefits the prompt stands as one line, with no list. +#[gpui::test] +fn a_prompt_without_benefits_stands_as_a_line(cx: &mut TestAppContext) { + let (_, cx) = bench(line, cx); + assert!(cx.debug_bounds("paywall-benefits").is_none()); +} + +/// Accounts, workspaces, a provider and roles that left their lists. +fn departed(_: &Bench, _: Entity) -> AnyElement { + let account = crate::account::Account { + key: "ada".into(), + name: "Ada".into(), + email: "ada@work.com".into(), + image: None, + }; + let space = crate::account::Workspace { + key: "north".into(), + name: "North".into(), + detail: "Pro".into(), + }; + let invitation = Invitation { + key: "bo".into(), + email: "bo@example.com".into(), + role: "gone".into(), + sent: "Sent 2 days ago".into(), + expired: false, + }; + let member = Member { + key: "bo".into(), + name: "Bo".into(), + email: "bo@example.com".into(), + role: "gone".into(), + seen: "Active today".into(), + image: None, + owner: false, + }; + div() + .w(px(360.0)) + .child(crate::account::AccountSwitcher::new( + "accounts", + [account], + "gone", + |_, _, _| {}, + )) + .child(crate::account::WorkspaceSwitcher::new( + "spaces", + [space], + "gone", + |_, _, _| {}, + )) + .child( + crate::account::OAuthButtons::new("oauth", [("github", "GitHub")], |_, _, _| {}) + .busy("gone"), + ) + .child(InvitationList::new( + "invites", + [invitation], + roles(), + |_, _, _, _| {}, + |_, _, _| {}, + |_, _, _| {}, + )) + .child(TeamMemberTable::new( + "team", + [member], + roles(), + |_, _, _, _| {}, + |_, _, _| {}, + )) + .into_any_element() +} + +#[gpui::test] +fn accounts_workspaces_and_roles_that_left_draw(cx: &mut TestAppContext) { + let (_, cx) = bench(departed, cx); + settle(cx); +} + +/// Invitations whose first role leaves once the bench says sent. +fn departing_role(state: &Bench, owner: Entity) -> AnyElement { + let offered: Vec = roles() + .into_iter() + .filter(|role| !state.sent || role.key != "member") + .collect(); + InvitationList::new( + "invites", + [], + offered, + move |email, role, _, cx| say(&owner, format!("invite {email} {role}"), cx), + |_, _, _| {}, + |_, _, _| {}, + ) + .into_any_element() +} + +#[gpui::test] +fn an_invitation_as_a_role_that_left_sends_nothing(cx: &mut TestAppContext) { + let (host, cx) = bench(departing_role, cx); + tab(1, cx); + write("cy@example.com", cx); + host.update(cx, |state, cx| { + state.sent = true; + cx.notify(); + }); + settle(cx); + tap("enter", cx); + tab(3, cx); + tap("space", cx); + assert_eq!(said(&host, cx), Vec::::new()); +} diff --git a/vendor/ely/src/account/tests/mod.rs b/vendor/ely/src/account/tests/mod.rs new file mode 100644 index 00000000..9444868e --- /dev/null +++ b/vendor/ely/src/account/tests/mod.rs @@ -0,0 +1,87 @@ +use gpui::{ + AnyElement, App, Context, Entity, IntoElement, KeyBinding, ParentElement, Render, Styled, + TestAppContext, VisualTestContext, Window, div, px, +}; + +use crate::{forms, primitives::FocusNext, theme::Theme}; + +pub(super) type Part = fn(&Bench, Entity) -> AnyElement; + +/// A view that shows one account part, keeps what it heard, and holds what the owner decides: whether a link went, and how many codes failed. +pub(super) struct Bench { + part: Part, + said: Vec, + pub(super) sent: bool, + pub(super) failed: usize, +} + +impl Render for Bench { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + div().w(px(360.0)).child((self.part)(self, cx.entity())) + } +} + +pub(super) fn bench( + part: Part, + cx: &mut TestAppContext, +) -> (Entity, &mut VisualTestContext) { + cx.update(|cx| { + Theme::init(cx); + Theme::update(cx, |theme| theme.reduced_motion = true); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); + let (host, cx) = cx.add_window_view(|_, _| Bench { + part, + said: Vec::new(), + sent: false, + failed: 0, + }); + settle(cx); + (host, cx) +} + +pub(super) fn settle(cx: &mut VisualTestContext) { + for _ in 0..3 { + cx.run_until_parked(); + cx.update(|window, _| window.refresh()); + } + cx.run_until_parked(); +} + +pub(super) fn say(owner: &Entity, words: String, cx: &mut App) { + owner.update(cx, |bench, cx| { + bench.said.push(words); + cx.notify(); + }); +} + +pub(super) fn said(host: &Entity, cx: &mut VisualTestContext) -> Vec { + host.read_with(cx, |bench, _| bench.said.clone()) +} + +/// Focus on the `stops`th Tab stop from the top. +pub(super) fn tab(stops: usize, cx: &mut VisualTestContext) { + cx.update(|window, cx| { + window.blur(cx); + (0..stops).for_each(|_| window.focus_next(cx)); + }); + settle(cx); +} + +pub(super) fn tap(key: &str, cx: &mut VisualTestContext) { + cx.simulate_keystrokes(key); + cx.simulate_event(gpui::KeyUpEvent { + keystroke: gpui::Keystroke::parse(key).expect("a key"), + }); + settle(cx); +} + +pub(super) fn write(text: &str, cx: &mut VisualTestContext) { + cx.simulate_input(text); + settle(cx); +} + +mod access; +mod billing; +mod sign_in; diff --git a/vendor/ely/src/account/tests/sign_in.rs b/vendor/ely/src/account/tests/sign_in.rs new file mode 100644 index 00000000..1c79c843 --- /dev/null +++ b/vendor/ely/src/account/tests/sign_in.rs @@ -0,0 +1,270 @@ +use gpui::{AnyElement, Entity, IntoElement, TestAppContext}; + +use super::{Bench, bench, said, say, settle, tab, tap, write}; +use crate::account::{ + ForgotPassword, LoginForm, MagicLinkForm, OAuthButtons, SignupForm, TwoFactorInput, +}; + +fn login(_: &Bench, owner: Entity) -> AnyElement { + LoginForm::new("login", move |login, _, cx| { + say( + &owner, + format!("{} {} {}", login.email, login.password, login.remember), + cx, + ) + }) + .on_forgot(|_, _| {}) + .into_any_element() +} + +/// Stops: email, password, its eye, the box, the forgotten password, Sign in. +#[gpui::test] +fn sign_in_waits_for_an_address_and_a_password_and_enter_sends(cx: &mut TestAppContext) { + let (host, cx) = bench(login, cx); + tab(1, cx); + write("ada@example", cx); + tab(2, cx); + write("secret", cx); + tap("enter", cx); + assert!( + said(&host, cx).is_empty(), + "an address without a dot is no address" + ); + tab(1, cx); + write(".com", cx); + tab(4, cx); + tap("space", cx); + tab(2, cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["ada@example.com secret true"]); +} + +fn signup(_: &Bench, owner: Entity) -> AnyElement { + SignupForm::new("signup", move |signup, _, cx| { + say( + &owner, + format!("{} {} {}", signup.name, signup.email, signup.password), + cx, + ) + }) + .terms("I agree to the terms") + .into_any_element() +} + +/// Stops: name, email, password, its eye, the terms, then Create account once it holds. +#[gpui::test] +fn sign_up_waits_for_every_rule_and_the_terms(cx: &mut TestAppContext) { + let (host, cx) = bench(signup, cx); + tab(1, cx); + write("Ada", cx); + tab(2, cx); + write("ada@example.com", cx); + tab(3, cx); + write("abcdefg1", cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty(), "the terms are not yet accepted"); + tab(5, cx); + tap("space", cx); + tab(3, cx); + tap("backspace", cx); + tap("enter", cx); + assert!( + said(&host, cx).is_empty(), + "seven characters and no number meet no rule but one" + ); + write("1", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["Ada ada@example.com abcdefg1"]); +} + +fn providers(bench: &Bench, owner: Entity) -> AnyElement { + let buttons = OAuthButtons::new( + "oauth", + [("github", "GitHub"), ("google", "Google")], + move |key, _, cx| say(&owner, key.to_string(), cx), + ); + match bench.sent { + true => buttons.busy("github").into_any_element(), + false => buttons.into_any_element(), + } +} + +/// Stops: GitHub, Google; while GitHub is on its way, neither. +#[gpui::test] +fn a_provider_hands_its_key_and_rests_while_one_is_on_its_way(cx: &mut TestAppContext) { + let (host, cx) = bench(providers, cx); + tab(2, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["google"]); + host.update(cx, |bench, cx| { + bench.sent = true; + cx.notify(); + }); + settle(cx); + for stop in [1, 2] { + tab(stop, cx); + tap("space", cx); + } + assert_eq!( + said(&host, cx), + ["google"], + "no provider takes a press while one is on its way" + ); +} + +fn magic(bench: &Bench, owner: Entity) -> AnyElement { + let other = owner.clone(); + MagicLinkForm::new("magic", move |address, _, cx| { + say(&owner, format!("send {address}"), cx); + owner.update(cx, |bench, _| bench.sent = true); + }) + .sent(bench.sent) + .on_other(move |_, cx| { + other.update(cx, |bench, cx| { + bench.sent = false; + cx.notify(); + }) + }) + .into_any_element() +} + +/// Stops: email, then the link button; once sent, Send again and Use another email. +#[gpui::test] +fn a_link_goes_to_the_address_and_again_on_request(cx: &mut TestAppContext) { + let (host, cx) = bench(magic, cx); + tab(1, cx); + write("ada@example.com", cx); + tap("enter", cx); + tab(1, cx); + tap("space", cx); + assert_eq!( + said(&host, cx), + ["send ada@example.com", "send ada@example.com"] + ); + tab(2, cx); + tap("space", cx); + assert!( + !host.read_with(cx, |bench, _| bench.sent), + "Use another email goes back to the address" + ); +} + +fn forgot(bench: &Bench, owner: Entity) -> AnyElement { + let back = owner.clone(); + ForgotPassword::new("forgot", move |address, _, cx| { + say(&owner, format!("reset {address}"), cx) + }) + .sent(bench.sent) + .on_back(move |_, cx| say(&back, "back".into(), cx)) + .into_any_element() +} + +/// Stops: email, then Back to sign in while the send rests. +#[gpui::test] +fn a_reset_waits_for_an_address_and_offers_the_way_back(cx: &mut TestAppContext) { + let (host, cx) = bench(forgot, cx); + tab(2, cx); + tap("enter", cx); + assert_eq!( + said(&host, cx), + ["back"], + "with no address the send rests, so the second stop is the way back" + ); +} + +fn factor(bench: &Bench, owner: Entity) -> AnyElement { + TwoFactorInput::new("factor", move |code, _, cx| { + say(&owner, code.to_string(), cx) + }) + .failed(bench.failed) + .into_any_element() +} + +/// Stops: the code. +#[gpui::test] +fn a_failed_code_clears_the_boxes_for_the_next(cx: &mut TestAppContext) { + let (host, cx) = bench(factor, cx); + tab(1, cx); + write("123456", cx); + host.update(cx, |bench, cx| { + bench.failed = 1; + cx.notify(); + }); + settle(cx); + write("654321", cx); + assert_eq!(said(&host, cx), ["123456", "654321"]); +} + +/// Stops: email, password, its eye, the box, Forgot password. +#[gpui::test] +fn sign_in_waits_for_a_password(cx: &mut TestAppContext) { + let (host, cx) = bench(login, cx); + tab(1, cx); + write("ada@example.com", cx); + tap("enter", cx); + assert!( + said(&host, cx).is_empty(), + "an address alone signs nobody in" + ); +} + +fn busy_login(_: &Bench, owner: Entity) -> AnyElement { + LoginForm::new("login", move |login, _, cx| { + say(&owner, login.email.to_string(), cx) + }) + .busy(true) + .into_any_element() +} + +/// Stops: email, password, its eye, the box; Sign in rests while busy, so a fifth Tab wraps to the email. +#[gpui::test] +fn sign_in_rests_while_busy(cx: &mut TestAppContext) { + let (host, cx) = bench(busy_login, cx); + tab(1, cx); + write("ada@example.com", cx); + tab(2, cx); + write("secret", cx); + tap("enter", cx); + tab(5, cx); + tap("space", cx); + assert!(said(&host, cx).is_empty()); +} + +/// Stops: name, email, password, its eye, the terms. +#[gpui::test] +fn sign_up_waits_for_a_name(cx: &mut TestAppContext) { + let (host, cx) = bench(signup, cx); + tab(2, cx); + write("ada@example.com", cx); + tab(3, cx); + write("abcdefg1", cx); + tab(5, cx); + tap("space", cx); + tab(3, cx); + tap("enter", cx); + assert!(said(&host, cx).is_empty(), "no name, no account"); + tab(1, cx); + write("Ada", cx); + tap("enter", cx); + assert_eq!(said(&host, cx), ["Ada ada@example.com abcdefg1"]); +} + +fn busy_sent(_: &Bench, owner: Entity) -> AnyElement { + let other = owner.clone(); + MagicLinkForm::new("magic", move |address, _, cx| { + say(&owner, format!("send {address}"), cx) + }) + .sent(true) + .busy(true) + .on_other(move |_, cx| say(&other, "other".into(), cx)) + .into_any_element() +} + +/// While a link is on its way Send again rests, so the first stop is Use another email. +#[gpui::test] +fn send_again_rests_while_busy(cx: &mut TestAppContext) { + let (host, cx) = bench(busy_sent, cx); + tab(1, cx); + tap("space", cx); + assert_eq!(said(&host, cx), ["other"]); +} diff --git a/vendor/ely/src/account/upgrade.rs b/vendor/ely/src/account/upgrade.rs new file mode 100644 index 00000000..2ec239b2 --- /dev/null +++ b/vendor/ely/src/account/upgrade.rs @@ -0,0 +1,140 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, FontWeight, InteractiveElement, IntoElement, ParentElement, RenderOnce, + SharedString, Styled, Window, div, +}; + +use super::login::Run; +use crate::{ + buttons::{Button, ButtonVariant}, + layout::Card, + primitives::{Icon, IconName}, + theme::{ActiveTheme, IconSize, TextSize}, +}; + +/// A way past a limit: why, what the next plan brings, and Upgrade. With benefits it stands as a paywall; without, as one line. +#[derive(IntoElement)] +pub struct UpgradePrompt { + id: ElementId, + title: SharedString, + body: Option, + benefits: Vec, + on_upgrade: Run, + on_dismiss: Option, +} + +impl UpgradePrompt { + pub fn new( + id: impl Into, + title: impl Into, + on_upgrade: impl Fn(&mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + title: title.into(), + body: None, + benefits: Vec::new(), + on_upgrade: Rc::new(on_upgrade), + on_dismiss: None, + } + } + + pub fn body(mut self, body: impl Into) -> Self { + self.body = Some(body.into()); + self + } + + /// Something the next plan brings; any makes this a paywall. + pub fn benefit(mut self, benefit: impl Into) -> Self { + self.benefits.push(benefit.into()); + self + } + + /// Shows "Not now". + pub fn on_dismiss(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_dismiss = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for UpgradePrompt { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let id = self.id; + let upgrade = self.on_upgrade; + let theme = cx.theme(); + let wall = !self.benefits.is_empty(); + let actions = div() + .flex() + .flex_wrap() + .gap_2() + .child( + Button::new((id.clone(), "upgrade"), "Upgrade") + .variant(ButtonVariant::Primary) + .on_click(move |_, window, cx| { + log::info!("upgrade prompt: upgrade"); + upgrade(window, cx); + }), + ) + .children(self.on_dismiss.map(|run| { + Button::new((id.clone(), "dismiss"), "Not now") + .variant(ButtonVariant::Ghost) + .on_click(move |_, window, cx| run(window, cx)) + })); + let words = div() + .flex_1() + .min_w(theme.label_width()) + .child(div().font_weight(FontWeight::SEMIBOLD).child(self.title)) + .children( + self.body + .map(|body| div().text_color(theme.colors.fg_muted).child(body)), + ); + let benefits = self.benefits.into_iter().map(|benefit| { + div() + .flex() + .items_center() + .gap_2() + .child( + Icon::new(IconName::Check) + .size(IconSize::Sm) + .color(theme.colors.success), + ) + .child(div().flex_1().min_w_0().child(benefit)) + }); + let body = match wall { + true => div() + .flex() + .flex_col() + .gap_4() + .child( + div() + .flex() + .items_start() + .gap_3() + .child( + Icon::new(IconName::Lock) + .size(IconSize::Md) + .color(theme.colors.fg_muted), + ) + .child(words), + ) + .child( + div() + .debug_selector(|| "paywall-benefits".into()) + .flex() + .flex_col() + .gap_1p5() + .children(benefits), + ) + .child(actions), + false => div() + .flex() + .flex_wrap() + .items_center() + .gap_3() + .child(words) + .child(actions), + }; + Card::new().child(div().text_size(theme.text_size(TextSize::Sm)).child(body)) + } +} diff --git a/vendor/ely/src/agent/artifact.rs b/vendor/ely/src/agent/artifact.rs new file mode 100644 index 00000000..55a9ff7d --- /dev/null +++ b/vendor/ely/src/agent/artifact.rs @@ -0,0 +1,202 @@ +use std::rc::Rc; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, InteractiveElement, IntoElement, ParentElement, + RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window, div, prelude::*, +}; + +use crate::{ + buttons::{ButtonVariant, IconButton, SegmentedControl}, + chat::BranchNavigator, + forms::{Pick, Run}, + primitives::{Icon, IconName}, + theme::{ActiveTheme, ControlSize, IconSize, Radius, TextSize}, + typography::Ellipsis, +}; + +/// What an agent made, in a panel of its own: its title, the version shown among all, copy and download, and the artifact, as preview or source when it has both. +#[derive(IntoElement)] +pub struct ArtifactPanel { + id: ElementId, + title: SharedString, + icon: IconName, + preview: Option, + source: Option, + version: Option<(usize, usize, Pick)>, + on_copy: Option, + on_download: Option, +} + +impl ArtifactPanel { + pub fn new(id: impl Into, title: impl Into, icon: IconName) -> Self { + Self { + id: id.into(), + title: title.into(), + icon, + preview: None, + source: None, + version: None, + on_copy: None, + on_download: None, + } + } + + /// The artifact as it shows, such as a page or a document. + pub fn preview(mut self, element: impl IntoElement) -> Self { + self.preview = Some(element.into_any_element()); + self + } + + /// The artifact as written, its code or markup. + pub fn source(mut self, element: impl IntoElement) -> Self { + self.source = Some(element.into_any_element()); + self + } + + /// The version shown, of all; `on_version` gets the one asked for. + pub fn version( + mut self, + current: usize, + total: usize, + on_version: impl Fn(usize, &mut Window, &mut App) + 'static, + ) -> Self { + self.version = Some((current, total, Rc::new(on_version))); + self + } + + pub fn on_copy(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_copy = Some(Rc::new(handler)); + self + } + + pub fn on_download(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_download = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for ArtifactPanel { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + assert!( + self.preview.is_some() || self.source.is_some(), + "artifact {:?} shows neither preview nor source", + self.id + ); + let reading = window.use_keyed_state((self.id.clone(), "source"), cx, |_, _| false); + let both = self.preview.is_some() && self.source.is_some(); + let showing_source = self.preview.is_none() || (both && *reading.read(cx)); + let theme = cx.theme(); + let colors = theme.colors.clone(); + let action = |key: &'static str, icon: IconName, tip: &'static str, run: Run| { + IconButton::new((self.id.clone(), key), icon) + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .tooltip(tip) + .on_click(move |_, window, cx| { + log::info!("artifact: {tip}"); + run(window, cx) + }) + }; + let view = both.then(|| { + SegmentedControl::new( + (self.id.clone(), "view"), + if showing_source { "source" } else { "preview" }, + ) + .size(ControlSize::Sm) + .segment("preview", "Preview", Some(IconName::Eye)) + .segment("source", "Source", Some(IconName::Code)) + .on_change(move |key, _, cx| { + let source = key.as_ref() == "source"; + log::info!("artifact: shows {key}"); + reading.update(cx, |reading, cx| { + *reading = source; + cx.notify(); + }) + }) + }); + let version = self.version.map(|(current, total, pick)| { + BranchNavigator::new( + (self.id.clone(), "versions"), + current, + total, + move |to, window, cx| pick(to, window, cx), + ) + .into_any_element() + }); + let copy = (self.on_copy) + .map(|copy| action("copy", IconName::Copy, "Copy", copy).into_any_element()); + let save = (self.on_download).map(|save| { + action("download", IconName::Download, "Download", save).into_any_element() + }); + let controls: Vec = + [version, view.map(IntoElement::into_any_element), copy, save] + .into_iter() + .flatten() + .collect(); + let body = if showing_source { + self.source + } else { + self.preview + }; + div() + .size_full() + .flex() + .flex_col() + .rounded(theme.radius(Radius::Lg)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .child( + div() + .flex_none() + .flex() + .flex_wrap() + .items_center() + .gap_x_2() + .gap_y_1() + .px_3() + .py_2() + .border_b_1() + .border_color(colors.border) + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .flex() + .items_center() + .gap_2() + .child( + Icon::new(self.icon) + .size(IconSize::Sm) + .color(colors.fg_muted), + ) + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .child(Ellipsis::new(self.title)), + ), + ) + .when(!controls.is_empty(), |header| { + header.child( + div() + .flex() + .flex_wrap() + .items_center() + .gap_1() + .children(controls), + ) + }), + ) + .child( + div() + .id((self.id.clone(), "body")) + .flex_1() + .min_h_0() + .overflow_y_scroll() + .children(body), + ) + } +} diff --git a/vendor/ely/src/agent/changes.rs b/vendor/ely/src/agent/changes.rs new file mode 100644 index 00000000..380392e3 --- /dev/null +++ b/vendor/ely/src/agent/changes.rs @@ -0,0 +1,319 @@ +use std::rc::Rc; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, InteractiveElement, IntoElement, MouseButton, + ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window, div, + prelude::*, transparent_black, +}; + +use crate::{ + buttons::{Button, ButtonVariant}, + collab::Decision, + forms::OnFlag, + git::{DiffStat, DiffViewer, stat}, + primitives::{Disclosure, FocusRing, Icon, IconName, file_icon}, + theme::{ActiveTheme, ControlSize, IconSize, Radius, TextSize}, + typography::Ellipsis, +}; + +/// Where a proposed change stands. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ChangeState { + Proposed, + Accepted, + Rejected, +} + +/// A change an agent proposes to one file: its path, the text before and after, and where it stands. +#[derive(Clone, Debug, PartialEq)] +pub struct FileChange { + pub path: SharedString, + pub old: SharedString, + pub new: SharedString, + pub state: ChangeState, +} + +type OnDecision = Rc; + +/// Reject and Accept while the change is proposed; after, a quiet word for how it ended. +fn verdict(id: &ElementId, state: ChangeState, on_decide: Option, cx: &App) -> AnyElement { + let colors = &cx.theme().colors; + let said = |icon: IconName, word: &'static str, color| { + div() + .flex() + .items_center() + .gap_1() + .text_color(color) + .child(Icon::new(icon).size(IconSize::Xs).color(color)) + .child(word) + .into_any_element() + }; + match (state, on_decide) { + (ChangeState::Proposed, Some(decide)) => { + let (reject, accept) = (decide.clone(), decide); + div() + .flex() + .items_center() + .gap_1() + .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation()) + .child( + Button::new((id.clone(), "reject"), "Reject") + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| reject(false, window, cx)), + ) + .child( + Button::new((id.clone(), "accept"), "Accept") + .variant(ButtonVariant::Secondary) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| accept(true, window, cx)), + ) + .into_any_element() + } + (ChangeState::Proposed, None) => said(IconName::Clock, "Proposed", colors.fg_subtle), + (ChangeState::Accepted, _) => said(IconName::Check, "Accepted", colors.success), + (ChangeState::Rejected, _) => said(IconName::X, "Rejected", colors.fg_subtle), + } +} + +/// One file an agent would change: its path and how much moves, Reject or Accept while proposed; opened, the diff. +#[derive(IntoElement)] +pub struct FileChangeCard { + id: ElementId, + change: FileChange, + on_decide: Option, +} + +impl FileChangeCard { + pub fn new(id: impl Into, change: FileChange) -> Self { + Self { + id: id.into(), + change, + on_decide: None, + } + } + + /// `on_decide` gets true to accept, false to reject. + pub fn on_decide(mut self, handler: impl Fn(bool, &mut Window, &mut App) + 'static) -> Self { + self.on_decide = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for FileChangeCard { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let state = window.use_keyed_state((self.id.clone(), "open"), cx, |_, _| false); + let folds = window.use_keyed_state((self.id.clone(), "folds"), cx, |_, _| Vec::new()); + let (open, unfolded) = (*state.read(cx), folds.read(cx).clone()); + let (added, removed) = stat(&self.change.old, &self.change.new); + let path = self.change.path.clone(); + let decide = self.on_decide.map(|decide| -> OnFlag { + Rc::new(move |accepted, window, cx| { + log::info!( + "file change {path}: {}", + if accepted { "accepted" } else { "rejected" } + ); + decide(accepted, window, cx) + }) + }); + let theme = cx.theme(); + let colors = theme.colors.clone(); + div() + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .id((self.id.clone(), "header")) + .flex() + .flex_wrap() + .items_center() + .gap_2() + .px_2() + .py_1p5() + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(transparent_black()) + .tab_index(0) + .focus_ring(cx) + .cursor_pointer() + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .on_click(move |_, _, cx| { + state.update(cx, |open, cx| { + *open = !*open; + log::info!("file change: open {open}"); + cx.notify(); + }) + }) + .child(Disclosure::new((self.id.clone(), "chevron"), open).size(IconSize::Sm)) + .child( + Icon::new(file_icon(&self.change.path, cx)) + .size(IconSize::Sm) + .color(colors.fg_muted), + ) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .font_family(theme.mono_family.clone()) + .child(Ellipsis::new(self.change.path.clone())), + ) + .child( + div() + .flex_none() + .ml_auto() + .flex() + .items_center() + .gap_2() + .child(DiffStat::new(added, removed)) + .child(verdict(&self.id, self.change.state, decide, cx)), + ), + ) + .when(open, |card| { + card.child( + div() + .h(theme.list_max_height()) + .border_t_1() + .border_color(colors.border) + .child( + DiffViewer::new( + (self.id.clone(), "diff"), + self.change.path, + &self.change.old, + &self.change.new, + ) + .headless() + .open(unfolded) + .on_open(move |ix, _, cx| { + folds.update(cx, |folds: &mut Vec, cx| { + folds.push(ix); + cx.notify(); + }) + }), + ), + ) + }) + } +} + +/// Every file an agent would change, reviewed together: how many and how much, all at once or a card each. +#[derive(IntoElement)] +pub struct MultiFileDiffReview { + id: ElementId, + changes: Vec, + on_decide: Option, +} + +impl MultiFileDiffReview { + pub fn new(id: impl Into, changes: impl IntoIterator) -> Self { + Self { + id: id.into(), + changes: changes.into_iter().collect(), + on_decide: None, + } + } + + /// `on_decide` gets one file's verdict, by index, or all of them. + pub fn on_decide( + mut self, + handler: impl Fn(Decision, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_decide = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for MultiFileDiffReview { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let (added, removed) = self + .changes + .iter() + .fold((0, 0), |(added, removed), change| { + let (more, less) = stat(&change.old, &change.new); + (added + more, removed + less) + }); + let open = self + .changes + .iter() + .filter(|change| change.state == ChangeState::Proposed) + .count(); + let count = self.changes.len(); + let all = self.on_decide.clone().filter(|_| open > 0).map(|decide| { + let (reject, accept) = (decide.clone(), decide); + div() + .flex_none() + .flex() + .items_center() + .gap_1() + .child( + Button::new((self.id.clone(), "reject-all"), "Reject all") + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("file changes: reject all"); + reject(Decision::RejectAll, window, cx) + }), + ) + .child( + Button::new((self.id.clone(), "accept-all"), "Accept all") + .variant(ButtonVariant::Primary) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("file changes: accept all"); + accept(Decision::AcceptAll, window, cx) + }), + ) + }); + div() + .flex() + .flex_col() + .gap_2() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .flex_wrap() + .items_center() + .justify_between() + .gap_y_2() + .child( + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_3() + .gap_y_1() + .child( + div() + .font_weight(FontWeight::MEDIUM) + .child(format!("{count} files changed")), + ) + .child(DiffStat::new(added, removed)) + .child( + div() + .text_color(colors.fg_subtle) + .child(format!("{} of {count} reviewed", count - open)), + ), + ) + .children(all), + ) + .children(self.changes.into_iter().enumerate().map(|(ix, change)| { + let card = FileChangeCard::new((self.id.clone(), format!("file-{ix}")), change); + match self.on_decide.clone() { + Some(decide) => card.on_decide(move |accepted, window, cx| { + let decision = if accepted { + Decision::Accept(ix) + } else { + Decision::Reject(ix) + }; + decide(decision, window, cx) + }), + None => card, + } + })) + } +} diff --git a/vendor/ely/src/agent/control.rs b/vendor/ely/src/agent/control.rs new file mode 100644 index 00000000..8c18f224 --- /dev/null +++ b/vendor/ely/src/agent/control.rs @@ -0,0 +1,201 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, Entity, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, +}; + +use super::line::{OnText, send_line}; +use crate::{ + buttons::{Button, ButtonVariant}, + data_display::UsageBar, + forms::TextInput, + primitives::{Icon, IconName}, + theme::{ActiveTheme, ControlSize, IconSize, Radius, TextSize}, + typography::{format::currency, tabular}, +}; + +/// A question an agent waits on: a few answers to pick, a line to write one, and, once answered, the answer. +#[derive(IntoElement)] +pub struct HumanInputRequest { + id: ElementId, + question: SharedString, + field: Entity, + choices: Vec, + answered: Option, + on_answer: OnText, +} + +impl HumanInputRequest { + /// `field` is the owner's line for a written answer. + pub fn new( + id: impl Into, + question: impl Into, + field: &Entity, + on_answer: impl Fn(&str, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + question: question.into(), + field: field.clone(), + choices: Vec::new(), + answered: None, + on_answer: Rc::new(on_answer), + } + } + + /// Answers to pick with a press. + pub fn choices(mut self, choices: impl IntoIterator>) -> Self { + self.choices = choices.into_iter().map(Into::into).collect(); + self + } + + /// The answer given; the request stops asking. + pub fn answered(mut self, answer: impl Into) -> Self { + self.answered = Some(answer.into()); + self + } +} + +impl RenderOnce for HumanInputRequest { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let asking = self.answered.is_none(); + let choices = (asking && !self.choices.is_empty()).then(|| { + div() + .flex() + .flex_wrap() + .gap_2() + .children(self.choices.iter().enumerate().map(|(ix, choice)| { + let (answer, picked) = (self.on_answer.clone(), choice.clone()); + Button::new((self.id.clone(), format!("choice-{ix}")), choice.clone()) + .variant(ButtonVariant::Secondary) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + log::info!("human input: picked {ix}"); + answer(&picked, window, cx) + }) + })) + }); + let line = asking.then(|| { + send_line( + &self.field, + Button::new((self.id.clone(), "reply"), "Reply").variant(ButtonVariant::Primary), + self.on_answer.clone(), + "human input", + cx, + ) + }); + let theme = cx.theme(); + let colors = theme.colors.clone(); + div() + .flex() + .flex_col() + .gap_3() + .p_4() + .rounded(theme.radius(Radius::Lg)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_start() + .gap_2() + .child( + div().flex_none().child( + Icon::new(IconName::CircleHelp) + .size(IconSize::Sm) + .color(colors.fg_muted), + ), + ) + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .text_color(colors.fg) + .child(self.question), + ), + ) + .children(self.answered.map(|answer| { + div() + .flex() + .items_start() + .gap_2() + .text_color(colors.fg_muted) + .child( + div().flex_none().child( + Icon::new(IconName::Check) + .size(IconSize::Sm) + .color(colors.success), + ), + ) + .child(div().flex_1().min_w_0().child(answer)) + })) + .children(choices) + .children(line) + } +} + +/// What a session cost, as a whole and part by part: the total, then a bar of each part's share with its amount. +#[derive(IntoElement)] +pub struct CostBreakdown { + label: SharedString, + code: &'static str, + parts: Vec<(SharedString, f64)>, +} + +impl CostBreakdown { + /// `code` is the currency, such as "USD". + pub fn new(label: impl Into, code: &'static str) -> Self { + Self { + label: label.into(), + code, + parts: Vec::new(), + } + } + + pub fn part(mut self, name: impl Into, cost: f64) -> Self { + assert!(cost >= 0.0 && cost.is_finite(), "a cost of {cost}"); + self.parts.push((name.into(), cost)); + self + } +} + +impl RenderOnce for CostBreakdown { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let total: f64 = self.parts.iter().map(|(_, cost)| cost).sum(); + let code = self.code; + let bar = (total > 0.0).then(|| { + self.parts.into_iter().fold( + UsageBar::new(total).amounts(move |amount| currency(amount, code)), + |bar, (name, cost)| bar.part(name, cost), + ) + }); + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .flex_wrap() + .items_baseline() + .justify_between() + .gap_x_3() + .child(div().text_color(colors.fg_muted).child(self.label)) + .child( + tabular(div()) + .text_size(theme.text_size(TextSize::Lg)) + .font_weight(FontWeight::SEMIBOLD) + .text_color(colors.fg) + .child(currency(total, code)), + ), + ) + .children(bar) + } +} diff --git a/vendor/ely/src/agent/environment.rs b/vendor/ely/src/agent/environment.rs new file mode 100644 index 00000000..cd09b480 --- /dev/null +++ b/vendor/ely/src/agent/environment.rs @@ -0,0 +1,293 @@ +use std::{rc::Rc, time::Duration}; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, Hsla, IntoElement, ParentElement, RenderOnce, + SharedString, Styled, Window, div, prelude::*, +}; + +use crate::{ + data_display::Meter, + forms::Switch, + lists::{List, ListItem}, + motion::Pulse, + theme::{ActiveTheme, IconSize, Palette, Radius, TextSize}, + typography::{ + Ellipsis, + format::{DurationStyle, duration, file_size, plural}, + }, +}; + +/// A dot in `color`, ringing while `live`. +fn dot(id: ElementId, color: Hsla, live: bool, cx: &App) -> AnyElement { + let mark = div() + .flex_none() + .size(cx.theme().status_dot()) + .rounded_full() + .bg(color); + if live { + Pulse::new(id).child(mark).into_any_element() + } else { + mark.into_any_element() + } +} + +/// Where a sandbox stands. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum SandboxState { + Starting, + Ready, + Busy, + Stopped, + Failed, +} + +impl SandboxState { + fn word(self) -> &'static str { + match self { + Self::Starting => "Starting", + Self::Ready => "Ready", + Self::Busy => "Busy", + Self::Stopped => "Stopped", + Self::Failed => "Failed", + } + } + + fn color(self, colors: &Palette) -> Hsla { + match self { + Self::Starting => colors.warning, + Self::Busy => colors.info, + Self::Ready => colors.success, + Self::Stopped => colors.fg_subtle, + Self::Failed => colors.danger, + } + } +} + +/// Where an agent's sandbox stands: its name, a dot and a word, what it uses of what it has, and how long it has run. +#[derive(IntoElement)] +pub struct SandboxStatus { + id: ElementId, + name: SharedString, + state: SandboxState, + cpu: Option, + memory: Option<(u64, u64)>, + uptime: Option, +} + +impl SandboxStatus { + pub fn new( + id: impl Into, + name: impl Into, + state: SandboxState, + ) -> Self { + Self { + id: id.into(), + name: name.into(), + state, + cpu: None, + memory: None, + uptime: None, + } + } + + /// The share of its processors in use, 0 to 1. + pub fn cpu(mut self, share: f32) -> Self { + assert!((0.0..=1.0).contains(&share), "cpu {share} of 1"); + self.cpu = Some(share); + self + } + + /// Memory in use and its limit, in bytes. + pub fn memory(mut self, used: u64, limit: u64) -> Self { + assert!(limit > 0, "memory {used} of no limit"); + if used > limit { + log::error!("environment: memory {used} past its limit {limit}; the meter fills"); + } + self.memory = Some((used, limit)); + self + } + + pub fn uptime(mut self, uptime: Duration) -> Self { + self.uptime = Some(uptime); + self + } +} + +impl RenderOnce for SandboxStatus { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let live = matches!(self.state, SandboxState::Starting | SandboxState::Busy); + let color = self.state.color(&colors); + div() + .flex() + .flex_col() + .gap_3() + .p_4() + .rounded(theme.radius(Radius::Lg)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_2() + .gap_y_1() + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .flex() + .items_center() + .gap_2() + .child(dot((self.id.clone(), "state").into(), color, live, cx)) + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .child(Ellipsis::new(self.name)), + ), + ) + .child( + div() + .flex_none() + .flex() + .items_center() + .gap_2() + .text_color(colors.fg_muted) + .child(self.state.word()) + .children(self.uptime.map(|up| { + div().text_color(colors.fg_subtle).child(format!( + "up {}", + duration(up.as_secs(), DurationStyle::Compact) + )) + })), + ), + ) + .children( + self.cpu + .map(|share| Meter::new((self.id.clone(), "cpu"), "Processors", share)), + ) + .children(self.memory.map(|(used, limit)| { + Meter::new( + (self.id.clone(), "memory"), + "Memory", + used.min(limit) as f32 / limit as f32, + ) + .detail(format!( + "{} of {}", + file_size(used, true), + file_size(limit, true) + )) + })) + } +} + +/// Where a connected server stands. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ServerState { + Connected, + Connecting, + Failed, + Off, +} + +/// A server or connector the agent can reach: its key and name, where it runs or why it failed, where it stands and how many tools it brings. +#[derive(Clone, Debug, PartialEq)] +pub struct McpServer { + pub key: SharedString, + pub name: SharedString, + pub detail: SharedString, + pub state: ServerState, + pub tools: usize, +} + +type OnToggle = Rc; + +/// Servers and connectors the agent can reach: each with a dot for where it stands, what it runs or why it failed, how many tools it brings, and a switch. +#[derive(IntoElement)] +pub struct McpServerList { + id: ElementId, + servers: Vec, + on_toggle: Option, +} + +impl McpServerList { + pub fn new(id: impl Into, servers: impl IntoIterator) -> Self { + Self { + id: id.into(), + servers: servers.into_iter().collect(), + on_toggle: None, + } + } + + /// Gets a server's key and whether it is now on. + pub fn on_toggle( + mut self, + handler: impl Fn(&SharedString, bool, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_toggle = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for McpServerList { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let colors = cx.theme().colors.clone(); + List::new() + .divided() + .children(self.servers.into_iter().map(|server| { + let (color, live) = match server.state { + ServerState::Connected => (colors.success, false), + ServerState::Connecting => (colors.warning, true), + ServerState::Failed => (colors.danger, false), + ServerState::Off => (colors.fg_subtle, false), + }; + let toggle = self.on_toggle.clone().map(|toggle| { + let key = server.key.clone(); + Switch::new( + (self.id.clone(), format!("switch-{}", server.key)), + server.state != ServerState::Off, + ) + .on_change(move |on, window, cx| { + log::info!("mcp server {key}: {}", if on { "on" } else { "off" }); + toggle(&key, on, window, cx) + }) + }); + ListItem::new( + (self.id.clone(), format!("server-{}", server.key)), + server.name, + ) + .description(server.detail) + .leading( + div() + .size(cx.theme().icon_size(IconSize::Sm)) + .flex() + .items_center() + .justify_center() + .child(dot( + (self.id.clone(), format!("dot-{}", server.key)).into(), + color, + live, + cx, + )), + ) + .trailing( + div() + .flex() + .items_center() + .gap_3() + .text_size(cx.theme().text_size(TextSize::Xs)) + .text_color(colors.fg_subtle) + .when(server.state == ServerState::Connected, |end| { + end.child(plural(server.tools as u64, "tool", "tools")) + }) + .children(toggle), + ) + })) + } +} diff --git a/vendor/ely/src/agent/line.rs b/vendor/ely/src/agent/line.rs new file mode 100644 index 00000000..72a1c2ac --- /dev/null +++ b/vendor/ely/src/agent/line.rs @@ -0,0 +1,58 @@ +use std::rc::Rc; + +use gpui::{App, Div, Entity, InteractiveElement, ParentElement, Styled, Window, div}; + +use crate::{ + buttons::Button, + forms::{Enter, Input, TextInput}, +}; + +pub(super) type OnText = Rc; + +/// Hands the field's words to `send` and empties it; blank words are kept out. +fn send( + field: &Entity, + on_send: &OnText, + what: &str, + window: &mut Window, + cx: &mut App, +) { + let text = field.read(cx).text().trim().to_string(); + if text.is_empty() { + return; + } + log::info!("{what}: sent {} characters", text.len()); + on_send(&text, window, cx); + field.update(cx, |input, cx| input.set_text("", cx)); +} + +/// The owner's field beside `button`: Enter or a press sends its words, and the button waits for some. +pub(super) fn send_line( + field: &Entity, + button: Button, + on_send: OnText, + what: &'static str, + cx: &App, +) -> Div { + let ready = !field.read(cx).text().trim().is_empty(); + let (typed, pressed, enter) = (field.clone(), field.clone(), on_send.clone()); + div() + .flex() + .items_center() + .gap_2() + .child( + div() + .flex_1() + .min_w_0() + .capture_action(move |_: &Enter, window, cx| { + cx.stop_propagation(); + send(&typed, &enter, what, window, cx) + }) + .child(Input::new(field)), + ) + .child( + button + .disabled(!ready) + .on_click(move |_, window, cx| send(&pressed, &on_send, what, window, cx)), + ) +} diff --git a/vendor/ely/src/agent/memory.rs b/vendor/ely/src/agent/memory.rs new file mode 100644 index 00000000..fae4bb9d --- /dev/null +++ b/vendor/ely/src/agent/memory.rs @@ -0,0 +1,250 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, Entity, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, prelude::*, +}; +use jiff::Timestamp; + +use super::line::{OnText, send_line}; +use crate::{ + buttons::{Button, ButtonVariant, IconButton}, + data_display::{Timeline, TimelineItem, Tone}, + forms::{Pick, TextInput}, + primitives::IconName, + theme::{ActiveTheme, ControlSize, TextSize}, + typography::{RelativeTime, format::plural}, +}; + +/// Something an agent keeps between conversations: its key and words, where it came from, and when. +#[derive(Clone, Debug, PartialEq)] +pub struct Memory { + pub key: SharedString, + pub text: SharedString, + pub source: Option, + pub at: Timestamp, +} + +type OnForget = Rc; + +/// What an agent keeps between conversations: a field to add a memory, then each one with where it came from, when, and a way to forget it. +#[derive(IntoElement)] +pub struct MemoryPanel { + id: ElementId, + field: Entity, + memories: Vec, + on_add: Option, + on_forget: Option, +} + +impl MemoryPanel { + /// `field` is the owner's line for a new memory. + pub fn new( + id: impl Into, + field: &Entity, + memories: impl IntoIterator, + ) -> Self { + Self { + id: id.into(), + field: field.clone(), + memories: memories.into_iter().collect(), + on_add: None, + on_forget: None, + } + } + + /// Gets the words to keep; the field empties after. + pub fn on_add(mut self, handler: impl Fn(&str, &mut Window, &mut App) + 'static) -> Self { + self.on_add = Some(Rc::new(handler)); + self + } + + /// Gets the key of the memory to forget. + pub fn on_forget( + mut self, + handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_forget = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for MemoryPanel { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let count = self.memories.len(); + let adding = self.on_add.map(|add| { + send_line( + &self.field, + Button::new((self.id.clone(), "add"), "Remember").variant(ButtonVariant::Secondary), + add, + "memory", + cx, + ) + }); + div() + .flex() + .flex_col() + .gap_3() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_center() + .justify_between() + .child(div().font_weight(FontWeight::MEDIUM).child("Memory")) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(colors.fg_subtle) + .child(plural(count as u64, "memory", "memories")), + ), + ) + .children(adding) + .when(count == 0, |panel| { + panel.child(div().text_color(colors.fg_subtle).child("Nothing kept yet")) + }) + .children(self.memories.into_iter().map(|memory| { + let forget = self.on_forget.clone().map(|forget| { + let key = memory.key.clone(); + IconButton::new( + (self.id.clone(), format!("forget-{}", memory.key)), + IconName::Trash2, + ) + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .tooltip("Forget") + .on_click(move |_, window, cx| { + log::info!("memory: forget {key}"); + forget(&key, window, cx) + }) + }); + div() + .flex() + .items_start() + .gap_2() + .py_2() + .border_t_1() + .border_color(colors.border) + .child( + div() + .flex_1() + .min_w_0() + .child(div().text_color(colors.fg).child(memory.text)) + .child( + div() + .mt_0p5() + .flex() + .flex_wrap() + .gap_x_1() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(colors.fg_subtle) + .children(memory.source.map(|source| format!("{source} ·"))) + .child(RelativeTime::new( + (self.id.clone(), format!("when-{}", memory.key)), + memory.at, + )), + ), + ) + .children(forget.map(|button| div().flex_none().child(button))) + })) + } +} + +/// A point an agent can go back to: its key, what it had done, when, and how many files it had touched. +#[derive(Clone, Debug, PartialEq)] +pub struct Checkpoint { + pub key: SharedString, + pub label: SharedString, + pub at: Timestamp, + pub files: usize, +} + +/// Points an agent can go back to, newest first: each with what it had done, when and how many files it had touched; the one it stands on marked, Rewind on the rest. +#[derive(IntoElement)] +pub struct CheckpointList { + id: ElementId, + checkpoints: Vec, + current: Option, + on_rewind: Option, +} + +impl CheckpointList { + /// `checkpoints` oldest first; `current` indexes the one the agent stands on. + pub fn new( + id: impl Into, + checkpoints: impl IntoIterator, + current: usize, + ) -> Self { + let checkpoints: Vec = checkpoints.into_iter().collect(); + let held = current < checkpoints.len(); + if !held { + log::error!( + "checkpoints: checkpoint {current} of {}; none current", + checkpoints.len() + ); + } + Self { + id: id.into(), + checkpoints, + current: held.then_some(current), + on_rewind: None, + } + } + + /// Gets the index of the checkpoint to go back to. + pub fn on_rewind(mut self, handler: impl Fn(usize, &mut Window, &mut App) + 'static) -> Self { + self.on_rewind = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for CheckpointList { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let colors = cx.theme().colors.clone(); + let current = self.current; + let items: Vec<(usize, Checkpoint)> = + self.checkpoints.into_iter().enumerate().rev().collect(); + items + .into_iter() + .fold(Timeline::new(), |timeline, (ix, point)| { + let rewind = self + .on_rewind + .clone() + .filter(|_| current != Some(ix)) + .map(|rewind| { + Button::new((self.id.clone(), format!("rewind-{ix}")), "Rewind to here") + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .icon(IconName::RotateCcw) + .on_click(move |_, window, cx| { + log::info!("checkpoints: rewind to {ix}"); + rewind(ix, window, cx) + }) + }); + let item = TimelineItem::new(point.label) + .time(RelativeTime::new( + (self.id.clone(), format!("when-{ix}")), + point.at, + )) + .child( + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_2() + .child(plural(point.files as u64, "file", "files")) + .when(current == Some(ix), |meta| { + meta.child(div().text_color(colors.accent).child("Here now")) + }) + .children(rewind), + ); + timeline.item(if current == Some(ix) { + item.tone(Tone::Accent) + } else { + item + }) + }) + } +} diff --git a/vendor/ely/src/agent/mod.rs b/vendor/ely/src/agent/mod.rs new file mode 100644 index 00000000..f954fbfe --- /dev/null +++ b/vendor/ely/src/agent/mod.rs @@ -0,0 +1,24 @@ +mod artifact; +mod changes; +mod control; +mod environment; +mod line; +mod memory; +mod permission; +mod previews; +mod progress; +mod registry; +#[cfg(all(test, feature = "test-support"))] +mod tests; +mod tools; + +pub use artifact::ArtifactPanel; +pub use changes::{ChangeState, FileChange, FileChangeCard, MultiFileDiffReview}; +pub use control::{CostBreakdown, HumanInputRequest}; +pub use environment::{McpServer, McpServerList, SandboxState, SandboxStatus, ServerState}; +pub use memory::{Checkpoint, CheckpointList, Memory, MemoryPanel}; +pub use permission::{Permission, PermissionPrompt, ToolApprovalDialog}; +pub use previews::{BrowserPreview, ComputerUseViewer, LivePreview}; +pub use progress::{AgentPlan, AgentProgress, AgentState, AgentStatus, AgentStep, AgentStepList}; +pub use registry::{RegisteredTool, ToolAccess, ToolRegistry}; +pub use tools::{ToolCallCard, ToolCallGroup}; diff --git a/vendor/ely/src/agent/permission.rs b/vendor/ely/src/agent/permission.rs new file mode 100644 index 00000000..a11b2c61 --- /dev/null +++ b/vendor/ely/src/agent/permission.rs @@ -0,0 +1,208 @@ +use std::{cell::Cell, rc::Rc}; + +use gpui::{ + App, ElementId, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, Styled, + Window, div, prelude::*, +}; + +use crate::{ + buttons::{Button, ButtonVariant}, + chat::CodeBlock, + forms::OnFlag, + overlays::Dialog, + primitives::{Icon, IconName}, + theme::{ActiveTheme, IconSize, Radius, TextSize}, +}; + +/// Asks before a tool runs: what it will do and its arguments, then Deny or Run. Escape, the scrim and Deny refuse it. Render it while the call waits. +#[derive(IntoElement)] +pub struct ToolApprovalDialog { + id: ElementId, + tool: SharedString, + arguments: SharedString, + detail: Option, + on_answer: OnFlag, +} + +impl ToolApprovalDialog { + /// `arguments` as JSON; `on_answer` gets whether the call may run. + pub fn new( + id: impl Into, + tool: impl Into, + arguments: impl Into, + on_answer: impl Fn(bool, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + tool: tool.into(), + arguments: arguments.into(), + detail: None, + on_answer: Rc::new(on_answer), + } + } + + /// A line on what the call will do. + pub fn detail(mut self, text: impl Into) -> Self { + self.detail = Some(text.into()); + self + } +} + +impl RenderOnce for ToolApprovalDialog { + fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement { + let approved = Rc::new(Cell::new(false)); + let (answer, tool, chosen) = (self.on_answer, self.tool.clone(), approved.clone()); + let (deny, run) = ((self.id.clone(), "deny"), (self.id.clone(), "run")); + Dialog::new( + self.id.clone(), + format!("Run {}?", self.tool), + move |window, cx| { + let approved = chosen.get(); + log::info!( + "tool approval: {tool} {}", + if approved { "runs" } else { "denied" } + ); + answer(approved, window, cx) + }, + ) + .when_some(self.detail, |dialog, detail| dialog.detail(detail)) + .child(CodeBlock::new((self.id.clone(), "arguments"), self.arguments).language("json")) + .action(move |close| { + Button::new(deny, "Deny") + .variant(ButtonVariant::Secondary) + .on_click(move |_, window, cx| close(window, cx)) + }) + .action(move |close| { + Button::new(run, "Run") + .variant(ButtonVariant::Primary) + .on_click(move |_, window, cx| { + approved.set(true); + close(window, cx) + }) + }) + } +} + +/// An answer to a request for permission. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Permission { + Once, + Always, + Deny, +} + +type OnPermission = Rc; + +/// Asks in place whether the agent may do something: allow once, always allow, or deny. +#[derive(IntoElement)] +pub struct PermissionPrompt { + id: ElementId, + title: SharedString, + detail: Option, + on_answer: OnPermission, +} + +impl PermissionPrompt { + pub fn new( + id: impl Into, + title: impl Into, + on_answer: impl Fn(Permission, &mut Window, &mut App) + 'static, + ) -> Self { + Self { + id: id.into(), + title: title.into(), + detail: None, + on_answer: Rc::new(on_answer), + } + } + + /// What the permission covers, such as the command or the folder. + pub fn detail(mut self, text: impl Into) -> Self { + self.detail = Some(text.into()); + self + } +} + +impl RenderOnce for PermissionPrompt { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let choice = |key: &'static str, label: &'static str, variant, answer: Permission| { + let on_answer = self.on_answer.clone(); + Button::new((self.id.clone(), key), label) + .variant(variant) + .on_click(move |_, window, cx| { + log::info!("permission: {answer:?}"); + on_answer(answer, window, cx) + }) + }; + div() + .flex() + .flex_col() + .gap_3() + .p_4() + .rounded(theme.radius(Radius::Lg)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_center() + .gap_2() + .child( + Icon::new(IconName::Shield) + .size(IconSize::Sm) + .color(colors.fg_muted), + ) + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .text_color(colors.fg) + .child(self.title.clone()), + ), + ) + .children(self.detail.clone().map(|detail| { + div().w_full().flex().child( + div() + .flex_1() + .min_w_0() + .px_2() + .py_1p5() + .rounded(theme.radius(Radius::Md)) + .bg(colors.sunken) + .font_family(theme.mono_family.clone()) + .text_color(colors.fg_muted) + .child(detail), + ) + })) + .child( + div() + .flex() + .flex_wrap() + .justify_end() + .gap_2() + .child(choice( + "deny", + "Deny", + ButtonVariant::Ghost, + Permission::Deny, + )) + .child(choice( + "always", + "Always allow", + ButtonVariant::Secondary, + Permission::Always, + )) + .child(choice( + "once", + "Allow once", + ButtonVariant::Primary, + Permission::Once, + )), + ) + } +} diff --git a/vendor/ely/src/agent/previews.rs b/vendor/ely/src/agent/previews.rs new file mode 100644 index 00000000..fb9324cb --- /dev/null +++ b/vendor/ely/src/agent/previews.rs @@ -0,0 +1,415 @@ +use std::rc::Rc; + +use gpui::{ + Animation, AnimationExt, AnyElement, App, Div, ElementId, FocusHandle, InteractiveElement, + IntoElement, MouseButton, ParentElement, Point, RenderOnce, ScrollHandle, SharedString, + StatefulInteractiveElement, Styled, Window, div, prelude::*, relative, +}; + +use crate::{ + buttons::{ButtonVariant, IconButton}, + documents::source, + forms::{Pick, Run, reveal, revealer}, + layout::on_axis, + motion::{self, Spinner}, + primitives::{FocusRing, Icon, IconName, Image, checked_ratio, framed, tab_stop}, + theme::{ActiveTheme, AvatarSize, ControlSize, IconSize, Radius, TextSize}, + typography::Ellipsis, +}; + +/// Width over height of a frame from the host, unless it says. +const FRAME: f32 = 16.0 / 10.0; + +/// The bar over a page: a lock, the address, a spinner while it loads, and the owner's actions. +fn address_bar( + id: &ElementId, + url: SharedString, + loading: bool, + actions: Option, + cx: &App, +) -> Div { + let theme = cx.theme(); + let colors = &theme.colors; + div() + .flex() + .items_center() + .gap_2() + .px_3() + .py_1p5() + .border_b_1() + .border_color(colors.border) + .text_size(theme.text_size(TextSize::Xs)) + .text_color(colors.fg_muted) + .child( + Icon::new(IconName::Lock) + .size(IconSize::Xs) + .color(colors.fg_subtle), + ) + .child(div().flex_1().min_w_0().child(Ellipsis::new(url))) + .when(loading, |bar| { + bar.child(Spinner::new((id.clone(), "loading")).size(IconSize::Xs)) + }) + .children(actions) +} + +/// The card a page sits in. +fn card(cx: &App) -> Div { + let theme = cx.theme(); + div() + .debug_selector(|| "preview-root".into()) + .flex() + .flex_col() + .rounded(theme.radius(Radius::Lg)) + .border_1() + .border_color(theme.colors.border) + .bg(theme.colors.surface) +} + +/// A browser an agent drives, as the host shows it: the address, a spinner while a page loads, the frame shown, and the frames so far along the foot; a press on one shows it. +#[derive(IntoElement)] +pub struct BrowserPreview { + id: ElementId, + url: SharedString, + frames: Vec, + shown: Option, + ratio: f32, + loading: bool, + on_show: Option, +} + +impl BrowserPreview { + /// `frames` are the host's screenshots, oldest first, as paths or addresses; `shown` indexes them. + pub fn new( + id: impl Into, + url: impl Into, + frames: impl IntoIterator>, + shown: usize, + ) -> Self { + let frames: Vec = frames.into_iter().map(Into::into).collect(); + let held = shown < frames.len(); + if !held { + log::error!( + "browser preview: frame {shown} of {}; none shown", + frames.len() + ); + } + Self { + id: id.into(), + url: url.into(), + frames, + shown: held.then_some(shown), + ratio: FRAME, + loading: false, + on_show: None, + } + } + + /// The frames' width over their height, 16:10 unless set, so the boxes take the pictures' shape. + pub fn ratio(mut self, width_over_height: f32) -> Self { + self.ratio = checked_ratio(width_over_height); + self + } + + pub fn loading(mut self, loading: bool) -> Self { + self.loading = loading; + self + } + + /// Gets the frame pressed along the foot. + pub fn on_show(mut self, handler: impl Fn(usize, &mut Window, &mut App) + 'static) -> Self { + self.on_show = Some(Rc::new(handler)); + self + } +} + +/// A frame strip's scroll, and the frame it last brought into view. +#[derive(Default)] +struct Strip { + scroll: ScrollHandle, + revealed: Option, +} + +impl RenderOnce for BrowserPreview { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let pressable = self.on_show.is_some(); + let handles: Vec = (0..self.frames.len()) + .map(|ix| { + tab_stop( + (self.id.clone(), format!("frame-focus-{ix}")).into(), + pressable, + window, + cx, + ) + }) + .collect(); + let focused = handles.iter().position(|handle| handle.is_focused(window)); + let state = window.use_keyed_state((self.id.clone(), "strip-state"), cx, |_, _| { + Strip::default() + }); + let reveal = reveal( + &state, + |strip| &mut strip.revealed, + focused.is_some(), + focused.unwrap_or(0), + cx, + ); + let scroll = state.read(cx).scroll.clone(); + let theme = cx.theme(); + let colors = theme.colors.clone(); + let thumb = theme.avatar_size(AvatarSize::Lg); + let shown = self.shown; + let strip = (self.frames.len() > 1).then(|| { + on_axis(div().id((self.id.clone(), "strip"))) + .track_scroll(&scroll) + .overflow_x_scroll() + .flex() + .gap_1p5() + .p_2() + .border_t_1() + .border_color(colors.border) + .children(self.frames.iter().enumerate().map(|(ix, frame)| { + let show = self.on_show.clone(); + let mut tile = div() + .id((self.id.clone(), format!("frame-{ix}"))) + .relative() + .flex_none() + .h(thumb) + .rounded(theme.radius(Radius::Sm)) + .border_1() + .border_color(if shown == Some(ix) { + colors.accent + } else { + colors.border + }) + .child( + Image::new((self.id.clone(), format!("thumb-{ix}")), source(frame)) + .rounded(theme.radius(Radius::Sm)) + .size_full(), + ); + tile.style().aspect_ratio = Some(self.ratio); + tile.when_some(show, |tile, show| { + tile.track_focus(&handles[ix]) + .focus_ring(cx) + .cursor_pointer() + .on_mouse_down(MouseButton::Left, |_, window, _| { + window.prevent_default() + }) + .on_click(move |_, window, cx| { + log::info!("browser preview: frame {ix}"); + show(ix, window, cx) + }) + }) + })) + .when_some(reveal, |strip, (ix, done)| { + strip.child(revealer(&scroll, ix, done)) + }) + }); + card(cx) + .child(address_bar(&self.id, self.url, self.loading, None, cx)) + .child( + framed(self.ratio, cx) + .when(strip.is_none(), |frame| { + frame.rounded_b(theme.radius(Radius::Lg)) + }) + .children(shown.map(|shown| { + let image = + Image::new((self.id.clone(), "frame"), source(&self.frames[shown])) + .size_full(); + if strip.is_none() { + image.rounded_b(theme.radius(Radius::Lg)) + } else { + image + } + })), + ) + .children(strip) + } +} + +/// A screen an agent works on, as the host shows it: the frame, where the agent points, and what it does there; each new point rings once. +#[derive(IntoElement)] +pub struct ComputerUseViewer { + id: ElementId, + frame: SharedString, + ratio: f32, + pointer: Option>, + action: Option, +} + +impl ComputerUseViewer { + /// `frame` is the host's latest screenshot, a path or an address. + pub fn new(id: impl Into, frame: impl Into) -> Self { + Self { + id: id.into(), + frame: frame.into(), + ratio: FRAME, + pointer: None, + action: None, + } + } + + /// The frame's width over its height, 16:10 unless set, so the box takes the picture's shape. + pub fn ratio(mut self, width_over_height: f32) -> Self { + self.ratio = checked_ratio(width_over_height); + self + } + + /// Where the agent points, each side a share of the frame from its top left. + pub fn pointer(mut self, at: Point) -> Self { + assert!( + (0.0..=1.0).contains(&at.x) && (0.0..=1.0).contains(&at.y), + "a pointer inside the frame, not {at:?}" + ); + self.pointer = Some(at); + self + } + + /// What the agent does there, such as "click Save". + pub fn action(mut self, text: impl Into) -> Self { + self.action = Some(text.into()); + self + } +} + +impl RenderOnce for ComputerUseViewer { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let moves = motion::changes( + (self.id.clone(), "pointer"), + self.pointer.map(|at| (at.x.to_bits(), at.y.to_bits())), + window, + cx, + ); + let theme = cx.theme(); + let colors = theme.colors.clone(); + let ring = theme.icon_size(IconSize::Lg); + let pointer = self.pointer.map(|at| { + let mark = div() + .flex_none() + .size(ring) + .rounded_full() + .border_2() + .border_color(colors.focus) + .bg(colors.focus.opacity(0.16)); + let mark = if moves == 0 { + mark.into_any_element() + } else { + mark.with_animation( + (self.id.clone(), format!("ring-{moves}")), + Animation::new(motion::duration(motion::SLOW, cx)) + .with_easing(motion::ease_out_cubic), + move |mark, t| mark.bg(colors.focus.opacity(0.16 + 0.24 * (1.0 - t))), + ) + .into_any_element() + }; + div() + .absolute() + .left(relative(at.x)) + .top(relative(at.y)) + .size_0() + .flex() + .items_center() + .justify_center() + .child(mark) + }); + card(cx) + .child( + framed(self.ratio, cx) + .rounded_t(theme.radius(Radius::Lg)) + .when(self.action.is_none(), |frame| { + frame.rounded_b(theme.radius(Radius::Lg)) + }) + .child({ + let image = Image::new((self.id.clone(), "frame"), source(&self.frame)) + .rounded_t(theme.radius(Radius::Lg)) + .size_full(); + if self.action.is_none() { + image.rounded_b(theme.radius(Radius::Lg)) + } else { + image + } + }) + .children(pointer), + ) + .children(self.action.map(|action| { + div() + .flex() + .items_center() + .gap_2() + .px_3() + .py_2() + .border_t_1() + .border_color(colors.border) + .text_size(theme.text_size(TextSize::Sm)) + .text_color(colors.fg_muted) + .child( + Icon::new(IconName::MousePointer2) + .size(IconSize::Sm) + .color(colors.fg_subtle), + ) + .child(div().flex_1().min_w_0().child(Ellipsis::new(action))) + })) + } +} + +/// A page as it renders while the agent builds it: its address, a spinner while it updates, reload, and the host's element that draws it. +#[derive(IntoElement)] +pub struct LivePreview { + id: ElementId, + url: SharedString, + updating: bool, + content: AnyElement, + on_reload: Option, +} + +impl LivePreview { + pub fn new( + id: impl Into, + url: impl Into, + content: impl IntoElement, + ) -> Self { + Self { + id: id.into(), + url: url.into(), + updating: false, + content: content.into_any_element(), + on_reload: None, + } + } + + pub fn updating(mut self, updating: bool) -> Self { + self.updating = updating; + self + } + + pub fn on_reload(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_reload = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for LivePreview { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let reload = self.on_reload.map(|reload| { + IconButton::new((self.id.clone(), "reload"), IconName::RotateCw) + .variant(ButtonVariant::Ghost) + .size(ControlSize::Sm) + .tooltip("Reload") + .on_click(move |_, window, cx| { + log::info!("live preview: reload"); + reload(window, cx) + }) + .into_any_element() + }); + card(cx) + .h_full() + .child(address_bar(&self.id, self.url, self.updating, reload, cx)) + .child( + div() + .id((self.id.clone(), "page")) + .flex_1() + .min_h_0() + .overflow_y_scroll() + .child(self.content), + ) + } +} diff --git a/vendor/ely/src/agent/progress.rs b/vendor/ely/src/agent/progress.rs new file mode 100644 index 00000000..f07e2312 --- /dev/null +++ b/vendor/ely/src/agent/progress.rs @@ -0,0 +1,325 @@ +use std::time::Duration; + +use gpui::{ + AnyElement, App, ElementId, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, + Styled, Window, div, prelude::*, +}; + +use crate::{ + chat::{StepState, step_mark}, + data_display::{Timeline, TimelineItem}, + motion::{ProgressBar, Spinner}, + primitives::{Icon, IconName, Severity}, + theme::{ActiveTheme, IconSize, TextSize}, + typography::{Ellipsis, format::took, tabular}, +}; + +/// One step of an agent's work: what it did, where it stands, a line below, how long it took. +#[derive(Clone, Debug, PartialEq)] +pub struct AgentStep { + pub title: SharedString, + pub state: StepState, + pub detail: Option, + pub took: Option, +} + +/// An agent's steps down a rail, each marked by where it stands. +#[derive(IntoElement)] +pub struct AgentStepList { + id: ElementId, + steps: Vec, +} + +impl AgentStepList { + pub fn new(id: impl Into, steps: impl IntoIterator) -> Self { + Self { + id: id.into(), + steps: steps.into_iter().collect(), + } + } +} + +impl RenderOnce for AgentStepList { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let marks: Vec = (self.steps.iter().enumerate()) + .map(|(ix, step)| { + step_mark( + (self.id.clone(), format!("step-{ix}")).into(), + step.state, + window, + cx, + ) + }) + .collect(); + let colors = cx.theme().colors.clone(); + self.steps + .into_iter() + .zip(marks) + .fold(Timeline::new(), |timeline, (step, mark)| { + let title = div() + .text_color(match step.state { + StepState::Waiting => colors.fg_subtle, + _ => colors.fg, + }) + .child(step.title); + let item = TimelineItem::new(title) + .marker(mark) + .when_some(step.took, |item, spent| item.time(took(spent))); + timeline.item(match step.detail { + Some(detail) => item.child(detail), + None => item, + }) + }) + } +} + +/// An agent's plan: items waiting, at work or done, with how many are done; a done item goes quiet and struck through. +#[derive(IntoElement)] +pub struct AgentPlan { + id: ElementId, + title: SharedString, + items: Vec<(SharedString, StepState)>, +} + +impl AgentPlan { + pub fn new( + id: impl Into, + title: impl Into, + items: impl IntoIterator, StepState)>, + ) -> Self { + Self { + id: id.into(), + title: title.into(), + items: items + .into_iter() + .map(|(label, state)| (label.into(), state)) + .collect(), + } + } +} + +impl RenderOnce for AgentPlan { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let marks: Vec = (self.items.iter().enumerate()) + .map(|(ix, (_, state))| { + step_mark( + (self.id.clone(), format!("item-{ix}")).into(), + *state, + window, + cx, + ) + }) + .collect(); + let theme = cx.theme(); + let colors = theme.colors.clone(); + let done = self + .items + .iter() + .filter(|(_, state)| *state == StepState::Done) + .count(); + div() + .flex() + .flex_col() + .gap_2() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_center() + .gap_2() + .child( + div() + .flex_1() + .min_w_0() + .font_weight(FontWeight::MEDIUM) + .child(Ellipsis::new(self.title)), + ) + .child( + tabular(div().flex_none().text_color(colors.fg_subtle)) + .child(format!("{done} of {}", self.items.len())), + ), + ) + .children( + self.items + .into_iter() + .zip(marks) + .map(|((label, state), mark)| { + div().flex().items_center().gap_2().child(mark).child( + div() + .flex_1() + .min_w_0() + .text_color(match state { + StepState::Waiting => colors.fg_muted, + StepState::Working => colors.fg, + StepState::Done => colors.fg_subtle, + StepState::Failed => Severity::Danger.color(&colors), + }) + .when(state == StepState::Done, |text| text.line_through()) + .child(label), + ) + }), + ) + } +} + +/// Where an agent stands. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AgentState { + Planning, + Working, + Waiting, + Done, + Failed, +} + +impl AgentState { + pub fn label(self) -> &'static str { + match self { + Self::Planning => "Planning", + Self::Working => "Working", + Self::Waiting => "Waiting for you", + Self::Done => "Done", + Self::Failed => "Failed", + } + } +} + +/// A pill that says where an agent stands, moving while it plans or works. +#[derive(IntoElement)] +pub struct AgentStatus { + id: ElementId, + state: AgentState, +} + +impl AgentStatus { + pub fn new(id: impl Into, state: AgentState) -> Self { + Self { + id: id.into(), + state, + } + } +} + +impl RenderOnce for AgentStatus { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let tone = match self.state { + AgentState::Planning | AgentState::Working => Severity::Info, + AgentState::Waiting => Severity::Warning, + AgentState::Done => Severity::Success, + AgentState::Failed => Severity::Danger, + }; + let ink = tone.color(&colors); + let mark = match self.state { + AgentState::Planning | AgentState::Working => Spinner::new((self.id.clone(), "mark")) + .size(IconSize::Xs) + .color(ink) + .into_any_element(), + AgentState::Waiting => Icon::new(IconName::Hand) + .size(IconSize::Xs) + .color(ink) + .into_any_element(), + AgentState::Done => Icon::new(IconName::Check) + .size(IconSize::Xs) + .color(ink) + .into_any_element(), + AgentState::Failed => Icon::new(IconName::X) + .size(IconSize::Xs) + .color(ink) + .into_any_element(), + }; + div() + .flex() + .items_center() + .gap_1p5() + .px_2() + .py_0p5() + .rounded_full() + .bg(tone.subtle(&colors)) + .text_size(theme.text_size(TextSize::Xs)) + .font_weight(FontWeight::MEDIUM) + .text_color(ink) + .child(mark) + .child(self.state.label()) + } +} + +/// How far an agent has come: the step at work, how many are done of how many, the time so far, and a bar split by step when there are two or more. +#[derive(IntoElement)] +pub struct AgentProgress { + id: ElementId, + current: SharedString, + done: usize, + total: usize, + elapsed: Option, +} + +impl AgentProgress { + pub fn new( + id: impl Into, + current: impl Into, + done: usize, + total: usize, + ) -> Self { + assert!(total > 0, "progress of {done} in none"); + if done > total { + log::error!("agent progress: {done} done of {total}; the bar fills"); + } + Self { + id: id.into(), + current: current.into(), + done, + total, + elapsed: None, + } + } + + pub fn elapsed(mut self, elapsed: Duration) -> Self { + self.elapsed = Some(elapsed); + self + } +} + +impl RenderOnce for AgentProgress { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + div() + .flex() + .flex_col() + .gap_2() + .text_size(theme.text_size(TextSize::Sm)) + .child( + div() + .flex() + .items_center() + .gap_2() + .child( + div() + .flex_1() + .min_w_0() + .text_color(colors.fg) + .child(Ellipsis::new(self.current)), + ) + .child( + tabular(div().flex_none().text_color(colors.fg_subtle)) + .child(format!("{} of {}", self.done, self.total)), + ) + .children(self.elapsed.map(|spent| { + tabular(div().flex_none().text_color(colors.fg_subtle)).child(took(spent)) + })), + ) + .child({ + let bar = ProgressBar::new( + (self.id, "bar"), + self.done.min(self.total) as f32 / self.total as f32, + ); + if self.total >= 2 { + bar.segments(self.total) + } else { + bar + } + }) + } +} diff --git a/vendor/ely/src/agent/registry.rs b/vendor/ely/src/agent/registry.rs new file mode 100644 index 00000000..1c35a0e7 --- /dev/null +++ b/vendor/ely/src/agent/registry.rs @@ -0,0 +1,230 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, Styled, + Window, div, prelude::*, +}; + +use crate::{ + buttons::SegmentedControl, + theme::{ActiveTheme, ControlSize, TextSize}, + typography::Ellipsis, +}; + +/// What an agent may do with a tool. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ToolAccess { + Allow, + Ask, + Deny, +} + +impl ToolAccess { + const ALL: [(ToolAccess, &'static str, &'static str); 3] = [ + (ToolAccess::Allow, "allow", "Allow"), + (ToolAccess::Ask, "ask", "Ask"), + (ToolAccess::Deny, "deny", "Deny"), + ]; + + fn key(self) -> &'static str { + Self::ALL + .iter() + .find(|(access, _, _)| *access == self) + .expect("every access has a key") + .1 + } +} + +/// A tool the agent can call: its name, where it comes from, what it does, and what the agent may do with it. +#[derive(Clone, Debug, PartialEq)] +pub struct RegisteredTool { + pub name: SharedString, + pub source: SharedString, + pub description: SharedString, + pub access: ToolAccess, +} + +/// The tools whose name or description holds every word of `query`, ignoring case, by index. +pub(crate) fn found(tools: &[RegisteredTool], query: &str) -> Vec { + let words: Vec = query.split_whitespace().map(str::to_lowercase).collect(); + (0..tools.len()) + .filter(|ix| { + let text = format!("{} {}", tools[*ix].name, tools[*ix].description).to_lowercase(); + words.iter().all(|word| text.contains(word)) + }) + .collect() +} + +/// The kept tools gathered by source, sources in the order they first appear. +pub(crate) fn grouped(tools: &[RegisteredTool], kept: &[usize]) -> Vec<(SharedString, Vec)> { + let mut groups: Vec<(SharedString, Vec)> = Vec::new(); + for &ix in kept { + let source = &tools[ix].source; + match groups.iter_mut().find(|(name, _)| name == source) { + Some((_, items)) => items.push(ix), + None => groups.push((source.clone(), vec![ix])), + } + } + groups +} + +type OnAccess = Rc; + +/// Every tool the agent may call, grouped by where it comes from and found by the owner's query: each allowed, asked for first, or denied. +#[derive(IntoElement)] +pub struct ToolRegistry { + id: ElementId, + tools: Vec, + query: SharedString, + on_access: Option, +} + +impl ToolRegistry { + pub fn new(id: impl Into, tools: impl IntoIterator) -> Self { + Self { + id: id.into(), + tools: tools.into_iter().collect(), + query: SharedString::default(), + on_access: None, + } + } + + /// Keeps the tools that hold every word, such as a `forms::SearchInput`'s. + pub fn query(mut self, query: impl Into) -> Self { + self.query = query.into(); + self + } + + /// Gets a tool's index and its new access. + pub fn on_access( + mut self, + handler: impl Fn(usize, ToolAccess, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_access = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for ToolRegistry { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = theme.colors.clone(); + let groups = grouped(&self.tools, &found(&self.tools, &self.query)); + let empty = groups.is_empty(); + div() + .flex() + .flex_col() + .gap_4() + .text_size(theme.text_size(TextSize::Sm)) + .when(empty, |list| { + list.child(div().text_color(colors.fg_subtle).child("No tools match")) + }) + .children(groups.into_iter().map(|(source, items)| { + div() + .flex() + .flex_col() + .child( + div() + .pb_1() + .text_size(theme.text_size(TextSize::Xs)) + .font_weight(FontWeight::MEDIUM) + .text_color(colors.fg_subtle) + .child(format!("{source} · {}", items.len())), + ) + .children(items.into_iter().map(|ix| { + let tool = &self.tools[ix]; + let access = self.on_access.clone(); + let control = ToolAccess::ALL.iter().fold( + SegmentedControl::new( + (self.id.clone(), format!("access-{ix}")), + tool.access.key(), + ) + .size(ControlSize::Sm), + |control, (_, key, label)| control.segment(*key, *label, None), + ); + let control = match access { + Some(access) => control.on_change(move |key, window, cx| { + let next = ToolAccess::ALL + .iter() + .find(|(_, name, _)| *name == key.as_ref()) + .expect("a segment names an access") + .0; + log::info!("tool registry: tool {ix} {next:?}"); + access(ix, next, window, cx) + }), + None => control, + }; + div() + .flex() + .flex_wrap() + .items_center() + .gap_x_3() + .gap_y_1() + .py_2() + .border_t_1() + .border_color(colors.border) + .child( + div() + .flex_1() + .min_w(theme.label_width()) + .child( + div() + .font_family(theme.mono_family.clone()) + .child(Ellipsis::new(tool.name.clone())), + ) + .child( + div() + .text_size(theme.text_size(TextSize::Xs)) + .text_color(colors.fg_muted) + .child(Ellipsis::new(tool.description.clone())), + ), + ) + .child(div().flex_none().child(control)) + })) + })) + } +} + +#[cfg(test)] +mod tests { + use gpui::SharedString; + + use super::{RegisteredTool, ToolAccess, found, grouped}; + + fn tool(name: &str, description: &str) -> RegisteredTool { + RegisteredTool { + name: name.to_string().into(), + source: "files".into(), + description: description.to_string().into(), + access: ToolAccess::Ask, + } + } + + #[test] + fn a_query_keeps_tools_that_hold_every_word() { + let tools = [ + tool("read_file", "Reads a file"), + tool("write_file", "Writes a file"), + tool("web_search", "Searches the web"), + ]; + assert_eq!(found(&tools, ""), [0, 1, 2]); + assert_eq!(found(&tools, "FILE"), [0, 1]); + assert_eq!(found(&tools, "writes file"), [1]); + assert_eq!(found(&tools, "web file"), Vec::::new()); + } + + #[test] + fn kept_tools_gather_by_source_in_first_seen_order() { + let from = |source: &str| RegisteredTool { + source: source.to_string().into(), + ..tool("tool", "") + }; + let tools = [from("A"), from("B"), from("A")]; + let (a, b) = (SharedString::from("A"), SharedString::from("B")); + assert_eq!( + grouped(&tools, &[0, 1, 2]), + [(a.clone(), vec![0, 2]), (b.clone(), vec![1])] + ); + assert_eq!(grouped(&tools, &[1, 2]), [(b, vec![1]), (a, vec![2])]); + } +} diff --git a/vendor/ely/src/agent/tests/changes.rs b/vendor/ely/src/agent/tests/changes.rs new file mode 100644 index 00000000..ee610a76 --- /dev/null +++ b/vendor/ely/src/agent/tests/changes.rs @@ -0,0 +1,199 @@ +use std::{cell::Cell, rc::Rc}; + +use gpui::{ + Context, Entity, IntoElement, KeyBinding, Modifiers, ParentElement, Pixels, Render, Styled, + TestAppContext, VisualTestContext, Window, canvas, div, point, px, +}; + +use super::{press, settle}; +use crate::{ + agent::{ChangeState, FileChange, FileChangeCard, MultiFileDiffReview}, + collab::Decision, + forms, + primitives::FocusNext, + theme::Theme, +}; + +fn change(path: &str) -> FileChange { + FileChange { + path: path.to_string().into(), + old: "let lift = 0.12;\n".into(), + new: "let lift = 0.18;\n".into(), + state: ChangeState::Proposed, + } +} + +fn setup(cx: &mut TestAppContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); +} + +/// One change card in a 640px column, its verdicts and the column's height. +struct Card { + verdicts: Vec, + height: Rc>, +} + +impl Render for Card { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let (view, height) = (cx.entity(), self.height.clone()); + // gpui fills the window with an auto-sized root, so the measured box sits inside one. + div().child( + div() + .relative() + .w(px(640.0)) + .child( + FileChangeCard::new("card", change("src/theme/lift.rs")).on_decide( + move |accepted, _, cx| { + view.update(cx, |card, _| card.verdicts.push(accepted)) + }, + ), + ) + .child( + canvas( + move |bounds, _, _| height.set(bounds.size.height), + |_, _, _, _| {}, + ) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ) + } +} + +#[gpui::test] +fn a_press_on_accept_decides_and_leaves_the_card_shut(cx: &mut TestAppContext) { + setup(cx); + let height = Rc::new(Cell::new(Pixels::ZERO)); + let seen = height.clone(); + let (view, cx) = cx.add_window_view(|_, _| Card { + verdicts: Vec::new(), + height: seen, + }); + settle(cx); + let shut = height.get(); + let accept = point(px(640.0 - 16.0), shut / 2.0); + cx.simulate_mouse_move(accept, None, Modifiers::none()); + cx.simulate_click(accept, Modifiers::none()); + settle(cx); + assert_eq!(view.read_with(cx, |card, _| card.verdicts.clone()), [true]); + assert_eq!(height.get(), shut, "the press stays with the button"); + let chevron = point(px(14.0), shut / 2.0); + cx.simulate_mouse_move(chevron, None, Modifiers::none()); + cx.simulate_click(chevron, Modifiers::none()); + settle(cx); + assert!(height.get() > shut, "the header opens the diff"); +} + +/// Three proposed changes under review, and the decisions made. +struct Review { + decisions: Vec, +} + +impl Render for Review { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + div().w(px(560.0)).child( + MultiFileDiffReview::new("review", ["a.rs", "b.rs", "c.rs"].map(change)).on_decide( + move |decision, _, cx| view.update(cx, |review, _| review.decisions.push(decision)), + ), + ) + } +} + +fn review(cx: &mut TestAppContext) -> (Entity, &mut VisualTestContext) { + setup(cx); + let (view, cx) = cx.add_window_view(|_, _| Review { + decisions: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + (view, cx) +} + +#[gpui::test] +fn accept_all_decides_every_file(cx: &mut TestAppContext) { + let (view, cx) = review(cx); + cx.update(|window, cx| window.focus_next(cx)); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + assert_eq!( + view.read_with(cx, |review, _| review.decisions.clone()), + [Decision::AcceptAll] + ); +} + +#[gpui::test] +fn a_cards_verdict_names_its_file(cx: &mut TestAppContext) { + let (view, cx) = review(cx); + for _ in 0..8 { + cx.update(|window, cx| window.focus_next(cx)); + } + press("enter", cx); + assert_eq!( + view.read_with(cx, |review, _| review.decisions.clone()), + [Decision::Accept(1)] + ); +} + +/// A review at `width`, and its height as drawn. +struct Narrow { + width: Pixels, + height: Rc>, +} + +impl Render for Narrow { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.height.clone(); + div().child( + div() + .relative() + .w(self.width) + .child( + MultiFileDiffReview::new( + "narrow", + ["src/theme/lift.rs", "src/theme/tokens.rs"].map(change), + ) + .on_decide(|_, _, _| {}), + ) + .child( + canvas( + move |bounds, _, _| height.set(bounds.size.height), + |_, _, _, _| {}, + ) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ) + } +} + +#[gpui::test] +fn a_narrow_review_wraps_its_rows_inside_its_box(cx: &mut TestAppContext) { + setup(cx); + let height = Rc::new(Cell::new(Pixels::ZERO)); + let seen = height.clone(); + let (view, cx) = cx.add_window_view(|_, _| Narrow { + width: px(640.0), + height: seen, + }); + settle(cx); + let wide = height.get(); + view.update(cx, |narrow, cx| { + narrow.width = px(280.0); + cx.notify(); + }); + settle(cx); + assert!( + height.get() > wide, + "at 280px the counts and verdicts wrap below: {:?} vs {wide:?}", + height.get() + ); +} diff --git a/vendor/ely/src/agent/tests/control.rs b/vendor/ely/src/agent/tests/control.rs new file mode 100644 index 00000000..0588d181 --- /dev/null +++ b/vendor/ely/src/agent/tests/control.rs @@ -0,0 +1,105 @@ +use gpui::{ + AppContext as _, Context, Entity, IntoElement, KeyBinding, ParentElement, Render, Styled, + TestAppContext, VisualTestContext, Window, div, px, +}; + +use super::{press, settle}; +use crate::{ + agent::{CostBreakdown, HumanInputRequest}, + forms::{self, TextInput}, + primitives::FocusNext, + theme::Theme, +}; + +/// A question with two answers to pick, and the answers given; once answered, it shows the first. +struct Asked { + field: Entity, + answers: Vec, +} + +impl Render for Asked { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + let request = HumanInputRequest::new( + "asked", + "Keep the accents?", + &self.field, + move |answer, _, cx| { + view.update(cx, |asked, cx| { + asked.answers.push(answer.to_string()); + cx.notify(); + }) + }, + ) + .choices(["Keep them", "Lift further"]); + let request = match self.answers.first() { + Some(answer) => request.answered(answer.clone()), + None => request, + }; + div().w(px(420.0)).child(request) + } +} + +fn asked(cx: &mut TestAppContext) -> (Entity, &mut VisualTestContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); + let (view, cx) = cx.add_window_view(|window, cx| Asked { + field: cx.new(|cx| TextInput::new(window, cx)), + answers: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + (view, cx) +} + +#[gpui::test] +fn a_pick_answers_the_question_and_the_answer_stands_alone(cx: &mut TestAppContext) { + let (view, cx) = asked(cx); + cx.update(|window, cx| window.focus_next(cx)); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + assert_eq!( + view.read_with(cx, |asked, _| asked.answers.clone()), + ["Lift further"], + "once answered, no choice is left to press" + ); +} + +#[gpui::test] +fn enter_sends_a_written_answer_and_skips_a_blank_one(cx: &mut TestAppContext) { + let (view, cx) = asked(cx); + for _ in 0..3 { + cx.update(|window, cx| window.focus_next(cx)); + } + cx.simulate_input(" "); + press("enter", cx); + cx.simulate_input("Lift them to 18%"); + press("enter", cx); + view.read_with(cx, |asked, cx| { + assert_eq!(asked.answers, ["Lift them to 18%"]); + assert_eq!(asked.field.read(cx).text(), ""); + }); +} + +/// A breakdown of a session that has cost nothing yet. +struct Nothing; + +impl Render for Nothing { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div() + .w(px(320.0)) + .child(CostBreakdown::new("This session", "USD")) + } +} + +#[gpui::test] +fn a_session_that_cost_nothing_draws_its_total(cx: &mut TestAppContext) { + cx.update(Theme::init); + let (_, cx) = cx.add_window_view(|_, _| Nothing); + settle(cx); +} diff --git a/vendor/ely/src/agent/tests/environment.rs b/vendor/ely/src/agent/tests/environment.rs new file mode 100644 index 00000000..7c803bd6 --- /dev/null +++ b/vendor/ely/src/agent/tests/environment.rs @@ -0,0 +1,195 @@ +use gpui::{ + AppContext as _, Context, Entity, IntoElement, KeyBinding, ParentElement, Render, SharedString, + Styled, TestAppContext, VisualTestContext, Window, div, px, +}; +use jiff::Timestamp; + +use super::{press, settle}; +use crate::{ + agent::{ + Checkpoint, CheckpointList, McpServer, McpServerList, Memory, MemoryPanel, SandboxState, + SandboxStatus, ServerState, + }, + forms::{self, TextInput}, + primitives::FocusNext, + theme::Theme, +}; + +fn setup(cx: &mut TestAppContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); +} + +/// A memory panel over a field, and the words it kept. +struct Memories { + field: Entity, + kept: Vec, +} + +impl Render for Memories { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + let memory = Memory { + key: "tone".into(), + text: "Prefers plain words".into(), + source: None, + at: Timestamp::UNIX_EPOCH, + }; + div().w(px(360.0)).child( + MemoryPanel::new("memory", &self.field, [memory]) + .on_add(move |text, _, cx| { + view.update(cx, |memories, _| memories.kept.push(text.to_string())) + }) + .on_forget(|_, _, _| {}), + ) + } +} + +fn memories(cx: &mut TestAppContext) -> (Entity, &mut VisualTestContext) { + setup(cx); + let (view, cx) = cx.add_window_view(|window, cx| Memories { + field: cx.new(|cx| TextInput::new(window, cx)), + kept: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + (view, cx) +} + +#[gpui::test] +fn enter_keeps_a_memory_and_empties_the_field(cx: &mut TestAppContext) { + let (view, cx) = memories(cx); + cx.update(|window, cx| window.focus_next(cx)); + cx.simulate_input(" "); + press("enter", cx); + cx.simulate_input("Lifts stay under 20%"); + press("enter", cx); + view.read_with(cx, |memories, cx| { + assert_eq!( + memories.kept, + ["Lifts stay under 20%"], + "blank words are kept out" + ); + assert_eq!(memories.field.read(cx).text(), ""); + }); +} + +/// Two servers, and the switches thrown. +struct Servers { + thrown: Vec<(SharedString, bool)>, +} + +impl Render for Servers { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + let server = |key: &str, state| McpServer { + key: key.to_string().into(), + name: key.to_string().into(), + detail: "npx server".into(), + state, + tools: 3, + }; + div().w(px(360.0)).child( + McpServerList::new( + "servers", + [ + server("files", ServerState::Connected), + server("web", ServerState::Off), + ], + ) + .on_toggle(move |key, on, _, cx| { + view.update(cx, |servers, _| servers.thrown.push((key.clone(), on))) + }), + ) + } +} + +#[gpui::test] +fn a_servers_switch_turns_it_off_and_on(cx: &mut TestAppContext) { + setup(cx); + let (view, cx) = cx.add_window_view(|_, _| Servers { thrown: Vec::new() }); + cx.update(|window, _| window.activate_window()); + settle(cx); + cx.update(|window, cx| window.focus_next(cx)); + press("space", cx); + cx.update(|window, cx| window.focus_next(cx)); + press("space", cx); + let thrown = view.read_with(cx, |servers, _| servers.thrown.clone()); + assert_eq!(thrown, [("files".into(), false), ("web".into(), true)]); +} + +/// Three checkpoints standing on the middle one, and the rewinds asked for. +struct Points { + asked: Vec, +} + +impl Render for Points { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + let point = |key: &str| Checkpoint { + key: key.to_string().into(), + label: key.to_string().into(), + at: Timestamp::UNIX_EPOCH, + files: 2, + }; + div().w(px(360.0)).child( + CheckpointList::new( + "points", + [point("first"), point("second"), point("third")], + 1, + ) + .on_rewind(move |ix, _, cx| view.update(cx, |points, _| points.asked.push(ix))), + ) + } +} + +#[gpui::test] +fn every_checkpoint_but_the_current_rewinds(cx: &mut TestAppContext) { + setup(cx); + let (view, cx) = cx.add_window_view(|_, _| Points { asked: Vec::new() }); + cx.update(|window, _| window.activate_window()); + settle(cx); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + assert_eq!( + view.read_with(cx, |points, _| points.asked.clone()), + [2, 0], + "newest first, the current skipped" + ); +} + +/// A sandbox past its memory limit and checkpoints whose current one left. +struct Overrun; + +impl Render for Overrun { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let point = Checkpoint { + key: "one".into(), + label: "One".into(), + at: Timestamp::UNIX_EPOCH, + files: 1, + }; + div() + .w(px(360.0)) + .child(SandboxStatus::new("box", "python", SandboxState::Ready).memory(5, 4)) + .child(CheckpointList::new("points", [point], 4)) + } +} + +#[gpui::test] +fn memory_past_its_limit_and_a_gone_checkpoint_draw(cx: &mut TestAppContext) { + setup(cx); + let (_, cx) = cx.add_window_view(|_, _| Overrun); + settle(cx); +} + +#[test] +#[should_panic(expected = "cpu 1.8 of 1")] +fn cpu_past_full_fails_loud() { + let _ = SandboxStatus::new("box", "python", SandboxState::Ready).cpu(1.8); +} diff --git a/vendor/ely/src/agent/tests/mod.rs b/vendor/ely/src/agent/tests/mod.rs new file mode 100644 index 00000000..5d193858 --- /dev/null +++ b/vendor/ely/src/agent/tests/mod.rs @@ -0,0 +1,162 @@ +use gpui::{ + Context, Entity, IntoElement, KeyBinding, KeyUpEvent, Keystroke, ParentElement, Render, Styled, + TestAppContext, VisualTestContext, Window, div, +}; + +mod changes; +mod control; +mod environment; +mod previews; + +use super::{AgentProgress, Permission, PermissionPrompt, ToolApprovalDialog}; +use crate::{forms, primitives::FocusNext, theme::Theme}; + +/// An approval dialog while open, and the answers it gave. +struct Asking { + open: bool, + answers: Vec, +} + +impl Render for Asking { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + div().size_full().children(self.open.then(|| { + ToolApprovalDialog::new( + "approve", + "write_file", + r#"{ "path": "lift.rs" }"#, + move |approved, _, cx| { + view.update(cx, |asking, cx| { + asking.answers.push(approved); + asking.open = false; + cx.notify(); + }) + }, + ) + })) + } +} + +pub(super) fn settle(cx: &mut VisualTestContext) { + cx.run_until_parked(); + cx.update(|window, _| window.refresh()); + cx.run_until_parked(); +} + +/// Presses and releases `key`, a frame apart. +pub(super) fn press(key: &str, cx: &mut VisualTestContext) { + cx.simulate_keystrokes(key); + settle(cx); + cx.simulate_event(KeyUpEvent { + keystroke: Keystroke::parse(key).expect("a key"), + }); + settle(cx); +} + +fn asking(cx: &mut TestAppContext) -> (Entity, &mut VisualTestContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); + let (view, cx) = cx.add_window_view(|_, _| Asking { + open: true, + answers: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + (view, cx) +} + +#[gpui::test] +fn escape_denies_the_call(cx: &mut TestAppContext) { + let (view, cx) = asking(cx); + press("escape", cx); + assert_eq!( + view.read_with(cx, |asking, _| asking.answers.clone()), + [false] + ); +} + +#[gpui::test] +fn run_approves_the_call_once(cx: &mut TestAppContext) { + let (view, cx) = asking(cx); + press("tab", cx); + press("tab", cx); + press("tab", cx); + press("enter", cx); + assert_eq!( + view.read_with(cx, |asking, _| asking.answers.clone()), + [true] + ); +} + +/// A permission prompt and the answers it gave. +struct Prompting { + answers: Vec, +} + +impl Render for Prompting { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + div().w_full().child( + PermissionPrompt::new("permission", "Run commands here?", move |answer, _, cx| { + view.update(cx, |prompting, _| prompting.answers.push(answer)) + }) + .detail("cargo test"), + ) + } +} + +#[gpui::test] +fn the_prompt_walks_deny_always_then_once(cx: &mut TestAppContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + }); + let (view, cx) = cx.add_window_view(|_, _| Prompting { + answers: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + for _ in 0..3 { + cx.update(|window, cx| window.focus_next(cx)); + } + press("enter", cx); + assert_eq!( + view.read_with(cx, |prompting, _| prompting.answers.clone()), + [Permission::Once] + ); +} + +/// A progress bar for a task of one step, `done` or not; live counts may run past it. +struct Single { + done: usize, +} + +impl Render for Single { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div() + .w_full() + .child(AgentProgress::new("single", "The one step", self.done, 1)) + } +} + +#[gpui::test] +fn progress_past_its_total_fills_the_bar(cx: &mut TestAppContext) { + cx.update(Theme::init); + let (_, cx) = cx.add_window_view(|_, _| Single { done: 6 }); + settle(cx); +} + +#[gpui::test] +fn a_task_of_one_step_draws_before_and_after(cx: &mut TestAppContext) { + cx.update(Theme::init); + let (view, cx) = cx.add_window_view(|_, _| Single { done: 0 }); + settle(cx); + view.update(cx, |single, cx| { + single.done = 1; + cx.notify(); + }); + settle(cx); +} diff --git a/vendor/ely/src/agent/tests/previews.rs b/vendor/ely/src/agent/tests/previews.rs new file mode 100644 index 00000000..936e49cb --- /dev/null +++ b/vendor/ely/src/agent/tests/previews.rs @@ -0,0 +1,332 @@ +use std::{cell::Cell, rc::Rc}; + +use gpui::{ + Context, IntoElement, KeyBinding, Modifiers, ParentElement, Pixels, Render, ScrollDelta, + ScrollWheelEvent, Styled, TestAppContext, TouchPhase, Window, canvas, div, point, px, +}; + +use super::{press, settle}; +use crate::{ + agent::{ArtifactPanel, BrowserPreview, ComputerUseViewer, LivePreview}, + forms, + layout::tests::narrow_width, + primitives::{FocusNext, IconName}, + theme::{ActiveTheme, AvatarSize, Theme}, +}; + +fn setup(cx: &mut TestAppContext) { + cx.update(|cx| { + Theme::init(cx); + forms::bind_keys(cx); + cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]); + }); +} + +/// A browser with three frames, and the frames asked for. +struct Browsing { + asked: Vec, +} + +impl Render for Browsing { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let view = cx.entity(); + div().w(px(480.0)).child( + BrowserPreview::new("browser", "localhost:5173", ["a.png", "b.png", "c.png"], 2) + .on_show(move |ix, _, cx| view.update(cx, |browsing, _| browsing.asked.push(ix))), + ) + } +} + +#[gpui::test] +fn a_frame_shows_from_the_keyboard(cx: &mut TestAppContext) { + setup(cx); + let (view, cx) = cx.add_window_view(|_, _| Browsing { asked: Vec::new() }); + cx.update(|window, _| window.activate_window()); + settle(cx); + cx.update(|window, cx| window.focus_next(cx)); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + assert_eq!( + view.read_with(cx, |browsing, _| browsing.asked.clone()), + [1] + ); +} + +/// A browser asked to show a frame it no longer holds. +struct Past; + +impl Render for Past { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div().w(px(480.0)).child(BrowserPreview::new( + "browser", + "localhost", + ["a.png", "b.png", "c.png"], + 3, + )) + } +} + +#[gpui::test] +fn a_frame_past_the_last_shows_none(cx: &mut TestAppContext) { + setup(cx); + let (_, cx) = cx.add_window_view(|_, _| Past); + settle(cx); +} + +#[test] +#[should_panic(expected = "a pointer inside the frame")] +fn a_pointer_off_the_frame_fails_loud() { + let _ = ComputerUseViewer::new("screen", "a.png").pointer(point(1.2, 0.5)); +} + +/// A panel with a preview and a source, noting which one drew. +struct Panel { + drew_source: Rc>, +} + +impl Render for Panel { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let drew = self.drew_source.clone(); + div().w(px(480.0)).h(px(320.0)).child( + ArtifactPanel::new("panel", "Notes", IconName::FileText) + .preview(div().h(px(40.0))) + .source( + div().relative().h(px(40.0)).child( + canvas(move |_, _, _| drew.set(true), |_, _, _, _| {}) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ), + ) + } +} + +#[gpui::test] +fn the_source_shows_when_asked(cx: &mut TestAppContext) { + setup(cx); + let drew = Rc::new(Cell::new(false)); + let seen = drew.clone(); + let (_, cx) = cx.add_window_view(|_, _| Panel { drew_source: seen }); + cx.update(|window, _| window.activate_window()); + settle(cx); + assert!(!drew.get(), "the preview shows first"); + cx.update(|window, cx| window.focus_next(cx)); + cx.update(|window, cx| window.focus_next(cx)); + press("enter", cx); + assert!(drew.get(), "the source shows once asked"); +} + +/// A narrow browser with eight frames, its height as drawn, and the frames asked for. +struct Strip { + height: Rc>, + asked: Vec, +} + +impl Render for Strip { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let (view, height) = (cx.entity(), self.height.clone()); + let frames = (0..8).map(|ix| format!("{ix}.png")); + // gpui fills the window with an auto-sized root, so the measured box sits inside one. + div().child( + div() + .relative() + .w(px(280.0)) + .child( + BrowserPreview::new("strip", "localhost", frames, 0) + .on_show(move |ix, _, cx| view.update(cx, |strip, _| strip.asked.push(ix))), + ) + .child( + canvas( + move |bounds, _, _| height.set(bounds.size.height), + |_, _, _, _| {}, + ) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ) + } +} + +#[gpui::test] +fn a_narrow_strip_scrolls_to_its_last_frame(cx: &mut TestAppContext) { + setup(cx); + let height = Rc::new(Cell::new(Pixels::ZERO)); + let seen = height.clone(); + let (view, cx) = cx.add_window_view(|_, _| Strip { + height: seen, + asked: Vec::new(), + }); + settle(cx); + let thumb = cx.update(|window, cx| { + cx.theme() + .avatar_size(AvatarSize::Lg) + .to_pixels(window.rem_size()) + }); + let row = height.get() - px(9.0) - thumb / 2.0; + cx.simulate_event(ScrollWheelEvent { + position: point(px(140.0), row), + delta: ScrollDelta::Pixels(point(px(-2000.0), px(0.0))), + modifiers: Modifiers::none(), + touch_phase: TouchPhase::Moved, + }); + settle(cx); + let last = point(px(280.0 - 24.0), row); + cx.simulate_mouse_move(last, None, Modifiers::none()); + cx.simulate_click(last, Modifiers::none()); + settle(cx); + assert_eq!(view.read_with(cx, |strip, _| strip.asked.clone()), [7]); +} + +/// A panel with every control at `width`, noting where its body starts. +struct Crowded { + width: Pixels, + top: Rc>, +} + +impl Render for Crowded { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let top = self.top.clone(); + div().w(self.width).h(px(320.0)).child( + ArtifactPanel::new("crowded", "Notes on lift", IconName::FileText) + .version(1, 3, |_, _, _| {}) + .preview( + div().relative().h(px(40.0)).child( + canvas(move |bounds, _, _| top.set(bounds.top()), |_, _, _, _| {}) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ) + .source(div().h(px(40.0))) + .on_copy(|_, _| {}) + .on_download(|_, _| {}), + ) + } +} + +#[gpui::test] +fn a_narrow_panel_wraps_its_header(cx: &mut TestAppContext) { + setup(cx); + let top = Rc::new(Cell::new(Pixels::ZERO)); + let seen = top.clone(); + let (view, cx) = cx.add_window_view(|_, _| Crowded { + width: px(640.0), + top: seen, + }); + settle(cx); + let wide = top.get(); + view.update(cx, |crowded, cx| { + crowded.width = px(280.0); + cx.notify(); + }); + settle(cx); + assert!( + top.get() > wide, + "the header wraps below at 280px: {:?} vs {wide:?}", + top.get() + ); +} + +#[gpui::test] +fn tab_brings_a_hidden_frame_into_view(cx: &mut TestAppContext) { + setup(cx); + let height = Rc::new(Cell::new(Pixels::ZERO)); + let seen = height.clone(); + let (view, cx) = cx.add_window_view(|_, _| Strip { + height: seen, + asked: Vec::new(), + }); + cx.update(|window, _| window.activate_window()); + settle(cx); + for _ in 0..8 { + cx.update(|window, cx| window.focus_next(cx)); + settle(cx); + } + settle(cx); + let thumb = cx.update(|window, cx| { + cx.theme() + .avatar_size(AvatarSize::Lg) + .to_pixels(window.rem_size()) + }); + let last = point(px(280.0 - 24.0), height.get() - px(9.0) - thumb / 2.0); + cx.simulate_mouse_move(last, None, Modifiers::none()); + cx.simulate_click(last, Modifiers::none()); + settle(cx); + assert_eq!( + view.read_with(cx, |strip, _| strip.asked.clone()), + [7], + "the eighth frame sits in view" + ); +} + +/// A 4:3 screen in a 480px column, and its height as drawn. +struct Screen { + height: Rc>, +} + +impl Render for Screen { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let height = self.height.clone(); + div().child( + div() + .relative() + .w(px(480.0)) + .child( + ComputerUseViewer::new("screen", "a.png") + .ratio(4.0 / 3.0) + .pointer(point(0.5, 0.95)), + ) + .child( + canvas( + move |bounds, _, _| height.set(bounds.size.height), + |_, _, _, _| {}, + ) + .absolute() + .top_0() + .left_0() + .size_full(), + ), + ) + } +} + +#[gpui::test] +fn a_screen_takes_its_pictures_shape(cx: &mut TestAppContext) { + setup(cx); + let height = Rc::new(Cell::new(Pixels::ZERO)); + let seen = height.clone(); + let (_, cx) = cx.add_window_view(|_, _| Screen { height: seen }); + settle(cx); + let expected = px(478.0 * 3.0 / 4.0 + 2.0); + assert!( + (height.get() - expected).abs() < px(1.0), + "478px inside the border at 4:3, plus the border: {:?} vs {expected:?}", + height.get() + ); +} + +#[gpui::test] +fn previews_fill_a_column_their_block_measures_by_content(cx: &mut TestAppContext) { + setup(cx); + let widths = [ + narrow_width(cx, "preview-root", |_, _| { + BrowserPreview::new("browser", "localhost", ["a.png"], 0).into_any_element() + }), + narrow_width(cx, "preview-root", |_, _| { + ComputerUseViewer::new("screen", "a.png").into_any_element() + }), + narrow_width(cx, "preview-root", |_, _| { + LivePreview::new("live", "localhost", div()).into_any_element() + }), + ]; + assert_eq!( + widths, + [px(240.0); 3], + "each preview spans the card inside its padding" + ); +} diff --git a/vendor/ely/src/agent/tools.rs b/vendor/ely/src/agent/tools.rs new file mode 100644 index 00000000..af6b8070 --- /dev/null +++ b/vendor/ely/src/agent/tools.rs @@ -0,0 +1,240 @@ +use std::time::Duration; + +use gpui::{ + AnyElement, App, Div, ElementId, Entity, FontWeight, InteractiveElement, IntoElement, + MouseButton, ParentElement, RenderOnce, SharedString, Stateful, StatefulInteractiveElement, + Styled, Window, div, prelude::*, transparent_black, +}; +use smallvec::SmallVec; + +use crate::{ + chat::{CodeBlock, StepState, step_mark}, + primitives::{Disclosure, FocusRing, Icon, IconName, Severity}, + theme::{ActiveTheme, IconSize, Radius, TextSize}, + typography::{Ellipsis, format::took, tabular}, +}; + +/// A row that opens a body through `toggle`: a Tab stop while it has one. +fn header(id: ElementId, toggle: Option>, cx: &App) -> Stateful
    { + let theme = cx.theme(); + div() + .id(id.clone()) + .w_full() + .flex() + .items_center() + .gap_2() + .px_3() + .py_2() + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(transparent_black()) + .when_some(toggle, |row, state| { + row.tab_index(0) + .focus_ring(cx) + .cursor_pointer() + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .on_click(move |_, _, cx| { + state.update(cx, |open, cx| { + *open = !*open; + log::info!("tool call: open {open}"); + cx.notify(); + }) + }) + }) +} + +/// One call to a tool: its status, name, what it touched and how long it took; opened, its arguments and what came back. +#[derive(IntoElement)] +pub struct ToolCallCard { + id: ElementId, + name: SharedString, + status: StepState, + summary: Option, + took: Option, + arguments: Option, + result: Option, +} + +impl ToolCallCard { + pub fn new(id: impl Into, name: impl Into, status: StepState) -> Self { + Self { + id: id.into(), + name: name.into(), + status, + summary: None, + took: None, + arguments: None, + result: None, + } + } + + /// A few words on what the call touched, such as a path or a query. + pub fn summary(mut self, text: impl Into) -> Self { + self.summary = Some(text.into()); + self + } + + pub fn took(mut self, took: Duration) -> Self { + self.took = Some(took); + self + } + + /// The arguments, as JSON. + pub fn arguments(mut self, json: impl Into) -> Self { + self.arguments = Some(json.into()); + self + } + + /// What came back, or the error when the call failed. + pub fn result(mut self, text: impl Into) -> Self { + self.result = Some(text.into()); + self + } +} + +impl RenderOnce for ToolCallCard { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let state = window.use_keyed_state((self.id.clone(), "open"), cx, |_, _| false); + let open = *state.read(cx); + let opens = self.arguments.is_some() || self.result.is_some(); + let failed = self.status == StepState::Failed; + let mark = step_mark((self.id.clone(), "mark").into(), self.status, window, cx); + let theme = cx.theme(); + let colors = theme.colors.clone(); + let label = |text: &'static str| { + div() + .text_size(theme.text_size(TextSize::Xs)) + .font_weight(FontWeight::MEDIUM) + .text_color(colors.fg_subtle) + .child(text) + }; + div() + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(colors.border) + .bg(colors.surface) + .text_size(theme.text_size(TextSize::Sm)) + .child( + header( + (self.id.clone(), "header").into(), + opens.then_some(state), + cx, + ) + .child(mark) + .child( + div() + .min_w_0() + .font_family(theme.mono_family.clone()) + .text_color(colors.fg) + .child(Ellipsis::new(self.name)), + ) + .child( + div() + .flex_1() + .min_w_0() + .text_color(colors.fg_muted) + .children(self.summary.map(Ellipsis::new)), + ) + .children(self.took.map(|spent| { + tabular(div().flex_none().text_color(colors.fg_subtle)).child(took(spent)) + })) + .when(opens, |row| { + row.child( + Disclosure::new((self.id.clone(), "chevron"), open).size(IconSize::Sm), + ) + }), + ) + .when(open && opens, |card| { + card.child( + div() + .flex() + .flex_col() + .gap_2() + .px_3() + .pt_1() + .pb_3() + .children(self.arguments.map(|json| { + div() + .flex() + .flex_col() + .gap_1() + .child(label("Arguments")) + .child( + CodeBlock::new((self.id.clone(), "arguments"), json) + .language("json"), + ) + })) + .children(self.result.map(|text| { + div() + .flex() + .flex_col() + .gap_1() + .child(label(if failed { "Error" } else { "Result" })) + .child(if failed { + div() + .text_color(Severity::Danger.color(&colors)) + .child(text) + .into_any_element() + } else { + CodeBlock::new((self.id.clone(), "result"), text) + .into_any_element() + }) + })), + ) + }) + } +} + +/// Several tool calls under one line, shut until opened, such as "Read 3 files". +#[derive(IntoElement)] +pub struct ToolCallGroup { + id: ElementId, + label: SharedString, + calls: SmallVec<[AnyElement; 4]>, +} + +impl ToolCallGroup { + pub fn new(id: impl Into, label: impl Into) -> Self { + Self { + id: id.into(), + label: label.into(), + calls: SmallVec::new(), + } + } +} + +impl ParentElement for ToolCallGroup { + fn extend(&mut self, elements: impl IntoIterator) { + self.calls.extend(elements); + } +} + +impl RenderOnce for ToolCallGroup { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let state = window.use_keyed_state((self.id.clone(), "open"), cx, |_, _| false); + let open = *state.read(cx); + let theme = cx.theme(); + let colors = theme.colors.clone(); + div() + .flex() + .flex_col() + .gap_2() + .text_size(theme.text_size(TextSize::Sm)) + .child( + header((self.id.clone(), "header").into(), Some(state), cx) + .px_1() + .py_0p5() + .text_color(colors.fg_muted) + .child( + Icon::new(IconName::Wrench) + .size(IconSize::Sm) + .color(colors.fg_subtle), + ) + .child(div().flex_1().min_w_0().child(Ellipsis::new(self.label))) + .child(Disclosure::new((self.id.clone(), "chevron"), open).size(IconSize::Sm)), + ) + .when(open, |group| { + group.child(div().flex().flex_col().gap_2().pl_3().children(self.calls)) + }) + } +} diff --git a/vendor/ely/src/assets.rs b/vendor/ely/src/assets.rs new file mode 100644 index 00000000..8c70d69b --- /dev/null +++ b/vendor/ely/src/assets.rs @@ -0,0 +1,138 @@ +use std::borrow::Cow; + +use anyhow::Context as _; +use gpui::{App, AssetSource, Result, SharedString}; +use rust_embed::RustEmbed; + +/// Icons and fonts. Pass to `Application::with_assets`, alone or through `Assets::before`. +#[derive(RustEmbed)] +#[folder = "assets"] +pub struct Assets; + +impl AssetSource for Assets { + fn load(&self, path: &str) -> Result>> { + Ok(Self::get(path).map(|file| file.data)) + } + + fn list(&self, path: &str) -> Result> { + Ok(Self::iter() + .filter(|name| name.starts_with(path)) + .map(SharedString::from) + .collect()) + } +} + +pub(crate) fn load_fonts(cx: &App) -> Result<()> { + let fonts = Assets::iter() + .filter(|name| name.ends_with(".ttf")) + .map(|name| { + Assets::get(&name) + .map(|file| file.data) + .with_context(|| format!("font {name} vanished from the bundle")) + }) + .collect::>>()?; + log::info!("assets: registering {} fonts", fonts.len()); + cx.text_system().add_fonts(fonts) +} + +/// Ely's files first, then another source's: one source for an app that runs both. +pub struct Before(T); + +impl Assets { + /// Serves Ely's files, and every other path from `other`, such as GPUI Kit's `Assets`. + pub fn before(other: T) -> Before { + Before(other) + } +} + +impl AssetSource for Before { + fn load(&self, path: &str) -> Result>> { + match Assets.load(path)? { + Some(data) => Ok(Some(data)), + None => self.0.load(path), + } + } + + fn list(&self, path: &str) -> Result> { + let mut names = Assets.list(path)?; + names.extend(self.0.list(path)?); + names.sort(); + names.dedup(); + Ok(names) + } +} + +/// Ely's files the source cannot load, each with the reason. +pub(crate) fn missing(source: &dyn AssetSource) -> Vec { + Assets::iter() + .filter_map(|path| match source.load(&path) { + Ok(Some(_)) => None, + Ok(None) => Some(format!("{path}: not found")), + Err(error) => Some(format!("{path}: {error}")), + }) + .collect() +} + +#[cfg(test)] +mod tests { + use std::borrow::Cow; + + use gpui::{AssetSource, Result, SharedString}; + + use super::{Assets, missing}; + + const PLEX: &str = "fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf"; + + /// Icons alone, and an error for any other path, as GPUI Kit's source answers. + struct IconsOnly; + + impl AssetSource for IconsOnly { + fn load(&self, path: &str) -> Result>> { + if path == "icons/kit-only.svg" { + return Ok(Some(Cow::Borrowed(b""))); + } + match Assets.load(path)? { + Some(data) if path.starts_with("icons/") => Ok(Some(data)), + _ => Err(anyhow::anyhow!("could not find asset at path {path}")), + } + } + + fn list(&self, _: &str) -> Result> { + Ok(vec!["icons/check.svg".into(), "icons/kit-only.svg".into()]) + } + } + + #[test] + fn ely_s_own_source_holds_every_file() { + assert_eq!(missing(&Assets), Vec::::new()); + } + + #[test] + fn an_icons_only_source_lacks_ely_s_fonts() { + let missing = missing(&IconsOnly); + assert!( + missing.iter().any(|line| line.starts_with(PLEX)), + "{missing:?}" + ); + } + + #[test] + fn ely_s_files_come_first_then_the_other_s() { + let both = Assets::before(IconsOnly); + assert_eq!(missing(&both), Vec::::new()); + let plex = both.load(PLEX).unwrap().unwrap(); + assert_eq!(plex, Assets.load(PLEX).unwrap().unwrap()); + assert_eq!( + &*both.load("icons/kit-only.svg").unwrap().unwrap(), + b"" + ); + assert!(both.load("icons/neither.svg").is_err()); + let icons = both.list("icons/").unwrap(); + let checks = icons + .iter() + .filter(|name| *name == "icons/check.svg") + .count(); + assert_eq!(checks, 1); + assert!(icons.iter().any(|name| name == "icons/kit-only.svg")); + } +} diff --git a/vendor/ely/src/buttons/bars.rs b/vendor/ely/src/buttons/bars.rs new file mode 100644 index 00000000..b6164fb4 --- /dev/null +++ b/vendor/ely/src/buttons/bars.rs @@ -0,0 +1,161 @@ +use std::rc::Rc; + +use gpui::{ + Animation, AnimationExt, AnyElement, App, Div, ElementId, IntoElement, ParentElement, + RenderOnce, StyleRefinement, Styled, Window, div, prelude::*, +}; +use smallvec::SmallVec; + +use super::IconButton; +use crate::{ + motion, + primitives::IconName, + theme::{ActiveTheme, ControlSize, Elevation, TextSize}, + typography::AnimatedNumber, +}; + +/// Actions in a row at a region's foot: docked, or floating as a pill. +#[derive(IntoElement)] +pub struct ActionBar { + base: Div, + floating: bool, + children: SmallVec<[AnyElement; 4]>, +} + +impl ActionBar { + pub fn new() -> Self { + Self { + base: div(), + floating: false, + children: SmallVec::new(), + } + } + + /// A raised pill instead of a full-width strip. + pub fn floating(mut self) -> Self { + self.floating = true; + self + } +} + +impl Default for ActionBar { + fn default() -> Self { + Self::new() + } +} + +impl Styled for ActionBar { + fn style(&mut self) -> &mut StyleRefinement { + self.base.style() + } +} + +impl ParentElement for ActionBar { + fn extend(&mut self, elements: impl IntoIterator) { + self.children.extend(elements); + } +} + +impl RenderOnce for ActionBar { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = &theme.colors; + let bar = self.base.flex().items_center().gap_2(); + let bar = if self.floating { + bar.p_1p5() + .rounded_full() + .bg(colors.overlay) + .border_1() + .border_color(colors.border) + .shadow(theme.elevation(Elevation::Floating)) + } else { + bar.justify_end() + .px_4() + .py_3() + .bg(colors.surface) + .border_t_1() + .border_color(colors.border) + }; + bar.children(self.children).with_animation( + "action-bar-in", + Animation::new(motion::duration(motion::BASE, cx)).with_easing(motion::ease_out_cubic), + |bar, t| bar.opacity(t).mt(motion::NUDGE * 2.0 * (1.0 - t)), + ) + } +} + +type OnClear = Rc; + +/// Rises when items are selected: the count, bulk actions, and a clear button. +#[derive(IntoElement)] +pub struct BulkActionBar { + id: ElementId, + count: usize, + actions: SmallVec<[AnyElement; 4]>, + on_clear: Option, +} + +impl BulkActionBar { + pub fn new(id: impl Into, count: usize) -> Self { + Self { + id: id.into(), + count, + actions: SmallVec::new(), + on_clear: None, + } + } + + pub fn action(mut self, action: impl IntoElement) -> Self { + self.actions.push(action.into_any_element()); + self + } + + pub fn on_clear(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_clear = Some(Rc::new(handler)); + self + } +} + +impl RenderOnce for BulkActionBar { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + if self.count == 0 { + return div().into_any_element(); + } + let theme = cx.theme(); + let colors = &theme.colors; + ActionBar::new() + .floating() + .child( + div() + .flex() + .items_center() + .gap_1() + .pl_2() + .text_size(theme.text_size(TextSize::Sm)) + .text_color(colors.fg) + .child( + AnimatedNumber::new(self.id.clone(), self.count as f64).size(TextSize::Sm), + ) + .child("selected"), + ) + .child( + div() + .h(theme.control_height(ControlSize::Sm)) + .border_l_1() + .border_color(colors.border), + ) + .children(self.actions) + .when_some(self.on_clear, |bar, clear| { + bar.child( + IconButton::new("bulk-clear", IconName::X) + .size(ControlSize::Sm) + .tooltip("Clear selection") + .on_click(move |_, window, cx| { + log::info!("bulk action bar: cleared"); + clear(window, cx) + }), + ) + }) + .into_any_element() + } +} diff --git a/vendor/ely/src/buttons/button.rs b/vendor/ely/src/buttons/button.rs new file mode 100644 index 00000000..d895dfd2 --- /dev/null +++ b/vendor/ely/src/buttons/button.rs @@ -0,0 +1,329 @@ +use gpui::{ + App, ClickEvent, ElementId, FocusHandle, FontWeight, Hsla, IntoElement, MouseButton, + RenderOnce, Role, SharedString, StatefulInteractiveElement, Window, div, prelude::*, + transparent_black, +}; + +use crate::{ + i18n, + motion::Spinner, + primitives::{FocusRing, Icon, IconName}, + theme::{ActiveTheme, ControlSize, IconSize, Mix, Palette, Platform, Radius, TextSize}, + typography::{ + Ellipsis, + keys::{keystroke, keystroke_labels}, + }, +}; + +pub(crate) type ClickHandler = Box; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum ButtonVariant { + Primary, + #[default] + Secondary, + Outline, + Ghost, + Subtle, + /// Confirms a gain, such as a purchase; green. + Success, + Danger, + Link, +} + +pub(crate) struct Tone { + pub bg: Hsla, + pub hover: Hsla, + pub pressed: Hsla, + pub fg: Hsla, + pub border: Hsla, +} + +pub(crate) fn tone(variant: ButtonVariant, colors: &Palette) -> Tone { + let clear = transparent_black(); + match variant { + ButtonVariant::Primary => Tone { + bg: colors.accent, + hover: colors.accent_hover, + pressed: colors.accent_hover.mix(&colors.on_accent, 0.12), + fg: colors.on_accent, + border: clear, + }, + ButtonVariant::Secondary => Tone { + bg: colors.surface, + hover: colors.hover, + pressed: colors.active, + fg: colors.fg, + border: colors.border, + }, + ButtonVariant::Outline => Tone { + bg: clear, + hover: colors.hover, + pressed: colors.active, + fg: colors.fg, + border: colors.border_strong, + }, + ButtonVariant::Ghost => Tone { + bg: clear, + hover: colors.hover, + pressed: colors.active, + fg: colors.fg, + border: clear, + }, + ButtonVariant::Subtle => Tone { + bg: colors.hover, + hover: colors.active, + pressed: colors.active.mix(&colors.border_strong, 0.5), + fg: colors.fg, + border: clear, + }, + ButtonVariant::Success => Tone { + bg: colors.success, + hover: colors.success.mix(&colors.fg, 0.14), + pressed: colors.success.mix(&colors.fg, 0.24), + fg: colors.on_accent, + border: clear, + }, + ButtonVariant::Danger => Tone { + bg: colors.danger, + hover: colors.danger.mix(&colors.fg, 0.14), + pressed: colors.danger.mix(&colors.fg, 0.24), + fg: colors.on_accent, + border: clear, + }, + ButtonVariant::Link => Tone { + bg: clear, + hover: clear, + pressed: clear, + fg: colors.link, + border: clear, + }, + } +} + +pub(crate) fn label_size(size: ControlSize) -> (TextSize, IconSize) { + match size { + ControlSize::Sm => (TextSize::Sm, IconSize::Xs), + ControlSize::Md => (TextSize::Base, IconSize::Sm), + ControlSize::Lg => (TextSize::Md, IconSize::Md), + } +} + +/// Where a button sits inside a `ButtonGroup`. +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) enum Slot { + First, + Middle, + Last, +} + +/// Fails on a keystroke gpui cannot read, when a builder takes it. +pub(crate) fn keystroke_of(source: &str) { + keystroke(source, Platform::current()); +} + +/// A keystroke in gpui key syntax as `platform` spells it: `⌘S`, or `Ctrl+S`. +pub(crate) fn shortcut_text(source: &str, platform: Platform) -> String { + let glue = if platform == Platform::Mac { "" } else { "+" }; + keystroke_labels(&keystroke(source, platform), platform).join(glue) +} + +#[derive(IntoElement)] +pub struct Button { + id: ElementId, + label: SharedString, + icon: Option, + trailing_icon: Option, + shortcut: Option, + variant: ButtonVariant, + size: ControlSize, + disabled: bool, + loading: bool, + full_width: bool, + focus: Option, + pub(crate) slot: Option, + on_click: Option, +} + +impl Button { + pub fn new(id: impl Into, label: impl Into) -> Self { + Self { + id: id.into(), + label: label.into(), + icon: None, + trailing_icon: None, + shortcut: None, + variant: ButtonVariant::default(), + size: ControlSize::default(), + disabled: false, + loading: false, + full_width: false, + focus: None, + slot: None, + on_click: None, + } + } + + pub fn variant(mut self, variant: ButtonVariant) -> Self { + self.variant = variant; + self + } + + pub fn primary(self) -> Self { + self.variant(ButtonVariant::Primary) + } + + pub fn size(mut self, size: ControlSize) -> Self { + self.size = size; + self + } + + pub fn icon(mut self, icon: IconName) -> Self { + self.icon = Some(icon); + self + } + + pub fn trailing_icon(mut self, icon: IconName) -> Self { + self.trailing_icon = Some(icon); + self + } + + /// Shows the keystroke that also runs it, e.g. `"cmd-s"`. Panics on a bad keystroke. + pub fn shortcut(mut self, keystroke: &str) -> Self { + keystroke_of(keystroke); + self.shortcut = Some(SharedString::from(keystroke.to_string())); + self + } + + /// Takes focus through the owner's handle, one that outlives a mode where the button changes; a Tab stop when built with `tab_stop`. + pub fn focus_handle(mut self, handle: &FocusHandle) -> Self { + self.focus = Some(handle.clone()); + self + } + + pub fn disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } + + /// Spins in place of its content, at the same width, and ignores presses. Tab still reaches it. + pub fn loading(mut self, loading: bool) -> Self { + self.loading = loading; + self + } + + pub fn full_width(mut self) -> Self { + self.full_width = true; + self + } + + pub fn on_click( + mut self, + handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_click = Some(Box::new(handler)); + self + } +} + +impl RenderOnce for Button { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let tone = tone(self.variant, &theme.colors); + let (text, icon_size) = label_size(self.size); + let link = self.variant == ButtonVariant::Link; + let icon = |name| Icon::new(name).size(icon_size).color(tone.fg); + let radius = theme.radius(Radius::Md); + let platform = cx.theme().platform; + let hint = self.shortcut.map(|source| shortcut_text(&source, platform)); + let spinner = (self.id.clone(), "spinner"); + let name = self.label.clone(); + let parts = div() + .flex() + .min_w_0() + .items_center() + .gap_1p5() + .when_some(self.icon, |el, name| el.child(icon(name))) + .when(!self.label.is_empty(), |el| { + el.child(div().min_w_0().child(Ellipsis::new(self.label))) + }) + .when_some(self.trailing_icon, |el, name| el.child(icon(name))) + .when_some(hint, |el, hint| { + el.child( + div() + .pl_1() + .font_weight(FontWeight::NORMAL) + .text_color(tone.fg.opacity(0.55)) + .child(hint), + ) + }); + + div() + .id(self.id) + .role(Role::Button) + .when(!name.is_empty(), |el| el.aria_label(name)) + .flex() + // Never grows; shrinks only when a row cannot wrap. + .flex_grow_0() + .flex_shrink_1() + .min_w_0() + .items_center() + .justify_center() + .gap_1p5() + .h(theme.control_height(self.size)) + .when(!link, |el| el.px(theme.control_padding(self.size))) + .border_1() + .border_color(tone.border) + .map(|el| match self.slot { + None => el.rounded(radius), + Some(Slot::First) => el.rounded_l(radius), + Some(Slot::Middle) => el.border_l_0(), + Some(Slot::Last) => el.rounded_r(radius).border_l_0(), + }) + .text_size(theme.text_size(text)) + .font_weight(FontWeight::MEDIUM) + .text_color(tone.fg) + .bg(tone.bg) + .when(self.full_width, |el| el.w_full()) + .map(|el| { + if !self.loading { + return el.child(parts); + } + el.relative().child(parts.invisible()).child( + div() + .absolute() + .inset_0() + .flex() + .items_center() + .justify_center() + .child(Spinner::new(spinner).size(icon_size).color(tone.fg)), + ) + }) + .map(|el| { + if self.disabled { + return el + .aria_description(i18n::text(cx, "state.unavailable", &[])) + .opacity(0.45) + .cursor_not_allowed(); + } + let el = match &self.focus { + Some(handle) => el.track_focus(handle), + None => el.tab_index(0), + }; + if self.loading { + return el + .focus_ring(cx) + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()); + } + el.cursor_pointer() + .hover(|style| { + let style = style.bg(tone.hover); + if link { style.underline() } else { style } + }) + .active(|style| style.bg(tone.pressed)) + .focus_ring(cx) + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .when_some(self.on_click, |el, handler| el.on_click(handler)) + }) + } +} diff --git a/vendor/ely/src/buttons/confirm.rs b/vendor/ely/src/buttons/confirm.rs new file mode 100644 index 00000000..7d125d8c --- /dev/null +++ b/vendor/ely/src/buttons/confirm.rs @@ -0,0 +1,289 @@ +use std::{rc::Rc, time::Duration}; + +use gpui::{ + Animation, AnimationExt, App, ElementId, FontWeight, InteractiveElement, IntoElement, + MouseButton, ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Task, + Window, div, prelude::*, relative, +}; + +use super::button::{ButtonVariant, label_size, tone}; +use crate::{ + motion, + primitives::{FocusRing, Icon, IconName}, + theme::{ActiveTheme, ControlSize, Radius}, +}; + +/// How long a hold takes to confirm. +const HOLD: Duration = Duration::from_millis(1200); +/// How long a first click stays armed. +const ARMED: Duration = Duration::from_millis(3000); +/// How long the done state shows. +const DONE: Duration = Duration::from_millis(1400); + +/// Hold the button down, or click it twice. Keys always press twice. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ConfirmMode { + Hold, + Twice, +} + +#[derive(Default)] +struct Confirm { + holding: bool, + armed: bool, + done: bool, + generation: u64, + _timer: Option>, +} + +type OnConfirm = Rc; + +/// A destructive button that asks twice: by holding, or by a second click. +#[derive(IntoElement)] +pub struct ConfirmButton { + id: ElementId, + label: SharedString, + armed_label: SharedString, + mode: ConfirmMode, + size: ControlSize, + on_confirm: Option, +} + +impl ConfirmButton { + pub fn new( + id: impl Into, + label: impl Into, + mode: ConfirmMode, + ) -> Self { + let label = label.into(); + Self { + id: id.into(), + armed_label: match mode { + ConfirmMode::Hold => "Press again to confirm".into(), + ConfirmMode::Twice => "Click again to confirm".into(), + }, + label, + mode, + size: ControlSize::default(), + on_confirm: None, + } + } + + /// The label while waiting for the second click. + pub fn armed_label(mut self, label: impl Into) -> Self { + self.armed_label = label.into(); + self + } + + pub fn size(mut self, size: ControlSize) -> Self { + self.size = size; + self + } + + pub fn on_confirm(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self { + self.on_confirm = Some(Rc::new(handler)); + self + } +} + +/// Clears `field` after `after`, unless a newer change came first. +fn expire( + state: &gpui::Entity, + after: Duration, + clear: fn(&mut Confirm), + window: &mut Window, + cx: &mut App, +) -> Task<()> { + let (weak, generation) = (state.downgrade(), state.read(cx).generation); + window.spawn(cx, async move |cx| { + cx.background_executor().timer(after).await; + let cleared = cx.update(|_, cx| { + weak.update(cx, |confirm, cx| { + if confirm.generation == generation { + clear(confirm); + cx.notify(); + } + }) + }); + if let Err(error) = cleared.and_then(|inner| inner) { + log::error!("confirm button: state gone before it expired: {error:#}"); + } + }) +} + +fn confirm_now( + state: &gpui::Entity, + handler: &Option, + window: &mut Window, + cx: &mut App, +) { + log::info!("confirm button: confirmed"); + state.update(cx, |confirm, _| { + confirm.holding = false; + confirm.armed = false; + confirm.done = true; + confirm.generation += 1; + }); + let timer = expire(state, DONE, |confirm| confirm.done = false, window, cx); + state.update(cx, |confirm, cx| { + confirm._timer = Some(timer); + cx.notify(); + }); + if let Some(handler) = handler { + handler(window, cx); + } +} + +impl RenderOnce for ConfirmButton { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let state = window.use_keyed_state(self.id.clone(), cx, |_, _| Confirm::default()); + let (holding, armed, done, generation) = { + let confirm = state.read(cx); + ( + confirm.holding, + confirm.armed, + confirm.done, + confirm.generation, + ) + }; + let theme = cx.theme(); + let colors = &theme.colors; + let variant = if armed { + ButtonVariant::Danger + } else { + ButtonVariant::Outline + }; + let tone = tone(variant, colors); + let (text, icon_size) = label_size(self.size); + let label = if armed { + self.armed_label.clone() + } else { + self.label.clone() + }; + let fill = colors.danger.opacity(0.16); + let handler = self.on_confirm.clone(); + let (press, release, out, click) = + (state.clone(), state.clone(), state.clone(), state.clone()); + let hold = self.mode == ConfirmMode::Hold; + let (hold_handler, click_handler) = (handler.clone(), handler); + div() + .id(self.id) + .relative() + .overflow_hidden() + .flex() + .flex_none() + .items_center() + .justify_center() + .gap_1p5() + .h(theme.control_height(self.size)) + .px(theme.control_padding(self.size)) + .rounded(theme.radius(Radius::Md)) + .border_1() + .border_color(if holding { colors.danger } else { tone.border }) + .bg(tone.bg) + .text_size(theme.text_size(text)) + .font_weight(FontWeight::MEDIUM) + .text_color(if holding { colors.danger } else { tone.fg }) + .cursor_pointer() + .tab_index(0) + .focus_ring(cx) + .hover(|style| style.bg(tone.hover)) + .on_mouse_down(MouseButton::Left, move |_, window, cx| { + window.prevent_default(); + if !hold || press.read(cx).done { + return; + } + press.update(cx, |confirm, _| { + confirm.holding = true; + confirm.generation += 1; + }); + let (weak, handler) = (press.downgrade(), hold_handler.clone()); + let generation = press.read(cx).generation; + let timer = window.spawn(cx, async move |cx| { + cx.background_executor().timer(HOLD).await; + let held = cx.update(|window, cx| { + let Some(state) = weak.upgrade() else { + return; + }; + if state.read(cx).holding && state.read(cx).generation == generation { + confirm_now(&state, &handler, window, cx); + } + }); + if let Err(error) = held { + log::error!("confirm button: window gone during a hold: {error:#}"); + } + }); + press.update(cx, |confirm, cx| { + confirm._timer = Some(timer); + cx.notify(); + }); + }) + .on_mouse_up(MouseButton::Left, move |_, _, cx| let_go(&release, cx)) + .on_mouse_up_out(MouseButton::Left, move |_, _, cx| let_go(&out, cx)) + .on_click(move |event, window, cx| { + if (hold && !event.is_keyboard()) || click.read(cx).done { + return; + } + if click.read(cx).armed { + confirm_now(&click, &click_handler, window, cx); + return; + } + log::info!("confirm button: armed"); + click.update(cx, |confirm, _| { + confirm.armed = true; + confirm.generation += 1; + }); + let timer = expire(&click, ARMED, |confirm| confirm.armed = false, window, cx); + click.update(cx, |confirm, cx| { + confirm._timer = Some(timer); + cx.notify(); + }); + }) + .when(holding, |button| { + button.child( + div() + .absolute() + .top_0() + .bottom_0() + .left_0() + .bg(fill) + .with_animation( + ("confirm-hold", generation), + Animation::new(HOLD), + |bar, t| bar.w(relative(t)), + ), + ) + }) + .map(|button| { + if done { + button.child( + Icon::new(IconName::Check) + .size(icon_size) + .color(colors.success) + .with_animation( + ("confirm-done", generation), + Animation::new(motion::duration(motion::FAST, cx)) + .with_easing(motion::ease_out_cubic), + |icon, t| icon.rotate(gpui::radians((1.0 - t) * -0.6)), + ), + ) + } else { + button + } + }) + .child(label) + } +} + +fn let_go(state: &gpui::Entity, cx: &mut App) { + if !state.read(cx).holding { + return; + } + log::info!("confirm button: released early"); + state.update(cx, |confirm, cx| { + confirm.holding = false; + confirm.generation += 1; + confirm._timer = None; + cx.notify(); + }); +} diff --git a/vendor/ely/src/buttons/copy.rs b/vendor/ely/src/buttons/copy.rs new file mode 100644 index 00000000..44b84326 --- /dev/null +++ b/vendor/ely/src/buttons/copy.rs @@ -0,0 +1,97 @@ +use std::time::Duration; + +use gpui::{ + Animation, AnimationExt, App, ClipboardItem, ElementId, InteractiveElement, IntoElement, + ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Task, Window, div, + prelude::*, +}; + +use super::IconButton; +use crate::{ + motion, + primitives::{Icon, IconName, Tooltip}, + theme::{ActiveTheme, ControlSize, IconSize}, +}; + +const CONFIRM: Duration = Duration::from_millis(1400); + +#[derive(Default)] +struct Copied { + count: u32, + _reset: Option>, +} + +/// Copies text, then shows a check for a moment. +#[derive(IntoElement)] +pub struct CopyButton { + id: ElementId, + text: SharedString, +} + +impl CopyButton { + pub fn new(id: impl Into, text: impl Into) -> Self { + Self { + id: id.into(), + text: text.into(), + } + } +} + +impl RenderOnce for CopyButton { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let state = window.use_keyed_state(self.id.clone(), cx, |_, _| Copied::default()); + let count = state.read(cx).count; + let copied = state.read(cx)._reset.is_some(); + let theme = cx.theme(); + let success = theme.colors.success; + let text = self.text; + let button = IconButton::new("copy", IconName::Copy) + .size(ControlSize::Sm) + .on_click(move |_, window, cx| { + cx.write_to_clipboard(ClipboardItem::new_string(text.to_string())); + log::info!("copy button: {} characters copied", text.chars().count()); + let weak = state.downgrade(); + let reset = window.spawn(cx, async move |cx| { + cx.background_executor().timer(CONFIRM).await; + let cleared = cx.update(|_, cx| { + weak.update(cx, |copied, cx| { + copied._reset = None; + cx.notify(); + }) + }); + if let Err(error) = cleared.and_then(|inner| inner) { + log::error!("copy button: reset lost its state: {error:#}"); + } + }); + state.update(cx, |copied, cx| { + copied.count += 1; + copied._reset = Some(reset); + cx.notify(); + }); + }); + let check = Icon::new(IconName::Check) + .size(IconSize::Sm) + .color(success) + .with_animation( + ("copied", count), + Animation::new(motion::duration(motion::FAST, cx)) + .with_easing(motion::ease_out_cubic), + |icon, t| icon.rotate(gpui::radians((1.0 - t) * -0.6)), + ); + div() + .id(self.id) + .flex_none() + .size(theme.control_height(ControlSize::Sm)) + .flex() + .items_center() + .justify_center() + .tooltip(Tooltip::text(if copied { "Copied" } else { "Copy" })) + .map(|slot| { + if copied { + slot.child(check) + } else { + slot.child(button) + } + }) + } +} diff --git a/vendor/ely/src/buttons/fab.rs b/vendor/ely/src/buttons/fab.rs new file mode 100644 index 00000000..3bdf64ad --- /dev/null +++ b/vendor/ely/src/buttons/fab.rs @@ -0,0 +1,100 @@ +use gpui::{ + Animation, AnimationExt, App, ClickEvent, ElementId, FontWeight, InteractiveElement, + IntoElement, MouseButton, ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, + Styled, Window, div, prelude::*, +}; + +use super::button::ClickHandler; +use crate::{ + motion, + primitives::{FocusRing, Icon, IconName, Tooltip}, + theme::{ActiveTheme, Elevation, IconSize, TextSize}, +}; + +/// A raised round button for a screen's main action; a label makes it a pill. +#[derive(IntoElement)] +pub struct FloatingActionButton { + id: ElementId, + icon: IconName, + label: Option, + tooltip: Option, + on_click: Option, +} + +impl FloatingActionButton { + pub fn new(id: impl Into, icon: IconName) -> Self { + Self { + id: id.into(), + icon, + label: None, + tooltip: None, + on_click: None, + } + } + + pub fn label(mut self, label: impl Into) -> Self { + self.label = Some(label.into()); + self + } + + pub fn tooltip(mut self, text: impl Into) -> Self { + self.tooltip = Some(text.into()); + self + } + + pub fn on_click( + mut self, + handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, + ) -> Self { + self.on_click = Some(Box::new(handler)); + self + } +} + +impl RenderOnce for FloatingActionButton { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let theme = cx.theme(); + let colors = &theme.colors; + let side = theme.fab_size(); + let (hover, lifted) = (colors.accent_hover, theme.elevation(Elevation::Modal)); + div() + .id(self.id) + .flex() + .flex_none() + .items_center() + .justify_center() + .gap_2() + .h(side) + .map(|fab| match &self.label { + Some(_) => fab.pl_5().pr_6(), + None => fab.w(side), + }) + .rounded_full() + .bg(colors.accent) + .text_color(colors.on_accent) + .text_size(theme.text_size(TextSize::Md)) + .font_weight(FontWeight::MEDIUM) + .border_1() + .border_color(gpui::transparent_black()) + .shadow(theme.elevation(Elevation::Floating)) + .cursor_pointer() + .tab_index(0) + .focus_ring(cx) + .hover(move |style| style.bg(hover).shadow(lifted)) + .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default()) + .when_some(self.on_click, |fab, handler| fab.on_click(handler)) + .when_some(self.tooltip, |fab, text| fab.tooltip(Tooltip::text(text))) + .child( + Icon::new(self.icon) + .size(IconSize::Lg) + .color(colors.on_accent), + ) + .when_some(self.label, |fab, label| fab.child(label)) + .with_animation( + "fab-in", + Animation::new(motion::duration(motion::SLOW, cx)) + .with_easing(motion::ease_out_cubic), + |fab, t| fab.opacity(t).mt(motion::NUDGE * 2.0 * (1.0 - t)), + ) + } +} diff --git a/vendor/ely/src/buttons/group.rs b/vendor/ely/src/buttons/group.rs new file mode 100644 index 00000000..81265f61 --- /dev/null +++ b/vendor/ely/src/buttons/group.rs @@ -0,0 +1,340 @@ +use std::rc::Rc; + +use gpui::{ + App, ElementId, FontWeight, InteractiveElement, IntoElement, MouseButton, ParentElement, + RenderOnce, Role, SharedString, StatefulInteractiveElement, Styled, Window, div, prelude::*, +}; + +use super::{ + Button, + button::{Slot, label_size}, +}; +use crate::{ + i18n, + primitives::{FocusRing, Icon, IconName, Tooltip}, + theme::{ActiveTheme, ControlSize, Radius}, +}; + +/// Buttons joined edge to edge. +#[derive(IntoElement, Default)] +pub struct ButtonGroup { + buttons: Vec

    , +} + +impl ContentMask { + /// Scale the content mask's pixel units by the given scaling factor. + pub fn scale(&self, factor: f32) -> ContentMask { + ContentMask { + bounds: self.bounds.scale(factor), + } + } + + /// Intersect the content mask with the given content mask. + pub fn intersect(&self, other: &Self) -> Self { + let bounds = self.bounds.intersect(&other.bounds); + ContentMask { bounds } + } +} + +impl Window { + fn mark_view_dirty(&mut self, view_id: EntityId) { + // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors + // should already be dirty. + for view_id in self + .rendered_frame + .dispatch_tree + .view_path_reversed(view_id) + { + if !self.dirty_views.insert(view_id) { + break; + } + } + } + + pub(crate) fn refresh_visibility(&mut self, cx: &mut App) { + let visibility = self.platform_window.visibility(); + if self.visibility != visibility { + self.visibility = visibility; + #[cfg(feature = "profiler")] + profiler::journal::record_window_visibility(self.handle.window_id(), visibility); + self.visibility_observers + .clone() + .retain(&(), |callback| callback(visibility, self, cx)); + } + #[cfg(feature = "profiler")] + if self.invalidator.is_dirty() || self.needs_present.get() { + profiler::journal::record_frame_pending(self.handle.window_id(), Instant::now()); + } + } + + /// Whether the platform is presenting this window's frames (see + /// [`WindowVisibility`]). + pub fn visibility(&self) -> WindowVisibility { + self.visibility + } + + /// Whether frames drawn for this window will be shown. + /// + /// This is not the window's shown/hidden state: a shown window that is + /// fully behind another window, minimized, or on a sleeping display is not + /// visible here. + pub fn is_visible(&self) -> bool { + self.visibility.is_visible() + } + + /// Registers a callback to be invoked when the window's visibility changes. + pub fn observe_window_visibility( + &self, + mut callback: impl FnMut(WindowVisibility, &mut Window, &mut App) + 'static, + ) -> Subscription { + let (subscription, activate) = self.visibility_observers.insert( + (), + Box::new(move |visibility, window, cx| { + callback(visibility, window, cx); + true + }), + ); + activate(); + subscription + } + + /// Registers a callback to be invoked when the window appearance changes. + pub fn observe_window_appearance( + &self, + mut callback: impl FnMut(&mut Window, &mut App) + 'static, + ) -> Subscription { + let (subscription, activate) = self.appearance_observers.insert( + (), + Box::new(move |window, cx| { + callback(window, cx); + true + }), + ); + activate(); + subscription + } + + /// Registers a callback to be invoked when the window button layout changes. + pub fn observe_button_layout_changed( + &self, + mut callback: impl FnMut(&mut Window, &mut App) + 'static, + ) -> Subscription { + let (subscription, activate) = self.button_layout_observers.insert( + (), + Box::new(move |window, cx| { + callback(window, cx); + true + }), + ); + activate(); + subscription + } + + /// Replaces the root entity of the window with a new one. + pub fn replace_root( + &mut self, + cx: &mut App, + build_view: impl FnOnce(&mut Window, &mut Context) -> E, + ) -> Entity + where + E: 'static + Render, + { + let view = cx.new(|cx| build_view(self, cx)); + self.root = Some(view.clone().into()); + self.refresh(); + view + } + + /// Returns the root entity of the window, if it has one. + pub fn root(&self) -> Option>> + where + E: 'static + Render, + { + self.root + .as_ref() + .map(|view| view.clone().downcast::().ok()) + } + + /// Obtain a handle to the window that belongs to this context. + pub fn window_handle(&self) -> AnyWindowHandle { + self.handle + } + + /// Mark the window as dirty, scheduling it to be redrawn on the next frame. + pub fn refresh(&mut self) { + if self.invalidator.not_drawing() { + self.refreshing = true; + self.invalidator.set_dirty(true); + } + } + + /// Close this window. + pub fn remove_window(&mut self) { + self.removed = true; + } + + /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`. + pub fn focused(&self, cx: &App) -> Option { + self.focus + .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles)) + } + + /// While focus-lost listeners are being dispatched, returns the closest ancestor of the + /// previously focused element that can still receive focus, making it a suitable target + /// for focus restoration. Returns `None` at all other times, or when no such ancestor exists. + pub fn focus_lost_restore_target(&self, cx: &App) -> Option { + let (_leaf, ancestors) = self.focus_lost_path.split_last()?; + ancestors.iter().rev().find_map(|id| { + self.rendered_frame.dispatch_tree.focusable_node_id(*id)?; + FocusHandle::for_id(*id, &cx.focus_handles) + }) + } + + /// Move focus to the element associated with the given [`FocusHandle`]. + pub fn focus(&mut self, handle: &FocusHandle, cx: &mut App) { + if !self.focus_enabled || self.focus == Some(handle.id) { + return; + } + + self.focus = Some(handle.id); + self.focus_generation = self.focus_generation.wrapping_add(1); + self.clear_pending_keystrokes(cx); + + self.refresh(); + } + + /// Remove focus from all elements within this context's window. + pub fn blur(&mut self, cx: &mut App) { + self.clear_pending_keystrokes(cx); + + if !self.focus_enabled { + return; + } + + if self.focus.is_some() { + self.focus_generation = self.focus_generation.wrapping_add(1); + } + self.focus = None; + self.refresh(); + } + + /// Blur the window and don't allow anything in it to be focused again. + pub fn disable_focus(&mut self, cx: &mut App) { + self.blur(cx); + self.focus_enabled = false; + } + + /// Move focus to next tab stop. + pub fn focus_next(&mut self, cx: &mut App) { + if !self.focus_enabled { + return; + } + + if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) { + self.focus(&handle, cx) + } + } + + /// Move focus to previous tab stop. + pub fn focus_prev(&mut self, cx: &mut App) { + if !self.focus_enabled { + return; + } + + if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) { + self.focus(&handle, cx) + } + } + + /// Accessor for the text system. + pub fn text_system(&self) -> &Arc { + &self.text_system + } + + /// The current text style. Which is composed of all the style refinements provided to `with_text_style`. + pub fn text_style(&self) -> TextStyle { + let mut style = TextStyle::default(); + for refinement in &self.text_style_stack { + style.refine(refinement); + } + style + } + + /// Check if the platform window is maximized. + /// + /// On some platforms (namely Windows) this is different than the bounds being the size of the display + pub fn is_maximized(&self) -> bool { + self.platform_window.is_maximized() + } + + /// request a certain window decoration (Wayland) + pub fn request_decorations(&self, decorations: WindowDecorations) { + self.platform_window.request_decorations(decorations); + } + + /// Set the exclusive zone for a layer-shell surface: how much screen space it + /// reserves so other surfaces avoid occluding it (e.g. a panel reserving space). + /// Positive values reserve that distance from the anchored edge, 0 lets the + /// surface be moved out of others' exclusive zones, and -1 ignores reserved + /// space and may extend under other surfaces. (Wayland layer-shell windows only) + pub fn set_exclusive_zone(&self, zone: Pixels) { + self.platform_window.set_exclusive_zone(zone); + } + + /// Set which anchored edge a layer-shell surface's exclusive zone applies to. + /// This is only needed to disambiguate a corner-anchored surface; otherwise the + /// edge is deduced from the anchor. The edge must be a single edge the surface + /// is anchored to, or it is ignored. (Wayland layer-shell windows only) + #[cfg(all(target_os = "linux", feature = "wayland"))] + pub fn set_exclusive_edge(&self, edge: crate::layer_shell::Anchor) { + self.platform_window.set_exclusive_edge(edge); + } + + /// Start an interactive window resize operation if this window is resizable. + pub fn start_window_resize(&self, edge: ResizeEdge) { + if self.is_resizable { + self.platform_window.start_window_resize(edge); + } + } + + /// Linux (wayland) only: Set the window's input region, the area that receives pointer + /// and touch input. Events outside it pass through to whatever is below the window. + /// + /// - `Some(rects)` restricts input to the union of `rects`, in window coordinates. + /// - `Some(&[])` is an empty region, so the window receives no pointer or touch input. + /// - `None` resets the region to the default, so the whole window receives input again. + pub fn set_input_region(&self, region: Option<&[Bounds]>) { + self.platform_window.set_input_region(region); + } + + /// Return the `WindowBounds` to indicate that how a window should be opened + /// after it has been closed + pub fn window_bounds(&self) -> WindowBounds { + self.platform_window.window_bounds() + } + + /// Return the `WindowBounds` excluding insets (Wayland and X11) + pub fn inner_window_bounds(&self) -> WindowBounds { + self.platform_window.inner_window_bounds() + } + + /// Encode the window's native restorable state into an opaque blob. + /// Returns `None` on platforms without native state restoration or if encoding fails. + pub fn native_window_state(&self) -> Option> { + self.platform_window.native_window_state() + } + + /// Restore the window's native state from a blob previously produced + /// by [`Window::native_window_state`]. A no-op on platforms without native state restoration. + pub fn restore_native_window_state(&self, state: &[u8]) { + self.platform_window.restore_native_window_state(state); + } + + /// Dispatch the given action on the currently focused element. + pub fn dispatch_action(&mut self, action: Box, cx: &mut App) { + let focus_id = self.focused(cx).map(|handle| handle.id); + + let window = self.handle; + cx.defer(move |cx| { + window + .update(cx, |_, window, cx| { + let node_id = window.focus_node_id_in_rendered_frame(focus_id); + window.dispatch_action_on_node(node_id, action.as_ref(), cx); + }) + .log_err(); + }) + } + + pub(crate) fn dispatch_keystroke_observers( + &mut self, + keystroke: &Keystroke, + input_preference: InputPreference, + action: Option<&dyn Action>, + context_stack: Vec, + cx: &mut App, + ) { + cx.keystroke_observers.clone().retain(&(), move |callback| { + (callback)( + &KeystrokeEvent { + keystroke: keystroke.clone(), + input_preference, + action: action.map(|action| action.boxed_clone()), + context_stack: context_stack.clone(), + }, + self, + cx, + ) + }); + } + + pub(crate) fn dispatch_keystroke_interceptors( + &mut self, + keystroke: &Keystroke, + input_preference: InputPreference, + context_stack: Vec, + cx: &mut App, + ) { + cx.keystroke_interceptors + .clone() + .retain(&(), move |callback| { + (callback)( + &KeystrokeEvent { + keystroke: keystroke.clone(), + input_preference, + action: None, + context_stack: context_stack.clone(), + }, + self, + cx, + ) + }); + } + + /// Schedules the given function to be run at the end of the current effect cycle, allowing entities + /// that are currently on the stack to be returned to the app. + pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) { + let handle = self.handle; + cx.defer(move |cx| { + handle.update(cx, |_, window, cx| f(window, cx)).ok(); + }); + } + + /// Subscribe to events emitted by a entity. + /// The entity to which you're subscribing must implement the [`EventEmitter`] trait. + /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window. + pub fn observe( + &mut self, + observed: &Entity, + cx: &mut App, + mut on_notify: impl FnMut(Entity, &mut Window, &mut App) + 'static, + ) -> Subscription { + let entity_id = observed.entity_id(); + let observed = observed.downgrade(); + let window_handle = self.handle; + cx.new_observer( + entity_id, + Box::new(move |cx| { + window_handle + .update(cx, |_, window, cx| { + if let Some(handle) = observed.upgrade() { + on_notify(handle, window, cx); + true + } else { + false + } + }) + .unwrap_or(false) + }), + ) + } + + /// Subscribe to events emitted by a entity. + /// The entity to which you're subscribing must implement the [`EventEmitter`] trait. + /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window. + pub fn subscribe( + &mut self, + entity: &Entity, + cx: &mut App, + mut on_event: impl FnMut(Entity, &Evt, &mut Window, &mut App) + 'static, + ) -> Subscription + where + Emitter: EventEmitter, + Evt: 'static, + { + let entity_id = entity.entity_id(); + let handle = entity.downgrade(); + let window_handle = self.handle; + cx.new_subscription( + entity_id, + ( + TypeId::of::(), + Box::new(move |event, cx| { + window_handle + .update(cx, |_, window, cx| { + if let Some(entity) = handle.upgrade() { + let event = event.downcast_ref().expect("invalid event type"); + on_event(entity, event, window, cx); + true + } else { + false + } + }) + .unwrap_or(false) + }), + ), + ) + } + + /// Register a callback to be invoked when the given `Entity` is released. + pub fn observe_release( + &self, + entity: &Entity, + cx: &mut App, + mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static, + ) -> Subscription + where + T: 'static, + { + let entity_id = entity.entity_id(); + let window_handle = self.handle; + let (subscription, activate) = cx.release_listeners.insert( + entity_id, + Box::new(move |entity, cx| { + let entity = entity.downcast_mut().expect("invalid entity type"); + let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx)); + }), + ); + activate(); + subscription + } + + /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across + /// await points in async code. + pub fn to_async(&self, cx: &App) -> AsyncWindowContext { + AsyncWindowContext::new_context(cx.to_async(), self.handle) + } + + /// Schedule the given closure to be run directly after the current frame is rendered. + pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) { + RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback)); + self.platform_window.schedule_frame(); + // Next-frame callbacks create frame demand without dirtying the + // window, so the platform's frame source must be woken explicitly. + self.invalidator.wake_platform(); + } + + /// Schedule a frame to be drawn on the next animation frame. + /// + /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF. + /// It will cause the window to redraw on the next frame, even if no other changes have occurred. + /// + /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window. + /// + /// Callers driving purely decorative animations (spinners, pulses, and the + /// like) should prefer [`AnimationExt::with_animation`](crate::AnimationExt::with_animation), + /// which automatically respects [`App::reduce_motion`]. When using this + /// method directly for decorative motion, check [`App::reduce_motion`] + /// and skip the frame request when it is set. + pub fn request_animation_frame(&self) { + let entity = self.current_view(); + self.on_next_frame(move |_, cx| cx.notify(entity)); + } + + /// Runs all callbacks scheduled via [`Self::on_next_frame`], returning how many ran. + /// + /// Tests have no platform frame loop, so this simulates the delivery of the + /// next frame. + #[cfg(any(test, feature = "test-support"))] + pub fn simulate_next_frame(&mut self, cx: &mut App) -> usize { + let callbacks = self.next_frame_callbacks.take(); + let count = callbacks.len(); + for callback in callbacks { + callback(self, cx); + } + count + } + + /// Spawn the future returned by the given closure on the application thread pool. + /// The closure is provided a handle to the current window and an `AsyncWindowContext` for + /// use within your future. + #[track_caller] + pub fn spawn(&self, cx: &App, f: AsyncFn) -> Task + where + R: 'static, + AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static, + { + let handle = self.handle; + cx.spawn(async move |app| { + let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle); + f(&mut async_window_cx).await + }) + } + + /// Spawn the future returned by the given closure on the application thread + /// pool, with the given priority. The closure is provided a handle to the + /// current window and an `AsyncWindowContext` for use within your future. + #[track_caller] + pub fn spawn_with_priority( + &self, + priority: Priority, + cx: &App, + f: AsyncFn, + ) -> Task + where + R: 'static, + AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static, + { + let handle = self.handle; + cx.spawn_with_priority(priority, async move |app| { + let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle); + f(&mut async_window_cx).await + }) + } + + /// Notify the window that its bounds have changed. + /// + /// This updates internal state like `viewport_size` and `scale_factor` from + /// the platform window, then notifies observers. Normally called automatically + /// by the platform's resize callback, but exposed publicly for test infrastructure. + pub fn bounds_changed(&mut self, cx: &mut App) { + self.scale_factor = self.platform_window.scale_factor(); + self.viewport_size = self.platform_window.content_size(); + self.display_id = self.platform_window.display().map(|display| display.id()); + self.mouse_position = self.platform_window.mouse_position(); + + self.refresh(); + + self.bounds_observers + .clone() + .retain(&(), |callback| callback(self, cx)); + } + + /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays. + pub fn bounds(&self) -> Bounds { + self.platform_window.bounds() + } + + /// Renders the current frame's scene to a texture and returns the pixel data as an RGBA image. + /// This does not present the frame to screen - useful for visual testing where we want + /// to capture what would be rendered without displaying it or requiring the window to be visible. + #[cfg(any(test, feature = "test-support"))] + pub fn render_to_image(&self) -> anyhow::Result { + self.platform_window + .render_to_image(&self.rendered_frame.scene) + } + + /// Returns the quads in the most recently rendered frame's scene, so tests can assert on + /// painted output without rasterizing the frame. Quad bounds are in scaled pixels and are + /// not clipped; each quad carries the content mask it will be clipped to when drawn. Quads + /// whose bounds don't intersect their content mask are culled at paint time and won't appear. + #[cfg(any(test, feature = "test-support"))] + pub fn painted_quads(&self) -> Vec { + self.rendered_frame.scene.quads.clone() + } + + /// Returns the underlines in the most recently rendered frame's scene. + #[cfg(any(test, feature = "test-support"))] + pub fn painted_underlines(&self) -> Vec { + self.rendered_frame.scene.underlines.clone() + } + + /// Set the content size of the window. + pub fn resize(&mut self, size: Size) { + self.platform_window.resize(size); + } + + /// Returns whether or not the window is currently fullscreen + pub fn is_fullscreen(&self) -> bool { + self.platform_window.is_fullscreen() + } + + /// Returns whether the window is currently in simple (borderless) fullscreen, + /// where it covers the entire screen including the menu bar and notch area. + /// Always `false` on platforms other than macOS. + pub fn is_simple_fullscreen(&self) -> bool { + self.platform_window.is_simple_fullscreen() + } + + pub(crate) fn appearance_changed(&mut self, cx: &mut App) { + self.appearance = self.platform_window.appearance(); + + self.appearance_observers + .clone() + .retain(&(), |callback| callback(self, cx)); + } + + pub(crate) fn button_layout_changed(&mut self, cx: &mut App) { + self.button_layout_observers + .clone() + .retain(&(), |callback| callback(self, cx)); + } + + /// Returns the appearance of the current window. + pub fn appearance(&self) -> WindowAppearance { + self.appearance + } + + /// Returns the size of the drawable area within the window. + pub fn viewport_size(&self) -> Size { + self.viewport_size + } + + /// Returns the platform's visible viewport in window-local logical pixels. + /// + /// Unlike `viewport_size`, this can shrink or move when the keyboard opens. + /// During drawing this is a consistent frame snapshot. Outside drawing it + /// reflects the latest platform sample, not a synchronous geometry query. + pub fn visual_viewport_bounds(&self) -> Bounds { + self.platform_window.visual_viewport_bounds() + } + + /// Returns a conservative rectangle avoiding platform-known obscured content. + /// + /// Intersects the visual viewport with the full layout area inset by system + /// safe areas and keyboard occlusion. Unknown overlays cannot be excluded. + pub fn fully_visible_bounds(&self) -> Bounds { + let insets = self.platform_window.insets().effective(); + let viewport = self.viewport_size(); + let left = insets.left.max(Pixels::ZERO).min(viewport.width); + let top = insets.top.max(Pixels::ZERO).min(viewport.height); + let right = (viewport.width - insets.right.max(Pixels::ZERO)).max(left); + let bottom = (viewport.height - insets.bottom.max(Pixels::ZERO)).max(top); + let safe_bounds = Bounds::from_corners(point(left, top), point(right, bottom)); + let mut visible = safe_bounds.intersect(&self.visual_viewport_bounds()); + visible.size.width = visible.size.width.max(Pixels::ZERO); + visible.size.height = visible.size.height.max(Pixels::ZERO); + visible + } + + /// Requests the virtual keyboard for the currently focused text input. + /// + /// Call from a user gesture on platforms that require one. The platform may + /// decline the request; this does not change focus or the layout viewport. + pub fn request_virtual_keyboard(&self) { + self.platform_window.show_soft_keyboard(); + } + + /// Requests dismissal of the virtual keyboard without changing GPUI focus. + pub fn dismiss_virtual_keyboard(&self) { + self.platform_window.hide_soft_keyboard(); + } + + /// Returns whether this window is focused by the operating system (receiving key events). + pub fn is_window_active(&self) -> bool { + self.active.get() + } + + /// Returns whether this window is considered to be the window + /// that currently owns the mouse cursor. + /// On mac, this is equivalent to `is_window_active`. + pub fn is_window_hovered(&self) -> bool { + if cfg!(any( + target_os = "windows", + target_os = "linux", + target_os = "freebsd" + )) { + self.hovered.get() + } else { + self.is_window_active() + } + } + + /// Toggle zoom on the window. + pub fn zoom_window(&self) { + self.platform_window.zoom(); + } + + /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11) + pub fn show_window_menu(&self, position: Point) { + self.platform_window.show_window_menu(position) + } + + /// Handle window movement for Linux and macOS. + /// Tells the compositor to take control of window movement (Wayland and X11) + /// + /// Events may not be received during a move operation. + pub fn start_window_move(&self) { + self.platform_window.start_window_move() + } + + /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11) + pub fn set_client_inset(&mut self, inset: Pixels) { + self.client_inset = Some(inset); + self.platform_window.set_client_inset(inset); + } + + /// Returns the client_inset value by [`Self::set_client_inset`]. + pub fn client_inset(&self) -> Option { + self.client_inset + } + + /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11) + pub fn window_decorations(&self) -> Decorations { + self.platform_window.window_decorations() + } + + /// Returns whether this window is resizable. + pub fn is_resizable(&self) -> bool { + self.is_resizable + } + + /// Returns whether this window is minimizable. + pub fn is_minimizable(&self) -> bool { + self.is_minimizable + } + + /// Returns the controls supported by the platform. + pub fn window_controls(&self) -> WindowControls { + self.platform_window.window_controls() + } + + /// Updates the window's title at the platform level. + pub fn set_window_title(&mut self, title: &str) { + self.platform_window.set_title(title); + self.a11y.set_window_title(title.to_string()); + } + + /// Sets the position of the macOS traffic light buttons. + #[cfg(target_os = "macos")] + pub fn set_traffic_light_position(&self, position: Point) { + self.platform_window.set_traffic_light_position(position); + } + + /// Sets the application identifier. + pub fn set_app_id(&mut self, app_id: &str) { + self.platform_window.set_app_id(app_id); + } + + /// Sets the window background appearance. + pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) { + self.platform_window + .set_background_appearance(background_appearance); + } + + /// Mark the window as dirty at the platform level. + pub fn set_window_edited(&mut self, edited: bool) { + self.platform_window.set_edited(edited); + } + + /// Set the path of the file this window represents. + /// On macOS, this sets the window's accessibility document property (AXDocument). + pub fn set_document_path(&self, path: Option<&std::path::Path>) { + self.platform_window.set_document_path(path); + } + + /// Determine the display on which the window is visible. + pub fn display(&self, cx: &App) -> Option> { + cx.platform + .displays() + .into_iter() + .find(|display| Some(display.id()) == self.display_id) + } + + /// Show the platform character palette. + pub fn show_character_palette(&self) { + self.platform_window.show_character_palette(); + } + + /// The scale factor of the display associated with the window. For example, it could + /// return 2.0 for a "retina" display, indicating that each logical pixel should actually + /// be rendered as two pixels on screen. + pub fn scale_factor(&self) -> f32 { + self.scale_factor + } + + /// Overrides the display scale factor for tests. + #[cfg(any(test, feature = "test-support"))] + pub fn set_scale_factor(&mut self, scale_factor: f32) { + self.scale_factor = scale_factor; + self.refresh(); + } + + /// The size of an em for the base font of the application. Adjusting this value allows the + /// UI to scale, just like zooming a web page. + pub fn rem_size(&self) -> Pixels { + self.rem_size_override_stack + .last() + .copied() + .unwrap_or(self.rem_size) + } + + /// Sets the size of an em for the base font of the application. Adjusting this value allows the + /// UI to scale, just like zooming a web page. + pub fn set_rem_size(&mut self, rem_size: impl Into) { + self.rem_size = rem_size.into(); + } + + /// Acquire a globally unique identifier for the given ElementId. + /// Only valid for the duration of the provided closure. + pub fn with_global_id( + &mut self, + element_id: ElementId, + f: impl FnOnce(&GlobalElementId, &mut Self) -> R, + ) -> R { + self.with_id(element_id, |this| { + let global_id = GlobalElementId(Arc::from(&*this.element_id_stack)); + + f(&global_id, this) + }) + } + + /// Calls the provided closure with the element ID pushed on the stack. + #[inline] + pub fn with_id( + &mut self, + element_id: impl Into, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.element_id_stack.push(element_id.into()); + let result = f(self); + self.element_id_stack.pop(); + result + } + + /// Executes the provided function with the specified rem size. + /// + /// This method must only be called as part of element drawing. + // This function is called in a highly recursive manner in editor + // prepainting, make sure its inlined to reduce the stack burden + #[inline] + pub fn with_rem_size(&mut self, rem_size: Option>, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.invalidator.debug_assert_paint_or_prepaint(); + + if let Some(rem_size) = rem_size { + self.rem_size_override_stack.push(rem_size.into()); + let result = f(self); + self.rem_size_override_stack.pop(); + result + } else { + f(self) + } + } + + /// The line height associated with the current text style. + pub fn line_height(&self) -> Pixels { + self.text_style().line_height_in_pixels(self.rem_size()) + } + + /// Rounds a logical value to the nearest device pixel. + #[inline] + pub fn pixel_snap(&self, value: Pixels) -> Pixels { + px(round_to_device_pixel(value.0, self.scale_factor()) / self.scale_factor()) + } + + /// f64 variant of [`Self::pixel_snap`]. + #[inline] + pub fn pixel_snap_f64(&self, value: f64) -> f64 { + let scale_factor = f64::from(self.scale_factor()); + round_half_toward_zero_f64(value * scale_factor) / scale_factor + } + + /// Snaps a bounds' origin and size to the nearest device pixel. + #[inline] + pub fn pixel_snap_bounds(&self, bounds: Bounds) -> Bounds { + bounds.map(|c| self.pixel_snap(c)) + } + + /// Snaps a point's coordinates to the nearest device pixel. + #[inline] + pub fn pixel_snap_point(&self, position: Point) -> Point { + position.map(|c| self.pixel_snap(c)) + } + + /// Returns the snapped device-space bounds used to paint an underline. + pub fn underline_bounds( + &self, + origin: Point, + width: Pixels, + style: &UnderlineStyle, + ) -> Bounds { + let scale_factor = self.scale_factor(); + let thickness = self.snap_stroke(style.thickness); + let height = if style.wavy { + ScaledPixels(thickness.0 * 3.) + } else { + thickness + }; + Bounds { + origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))), + size: size(self.snap_stroke(width), height), + } + } + + /// Paints an underline excluding absolute device-space horizontal spans. + pub fn paint_underline_with_exclusions( + &mut self, + origin: Point, + width: Pixels, + style: &UnderlineStyle, + exclusions: &[Range], + ) { + self.invalidator.debug_assert_paint(); + let underline = self.underline(origin, width, style); + if exclusions.is_empty() { + self.next_frame.scene.insert_primitive(underline); + return; + } + + let bounds = underline.bounds.intersect(&underline.content_mask.bounds); + if bounds.is_empty() { + return; + } + + let mut exclusions = exclusions + .iter() + .filter_map(|span| { + let start = span.start.max(bounds.left()); + let end = span.end.min(bounds.right()); + (start < end).then_some(start..end) + }) + .collect::>(); + if exclusions.is_empty() { + self.next_frame.scene.insert_primitive(underline); + return; + } + exclusions.sort_unstable_by_key(|span| span.start); + + let mut paint_span = |start, end| { + self.next_frame.scene.insert_primitive(Underline { + content_mask: ContentMask { + bounds: Bounds::from_corners( + point(start, bounds.top()), + point(end, bounds.bottom()), + ), + }, + ..underline + }); + }; + let mut start = bounds.left(); + for exclusion in exclusions { + if start < exclusion.start { + paint_span(start, exclusion.start); + } + start = start.max(exclusion.end); + } + if start < bounds.right() { + paint_span(start, bounds.right()); + } + } + + fn underline(&self, origin: Point, width: Pixels, style: &UnderlineStyle) -> Underline { + Underline { + order: 0, + pad: 0, + bounds: self.underline_bounds(origin, width, style), + content_mask: self.snapped_content_mask(), + color: style + .color + .unwrap_or_default() + .opacity(self.element_opacity()), + thickness: self.snap_stroke(style.thickness), + wavy: style.wavy.into(), + } + } + + #[inline] + fn snap_bounds(&self, bounds: Bounds) -> Bounds { + let scale_factor = self.scale_factor(); + let left = round_to_device_pixel(bounds.left().0, scale_factor); + let top = round_to_device_pixel(bounds.top().0, scale_factor); + let right = round_to_device_pixel(bounds.right().0, scale_factor).max(left); + let bottom = round_to_device_pixel(bounds.bottom().0, scale_factor).max(top); + Bounds::from_corners( + point(ScaledPixels(left), ScaledPixels(top)), + point(ScaledPixels(right), ScaledPixels(bottom)), + ) + } + + /// Rounds half-to-zero but clamps any non-zero input up to 1 dp so thin strokes do not disappear. + #[inline] + fn snap_stroke(&self, value: Pixels) -> ScaledPixels { + ScaledPixels(round_stroke_to_device_pixel(value.0, self.scale_factor())) + } + + #[inline] + fn snap_border_widths(&self, edges: Edges) -> Edges { + edges.map(|e| self.snap_stroke(*e)) + } + + /// Floors the near edge and ceils the far edge, producing a strict superset of the raw region. + #[inline] + fn cover_bounds(&self, bounds: Bounds) -> Bounds { + let scale_factor = self.scale_factor(); + let left = floor_to_device_pixel(bounds.left().0, scale_factor); + let top = floor_to_device_pixel(bounds.top().0, scale_factor); + let right = ceil_to_device_pixel(bounds.right().0, scale_factor).max(left); + let bottom = ceil_to_device_pixel(bounds.bottom().0, scale_factor).max(top); + Bounds::from_corners( + point(ScaledPixels(left), ScaledPixels(top)), + point(ScaledPixels(right), ScaledPixels(bottom)), + ) + } + + #[inline] + fn snapped_content_mask(&self) -> ContentMask { + ContentMask { + bounds: self.cover_bounds(self.content_mask().bounds), + } + } + + /// Call to prevent the default action of an event. Currently only used to prevent + /// parent elements from becoming focused on mouse down. + pub fn prevent_default(&mut self) { + self.default_prevented = true; + } + + /// Obtain whether default has been prevented for the event currently being dispatched. + pub fn default_prevented(&self) -> bool { + self.default_prevented + } + + /// Determine whether the given action is available along the dispatch path to the currently focused element. + pub fn is_action_available(&self, action: &dyn Action, cx: &App) -> bool { + let node_id = + self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id)); + self.rendered_frame + .dispatch_tree + .is_action_available(action, node_id) + } + + /// Determine whether the given action is available along the dispatch path to the given focus_handle. + pub fn is_action_available_in(&self, action: &dyn Action, focus_handle: &FocusHandle) -> bool { + let node_id = self.focus_node_id_in_rendered_frame(Some(focus_handle.id)); + self.rendered_frame + .dispatch_tree + .is_action_available(action, node_id) + } + + /// The position of the mouse relative to the window. + pub fn mouse_position(&self) -> Point { + self.mouse_position + } + + /// Captures the pointer for the given hitbox. While captured, all mouse move and mouse up + /// events will be routed to listeners that check this hitbox's `is_hovered` status, + /// regardless of actual hit testing. This enables drag operations that continue + /// even when the pointer moves outside the element's bounds. + /// + /// The capture is automatically released on mouse up. + pub fn capture_pointer(&mut self, hitbox_id: HitboxId) { + self.captured_hitbox = Some(hitbox_id); + } + + /// Releases any active pointer capture. + pub fn release_pointer(&mut self) { + self.captured_hitbox = None; + } + + /// Returns the hitbox that has captured the pointer, if any. + pub fn captured_hitbox(&self) -> Option { + self.captured_hitbox + } + + /// Captures the current long press for the given entity. + /// + /// The capture is released when the gesture ends or is cancelled, or when + /// a replacement touch begins. A listener must also call + /// [`Self::prevent_default`] on the started event to claim the gesture. + pub fn capture_long_press(&mut self, entity: &Entity) { + self.long_press_capture = Some(entity.entity_id()); + } + + /// Returns whether the given entity has captured the current long press. + pub fn has_long_press_capture(&self, entity: &Entity) -> bool { + self.long_press_capture == Some(entity.entity_id()) + } + + /// The current state of the keyboard's modifiers + pub fn modifiers(&self) -> Modifiers { + self.modifiers + } + + /// Returns true if the last input event was keyboard-based (key press, tab navigation, etc.) + /// This is used for focus-visible styling to show focus indicators only for keyboard navigation. + pub fn last_input_was_keyboard(&self) -> bool { + self.last_input_modality == InputModality::Keyboard + } + + pub(crate) fn last_input_was_touch(&self) -> bool { + self.last_input_modality == InputModality::Touch + } + + /// The current state of the keyboard's capslock + pub fn capslock(&self) -> Capslock { + self.capslock + } + + /// Produces a new frame and assigns it to `rendered_frame`. To actually show + /// the contents of the new [`Scene`], use [`Self::present`]. + #[profiling::function] + pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded { + // Drain every draw in profiler builds so a previous frame's + // first-invalidation timestamp can't be attributed to this one. + #[cfg(feature = "profiler")] + let frame_dirty = self.invalidator.take_frame_dirty(); + #[cfg(feature = "profiler")] + self.window_profiler.begin_draw(); + + // Set up the per-App arena for element allocation during this draw. + // This ensures that multiple test Apps have isolated arenas. + let arena_scope = ElementArenaScope::enter(&cx.element_arena); + + if self.platform_window.prepare_frame() { + self.refresh(); + } + self.invalidate_entities(); + cx.entities.clear_accessed(); + debug_assert!(self.rendered_entity_stack.is_empty()); + self.invalidator.set_dirty(false); + self.requested_autoscroll = None; + + // Restore the previously-used input handler. + // Place it back into a None slot (left by a previous .take()) so that + // cached paint_range indices in reuse_paint find the handler at the + // expected position. + if let Some(input_handler) = self.platform_window.take_input_handler() { + if let Some(slot) = self + .rendered_frame + .input_handlers + .iter_mut() + .rev() + .find(|h| h.is_none()) + { + *slot = Some(input_handler); + } else { + self.rendered_frame.input_handlers.push(Some(input_handler)); + } + } + if !cx.mode.skip_drawing() { + self.draw_roots(cx); + #[cfg(feature = "profiler")] + { + let viewport_size = self.viewport_size; + let scale_factor = self.scale_factor(); + self.debug_frame_overlay.paint( + &mut self.next_frame.scene, + viewport_size, + scale_factor, + ); + } + } + self.dirty_views.clear(); + self.next_frame.window_active = self.active.get(); + + // Register requested input handler with the platform window. + // Use .take() instead of .pop() to preserve Vec length, so that cached + // paint_range indices remain valid for reuse_paint on the next frame. + // Search backwards to find the last Some entry, since reuse_paint may + // have copied None slots from the previous frame. (Fixes #50456) + let focused_text_input_active = if let Some(mut input_handler) = self + .next_frame + .input_handlers + .iter_mut() + .rev() + .find_map(|h| h.take()) + { + let accepts_text_input = input_handler.accepts_text_input(self, cx); + self.platform_window.set_input_handler(input_handler); + accepts_text_input + } else { + false + }; + self.apply_text_input_configuration(cx); + if focused_text_input_active != self.focused_text_input_active { + self.focused_text_input_active = focused_text_input_active; + self.platform_window + .text_input_state_changed(if focused_text_input_active { + TextInputStateChange::FocusGained + } else { + TextInputStateChange::FocusLost + }); + } + + self.layout_engine.as_mut().unwrap().clear(); + self.text_system().finish_frame(); + self.next_frame.finish(&mut self.rendered_frame); + + self.invalidator.set_phase(DrawPhase::Focus); + let previous_focus_path = self.rendered_frame.focus_path(); + let previous_window_active = self.rendered_frame.window_active; + mem::swap(&mut self.rendered_frame, &mut self.next_frame); + self.next_frame.clear(); + let current_focus_path = self.rendered_frame.focus_path(); + let current_window_active = self.rendered_frame.window_active; + let mut focus_before_listeners = self.focus; + + if previous_focus_path != current_focus_path + || previous_window_active != current_window_active + { + if !previous_focus_path.is_empty() && current_focus_path.is_empty() { + self.focus_lost_path = previous_focus_path.clone(); + self.focus_lost_listeners + .clone() + .retain(&(), |listener| listener(self, cx)); + self.focus_lost_path = SmallVec::new(); + // The focus-lost fallback (e.g. a workspace refocusing itself) may target + // an element that isn't part of the element tree, in which case scheduling + // a redraw below would dispatch focus-lost again, looping forever. Only + // track focus movement caused by the focus listeners. + focus_before_listeners = self.focus; + } + + let event = WindowFocusEvent { + previous_focus_path: if previous_window_active { + previous_focus_path + } else { + Default::default() + }, + current_focus_path: if current_window_active { + current_focus_path + } else { + Default::default() + }, + }; + self.focus_listeners + .clone() + .retain(&(), |listener| listener(&event, self, cx)); + } + + debug_assert!(self.rendered_entity_stack.is_empty()); + self.record_entities_accessed(cx); + self.reset_cursor_style(cx); + self.refreshing = false; + self.invalidator.set_phase(DrawPhase::None); + // Focus listeners may move focus (e.g. a dock forwarding focus to its active + // panel). `Window::focus` suppresses `refresh` while a draw is in progress, so + // schedule another frame here to render the new focus state and dispatch the + // resulting focus events. + if self.focus != focus_before_listeners { + self.refresh(); + } + self.needs_present.set(true); + + #[cfg(feature = "profiler")] + { + let draw_duration = self + .window_profiler + .end_draw(frame_dirty.dirty_at, frame_dirty.invalidations); + self.debug_frame_overlay.record_frame(draw_duration); + } + + // Exit the scope to obtain the arena-clear token this draw owes; the + // scope's teardown itself happens in `ElementArenaScope::drop`. + arena_scope.exit(&cx.element_arena) + } + + fn record_entities_accessed(&mut self, cx: &mut App) { + let mut entities_ref = cx.entities.accessed_entities.get_mut(); + let mut entities = mem::take(entities_ref.deref_mut()); + let handle = self.handle; + cx.record_entities_accessed( + handle, + // Try moving window invalidator into the Window + self.invalidator.clone(), + &entities, + ); + let mut entities_ref = cx.entities.accessed_entities.get_mut(); + mem::swap(&mut entities, entities_ref.deref_mut()); + } + + fn invalidate_entities(&mut self) { + let mut views = self.invalidator.take_views(); + for entity in views.drain() { + self.mark_view_dirty(entity); + } + self.invalidator.replace_views(views); + } + + #[profiling::function] + fn present(&mut self) { + #[cfg(feature = "profiler")] + let _foreground_turn = profiler::journal::foreground_turn(); + #[cfg(feature = "profiler")] + let present_start = Instant::now(); + self.platform_window.draw(&self.rendered_frame.scene); + #[cfg(feature = "profiler")] + self.window_profiler.record_present( + present_start, + Instant::now(), + self.active.get(), + !self.next_frame_callbacks.borrow().is_empty(), + ); + self.needs_present.set(false); + profiling::finish_frame!(); + } + + /// Presents the most recently drawn frame if it hasn't been presented yet. + #[cfg(all(test, feature = "profiler"))] + pub fn present_if_needed(&mut self) { + if self.needs_present.get() { + self.present(); + } + } + + /// Returns a snapshot of the current input-latency histograms. + #[cfg(feature = "profiler")] + pub fn input_latency_snapshot(&self) -> profiler::InputLatencySnapshot { + self.window_profiler.input_latency_snapshot() + } + + /// Returns a snapshot of the current frame-duration histograms. + #[cfg(feature = "profiler")] + pub fn frame_duration_snapshot(&self) -> profiler::FrameDurationSnapshot { + self.window_profiler.frame_duration_snapshot() + } + + /// Returns the current mode of the debug frame overlay. + #[cfg(feature = "profiler")] + pub fn debug_frame_overlay_mode(&self) -> DebugFrameOverlayMode { + self.debug_frame_overlay.mode() + } + + /// Sets the mode of the debug frame overlay and schedules a redraw. + #[cfg(feature = "profiler")] + pub fn set_debug_frame_overlay_mode(&mut self, mode: DebugFrameOverlayMode) { + self.debug_frame_overlay.set_mode(mode); + self.refresh(); + } + + /// Advances the debug frame overlay through its hidden, frame-time-only, + /// and detailed modes. + #[cfg(feature = "profiler")] + pub fn cycle_debug_frame_overlay_mode(&mut self) { + self.set_debug_frame_overlay_mode(self.debug_frame_overlay.mode().next()); + } + + /// Clears the debug frame overlay's frame-time statistics, except for the + /// total frame count, and schedules a redraw. + #[cfg(feature = "profiler")] + pub fn reset_debug_frame_overlay_stats(&mut self) { + self.debug_frame_overlay.reset_stats(); + self.refresh(); + } + + fn draw_roots(&mut self, cx: &mut App) { + self.invalidator.set_phase(DrawPhase::Prepaint); + self.tooltip_bounds.take(); + + self.a11y.sync_active_flag(); + if self.a11y.is_active() { + self.a11y.begin_frame(); + } + + let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size()); + let root_size = { + #[cfg(any(feature = "inspector", debug_assertions))] + { + if self.inspector.is_some() { + let mut size = self.viewport_size; + size.width = (size.width - _inspector_width).max(px(0.0)); + size + } else { + self.viewport_size + } + } + #[cfg(not(any(feature = "inspector", debug_assertions)))] + { + self.viewport_size + } + }; + + // Layout all root elements. Like the root element on the web, which + // stretches to fill the viewport unless explicitly sized, window roots + // fill the window when their size is `auto`. + let scale_factor = self.scale_factor(); + let mut root_element = self.root.as_ref().unwrap().clone().into_any_element(); + let root_layout_id = root_element.request_layout(self, cx); + self.layout_engine + .as_mut() + .unwrap() + .stretch_auto_size_to_fill(root_layout_id, root_size, scale_factor); + root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx); + + #[cfg(any(feature = "inspector", debug_assertions))] + let inspector_element = self.prepaint_inspector(_inspector_width, cx); + + self.prepaint_deferred_draws(cx); + + let mut prompt_element = None; + let mut active_drag_element = None; + let mut tooltip_element = None; + if let Some(prompt) = self.prompt.take() { + let mut element = prompt.view.any_view().into_any_element(); + let prompt_layout_id = element.request_layout(self, cx); + self.layout_engine + .as_mut() + .unwrap() + .stretch_auto_size_to_fill(prompt_layout_id, root_size, scale_factor); + element.prepaint_as_root(Point::default(), root_size.into(), self, cx); + prompt_element = Some(element); + self.prompt = Some(prompt); + } else if let Some(active_drag) = cx.active_drag.take() { + let mut element = active_drag.view.clone().into_any_element(); + let offset = self.mouse_position() - active_drag.cursor_offset; + element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx); + active_drag_element = Some(element); + cx.active_drag = Some(active_drag); + } else { + tooltip_element = self.prepaint_tooltip(cx); + } + + self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position); + + // Now actually paint the elements. + self.invalidator.set_phase(DrawPhase::Paint); + root_element.paint(self, cx); + + #[cfg(any(feature = "inspector", debug_assertions))] + self.paint_inspector(inspector_element, cx); + + self.paint_deferred_draws(cx); + + if let Some(mut prompt_element) = prompt_element { + prompt_element.paint(self, cx); + } else if let Some(mut drag_element) = active_drag_element { + drag_element.paint(self, cx); + } else if let Some(mut tooltip_element) = tooltip_element { + tooltip_element.paint(self, cx); + } + + #[cfg(any(feature = "inspector", debug_assertions))] + self.paint_inspector_hitbox(cx); + + // a11y may have been activated/deactivated halfway through the frame + let a11y_active_start_of_frame = self.a11y.is_active(); + self.a11y.sync_active_flag(); + let a11y_active_end_of_frame = self.a11y.is_active(); + + let should_send_a11y_update = a11y_active_start_of_frame && a11y_active_end_of_frame; + + if a11y_active_start_of_frame { + // Harvest frame metadata for the debug dump while the live window + // and frame are still in scope. + let frame_info = crate::window::a11y::debug::FrameDebugInfo { + viewport_size: self.viewport_size, + scale_factor: self.scale_factor, + tab_stop_count: self.next_frame.tab_stops.tab_stop_count(), + }; + // clear the builder state regardless + let tree_update = self.a11y.end_frame(frame_info); + + if should_send_a11y_update { + log::debug!( + "Sending a11y tree update: {} nodes", + tree_update.nodes.len() + ); + self.platform_window.a11y_tree_update(tree_update); + } + } + } + + fn prepaint_tooltip(&mut self, cx: &mut App) -> Option { + // Use indexing instead of iteration to avoid borrowing self for the duration of the loop. + for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() { + let Some(Some(tooltip_request)) = self + .next_frame + .tooltip_requests + .get(tooltip_request_index) + .cloned() + else { + log::error!("Unexpectedly absent TooltipRequest"); + continue; + }; + let mut element = tooltip_request.tooltip.view.clone().into_any_element(); + let mouse_position = tooltip_request.tooltip.mouse_position; + let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx); + + let mut tooltip_bounds = + Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size); + let window_bounds = Bounds { + origin: Point::default(), + size: self.viewport_size(), + }; + + if tooltip_bounds.right() > window_bounds.right() { + let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.); + if new_x >= Pixels::ZERO { + tooltip_bounds.origin.x = new_x; + } else { + tooltip_bounds.origin.x = cmp::max( + Pixels::ZERO, + tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(), + ); + } + } + + if tooltip_bounds.bottom() > window_bounds.bottom() { + let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.); + if new_y >= Pixels::ZERO { + tooltip_bounds.origin.y = new_y; + } else { + tooltip_bounds.origin.y = cmp::max( + Pixels::ZERO, + tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(), + ); + } + } + + // It's possible for an element to have an active tooltip while not being painted (e.g. + // via the `visible_on_hover` method). Since mouse listeners are not active in this + // case, instead update the tooltip's visibility here. + let is_visible = + (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx); + if !is_visible { + continue; + } + + self.with_absolute_element_offset(tooltip_bounds.origin, |window| { + element.prepaint(window, cx) + }); + + self.tooltip_bounds = Some(TooltipBounds { + id: tooltip_request.id, + bounds: tooltip_bounds, + }); + return Some(element); + } + None + } + + fn prepaint_deferred_draws(&mut self, cx: &mut App) { + assert_eq!(self.element_id_stack.len(), 0); + + // Process deferred draws in multiple rounds to support nesting. + // Each round processes all current deferred draws, which may push new ones. + // + // The draws are processed in place rather than being moved out of + // `next_frame.deferred_draws`: `prepaint_index` snapshots that vector's + // length, so any prepaint range recorded during a round (view caches, + // nested deferred draws) must index the same vector `reuse_prepaint` + // slices on the next frame. Moving the draws out and re-appending them + // shifts the indices of nested draws, causing reused subtrees to graft + // the wrong deferred draws and panic in the dispatch tree. + let mut round_start = 0; + let mut depth = 0; + loop { + let round_end = self.next_frame.deferred_draws.len(); + if round_start == round_end { + break; + } + // Limit maximum nesting depth to prevent infinite loops. + assert!(depth < 10, "Exceeded maximum (10) deferred depth"); + depth += 1; + + // Sort this round by priority. + let mut traversal_order = (round_start..round_end).collect::>(); + traversal_order.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority); + + for deferred_draw_ix in traversal_order { + let (element, parent_node, current_view, rem_size, absolute_offset, prepaint_range) = { + let deferred_draw = &mut self.next_frame.deferred_draws[deferred_draw_ix]; + self.element_id_stack + .clone_from(&deferred_draw.element_id_stack); + self.text_style_stack + .clone_from(&deferred_draw.text_style_stack); + ( + deferred_draw.element.take(), + deferred_draw.parent_node, + deferred_draw.current_view, + deferred_draw.rem_size, + deferred_draw.absolute_offset, + deferred_draw.prepaint_range.clone(), + ) + }; + self.next_frame.dispatch_tree.set_active_node(parent_node); + + let prepaint_start = self.prepaint_index(); + if let Some(mut element) = element { + self.with_rendered_view(current_view, |window| { + window.with_rem_size(Some(rem_size), |window| { + window.with_absolute_element_offset(absolute_offset, |window| { + element.prepaint(window, cx); + }); + }); + }); + self.next_frame.deferred_draws[deferred_draw_ix].element = Some(element); + } else { + self.reuse_prepaint(prepaint_range); + } + let prepaint_end = self.prepaint_index(); + self.next_frame.deferred_draws[deferred_draw_ix].prepaint_range = + prepaint_start..prepaint_end; + } + + self.element_id_stack.clear(); + self.text_style_stack.clear(); + round_start = round_end; + } + } + + fn paint_deferred_draws(&mut self, cx: &mut App) { + assert_eq!(self.element_id_stack.len(), 0); + + // Paint all deferred draws in priority order. + // Since prepaint has already processed nested deferreds, we just paint them all. + if self.next_frame.deferred_draws.len() == 0 { + return; + } + + let traversal_order = self.deferred_draw_traversal_order(); + let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws); + for deferred_draw_ix in traversal_order { + let mut deferred_draw = &mut deferred_draws[deferred_draw_ix]; + self.element_id_stack + .clone_from(&deferred_draw.element_id_stack); + self.next_frame + .dispatch_tree + .set_active_node(deferred_draw.parent_node); + + let paint_start = self.paint_index(); + let content_mask = deferred_draw.content_mask; + if let Some(element) = deferred_draw.element.as_mut() { + self.with_rendered_view(deferred_draw.current_view, |window| { + window.with_content_mask(content_mask, |window| { + window.with_rem_size(Some(deferred_draw.rem_size), |window| { + element.paint(window, cx); + }); + }) + }) + } else { + self.reuse_paint(deferred_draw.paint_range.clone()); + } + let paint_end = self.paint_index(); + deferred_draw.paint_range = paint_start..paint_end; + } + self.next_frame.deferred_draws = deferred_draws; + self.element_id_stack.clear(); + } + + fn deferred_draw_traversal_order(&mut self) -> SmallVec<[usize; 8]> { + let deferred_count = self.next_frame.deferred_draws.len(); + let mut sorted_indices = (0..deferred_count).collect::>(); + sorted_indices.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority); + sorted_indices + } + + pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex { + PrepaintStateIndex { + hitboxes_index: self.next_frame.hitboxes.len(), + tooltips_index: self.next_frame.tooltip_requests.len(), + deferred_draws_index: self.next_frame.deferred_draws.len(), + dispatch_tree_index: self.next_frame.dispatch_tree.len(), + accessed_element_states_index: self.next_frame.accessed_element_states.len(), + line_layout_index: self.text_system.layout_index(), + } + } + + pub(crate) fn reuse_prepaint(&mut self, range: Range) { + self.next_frame.hitboxes.extend( + self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index] + .iter() + .cloned(), + ); + self.next_frame.tooltip_requests.extend( + self.rendered_frame.tooltip_requests + [range.start.tooltips_index..range.end.tooltips_index] + .iter_mut() + .map(|request| request.take()), + ); + self.next_frame.accessed_element_states.extend( + self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index + ..range.end.accessed_element_states_index] + .iter() + .map(|(id, type_id)| (id.clone(), *type_id)), + ); + self.text_system + .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index); + + let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree( + range.start.dispatch_tree_index..range.end.dispatch_tree_index, + &mut self.rendered_frame.dispatch_tree, + self.focus, + ); + + if reused_subtree.contains_focus() { + self.next_frame.focus = self.focus; + } + + self.next_frame.deferred_draws.extend( + self.rendered_frame.deferred_draws + [range.start.deferred_draws_index..range.end.deferred_draws_index] + .iter() + .map(|deferred_draw| DeferredDraw { + current_view: deferred_draw.current_view, + parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node), + element_id_stack: deferred_draw.element_id_stack.clone(), + text_style_stack: deferred_draw.text_style_stack.clone(), + content_mask: deferred_draw.content_mask, + rem_size: deferred_draw.rem_size, + priority: deferred_draw.priority, + element: None, + absolute_offset: deferred_draw.absolute_offset, + prepaint_range: deferred_draw.prepaint_range.clone(), + paint_range: deferred_draw.paint_range.clone(), + }), + ); + } + + pub(crate) fn paint_index(&self) -> PaintIndex { + PaintIndex { + scene_index: self.next_frame.scene.len(), + #[cfg(any(test, feature = "test-support"))] + debug_bounds_index: self.next_frame.debug_bounds_records.len(), + mouse_listeners_index: self.next_frame.mouse_listeners.len(), + input_handlers_index: self.next_frame.input_handlers.len(), + cursor_styles_index: self.next_frame.cursor_styles.len(), + accessed_element_states_index: self.next_frame.accessed_element_states.len(), + tab_handle_index: self.next_frame.tab_stops.paint_index(), + line_layout_index: self.text_system.layout_index(), + } + } + + pub(crate) fn reuse_paint(&mut self, range: Range) { + // Cached elements still exist in the frame even when their paint methods don't run. + #[cfg(any(test, feature = "test-support"))] + for (selector, bounds) in &self.rendered_frame.debug_bounds_records + [range.start.debug_bounds_index..range.end.debug_bounds_index] + { + self.next_frame + .record_debug_bounds(selector.clone(), *bounds); + } + self.next_frame.cursor_styles.extend( + self.rendered_frame.cursor_styles + [range.start.cursor_styles_index..range.end.cursor_styles_index] + .iter() + .cloned(), + ); + self.next_frame.input_handlers.extend( + self.rendered_frame.input_handlers + [range.start.input_handlers_index..range.end.input_handlers_index] + .iter_mut() + .map(|handler| handler.take()), + ); + self.next_frame.mouse_listeners.extend( + self.rendered_frame.mouse_listeners + [range.start.mouse_listeners_index..range.end.mouse_listeners_index] + .iter_mut() + .map(|listener| listener.take()), + ); + self.next_frame.accessed_element_states.extend( + self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index + ..range.end.accessed_element_states_index] + .iter() + .map(|(id, type_id)| (id.clone(), *type_id)), + ); + self.next_frame.tab_stops.replay( + &self.rendered_frame.tab_stops.insertion_history + [range.start.tab_handle_index..range.end.tab_handle_index], + ); + + self.text_system + .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index); + self.next_frame.scene.replay( + range.start.scene_index..range.end.scene_index, + &self.rendered_frame.scene, + ); + } + + /// Push a text style onto the stack, and call a function with that style active. + /// Use [`Window::text_style`] to get the current, combined text style. This method + /// should only be called as part of element drawing. + pub fn with_text_style(&mut self, style: Option, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.invalidator.debug_assert_paint_or_prepaint(); + if let Some(style) = style { + self.text_style_stack.push(style); + let result = f(self); + self.text_style_stack.pop(); + result + } else { + f(self) + } + } + + /// Updates the cursor style at the platform level. This method should only be called + /// during the paint phase of element drawing. + pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) { + self.invalidator.debug_assert_paint(); + self.next_frame.cursor_styles.push(CursorStyleRequest { + hitbox_id: Some(hitbox.id), + style, + }); + } + + /// Updates the cursor style for the entire window at the platform level. A cursor + /// style using this method will have precedence over any cursor style set using + /// `set_cursor_style`. This method should only be called during the paint + /// phase of element drawing. + pub fn set_window_cursor_style(&mut self, style: CursorStyle) { + self.invalidator.debug_assert_paint(); + self.next_frame.cursor_styles.push(CursorStyleRequest { + hitbox_id: None, + style, + }) + } + + /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called + /// during the paint phase of element drawing. + pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId { + self.invalidator.debug_assert_prepaint(); + let id = TooltipId(post_inc(&mut self.next_tooltip_id.0)); + self.next_frame + .tooltip_requests + .push(Some(TooltipRequest { id, tooltip })); + id + } + + /// Invoke the given function with the given content mask after intersecting it + /// with the current mask. This method should only be called during element drawing. + // This function is called in a highly recursive manner in editor + // prepainting, make sure its inlined to reduce the stack burden + #[inline] + pub fn with_content_mask( + &mut self, + mask: Option>, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.invalidator.debug_assert_paint_or_prepaint(); + if let Some(mask) = mask { + let mask = mask.intersect(&self.content_mask()); + self.content_mask_stack.push(mask); + let result = f(self); + self.content_mask_stack.pop(); + result + } else { + f(self) + } + } + + /// Updates the global element offset relative to the current offset. This is used to implement + /// scrolling. This method should only be called during the prepaint phase of element drawing. + pub fn with_element_offset( + &mut self, + offset: Point, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.invalidator.debug_assert_prepaint(); + + if offset.is_zero() { + return f(self); + }; + + let abs_offset = self.element_offset() + offset; + self.with_absolute_element_offset(abs_offset, f) + } + + /// Updates the global element offset based on the given offset. This is used to implement + /// drag handles and other manual painting of elements. This method should only be called during + /// the prepaint phase of element drawing. + pub fn with_absolute_element_offset( + &mut self, + offset: Point, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.invalidator.debug_assert_prepaint(); + self.element_offset_stack.push(offset); + let result = f(self); + self.element_offset_stack.pop(); + result + } + + pub(crate) fn with_element_opacity( + &mut self, + opacity: Option, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.invalidator.debug_assert_paint_or_prepaint(); + + let Some(opacity) = opacity else { + return f(self); + }; + + let previous_opacity = self.element_opacity; + self.element_opacity = previous_opacity * opacity; + let result = f(self); + self.element_opacity = previous_opacity; + result + } + + /// Perform prepaint on child elements in a "retryable" manner, so that any side effects + /// of prepaints can be discarded before prepainting again. This is used to support autoscroll + /// where we need to prepaint children to detect the autoscroll bounds, then adjust the + /// element offset and prepaint again. See [`crate::List`] for an example. This method should only be + /// called during the prepaint phase of element drawing. + pub fn transact(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result { + self.invalidator.debug_assert_prepaint(); + let index = self.prepaint_index(); + let result = f(self); + if result.is_err() { + self.next_frame.hitboxes.truncate(index.hitboxes_index); + self.next_frame + .tooltip_requests + .truncate(index.tooltips_index); + self.next_frame + .deferred_draws + .truncate(index.deferred_draws_index); + self.next_frame + .dispatch_tree + .truncate(index.dispatch_tree_index); + self.next_frame + .accessed_element_states + .truncate(index.accessed_element_states_index); + self.text_system.truncate_layouts(index.line_layout_index); + } + result + } + + /// When you call this method during [`Element::prepaint`], containing elements will attempt to + /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call + /// [`Element::prepaint`] again with a new set of bounds. See [`crate::List`] for an example of an element + /// that supports this method being called on the elements it contains. This method should only be + /// called during the prepaint phase of element drawing. + pub fn request_autoscroll(&mut self, bounds: Bounds) { + self.invalidator.debug_assert_prepaint(); + self.requested_autoscroll = Some(bounds); + } + + /// This method can be called from a containing element such as [`crate::List`] to support the autoscroll behavior + /// described in [`Self::request_autoscroll`]. + pub fn take_autoscroll(&mut self) -> Option> { + self.invalidator.debug_assert_prepaint(); + self.requested_autoscroll.take() + } + + /// Asynchronously load an asset, if the asset hasn't finished loading this will return None. + /// Your view will be re-drawn once the asset has finished loading. + /// + /// Note that the multiple calls to this method will only result in one `Asset::load` call at a + /// time. + pub fn use_asset(&mut self, source: &A::Source, cx: &mut App) -> Option { + cx.asset_entry::(source).use_by(self.current_view()) + } + + /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None. + /// Your view will not be re-drawn once the asset has finished loading. + /// + /// Note that the multiple calls to this method will only result in one `Asset::load` call at a + /// time. + pub fn get_asset(&mut self, source: &A::Source, cx: &mut App) -> Option { + cx.fetch_asset::(source) + } + /// Obtain the current element offset. This method should only be called during the + /// prepaint phase of element drawing. + pub fn element_offset(&self) -> Point { + self.invalidator.debug_assert_prepaint(); + self.element_offset_stack + .last() + .copied() + .unwrap_or_default() + } + + /// Obtain the current element opacity. This method should only be called during the + /// prepaint phase of element drawing. + #[inline] + pub(crate) fn element_opacity(&self) -> f32 { + self.invalidator.debug_assert_paint_or_prepaint(); + self.element_opacity + } + + /// Obtain the current content mask. This method should only be called during element drawing. + pub fn content_mask(&self) -> ContentMask { + self.invalidator.debug_assert_paint_or_prepaint(); + self.content_mask_stack + .last() + .cloned() + .unwrap_or_else(|| ContentMask { + bounds: Bounds { + origin: Point::default(), + size: self.viewport_size, + }, + }) + } + + /// Provide elements in the called function with a new namespace in which their identifiers must be unique. + /// This can be used within a custom element to distinguish multiple sets of child elements. + pub fn with_element_namespace( + &mut self, + element_id: impl Into, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.element_id_stack.push(element_id.into()); + let result = f(self); + self.element_id_stack.pop(); + result + } + + /// Use a piece of state that exists as long this element is being rendered in consecutive frames. + pub fn use_keyed_state( + &mut self, + key: impl Into, + cx: &mut App, + init: impl FnOnce(&mut Self, &mut Context) -> S, + ) -> Entity { + let current_view = self.current_view(); + self.with_global_id(key.into(), |global_id, window| { + window.with_element_state(global_id, |state: Option>, window| { + if let Some(state) = state { + (state.clone(), state) + } else { + let new_state = cx.new(|cx| init(window, cx)); + Self::observe_keyed_state(&new_state, current_view, cx); + (new_state.clone(), new_state) + } + }) + }) + } + + /// Use a piece of state that exists as long this element is being rendered in consecutive frames, without needing to specify a key + /// + /// NOTE: This method uses the location of the caller to generate an ID for this state. + /// If this is not sufficient to identify your state (e.g. you're rendering a list item), + /// you can provide a custom ElementID using the `use_keyed_state` method. + #[track_caller] + pub fn use_state( + &mut self, + cx: &mut App, + init: impl FnOnce(&mut Self, &mut Context) -> S, + ) -> Entity { + self.use_keyed_state( + ElementId::CodeLocation(*core::panic::Location::caller()), + cx, + init, + ) + } + + /// Updates or initializes state for an element with the given id that lives across multiple + /// frames. If an element with this ID existed in the rendered frame, its state will be passed + /// to the given closure. The state returned by the closure will be stored so it can be referenced + /// when drawing the next frame. This method should only be called as part of element drawing. + #[inline(always)] + pub fn with_element_state( + &mut self, + global_id: &GlobalElementId, + f: impl FnOnce(Option, &mut Self) -> (R, S), + ) -> R + where + S: 'static, + { + self.invalidator.debug_assert_paint_or_prepaint(); + + let (key, state) = self.take_element_state(global_id, TypeId::of::()); + + if let Some(any) = state { + let ElementStateBox { + inner, + #[cfg(debug_assertions)] + type_name, + } = any; + // Using the extra inner option to avoid needing to reallocate a new box. + let mut state_box = inner + .downcast::>() + .map_err(|_| { + #[cfg(debug_assertions)] + { + anyhow::anyhow!( + "invalid element state type for id, requested {:?}, actual: {:?}", + std::any::type_name::(), + type_name + ) + } + + #[cfg(not(debug_assertions))] + { + anyhow::anyhow!( + "invalid element state type for id, requested {:?}", + std::any::type_name::(), + ) + } + }) + .unwrap(); + + let state = state_box.take().expect( + "reentrant call to with_element_state for the same state type and element id", + ); + let (result, state) = f(Some(state), self); + state_box.replace(state); + self.insert_element_state( + key, + ElementStateBox { + inner: state_box, + #[cfg(debug_assertions)] + type_name, + }, + ); + result + } else { + let (result, state) = f(None, self); + self.insert_element_state( + key, + ElementStateBox { + inner: Box::new(Some(state)), + #[cfg(debug_assertions)] + type_name: std::any::type_name::(), + }, + ); + result + } + } + + /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience + /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state` + /// when the element is guaranteed to have an id. + /// + /// The first option means 'no ID provided' + /// The second option means 'not yet initialized' + pub fn with_optional_element_state( + &mut self, + global_id: Option<&GlobalElementId>, + f: impl FnOnce(Option>, &mut Self) -> (R, Option), + ) -> R + where + S: 'static, + { + self.invalidator.debug_assert_paint_or_prepaint(); + + if let Some(global_id) = global_id { + self.with_element_state(global_id, |state, cx| { + let (result, state) = f(Some(state), cx); + let state = + state.expect("you must return some state when you pass some element id"); + (result, state) + }) + } else { + let (result, state) = f(None, self); + debug_assert!( + state.is_none(), + "you must not return an element state when passing None for the global id" + ); + result + } + } + + /// Executes the given closure within the context of a tab group. + #[inline] + pub fn with_tab_group(&mut self, index: Option, f: impl FnOnce(&mut Self) -> R) -> R { + if let Some(index) = index { + self.next_frame.tab_stops.begin_group(index); + let result = f(self); + self.next_frame.tab_stops.end_group(); + result + } else { + f(self) + } + } + + /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree + /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements, + /// with higher values being drawn on top. + /// + /// When `content_mask` is provided, the deferred element will be clipped to that region during + /// both prepaint and paint. When `None`, no additional clipping is applied. + /// + /// This method should only be called as part of the prepaint phase of element drawing. + pub fn defer_draw( + &mut self, + element: AnyElement, + absolute_offset: Point, + priority: usize, + content_mask: Option>, + ) { + self.invalidator.debug_assert_prepaint(); + let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap(); + self.next_frame.deferred_draws.push(DeferredDraw { + current_view: self.current_view(), + parent_node, + element_id_stack: self.element_id_stack.clone(), + text_style_stack: self.text_style_stack.clone(), + content_mask, + rem_size: self.rem_size(), + priority, + element: Some(element), + absolute_offset, + prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(), + paint_range: PaintIndex::default()..PaintIndex::default(), + }); + } + + /// Creates a new painting layer for the specified bounds. A "layer" is a batch + /// of geometry that are non-overlapping and have the same draw order. This is typically used + /// for performance reasons. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_layer(&mut self, bounds: Bounds, f: impl FnOnce(&mut Self) -> R) -> R { + self.invalidator.debug_assert_paint(); + + let content_mask = self.content_mask(); + let clipped_bounds = bounds.intersect(&content_mask.bounds); + if !clipped_bounds.is_empty() { + self.next_frame + .scene + .push_layer(self.cover_bounds(clipped_bounds)); + } + + let result = f(self); + + if !clipped_bounds.is_empty() { + self.next_frame.scene.pop_layer(); + } + + result + } + + /// Paint the drop (non-inset) shadows from `shadows` into the scene at the current + /// z-index. Inset shadows are skipped; paint those with [`Self::paint_inset_shadows`] + /// after the element's background so they layer on top of the fill. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_drop_shadows( + &mut self, + bounds: Bounds, + corner_radii: Corners, + shadows: &[BoxShadow], + ) { + self.invalidator.debug_assert_paint(); + + let scale_factor = self.scale_factor(); + let content_mask = self.snapped_content_mask(); + let opacity = self.element_opacity(); + let element_bounds = self.cover_bounds(bounds); + let element_corner_radii = corner_radii.scale(scale_factor); + for shadow in shadows { + if shadow.inset { + continue; + } + let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius); + self.next_frame.scene.insert_primitive(Shadow { + order: 0, + blur_radius: shadow.blur_radius.scale(scale_factor), + bounds: self.cover_bounds(shadow_bounds), + content_mask, + corner_radii: corner_radii.scale(scale_factor), + color: shadow.color.opacity(opacity), + element_bounds, + element_corner_radii, + inset: 0, + pad: 0, + }); + } + } + + /// Paint the inset shadows from `shadows` into the scene at the current z-index. Should + /// be called after the element's background so the shadow layers on top of the fill. + /// Drop shadows are skipped; paint those with [`Self::paint_drop_shadows`] before the background. + pub fn paint_inset_shadows( + &mut self, + bounds: Bounds, + corner_radii: Corners, + shadows: &[BoxShadow], + ) { + self.invalidator.debug_assert_paint(); + + let scale_factor = self.scale_factor(); + let content_mask = self.snapped_content_mask(); + let opacity = self.element_opacity(); + let element_bounds = self.cover_bounds(bounds); + let element_corner_radii = corner_radii.scale(scale_factor); + for shadow in shadows { + if !shadow.inset { + continue; + } + let hole = (bounds + shadow.offset).dilate(-shadow.spread_radius); + // Clamp at zero so a large spread can't produce negative radii, which would + // break the SDF in the shader. + let zero = Pixels::ZERO; + let hole_corner_radii = Corners { + top_left: (corner_radii.top_left - shadow.spread_radius).max(zero), + top_right: (corner_radii.top_right - shadow.spread_radius).max(zero), + bottom_right: (corner_radii.bottom_right - shadow.spread_radius).max(zero), + bottom_left: (corner_radii.bottom_left - shadow.spread_radius).max(zero), + }; + self.next_frame.scene.insert_primitive(Shadow { + order: 0, + blur_radius: shadow.blur_radius.scale(scale_factor), + bounds: self.cover_bounds(hole), + content_mask, + corner_radii: hole_corner_radii.scale(scale_factor), + color: shadow.color.opacity(opacity), + element_bounds, + element_corner_radii, + inset: 1, + pad: 0, + }); + } + } + + fn largest_border_interior(quad: &Quad) -> Bounds { + let radii = &quad.corner_radii; + let widths = &quad.border_widths; + let edge_radii = Edges { + top: radii.top_left.max(radii.top_right), + right: radii.top_right.max(radii.bottom_right), + bottom: radii.bottom_left.max(radii.bottom_right), + left: radii.top_left.max(radii.bottom_left), + }; + + let antialias_inset = point(ScaledPixels(1.0), ScaledPixels(1.0)); + let inset_bounds = |top_left_inset, bottom_right_inset| { + Bounds::from_corners( + quad.bounds.origin + top_left_inset + antialias_inset, + quad.bounds.bottom_right() - bottom_right_inset - antialias_inset, + ) + }; + + // Rounded corners need only be excluded on one axis. Either candidate + // is empty of border pixels, so use the larger interior. + let horizontal_band = inset_bounds( + point(widths.left, widths.top.max(edge_radii.top)), + point(widths.right, widths.bottom.max(edge_radii.bottom)), + ); + let vertical_band = inset_bounds( + point(widths.left.max(edge_radii.left), widths.top), + point(widths.right.max(edge_radii.right), widths.bottom), + ); + + let area = |bounds: &Bounds| { + bounds.size.width.0.max(0.) * bounds.size.height.0.max(0.) + }; + if area(&horizontal_band) >= area(&vertical_band) { + horizontal_band + } else { + vertical_band + } + } + + /// Paint one or more quads into the scene for the next frame at the current stacking context. + /// Quads are colored rectangular regions with an optional background, border, and corner radius. + /// see [`fill`], [`outline`], and [`quad`] to construct this type. + /// + /// This method should only be called as part of the paint phase of element drawing. + /// + /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners + /// where the circular arcs meet. This will not display well when combined with dashed borders. + /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds. + pub fn paint_quad(&mut self, quad: PaintQuad) { + self.invalidator.debug_assert_paint(); + + let opacity = self.element_opacity(); + let snapped_bounds = self.snap_bounds(quad.bounds); + let snapped_border_widths = self.snap_border_widths(quad.border_widths); + let quad = Quad { + order: 0, + bounds: snapped_bounds, + content_mask: self.snapped_content_mask(), + background: quad.background.opacity(opacity), + border_color: quad.border_color.opacity(opacity), + corner_radii: quad.corner_radii.scale(self.scale_factor()), + border_widths: snapped_border_widths, + border_style: quad.border_style, + }; + + if !quad.background.is_transparent() { + self.next_frame.scene.insert_primitive(quad); + return; + } + + // Splitting a border-only quad around its empty interior avoids shading + // every transparent pixel inside large outlines. + let outer_bounds = quad.bounds; + let inner_bounds = Self::largest_border_interior(&quad); + + if inner_bounds.is_empty() { + self.next_frame.scene.insert_primitive(quad); + return; + } + + let strips = [ + // Top + Bounds::from_corners( + outer_bounds.origin, + point(outer_bounds.right(), inner_bounds.top()), + ), + // Bottom + Bounds::from_corners( + point(outer_bounds.left(), inner_bounds.bottom()), + outer_bounds.bottom_right(), + ), + // Left + Bounds::from_corners( + point(outer_bounds.left(), inner_bounds.top()), + inner_bounds.bottom_left(), + ), + // Right + Bounds::from_corners( + inner_bounds.top_right(), + point(outer_bounds.right(), inner_bounds.bottom()), + ), + ]; + + for strip in strips { + let content_mask_bounds = quad.content_mask.bounds.intersect(&strip); + if !content_mask_bounds.is_empty() { + self.next_frame.scene.insert_primitive(Quad { + content_mask: ContentMask { + bounds: content_mask_bounds, + }, + ..quad + }); + } + } + } + + /// Paint the given `Path` into the scene for the next frame at the current z-index. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_path(&mut self, mut path: Path, color: impl Into) { + self.invalidator.debug_assert_paint(); + + let scale_factor = self.scale_factor(); + let content_mask = self.content_mask(); + let opacity = self.element_opacity(); + path.content_mask = content_mask; + let color: Background = color.into(); + path.color = color.opacity(opacity); + self.next_frame + .scene + .insert_primitive(path.scale(scale_factor)); + } + + /// Paint an underline into the scene for the next frame at the current z-index. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_underline( + &mut self, + origin: Point, + width: Pixels, + style: &UnderlineStyle, + ) { + self.invalidator.debug_assert_paint(); + let underline = self.underline(origin, width, style); + self.next_frame.scene.insert_primitive(underline); + } + + /// Paint a strikethrough into the scene for the next frame at the current z-index. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_strikethrough( + &mut self, + origin: Point, + width: Pixels, + style: &StrikethroughStyle, + ) { + self.invalidator.debug_assert_paint(); + + let scale_factor = self.scale_factor(); + let height = style.thickness; + let bounds = Bounds { + origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))), + size: size(self.snap_stroke(width), self.snap_stroke(height)), + }; + let opacity = self.element_opacity(); + + self.next_frame.scene.insert_primitive(Underline { + order: 0, + pad: 0, + bounds, + content_mask: self.snapped_content_mask(), + thickness: self.snap_stroke(style.thickness), + color: style.color.unwrap_or_default().opacity(opacity), + wavy: false.into(), + }); + } + + /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index. + /// + /// The y component of the origin is the baseline of the glyph. + /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or + /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem). + /// This method is only useful if you need to paint a single glyph that has already been shaped. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_glyph( + &mut self, + origin: Point, + font_id: FontId, + glyph_id: GlyphId, + font_size: Pixels, + color: Hsla, + ) -> Result<()> { + self.invalidator.debug_assert_paint(); + + let element_opacity = self.element_opacity(); + let scale_factor = self.scale_factor(); + let glyph_origin = origin.scale(scale_factor); + + let quantized_origin = Point::new( + round_half_toward_zero(glyph_origin.x.0 * SUBPIXEL_VARIANTS_X as f32) + / SUBPIXEL_VARIANTS_X as f32, + round_half_toward_zero(glyph_origin.y.0 * SUBPIXEL_VARIANTS_Y as f32) + / SUBPIXEL_VARIANTS_Y as f32, + ); + let subpixel_variant = Point::new( + (quantized_origin.x.fract() * SUBPIXEL_VARIANTS_X as f32) as u8, + (quantized_origin.y.fract() * SUBPIXEL_VARIANTS_Y as f32) as u8, + ); + let integer_origin = quantized_origin.map(|c| ScaledPixels(c.trunc())); + let subpixel_rendering = self.should_use_subpixel_rendering(font_id, font_size); + let dilation = self.text_system().glyph_dilation_for_color(color); + let params = RenderGlyphParams { + font_id, + glyph_id, + font_size, + subpixel_variant, + scale_factor, + is_emoji: false, + subpixel_rendering, + dilation, + }; + + let raster_bounds = self.text_system().raster_bounds(¶ms)?; + if !raster_bounds.is_zero() { + let tile = self + .sprite_atlas + .get_or_insert_with(params.clone().into(), &mut || { + let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?; + Ok(Some((size, Cow::Owned(bytes)))) + })? + .expect("Callback above only errors or returns Some"); + let bounds = Bounds { + origin: integer_origin + raster_bounds.origin.map(Into::into), + size: tile.bounds.size.map(Into::into), + }; + let content_mask = self.snapped_content_mask(); + + if subpixel_rendering { + self.next_frame.scene.insert_primitive(SubpixelSprite { + order: 0, + pad: 0, + bounds, + content_mask, + color: color.opacity(element_opacity), + tile, + transformation: TransformationMatrix::unit(), + }); + } else { + self.next_frame.scene.insert_primitive(MonochromeSprite { + order: 0, + pad: 0, + bounds, + content_mask, + color: color.opacity(element_opacity), + tile, + transformation: TransformationMatrix::unit(), + }); + } + } + Ok(()) + } + + fn should_use_subpixel_rendering(&self, font_id: FontId, font_size: Pixels) -> bool { + if self.platform_window.background_appearance() != WindowBackgroundAppearance::Opaque { + return false; + } + + if !self.platform_window.is_subpixel_rendering_supported() { + return false; + } + + let mode = match self.text_rendering_mode.get() { + TextRenderingMode::PlatformDefault => self + .text_system() + .recommended_rendering_mode(font_id, font_size), + mode => mode, + }; + + mode == TextRenderingMode::Subpixel + } + + /// Paints an emoji glyph into the scene for the next frame at the current z-index. + /// + /// The y component of the origin is the baseline of the glyph. + /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or + /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem). + /// This method is only useful if you need to paint a single emoji that has already been shaped. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_emoji( + &mut self, + origin: Point, + font_id: FontId, + glyph_id: GlyphId, + font_size: Pixels, + ) -> Result<()> { + self.invalidator.debug_assert_paint(); + + let scale_factor = self.scale_factor(); + let glyph_origin = origin.scale(scale_factor); + let integer_origin = glyph_origin.map(|c| ScaledPixels(round_half_toward_zero(c.0))); + let params = RenderGlyphParams { + font_id, + glyph_id, + font_size, + subpixel_variant: Default::default(), + scale_factor, + is_emoji: true, + subpixel_rendering: false, + dilation: 0, + }; + + let raster_bounds = self.text_system().raster_bounds(¶ms)?; + if !raster_bounds.is_zero() { + let tile = self + .sprite_atlas + .get_or_insert_with(params.clone().into(), &mut || { + let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?; + Ok(Some((size, Cow::Owned(bytes)))) + })? + .expect("Callback above only errors or returns Some"); + + let bounds = Bounds { + origin: integer_origin + raster_bounds.origin.map(Into::into), + size: tile.bounds.size.map(Into::into), + }; + let content_mask = self.snapped_content_mask(); + let opacity = self.element_opacity(); + + self.next_frame.scene.insert_primitive(PolychromeSprite { + order: 0, + pad: 0, + grayscale: false.into(), + bounds, + corner_radii: Default::default(), + content_mask, + tile, + opacity, + }); + } + Ok(()) + } + + /// Paint a monochrome SVG into the scene for the next frame at the current stacking context. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn paint_svg( + &mut self, + bounds: Bounds, + path: SharedString, + mut data: Option<&[u8]>, + transformation: TransformationMatrix, + color: Hsla, + cx: &App, + ) -> Result<()> { + self.invalidator.debug_assert_paint(); + + let element_opacity = self.element_opacity(); + let bounds = self.snap_bounds(bounds); + + let params = RenderSvgParams { + path, + size: bounds.size.map(|pixels| { + DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32) + }), + }; + + let Some(tile) = + self.sprite_atlas + .get_or_insert_with(params.clone().into(), &mut || { + let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(¶ms, data)? + else { + return Ok(None); + }; + Ok(Some((size, Cow::Owned(bytes)))) + })? + else { + return Ok(()); + }; + let content_mask = self.snapped_content_mask(); + let svg_bounds = Bounds { + origin: bounds.center() + - Point::new( + ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.), + ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.), + ), + size: tile + .bounds + .size + .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)), + }; + let final_bounds = svg_bounds + .map_origin(|value| ScaledPixels(round_half_toward_zero(value.0))) + .map_size(|size| size.ceil()); + + self.next_frame.scene.insert_primitive(MonochromeSprite { + order: 0, + pad: 0, + bounds: final_bounds, + content_mask, + color: color.opacity(element_opacity), + tile, + transformation, + }); + + Ok(()) + } + + /// Paint an image into the scene for the next frame at the current z-index. + /// This method will panic if the frame_index is not valid + /// + /// This method should only be called as part of the paint phase of element drawing. + /// Paint an image into `bounds`, positioning and scaling it according to `image_bounds`. + /// + /// The visible region rendered is `bounds.intersect(&image_bounds)`, with `corner_radii` + /// applied to `bounds`. + pub fn paint_image( + &mut self, + bounds: Bounds, + image_bounds: Bounds, + corner_radii: Corners, + data: Arc, + frame_index: usize, + grayscale: bool, + ) -> Result<()> { + self.invalidator.debug_assert_paint(); + + let visible_bounds = bounds.intersect(&image_bounds); + if visible_bounds.size.width <= Pixels::ZERO || visible_bounds.size.height <= Pixels::ZERO { + return Ok(()); + } + if image_bounds.size.width <= Pixels::ZERO || image_bounds.size.height <= Pixels::ZERO { + return Ok(()); + } + + let params = RenderImageParams { + image_id: data.id, + frame_index, + }; + + let tile = self + .sprite_atlas + .get_or_insert_with(params.into(), &mut || { + Ok(Some(( + data.size(frame_index), + Cow::Borrowed( + data.as_bytes(frame_index) + .expect("It's the caller's job to pass a valid frame index"), + ), + ))) + })? + .expect("Callback above only returns Some"); + + let visible_bounds_snapped = self.snap_bounds(visible_bounds); + + let sub_tile = if visible_bounds == image_bounds { + tile + } else { + let x_offset_ratio = + (visible_bounds.origin.x - image_bounds.origin.x) / image_bounds.size.width; + let y_offset_ratio = + (visible_bounds.origin.y - image_bounds.origin.y) / image_bounds.size.height; + let width_ratio = visible_bounds.size.width / image_bounds.size.width; + let height_ratio = visible_bounds.size.height / image_bounds.size.height; + + let tile_origin_x = tile.bounds.origin.x.0; + let tile_origin_y = tile.bounds.origin.y.0; + let tile_width = tile.bounds.size.width.0; + let tile_height = tile.bounds.size.height.0; + + let sub_origin_x = tile_origin_x + (x_offset_ratio * tile_width as f32).round() as i32; + let sub_origin_y = tile_origin_y + (y_offset_ratio * tile_height as f32).round() as i32; + let sub_width = (width_ratio * tile_width as f32).round() as i32; + let sub_height = (height_ratio * tile_height as f32).round() as i32; + + let max_x = tile_origin_x + tile_width; + let max_y = tile_origin_y + tile_height; + + let clamped_origin_x = sub_origin_x.clamp(tile_origin_x, max_x); + let clamped_origin_y = sub_origin_y.clamp(tile_origin_y, max_y); + let clamped_width = sub_width.min(max_x - clamped_origin_x).max(0); + let clamped_height = sub_height.min(max_y - clamped_origin_y).max(0); + + AtlasTile { + bounds: Bounds { + origin: point( + DevicePixels(clamped_origin_x), + DevicePixels(clamped_origin_y), + ), + size: size(DevicePixels(clamped_width), DevicePixels(clamped_height)), + }, + ..tile + } + }; + + let content_mask = self.snapped_content_mask(); + let corner_radii = corner_radii + .clamp_radii_for_quad_size(visible_bounds.size) + .scale(self.scale_factor()); + let opacity = self.element_opacity(); + + self.next_frame.scene.insert_primitive(PolychromeSprite { + order: 0, + pad: 0, + grayscale: grayscale.into(), + bounds: visible_bounds_snapped, + content_mask, + corner_radii, + tile: sub_tile, + opacity, + }); + Ok(()) + } + + /// Paint a surface into the scene for the next frame at the current z-index. + /// + /// This method should only be called as part of the paint phase of element drawing. + #[cfg(any(target_os = "macos", target_os = "ios"))] + pub fn paint_surface(&mut self, bounds: Bounds, image_buffer: CVPixelBuffer) { + use crate::PaintSurface; + + self.invalidator.debug_assert_paint(); + + let bounds = self.snap_bounds(bounds); + let content_mask = self.snapped_content_mask(); + self.next_frame.scene.insert_primitive(PaintSurface { + order: 0, + bounds, + content_mask, + image_buffer, + }); + } + + /// Removes an image from the sprite atlas. + pub fn drop_image(&mut self, data: Arc) -> Result<()> { + for frame_index in 0..data.frame_count() { + let params = RenderImageParams { + image_id: data.id, + frame_index, + }; + + self.sprite_atlas.remove(¶ms.clone().into()); + } + + Ok(()) + } + + /// Returns whether every frame of an image is present in the sprite atlas. + #[cfg(any(test, feature = "test-support"))] + pub fn has_image_atlas_entry(&self, data: &RenderImage) -> bool { + data.frame_count() > 0 + && (0..data.frame_count()).all(|frame_index| { + self.sprite_atlas.contains( + &RenderImageParams { + image_id: data.id, + frame_index, + } + .into(), + ) + }) + } + + /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which + /// layout is being requested, along with the layout ids of any children. This method is called during + /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout. + /// + /// This method should only be called as part of the request_layout or prepaint phase of element drawing. + #[must_use] + pub fn request_layout( + &mut self, + style: Style, + children: impl IntoIterator, + cx: &mut App, + ) -> LayoutId { + self.invalidator.debug_assert_prepaint(); + + cx.layout_id_buffer.clear(); + cx.layout_id_buffer.extend(children); + let rem_size = self.rem_size(); + let scale_factor = self.scale_factor(); + + self.layout_engine.as_mut().unwrap().request_layout( + style, + rem_size, + scale_factor, + &cx.layout_id_buffer, + ) + } + + /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children, + /// this variant takes a function that is invoked during layout so you can use arbitrary logic to + /// determine the element's size. One place this is used internally is when measuring text. + /// + /// The given closure is invoked at layout time with the known dimensions and available space and + /// returns a `Size`. + /// + /// This method should only be called as part of the request_layout or prepaint phase of element drawing. + pub fn request_measured_layout(&mut self, style: Style, measure: F) -> LayoutId + where + F: Fn(Size>, Size, &mut Window, &mut App) -> Size + + 'static, + { + self.invalidator.debug_assert_prepaint(); + + let rem_size = self.rem_size(); + let scale_factor = self.scale_factor(); + self.layout_engine + .as_mut() + .unwrap() + .request_measured_layout(style, rem_size, scale_factor, measure) + } + + /// Compute the layout for the given id within the given available space. + /// This method is called for its side effect, typically by the framework prior to painting. + /// After calling it, you can request the bounds of the given layout node id or any descendant. + /// + /// This method should only be called as part of the prepaint phase of element drawing. + pub fn compute_layout( + &mut self, + layout_id: LayoutId, + available_space: Size, + cx: &mut App, + ) { + self.invalidator.debug_assert_prepaint(); + + let mut layout_engine = self.layout_engine.take().unwrap(); + layout_engine.compute_layout(layout_id, available_space, self, cx); + self.layout_engine = Some(layout_engine); + } + + /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by + /// GPUI itself automatically in order to pass your element its `Bounds` automatically. + /// + /// This method should only be called as part of element drawing. + pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds { + self.invalidator.debug_assert_prepaint(); + + let scale_factor = self.scale_factor(); + let mut bounds = self + .layout_engine + .as_mut() + .unwrap() + .layout_bounds(layout_id, scale_factor) + .map(Into::into); + let snapped_offset = self.pixel_snap_point(self.element_offset()); + bounds.origin += snapped_offset; + bounds + } + + /// This method should be called during `prepaint`. You can use + /// the returned [Hitbox] during `paint` or in an event handler + /// to determine whether the inserted hitbox was the topmost. + /// + /// This method should only be called as part of the prepaint phase of element drawing. + pub fn insert_hitbox(&mut self, bounds: Bounds, behavior: HitboxBehavior) -> Hitbox { + self.invalidator.debug_assert_prepaint(); + + let content_mask = self.content_mask(); + let mut id = self.next_hitbox_id; + self.next_hitbox_id = self.next_hitbox_id.next(); + let hitbox = Hitbox { + id, + bounds, + content_mask, + behavior, + }; + self.next_frame.hitboxes.push(hitbox.clone()); + hitbox + } + + /// Set a hitbox which will act as a control area of the platform window. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) { + self.invalidator.debug_assert_paint(); + self.next_frame.window_control_hitboxes.push((area, hitbox)); + } + + /// Sets the key context for the current element. This context will be used to translate + /// keybindings into actions. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn set_key_context(&mut self, context: KeyContext) { + self.invalidator.debug_assert_paint(); + self.next_frame.dispatch_tree.set_key_context(context); + } + + /// Sets the focus handle for the current element. This handle will be used to manage focus state + /// and keyboard event dispatch for the element. + /// + /// This method should only be called as part of the prepaint phase of element drawing. + pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) { + self.invalidator.debug_assert_prepaint(); + if focus_handle.is_focused(self) { + self.next_frame.focus = Some(focus_handle.id); + } + self.next_frame.dispatch_tree.set_focus_id(focus_handle.id); + } + + /// Sets the view id for the current element, which will be used to manage view caching. + /// + /// This method should only be called as part of element prepaint. We plan on removing this + /// method eventually when we solve some issues that require us to construct editor elements + /// directly instead of always using editors via views. + pub fn set_view_id(&mut self, view_id: EntityId) { + self.invalidator.debug_assert_prepaint(); + self.next_frame.dispatch_tree.set_view_id(view_id); + } + + /// Get the entity ID for the currently rendering view + pub fn current_view(&self) -> EntityId { + self.invalidator.debug_assert_paint_or_prepaint(); + self.rendered_entity_stack.last().copied().unwrap() + } + + #[inline] + pub(crate) fn with_rendered_view( + &mut self, + id: EntityId, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.rendered_entity_stack.push(id); + let result = f(self); + self.rendered_entity_stack.pop(); + result + } + + /// Executes the provided function with the specified image cache. + pub fn with_image_cache(&mut self, image_cache: Option, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + if let Some(image_cache) = image_cache { + self.image_cache_stack.push(image_cache); + let result = f(self); + self.image_cache_stack.pop(); + result + } else { + f(self) + } + } + + /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the + /// platform to receive textual input with proper integration with concerns such + /// as IME interactions. This handler will be active for the upcoming frame until the following frame is + /// rendered. + /// + /// This method should only be called as part of the paint phase of element drawing. + /// + /// [element_input_handler]: crate::ElementInputHandler + pub fn handle_input( + &mut self, + focus_handle: &FocusHandle, + input_handler: impl InputHandler, + cx: &App, + ) { + self.invalidator.debug_assert_paint(); + + if focus_handle.is_focused(self) { + let cx = self.to_async(cx); + self.next_frame + .input_handlers + .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler)))); + } + } + + /// Forwards the focused input handler's [`TextInputConfiguration`] to the + /// platform window when it differs from the last forwarded value. With no + /// input handler the default configuration applies, so a field's + /// preferences don't outlive its focus. + fn apply_text_input_configuration(&mut self, cx: &mut App) { + let configuration = match self.platform_window.take_input_handler() { + Some(mut input_handler) => { + let configuration = input_handler.text_input_configuration(self, cx); + self.platform_window.set_input_handler(input_handler); + configuration + } + None => TextInputConfiguration::default(), + }; + if self.last_text_input_configuration.as_ref() != Some(&configuration) { + self.platform_window + .set_text_input_configuration(configuration.clone()); + self.last_text_input_configuration = Some(configuration); + } + } + + /// Register a mouse event listener on the window for the next frame. The type of event + /// is determined by the first parameter of the given listener. When the next frame is rendered + /// the listener will be cleared. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn on_mouse_event( + &mut self, + mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static, + ) { + self.invalidator.debug_assert_paint(); + + self.next_frame.mouse_listeners.push(Some(Box::new( + move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| { + if let Some(event) = event.downcast_ref() { + listener(event, phase, window, cx) + } + }, + ))); + } + + /// Register a key event listener on this node for the next frame. The type of event + /// is determined by the first parameter of the given listener. When the next frame is rendered + /// the listener will be cleared. + /// + /// This is a fairly low-level method, so prefer using event handlers on elements unless you have + /// a specific need to register a listener yourself. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn on_key_event( + &mut self, + listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static, + ) { + self.invalidator.debug_assert_paint(); + + self.next_frame.dispatch_tree.on_key_event(Rc::new( + move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| { + if let Some(event) = event.downcast_ref::() { + listener(event, phase, window, cx) + } + }, + )); + } + + /// Register a modifiers changed event listener on the window for the next frame. + /// + /// This is a fairly low-level method, so prefer using event handlers on elements unless you have + /// a specific need to register a global listener. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn on_modifiers_changed( + &mut self, + listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static, + ) { + self.invalidator.debug_assert_paint(); + + self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new( + move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| { + listener(event, window, cx) + }, + )); + } + + /// Register a listener to be called when the given focus handle or one of its descendants receives focus. + /// This does not fire if the given focus handle - or one of its descendants - was previously focused. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus_in( + &mut self, + handle: &FocusHandle, + cx: &mut App, + mut listener: impl FnMut(&mut Window, &mut App) + 'static, + ) -> Subscription { + let focus_id = handle.id; + let (subscription, activate) = + self.new_focus_listener(Box::new(move |event, window, cx| { + if event.is_focus_in(focus_id) { + listener(window, cx); + } + true + })); + cx.defer(move |_| activate()); + subscription + } + + /// Register a listener to be called when the given focus handle or one of its descendants loses focus. + /// Returns a subscription and persists until the subscription is dropped. + pub fn on_focus_out( + &mut self, + handle: &FocusHandle, + cx: &mut App, + mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static, + ) -> Subscription { + let focus_id = handle.id; + let (subscription, activate) = + self.new_focus_listener(Box::new(move |event, window, cx| { + if let Some(blurred_id) = event.previous_focus_path.last().copied() + && event.is_focus_out(focus_id) + { + let event = FocusOutEvent { + blurred: WeakFocusHandle { + id: blurred_id, + handles: Arc::downgrade(&cx.focus_handles), + }, + }; + listener(event, window, cx) + } + true + })); + cx.defer(move |_| activate()); + subscription + } + + fn reset_cursor_style(&self, cx: &mut App) { + // Set the cursor only if we're the active window. + if self.is_window_hovered() { + let style = self + .rendered_frame + .cursor_style(self) + .unwrap_or(CursorStyle::Arrow); + cx.platform.set_cursor_style(style); + } + } + + /// Dispatch a given keystroke as though the user had typed it. + /// You can create a keystroke with Keystroke::parse(""). + pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool { + let keystroke = keystroke.with_simulated_ime(); + let result = self.dispatch_event( + PlatformInput::KeyDown(KeyDownEvent { + keystroke: keystroke.clone(), + is_held: false, + prefer_character_input: false, + }), + cx, + ); + if !result.propagate { + return true; + } + + if let Some(input) = keystroke.key_char + && let Some(mut input_handler) = self.platform_window.take_input_handler() + { + input_handler.dispatch_input(&input, self, cx); + self.platform_window.set_input_handler(input_handler); + return true; + } + + false + } + + /// Return a key binding string for an action, to display in the UI. Uses the highest precedence + /// binding for the action (last binding added to the keymap). + pub fn keystroke_text_for(&self, action: &dyn Action) -> String { + self.highest_precedence_binding_for_action(action) + .map(|binding| { + binding + .keystrokes() + .iter() + .map(ToString::to_string) + .collect::>() + .join(" ") + }) + .unwrap_or_else(|| action.name().to_string()) + } + + /// Dispatch a mouse, keyboard, or touch event on the window. + #[profiling::function] + pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult { + #[cfg(feature = "profiler")] + self.window_profiler.begin_input(event.kind_name()); + let update_count_before = self.invalidator.update_count(); + // Track input modality for focus-visible styling and hover suppression. + // Hover is suppressed during keyboard modality so that keyboard navigation + // doesn't show hover highlights on the item under the mouse cursor. + let old_modality = self.last_input_modality; + self.last_input_modality = match &event { + PlatformInput::KeyDown(_) => InputModality::Keyboard, + PlatformInput::MouseMove(_) | PlatformInput::MouseDown(_) => InputModality::Mouse, + PlatformInput::Touch(_) => InputModality::Touch, + _ => self.last_input_modality, + }; + if self.last_input_modality != old_modality { + self.refresh(); + } + + // Handlers may set this to false by calling `stop_propagation`. + cx.propagate_event = true; + // Handlers may set this to true by calling `prevent_default`. + self.default_prevented = false; + + let event = match event { + // Track the mouse position with our own state, since accessing the platform + // API for the mouse position can only occur on the main thread. + PlatformInput::MouseMove(mouse_move) => { + self.mouse_position = mouse_move.position; + self.modifiers = mouse_move.modifiers; + PlatformInput::MouseMove(mouse_move) + } + PlatformInput::MouseDown(mouse_down) => { + self.mouse_position = mouse_down.position; + self.modifiers = mouse_down.modifiers; + PlatformInput::MouseDown(mouse_down) + } + PlatformInput::MouseUp(mouse_up) => { + self.mouse_position = mouse_up.position; + self.modifiers = mouse_up.modifiers; + PlatformInput::MouseUp(mouse_up) + } + PlatformInput::MousePressure(mouse_pressure) => { + PlatformInput::MousePressure(mouse_pressure) + } + PlatformInput::MouseExited(mouse_exited) => { + self.modifiers = mouse_exited.modifiers; + PlatformInput::MouseExited(mouse_exited) + } + PlatformInput::ModifiersChanged(modifiers_changed) => { + self.modifiers = modifiers_changed.modifiers; + self.capslock = modifiers_changed.capslock; + PlatformInput::ModifiersChanged(modifiers_changed) + } + PlatformInput::ScrollWheel(scroll_wheel) => { + self.mouse_position = scroll_wheel.position; + self.modifiers = scroll_wheel.modifiers; + PlatformInput::ScrollWheel(scroll_wheel) + } + PlatformInput::Pinch(pinch) => { + self.mouse_position = pinch.position; + self.modifiers = pinch.modifiers; + PlatformInput::Pinch(pinch) + } + // Translate dragging and dropping of external files from the operating system + // to internal drag and drop events. + PlatformInput::FileDrop(file_drop) => match file_drop { + FileDropEvent::Entered { position, paths } => { + self.mouse_position = position; + let source_window = self.handle.window_id(); + if !cx.restore_platform_drag(source_window) && cx.active_drag.is_none() { + cx.active_drag = Some(AnyDrag { + value: Arc::new(paths.clone()), + view: cx.new(|_| paths).into(), + cursor_offset: position, + cursor_style: None, + external_payload_source: None, + }); + } + PlatformInput::MouseMove(MouseMoveEvent { + position, + pressed_button: Some(MouseButton::Left), + modifiers: Modifiers::default(), + }) + } + FileDropEvent::Pending { position } => { + self.mouse_position = position; + PlatformInput::MouseMove(MouseMoveEvent { + position, + pressed_button: Some(MouseButton::Left), + modifiers: Modifiers::default(), + }) + } + FileDropEvent::Submit { position } => { + cx.activate(true); + self.mouse_position = position; + PlatformInput::MouseUp(MouseUpEvent { + button: MouseButton::Left, + position, + modifiers: Modifiers::default(), + click_count: 1, + }) + } + FileDropEvent::Exited => { + if !cx.hand_restored_drag_to_platform(self.handle.window_id()) { + cx.active_drag.take(); + } + self.refresh(); + PlatformInput::FileDrop(FileDropEvent::Exited) + } + FileDropEvent::Ended => { + cx.end_platform_drag(self.handle.window_id()); + self.refresh(); + PlatformInput::FileDrop(FileDropEvent::Ended) + } + }, + PlatformInput::Touch(touch) => PlatformInput::Touch(touch), + PlatformInput::LongPress(long_press) => { + self.mouse_position = if long_press.phase == crate::TouchPhase::Started { + long_press.start_position + } else { + long_press.position + }; + if long_press.phase == crate::TouchPhase::Started { + self.long_press_capture = None; + } + PlatformInput::LongPress(long_press) + } + PlatformInput::TouchDrag(touch_drag) => { + self.mouse_position = touch_drag.start_position; + PlatformInput::TouchDrag(touch_drag) + } + PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event, + }; + + if let Some(any_mouse_event) = event.mouse_event() { + self.dispatch_mouse_event(any_mouse_event, cx); + } else if let Some(any_key_event) = event.keyboard_event() { + self.dispatch_key_event(any_key_event, cx); + } else if let Some(touch_event) = event.touch_event() { + self.dispatch_touch_event(touch_event, cx); + } + if let PlatformInput::LongPress(long_press) = &event { + match long_press.phase { + crate::TouchPhase::Started if !self.default_prevented => { + self.long_press_capture = None; + } + crate::TouchPhase::Ended | crate::TouchPhase::Cancelled => { + self.long_press_capture = None; + } + crate::TouchPhase::Started | crate::TouchPhase::Moved => {} + } + } + + // Must run after the move is dispatched: the platform owns the gesture afterwards, so this + // is the last chance for drag listeners to see the pointer leave and reset their state. + self.promote_external_drag_to_platform(&event, cx); + + let caused_invalidation = self.invalidator.update_count() > update_count_before; + if caused_invalidation { + self.input_rate_tracker.borrow_mut().record_input(); + } + #[cfg(feature = "profiler")] + self.window_profiler.end_input(caused_invalidation); + + DispatchEventResult { + propagate: cx.propagate_event, + default_prevented: self.default_prevented, + } + } + + fn promote_external_drag_to_platform(&mut self, event: &PlatformInput, cx: &mut App) { + let PlatformInput::MouseMove(mouse_move) = event else { + return; + }; + if mouse_move.pressed_button != Some(MouseButton::Left) { + return; + } + if Bounds::new(Point::default(), self.viewport_size).contains(&mouse_move.position) { + return; + } + if !self.platform_window.can_start_external_drag() { + return; + } + let Some(payload_source) = cx + .active_drag + .as_mut() + .and_then(|drag| drag.external_payload_source.take()) + else { + return; + }; + let Some(payload) = payload_source(self, cx) else { + return; + }; + if self.platform_window.start_external_drag(&payload) + && cx.hand_active_drag_to_platform(self.handle.window_id()) + { + self.refresh(); + } + } + + /// Whether recognized touch pans may use the platform's predicted touch + /// positions ([`TouchEvent::predicted_position`]) to compensate for input + /// latency. Defaults to true. + pub fn touch_prediction_enabled(&self) -> bool { + self.touch_prediction_enabled + } + + /// Sets whether recognized touch pans may use the platform's predicted + /// touch positions. Disabling drops [`TouchEvent::predicted_position`] + /// before gesture recognition, so pans track only raw touch positions. + pub fn set_touch_prediction_enabled(&mut self, enabled: bool) { + self.touch_prediction_enabled = enabled; + } + + /// Runs the portable gesture recognizer over a raw touch event and + /// dispatches whatever it resolves (scroll steps, synthesized taps) + /// through the ordinary mouse-event path. + fn dispatch_touch_event(&mut self, event: &TouchEvent, cx: &mut App) { + let mut event = event.clone(); + if !self.touch_prediction_enabled { + event.predicted_position = None; + } + let recognized_gestures = self.touch_gestures.handle_event(&event); + if event.phase == crate::TouchPhase::Started + && let Some(touch_drag) = self.touch_gestures.offer_touch_drag(event.id) + { + self.dispatch_recognized_touch_gesture(touch_drag, cx); + } + if event.phase == crate::TouchPhase::Started + && self.touch_gestures.pending_long_press().is_some() + { + self.long_press_capture = None; + } + let mut tapped = false; + for gesture in recognized_gestures { + tapped |= matches!(gesture, RecognizedTouchGesture::Tap { .. }); + self.dispatch_recognized_touch_gesture(gesture, cx); + } + if event.phase == crate::TouchPhase::Started { + self.schedule_long_press_timer(cx); + } else if self.touch_gestures.pending_long_press().is_none() { + self.long_press_timer.take(); + } + // The platform's touch-release handler may inspect the input handler + // as soon as this dispatch returns (the web platform decides virtual + // keyboard visibility there, inside the user gesture). Input handlers + // are registered during draw, so draw now to make them reflect any + // focus change the tap just caused. + if tapped && self.invalidator.is_dirty() { + self.draw(cx).clear(cx); + } + if self.touch_gestures.has_momentum() { + self.schedule_touch_momentum_tick(); + } + } + + fn dispatch_recognized_touch_gesture(&mut self, gesture: RecognizedTouchGesture, cx: &mut App) { + match gesture { + RecognizedTouchGesture::Scroll(scroll_wheel) => { + self.mouse_position = scroll_wheel.position; + cx.propagate_event = true; + self.dispatch_mouse_event(&scroll_wheel, cx); + } + RecognizedTouchGesture::Tap { down, up } => { + self.mouse_position = up.position; + cx.propagate_event = true; + self.dispatch_mouse_event(&down, cx); + cx.propagate_event = true; + self.dispatch_mouse_event(&up, cx); + } + RecognizedTouchGesture::TouchDrag(touch_drag) => { + self.mouse_position = touch_drag.start_position; + cx.propagate_event = true; + self.default_prevented = false; + let started = touch_drag.phase == crate::TouchPhase::Started; + self.dispatch_mouse_event(&touch_drag, cx); + if started { + self.touch_gestures + .resolve_touch_drag(self.default_prevented); + } + } + RecognizedTouchGesture::LongPress(long_press) => { + self.mouse_position = if long_press.phase == crate::TouchPhase::Started { + long_press.start_position + } else { + long_press.position + }; + cx.propagate_event = true; + self.default_prevented = false; + let started = long_press.phase == crate::TouchPhase::Started; + let ended = matches!( + long_press.phase, + crate::TouchPhase::Ended | crate::TouchPhase::Cancelled + ); + self.dispatch_mouse_event(&long_press, cx); + if started { + let claimed = self.default_prevented; + self.touch_gestures.resolve_long_press(claimed); + if !claimed { + self.long_press_capture = None; + } + } + if ended { + self.long_press_capture = None; + } + } + } + } + + fn schedule_long_press_timer(&mut self, cx: &mut App) { + self.long_press_timer.take(); + let Some((touch_id, duration)) = self.touch_gestures.pending_long_press() else { + return; + }; + self.long_press_timer = Some(self.spawn(cx, async move |cx| { + cx.background_executor.timer(duration).await; + cx.update(move |window, cx| { + window.long_press_timer.take(); + if let Some(gesture) = window.touch_gestures.offer_long_press(touch_id) { + window.dispatch_recognized_touch_gesture(gesture, cx); + } + }) + .log_err(); + })); + } + + fn schedule_touch_momentum_tick(&mut self) { + self.on_next_frame(|window, cx| { + if let Some(gesture) = window.touch_gestures.tick_momentum() { + window.dispatch_recognized_touch_gesture(gesture, cx); + } + if window.touch_gestures.has_momentum() { + window.schedule_touch_momentum_tick(); + } + }); + } + + fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) { + let hit_test = self.rendered_frame.hit_test(self.mouse_position()); + if hit_test != self.mouse_hit_test { + self.mouse_hit_test = hit_test; + self.reset_cursor_style(cx); + } + + #[cfg(any(feature = "inspector", debug_assertions))] + if self.is_inspector_picking(cx) { + self.handle_inspector_mouse_event(event, cx); + // When inspector is picking, all other mouse handling is skipped. + return; + } + + let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners); + + // Capture phase, events bubble from back to front. Handlers for this phase are used for + // special purposes, such as detecting events outside of a given Bounds. + for listener in &mut mouse_listeners { + let listener = listener.as_mut().unwrap(); + listener(event, DispatchPhase::Capture, self, cx); + if !cx.propagate_event { + break; + } + } + + // Bubble phase, where most normal handlers do their work. + if cx.propagate_event { + for listener in mouse_listeners.iter_mut().rev() { + let listener = listener.as_mut().unwrap(); + listener(event, DispatchPhase::Bubble, self, cx); + if !cx.propagate_event { + break; + } + } + } + + self.rendered_frame.mouse_listeners = mouse_listeners; + + if cx.has_active_drag() { + if event.is::() { + // If this was a mouse move event, redraw the window so that the + // active drag can follow the mouse cursor. + self.refresh(); + } else if event.is::() { + // If this was a mouse up event, cancel the active drag and redraw + // the window. + cx.active_drag = None; + self.refresh(); + } + } + + // Auto-release pointer capture on mouse up + if event.is::() && self.captured_hitbox.is_some() { + self.captured_hitbox = None; + } + } + + // If modifiers are not excessive (e.g. AltGr), and the input handler is accepting text input, + // we prefer the text input over bindings. + fn input_preference(&mut self, event: &dyn Any, cx: &mut App) -> InputPreference { + let prefer_character_input = event + .downcast_ref::() + .is_some_and(|key_down_event| key_down_event.prefer_character_input); + if !prefer_character_input { + return InputPreference::KeyBindings; + } + let Some(mut input_handler) = self.platform_window.take_input_handler() else { + return InputPreference::KeyBindings; + }; + let accepts_text_input = input_handler.accepts_text_input(self, cx); + self.platform_window.set_input_handler(input_handler); + if accepts_text_input { + InputPreference::CharacterInput + } else { + InputPreference::KeyBindings + } + } + + fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) { + if self.invalidator.is_dirty() { + self.draw(cx).clear(cx); + } + + let node_id = self.focus_node_id_in_rendered_frame(self.focus); + let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id); + + let mut keystroke: Option = None; + + if let Some(event) = event.downcast_ref::() { + if event.modifiers.number_of_modifiers() == 0 + && self.pending_modifier.modifiers.number_of_modifiers() == 1 + && !self.pending_modifier.saw_other_input + { + let key = match self.pending_modifier.modifiers { + modifiers if modifiers.shift => Some("shift"), + modifiers if modifiers.control => Some("control"), + modifiers if modifiers.alt => Some("alt"), + modifiers if modifiers.platform => Some("platform"), + modifiers if modifiers.function => Some("function"), + _ => None, + }; + if let Some(key) = key { + keystroke = Some(Keystroke { + key: key.to_string(), + key_char: None, + modifiers: Modifiers::default(), + }); + } + } + + if self.pending_modifier.modifiers.number_of_modifiers() == 0 + && event.modifiers.number_of_modifiers() == 1 + { + self.pending_modifier.saw_other_input = false + } else if event.modifiers.number_of_modifiers() > 1 { + self.pending_modifier.saw_other_input = true + } + self.pending_modifier.modifiers = event.modifiers + } else if let Some(key_down_event) = event.downcast_ref::() { + self.pending_modifier.saw_other_input = true; + keystroke = Some(key_down_event.keystroke.clone()); + if key_down_event.keystroke.key_char.is_some() + && matches!( + cx.cursor_hide_mode, + CursorHideMode::OnTyping | CursorHideMode::OnTypingAndAction + ) + { + cx.platform.hide_cursor_until_mouse_moves(); + } + } + + let Some(keystroke) = keystroke else { + self.finish_dispatch_key_event( + event, + None, + InputPreference::KeyBindings, + dispatch_path, + self.context_stack(), + cx, + ); + return; + }; + + let input_preference = self.input_preference(event, cx); + + cx.propagate_event = true; + self.dispatch_keystroke_interceptors( + &keystroke, + input_preference, + self.context_stack(), + cx, + ); + if !cx.propagate_event { + self.finish_dispatch_key_event( + event, + Some(&keystroke), + input_preference, + dispatch_path, + self.context_stack(), + cx, + ); + return; + } + + let mut currently_pending = self.pending_input.take().unwrap_or_default(); + if currently_pending.focus.is_some() && currently_pending.focus != self.focus { + currently_pending = PendingInput::default(); + } + + let match_result = self.rendered_frame.dispatch_tree.dispatch_key( + currently_pending.keystrokes, + keystroke.clone(), + &dispatch_path, + ); + + if !match_result.to_replay.is_empty() { + self.replay_pending_input(match_result.to_replay, cx); + cx.propagate_event = true; + } + + if !match_result.pending.is_empty() { + let previous_timeout = currently_pending.timeout.take(); + currently_pending.keystrokes = match_result.pending; + currently_pending.focus = self.focus; + + let text_input_requires_timeout = event + .downcast_ref::() + .filter(|key_down| key_down.keystroke.key_char.is_some()) + .and_then(|_| self.platform_window.take_input_handler()) + .map_or(false, |mut input_handler| { + let accepts = input_handler.accepts_text_input(self, cx); + self.platform_window.set_input_handler(input_handler); + accepts + }); + + let needs_timeout = previous_timeout.is_some() + || match_result.pending_has_binding + || text_input_requires_timeout; + currently_pending.timeout = if needs_timeout { + match previous_timeout { + Some(mut timeout) if timeout.is_paused() => { + timeout.reset_duration(PENDING_INPUT_TIMEOUT); + Some(timeout) + } + previous_timeout => { + drop(previous_timeout); + Some(self.new_pending_input_timeout(PENDING_INPUT_TIMEOUT, cx)) + } + } + } else { + None + }; + self.pending_input = Some(currently_pending); + self.pending_input_changed(cx); + cx.propagate_event = false; + return; + } + + // Interceptors or replayed actions may have changed whether the input handler accepts text. + let input_preference = self.input_preference(event, cx); + if input_preference == InputPreference::KeyBindings { + for binding in match_result.bindings { + self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx); + if !cx.propagate_event { + self.dispatch_keystroke_observers( + &keystroke, + input_preference, + Some(binding.action.as_ref()), + match_result.context_stack, + cx, + ); + self.pending_input_changed(cx); + return; + } + } + } + + self.finish_dispatch_key_event( + event, + Some(&keystroke), + input_preference, + dispatch_path, + match_result.context_stack, + cx, + ); + self.pending_input_changed(cx); + } + + fn new_pending_input_timeout(&self, duration: Duration, cx: &App) -> PendingInputTimeout { + let (started_at, task) = self.start_pending_input_timeout(duration, cx); + PendingInputTimeout { + duration, + remaining: duration, + state: PendingInputTimeoutState::Running { started_at, task }, + } + } + + fn start_pending_input_timeout(&self, remaining: Duration, cx: &App) -> (Instant, Task<()>) { + let started_at = cx.background_executor().now(); + let task = self.spawn(cx, async move |cx| { + cx.background_executor.timer(remaining).await; + cx.update(move |window, cx| { + let Some(currently_pending) = window + .pending_input + .take() + .filter(|pending| pending.focus == window.focus) + else { + return; + }; + + let node_id = window.focus_node_id_in_rendered_frame(window.focus); + let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id); + + let to_replay = window + .rendered_frame + .dispatch_tree + .flush_dispatch(currently_pending.keystrokes, &dispatch_path); + + window.pending_input_changed(cx); + window.replay_pending_input(to_replay, cx) + }) + .log_err(); + }); + (started_at, task) + } + + fn finish_dispatch_key_event( + &mut self, + event: &dyn Any, + recognized_keystroke: Option<&Keystroke>, + input_preference: InputPreference, + dispatch_path: SmallVec<[DispatchNodeId; 32]>, + context_stack: Vec, + cx: &mut App, + ) { + self.dispatch_key_down_up_event(event, &dispatch_path, cx); + if !cx.propagate_event { + return; + } + + self.dispatch_modifiers_changed_event(event, &dispatch_path, cx); + if !cx.propagate_event { + return; + } + + if let Some(keystroke) = recognized_keystroke { + self.dispatch_keystroke_observers(keystroke, input_preference, None, context_stack, cx); + } + } + + pub(crate) fn pending_input_changed(&mut self, cx: &mut App) { + self.pending_input_observers + .clone() + .retain(&(), |callback| callback(self, cx)); + } + + fn defer_pending_input_changed(&self, cx: &mut App) { + // Avoid re-entrant entity updates by deferring observer notifications to the end of the + // current effect cycle, and only for this window. + let window_handle = self.handle; + cx.defer(move |cx| { + window_handle + .update(cx, |_, window, cx| { + window.pending_input_changed(cx); + }) + .ok(); + }); + } + + fn dispatch_key_down_up_event( + &mut self, + event: &dyn Any, + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + cx: &mut App, + ) { + // Capture phase + for node_id in dispatch_path { + let node = self.rendered_frame.dispatch_tree.node(*node_id); + + for key_listener in node.key_listeners.clone() { + key_listener(event, DispatchPhase::Capture, self, cx); + if !cx.propagate_event { + return; + } + } + } + + // Bubble phase + for node_id in dispatch_path.iter().rev() { + // Handle low level key events + let node = self.rendered_frame.dispatch_tree.node(*node_id); + for key_listener in node.key_listeners.clone() { + key_listener(event, DispatchPhase::Bubble, self, cx); + if !cx.propagate_event { + return; + } + } + } + } + + fn dispatch_modifiers_changed_event( + &mut self, + event: &dyn Any, + dispatch_path: &SmallVec<[DispatchNodeId; 32]>, + cx: &mut App, + ) { + let Some(event) = event.downcast_ref::() else { + return; + }; + for node_id in dispatch_path.iter().rev() { + let node = self.rendered_frame.dispatch_tree.node(*node_id); + for listener in node.modifiers_changed_listeners.clone() { + listener(event, self, cx); + if !cx.propagate_event { + return; + } + } + } + } + + /// Determine whether a potential multi-stroke key binding is in progress on this window. + pub fn has_pending_keystrokes(&self) -> bool { + self.pending_input().is_some() + } + + #[cfg(test)] + pub(crate) fn pending_input_is_none(&self) -> bool { + self.pending_input.is_none() + } + + pub(crate) fn clear_pending_keystrokes(&mut self, cx: &mut App) { + if self.pending_input.take().is_some() { + self.defer_pending_input_changed(cx); + } + } + + /// Returns pending input that can still complete a multi-stroke key binding. Input left over + /// from a previous focus can never complete one. + pub fn pending_input(&self) -> Option> { + self.pending_input + .as_ref() + .filter(|pending_input| pending_input.focus == self.focus) + .map(|pending_input| PendingInputStatus { + keystrokes: pending_input.keystrokes.as_slice(), + timeout: pending_input + .timeout + .as_ref() + .map(PendingInputTimeout::status), + }) + } + + /// Pauses or resumes the current pending input timeout on behalf of `owner`. + /// + /// A paused timeout resumes automatically if `owner` is released. Returns whether the timeout + /// state changed. A timeout paused by one owner cannot be resumed by another. + pub fn set_pending_input_timeout_paused( + &mut self, + owner: &Entity, + paused: bool, + cx: &mut App, + ) -> bool { + let owner_id = owner.entity_id(); + if !paused { + return self.resume_pending_input_timeout(owner_id, cx); + } + + let timeout = self + .pending_input + .as_ref() + .filter(|pending_input| pending_input.focus == self.focus) + .and_then(|pending_input| pending_input.timeout.as_ref()); + let Some(timeout) = timeout else { + return false; + }; + if timeout.is_paused() { + return false; + } + + let release_subscription = self.observe_release(owner, cx, move |_, window, cx| { + window.resume_pending_input_timeout(owner_id, cx); + }); + let now = cx.background_executor().now(); + let changed = self + .pending_input + .as_mut() + .filter(|pending_input| pending_input.focus == self.focus) + .and_then(|pending_input| pending_input.timeout.as_mut()) + .is_some_and(|timeout| { + timeout.pause( + PendingInputTimeoutPause { + owner_id, + _release_subscription: release_subscription, + }, + now, + ) + }); + + if changed { + self.defer_pending_input_changed(cx); + } + changed + } + + fn resume_pending_input_timeout(&mut self, owner_id: EntityId, cx: &mut App) -> bool { + let Some(remaining) = self + .pending_input + .as_ref() + .and_then(|pending_input| pending_input.timeout.as_ref()) + .filter(|timeout| timeout.pause_owner_id() == Some(owner_id)) + .map(|timeout| timeout.remaining) + else { + return false; + }; + + let (started_at, task) = self.start_pending_input_timeout(remaining, cx); + let changed = self + .pending_input + .as_mut() + .and_then(|pending_input| pending_input.timeout.as_mut()) + .is_some_and(|timeout| timeout.resume(owner_id, started_at, task)); + + if changed { + self.defer_pending_input_changed(cx); + } + changed + } + + /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding. + pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> { + self.pending_input() + .map(|pending_input| pending_input.keystrokes()) + } + + fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) { + let node_id = self.focus_node_id_in_rendered_frame(self.focus); + let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id); + + 'replay: for replay in replays { + let event = KeyDownEvent { + keystroke: replay.keystroke.clone(), + is_held: false, + prefer_character_input: true, + }; + + cx.propagate_event = true; + for binding in replay.bindings { + self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx); + if !cx.propagate_event { + self.dispatch_keystroke_observers( + &replay.keystroke, + InputPreference::KeyBindings, + Some(binding.action.as_ref()), + Vec::default(), + cx, + ); + continue 'replay; + } + } + + self.dispatch_key_down_up_event(&event, &dispatch_path, cx); + if !cx.propagate_event { + continue 'replay; + } + if let Some(input) = replay.keystroke.key_char.as_ref().cloned() + && let Some(mut input_handler) = self.platform_window.take_input_handler() + { + input_handler.dispatch_input(&input, self, cx); + self.platform_window.set_input_handler(input_handler) + } + } + } + + fn focus_node_id_in_rendered_frame(&self, focus_id: Option) -> DispatchNodeId { + focus_id + .and_then(|focus_id| { + self.rendered_frame + .dispatch_tree + .focusable_node_id(focus_id) + }) + .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id()) + } + + fn dispatch_action_on_node( + &mut self, + node_id: DispatchNodeId, + action: &dyn Action, + cx: &mut App, + ) { + self.dispatch_action_on_node_inner(node_id, action, cx); + + if !cx.propagate_event + && cx.cursor_hide_mode == CursorHideMode::OnTypingAndAction + && self.last_input_was_keyboard() + { + cx.platform.hide_cursor_until_mouse_moves(); + } + } + + fn dispatch_action_on_node_inner( + &mut self, + node_id: DispatchNodeId, + action: &dyn Action, + cx: &mut App, + ) { + let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id); + + // Capture phase for global actions. + cx.propagate_event = true; + if let Some(mut global_listeners) = cx + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in &global_listeners { + #[cfg(feature = "profiler")] + self.window_profiler.begin_action_handler(action, cx); + listener(action.as_any(), DispatchPhase::Capture, cx); + #[cfg(feature = "profiler")] + self.window_profiler.end_action_handler(); + if !cx.propagate_event { + break; + } + } + + global_listeners.extend( + cx.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + cx.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } + + if !cx.propagate_event { + return; + } + + // Capture phase for window actions. + for node_id in &dispatch_path { + let node = self.rendered_frame.dispatch_tree.node(*node_id); + for DispatchActionListener { + action_type, + listener, + } in node.action_listeners.clone() + { + let any_action = action.as_any(); + if action_type == any_action.type_id() { + #[cfg(feature = "profiler")] + self.window_profiler.begin_action_handler(action, cx); + listener(any_action, DispatchPhase::Capture, self, cx); + #[cfg(feature = "profiler")] + self.window_profiler.end_action_handler(); + + if !cx.propagate_event { + return; + } + } + } + } + + // Bubble phase for window actions. + for node_id in dispatch_path.iter().rev() { + let node = self.rendered_frame.dispatch_tree.node(*node_id); + for DispatchActionListener { + action_type, + listener, + } in node.action_listeners.clone() + { + let any_action = action.as_any(); + if action_type == any_action.type_id() { + cx.propagate_event = false; // Actions stop propagation by default during the bubble phase + #[cfg(feature = "profiler")] + self.window_profiler.begin_action_handler(action, cx); + listener(any_action, DispatchPhase::Bubble, self, cx); + #[cfg(feature = "profiler")] + self.window_profiler.end_action_handler(); + + if !cx.propagate_event { + return; + } + } + } + } + + // Bubble phase for global actions. + if let Some(mut global_listeners) = cx + .global_action_listeners + .remove(&action.as_any().type_id()) + { + for listener in global_listeners.iter().rev() { + cx.propagate_event = false; // Actions stop propagation by default during the bubble phase + + #[cfg(feature = "profiler")] + self.window_profiler.begin_action_handler(action, cx); + listener(action.as_any(), DispatchPhase::Bubble, cx); + #[cfg(feature = "profiler")] + self.window_profiler.end_action_handler(); + if !cx.propagate_event { + break; + } + } + + global_listeners.extend( + cx.global_action_listeners + .remove(&action.as_any().type_id()) + .unwrap_or_default(), + ); + + cx.global_action_listeners + .insert(action.as_any().type_id(), global_listeners); + } + } + + /// Register the given handler to be invoked whenever the global of the given type + /// is updated. + pub fn observe_global( + &mut self, + cx: &mut App, + f: impl Fn(&mut Window, &mut App) + 'static, + ) -> Subscription { + let window_handle = self.handle; + let (subscription, activate) = cx.global_observers.insert( + TypeId::of::(), + Box::new(move |cx| { + window_handle + .update(cx, |_, window, cx| f(window, cx)) + .is_ok() + }), + ); + cx.defer(move |_| activate()); + subscription + } + + /// Focus the current window and bring it to the foreground at the platform level. + pub fn activate_window(&self) { + self.platform_window.activate(); + } + + /// Requests that the operating system draw attention to this window. + pub fn request_attention(&self) { + self.platform_window.request_attention(); + } + + /// Minimize the current window at the platform level. + pub fn minimize_window(&self) { + self.platform_window.minimize(); + } + + /// Toggle full screen status on the current window at the platform level. + pub fn toggle_fullscreen(&self) { + self.platform_window.toggle_fullscreen(); + } + + /// Toggle simple (borderless) fullscreen, where the window covers the entire + /// screen including the menu bar and, on notched displays, the area around the + /// notch. Unlike [`Window::toggle_fullscreen`], this does not move the window + /// into its own Mission Control space. Only has an effect on macOS. + pub fn toggle_simple_fullscreen(&self) { + self.platform_window.toggle_simple_fullscreen(); + } + + /// Updates the IME panel position suggestions for languages like japanese, chinese. + pub fn invalidate_character_coordinates(&self) { + self.on_next_frame(|window, cx| { + if let Some(mut input_handler) = window.platform_window.take_input_handler() { + if let Some(bounds) = input_handler.selected_bounds(window, cx) { + window.platform_window.update_ime_position(bounds); + } + window.platform_window.set_input_handler(input_handler); + } + }); + } + + /// Present a platform dialog. + /// The provided message will be presented, along with buttons for each answer. + /// When a button is clicked, the returned Receiver will receive the index of the clicked button. + pub fn prompt( + &mut self, + level: PromptLevel, + message: &str, + detail: Option<&str>, + answers: &[T], + cx: &mut App, + ) -> oneshot::Receiver + where + T: Clone + Into, + { + let prompt_builder = cx.prompt_builder.take(); + let Some(prompt_builder) = prompt_builder else { + unreachable!("Re-entrant window prompting is not supported by GPUI"); + }; + + let answers = answers + .iter() + .map(|answer| answer.clone().into()) + .collect::>(); + + let receiver = match &prompt_builder { + PromptBuilder::Default => self + .platform_window + .prompt(level, message, detail, &answers) + .unwrap_or_else(|| { + self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx) + }), + PromptBuilder::Custom(_) => { + self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx) + } + }; + + cx.prompt_builder = Some(prompt_builder); + + receiver + } + + fn build_custom_prompt( + &mut self, + prompt_builder: &PromptBuilder, + level: PromptLevel, + message: &str, + detail: Option<&str>, + answers: &[PromptButton], + cx: &mut App, + ) -> oneshot::Receiver { + let (sender, receiver) = oneshot::channel(); + let handle = PromptHandle::new(sender); + let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx); + self.prompt = Some(handle); + receiver + } + + /// Returns whether a prompt rendered by GPUI is currently active in this window. + /// + /// This is only true for prompts rendered in the window (see + /// [`App::set_prompt_builder`]), not for platform-native prompt dialogs. + pub fn has_active_prompt(&self) -> bool { + self.prompt.is_some() + } + + /// Returns the current context stack. + pub fn context_stack(&self) -> Vec { + let node_id = self.focus_node_id_in_rendered_frame(self.focus); + let dispatch_tree = &self.rendered_frame.dispatch_tree; + dispatch_tree + .dispatch_path(node_id) + .iter() + .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone()) + .collect() + } + + /// Returns all available actions for the focused element. + pub fn available_actions(&self, cx: &App) -> Vec> { + let node_id = self.focus_node_id_in_rendered_frame(self.focus); + let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id); + for action_type in cx.global_action_listeners.keys() { + if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) { + let action = cx.actions.build_action_type(action_type).ok(); + if let Some(action) = action { + actions.insert(ix, action); + } + } + } + actions + } + + /// Returns key bindings that invoke an action on the currently focused element. Bindings are + /// returned in the order they were added. For display, the last binding should take precedence. + pub fn bindings_for_action(&self, action: &dyn Action) -> Vec { + self.rendered_frame + .dispatch_tree + .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack) + } + + /// Returns the highest precedence key binding that invokes an action on the currently focused + /// element. This is more efficient than getting the last result of `bindings_for_action`. + pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option { + self.rendered_frame + .dispatch_tree + .highest_precedence_binding_for_action( + action, + &self.rendered_frame.dispatch_tree.context_stack, + ) + } + + /// Returns the key bindings for an action in a context. + pub fn bindings_for_action_in_context( + &self, + action: &dyn Action, + context: KeyContext, + ) -> Vec { + let dispatch_tree = &self.rendered_frame.dispatch_tree; + dispatch_tree.bindings_for_action(action, &[context]) + } + + /// Returns the highest precedence key binding for an action in a context. This is more + /// efficient than getting the last result of `bindings_for_action_in_context`. + pub fn highest_precedence_binding_for_action_in_context( + &self, + action: &dyn Action, + context: KeyContext, + ) -> Option { + let dispatch_tree = &self.rendered_frame.dispatch_tree; + dispatch_tree.highest_precedence_binding_for_action(action, &[context]) + } + + /// Returns any bindings that would invoke an action on the given focus handle if it were + /// focused. Bindings are returned in the order they were added. For display, the last binding + /// should take precedence. + pub fn bindings_for_action_in( + &self, + action: &dyn Action, + focus_handle: &FocusHandle, + ) -> Vec { + let dispatch_tree = &self.rendered_frame.dispatch_tree; + let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else { + return vec![]; + }; + dispatch_tree.bindings_for_action(action, &context_stack) + } + + /// Returns the highest precedence key binding that would invoke an action on the given focus + /// handle if it were focused. This is more efficient than getting the last result of + /// `bindings_for_action_in`. + pub fn highest_precedence_binding_for_action_in( + &self, + action: &dyn Action, + focus_handle: &FocusHandle, + ) -> Option { + let dispatch_tree = &self.rendered_frame.dispatch_tree; + let context_stack = self.context_stack_for_focus_handle(focus_handle)?; + dispatch_tree.highest_precedence_binding_for_action(action, &context_stack) + } + + /// Find the bindings that can follow the current input sequence for the current context stack. + pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec { + self.rendered_frame + .dispatch_tree + .possible_next_bindings_for_input(input, &self.context_stack()) + } + + fn context_stack_for_focus_handle( + &self, + focus_handle: &FocusHandle, + ) -> Option> { + let dispatch_tree = &self.rendered_frame.dispatch_tree; + let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?; + let context_stack: Vec<_> = dispatch_tree + .dispatch_path(node_id) + .into_iter() + .filter_map(|node_id| dispatch_tree.node(node_id).context.clone()) + .collect(); + Some(context_stack) + } + + /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle. + pub fn listener_for( + &self, + view: &Entity, + f: impl Fn(&mut T, &E, &mut Window, &mut Context) + 'static, + ) -> impl Fn(&E, &mut Window, &mut App) + 'static { + let view = view.downgrade(); + move |e: &E, window: &mut Window, cx: &mut App| { + view.update(cx, |view, cx| f(view, e, window, cx)).ok(); + } + } + + /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle. + pub fn handler_for) + 'static>( + &self, + entity: &Entity, + f: Callback, + ) -> impl Fn(&mut Window, &mut App) + 'static { + let entity = entity.downgrade(); + move |window: &mut Window, cx: &mut App| { + entity.update(cx, |entity, cx| f(entity, window, cx)).ok(); + } + } + + /// Register a callback that can interrupt the closing of the current window based the returned boolean. + /// If the callback returns false, the window won't be closed. + pub fn on_window_should_close( + &self, + cx: &App, + f: impl Fn(&mut Window, &mut App) -> bool + 'static, + ) { + let mut cx = self.to_async(cx); + self.platform_window.on_should_close(Box::new(move || { + cx.update(|window, cx| f(window, cx)).unwrap_or(true) + })) + } + + /// Register an action listener on this node for the next frame. The type of action + /// is determined by the first parameter of the given listener. When the next frame is rendered + /// the listener will be cleared. + /// + /// This is a fairly low-level method, so prefer using action handlers on elements unless you have + /// a specific need to register a listener yourself. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn on_action( + &mut self, + action_type: TypeId, + listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static, + ) { + self.invalidator.debug_assert_paint(); + + self.next_frame + .dispatch_tree + .on_action(action_type, Rc::new(listener)); + } + + /// Register a capturing action listener on this node for the next frame if the condition is true. + /// The type of action is determined by the first parameter of the given listener. When the next + /// frame is rendered the listener will be cleared. + /// + /// This is a fairly low-level method, so prefer using action handlers on elements unless you have + /// a specific need to register a listener yourself. + /// + /// This method should only be called as part of the paint phase of element drawing. + pub fn on_action_when( + &mut self, + condition: bool, + action_type: TypeId, + listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static, + ) { + self.invalidator.debug_assert_paint(); + + if condition { + self.next_frame + .dispatch_tree + .on_action(action_type, Rc::new(listener)); + } + } + + /// Read information about the GPU backing this window. + /// Currently returns None on Mac and Windows. + pub fn gpu_specs(&self) -> Option { + self.platform_window.gpu_specs() + } + + /// Perform titlebar double-click action. + /// This is macOS specific. + pub fn titlebar_double_click(&self) { + self.platform_window + .titlebar_double_click(self.is_resizable, self.is_minimizable); + } + + /// Gets the window's title at the platform level. + /// This is macOS specific. + pub fn window_title(&self) -> String { + self.platform_window.get_title() + } + + /// Returns a list of all tabbed windows and their titles. + /// This is macOS specific. + pub fn tabbed_windows(&self) -> Option> { + self.platform_window.tabbed_windows() + } + + /// Returns the tab bar visibility. + /// This is macOS specific. + pub fn tab_bar_visible(&self) -> bool { + self.platform_window.tab_bar_visible() + } + + /// Merges all open windows into a single tabbed window. + /// This is macOS specific. + pub fn merge_all_windows(&self) { + self.platform_window.merge_all_windows() + } + + /// Moves the tab to a new containing window. + /// This is macOS specific. + pub fn move_tab_to_new_window(&self) { + self.platform_window.move_tab_to_new_window() + } + + /// Shows or hides the window tab overview. + /// This is macOS specific. + pub fn toggle_window_tab_overview(&self) { + self.platform_window.toggle_window_tab_overview() + } + + /// Sets the tabbing identifier for the window. + /// This is macOS specific. + pub fn set_tabbing_identifier(&self, tabbing_identifier: Option) { + self.platform_window + .set_tabbing_identifier(tabbing_identifier) + } + + /// Request the OS to play an alert sound. On some platforms this is associated + /// with the window, for others it's just a simple global function call. + pub fn play_system_bell(&self) { + self.platform_window.play_system_bell() + } + + /// Returns whether accessibility support is enabled for this window. + /// + /// This is false when the app was created with [`crate::Application::new_inaccessible`]. + /// Unlike [`Self::is_a11y_active`], this does not depend on whether assistive + /// technology is currently connected, so it can be used to gate subscriptions + /// that are only needed for accessibility. + pub fn is_a11y_enabled(&self) -> bool { + self.a11y.is_enabled() + } + + /// Returns whether accessibility features are active for this frame, + /// i.e. whether assistive technology (such as a screen reader) is + /// connected and an accessibility tree is being built. + /// + /// Use this to skip computing data during rendering that is only + /// observable through the accessibility tree. When accessibility is + /// activated, a redraw is forced, so gated work is recomputed before the + /// next tree update is sent to the platform. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + pub fn is_a11y_active(&self) -> bool { + self.a11y.is_active() + } + + /// Debug representation of the last frame's accessibility information. + pub fn debug_a11y_tree_json(&self) -> Option { + self.a11y.debug_tree_json() + } + + /// Register a listener for an accessibility action on a specific node. + /// The listener will be called when a screen reader requests the given + /// action on the node identified by `node_id`. + /// + /// See the [accessibility guide](crate::_accessibility) for an overview. + pub fn on_a11y_action( + &mut self, + node_id: accesskit::NodeId, + action: accesskit::Action, + listener: impl FnMut(Option<&accesskit::ActionData>, &mut Window, &mut App) + 'static, + ) { + self.a11y + .action_listeners + .entry(node_id) + .or_default() + .push((action, Box::new(listener))); + } + + #[cfg(not(target_family = "wasm"))] + pub(crate) fn handle_a11y_action(&mut self, request: accesskit::ActionRequest, cx: &mut App) { + // Take listeners out temporarily so the closures can borrow Window + // mutably, then restore them afterward. + if let Some(mut listeners) = self.a11y.action_listeners.remove(&request.target_node) { + let extra_data = request.data.as_ref(); + let mut matched = false; + for (action, listener) in &mut listeners { + if *action == request.action { + listener(extra_data, self, cx); + matched = true; + } + } + self.a11y + .action_listeners + .insert(request.target_node, listeners); + if matched { + return; + } + } + + // Fall back to built-in action handling. + match request.action { + accesskit::Action::Click => { + if let Some(bounds) = self.a11y.node_bounds.get(&request.target_node).copied() { + let center = bounds.center(); + let mouse_down = PlatformInput::MouseDown(crate::MouseDownEvent { + button: MouseButton::Left, + position: center, + modifiers: Modifiers::default(), + click_count: 1, + first_mouse: false, + }); + let mouse_up = PlatformInput::MouseUp(MouseUpEvent { + button: MouseButton::Left, + position: center, + modifiers: Modifiers::default(), + click_count: 1, + }); + self.dispatch_event(mouse_down, cx); + self.dispatch_event(mouse_up, cx); + } + } + accesskit::Action::Focus => { + if let Some(focus_id) = self.a11y.focus_ids.get(&request.target_node).copied() + && let Some(handle) = FocusHandle::for_id(focus_id, &cx.focus_handles) + { + self.focus(&handle, cx); + } + } + accesskit::Action::Blur => { + self.blur(cx); + } + _ => { + log::debug!( + "Unhandled a11y action: {:?} on {:?}", + request.action, + request.target_node + ); + } + } + } + + /// Toggles the inspector mode on this window. + #[cfg(any(feature = "inspector", debug_assertions))] + pub fn toggle_inspector(&mut self, cx: &mut App) { + self.inspector = match self.inspector { + None => Some(cx.new(|_| Inspector::new())), + Some(_) => { + self.rendered_frame.next_inspector_instance_ids = FxHashMap::default(); + self.rendered_frame.inspector_hitboxes = FxHashMap::default(); + self.next_frame.next_inspector_instance_ids = FxHashMap::default(); + self.next_frame.inspector_hitboxes = FxHashMap::default(); + None + } + }; + self.refresh(); + } + + /// Returns true if the window is in inspector mode. + pub fn is_inspector_picking(&self, _cx: &App) -> bool { + #[cfg(any(feature = "inspector", debug_assertions))] + { + if let Some(inspector) = &self.inspector { + return inspector.read(_cx).is_picking(); + } + } + false + } + + /// Executes the provided function with mutable access to an inspector state. + #[cfg(any(feature = "inspector", debug_assertions))] + pub fn with_inspector_state( + &mut self, + inspector_id: Option<&crate::InspectorElementId>, + cx: &mut App, + f: impl FnOnce(&mut Option, &mut Self) -> R, + ) -> Option { + let inspector_id = inspector_id?; + let inspector = self.inspector.as_ref()?; + if inspector.read(cx).active_element_id() != Some(inspector_id) { + return None; + } + let inspector = inspector.clone(); + Some(inspector.update(cx, |inspector, _cx| { + inspector.with_active_element_state(self, f) + })) + } + + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) fn inspector_enabled(&self) -> bool { + self.inspector.is_some() + } + + #[cfg(any(feature = "inspector", debug_assertions))] + pub(crate) fn build_inspector_element_id( + &mut self, + path: crate::InspectorElementPath, + ) -> crate::InspectorElementId { + self.invalidator.debug_assert_paint_or_prepaint(); + let path = Rc::new(path); + let next_instance_id = self + .next_frame + .next_inspector_instance_ids + .entry(path.clone()) + .or_insert(0); + let instance_id = *next_instance_id; + *next_instance_id += 1; + crate::InspectorElementId { path, instance_id } + } + + #[cfg(any(feature = "inspector", debug_assertions))] + fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option { + if let Some(inspector) = self.inspector.take() { + let mut inspector_element = AnyView::from(inspector.clone()).into_any_element(); + inspector_element.prepaint_as_root( + point(self.viewport_size.width - inspector_width, px(0.0)), + size(inspector_width, self.viewport_size.height).into(), + self, + cx, + ); + self.inspector = Some(inspector); + Some(inspector_element) + } else { + None + } + } + + #[cfg(any(feature = "inspector", debug_assertions))] + fn paint_inspector(&mut self, mut inspector_element: Option, cx: &mut App) { + if let Some(mut inspector_element) = inspector_element { + inspector_element.paint(self, cx); + }; + } + + /// Registers a hitbox that can be used for inspector picking mode, allowing users to select and + /// inspect UI elements by clicking on them. + #[cfg(any(feature = "inspector", debug_assertions))] + pub fn insert_inspector_hitbox( + &mut self, + hitbox_id: HitboxId, + inspector_id: Option<&crate::InspectorElementId>, + cx: &App, + ) { + self.invalidator.debug_assert_paint_or_prepaint(); + if !self.is_inspector_picking(cx) { + return; + } + if let Some(inspector_id) = inspector_id { + self.next_frame + .inspector_hitboxes + .insert(hitbox_id, inspector_id.clone()); + } + } + + #[cfg(any(feature = "inspector", debug_assertions))] + fn paint_inspector_hitbox(&mut self, cx: &App) { + if let Some(inspector) = self.inspector.as_ref() { + let inspector = inspector.read(cx); + if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame) + && let Some(hitbox) = self + .next_frame + .hitboxes + .iter() + .find(|hitbox| hitbox.id == hitbox_id) + { + self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d))); + } + } + } + + #[cfg(any(feature = "inspector", debug_assertions))] + fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) { + let Some(inspector) = self.inspector.clone() else { + return; + }; + if event.downcast_ref::().is_some() { + inspector.update(cx, |inspector, _cx| { + if let Some((_, inspector_id)) = + self.hovered_inspector_hitbox(inspector, &self.rendered_frame) + { + inspector.hover(inspector_id, self); + } + }); + } else if event.downcast_ref::().is_some() { + inspector.update(cx, |inspector, _cx| { + if let Some((_, inspector_id)) = + self.hovered_inspector_hitbox(inspector, &self.rendered_frame) + { + inspector.select(inspector_id, self); + } + }); + } else if let Some(event) = event.downcast_ref::() { + // This should be kept in sync with SCROLL_LINES in x11 platform. + const SCROLL_LINES: f32 = 3.0; + const SCROLL_PIXELS_PER_LAYER: f32 = 36.0; + let delta_y = event + .delta + .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES)) + .y; + if let Some(inspector) = self.inspector.clone() { + inspector.update(cx, |inspector, _cx| { + if let Some(depth) = inspector.pick_depth.as_mut() { + *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER; + let max_depth = self.mouse_hit_test.ids.len() as f32 - 0.5; + if *depth < 0.0 { + *depth = 0.0; + } else if *depth > max_depth { + *depth = max_depth; + } + if let Some((_, inspector_id)) = + self.hovered_inspector_hitbox(inspector, &self.rendered_frame) + { + inspector.set_active_element_id(inspector_id, self); + } + } + }); + } + } + } + + #[cfg(any(feature = "inspector", debug_assertions))] + fn hovered_inspector_hitbox( + &self, + inspector: &Inspector, + frame: &Frame, + ) -> Option<(HitboxId, crate::InspectorElementId)> { + if let Some(pick_depth) = inspector.pick_depth { + let depth = (pick_depth as i64).try_into().unwrap_or(0); + let max_skipped = self.mouse_hit_test.ids.len().saturating_sub(1); + let skip_count = (depth as usize).min(max_skipped); + for hitbox_id in self.mouse_hit_test.ids.iter().skip(skip_count) { + if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) { + return Some((*hitbox_id, inspector_id.clone())); + } + } + } + None + } + + /// For testing: set the current modifier keys state. + /// This does not generate any events. + #[cfg(any(test, feature = "test-support"))] + pub fn set_modifiers(&mut self, modifiers: Modifiers) { + self.modifiers = modifiers; + } + + /// For testing: simulate a mouse move event to the given position. + /// This dispatches the event through the normal event handling path, + /// which will trigger hover states and tooltips. + #[cfg(any(test, feature = "test-support"))] + pub fn simulate_mouse_move(&mut self, position: Point, cx: &mut App) { + let event = PlatformInput::MouseMove(MouseMoveEvent { + position, + modifiers: self.modifiers, + pressed_button: None, + }); + let _ = self.dispatch_event(event, cx); + } + + #[inline(never)] + fn take_element_state( + &mut self, + global_id: &GlobalElementId, + state_type: TypeId, + ) -> ((GlobalElementId, TypeId), Option) { + let key = (global_id.clone(), state_type); + self.next_frame.accessed_element_states.push(key.clone()); + let state = self + .next_frame + .element_states + .remove(&key) + .or_else(|| self.rendered_frame.element_states.remove(&key)); + (key, state) + } + + #[inline(never)] + fn insert_element_state( + &mut self, + key: (GlobalElementId, TypeId), + state: ElementStateBox, + ) -> Option { + self.next_frame.element_states.insert(key, state) + } + + #[inline(never)] + fn observe_keyed_state(state: &Entity, current_view: EntityId, cx: &mut App) { + cx.observe(state, move |_, cx| { + cx.notify(current_view); + }) + .detach(); + } +} + +// #[derive(Clone, Copy, Eq, PartialEq, Hash)] +slotmap::new_key_type! { + /// A unique identifier for a window. + pub struct WindowId; +} + +impl WindowId { + /// Converts this window ID to a `u64`. + pub fn as_u64(&self) -> u64 { + self.0.as_ffi() + } +} + +impl From for WindowId { + fn from(value: u64) -> Self { + WindowId(slotmap::KeyData::from_ffi(value)) + } +} + +/// A handle to a window with a specific root view type. +/// Note that this does not keep the window alive on its own. +#[derive(Deref, DerefMut)] +pub struct WindowHandle { + #[deref] + #[deref_mut] + pub(crate) any_handle: AnyWindowHandle, + state_type: PhantomData V>, +} + +impl Debug for WindowHandle { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("WindowHandle") + .field("any_handle", &self.any_handle.id.as_u64()) + .finish() + } +} + +impl WindowHandle { + /// Creates a new handle from a window ID. + /// This does not check if the root type of the window is `V`. + pub fn new(id: WindowId) -> Self { + WindowHandle { + any_handle: AnyWindowHandle { + id, + state_type: TypeId::of::(), + root_entity_type_name: std::any::type_name::(), + }, + state_type: PhantomData, + } + } + + /// Get the root view out of this window. + /// + /// This will fail if the window is closed or if the root view's type does not match `V`. + #[cfg(any(test, feature = "test-support"))] + pub fn root(&self, cx: &mut C) -> Result> + where + C: AppContext, + { + cx.update_window(self.any_handle, |root_view, _, _| { + root_view + .downcast::() + .map_err(|_| anyhow!("the type of the window's root view has changed")) + })? + } + + /// Updates the root view of this window. + /// + /// This will fail if the window has been closed or if the root view's type does not match + pub fn update( + &self, + cx: &mut C, + update: impl FnOnce(&mut V, &mut Window, &mut Context) -> R, + ) -> Result + where + C: AppContext, + { + cx.update_window(self.any_handle, |root_view, window, cx| { + let view = root_view + .downcast::() + .map_err(|_| anyhow!("the type of the window's root view has changed"))?; + + Ok(view.update(cx, |view, cx| update(view, window, cx))) + })? + } + + /// Read the root view out of this window. + /// + /// This will fail if the window is closed or if the root view's type does not match `V`. + pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> { + let x = cx + .windows + .get(self.id) + .and_then(|window| { + window + .as_deref() + .and_then(|window| window.root.clone()) + .map(|root_view| root_view.downcast::()) + }) + .context("window not found")? + .map_err(|_| anyhow!("the type of the window's root view has changed"))?; + + Ok(x.read(cx)) + } + + /// Read the root view out of this window, with a callback + /// + /// This will fail if the window is closed or if the root view's type does not match `V`. + pub fn read_with(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result + where + C: AppContext, + { + cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx)) + } + + /// Read the root view pointer off of this window. + /// + /// This will fail if the window is closed or if the root view's type does not match `V`. + pub fn entity(&self, cx: &C) -> Result> + where + C: AppContext, + { + cx.read_window(self, |root_view, _cx| root_view) + } + + /// Check if this window is 'active'. + /// + /// Will return `None` if the window is closed or currently + /// borrowed. + pub fn is_active(&self, cx: &mut App) -> Option { + cx.update_window(self.any_handle, |_, window, _| window.is_window_active()) + .ok() + } +} + +impl Copy for WindowHandle {} + +impl Clone for WindowHandle { + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for WindowHandle { + fn eq(&self, other: &Self) -> bool { + self.any_handle == other.any_handle + } +} + +impl Eq for WindowHandle {} + +impl Hash for WindowHandle { + fn hash(&self, state: &mut H) { + self.any_handle.hash(state); + } +} + +impl From> for AnyWindowHandle { + fn from(val: WindowHandle) -> Self { + val.any_handle + } +} + +/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct AnyWindowHandle { + pub(crate) id: WindowId, + state_type: TypeId, + root_entity_type_name: &'static str, +} + +impl AnyWindowHandle { + /// Get the ID of this window. + pub fn window_id(&self) -> WindowId { + self.id + } + + /// Returns the name of the window's declared root entity type. + pub fn root_entity_type_name(&self) -> &'static str { + self.root_entity_type_name + } + + /// Attempt to convert this handle to a window handle with a specific root view type. + /// If the types do not match, this will return `None`. + pub fn downcast(&self) -> Option> { + if TypeId::of::() == self.state_type { + Some(WindowHandle { + any_handle: *self, + state_type: PhantomData, + }) + } else { + None + } + } + + /// Updates the state of the root view of this window. + /// + /// This will fail if the window has been closed. + pub fn update( + self, + cx: &mut C, + update: impl FnOnce(AnyView, &mut Window, &mut App) -> R, + ) -> Result + where + C: AppContext, + { + cx.update_window(self, update) + } + + /// Read the state of the root view of this window. + /// + /// This will fail if the window has been closed. + pub fn read(self, cx: &C, read: impl FnOnce(Entity, &App) -> R) -> Result + where + C: AppContext, + T: 'static, + { + let view = self + .downcast::() + .context("the type of the window's root view has changed")?; + + cx.read_window(&view, read) + } +} + +impl HasWindowHandle for Window { + fn window_handle(&self) -> Result, HandleError> { + self.platform_window.window_handle() + } +} + +impl HasDisplayHandle for Window { + fn display_handle( + &self, + ) -> std::result::Result, HandleError> { + self.platform_window.display_handle() + } +} + +/// An identifier for an [`Element`]. +/// +/// Can be constructed with a string, a number, or both, as well +/// as other internal representations. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum ElementId { + /// The ID of a View element + View(EntityId), + /// An integer ID. + Integer(u64), + /// A string based ID. + Name(SharedString), + /// A UUID. + Uuid(Uuid), + /// An ID that's equated with a focus handle. + FocusHandle(FocusId), + /// A combination of a name and an integer. + NamedInteger(SharedString, u64), + /// A path. + Path(Arc), + /// A code location. + CodeLocation(core::panic::Location<'static>), + /// A labeled child of an element. + NamedChild(Arc, SharedString), + /// A byte array ID (used for text-anchors) + OpaqueId([u8; 20]), +} + +impl ElementId { + /// Constructs an `ElementId::NamedInteger` from a name and `usize`. + pub fn named_usize(name: impl Into, integer: usize) -> ElementId { + Self::NamedInteger(name.into(), integer as u64) + } +} + +impl Display for ElementId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?, + ElementId::Integer(ix) => write!(f, "{}", ix)?, + ElementId::Name(name) => write!(f, "{}", name)?, + ElementId::FocusHandle(_) => write!(f, "FocusHandle")?, + ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?, + ElementId::Uuid(uuid) => write!(f, "{}", uuid)?, + ElementId::Path(path) => write!(f, "{}", path.display())?, + ElementId::CodeLocation(location) => write!(f, "{}", location)?, + ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?, + ElementId::OpaqueId(opaque_id) => write!(f, "{:x?}", opaque_id)?, + } + + Ok(()) + } +} + +impl TryInto for ElementId { + type Error = anyhow::Error; + + fn try_into(self) -> anyhow::Result { + if let ElementId::Name(name) = self { + Ok(name) + } else { + anyhow::bail!("element id is not string") + } + } +} + +impl From for ElementId { + fn from(id: u64) -> Self { + ElementId::Integer(id) + } +} + +impl From for ElementId { + fn from(id: usize) -> Self { + ElementId::Integer(id as u64) + } +} + +impl From for ElementId { + fn from(id: i32) -> Self { + Self::Integer(id as u64) + } +} + +impl From for ElementId { + fn from(name: SharedString) -> Self { + ElementId::Name(name) + } +} + +impl From for ElementId { + fn from(name: String) -> Self { + ElementId::Name(name.into()) + } +} + +impl From> for ElementId { + fn from(name: Arc) -> Self { + ElementId::Name(name.into()) + } +} + +impl From> for ElementId { + fn from(path: Arc) -> Self { + ElementId::Path(path) + } +} + +impl From<&'static str> for ElementId { + fn from(name: &'static str) -> Self { + ElementId::Name(SharedString::new_static(name)) + } +} + +impl<'a> From<&'a FocusHandle> for ElementId { + fn from(handle: &'a FocusHandle) -> Self { + ElementId::FocusHandle(handle.id) + } +} + +impl From<(&'static str, EntityId)> for ElementId { + fn from((name, id): (&'static str, EntityId)) -> Self { + ElementId::NamedInteger(SharedString::new_static(name), id.as_u64()) + } +} + +impl From<(&'static str, usize)> for ElementId { + fn from((name, id): (&'static str, usize)) -> Self { + ElementId::NamedInteger(SharedString::new_static(name), id as u64) + } +} + +impl From<(SharedString, usize)> for ElementId { + fn from((name, id): (SharedString, usize)) -> Self { + ElementId::NamedInteger(name, id as u64) + } +} + +impl From<(&'static str, u64)> for ElementId { + fn from((name, id): (&'static str, u64)) -> Self { + ElementId::NamedInteger(SharedString::new_static(name), id) + } +} + +impl From for ElementId { + fn from(value: Uuid) -> Self { + Self::Uuid(value) + } +} + +impl From<(&'static str, u32)> for ElementId { + fn from((name, id): (&'static str, u32)) -> Self { + ElementId::NamedInteger(SharedString::new_static(name), u64::from(id)) + } +} + +impl> From<(ElementId, T)> for ElementId { + fn from((id, name): (ElementId, T)) -> Self { + ElementId::NamedChild(Arc::new(id), name.into()) + } +} + +impl From<&'static core::panic::Location<'static>> for ElementId { + fn from(location: &'static core::panic::Location<'static>) -> Self { + ElementId::CodeLocation(*location) + } +} + +impl From<[u8; 20]> for ElementId { + fn from(opaque_id: [u8; 20]) -> Self { + ElementId::OpaqueId(opaque_id) + } +} + +/// A rectangle to be rendered in the window at the given position and size. +/// Passed as an argument [`Window::paint_quad`]. +#[derive(Clone)] +pub struct PaintQuad { + /// The bounds of the quad within the window. + pub bounds: Bounds, + /// The radii of the quad's corners. + pub corner_radii: Corners, + /// The background color of the quad. + pub background: Background, + /// The widths of the quad's borders. + pub border_widths: Edges, + /// The color of the quad's borders. + pub border_color: Hsla, + /// The style of the quad's borders. + pub border_style: BorderStyle, +} + +impl PaintQuad { + /// Sets the corner radii of the quad. + pub fn corner_radii(self, corner_radii: impl Into>) -> Self { + PaintQuad { + corner_radii: corner_radii.into(), + ..self + } + } + + /// Sets the border widths of the quad. + pub fn border_widths(self, border_widths: impl Into>) -> Self { + PaintQuad { + border_widths: border_widths.into(), + ..self + } + } + + /// Sets the border color of the quad. + pub fn border_color(self, border_color: impl Into) -> Self { + PaintQuad { + border_color: border_color.into(), + ..self + } + } + + /// Sets the background color of the quad. + pub fn background(self, background: impl Into) -> Self { + PaintQuad { + background: background.into(), + ..self + } + } +} + +/// Creates a quad with the given parameters. +pub fn quad( + bounds: Bounds, + corner_radii: impl Into>, + background: impl Into, + border_widths: impl Into>, + border_color: impl Into, + border_style: BorderStyle, +) -> PaintQuad { + PaintQuad { + bounds, + corner_radii: corner_radii.into(), + background: background.into(), + border_widths: border_widths.into(), + border_color: border_color.into(), + border_style, + } +} + +/// Creates a filled quad with the given bounds and background color. +pub fn fill(bounds: impl Into>, background: impl Into) -> PaintQuad { + PaintQuad { + bounds: bounds.into(), + corner_radii: (0.).into(), + background: background.into(), + border_widths: (0.).into(), + border_color: transparent_black(), + border_style: BorderStyle::default(), + } +} + +/// Creates a rectangle outline with the given bounds, border color, and a 1px border width +pub fn outline( + bounds: impl Into>, + border_color: impl Into, + border_style: BorderStyle, +) -> PaintQuad { + PaintQuad { + bounds: bounds.into(), + corner_radii: (0.).into(), + background: transparent_black().into(), + border_widths: (1.).into(), + border_color: border_color.into(), + border_style, + } +} + +#[inline(never)] +fn with_element_arena_erased(callback: &mut dyn FnMut(&mut Arena)) -> Result<(), AccessError> { + if let Some(arena_pointer) = CURRENT_ELEMENT_ARENA.try_with(Cell::get)? { + // SAFETY: The pointer is valid for the duration of the draw operation + // that set it, and we're being called during that same draw. + let arena_cell = unsafe { &*arena_pointer }; + callback(&mut arena_cell.borrow_mut()); + Ok(()) + } else { + ELEMENT_ARENA.try_with(|arena| callback(&mut arena.borrow_mut())) + } +} + +#[cfg(test)] +mod tests { + use std::{ + cell::{Cell, RefCell}, + path::PathBuf, + rc::Rc, + time::Duration, + }; + + use crate::{ + AnyWindowHandle, AppContext as _, Bounds, ContentMask, Context, DispatchPhase, + DragMoveEvent, Empty, ExternalDragPayload, ExternalPaths, FileDragPaths, FileDropEvent, + FocusHandle, InputEvent as _, InteractiveElement as _, IntoElement, KeyDownEvent, + Keystroke, LongPressEvent, MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, + Pixels, PlatformInput, Point, Render, RequestFrameOptions, ScaledPixels, + StatefulInteractiveElement as _, Styled, TestAppContext, TouchDragEvent, TouchEvent, + TouchId, TouchPhase, Underline, UnderlineStyle, Window, WindowAppearance, WindowOptions, + canvas, div, hsla, point, px, size, + }; + + #[cfg(feature = "profiler")] + #[gpui::test] + fn test_frame_requests_and_skips_are_journaled(cx: &mut TestAppContext) { + use crate::FrameRequestSource; + use crate::profiler::journal::{ + self, ForegroundJournalEntry, FrameSkipReason, IntervalBoundary, + }; + use scheduler::Instant; + + cx.app.borrow_mut().mode = crate::app::GpuiMode::Production; + let window = cx.add_window(|_, _| EmptyView); + let platform_window = cx.test_window(window.into()); + platform_window.simulate_frame_request(RequestFrameOptions::default()); + let (journal, _guard) = journal::install_test_foreground_journal(64, 4); + let mut collector = journal.collector(); + + for (signal_at, source) in [ + (Some(Instant::now()), FrameRequestSource::NativeCallback), + (Some(Instant::now()), FrameRequestSource::LocalSchedule), + (None, FrameRequestSource::NativeCallback), + ] { + platform_window.simulate_frame_request(RequestFrameOptions { + signal_at, + signal_source: source, + require_presentation: true, + ..Default::default() + }); + let entries = collector.collect_unseen().entries; + let signal_index = entries + .iter() + .position(|entry| { + matches!( + entry, + ForegroundJournalEntry::PlatformSignal(signal) + if signal.window_id == window.window_id() + && signal.signal_at == signal_at + && signal.source == source + && signal_at.is_none_or(|at| signal.handled_at >= at) + ) + }) + .expect("frame request metadata"); + let skip_index = entries + .iter() + .position(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::FrameSkipped(skipped)) + if skipped.window_id == window.window_id() + && skipped.reason == FrameSkipReason::NoRenderNeeded + ) + }) + .expect("completed no-render boundary"); + assert!(signal_index < skip_index); + } + } + + #[cfg(feature = "profiler")] + #[gpui::test] + fn test_frame_demand_survives_throttling(cx: &mut TestAppContext) { + use crate::profiler::journal::{ + self, ForegroundJournalEntry, FrameSkipReason, IntervalBoundary, + }; + use scheduler::Instant; + + // Test mode draws during effect flushing, bypassing platform frame throttling. + cx.app.borrow_mut().mode = crate::app::GpuiMode::Production; + let (journal, _guard) = journal::install_test_foreground_journal(256, 4); + let mut collector = journal.collector(); + for initially_dirty in [true, false] { + // Keep the throttle closed without depending on short wall-clock deadlines. + let window = cx + .app + .borrow_mut() + .open_window( + WindowOptions { + inactive_frame_interval: Some(Duration::from_secs(3600)), + ..Default::default() + }, + |_, cx| cx.new(|_| EmptyView), + ) + .expect("open inactive test window"); + let platform_window = cx.test_window(window.into()); + platform_window.simulate_active_status_change(false); + platform_window.simulate_frame_request(RequestFrameOptions::default()); + let callback_ran = Rc::new(Cell::new(false)); + let draws_before = window + .update(cx, |_, window, _| { + let draws_before = window + .frame_duration_snapshot() + .draw_duration_histogram + .len(); + if initially_dirty { + window.refresh(); + } + window.on_next_frame({ + let callback_ran = callback_ran.clone(); + move |window, _| { + callback_ran.set(true); + window.refresh(); + } + }); + draws_before + }) + .expect("schedule throttled frame"); + // Skips only seal retained work, so give the throttled skip some. + let input_at = Instant::now(); + journal::record_input(journal::InputTiming { + kind: "test", + start: input_at, + end: input_at, + caused_invalidation: false, + }); + collector.collect_unseen(); + platform_window.simulate_frame_request(RequestFrameOptions { + signal_at: Some(Instant::now()), + ..Default::default() + }); + window + .update(cx, |_, window, _| { + assert_eq!( + window + .frame_duration_snapshot() + .draw_duration_histogram + .len(), + draws_before, + ); + }) + .expect("inspect deferred frame"); + assert!(!callback_ran.get()); + assert!(collector.collect_unseen().entries.iter().any(|entry| { + matches!( + entry, + ForegroundJournalEntry::Boundary(IntervalBoundary::FrameSkipped(skipped)) + if skipped.window_id == window.window_id() + && skipped.reason == FrameSkipReason::InactiveFrameRateLimit + ) + })); + platform_window.simulate_frame_request(RequestFrameOptions { + signal_at: Some(Instant::now()), + require_presentation: true, + ..Default::default() + }); + window + .update(cx, |_, window, _| { + assert_eq!( + window + .frame_duration_snapshot() + .draw_duration_histogram + .len(), + draws_before + 1, + ); + }) + .expect("inspect presented frame"); + assert!(callback_ran.get()); + } + } + + /// Visibility transitions reach observers exactly once each, with the new + /// state already stored on the window, and never wake the platform for a + /// frame: the platform requests one itself when it resumes presenting. + #[gpui::test] + fn test_window_visibility(cx: &mut TestAppContext) { + use crate::WindowVisibility; + + let window = cx.add_window(|_, _| EmptyView); + let observed = Rc::new(RefCell::new(Vec::new())); + let _subscription = window + .update(cx, { + let observed = observed.clone(); + move |_, window, _| { + assert_eq!(window.visibility(), WindowVisibility::Visible); + assert!(window.is_visible()); + window.observe_window_visibility(move |visibility, window, _| { + assert_eq!(window.visibility(), visibility); + observed.borrow_mut().push(visibility); + }) + } + }) + .unwrap(); + let test_window = cx.test_window(window.into()); + let frame_wake_count = test_window.frame_wake_count(); + + test_window.simulate_visibility_change(WindowVisibility::Hidden); + assert_eq!(*observed.borrow(), [WindowVisibility::Hidden]); + window + .update(cx, |_, window, _| assert!(!window.is_visible())) + .unwrap(); + + // Platforms may report the same state again; observers only see changes. + test_window.simulate_visibility_change(WindowVisibility::Hidden); + assert_eq!(observed.borrow().len(), 1); + + test_window.simulate_visibility_change(WindowVisibility::Visible); + assert_eq!( + *observed.borrow(), + [WindowVisibility::Hidden, WindowVisibility::Visible] + ); + window + .update(cx, |_, window, _| assert!(window.is_visible())) + .unwrap(); + assert_eq!(test_window.frame_wake_count(), frame_wake_count); + } + + #[gpui::test] + fn test_fully_visible_bounds_preserve_layout_viewport(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| EmptyView); + let mut platform_window = cx.test_window(window.into()); + platform_window.simulate_resize(size(px(400.), px(800.))); + window + .update(cx, |_, window, _| { + assert_eq!( + window.visual_viewport_bounds(), + Bounds::new(Point::default(), size(px(400.), px(800.))) + ); + assert_eq!( + window.fully_visible_bounds(), + window.visual_viewport_bounds() + ); + }) + .unwrap(); + + platform_window.simulate_frame_request(RequestFrameOptions::default()); + let wakes = platform_window.frame_wake_count(); + let visual_bounds = Bounds::new(point(px(10.), px(40.)), size(px(380.), px(460.))); + platform_window.simulate_visual_viewport_change(visual_bounds); + assert!(platform_window.frame_wake_count() > wakes); + platform_window.simulate_frame_request(RequestFrameOptions::default()); + let wakes = platform_window.frame_wake_count(); + platform_window.simulate_insets_change(crate::WindowInsets { + safe_area: crate::Edges { + top: px(60.), + right: px(20.), + bottom: px(30.), + left: px(-10.), + }, + ime: crate::Edges { + bottom: px(350.), + ..Default::default() + }, + }); + assert!(platform_window.frame_wake_count() > wakes); + window + .update(cx, |_, window, _| { + assert_eq!(window.viewport_size(), size(px(400.), px(800.))); + assert_eq!(window.visual_viewport_bounds(), visual_bounds); + assert_eq!( + window.fully_visible_bounds(), + Bounds::new(point(px(10.), px(60.)), size(px(370.), px(390.))) + ); + window.request_virtual_keyboard(); + window.dismiss_virtual_keyboard(); + assert_eq!(window.viewport_size(), size(px(400.), px(800.))); + }) + .unwrap(); + assert_eq!(platform_window.virtual_keyboard_requests(), 1); + assert_eq!(platform_window.virtual_keyboard_dismissals(), 1); + + platform_window.simulate_insets_change(crate::WindowInsets { + safe_area: crate::Edges { + top: px(900.), + left: px(500.), + ..Default::default() + }, + ..Default::default() + }); + window + .update(cx, |_, window, _| { + assert_eq!( + window.fully_visible_bounds().size, + size(Pixels::ZERO, Pixels::ZERO) + ); + }) + .unwrap(); + } + + struct EmptyView; + + impl Render for EmptyView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div() + } + } + + struct OpensWindowOnPaint { + opened: Rc>, + } + + impl Render for OpensWindowOnPaint { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let opened = self.opened.clone(); + div() + .size_full() + .child(canvas( + |_, _, _| {}, + move |_, _, _window, cx| { + if !opened.replace(true) { + cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| EmptyView)) + .unwrap(); + } + }, + )) + // Siblings painted after the canvas: their elements were + // allocated in the arena before the nested draw, so they detect + // a mid-draw arena clear when painted afterwards. + .child(div().child("after")) + } + } + + /// Opening a window synchronously draws it and requests an element arena + /// clear. When that happens from within another window's draw (here: from + /// an element's paint), the clear must be deferred until the outer draw + /// finishes, or the outer draw's arena-allocated elements would be freed + /// out from under it. + #[test] + fn test_window_opened_during_draw_defers_arena_clear() { + let mut cx = TestAppContext::single(); + + let opened = Rc::new(Cell::new(false)); + // add_window draws once, which runs the nested open_window mid-draw. + let window = cx.add_window({ + let opened = opened.clone(); + move |_, _| OpensWindowOnPaint { opened } + }); + + assert!(opened.get()); + assert_eq!(cx.windows().len(), 2); + + // The deferred clear must actually run once the outer draw unwinds: + // subsequent draws of both windows work against a fresh arena. + cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + } + + #[test] + fn test_scale_factor_change_preserves_bounds_and_survives_resize() { + let mut cx = TestAppContext::single(); + let window = cx.add_window(|_, _| EmptyView); + let handle: AnyWindowHandle = window.into(); + let window_state = |cx: &mut TestAppContext| { + cx.update_window(handle, |_, window, _| { + ( + window.scale_factor(), + window.bounds(), + window.viewport_size(), + ) + }) + .unwrap() + }; + + let (scale_factor, mut expected_bounds, _) = window_state(&mut cx); + assert_eq!(scale_factor, 2.0); + + for (scale_factor, resized_size) in [ + (1.0, size(px(800.), px(600.))), + (1.25, size(px(640.), px(480.))), + (2.0, size(px(1024.), px(768.))), + ] { + cx.simulate_window_scale_factor_change(handle, scale_factor); + assert_eq!( + window_state(&mut cx), + (scale_factor, expected_bounds, expected_bounds.size) + ); + + cx.simulate_window_resize(handle, resized_size); + expected_bounds.size = resized_size; + assert_eq!( + window_state(&mut cx), + (scale_factor, expected_bounds, resized_size) + ); + } + } + + /// Platforms that stop requesting frames for idle windows (currently web) + /// rely on the frame waker firing whenever frame demand arises; a demand + /// source that skips the waker shows up there as a window that silently + /// stops repainting until unrelated activity wakes it. + #[gpui::test] + fn test_frame_waker_fires_on_frame_demand(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| EmptyView); + let test_window = cx.test_window(window.into()); + + // Windows start dirty, and that can predate waker installation; + // installing the waker must deliver the pending wake or the first + // frame would never be requested. + assert!( + test_window.frame_wake_count() >= 1, + "opening a window must wake the frame source for the initial frame" + ); + + // Serve outstanding demand (present the frame drawn by `add_window`). + test_window.simulate_frame_request(RequestFrameOptions::default()); + + // An idle window must not wake on clean frames or plain updates, or + // the frame source could never stop. + let baseline = test_window.frame_wake_count(); + test_window.simulate_frame_request(RequestFrameOptions::default()); + window.update(cx, |_, _, _| {}).unwrap(); + assert_eq!( + test_window.frame_wake_count(), + baseline, + "clean frames and non-notifying updates must not wake the frame source" + ); + + // Notifying a view in an idle window is the core demand signal. + window.update(cx, |_, _, cx| cx.notify()).unwrap(); + assert!( + test_window.frame_wake_count() > baseline, + "notifying a view in an idle window must wake the frame source" + ); + + // Serving that demand returns to idle without further wakes. + test_window.simulate_frame_request(RequestFrameOptions::default()); + let baseline = test_window.frame_wake_count(); + test_window.simulate_frame_request(RequestFrameOptions::default()); + assert_eq!( + test_window.frame_wake_count(), + baseline, + "serving demand must return the window to idle" + ); + + // Next-frame callbacks create demand without dirtying the window. + window + .update(cx, |_, window, _| window.on_next_frame(|_, _| {})) + .unwrap(); + assert!( + test_window.frame_wake_count() > baseline, + "scheduling a next-frame callback in an idle window must wake the frame source" + ); + } + + /// A frame request that arrives while next-frame callbacks are pending + /// must never strand them: either the frame runs them, or (when the + /// inactive-window frame-rate throttle defers the frame) the waker fires + /// so another request is delivered. + #[gpui::test] + fn test_pending_next_frame_callbacks_are_not_stranded(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| EmptyView); + let test_window = cx.test_window(window.into()); + // Establish a recent last-frame time so the inactive-window throttle + // can engage on the next request. + test_window.simulate_frame_request(RequestFrameOptions::default()); + + let callback_ran = Rc::new(Cell::new(false)); + window + .update(cx, { + let callback_ran = callback_ran.clone(); + move |_, window, _| { + window.on_next_frame(move |_, _| callback_ran.set(true)); + } + }) + .unwrap(); + + let baseline = test_window.frame_wake_count(); + test_window.simulate_frame_request(RequestFrameOptions::default()); + // The test window is inactive, so this request throttles to ~30fps + // when it lands within the throttle interval of the previous frame + // (the common case here, but timing-dependent): the callback is + // deferred and the waker must re-arm the frame source. On a slow run + // the request instead lands outside the interval and runs the + // callback directly. + assert!( + test_window.frame_wake_count() > baseline || callback_ran.get(), + "a frame request with pending next-frame callbacks must either run them or re-arm the frame source" + ); + } + + #[gpui::test] + fn test_window_reports_no_raw_handle_instead_of_panicking(cx: &mut TestAppContext) { + use raw_window_handle::{HandleError, HasDisplayHandle as _, HasWindowHandle as _}; + + let window = cx.add_window(|_, _| EmptyView); + window + .update(cx, |_, window, _| { + assert!(matches!( + window.window_handle(), + Err(HandleError::NotSupported) + )); + assert!(matches!( + window.display_handle(), + Err(HandleError::NotSupported) + )); + }) + .unwrap(); + } + + #[gpui::test] + fn test_appearance_change_runs_after_app_update(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| EmptyView); + let observed_appearance = Rc::new(Cell::new(None)); + let _subscription = window + .update(cx, { + let observed_appearance = observed_appearance.clone(); + move |_, window, _| { + window.observe_window_appearance(move |window, _| { + observed_appearance.set(Some(window.appearance())); + }) + } + }) + .unwrap(); + let test_window = cx.test_window(window.into()); + + cx.update(|_| { + test_window.simulate_appearance_change(WindowAppearance::Dark); + assert_eq!(observed_appearance.get(), None); + }); + cx.run_until_parked(); + + assert_eq!(observed_appearance.get(), Some(WindowAppearance::Dark)); + } + + #[gpui::test] + fn queued_frame_callback_wakes_a_parked_render_loop(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| Empty); + let test_window = cx.test_window(window.into()); + + assert!(test_window.simulate_scheduled_frame()); + assert!(test_window.simulate_scheduled_frame()); + assert!(!test_window.frame_scheduled()); + + cx.update_window(window.into(), |_, window, _| { + window.active.set(true); + window.on_next_frame(|_, _| {}); + }) + .unwrap(); + assert!( + test_window.frame_scheduled(), + "queuing work on a parked window must wake the render loop" + ); + + assert!(test_window.simulate_scheduled_frame()); + assert!( + test_window.frame_scheduled(), + "presenting the frame must await one compositor callback" + ); + assert!(test_window.simulate_scheduled_frame()); + assert!(!test_window.frame_scheduled()); + } + + #[gpui::test] + fn pending_presentation_wakes_a_parked_render_loop(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| Empty); + let test_window = cx.test_window(window.into()); + + assert!(test_window.simulate_scheduled_frame()); + assert!(test_window.simulate_scheduled_frame()); + assert!(!test_window.frame_scheduled()); + + cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + + assert!( + test_window.frame_scheduled(), + "a rendered scene awaiting presentation must wake the render loop" + ); + } + + #[gpui::test] + fn callback_queued_during_a_frame_requests_a_follow_up(cx: &mut TestAppContext) { + let window = cx.add_window(|_, _| Empty); + let test_window = cx.test_window(window.into()); + + let callback_ran = Rc::new(Cell::new(false)); + cx.update_window(window.into(), |_, window, _| { + // Inactive windows are frame-rate throttled, which would defer the + // ticks this test drives manually. + window.active.set(true); + let callback_ran = callback_ran.clone(); + window.on_next_frame(move |window, _| { + window.on_next_frame(move |_, _| callback_ran.set(true)); + }); + }) + .unwrap(); + + assert!(test_window.simulate_scheduled_frame()); + assert!(!callback_ran.get()); + assert!( + test_window.frame_scheduled(), + "a callback queued mid-frame must schedule a follow-up before the loop parks" + ); + + assert!(test_window.simulate_scheduled_frame()); + assert!(callback_ran.get()); + } + + struct RootView { + explicit_size: bool, + child_bounds: Rc>>, + } + + impl Render for RootView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let child_bounds = self.child_bounds.clone(); + let root = div().flex().flex_col().child( + canvas( + move |bounds, _, _| child_bounds.set(bounds), + |_, _, _, _| {}, + ) + .size_full(), + ); + if self.explicit_size { + root.w(px(300.)).h(px(200.)) + } else { + root + } + } + } + + #[test] + fn auto_sized_window_root_fills_the_window() { + let mut cx = TestAppContext::single(); + let child_bounds = Rc::new(Cell::new(Bounds::default())); + let window = cx.add_window({ + let child_bounds = child_bounds.clone(); + move |_, _| RootView { + explicit_size: false, + child_bounds, + } + }); + + let viewport_size = cx + .update_window(window.into(), |_, window, cx| { + window.draw(cx).clear(cx); + window.viewport_size() + }) + .unwrap(); + + assert_eq!(child_bounds.get().size, viewport_size); + } + + #[test] + fn explicitly_sized_window_root_keeps_its_size() { + let mut cx = TestAppContext::single(); + let child_bounds = Rc::new(Cell::new(Bounds::default())); + let window = cx.add_window({ + let child_bounds = child_bounds.clone(); + move |_, _| RootView { + explicit_size: true, + child_bounds, + } + }); + + cx.update_window(window.into(), |_, window, cx| { + window.draw(cx).clear(cx); + }) + .unwrap(); + + assert_eq!(child_bounds.get().size, size(px(300.), px(200.))); + } + + struct FileDragView { + path: PathBuf, + observed_drag_moves: Rc>>>, + observed_drops: Rc>>, + } + + struct FileDropExitView(Rc>); + + impl Render for FileDropExitView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div().size_full().on_file_drop_exit({ + let observed_file_drop_exit = self.0.clone(); + move |_, _, _| observed_file_drop_exit.set(observed_file_drop_exit.get() + 1) + }) + } + } + + impl Render for FileDragView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div() + .id("file-drag") + .size_full() + .on_drag(self.path.clone(), |_, _, _, cx| cx.new(|_| Empty)) + .external_drag_payload(|path: &PathBuf, _, _| { + Some(ExternalDragPayload::Files(FileDragPaths::new([( + path.clone(), + true, + )]))) + }) + .on_drag_move({ + let observed_drag_moves = self.observed_drag_moves.clone(); + move |event: &DragMoveEvent, _, _| { + observed_drag_moves.borrow_mut().push(event.event.position); + } + }) + .on_drop({ + let observed_drops = self.observed_drops.clone(); + move |path: &PathBuf, _, _| observed_drops.borrow_mut().push(path.clone()) + }) + } + } + + #[gpui::test] + fn file_drag_is_promoted_once_and_restored_in_source_window(cx: &mut TestAppContext) { + struct Drag { + window: AnyWindowHandle, + observed_drag_moves: Rc>>>, + observed_drops: Rc>>, + } + + fn start_drag(cx: &mut TestAppContext, path: PathBuf, platform_result: bool) -> Drag { + let observed_drag_moves = Rc::new(RefCell::new(Vec::new())); + let observed_drops = Rc::new(RefCell::new(Vec::new())); + let window: AnyWindowHandle = cx + .add_window({ + let observed_drag_moves = observed_drag_moves.clone(); + let observed_drops = observed_drops.clone(); + move |_, _| FileDragView { + path, + observed_drag_moves, + observed_drops, + } + }) + .into(); + cx.test_window(window) + .set_start_external_drag_result(platform_result); + + let update_result = cx.update_window(window, |_, window, cx| { + window.draw(cx).clear(cx); + window.dispatch_event( + MouseDownEvent { + position: point(px(10.), px(10.)), + button: MouseButton::Left, + modifiers: Default::default(), + click_count: 1, + first_mouse: false, + } + .to_platform_input(), + cx, + ); + window.dispatch_event( + MouseMoveEvent { + position: point(px(20.), px(20.)), + pressed_button: Some(MouseButton::Left), + modifiers: Default::default(), + } + .to_platform_input(), + cx, + ); + assert!(cx.active_drag.is_some()); + }); + assert!( + update_result.is_ok(), + "failed to start drag: {update_result:?}" + ); + + assert!(cx.test_window(window).external_drag_files().is_empty()); + Drag { + window, + observed_drag_moves, + observed_drops, + } + } + + let successful_path = PathBuf::from("/tmp/successful-drag"); + let successful = start_drag(cx, successful_path.clone(), true); + let outside_position = point(px(-1.), px(20.)); + let update_result = cx.update_window(successful.window, |_, window, cx| { + window.dispatch_event( + MouseMoveEvent { + position: outside_position, + pressed_button: Some(MouseButton::Left), + modifiers: Default::default(), + } + .to_platform_input(), + cx, + ); + assert!(cx.active_drag.is_none()); + }); + assert!( + update_result.is_ok(), + "failed to promote drag: {update_result:?}" + ); + assert_eq!( + cx.test_window(successful.window).external_drag_files(), + [(successful_path.clone(), true)] + ); + // Views must still see the move that leaves the window, otherwise they never learn to tear + // down the drag state they built up while the pointer was inside. + assert_eq!( + successful.observed_drag_moves.borrow().last(), + Some(&outside_position) + ); + + let first_destination_exit_count = Rc::new(Cell::new(0)); + let first_destination: AnyWindowHandle = cx + .add_window({ + let first_destination_exit_count = first_destination_exit_count.clone(); + move |_, _| FileDropExitView(first_destination_exit_count) + }) + .into(); + let second_destination_exit_count = Rc::new(Cell::new(0)); + let second_destination: AnyWindowHandle = cx + .add_window({ + let second_destination_exit_count = second_destination_exit_count.clone(); + move |_, _| FileDropExitView(second_destination_exit_count) + }) + .into(); + let reentry_position = point(px(30.), px(30.)); + let external_paths = || ExternalPaths([successful_path.clone()].into_iter().collect()); + let update_result = cx.update_window(first_destination, |_, window, cx| { + window.draw(cx).clear(cx); + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: external_paths(), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx); + assert!(cx.active_drag.is_none()); + assert_eq!(first_destination_exit_count.get(), 1); + assert_eq!(second_destination_exit_count.get(), 0); + }); + assert!( + update_result.is_ok(), + "failed to handle drag in first destination window: {update_result:?}" + ); + + let update_result = cx.update_window(second_destination, |_, window, cx| { + window.draw(cx).clear(cx); + window.dispatch_event( + PlatformInput::KeyDown(KeyDownEvent { + keystroke: Keystroke::parse("down").expect("valid keystroke"), + is_held: false, + prefer_character_input: false, + }), + cx, + ); + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: external_paths(), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + assert_eq!(first_destination_exit_count.get(), 1); + assert_eq!(second_destination_exit_count.get(), 0); + + window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx); + assert!(cx.active_drag.is_none()); + assert_eq!(first_destination_exit_count.get(), 1); + assert_eq!(second_destination_exit_count.get(), 1); + }); + assert!( + update_result.is_ok(), + "failed to handle drag in second destination window: {update_result:?}" + ); + + let update_result = cx.update_window(successful.window, |_, window, cx| { + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: external_paths(), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + assert_eq!( + successful.observed_drag_moves.borrow().last(), + Some(&reentry_position) + ); + + window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx); + assert!(cx.active_drag.is_none()); + + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: external_paths(), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + + window.dispatch_event( + FileDropEvent::Submit { + position: reentry_position, + } + .to_platform_input(), + cx, + ); + assert_eq!( + successful.observed_drops.borrow().as_slice(), + std::slice::from_ref(&successful_path) + ); + assert!(cx.active_drag.is_none()); + + window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx); + assert!(cx.active_drag.is_none()); + window.dispatch_event(FileDropEvent::Ended.to_platform_input(), cx); + assert!(cx.active_drag.is_none()); + + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: external_paths(), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx); + }); + assert!( + update_result.is_ok(), + "failed to restore drag in source window: {update_result:?}" + ); + + let cancelled_path = PathBuf::from("/tmp/cancelled-drag"); + let cancelled = start_drag(cx, cancelled_path.clone(), true); + let update_result = cx.update_window(cancelled.window, |_, window, cx| { + window.dispatch_event( + MouseMoveEvent { + position: outside_position, + pressed_button: Some(MouseButton::Left), + modifiers: Default::default(), + } + .to_platform_input(), + cx, + ); + assert!(cx.active_drag.is_none()); + + window.dispatch_event( + FileDropEvent::Entered { + position: reentry_position, + paths: ExternalPaths([cancelled_path].into_iter().collect()), + } + .to_platform_input(), + cx, + ); + assert!( + cx.active_drag + .as_ref() + .is_some_and(|drag| drag.value.downcast_ref::().is_some()) + ); + assert!(cx.stop_active_drag(window)); + assert!(cx.active_drag.is_none()); + }); + assert!( + update_result.is_ok(), + "failed to cancel restored drag: {update_result:?}" + ); + assert!(!cx.update(|cx| cx.end_platform_drag(cancelled.window.window_id()))); + + let removed_path = PathBuf::from("/tmp/removed-window-drag"); + let removed = start_drag(cx, removed_path, true); + let removed_window_id = removed.window.window_id(); + let update_result = cx.update_window(removed.window, |_, window, cx| { + window.dispatch_event( + MouseMoveEvent { + position: outside_position, + pressed_button: Some(MouseButton::Left), + modifiers: Default::default(), + } + .to_platform_input(), + cx, + ); + assert!(cx.active_drag.is_none()); + window.remove_window(); + }); + assert!( + update_result.is_ok(), + "failed to remove drag source window: {update_result:?}" + ); + assert!(!cx.update(|cx| cx.end_platform_drag(removed_window_id))); + + let failed_path = PathBuf::from("/tmp/failed-drag"); + let failed = start_drag(cx, failed_path.clone(), false); + let update_result = cx.update_window(failed.window, |_, window, cx| { + for x_position in [-1., -2.] { + window.dispatch_event( + MouseMoveEvent { + position: point(px(x_position), px(20.)), + pressed_button: Some(MouseButton::Left), + modifiers: Default::default(), + } + .to_platform_input(), + cx, + ); + } + assert!(cx.active_drag.is_some()); + }); + assert!( + update_result.is_ok(), + "failed to retain drag after platform failure: {update_result:?}" + ); + assert_eq!( + cx.test_window(failed.window).external_drag_files(), + [(failed_path, true)] + ); + } + + struct FocusForwarder { + a: FocusHandle, + b: FocusHandle, + } + + impl Render for FocusForwarder { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div() + .size_full() + .child(div().w(px(50.)).h(px(50.)).track_focus(&self.a)) + .child(div().w(px(50.)).h(px(50.)).track_focus(&self.b)) + } + } + + /// When a focus listener moves focus again (e.g. a dock forwarding focus to its + /// active panel), the resulting focus events must be dispatched without waiting + /// for an unrelated redraw of the window. + #[gpui::test] + fn test_focus_moved_by_focus_listener_is_dispatched(cx: &mut TestAppContext) { + let b_focus_count = Rc::new(Cell::new(0)); + let window = cx.add_window({ + let b_focus_count = b_focus_count.clone(); + move |window, cx| { + let a = cx.focus_handle(); + let b = cx.focus_handle(); + cx.on_focus(&a, window, |this: &mut FocusForwarder, window, cx| { + let b = this.b.clone(); + window.focus(&b, cx); + }) + .detach(); + cx.on_focus(&b, window, move |_, _, _| { + b_focus_count.set(b_focus_count.get() + 1); + }) + .detach(); + FocusForwarder { a, b } + } + }); + + window + .update(cx, |_, window, _| window.activate_window()) + .unwrap(); + cx.executor().run_until_parked(); + + window + .update(cx, |this, window, cx| { + let a = this.a.clone(); + window.focus(&a, cx); + }) + .unwrap(); + cx.executor().run_until_parked(); + + window + .update(cx, |this, window, _| { + assert!(this.b.is_focused(window)); + }) + .unwrap(); + assert_eq!(b_focus_count.get(), 1); + } + + #[gpui::test] + fn claimed_touch_drag_receives_movement_and_release(cx: &mut TestAppContext) { + let events = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let events = events.clone(); + move |_, _| TouchDragListener { events } + }); + let touch = TouchId(1); + + dispatch_touch(window, cx, touch, TouchPhase::Started, 10.); + dispatch_touch(window, cx, touch, TouchPhase::Moved, 30.); + dispatch_touch(window, cx, touch, TouchPhase::Ended, 40.); + + assert_eq!( + events.borrow().as_slice(), + [ + (TouchPhase::Started, px(10.)), + (TouchPhase::Moved, px(30.)), + (TouchPhase::Ended, px(40.)), + ] + ); + } + + struct TouchDragListener { + events: Rc>>, + } + + impl Render for TouchDragListener { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let events = self.events.clone(); + canvas( + |_, _, _| {}, + move |_, _, window, _| { + window.on_mouse_event(move |event: &TouchDragEvent, phase, window, _cx| { + if phase != DispatchPhase::Bubble { + return; + } + events.borrow_mut().push((event.phase, event.position.x)); + if event.phase == TouchPhase::Started { + window.prevent_default(); + } + }); + }, + ) + } + } + + #[gpui::test] + fn long_press_is_claimed_only_when_started_prevents_default(cx: &mut TestAppContext) { + for response in [ + LongPressResponse::PreventDefault, + LongPressResponse::StopPropagation, + LongPressResponse::None, + ] { + let phases = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let phases = phases.clone(); + move |_, _| LongPressListener { phases, response } + }); + dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.); + cx.executor().advance_clock(Duration::from_millis(501)); + cx.executor().run_until_parked(); + window + .update(cx, |_, window, _| { + assert_eq!( + window.long_press_capture.is_some(), + response == LongPressResponse::PreventDefault + ); + }) + .unwrap(); + dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.); + dispatch_touch(window, cx, TouchId(1), TouchPhase::Ended, 2.); + window + .update(cx, |_, window, _| { + assert!(window.long_press_capture.is_none()); + }) + .unwrap(); + + let phases = phases.borrow(); + if response == LongPressResponse::PreventDefault { + assert_eq!( + phases.as_slice(), + [TouchPhase::Started, TouchPhase::Moved, TouchPhase::Ended] + ); + } else { + assert_eq!(phases.as_slice(), [TouchPhase::Started]); + } + } + } + + #[gpui::test] + fn stale_default_prevention_does_not_claim_long_press(cx: &mut TestAppContext) { + let phases = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let phases = phases.clone(); + move |_, _| LongPressListener { + phases, + response: LongPressResponse::None, + } + }); + window + .update(cx, |_, window, _| { + window.prevent_default(); + }) + .unwrap(); + + dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.); + cx.executor().advance_clock(Duration::from_millis(501)); + cx.executor().run_until_parked(); + dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.); + + assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]); + } + + #[gpui::test] + fn resolved_touch_cancels_scheduled_long_press(cx: &mut TestAppContext) { + for (phase, position) in [ + (TouchPhase::Ended, 0.), + (TouchPhase::Cancelled, 0.), + (TouchPhase::Moved, 20.), + ] { + let phases = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let phases = phases.clone(); + move |_, _| LongPressListener { + phases, + response: LongPressResponse::PreventDefault, + } + }); + dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.); + dispatch_touch(window, cx, TouchId(1), phase, position); + cx.executor().advance_clock(Duration::from_millis(501)); + cx.executor().run_until_parked(); + + assert!(phases.borrow().is_empty(), "{phase:?} allowed long press"); + } + } + + #[gpui::test] + fn stale_long_press_timer_cannot_affect_replacement_touch(cx: &mut TestAppContext) { + let phases = Rc::new(RefCell::new(Vec::new())); + let window = cx.add_window({ + let phases = phases.clone(); + move |_, _| LongPressListener { + phases, + response: LongPressResponse::PreventDefault, + } + }); + let first_touch = TouchId(1); + dispatch_touch(window, cx, first_touch, TouchPhase::Started, 0.); + cx.executor().advance_clock(Duration::from_millis(250)); + dispatch_touch(window, cx, first_touch, TouchPhase::Cancelled, 0.); + dispatch_touch(window, cx, TouchId(2), TouchPhase::Started, 10.); + + cx.executor().advance_clock(Duration::from_millis(251)); + cx.executor().run_until_parked(); + assert!(phases.borrow().is_empty()); + + cx.executor().advance_clock(Duration::from_millis(250)); + cx.executor().run_until_parked(); + assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]); + } + + #[gpui::test] + fn test_underline_exclusions_preserve_device_geometry(cx: &mut TestAppContext) { + test_underline_paint_at_scales(cx, |window| { + let (numerator, denominator) = match window.scale_factor() { + 1.0 => (1, 1), + 1.25 => (5, 4), + 1.5 => (3, 2), + 2.0 => (2, 1), + 3.0 => (3, 1), + scale => panic!("unexpected scale {scale}"), + }; + let snap = |quarters: i32| { + let scaled = quarters * numerator; + let divisor = 4 * denominator; + let rounded = + scaled.abs() / divisor + i32::from(2 * (scaled.abs() % divisor) > divisor); + ScaledPixels((scaled.signum() * rounded) as f32) + }; + let stroke = |quarters| { + if quarters == 0 { + ScaledPixels(0.) + } else { + snap(quarters).max(ScaledPixels(1.)) + } + }; + + for origin in [-101, -3, -2, -1, 0, 1, 2, 3, 101] { + for width in [0, 1, 3, 84] { + for thickness in [0, 1, 4, 7] { + for wavy in [false, true] { + let style = UnderlineStyle { + thickness: px(thickness as f32 / 4.), + color: Some(hsla(0.25, 0.5, 0.75, 0.5)), + wavy, + }; + let bounds = Bounds::new( + point(snap(origin), snap(-origin)), + size( + stroke(width), + stroke(thickness) * if wavy { 3. } else { 1. }, + ), + ); + let origin = point(px(origin as f32 / 4.), px(-origin as f32 / 4.)); + let width = px(width as f32 / 4.); + assert_eq!(window.underline_bounds(origin, width, &style), bounds); + let original = paint_test_underlines(window, |window| { + window.paint_underline(origin, width, &style); + }) + .to_vec(); + assert_eq!(original.len(), usize::from(!bounds.is_empty())); + if let Some(underline) = original.first() { + assert_eq!(underline.bounds, bounds); + assert_eq!(underline.thickness, stroke(thickness)); + assert_eq!(underline.wavy, wavy.into()); + assert_eq!(underline.color, hsla(0.25, 0.5, 0.75, 0.5)); + } + + let underlines = paint_test_underlines(window, |window| { + window.paint_underline_with_exclusions(origin, width, &style, &[]); + }); + assert_eq!(underlines.len(), original.len()); + for (actual, original) in underlines.iter().zip(&original) { + assert_same_underline_geometry(actual, original); + assert_eq!(actual.content_mask, original.content_mask); + } + + let left = bounds.left().0 as i32; + let right = bounds.right().0 as i32; + let exclusions = [ + (15, 25), + (3, 7), + (5, 10), + (10, 12), + (0, 0), + (4, 2), + (-50, -1), + (70, 100), + ] + .map(|(start, end)| { + ScaledPixels((left + start) as f32) + ..ScaledPixels((left + end) as f32) + }); + let underlines = paint_test_underlines(window, |window| { + window.paint_underline_with_exclusions( + origin, + width, + &style, + &exclusions, + ); + }); + let expected = (left..right) + .filter(|column| { + !bounds.is_empty() + && !exclusions.iter().any(|span| { + span.contains(&ScaledPixels(*column as f32)) + }) + }) + .collect::>(); + assert_eq!(underline_device_columns(underlines), expected); + for underline in underlines { + assert_same_underline_geometry(underline, &original[0]); + } + } + } + } + } + }); + } + + #[gpui::test] + fn test_underline_exclusions_preserve_helvetica_warning_edge(cx: &mut TestAppContext) { + test_underline_paint_at_scales(cx, |window| { + if window.scale_factor() != 2.0 { + return; + } + let style = UnderlineStyle { + thickness: px(1.), + color: None, + wavy: true, + }; + let origin = point(px(2.888_183_8), px(15.357_917)); + let width = px(23.848_145) - origin.x; + let original = paint_test_underlines(window, |window| { + window.paint_underline(origin, width, &style); + })[0]; + assert_eq!(original.bounds.left(), ScaledPixels(6.)); + assert_eq!(original.bounds.right(), ScaledPixels(48.)); + let point_bounds = window.underline_bounds(origin, px(10.829_102), &style); + assert_eq!(point_bounds.left(), ScaledPixels(6.)); + assert_eq!(point_bounds.right(), ScaledPixels(28.)); + + let underlines = paint_test_underlines(window, |window| { + window.paint_underline_with_exclusions( + origin, + width, + &style, + &[point_bounds.left()..point_bounds.right()], + ); + }); + assert_eq!(underlines.len(), 1); + assert_same_underline_geometry(&underlines[0], &original); + assert_eq!( + underline_device_columns(underlines), + (28..48).collect::>() + ); + }); + } + + #[gpui::test] + fn test_underline_exclusions_preserve_content_mask_and_opacity(cx: &mut TestAppContext) { + test_underline_paint_at_scales(cx, |window| { + let scale = window.scale_factor(); + let original_mask = window.content_mask(); + let original_opacity = window.element_opacity(); + let mask = ContentMask { + bounds: Bounds::from_corners(point(px(4.), px(10.)), point(px(16.), px(12.))), + }; + let style = UnderlineStyle { + thickness: px(2.), + color: Some(hsla(0.25, 0.5, 0.75, 0.5)), + wavy: true, + }; + let origin = point(px(-1.25), px(9.25)); + let width = px(24.); + window.with_content_mask(Some(mask), |window| { + window.with_element_opacity(Some(0.5), |window| { + window.with_element_opacity(Some(0.5), |window| { + let original = paint_test_underlines(window, |window| { + window.paint_underline(origin, width, &style); + })[0]; + assert_eq!(original.color, hsla(0.25, 0.5, 0.75, 0.125)); + let underlines = paint_test_underlines(window, |window| { + window.paint_underline_with_exclusions( + origin, + width, + &style, + &[ScaledPixels(6. * scale)..ScaledPixels(8. * scale)], + ); + }); + assert_eq!(underlines.len(), 2); + let expected = [(4. * scale, 6. * scale), (8. * scale, 16. * scale)].map( + |(left, right)| { + Bounds::from_corners( + point(ScaledPixels(left), ScaledPixels((10. * scale).floor())), + point(ScaledPixels(right), ScaledPixels((12. * scale).ceil())), + ) + }, + ); + assert_eq!( + underlines + .iter() + .map(|underline| underline.content_mask.bounds) + .collect::>(), + expected + ); + for underline in underlines { + assert_same_underline_geometry(underline, &original); + } + }); + }); + }); + assert_eq!(window.content_mask(), original_mask); + assert_eq!(window.element_opacity(), original_opacity); + }); + } + + #[gpui::test] + fn test_underline_exclusions_adversarial_permutations(cx: &mut TestAppContext) { + test_underline_paint_at_scales(cx, |window| { + let style = UnderlineStyle { + thickness: px(1.), + color: None, + wavy: true, + }; + let origin = point(px(-4.), px(-1.)); + let width = px(8.); + let left = (-4. * window.scale_factor()) as i32; + let right = (4. * window.scale_factor()) as i32; + let endpoints = [-16, -8, -1, 0, 1, 8, 16]; + for first_start in endpoints { + for first_end in endpoints { + for second_start in endpoints { + for second_end in endpoints { + let exclusions = [first_start..first_end, second_start..second_end]; + let expected = (left..right) + .filter(|column| { + !exclusions.iter().any(|span| span.contains(column)) + }) + .collect::>(); + let exclusions = exclusions.map(|span| { + ScaledPixels(span.start as f32)..ScaledPixels(span.end as f32) + }); + let underlines = paint_test_underlines(window, |window| { + window.paint_underline_with_exclusions( + origin, + width, + &style, + &exclusions, + ); + }); + assert_eq!( + underline_device_columns(underlines), + expected, + "{exclusions:?}" + ); + } + } + } + } + }); + } + + #[derive(Clone, Copy, PartialEq)] + enum LongPressResponse { + PreventDefault, + StopPropagation, + None, + } + + struct LongPressListener { + phases: Rc>>, + response: LongPressResponse, + } + + impl Render for LongPressListener { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + let entity = cx.entity(); + let phases = self.phases.clone(); + let response = self.response; + canvas( + |_, _, _| {}, + move |_, _, window, _| { + window.on_mouse_event(move |event: &LongPressEvent, phase, window, cx| { + if phase != DispatchPhase::Bubble { + return; + } + phases.borrow_mut().push(event.phase); + match response { + LongPressResponse::PreventDefault => { + window.capture_long_press(&entity); + window.prevent_default(); + } + LongPressResponse::StopPropagation => cx.stop_propagation(), + LongPressResponse::None => {} + } + }); + }, + ) + } + } + + struct UnderlineTestView(Rc); + + impl Render for UnderlineTestView { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let paint = self.0.clone(); + canvas( + |_, _, _| {}, + move |_, _, window, _| { + window.content_mask_stack.push(ContentMask { + bounds: Bounds::from_corners( + point(px(-1000.), px(-1000.)), + point(px(1000.), px(1000.)), + ), + }); + paint(window); + window.content_mask_stack.pop(); + }, + ) + .size_full() + } + } + + fn test_underline_paint_at_scales( + cx: &mut TestAppContext, + paint: impl Fn(&mut Window) + 'static, + ) { + let window = cx.add_window(move |_, _| UnderlineTestView(Rc::new(paint))); + for scale in [1., 1.25, 1.5, 2., 3.] { + cx.simulate_window_scale_factor_change(window.into(), scale); + cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx)) + .unwrap(); + } + } + + fn paint_test_underlines(window: &mut Window, paint: impl FnOnce(&mut Window)) -> &[Underline] { + window.next_frame.scene.clear(); + paint(window); + &window.next_frame.scene.underlines + } + + fn assert_same_underline_geometry(actual: &Underline, expected: &Underline) { + assert_eq!(actual.bounds, expected.bounds); + assert_eq!(actual.thickness, expected.thickness); + assert_eq!(actual.wavy, expected.wavy); + assert_eq!(actual.color, expected.color); + assert_eq!(actual.pad, expected.pad); + } + + fn underline_device_columns(underlines: &[Underline]) -> Vec { + underlines + .iter() + .flat_map(|underline| { + let bounds = underline.bounds.intersect(&underline.content_mask.bounds); + bounds.left().0 as i32..bounds.right().0 as i32 + }) + .collect() + } + + fn dispatch_touch( + window: crate::WindowHandle, + cx: &mut TestAppContext, + id: TouchId, + phase: TouchPhase, + x: f32, + ) { + window + .update(cx, |_, window, cx| { + window.dispatch_event( + TouchEvent { + id, + phase, + position: point(px(x), px(0.)), + predicted_position: None, + force: None, + } + .to_platform_input(), + cx, + ); + }) + .unwrap(); + } +} + +#[cfg(all(test, any(feature = "inspector", debug_assertions)))] +mod inspector_tests { + use super::*; + use crate::{ + DivInspectorState, InspectorElementId, MouseDownEvent, StyleRefinement, TestAppContext, div, + }; + + #[gpui::test] + fn inspector_only_tracks_its_open_window(cx: &mut TestAppContext) { + let windows = [ + cx.add_window(|_, cx| InspectorTestRoot { + child: cx.new(|_| InspectorTestView::default()), + }), + cx.add_window(|_, cx| InspectorTestRoot { + child: cx.new(|_| InspectorTestView::default()), + }), + ]; + for window in windows { + assert_closed_inspector(window.into(), cx); + } + for _ in 0..2 { + cx.update_window(windows[0].into(), |root, window, cx| { + let root = root.downcast::().expect("test root"); + let child_widths = root.read(cx).child.read(cx).child_widths.clone(); + window.toggle_inspector(cx); + window.draw(cx).clear(cx); + assert_eq!(child_widths.borrow().as_slice(), &[px(10.); 3]); + let path = window + .rendered_frame + .next_inspector_instance_ids + .iter() + .find_map(|(path, count)| (*count == 3).then(|| path.clone())) + .expect("anonymous siblings share an inspector path"); + let selected_id = InspectorElementId { + path, + instance_id: 1, + }; + let position = window + .rendered_frame + .hitboxes + .iter() + .find(|hitbox| { + window.rendered_frame.inspector_hitboxes.get(&hitbox.id) + == Some(&selected_id) + }) + .expect("middle sibling is pickable") + .bounds + .center(); + window.simulate_mouse_move(position, cx); + window.dispatch_event( + PlatformInput::MouseDown(MouseDownEvent { + position, + button: MouseButton::Left, + modifiers: Modifiers::default(), + click_count: 1, + first_mouse: false, + }), + cx, + ); + window.dispatch_event( + PlatformInput::MouseUp(MouseUpEvent { + position, + button: MouseButton::Left, + modifiers: Modifiers::default(), + click_count: 1, + }), + cx, + ); + assert!(!window.is_inspector_picking(cx)); + assert_eq!( + window + .inspector + .as_ref() + .expect("open inspector") + .read(cx) + .active_element_id(), + Some(&selected_id) + ); + window.draw(cx).clear(cx); + window.with_inspector_state::( + Some(&selected_id), + cx, + |state, _| { + let state = state.as_mut().expect("selected div has style state"); + assert_eq!( + state.base_style.size.width, + Some(crate::Length::from(px(10.))) + ); + state.base_style.size.width = Some(crate::Length::from(px(25.))); + }, + ); + window.refresh(); + window.draw(cx).clear(cx); + assert_eq!( + child_widths.borrow().as_slice(), + &[px(10.), px(25.), px(10.)] + ); + }) + .expect("pick and edit a cached child"); + assert_closed_inspector(windows[1].into(), cx); + windows[0] + .update(cx, |_, window, cx| window.toggle_inspector(cx)) + .expect("close inspector"); + assert_closed_inspector(windows[0].into(), cx); + } + } + + struct InspectorTestRoot { + child: Entity, + } + + impl Render for InspectorTestRoot { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + self.child + .clone() + .cached(StyleRefinement::default().size(px(100.))) + } + } + + #[derive(Default)] + struct InspectorTestView { + child_widths: Rc>>, + } + + impl Render for InspectorTestView { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + let child_widths = self.child_widths.clone(); + div() + .on_children_prepainted(move |bounds, _, _| { + *child_widths.borrow_mut() = + bounds.iter().map(|bounds| bounds.size.width).collect(); + }) + .with_dynamic_prepaint_order(|_, _| SmallVec::from_iter([2, 0, 1])) + .id("inspector-root") + .flex() + .children((0..3).map(|_| div().size(px(10.)).flex_shrink_0())) + } + } + + fn assert_closed_inspector(window: AnyWindowHandle, cx: &mut TestAppContext) { + cx.update_window(window, |root, window, cx| { + window.draw(cx).clear(cx); + window.draw(cx).clear(cx); + let root = root.downcast::().expect("test root"); + assert_eq!( + root.read(cx) + .child + .read(cx) + .child_widths + .borrow() + .as_slice(), + &[px(10.); 3] + ); + for frame in [&window.rendered_frame, &window.next_frame] { + assert_eq!(frame.next_inspector_instance_ids.capacity(), 0); + assert_eq!(frame.inspector_hitboxes.capacity(), 0); + } + }) + .expect("closed inspector has no bookkeeping and no style overrides"); + } +} diff --git a/vendor/gpui-pre/src/window/a11y.rs b/vendor/gpui-pre/src/window/a11y.rs new file mode 100644 index 00000000..5b638212 --- /dev/null +++ b/vendor/gpui-pre/src/window/a11y.rs @@ -0,0 +1,905 @@ +//! Accessibility support, provided by [AccessKit][accesskit]. +//! +//! There are user-facing guide-level docs [here](crate::_accessibility). +//! +//! ## Architecture +//! +//! ```text +//! ┌────────────────────────────────┐ ┌─────────────────────┐ +//! ┌─▶│ AccessKit Adapter (MacOS) │◀─▶│ MacOS System APIs │ +//! │ └────────────────────────────────┘ └─────────────────────┘ +//! │ +//! ┌──────┐ ┌───────────┐ │ ┌────────────────────────────────┐ ┌─────────────────────┐ +//! │ GPUI │◀─▶│ AccessKit │◀─┼─▶│ AccessKit Adapter (Windows) │◀─▶│ Windows System APIs │ +//! └──────┘ └───────────┘ │ └────────────────────────────────┘ └─────────────────────┘ +//! │ +//! │ ┌────────────────────────────────┐ ┌─────────────────────┐ +//! └─▶│ AccessKit Adapter (Linux) │◀─▶│ dbus │ +//! └────────────────────────────────┘ └─────────────────────┘ +//! ``` +//! +//! In order for GPUI apps to be usable for people using assistive technology, +//! we must do a few things: +//! - Inform the system when the UI changes meaningfully. This includes: +//! - Reporting new/removed/changed UI elements +//! - *Not* reporting irrelevant UI changes, e.g. an invisible `div()` being +//! added. +//! - Reporting the appearance and capabilities of each UI element. For example: +//! - What does this piece of text say? +//! - How far along is this progress bar? +//! - Can this node be focused? +//! - Can this node have a value directly assigned? (e.g. a slider) +//! - Allowing the system to interact with the UI by dispatching actions to +//! nodes. Note that AccessKit has its own [`Action`] type, which is not the +//! [`crate::Action`] trait. +//! - Activate and deactivate accessibility features when requested by the +//! system. +//! +//! Activating and deactivating at the right time is trivial, so I won't go into +//! detail here. The other two are almost orthogonal in implementation. +//! +//! The state for both lives in the [`A11y`] struct in this module. +//! +//! ### Reporting UI changes +//! +//! Every frame, we build a [`TreeUpdate`] and send it to the platform-specific +//! adapter. A [`TreeUpdate`] is a representation of a subset of the UI tree. +//! When the adapter receives the update, it diffs it against the previous +//! update, and calls platform-specific APIs to inform screen readers about the +//! changes. Nodes may have been created, destroyed, or updated. +//! +//! Each node has an ID, and this ID *should* be stable across frames. If a +//! node's ID changes, then, from AccessKit's point of view, it is a different +//! node. +//! +//! We derive the node ID from the [`GlobalElementId`] in +//! [`GlobalElementId::accesskit_node_id`]. Nodes without [`GlobalElementId`]s +//! cannot produce an AccessKit [`NodeId`], and so are not included in the +//! accessibility tree. We try to warn when using accessibility APIs on +//! [`div()`] without setting an ID. +//! +//! This all happens in [`Drawable::prepaint`]. The [`A11y`] struct maintains a +//! stack of nodes during prepainting, which we can use to calculate the +//! [`NodeId`]s, and record parent-child relationships. Once all [`Element`]s in +//! a frame have been prepainted, we send the resulting [`TreeUpdate`] object to +//! the adapter and the screen reader can announce the changes. +//! +//! #### Synthetic children +//! +//! Additionally, some nodes can register "synthetic children" using +//! [`Element::a11y_synthetic_children`]. Normally, one accesskit node is pushed +//! for every [`Element`] with a role and id. However, sometimes a single +//! element may want to produce many accesskit nodes. These extra nodes are +//! referred to as "synthetic children" of the element providing a non-default +//! [`Element::a11y_synthetic_children`] implementation. +//! +//! The user is provided a builder-style API using [`A11ySubtreeBuilder`], which +//! allows them to create push nodes that are children of the current node, as +//! well as modify the current node itself. +//! +//! GPUI calls this callback *after* prepainting (and just before popping the +//! corresponding element), since this step may need prepaint information to be +//! available. In the future, we may want to add prepaint information more +//! generally to [`Element::write_a11y_info`], but for now that's not necessary. +//! +//! ### Responding to actions +//! +//! On adapter creation, we provide a callback to the adapter, which can be used +//! to dispatch actions. This callback forwards to [`A11y::action_listeners`], a +//! mapping from [`NodeId`]s to action handlers (basically just `Box`). +//! +//! This is populated in: +//! - [`Window::on_a11y_action`], which is called by: +//! - [`Interactivity::paint`], which is called by: +//! - [`StatefulInteractiveElement::on_a11y_action`], which is a public-facing API +//! +//! These are cleared at the start of a frame, and re-populated during painting. +//! +//! [`NodeId`]: accesskit::NodeId + +use crate::*; + +pub(crate) mod debug; + +use crate::{App, Bounds, FocusId, Pixels, SharedString, Window}; +use accesskit::{Action, NodeId, TreeUpdate}; +use collections::{FxHashMap, FxHashSet}; +use smallvec::SmallVec; +use std::hash::{Hash, Hasher}; +use std::sync::{ + Arc, + atomic::{AtomicBool, Ordering}, +}; + +/// The fixed AccessKit node ID used for the root of every window's a11y tree. +pub(crate) const ROOT_NODE_ID: NodeId = NodeId(0); + +/// A listener for an accessibility action on a specific node. +pub(crate) type A11yActionListener = + Box, &mut Window, &mut App) + 'static>; + +/// Per-window accessibility state. +/// +/// Manages the AccessKit tree that is built each frame and the mappings +/// needed to dispatch incoming action requests back to the right elements. +pub(crate) struct A11y { + /// Whether accessibility has been [forcibly disabled] for this window. + /// + /// [forcibly disabled]: crate::Application::new_inaccessible + force_disabled: bool, + /// Whether a11y features have been requested by the system. + /// + /// Updated by AccessKit using callbacks provided to the adapter. Can change + /// halfway through a frame. + active_flag: Arc, + /// Whether a11y features are active for *this specific frame*. + /// + /// At the start of each frame, we load [`Self::active_flag`] (using + /// [`Self::sync_active_flag`]) and use this to determine whether we + /// should construct a [`TreeUpdate`] for this frame. It's important that + /// this value is stable within a frame, because the builder API exposed by + /// this type maintains a stack of nodes and each must be pushed and popped + /// exactly once. + /// + /// At the end of the frame, we re-call [`Self::sync_active_flag`] to + /// determine whether we should actually send the finished [`TreeUpdate`]. + active_this_frame: bool, + pub(crate) nodes: A11yNodeBuilder, + pub(crate) focus_ids: FxHashMap, + pub(crate) node_bounds: FxHashMap>, + pub(crate) action_listeners: FxHashMap>, + /// The window's title, used to label the root node so assistive + /// technology can tell windows apart. + window_title: Option, + /// The focus id we most recently reported as having no accessibility node, + /// used to log at most once per focus change rather than every frame. + last_focus_without_node: Option, + /// Retains the last tree update (and, in debug builds, per-node provenance) + /// so it can be dumped via [`crate::Window::debug_a11y_tree_json`]. + debug: debug::A11yDebug, + /// Maps a view's [`EntityId`] to its `Render` type name + #[cfg(debug_assertions)] + pub(crate) view_type_names: FxHashMap, +} + +impl A11y { + pub(crate) fn new( + active_flag: Arc, + force_disabled: bool, + window_title: Option, + ) -> Self { + Self { + force_disabled, + active_flag, + active_this_frame: false, + nodes: A11yNodeBuilder::new(), + focus_ids: FxHashMap::default(), + node_bounds: FxHashMap::default(), + action_listeners: FxHashMap::default(), + window_title, + last_focus_without_node: None, + debug: debug::A11yDebug::default(), + #[cfg(debug_assertions)] + view_type_names: FxHashMap::default(), + } + } + + /// Logs (once per focus change) that the focused element is not exposed to + /// assistive technology because it has no accessibility node. When this + /// happens, screen readers fall back to announcing the whole window instead + /// of the focused element. The fix is to give the element both an + /// `.id(...)` and a `.role(...)`. + pub(crate) fn note_focus_without_node(&mut self, focus_id: FocusId, reason: &str) { + if self.last_focus_without_node != Some(focus_id) { + self.last_focus_without_node = Some(focus_id); + log::info!( + "a11y: focused element ({focus_id:?}) has no accessibility node \ + ({reason}); assistive technology will announce the whole window \ + instead. Give it both an `.id(...)` and a `.role(...)` to expose it." + ); + } + } + + pub(crate) fn set_window_title(&mut self, title: impl Into) { + self.window_title = Some(title.into()); + } + + /// Ensures that [`Self::is_active`] returns up to date information. + /// + /// See the docs for [`Self::active_flag`] and [`Self::active_this_frame`] + /// for more commentary. + pub(crate) fn sync_active_flag(&mut self) { + self.active_this_frame = self.is_enabled() && self.active_flag.load(Ordering::SeqCst); + } + + pub(crate) fn is_enabled(&self) -> bool { + !self.force_disabled + } + + pub(crate) fn is_active(&self) -> bool { + self.active_this_frame + } + + pub(crate) fn set_focusable(&mut self, node_id: NodeId, focus_id: FocusId) { + self.focus_ids.insert(node_id, focus_id); + } + + /// Report `node_id` as the currently-focused node, if it is present in the + /// tree. + /// + /// Must only be called once per frame. + pub(crate) fn set_focus(&mut self, node_id: NodeId) { + // A focused node must have been registered as focusable this frame. + if !self.focus_ids.contains_key(&node_id) { + if cfg!(debug_assertions) { + panic!("set_focus called for a node that was not registered with set_focusable"); + } else { + log::warn!( + "a11y: set_focus called for a node that was not registered with \ + set_focusable ({node_id:?})" + ); + } + } + if self.nodes.has_node(node_id) { + // The focused element is properly exposed; reset the dedup so a + // later focus on a node-less element logs again. + self.last_focus_without_node = None; + self.nodes.set_focus(node_id); + } else { + // The element registered a focus handle and an id, but never got a + // node because it has no role. + if let Some(focus_id) = self.focus_ids.get(&node_id).copied() { + self.note_focus_without_node(focus_id, "it has an id but no role"); + } + } + } + + pub(crate) fn set_active_descendant(&mut self, node_id: NodeId) { + // The active descendant must be a descendant of the focused container, + // not the focused node itself. + if self.nodes.node_is_focused(node_id) { + if cfg!(debug_assertions) { + panic!("set_active_descendant called on the focused node"); + } else { + log::warn!("a11y: set_active_descendant called on the focused node ({node_id:?})"); + } + return; + } + if self.nodes.has_node(node_id) && self.nodes.focus_is_ancestor_of_current() { + self.nodes.set_active_descendant(node_id); + } + } + + /// Clear per-frame state and push the root node to start a new frame. + pub(crate) fn begin_frame(&mut self) { + self.focus_ids.clear(); + self.node_bounds.clear(); + self.action_listeners.clear(); + self.nodes.begin_frame(self.window_title.as_ref()); + } + + /// Finalize the tree and produce a [`TreeUpdate`] for the platform adapter. + pub(crate) fn end_frame(&mut self, frame: debug::FrameDebugInfo) -> TreeUpdate { + let update = self.nodes.finalize(); + self.debug.capture( + &update, + self.nodes.focus, + self.nodes.active_descendant, + self.window_title.as_ref(), + frame, + ); + #[cfg(debug_assertions)] + self.debug.capture_node_info(&self.nodes.node_info); + update + } + + pub(crate) fn debug_tree_json(&self) -> Option { + self.debug.to_json() + } +} + +/// Builder API for synthetic children. See the docs for +/// [`Element::a11y_synthetic_children`]. +pub struct A11ySubtreeBuilder<'a> { + parent_id: NodeId, + nodes: &'a mut A11yNodeBuilder, + /// Provenance of the real element whose `a11y_synthetic_children` is + /// running. + #[cfg(debug_assertions)] + creator: debug::NodeCreator, +} + +impl<'a> A11ySubtreeBuilder<'a> { + pub(crate) fn new(parent_id: NodeId, nodes: &'a mut A11yNodeBuilder) -> Self { + Self { + parent_id, + nodes, + #[cfg(debug_assertions)] + creator: debug::NodeCreator::default(), + } + } + + #[cfg(debug_assertions)] + pub(crate) fn with_creator(mut self, creator: debug::NodeCreator) -> Self { + self.creator = creator; + self + } + + /// Derive a [`NodeId`] for a synthetic child. + /// + /// The generated ID is based on the hash of `key`, as well as the parent's + /// ID. This means that `key`s must be unique within the same + /// [`Element::a11y_synthetic_children`] call, but may be duplicated across + /// different calls. + pub fn synthetic_node_id(&self, key: impl Hash) -> NodeId { + let mut hasher = std::hash::DefaultHasher::default(); + self.parent_id.0.hash(&mut hasher); + key.hash(&mut hasher); + NodeId(hasher.finish()) + } + + /// Append a synthetic leaf node as a child of this element's node. + /// + /// Returns `false` if a node with this id is already present in the tree, + /// in which case the node is discarded. + pub fn push_child(&mut self, id: NodeId, node: accesskit::Node) -> bool { + let pushed = self.nodes.push_leaf(id, node); + #[cfg(debug_assertions)] + if pushed { + self.nodes.record_node_info( + id, + debug::NodeDebugInfo { + synthetic: true, + view: self.creator.view, + element_id: self.creator.element_id.clone(), + source_location: self.creator.source_location, + }, + ); + } + pushed + } + + /// A mutable reference to the parent node. + pub fn parent_node(&mut self) -> &mut accesskit::Node { + self.nodes + .current_node_mut() + .expect("A11ySubtreeBuilder exists only while its element's node is on the stack") + } +} + +pub(crate) struct A11yNodeBuilder { + ids_stack: SmallVec<[NodeId; 16]>, + nodes_stack: SmallVec<[accesskit::Node; 16]>, + /// This is the exact type required by accesskit, so we can't just make it a + /// `HashMap` to remove the need for `seen_ids` + all_nodes: Vec<(NodeId, accesskit::Node)>, + seen_ids: FxHashSet, + /// The node that GPUI considers focused. Note that this may be different to + /// what is reported to accesskit - see [`Self::active_descendant`] + focus: Option, + /// If a node calls `.aria_active_descendant()`, AND an ancestor is focused, + /// override it as the focused node. This supports the "active descendant" + /// pattern, which allows a focused container to act as if a descendant is + /// focused. + active_descendant: Option, + #[cfg(debug_assertions)] + node_info: FxHashMap, +} + +impl A11yNodeBuilder { + fn new() -> Self { + Self { + ids_stack: SmallVec::new(), + nodes_stack: SmallVec::new(), + all_nodes: Vec::new(), + seen_ids: FxHashSet::default(), + focus: None, + active_descendant: None, + #[cfg(debug_assertions)] + node_info: FxHashMap::default(), + } + } + + /// Records provenance for a node already pushed this frame. Debug builds only. + #[cfg(debug_assertions)] + pub(crate) fn record_node_info(&mut self, id: NodeId, info: debug::NodeDebugInfo) { + self.node_info.insert(id, info); + } + + #[must_use] + fn can_push(&mut self, id: NodeId) -> bool { + debug_assert!(!self.ids_stack.is_empty(), "node pushed before push_root"); + + if !self.seen_ids.insert(id) { + debug_assert!( + false, + "Duplicate a11y node id: {id:?}. In a release build, this node would be silently discarded from the a11y tree." + ); + return false; + } + + true + } + + /// Push a new node onto the stack. It becomes a child of the current + /// top-of-stack node. + /// + /// Returns `true` if the node was successfully pushed. + pub(crate) fn push(&mut self, id: NodeId, node: accesskit::Node) -> bool { + if !self.can_push(id) { + return false; + } + + if let Some(parent) = self.nodes_stack.last_mut() { + parent.push_child(id); + } + self.ids_stack.push(id); + self.nodes_stack.push(node); + true + } + + /// Add a leaf node as a child of the current top-of-stack node, without + /// pushing it onto the stack. Semantically equivalent to a [`Self::push`] + /// followed by a [`Self::pop`]. + /// + /// Returns `true` if the node was successfully pushed. + pub(crate) fn push_leaf(&mut self, id: NodeId, node: accesskit::Node) -> bool { + if !self.can_push(id) { + return false; + } + + if let Some(parent) = self.nodes_stack.last_mut() { + parent.push_child(id); + } + self.all_nodes.push((id, node)); + true + } + + pub(crate) fn current_node_mut(&mut self) -> Option<&mut accesskit::Node> { + self.nodes_stack.last_mut() + } + + /// Pop the current node off the stack and finalize it into the all_nodes + /// list. + pub(crate) fn pop(&mut self) { + debug_assert!(self.ids_stack.len() > 1, "pop would remove the root node"); + + if let (Some(id), Some(node)) = (self.ids_stack.pop(), self.nodes_stack.pop()) { + self.all_nodes.push((id, node)); + } + } + + /// Push the root node to start a new frame. + fn begin_frame(&mut self, window_title: Option<&SharedString>) { + self.all_nodes.clear(); + self.ids_stack.clear(); + self.nodes_stack.clear(); + self.seen_ids.clear(); + #[cfg(debug_assertions)] + self.node_info.clear(); + let mut root_node = accesskit::Node::new(accesskit::Role::Window); + if let Some(title) = window_title { + root_node.set_label(title.to_string()); + } + + self.ids_stack.push(ROOT_NODE_ID); + self.nodes_stack.push(root_node); + self.focus = None; + self.active_descendant = None; + } + + /// Returns whether a node with the given ID has been pushed in this frame. + pub(crate) fn has_node(&self, id: NodeId) -> bool { + id == ROOT_NODE_ID || self.seen_ids.contains(&id) + } + + /// Returns whether `id` is the node currently reported as focused. + pub(crate) fn node_is_focused(&self, id: NodeId) -> bool { + self.focus == Some(id) + } + + pub(crate) fn focus_is_ancestor_of_current(&self) -> bool { + let Some(focus) = self.focus else { + return false; + }; + + // The current node is on top of the stack; everything below it is an + // ancestor. + let ancestor_count = self.ids_stack.len().saturating_sub(1); + self.ids_stack[..ancestor_count].contains(&focus) + } + + pub(crate) fn set_active_descendant(&mut self, id: NodeId) { + if self + .active_descendant + .is_some_and(|existing| existing != id) + { + if cfg!(debug_assertions) { + panic!("active descendant claimed by multiple nodes in one frame"); + } else { + log::warn!( + "a11y: multiple nodes claimed the active descendant this frame; \ + using last-wins ({id:?})" + ); + } + } + self.active_descendant = Some(id); + } + + pub(crate) fn set_focus(&mut self, id: NodeId) { + if self.focus.is_some() { + if cfg!(debug_assertions) { + panic!("set_focus called more than once in a single frame"); + } else { + log::warn!( + "a11y: set_focus called more than once in a single frame; \ + using last-wins ({id:?})" + ); + } + } + self.focus = Some(id); + } + + fn finalize(&mut self) -> TreeUpdate { + // Stack should contain only the root node + debug_assert_eq!(self.ids_stack.len(), 1); + debug_assert_eq!(self.ids_stack[0], ROOT_NODE_ID); + + if self.ids_stack.len() != 1 { + log::error!( + "a11y: Stack imbalance at end of frame: expected 1 (root), got {}. \ + Some elements may have pushed without popping.", + self.ids_stack.len() + ); + } + + // Pop remaining nodes (should just be the root). + while !self.ids_stack.is_empty() { + if let (Some(id), Some(node)) = (self.ids_stack.pop(), self.nodes_stack.pop()) { + self.all_nodes.push((id, node)); + } + } + + let focus = match self.active_descendant { + Some(id) if self.has_node(id) => id, + Some(id) => { + if cfg!(debug_assertions) { + panic!("active_descendant set to {id:?}, which is not in the tree"); + } else { + log::warn!("active_descendant set to {id:?}, which is not in the tree"); + self.focus.unwrap_or(ROOT_NODE_ID) + } + } + + _ => self.focus.unwrap_or(ROOT_NODE_ID), + }; + + let nodes = std::mem::take(&mut self.all_nodes); + let update = TreeUpdate { + nodes, + tree: Some(accesskit::Tree::new(ROOT_NODE_ID)), + tree_id: accesskit::TreeId::ROOT, + focus, + }; + + Self::repair_tree_update(update) + } + + /// Accesskit panics on invalid [`TreeUpdate`]s. This function defensively + /// checks invariants that accesskit panics on, and tries to fix them. + fn repair_tree_update(mut update: TreeUpdate) -> TreeUpdate { + let node_ids: FxHashSet = update.nodes.iter().map(|(id, _)| *id).collect(); + + // Focus must point to a node in the tree. + if !node_ids.contains(&update.focus) { + log::error!( + "a11y: Focused node {:?} is not in the tree ({} nodes). \ + Falling back to root. This is a bug in the a11y tree builder.", + update.focus, + update.nodes.len() + ); + update.focus = ROOT_NODE_ID; + } + + // Every child reference must point to a node in the update. + for (id, node) in &mut update.nodes { + let has_invalid_child = node + .children() + .iter() + .any(|child_id| !node_ids.contains(child_id)); + if has_invalid_child { + let children = node.children(); + let invalid_count = children + .iter() + .filter(|child_id| !node_ids.contains(child_id)) + .count(); + log::error!( + "a11y: Node {:?} references {} children not present in the tree. \ + Stripping invalid child references.", + id, + invalid_count + ); + let valid: Vec = children + .iter() + .copied() + .filter(|child_id| node_ids.contains(child_id)) + .collect(); + node.set_children(valid); + } + } + + update + } +} + +#[cfg(test)] +mod tests { + // Import specific items rather than glob-importing `super`, which would pull + // in gpui's own `test` attribute macro and shadow the standard one. + use super::{A11y, A11yNodeBuilder, ROOT_NODE_ID}; + use crate::FocusId; + use accesskit::{NodeId, Role}; + use std::sync::{Arc, atomic::AtomicBool}; + + fn test_node() -> accesskit::Node { + accesskit::Node::new(Role::GenericContainer) + } + + fn new_builder() -> A11yNodeBuilder { + let mut builder = A11yNodeBuilder::new(); + builder.begin_frame(None); + builder + } + + fn new_a11y() -> A11y { + let mut a11y = A11y::new(Arc::new(AtomicBool::new(true)), false, None); + a11y.begin_frame(); + a11y + } + + #[test] + fn accessibility_enabled_is_independent_of_activation() { + for force_disabled in [false, true] { + for active in [false, true] { + let mut a11y = A11y::new(Arc::new(AtomicBool::new(active)), force_disabled, None); + a11y.sync_active_flag(); + + assert_eq!(a11y.is_enabled(), !force_disabled); + assert_eq!(a11y.is_active(), !force_disabled && active); + } + } + } + + #[test] + fn active_descendant_honored_when_container_focused() { + let mut builder = new_builder(); + let container = NodeId(1); + let item = NodeId(2); + + assert!(builder.push(container, test_node())); + builder.set_focus(container); + assert!(builder.push(item, test_node())); + + // The item is on top of the stack; the focused container is its + // ancestor, so the claim is honored. + assert!(builder.focus_is_ancestor_of_current()); + builder.set_active_descendant(item); + + builder.pop(); // item + builder.pop(); // container + let update = builder.finalize(); + assert_eq!(update.focus, item); + } + + #[test] + fn active_descendant_honored_for_deep_descendant() { + let mut builder = new_builder(); + let container = NodeId(1); + let group = NodeId(2); + let item = NodeId(3); + + assert!(builder.push(container, test_node())); + builder.set_focus(container); + assert!(builder.push(group, test_node())); + assert!(builder.push(item, test_node())); + + // The item is a grandchild of the focused container; depth doesn't + // matter, the focused ancestor is still on the stack. + assert!(builder.focus_is_ancestor_of_current()); + builder.set_active_descendant(item); + + builder.pop(); // item + builder.pop(); // group + builder.pop(); // container + let update = builder.finalize(); + assert_eq!(update.focus, item); + } + + #[test] + fn active_descendant_ignored_when_focus_in_other_subtree() { + let mut builder = new_builder(); + let focused_container = NodeId(1); + let focused_leaf = NodeId(2); + let other_container = NodeId(3); + let other_item = NodeId(4); + + // First subtree holds real focus. + assert!(builder.push(focused_container, test_node())); + assert!(builder.push(focused_leaf, test_node())); + builder.set_focus(focused_leaf); + builder.pop(); // focused_leaf + builder.pop(); // focused_container + + // Second subtree: its item would claim the active descendant, but the + // focus is not on any of its ancestors, so the gate rejects it. + assert!(builder.push(other_container, test_node())); + assert!(builder.push(other_item, test_node())); + assert!(!builder.focus_is_ancestor_of_current()); + builder.pop(); // other_item + builder.pop(); // other_container + + let update = builder.finalize(); + assert_eq!(update.focus, focused_leaf); + } + + #[test] + fn active_descendant_ignored_when_nothing_focused() { + let mut builder = new_builder(); + let container = NodeId(1); + let item = NodeId(2); + + assert!(builder.push(container, test_node())); + assert!(builder.push(item, test_node())); + + // Nothing is focused (focus defaults to the root window node), so the + // gate rejects the claim. + assert!(!builder.focus_is_ancestor_of_current()); + builder.pop(); + builder.pop(); + + let update = builder.finalize(); + assert_eq!(update.focus, ROOT_NODE_ID); + } + + #[test] + fn regular_focus_used_when_no_active_descendant() { + let mut builder = new_builder(); + let focused = NodeId(1); + + assert!(builder.push(focused, test_node())); + builder.set_focus(focused); + builder.pop(); + + let update = builder.finalize(); + assert_eq!(update.focus, focused); + } + + #[test] + fn focus_is_ancestor_excludes_self_and_non_ancestors() { + let mut builder = new_builder(); + let container = NodeId(1); + let item = NodeId(2); + + assert!(builder.push(container, test_node())); + builder.set_focus(container); + + // With the focused container itself on top, it is not its own (strict) + // ancestor, so the gate is false. + assert!(!builder.focus_is_ancestor_of_current()); + + assert!(builder.push(item, test_node())); + // Now the focused container is a strict ancestor of the item on top. + assert!(builder.focus_is_ancestor_of_current()); + + builder.pop(); + builder.pop(); + } + + // The double-claim guard panics only in debug builds; in release it falls + // back to last-wins with a warning. + #[test] + #[cfg_attr( + debug_assertions, + should_panic(expected = "active descendant claimed by multiple nodes") + )] + fn multiple_active_descendant_claims_panic_in_debug() { + let mut builder = new_builder(); + builder.set_active_descendant(NodeId(1)); + builder.set_active_descendant(NodeId(2)); + } + + // Setting focus twice in one frame means two elements both claimed window + // focus; that panics in debug and falls back to last-wins in release. + #[test] + #[cfg_attr( + debug_assertions, + should_panic(expected = "set_focus called more than once") + )] + fn setting_focus_twice_panics_in_debug() { + let mut builder = new_builder(); + builder.set_focus(NodeId(1)); + builder.set_focus(NodeId(2)); + } + + // Focusing a node that was never registered as focusable is a bug: panic in + // debug, warn in release. + #[test] + #[cfg_attr( + debug_assertions, + should_panic(expected = "was not registered with set_focusable") + )] + fn set_focus_without_set_focusable() { + let mut a11y = new_a11y(); + let node = NodeId(1); + assert!(a11y.nodes.push(node, test_node())); + // set_focusable was never called for `node`. + a11y.set_focus(node); + } + + // The focused node cannot also be its own active descendant: panic in + // debug, warn in release. + #[test] + #[cfg_attr(debug_assertions, should_panic(expected = "on the focused node"))] + fn set_active_descendant_on_focused_node() { + let mut a11y = new_a11y(); + let node = NodeId(1); + assert!(a11y.nodes.push(node, test_node())); + a11y.set_focusable(node, FocusId::default()); + a11y.set_focus(node); + a11y.set_active_descendant(node); + } + + // Two sibling children of a focused container both claim the active + // descendant (both pass the focus gate). The second claim is a bug: panic + // in debug, last-wins + warn in release. + #[test] + #[cfg_attr( + debug_assertions, + should_panic(expected = "active descendant claimed by multiple nodes") + )] + fn two_siblings_claiming_active_descendant() { + let mut a11y = new_a11y(); + let container = NodeId(1); + let first = NodeId(2); + let second = NodeId(3); + + assert!(a11y.nodes.push(container, test_node())); + a11y.set_focusable(container, FocusId::default()); + a11y.set_focus(container); + + assert!(a11y.nodes.push(first, test_node())); + a11y.set_active_descendant(first); + a11y.nodes.pop(); // first + + assert!(a11y.nodes.push(second, test_node())); + a11y.set_active_descendant(second); + a11y.nodes.pop(); // second + + a11y.nodes.pop(); // container + } + + // Node A is focused; node C (a child of the unfocused node B) claims the + // active descendant. The final tree must still report A as focused. + #[test] + fn active_descendant_in_unfocused_subtree_keeps_real_focus() { + let mut a11y = new_a11y(); + let a = NodeId(1); + let b = NodeId(2); + let c = NodeId(3); + + assert!(a11y.nodes.push(a, test_node())); + a11y.set_focusable(a, FocusId::default()); + a11y.set_focus(a); + a11y.nodes.pop(); // a + + assert!(a11y.nodes.push(b, test_node())); + assert!(a11y.nodes.push(c, test_node())); + a11y.set_active_descendant(c); + a11y.nodes.pop(); // c + a11y.nodes.pop(); // b + + let update = a11y.end_frame(Default::default()); + assert_eq!(update.focus, a); + } +} diff --git a/vendor/gpui-pre/src/window/a11y/debug.rs b/vendor/gpui-pre/src/window/a11y/debug.rs new file mode 100644 index 00000000..ae98aa52 --- /dev/null +++ b/vendor/gpui-pre/src/window/a11y/debug.rs @@ -0,0 +1,330 @@ +//! Developer tooling for inspecting the accessibility tree. +//! +//! [`A11yDebug`] retains the last [`TreeUpdate`] sent to the platform adapter so +//! it can be serialized on demand (see +//! [`crate::Window::debug_a11y_tree_json`]). In `cfg(debug_assertions)` builds, +//! we capture extra info. + +use accesskit::{Action, NodeId, TreeUpdate}; +use collections::FxHashMap; + +use crate::{Pixels, SharedString, Size}; + +#[derive(Default)] +pub(crate) struct FrameDebugInfo { + pub viewport_size: Size, + pub scale_factor: f32, + pub tab_stop_count: usize, +} + +struct CapturedFrame { + rendered_at: String, + frame_number: u64, + window_title: Option, + node_count: usize, + tab_stop_count: usize, + viewport_size: Size, + scale_factor: f32, +} + +#[cfg(debug_assertions)] +#[derive(Clone, Default)] +pub(crate) struct NodeDebugInfo { + /// Whether the node was synthesized via + /// [`crate::Element::a11y_synthetic_children`] rather than created from a + /// real element with a role and ID. + pub synthetic: bool, + /// The type name of the `Render` view that was rendering when the node was + /// created. + pub view: Option<&'static str>, + /// The [`ElementId`](crate::ElementId) of the creating element (the leaf of + /// its `GlobalElementId`, not the full path). For a synthetic node, this is + /// the real element whose `a11y_synthetic_children` produced it. + pub element_id: Option, + /// Source location where the creating element was constructed. + pub source_location: Option<&'static core::panic::Location<'static>>, +} + +#[cfg(debug_assertions)] +#[derive(Clone, Default)] +pub(crate) struct NodeCreator { + pub view: Option<&'static str>, + pub element_id: Option, + pub source_location: Option<&'static core::panic::Location<'static>>, +} + +#[derive(Default)] +pub(crate) struct A11yDebug { + last_tree_update: Option, + last_gpui_focus: Option, + last_active_descendant: Option, + /// Monotonic counter incremented on each captured frame, so a re-dump makes + /// it obvious whether the tree actually refreshed. + frame_number: u64, + /// Metadata about the most recently captured frame. + last_frame: Option, + #[cfg(debug_assertions)] + last_node_info: FxHashMap, +} + +impl A11yDebug { + pub(crate) fn capture( + &mut self, + update: &TreeUpdate, + gpui_focus: Option, + active_descendant: Option, + window_title: Option<&SharedString>, + frame: FrameDebugInfo, + ) { + self.last_tree_update = Some(update.clone()); + self.last_gpui_focus = gpui_focus; + self.last_active_descendant = active_descendant; + self.frame_number += 1; + self.last_frame = Some(CapturedFrame { + rendered_at: chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, false), + frame_number: self.frame_number, + window_title: window_title.cloned(), + node_count: update.nodes.len(), + tab_stop_count: frame.tab_stop_count, + viewport_size: frame.viewport_size, + scale_factor: frame.scale_factor, + }); + } + + #[cfg(debug_assertions)] + pub(crate) fn capture_node_info(&mut self, node_info: &FxHashMap) { + self.last_node_info = node_info.clone(); + } + + /// Serialize the last tree update to a readable JSON string. Node ids are + /// replaced with short ephemeral ids (`a`, `b`, ..., `z`, `aa`, ...). + pub(crate) fn to_json(&self) -> Option { + let update = self.last_tree_update.as_ref()?; + + let mut ephemeral: FxHashMap = FxHashMap::default(); + for (index, (id, _)) in update.nodes.iter().enumerate() { + ephemeral.insert(*id, ephemeral_id(index)); + } + + let mut nodes = serde_json::Map::new(); + for (id, node) in &update.nodes { + let key = ephemeral + .get(id) + .cloned() + .unwrap_or_else(|| id.0.to_string()); + #[cfg(debug_assertions)] + let provenance = self + .last_node_info + .get(id) + .map(|info| NodeProvenance { + element_id: info.element_id.as_deref(), + view: info.view, + source_location: info.source_location.map(|loc| loc.to_string()), + // Only surface synthetic nodes; `false` is the default and + // would just be noise on every real node. + synthetic: info.synthetic.then_some(true), + }) + .unwrap_or_default(); + #[cfg(not(debug_assertions))] + let provenance = NodeProvenance::default(); + let value = node_to_json(*id, node, &ephemeral, &provenance); + nodes.insert(key, value); + } + + let frame = self.last_frame.as_ref().map(|frame| { + serde_json::json!({ + "rendered_at": frame.rendered_at, + "frame_number": frame.frame_number, + "window_title": frame.window_title.as_ref().map(|title| title.to_string()), + "node_count": frame.node_count, + "tab_stop_count": frame.tab_stop_count, + "viewport_size": { + "width": frame.viewport_size.width.0, + "height": frame.viewport_size.height.0, + }, + "scale_factor": frame.scale_factor, + }) + }); + + let root = update + .tree + .as_ref() + .map(|tree| tree.root) + .and_then(|id| ephemeral.get(&id).cloned()); + + let value = serde_json::json!({ + "root": root, + "gpui_focus": self.last_gpui_focus.and_then(|id| ephemeral.get(&id).cloned()), + "active_descendant_focus": self.last_active_descendant.and_then(|id| ephemeral.get(&id).cloned()), + "frame": frame, + "nodes": nodes, + }); + Some(serde_json::to_string_pretty(&value).unwrap_or_else(|_| "{}".to_string())) + } +} + +#[derive(Default)] +struct NodeProvenance<'a> { + element_id: Option<&'a str>, + view: Option<&'a str>, + source_location: Option, + synthetic: Option, +} + +fn node_to_json( + id: NodeId, + node: &accesskit::Node, + ephemeral: &FxHashMap, + provenance: &NodeProvenance, +) -> serde_json::Value { + use serde_json::json; + + let mut map = serde_json::Map::new(); + map.insert("accesskit_id".into(), json!(id.0.to_string())); + + let children: Vec = node + .children() + .iter() + .map(|child| { + ephemeral + .get(child) + .cloned() + .unwrap_or_else(|| child.0.to_string()) + }) + .collect(); + if !children.is_empty() { + map.insert("children".into(), json!(children)); + } + + // Provenance (debug builds only), ordered before the accessibility section. + if let Some(element_id) = provenance.element_id { + map.insert("element_id".into(), json!(element_id)); + } + if let Some(view) = provenance.view { + map.insert("view".into(), json!(view)); + } + if let Some(source_location) = &provenance.source_location { + map.insert("source_location".into(), json!(source_location)); + } + if let Some(synthetic) = provenance.synthetic { + map.insert("synthetic".into(), json!(synthetic)); + } + + // Accessibility semantics for this node, grouped together. + let mut aria = serde_json::Map::new(); + aria.insert("role".into(), json!(format!("{:?}", node.role()))); + + // Which action types the node supports. AccessKit keeps these in a private + // bitset with no getter or iterator, so we probe each variant. `Action::n` + // (from AccessKit's `enumn` feature) maps a discriminant to its variant, + // returning `None` past the last one - so this can't drift out of sync with + // AccessKit's `Action` enum the way a hand-maintained list would. + let mut next_action = 0u8; + let on_action: Vec = std::iter::from_fn(move || { + let action = Action::n(next_action)?; + next_action += 1; + Some(action) + }) + .filter(|action| node.supports_action(*action)) + .map(|action| format!("{action:?}")) + .collect(); + if !on_action.is_empty() { + aria.insert("on_action".into(), json!(on_action)); + } + + // String properties. + if let Some(v) = node.label() { + aria.insert("label".into(), json!(v)); + } + if let Some(v) = node.description() { + aria.insert("description".into(), json!(v)); + } + if let Some(v) = node.value() { + aria.insert("value".into(), json!(v)); + } + if let Some(v) = node.keyboard_shortcut() { + aria.insert("keyboard_shortcut".into(), json!(v)); + } + if let Some(v) = node.access_key() { + aria.insert("access_key".into(), json!(v)); + } + if let Some(v) = node.placeholder() { + aria.insert("placeholder".into(), json!(v)); + } + if let Some(v) = node.tooltip() { + aria.insert("tooltip".into(), json!(v)); + } + if let Some(v) = node.role_description() { + aria.insert("role_description".into(), json!(v)); + } + + // Boolean / enum states. + if let Some(v) = node.is_selected() { + aria.insert("selected".into(), json!(v)); + } + if let Some(v) = node.is_expanded() { + aria.insert("expanded".into(), json!(v)); + } + if let Some(v) = node.toggled() { + aria.insert("toggled".into(), json!(format!("{v:?}"))); + } + if let Some(v) = node.orientation() { + aria.insert("orientation".into(), json!(format!("{v:?}"))); + } + + // Numeric properties. + if let Some(v) = node.numeric_value() { + aria.insert("numeric_value".into(), json!(v)); + } + if let Some(v) = node.min_numeric_value() { + aria.insert("min_numeric_value".into(), json!(v)); + } + if let Some(v) = node.max_numeric_value() { + aria.insert("max_numeric_value".into(), json!(v)); + } + if let Some(v) = node.numeric_value_step() { + aria.insert("numeric_value_step".into(), json!(v)); + } + + // Set / table properties. + if let Some(v) = node.level() { + aria.insert("level".into(), json!(v)); + } + if let Some(v) = node.position_in_set() { + aria.insert("position_in_set".into(), json!(v)); + } + if let Some(v) = node.size_of_set() { + aria.insert("size_of_set".into(), json!(v)); + } + if let Some(v) = node.row_index() { + aria.insert("row_index".into(), json!(v)); + } + if let Some(v) = node.column_index() { + aria.insert("column_index".into(), json!(v)); + } + if let Some(v) = node.row_count() { + aria.insert("row_count".into(), json!(v)); + } + if let Some(v) = node.column_count() { + aria.insert("column_count".into(), json!(v)); + } + + map.insert("aria".into(), serde_json::Value::Object(aria)); + + serde_json::Value::Object(map) +} + +/// Maps a 0-based index to a short id in the sequence `a, b, ..., z, aa, ab, +/// ...` (bijective base-26). +fn ephemeral_id(mut index: usize) -> String { + let mut bytes = Vec::new(); + loop { + bytes.push(b'a' + (index % 26) as u8); + if index < 26 { + break; + } + index = index / 26 - 1; + } + bytes.reverse(); + String::from_utf8(bytes).unwrap_or_default() +} diff --git a/vendor/gpui-pre/src/window/prompts.rs b/vendor/gpui-pre/src/window/prompts.rs new file mode 100644 index 00000000..980c6f68 --- /dev/null +++ b/vendor/gpui-pre/src/window/prompts.rs @@ -0,0 +1,232 @@ +use std::ops::Deref; + +use futures::channel::oneshot; + +use crate::{ + AnyView, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable, + InteractiveElement, IntoElement, ParentElement, PromptButton, PromptLevel, Render, + StatefulInteractiveElement, Styled, div, opaque_grey, white, +}; + +use super::Window; + +/// The event emitted when a prompt's option is selected. +/// The usize is the index of the selected option, from the actions +/// passed to the prompt. +pub struct PromptResponse(pub usize); + +/// A prompt that can be rendered in the window. +pub trait Prompt: EventEmitter + Focusable {} + +impl + Focusable> Prompt for V {} + +/// A handle to a prompt that can be used to interact with it. +pub struct PromptHandle { + sender: oneshot::Sender, +} + +impl PromptHandle { + pub(crate) fn new(sender: oneshot::Sender) -> Self { + Self { sender } + } + + /// Construct a new prompt handle from a view of the appropriate types + pub fn with_view( + self, + view: Entity, + window: &mut Window, + cx: &mut App, + ) -> RenderablePromptHandle { + let mut sender = Some(self.sender); + let previous_focus = window.focused(cx); + let window_handle = window.window_handle(); + cx.subscribe(&view, move |_: Entity, e: &PromptResponse, cx| { + if let Some(sender) = sender.take() { + sender.send(e.0).ok(); + window_handle + .update(cx, |_, window, cx| { + window.prompt.take(); + if let Some(previous_focus) = &previous_focus { + window.focus(previous_focus, cx); + } + }) + .ok(); + } + }) + .detach(); + + window.focus(&view.focus_handle(cx), cx); + + RenderablePromptHandle { + view: Box::new(view), + } + } +} + +/// A prompt handle capable of being rendered in a window. +pub struct RenderablePromptHandle { + pub(crate) view: Box, +} + +/// Use this function in conjunction with [App::set_prompt_builder] to force +/// GPUI to always use the fallback prompt renderer. +pub fn fallback_prompt_renderer( + level: PromptLevel, + message: &str, + detail: Option<&str>, + actions: &[PromptButton], + handle: PromptHandle, + window: &mut Window, + cx: &mut App, +) -> RenderablePromptHandle { + let renderer = cx.new(|cx| FallbackPromptRenderer { + _level: level, + message: message.to_string(), + detail: detail.map(ToString::to_string), + actions: actions.to_vec(), + focus: cx.focus_handle(), + }); + + handle.with_view(renderer, window, cx) +} + +/// The default GPUI fallback for rendering prompts, when the platform doesn't support it. +pub struct FallbackPromptRenderer { + _level: PromptLevel, + message: String, + detail: Option, + actions: Vec, + focus: FocusHandle, +} + +impl Render for FallbackPromptRenderer { + fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + let prompt = div() + .cursor_default() + .track_focus(&self.focus) + .w_72() + .bg(white()) + .rounded_lg() + .overflow_hidden() + .p_3() + .child( + div() + .w_full() + .flex() + .flex_row() + .justify_around() + .child(div().overflow_hidden().child(self.message.clone())), + ) + .children(self.detail.clone().map(|detail| { + div() + .w_full() + .flex() + .flex_row() + .justify_around() + .text_sm() + .mb_2() + .child(div().child(detail)) + })) + .children(self.actions.iter().enumerate().map(|(ix, action)| { + div() + .flex() + .flex_row() + .justify_around() + .border_1() + .border_color(opaque_grey(0.2, 0.5)) + .mt_1() + .rounded_xs() + .cursor_pointer() + .text_sm() + .child(action.label().clone()) + .id(ix) + .on_click(cx.listener(move |_, _, _, cx| { + cx.emit(PromptResponse(ix)); + cx.stop_propagation(); + })) + })); + + div() + .size_full() + .child( + div() + .size_full() + .bg(opaque_grey(0.5, 0.6)) + .absolute() + .top_0() + .left_0(), + ) + .child( + div() + .size_full() + .absolute() + .top_0() + .left_0() + .flex() + .flex_col() + .justify_around() + .child( + div() + .w_full() + .flex() + .flex_row() + .justify_around() + .child(prompt), + ), + ) + } +} + +impl EventEmitter for FallbackPromptRenderer {} + +impl Focusable for FallbackPromptRenderer { + fn focus_handle(&self, _: &crate::App) -> FocusHandle { + self.focus.clone() + } +} + +pub(crate) trait PromptViewHandle { + fn any_view(&self) -> AnyView; +} + +impl PromptViewHandle for Entity { + fn any_view(&self) -> AnyView { + self.clone().into() + } +} + +pub(crate) enum PromptBuilder { + Default, + Custom( + Box< + dyn Fn( + PromptLevel, + &str, + Option<&str>, + &[PromptButton], + PromptHandle, + &mut Window, + &mut App, + ) -> RenderablePromptHandle, + >, + ), +} + +impl Deref for PromptBuilder { + type Target = dyn Fn( + PromptLevel, + &str, + Option<&str>, + &[PromptButton], + PromptHandle, + &mut Window, + &mut App, + ) -> RenderablePromptHandle; + + fn deref(&self) -> &Self::Target { + match self { + Self::Default => &fallback_prompt_renderer, + Self::Custom(f) => f.as_ref(), + } + } +} From 217debb9d9736a143b38b05ab961f873ab16d7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Tue, 3 Nov 2026 17:48:49 +0800 Subject: [PATCH 3/6] A font picker offers monospaced families alone Settings gains Monospaced only, on by default: a terminal's font is monospaced, and the picker offered all 146 families the system names, of which 42 are. vendor/ely is Ely's sources with one addition: FontPicker::monospace(bool), which filters inside the keyed state the picker already caches, so the list is walked once per switch rather than once per frame. The upstream fix is a one-line PR to Ely; it is vendored here only so this branch runs as it stands. --- vendor/ely/Cargo.toml | 134 +++++ vendor/ely/LICENSE | 21 + vendor/ely/assets/fonts/Inter-Italic.ttf | Bin 0 -> 417388 bytes vendor/ely/assets/fonts/Inter-LICENSE.txt | 92 ++++ vendor/ely/assets/fonts/Inter-Medium.ttf | Bin 0 -> 417300 bytes vendor/ely/assets/fonts/Inter-Regular.ttf | Bin 0 -> 411640 bytes vendor/ely/assets/fonts/Inter-SemiBold.ttf | Bin 0 -> 419744 bytes .../assets/fonts/JetBrainsMono-LICENSE.txt | 93 ++++ .../ely/assets/fonts/JetBrainsMono-Medium.ttf | Bin 0 -> 273860 bytes .../assets/fonts/JetBrainsMono-Regular.ttf | Bin 0 -> 273900 bytes .../ibm-plex-sans/IBMPlexSans-LICENSE.txt | 92 ++++ .../ibm-plex-sans/IBMPlexSans-Regular.ttf | Bin 0 -> 200500 bytes vendor/ely/assets/icons/LICENSE | 43 ++ vendor/ely/assets/icons/a-arrow-down.svg | 18 + vendor/ely/assets/icons/a-arrow-up.svg | 18 + vendor/ely/assets/icons/accessibility.svg | 19 + vendor/ely/assets/icons/activity.svg | 15 + vendor/ely/assets/icons/alarm-clock.svg | 20 + .../assets/icons/align-center-horizontal.svg | 19 + .../assets/icons/align-center-vertical.svg | 19 + vendor/ely/assets/icons/align-center.svg | 17 + .../ely/assets/icons/align-end-horizontal.svg | 17 + .../ely/assets/icons/align-end-vertical.svg | 17 + .../align-horizontal-distribute-center.svg | 20 + vendor/ely/assets/icons/align-justify.svg | 17 + vendor/ely/assets/icons/align-left.svg | 17 + vendor/ely/assets/icons/align-right.svg | 17 + .../assets/icons/align-start-horizontal.svg | 17 + .../ely/assets/icons/align-start-vertical.svg | 17 + .../align-vertical-distribute-center.svg | 20 + vendor/ely/assets/icons/app-window.svg | 18 + vendor/ely/assets/icons/archive.svg | 17 + vendor/ely/assets/icons/arrow-down-left.svg | 16 + vendor/ely/assets/icons/arrow-down-to-dot.svg | 17 + .../ely/assets/icons/arrow-down-to-line.svg | 17 + vendor/ely/assets/icons/arrow-down-up.svg | 18 + .../assets/icons/arrow-down-wide-narrow.svg | 19 + vendor/ely/assets/icons/arrow-down.svg | 16 + vendor/ely/assets/icons/arrow-left.svg | 16 + vendor/ely/assets/icons/arrow-right.svg | 16 + vendor/ely/assets/icons/arrow-up-from-dot.svg | 17 + .../ely/assets/icons/arrow-up-narrow-wide.svg | 19 + vendor/ely/assets/icons/arrow-up-right.svg | 16 + vendor/ely/assets/icons/arrow-up.svg | 16 + vendor/ely/assets/icons/at-sign.svg | 16 + vendor/ely/assets/icons/audio-lines.svg | 20 + vendor/ely/assets/icons/ban.svg | 16 + vendor/ely/assets/icons/battery.svg | 16 + vendor/ely/assets/icons/bell.svg | 16 + vendor/ely/assets/icons/bold.svg | 15 + vendor/ely/assets/icons/book-open.svg | 16 + vendor/ely/assets/icons/bookmark.svg | 15 + vendor/ely/assets/icons/bot.svg | 20 + vendor/ely/assets/icons/box.svg | 17 + vendor/ely/assets/icons/braces.svg | 16 + vendor/ely/assets/icons/brush.svg | 17 + vendor/ely/assets/icons/bug.svg | 25 + vendor/ely/assets/icons/calendar-days.svg | 24 + vendor/ely/assets/icons/calendar-range.svg | 22 + vendor/ely/assets/icons/calendar.svg | 18 + vendor/ely/assets/icons/camera.svg | 16 + vendor/ely/assets/icons/captions-off.svg | 20 + vendor/ely/assets/icons/captions.svg | 16 + vendor/ely/assets/icons/case-sensitive.svg | 18 + vendor/ely/assets/icons/chart-area.svg | 16 + vendor/ely/assets/icons/chart-bar.svg | 18 + vendor/ely/assets/icons/chart-candlestick.svg | 21 + vendor/ely/assets/icons/chart-column.svg | 18 + vendor/ely/assets/icons/chart-gantt.svg | 18 + vendor/ely/assets/icons/chart-line.svg | 16 + vendor/ely/assets/icons/chart-pie.svg | 16 + vendor/ely/assets/icons/check-check.svg | 16 + vendor/ely/assets/icons/check.svg | 15 + vendor/ely/assets/icons/chevron-down.svg | 15 + vendor/ely/assets/icons/chevron-left.svg | 15 + vendor/ely/assets/icons/chevron-right.svg | 15 + vendor/ely/assets/icons/chevron-up.svg | 15 + .../ely/assets/icons/chevrons-left-right.svg | 16 + vendor/ely/assets/icons/chevrons-left.svg | 16 + vendor/ely/assets/icons/chevrons-right.svg | 16 + vendor/ely/assets/icons/chevrons-up-down.svg | 16 + vendor/ely/assets/icons/circle-alert.svg | 17 + vendor/ely/assets/icons/circle-check.svg | 16 + vendor/ely/assets/icons/circle-dashed.svg | 22 + vendor/ely/assets/icons/circle-dot-dashed.svg | 23 + vendor/ely/assets/icons/circle-dot.svg | 16 + vendor/ely/assets/icons/circle-help.svg | 17 + vendor/ely/assets/icons/circle-pause.svg | 17 + vendor/ely/assets/icons/circle-stop.svg | 16 + vendor/ely/assets/icons/circle-x.svg | 17 + vendor/ely/assets/icons/circle.svg | 15 + vendor/ely/assets/icons/clipboard-check.svg | 17 + vendor/ely/assets/icons/clipboard.svg | 16 + vendor/ely/assets/icons/clock.svg | 16 + vendor/ely/assets/icons/cloud-alert.svg | 17 + vendor/ely/assets/icons/cloud-check.svg | 16 + vendor/ely/assets/icons/cloud-off.svg | 17 + vendor/ely/assets/icons/cloud-upload.svg | 17 + vendor/ely/assets/icons/cloud.svg | 15 + vendor/ely/assets/icons/code.svg | 16 + vendor/ely/assets/icons/columns-2.svg | 16 + vendor/ely/assets/icons/columns-3.svg | 17 + vendor/ely/assets/icons/command.svg | 15 + vendor/ely/assets/icons/compass.svg | 16 + vendor/ely/assets/icons/contrast.svg | 16 + vendor/ely/assets/icons/copy.svg | 16 + vendor/ely/assets/icons/corner-down-right.svg | 16 + vendor/ely/assets/icons/cpu.svg | 28 + vendor/ely/assets/icons/credit-card.svg | 17 + vendor/ely/assets/icons/crop.svg | 16 + vendor/ely/assets/icons/crosshair.svg | 19 + vendor/ely/assets/icons/database.svg | 17 + vendor/ely/assets/icons/delete.svg | 17 + vendor/ely/assets/icons/dices.svg | 20 + vendor/ely/assets/icons/dollar-sign.svg | 16 + vendor/ely/assets/icons/dot.svg | 15 + vendor/ely/assets/icons/download.svg | 17 + vendor/ely/assets/icons/ellipsis-vertical.svg | 17 + vendor/ely/assets/icons/ellipsis.svg | 17 + vendor/ely/assets/icons/eraser.svg | 16 + vendor/ely/assets/icons/external-link.svg | 17 + vendor/ely/assets/icons/eye-off.svg | 18 + vendor/ely/assets/icons/eye.svg | 16 + vendor/ely/assets/icons/file-archive.svg | 20 + vendor/ely/assets/icons/file-audio.svg | 17 + vendor/ely/assets/icons/file-code.svg | 18 + vendor/ely/assets/icons/file-cog.svg | 26 + vendor/ely/assets/icons/file-image.svg | 18 + vendor/ely/assets/icons/file-json.svg | 18 + vendor/ely/assets/icons/file-plus.svg | 18 + vendor/ely/assets/icons/file-spreadsheet.svg | 20 + vendor/ely/assets/icons/file-terminal.svg | 18 + vendor/ely/assets/icons/file-text.svg | 19 + vendor/ely/assets/icons/file-type.svg | 19 + vendor/ely/assets/icons/file-video-camera.svg | 18 + vendor/ely/assets/icons/file.svg | 16 + vendor/ely/assets/icons/filter.svg | 15 + vendor/ely/assets/icons/fingerprint.svg | 23 + vendor/ely/assets/icons/flag.svg | 15 + vendor/ely/assets/icons/folder-open.svg | 15 + vendor/ely/assets/icons/folder-plus.svg | 17 + vendor/ely/assets/icons/folder.svg | 15 + vendor/ely/assets/icons/forward.svg | 16 + vendor/ely/assets/icons/frame.svg | 18 + vendor/ely/assets/icons/frown.svg | 18 + vendor/ely/assets/icons/fullscreen.svg | 19 + vendor/ely/assets/icons/gauge.svg | 16 + vendor/ely/assets/icons/git-branch.svg | 17 + .../assets/icons/git-commit-horizontal.svg | 17 + vendor/ely/assets/icons/git-merge.svg | 17 + .../assets/icons/git-pull-request-closed.svg | 20 + .../assets/icons/git-pull-request-draft.svg | 19 + vendor/ely/assets/icons/git-pull-request.svg | 18 + vendor/ely/assets/icons/globe.svg | 17 + vendor/ely/assets/icons/grip-horizontal.svg | 20 + vendor/ely/assets/icons/grip-vertical.svg | 20 + vendor/ely/assets/icons/hand.svg | 18 + vendor/ely/assets/icons/hard-drive.svg | 18 + vendor/ely/assets/icons/hash.svg | 18 + vendor/ely/assets/icons/heading-1.svg | 18 + vendor/ely/assets/icons/heading-2.svg | 18 + vendor/ely/assets/icons/heading-3.svg | 19 + vendor/ely/assets/icons/heading.svg | 17 + vendor/ely/assets/icons/headphones.svg | 15 + vendor/ely/assets/icons/heart.svg | 15 + vendor/ely/assets/icons/hexagon.svg | 15 + vendor/ely/assets/icons/history.svg | 17 + vendor/ely/assets/icons/hourglass.svg | 18 + vendor/ely/assets/icons/house.svg | 16 + vendor/ely/assets/icons/image-off.svg | 20 + vendor/ely/assets/icons/image.svg | 17 + vendor/ely/assets/icons/inbox.svg | 16 + vendor/ely/assets/icons/info.svg | 17 + vendor/ely/assets/icons/italic.svg | 17 + vendor/ely/assets/icons/kanban.svg | 17 + vendor/ely/assets/icons/key.svg | 17 + vendor/ely/assets/icons/keyboard.svg | 23 + vendor/ely/assets/icons/languages.svg | 20 + vendor/ely/assets/icons/laugh.svg | 18 + vendor/ely/assets/icons/layers.svg | 17 + vendor/ely/assets/icons/layout-dashboard.svg | 18 + vendor/ely/assets/icons/layout-grid.svg | 18 + vendor/ely/assets/icons/library.svg | 18 + vendor/ely/assets/icons/lightbulb.svg | 17 + vendor/ely/assets/icons/link.svg | 16 + vendor/ely/assets/icons/list-checks.svg | 19 + vendor/ely/assets/icons/list-ordered.svg | 20 + vendor/ely/assets/icons/list-todo.svg | 19 + vendor/ely/assets/icons/list.svg | 20 + vendor/ely/assets/icons/loader-circle.svg | 15 + vendor/ely/assets/icons/lock-open.svg | 16 + vendor/ely/assets/icons/lock.svg | 16 + vendor/ely/assets/icons/log-in.svg | 17 + vendor/ely/assets/icons/log-out.svg | 17 + vendor/ely/assets/icons/mail.svg | 16 + vendor/ely/assets/icons/map-pin.svg | 16 + vendor/ely/assets/icons/map.svg | 17 + vendor/ely/assets/icons/maximize-2.svg | 18 + vendor/ely/assets/icons/meh.svg | 18 + vendor/ely/assets/icons/memory-stick.svg | 25 + vendor/ely/assets/icons/menu.svg | 17 + vendor/ely/assets/icons/merge.svg | 17 + .../ely/assets/icons/message-square-diff.svg | 18 + .../assets/icons/message-square-warning.svg | 17 + vendor/ely/assets/icons/message-square.svg | 15 + vendor/ely/assets/icons/mic-off.svg | 20 + vendor/ely/assets/icons/mic.svg | 17 + vendor/ely/assets/icons/minimize-2.svg | 18 + vendor/ely/assets/icons/minus.svg | 15 + vendor/ely/assets/icons/monitor.svg | 17 + vendor/ely/assets/icons/moon.svg | 15 + vendor/ely/assets/icons/mouse-pointer-2.svg | 15 + vendor/ely/assets/icons/move-up-right.svg | 16 + vendor/ely/assets/icons/move.svg | 20 + vendor/ely/assets/icons/music.svg | 17 + vendor/ely/assets/icons/network.svg | 19 + vendor/ely/assets/icons/notebook-pen.svg | 20 + vendor/ely/assets/icons/octagon-alert.svg | 17 + vendor/ely/assets/icons/package.svg | 18 + vendor/ely/assets/icons/palette.svg | 19 + vendor/ely/assets/icons/panel-bottom.svg | 16 + vendor/ely/assets/icons/panel-left.svg | 16 + vendor/ely/assets/icons/panel-right.svg | 16 + vendor/ely/assets/icons/paperclip.svg | 15 + vendor/ely/assets/icons/pause.svg | 16 + vendor/ely/assets/icons/pen-line.svg | 16 + vendor/ely/assets/icons/pen-tool.svg | 18 + vendor/ely/assets/icons/pencil.svg | 16 + vendor/ely/assets/icons/phone-off.svg | 17 + vendor/ely/assets/icons/phone.svg | 15 + .../ely/assets/icons/picture-in-picture-2.svg | 16 + vendor/ely/assets/icons/pin-off.svg | 18 + vendor/ely/assets/icons/pin.svg | 16 + vendor/ely/assets/icons/pipette.svg | 17 + vendor/ely/assets/icons/play.svg | 15 + vendor/ely/assets/icons/plus.svg | 16 + vendor/ely/assets/icons/power.svg | 16 + vendor/ely/assets/icons/printer.svg | 17 + vendor/ely/assets/icons/puzzle.svg | 15 + vendor/ely/assets/icons/quote.svg | 16 + vendor/ely/assets/icons/redo-2.svg | 16 + vendor/ely/assets/icons/redo-dot.svg | 17 + vendor/ely/assets/icons/refresh-cw.svg | 18 + vendor/ely/assets/icons/regex.svg | 18 + vendor/ely/assets/icons/repeat-1.svg | 19 + vendor/ely/assets/icons/repeat.svg | 18 + vendor/ely/assets/icons/reply-all.svg | 17 + vendor/ely/assets/icons/reply.svg | 16 + vendor/ely/assets/icons/rocket.svg | 18 + vendor/ely/assets/icons/rotate-ccw.svg | 16 + vendor/ely/assets/icons/rotate-cw.svg | 16 + vendor/ely/assets/icons/rows-2.svg | 16 + vendor/ely/assets/icons/save.svg | 17 + vendor/ely/assets/icons/scissors.svg | 19 + vendor/ely/assets/icons/screen-share-off.svg | 19 + vendor/ely/assets/icons/screen-share.svg | 19 + vendor/ely/assets/icons/search-x.svg | 18 + vendor/ely/assets/icons/search.svg | 16 + vendor/ely/assets/icons/send.svg | 16 + vendor/ely/assets/icons/server.svg | 18 + vendor/ely/assets/icons/settings.svg | 16 + vendor/ely/assets/icons/shapes.svg | 17 + vendor/ely/assets/icons/share-2.svg | 19 + vendor/ely/assets/icons/shield.svg | 15 + vendor/ely/assets/icons/shuffle.svg | 19 + vendor/ely/assets/icons/skip-back.svg | 16 + vendor/ely/assets/icons/skip-forward.svg | 16 + vendor/ely/assets/icons/slash.svg | 15 + .../ely/assets/icons/sliders-horizontal.svg | 23 + vendor/ely/assets/icons/smartphone.svg | 16 + vendor/ely/assets/icons/smile-plus.svg | 20 + vendor/ely/assets/icons/smile.svg | 18 + vendor/ely/assets/icons/sparkles.svg | 18 + vendor/ely/assets/icons/spline.svg | 17 + vendor/ely/assets/icons/square-check.svg | 16 + vendor/ely/assets/icons/square-function.svg | 17 + vendor/ely/assets/icons/square-pen.svg | 16 + .../ely/assets/icons/square-round-corner.svg | 16 + vendor/ely/assets/icons/square.svg | 15 + vendor/ely/assets/icons/star.svg | 15 + vendor/ely/assets/icons/step-forward.svg | 16 + vendor/ely/assets/icons/sticky-note.svg | 16 + vendor/ely/assets/icons/strikethrough.svg | 17 + vendor/ely/assets/icons/sun.svg | 23 + vendor/ely/assets/icons/table.svg | 18 + vendor/ely/assets/icons/tag.svg | 16 + vendor/ely/assets/icons/target.svg | 17 + vendor/ely/assets/icons/terminal.svg | 16 + vendor/ely/assets/icons/thumbs-down.svg | 16 + vendor/ely/assets/icons/thumbs-up.svg | 16 + vendor/ely/assets/icons/timer.svg | 17 + vendor/ely/assets/icons/trash-2.svg | 19 + vendor/ely/assets/icons/trending-down.svg | 16 + vendor/ely/assets/icons/trending-up.svg | 16 + vendor/ely/assets/icons/triangle-alert.svg | 17 + vendor/ely/assets/icons/type.svg | 17 + vendor/ely/assets/icons/underline.svg | 16 + vendor/ely/assets/icons/undo-2.svg | 16 + vendor/ely/assets/icons/upload.svg | 17 + vendor/ely/assets/icons/user-plus.svg | 18 + vendor/ely/assets/icons/user.svg | 16 + vendor/ely/assets/icons/users.svg | 18 + vendor/ely/assets/icons/variable.svg | 18 + vendor/ely/assets/icons/video-off.svg | 17 + vendor/ely/assets/icons/video.svg | 16 + vendor/ely/assets/icons/volume-1.svg | 16 + vendor/ely/assets/icons/volume-2.svg | 17 + vendor/ely/assets/icons/volume-x.svg | 17 + vendor/ely/assets/icons/volume.svg | 15 + vendor/ely/assets/icons/wallet.svg | 16 + vendor/ely/assets/icons/wand-sparkles.svg | 22 + vendor/ely/assets/icons/whole-word.svg | 19 + vendor/ely/assets/icons/wifi-off.svg | 21 + vendor/ely/assets/icons/wifi.svg | 18 + vendor/ely/assets/icons/workflow.svg | 17 + vendor/ely/assets/icons/wrench.svg | 15 + vendor/ely/assets/icons/x.svg | 16 + vendor/ely/assets/icons/zap.svg | 15 + vendor/ely/assets/icons/zoom-in.svg | 18 + vendor/ely/assets/icons/zoom-out.svg | 17 + vendor/ely/assets/maps/countries.geojson | 1 + vendor/ely/src/account/billing.rs | 425 +++++++++++++++ vendor/ely/src/account/factor.rs | 116 ++++ vendor/ely/src/account/keys.rs | 209 ++++++++ vendor/ely/src/account/login.rs | 193 +++++++ vendor/ely/src/account/mail.rs | 277 ++++++++++ vendor/ely/src/account/mod.rs | 33 ++ vendor/ely/src/account/oauth.rs | 80 +++ vendor/ely/src/account/payment.rs | 344 ++++++++++++ vendor/ely/src/account/profile.rs | 357 +++++++++++++ vendor/ely/src/account/sessions.rs | 145 +++++ vendor/ely/src/account/signup.rs | 207 ++++++++ vendor/ely/src/account/switcher.rs | 357 +++++++++++++ vendor/ely/src/account/team.rs | 411 ++++++++++++++ vendor/ely/src/account/tests/access.rs | 259 +++++++++ vendor/ely/src/account/tests/billing.rs | 488 +++++++++++++++++ vendor/ely/src/account/tests/mod.rs | 87 +++ vendor/ely/src/account/tests/sign_in.rs | 270 ++++++++++ vendor/ely/src/account/upgrade.rs | 140 +++++ vendor/ely/src/agent/artifact.rs | 202 +++++++ vendor/ely/src/agent/changes.rs | 319 +++++++++++ vendor/ely/src/agent/control.rs | 201 +++++++ vendor/ely/src/agent/environment.rs | 293 ++++++++++ vendor/ely/src/agent/line.rs | 58 ++ vendor/ely/src/agent/memory.rs | 250 +++++++++ vendor/ely/src/agent/mod.rs | 24 + vendor/ely/src/agent/permission.rs | 208 ++++++++ vendor/ely/src/agent/previews.rs | 415 +++++++++++++++ vendor/ely/src/agent/progress.rs | 325 ++++++++++++ vendor/ely/src/agent/registry.rs | 230 ++++++++ vendor/ely/src/agent/tests/changes.rs | 199 +++++++ vendor/ely/src/agent/tests/control.rs | 105 ++++ vendor/ely/src/agent/tests/environment.rs | 195 +++++++ vendor/ely/src/agent/tests/mod.rs | 162 ++++++ vendor/ely/src/agent/tests/previews.rs | 332 ++++++++++++ vendor/ely/src/agent/tools.rs | 240 +++++++++ vendor/ely/src/assets.rs | 138 +++++ vendor/ely/src/buttons/bars.rs | 161 ++++++ vendor/ely/src/buttons/button.rs | 329 ++++++++++++ vendor/ely/src/buttons/confirm.rs | 289 ++++++++++ vendor/ely/src/buttons/copy.rs | 97 ++++ vendor/ely/src/buttons/fab.rs | 100 ++++ vendor/ely/src/buttons/group.rs | 340 ++++++++++++ vendor/ely/src/buttons/icon_button.rs | 110 ++++ vendor/ely/src/buttons/mod.rs | 30 ++ vendor/ely/src/buttons/presets.rs | 19 + vendor/ely/src/buttons/quick.rs | 203 +++++++ vendor/ely/src/buttons/segmented.rs | 280 ++++++++++ vendor/ely/src/buttons/share.rs | 166 ++++++ vendor/ely/src/buttons/sheet.rs | 202 +++++++ vendor/ely/src/buttons/tests.rs | 172 ++++++ vendor/ely/src/calendar/agenda.rs | 223 ++++++++ vendor/ely/src/calendar/allday.rs | 150 ++++++ vendor/ely/src/calendar/availability.rs | 270 ++++++++++ vendor/ely/src/calendar/card.rs | 119 +++++ vendor/ely/src/calendar/chip.rs | 145 +++++ vendor/ely/src/calendar/days.rs | 294 ++++++++++ vendor/ely/src/calendar/editor.rs | 473 +++++++++++++++++ vendor/ely/src/calendar/event.rs | 168 ++++++ vendor/ely/src/calendar/grid.rs | 451 ++++++++++++++++ vendor/ely/src/calendar/head.rs | 66 +++ vendor/ely/src/calendar/hours.rs | 204 +++++++ vendor/ely/src/calendar/mod.rs | 59 +++ vendor/ely/src/calendar/month.rs | 451 ++++++++++++++++ vendor/ely/src/calendar/now.rs | 78 +++ vendor/ely/src/calendar/people.rs | 217 ++++++++ vendor/ely/src/calendar/popover.rs | 186 +++++++ vendor/ely/src/calendar/recurrence.rs | 289 ++++++++++ vendor/ely/src/calendar/reminders.rs | 170 ++++++ vendor/ely/src/calendar/repeat.rs | 334 ++++++++++++ vendor/ely/src/calendar/tests/editing.rs | 244 +++++++++ vendor/ely/src/calendar/tests/mod.rs | 290 ++++++++++ vendor/ely/src/calendar/tests/people.rs | 114 ++++ vendor/ely/src/calendar/tests/times.rs | 317 +++++++++++ vendor/ely/src/calendar/weeks.rs | 215 ++++++++ vendor/ely/src/calendar/year.rs | 361 +++++++++++++ vendor/ely/src/canvas/align.rs | 222 ++++++++ vendor/ely/src/canvas/assets.rs | 136 +++++ vendor/ely/src/canvas/autolayout.rs | 312 +++++++++++ vendor/ely/src/canvas/constraints.rs | 264 +++++++++ vendor/ely/src/canvas/edit.rs | 342 ++++++++++++ vendor/ely/src/canvas/export.rs | 267 ++++++++++ vendor/ely/src/canvas/flow.rs | 114 ++++ vendor/ely/src/canvas/gesture.rs | 219 ++++++++ vendor/ely/src/canvas/graph.rs | 231 ++++++++ vendor/ely/src/canvas/history.rs | 86 +++ vendor/ely/src/canvas/inspector.rs | 143 +++++ vendor/ely/src/canvas/layers.rs | 183 +++++++ vendor/ely/src/canvas/links.rs | 113 ++++ vendor/ely/src/canvas/marks.rs | 136 +++++ vendor/ely/src/canvas/mindmap.rs | 252 +++++++++ vendor/ely/src/canvas/mindmap_view.rs | 329 ++++++++++++ vendor/ely/src/canvas/minimap.rs | 181 +++++++ vendor/ely/src/canvas/mod.rs | 65 +++ vendor/ely/src/canvas/nodes.rs | 445 ++++++++++++++++ vendor/ely/src/canvas/paint.rs | 145 +++++ vendor/ely/src/canvas/palette.rs | 183 +++++++ vendor/ely/src/canvas/panel.rs | 92 ++++ vendor/ely/src/canvas/plane.rs | 437 +++++++++++++++ vendor/ely/src/canvas/press.rs | 151 ++++++ vendor/ely/src/canvas/shape.rs | 218 ++++++++ vendor/ely/src/canvas/style.rs | 367 +++++++++++++ vendor/ely/src/canvas/tests/boards.rs | 378 +++++++++++++ vendor/ely/src/canvas/tests/mod.rs | 228 ++++++++ vendor/ely/src/canvas/tests/panels.rs | 138 +++++ vendor/ely/src/canvas/tests/stale.rs | 43 ++ vendor/ely/src/canvas/tests/tools.rs | 212 ++++++++ vendor/ely/src/canvas/tools.rs | 470 ++++++++++++++++ vendor/ely/src/canvas/typography.rs | 184 +++++++ vendor/ely/src/canvas/view.rs | 174 ++++++ vendor/ely/src/canvas/whiteboard.rs | 321 +++++++++++ vendor/ely/src/canvas/wiring.rs | 115 ++++ vendor/ely/src/canvas/writing.rs | 68 +++ vendor/ely/src/canvas/zoom.rs | 159 ++++++ vendor/ely/src/charts/axes.rs | 209 ++++++++ vendor/ely/src/charts/burndown.rs | 272 ++++++++++ vendor/ely/src/charts/calendar.rs | 203 +++++++ vendor/ely/src/charts/cartesian.rs | 419 +++++++++++++++ vendor/ely/src/charts/distribution.rs | 419 +++++++++++++++ vendor/ely/src/charts/export.rs | 230 ++++++++ vendor/ely/src/charts/flow.rs | 464 ++++++++++++++++ vendor/ely/src/charts/funnel.rs | 269 ++++++++++ vendor/ely/src/charts/geometry.rs | 441 +++++++++++++++ vendor/ely/src/charts/glide.rs | 95 ++++ vendor/ely/src/charts/layout.rs | 135 +++++ vendor/ely/src/charts/mod.rs | 58 ++ vendor/ely/src/charts/network.rs | 411 ++++++++++++++ vendor/ely/src/charts/paint.rs | 232 ++++++++ vendor/ely/src/charts/parallel.rs | 302 +++++++++++ vendor/ely/src/charts/parts.rs | 152 ++++++ vendor/ely/src/charts/pie.rs | 400 ++++++++++++++ vendor/ely/src/charts/plot.rs | 246 +++++++++ vendor/ely/src/charts/pointer.rs | 325 ++++++++++++ vendor/ely/src/charts/radar.rs | 365 +++++++++++++ vendor/ely/src/charts/realtime.rs | 189 +++++++ vendor/ely/src/charts/relations.rs | 300 +++++++++++ vendor/ely/src/charts/scale.rs | 194 +++++++ vendor/ely/src/charts/schedule.rs | 415 +++++++++++++++ vendor/ely/src/charts/series.rs | 243 +++++++++ vendor/ely/src/charts/stats.rs | 227 ++++++++ vendor/ely/src/charts/sunburst.rs | 292 ++++++++++ vendor/ely/src/charts/targets.rs | 455 ++++++++++++++++ vendor/ely/src/charts/tests/limits.rs | 270 ++++++++++ vendor/ely/src/charts/tests/mod.rs | 410 ++++++++++++++ vendor/ely/src/charts/tiles.rs | 462 ++++++++++++++++ vendor/ely/src/chat/actions.rs | 394 ++++++++++++++ vendor/ely/src/chat/attach.rs | 201 +++++++ vendor/ely/src/chat/cite.rs | 283 ++++++++++ vendor/ely/src/chat/code.rs | 191 +++++++ vendor/ely/src/chat/composer.rs | 409 ++++++++++++++ vendor/ely/src/chat/conversations.rs | 423 +++++++++++++++ vendor/ely/src/chat/list.rs | 295 +++++++++++ vendor/ely/src/chat/media.rs | 404 ++++++++++++++ vendor/ely/src/chat/message.rs | 344 ++++++++++++ vendor/ely/src/chat/mod.rs | 47 ++ vendor/ely/src/chat/params.rs | 381 +++++++++++++ vendor/ely/src/chat/play.rs | 322 +++++++++++ vendor/ely/src/chat/projects.rs | 414 +++++++++++++++ vendor/ely/src/chat/search.rs | 336 ++++++++++++ vendor/ely/src/chat/status.rs | 421 +++++++++++++++ vendor/ely/src/chat/stream.rs | 235 ++++++++ vendor/ely/src/chat/tests/cite.rs | 137 +++++ vendor/ely/src/chat/tests/compose.rs | 273 ++++++++++ vendor/ely/src/chat/tests/history.rs | 98 ++++ vendor/ely/src/chat/tests/mod.rs | 447 ++++++++++++++++ vendor/ely/src/chat/tests/welcome.rs | 55 ++ vendor/ely/src/chat/voice.rs | 125 +++++ vendor/ely/src/chat/welcome.rs | 325 ++++++++++++ vendor/ely/src/collab/annotate.rs | 167 ++++++ vendor/ely/src/collab/comments.rs | 354 +++++++++++++ vendor/ely/src/collab/mod.rs | 19 + vendor/ely/src/collab/peers.rs | 340 ++++++++++++ vendor/ely/src/collab/reactions.rs | 224 ++++++++ vendor/ely/src/collab/remote.rs | 172 ++++++ vendor/ely/src/collab/share.rs | 500 ++++++++++++++++++ vendor/ely/src/collab/sidebar.rs | 216 ++++++++ vendor/ely/src/collab/tests.rs | 214 ++++++++ vendor/ely/src/collab/track.rs | 494 +++++++++++++++++ vendor/ely/src/dashboard/alerts.rs | 332 ++++++++++++ vendor/ely/src/dashboard/card.rs | 108 ++++ vendor/ely/src/dashboard/controls.rs | 282 ++++++++++ vendor/ely/src/dashboard/events.rs | 212 ++++++++ vendor/ely/src/dashboard/grid.rs | 409 ++++++++++++++ vendor/ely/src/dashboard/mod.rs | 20 + vendor/ely/src/dashboard/status.rs | 358 +++++++++++++ vendor/ely/src/dashboard/tests.rs | 336 ++++++++++++ vendor/ely/src/dashboard/tiles.rs | 189 +++++++ vendor/ely/src/data_display/avatar.rs | 335 ++++++++++++ vendor/ely/src/data_display/badge.rs | 364 +++++++++++++ vendor/ely/src/data_display/before_after.rs | 205 +++++++ vendor/ely/src/data_display/carousel.rs | 301 +++++++++++ vendor/ely/src/data_display/changelog.rs | 180 +++++++ vendor/ely/src/data_display/codes.rs | 296 +++++++++++ vendor/ely/src/data_display/comparison.rs | 176 ++++++ vendor/ely/src/data_display/feed.rs | 175 ++++++ vendor/ely/src/data_display/gallery.rs | 138 +++++ vendor/ely/src/data_display/measures.rs | 453 ++++++++++++++++ vendor/ely/src/data_display/mod.rs | 39 ++ vendor/ely/src/data_display/records.rs | 247 +++++++++ vendor/ely/src/data_display/spark.rs | 163 ++++++ vendor/ely/src/data_display/stars.rs | 126 +++++ vendor/ely/src/data_display/stat.rs | 248 +++++++++ vendor/ely/src/data_display/tests.rs | 350 ++++++++++++ vendor/ely/src/data_display/timeline.rs | 202 +++++++ vendor/ely/src/data_display/watermark.rs | 88 +++ vendor/ely/src/debug/disasm.rs | 303 +++++++++++ vendor/ely/src/debug/flame.rs | 400 ++++++++++++++ vendor/ely/src/debug/hex.rs | 235 ++++++++ vendor/ely/src/debug/mod.rs | 27 + vendor/ely/src/debug/network.rs | 265 ++++++++++ vendor/ely/src/debug/session.rs | 306 +++++++++++ vendor/ely/src/debug/stack.rs | 322 +++++++++++ vendor/ely/src/debug/tests.rs | 249 +++++++++ vendor/ely/src/debug/timeline.rs | 325 ++++++++++++ vendor/ely/src/debug/variables.rs | 344 ++++++++++++ vendor/ely/src/devtools/collection.rs | 272 ++++++++++ vendor/ely/src/devtools/connection_form.rs | 333 ++++++++++++ vendor/ely/src/devtools/connections.rs | 288 ++++++++++ vendor/ely/src/devtools/contrast.rs | 216 ++++++++ vendor/ely/src/devtools/datum.rs | 496 +++++++++++++++++ vendor/ely/src/devtools/document.rs | 227 ++++++++ vendor/ely/src/devtools/encode.rs | 321 +++++++++++ vendor/ely/src/devtools/environment.rs | 196 +++++++ vendor/ely/src/devtools/graphql.rs | 221 ++++++++ vendor/ely/src/devtools/json_editor.rs | 132 +++++ vendor/ely/src/devtools/machines.rs | 420 +++++++++++++++ vendor/ely/src/devtools/mod.rs | 46 ++ vendor/ely/src/devtools/monitor.rs | 136 +++++ vendor/ely/src/devtools/queries.rs | 252 +++++++++ vendor/ely/src/devtools/redis.rs | 268 ++++++++++ vendor/ely/src/devtools/regex.rs | 317 +++++++++++ vendor/ely/src/devtools/request.rs | 489 +++++++++++++++++ vendor/ely/src/devtools/response.rs | 197 +++++++ vendor/ely/src/devtools/schema.rs | 344 ++++++++++++ vendor/ely/src/devtools/socket.rs | 244 +++++++++ vendor/ely/src/devtools/structure.rs | 479 +++++++++++++++++ vendor/ely/src/devtools/tests/api.rs | 353 +++++++++++++ vendor/ely/src/devtools/tests/formats.rs | 83 +++ vendor/ely/src/devtools/tests/mod.rs | 253 +++++++++ vendor/ely/src/devtools/tests/tools.rs | 95 ++++ vendor/ely/src/devtools/xml.rs | 385 ++++++++++++++ vendor/ely/src/documents/blocks/content.rs | 242 +++++++++ vendor/ely/src/documents/blocks/edit.rs | 197 +++++++ vendor/ely/src/documents/blocks/export.rs | 199 +++++++ .../src/documents/blocks/import/details.rs | 186 +++++++ vendor/ely/src/documents/blocks/import/mod.rs | 378 +++++++++++++ vendor/ely/src/documents/blocks/keys.rs | 196 +++++++ vendor/ely/src/documents/blocks/kind.rs | 287 ++++++++++ vendor/ely/src/documents/blocks/media.rs | 387 ++++++++++++++ vendor/ely/src/documents/blocks/mod.rs | 492 +++++++++++++++++ vendor/ely/src/documents/blocks/span.rs | 482 +++++++++++++++++ vendor/ely/src/documents/blocks/table.rs | 331 ++++++++++++ .../src/documents/blocks/tests/markdown.rs | 238 +++++++++ vendor/ely/src/documents/blocks/tests/mod.rs | 394 ++++++++++++++ .../ely/src/documents/blocks/tests/scroll.rs | 110 ++++ vendor/ely/src/documents/blocks/tests/span.rs | 238 +++++++++ .../ely/src/documents/blocks/tests/stale.rs | 141 +++++ vendor/ely/src/documents/blocks/view.rs | 374 +++++++++++++ vendor/ely/src/documents/contents.rs | 61 +++ vendor/ely/src/documents/counts.rs | 85 +++ vendor/ely/src/documents/diagram.rs | 345 ++++++++++++ vendor/ely/src/documents/document/apart.rs | 211 ++++++++ vendor/ely/src/documents/document/attach.rs | 62 +++ vendor/ely/src/documents/document/block.rs | 458 ++++++++++++++++ .../ely/src/documents/document/block/check.rs | 109 ++++ .../src/documents/document/block/heading.rs | 221 ++++++++ .../src/documents/document/block/insert.rs | 319 +++++++++++ .../ely/src/documents/document/block/list.rs | 315 +++++++++++ .../ely/src/documents/document/block/quote.rs | 166 ++++++ .../ely/src/documents/document/block/split.rs | 229 ++++++++ vendor/ely/src/documents/document/cells.rs | 338 ++++++++++++ vendor/ely/src/documents/document/edit.rs | 355 +++++++++++++ vendor/ely/src/documents/document/finding.rs | 101 ++++ vendor/ely/src/documents/document/format.rs | 471 +++++++++++++++++ .../src/documents/document/format/clear.rs | 85 +++ vendor/ely/src/documents/document/lists.rs | 319 +++++++++++ vendor/ely/src/documents/document/look.rs | 103 ++++ vendor/ely/src/documents/document/mod.rs | 368 +++++++++++++ vendor/ely/src/documents/document/parse.rs | 194 +++++++ vendor/ely/src/documents/document/place.rs | 245 +++++++++ vendor/ely/src/documents/document/point.rs | 361 +++++++++++++ vendor/ely/src/documents/document/tables.rs | 491 +++++++++++++++++ .../src/documents/document/tests/attach.rs | 76 +++ .../ely/src/documents/document/tests/block.rs | 374 +++++++++++++ .../documents/document/tests/block_edges.rs | 223 ++++++++ .../ely/src/documents/document/tests/cells.rs | 302 +++++++++++ .../src/documents/document/tests/format.rs | 426 +++++++++++++++ .../src/documents/document/tests/history.rs | 130 +++++ .../ely/src/documents/document/tests/lend.rs | 95 ++++ .../ely/src/documents/document/tests/links.rs | 60 +++ .../ely/src/documents/document/tests/look.rs | 343 ++++++++++++ .../ely/src/documents/document/tests/mod.rs | 417 +++++++++++++++ .../src/documents/document/tests/open_look.rs | 197 +++++++ .../ely/src/documents/document/tests/place.rs | 239 +++++++++ .../ely/src/documents/document/tests/point.rs | 439 +++++++++++++++ .../src/documents/document/tests/presses.rs | 122 +++++ .../src/documents/document/tests/reading.rs | 181 +++++++ .../src/documents/document/tests/secondary.rs | 221 ++++++++ .../ely/src/documents/document/tests/toc.rs | 190 +++++++ .../ely/src/documents/document/tests/tools.rs | 435 +++++++++++++++ vendor/ely/src/documents/document/visual.rs | 399 ++++++++++++++ vendor/ely/src/documents/epub.rs | 246 +++++++++ vendor/ely/src/documents/find.rs | 25 + vendor/ely/src/documents/format.rs | 289 ++++++++++ vendor/ely/src/documents/history.rs | 373 +++++++++++++ vendor/ely/src/documents/knowledge.rs | 418 +++++++++++++++ vendor/ely/src/documents/link.rs | 235 ++++++++ vendor/ely/src/documents/markdown.rs | 352 ++++++++++++ vendor/ely/src/documents/markdown/tex.rs | 294 ++++++++++ .../ely/src/documents/markdown/tex/tests.rs | 123 +++++ vendor/ely/src/documents/mod.rs | 71 +++ vendor/ely/src/documents/modes.rs | 481 +++++++++++++++++ vendor/ely/src/documents/modes/tests.rs | 150 ++++++ vendor/ely/src/documents/pages.rs | 183 +++++++ vendor/ely/src/documents/picture.rs | 301 +++++++++++ vendor/ely/src/documents/print.rs | 349 ++++++++++++ vendor/ely/src/documents/reading.rs | 349 ++++++++++++ vendor/ely/src/documents/render.rs | 482 +++++++++++++++++ vendor/ely/src/documents/render/blocks.rs | 197 +++++++ vendor/ely/src/documents/render/math_text.rs | 433 +++++++++++++++ vendor/ely/src/documents/render/point.rs | 207 ++++++++ vendor/ely/src/documents/render/table.rs | 106 ++++ vendor/ely/src/documents/render/tests.rs | 153 ++++++ vendor/ely/src/documents/rich.rs | 188 +++++++ vendor/ely/src/documents/suggest.rs | 91 ++++ vendor/ely/src/documents/templates.rs | 344 ++++++++++++ vendor/ely/src/documents/tests.rs | 399 ++++++++++++++ vendor/ely/src/documents/thumbs.rs | 101 ++++ vendor/ely/src/documents/todo.rs | 177 +++++++ vendor/ely/src/documents/toolbar.rs | 127 +++++ vendor/ely/src/documents/tree/blocks.rs | 216 ++++++++ vendor/ely/src/documents/tree/emoji.rs | 103 ++++ vendor/ely/src/documents/tree/html.rs | 476 +++++++++++++++++ vendor/ely/src/documents/tree/html_block.rs | 318 +++++++++++ vendor/ely/src/documents/tree/mod.rs | 464 ++++++++++++++++ vendor/ely/src/documents/tree/sources.rs | 432 +++++++++++++++ vendor/ely/src/documents/tree/stack.rs | 88 +++ vendor/ely/src/documents/tree/tests.rs | 462 ++++++++++++++++ vendor/ely/src/documents/viewer.rs | 493 +++++++++++++++++ vendor/ely/src/editor/anchors.rs | 131 +++++ vendor/ely/src/editor/buffer.rs | 282 ++++++++++ vendor/ely/src/editor/chat.rs | 137 +++++ vendor/ely/src/editor/console.rs | 307 +++++++++++ vendor/ely/src/editor/cursor.rs | 252 +++++++++ vendor/ely/src/editor/decor.rs | 195 +++++++ vendor/ely/src/editor/edit.rs | 499 +++++++++++++++++ vendor/ely/src/editor/extensions.rs | 208 ++++++++ vendor/ely/src/editor/filters.rs | 156 ++++++ vendor/ely/src/editor/find.rs | 399 ++++++++++++++ vendor/ely/src/editor/gutter.rs | 192 +++++++ vendor/ely/src/editor/hints.rs | 363 +++++++++++++ vendor/ely/src/editor/hover.rs | 166 ++++++ vendor/ely/src/editor/ime.rs | 268 ++++++++++ vendor/ely/src/editor/keybindings.rs | 267 ++++++++++ vendor/ely/src/editor/keys.rs | 300 +++++++++++ vendor/ely/src/editor/layout.rs | 275 ++++++++++ vendor/ely/src/editor/line.rs | 479 +++++++++++++++++ vendor/ely/src/editor/measure.rs | 86 +++ vendor/ely/src/editor/mod.rs | 68 +++ vendor/ely/src/editor/moves.rs | 174 ++++++ vendor/ely/src/editor/preview.rs | 184 +++++++ vendor/ely/src/editor/problems.rs | 285 ++++++++++ vendor/ely/src/editor/prose.rs | 83 +++ vendor/ely/src/editor/refactor.rs | 195 +++++++ vendor/ely/src/editor/row.rs | 188 +++++++ vendor/ely/src/editor/search.rs | 491 +++++++++++++++++ vendor/ely/src/editor/settings.rs | 432 +++++++++++++++ vendor/ely/src/editor/state.rs | 496 +++++++++++++++++ vendor/ely/src/editor/status.rs | 383 ++++++++++++++ vendor/ely/src/editor/symbols.rs | 479 +++++++++++++++++ vendor/ely/src/editor/syntax.rs | 199 +++++++ vendor/ely/src/editor/tasks.rs | 269 ++++++++++ vendor/ely/src/editor/tests/chinese.rs | 40 ++ vendor/ely/src/editor/tests/history.rs | 34 ++ vendor/ely/src/editor/tests/mod.rs | 325 ++++++++++++ vendor/ely/src/editor/tests/stale.rs | 252 +++++++++ vendor/ely/src/editor/tests/wide.rs | 66 +++ vendor/ely/src/editor/view.rs | 390 ++++++++++++++ vendor/ely/src/editor/welcome.rs | 495 +++++++++++++++++ vendor/ely/src/editor/writing.rs | 26 + vendor/ely/src/feedback/clock.rs | 271 ++++++++++ vendor/ely/src/feedback/confirm.rs | 141 +++++ vendor/ely/src/feedback/messages.rs | 394 ++++++++++++++ vendor/ely/src/feedback/mod.rs | 22 + vendor/ely/src/feedback/notification.rs | 296 +++++++++++ vendor/ely/src/feedback/result.rs | 168 ++++++ vendor/ely/src/feedback/states.rs | 295 +++++++++++ vendor/ely/src/feedback/status.rs | 194 +++++++ vendor/ely/src/feedback/suspense.rs | 154 ++++++ vendor/ely/src/feedback/tests/loading.rs | 87 +++ vendor/ely/src/feedback/tests/mod.rs | 291 ++++++++++ vendor/ely/src/feedback/tests/states.rs | 226 ++++++++ vendor/ely/src/feedback/toast.rs | 424 +++++++++++++++ vendor/ely/src/files/archive.rs | 189 +++++++ vendor/ely/src/files/columns.rs | 135 +++++ vendor/ely/src/files/duplicates.rs | 244 +++++++++ vendor/ely/src/files/explorer.rs | 285 ++++++++++ vendor/ely/src/files/grid.rs | 249 +++++++++ vendor/ely/src/files/icon.rs | 65 +++ vendor/ely/src/files/item.rs | 48 ++ vendor/ely/src/files/mod.rs | 37 ++ vendor/ely/src/files/operation.rs | 242 +++++++++ vendor/ely/src/files/preview.rs | 145 +++++ vendor/ely/src/files/recent.rs | 148 ++++++ vendor/ely/src/files/search.rs | 131 +++++ vendor/ely/src/files/tests/explorer.rs | 237 +++++++++ vendor/ely/src/files/tests/find.rs | 383 ++++++++++++++ vendor/ely/src/files/tests/mod.rs | 199 +++++++ vendor/ely/src/files/tests/stale.rs | 115 ++++ vendor/ely/src/files/tests/transfers.rs | 274 ++++++++++ vendor/ely/src/files/transfer.rs | 211 ++++++++ vendor/ely/src/files/transfers.rs | 202 +++++++ vendor/ely/src/finance/blotter.rs | 373 +++++++++++++ vendor/ely/src/finance/book.rs | 344 ++++++++++++ vendor/ely/src/finance/calendars.rs | 406 ++++++++++++++ vendor/ely/src/finance/candles.rs | 312 +++++++++++ vendor/ely/src/finance/controls.rs | 345 ++++++++++++ vendor/ely/src/finance/depth.rs | 347 ++++++++++++ vendor/ely/src/finance/draw.rs | 440 +++++++++++++++ vendor/ely/src/finance/heatmap.rs | 216 ++++++++ vendor/ely/src/finance/indicators.rs | 253 +++++++++ vendor/ely/src/finance/labels.rs | 376 +++++++++++++ vendor/ely/src/finance/market.rs | 483 +++++++++++++++++ vendor/ely/src/finance/mod.rs | 59 +++ vendor/ely/src/finance/options.rs | 289 ++++++++++ vendor/ely/src/finance/overview.rs | 369 +++++++++++++ vendor/ely/src/finance/payoff.rs | 242 +++++++++ vendor/ely/src/finance/portfolio.rs | 395 ++++++++++++++ vendor/ely/src/finance/quotes.rs | 405 ++++++++++++++ vendor/ely/src/finance/renko.rs | 406 ++++++++++++++ vendor/ely/src/finance/risk.rs | 209 ++++++++ vendor/ely/src/finance/series.rs | 187 +++++++ vendor/ely/src/finance/spread.rs | 149 ++++++ vendor/ely/src/finance/stage.rs | 185 +++++++ vendor/ely/src/finance/steer.rs | 180 +++++++ vendor/ely/src/finance/symbols.rs | 312 +++++++++++ vendor/ely/src/finance/tape.rs | 310 +++++++++++ vendor/ely/src/finance/tests.rs | 374 +++++++++++++ vendor/ely/src/finance/tools.rs | 337 ++++++++++++ vendor/ely/src/finance/trade.rs | 378 +++++++++++++ vendor/ely/src/finance/wallet.rs | 454 ++++++++++++++++ vendor/ely/src/forms/avatar.rs | 169 ++++++ vendor/ely/src/forms/card.rs | 253 +++++++++ vendor/ely/src/forms/cascade.rs | 399 ++++++++++++++ vendor/ely/src/forms/catalogs.rs | 202 +++++++ vendor/ely/src/forms/check.rs | 306 +++++++++++ vendor/ely/src/forms/checked.rs | 150 ++++++ vendor/ely/src/forms/chips.rs | 121 +++++ vendor/ely/src/forms/code.rs | 293 ++++++++++ vendor/ely/src/forms/color/dropper.rs | 134 +++++ vendor/ely/src/forms/color/fields.rs | 150 ++++++ vendor/ely/src/forms/color/gradient.rs | 336 ++++++++++++ vendor/ely/src/forms/color/mod.rs | 158 ++++++ vendor/ely/src/forms/color/picker.rs | 409 ++++++++++++++ vendor/ely/src/forms/color/swatch.rs | 268 ++++++++++ vendor/ely/src/forms/combobox.rs | 301 +++++++++++ vendor/ely/src/forms/date/calendar.rs | 424 +++++++++++++++ vendor/ely/src/forms/date/cron.rs | 154 ++++++ vendor/ely/src/forms/date/mod.rs | 87 +++ vendor/ely/src/forms/date/period.rs | 469 ++++++++++++++++ vendor/ely/src/forms/date/picker.rs | 389 ++++++++++++++ vendor/ely/src/forms/date/relative.rs | 176 ++++++ vendor/ely/src/forms/date/rule.rs | 379 +++++++++++++ vendor/ely/src/forms/date/time.rs | 494 +++++++++++++++++ vendor/ely/src/forms/date/week.rs | 114 ++++ vendor/ely/src/forms/date/zone.rs | 106 ++++ vendor/ely/src/forms/expression.rs | 352 ++++++++++++ vendor/ely/src/forms/files.rs | 402 ++++++++++++++ vendor/ely/src/forms/glyphs.rs | 216 ++++++++ vendor/ely/src/forms/group.rs | 120 +++++ vendor/ely/src/forms/hotkey.rs | 110 ++++ vendor/ely/src/forms/inline.rs | 203 +++++++ vendor/ely/src/forms/input.rs | 223 ++++++++ vendor/ely/src/forms/knob.rs | 200 +++++++ vendor/ely/src/forms/listbox.rs | 196 +++++++ vendor/ely/src/forms/masked.rs | 359 +++++++++++++ vendor/ely/src/forms/mention.rs | 371 +++++++++++++ vendor/ely/src/forms/mod.rs | 125 +++++ vendor/ely/src/forms/multi.rs | 234 ++++++++ vendor/ely/src/forms/number.rs | 498 +++++++++++++++++ vendor/ely/src/forms/number/scrub.rs | 45 ++ vendor/ely/src/forms/number/tests.rs | 123 +++++ vendor/ely/src/forms/options.rs | 370 +++++++++++++ vendor/ely/src/forms/pairs.rs | 309 +++++++++++ vendor/ely/src/forms/path.rs | 144 +++++ vendor/ely/src/forms/pattern.rs | 184 +++++++ vendor/ely/src/forms/picks.rs | 306 +++++++++++ vendor/ely/src/forms/pin.rs | 167 ++++++ vendor/ely/src/forms/radio.rs | 271 ++++++++++ vendor/ely/src/forms/rating.rs | 161 ++++++ vendor/ely/src/forms/search.rs | 121 +++++ vendor/ely/src/forms/select.rs | 398 ++++++++++++++ vendor/ely/src/forms/signature.rs | 307 +++++++++++ vendor/ely/src/forms/slider.rs | 466 ++++++++++++++++ vendor/ely/src/forms/stepper.rs | 109 ++++ vendor/ely/src/forms/structure.rs | 358 +++++++++++++ vendor/ely/src/forms/switch.rs | 167 ++++++ vendor/ely/src/forms/syntax.rs | 194 +++++++ vendor/ely/src/forms/tags.rs | 284 ++++++++++ vendor/ely/src/forms/tests/choices.rs | 481 +++++++++++++++++ vendor/ely/src/forms/tests/colors.rs | 85 +++ vendor/ely/src/forms/tests/dates.rs | 259 +++++++++ vendor/ely/src/forms/tests/mod.rs | 471 +++++++++++++++++ vendor/ely/src/forms/tests/other.rs | 178 +++++++ vendor/ely/src/forms/tests/path.rs | 68 +++ vendor/ely/src/forms/tests/popup.rs | 50 ++ vendor/ely/src/forms/tests/stale.rs | 68 +++ vendor/ely/src/forms/tests/structure.rs | 242 +++++++++ vendor/ely/src/forms/tests/tags.rs | 137 +++++ vendor/ely/src/forms/tests/upload.rs | 78 +++ vendor/ely/src/forms/text/actions.rs | 433 +++++++++++++++ vendor/ely/src/forms/text/edit.rs | 268 ++++++++++ vendor/ely/src/forms/text/element.rs | 490 +++++++++++++++++ vendor/ely/src/forms/text/geometry.rs | 98 ++++ vendor/ely/src/forms/text/highlight.rs | 24 + vendor/ely/src/forms/text/ime.rs | 148 ++++++ vendor/ely/src/forms/text/mod.rs | 492 +++++++++++++++++ vendor/ely/src/forms/transfer.rs | 217 ++++++++ vendor/ely/src/forms/unit.rs | 94 ++++ vendor/ely/src/forms/upload.rs | 199 +++++++ vendor/ely/src/generative/audio.rs | 220 ++++++++ vendor/ely/src/generative/brush.rs | 152 ++++++ vendor/ely/src/generative/compare.rs | 205 +++++++ vendor/ely/src/generative/downloads.rs | 297 +++++++++++ vendor/ely/src/generative/embed.rs | 327 ++++++++++++ vendor/ely/src/generative/grid.rs | 212 ++++++++ vendor/ely/src/generative/hardware.rs | 79 +++ vendor/ely/src/generative/lens.rs | 193 +++++++ vendor/ely/src/generative/mask.rs | 445 ++++++++++++++++ vendor/ely/src/generative/mod.rs | 44 ++ vendor/ely/src/generative/models.rs | 304 +++++++++++ vendor/ely/src/generative/playground.rs | 265 ++++++++++ vendor/ely/src/generative/prompt.rs | 240 +++++++++ vendor/ely/src/generative/queue.rs | 268 ++++++++++ vendor/ely/src/generative/ratio.rs | 164 ++++++ vendor/ely/src/generative/seed.rs | 101 ++++ vendor/ely/src/generative/style.rs | 146 +++++ vendor/ely/src/generative/tests/canvas.rs | 181 +++++++ vendor/ely/src/generative/tests/data.rs | 268 ++++++++++ vendor/ely/src/generative/tests/mod.rs | 41 ++ vendor/ely/src/generative/tests/models.rs | 133 +++++ vendor/ely/src/generative/tests/results.rs | 206 ++++++++ vendor/ely/src/generative/tests/settings.rs | 190 +++++++ vendor/ely/src/generative/tests/sound.rs | 283 ++++++++++ vendor/ely/src/generative/tests/stale.rs | 270 ++++++++++ vendor/ely/src/generative/tuning.rs | 255 +++++++++ vendor/ely/src/generative/variation.rs | 203 +++++++ vendor/ely/src/generative/versions.rs | 387 ++++++++++++++ vendor/ely/src/generative/video.rs | 333 ++++++++++++ vendor/ely/src/generative/voice.rs | 226 ++++++++ vendor/ely/src/git/badges.rs | 104 ++++ vendor/ely/src/git/blame.rs | 296 +++++++++++ vendor/ely/src/git/changes.rs | 476 +++++++++++++++++ vendor/ely/src/git/commits.rs | 310 +++++++++++ vendor/ely/src/git/diff.rs | 317 +++++++++++ vendor/ely/src/git/graph.rs | 152 ++++++ vendor/ely/src/git/history.rs | 157 ++++++ vendor/ely/src/git/merge.rs | 372 +++++++++++++ vendor/ely/src/git/merging.rs | 380 +++++++++++++ vendor/ely/src/git/mod.rs | 33 ++ vendor/ely/src/git/refs.rs | 462 ++++++++++++++++ vendor/ely/src/git/review.rs | 400 ++++++++++++++ vendor/ely/src/git/rows.rs | 253 +++++++++ vendor/ely/src/git/tags.rs | 224 ++++++++ vendor/ely/src/git/tests/commit.rs | 227 ++++++++ vendor/ely/src/git/tests/mod.rs | 246 +++++++++ vendor/ely/src/git/tests/narrow.rs | 39 ++ vendor/ely/src/git/tests/picking.rs | 253 +++++++++ vendor/ely/src/git/viewer.rs | 445 ++++++++++++++++ vendor/ely/src/i18n/builtin.rs | 327 ++++++++++++ vendor/ely/src/i18n/locale.rs | 110 ++++ vendor/ely/src/i18n/mod.rs | 153 ++++++ vendor/ely/src/i18n/skip.rs | 70 +++ vendor/ely/src/i18n/tests/a11y.rs | 248 +++++++++ vendor/ely/src/i18n/tests/mod.rs | 214 ++++++++ vendor/ely/src/i18n/tests/shipped.rs | 74 +++ vendor/ely/src/interaction/mod.rs | 14 + vendor/ely/src/interaction/resizable.rs | 245 +++++++++ vendor/ely/src/interaction/rotatable.rs | 181 +++++++ vendor/ely/src/interaction/roving.rs | 163 ++++++ vendor/ely/src/interaction/selection.rs | 341 ++++++++++++ vendor/ely/src/interaction/sync.rs | 136 +++++ vendor/ely/src/interaction/tests/limits.rs | 142 +++++ vendor/ely/src/interaction/tests/mod.rs | 422 +++++++++++++++ vendor/ely/src/layout/collapse.rs | 240 +++++++++ vendor/ely/src/layout/dock/mod.rs | 214 ++++++++ vendor/ely/src/layout/dock/view.rs | 316 +++++++++++ vendor/ely/src/layout/floating.rs | 170 ++++++ vendor/ely/src/layout/grid.rs | 209 ++++++++ vendor/ely/src/layout/mod.rs | 38 ++ vendor/ely/src/layout/narrow.rs | 54 ++ vendor/ely/src/layout/page.rs | 198 +++++++ vendor/ely/src/layout/panes.rs | 457 ++++++++++++++++ vendor/ely/src/layout/scroll.rs | 361 +++++++++++++ vendor/ely/src/layout/scroll_aids.rs | 253 +++++++++ vendor/ely/src/layout/seeded.rs | 26 + vendor/ely/src/layout/sheet.rs | 303 +++++++++++ vendor/ely/src/layout/sidebar.rs | 94 ++++ vendor/ely/src/layout/split.rs | 259 +++++++++ vendor/ely/src/layout/stack.rs | 135 +++++ vendor/ely/src/layout/surface.rs | 395 ++++++++++++++ vendor/ely/src/layout/tests.rs | 303 +++++++++++ vendor/ely/src/layout/viewport.rs | 189 +++++++ vendor/ely/src/layout/workspace.rs | 105 ++++ vendor/ely/src/lib.rs | 102 ++++ vendor/ely/src/lists/directory.rs | 390 ++++++++++++++ vendor/ely/src/lists/files.rs | 317 +++++++++++ vendor/ely/src/lists/grouped.rs | 85 +++ vendor/ely/src/lists/item.rs | 278 ++++++++++ vendor/ely/src/lists/long.rs | 145 +++++ vendor/ely/src/lists/mod.rs | 29 + vendor/ely/src/lists/outline.rs | 150 ++++++ vendor/ely/src/lists/sections.rs | 120 +++++ vendor/ely/src/lists/select.rs | 441 +++++++++++++++ vendor/ely/src/lists/sortable.rs | 150 ++++++ vendor/ely/src/lists/swipe.rs | 239 +++++++++ vendor/ely/src/lists/tests/editor.rs | 49 ++ vendor/ely/src/lists/tests/keys.rs | 138 +++++ vendor/ely/src/lists/tests/mod.rs | 485 +++++++++++++++++ vendor/ely/src/lists/tree/mod.rs | 404 ++++++++++++++ vendor/ely/src/lists/tree/model.rs | 403 ++++++++++++++ vendor/ely/src/lists/tree/row.rs | 321 +++++++++++ vendor/ely/src/lists/tree/select.rs | 158 ++++++ vendor/ely/src/lists/tree/tests.rs | 276 ++++++++++ vendor/ely/src/mail/boxes.rs | 185 +++++++ vendor/ely/src/mail/compose.rs | 386 ++++++++++++++ vendor/ely/src/mail/labels.rs | 283 ++++++++++ vendor/ely/src/mail/list.rs | 360 +++++++++++++ vendor/ely/src/mail/mod.rs | 25 + vendor/ely/src/mail/quoted.rs | 80 +++ vendor/ely/src/mail/reader.rs | 385 ++++++++++++++ vendor/ely/src/mail/send.rs | 185 +++++++ vendor/ely/src/mail/signature.rs | 139 +++++ vendor/ely/src/mail/snooze.rs | 186 +++++++ vendor/ely/src/mail/tests/mod.rs | 220 ++++++++ vendor/ely/src/mail/tests/read.rs | 201 +++++++ vendor/ely/src/mail/tests/sort.rs | 209 ++++++++ vendor/ely/src/mail/tests/write.rs | 232 ++++++++ vendor/ely/src/mail/thread.rs | 214 ++++++++ vendor/ely/src/mail/times.rs | 210 ++++++++ vendor/ely/src/maps/choropleth.rs | 282 ++++++++++ vendor/ely/src/maps/cluster.rs | 209 ++++++++ vendor/ely/src/maps/coords.rs | 98 ++++ vendor/ely/src/maps/geo.rs | 486 +++++++++++++++++ vendor/ely/src/maps/geojson.rs | 229 ++++++++ vendor/ely/src/maps/heat.rs | 120 +++++ vendor/ely/src/maps/layer.rs | 369 +++++++++++++ vendor/ely/src/maps/marker.rs | 316 +++++++++++ vendor/ely/src/maps/mod.rs | 24 + vendor/ely/src/maps/picker.rs | 85 +++ vendor/ely/src/maps/tests/layers.rs | 238 +++++++++ vendor/ely/src/maps/tests/mod.rs | 443 ++++++++++++++++ vendor/ely/src/maps/tests/popup.rs | 245 +++++++++ vendor/ely/src/maps/tile.rs | 143 +++++ vendor/ely/src/maps/view.rs | 391 ++++++++++++++ vendor/ely/src/maps/world.rs | 159 ++++++ vendor/ely/src/media/annotate.rs | 437 +++++++++++++++ vendor/ely/src/media/audio.rs | 256 +++++++++ vendor/ely/src/media/camera.rs | 243 +++++++++ vendor/ely/src/media/controls.rs | 329 ++++++++++++ vendor/ely/src/media/crop.rs | 372 +++++++++++++ vendor/ely/src/media/cropper.rs | 266 ++++++++++ vendor/ely/src/media/listen.rs | 315 +++++++++++ vendor/ely/src/media/marks.rs | 331 ++++++++++++ vendor/ely/src/media/mod.rs | 51 ++ vendor/ely/src/media/model.rs | 252 +++++++++ vendor/ely/src/media/player.rs | 420 +++++++++++++++ vendor/ely/src/media/record.rs | 286 ++++++++++ vendor/ely/src/media/scrubber.rs | 356 +++++++++++++ vendor/ely/src/media/strip.rs | 368 +++++++++++++ vendor/ely/src/media/subtitles.rs | 373 +++++++++++++ vendor/ely/src/media/tests/audio.rs | 375 +++++++++++++ vendor/ely/src/media/tests/devices.rs | 305 +++++++++++ vendor/ely/src/media/tests/edit.rs | 353 +++++++++++++ vendor/ely/src/media/tests/images.rs | 297 +++++++++++ vendor/ely/src/media/tests/mod.rs | 70 +++ vendor/ely/src/media/tests/player.rs | 345 ++++++++++++ vendor/ely/src/media/tests/stale.rs | 107 ++++ vendor/ely/src/media/tests/video.rs | 292 ++++++++++ vendor/ely/src/media/thumbnail.rs | 105 ++++ vendor/ely/src/media/turn.rs | 88 +++ vendor/ely/src/media/upload.rs | 221 ++++++++ vendor/ely/src/media/viewer.rs | 458 ++++++++++++++++ vendor/ely/src/menus/aim.rs | 129 +++++ vendor/ely/src/menus/bar.rs | 206 ++++++++ vendor/ely/src/menus/draw.rs | 301 +++++++++++ vendor/ely/src/menus/hosts.rs | 365 +++++++++++++ vendor/ely/src/menus/menu.rs | 500 ++++++++++++++++++ vendor/ely/src/menus/mod.rs | 15 + vendor/ely/src/menus/model.rs | 223 ++++++++ vendor/ely/src/menus/pie.rs | 321 +++++++++++ vendor/ely/src/menus/tests/aim.rs | 283 ++++++++++ vendor/ely/src/menus/tests/buttons.rs | 247 +++++++++ vendor/ely/src/menus/tests/mod.rs | 412 +++++++++++++++ vendor/ely/src/menus/tests/more.rs | 281 ++++++++++ vendor/ely/src/messaging/call.rs | 328 ++++++++++++ vendor/ely/src/messaging/channels.rs | 284 ++++++++++ vendor/ely/src/messaging/gifs.rs | 322 +++++++++++ vendor/ely/src/messaging/header.rs | 152 ++++++ vendor/ely/src/messaging/incoming.rs | 112 ++++ vendor/ely/src/messaging/members.rs | 254 +++++++++ vendor/ely/src/messaging/messages.rs | 241 +++++++++ vendor/ely/src/messaging/mod.rs | 32 ++ vendor/ely/src/messaging/people.rs | 224 ++++++++ vendor/ely/src/messaging/pins.rs | 187 +++++++ vendor/ely/src/messaging/receipt.rs | 93 ++++ vendor/ely/src/messaging/status.rs | 340 ++++++++++++ vendor/ely/src/messaging/stickers.rs | 179 +++++++ vendor/ely/src/messaging/tests/calls.rs | 297 +++++++++++ vendor/ely/src/messaging/tests/messages.rs | 184 +++++++ vendor/ely/src/messaging/tests/mod.rs | 280 ++++++++++ vendor/ely/src/messaging/tests/people.rs | 264 +++++++++ vendor/ely/src/messaging/tests/pickers.rs | 217 ++++++++ vendor/ely/src/messaging/thread.rs | 254 +++++++++ vendor/ely/src/messaging/tiles.rs | 386 ++++++++++++++ vendor/ely/src/misc/calculator.rs | 413 +++++++++++++++ vendor/ely/src/misc/captcha.rs | 197 +++++++ vendor/ely/src/misc/clock.rs | 328 ++++++++++++ vendor/ely/src/misc/consent.rs | 124 +++++ vendor/ely/src/misc/cookies.rs | 191 +++++++ vendor/ely/src/misc/csv.rs | 279 ++++++++++ vendor/ely/src/misc/export.rs | 148 ++++++ vendor/ely/src/misc/flashcards.rs | 190 +++++++ vendor/ely/src/misc/import.rs | 287 ++++++++++ vendor/ely/src/misc/licenses.rs | 145 +++++ vendor/ely/src/misc/mod.rs | 37 ++ vendor/ely/src/misc/poll.rs | 216 ++++++++ vendor/ely/src/misc/quiz.rs | 327 ++++++++++++ vendor/ely/src/misc/scanner.rs | 217 ++++++++ vendor/ely/src/misc/stopwatch.rs | 252 +++++++++ vendor/ely/src/misc/survey.rs | 285 ++++++++++ vendor/ely/src/misc/tests/asking.rs | 257 +++++++++ vendor/ely/src/misc/tests/codes.rs | 198 +++++++ vendor/ely/src/misc/tests/drift.rs | 127 +++++ vendor/ely/src/misc/tests/mod.rs | 212 ++++++++ vendor/ely/src/misc/tests/notices.rs | 208 ++++++++ vendor/ely/src/misc/tests/numbers.rs | 140 +++++ vendor/ely/src/misc/tests/transfer.rs | 294 ++++++++++ vendor/ely/src/misc/units.rs | 378 +++++++++++++ vendor/ely/src/misc/web.rs | 304 +++++++++++ vendor/ely/src/motion/changes.rs | 26 + vendor/ely/src/motion/curve.rs | 81 +++ vendor/ely/src/motion/effects.rs | 405 ++++++++++++++ vendor/ely/src/motion/list.rs | 283 ++++++++++ vendor/ely/src/motion/mod.rs | 31 ++ vendor/ely/src/motion/overlay.rs | 282 ++++++++++ vendor/ely/src/motion/particles.rs | 448 ++++++++++++++++ vendor/ely/src/motion/progress.rs | 299 +++++++++++ vendor/ely/src/motion/reorder.rs | 226 ++++++++ vendor/ely/src/motion/skeleton.rs | 393 ++++++++++++++ vendor/ely/src/motion/slide.rs | 150 ++++++ vendor/ely/src/motion/spinner.rs | 231 ++++++++ vendor/ely/src/motion/tests.rs | 434 +++++++++++++++ vendor/ely/src/motion/transition.rs | 171 ++++++ vendor/ely/src/navigation/breadcrumb.rs | 186 +++++++ vendor/ely/src/navigation/editor_tabs.rs | 384 ++++++++++++++ vendor/ely/src/navigation/goto.rs | 132 +++++ vendor/ely/src/navigation/history.rs | 116 ++++ vendor/ely/src/navigation/menu.rs | 283 ++++++++++ vendor/ely/src/navigation/mod.rs | 30 ++ vendor/ely/src/navigation/nav.rs | 232 ++++++++ vendor/ely/src/navigation/overflow.rs | 112 ++++ vendor/ely/src/navigation/pages.rs | 306 +++++++++++ vendor/ely/src/navigation/palette/kinds.rs | 491 +++++++++++++++++ vendor/ely/src/navigation/palette/launcher.rs | 91 ++++ vendor/ely/src/navigation/palette/mod.rs | 397 ++++++++++++++ vendor/ely/src/navigation/palette/tests.rs | 285 ++++++++++ vendor/ely/src/navigation/steps.rs | 353 +++++++++++++ vendor/ely/src/navigation/tabs.rs | 349 ++++++++++++ vendor/ely/src/navigation/tests/mod.rs | 361 +++++++++++++ vendor/ely/src/navigation/tests/pages.rs | 144 +++++ vendor/ely/src/navigation/tests/stale.rs | 112 ++++ vendor/ely/src/navigation/tests/tabs.rs | 290 ++++++++++ vendor/ely/src/navigation/toc.rs | 264 +++++++++ vendor/ely/src/onboarding/checklist.rs | 213 ++++++++ vendor/ely/src/onboarding/dialogs.rs | 112 ++++ vendor/ely/src/onboarding/feedback.rs | 181 +++++++ vendor/ely/src/onboarding/help.rs | 347 ++++++++++++ vendor/ely/src/onboarding/highlight.rs | 121 +++++ vendor/ely/src/onboarding/hotspot.rs | 118 +++++ vendor/ely/src/onboarding/mod.rs | 20 + vendor/ely/src/onboarding/support.rs | 192 +++++++ vendor/ely/src/onboarding/tests/flows.rs | 240 +++++++++ vendor/ely/src/onboarding/tests/help.rs | 345 ++++++++++++ vendor/ely/src/onboarding/tests/mod.rs | 113 ++++ vendor/ely/src/onboarding/wizard.rs | 176 ++++++ vendor/ely/src/overlays/dialog.rs | 303 +++++++++++ vendor/ely/src/overlays/dialogs.rs | 341 ++++++++++++ vendor/ely/src/overlays/floats.rs | 171 ++++++ vendor/ely/src/overlays/hover.rs | 147 +++++ vendor/ely/src/overlays/lightbox.rs | 303 +++++++++++ vendor/ely/src/overlays/mod.rs | 18 + vendor/ely/src/overlays/popover.rs | 239 +++++++++ vendor/ely/src/overlays/spotlight.rs | 447 ++++++++++++++++ vendor/ely/src/overlays/tests/guides.rs | 372 +++++++++++++ vendor/ely/src/overlays/tests/mod.rs | 496 +++++++++++++++++ vendor/ely/src/primitives/backdrop.rs | 108 ++++ vendor/ely/src/primitives/caret.rs | 65 +++ vendor/ely/src/primitives/disclosure.rs | 65 +++ vendor/ely/src/primitives/divider.rs | 57 ++ vendor/ely/src/primitives/files.rs | 116 ++++ vendor/ely/src/primitives/focus.rs | 292 ++++++++++ vendor/ely/src/primitives/ghost.rs | 46 ++ vendor/ely/src/primitives/held.rs | 129 +++++ vendor/ely/src/primitives/icon.rs | 481 +++++++++++++++++ vendor/ely/src/primitives/icon/tests.rs | 70 +++ vendor/ely/src/primitives/image.rs | 127 +++++ vendor/ely/src/primitives/layer.rs | 212 ++++++++ vendor/ely/src/primitives/measure.rs | 122 +++++ vendor/ely/src/primitives/mod.rs | 42 ++ vendor/ely/src/primitives/pressable.rs | 111 ++++ vendor/ely/src/primitives/retired.rs | 50 ++ vendor/ely/src/primitives/severity.rs | 43 ++ vendor/ely/src/primitives/tests.rs | 391 ++++++++++++++ vendor/ely/src/primitives/tooltip.rs | 233 ++++++++ vendor/ely/src/project/board.rs | 496 +++++++++++++++++ vendor/ely/src/project/card.rs | 152 ++++++ vendor/ely/src/project/database.rs | 369 +++++++++++++ vendor/ely/src/project/labels.rs | 303 +++++++++++ vendor/ely/src/project/marks.rs | 239 +++++++++ vendor/ely/src/project/milestone.rs | 243 +++++++++ vendor/ely/src/project/mod.rs | 31 ++ vendor/ely/src/project/moves.rs | 73 +++ vendor/ely/src/project/panel.rs | 279 ++++++++++ vendor/ely/src/project/pomodoro.rs | 350 ++++++++++++ vendor/ely/src/project/roadmap.rs | 284 ++++++++++ vendor/ely/src/project/tasks.rs | 251 +++++++++ vendor/ely/src/project/tests/boards.rs | 453 ++++++++++++++++ vendor/ely/src/project/tests/mod.rs | 201 +++++++ vendor/ely/src/project/tests/time.rs | 148 ++++++ vendor/ely/src/project/tracker.rs | 271 ++++++++++ vendor/ely/src/project/work.rs | 317 +++++++++++ vendor/ely/src/project/workload.rs | 171 ++++++ vendor/ely/src/rendering/mod.rs | 5 + vendor/ely/src/rendering/surface.rs | 148 ++++++ vendor/ely/src/rendering/tests.rs | 129 +++++ vendor/ely/src/settings/advanced.rs | 198 +++++++ vendor/ely/src/settings/appearance.rs | 311 +++++++++++ vendor/ely/src/settings/editor.rs | 194 +++++++ vendor/ely/src/settings/importer.rs | 188 +++++++ vendor/ely/src/settings/mod.rs | 32 ++ vendor/ely/src/settings/network.rs | 211 ++++++++ vendor/ely/src/settings/preferences.rs | 265 ++++++++++ vendor/ely/src/settings/search.rs | 140 +++++ vendor/ely/src/settings/section.rs | 224 ++++++++ vendor/ely/src/settings/shortcuts.rs | 132 +++++ vendor/ely/src/settings/storage.rs | 281 ++++++++++ vendor/ely/src/settings/syntax.rs | 105 ++++ vendor/ely/src/settings/tests/appearance.rs | 105 ++++ vendor/ely/src/settings/tests/mod.rs | 465 ++++++++++++++++ vendor/ely/src/settings/tests/theme.rs | 240 +++++++++ vendor/ely/src/settings/vscode.rs | 378 +++++++++++++ vendor/ely/src/shell/activity.rs | 176 ++++++ vendor/ely/src/shell/bars.rs | 272 ++++++++++ vendor/ely/src/shell/chrome.rs | 442 ++++++++++++++++ vendor/ely/src/shell/columns.rs | 419 +++++++++++++++ vendor/ely/src/shell/crash.rs | 163 ++++++ vendor/ely/src/shell/dialogs.rs | 245 +++++++++ vendor/ely/src/shell/frame.rs | 181 +++++++ vendor/ely/src/shell/mod.rs | 34 ++ vendor/ely/src/shell/native.rs | 242 +++++++++ vendor/ely/src/shell/status.rs | 312 +++++++++++ vendor/ely/src/shell/switcher.rs | 166 ++++++ vendor/ely/src/shell/tabs.rs | 246 +++++++++ vendor/ely/src/shell/tests.rs | 477 +++++++++++++++++ vendor/ely/src/shell/tests/border.rs | 264 +++++++++ vendor/ely/src/shell/title_tests.rs | 174 ++++++ vendor/ely/src/shell/update.rs | 284 ++++++++++ vendor/ely/src/shell/vibrancy.rs | 42 ++ vendor/ely/src/shell/windows.rs | 276 ++++++++++ vendor/ely/src/tables/body.rs | 358 +++++++++++++ vendor/ely/src/tables/builders.rs | 458 ++++++++++++++++ vendor/ely/src/tables/cell.rs | 257 +++++++++ vendor/ely/src/tables/foot.rs | 74 +++ vendor/ely/src/tables/formula.rs | 336 ++++++++++++ vendor/ely/src/tables/grid.rs | 468 ++++++++++++++++ vendor/ely/src/tables/gridkeys.rs | 381 +++++++++++++ vendor/ely/src/tables/header.rs | 313 +++++++++++ vendor/ely/src/tables/mod.rs | 29 + vendor/ely/src/tables/model.rs | 148 ++++++ vendor/ely/src/tables/options.rs | 120 +++++ vendor/ely/src/tables/pivot.rs | 246 +++++++++ vendor/ely/src/tables/rules.rs | 336 ++++++++++++ vendor/ely/src/tables/sheets.rs | 166 ++++++ vendor/ely/src/tables/simple.rs | 192 +++++++ vendor/ely/src/tables/table.rs | 462 ++++++++++++++++ vendor/ely/src/tables/tests/chinese.rs | 62 +++ vendor/ely/src/tables/tests/clipboard.rs | 33 ++ vendor/ely/src/tables/tests/columns.rs | 191 +++++++ vendor/ely/src/tables/tests/mod.rs | 489 +++++++++++++++++ vendor/ely/src/tables/tests/stale.rs | 31 ++ vendor/ely/src/tables/toolbar.rs | 170 ++++++ vendor/ely/src/tables/tree_table.rs | 184 +++++++ vendor/ely/src/terminal/ansi.rs | 188 +++++++ vendor/ely/src/terminal/block.rs | 191 +++++++ vendor/ely/src/terminal/colors.rs | 161 ++++++ vendor/ely/src/terminal/frame.rs | 252 +++++++++ vendor/ely/src/terminal/history.rs | 124 +++++ vendor/ely/src/terminal/input.rs | 311 +++++++++++ vendor/ely/src/terminal/keys.rs | 129 +++++ vendor/ely/src/terminal/links.rs | 141 +++++ vendor/ely/src/terminal/logs.rs | 303 +++++++++++ vendor/ely/src/terminal/mod.rs | 38 ++ vendor/ely/src/terminal/paint.rs | 186 +++++++ vendor/ely/src/terminal/processes.rs | 151 ++++++ vendor/ely/src/terminal/pty.rs | 204 +++++++ vendor/ely/src/terminal/search.rs | 131 +++++ vendor/ely/src/terminal/shells.rs | 215 ++++++++ vendor/ely/src/terminal/tests.rs | 112 ++++ vendor/ely/src/terminal/view.rs | 337 ++++++++++++ vendor/ely/src/theme/calendar.rs | 33 ++ vendor/ely/src/theme/canvas.rs | 62 +++ vendor/ely/src/theme/chart.rs | 44 ++ vendor/ely/src/theme/dashboard.rs | 27 + vendor/ely/src/theme/files.rs | 24 + vendor/ely/src/theme/generative.rs | 27 + vendor/ely/src/theme/interaction.rs | 21 + vendor/ely/src/theme/maps.rs | 48 ++ vendor/ely/src/theme/media.rs | 45 ++ vendor/ely/src/theme/messaging.rs | 24 + vendor/ely/src/theme/misc.rs | 30 ++ vendor/ely/src/theme/mod.rs | 227 ++++++++ vendor/ely/src/theme/onboarding.rs | 18 + vendor/ely/src/theme/palette.rs | 359 +++++++++++++ vendor/ely/src/theme/platform.rs | 20 + vendor/ely/src/theme/project.rs | 24 + vendor/ely/src/theme/syntax.rs | 87 +++ vendor/ely/src/theme/tests.rs | 92 ++++ vendor/ely/src/theme/tokens.rs | 500 ++++++++++++++++++ vendor/ely/src/theme/tooling.rs | 27 + vendor/ely/src/tooling/a11y.rs | 281 ++++++++++ vendor/ely/src/tooling/events.rs | 304 +++++++++++ vendor/ely/src/tooling/inspector.rs | 428 +++++++++++++++ vendor/ely/src/tooling/mod.rs | 19 + vendor/ely/src/tooling/perf.rs | 224 ++++++++ vendor/ely/src/tooling/playground.rs | 322 +++++++++++ vendor/ely/src/tooling/renders.rs | 61 +++ vendor/ely/src/tooling/tests/catalogs.rs | 152 ++++++ vendor/ely/src/tooling/tests/inspection.rs | 293 ++++++++++ vendor/ely/src/tooling/tests/mod.rs | 136 +++++ vendor/ely/src/tooling/tokens.rs | 326 ++++++++++++ vendor/ely/src/typography/copy.rs | 53 ++ vendor/ely/src/typography/effects.rs | 186 +++++++ vendor/ely/src/typography/emoji.rs | 49 ++ vendor/ely/src/typography/fit.rs | 315 +++++++++++ vendor/ely/src/typography/format.rs | 421 +++++++++++++++ vendor/ely/src/typography/formatted.rs | 283 ++++++++++ vendor/ely/src/typography/inline.rs | 240 +++++++++ vendor/ely/src/typography/keys.rs | 112 ++++ vendor/ely/src/typography/link.rs | 133 +++++ vendor/ely/src/typography/math.rs | 275 ++++++++++ vendor/ely/src/typography/math/tests.rs | 273 ++++++++++ vendor/ely/src/typography/mod.rs | 33 ++ vendor/ely/src/typography/rolling.rs | 209 ++++++++ vendor/ely/src/typography/select.rs | 133 +++++ vendor/ely/src/typography/text.rs | 191 +++++++ 1276 files changed, 233559 insertions(+) create mode 100644 vendor/ely/Cargo.toml create mode 100644 vendor/ely/LICENSE create mode 100644 vendor/ely/assets/fonts/Inter-Italic.ttf create mode 100644 vendor/ely/assets/fonts/Inter-LICENSE.txt create mode 100644 vendor/ely/assets/fonts/Inter-Medium.ttf create mode 100644 vendor/ely/assets/fonts/Inter-Regular.ttf create mode 100644 vendor/ely/assets/fonts/Inter-SemiBold.ttf create mode 100644 vendor/ely/assets/fonts/JetBrainsMono-LICENSE.txt create mode 100644 vendor/ely/assets/fonts/JetBrainsMono-Medium.ttf create mode 100644 vendor/ely/assets/fonts/JetBrainsMono-Regular.ttf create mode 100644 vendor/ely/assets/fonts/ibm-plex-sans/IBMPlexSans-LICENSE.txt create mode 100644 vendor/ely/assets/fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf create mode 100644 vendor/ely/assets/icons/LICENSE create mode 100644 vendor/ely/assets/icons/a-arrow-down.svg create mode 100644 vendor/ely/assets/icons/a-arrow-up.svg create mode 100644 vendor/ely/assets/icons/accessibility.svg create mode 100644 vendor/ely/assets/icons/activity.svg create mode 100644 vendor/ely/assets/icons/alarm-clock.svg create mode 100644 vendor/ely/assets/icons/align-center-horizontal.svg create mode 100644 vendor/ely/assets/icons/align-center-vertical.svg create mode 100644 vendor/ely/assets/icons/align-center.svg create mode 100644 vendor/ely/assets/icons/align-end-horizontal.svg create mode 100644 vendor/ely/assets/icons/align-end-vertical.svg create mode 100644 vendor/ely/assets/icons/align-horizontal-distribute-center.svg create mode 100644 vendor/ely/assets/icons/align-justify.svg create mode 100644 vendor/ely/assets/icons/align-left.svg create mode 100644 vendor/ely/assets/icons/align-right.svg create mode 100644 vendor/ely/assets/icons/align-start-horizontal.svg create mode 100644 vendor/ely/assets/icons/align-start-vertical.svg create mode 100644 vendor/ely/assets/icons/align-vertical-distribute-center.svg create mode 100644 vendor/ely/assets/icons/app-window.svg create mode 100644 vendor/ely/assets/icons/archive.svg create mode 100644 vendor/ely/assets/icons/arrow-down-left.svg create mode 100644 vendor/ely/assets/icons/arrow-down-to-dot.svg create mode 100644 vendor/ely/assets/icons/arrow-down-to-line.svg create mode 100644 vendor/ely/assets/icons/arrow-down-up.svg create mode 100644 vendor/ely/assets/icons/arrow-down-wide-narrow.svg create mode 100644 vendor/ely/assets/icons/arrow-down.svg create mode 100644 vendor/ely/assets/icons/arrow-left.svg create mode 100644 vendor/ely/assets/icons/arrow-right.svg create mode 100644 vendor/ely/assets/icons/arrow-up-from-dot.svg create mode 100644 vendor/ely/assets/icons/arrow-up-narrow-wide.svg create mode 100644 vendor/ely/assets/icons/arrow-up-right.svg create mode 100644 vendor/ely/assets/icons/arrow-up.svg create mode 100644 vendor/ely/assets/icons/at-sign.svg create mode 100644 vendor/ely/assets/icons/audio-lines.svg create mode 100644 vendor/ely/assets/icons/ban.svg create mode 100644 vendor/ely/assets/icons/battery.svg create mode 100644 vendor/ely/assets/icons/bell.svg create mode 100644 vendor/ely/assets/icons/bold.svg create mode 100644 vendor/ely/assets/icons/book-open.svg create mode 100644 vendor/ely/assets/icons/bookmark.svg create mode 100644 vendor/ely/assets/icons/bot.svg create mode 100644 vendor/ely/assets/icons/box.svg create mode 100644 vendor/ely/assets/icons/braces.svg create mode 100644 vendor/ely/assets/icons/brush.svg create mode 100644 vendor/ely/assets/icons/bug.svg create mode 100644 vendor/ely/assets/icons/calendar-days.svg create mode 100644 vendor/ely/assets/icons/calendar-range.svg create mode 100644 vendor/ely/assets/icons/calendar.svg create mode 100644 vendor/ely/assets/icons/camera.svg create mode 100644 vendor/ely/assets/icons/captions-off.svg create mode 100644 vendor/ely/assets/icons/captions.svg create mode 100644 vendor/ely/assets/icons/case-sensitive.svg create mode 100644 vendor/ely/assets/icons/chart-area.svg create mode 100644 vendor/ely/assets/icons/chart-bar.svg create mode 100644 vendor/ely/assets/icons/chart-candlestick.svg create mode 100644 vendor/ely/assets/icons/chart-column.svg create mode 100644 vendor/ely/assets/icons/chart-gantt.svg create mode 100644 vendor/ely/assets/icons/chart-line.svg create mode 100644 vendor/ely/assets/icons/chart-pie.svg create mode 100644 vendor/ely/assets/icons/check-check.svg create mode 100644 vendor/ely/assets/icons/check.svg create mode 100644 vendor/ely/assets/icons/chevron-down.svg create mode 100644 vendor/ely/assets/icons/chevron-left.svg create mode 100644 vendor/ely/assets/icons/chevron-right.svg create mode 100644 vendor/ely/assets/icons/chevron-up.svg create mode 100644 vendor/ely/assets/icons/chevrons-left-right.svg create mode 100644 vendor/ely/assets/icons/chevrons-left.svg create mode 100644 vendor/ely/assets/icons/chevrons-right.svg create mode 100644 vendor/ely/assets/icons/chevrons-up-down.svg create mode 100644 vendor/ely/assets/icons/circle-alert.svg create mode 100644 vendor/ely/assets/icons/circle-check.svg create mode 100644 vendor/ely/assets/icons/circle-dashed.svg create mode 100644 vendor/ely/assets/icons/circle-dot-dashed.svg create mode 100644 vendor/ely/assets/icons/circle-dot.svg create mode 100644 vendor/ely/assets/icons/circle-help.svg create mode 100644 vendor/ely/assets/icons/circle-pause.svg create mode 100644 vendor/ely/assets/icons/circle-stop.svg create mode 100644 vendor/ely/assets/icons/circle-x.svg create mode 100644 vendor/ely/assets/icons/circle.svg create mode 100644 vendor/ely/assets/icons/clipboard-check.svg create mode 100644 vendor/ely/assets/icons/clipboard.svg create mode 100644 vendor/ely/assets/icons/clock.svg create mode 100644 vendor/ely/assets/icons/cloud-alert.svg create mode 100644 vendor/ely/assets/icons/cloud-check.svg create mode 100644 vendor/ely/assets/icons/cloud-off.svg create mode 100644 vendor/ely/assets/icons/cloud-upload.svg create mode 100644 vendor/ely/assets/icons/cloud.svg create mode 100644 vendor/ely/assets/icons/code.svg create mode 100644 vendor/ely/assets/icons/columns-2.svg create mode 100644 vendor/ely/assets/icons/columns-3.svg create mode 100644 vendor/ely/assets/icons/command.svg create mode 100644 vendor/ely/assets/icons/compass.svg create mode 100644 vendor/ely/assets/icons/contrast.svg create mode 100644 vendor/ely/assets/icons/copy.svg create mode 100644 vendor/ely/assets/icons/corner-down-right.svg create mode 100644 vendor/ely/assets/icons/cpu.svg create mode 100644 vendor/ely/assets/icons/credit-card.svg create mode 100644 vendor/ely/assets/icons/crop.svg create mode 100644 vendor/ely/assets/icons/crosshair.svg create mode 100644 vendor/ely/assets/icons/database.svg create mode 100644 vendor/ely/assets/icons/delete.svg create mode 100644 vendor/ely/assets/icons/dices.svg create mode 100644 vendor/ely/assets/icons/dollar-sign.svg create mode 100644 vendor/ely/assets/icons/dot.svg create mode 100644 vendor/ely/assets/icons/download.svg create mode 100644 vendor/ely/assets/icons/ellipsis-vertical.svg create mode 100644 vendor/ely/assets/icons/ellipsis.svg create mode 100644 vendor/ely/assets/icons/eraser.svg create mode 100644 vendor/ely/assets/icons/external-link.svg create mode 100644 vendor/ely/assets/icons/eye-off.svg create mode 100644 vendor/ely/assets/icons/eye.svg create mode 100644 vendor/ely/assets/icons/file-archive.svg create mode 100644 vendor/ely/assets/icons/file-audio.svg create mode 100644 vendor/ely/assets/icons/file-code.svg create mode 100644 vendor/ely/assets/icons/file-cog.svg create mode 100644 vendor/ely/assets/icons/file-image.svg create mode 100644 vendor/ely/assets/icons/file-json.svg create mode 100644 vendor/ely/assets/icons/file-plus.svg create mode 100644 vendor/ely/assets/icons/file-spreadsheet.svg create mode 100644 vendor/ely/assets/icons/file-terminal.svg create mode 100644 vendor/ely/assets/icons/file-text.svg create mode 100644 vendor/ely/assets/icons/file-type.svg create mode 100644 vendor/ely/assets/icons/file-video-camera.svg create mode 100644 vendor/ely/assets/icons/file.svg create mode 100644 vendor/ely/assets/icons/filter.svg create mode 100644 vendor/ely/assets/icons/fingerprint.svg create mode 100644 vendor/ely/assets/icons/flag.svg create mode 100644 vendor/ely/assets/icons/folder-open.svg create mode 100644 vendor/ely/assets/icons/folder-plus.svg create mode 100644 vendor/ely/assets/icons/folder.svg create mode 100644 vendor/ely/assets/icons/forward.svg create mode 100644 vendor/ely/assets/icons/frame.svg create mode 100644 vendor/ely/assets/icons/frown.svg create mode 100644 vendor/ely/assets/icons/fullscreen.svg create mode 100644 vendor/ely/assets/icons/gauge.svg create mode 100644 vendor/ely/assets/icons/git-branch.svg create mode 100644 vendor/ely/assets/icons/git-commit-horizontal.svg create mode 100644 vendor/ely/assets/icons/git-merge.svg create mode 100644 vendor/ely/assets/icons/git-pull-request-closed.svg create mode 100644 vendor/ely/assets/icons/git-pull-request-draft.svg create mode 100644 vendor/ely/assets/icons/git-pull-request.svg create mode 100644 vendor/ely/assets/icons/globe.svg create mode 100644 vendor/ely/assets/icons/grip-horizontal.svg create mode 100644 vendor/ely/assets/icons/grip-vertical.svg create mode 100644 vendor/ely/assets/icons/hand.svg create mode 100644 vendor/ely/assets/icons/hard-drive.svg create mode 100644 vendor/ely/assets/icons/hash.svg create mode 100644 vendor/ely/assets/icons/heading-1.svg create mode 100644 vendor/ely/assets/icons/heading-2.svg create mode 100644 vendor/ely/assets/icons/heading-3.svg create mode 100644 vendor/ely/assets/icons/heading.svg create mode 100644 vendor/ely/assets/icons/headphones.svg create mode 100644 vendor/ely/assets/icons/heart.svg create mode 100644 vendor/ely/assets/icons/hexagon.svg create mode 100644 vendor/ely/assets/icons/history.svg create mode 100644 vendor/ely/assets/icons/hourglass.svg create mode 100644 vendor/ely/assets/icons/house.svg create mode 100644 vendor/ely/assets/icons/image-off.svg create mode 100644 vendor/ely/assets/icons/image.svg create mode 100644 vendor/ely/assets/icons/inbox.svg create mode 100644 vendor/ely/assets/icons/info.svg create mode 100644 vendor/ely/assets/icons/italic.svg create mode 100644 vendor/ely/assets/icons/kanban.svg create mode 100644 vendor/ely/assets/icons/key.svg create mode 100644 vendor/ely/assets/icons/keyboard.svg create mode 100644 vendor/ely/assets/icons/languages.svg create mode 100644 vendor/ely/assets/icons/laugh.svg create mode 100644 vendor/ely/assets/icons/layers.svg create mode 100644 vendor/ely/assets/icons/layout-dashboard.svg create mode 100644 vendor/ely/assets/icons/layout-grid.svg create mode 100644 vendor/ely/assets/icons/library.svg create mode 100644 vendor/ely/assets/icons/lightbulb.svg create mode 100644 vendor/ely/assets/icons/link.svg create mode 100644 vendor/ely/assets/icons/list-checks.svg create mode 100644 vendor/ely/assets/icons/list-ordered.svg create mode 100644 vendor/ely/assets/icons/list-todo.svg create mode 100644 vendor/ely/assets/icons/list.svg create mode 100644 vendor/ely/assets/icons/loader-circle.svg create mode 100644 vendor/ely/assets/icons/lock-open.svg create mode 100644 vendor/ely/assets/icons/lock.svg create mode 100644 vendor/ely/assets/icons/log-in.svg create mode 100644 vendor/ely/assets/icons/log-out.svg create mode 100644 vendor/ely/assets/icons/mail.svg create mode 100644 vendor/ely/assets/icons/map-pin.svg create mode 100644 vendor/ely/assets/icons/map.svg create mode 100644 vendor/ely/assets/icons/maximize-2.svg create mode 100644 vendor/ely/assets/icons/meh.svg create mode 100644 vendor/ely/assets/icons/memory-stick.svg create mode 100644 vendor/ely/assets/icons/menu.svg create mode 100644 vendor/ely/assets/icons/merge.svg create mode 100644 vendor/ely/assets/icons/message-square-diff.svg create mode 100644 vendor/ely/assets/icons/message-square-warning.svg create mode 100644 vendor/ely/assets/icons/message-square.svg create mode 100644 vendor/ely/assets/icons/mic-off.svg create mode 100644 vendor/ely/assets/icons/mic.svg create mode 100644 vendor/ely/assets/icons/minimize-2.svg create mode 100644 vendor/ely/assets/icons/minus.svg create mode 100644 vendor/ely/assets/icons/monitor.svg create mode 100644 vendor/ely/assets/icons/moon.svg create mode 100644 vendor/ely/assets/icons/mouse-pointer-2.svg create mode 100644 vendor/ely/assets/icons/move-up-right.svg create mode 100644 vendor/ely/assets/icons/move.svg create mode 100644 vendor/ely/assets/icons/music.svg create mode 100644 vendor/ely/assets/icons/network.svg create mode 100644 vendor/ely/assets/icons/notebook-pen.svg create mode 100644 vendor/ely/assets/icons/octagon-alert.svg create mode 100644 vendor/ely/assets/icons/package.svg create mode 100644 vendor/ely/assets/icons/palette.svg create mode 100644 vendor/ely/assets/icons/panel-bottom.svg create mode 100644 vendor/ely/assets/icons/panel-left.svg create mode 100644 vendor/ely/assets/icons/panel-right.svg create mode 100644 vendor/ely/assets/icons/paperclip.svg create mode 100644 vendor/ely/assets/icons/pause.svg create mode 100644 vendor/ely/assets/icons/pen-line.svg create mode 100644 vendor/ely/assets/icons/pen-tool.svg create mode 100644 vendor/ely/assets/icons/pencil.svg create mode 100644 vendor/ely/assets/icons/phone-off.svg create mode 100644 vendor/ely/assets/icons/phone.svg create mode 100644 vendor/ely/assets/icons/picture-in-picture-2.svg create mode 100644 vendor/ely/assets/icons/pin-off.svg create mode 100644 vendor/ely/assets/icons/pin.svg create mode 100644 vendor/ely/assets/icons/pipette.svg create mode 100644 vendor/ely/assets/icons/play.svg create mode 100644 vendor/ely/assets/icons/plus.svg create mode 100644 vendor/ely/assets/icons/power.svg create mode 100644 vendor/ely/assets/icons/printer.svg create mode 100644 vendor/ely/assets/icons/puzzle.svg create mode 100644 vendor/ely/assets/icons/quote.svg create mode 100644 vendor/ely/assets/icons/redo-2.svg create mode 100644 vendor/ely/assets/icons/redo-dot.svg create mode 100644 vendor/ely/assets/icons/refresh-cw.svg create mode 100644 vendor/ely/assets/icons/regex.svg create mode 100644 vendor/ely/assets/icons/repeat-1.svg create mode 100644 vendor/ely/assets/icons/repeat.svg create mode 100644 vendor/ely/assets/icons/reply-all.svg create mode 100644 vendor/ely/assets/icons/reply.svg create mode 100644 vendor/ely/assets/icons/rocket.svg create mode 100644 vendor/ely/assets/icons/rotate-ccw.svg create mode 100644 vendor/ely/assets/icons/rotate-cw.svg create mode 100644 vendor/ely/assets/icons/rows-2.svg create mode 100644 vendor/ely/assets/icons/save.svg create mode 100644 vendor/ely/assets/icons/scissors.svg create mode 100644 vendor/ely/assets/icons/screen-share-off.svg create mode 100644 vendor/ely/assets/icons/screen-share.svg create mode 100644 vendor/ely/assets/icons/search-x.svg create mode 100644 vendor/ely/assets/icons/search.svg create mode 100644 vendor/ely/assets/icons/send.svg create mode 100644 vendor/ely/assets/icons/server.svg create mode 100644 vendor/ely/assets/icons/settings.svg create mode 100644 vendor/ely/assets/icons/shapes.svg create mode 100644 vendor/ely/assets/icons/share-2.svg create mode 100644 vendor/ely/assets/icons/shield.svg create mode 100644 vendor/ely/assets/icons/shuffle.svg create mode 100644 vendor/ely/assets/icons/skip-back.svg create mode 100644 vendor/ely/assets/icons/skip-forward.svg create mode 100644 vendor/ely/assets/icons/slash.svg create mode 100644 vendor/ely/assets/icons/sliders-horizontal.svg create mode 100644 vendor/ely/assets/icons/smartphone.svg create mode 100644 vendor/ely/assets/icons/smile-plus.svg create mode 100644 vendor/ely/assets/icons/smile.svg create mode 100644 vendor/ely/assets/icons/sparkles.svg create mode 100644 vendor/ely/assets/icons/spline.svg create mode 100644 vendor/ely/assets/icons/square-check.svg create mode 100644 vendor/ely/assets/icons/square-function.svg create mode 100644 vendor/ely/assets/icons/square-pen.svg create mode 100644 vendor/ely/assets/icons/square-round-corner.svg create mode 100644 vendor/ely/assets/icons/square.svg create mode 100644 vendor/ely/assets/icons/star.svg create mode 100644 vendor/ely/assets/icons/step-forward.svg create mode 100644 vendor/ely/assets/icons/sticky-note.svg create mode 100644 vendor/ely/assets/icons/strikethrough.svg create mode 100644 vendor/ely/assets/icons/sun.svg create mode 100644 vendor/ely/assets/icons/table.svg create mode 100644 vendor/ely/assets/icons/tag.svg create mode 100644 vendor/ely/assets/icons/target.svg create mode 100644 vendor/ely/assets/icons/terminal.svg create mode 100644 vendor/ely/assets/icons/thumbs-down.svg create mode 100644 vendor/ely/assets/icons/thumbs-up.svg create mode 100644 vendor/ely/assets/icons/timer.svg create mode 100644 vendor/ely/assets/icons/trash-2.svg create mode 100644 vendor/ely/assets/icons/trending-down.svg create mode 100644 vendor/ely/assets/icons/trending-up.svg create mode 100644 vendor/ely/assets/icons/triangle-alert.svg create mode 100644 vendor/ely/assets/icons/type.svg create mode 100644 vendor/ely/assets/icons/underline.svg create mode 100644 vendor/ely/assets/icons/undo-2.svg create mode 100644 vendor/ely/assets/icons/upload.svg create mode 100644 vendor/ely/assets/icons/user-plus.svg create mode 100644 vendor/ely/assets/icons/user.svg create mode 100644 vendor/ely/assets/icons/users.svg create mode 100644 vendor/ely/assets/icons/variable.svg create mode 100644 vendor/ely/assets/icons/video-off.svg create mode 100644 vendor/ely/assets/icons/video.svg create mode 100644 vendor/ely/assets/icons/volume-1.svg create mode 100644 vendor/ely/assets/icons/volume-2.svg create mode 100644 vendor/ely/assets/icons/volume-x.svg create mode 100644 vendor/ely/assets/icons/volume.svg create mode 100644 vendor/ely/assets/icons/wallet.svg create mode 100644 vendor/ely/assets/icons/wand-sparkles.svg create mode 100644 vendor/ely/assets/icons/whole-word.svg create mode 100644 vendor/ely/assets/icons/wifi-off.svg create mode 100644 vendor/ely/assets/icons/wifi.svg create mode 100644 vendor/ely/assets/icons/workflow.svg create mode 100644 vendor/ely/assets/icons/wrench.svg create mode 100644 vendor/ely/assets/icons/x.svg create mode 100644 vendor/ely/assets/icons/zap.svg create mode 100644 vendor/ely/assets/icons/zoom-in.svg create mode 100644 vendor/ely/assets/icons/zoom-out.svg create mode 100644 vendor/ely/assets/maps/countries.geojson create mode 100644 vendor/ely/src/account/billing.rs create mode 100644 vendor/ely/src/account/factor.rs create mode 100644 vendor/ely/src/account/keys.rs create mode 100644 vendor/ely/src/account/login.rs create mode 100644 vendor/ely/src/account/mail.rs create mode 100644 vendor/ely/src/account/mod.rs create mode 100644 vendor/ely/src/account/oauth.rs create mode 100644 vendor/ely/src/account/payment.rs create mode 100644 vendor/ely/src/account/profile.rs create mode 100644 vendor/ely/src/account/sessions.rs create mode 100644 vendor/ely/src/account/signup.rs create mode 100644 vendor/ely/src/account/switcher.rs create mode 100644 vendor/ely/src/account/team.rs create mode 100644 vendor/ely/src/account/tests/access.rs create mode 100644 vendor/ely/src/account/tests/billing.rs create mode 100644 vendor/ely/src/account/tests/mod.rs create mode 100644 vendor/ely/src/account/tests/sign_in.rs create mode 100644 vendor/ely/src/account/upgrade.rs create mode 100644 vendor/ely/src/agent/artifact.rs create mode 100644 vendor/ely/src/agent/changes.rs create mode 100644 vendor/ely/src/agent/control.rs create mode 100644 vendor/ely/src/agent/environment.rs create mode 100644 vendor/ely/src/agent/line.rs create mode 100644 vendor/ely/src/agent/memory.rs create mode 100644 vendor/ely/src/agent/mod.rs create mode 100644 vendor/ely/src/agent/permission.rs create mode 100644 vendor/ely/src/agent/previews.rs create mode 100644 vendor/ely/src/agent/progress.rs create mode 100644 vendor/ely/src/agent/registry.rs create mode 100644 vendor/ely/src/agent/tests/changes.rs create mode 100644 vendor/ely/src/agent/tests/control.rs create mode 100644 vendor/ely/src/agent/tests/environment.rs create mode 100644 vendor/ely/src/agent/tests/mod.rs create mode 100644 vendor/ely/src/agent/tests/previews.rs create mode 100644 vendor/ely/src/agent/tools.rs create mode 100644 vendor/ely/src/assets.rs create mode 100644 vendor/ely/src/buttons/bars.rs create mode 100644 vendor/ely/src/buttons/button.rs create mode 100644 vendor/ely/src/buttons/confirm.rs create mode 100644 vendor/ely/src/buttons/copy.rs create mode 100644 vendor/ely/src/buttons/fab.rs create mode 100644 vendor/ely/src/buttons/group.rs create mode 100644 vendor/ely/src/buttons/icon_button.rs create mode 100644 vendor/ely/src/buttons/mod.rs create mode 100644 vendor/ely/src/buttons/presets.rs create mode 100644 vendor/ely/src/buttons/quick.rs create mode 100644 vendor/ely/src/buttons/segmented.rs create mode 100644 vendor/ely/src/buttons/share.rs create mode 100644 vendor/ely/src/buttons/sheet.rs create mode 100644 vendor/ely/src/buttons/tests.rs create mode 100644 vendor/ely/src/calendar/agenda.rs create mode 100644 vendor/ely/src/calendar/allday.rs create mode 100644 vendor/ely/src/calendar/availability.rs create mode 100644 vendor/ely/src/calendar/card.rs create mode 100644 vendor/ely/src/calendar/chip.rs create mode 100644 vendor/ely/src/calendar/days.rs create mode 100644 vendor/ely/src/calendar/editor.rs create mode 100644 vendor/ely/src/calendar/event.rs create mode 100644 vendor/ely/src/calendar/grid.rs create mode 100644 vendor/ely/src/calendar/head.rs create mode 100644 vendor/ely/src/calendar/hours.rs create mode 100644 vendor/ely/src/calendar/mod.rs create mode 100644 vendor/ely/src/calendar/month.rs create mode 100644 vendor/ely/src/calendar/now.rs create mode 100644 vendor/ely/src/calendar/people.rs create mode 100644 vendor/ely/src/calendar/popover.rs create mode 100644 vendor/ely/src/calendar/recurrence.rs create mode 100644 vendor/ely/src/calendar/reminders.rs create mode 100644 vendor/ely/src/calendar/repeat.rs create mode 100644 vendor/ely/src/calendar/tests/editing.rs create mode 100644 vendor/ely/src/calendar/tests/mod.rs create mode 100644 vendor/ely/src/calendar/tests/people.rs create mode 100644 vendor/ely/src/calendar/tests/times.rs create mode 100644 vendor/ely/src/calendar/weeks.rs create mode 100644 vendor/ely/src/calendar/year.rs create mode 100644 vendor/ely/src/canvas/align.rs create mode 100644 vendor/ely/src/canvas/assets.rs create mode 100644 vendor/ely/src/canvas/autolayout.rs create mode 100644 vendor/ely/src/canvas/constraints.rs create mode 100644 vendor/ely/src/canvas/edit.rs create mode 100644 vendor/ely/src/canvas/export.rs create mode 100644 vendor/ely/src/canvas/flow.rs create mode 100644 vendor/ely/src/canvas/gesture.rs create mode 100644 vendor/ely/src/canvas/graph.rs create mode 100644 vendor/ely/src/canvas/history.rs create mode 100644 vendor/ely/src/canvas/inspector.rs create mode 100644 vendor/ely/src/canvas/layers.rs create mode 100644 vendor/ely/src/canvas/links.rs create mode 100644 vendor/ely/src/canvas/marks.rs create mode 100644 vendor/ely/src/canvas/mindmap.rs create mode 100644 vendor/ely/src/canvas/mindmap_view.rs create mode 100644 vendor/ely/src/canvas/minimap.rs create mode 100644 vendor/ely/src/canvas/mod.rs create mode 100644 vendor/ely/src/canvas/nodes.rs create mode 100644 vendor/ely/src/canvas/paint.rs create mode 100644 vendor/ely/src/canvas/palette.rs create mode 100644 vendor/ely/src/canvas/panel.rs create mode 100644 vendor/ely/src/canvas/plane.rs create mode 100644 vendor/ely/src/canvas/press.rs create mode 100644 vendor/ely/src/canvas/shape.rs create mode 100644 vendor/ely/src/canvas/style.rs create mode 100644 vendor/ely/src/canvas/tests/boards.rs create mode 100644 vendor/ely/src/canvas/tests/mod.rs create mode 100644 vendor/ely/src/canvas/tests/panels.rs create mode 100644 vendor/ely/src/canvas/tests/stale.rs create mode 100644 vendor/ely/src/canvas/tests/tools.rs create mode 100644 vendor/ely/src/canvas/tools.rs create mode 100644 vendor/ely/src/canvas/typography.rs create mode 100644 vendor/ely/src/canvas/view.rs create mode 100644 vendor/ely/src/canvas/whiteboard.rs create mode 100644 vendor/ely/src/canvas/wiring.rs create mode 100644 vendor/ely/src/canvas/writing.rs create mode 100644 vendor/ely/src/canvas/zoom.rs create mode 100644 vendor/ely/src/charts/axes.rs create mode 100644 vendor/ely/src/charts/burndown.rs create mode 100644 vendor/ely/src/charts/calendar.rs create mode 100644 vendor/ely/src/charts/cartesian.rs create mode 100644 vendor/ely/src/charts/distribution.rs create mode 100644 vendor/ely/src/charts/export.rs create mode 100644 vendor/ely/src/charts/flow.rs create mode 100644 vendor/ely/src/charts/funnel.rs create mode 100644 vendor/ely/src/charts/geometry.rs create mode 100644 vendor/ely/src/charts/glide.rs create mode 100644 vendor/ely/src/charts/layout.rs create mode 100644 vendor/ely/src/charts/mod.rs create mode 100644 vendor/ely/src/charts/network.rs create mode 100644 vendor/ely/src/charts/paint.rs create mode 100644 vendor/ely/src/charts/parallel.rs create mode 100644 vendor/ely/src/charts/parts.rs create mode 100644 vendor/ely/src/charts/pie.rs create mode 100644 vendor/ely/src/charts/plot.rs create mode 100644 vendor/ely/src/charts/pointer.rs create mode 100644 vendor/ely/src/charts/radar.rs create mode 100644 vendor/ely/src/charts/realtime.rs create mode 100644 vendor/ely/src/charts/relations.rs create mode 100644 vendor/ely/src/charts/scale.rs create mode 100644 vendor/ely/src/charts/schedule.rs create mode 100644 vendor/ely/src/charts/series.rs create mode 100644 vendor/ely/src/charts/stats.rs create mode 100644 vendor/ely/src/charts/sunburst.rs create mode 100644 vendor/ely/src/charts/targets.rs create mode 100644 vendor/ely/src/charts/tests/limits.rs create mode 100644 vendor/ely/src/charts/tests/mod.rs create mode 100644 vendor/ely/src/charts/tiles.rs create mode 100644 vendor/ely/src/chat/actions.rs create mode 100644 vendor/ely/src/chat/attach.rs create mode 100644 vendor/ely/src/chat/cite.rs create mode 100644 vendor/ely/src/chat/code.rs create mode 100644 vendor/ely/src/chat/composer.rs create mode 100644 vendor/ely/src/chat/conversations.rs create mode 100644 vendor/ely/src/chat/list.rs create mode 100644 vendor/ely/src/chat/media.rs create mode 100644 vendor/ely/src/chat/message.rs create mode 100644 vendor/ely/src/chat/mod.rs create mode 100644 vendor/ely/src/chat/params.rs create mode 100644 vendor/ely/src/chat/play.rs create mode 100644 vendor/ely/src/chat/projects.rs create mode 100644 vendor/ely/src/chat/search.rs create mode 100644 vendor/ely/src/chat/status.rs create mode 100644 vendor/ely/src/chat/stream.rs create mode 100644 vendor/ely/src/chat/tests/cite.rs create mode 100644 vendor/ely/src/chat/tests/compose.rs create mode 100644 vendor/ely/src/chat/tests/history.rs create mode 100644 vendor/ely/src/chat/tests/mod.rs create mode 100644 vendor/ely/src/chat/tests/welcome.rs create mode 100644 vendor/ely/src/chat/voice.rs create mode 100644 vendor/ely/src/chat/welcome.rs create mode 100644 vendor/ely/src/collab/annotate.rs create mode 100644 vendor/ely/src/collab/comments.rs create mode 100644 vendor/ely/src/collab/mod.rs create mode 100644 vendor/ely/src/collab/peers.rs create mode 100644 vendor/ely/src/collab/reactions.rs create mode 100644 vendor/ely/src/collab/remote.rs create mode 100644 vendor/ely/src/collab/share.rs create mode 100644 vendor/ely/src/collab/sidebar.rs create mode 100644 vendor/ely/src/collab/tests.rs create mode 100644 vendor/ely/src/collab/track.rs create mode 100644 vendor/ely/src/dashboard/alerts.rs create mode 100644 vendor/ely/src/dashboard/card.rs create mode 100644 vendor/ely/src/dashboard/controls.rs create mode 100644 vendor/ely/src/dashboard/events.rs create mode 100644 vendor/ely/src/dashboard/grid.rs create mode 100644 vendor/ely/src/dashboard/mod.rs create mode 100644 vendor/ely/src/dashboard/status.rs create mode 100644 vendor/ely/src/dashboard/tests.rs create mode 100644 vendor/ely/src/dashboard/tiles.rs create mode 100644 vendor/ely/src/data_display/avatar.rs create mode 100644 vendor/ely/src/data_display/badge.rs create mode 100644 vendor/ely/src/data_display/before_after.rs create mode 100644 vendor/ely/src/data_display/carousel.rs create mode 100644 vendor/ely/src/data_display/changelog.rs create mode 100644 vendor/ely/src/data_display/codes.rs create mode 100644 vendor/ely/src/data_display/comparison.rs create mode 100644 vendor/ely/src/data_display/feed.rs create mode 100644 vendor/ely/src/data_display/gallery.rs create mode 100644 vendor/ely/src/data_display/measures.rs create mode 100644 vendor/ely/src/data_display/mod.rs create mode 100644 vendor/ely/src/data_display/records.rs create mode 100644 vendor/ely/src/data_display/spark.rs create mode 100644 vendor/ely/src/data_display/stars.rs create mode 100644 vendor/ely/src/data_display/stat.rs create mode 100644 vendor/ely/src/data_display/tests.rs create mode 100644 vendor/ely/src/data_display/timeline.rs create mode 100644 vendor/ely/src/data_display/watermark.rs create mode 100644 vendor/ely/src/debug/disasm.rs create mode 100644 vendor/ely/src/debug/flame.rs create mode 100644 vendor/ely/src/debug/hex.rs create mode 100644 vendor/ely/src/debug/mod.rs create mode 100644 vendor/ely/src/debug/network.rs create mode 100644 vendor/ely/src/debug/session.rs create mode 100644 vendor/ely/src/debug/stack.rs create mode 100644 vendor/ely/src/debug/tests.rs create mode 100644 vendor/ely/src/debug/timeline.rs create mode 100644 vendor/ely/src/debug/variables.rs create mode 100644 vendor/ely/src/devtools/collection.rs create mode 100644 vendor/ely/src/devtools/connection_form.rs create mode 100644 vendor/ely/src/devtools/connections.rs create mode 100644 vendor/ely/src/devtools/contrast.rs create mode 100644 vendor/ely/src/devtools/datum.rs create mode 100644 vendor/ely/src/devtools/document.rs create mode 100644 vendor/ely/src/devtools/encode.rs create mode 100644 vendor/ely/src/devtools/environment.rs create mode 100644 vendor/ely/src/devtools/graphql.rs create mode 100644 vendor/ely/src/devtools/json_editor.rs create mode 100644 vendor/ely/src/devtools/machines.rs create mode 100644 vendor/ely/src/devtools/mod.rs create mode 100644 vendor/ely/src/devtools/monitor.rs create mode 100644 vendor/ely/src/devtools/queries.rs create mode 100644 vendor/ely/src/devtools/redis.rs create mode 100644 vendor/ely/src/devtools/regex.rs create mode 100644 vendor/ely/src/devtools/request.rs create mode 100644 vendor/ely/src/devtools/response.rs create mode 100644 vendor/ely/src/devtools/schema.rs create mode 100644 vendor/ely/src/devtools/socket.rs create mode 100644 vendor/ely/src/devtools/structure.rs create mode 100644 vendor/ely/src/devtools/tests/api.rs create mode 100644 vendor/ely/src/devtools/tests/formats.rs create mode 100644 vendor/ely/src/devtools/tests/mod.rs create mode 100644 vendor/ely/src/devtools/tests/tools.rs create mode 100644 vendor/ely/src/devtools/xml.rs create mode 100644 vendor/ely/src/documents/blocks/content.rs create mode 100644 vendor/ely/src/documents/blocks/edit.rs create mode 100644 vendor/ely/src/documents/blocks/export.rs create mode 100644 vendor/ely/src/documents/blocks/import/details.rs create mode 100644 vendor/ely/src/documents/blocks/import/mod.rs create mode 100644 vendor/ely/src/documents/blocks/keys.rs create mode 100644 vendor/ely/src/documents/blocks/kind.rs create mode 100644 vendor/ely/src/documents/blocks/media.rs create mode 100644 vendor/ely/src/documents/blocks/mod.rs create mode 100644 vendor/ely/src/documents/blocks/span.rs create mode 100644 vendor/ely/src/documents/blocks/table.rs create mode 100644 vendor/ely/src/documents/blocks/tests/markdown.rs create mode 100644 vendor/ely/src/documents/blocks/tests/mod.rs create mode 100644 vendor/ely/src/documents/blocks/tests/scroll.rs create mode 100644 vendor/ely/src/documents/blocks/tests/span.rs create mode 100644 vendor/ely/src/documents/blocks/tests/stale.rs create mode 100644 vendor/ely/src/documents/blocks/view.rs create mode 100644 vendor/ely/src/documents/contents.rs create mode 100644 vendor/ely/src/documents/counts.rs create mode 100644 vendor/ely/src/documents/diagram.rs create mode 100644 vendor/ely/src/documents/document/apart.rs create mode 100644 vendor/ely/src/documents/document/attach.rs create mode 100644 vendor/ely/src/documents/document/block.rs create mode 100644 vendor/ely/src/documents/document/block/check.rs create mode 100644 vendor/ely/src/documents/document/block/heading.rs create mode 100644 vendor/ely/src/documents/document/block/insert.rs create mode 100644 vendor/ely/src/documents/document/block/list.rs create mode 100644 vendor/ely/src/documents/document/block/quote.rs create mode 100644 vendor/ely/src/documents/document/block/split.rs create mode 100644 vendor/ely/src/documents/document/cells.rs create mode 100644 vendor/ely/src/documents/document/edit.rs create mode 100644 vendor/ely/src/documents/document/finding.rs create mode 100644 vendor/ely/src/documents/document/format.rs create mode 100644 vendor/ely/src/documents/document/format/clear.rs create mode 100644 vendor/ely/src/documents/document/lists.rs create mode 100644 vendor/ely/src/documents/document/look.rs create mode 100644 vendor/ely/src/documents/document/mod.rs create mode 100644 vendor/ely/src/documents/document/parse.rs create mode 100644 vendor/ely/src/documents/document/place.rs create mode 100644 vendor/ely/src/documents/document/point.rs create mode 100644 vendor/ely/src/documents/document/tables.rs create mode 100644 vendor/ely/src/documents/document/tests/attach.rs create mode 100644 vendor/ely/src/documents/document/tests/block.rs create mode 100644 vendor/ely/src/documents/document/tests/block_edges.rs create mode 100644 vendor/ely/src/documents/document/tests/cells.rs create mode 100644 vendor/ely/src/documents/document/tests/format.rs create mode 100644 vendor/ely/src/documents/document/tests/history.rs create mode 100644 vendor/ely/src/documents/document/tests/lend.rs create mode 100644 vendor/ely/src/documents/document/tests/links.rs create mode 100644 vendor/ely/src/documents/document/tests/look.rs create mode 100644 vendor/ely/src/documents/document/tests/mod.rs create mode 100644 vendor/ely/src/documents/document/tests/open_look.rs create mode 100644 vendor/ely/src/documents/document/tests/place.rs create mode 100644 vendor/ely/src/documents/document/tests/point.rs create mode 100644 vendor/ely/src/documents/document/tests/presses.rs create mode 100644 vendor/ely/src/documents/document/tests/reading.rs create mode 100644 vendor/ely/src/documents/document/tests/secondary.rs create mode 100644 vendor/ely/src/documents/document/tests/toc.rs create mode 100644 vendor/ely/src/documents/document/tests/tools.rs create mode 100644 vendor/ely/src/documents/document/visual.rs create mode 100644 vendor/ely/src/documents/epub.rs create mode 100644 vendor/ely/src/documents/find.rs create mode 100644 vendor/ely/src/documents/format.rs create mode 100644 vendor/ely/src/documents/history.rs create mode 100644 vendor/ely/src/documents/knowledge.rs create mode 100644 vendor/ely/src/documents/link.rs create mode 100644 vendor/ely/src/documents/markdown.rs create mode 100644 vendor/ely/src/documents/markdown/tex.rs create mode 100644 vendor/ely/src/documents/markdown/tex/tests.rs create mode 100644 vendor/ely/src/documents/mod.rs create mode 100644 vendor/ely/src/documents/modes.rs create mode 100644 vendor/ely/src/documents/modes/tests.rs create mode 100644 vendor/ely/src/documents/pages.rs create mode 100644 vendor/ely/src/documents/picture.rs create mode 100644 vendor/ely/src/documents/print.rs create mode 100644 vendor/ely/src/documents/reading.rs create mode 100644 vendor/ely/src/documents/render.rs create mode 100644 vendor/ely/src/documents/render/blocks.rs create mode 100644 vendor/ely/src/documents/render/math_text.rs create mode 100644 vendor/ely/src/documents/render/point.rs create mode 100644 vendor/ely/src/documents/render/table.rs create mode 100644 vendor/ely/src/documents/render/tests.rs create mode 100644 vendor/ely/src/documents/rich.rs create mode 100644 vendor/ely/src/documents/suggest.rs create mode 100644 vendor/ely/src/documents/templates.rs create mode 100644 vendor/ely/src/documents/tests.rs create mode 100644 vendor/ely/src/documents/thumbs.rs create mode 100644 vendor/ely/src/documents/todo.rs create mode 100644 vendor/ely/src/documents/toolbar.rs create mode 100644 vendor/ely/src/documents/tree/blocks.rs create mode 100644 vendor/ely/src/documents/tree/emoji.rs create mode 100644 vendor/ely/src/documents/tree/html.rs create mode 100644 vendor/ely/src/documents/tree/html_block.rs create mode 100644 vendor/ely/src/documents/tree/mod.rs create mode 100644 vendor/ely/src/documents/tree/sources.rs create mode 100644 vendor/ely/src/documents/tree/stack.rs create mode 100644 vendor/ely/src/documents/tree/tests.rs create mode 100644 vendor/ely/src/documents/viewer.rs create mode 100644 vendor/ely/src/editor/anchors.rs create mode 100644 vendor/ely/src/editor/buffer.rs create mode 100644 vendor/ely/src/editor/chat.rs create mode 100644 vendor/ely/src/editor/console.rs create mode 100644 vendor/ely/src/editor/cursor.rs create mode 100644 vendor/ely/src/editor/decor.rs create mode 100644 vendor/ely/src/editor/edit.rs create mode 100644 vendor/ely/src/editor/extensions.rs create mode 100644 vendor/ely/src/editor/filters.rs create mode 100644 vendor/ely/src/editor/find.rs create mode 100644 vendor/ely/src/editor/gutter.rs create mode 100644 vendor/ely/src/editor/hints.rs create mode 100644 vendor/ely/src/editor/hover.rs create mode 100644 vendor/ely/src/editor/ime.rs create mode 100644 vendor/ely/src/editor/keybindings.rs create mode 100644 vendor/ely/src/editor/keys.rs create mode 100644 vendor/ely/src/editor/layout.rs create mode 100644 vendor/ely/src/editor/line.rs create mode 100644 vendor/ely/src/editor/measure.rs create mode 100644 vendor/ely/src/editor/mod.rs create mode 100644 vendor/ely/src/editor/moves.rs create mode 100644 vendor/ely/src/editor/preview.rs create mode 100644 vendor/ely/src/editor/problems.rs create mode 100644 vendor/ely/src/editor/prose.rs create mode 100644 vendor/ely/src/editor/refactor.rs create mode 100644 vendor/ely/src/editor/row.rs create mode 100644 vendor/ely/src/editor/search.rs create mode 100644 vendor/ely/src/editor/settings.rs create mode 100644 vendor/ely/src/editor/state.rs create mode 100644 vendor/ely/src/editor/status.rs create mode 100644 vendor/ely/src/editor/symbols.rs create mode 100644 vendor/ely/src/editor/syntax.rs create mode 100644 vendor/ely/src/editor/tasks.rs create mode 100644 vendor/ely/src/editor/tests/chinese.rs create mode 100644 vendor/ely/src/editor/tests/history.rs create mode 100644 vendor/ely/src/editor/tests/mod.rs create mode 100644 vendor/ely/src/editor/tests/stale.rs create mode 100644 vendor/ely/src/editor/tests/wide.rs create mode 100644 vendor/ely/src/editor/view.rs create mode 100644 vendor/ely/src/editor/welcome.rs create mode 100644 vendor/ely/src/editor/writing.rs create mode 100644 vendor/ely/src/feedback/clock.rs create mode 100644 vendor/ely/src/feedback/confirm.rs create mode 100644 vendor/ely/src/feedback/messages.rs create mode 100644 vendor/ely/src/feedback/mod.rs create mode 100644 vendor/ely/src/feedback/notification.rs create mode 100644 vendor/ely/src/feedback/result.rs create mode 100644 vendor/ely/src/feedback/states.rs create mode 100644 vendor/ely/src/feedback/status.rs create mode 100644 vendor/ely/src/feedback/suspense.rs create mode 100644 vendor/ely/src/feedback/tests/loading.rs create mode 100644 vendor/ely/src/feedback/tests/mod.rs create mode 100644 vendor/ely/src/feedback/tests/states.rs create mode 100644 vendor/ely/src/feedback/toast.rs create mode 100644 vendor/ely/src/files/archive.rs create mode 100644 vendor/ely/src/files/columns.rs create mode 100644 vendor/ely/src/files/duplicates.rs create mode 100644 vendor/ely/src/files/explorer.rs create mode 100644 vendor/ely/src/files/grid.rs create mode 100644 vendor/ely/src/files/icon.rs create mode 100644 vendor/ely/src/files/item.rs create mode 100644 vendor/ely/src/files/mod.rs create mode 100644 vendor/ely/src/files/operation.rs create mode 100644 vendor/ely/src/files/preview.rs create mode 100644 vendor/ely/src/files/recent.rs create mode 100644 vendor/ely/src/files/search.rs create mode 100644 vendor/ely/src/files/tests/explorer.rs create mode 100644 vendor/ely/src/files/tests/find.rs create mode 100644 vendor/ely/src/files/tests/mod.rs create mode 100644 vendor/ely/src/files/tests/stale.rs create mode 100644 vendor/ely/src/files/tests/transfers.rs create mode 100644 vendor/ely/src/files/transfer.rs create mode 100644 vendor/ely/src/files/transfers.rs create mode 100644 vendor/ely/src/finance/blotter.rs create mode 100644 vendor/ely/src/finance/book.rs create mode 100644 vendor/ely/src/finance/calendars.rs create mode 100644 vendor/ely/src/finance/candles.rs create mode 100644 vendor/ely/src/finance/controls.rs create mode 100644 vendor/ely/src/finance/depth.rs create mode 100644 vendor/ely/src/finance/draw.rs create mode 100644 vendor/ely/src/finance/heatmap.rs create mode 100644 vendor/ely/src/finance/indicators.rs create mode 100644 vendor/ely/src/finance/labels.rs create mode 100644 vendor/ely/src/finance/market.rs create mode 100644 vendor/ely/src/finance/mod.rs create mode 100644 vendor/ely/src/finance/options.rs create mode 100644 vendor/ely/src/finance/overview.rs create mode 100644 vendor/ely/src/finance/payoff.rs create mode 100644 vendor/ely/src/finance/portfolio.rs create mode 100644 vendor/ely/src/finance/quotes.rs create mode 100644 vendor/ely/src/finance/renko.rs create mode 100644 vendor/ely/src/finance/risk.rs create mode 100644 vendor/ely/src/finance/series.rs create mode 100644 vendor/ely/src/finance/spread.rs create mode 100644 vendor/ely/src/finance/stage.rs create mode 100644 vendor/ely/src/finance/steer.rs create mode 100644 vendor/ely/src/finance/symbols.rs create mode 100644 vendor/ely/src/finance/tape.rs create mode 100644 vendor/ely/src/finance/tests.rs create mode 100644 vendor/ely/src/finance/tools.rs create mode 100644 vendor/ely/src/finance/trade.rs create mode 100644 vendor/ely/src/finance/wallet.rs create mode 100644 vendor/ely/src/forms/avatar.rs create mode 100644 vendor/ely/src/forms/card.rs create mode 100644 vendor/ely/src/forms/cascade.rs create mode 100644 vendor/ely/src/forms/catalogs.rs create mode 100644 vendor/ely/src/forms/check.rs create mode 100644 vendor/ely/src/forms/checked.rs create mode 100644 vendor/ely/src/forms/chips.rs create mode 100644 vendor/ely/src/forms/code.rs create mode 100644 vendor/ely/src/forms/color/dropper.rs create mode 100644 vendor/ely/src/forms/color/fields.rs create mode 100644 vendor/ely/src/forms/color/gradient.rs create mode 100644 vendor/ely/src/forms/color/mod.rs create mode 100644 vendor/ely/src/forms/color/picker.rs create mode 100644 vendor/ely/src/forms/color/swatch.rs create mode 100644 vendor/ely/src/forms/combobox.rs create mode 100644 vendor/ely/src/forms/date/calendar.rs create mode 100644 vendor/ely/src/forms/date/cron.rs create mode 100644 vendor/ely/src/forms/date/mod.rs create mode 100644 vendor/ely/src/forms/date/period.rs create mode 100644 vendor/ely/src/forms/date/picker.rs create mode 100644 vendor/ely/src/forms/date/relative.rs create mode 100644 vendor/ely/src/forms/date/rule.rs create mode 100644 vendor/ely/src/forms/date/time.rs create mode 100644 vendor/ely/src/forms/date/week.rs create mode 100644 vendor/ely/src/forms/date/zone.rs create mode 100644 vendor/ely/src/forms/expression.rs create mode 100644 vendor/ely/src/forms/files.rs create mode 100644 vendor/ely/src/forms/glyphs.rs create mode 100644 vendor/ely/src/forms/group.rs create mode 100644 vendor/ely/src/forms/hotkey.rs create mode 100644 vendor/ely/src/forms/inline.rs create mode 100644 vendor/ely/src/forms/input.rs create mode 100644 vendor/ely/src/forms/knob.rs create mode 100644 vendor/ely/src/forms/listbox.rs create mode 100644 vendor/ely/src/forms/masked.rs create mode 100644 vendor/ely/src/forms/mention.rs create mode 100644 vendor/ely/src/forms/mod.rs create mode 100644 vendor/ely/src/forms/multi.rs create mode 100644 vendor/ely/src/forms/number.rs create mode 100644 vendor/ely/src/forms/number/scrub.rs create mode 100644 vendor/ely/src/forms/number/tests.rs create mode 100644 vendor/ely/src/forms/options.rs create mode 100644 vendor/ely/src/forms/pairs.rs create mode 100644 vendor/ely/src/forms/path.rs create mode 100644 vendor/ely/src/forms/pattern.rs create mode 100644 vendor/ely/src/forms/picks.rs create mode 100644 vendor/ely/src/forms/pin.rs create mode 100644 vendor/ely/src/forms/radio.rs create mode 100644 vendor/ely/src/forms/rating.rs create mode 100644 vendor/ely/src/forms/search.rs create mode 100644 vendor/ely/src/forms/select.rs create mode 100644 vendor/ely/src/forms/signature.rs create mode 100644 vendor/ely/src/forms/slider.rs create mode 100644 vendor/ely/src/forms/stepper.rs create mode 100644 vendor/ely/src/forms/structure.rs create mode 100644 vendor/ely/src/forms/switch.rs create mode 100644 vendor/ely/src/forms/syntax.rs create mode 100644 vendor/ely/src/forms/tags.rs create mode 100644 vendor/ely/src/forms/tests/choices.rs create mode 100644 vendor/ely/src/forms/tests/colors.rs create mode 100644 vendor/ely/src/forms/tests/dates.rs create mode 100644 vendor/ely/src/forms/tests/mod.rs create mode 100644 vendor/ely/src/forms/tests/other.rs create mode 100644 vendor/ely/src/forms/tests/path.rs create mode 100644 vendor/ely/src/forms/tests/popup.rs create mode 100644 vendor/ely/src/forms/tests/stale.rs create mode 100644 vendor/ely/src/forms/tests/structure.rs create mode 100644 vendor/ely/src/forms/tests/tags.rs create mode 100644 vendor/ely/src/forms/tests/upload.rs create mode 100644 vendor/ely/src/forms/text/actions.rs create mode 100644 vendor/ely/src/forms/text/edit.rs create mode 100644 vendor/ely/src/forms/text/element.rs create mode 100644 vendor/ely/src/forms/text/geometry.rs create mode 100644 vendor/ely/src/forms/text/highlight.rs create mode 100644 vendor/ely/src/forms/text/ime.rs create mode 100644 vendor/ely/src/forms/text/mod.rs create mode 100644 vendor/ely/src/forms/transfer.rs create mode 100644 vendor/ely/src/forms/unit.rs create mode 100644 vendor/ely/src/forms/upload.rs create mode 100644 vendor/ely/src/generative/audio.rs create mode 100644 vendor/ely/src/generative/brush.rs create mode 100644 vendor/ely/src/generative/compare.rs create mode 100644 vendor/ely/src/generative/downloads.rs create mode 100644 vendor/ely/src/generative/embed.rs create mode 100644 vendor/ely/src/generative/grid.rs create mode 100644 vendor/ely/src/generative/hardware.rs create mode 100644 vendor/ely/src/generative/lens.rs create mode 100644 vendor/ely/src/generative/mask.rs create mode 100644 vendor/ely/src/generative/mod.rs create mode 100644 vendor/ely/src/generative/models.rs create mode 100644 vendor/ely/src/generative/playground.rs create mode 100644 vendor/ely/src/generative/prompt.rs create mode 100644 vendor/ely/src/generative/queue.rs create mode 100644 vendor/ely/src/generative/ratio.rs create mode 100644 vendor/ely/src/generative/seed.rs create mode 100644 vendor/ely/src/generative/style.rs create mode 100644 vendor/ely/src/generative/tests/canvas.rs create mode 100644 vendor/ely/src/generative/tests/data.rs create mode 100644 vendor/ely/src/generative/tests/mod.rs create mode 100644 vendor/ely/src/generative/tests/models.rs create mode 100644 vendor/ely/src/generative/tests/results.rs create mode 100644 vendor/ely/src/generative/tests/settings.rs create mode 100644 vendor/ely/src/generative/tests/sound.rs create mode 100644 vendor/ely/src/generative/tests/stale.rs create mode 100644 vendor/ely/src/generative/tuning.rs create mode 100644 vendor/ely/src/generative/variation.rs create mode 100644 vendor/ely/src/generative/versions.rs create mode 100644 vendor/ely/src/generative/video.rs create mode 100644 vendor/ely/src/generative/voice.rs create mode 100644 vendor/ely/src/git/badges.rs create mode 100644 vendor/ely/src/git/blame.rs create mode 100644 vendor/ely/src/git/changes.rs create mode 100644 vendor/ely/src/git/commits.rs create mode 100644 vendor/ely/src/git/diff.rs create mode 100644 vendor/ely/src/git/graph.rs create mode 100644 vendor/ely/src/git/history.rs create mode 100644 vendor/ely/src/git/merge.rs create mode 100644 vendor/ely/src/git/merging.rs create mode 100644 vendor/ely/src/git/mod.rs create mode 100644 vendor/ely/src/git/refs.rs create mode 100644 vendor/ely/src/git/review.rs create mode 100644 vendor/ely/src/git/rows.rs create mode 100644 vendor/ely/src/git/tags.rs create mode 100644 vendor/ely/src/git/tests/commit.rs create mode 100644 vendor/ely/src/git/tests/mod.rs create mode 100644 vendor/ely/src/git/tests/narrow.rs create mode 100644 vendor/ely/src/git/tests/picking.rs create mode 100644 vendor/ely/src/git/viewer.rs create mode 100644 vendor/ely/src/i18n/builtin.rs create mode 100644 vendor/ely/src/i18n/locale.rs create mode 100644 vendor/ely/src/i18n/mod.rs create mode 100644 vendor/ely/src/i18n/skip.rs create mode 100644 vendor/ely/src/i18n/tests/a11y.rs create mode 100644 vendor/ely/src/i18n/tests/mod.rs create mode 100644 vendor/ely/src/i18n/tests/shipped.rs create mode 100644 vendor/ely/src/interaction/mod.rs create mode 100644 vendor/ely/src/interaction/resizable.rs create mode 100644 vendor/ely/src/interaction/rotatable.rs create mode 100644 vendor/ely/src/interaction/roving.rs create mode 100644 vendor/ely/src/interaction/selection.rs create mode 100644 vendor/ely/src/interaction/sync.rs create mode 100644 vendor/ely/src/interaction/tests/limits.rs create mode 100644 vendor/ely/src/interaction/tests/mod.rs create mode 100644 vendor/ely/src/layout/collapse.rs create mode 100644 vendor/ely/src/layout/dock/mod.rs create mode 100644 vendor/ely/src/layout/dock/view.rs create mode 100644 vendor/ely/src/layout/floating.rs create mode 100644 vendor/ely/src/layout/grid.rs create mode 100644 vendor/ely/src/layout/mod.rs create mode 100644 vendor/ely/src/layout/narrow.rs create mode 100644 vendor/ely/src/layout/page.rs create mode 100644 vendor/ely/src/layout/panes.rs create mode 100644 vendor/ely/src/layout/scroll.rs create mode 100644 vendor/ely/src/layout/scroll_aids.rs create mode 100644 vendor/ely/src/layout/seeded.rs create mode 100644 vendor/ely/src/layout/sheet.rs create mode 100644 vendor/ely/src/layout/sidebar.rs create mode 100644 vendor/ely/src/layout/split.rs create mode 100644 vendor/ely/src/layout/stack.rs create mode 100644 vendor/ely/src/layout/surface.rs create mode 100644 vendor/ely/src/layout/tests.rs create mode 100644 vendor/ely/src/layout/viewport.rs create mode 100644 vendor/ely/src/layout/workspace.rs create mode 100644 vendor/ely/src/lib.rs create mode 100644 vendor/ely/src/lists/directory.rs create mode 100644 vendor/ely/src/lists/files.rs create mode 100644 vendor/ely/src/lists/grouped.rs create mode 100644 vendor/ely/src/lists/item.rs create mode 100644 vendor/ely/src/lists/long.rs create mode 100644 vendor/ely/src/lists/mod.rs create mode 100644 vendor/ely/src/lists/outline.rs create mode 100644 vendor/ely/src/lists/sections.rs create mode 100644 vendor/ely/src/lists/select.rs create mode 100644 vendor/ely/src/lists/sortable.rs create mode 100644 vendor/ely/src/lists/swipe.rs create mode 100644 vendor/ely/src/lists/tests/editor.rs create mode 100644 vendor/ely/src/lists/tests/keys.rs create mode 100644 vendor/ely/src/lists/tests/mod.rs create mode 100644 vendor/ely/src/lists/tree/mod.rs create mode 100644 vendor/ely/src/lists/tree/model.rs create mode 100644 vendor/ely/src/lists/tree/row.rs create mode 100644 vendor/ely/src/lists/tree/select.rs create mode 100644 vendor/ely/src/lists/tree/tests.rs create mode 100644 vendor/ely/src/mail/boxes.rs create mode 100644 vendor/ely/src/mail/compose.rs create mode 100644 vendor/ely/src/mail/labels.rs create mode 100644 vendor/ely/src/mail/list.rs create mode 100644 vendor/ely/src/mail/mod.rs create mode 100644 vendor/ely/src/mail/quoted.rs create mode 100644 vendor/ely/src/mail/reader.rs create mode 100644 vendor/ely/src/mail/send.rs create mode 100644 vendor/ely/src/mail/signature.rs create mode 100644 vendor/ely/src/mail/snooze.rs create mode 100644 vendor/ely/src/mail/tests/mod.rs create mode 100644 vendor/ely/src/mail/tests/read.rs create mode 100644 vendor/ely/src/mail/tests/sort.rs create mode 100644 vendor/ely/src/mail/tests/write.rs create mode 100644 vendor/ely/src/mail/thread.rs create mode 100644 vendor/ely/src/mail/times.rs create mode 100644 vendor/ely/src/maps/choropleth.rs create mode 100644 vendor/ely/src/maps/cluster.rs create mode 100644 vendor/ely/src/maps/coords.rs create mode 100644 vendor/ely/src/maps/geo.rs create mode 100644 vendor/ely/src/maps/geojson.rs create mode 100644 vendor/ely/src/maps/heat.rs create mode 100644 vendor/ely/src/maps/layer.rs create mode 100644 vendor/ely/src/maps/marker.rs create mode 100644 vendor/ely/src/maps/mod.rs create mode 100644 vendor/ely/src/maps/picker.rs create mode 100644 vendor/ely/src/maps/tests/layers.rs create mode 100644 vendor/ely/src/maps/tests/mod.rs create mode 100644 vendor/ely/src/maps/tests/popup.rs create mode 100644 vendor/ely/src/maps/tile.rs create mode 100644 vendor/ely/src/maps/view.rs create mode 100644 vendor/ely/src/maps/world.rs create mode 100644 vendor/ely/src/media/annotate.rs create mode 100644 vendor/ely/src/media/audio.rs create mode 100644 vendor/ely/src/media/camera.rs create mode 100644 vendor/ely/src/media/controls.rs create mode 100644 vendor/ely/src/media/crop.rs create mode 100644 vendor/ely/src/media/cropper.rs create mode 100644 vendor/ely/src/media/listen.rs create mode 100644 vendor/ely/src/media/marks.rs create mode 100644 vendor/ely/src/media/mod.rs create mode 100644 vendor/ely/src/media/model.rs create mode 100644 vendor/ely/src/media/player.rs create mode 100644 vendor/ely/src/media/record.rs create mode 100644 vendor/ely/src/media/scrubber.rs create mode 100644 vendor/ely/src/media/strip.rs create mode 100644 vendor/ely/src/media/subtitles.rs create mode 100644 vendor/ely/src/media/tests/audio.rs create mode 100644 vendor/ely/src/media/tests/devices.rs create mode 100644 vendor/ely/src/media/tests/edit.rs create mode 100644 vendor/ely/src/media/tests/images.rs create mode 100644 vendor/ely/src/media/tests/mod.rs create mode 100644 vendor/ely/src/media/tests/player.rs create mode 100644 vendor/ely/src/media/tests/stale.rs create mode 100644 vendor/ely/src/media/tests/video.rs create mode 100644 vendor/ely/src/media/thumbnail.rs create mode 100644 vendor/ely/src/media/turn.rs create mode 100644 vendor/ely/src/media/upload.rs create mode 100644 vendor/ely/src/media/viewer.rs create mode 100644 vendor/ely/src/menus/aim.rs create mode 100644 vendor/ely/src/menus/bar.rs create mode 100644 vendor/ely/src/menus/draw.rs create mode 100644 vendor/ely/src/menus/hosts.rs create mode 100644 vendor/ely/src/menus/menu.rs create mode 100644 vendor/ely/src/menus/mod.rs create mode 100644 vendor/ely/src/menus/model.rs create mode 100644 vendor/ely/src/menus/pie.rs create mode 100644 vendor/ely/src/menus/tests/aim.rs create mode 100644 vendor/ely/src/menus/tests/buttons.rs create mode 100644 vendor/ely/src/menus/tests/mod.rs create mode 100644 vendor/ely/src/menus/tests/more.rs create mode 100644 vendor/ely/src/messaging/call.rs create mode 100644 vendor/ely/src/messaging/channels.rs create mode 100644 vendor/ely/src/messaging/gifs.rs create mode 100644 vendor/ely/src/messaging/header.rs create mode 100644 vendor/ely/src/messaging/incoming.rs create mode 100644 vendor/ely/src/messaging/members.rs create mode 100644 vendor/ely/src/messaging/messages.rs create mode 100644 vendor/ely/src/messaging/mod.rs create mode 100644 vendor/ely/src/messaging/people.rs create mode 100644 vendor/ely/src/messaging/pins.rs create mode 100644 vendor/ely/src/messaging/receipt.rs create mode 100644 vendor/ely/src/messaging/status.rs create mode 100644 vendor/ely/src/messaging/stickers.rs create mode 100644 vendor/ely/src/messaging/tests/calls.rs create mode 100644 vendor/ely/src/messaging/tests/messages.rs create mode 100644 vendor/ely/src/messaging/tests/mod.rs create mode 100644 vendor/ely/src/messaging/tests/people.rs create mode 100644 vendor/ely/src/messaging/tests/pickers.rs create mode 100644 vendor/ely/src/messaging/thread.rs create mode 100644 vendor/ely/src/messaging/tiles.rs create mode 100644 vendor/ely/src/misc/calculator.rs create mode 100644 vendor/ely/src/misc/captcha.rs create mode 100644 vendor/ely/src/misc/clock.rs create mode 100644 vendor/ely/src/misc/consent.rs create mode 100644 vendor/ely/src/misc/cookies.rs create mode 100644 vendor/ely/src/misc/csv.rs create mode 100644 vendor/ely/src/misc/export.rs create mode 100644 vendor/ely/src/misc/flashcards.rs create mode 100644 vendor/ely/src/misc/import.rs create mode 100644 vendor/ely/src/misc/licenses.rs create mode 100644 vendor/ely/src/misc/mod.rs create mode 100644 vendor/ely/src/misc/poll.rs create mode 100644 vendor/ely/src/misc/quiz.rs create mode 100644 vendor/ely/src/misc/scanner.rs create mode 100644 vendor/ely/src/misc/stopwatch.rs create mode 100644 vendor/ely/src/misc/survey.rs create mode 100644 vendor/ely/src/misc/tests/asking.rs create mode 100644 vendor/ely/src/misc/tests/codes.rs create mode 100644 vendor/ely/src/misc/tests/drift.rs create mode 100644 vendor/ely/src/misc/tests/mod.rs create mode 100644 vendor/ely/src/misc/tests/notices.rs create mode 100644 vendor/ely/src/misc/tests/numbers.rs create mode 100644 vendor/ely/src/misc/tests/transfer.rs create mode 100644 vendor/ely/src/misc/units.rs create mode 100644 vendor/ely/src/misc/web.rs create mode 100644 vendor/ely/src/motion/changes.rs create mode 100644 vendor/ely/src/motion/curve.rs create mode 100644 vendor/ely/src/motion/effects.rs create mode 100644 vendor/ely/src/motion/list.rs create mode 100644 vendor/ely/src/motion/mod.rs create mode 100644 vendor/ely/src/motion/overlay.rs create mode 100644 vendor/ely/src/motion/particles.rs create mode 100644 vendor/ely/src/motion/progress.rs create mode 100644 vendor/ely/src/motion/reorder.rs create mode 100644 vendor/ely/src/motion/skeleton.rs create mode 100644 vendor/ely/src/motion/slide.rs create mode 100644 vendor/ely/src/motion/spinner.rs create mode 100644 vendor/ely/src/motion/tests.rs create mode 100644 vendor/ely/src/motion/transition.rs create mode 100644 vendor/ely/src/navigation/breadcrumb.rs create mode 100644 vendor/ely/src/navigation/editor_tabs.rs create mode 100644 vendor/ely/src/navigation/goto.rs create mode 100644 vendor/ely/src/navigation/history.rs create mode 100644 vendor/ely/src/navigation/menu.rs create mode 100644 vendor/ely/src/navigation/mod.rs create mode 100644 vendor/ely/src/navigation/nav.rs create mode 100644 vendor/ely/src/navigation/overflow.rs create mode 100644 vendor/ely/src/navigation/pages.rs create mode 100644 vendor/ely/src/navigation/palette/kinds.rs create mode 100644 vendor/ely/src/navigation/palette/launcher.rs create mode 100644 vendor/ely/src/navigation/palette/mod.rs create mode 100644 vendor/ely/src/navigation/palette/tests.rs create mode 100644 vendor/ely/src/navigation/steps.rs create mode 100644 vendor/ely/src/navigation/tabs.rs create mode 100644 vendor/ely/src/navigation/tests/mod.rs create mode 100644 vendor/ely/src/navigation/tests/pages.rs create mode 100644 vendor/ely/src/navigation/tests/stale.rs create mode 100644 vendor/ely/src/navigation/tests/tabs.rs create mode 100644 vendor/ely/src/navigation/toc.rs create mode 100644 vendor/ely/src/onboarding/checklist.rs create mode 100644 vendor/ely/src/onboarding/dialogs.rs create mode 100644 vendor/ely/src/onboarding/feedback.rs create mode 100644 vendor/ely/src/onboarding/help.rs create mode 100644 vendor/ely/src/onboarding/highlight.rs create mode 100644 vendor/ely/src/onboarding/hotspot.rs create mode 100644 vendor/ely/src/onboarding/mod.rs create mode 100644 vendor/ely/src/onboarding/support.rs create mode 100644 vendor/ely/src/onboarding/tests/flows.rs create mode 100644 vendor/ely/src/onboarding/tests/help.rs create mode 100644 vendor/ely/src/onboarding/tests/mod.rs create mode 100644 vendor/ely/src/onboarding/wizard.rs create mode 100644 vendor/ely/src/overlays/dialog.rs create mode 100644 vendor/ely/src/overlays/dialogs.rs create mode 100644 vendor/ely/src/overlays/floats.rs create mode 100644 vendor/ely/src/overlays/hover.rs create mode 100644 vendor/ely/src/overlays/lightbox.rs create mode 100644 vendor/ely/src/overlays/mod.rs create mode 100644 vendor/ely/src/overlays/popover.rs create mode 100644 vendor/ely/src/overlays/spotlight.rs create mode 100644 vendor/ely/src/overlays/tests/guides.rs create mode 100644 vendor/ely/src/overlays/tests/mod.rs create mode 100644 vendor/ely/src/primitives/backdrop.rs create mode 100644 vendor/ely/src/primitives/caret.rs create mode 100644 vendor/ely/src/primitives/disclosure.rs create mode 100644 vendor/ely/src/primitives/divider.rs create mode 100644 vendor/ely/src/primitives/files.rs create mode 100644 vendor/ely/src/primitives/focus.rs create mode 100644 vendor/ely/src/primitives/ghost.rs create mode 100644 vendor/ely/src/primitives/held.rs create mode 100644 vendor/ely/src/primitives/icon.rs create mode 100644 vendor/ely/src/primitives/icon/tests.rs create mode 100644 vendor/ely/src/primitives/image.rs create mode 100644 vendor/ely/src/primitives/layer.rs create mode 100644 vendor/ely/src/primitives/measure.rs create mode 100644 vendor/ely/src/primitives/mod.rs create mode 100644 vendor/ely/src/primitives/pressable.rs create mode 100644 vendor/ely/src/primitives/retired.rs create mode 100644 vendor/ely/src/primitives/severity.rs create mode 100644 vendor/ely/src/primitives/tests.rs create mode 100644 vendor/ely/src/primitives/tooltip.rs create mode 100644 vendor/ely/src/project/board.rs create mode 100644 vendor/ely/src/project/card.rs create mode 100644 vendor/ely/src/project/database.rs create mode 100644 vendor/ely/src/project/labels.rs create mode 100644 vendor/ely/src/project/marks.rs create mode 100644 vendor/ely/src/project/milestone.rs create mode 100644 vendor/ely/src/project/mod.rs create mode 100644 vendor/ely/src/project/moves.rs create mode 100644 vendor/ely/src/project/panel.rs create mode 100644 vendor/ely/src/project/pomodoro.rs create mode 100644 vendor/ely/src/project/roadmap.rs create mode 100644 vendor/ely/src/project/tasks.rs create mode 100644 vendor/ely/src/project/tests/boards.rs create mode 100644 vendor/ely/src/project/tests/mod.rs create mode 100644 vendor/ely/src/project/tests/time.rs create mode 100644 vendor/ely/src/project/tracker.rs create mode 100644 vendor/ely/src/project/work.rs create mode 100644 vendor/ely/src/project/workload.rs create mode 100644 vendor/ely/src/rendering/mod.rs create mode 100644 vendor/ely/src/rendering/surface.rs create mode 100644 vendor/ely/src/rendering/tests.rs create mode 100644 vendor/ely/src/settings/advanced.rs create mode 100644 vendor/ely/src/settings/appearance.rs create mode 100644 vendor/ely/src/settings/editor.rs create mode 100644 vendor/ely/src/settings/importer.rs create mode 100644 vendor/ely/src/settings/mod.rs create mode 100644 vendor/ely/src/settings/network.rs create mode 100644 vendor/ely/src/settings/preferences.rs create mode 100644 vendor/ely/src/settings/search.rs create mode 100644 vendor/ely/src/settings/section.rs create mode 100644 vendor/ely/src/settings/shortcuts.rs create mode 100644 vendor/ely/src/settings/storage.rs create mode 100644 vendor/ely/src/settings/syntax.rs create mode 100644 vendor/ely/src/settings/tests/appearance.rs create mode 100644 vendor/ely/src/settings/tests/mod.rs create mode 100644 vendor/ely/src/settings/tests/theme.rs create mode 100644 vendor/ely/src/settings/vscode.rs create mode 100644 vendor/ely/src/shell/activity.rs create mode 100644 vendor/ely/src/shell/bars.rs create mode 100644 vendor/ely/src/shell/chrome.rs create mode 100644 vendor/ely/src/shell/columns.rs create mode 100644 vendor/ely/src/shell/crash.rs create mode 100644 vendor/ely/src/shell/dialogs.rs create mode 100644 vendor/ely/src/shell/frame.rs create mode 100644 vendor/ely/src/shell/mod.rs create mode 100644 vendor/ely/src/shell/native.rs create mode 100644 vendor/ely/src/shell/status.rs create mode 100644 vendor/ely/src/shell/switcher.rs create mode 100644 vendor/ely/src/shell/tabs.rs create mode 100644 vendor/ely/src/shell/tests.rs create mode 100644 vendor/ely/src/shell/tests/border.rs create mode 100644 vendor/ely/src/shell/title_tests.rs create mode 100644 vendor/ely/src/shell/update.rs create mode 100644 vendor/ely/src/shell/vibrancy.rs create mode 100644 vendor/ely/src/shell/windows.rs create mode 100644 vendor/ely/src/tables/body.rs create mode 100644 vendor/ely/src/tables/builders.rs create mode 100644 vendor/ely/src/tables/cell.rs create mode 100644 vendor/ely/src/tables/foot.rs create mode 100644 vendor/ely/src/tables/formula.rs create mode 100644 vendor/ely/src/tables/grid.rs create mode 100644 vendor/ely/src/tables/gridkeys.rs create mode 100644 vendor/ely/src/tables/header.rs create mode 100644 vendor/ely/src/tables/mod.rs create mode 100644 vendor/ely/src/tables/model.rs create mode 100644 vendor/ely/src/tables/options.rs create mode 100644 vendor/ely/src/tables/pivot.rs create mode 100644 vendor/ely/src/tables/rules.rs create mode 100644 vendor/ely/src/tables/sheets.rs create mode 100644 vendor/ely/src/tables/simple.rs create mode 100644 vendor/ely/src/tables/table.rs create mode 100644 vendor/ely/src/tables/tests/chinese.rs create mode 100644 vendor/ely/src/tables/tests/clipboard.rs create mode 100644 vendor/ely/src/tables/tests/columns.rs create mode 100644 vendor/ely/src/tables/tests/mod.rs create mode 100644 vendor/ely/src/tables/tests/stale.rs create mode 100644 vendor/ely/src/tables/toolbar.rs create mode 100644 vendor/ely/src/tables/tree_table.rs create mode 100644 vendor/ely/src/terminal/ansi.rs create mode 100644 vendor/ely/src/terminal/block.rs create mode 100644 vendor/ely/src/terminal/colors.rs create mode 100644 vendor/ely/src/terminal/frame.rs create mode 100644 vendor/ely/src/terminal/history.rs create mode 100644 vendor/ely/src/terminal/input.rs create mode 100644 vendor/ely/src/terminal/keys.rs create mode 100644 vendor/ely/src/terminal/links.rs create mode 100644 vendor/ely/src/terminal/logs.rs create mode 100644 vendor/ely/src/terminal/mod.rs create mode 100644 vendor/ely/src/terminal/paint.rs create mode 100644 vendor/ely/src/terminal/processes.rs create mode 100644 vendor/ely/src/terminal/pty.rs create mode 100644 vendor/ely/src/terminal/search.rs create mode 100644 vendor/ely/src/terminal/shells.rs create mode 100644 vendor/ely/src/terminal/tests.rs create mode 100644 vendor/ely/src/terminal/view.rs create mode 100644 vendor/ely/src/theme/calendar.rs create mode 100644 vendor/ely/src/theme/canvas.rs create mode 100644 vendor/ely/src/theme/chart.rs create mode 100644 vendor/ely/src/theme/dashboard.rs create mode 100644 vendor/ely/src/theme/files.rs create mode 100644 vendor/ely/src/theme/generative.rs create mode 100644 vendor/ely/src/theme/interaction.rs create mode 100644 vendor/ely/src/theme/maps.rs create mode 100644 vendor/ely/src/theme/media.rs create mode 100644 vendor/ely/src/theme/messaging.rs create mode 100644 vendor/ely/src/theme/misc.rs create mode 100644 vendor/ely/src/theme/mod.rs create mode 100644 vendor/ely/src/theme/onboarding.rs create mode 100644 vendor/ely/src/theme/palette.rs create mode 100644 vendor/ely/src/theme/platform.rs create mode 100644 vendor/ely/src/theme/project.rs create mode 100644 vendor/ely/src/theme/syntax.rs create mode 100644 vendor/ely/src/theme/tests.rs create mode 100644 vendor/ely/src/theme/tokens.rs create mode 100644 vendor/ely/src/theme/tooling.rs create mode 100644 vendor/ely/src/tooling/a11y.rs create mode 100644 vendor/ely/src/tooling/events.rs create mode 100644 vendor/ely/src/tooling/inspector.rs create mode 100644 vendor/ely/src/tooling/mod.rs create mode 100644 vendor/ely/src/tooling/perf.rs create mode 100644 vendor/ely/src/tooling/playground.rs create mode 100644 vendor/ely/src/tooling/renders.rs create mode 100644 vendor/ely/src/tooling/tests/catalogs.rs create mode 100644 vendor/ely/src/tooling/tests/inspection.rs create mode 100644 vendor/ely/src/tooling/tests/mod.rs create mode 100644 vendor/ely/src/tooling/tokens.rs create mode 100644 vendor/ely/src/typography/copy.rs create mode 100644 vendor/ely/src/typography/effects.rs create mode 100644 vendor/ely/src/typography/emoji.rs create mode 100644 vendor/ely/src/typography/fit.rs create mode 100644 vendor/ely/src/typography/format.rs create mode 100644 vendor/ely/src/typography/formatted.rs create mode 100644 vendor/ely/src/typography/inline.rs create mode 100644 vendor/ely/src/typography/keys.rs create mode 100644 vendor/ely/src/typography/link.rs create mode 100644 vendor/ely/src/typography/math.rs create mode 100644 vendor/ely/src/typography/math/tests.rs create mode 100644 vendor/ely/src/typography/mod.rs create mode 100644 vendor/ely/src/typography/rolling.rs create mode 100644 vendor/ely/src/typography/select.rs create mode 100644 vendor/ely/src/typography/text.rs diff --git a/vendor/ely/Cargo.toml b/vendor/ely/Cargo.toml new file mode 100644 index 00000000..2dbff68c --- /dev/null +++ b/vendor/ely/Cargo.toml @@ -0,0 +1,134 @@ +[package] +name = "ely-gpui-component" +version = "0.1.1" +edition = "2024" +rust-version = "1.95" +license = "MIT" +description = "A restrained component library for GPUI, in light and dark." +repository = "https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components" +publish = false + +[features] +default = ["runtime_shaders"] +runtime_shaders = ["gpui_platform/runtime_shaders"] +test-support = ["gpui/test-support", "gpui/leak-detection"] + +[dependencies] +anyhow = "1" +base64 = "0.22" +barcoders = { version = "2", default-features = false, features = ["std"] } +emojis = "0.9" +futures = "0.3" +gpui = { package = "gpui-pre", version = "=0.3.8", default-features = false, features = ["stacker"] } +gpui_platform = { package = "gpui-pre-platform", version = "=0.3.8", features = ["font-kit"] } +image = { version = "0.25", default-features = false } +iso_currency = { version = "0.7", features = ["iterator"] } +isocountry = "0.3" +isolang = { version = "2.4", features = ["local_names", "list_languages"] } +jiff = "0.2" +log = "0.4" +markdown = "=1.0.0" +mermaid-rs-renderer = { version = "=0.3.1", default-features = false } +pulldown-cmark = { version = "0.13", default-features = false } +qrcode = { version = "0.14", default-features = false } +ratex-layout = "=0.1.14" +ratex-parser = "=0.1.14" +ratex-svg = { version = "=0.1.14", features = ["embed-fonts"] } +ratex-types = "=0.1.14" +regex = "1" +rqrr = { version = "0.11", default-features = false } +rust-embed = "8.12" +serde = { version = "1", features = ["derive"] } +serde_json = { version = "1", features = ["preserve_order"] } +similar = { version = "3.2", default-features = false, features = ["std", "text", "inline", "unicode"] } +smallvec = "1" +unicode-segmentation = "1" +unicode-width = "0.2" +usvg = "0.46" +vte = { version = "0.15", default-features = false, features = ["std", "ansi"] } +web-time = "1.1" + +[target.'cfg(not(target_family = "wasm"))'.dependencies] +alacritty_terminal = { version = "0.26", default-features = false } + +[target.'cfg(target_family = "wasm")'.dependencies] +jiff = { version = "0.2", features = ["js"] } +rust-embed = { version = "8.12", features = ["debug-embed"] } +similar = { version = "3.2", default-features = false, features = ["wasm32_web_time"] } + +[target.'cfg(target_os = "macos")'.dependencies] +block = "0.1" +cocoa = "0.26" +objc = "0.2" +raw-window-handle = "0.6" +wry = { version = "0.57", default-features = false } + +[target.'cfg(unix)'.dependencies] +rustix = { version = "1", default-features = false, features = ["std", "fs"] } + +[dev-dependencies] +env_logger = "0.11" + +[target.'cfg(target_family = "wasm")'.dev-dependencies] +gpui_web = { package = "gpui-pre-web", version = "=0.3.8" } +js-sys = "0.3" +wasm-bindgen = "0.2" +web-sys = { version = "0.3", features = ["Location", "UrlSearchParams", "Window"] } + +[target.'cfg(target_os = "macos")'.dev-dependencies] +core-foundation = "0.10" +core-graphics = "0.24" +image = { version = "0.25", default-features = false, features = ["png"] } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("cargo-clippy"))'] } + +[lints.clippy] +all = { level = "warn", priority = -1 } + +# The web gallery: small over fast, one unit so LTO sees everything. +[profile.web] +inherits = "release" +opt-level = "z" +lto = true +codegen-units = 1 + +[[example]] +name = "gallery" +path = "examples/gallery/main.rs" + +[[example]] +name = "docs_hello" +path = "examples/docs/hello.rs" + +[[example]] +name = "docs_start" +path = "examples/docs/start.rs" + +[[example]] +name = "docs_theme" +path = "examples/docs/theme.rs" + +[[example]] +name = "docs_focus" +path = "examples/docs/focus.rs" + +[[example]] +name = "docs_motion" +path = "examples/docs/motion.rs" + +[[example]] +name = "docs_icons" +path = "examples/docs/icons.rs" + +[[example]] +name = "docs_overlays" +path = "examples/docs/overlays.rs" + +[[example]] +name = "docs_i18n" +path = "examples/docs/i18n.rs" + +[[example]] +name = "docs_render" +path = "examples/docs/render.rs" diff --git a/vendor/ely/LICENSE b/vendor/ely/LICENSE new file mode 100644 index 00000000..f01d9946 --- /dev/null +++ b/vendor/ely/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ely GPUI Component contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/ely/assets/fonts/Inter-Italic.ttf b/vendor/ely/assets/fonts/Inter-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e7ed211d2d6052b781509fe7bf253951eac7162f GIT binary patch literal 417388 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Ç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 literal 0 HcmV?d00001 diff --git a/vendor/ely/assets/fonts/Inter-LICENSE.txt b/vendor/ely/assets/fonts/Inter-LICENSE.txt new file mode 100644 index 00000000..9b2ca37b --- /dev/null +++ b/vendor/ely/assets/fonts/Inter-LICENSE.txt @@ -0,0 +1,92 @@ +Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter) + +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 AND 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/vendor/ely/assets/fonts/Inter-Medium.ttf b/vendor/ely/assets/fonts/Inter-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..458cd0601d28013d3817481aa2839c9bbb5ded70 GIT binary patch literal 417300 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�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 z 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 literal 0 HcmV?d00001 diff --git a/vendor/ely/assets/fonts/Inter-SemiBold.ttf b/vendor/ely/assets/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..47f8ab1d68144fc004b310d65d95180d502b449b GIT binary patch literal 419744 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�# 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 literal 0 HcmV?d00001 diff --git a/vendor/ely/assets/fonts/JetBrainsMono-LICENSE.txt b/vendor/ely/assets/fonts/JetBrainsMono-LICENSE.txt new file mode 100644 index 00000000..8bee4148 --- /dev/null +++ b/vendor/ely/assets/fonts/JetBrainsMono-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +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: +https://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/vendor/ely/assets/fonts/JetBrainsMono-Medium.ttf b/vendor/ely/assets/fonts/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..97671156df256e850498054fdebcd41d74a65d6b GIT binary patch literal 273860 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%0AmA2ptU z`zE>nAom61RSJES+%Lg>(f9@2?Hnrke}!+GO8G0ueTdu#kfUPb4#01bdk){Qmpl)G zUO@b3$UVn#rG#VB4(AV%`vh6z7`ca(Wr+TQgvC7UWC}4?y7(RxV!;JnA8)qe6hId7 zpH%!}yi6D0UXyMP++UD{nNoidW*2!E%>;i!>LcO=Ur+EynWE^DGyX2hMPv|9wX_EK zVHr^-OG<=fiHQ9&RQnC_TrKI^Bb4qm8LB->Fh)CYjutX6w@@mR$elv&NOG?sId74i zVU*TT17#sTLX?rRbi{2WZ8U|BBuz#dQcpoVVOcK7Dar*dNB_gJgdp%LYvRn{~ zS|q}hJ6qNbQ7P+*2+KNyP}CwZi|8?SCI4jv$7L-742rf|>Z7eTehA8Z3LQ%>z7GXT z9myO^GRMj~DVEEU63Z#HgmkVVi~WxBl`rk1y-Dy)$)kNt|1|i+#2+RJizzSHk~@WR zG?H?34e<<>^0l`JE~C_kQmk^)^KL4URg~h}`VS!aM&m5pk>m=7e+J4#(yf>@kz*#T zK_xy|)+

  • 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