From cb3811945103b323f43188aa4350e91940fa83dd Mon Sep 17 00:00:00 2001 From: qqz003 Date: Fri, 13 Sep 2024 21:02:02 +0800 Subject: [PATCH] Add textFitWidth and textFitHeight Properties to Sprites (#2780) Co-authored-by: Xiaolian Qin --- include/mbgl/style/image.hpp | 31 ++- metrics/cache-style.db | Bin 19214336 -> 19214336 bytes metrics/ignores/platform-all.json | 1 + metrics/integration/geojson/grid-tall.json | 85 ++++++++ metrics/integration/geojson/grid.json | 85 ++++++++ .../textFit-anchors-long/expected.png | Bin 0 -> 22220 bytes .../textFit-anchors-long/style.json | 193 ++++++++++++++++++ .../textFit-anchors-short/expected.png | Bin 0 -> 4562 bytes .../textFit-anchors-short/style.json | 193 ++++++++++++++++++ .../textFit-collision/expected.png | Bin 0 -> 1265 bytes .../textFit-collision/style.json | 99 +++++++++ .../textFit-grid-long-vertical/expected.png | Bin 0 -> 7654 bytes .../textFit-grid-long-vertical/style.json | 191 +++++++++++++++++ .../textFit-grid-long/expected-mac.png | Bin 0 -> 16183 bytes .../textFit-grid-long/expected.png | Bin 0 -> 16304 bytes .../textFit-grid-long/expected_Alt.png | Bin 0 -> 16321 bytes .../textFit-grid-long/style.json | 182 +++++++++++++++++ .../textFit-grid-short-vertical/expected.png | Bin 0 -> 5686 bytes .../textFit-grid-short-vertical/style.json | 191 +++++++++++++++++ .../textFit-grid-short/expected.png | Bin 0 -> 2723 bytes .../textFit-grid-short/style.json | 182 +++++++++++++++++ metrics/integration/sprites/stretch.json | 13 ++ metrics/integration/sprites/textFit.json | 119 +++++++++++ metrics/integration/sprites/textFit.png | Bin 0 -> 421 bytes metrics/ios-render-test-runner-style.json | 2 +- .../stretchable-content/metrics.json | 4 +- .../icon-image/stretchable/metrics.json | 4 +- .../stretch-fifteen-part/metrics.json | 4 +- .../stretch-nine-part-@2x/metrics.json | 4 +- .../metrics.json | 4 +- .../stretch-nine-part-content/metrics.json | 4 +- .../metrics.json | 4 +- .../stretch-nine-part-just-width/metrics.json | 4 +- .../stretch-nine-part/metrics.json | 4 +- .../stretch-three-part/metrics.json | 4 +- .../stretch-two-part/metrics.json | 4 +- .../stretch-underscale/metrics.json | 4 +- .../textFit-anchors-long/metrics.json | 14 ++ .../textFit-anchors-short/metrics.json | 14 ++ .../textFit-collision/metrics.json | 14 ++ .../textFit-grid-long-vertical/metrics.json | 14 ++ .../textFit-grid-long/metrics.json | 14 ++ .../textFit-grid-short-vertical/metrics.json | 14 ++ .../textFit-grid-short/metrics.json | 14 ++ src/mbgl/renderer/image_atlas.cpp | 4 +- src/mbgl/renderer/image_atlas.hpp | 2 + src/mbgl/sprite/sprite_parser.cpp | 55 ++++- src/mbgl/sprite/sprite_parser.hpp | 4 +- src/mbgl/style/image.cpp | 22 +- src/mbgl/style/image_impl.cpp | 8 +- src/mbgl/style/image_impl.hpp | 11 +- src/mbgl/text/collision_feature.cpp | 63 +++++- src/mbgl/text/collision_feature.hpp | 55 ++--- src/mbgl/text/quads.cpp | 33 +-- src/mbgl/text/shaping.cpp | 39 ++++ src/mbgl/text/shaping.hpp | 4 + test/sprite/sprite_parser.test.cpp | 84 ++++++++ test/text/shaping.test.cpp | 122 +++++++++++ 58 files changed, 2116 insertions(+), 103 deletions(-) create mode 100644 metrics/integration/geojson/grid-tall.json create mode 100644 metrics/integration/geojson/grid.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-anchors-long/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-anchors-long/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-anchors-short/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-anchors-short/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-collision/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-collision/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected-mac.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected_Alt.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-long/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-short-vertical/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-short-vertical/style.json create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-short/expected.png create mode 100644 metrics/integration/render-tests/icon-text-fit/textFit-grid-short/style.json create mode 100644 metrics/integration/sprites/textFit.json create mode 100644 metrics/integration/sprites/textFit.png create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-long/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-short/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-collision/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long-vertical/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short-vertical/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short/metrics.json diff --git a/include/mbgl/style/image.hpp b/include/mbgl/style/image.hpp index 30206a740d9..35c42e8a39d 100644 --- a/include/mbgl/style/image.hpp +++ b/include/mbgl/style/image.hpp @@ -14,6 +14,12 @@ namespace style { using ImageStretch = std::pair; using ImageStretches = std::vector; +enum class TextFit { + stretchOrShrink, + stretchOnly, + proportional +}; + class ImageContent { public: float left; @@ -34,15 +40,26 @@ class Image { bool sdf, ImageStretches stretchX = {}, ImageStretches stretchY = {}, - const std::optional& content = std::nullopt); + const std::optional& content = std::nullopt, + const std::optional& textFitWidth = std::nullopt, + const std::optional& textFitHeight = std::nullopt); Image(std::string id, PremultipliedImage&& image, float pixelRatio, ImageStretches stretchX = {}, ImageStretches stretchY = {}, - const std::optional& content = std::nullopt) - : Image(std::move(id), std::move(image), pixelRatio, false, std::move(stretchX), std::move(stretchY), content) { - } + const std::optional& content = std::nullopt, + const std::optional& textFitWidth = std::nullopt, + const std::optional& textFitHeight = std::nullopt) + : Image(std::move(id), + std::move(image), + pixelRatio, + false, + std::move(stretchX), + std::move(stretchY), + content, + textFitWidth, + textFitHeight) {} Image(const Image&); std::string getID() const; @@ -63,6 +80,12 @@ class Image { /// The space where text can be fit into this image. const std::optional& getContent() const; + /// The constraints on the horizontal scaling of the image when `icon-text-fit` is used + const std::optional& getTextFitWidth() const; + + /// The constraints on the vertical scaling of the image when `icon-text-fit` is used + const std::optional& getTextFitHeight() const; + class Impl; Immutable baseImpl; explicit Image(Immutable baseImpl_) diff --git a/metrics/cache-style.db b/metrics/cache-style.db index b24c05547e149083cfe58def7df6af8fcbba7fe8..7fbe6a9aaad37639bbed9ccd6192e4e0c3819977 100644 GIT binary patch delta 3246 zcmaLYdpK129|!Pr=4Qr>`zXmIQdFC3+eJ5*Eh#m+u87KAt0+?`)tE`Okqr}5RJzEe zR*V@dWbIO7wI#-O`O!u!(rtHHDVu#CJ=<@ep8fs)c)g!<&OB!>@A-VcC-(7iPAnvi z)k-D^{Z#~^7fuj_X|mN!W-?*DwM-Fs)|4Hf^%@uTXUKTtuhX<%E0Qfq<)GOxmxYT{ zBsR)-)4I(_rLs#Xh@>kxN0l1i`H*bRCC*t+8qV}$&DmBQI)fHmEB%R3emE-naHRNf zRCqvDcUVwVG2xzPhc8YgALe%9oT~dOovZl2F!$6FdH0U4$OslFdr6x z6F7qlxWZ?!5Eg+OECzR20!zUImceomf+wtim9Pp{!x~r%pMw{y18?ww_23JBumLv0 zCh&&<2!tRAh7bsaFxU)VKsaoHtq=i`uno3D6o_C4?1Wtq4ZC3v#K2zI2m3(`u^<5{ z9Dq1D2#4S>d`(E@oU~_%h}&PBZrL+=yBo zN4Zg~D%TS0iZG|U(LzO{NJkr+kf4aoQ4w2hLbitmP7`ek54WaH38h>wPGuq=j8tir z@Fgm9ZF3FWAfV6txBK4TQY6!}H6w06+u0aKS3zhI4d=FJn4cFlY)WA)sg*x~F>fsjr2)E%5 zG{9YGgeFi!GyDYi;66NnhwvY0fmV0~Kf_~agLZfV9ncBCKo@jF4?Kllcm~hm1-yh; z@GJZVze6AN!yhmJuVE10z*`uCKjB@8Fmw1+Ig^Qhh@N5RLypOC@*(F^!OSS|CYcFB zAMzMbL8F3B1%nDE6)Y+=s9;mUp+b`iE)_f~w5ZUgLWc@nD)gw(r^0{=J{5*!rO;;- zd37~&9Cr4}$9RRKNW^F=jHnnxg)tRlsW72JK*cyJOsN=8g&A4ND>NtjGIh1^vlv`& zLOWke%G=KM#?xR4S1jdA9C(Bqi5CxeaTx6XJN-1%1U7qj()D11{?W3iklE=-ZFLV0 zyo=9vu<%H~nm((1EGv$l!M~Ds(}_Lo8@^(3pz5CDdmRSwk2-Hr=GGmKQv{#((lts z+wKjIiCNfsH#ju(tL`bShJ3%NO#x}Ou9JS>@g@60huGcQcMa=&k!|v<*17H02LmiO znR<{Zc&7%+Q0jiIo_@s5tRu>zJ8%krg74CWH)aSBC@Y&GI;v@Mk zf{c3ciCr(PO$Y4Rvjqz)m^+R?JTjE>{E!yd$$J zLKM;YjDSZoTr!Mv-S>5FYd%MYOV$tf4j-*J`y%wy>C@drsV_7&3sQT`mUe8l`90|4 zLRy~uT}Zu`SG3r?rn<_YsP>bY7FB7J1Hzt}IyAk?I+}3EG9+VqsnHGYePL(Thej+V zc09tFY9x;F-$wpryJAv<62ANz2IZfdSTFBYR99z8yZ^?GkNf)~IkZOcWT$5}-?J?8 zAMzX|{D5sqWKow2h@@9qZE;2U=mV#MFt{@D8KiN*0c_S+6W z@4QxVIi`2?l(^yHrc8s$YB%}urey-lY=!1>b?4fZ@uQ-)J;-jlYuCq* zPWU8mf647<8}d{?lx2_m(ZC^zZCW4oW@*HzEZaT8Tn1~}ft<^k^^Q4llZZ1n-(J0l zdPc@aD6!=ct|MjrV|+d;OFS|zEUK>Gg#WB-WcTirRccn*>edX*U)a+kwT_=3dzIsu z%RlUYfs>YXo$j;b=hlQt4eAB?-TadJUGk+bQ@XV3)+jUL#5+?Roj7%SB(|3{7g1pr%*-j ze_VsPj1p}R5(R|5U#`tE#pY^TU8h~*gAL)5X*prt>O2uQFf5^Nqkf*g(E}@uo$SE@ zKmCiv#^=%}3Cd3YeEL0l z5ZS&Wr`W1ApymcGE@+xsXtI<`A~23R z;iymr#}3j^Lx+dbKacu>s)eB>}x2HB(GFS zGR~4DDbNz$Ut1tWPnWA_lm+Of86I)z6=~H6HdI?8vj1F7 zg^OC_d>~z}G3KP`^3}!_YNL!!&_IC}PH=_}E^vh#^f1639`J+_Ug(T2=n8LiLwER~ z2YlfNfAmBE0uh8@gusMQJb^HTBLb0#!jtHQX!J%O#2^-Z@f4m$KlH}{JcBq4#2^gD z5X2(^Lop1AcoxI)97f=Iynq++5=J5kqmT?UMk58O7=y8R8RIY>6Oe{5B|jiJjA2Al+wo~`|L64vX4C>U3L}G z+AGsYa=P5>|8X^A5kxwPXhakdt%#F|vxrW_MZ{IaO++tZ5OEjr5b+c-ig<~17U?3= zRdyt&d&_&rXaiWA{fhKe-ZJSX(p|(yq=$&Fh@XhRNKcUfkwB3k*`cormhY50WOK0m zINssOaWmdhW-M$9k?WgGvTSza(R9+3OYZHO@@mUQjiWpyR37T)nb$Sfq?Zz9MKR=$ za#3`)Dx2!N%xSXUlm=n(rrNbfUGow=b8ZYd*nBEsT-2qOz6&B7@>@*I8ZU$w%+Crm+x=TRf=25udz@YpcWuL< zv01fA4=dVZ#+gDCv&KIDVrE)Wm8-R*rD4Ol-rC_#i6dsrY_$zul)ZmoSk%4zu@?P+ yc@@^%tB>E^cK_t<)|DJXsEk`4)JBqgMzL68&>>Fx%R zejodvH}l?`H?zC$&VrnK&Ue1=S4Whpvg{pf3hZmwuHBKBLq3IHJK^tGOmz5X(nJUO zwQHKu@<<7Fm+Ko%7zTRIhC7?nmlF<0gH!G=V&9C#R?U--?*>wtZR5+)s=hGS_KVH> ze6T5-{#fBR)>!Y`y1Duz>M|2odFnsz6ZO49G;viY)oSd_>EEA6oj&5Rv$Jc7LInrk zi&fOsohUJ$o161zB)WT7fIXqQy4tX-wXN-r0uv{vwbuW9>9OxgT;uQsR)rT+yJAau zOt*VyzurQ0uHOB5Nn<8=$?$#sxwNzsm0c>a5C8w)Y>8-1tb6(cQ{W;`j{O)HYJX2r z422VU?XT+HqvOUO?wC!_Jb1c1BtJgEc)UYxc2L!C!IG`gyA;i$X4&+`NsVHv&)wX^ z=>J;TWn(|z9Xhnjd*+G$_}a}lDJ$|s>^^@JyXqere=XOoxNr9P=qdkVO ze8*hP(QE}X!NZv?ljRRi|8DC0Kh^lC{VX;jT3e1?=~<2ABKz07VS@vc-VbKltey7q zTyJ-k65f?!veshmqn-(MYRt&{dOdio{Qz}aPU(lSs>3*m{>!7=z50(nT*Gl=2+FtJ zIMDw~`JzuxL9F}dkPX9Hic(*>)3ylO4KYQg+ffmiem?M#e*QgwU42>kfa_iJjV~RW zR5Qa5#g`?e?vR#;%D*z3hb0c%Zc-Lh)yWA`HXCpeC=hz9EfRHhu^X$Zykxd%IAv2# z6@8y=L3SYHC`=WVm1&|#LWJ$qdY-B{amw<<_h;?2>E=k>?y)E`FW(#ATWeGAr>?~# z6}Kn+MD0DFXmgTPS-!&>1gC9-G?G$t$_f)heo<0ZqFIq*3}>2g<$K(~)wv=1j>_uy zF?uM+Vd2;rp$0>aLAfB=+T>=j{pa0BYO`{ITKZ{8wt~o~k`%m59EjM*5y|oGpA1;O z-?q67Br^LOnWFZ6q11uper~I!6F%lYmY*fpM*~kq6RM9erJL*OwwO1>>aHiXHEooZ zk2x4KL}k6owfp#Nm*e~q$>;h1_V=yn^~;m!#&nxcNea&`yX1Zv_Wt@D!kQ*0V~JbJ zZhBAL^DoWn+UuOm0&<-TIir+9(eG0&_wM&_PfDP zPbZ}8((2(qyH4|o;PX(Ian=%7OqaRD$ST)8j^FIKMu!JZCHC_+ffPDIp-X?+%oAnU z)24m!Z`2N>3Ws=;0|}S zmS%Cs(%DOXMM%G3Ni)cH?(uNTdW3rvZZbB(j*t%^ObF>Nnk{j*XP}zoaCv8aP?p+L z@yLJvFRty(KTSvB1SkC$Kfk>x=8EYMfr7!LGq-$0 zi+}K{^f&Bp>n8!8+{{|P*FWQIe-qy4D9oB3ZW&$*M)SG;G@2K7aTz`KwTd$9%&Xjo zJW=zJB0}U1AGPv-*fi`Dm8vXNIZEEYzN%(qeil13udpMAiXd*J$rpqQcjUVB%qd5 z9PYjZhRVi_4(6Fg)ZhKEuGs=5sqvrTo<;g>I_n4GD3z=zP=N)~N9=?mbWM((hVgVQA*>A2Y-% z=hl9B$7AQEe$Tm~DLr~z{)ybHG4Fr@d0})v2E)HpldWytW~#)uq(iwfjM*)^v@z+( zehm!wY~xsKTd@jcWL~ZI8oL`WY3F(CzI*~-m0osHd8Ddfp!iH1&CcGQh`2=TA@Y{DCo!Ys zuV9-?vf!@v(Z-#dWka{CsdGdLvAT;M1tS-Zg#Fuu&WFE-0) ze0tz#-PeoJ-2C=;-C}(eYsb3bS2vO@A7+{7b38Tv0w1I-PY|JDZfXNAj1*;c=`KNN zJWKEeYg8nZ|y?qVl(q0C)daMSo*&iPNZ!X6;htK=yeOsHg zou8=*;}-Y*6uFni!0<5cEcq$BDVtbh+&2a0-xcdh8CR9^@cvCYM7Cz%D;P=I<%cHl zE}m%&2tmP$9Eds6mSdbEh3hb6NV$+E_d zUqD*c>vkU3@AF) zoV7nPS;6vC)p;yik=BXT z_yHUrB;>Iy9_`MEmz?gPTlP{lFK#giai=ub*;}W2-pd@~z%OLnIx-f!kv1*0>G#Uz z+?usJUtXctDECV$f3HAtMrQ3TrC~YwUW1L!`v~D@C=$$*8n{*2mFN?xo=~qFAva_` zs6(#?<;xT|Eap)p!XAdo?x>4>EZ6S?wr*X z>!xMrSA6l>e4dYlH2oQUTZ!;4ZYE~iF-T%&WUFX>Kft;TCzo!EuQb%Z9=c*8N+XlO z`>|vD6g@GU&ex!SBd?0*^$$Yt^lSO~w7%bs`51g#4+S?+>?udI!AlcTEX2szLx3-y z%!ADV!+-2TZ{K<7cv#8cODj_Uo|`1PL_4K*@1L&jH(dpXQ<6twcV&D~b%lg7AD_SC zc~KoX681W|K->@CJBew^TfzqMW8T5;+ZGoAV~=W3KGzp}3al_=|Fx|*%X1%Jd~+Y) zIT01yL`?|UQ3}xS(|vW~-)sN&((bHBKLnlkrTg6U)s{v8%=|eLC*w=zjWTA=w<#zRv(xjj^Yfz;Vms;;(mq)(5Py+XBbj<} z$$lDU-E37B6`3eyqWw@Uu6THN@5iO__sQ@sbEa5)?~bigbfE-k9P9uotEqER_b{v0 z#Vx5JK0ZF*2o`xeu7>7b3vInZ#no7UIZoVEXGh=*ru4irzkU9ey$lA%V z{9*heD9ZcEmkyepGNWOYJR#>mG+7=Kzs#;Kc0~T)W^T{@c05e~8}T8gMp$&6Px_df zB711zexFbk+x=U>trHV~Po8ebJ(k<6l+K!B*yVwlvxd7ja$;s~Ss#+0kEEwVq%&x? zd=>snHRhXvBva#wovXucj>LzXn*&XFbo3&sxsD)<$z*VRRNnce2zj1R$d`EEq12xD zwE>d>{I*4lgn)2gKe;UncbCkvZ}twQNIiyz#x6!(>)y!(PW5R7g6gBmJc`lRcPO@# zR%yt^ectAG$^64YQxOyCS1fE4p+l*G4`vv}dGS`}`%Ic9U#V_-W+18(IBZguyfXjX zmKD-0$Dl)dC9BN%pcc*Rd-oL>nQ%$HTAaQMoV{`nmCE<7;|2vP(CuCToL+lU~whAamIZmL@(E!O=^7 zy!)IR?vG4tSWcPMBS|@AXkL5|p4a)2qhpn-^DbI>HoM{0!FZ=)-z)Vov;()BK4pV@ z$8BuWpFhvDD!qxj|A0cOFna`jYO>NBDU1CdTBlA6&OO_BO5J#wbcI^6=*S$G&Il?u zJnzByV{ksFde+e=jfs-zl@swj`RCBdrZj7{gI4bKFez6re2c!A&!=5s^2~zY#8XO0A39^E#Y6Lb-2o;*g2*QSU=(j&qZ_G)2KkRq0``4HX|LcD5)!85 z{X3(s^Au2H%1p5PI7G%OP=M((<(r?kf}kpuoTc5ia!Z978#{4!tro9HR*k-O?^qO* zu4Fvk_v)xOOVq`eJE7Q_4hN`h|4vS3rrhFdP=9P2+5_rc|-T1YxUTX9Pj z&w2Yf4=;R4Y0i#Y$?cA%=ze`kLIxsLCf;xP|Ybb#qIsPV6qNoIfR)${b9^EkM|GAD70XpQKcv7--MofVFR) z-@i{LZTS?v^s4So*uJvs>~KlDl3aDV#B759{gV%Cuw*5n#Q+c}eIY_&QLP!!68pU~ z%FdU;@SEEU_@4;IEW;|{V_F`X$HfAwF9d_ce>KgIlL0ISP8k@*YNTiVNCkMq#rwFE z0;dY6hf&dLo%P+R-_5zWb1&Ak-_lGywwuC?ojRihM2xd|SgWS-k#{+KPet6#+koYL zmjRPNK_GebUGBFF>KRbYw(ci#Pvlze?(AfmHOjl2@qYM(r#-^!I-yIQ>V8}9%(YrL zGSxL%DcJM-_M?5lYT;vrbPI~BA|}Rts>T!Mo&3}&r9fO7h69jdh3Bs=HqDKZyINbi zXJnFcIKpbRX)QT#dE8nNOUgPj+m8jLEE4_uw&~V(x>Ayb-QTMU`i>cY=Bf%AduC$- z-mzk+Jg)(j zrd4{T-FU8H`GA_45Q_lk7BoXCjW%Prb>s_pF4{G_Lf&-Z0Q(>1btOP6`D969PEksj z+$Cs*_1~0$p+5O;v%*pL^WQl;YTXNIQ)T@Sz+y-gzFKo#>DF^77@i?}a@(VUUw^*W zj%(5e=$-9nSYB8q_BHc{@5h;sraNEF(6_H|R85^-D^u?K^titRc#}iXF(GIMatKA~ zRl)YKWXUH+!ai=NBCclh4)B}8jj@O#99-F2fBftr^d^|R-;FBMSqO-wnFz6l#wH~l z#!W0AP%f9AHuP5iusEo7>*os%Bs82HA%RjVq(*#Gvh<`8u(hQrxnLl8V!pReC&_(dEF$VZTr!K4k zYb|UshDXoH(UI+ydv>hXmG25w(u}v|Fq5j9Fm0iSCI4wl+P+B4HQA>zRctdhBEMsL zC1Dv(VR}o@q=>$$c&qygP{^voA=G+Dq;HsWRsE0mwc*m`+v$Q{2m$-)!3SKg_Xy$A zqWfUM6%c6DzlKe*#qYCVn(@DR(-8~L^3rOCjCd$rS)4|IBHDK^Dk{zdN3OILT4 z8&todA-*Uqsmu(1e4+p1IPIXut=jd(K6ZNVzHbDXWqX!1&LCeX(bv;|#|oFtU!=C9 zlJpccUr>)96*n1Ga>JG=72QF)dRQaq`uhVdH>+h{JRvPpR#7%3@PUz+C!c_crqZ}W zOf~rvh?hi^BXaDGa%@k18q$mv8nRzPG->IZX;uKJ6vD#k@6+}1r$zTHE^b(;D7#U+ z#E?B4Y2&*m!%b_()#<*~;c*%Fvct4=zwhNS2?`~o+t>ByX5F_XGZ56SR&1T%#4LqH zSACqli1RcC(>>g3Zfvx%uRX;^HA*~6Rj?B{#FcJ_lqU%-x+5paHM1s-srv9^Ze=eM zT#EknI}0XpT%Cprv>^UKp>}Vd`L@Tp!R?DgP^sm~ld~r}(7Y{(W`Vn<1Pk9@Ar(G# ztNz3L*ok$NabNcB>JyIQx_u&a-Fo(TI}B$|PaL1APC#&6*+$qk+HJbuo^}ss2Rj~C z3=EA*{0dJ!CxtD@Rb>HgOTV_doCfmVZdLd>P0*f8)AYKoQb+{)`UWvY05mjG->|@PwvBjt2u{ zLqER8DpWY}bA!(LeX{$=Yxm)S+kc$M7NH2R-(CDtWTO(T;bd$(61w+cR?Y&g?_)K3 zUj{ltN_iv}U4%)37LyOT&lKp7NDU2thJ9IeucENK(-+)&^_x9O4auMPX+S;NGXzlv zrdUP@I#Cyv#TBn-2_N-?kM_e_;k&hy5x+K>vW^*1y6QEbslcH~IeQ~v`CfH5jBmM( znzC+|xIWN&SDX)N*BudKR;~3fl_u%*_0D;Lt0^ptcGi(sF~}3r#CA^xK&$*=&J~@a z_Sj;U#h*|TAM+&eiDP!ej9j}pA8&GHuMD43i&dFXl`v=t0N=j3{Q-3e^`p!Z-RW<| z+6Z3!j7gS{TWs}oL7qq}=o0b0sr>EXiOL`uQR#8C@{s@hU8Kyv;pW55z!aSj8$4hj zGo%i)d#rk02{;l|R`Y~CYj=A&w5--abw41U$E(59O~!ot-}f4`3vG$hZ6n^v3PdMq zAVCW*D`Y0dwr{u~hO5n#pW#T^g|dL-R-Bzdy(t{qBZRsKh4Gu)_-|JOj#;_*0cnO# z1;@wn>ruxHSLEV((gQ-LhIIee9EUg>00Wn4PGrMUrdm!miz5@0gA-rlZ^GnFS~) zR#;^BlBn;10lno#h{%;-1Y-X2(Mu1%!h;(pdZHi>8u7(ziS27{m=d|5PHjLvng1fN zvSLlQhTQb*9ZoaOg&Np;`S~;O!(&4D@I)!f*;NGzKne)GzDrr!lbS}~3Llkre@>K`9hs!jQzRh%9-mO{ z_VPpv+_ztP!cC20=K^q<`X@)jpk`ZAJNFW9M>>gNI_UAxd_bW2xiZ++oWO|nfnwcU zW#;7wmypEt=UEBuEc?*)YS|X{vNu%|bP2VGByjm$?MOhsu zOTn@K6P-&f>XZ0Q3O@hf_L>By#8V?-U~%yR^SDp;WO-Pine~b8aPV)rMVH?V8yJ`j zDI9vHuiI9)+Fes)N$lIVCy$U9hMohmysCzuL=a)qCKWBLhlLJp6z-g|JAHJ=&&9dL zp@Rdbeu4hbY>W61Qc&euK{!ef+a-lb5vDw-rprYbZuVZn;{KRoeq!600`toHc82UT zSgMRACxb!=m1IPRG|qXl*oyOuLI3TR|T5Z z6KvL1XQ%mncWw$rfVY7EkrXuq3E`dQT!wt{WWZmH`tKc=K$8L34HbHU4~jBuk}6Z? zt!Mdu;q*P+ za(@8!OwI9MwX@-{#yP)d54dU#_(f=5-oE4y5C7QV^)p!@wsd`slbY(3MZDqM%*y2u zVYkh=uTyYyT85CYl<*g+J-ylek4O9R(Gh$f<6i4CSpsojk-2?OQYAf)!aMi#8RLt) zE`)dRqYO$1n!gm(2D;TOnWVn_doR2C<$QEIjr=DezQjNMl16!n*c1LeHYr#SuG0|| z1Rchh2XqGg+C@1O`7@h|b~!tH#RU{lw~Kt5SGVO>qwsE2XKtyY?+;9TNbBObky)p^ z&!f`oM)+k|m00ixvr++1l>ZK~WwU|{o)Y5|rmb`Rv)321&-(U$Ri$MVNbU4^nR`q; z+NYtoyl7i?wO(~VQuMV1hZ7xn^4M+XAXnV~zN{uo=<1zWJ{H__oqaw%8vp8y(PWQ$ zFbmUeoB2P>RomS@YNTLFD*CB(Au=xkE$?Haqo}1Ab4&M*g|ZPNYKf!%MehxxE7LWC zb0$XEHjwkl;=A9{cS{LBFUh94*$-x(-Lg~{lTAyMD#V$*wUH5=d;MX`+poz$GFzVz z{?u{%ntZFZB=CCs>Sz?Z-uwe??_WQ(&R^^~F$aDuC~&>#VrCY7u&*Qklo$S@k)`HH zaEPoqC`hP_%f0#LI(KpgRgQUwJO(}cM_~3M1OsM{_ZyFv&9WMKBHqs46}{fLfJ2SI}#{ktUQvX5#-Se zO&N##`Zs)K*yUM}2nLC+c4jps#bZp8;FaZiG|W(~LqYcHWU&*Fnz zm!jNmR7vMM;|7hDW`_{vJFtEyUP)7|5N1e>{s@tR8i{{qv?C5seKe`-^pRXlndE4f zuM)GtS`tp_u_a~%$CvR35DxevX3%o5Z$&r?gPtUbDHak)C^H0>GU{_aD+R@NrUeKV zEdzWXANQ*WQc4yJM6m3OXIoI@=YJaN!jaX`fF6;b56EYr+s&T{8v_gN9F&FlLijEk z86;L_9)(-|2d(`4jPzZxM1N&w-k1$M7if2_-vE!CcU0P@&+>6P)0DACf7Jip(-oXY z{f-Dk*Au;Za9P?`9Rff~rX$8R;v(zn<1}1aXbYj{M%~k{JtR?1oeclEwh$ct$PdKl zHRH|e{F|Oc(i&vI_V<6+Pty)0NEQO_#Z8-N8Vl|qw>>1p#^`#|H{W$iGv_t;dsTEp zsE#0Q`e)AeImOuOt=6>-3zN$Mj^uimkf{sK3{b)oG)2Rcm^dV1H?Yy(QHqy`M}NgI zU#$+B-j>c8icCoDsMy_4c;v|m;+XAUn(^k|o38dZf3B@jBpP%hOQJUAZr}+$ zItPlG{1*XG_mA+=Q}wwmSgidI17QY zTW37rm(96ZuHlxxUGIj#!P96StSfnyG~)~Z%PbIFGr*$LVv6=NV0m09#ay|6^6ll| zeOv@Dk55TzWEI7T_yFL0#IHNY)nd`h9#}kBuK?}J$AU6g zaa?pG^5-*wFZy&;?Jk|X90DH}-`kaUi&hiPI@NX49T-qBLSAsQ>%GkRaQUy7qE~## z<09SW6;Gn8*^oow_&4uB!glzyMwJAZCm=%wIUMFx4?0F(AsB=_Fp9o5u$MBo2C*_g zjp+Hb)qo2;+E08&ItqbEe-#mdHZMDkEDZZ%YV04uNM6v^)LL4eAnZvE^bM!lUAtyh z;8(Ip577Dqo{OtvWC~638A@%9*%f#eq2sU5KRD>=H#%~b%%*hrccsn4XYGAbP~gJ? z{cS*}=zM9PNHN619#}TVlPjj#-WE;?lK{T^0Qf`MmBc7qX z{%$uAS+q6pRv*g&Mg`B0{OT%fV_hLVmi%Tg6XLlo=*Gxz`L@tiZn!2Y0bsMA z+aTebU4H=5UyOh^=s@_|v8a!6dd;62K5**0><92w@^gXAW!+#QbUgMsUWpV|=gK6G z?A=v^W;pW3-H*dvb8g@LUnANL33ecA;xn&|S6xh1>OW@G5g@6AOMM_DvJCwJE_~c7 z5h<7J1||5Dy}sPMx zm4BuM#XaYGdFV7kL$SM^DKFb0`_O4wD)qZf7KFUlRSnIhiK4`dVV^RLDc7AF{1Ngv z4E-p<=Xkun2yt3hheE z;wrd!p;{t%U*>!KGDBDkmYNrbu2LaYIcY38q9~L`c?1GAyYZ+btbGI>M5CEB zSwbI>b?mcl(R(07@CqTK^i^RNnz49#wcnVnXkAih|9_vV$PyEN%2f)VxxaQ!FP#B}9hDr2xxU@_V7pO8|yve%H> z9Jov&38-NsGeKs{BZrd-I%9u)$p| z`KkQ>PVpCAk(!N^YNOk6#;Jdf5Oo#z3p<%Qd7!? zmj;R1)H%5O$>NH0HGHrh*>?FjyI?}X3wauu*gNkZ$KJsigt-Z20sRy@R!_13L3!7c z^MtqR8krX_sNkR^qj>#FKMn~_tG1}>H{JuEr4kJ^dzjjG2M5%SQDJbxku!30c(E}) z4VFTAU#w)_O1eMih5Z3Vv2?xP%|H5MYM&~)4}nh;GDhFVAOc83t{lP_ArI??4jni= zKHUW^NA|(Jcu}YO;1*DSpoI=_ov!4?26&wU_A3jxe0Pk+vVx!Ye#*rrN3CY%m=Y-r z@u_Rjkzw0@xj=vr)oQ3ddNA7`ZR4b-O z>4#u7B>zQ%7I5W5s$R{l?Q3AI46KJz3VjWRIuB$q#CDL~`RR2+|Hhx~Y{s5p`d`xM zK=D6{Uo>+*ie$V#YXbswzTasM(k(m?&l5T4c56!Fix$k{xMINhV<7-aIaYVd0p5IE zvEJOU16!cmKa|Su50$qimh=1OiOqw@cvn~N5Y!GnB@j8ww^x`vu0MDi99_3TSjLNu zFNr@qHLM8Rh}COs&x4&?ZyN$h8zRh;PPw0--41XFIXp_D?)%c5;d$E5oU+GrdCRtQ zG6)oq(V@M&Icc7Vp4c8RJTNQ?KANN)+%p3fX%uXop6Hvx>0Mz+3}C%7RgHNG0``!L z^LPOe+cMj~q9H6_BsEC*_#phl30Vy;VuQ=wBCxD`nAn68{NVF}?1gl#yQ%xSA+X5+ zxg-VgCWDTPhjLM^Fz>lw-rKulxU6o{42@5Rj*mlMWfIScS*-F10$+zbi-ln1%{xD+ z!>yV_2k5r5tqJFFPXRTCz*kyAI}2Q_U@kRSO1bi_g;TCRzuH@!8wLELeSpN&)ct^Q zw#?3)_IadCcqJi!g%dFi}wh)MTP3XsE@`S# zK+vrO4uL)K9UkDhPgfXiZG!Gca61>!dL+G}x`yGE+?Suv_mzKVsM+MfP_~-u;~>M{S*mSZ@;JW_y&FV*pVmRX zkAHhj0f-^h7?AV?Kmx|sn?qwov&$VXq`)t1Nzi(DTRy5J@y+idtm^u6KEBj> z%OUB?Ej>SF=KcQ7mw?CchbKpsFY~BL`)cCA;Df}$n4JN~^CZr_AK6v$hy8>Xlzd9B z&i{`7c6KBJk!_-MWrz%i$>znP2zihL6lqs-O24M=ALaPfQ`fs$88ss#@6-H}G&Gx{0~B)e-1o>D`*wOp)$p%VTuqZNF&8fMC&=>HjQ@=62rpUOBW>W`yjL>!`YaD@zNxW;M;PHY zjF1_+!l{GL%21H3^jMlIp2u^+^u6KuwyJD>M!4bRXJd9%6^8Y^^A?Sr_-8iO>Ngje z;Av!lNIuG2wY}hn#5{7D})@gIk!L?N?g)VZzOqA6<%mTpTW(I-@`Ta&`3KAeLr8(t(yN9|E<2 zLyTZMfNOkk8rQU4nlPmJk|Gs*n0pn*h#>dx9_kCyP;mg#1B%_=%H&Hr4x!-n|0aO; zfcev?!T-W_8*THt=DD-~65i>)u0cY?hR6)hHsh_hBqp?U6vfU#>APu)rH~V0;<{EpN=2j#Z#MBIAspm6e0CZEw-pc6qaEcV3qClh=vZ%9|w> zD86#bq5Tc6WE6Uq z$3m`9I9Ep?xQPWxjukui?_E1ZgWM%tKFMq3~4=Uh3d;0sVvj_Akbnf|7Tm#5J&aL9e(iXm*Zjdg>yaj+w1J@UMa6#r zg#!lz6YX8=Q;01N;Y)&_;_+$9wAo$%bGIkWio!pZ%1xcNZ*SPR)|4h{{&B--X$dfS zI4DNbV}!hH3<7Z# zNG!sg(7(%bC5Y;4AM#tEmmDGcaT_vu1whGMx( zE%{6Nlop|PzNOX;_&GPz+ZGNV*nsB+rff5ysw)n&e9toQi9&C)p~5GY;v0}s1JhSI zd91GjYoFZl%LVbQZN#q%oWVl$?|n2$8Az?KySJ{)8Bk2|rgs^kuiJ})b^`ecDZMuh z$mc5e)Z}}K!5e0Q?2{;8=vKp9FkbHX&Q#tC2kVGwAW{mm;Yw09 zb-44jq~R`A=-hl&FX^EE6{Wkh#GH<$wQOxr)vEIm|ByS(m^Xl9DhM1?CmnLogqw>pZOl%x!-Ac=2P6kwo+1%xp^rrRq zh%Z*ACNEgmD~rJ~TreeZ*f^jLOB<7Ahd3jo@tW~G5AT4npb8@(%a;#8o5Cr{TdEf- zT*R~xZ5$wphM&LaMxk@>H#kU=auDW!YyPGtncBA*eTZ5gj*tRknZ_qGLY|jeXHD+ddA1?mwRnE~4APo@O zAx@PISrG8xm}7x1K@|HxGYnukuv-YYqpkvi-*<~())?@`gMr5cQ58tPa>W4s?)dN! zz+24S=XOJ_I#8f>J0o~t@|QIafOrqd0SK*hOfe+kOJ1c7!PtR++0Gu%tG6X4S9+xi zJahlfLlC2WKze#$)!08D{F=QvR^2UqsMp)&1K#>Jw1g-K27w!N)p87u@7nz)Bn!hQ zbgREkCodNj#!^4kd3^E=GMj;5^F<**=!E#z z$(U<)-yIMsJZCAf`lE|kJd4MO53&_tC#4}WfVwcVq}1qG0=K%RY^Y(;U2yw9e%SsI99SsunjDX8!c=hy9;Ix4m zfiI~g{nmtl|&ln{iuyn#13Zy_scNfw> zC%_2XLgoxJbQ=N(B6#*=$#(rKUi!xhWK3vM`_Jd%fyP|%WTyOM@m^yOeHXc2bvr)lrd9EWf>}h0zFdW%JAL@Xp@hw3OaH3C>pK z_GDuEOdzRSau7oq`|_PQD4ewq!we}xTMy*-@82&pVDG|OZS7#(?@ze|gYZf3TYlb! zE!kKTc-aGS1V#3Q50h)g?DtXR6OM;Bac~X^Y2p-pp&1uAi#L_#<5_H5G7)2E44BIW zsl1ZhRS()@qQ|_^;`l<;d1~h&Yx~RI()@GyHY2WhmQGHS7srpDW?jd0bV#>~75t*- zf&niZvJfWtZ=QCUw2l#~s*#7bkg7cOpkRyhioS2+U@oQ;&@K9yiwqLM(W!~uS%V1( z<}6-PFtY}4v8}9$DrmZ0C&*y2@8bx!TUZc#(KiBk5M?VIMfRKvh1E9H|KvpmhhE7I z`9X8??2i??RpyM#Y!6;j!gf}x+Wkd~<_@0TTArnsM`_G4DPvdN;6+RyIt2H$4DyiuORVVITmj}O8v2@fRcnV3w~3Awqs zGoucIl7bVme0SMM(KP51^RY2=kQ+{wqyz{-Cg^n|a`NaAVp z3W>m7-qq}>Z9DGQQOx^Mm*nU%>S9XQ)H8nG5tB`*_(-gDCoTiGCU9*>Hx;+xXAai; zCwu|Fd!1%;;){!~DW2Q`|ECAN69crYxN z#B*2wLRz+zj}f@|nzJ^qZC~nEhc`;7h@H%`UO&{&VDG<-rMI|?-sGpZ(aQPuDf_08 zZ<}rwdJJEf|Cf2K6$&wFjjhuu-a$)Le0;o`e5*&S4E@%{HaFXAO6imvuRV+A4sF%A z6ATwe(Fmhy=q4V~q8XhM`zd_-f2-$jfz~_6hXgA1m&DUvb69J4hN^%4YsRINytimY zp9p+N&SL|;rO}%fzi5gp^u;{8+h=yphrMFrY~9bxPF5_JmV0E0cFGiwZeEOV@IGq0 zyc^$rmVCTnHPQ8B?<3B^@t940ih`0yb%Nxy{!)e;pd5`O5l-Ui(eDHcAiqOW5PL5EvH$rE)C3QVd*CDJgf^%?*%_8 zBM)wMrEoml{S&LPAzDqMM(n!LL^JP*;ASVr-JP1cvvFd38(u=9wMc*xLyUwUR=xNq zfaQKX5~;CiSh?Zi=O0UPLxRRo2q!-XVR1DxV_#Dv#A{;)>Ms6TPEGC$qx+zWr}rN~ zQ;|fznV0vhT?)Xdb{nub3~{^+@&Z`oW0;>`ax}yLc57Nr_WA9L_juBg1k!iHNW!_& zTYr4cF3$;dx|g=tzdO0&gx+wpV#7tzgR_4!VKwVEIXzGjdR;c^vV|vc3!SKU z>Z8xgOwW1G=AWmv!`qayC47yqvJjL|yq^?0N!mA~`T&E?+2QQqIBfs$h`FVF2yE#%+F8Gw znsvNEuB=Hjx0e@uHPZ;^q7roZ@6`@>l@!&E>^Gm7<-QhE+8-0fE>l2_Opf;68`poF z!~1E7T$Loj9Nqy0!W-BI*UM)RC(Br^aPuGLPc~>7S(ebKIs6l#Wqa&&CESm-P~ksn z`fRj}anE&s^6svS9>D!)tTaK(-I(On8S%!P1nLJU~n0w z87u>rc54FT)!oRCid`s!$CUX}H2X@V;6win`wEKLR^9At2(x1rWtnJsRFiuQhsex1 zR8))-#Y*W4t)ufi+t>QKWkD=$h$!#+A?19AC&SwNfO#rX5oBkdFJkmi6QsJHR174G zAJd1{RIf`%qOw`AZLIWK#=@As#5;-7P`ly*e&h>x#>6j4q(ZbZGGNkYj=eLuOdYP zK<(xs+H(k%7%W+Suu0(~i8a8r&N#j)Hqv;Gaf0C<|Ima$ZE_IynLc%nYq)4;lv+1h$c)X@qcvLfXz9nvEF6&F*>20|C^qBM@ zL6q`Uj(j3`Xq>eWg&(I_QBaeXu`N(2 z-n4{8^|c8@P8}ujR*DIN0hm>05havY`3;K-4{B7OVR<`urqT7gYX*zf=>Be?Q9OOB zB~bzT3xHWbgF-_tQ9p(-Y=6(ySgf8y%ESMw6JMFrs2k7I{c6wMN#N4GZR`8cp1$5; z{?}#G0Dpi$n>klxv|4M={o8Q!n4oh+OFXA}n?zKUHGlNrGNygx1&9w2pX|-!L9mVXQWy$z9DH(mioq9I%3hAQT|KKbB-O*+(F~PbNgH9D? z83NZaM&#>l%j}$DB6u*h`YlsE^&|oWwb++VG=R@b*1o-}tJ+q=c3>`X*-`?d1y<>h zna|2xfVVf_9*yRG9c(+mvGEU`xGlQIkU&d;(RDsyGqBAKznr)rETXytWFLU`RSAzi zkKrOkiD$xe<+t|2y8fYHY5GaB=m(f2J9|2fpYxZv;B{VcpOoDc(o{)L(ZcXni{vbR zabrD2m2;rZmt$;gi(|+vJL?EgKmHEff^p-%-UjV<37`HkH6XR*8XVEh8v2_ zM+%yo1ik*)KM`O^5UzoV0-Z3|M(kFDb%SVCV0@o*iT&MLu?b&&vxPM_YpG&ht{$45 zQt0x0UsJ#o!^c5qxu4t$rFa!vi60kfJ>l?r{CK9F@hB=WMp~)GPFJ3f z*I>wJnv7m3!Bl$6Z%q-WqTQ+$%TX5{^$Xlm3xeGt)j)e zv0Zn`Y9^8t&-?B^k%B1~g#>=}n=uB(G(MW(u`o58=1rGxc~EwQ^i|8TI?GHZuOD(Vke~D zy3rBr3f~M~VmI4vDmu7x_-uTjO+)+acq~e_VUP0p<*p??zn2N`+|X!?>Rqp&FoBJK zzHa>FRT98vs@HKCye)%|%mAvkSFpt(si6Uh%kjT;?O+y|O=g?Pt8~$^2aFxgnnukH z#q)VGy}PLwn1Np9jxTXdLjz^&9sr#OAdezzihRXf9V$2f$7`G7jLKOwz52~SZ#iGE z!;c3~fdMnn12$tb)9afha<^Dt{Zwief!a-uZjCFfFG$dMot9nt)!$-qU#sRUNvr2= zJ1}LK(ZCl?k3Mkx;!pmR{})r~jhXqn6=H6*@A5X2k6$4C@fZ>A?*pgnb`ZivA8aO$ zZtj(}+i?PX251K%aOysM)95>)xe~>^M&<1UKP~MHs@i7{Yj*v-&!p9LTU3rNVw~5e z=;m_Vy?%&m=-%8eo+}KL_bUR~c4YhMJ3AhDX!{xg3<@;f)6e<27qo)%+mnSLyo0GX?s>j*OJPXvtYrXss`U2qiD^*$BJMa+;@EuniZ?(@YH zsn%-9!~L}0Q24Z{YS-ikHX~R0Cm%yzUbC`gb?l!glQYIPzwu7YBuqdN$qWEAQc5?cSMi%H+o#sx^GfhK{B zstC!hDkjp<=wHQ&57p#(YCo`!bCr1>n3UAl#A<=@ymL|yi+-E=VL;A9UfBJQ*4Mw& zdHJG>)~4JbElI|<;M8D{fffOrrE+`hyRY345G5FkNI;s<5WzFPoxu_nt=+R>p-^o< zau}jM>KHU#czhk~0}-1u^u^C{h7ZSu;LQ?fI&+jLbL5@;eA~+Mgg5T`5GMp(7%cWS z;|i`)V{||StxHr7qJa)QF=7Imb|gOG3s&_*I=|)^;~73L>z`jm*;DxvdOJi=_+lv!TTaUwoqR>hI%9(G1rd{9k2Uc{J4f`_Gak#n@AXVTLSO zhAd^Dp|M_Fo{jV%lq>@ukCrNzrJot6R}43=SIsXU_nC*iC7Ua`4S1@3Bcks5&KHNSt>SFI9qU3 za`o@L$XI8unV9KTlgJS6a4Kc~kpU8;%-5vJYlNT(XUAvw0EfY1jY5ud_X{CAg)QeC zMk5*F8z}n|dmPqg0w(2=A(9ius_!3ZJR}LWXNR9xe(>X5OI5gI)alxLsU=`DFcv-Xe!+XD>tOG-rwCCuv21 z%W`gGLFj@X8S~#{gNb)w9n8Hyx{h@g@LJ| z6cJ!9bdXG~I{kqj|6RH4i<{aKWayPsQ%5getS}M6dRh_<;bP$kakP*rDS{XT;x*~W zoCMy%^5m56(Z6;_^I%S|`^?KW?C)ST7ar~!K(aG(UOabI>3A%13WE6cEhf;p zjR?X>=)|kI)IWe{FjX)IDBdm&JCc6|PbUKY3xEfRV29AmAF9D(J)V6mn?g}|=g{P5 zp7(!C&fVpOPn@5KPo&8wEvz;|3^qxzD8Fu28(Nb_on1lE0V3YQ)aTeRy8psz^SwcH zqNz;65g5#ZSl2-dl7%z`n&4rNXi|-FDB}u@dbz8>e+FEP;Hh`K>a?1V5q>xOd1HKV zZ18z8#tgBa02**-D*|ri^xxtIe#5L*VduJo4&OuFUZ7tAOrQ5i zswu5Ya+f>CH5y7Ea$T3r<=mzoXf>mN?lT2P4hEA5F~zU<}K0HsT`o5I{;N zE&@U4N`w{=ng`_{gn$BZ!F2gT^`z6YFci7p4oU1Et8#zmC|MO@*9gAYmJ;?>y{z#G3Tfb?;7&1F6J;E5SeMxux&>2DD3scDZ#I)_ z%~h8UDJaBB0Z$tQADSQ6aN*6hwE_sB(NJ_0<}u)w+M`i7r!n25JeS>PbB>ZjWn~hO zkV;FNmJW!`vN;ps7xkXkQ0lJy4SYTYTbye_QGmTrraw5pO5L?EcXbF4;su!L4(F*u z;|LkTuay_N6hVR;f-y&|Jy9Qy0v02t42n)i-P;Pmj1E}ALIXdn@UzO`2$4xinWvaXJ4!ryWM34Y&h2Vax9&nW657`H+=_+Ohsa_H6G9F(!Uc!1h9^0E)4%F-N9iE$g zcmNQC;5EVN0{o%*J>8G7dLXEbj(MO?bXVg--84^Wi{=eLa0MP> zW%%0xNHPJE0&r;S94=;GLnQ%#`^gzj3PsOXcCB@ei58Vt$Rbu!bF%sue-}}cGf2;} zNhNKb)yyk%AHEu8Y5 zi1DV8Wj3TaQaDuB_?>3}1WW?1owr6i{9*}O{#Lby7+m)LkMh} z%B;`zde?JwgVS0#p9TS_u4rjVU@EGx6AKA6^!11J(^r=FWFbt%XticUY~U1Zu5~wV zFcun{9Z8!v=v^L!U{fInE1{S>#ZJw3XlYfl{LWcjXSLhW-t7<3a};V(+YyCQeXNkC zr4lu!EkEeQ&UL+QpgnxJ{AJOmIY@E3U$)RX^<#LCw->`V6x;MV@pu3 zgl}kY_>~;Hz0%dJz|B+=a1IlD59`rmg~bJNjs2HTSj-ID-9`qaB~lKs<|7eSwwhl5 zWYN2Fx8o`~Cpu8roiFQO*-}YECHD+VBU#~|I?`e!npeMQ4Sra+v)o3V^p%!5bnyGP z_MdsdAA4=h6Vbr~R(JR%GkY6IG?KNKAtw;-a+e@2P(AZOW_~p+DZqR4qF=G}+^E&S zd5yc|m9Y2~&SvcPYORagNymn-8PDVZoKOHJeH-dw-Y+YQq)9mo*u?zyiPSW@5)FbZ z?zQwmgNeT6fi4|CM6T|Ntms3w=RP3Huf0=O9qB5mwP6YjL+uB?G<^>guM6wXv>yWb z2MZ!ddk_~iQ2Jy)IzFylI(}3u52D(0d_NCcLDMA=G*WKZmqNT+qNP6?Z2Ioen;lCY z4yuQxK#)FwwXg1qB9wwEI#_ag;t#%i2m6;WJ1pmZy6hq{#$xh@+R$k!NI9|uAN#Nm>}E%DN+JG5@0B}-TH zNk8T@!j+CfjfRWO$gzT9dw{o(BflFYFRC_(y#Rp?WM}vY3u+5kU}|u#K?_G=HgZ!wAsSq&j%BbGI(Nn&Yx^O z%PRZ(5o_G!EVV_i%x|HJdCw(RV9i;l>Mhf`u?u{V=Mb~VQ9cI9rlNfN7-(T2Ud;ya zN%fq6EW!!h29PoQq&s*R^OUAtv8Us>aC2UMK*|1$4WU1+2v@GuGWRri%L?Qi7g|W_ z@~OiN#b);u9gfmrB8d8MwU1UXs+yXfaYyY92a6l+3_S@igiBaM2c3ZS3An-D3@Bei z_6sL2BLs8jmn=Nz|M!YFgC^#(ZL6ZQ2ITk!1u+W$=UF<@e9|ZLORzj~2PfjJlU_+> zBF|0OsCqm&c{4?eNOCXadK}~XL^bMp4Zd*CLV(KMVQSuMF5!&vQYzHyoV?+De>Fq;{)FN3 z61yjFI=s1J*N!lktZhi?Y^oKGKwkOxcw})s*d7?S>FlL|!$eaMD!vu%Ksfh+`B1+6 zqWd0s)y-QT%vCkf6bV*+jsc25zyEV5DXv=tMaSuiw?@Xfb}Ma(3r{xUkz#SqY_lhx zR|iCL@#;5Pqq?$n&lOb}cd-C3$Jo9p5uu~Kb()gm)6jr5n(V0W^05RSKn?7aqf*_*K~=XhWLJkasXY=be51V0k( z=pYBO6qP&p{4}z2boCT=B}+y+X!{ewY7gY|7rwvXTOF|{sV|@M+CSor75~tKXI|gZ z@3|9BZ4%%lKG7U*YPOpDK4;LGlUj1_q;5+4(jY%|!F!4;uJQodYD_T#S(x(j{7!;E zkNc zGJlvh@qT&E8i>e=)L@b7By`-vPqOU%5=3`w#DEO z*lkx8csXuUvlVqHS;6yw@{>qj>7*_hj@Q8X_o5HEIUwHJc%BQD6btj|Gy;g9c{D$MW-bw&JOGeowWtt*y5KfrBI-W`PkFTYwQA_ zXxE!vK4#UcI>%>+Z{9u-CIGLi%?w_Z!=eJlR%yqCKdT!~e;NUSOR^L9&g4NHk`a{k(yivP^2rSUU9XfxH`f@Eu6Ls8Os!o%F) z%uY}ylY}t^!gqf2bUab;%yvDo{1jMDp{n?>ZSqLlHQ4HxG@|Cn#1sYXC>e0c45a51 zJ)uAN(ejRt6wPv{_&n9eIae=DciGU&8(qcS$^O;;P;e`^DTXdeMt}Q^_YmJ}Acf&l zKTnV8k&yLWdEat4*C|a&9E(ZGcMWDhN4!Zk4QYxSugK|7JM-r<$}R*uB5*u%wG{ch zan9G{n`!nQt4oRfwRe%6+rnBy$TZVh#_EE9Z|)cHSGnVKo0_W69nE~!XP86U)Fw)A(=|W%(Q*xK-|TGJ%!hOwYU851i;rwE0>VboajK?lHo^&>BO{UE^Ve z4C+Cor2p_p-C9wwe+{L|7wqkjOIh+7aF;ncP%pOfRx-__HUG`yX7W>Bh$^R7q)_F0 zUr5C-2DUA04X-r2F+Ee#R&F(T#_e2Nu~=LDJYB39=fK8#@W9%#A0Ov1Ka%wfYy$?q z#U+R%Z$c~xGs?oVwdny|^d3AL-44Dxys_^3qg<*$^VQr?(i9B)YPSP%l2MB$gt%T@ z#=z?lEhMg>rDcQ08cK#Et>6VXGkwSzd}n}y76zAnm2kaoaM=C0Nwryf`fi+8#JA!S zpXysX?q|A*#XrK;$RYz&g;>A6?5y=4up@Tb>3-bs^BuGMNvKJ+j8u$9Cl1EK=~V=M zBC$AjPu_nrEG1jNH*oZo+mgbg^x$PfVfJPcUx%y04a{DkxVwgR^lYcd&GzahK)Qy+ z_fKuflC*e*T8;(l(4$8ei>AYzDGh!`ZFCiAnYJqwunzApnrV5#H?IO*G*>@HGy&?O z%o}eeQa0q)S2q7Fj;$4!?!-kG#;%jl7wOc{#cB78@){a5(kPCgGd^LYma-keEt=`a zYLi^i4sKO+2=8GZk46Q50xi(NG?n&HzH_`@!2RBGy&ofZ?(H&oJM5}bhgp+_$$P@v z);wPC2|2>2R8S#|v3?BjM>*fA+>dc97$#f2kh@)63#(W}@BKjTMIelAw(FCVjU?du z!n#g9Lj9_H1_#91g&R?~EZ(Bq;wp1o@tI%npHkssmt3Q%uL*F`>ld*8F0WEHQ?>=d zR{-IIe~729ptG!0?ANDep!$xCG>;7l4w}xrT0S~%zO0Ysv?TBA`#(T*jCubtaWMK3*&u1pvQ?e#rc-fG~;9i3waB0Rw~lU0`>UizU`jqWNor4g;iH4>((yzHB89qBl=jsn)WTF@Fs@wVvE*y(kMMN*sLSW+#5`u+Ydht4U zT;?pA)itNx#6m|cfGw|qF&cQS!v0sL&_$>e)JrR{av@h$W{MDxlzCD%-(l>1eERa6 z0EXRb@_?UACsau3;GS3onlP5_@mhb>P%}~BO^~s$g+gxJv^6iw6}TQ)KPH@!`lng- z5{IUYNQa3<-yApv2zF*lcb^s(3qogayXBocZC)8Fzfn4_5QPzD>L^{ew%MDmOdfBM zgf_RrR*Nu1p=9c45FwbIFI_QTTKL0wH_mMehc?8v@|Y24ax~j-c&%iP6?fZlRuog} z7jn(zgJUb|3lBJG0<9yz7f8u82U==FjXCB7TVA{;rSMt*6j|@RJY2Tu2Q1%_mHo6Z zygt#9B_P-N$|L1fMq*!Qd8q~nO)gXA%$~-=R*;h4P{b70Zc}U`|5GJ?jjZ>sf6B@B zPiB_^-AFPE7u|sDx!l>SmLHyk$fslH%pltp%|~uiUQYg3hlE*aK|XuhPEGf+lk%-+ zrVvuua(?PyDAbVyCvHRAt&&Wh0+(9)Q8-jn5EY+bsnVP_7n0Fxea<8wtkBnY93=OB zU+!gH(DCN8RZjNXg$${=!>6%L3GFnLwckd#<*T+x9|fC*O&46I!1Mn_M<5sl8Lyxc z-Od=dhe1G9%1P@}C3(4wrIj|h+}*GnpL>*^ZHI1)+wTHJSIjkPYXc}PJmz}#Ww3_B z<>5VgWZ|KD3ux-MG?#g7;qf-FW~S zLuLUx`TV55az_@o-EWJ}`^7J*lOz{VoOQOS35s1@?M`i!e`yO-C1NNq@?LQ z!W6%hqgONX8}7OxVEHYd;Xk=zd4~irA2kN}*{|6BE`PYOlPD|&<5#NWl8McFUWtp$ z+IYZ^_H+MU_ru~_iL90KI?5d;B~oJ{8E|CU)1x<-XQkMEKN(UZ;a&IUNR25~t`EPX zRe96E4Arqnrk@UW^Xc&Dg?HXN6Q4fB)ZmHQ3gobNeuM@|mlm<;LmEU+g(%lMKJ zqYY~KPu@kd_-b`p$;j{DKbPpYvsiH&JG#XL;}|F1{`N@nvh$Q)A4V;L26-D8Bpo)K zv*@Oa=9+%YFso8XTbdNondk{v^t%OIZ2a-cm76Fr==3M3QlU8i;{b*^Lm6wcF+<2o z8ZJhB)$myM2_kM@sF$R}3{2x_CRM{Y(QC5PU&9jTAARR#2>Rt^A}S`PP@ulLO?kf> z;$Ya@o?vZ=Y|b-)NZ^8|!xB~_vOdv&dH3J2)xR+8xqgju=^^BhIi|y#wuLiE(}^v% z(QxQTRZ~q0vV!R)EG1ivZX?`oBmrF81WuTOO`n85- zgo}{)^BNX2k;;pf(M+5dr=jTK9|A!@^y+=()6@ua%? zbKKD9r(@D^ci7If?FOMf{?{s=@u3diH4b|XzfSgW$+)9oB6(t`OrR&yPko%z^aS^) z9vvU8L>-YS5^++!;a2hm)e>X4$(W-0>O&NOmhz~b?(pL8FIj_3id$RWN#hPY5A90s zS5400sSHBEQ$Z2g!Y3)1(&cKRa;W6-99W`W8Xfe{%`SBqhb-(QG8EH9d19Ydr9cHo z3X2)&w-zTCL%w{(-WY1pQ5P)j**z|W8FS$(?2geLqer?UZ@n25<@f0Ypl^uXlOJBg z;&5o?UzIlZZN*=v^??}6ZW;&e?*`9I^|9i+k`i+|+7k{7SipM8`IKyQe0&NoTNJ1m zsgEvC+s5)b#x;EfQL@ls#*eS=&Qi%$$0y2otQIh}I$*)_!%g`olNZQ8D~wcIg=jtO$!g> z{>U3B7coA5&C^RDJw3gZ0KZBhP>|Ee_XN5?`DXU=o!O+~!SK_WZIF=un6N z&{9+h(+tTIaTGV$cj57jxD^g$?QU*7sTH}4(ufR@L!z=zaGpe?852O4k5C2>#b4|0 zH4qz)vMb+N<3x4efx8;cw(>sOhLnz-YXSxw z3I{3s-!RF1(I-{H-R6+gabcltt^=ArOtCX%{D!UzXM%K61w$W~`i=e!BJvkfDb88C ze{(S6M#8U~cUnfWrt@fswm#nsyfV!7_cL$;?oh2o4w^Q8QJ+A8*n}J7$$VAsj?hDV zoFSv~59Nq%tx@xW??MOubRtH4M8Guw_y1-!ekVN)z7ZLjbC=1L?O(}=-yQzWikwl= YsUApoGL#Gwb2TI|s4k>J#U}KB0NH|?L;wH) literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-anchors-short/style.json b/metrics/integration/render-tests/icon-text-fit/textFit-anchors-short/style.json new file mode 100644 index 00000000000..1587d6940b3 --- /dev/null +++ b/metrics/integration/render-tests/icon-text-fit/textFit-anchors-short/style.json @@ -0,0 +1,193 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 200, + "height": 150, + "description": "This an adaptation of stretch-nine-part-content but with '1' as the text and textFitWidth=stretchOnly and textFitHeight=proportional. Because of this, the aspect ratio of the content won't get more narrow than the starting content aspect ratio." + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": "local://geojson/anchors.json" + } + }, + "sprite": "local://sprites/stretch", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "anchor-center", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "center"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-left", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "left", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-top-left", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "top-left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "top-left", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-top", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "top"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "top", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-top-right", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "top-right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "top-right", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-right", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "right", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-bottom-left", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "bottom-left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "bottom-left", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-bottom", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "bottom"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "bottom", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchor-bottom-right", + "type": "symbol", + "source": "geojson", + "filter": ["==", "anchor", "bottom-right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "bottom-right", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "anchors", + "type": "circle", + "source": "geojson", + "paint": { + "circle-radius": 2, + "circle-color": "green", + "circle-stroke-color": "white", + "circle-stroke-width": 1 + } + } + ] + } \ No newline at end of file diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-collision/expected.png b/metrics/integration/render-tests/icon-text-fit/textFit-collision/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c73717653b94e2099fb6b5b6e3132f78694eb980 GIT binary patch literal 1265 zcmVSL9mgdqaYi11#6q3Il{HClTA~J8bd85y@N)0Je0T5B!MNufqn*!3FrjEm&j>os5di|M72fX{#~Ad#;|Q=945p`7AS&=3_O%2A#g^{CcI8 zUVjf}UF-ObOKs7Rw4;|lIiq! zQrA{T=JrgGQ7~|eVUbb9jdQc1d;_Y1_XkLtkVIWu9WfGvM?4S= zFl@m99`O((G581kBuz-7-ygt@wFHa(RMSfB`X4!QwVpW%b7-o+%uJ;iHl=8)zl?9I zkB0UJQXWd-Xywl=!CHdF{<_gaQQpV2Ts=ik*FIi*c{4MKPIKcm$}7t8^>$`+ z`qUY0-LxAG4YOWKUB!#fW#Dq@*g>#~?$WV}t_yY%98NIdVBh;_XoOqPwI8EO|1R#7 zMz~7Fnzl(4R1*8)#!GzXN-+(Ctcgi{&;Ob|@ivBzDFK_PeJW+;Vw z-G?zK!bm6BMAuzdMJc6gnij+cg2lwG^XB$U z3d=SU=nGI+eStqax`~ETYCdo*sDg1ysS7}|rfI!cNU&JyvL|@gyOZ4~c9Wct%$W^m z_`3WgQ93^Rli40`yO-RQ+(%0nmsSG{v5;V~aTDXH_@aW_yzO56AwS~Q83+U!4y9CF zZ=l!XZTE6pMMDLpi%aKXF~MRTSN^6Xy@cGOxh$W)9CygWKp@C)X`0rnl=5Xfo)KTw zT182E3I95Z#RQAh9XZd^MJw2}?G4(0@8G+ynlNG3q1A_u0n>o*fmg7YV1q9!zNNBy zKNH6%vN3ZT(b6=n4VaFN1cwtGPO!n`2d9!Udl7MQ_c785HW)MdeqLCR!T*8aaDu}L zgDAdv23(48Q}hPb26C`UQ(zgzeWwYhP=L<8AUK@haDu}L4krwvV6S!@&@fnsl^TGZ b{8#<~u*-rdFvlt+00000NkvXXu0mjf9RW@B literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-collision/style.json b/metrics/integration/render-tests/icon-text-fit/textFit-collision/style.json new file mode 100644 index 00000000000..21166a21043 --- /dev/null +++ b/metrics/integration/render-tests/icon-text-fit/textFit-collision/style.json @@ -0,0 +1,99 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 64, + "height": 64 + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "properties": { + "order": "no-match" + }, + "geometry": { + "type": "Point", + "coordinates": [-6.6, 12] + } + }, { + "type": "Feature", + "properties": { + "order": "no-match" + }, + "geometry": { + "type": "Point", + "coordinates": [6.6, 12] + } + }, { + "type": "Feature", + "properties": { + "order": "match" + }, + "geometry": { + "type": "Point", + "coordinates": [-6.6, -11.5] + } + }, { + "type": "Feature", + "properties": { + "order": "match" + }, + "geometry": { + "type": "Point", + "coordinates": [6.6, -11.5] + } + }] + } + } + }, + "sprite": "local://sprites/stretch", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "symbol", + "type": "symbol", + "source": "geojson", + "filter": ["==", "order", "no-match"], + "layout": { + "text-field": "I", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "icon-image": "nine-part-content", + "icon-text-fit": "both" + } + }, + { + "id": "symbol_with_offset", + "type": "symbol", + "source": "geojson", + "filter": ["==", "order", "match"], + "layout": { + "text-field": "I", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "icon-image": "nine-part-textfit-wh-stretchOnly-proportional", + "icon-text-fit": "both" + } + }, + { + "id": "anchors", + "type": "circle", + "source": "geojson", + "paint": { + "circle-radius": 2, + "circle-color": "green", + "circle-stroke-color": "white", + "circle-stroke-width": 1 + } + } + ] + } diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/expected.png b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..4a017e76b6026d919d14e497fc37d5f90f4cf6cb GIT binary patch literal 7654 zcmcJU2{_d6+Q-pC$d(vI%t+S8o;}-OkYu97L_(U9ZL&m&!q{gj%Gy81o@5CV8p$$Q zYb+&O#uiz!lkI)RdC$4tbN-#{f3Ej>-|HHe@%;Q|p5OD__xJwX-zW0iS)+rjM_3sc z7!DdE5hw-*#_RMSmi=JFf6SqqfkCLy7@=$F$2jxuQcT)v;Lvc#PGGQ$cB!l&huVAR zO4)~k&5@(eg_@!p7ZQnQ36;7G;<_P^FOIKK~E+}yGP|9Ahyi5E{-KQw>Z<5!nw)1GgUIqisQ&eYT1 z{qqcdv^+)bxji}NLcW?Je>oFM{F!vYi2*s!tE_pq7DiR)!XpozN8WlQ-gHOhOzKm; z!K;)$@H->zgn69ksynTocSh-smmn$lka+g>oDYviC_{>W`H(46hrKMN#F7v14Hqjx zj%1ibUWFP-Tgw<+IY9KxTDFoJ^G+T^>&Wy*_NPEo-mFlcou{->U)=7H=o9{>Nv-S- zD?kU#cU%uUxuJdb^G98xr{YBV2^C+$wFbqSY1I{JRellecD&h)>PibvSfNIvceQi} zGXMVPu({}r%l~#qEUhH@N!tr5*Sl6CPREzEFHG;_%dyYqzHH0cDK8gZ*4|wjtd|+i zscp>Fh;I`>S#dRfKcaqb4cblGm!S}g^mfy=DY*HaA(picf=Yubd$Z5#Z(fO%5xT#@ zrF|Rx@wMqckBXAKuphD|i78o^dI!^-Hhe{63m!+e+Npw=QxuE~DIVGDz>Yz?&B92w zPp)53(9l`^X)!v;-fIal<%xE=9);b@XO!#`DT6qiOk*P632BHFE8#Lw5{(ffv+Q5%c$6Gkd^WS)+E4kiKZwL^ZoLp2S0IAB}{LN6h4~iGtR&H)Nt=} zXyKto#ih6)yx}F-eM=XlRpc}Sc!4Q&u+W&Jb0#5>KdlobFj7ivYQ#eqSEi4!lswPL z51}5j$U+1P!dVDk+4J(A+K+xU4K~!GCE0~@YDJa}PB)ORIdAiY0f{@AH-E5zs*CT_#kc!r~Yg- zmXXFe!Bo%Lz7HAjyOd8!CNHVTw58_=w5$0W31?wFgsGJh`9H@OgAt_avx;?c?G)y> z_pprA%B-Z%B=0e`42cYZv^@de`_>gHHDDtKKN(FPIc-uZldhLMg0B5Z==jJAz74C+ zy!vo<@NB7`sYr^V(|I^cvEPyT`wg8qSwTJ!X% z&)L|Ijg#D|YL(C8LbO2IkIM$fOXSPF`r(<%7J{SxVg;XR=6UM?CU$eCz=@fjG!L*) z?!yagpGlh)!L{4*+Z?)AcrT2T7Vc|bUG2CV`H{yJm;1_p!|Y}HmZJ!hpqG1i7q7YZ zqe+3WxU8c^Jm#zTnZ6IYrXhO;shavz<>jhoL+#IW2Ll>ji>0#R#H#SC zc0rT-C(|v6%ItZjyjB$1q2t|Z2xXvn8M!fK7ai{G54~4QbInGsgp^ zj=P~ZOd2%T!)`kL@)4O)Ty6B7{ObSIy5znvzh~1FO&Mq@9%R(Xs4sHCV`?U0hxa!& zl5AxN4Po+b_FIgJlyj6eZqwTg9GG|$Oj?1<&QsSNx2qq{&hnZ15bP_P>z4UFbt%-? zi^jLvMP|5)9WdkG7x)LAmI$&Q6>^ENGSz4mJ80tcA5ZP;hFO44ra+Ysv$gcUSqS8N zndZE-hy0*HvHv7t#$}?|{<$SO3vKg$A2d^Yne)=+%BV6sw{4i>1lde;;Qi0%;&*c1 zX*FG{^hsRaWIC##C3>4vczB$YL+FXhU^P{-cO2hTbk$mu6@x2Nbk2`%OWO8pJsK5+k0{zhUCTuJ9^AaQ;2zJy{2) zp`(?GMgAbwe%V?p8bRx52{O{3IV=&e$!+R=zDObp--G2yWy`&Y*a!A78BB%SeDz$> z>wb2s&DhltPzAWny)EKtUwOusHK{f~3MxLdT_)N|SHS7BKhK-+p^dCt6Dks3mdM7` zljvUZ)<4=GD8XJvstsJuYtj8&g@hgmt!$7Cftm5BqNK$Rk;20dn0Gyl5d|QpkBjpR9Amb80LUU)&UQ zzm|r)IqkP3tZSLgJ@DShZ>@A^zXxTUJx{8elwi0IRH!tO7{ZibhDAsNp~u+CACoHj zYA>jb?uvjZ=9@-8c-9L8^dR`gL$wtElFT>NM@rTU1J=O%KKU!4ieaWqo^KMO#dhYz zY1AL30}$@wUjh(aIKiEV%+n(MgjEBlDn}T9)}MEQ4Kkm7ratQ@e20!x3#aIxR?YdB z1cw(+(o}1&asZr!>I086co59p4^L+-@iy=*K|BHrr~ZLXTPdpY1{!AIqOOwX)u?B@ z;Mv!W|3%CH4P8;P+jo|Ooo-F;Z)*k_zxYWO7TeNxd6bH^e}1@Jdz0<9yH=>uZ1dty zN>)k{^##J`p4JFC49mDM!rt3OdB1Zn7e%}T$3feSy*W!=HY=`&$tCI~moC?e3-m8K z03O3(8G+EcN)aXvHo0sbz7maGgCc{~M&eVe@AFNbFR9i7+M&1#OzDQ$9kN z9i#){51E0xv4-Amz43GaNbn+zkrtKmu`NMF@18^#>vRos(NHM?)Pg$XDv(c@c>=S~C6rM&DQW3^V z+AYfMYCOF`wa{2;{>8_vyCV)V1~R=NbV5z8@e5DrbJyejBscM0;Izrk%O*l&0;_cO zdfn&94AwRe_?3xFdr(b?o)tyg_xe8DKaj|9XeUexIIMkqv|Hzg_03^HuMmm!Jz0Am z{F%-hf*9G~v=GF66x1jPlWgehZ+Ji^q|6Y!2P2|&*2%Y5PZ5=+#$X`%KjnfA_RBxo zn+mlm9J}^G_H1Xab;%>ACO)EaPof(NZJWW(*MSEMUS{ZdD+vhN!DtvQ&&>%NZkaIC zXHf3WPm4&Oi5Ce%I{AYD;3fwCCUx-1QR@bScZY9wiT27<=y+YIg54GXAV9K*v(Rs& z7mS|#$E;}o*@7<7^hxK9PaSk&dL&lDKC`1ri=kosFI2v1(QVr2(k& z9zkm5CiNhglt|Qd!xAhGR89JtOPV@?1;2JlCQPZtAyUR7>x?3ri-`jh*MPFt)Gw7G z=$>++WTVn-jlJCrHa}|J<(=1;={D$CF~a{V2&1}ZZp!NLev&YC`VRRLtyF}zahz-{ zP|5^BTW8IR8C;mYV-hBK5F3|%>u>Z6O5=leIQy21VBL}$%Xy_@)BmCt_W)?@|QNd4>$u)q*11t;5%2JXrIiNfAJ+t3)WSI<$ae+XNG7FMOY-h+`$%8`i zJT?zCuC;5w2hT)Q&R_}s2my$=*CFPhMOHnv_2%tcYRJz$`mPjNGsk(QJ&sKz(I_dI zj%p5z2W5tql84NF73F+VHR!m|uJ+4UE1WGx&n>Yx+U5JP(o++B^Wib%wvcHq+SKyt4s(|IpV4kSk-8G$Iw??J#;BU zo{YZOy~tbPUAKTBrrC0c%+*|VND`5wO&%Mqd1C+87!V%yNO+edjI7%BZ7?2X`vCBl z^Rd+TG|7C)!Xntr6Z_O`-wn|&lw=V-UZ3c>#d+OHJJZ3^eTJ+M$>xX*C~PI`!aA8% zPk~;iy+4br`?UbwdfvwNgod1N=Py#;*yz)4-e+a6rID`Y8oSmH%LZ7Mprc_mZZ9AI%(R#io(*4@XG z!a?^BT39~!9nJB8BW#Mw(nnUhOJ(eWBej~yts2X5$LI)!4jjJeip#)lr)itHZ674Q z1}#k4+vaZ2P56#NK-mX;2(pI4Tsc2wUjmJSDb!@v^9a#5$CA=UNFgKUDDwVBr)xFT z_~lmC+!?stJzbxw?XXk*JBv2O#!w*x@qq`TUHo!fhu|fFRrhces!~}@q;(ZM06CtE z_M3;mCUK69a8Ld-qD|pn+K7f%Jc0tYnJ7{<+gho zUGXF?gI4G3s{BKt`<4@xwp{gew3SSsh9yqxZGL<`#_$clnvP}s5T{Gj0$n7!^^jF_ zR{_e-$VNH}7Im|w{$W~IrnU8nC>ZgzR00nWkQ$R8YIMf4Nw2DHuCtmtoX|t)kt!L*LovB=ng0xH(@RGV%=ZBxmH-0o8fsv1LG1*U$gz?-2?Xh$;F! zrx9|s=e?7^uSg+b`g@N1(*5Ha`|~csI-7d#KZ5}?0uvjeC48dnc!*eTgedXmcabXL z4W4gw%c8q>mUFjqAbc1wvDPJ^Lw8h?>Z>?}Ndv;wDFKocG-sABzynGbG}@F0l!mDR zrVnn1eVqV|BAoV#vuB`%Dgf2)1k3#!Qu#+~I?td6_)5Rp6PQ*JW&LzmTR8OYKk`8Q z?rF|>=xle4!Cce(1TFB}Qr-v$VfEf`s>DA#ZR-Ru=jx;MxxS{;)~?;fE&N*) zGpfJ%pV5u$jqQcf7Zdy#y4yl85{-pLKv|ntF=3#_5!EB`*>_pK7%#f*8Pb{kfH&Lc zAQ+v4No3O_s##=(HguNhS;C=a(u^%iMGUGUdOOXH|l&AnrNX5(YGl;!KpZr7-%7Ix-gc& z#hPNz%SXW#wwjN}e)SnGMgABahrjY0Ieg@k@@>594uq=SS#*Y)TgWU9dbJWY{d{0; zy^qk2U4!;%8)m!n$9lkZY;Lao%)vayGX71_MYh4%<~Q`cviQH;r+?U{PUrc_8}^sd zt8_|#`JQep7k#FCq$1t^TQ~WaRz~g_#Z)%6pT)t3n%%KVv%u*AYCK1M5w|VxqrD6CE?%odr#DmHMboZK!SN7zy1142C5H?M1BH~YjE{R4NC}W-ab%y~<^tIEXJ?y| z4W#RFkC&2k`eXwQLsSDU1(kI&eFlj&`BCtqs6XRUVk?iix9I9MN;Y2+xtxx*^20Wbr;Zitd&HW9n(unovfrp5mKu4h1dtC}zq2qx4j)FP?3|YnC^-BQP zBq6={Zh&~dEKiKfv0Is!am0<#$ zITO#==~}z;V{3ciETE&Q7`mGd49hP;OW68{LZjod*kO&G$md(a;@xWX;b6-)rZ_7% zw{{{y183$S6NzO!n#v||*sH!%%UZK7TrS-~U#9niQ2V}JL)F~d(+FZ-3Qd|}76f0f zfBgWO%gYG3|7Gb|4*mzO9&nNT$6#&1tC!2%yW|~BU>1y(9S3OSZQIiJaB?uNdbPR1 zDpbT!bKpL(;k>ZK07F8L9MNq(?8lPZ4#R5$z-vYDSMO+-@*^`?Fyu{|H=u@Gv5Zh) z=UoP&$orYk*!$r5wuROoAg8Hz1#F*L4hf*SN|Khl`+)4hy3@dMip8^FX3ZU%%J%Zk zx0BGHb0I_88~i&{%+=0pKQ~nDcgCND^i_|^z2aPJ>&!X5sV1Tar2dTzI+y?sF91lK z;`ba2EBd73&yLB#fjIFm*FK{R-0{!BYr#mT4ScyeYwI3a)Ibr#XM8d{$sK4)5_ah7 zk9XpgPfSQi2qdeHHA{~JQxrD&L~``nU_`bE{B-_9SasiHzbc-e8ns;Rl8hB0O<*zdB%_*v5uN3`l*7pbYTFYg0B`C(F! zzfn9i=u63*Be>b`Im=xk44eK9Y+NIP-cp<^GRedFiN$p}A+fT+N*j{`}UJ#_J7h8%0mk=kW zo@**qPlh-|6ZugPgy8O-tJfM%$rGtw&QZ5oKs?+{3)-56E3F6|`Arl5&j_KZL-)D3-06ph mP*}?EPJI4k}8H^3iB3|lU3H>i`i$Hk* literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/style.json b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/style.json new file mode 100644 index 00000000000..76d81ef8112 --- /dev/null +++ b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long-vertical/style.json @@ -0,0 +1,191 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 360, + "height": 360, + "description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a long string with a wider aspect ratio than the source image." + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": "local://geojson/grid-tall.json" + } + }, + "sprite": "local://sprites/textFit", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "wh-stretchOrShrink-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-left"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-middle"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-right"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-left"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-middle"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-right"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-left"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-middle"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-right"], + "layout": { + "text-field": "一二三四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + } + ] + } \ No newline at end of file diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected-mac.png b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected-mac.png new file mode 100644 index 0000000000000000000000000000000000000000..ca63b0b25466261e603427b54230afb19ad459cb GIT binary patch literal 16183 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 literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected.png b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..060dce66232589f53ffc6d73cf47b98162f87d12 GIT binary patch literal 16304 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 literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected_Alt.png b/metrics/integration/render-tests/icon-text-fit/textFit-grid-long/expected_Alt.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6667dc2441cea1e5b16e683ef62459630d1da8 GIT binary patch literal 16321 zcmcJ$2{hIJ|LcLpvsP5quoS)Z!9Gz^ntgk*;+rG;?7$a3y zW5u__oi6LA!lrfRsR&t6!l_1@M)bS>?)K9RXY#U(d3m3hAo$U9Qj;A?jYWwfx>bSb z=|}a*osX~A4-{wWXUXg9ndRb!o+2Bz4ueUeUJCY=IphmQy)4)HKlx@X<3Q=5`OBta zBE#Pdhoto<$q{^gH`xR1YJVv89OYdTxiLNRRKV~28?OJgyD)P2yFRI2Ir*+O`CjMo z<3>T$qrZMWufMf=GIn|lO&df-UZ$#IU|!deDwL+Mg=YMo!TYoSa*!L)#+;muA#$%yv6z` zmoz=esA_k%T6^T4M8S<1@~@|m>?J3$Zzac%SX7*U2c69PfN}B{51I~L?-ErUn(N@J!pW*2zCYC| zlbJTe#&t_%-}SLGxf64D_w;>L0j z@OIXVv~Eq|z-zC+C$sL5RzWjQ?Y6}^vZ=N>%@ca-qDVVxc6rV9Phyo)GFpQeQuEdo z`vu)j43pf>W6UF}WGklb8hu}^ennYM7kj+P*C3>v@kESu;L}K9Fu&U`V$}ya<1cm%WT&)i`}DQ>|(c3ym5&u3z$uP?4Y9T<15*L3HemdiY)DL1haYGYvxC;#`t zfG=B#j7miiQKo51asBnc_-oqI^~#eut+9@nI{d_pxJ=Nwso8exug^T{wA8v^=s);$ zWi&d|!fxvFNo1NdlQpk*QZgTYe~_3%HoHAurV=cj{OG%GE82=@hWj$C zh_Z2%ugT<+9>tojbIrYb{5#rTigwud5I9V(2f@Ywljr zJkl+A<3t^CeP>oo9M)!*#}8rmu33C?lp)-oGOUjC_F;|Zh#(u%HyftTuHJD}!=a@Mx1;<+Tm%AlBoj)1q z*>mdQUGgTqq}7QLbdYTh!2U6<34Aq)M--IlBL;1356>{(-9^GJ##mof)}Hd~v-G>s zxOa!R@3x?O19OD@lN1KzW6k=F_7ZJ1&CFkNYFn}T^el>7ca}5^X2tGtDUNC?PU_ib z3WW|kH?H`<`0P$v@NNJ{=Kb0-qfX86=L`+Id_497r~Aie)b#jt=~=QdI6n>S?09+e zNOu(T)j#_CcTXfu6e7%-o(LNm++3L=?i(w_8B~>?ZID07g+(s@Ws5~$ zCWzXwA}c7f~#e^wD;7c~Lozzx|4(c=p{ixmd&(b}I3}O>1$aw{fL*6W@cBD>Et<#Z%WEH`NM~T)75;5T`Up$C983U8}n=_ zZzuIP25K`|71gERYZWZ-KGYae(5+){@*Be&6^Ne`{ zit@^x`;&;2*M&cOlsH2*3Tzx%n8gInACc$nQI0R1i45~@e{V^4)1SI* zjWchQwZIjd6O$7{**{?8NK4NmyLrXVWC}(-;5$PTO1;pJVd(XK$P;=`n&{d4_Ixdu z@Z_?;2QQ?47uijDU=FN*zGgBI3nONcQ(0a%pz`EvmU>Rjl50d^V3-la^E21>urJ!w zqb}L#4?n+Xt8#&xYa&~T0J)a3ksi$XtC@Ylg0fiHx-oYq;!~1R5&BN*DhY-1%?SN@ z*8$%cH&+_!-TvD>>H3|pd(_>K>Z?l;nQL-tT*B`{-5rP7J$xh3b3CtH8%Ygcg%fUU zXq&ru!If?8R9NV+IjXLyDRp~9L}e7#yBF!DUK!ZMSf>_MSX7SsGRUb%OrZuXa1k!4 z>|AkUolxrX3nc30O^aq}E?FOkT>X}1M

ul$IXN*wCrmq3yY_-2o{$uPlc&u%gP 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 h8~+I*5BZzbzM(Ln5=|O15U^0Bgc1e_ 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 literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-short-vertical/style.json b/metrics/integration/render-tests/icon-text-fit/textFit-grid-short-vertical/style.json new file mode 100644 index 00000000000..b163434ee13 --- /dev/null +++ b/metrics/integration/render-tests/icon-text-fit/textFit-grid-short-vertical/style.json @@ -0,0 +1,191 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 360, + "height": 360, + "description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a long string with a wider aspect ratio than the source image." + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": "local://geojson/grid-tall.json" + } + }, + "sprite": "local://sprites/textFit", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "wh-stretchOrShrink-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-left"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-middle"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-right"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-left"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-middle"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-right"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-left"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-middle"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-right"], + "layout": { + "text-field": "四", + "text-size": 20, + "text-anchor": "center", + "text-writing-mode": ["vertical"], + "text-font": [ "NotoCJK" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + } + ] + } \ No newline at end of file diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-short/expected.png b/metrics/integration/render-tests/icon-text-fit/textFit-grid-short/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..4dff9a99a276dbef69c676cea5aa0d5c6d49fcd5 GIT binary patch literal 2723 zcmbuBc{J4R0>?$_QeHPpoJQ2mGBc983PaY6J zDan13A|fJEHr5s>5s_`az&qtHJAkn!;Kd0M5y@X|EX>f?x6Qno#tkpwUvih1SG;Lg zKdJuGDK&On|4?+Go#zz@ZPWeyYd5~h1`NYPplcKS{lQ-^?S?WGm5jyx@ z-9od>%ib^`%yUH~<}GsvSoNTU#KD8(vqN84e05Y+GLz%2v5DU`*RPqP>I35;RW?0HIP9LzLqrQqL zo{>%M=;(#l=Eb>GDy3ann^&C~fYe4fBc?c(tjk>vI{5H=w$9AqI?<3L%=*(*ax(sm zNyj+1VRyiq{-4GhMa4?+Zg%S|4aU#M>ENdhSL4}TE=G|GP+B3`YM_5@Ur{pu&gO|n z1Di1>8ikS^dtx|@ItSqyZB%EOR6Jg$V2hBjC)(MpmkY^(D{%t)=S4M?nsv!d`c=-C zBfKhVOGb6*LXMAElW&x0NP&?dBUhoZ`6D1!TbPTn{_9oQbtLRamO*Py(PnHSRKha`I6gkM#cy~6gjGLb#^it zM({F$(kl8l6M|?LJUv$OpDI%mHoBs2i0L$#MFuKe^R<8J()er%$@J zl;#@he;G2#i;?KfeZwr1o<9qZwxvV{-e%o8RFA#H5tS2%cCD33f6;+Q?^XYq&6qdQ zwY7J1jG^6$bYSHdnFCXHax<>zN?Qf@ZacMf;;IDYfJ)7@p5oBr)f?;mx!1JZ8dCk2 z1rj|EySnv`{zg9$Jbmk_OOUJ)UaSCZmc5H|pnazvIWkZOim{bH#$bjT8h{l+ixUHTs;f z0@aX?N?u;%J+oqg2X*Re)~{Y5utE0jC*g&pM*|rUbW#F#SNZ0iL6*9LX|%vxybtv`-`*i=-)(1Z#gxR8WR5C=?&kd>7!uuudx^#R5h=c47VT zGvfTyk?VSM7xde{@U**g!XKWhquLD8sVyQO&f|)OFs%69I3n`cJ`vjq{DH-Hvq7o z0v?J49Q7bh=r6!)C{i`T_}8Vq^ix|w{xy@o_athz&@5%?Ei3PR&0U4`6w7_H_)lqj zFT^BOh>7tBAtoy#!h+$84gm8X#QXpNx!YuZ1dMS0KhOyJ{m^Z$Wh0-O3I>Yr32P?K zh6p3|xpg>_k?^3ir0P~A8OdrYcEY9RU&^P)ebY9=lM%zObU6fFTpkmKzx?!zzXz{R zAj3N!pKPsgZfxo;?AblKsLYT*x&*Q~{s-is&RL=7RBG1S zg;56p5`=4{=Lk0J9QKdE!*C`&4>h81@5OZIu$bkzNpY=Fn87S#-0BN=4t5;@h?N&jg-QH)Ln_sV^E7!*vxX; z9kq?2K$?O+Z!iopNcQEPRvv942{sh$spN;RKyyI8N+}I4DgLWW>SEGBFDjzi@qX`} zyhnQoar9JF%;qb`(|xt~6aQ4nBh@|3e-;(D)hIyq#fP}LhHUun9_GP>Y@YiaD5Tk$ z2{uOH4Rs$jHS5lSvs?)aV&|);oF`}9+khw_f)Oy3+WUDD!L$_pkL|*WLC}DY`4;A^ z=~?%?^C?jGNzOM>_cii_&tQ2~Yl$>%M<_Ek4~%F-eTsjug$%H5Bn9hI!B$6?=TNtm zH!hLuBR02p_r%ew0F2(@8Xo(IfoveTo#N+GfRlKQ@!}AxH`2?!rk`ybq&LO7g+Bk7 zzTbEA8)O--fUBG_z_1FWHCQ^DT>u0&=@~FY_HwiyB>(V&B)mL1{{~n-xKC*O2Z_R~ jR+Q)e+%wp literal 0 HcmV?d00001 diff --git a/metrics/integration/render-tests/icon-text-fit/textFit-grid-short/style.json b/metrics/integration/render-tests/icon-text-fit/textFit-grid-short/style.json new file mode 100644 index 00000000000..432b6cee783 --- /dev/null +++ b/metrics/integration/render-tests/icon-text-fit/textFit-grid-short/style.json @@ -0,0 +1,182 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 360, + "height": 180, + "description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a short string with a narrower aspect ratio than the source image." + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": "local://geojson/grid.json" + } + }, + "sprite": "local://sprites/textFit", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "wh-stretchOrShrink-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-middle"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOrShrink", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "top-right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOrShrink", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-middle"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-stretchOnly", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "middle-right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-stretchOnly", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOrShrink-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-left"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOrShrink-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-stretchOnly-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-middle"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-stretchOnly-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + }, + { + "id": "wh-proportional-proportional", + "type": "symbol", + "source": "geojson", + "filter": ["==", "cell", "bottom-right"], + "layout": { + "text-field": "1", + "text-size": 20, + "text-anchor": "center", + "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], + "text-allow-overlap": true, + "text-ignore-placement": true, + "icon-image": "textFit-wh-proportional-proportional", + "icon-text-fit": "both", + "icon-allow-overlap": true, + "icon-ignore-placement": true + } + } + ] + } \ No newline at end of file diff --git a/metrics/integration/sprites/stretch.json b/metrics/integration/sprites/stretch.json index 35b03bec863..c6e5320cdf6 100644 --- a/metrics/integration/sprites/stretch.json +++ b/metrics/integration/sprites/stretch.json @@ -20,6 +20,19 @@ "sdf": false, "content": [10, 10, 30, 30] }, + "nine-part-textfit-wh-stretchOnly-proportional": { + "x": 0, + "y": 0, + "width": 40, + "height": 40, + "pixelRatio": 2, + "stretchX": [[10, 30]], + "stretchY": [[10, 30]], + "sdf": false, + "content": [10, 10, 30, 30], + "textFitWidth": "stretchOnly", + "textFitHeight": "proportional" + }, "fifteen-part": { "x": 50, "y": 0, diff --git a/metrics/integration/sprites/textFit.json b/metrics/integration/sprites/textFit.json new file mode 100644 index 00000000000..550c3f8057c --- /dev/null +++ b/metrics/integration/sprites/textFit.json @@ -0,0 +1,119 @@ +{ + "textFit-wh-stretchOrShrink-stretchOrShrink": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOrShrink", + "textFitHeight": "stretchOrShrink" + }, + "textFit-wh-stretchOnly-stretchOrShrink": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOnly", + "textFitHeight": "stretchOrShrink" + }, + "textFit-wh-proportional-stretchOrShrink": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "proportional", + "textFitHeight": "stretchOrShrink" + }, + "textFit-wh-stretchOrShrink-stretchOnly": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOrShrink", + "textFitHeight": "stretchOnly" + }, + "textFit-wh-stretchOnly-stretchOnly": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOnly", + "textFitHeight": "stretchOnly" + }, + "textFit-wh-proportional-stretchOnly": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "proportional", + "textFitHeight": "stretchOnly" + }, + "textFit-wh-stretchOrShrink-proportional": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOrShrink", + "textFitHeight": "proportional" + }, + "textFit-wh-stretchOnly-proportional": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "stretchOnly", + "textFitHeight": "proportional" + }, + "textFit-wh-proportional-proportional": { + "x": 0, + "y": 0, + "width": 100, + "height": 70, + "pixelRatio": 1, + "stretchX": [[9, 91]], + "stretchY": [[9, 61]], + "sdf": false, + "content": [9, 9, 91, 61], + "textFitWidth": "proportional", + "textFitHeight": "proportional" + } +} diff --git a/metrics/integration/sprites/textFit.png b/metrics/integration/sprites/textFit.png new file mode 100644 index 0000000000000000000000000000000000000000..90266af2add900a8a240580cfff61b79c7b9be6c GIT binary patch literal 421 zcmeAS@N?(olHy`uVBq!ia0vp^DM0MT!3HF)+6*&+6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?O(K&H|6fVg?2=RS;(M3{v?3)L`Z5;uum9_x9pO&ch5MM=tnGZ!}u`z37$* zn|8tx(O(~C#m|d-f4(ry-SL=6iVrezhwbIOy{mic7b=AR|I?onDIj=rlY-KwR7aPT z(@h;Grm+f6)a6!EiWYNm*{0LcG4vF8i!7;rx6bTeskF+vrXI}`Gmr=$%X9imZx*C5 TdQYeX1}%f9tDnm{r-UW|LrIm1 literal 0 HcmV?d00001 diff --git a/metrics/ios-render-test-runner-style.json b/metrics/ios-render-test-runner-style.json index e5d9de77be5..2af09d3ff36 100644 --- a/metrics/ios-render-test-runner-style.json +++ b/metrics/ios-render-test-runner-style.json @@ -14,4 +14,4 @@ "probeGFX", "probeNetwork" ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-image/stretchable-content/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-image/stretchable-content/metrics.json index 253fc965aa4..c49819c946f 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-image/stretchable-content/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-image/stretchable-content/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 3, - 3380 + 3696 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-image/stretchable/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-image/stretchable/metrics.json index 253fc965aa4..c49819c946f 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-image/stretchable/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-image/stretchable/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 3, - 3380 + 3696 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-fifteen-part/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-fifteen-part/metrics.json index 37cfb3b5fd3..b96283e28b6 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-fifteen-part/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-fifteen-part/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-@2x/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-@2x/metrics.json index 52972bf07ee..8405b98019c 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-@2x/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-@2x/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content-collision/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content-collision/metrics.json index a96054ffb96..32f0d48b415 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content-collision/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content-collision/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content/metrics.json index a96054ffb96..32f0d48b415 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-content/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-height/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-height/metrics.json index c410a69d195..6ce8b0325d5 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-height/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-height/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-width/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-width/metrics.json index c410a69d195..6ce8b0325d5 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-width/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part-just-width/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part/metrics.json index 5bec05e5841..d6ec82d8f31 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-nine-part/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-three-part/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-three-part/metrics.json index 0cd910a99ac..3b9c68707c1 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-three-part/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-three-part/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-two-part/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-two-part/metrics.json index 3e848e85338..733f6c4009e 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-two-part/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-two-part/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-underscale/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-underscale/metrics.json index 6048fc7e0b6..8193a6c6d74 100644 --- a/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-underscale/metrics.json +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/stretch-underscale/metrics.json @@ -3,7 +3,7 @@ [ "probeNetwork - default - end", 4, - 88322 + 88638 ], [ "probeNetwork - default - start", @@ -32,4 +32,4 @@ ] ] ] -} \ No newline at end of file +} diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-long/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-long/metrics.json new file mode 100644 index 00000000000..fce753d4340 --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-long/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 4, + 88638 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-short/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-short/metrics.json new file mode 100644 index 00000000000..fce753d4340 --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-anchors-short/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 4, + 88638 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-collision/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-collision/metrics.json new file mode 100644 index 00000000000..0ab854214ed --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-collision/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 3, + 86757 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long-vertical/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long-vertical/metrics.json new file mode 100644 index 00000000000..69a1acb43f1 --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long-vertical/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 5, + 390425 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long/metrics.json new file mode 100644 index 00000000000..b885feb80ca --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-long/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 4, + 90025 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short-vertical/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short-vertical/metrics.json new file mode 100644 index 00000000000..b1c125ef6dd --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short-vertical/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 4, + 199330 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short/metrics.json b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short/metrics.json new file mode 100644 index 00000000000..b885feb80ca --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/icon-text-fit/textFit-grid-short/metrics.json @@ -0,0 +1,14 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 4, + 90025 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ] +} \ No newline at end of file diff --git a/src/mbgl/renderer/image_atlas.cpp b/src/mbgl/renderer/image_atlas.cpp index 34adbb8281d..e4586ce9005 100644 --- a/src/mbgl/renderer/image_atlas.cpp +++ b/src/mbgl/renderer/image_atlas.cpp @@ -13,7 +13,9 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i version(version_), stretchX(image.stretchX), stretchY(image.stretchY), - content(image.content) {} + content(image.content), + textFitWidth(image.textFitWidth), + textFitHeight(image.textFitHeight) {} namespace { diff --git a/src/mbgl/renderer/image_atlas.hpp b/src/mbgl/renderer/image_atlas.hpp index aaaea1ba107..055c819088f 100644 --- a/src/mbgl/renderer/image_atlas.hpp +++ b/src/mbgl/renderer/image_atlas.hpp @@ -28,6 +28,8 @@ class ImagePosition { style::ImageStretches stretchX; style::ImageStretches stretchY; std::optional content; + std::optional textFitWidth; + std::optional textFitHeight; std::array tl() const { return {{static_cast(paddedRect.x + padding), static_cast(paddedRect.y + padding)}}; diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp index 8c7768b5c8b..f6a550e4c4a 100644 --- a/src/mbgl/sprite/sprite_parser.cpp +++ b/src/mbgl/sprite/sprite_parser.cpp @@ -26,7 +26,9 @@ std::unique_ptr createStyleImage(const std::string& id, const bool sdf, style::ImageStretches&& stretchX, style::ImageStretches&& stretchY, - const std::optional& content) { + const std::optional& content, + const std::optional& textFitWidth, + const std::optional& textFitHeight) { // Disallow invalid parameter configurations. if (width <= 0 || height <= 0 || width > 1024 || height > 1024 || ratio <= 0 || ratio > 10 || srcX < 0 || srcY < 0 || srcX >= static_cast(image.size.width) || srcY >= static_cast(image.size.height) || @@ -47,8 +49,15 @@ std::unique_ptr createStyleImage(const std::string& id, PremultipliedImage::copy(image, dstImage, {static_cast(srcX), static_cast(srcY)}, {0, 0}, size); try { - return std::make_unique( - id, std::move(dstImage), static_cast(ratio), sdf, std::move(stretchX), std::move(stretchY), content); + return std::make_unique(id, + std::move(dstImage), + static_cast(ratio), + sdf, + std::move(stretchX), + std::move(stretchY), + content, + textFitWidth, + textFitHeight); } catch (const util::StyleImageException& ex) { Log::Error(Event::Sprite, std::string("Can't create image with invalid metadata: ") + ex.what()); return nullptr; @@ -150,6 +159,40 @@ std::optional getContent(const JSValue& value, const char* return std::nullopt; } +std::optional parseTextFit(const std::string_view& value) { + if (value == "stretchOrShrink") { + return style::TextFit::stretchOrShrink; + } else if (value == "stretchOnly") { + return style::TextFit::stretchOnly; + } else if (value == "proportional") { + return style::TextFit::proportional; + } else { + return std::nullopt; + } +} + +std::optional getTextFit(const JSValue& value, const char* property, const char* name) { + if (value.HasMember(property)) { + const auto& v = value[property]; + if (v.IsString()) { + const auto& valueString = v.GetString(); + const auto textFit = parseTextFit(std::string_view(valueString)); + if (!textFit.has_value()) { + Log::Warning(Event::Sprite, + std::string("Invalid sprite image '") + name + "': value of '" + property + + "' is an invalid value '" + valueString + "'"); + } + return textFit; + } else { + Log::Warning( + Event::Sprite, + std::string("Invalid sprite image '") + name + "': value of '" + property + "' must be a string"); + } + } + + return std::nullopt; +} + } // namespace std::vector> parseSprite(const std::string& id, @@ -189,6 +232,8 @@ std::vector> parseSprite(const std::string& id, style::ImageStretches stretchX = getStretches(value, "stretchX", name.c_str()); style::ImageStretches stretchY = getStretches(value, "stretchY", name.c_str()); std::optional content = getContent(value, "content", name.c_str()); + std::optional textFitWidth = getTextFit(value, "textFitWidth", name.c_str()); + std::optional textFitHeight = getTextFit(value, "textFitHeight", name.c_str()); auto image = createStyleImage(completeName, raster, @@ -200,7 +245,9 @@ std::vector> parseSprite(const std::string& id, sdf, std::move(stretchX), std::move(stretchY), - content); + content, + textFitWidth, + textFitHeight); if (image) { images.push_back(std::move(image->baseImpl)); } diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp index d08d19110cb..1df6110c8d7 100644 --- a/src/mbgl/sprite/sprite_parser.hpp +++ b/src/mbgl/sprite/sprite_parser.hpp @@ -17,7 +17,9 @@ std::unique_ptr createStyleImage(const std::string& id, bool sdf, style::ImageStretches&& stretchX = {}, style::ImageStretches&& stretchY = {}, - const std::optional& content = std::nullopt); + const std::optional& content = std::nullopt, + const std::optional& textFitWidth = std::nullopt, + const std::optional& textFitHeight = std::nullopt); // Parses an image and an associated JSON file and returns the sprite objects. std::vector> parseSprite(const std::string& id, diff --git a/src/mbgl/style/image.cpp b/src/mbgl/style/image.cpp index ea4c8ee8d7e..c7dd4263252 100644 --- a/src/mbgl/style/image.cpp +++ b/src/mbgl/style/image.cpp @@ -11,9 +11,18 @@ Image::Image(std::string id, bool sdf, ImageStretches stretchX, ImageStretches stretchY, - const std::optional& content) - : baseImpl(makeMutable( - std::move(id), std::move(image), pixelRatio, sdf, std::move(stretchX), std::move(stretchY), content)) {} + const std::optional& content, + const std::optional& textFitWidth, + const std::optional& textFitHeight) + : baseImpl(makeMutable(std::move(id), + std::move(image), + pixelRatio, + sdf, + std::move(stretchX), + std::move(stretchY), + content, + textFitWidth, + textFitHeight)) {} std::string Image::getID() const { return baseImpl->id; @@ -45,5 +54,12 @@ const std::optional& Image::getContent() const { return baseImpl->content; } +const std::optional& Image::getTextFitWidth() const { + return baseImpl->textFitWidth; +} + +const std::optional& Image::getTextFitHeight() const { + return baseImpl->textFitHeight; +} } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/image_impl.cpp b/src/mbgl/style/image_impl.cpp index 3f60ae09ce3..a2468279a3e 100644 --- a/src/mbgl/style/image_impl.cpp +++ b/src/mbgl/style/image_impl.cpp @@ -38,14 +38,18 @@ Image::Impl::Impl(std::string id_, bool sdf_, ImageStretches stretchX_, ImageStretches stretchY_, - std::optional content_) + std::optional content_, + std::optional textFitWidth_, + std::optional textFitHeight_) : id(std::move(id_)), image(std::move(image_)), pixelRatio(pixelRatio_), sdf(sdf_), stretchX(std::move(stretchX_)), stretchY(std::move(stretchY_)), - content(std::move(content_)) { + content(std::move(content_)), + textFitWidth(std::move(textFitWidth_)), + textFitHeight(std::move(textFitHeight_)) { if (!image.valid()) { throw util::StyleImageException("dimensions may not be zero"); } else if (pixelRatio <= 0) { diff --git a/src/mbgl/style/image_impl.hpp b/src/mbgl/style/image_impl.hpp index 7983c5aa63d..2865972c952 100644 --- a/src/mbgl/style/image_impl.hpp +++ b/src/mbgl/style/image_impl.hpp @@ -17,7 +17,9 @@ class Image::Impl { bool sdf = false, ImageStretches stretchX = {}, ImageStretches stretchY = {}, - std::optional content = std::nullopt); + std::optional content = std::nullopt, + std::optional textFitWidth = std::nullopt, + std::optional textFitHeight = std::nullopt); const std::string id; @@ -35,6 +37,13 @@ class Image::Impl { // The space where text can be fit into this image. const std::optional content; + + // If `icon-text-fit` is used in a layer with this image, this option defines constraints on the horizontal scaling + // of the image. + const std::optional textFitWidth; + // If `icon-text-fit` is used in a layer with this image, this option defines constraints on the vertical scaling of + // the image. + const std::optional textFitHeight; }; } // namespace style diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp index 2b11507713e..8687425b61f 100644 --- a/src/mbgl/text/collision_feature.cpp +++ b/src/mbgl/text/collision_feature.cpp @@ -7,19 +7,70 @@ namespace mbgl { CollisionFeature::CollisionFeature(const GeometryCoordinates& line, const Anchor& anchor, - const float top, - const float bottom, - const float left, - const float right, - const std::optional& collisionPadding, + const Shaping& shapedText, const float boxScale, const float padding, const style::SymbolPlacementType placement, - IndexedSubfeature indexedFeature_, + const RefIndexedSubfeature& indexedFeature_, const float overscaling, const float rotate) : indexedFeature(std::move(indexedFeature_)), alongLine(placement != style::SymbolPlacementType::Point) { + initialize(line, + anchor, + shapedText.top, + shapedText.bottom, + shapedText.left, + shapedText.right, + std::nullopt, + boxScale, + padding, + overscaling, + rotate); +} + +CollisionFeature::CollisionFeature(const GeometryCoordinates& line, + const Anchor& anchor, + std::optional shapedIcon, + const float boxScale, + const float padding, + const RefIndexedSubfeature& indexedFeature_, + const float rotate) + : indexedFeature(std::move(indexedFeature_)), + alongLine(false) { + if (shapedIcon) { + const auto& image = shapedIcon->image(); + auto icon = *shapedIcon; + if (image.content && (image.textFitWidth || image.textFitHeight)) { + icon = shapedIcon->applyTextFit(); + } + initialize(line, + anchor, + icon.top(), + icon.bottom(), + icon.left(), + icon.right(), + shapedIcon->collisionPadding(), + boxScale, + padding, + 1, + rotate); + } else { + initialize(line, anchor, 0, 0, 0, 0, std::nullopt, boxScale, padding, 1, rotate); + } +} + +void CollisionFeature::initialize(const GeometryCoordinates& line, + const Anchor& anchor, + float top, + float bottom, + float left, + float right, + const std::optional& collisionPadding, + float boxScale, + float padding, + float overscaling, + float rotate) { if (top == 0 && bottom == 0 && left == 0 && right == 0) return; float y1 = top * boxScale - padding; diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp index 29f63ac2591..819cca508ba 100644 --- a/src/mbgl/text/collision_feature.hpp +++ b/src/mbgl/text/collision_feature.hpp @@ -89,20 +89,7 @@ class CollisionFeature { const style::SymbolPlacementType placement, const RefIndexedSubfeature& indexedFeature_, const float overscaling, - const float rotate) - : CollisionFeature(line, - anchor, - shapedText.top, - shapedText.bottom, - shapedText.left, - shapedText.right, - std::nullopt, - boxScale, - padding, - placement, - indexedFeature_, - overscaling, - rotate) {} + const float rotate); // for icons // Icons collision features are always SymbolPlacementType::Point, which @@ -118,40 +105,24 @@ class CollisionFeature { const float boxScale, const float padding, const RefIndexedSubfeature& indexedFeature_, - const float rotate) - : CollisionFeature(line, - anchor, - (shapedIcon ? shapedIcon->top() : 0), - (shapedIcon ? shapedIcon->bottom() : 0), - (shapedIcon ? shapedIcon->left() : 0), - (shapedIcon ? shapedIcon->right() : 0), - (shapedIcon ? shapedIcon->collisionPadding() : std::optional{std::nullopt}), - boxScale, - padding, - style::SymbolPlacementType::Point, - indexedFeature_, - 1, - rotate) {} - - CollisionFeature(const GeometryCoordinates& line, - const Anchor&, - float top, - float bottom, - float left, - float right, - const std::optional& collisionPadding, - float boxScale, - float padding, - style::SymbolPlacementType, - IndexedSubfeature, - float overscaling, - float rotate); + const float rotate); std::vector boxes; IndexedSubfeature indexedFeature; bool alongLine; private: + void initialize(const GeometryCoordinates& line, + const Anchor& anchor, + float top, + float bottom, + float left, + float right, + const std::optional& collisionPadding, + float boxScale, + float padding, + float overscaling, + float rotate); void bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint, std::size_t segment, diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 84b5521b0ef..1c57e4a1d45 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -76,9 +76,6 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon, const uint16_t imageWidth = image.paddedRect.w - 2 * border; const uint16_t imageHeight = image.paddedRect.h - 2 * border; - const float iconWidth = shapedIcon.right() - shapedIcon.left(); - const float iconHeight = shapedIcon.bottom() - shapedIcon.top(); - const ImageStretches stretchXFull{{0.0f, imageWidth}}; const ImageStretches stretchYFull{{0.0f, imageHeight}}; const ImageStretches& stretchX = !image.stretchX.empty() ? image.stretchX : stretchXFull; @@ -98,16 +95,23 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon, float fixedOffsetY = 0; float fixedContentHeight = fixedHeight; + auto icon = shapedIcon; + if (hasIconTextFit && image.content) { - auto& content = *image.content; + const auto& content = *image.content; + const auto contentWidth = content.right - content.left; + const auto contentHeight = content.bottom - content.top; + if (image.textFitWidth || image.textFitHeight) { + icon = icon.applyTextFit(); + } stretchOffsetX = sumWithinRange(stretchX, 0, content.left); stretchOffsetY = sumWithinRange(stretchY, 0, content.top); stretchContentWidth = sumWithinRange(stretchX, content.left, content.right); stretchContentHeight = sumWithinRange(stretchY, content.top, content.bottom); fixedOffsetX = content.left - stretchOffsetX; fixedOffsetY = content.top - stretchOffsetY; - fixedContentWidth = content.right - content.left - stretchContentWidth; - fixedContentHeight = content.bottom - content.top - stretchContentHeight; + fixedContentWidth = contentWidth - stretchContentWidth; + fixedContentHeight = contentHeight - stretchContentHeight; } std::optional> matrix{std::nullopt}; @@ -118,21 +122,22 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon, matrix = std::array{{angle_cos, -angle_sin, angle_sin, angle_cos}}; } + const float iconLeft = icon.left(); + const float iconTop = icon.top(); + const float iconWidth = icon.right() - iconLeft; + const float iconHeight = icon.bottom() - iconTop; + auto makeBox = [&](Cut left, Cut top, Cut right, Cut bottom) { - const float leftEm = getEmOffset( - left.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left()); + const float leftEm = getEmOffset(left.stretch - stretchOffsetX, stretchContentWidth, iconWidth, iconLeft); const float leftPx = getPxOffset(left.fixed - fixedOffsetX, fixedContentWidth, left.stretch, stretchWidth); - const float topEm = getEmOffset( - top.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top()); + const float topEm = getEmOffset(top.stretch - stretchOffsetY, stretchContentHeight, iconHeight, iconTop); const float topPx = getPxOffset(top.fixed - fixedOffsetY, fixedContentHeight, top.stretch, stretchHeight); - const float rightEm = getEmOffset( - right.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left()); + const float rightEm = getEmOffset(right.stretch - stretchOffsetX, stretchContentWidth, iconWidth, iconLeft); const float rightPx = getPxOffset(right.fixed - fixedOffsetX, fixedContentWidth, right.stretch, stretchWidth); - const float bottomEm = getEmOffset( - bottom.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top()); + const float bottomEm = getEmOffset(bottom.stretch - stretchOffsetY, stretchContentHeight, iconHeight, iconTop); const float bottomPx = getPxOffset( bottom.fixed - fixedOffsetY, fixedContentHeight, bottom.stretch, stretchHeight); diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index 991792fed79..1d6b30e80de 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -92,6 +92,45 @@ PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image, return PositionedIcon{image, top, bottom, left, right, collisionPadding}; } +PositionedIcon PositionedIcon::applyTextFit() const { + if (!_image.textFitWidth && !_image.textFitHeight) { + return *this; + } + const float width = _right - _left; + const float height = _bottom - _top; + + const float contentWidth = _image.content->right - _image.content->left; + const float contentHeight = _image.content->bottom - _image.content->top; + const float contentAspectRatio = contentWidth / contentHeight; + const auto textFitWidth = _image.textFitWidth.value(); + const auto textFitHeight = _image.textFitHeight.value(); + float newLeft = _left; + float newRight = _right; + float newTop = _top; + float newBottom = _bottom; + + if (textFitHeight == style::TextFit::proportional) { + if ((textFitWidth == style::TextFit::stretchOnly && (width / height) < contentAspectRatio) || + textFitWidth == style::TextFit::proportional) { + float newIconWidth = std::ceil(height * contentAspectRatio); + newLeft *= newIconWidth / width; + newRight = newLeft + newIconWidth; + } + } else if (textFitWidth == style::TextFit::proportional) { + if (textFitHeight == style::TextFit::stretchOnly && contentAspectRatio != 0 && + (width / height) > contentAspectRatio) { + float newIconHeight = std::ceil(width / contentAspectRatio); + newTop *= newIconHeight / height; + newBottom = newTop + newIconHeight; + } + } else { + // If neither textFitHeight nor textFitWidth are proportional then + // there is no effect since the content rectangle should be precisely + // matched to the content + } + return PositionedIcon{_image, newTop, newBottom, newLeft, newRight, _collisionPadding}; +} + void PositionedIcon::fitIconToText(const Shaping& shapedText, const style::IconTextFitType textFit, const std::array& padding, diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp index 8be0322f516..eb9a95f22cb 100644 --- a/src/mbgl/text/shaping.hpp +++ b/src/mbgl/text/shaping.hpp @@ -73,6 +73,10 @@ class PositionedIcon { const std::array& iconOffset, float fontScale); + // Called after a PositionedIcon has already been run through fitIconToText, + // but needs further adjustment to apply textFitWidth and textFitHeight. + PositionedIcon applyTextFit() const; + const ImagePosition& image() const { return _image; } float top() const { return _top; } float bottom() const { return _bottom; } diff --git a/test/sprite/sprite_parser.test.cpp b/test/sprite/sprite_parser.test.cpp index 57c1026d4c9..17e291b55a7 100644 --- a/test/sprite/sprite_parser.test.cpp +++ b/test/sprite/sprite_parser.test.cpp @@ -589,3 +589,87 @@ TEST(Sprite, SpriteParsingNullRatio) { "sprite", })); } + +TEST(Sprite, SpriteParsingTextFit) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + + const auto images = parseSprite("default", image_1x, R"JSON({ + "image": { + "width": 16, + "height": 16, + "x": 0, + "y": 0, + "pixelRatio": 1, + "textFitWidth": "stretchOrShrink", + "textFitHeight": "proportional" + } + })JSON"); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ("image", images[0]->id); + EXPECT_EQ(style::TextFit::stretchOrShrink, images[0]->textFitWidth); + EXPECT_EQ(style::TextFit::proportional, images[0]->textFitHeight); +} + +TEST(Sprite, SpriteParsingNullTextFit) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + + const auto images = parseSprite("default", image_1x, R"JSON({ + "image": { + "width": 16, + "height": 16, + "x": 0, + "y": 0, + "pixelRatio": 1, + "textFitHeight": "stretchOnly" + } + })JSON"); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ("image", images[0]->id); + EXPECT_FALSE(images[0]->textFitWidth.has_value()); + EXPECT_EQ(style::TextFit::stretchOnly, images[0]->textFitHeight); +} + +TEST(Sprite, SpriteParsingInvalidTextFit) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + + parseSprite("default", image_1x, R"JSON({ + "image": { + "width": 16, + "height": 16, + "x": 0, + "y": 0, + "pixelRatio": 1, + "textFitWidth": "invalid", + "textFitHeight": "stretchOnly" + } + })JSON"); + EXPECT_EQ(1u, + log.count({EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Invalid sprite image 'image': value of 'textFitWidth' " + "is an invalid value 'invalid'"})); + + parseSprite("default", image_1x, R"JSON({ + "image": { + "width": 16, + "height": 16, + "x": 0, + "y": 0, + "pixelRatio": 1, + "textFitHeight": 0 + } + })JSON"); + EXPECT_EQ(1u, + log.count({EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Invalid sprite image 'image': value of 'textFitHeight' " + "must be a string"})); +} \ No newline at end of file diff --git a/test/text/shaping.test.cpp b/test/text/shaping.test.cpp index 0f6c5f6adcd..bd502611f69 100644 --- a/test/text/shaping.test.cpp +++ b/test/text/shaping.test.cpp @@ -103,3 +103,125 @@ TEST(Shaping, ZWSP) { ASSERT_EQ(shaping.writingMode, WritingModeType::Horizontal); } } + +void setupShapedText(Shaping& shapedText, float textSize) { + const auto glyph = PositionedGlyph(32, + 0.0f, + 0.0f, + false, + 0, + 1.0, + /*texRect*/ {}, + /*metrics*/ {}, + /*imageID*/ std::nullopt); + shapedText.right = textSize; + shapedText.bottom = textSize; + shapedText.positionedLines.emplace_back(); + shapedText.positionedLines.back().positionedGlyphs.emplace_back(glyph); +} + +void testApplyTextFit(const mapbox::Bin& rectangle, + const style::ImageContent& content, + const std::optional textFitWidth, + const std::optional textFitHeight, + const Shaping& shapedText, + float fontScale, + float expectedRight, + float expectedBottom) { + ImagePosition image = { + rectangle, + style::Image::Impl("test", + PremultipliedImage({static_cast(rectangle.w), static_cast(rectangle.h)}), + 1.0f, + false, + {}, + {}, + content, + textFitWidth, + textFitHeight)}; + auto shapedIcon = PositionedIcon::shapeIcon(image, {0, 0}, style::SymbolAnchorType::TopLeft); + shapedIcon.fitIconToText(shapedText, style::IconTextFitType::Both, {0, 0, 0, 0}, {0, 0}, fontScale); + const auto& icon = shapedIcon.applyTextFit(); + ASSERT_EQ(icon.top(), 0); + ASSERT_EQ(icon.left(), 0); + ASSERT_EQ(icon.right(), expectedRight); + ASSERT_EQ(icon.bottom(), expectedBottom); +} + +TEST(Shaping, applyTextFit) { + float textSize = 4; + float fontScale = 4; + float expectedImageSize = textSize * fontScale; + Shaping shapedText; + setupShapedText(shapedText, textSize); + + { + // applyTextFitHorizontal + // This set of tests against applyTextFit starts with a 100x20 image with a 5,5,95,15 content box + // that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image. + const auto horizontalRectangle = mapbox::Bin(-1, 100, 20, -1, -1, 0, 0); + const style::ImageContent horizontalContent = {5, 5, 95, 15}; + + { + // applyTextFit: not specified + // No change should happen + testApplyTextFit(horizontalRectangle, + horizontalContent, + std::nullopt, + std::nullopt, + shapedText, + fontScale, + expectedImageSize, + expectedImageSize); + } + + { + // applyTextFit: both stretchOrShrink + // No change should happen + testApplyTextFit(horizontalRectangle, + horizontalContent, + style::TextFit::stretchOrShrink, + style::TextFit::stretchOrShrink, + shapedText, + fontScale, + expectedImageSize, + expectedImageSize); + } + + { + // applyTextFit: stretchOnly, proportional + // Since textFitWidth is stretchOnly, it should be returned to + // the aspect ratio of the content rectangle (9:1) aspect ratio so 144x16. + testApplyTextFit(horizontalRectangle, + horizontalContent, + style::TextFit::stretchOnly, + style::TextFit::proportional, + shapedText, + fontScale, + expectedImageSize * 9, + expectedImageSize); + } + } + + { + // applyTextFitVertical + // This set of tests against applyTextFit starts with a 20x100 image with a 5,5,15,95 content box + // that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image. + const auto verticalRectangle = mapbox::Bin(-1, 20, 100, -1, -1, 0, 0); + const style::ImageContent verticalContent = {5, 5, 15, 95}; + + { + // applyTextFit: stretchOnly, proportional + // Since textFitWidth is stretchOnly, it should be returned to + // the aspect ratio of the content rectangle (9:1) aspect ratio so 144x16. + testApplyTextFit(verticalRectangle, + verticalContent, + style::TextFit::proportional, + style::TextFit::stretchOnly, + shapedText, + fontScale, + expectedImageSize, + expectedImageSize * 9); + } + } +}