From cf0e6504359a1759c082fe0a1989aa0ccc6a08ae Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Wed, 13 May 2020 12:18:51 +0100 Subject: [PATCH] allow scale to be two dimensional add getScaleArray() method test two dimension scale icons test two dimension scale text add example of icon and label scaling use smaller icon and larger interval test two dimensional scale icons test two dimensional scale icons --- examples/data/fish.png | Bin 0 -> 427 bytes examples/icon-scale.html | 16 ++ examples/icon-scale.js | 133 +++++++++++++++++ rendering/cases/icon-scale/expected.png | Bin 0 -> 15318 bytes rendering/cases/icon-scale/main.js | 117 +++++++++++++++ .../text-style-linestring-nice/expected.png | Bin 23219 -> 23624 bytes .../cases/text-style-linestring-nice/main.js | 28 +++- rendering/cases/text-style/expected.png | Bin 7686 -> 8797 bytes rendering/cases/text-style/main.js | 14 +- rendering/data/fish.png | Bin 0 -> 427 bytes src/ol/format/KML.js | 6 +- src/ol/render/canvas.js | 27 +++- src/ol/render/canvas/Executor.js | 51 ++++--- src/ol/render/canvas/ImageBuilder.js | 8 +- src/ol/render/canvas/Immediate.js | 139 +++++++++++------- src/ol/render/canvas/TextBuilder.js | 39 +++-- src/ol/style/Icon.js | 7 +- src/ol/style/Image.js | 27 +++- src/ol/style/Text.js | 27 +++- 19 files changed, 528 insertions(+), 111 deletions(-) create mode 100644 examples/data/fish.png create mode 100644 examples/icon-scale.html create mode 100644 examples/icon-scale.js create mode 100644 rendering/cases/icon-scale/expected.png create mode 100644 rendering/cases/icon-scale/main.js create mode 100644 rendering/data/fish.png diff --git a/examples/data/fish.png b/examples/data/fish.png new file mode 100644 index 0000000000000000000000000000000000000000..8163d232855a24eea6a32965fa684bef6c334ee4 GIT binary patch literal 427 zcmV;c0aX5pP)reTNChGpc!T4~X|h`q2@QNpVjv=nWw;9DCV6fuHv zJjX@IpW|5qnrU-9aqI<16=UH&sTFbo)R&%R8=Am%fR!*A)&4v$NAwClY5jbX@$LJ2 zMoGM*_LUt+$*lmNQJZh4BV9?lnU9i3coMZdjLkN?yTW2T+Z`MrkAAmn3cL8-1mF^@ z7_H;gl!mZ?? + Icons and labels can be scaled in both dimensions if required. A negative value will flip the image + or text around its anchor point (reversed text is not suitable for line placement). A newline + character inserted in label text is interpreted in a vector layer, but will not be shown in + a vector context. +tags: "vector, style, icon, label, scale" +resources: + - https://code.jquery.com/jquery-2.2.3.min.js + - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css + - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js +--- +
diff --git a/examples/icon-scale.js b/examples/icon-scale.js new file mode 100644 index 0000000000..741f87c225 --- /dev/null +++ b/examples/icon-scale.js @@ -0,0 +1,133 @@ +import Feature from '../src/ol/Feature.js'; +import Map from '../src/ol/Map.js'; +import Overlay from '../src/ol/Overlay.js'; +import Point from '../src/ol/geom/Point.js'; +import TileJSON from '../src/ol/source/TileJSON.js'; +import VectorSource from '../src/ol/source/Vector.js'; +import View from '../src/ol/View.js'; +import {Icon, Style, Text} from '../src/ol/style.js'; +import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js'; +import {fromLonLat} from '../src/ol/proj.js'; +import {getVectorContext} from '../src/ol/render.js'; + +const rasterLayer = new TileLayer({ + source: new TileJSON({ + url: 'https://a.tiles.mapbox.com/v3/aj.1x1-degrees.json', + crossOrigin: '', + }), +}); + +const iconFeature = new Feature({ + geometry: new Point(fromLonLat([0, -10])), + name: 'Fish.1', +}); + +const feature1 = new Feature({ + geometry: new Point(fromLonLat([0, -10])), + name: 'Fish.1 Island', +}); + +const feature2 = new Feature({ + geometry: new Point(fromLonLat([-30, 10])), + name: 'Fish.2 Island', +}); + +const iconStyle = new Style({ + image: new Icon({ + anchor: [0.5, 0.9], + src: 'data/fish.png', + crossOrigin: '', + scale: [0, 0], + rotation: Math.PI / 4, + }), + text: new Text({ + text: 'FISH\nTEXT', + scale: [0, 0], + rotation: Math.PI / 4, + textAlign: 'center', + textBaseline: 'top', + }), +}); + +let i = 0; +let j = 45; + +iconFeature.setStyle(function () { + const x = Math.sin((i * Math.PI) / 180) * 3; + const y = Math.sin((j * Math.PI) / 180) * 4; + iconStyle.getImage().setScale([x, y]); + iconStyle.getText().setScale([x, y]); + return iconStyle; +}); + +rasterLayer.on('postrender', function (event) { + const vectorContext = getVectorContext(event); + const x = Math.cos((i * Math.PI) / 180) * 3; + const y = Math.cos((j * Math.PI) / 180) * 4; + iconStyle.getImage().setScale([x, y]); + iconStyle.getText().setScale([x, y]); + vectorContext.drawFeature(feature2, iconStyle); +}); + +const vectorSource = new VectorSource({ + features: [iconFeature, feature1, feature2], +}); + +const vectorLayer = new VectorLayer({ + source: vectorSource, +}); + +const map = new Map({ + layers: [rasterLayer, vectorLayer], + target: document.getElementById('map'), + view: new View({ + center: fromLonLat([-15, 0]), + zoom: 3, + }), +}); + +setInterval(function () { + i = (i + 4) % 360; + j = (j + 5) % 360; + vectorSource.changed(); +}, 1000); + +const element = document.getElementById('popup'); + +const popup = new Overlay({ + element: element, + positioning: 'bottom-center', + stopEvent: false, + offset: [0, -50], +}); +map.addOverlay(popup); + +// display popup on click +map.on('click', function (evt) { + const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { + return feature; + }); + $(element).popover('destroy'); + if (feature) { + const coordinates = feature.getGeometry().getCoordinates(); + popup.setPosition(coordinates); + $(element).popover({ + placement: 'top', + html: true, + animation: false, + content: feature.get('name'), + }); + $(element).popover('show'); + } +}); + +// change mouse cursor when over marker +map.on('pointermove', function (e) { + if (e.dragging) { + $(element).popover('destroy'); + return; + } + const pixel = map.getEventPixel(e.originalEvent); + const hit = map.hasFeatureAtPixel(pixel); + map.getTarget().style.cursor = hit ? 'pointer' : ''; +}); diff --git a/rendering/cases/icon-scale/expected.png b/rendering/cases/icon-scale/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..a3ef37e19c390e8ccd24ca78fc00ef23a1d5be6d GIT binary patch literal 15318 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 F{STtb#U20v literal 23219 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

}qY5tSaq!WgI4 z*VpUN@v8@3l5KHe?O}^|vGdxmhdF^_9WlaA;oM_mzdtUL#L*u20al9M^H_T7p~XS&rcT+?HmK8w6r}vy&cZ`n=SQE zQa0h^pSI7lB*bKg-G>NpLEN1P2Vf zO#8L3B@ID;E;3P(@~Gk{YONB5j54ubUzxEf`IXrjZeyc_!t6TMMiy7={VP|0<)>-J z&h};$j7N5L=>k*X1x*@ZDxz&~F91{zMwszu^`&NJK7zqwh?Y11>w~pIWn=DD>1Xx* zfdBSPQGrxMqtRRO)v$25qYFYr4u&sFU%&QT>Su>il2=fe1I`Z7j1D~9PfIgf0XEuW z&R=yB_5A(HxgHs`w^5|+`Ge|vu)i)mZhwC@M}x^{H;vaMz;Rx^l!5{}L;#q4)o$OV zK>!OXDRBbnJ#*)wuYp=08XiW9XT<}FyJXX_#pjdG*=B>}SK*W$JlszcN+(eiWTK+y;kl1Kf>~zZlA#?33N{YD(*jj% z0|pTW^T{UPd6Prd^F%dR5k&Lg=;$LTX0WDMdU|@C+}%4xrxK}^w!77k4&B2Btwnmz zu~*2FxR;^;H1_uP*uXjhNO_Op=jf+N6k$Knl|bjn^eOMpR7afaZ3_PBcjNH(hX8ue z0|03O5Ny#iGe?b&Tji++b1*YA18c#XmuUO=T+!6hl5!orbWTW!UsjgI*w|R)(xr|j z)q6qzWou~?(wS!S{mG6D-p{YCQ5hK-t@t$Z@9q#^BBC+!+d$^z;*)Z6dK7$OOeh!_ zf|{pCN6C1SqoIugi%8&BVu45iT3t&7If{=VmX9SK?)@3x2DOLpUeMq}^U2Gz4XEsM z#l^?-|B9ac{4Fc3Wn+T)m(*B(WF*O%^}a7mOar$!WvFP?+M|zUm(tAS=}SWHucmLi z9Le1gK<~k%-Uf-PSu~_xegmRfPScASDf;L14Gdagjm>OrlR-f9!*D4C`(u|{E5IH0 zmnVBs`P?a~8l=PD-}d}W(U9aHl!Op6a~^E5?U^PKN2+Hl3~+rJE&n|q9sT&f@n<^Cr-zS--KZt|zc-}5 z?B{Tx@efVW7oq%cBD?h~bpOMBJ3AtPy0cyf4>_q<3QC)&iRV5|#WnwZVDC1qWAy zNfo30Onk?-X=Ch5PDIcG&^&qHHKv^0ToCv~5)u+_V^u_eJfO7)j6`W7;$ld-PHz`+K(+6!R-9 zO)M=PKeEBD&f*0x-$sk#pymqm5+88MzBKLhiZ+7C)v&a(I?CNFe!406xW{K?WTX*x zvaEq^N-)A;zFxm}jZL-QJ=bLacvtbZL61k{R7!X`LYEDXui-xUZL#Z4DvT+7jIVWd zK6lWceYHYHhepW3f5$3ti1;LFbY8Nk3L1szTbfR9! z%3oVor%5m^ghZn6kBqB+M-5Iv<~prE5Mn}}G9~QzJX~x;aMLd>rbv7AFj&$0EN8u> zIpL_W5(C)+AqKVTQmiO+$J-BH#Oiy^P z6zhGuueLC$S4kuyCe{i2K|Ftsid~VFwFe>4#KKIB410cVp+ou!wmVEP&nRn!Q$n;4 z#~m4Tx+gdLEA)KSo&84j(7}DCmFQTwk;;KPBtZXteSI6em+3$tn%daVgk9=mk+?J2 z?&fo@l>tHQ>|BEy=oQeS_fE?(Y&tF}0eCw3%MMgKSI*-ZjOzn0C8h6&lZQt%K&iXC z7z~4>acSAx^Me`zLL#83IF2=uHn(d+&>YX9?k>_ZY8e!M!O=Z_Yp-J|nEWww4#lGk z<`ut5fwD82a&@C2Qj;I7R1^@hGqi4RCuWEx;o;!{z?N(MLK8AZ6=nx!Oc*t*2<7o3 zi+Uo$o3yl+vRjK@UpWB>VCPsXSt(5_rZ)j|cLOg4t zxMW2?q8!0SR_AsYC^R?};vxH?sf3{!r%-NcZh_y_RRV@CkoswsdT?wk1`N}%z8`z9 z)=`UQ^Pb`PNXf=3e+lC$8OwdFBMDNGfR0^>gz<&Tj(0*1|F=F-k3!-Rz*TP6-{)qc zidv1}epW@&veFvM7^bPw#U6pziqyz`d{0JjNLh&=Xp@ih(qIa#HUQ0i8?jWt}(^j24F3ZD)he1$cddWQaz905W{n=W* zuP4&0#1KVSy}X^3Qc~@XC_An$^e_(7$SVvn6;7Y+NrL=o7t=)$q|Ibu4`yJ|4Lb3k zCQRd7!y<@1PnEGSK}OxhB`D+`eBAnvU&NURwi5wG4mjt>QSo5s`MaXSY(YJzTm~LG z+8G&$p{m=OzdsdyJmNm!{2RF79u-wASjhwGB0jz$rurlym8JQXf5W}3#bSPE=F}5=@8@A6G}NAv5YiJuAP^Ge=Zabo2nKkG0l~)wf8MziTcV#_ zwVugC%7+|J|XLoZlTCyW>S*s=2>N;LMk))ZvkX zHA?n|>8`S|vGHf7id>}*u^gsRl1ouk_EY7!sI=TK%~Gt9ML4({%To)X>ytRww60B` znCV1=RWL#{9uYv;v{f*3((Z`a-Jy@cjZso4)%l+C#NX!|H?ArdmFxC!0r;);zy7z| zQDrf}TVwQ?rN{~O(6H&vw;syZPzusrW{o67wtY?p1}9dMn}#XWn}AxN*)Sp^qQPQ0 zQ_7Rq(5LwXlSh_%4$i}qD7X6;9yk#2fQYF=FE@~uQ>L6JlJf4|ZwvX;d{lB*0z6v? zvo6?)5Rd9VAB&EUB(G12C_l?%w#m_u!afDGU=#!yR(vfioI8(-h|v5SL}}0;kR9}= z#A1NGhwnY4v$Kc;^HapP)Am*6#R)EpUD+x)~EUH zcrzH%H~+?8x5UaN#bHB5ogi<1xN^@%%Dc&98eLx<+aO&#f<|Ofj3=mnYAWVD@gxYE z%T~^py&BYNMTJ%KBXN^gH!?({Jy@D@}SU|!H^+F>2M^lNw$l-Z3(fx2vL;?+f>R=h`p*agDnLG?VMe+&tv1^ zx$>iGW#dy)-jtg~lyG8bsOp`d+*)^?M}&T^l5S?D(=l@2J-WCM@JJsBtrew@*_4be zeoF}vRq;V)vzQtD(w|fJmu=NwYJew6pwt~-JUr|Utvx$E<(qa^ocshSmP6d$N~8xi z;!S;%x3%SsJad6RklpmxJ-@iv)^4|784bd!v!kM+>B73IQ{TFHD$Yy*qvsG5j5oNd zgLnCSgYOn)Kh)X*C$|{*GF#3_-TT0;QEW!%nC8OE*qC*mh>5$`d<}ePYpp9PMTM(S zJ$v{J3lG14d21ZeLV#yJA{?J*USNO|9v!WXtQb8FMbVSs1|RI-xNBH`_(PfWHm5%L z4@Oda`ne|cQ)diLsle9B91(0zaq;@j9`MPk2dHB=jqcz)yaH054yf`UYigV%vz!Tm zE#4p}VoC^UNfQP+I_9zZFY5H3&M+p0gkaAHU|?YMpUaOJVRns=S9kUh>0mPRZ{Bgv zxns_mqmXzXN0q7Q0a^A=K7Rn^u{7nOD{l&{RRCVE-=B~+uM7r#ot$_{9PaN_9h}Wwh-jk<>jTZ2)(njbAl&oK7Ig3 z+H3kl(0Y_r(rw2WUOq$2C?4M)j5puNP$!tGQfAbe1&$)=u^(<&VKrZCzYvJJ{r7j0 zh>ng9On}A3#Wgqnjpu+cjshFnjOF3HDpdL5sSD{H95f#+Q24vYcG*n>J8qjp~o9O&7uOs0;EZD`>)oi0T;rtL6Vp-krHbYO=?^3Yl z{j}xIXfD5gZL}=%G8m893uZZ#_QQQoN7D0fu!Bt24(=dHO#sm}i@q!T5v*P7xI8>t zZM8e`jcVEdf=NzJPFzC5`R~O2s_JUxmoKqEF3k+f)XFvxvf2_G85w;MFjC8ubhn=S zdB56nh#jy9lavQ!WqrM)^$2ON1Vr=R?wJoRDP#DU^~Pwfg5S+So%HoizBJ;fgI}*IWFT2!{qQih zqCy~w_CeKyhgu8-Fk5RR;_6+aM@)ANgRte`owv1i1Z`KR+q1Ry41IllUcSDQU+vXxELiEZDnC_j@Df;T2UwU-r;PQ{qlBeq zUtthLO940b9tU$>y$ScOR)Wdy2pYpmo;>Gx1$O>B@vZ4%$@iz@@{))5;atso#LY6w zvNN2b>E^KU-{E3<48!9ubHitQ(^uQFs6GWUna+8~)*%=M)|(nzns48}d9GV5(D*cG z6=nHE2HajJBqengyi7(XAb>LBFfx|z+1b>uUpbb-7=)!X%!Q!*K|58rIIQ6nM@WDzp-KNuu!jQDz!b5{j7A7lAIi-Q(B;3 z=OE&+kWy_mvh+RKMHg)zvu^i;Z+qUGkQeh4wr~rC&t1UukJYF0_F2R=(k9lynO( zE8~x4ksaO~NPa&k0ZX^3dAl`~-qRL@1@NrU|K^;SK`c5>7J0|f(eWcGQ~$~4009Ak z$?f$SSotD$9=TsVg7%EnaE3|y2b@hqvD@`HSs~BE1o#m`iG_WU{ie4V2e@J4-oJsNqgFW_;drF?)*%M2R7fN-R1kg@2eu60=K=g#(% z&sT~;JNcVYYfH0{+Gn7nRMJHHJW!`2vfD-30qj6W0C4~G<%<$fp8!6=xyxq6_-ToL z{P^*PpLVX+Uf(=vG)E4LIpES{VPOHl8USNj?_>{GSCE72ySovyb`Q@omrQ?<)6rQm z=z010xSVV#Lwx@2w1*PW^$rbfZuBJrHTHS$f(=6>1|aWLnVwlA0Iys23wR^^iJ|}5 zr0E5djE~!oIuJBNWqQ>mId!ok=0a$g`uX<3vslLVk&(Ds`}q?fV}wk8WB>D!0eVNq z_gpXl;nmdK4364#($9yuT#o~2wR(7HXg=q@*-z7Qd#(>cVfX_Mk+}c0$l>APM7aS& zv!Qw-muh%KL@uZ>-n9lW1-G{WZRALR5!LnE7v9_hAl%u-}KV4H}iq z%{lJgy*p9zI%+8Wak3P|oRC%fW$EM}V4*b8_uZuxE&YhA)2r1m7VFt6P9zf9bhVWp z5*q5f(My4jjpOy6N2x02=H`Otz2x%p^1Z{uTJr&@beFfF^yY` zm|I$c>r|j`x3;$S9E7O_iiqyv5lFz3-g|LqkaUw|3L|AQy*ygoag#LkJrE_v#j>CK zxq3EjBya(TDnaCHe!l%~|1W>i77b7!`rP)WVk#>Ifp3F?g6kD_cV(3=^UQ`0VLNJ2ggDvb*9B%N=;3TQN||;7*5Ev6Q7h>8qKYj0JPKqw9HnT zU@ZrtWY9Tl@XKvA=J66w?P8>%iL-}C_vGYf5V(}V?a&u52n`JlKes3;U_$ZBbfECu^F_t<`rp6(@K%%>xYlfy1rgZ9?QmhXHbyC*?eXL3+LLN&pxknH z+#oz!2#~U7tG`2ma7OEN?-PzFI)Uzi0bm=JSVoBt?Z!NR3_%TvMsvV!UjY|-0l-{a zbLqLYS#FU5+Qe$P#ozC2QWqrb5eU%4ganiMLW4#RpjX1YPq%*9PL{YdJ6ydG#7jy` ziv*Md+;e_N2$`Lo1ty%R{aaah1F-H*Yk+^k+O%y=G`(mfkW$CXC}i^a!Mw2lwHv*d z-E%)bX<&44*I8OjZ(rYPheb(g8JXkbW0TXZp?~|ciLJ=93Lq(bE)G>)T!g?IPaone zHIef?d>9LOpBOjz`@x583;?OluC9C+uOS2wJolp&Ia4#UgGG{b7z_f0j5XY0fd-Hr z`s{~`ji=oVj({BcLCOl!$CT;U#RAPH1W-vSmQio*Mbihk0Xpx>%gaHKZjEHaos86Y zF<2D|z`1*xyid{mZ&{ssu^gBUir4X;vC~$`t z{%55Gv^f+BRJf=do6l$g2W7|xWoe>COv0*>pCguaY62(Bgk{vfw&0 z+c;psMHCdm0}5%Yt-(}rDJi=9NE{+sCjbusJ4b@B@ap}pgh1;2@bnyb3i4(_37E&H zc}WLRq?T#=JA^>`e8wy!BqTmHweR|DuXMAHun!*^K7Vw6u2ec%<$Y?Ye+0;Kg!z4N{M_wVm7HKzyT zk(r96+bsSP1qv|t{dBpcC8J^%^-{Sr)yQY%^qq-JhqwGM}m3<$LD$49}S z<(T-ICP2?tH=jPXod{Q#y`?52BjZxb=mqK>#A$PL;~Vx=@F6)YTw+#k?l7P@C@3lA zD-4^%uh$%3Ot!tmR0Ss+*e#xCii| z444qMvtuoF@lOY|ytF9=1Oz}bdZTVHB;0n$)uoTInIzpkGujix^`bJMdWPw_vzM&x@HPz-u zX*E8coY{B(k*_CNd?HL<8(n9(0tW-+ee&c9nn+*(-cE+4;4?^1E8kBL^1Mj26a$qa z1vPai&|-ScKB7PiSae6<1vHbHlf&xksaXhaAez|M*%?9A2Poj)y$d!Sniu^G2#De1I$8=5` z|LuVNSrdW7DEi+HN*1(%7|)0?K#R^n>+NxcUiC+y!qJ-1P0}EB-s9(gGvfb52F`B{ zVOQw)7#eH&NwWkZoEu_SpR=*D;8L<1X=rFfbOr9uJPI(Zjb>fRhDKd_vEREl;9myN zO4w!Nd1D~#Ihsx2h`1-$))B5qU}GmyR#?#~JPrq7AD^4bGkkD{Tpye+)Tjd4=XzD3 z6;i~V*$ts-N*(1}LwA8t35~OdlgGP4*z(HCd>Gt7gMPmh%4;hzkh^heazz+ASfmY2nkI= zfoJg$>H91uZ!F#ML|%=QYH`6@+*?RfQ`1^4!#G7rVZA$sZ=tSHh7!1?gp!(C5i|lp z!Or8}xVCiFygjr|u`=s%kW%GRVBZ3_5~&gvh+|XusO^q1qSd#|HmO(bdL?*&q(BN^XXEn33%MIsCdJXY;hwJ6#9_an}zxMm^) z`wLYSo36N4_4K5-ca?YgKf`J+ml+<%7Jz!Nq?AuaDW+s1RNl#R7(`MyJzOn{1zI%j z{LSVSv(04W{d6%3(Ef_vFh3WU8n>U~2MM^lyW1q=z_=H1`#CNn^Vpy^8W1l{qlWcR znrKK^7@hA2L9jU}e!uvfRF)_}3n6(*d@qlKMIoU2dY|4JSYt!A3O1LHzZh4y7NL(m z-LCGk+oH0vdf0l+tHA69fkjYpyR5Zg?8)a^4q31555gu(qcSP?k!wUkz+RrLQ^1OUbjLF37p@6tTy7ZX$YVlAuxh5tH<8nZW(u~vQST>z|1`!>VD_i3 zchA)r*&V-fKl^K1gsrTsJdyS|4hL3lGp-fY3Vj^|azQbs2DB)I=ukrsC%!2Vj}pAW z5Z~T7y6`yI0m2FNrZF63Y{V_bx#j?2u36!+v$G3gsPCQ;BYI>H>jhp@V4k#MMbWF~ zk2&qn{BVJ@P*AjAPnO!mfBG%MBy|!PC(|9zreHThr;EV37Y+hfE&6T;13k%lx~N$j zgX7WEPaBb5lw;>d;=5YqFGJBv4S;=V(k@8f;$vQVOwI;_<7L15$9~W86RWDc@?5QS zzU%Aen(6A`_bNj**Y8Ja?XqcPtqIh(UN&Fw`XTxyAMtEMLU?&1U7m5zA1XeLY&D(- z8-o(cFgJiYg9;xXf92oq_@=D_AYf5mGY*YP4eMtTQL;dsFjcgwjqvG;6EuNSgz6Aq zUtW?kFuc^#q6E4jF!drCgs0XRdF2D@{=U_ri)DdV$1K-d3{7+o)?_6ltWW0m=vYR6 znDz9FN%PoUZw2!NRnrr-0hqVMv0BLlk1-h5S!)kT9U2_;HBJE*J2FbTXO za*buWchYim$s)*n$@?TrtkF~0=Fe9t$p8x)SrFePTW~UZ61PJ;c-BImkQy;9av!SP zg?eGmv8$%$$3)vbKtu}~WbO3>$uW1PgV*)2fKWPdIiUQ^ep(qwmd6cB|b%lZs zC1Z3%u7^W;bK|SB$gDdm>gwDwGMNSH((SQ((~kF%BHY}hp`nkgX9U?>E#OYSVmYc@yIL>7aF>li>koN*v2eDK~tVxI^WAK90QX1>z9kj-ZkN$ z{ndl3r=MFftgcSo63yMed?sw4R>KstH6j*ugJ&V~c3xoSP;H)PVfyGu_NH*GtSV*uXfb zFtVDfXkC*s`A`EP3JE(MYejZ_?2c*39UB!BP8>A~ELg7|`7-y>X7h!3^ol`j!!A?OTwKDWx8HP2 zpmo$8ahc~|o!Ebe0O()Zk+j#Q$FkUi@aZ_4DB91zvT`ba{uE&b42A@C0b$dxwLbi| zF+ZflJcHQRn6BT4xFoE+kYUuw0%BjL~^;;FGpIX@Q%M4i>T94z7AI$NX z16qr|y7eT@7H{vd8eR!Jpzk9f7_?nX>r+>hmMY@bK_9S5yEpIrHGCiwt!7x91KQ{kC`ennJK!N_69*92_S4 zhAbxFt@>E2MyR#oFud==!UVQsALbewqz#Km-CbQDO?`j=zDUjCVNHdhMMgS9&FM+m z$laJgX6tpOrmE`W!Jz^NKsX%S>siTRKSpJLo6hrW2yjuch}m{#;gXDQZ;Te(yb2iI zwf4Q0^e4f!-QHSDPH-N0?=~{f;od{a+~^W&uB)p;gAiNn*B&FsCnnx#^S__~Y}G+0 z+bhr7_^p8FO-4p!3m;aPjPw!c@71QJPGE|8`%+m8Q5XvyJDhI4Q-2QqraSV>c~zoT zsY6xRVRX;Fr@wLcTiMJTANPZ|cCCj$W448a@KsbTd^tAkosN zeIfv@DDudv>Eh?^@nI?HHD$|G>j4EZWRIJGso_#i336^C=;Ub0Wh7<|)!Caer{;wP z`^Yp8S|0uTnmjv5M?yc!_aFw>{jYK5oAC3amG++^59=FG-A&n3hllqEdsot`g#)I` zXXhmJ>K=k2Kj#B_-FNTG;GIZh?e^l^pE(6xzxU__TsArhkp72^OL}^4zYG{c5eW%$ zi42cZuIC*mhKD!{9SnYf2AW){#dN{TH-D$O$J--s)LwUU{s#ZQi(RirJNf*P17igj zm&@pQA~Y~C%WgW>siufd< zE5>_qvv$oD)2N2lcF20SoR|3h@^a$CiHM!`p6{oP@*|6;yISuVxYd`u8GM>+$RwGX zwPGV65KJQUcLCgXG4V*>%+pIw_*@AJ9!*Wtk{kOkSce!imL1%UnVNQ8ft?{$U$H&Y zy34})%R2_@+?5S%Q)$w{`?I#Sj00ku!rrAn+&V`&FG%0;=R1ShT;29KOJL_Z;wmpc zlD;f2o9RCp`q&?~vt@tiaU7h1UFIwT?Eq~D8MZfi_SPcB$4vQo+_*%6<3~gLuMvQz zY%`Qp(<(2LjhskHz9YmCw+&V&=I1@#Z%1f~Hx^r=7XGkeL0?+gUTSE#P-$5OUA5Q2yfDcRoMPO6Du1?6~X5+^ocJdZKe3XCA8Dlt+AW-lT3c<$(Z-y=v8uQ7Wo-0iV0eAA>%_@QP&Sj#G(*yq2LPR&M6 zY8U60PHaz1wi;+V*ss*JIqLa{Y>hrf*o&TDZCe&UH%P2C_tbwJ`O(uLNO!ugB9NP@ zuG5LHlUs0XC!vE}lS74m{=LMn1#Z_F--;8WH(V9S6;~b`Dj5wj>5`;eI3bzzX*^CK z*%KBhQ)sjT1V7)50wP_K{{OhC@J~-1t=v*36l|o`IR!3B>tUb2<(A&nQoA5p;RI2LsHVutCP8a*`SV!3Qh)} zO&-f%S!**^r~(-=%;iDaj|w=Wm9?L{yL;N9?jo;xR|(avXx`J;5XD<;etCz1nzsjD zyZZPk2gj>eQ`3Q#yi40Y{|KoD+7!Ks39GF%vA1+pFa_p@Ti#kMu9x@oJ>%B zh*=PZkj+bWMaRQ^Zy&+sQ#XV}TG2Yu593VZ;1F+PFc9kR6n*8Tw6$|#14!gbKoDIX z>FFJ^AgfW6JHrJiZsJqcU4;7v=Y=29;v$$9^iexuSeOu1*o&H)=G>3n#~tp1P{)>| zyF~s8ixg|4hszQ(X?>P6wj1xE}Fq>I=460E2O8ij1Q2QJ^|Lfo|RoYqtI z^&=i|aM+CtoSmKd3Y-ejmcZd{C2yk;N?0bb>x`G;3$_Si>fs)o`qkF6wWTbqs_JTF zgUZ1Nd(Z>ty3pc&5(H-T9=EM6dS!Ixz)!~9BKs)wVyX(1%HnUbs6$_^o}M1HJDsz) z0wngq#Kgoa67g0NHJuJSfkLk@KFIUN@woxeOecB;JFWlxx6J-{YpQp%qgM{kmb@?l zr(Gy1Ev@%gNAFj!FXyA>27;R}x!Bp4&Q@|ye$izu)9icQ_u5$$9ouhi7V{ty{zcl@ zs9Wbi51{Pk?(U4aI(hr_@d94RlpSN4O00A%T@cj+(K!xDXXncO7UqqJYglqpQgh*s zwmJjOqkB{V>MVgt&;iHR+Jpi&MF?Ab$5m}01+k*P|8*n++?f*G@$Y%wB~}Wzda$G( zR54k$kS)&_SFuajlAvpq3CgW#WCsCj%C3<|cNX4+Pbu}ay!>c8Ei<0B#A=ho~>cU@_BoEUpksHOYp<$DcNvEb`1wk=GPK1w~!n^hwlZh zDK)lZBuxcE z<+ZiidQBeXC*zp{_98p`=w9zblw8C}=EsjkWyWp(<9EVg*?%8&gsStbVf{Z5$dr-d9IsXO{=acQ!Wr?!s?V+koLLN*|q^9IThZUFO@N=jZ3T zH8yv^!n~A`IcxmEBUb_GN_RQ`i&>1}`aZSw@ZrN-rFUzu+d~ zeJ~_=(=%%0NbF?V6-I;$x;j0`#V9*F^ROiMk6FY&rhu3YuCA>yi->$GDPd#qKQ*28 z*?E2qZkqRKii(V!@1{2X+}uo8I2erd3t(+Su6OlagBPEp|U-VL7i~M=4=R#wt*0pLPeL8L@pv*$a zXF13uAdu=g=a&{8eH*}~4}myv|62Gd78=RZZ^F&(b8IJIH!f*y%_ebR4 z8Q=2I)YSa0UtVv>nL#f^8dty;4UZw~)Z@4d+GR(IHU>Vj-@wbys7G(pL-gwE3jBgu z{|kE(2C=?BU$ykUn?NnAGdd$ktDP34!Lai3^1JR0h4F4s+5FmCfk8_?9b>;5xDr&1 zbpn{HoCRdnO#}-Y+gXV2)vH(YE)Dg^leWU%`wwa2aEsCX%R`wB2fsu!gq-h_lase{ zdcR79z>4^3h`~Z7z!8wVqN1?hzcr21c<#r^hP1UwD5Y^)^v2USUu-wId3wI(&FC8( z1ceI!`BS>0}YtdwMAl5gKW0NNx(N3yuIq@boISBN@objwY`r&o-(D}H9DM9;rS1)mDOr^B3JS2mubOe_{pZ5GH23=!Ov{jS%ySaCTt}YE5kHl%Qiy-x>K{$BEp-xLfBM4>v>d2T}5fbVAn2jy6 z!F7e#d*6Hjfq4An$$eJVh&6QaK@Y8?x}ILtkmb@1f;xh4b@lf0adQVwZOOvNE*dY{ zWwA_%CTs0!qYKE$$lAep{e69qyt1;`q$G+gRaX7-R9c7npnH6lS#{;`*7NA+KF9M; zLc1p?R-m)N489e`=2!$L3kz;Yhoqbw-usrEpdjd*fGc-^Wp0`{96Y>(0e1L@l$4h* zU*Zf64Y|3wefacA(aWnIj%d4YPGmxKzNQv1;OKuqTToayQEf#E$R%VlDTXoND~)|x%opd-?M|2B_|WqrDr5TNYj#65?(J|V!z2gTWpZjNUMRCWQn z#b+@<1voDyB{i5Ukqht&01Ot~VywdG&!0axT$hxDaHhq8vKXiNPbg5E5TV!HX1|u9 zA578;*a_J-C0;Wp@ZT0^DDDN1qEM(Z!-k}^H}9i<{NUHFFzo;F4hQX7Mz4you^I8q9Y?sW}CgmPUk~lak2neJ;ApKh1}Pve2zDnxwsPc z_g${9PudRtXsK1&j&X9_Mbz0`tfC4x=i25ju9{8-?6YRSw6$SG>6LD#5E+T@P``kC zyfcRceL>_^R4lrq?8j3ZR=&FrAwp%r`W)!ihvAN zPbjOYk>0y^PwZl|8c1gLYXc1p@=QU;FAWX%vQ>Mtgk9@_PJ3_Fi~;umRcIF-zWA-g zm6(yCpsD%$R*OFYBwxRyqhs*XvzX9OoTQ|rlJfF@z%hW+h@Y=MU{TGI2ih=Z=t>L_ z2<+^;c|XPB`{z%eJ_Q9*fBjlUNeQ86zXPUDK*{pmv=jF>Az=$TnkFv%_}IfAI5B!= zW~*g7SJZP`&)#mXl|D|kGfr?ea>V9eU*ZGcqD~v-b^D_Rj+G8GBA}Qh-@Yxzi*DD? zCo?{Tgbv(`lLgvRIklA~nO~n3 zk|Fii=NmT`*Dm9^1jb$mQGUUr3HXw725;Emq1*CcMki~oue7Z#`}60|`JX*QO;2xL zK>%kXo;`cEa#@Cxttw|>@d$8mp}cOkv83^5XQzUKf++|TrxzE6=(TkIcND<2I%{1; zvQtu1&G>1!P6aG8aH+76y6r#12)$SHBXpZQo)#4q0dy?7i8KJ|YsqCLyLV5)$cR3I zguVa{Cj}*tlIqagdTQL7H9PypA9FDWc;=~bqFwf;g(jl2<6@@`DZ11A;@!J7JytJ8 z#oNI8!QLplntfm8FCSDczp+sS7;A=@ch!yK2dIqy`4fs>J9K}XmW}vV030MZ7z^OI zzrX+TVh#g{6280ZL_%DsmPXIJSKJ$gXqV7|UMJ(2y}Opa^CI5Ok9mjIa08nonkZ=tMnY0b8`; zZ-$z^4x1PX;H(iKj7CRC17WyHEOs-E zA1f*xb)gz2OposdQJ2E4K-&|7m7sc9RT2rcPI80Rwpfe(P3S5`&FMVM|Lk zC@XLu1;CSb;a(hBb^-`E_=53FN>ZFGKp1S(9^e;z3LUw7zjG zpd7DtjGnDaII3ewMmkCrqsi~w>CU}AWChfZii)~X_R&#U5DSu7)xPBA1%kJmtk28K zd%8dxApidTdCB!$r1@RRNWytHk(R5=a)Y`mU_>A{%7HSrw6q+aoK(B5Y3l3i1BW;C z*{b2t{ciGy1Z#jJkc@i%u-{lmM-Hq82rCnlz^ zVU>`lmW+%6)-VVR5ct-kM~`k$2f{lbiy7wn>PKy@%b1a8Vs`e{h9**}5h88)5FmGI z>)7AY1i-e*bEn6gmj|RTF!`Gfz!c4@aw z%_2y{SI1L&^-j#d@>@9%ICycHx;*~?uj^dM1GxG7*Bne>WMl*!PEi8tN=ZSDjEv^a zu*JCWwm`ZTJa5Ej?x|{Tm&C%tN*DFybg0V&jt#_@jf;zwmzSa#t)Q$-G=CQ95z;Zg z6pj4A4q@gDy3yz4wmTwf@ts($(WIaJtnd3ba*yx$z~Yhvsl7B4-3`EdbNUB90WVPJ0UY|@1Hu2OrT}AVrk)0g zYjPS|W@adZ|M=KQBpk&SU2xin&*MK4D|=lw=9)VsYhqgpN01vo(1En>ULL4xVUv^Z zo-SEoQpK)(*I((jOdd>IhRDR2j66}J-Dx9@Ad#{vF3$EonD3!o7!rJLFDUT7R!Kf^ zP#M{nPeY5eBb;lE%dfGtly7(!UumJ?pPkDio z0t|VG7AqRr-`IALW(c60`l4dxueAIRwfmE>d3mK5&QJ5Ru}Qefo;G*QZTjqN#oDo% z++#EE8Xizo-*B&bNcQs^^)qP>8fnpg)d3EpxACsn&O_jfk2ETPOTWiJTTojv$d z1EFzrh*BZ5BHRkq>i5vi&1CAwyDow7QT@zBDFyqdGY*1K2SJJPx&&KArLSMh%rW!( zA68fSdVTj5YU^s8zm*d=$-Wp5CAiG{9NKRTS25(_#a|_4p>%vH_jYRod-pOmHoj*9 z1$Auhh~T8|HZ`SN-wG=?cuYk6uXEQaUgvcO9^>#qu|#E2eh@?H$NC`XQ_lg!27!c05}HGlAR*Qxk}*B*fdu z=yJ1mN*6WzYxX<0om|43d`}(UY@EOZ>pQn1Wce=Zc-6rMMqg&3m!6&<54TECEbFjU z+yQvuLyp*>5Io^KF!>U+f|)%2WYf;_lYjuMX@^N{tmds#_S@Gd(=YU$xPu%7?Sq1b zXSa=ZIG!vblUXVs^CYT7MK#mkk!j0iq`$siaeNzT@cw;$kIg@IYc@D6PAE%t^6HAf zy+IzIK&r`sK9QtX*tp5qUtDL(?$EYI*Qi42s5YALA#|QFF%gD`%SK4hQE7^O%$(NG zNJ}&b&Yn1!0v~I$PZbvSSL&wUt`Ay@mUan{*n&b|WegEbyOLU9V~<~5%733~+2UV! zBf31UqpQ}hw5iE)Cm@(T@^=vQ>Fit^wNY5z>7Co^G1h2ph+|GF(@yp9;BA2?_?eo% z5~X{1bb=-)lWgb?K4`sw!6t8=(qK9W*o3eA;r&&QwG477Z~%L{wq$SNJ=0^Tw6`KBdDudzn%;{xvtY_M!6fx#=D<EDxzvR*>do{VGk;)CHmveI`s0y7<#t=cZ=uRKI45BBSakO_sxellu0 z)F69p4k}|Y`VR9E;|;EE6-~|Me)!H^#mk49@!<*$&HB2~dZ9ZzholDgpM2E<2ZmL@ z(WtBAIR)|t{80WoE4FojH?&Y^XsLi+lKmB*k>A+ED_=uIt=w2SnW24T*CWFYe$TS zeOE6!Ew!gM65k*2BDC%D*7?PAdzDW(uFGDnxf?Y_pS|L>3^v~Fq#BrvadKyfA;-!Z zcz2p$;Or;s9Wl}0)L5e9l#lr>eT-X?_9-7xJXR!iMd0j6$Jq4rq>WkljN&z?uT&4D zCj*pExi)-h1UE&8xbq7w21#dpGf6wr1B##O>1<2HS18tgd?QeBjC~{m%RueOd w7#xgoG>)bD@Ba(kp#Q-x_reTNChGpc!T4~X|h`q2@QNpVjv=nWw;9DCV6fuHv zJjX@IpW|5qnrU-9aqI<16=UH&sTFbo)R&%R8=Am%fR!*A)&4v$NAwClY5jbX@$LJ2 zMoGM*_LUt+$*lmNQJZh4BV9?lnU9i3coMZdjLkN?yTW2T+Z`MrkAAmn3cL8-1mF^@ z7_H;gl!mZ??} [padding] */ @@ -410,7 +410,7 @@ export function rotateAtOffset(context, rotation, offsetX, offsetY) { * @param {number} h Height. * @param {number} x X. * @param {number} y Y. - * @param {number} scale Scale. + * @param {import("../size.js").Size} scale Scale. */ export function drawImageOrLabel( context, @@ -437,10 +437,25 @@ export function drawImageOrLabel( if (/** @type {*} */ (labelOrImage).contextInstructions) { // label context.translate(x, y); - context.scale(scale, scale); + context.scale(scale[0], scale[1]); executeLabelInstructions(/** @type {Label} */ (labelOrImage), context); + } else if (scale[0] < 0 || scale[1] < 0) { + // flipped image + context.translate(x, y); + context.scale(scale[0], scale[1]); + context.drawImage( + /** @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} */ (labelOrImage), + originX, + originY, + w, + h, + 0, + 0, + w, + h + ); } else { - // image + // if image not flipped translate and scale can be avoided context.drawImage( /** @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} */ (labelOrImage), originX, @@ -449,8 +464,8 @@ export function drawImageOrLabel( h, x, y, - w * scale, - h * scale + w * scale[0], + h * scale[1] ); } diff --git a/src/ol/render/canvas/Executor.js b/src/ol/render/canvas/Executor.js index 26943c576e..ee3f708be4 100644 --- a/src/ol/render/canvas/Executor.js +++ b/src/ol/render/canvas/Executor.js @@ -187,7 +187,10 @@ class Executor { const fillState = fillKey ? this.fillStates[fillKey] : null; const textState = this.textStates[textKey]; const pixelRatio = this.pixelRatio; - const scale = textState.scale * pixelRatio; + const scale = [ + textState.scale[0] * pixelRatio, + textState.scale[1] * pixelRatio, + ]; const align = TEXT_ALIGN[textState.textAlign || defaultTextAlign]; const strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0; @@ -200,15 +203,17 @@ class Executor { const height = lineHeight * numLines; const renderWidth = width + strokeWidth; const contextInstructions = []; + // make canvas 2 pixels wider to account for italic text width measurement errors + const w = (renderWidth + 2) * scale[0]; + const h = (height + strokeWidth) * scale[1]; /** @type {import("../canvas.js").Label} */ const label = { - // make canvas 2 pixels wider to account for italic text width measurement errors - width: Math.ceil((renderWidth + 2) * scale), - height: Math.ceil((height + strokeWidth) * scale), + width: w < 0 ? Math.floor(w) : Math.ceil(w), + height: h < 0 ? Math.floor(h) : Math.ceil(h), contextInstructions: contextInstructions, }; - if (scale != 1) { - contextInstructions.push('scale', [scale, scale]); + if (scale[0] != 1 || scale[1] != 1) { + contextInstructions.push('scale', scale); } contextInstructions.push('font', textState.font); if (strokeKey) { @@ -310,7 +315,7 @@ class Executor { * @param {number} originX Origin X. * @param {number} originY Origin Y. * @param {number} rotation Rotation. - * @param {number} scale Scale. + * @param {import("../../size.js").Size} scale Scale. * @param {boolean} snapToPixel Snap to pixel. * @param {number} width Width. * @param {Array} padding Padding. @@ -339,8 +344,8 @@ class Executor { strokeInstruction ) { const fillStroke = fillInstruction || strokeInstruction; - anchorX *= scale; - anchorY *= scale; + anchorX *= scale[0]; + anchorY *= scale[1]; x -= anchorX; y -= anchorY; @@ -352,8 +357,8 @@ class Executor { height + originY > imageOrLabel.height ? imageOrLabel.height - originY : height; - const boxW = padding[3] + w * scale + padding[1]; - const boxH = padding[0] + h * scale + padding[2]; + const boxW = padding[3] + w * scale[0] + padding[1]; + const boxH = padding[0] + h * scale[1] + padding[2]; const boxX = x - padding[3]; const boxY = y - padding[0]; @@ -399,7 +404,7 @@ class Executor { } const canvas = context.canvas; const strokePadding = strokeInstruction - ? (strokeInstruction[2] * scale) / 2 + ? (strokeInstruction[2] * scale[0]) / 2 : 0; const intersects = tmpExtent[0] - strokePadding <= canvas.width / contextScale && @@ -586,7 +591,7 @@ class Executor { strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0; // Remove the 2 pixels we added in createLabel() for the anchor - const width = label.width / pixelRatio - 2 * textState.scale; + const width = label.width / pixelRatio - 2 * textState.scale[0]; const anchorX = align * width + 2 * (0.5 - align) * strokeWidth; const anchorY = (baseline * label.height) / pixelRatio + @@ -765,7 +770,7 @@ class Executor { const originY = /** @type {number} */ (instruction[10]); const rotateWithView = /** @type {boolean} */ (instruction[11]); let rotation = /** @type {number} */ (instruction[12]); - const scale = /** @type {number} */ (instruction[13]); + const scale = /** @type {import("../../size.js").Size} */ (instruction[13]); let width = /** @type {number} */ (instruction[14]); if (!image && instruction.length >= 19) { @@ -883,11 +888,17 @@ class Executor { const strokeWidth = /** @type {number} */ (instruction[11]); text = /** @type {string} */ (instruction[12]); textKey = /** @type {string} */ (instruction[13]); - const pixelRatioScale = /** @type {number} */ (instruction[14]); + const pixelRatioScale = [ + /** @type {number} */ (instruction[14]), + /** @type {number} */ (instruction[14]), + ]; const textState = this.textStates[textKey]; const font = textState.font; - const textScale = textState.scale * measurePixelRatio; + const textScale = [ + textState.scale[0] * measurePixelRatio, + textState.scale[1] * measurePixelRatio, + ]; let cachedWidths; if (font in this.widths_) { @@ -899,7 +910,8 @@ class Executor { const pathLength = lineStringLength(pixelCoordinates, begin, end, 2); const textLength = - textScale * measureAndCacheTextWidth(font, text, cachedWidths); + Math.abs(textScale[0]) * + measureAndCacheTextWidth(font, text, cachedWidths); if (overflow || textLength <= pathLength) { const textAlign = this.textStates[textKey].textAlign; const startM = (pathLength - textLength) * TEXT_ALIGN[textAlign]; @@ -911,7 +923,7 @@ class Executor { text, startM, maxAngle, - textScale, + Math.abs(textScale[0]), measureAndCacheTextWidth, font, cachedWidths @@ -926,7 +938,8 @@ class Executor { anchorX = /** @type {number} */ (part[2]) + strokeWidth; anchorY = baseline * label.height + - (0.5 - baseline) * 2 * strokeWidth - + ((0.5 - baseline) * 2 * strokeWidth * textScale[1]) / + textScale[0] - offsetY; this.replayImageOrLabel_( context, diff --git a/src/ol/render/canvas/ImageBuilder.js b/src/ol/render/canvas/ImageBuilder.js index 11f18bb52b..df8320742d 100644 --- a/src/ol/render/canvas/ImageBuilder.js +++ b/src/ol/render/canvas/ImageBuilder.js @@ -82,7 +82,7 @@ class CanvasImageBuilder extends CanvasBuilder { /** * @private - * @type {number|undefined} + * @type {import("../../size.js").Size|undefined} */ this.scale_ = undefined; @@ -145,7 +145,7 @@ class CanvasImageBuilder extends CanvasBuilder { this.originY_, this.rotateWithView_, this.rotation_, - this.scale_ * this.pixelRatio, + [this.scale_[0] * this.pixelRatio, this.scale_[1] * this.pixelRatio], this.width_, ]); this.hitDetectionInstructions.push([ @@ -202,7 +202,7 @@ class CanvasImageBuilder extends CanvasBuilder { this.originY_, this.rotateWithView_, this.rotation_, - this.scale_ * this.pixelRatio, + [this.scale_[0] * this.pixelRatio, this.scale_[1] * this.pixelRatio], this.width_, ]); this.hitDetectionInstructions.push([ @@ -268,7 +268,7 @@ class CanvasImageBuilder extends CanvasBuilder { this.originY_ = origin[1]; this.rotateWithView_ = imageStyle.getRotateWithView(); this.rotation_ = imageStyle.getRotation(); - this.scale_ = imageStyle.getScale(); + this.scale_ = imageStyle.getScaleArray(); this.width_ = size[0]; } } diff --git a/src/ol/render/canvas/Immediate.js b/src/ol/render/canvas/Immediate.js index ee427280fb..ba33de0a44 100644 --- a/src/ol/render/canvas/Immediate.js +++ b/src/ol/render/canvas/Immediate.js @@ -188,9 +188,9 @@ class CanvasImmediateRenderer extends VectorContext { /** * @private - * @type {number} + * @type {import("../../size.js").Size} */ - this.imageScale_ = 0; + this.imageScale_ = [0, 0]; /** * @private @@ -230,9 +230,9 @@ class CanvasImmediateRenderer extends VectorContext { /** * @private - * @type {number} + * @type {import("../../size.js").Size} */ - this.textScale_ = 0; + this.textScale_ = [0, 0]; /** * @private @@ -297,35 +297,51 @@ class CanvasImmediateRenderer extends VectorContext { for (let i = 0, ii = pixelCoordinates.length; i < ii; i += 2) { const x = pixelCoordinates[i] - this.imageAnchorX_; const y = pixelCoordinates[i + 1] - this.imageAnchorY_; - if (rotation !== 0 || this.imageScale_ != 1) { + if ( + rotation !== 0 || + this.imageScale_[0] != 1 || + this.imageScale_[1] != 1 + ) { const centerX = x + this.imageAnchorX_; const centerY = y + this.imageAnchorY_; composeTransform( localTransform, centerX, centerY, - this.imageScale_, - this.imageScale_, + 1, + 1, rotation, -centerX, -centerY ); context.setTransform.apply(context, localTransform); + context.translate(centerX, centerY); + context.scale(this.imageScale_[0], this.imageScale_[1]); + context.drawImage( + this.image_, + this.imageOriginX_, + this.imageOriginY_, + this.imageWidth_, + this.imageHeight_, + -this.imageAnchorX_, + -this.imageAnchorY_, + this.imageWidth_, + this.imageHeight_ + ); + context.setTransform(1, 0, 0, 1, 0, 0); + } else { + context.drawImage( + this.image_, + this.imageOriginX_, + this.imageOriginY_, + this.imageWidth_, + this.imageHeight_, + x, + y, + this.imageWidth_, + this.imageHeight_ + ); } - context.drawImage( - this.image_, - this.imageOriginX_, - this.imageOriginY_, - this.imageWidth_, - this.imageHeight_, - x, - y, - this.imageWidth_, - this.imageHeight_ - ); - } - if (rotation !== 0 || this.imageScale_ != 1) { - context.setTransform(1, 0, 0, 1, 0, 0); } if (this.imageOpacity_ != 1) { context.globalAlpha = alpha; @@ -366,28 +382,39 @@ class CanvasImmediateRenderer extends VectorContext { for (; offset < end; offset += stride) { const x = pixelCoordinates[offset] + this.textOffsetX_; const y = pixelCoordinates[offset + 1] + this.textOffsetY_; - if (rotation !== 0 || this.textScale_ != 1) { + if ( + rotation !== 0 || + this.textScale_[0] != 1 || + this.textScale_[1] != 1 + ) { const localTransform = composeTransform( this.tmpLocalTransform_, x, y, - this.textScale_, - this.textScale_, + 1, + 1, rotation, -x, -y ); context.setTransform.apply(context, localTransform); + context.translate(x, y); + context.scale(this.textScale_[0], this.textScale_[1]); + if (this.textStrokeState_) { + context.strokeText(this.text_, 0, 0); + } + if (this.textFillState_) { + context.fillText(this.text_, 0, 0); + } + context.setTransform(1, 0, 0, 1, 0, 0); + } else { + if (this.textStrokeState_) { + context.strokeText(this.text_, x, y); + } + if (this.textFillState_) { + context.fillText(this.text_, x, y); + } } - if (this.textStrokeState_) { - context.strokeText(this.text_, x, y); - } - if (this.textFillState_) { - context.fillText(this.text_, x, y); - } - } - if (rotation !== 0 || this.textScale_ != 1) { - context.setTransform(1, 0, 0, 1, 0, 0); } } @@ -994,22 +1021,30 @@ class CanvasImmediateRenderer extends VectorContext { if (!imageStyle) { this.image_ = null; } else { - const imageAnchor = imageStyle.getAnchor(); - // FIXME pixel ratio - const imageImage = imageStyle.getImage(1); - const imageOrigin = imageStyle.getOrigin(); const imageSize = imageStyle.getSize(); - this.imageAnchorX_ = imageAnchor[0]; - this.imageAnchorY_ = imageAnchor[1]; - this.imageHeight_ = imageSize[1]; - this.image_ = imageImage; - this.imageOpacity_ = imageStyle.getOpacity(); - this.imageOriginX_ = imageOrigin[0]; - this.imageOriginY_ = imageOrigin[1]; - this.imageRotateWithView_ = imageStyle.getRotateWithView(); - this.imageRotation_ = imageStyle.getRotation(); - this.imageScale_ = imageStyle.getScale() * this.pixelRatio_; - this.imageWidth_ = imageSize[0]; + if (!imageSize) { + this.image_ = null; + } else { + const imageAnchor = imageStyle.getAnchor(); + // FIXME pixel ratio + const imageImage = imageStyle.getImage(1); + const imageOrigin = imageStyle.getOrigin(); + const imageScale = imageStyle.getScaleArray(); + this.imageAnchorX_ = imageAnchor[0]; + this.imageAnchorY_ = imageAnchor[1]; + this.imageHeight_ = imageSize[1]; + this.image_ = imageImage; + this.imageOpacity_ = imageStyle.getOpacity(); + this.imageOriginX_ = imageOrigin[0]; + this.imageOriginY_ = imageOrigin[1]; + this.imageRotateWithView_ = imageStyle.getRotateWithView(); + this.imageRotation_ = imageStyle.getRotation(); + this.imageScale_ = [ + this.pixelRatio_ * imageScale[0], + this.pixelRatio_ * imageScale[1], + ]; + this.imageWidth_ = imageSize[0]; + } } } @@ -1078,7 +1113,7 @@ class CanvasImmediateRenderer extends VectorContext { const textOffsetY = textStyle.getOffsetY(); const textRotateWithView = textStyle.getRotateWithView(); const textRotation = textStyle.getRotation(); - const textScale = textStyle.getScale(); + const textScale = textStyle.getScaleArray(); const textText = textStyle.getText(); const textTextAlign = textStyle.getTextAlign(); const textTextBaseline = textStyle.getTextBaseline(); @@ -1099,8 +1134,10 @@ class CanvasImmediateRenderer extends VectorContext { this.textRotateWithView_ = textRotateWithView !== undefined ? textRotateWithView : false; this.textRotation_ = textRotation !== undefined ? textRotation : 0; - this.textScale_ = - this.pixelRatio_ * (textScale !== undefined ? textScale : 1); + this.textScale_ = [ + this.pixelRatio_ * textScale[0], + this.pixelRatio_ * textScale[1], + ]; } } } diff --git a/src/ol/render/canvas/TextBuilder.js b/src/ol/render/canvas/TextBuilder.js index af8528ac37..771cd2caac 100644 --- a/src/ol/render/canvas/TextBuilder.js +++ b/src/ol/render/canvas/TextBuilder.js @@ -303,6 +303,27 @@ class CanvasTextBuilder extends CanvasBuilder { this.beginGeometry(geometry, feature); + // adjust padding for negative scale + let padding = textState.padding; + if ( + padding != defaultPadding && + (textState.scale[0] < 0 || textState.scale[1] < 0) + ) { + let p0 = textState.padding[0]; + let p1 = textState.padding[1]; + let p2 = textState.padding[2]; + let p3 = textState.padding[3]; + if (textState.scale[0] < 0) { + p1 = -p1; + p3 = -p3; + } + if (textState.scale[1] < 0) { + p0 = -p0; + p2 = -p2; + } + padding = [p0, p1, p2, p3]; + } + // The image is unknown at this stage so we pass null; it will be computed at render time. // For clarity, we pass NaN for offsetX, offsetY, width and height, which will be computed at // render time. @@ -321,11 +342,11 @@ class CanvasTextBuilder extends CanvasBuilder { 0, this.textRotateWithView_, this.textRotation_, - 1, + [1, 1], NaN, - textState.padding == defaultPadding + padding == defaultPadding ? defaultPadding - : textState.padding.map(function (p) { + : padding.map(function (p) { return p * pixelRatio; }), !!textState.backgroundFill, @@ -338,6 +359,7 @@ class CanvasTextBuilder extends CanvasBuilder { this.textOffsetY_, geometryWidths, ]); + const scale = 1 / pixelRatio; this.hitDetectionInstructions.push([ CanvasInstruction.DRAW_IMAGE, begin, @@ -352,9 +374,9 @@ class CanvasTextBuilder extends CanvasBuilder { 0, this.textRotateWithView_, this.textRotation_, - 1 / this.pixelRatio, + [scale, scale], NaN, - textState.padding, + padding, !!textState.backgroundFill, !!textState.backgroundStroke, this.text_, @@ -431,9 +453,8 @@ class CanvasTextBuilder extends CanvasBuilder { const offsetY = this.textOffsetY_ * pixelRatio; const text = this.text_; - const textScale = textState.scale; const strokeWidth = strokeState - ? (strokeState.lineWidth * textScale) / 2 + ? (strokeState.lineWidth * Math.abs(textState.scale[0])) / 2 : 0; this.instructions.push([ @@ -529,7 +550,7 @@ class CanvasTextBuilder extends CanvasBuilder { textState = this.textState_; const font = textStyle.getFont() || defaultFont; registerFont(font); - const textScale = textStyle.getScale(); + const textScale = textStyle.getScaleArray(); textState.overflow = textStyle.getOverflow(); textState.font = font; textState.maxAngle = textStyle.getMaxAngle(); @@ -540,7 +561,7 @@ class CanvasTextBuilder extends CanvasBuilder { textState.backgroundFill = textStyle.getBackgroundFill(); textState.backgroundStroke = textStyle.getBackgroundStroke(); textState.padding = textStyle.getPadding() || defaultPadding; - textState.scale = textScale === undefined ? 1 : textScale; + textState.scale = textScale === undefined ? [1, 1] : textScale; const textOffsetX = textStyle.getOffsetX(); const textOffsetY = textStyle.getOffsetY(); diff --git a/src/ol/style/Icon.js b/src/ol/style/Icon.js index 35d961a668..a299a3e96b 100644 --- a/src/ol/style/Icon.js +++ b/src/ol/style/Icon.js @@ -36,7 +36,7 @@ import {getUid} from '../util.js'; * @property {import("./IconOrigin.js").default} [offsetOrigin='top-left'] Origin of the offset: `bottom-left`, `bottom-right`, * `top-left` or `top-right`. * @property {number} [opacity=1] Opacity of the icon. - * @property {number} [scale=1] Scale. + * @property {number|import("../size.js").Size} [scale=1] Scale. * @property {boolean} [rotateWithView=false] Whether to rotate the icon with the view. * @property {number} [rotation=0] Rotation in radians (positive rotation clockwise). * @property {import("../size.js").Size} [size] Icon size in pixel. Can be used together with `offset` to define the @@ -69,7 +69,7 @@ class Icon extends ImageStyle { const rotation = options.rotation !== undefined ? options.rotation : 0; /** - * @type {number} + * @type {number|import("../size.js").Size} */ const scale = options.scale !== undefined ? options.scale : 1; @@ -215,6 +215,7 @@ class Icon extends ImageStyle { * @api */ clone() { + const scale = this.getScale(); return new Icon({ anchor: this.anchor_.slice(), anchorOrigin: this.anchorOrigin_, @@ -230,7 +231,7 @@ class Icon extends ImageStyle { offsetOrigin: this.offsetOrigin_, size: this.size_ !== null ? this.size_.slice() : undefined, opacity: this.getOpacity(), - scale: this.getScale(), + scale: Array.isArray(scale) ? scale.slice() : scale, rotation: this.getRotation(), rotateWithView: this.getRotateWithView(), }); diff --git a/src/ol/style/Image.js b/src/ol/style/Image.js index 6c2ba13b63..4d9e83259a 100644 --- a/src/ol/style/Image.js +++ b/src/ol/style/Image.js @@ -2,13 +2,14 @@ * @module ol/style/Image */ import {abstract} from '../util.js'; +import {toSize} from '../size.js'; /** * @typedef {Object} Options * @property {number} opacity * @property {boolean} rotateWithView * @property {number} rotation - * @property {number} scale + * @property {number|import("../size.js").Size} scale * @property {Array} displacement */ @@ -45,10 +46,16 @@ class ImageStyle { /** * @private - * @type {number} + * @type {number|import("../size.js").Size} */ this.scale_ = options.scale; + /** + * @private + * @type {import("../size.js").Size} + */ + this.scaleArray_ = toSize(options.scale); + /** * @private * @type {Array} @@ -62,9 +69,10 @@ class ImageStyle { * @api */ clone() { + const scale = this.getScale(); return new ImageStyle({ opacity: this.getOpacity(), - scale: this.getScale(), + scale: Array.isArray(scale) ? scale.slice() : scale, rotation: this.getRotation(), rotateWithView: this.getRotateWithView(), displacement: this.getDisplacement().slice(), @@ -100,13 +108,21 @@ class ImageStyle { /** * Get the symbolizer scale. - * @return {number} Scale. + * @return {number|import("../size.js").Size} Scale. * @api */ getScale() { return this.scale_; } + /** + * Get the symbolizer scale array. + * @return {import("../size.js").Size} Scale array. + */ + getScaleArray() { + return this.scaleArray_; + } + /** * Get the displacement of the shape * @return {Array} Shape's center displacement @@ -219,11 +235,12 @@ class ImageStyle { /** * Set the scale. * - * @param {number} scale Scale. + * @param {number|import("../size.js").Size} scale Scale. * @api */ setScale(scale) { this.scale_ = scale; + this.scaleArray_ = toSize(scale); } /** diff --git a/src/ol/style/Text.js b/src/ol/style/Text.js index f7884861b9..a245e6f2d8 100644 --- a/src/ol/style/Text.js +++ b/src/ol/style/Text.js @@ -3,6 +3,7 @@ */ import Fill from './Fill.js'; import TextPlacement from './TextPlacement.js'; +import {toSize} from '../size.js'; /** * The default fill color to use if no fill was set at construction time; a @@ -23,7 +24,7 @@ const DEFAULT_FILL_COLOR = '#333'; * @property {boolean} [overflow=false] For polygon labels or when `placement` is set to `'line'`, allow text to exceed * the width of the polygon at the label position or the length of the path that it follows. * @property {import("./TextPlacement.js").default|string} [placement='point'] Text placement. - * @property {number} [scale] Scale. + * @property {number|import("../size.js").Size} [scale] Scale. * @property {boolean} [rotateWithView=false] Whether to rotate the text with the view. * @property {number} [rotation=0] Rotation in radians (positive rotation clockwise). * @property {string} [text] Text content. @@ -74,10 +75,16 @@ class Text { /** * @private - * @type {number|undefined} + * @type {number|import("../size.js").Size|undefined} */ this.scale_ = options.scale; + /** + * @private + * @type {import("../size.js").Size} + */ + this.scaleArray_ = toSize(options.scale !== undefined ? options.scale : 1); + /** * @private * @type {string|undefined} @@ -172,6 +179,7 @@ class Text { * @api */ clone() { + const scale = this.getScale(); return new Text({ font: this.getFont(), placement: this.getPlacement(), @@ -179,7 +187,7 @@ class Text { overflow: this.getOverflow(), rotation: this.getRotation(), rotateWithView: this.getRotateWithView(), - scale: this.getScale(), + scale: Array.isArray(scale) ? scale.slice() : scale, text: this.getText(), textAlign: this.getTextAlign(), textBaseline: this.getTextBaseline(), @@ -280,13 +288,21 @@ class Text { /** * Get the text scale. - * @return {number|undefined} Scale. + * @return {number|import("../size.js").Size|undefined} Scale. * @api */ getScale() { return this.scale_; } + /** + * Get the symbolizer scale array. + * @return {import("../size.js").Size} Scale array. + */ + getScaleArray() { + return this.scaleArray_; + } + /** * Get the stroke style for the text. * @return {import("./Stroke.js").default} Stroke style. @@ -443,11 +459,12 @@ class Text { /** * Set the scale. * - * @param {number|undefined} scale Scale. + * @param {number|import("../size.js").Size|undefined} scale Scale. * @api */ setScale(scale) { this.scale_ = scale; + this.scaleArray_ = toSize(scale !== undefined ? scale : 1); } /**