From a48df69ac6a4e7c49234de6ad884754df3de2e82 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 13 Apr 2020 17:17:33 -0400 Subject: [PATCH] fix "line-dasharray" with "line-cap": "square" fix #9531 --- src/render/line_atlas.js | 16 +++++++++------- src/render/program/line_program.js | 6 +++--- test/ignores.json | 1 - .../line-dasharray/case/square/expected.png | Bin 9458 -> 3716 bytes 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/render/line_atlas.js b/src/render/line_atlas.js index c755ea8990e..f265efb53dc 100644 --- a/src/render/line_atlas.js +++ b/src/render/line_atlas.js @@ -41,11 +41,11 @@ class LineAtlas { * @returns {Object} position of dash texture in { y, height, width } * @private */ - getDash(dasharray: Array, round: boolean) { - const key = dasharray.join(",") + String(round); + getDash(dasharray: Array, lineCap: string) { + const key = dasharray.join(",") + lineCap; if (!this.dashEntry[key]) { - this.dashEntry[key] = this.addDash(dasharray, round); + this.dashEntry[key] = this.addDash(dasharray, lineCap); } return this.dashEntry[key]; } @@ -108,7 +108,7 @@ class LineAtlas { } } - addRegularDash(ranges: Object) { + addRegularDash(ranges: Object, capLength: number) { // Collapse any zero-length range // Collapse neighbouring same-type parts into a single part @@ -144,13 +144,14 @@ class LineAtlas { const distRight = Math.abs(x - range.right); const minDist = Math.min(distLeft, distRight); - const signedDistance = range.isDash ? minDist : -minDist; + const signedDistance = (range.isDash ? minDist : -minDist) + capLength; this.data[index + x] = Math.max(0, Math.min(255, signedDistance + 128)); } } - addDash(dasharray: Array, round: boolean) { + addDash(dasharray: Array, lineCap: string) { + const round = lineCap === 'round'; const n = round ? 7 : 0; const height = 2 * n + 1; @@ -169,7 +170,8 @@ class LineAtlas { if (round) { this.addRoundDash(ranges, stretch, n); } else { - this.addRegularDash(ranges); + const capLength = lineCap === 'square' ? 0.5 * stretch : 0; + this.addRegularDash(ranges, capLength); } } diff --git a/src/render/program/line_program.js b/src/render/program/line_program.js index 4ab16c3e5c8..694b9a205eb 100644 --- a/src/render/program/line_program.js +++ b/src/render/program/line_program.js @@ -163,10 +163,10 @@ const lineSDFUniformValues = ( const lineAtlas = painter.lineAtlas; const tileRatio = calculateTileRatio(tile, transform); - const round = layer.layout.get('line-cap') === 'round'; + const lineCap = layer.layout.get('line-cap'); - const posA = lineAtlas.getDash(dasharray.from, round); - const posB = lineAtlas.getDash(dasharray.to, round); + const posA = lineAtlas.getDash(dasharray.from, lineCap); + const posB = lineAtlas.getDash(dasharray.to, lineCap); const widthA = posA.width * crossfade.fromScale; const widthB = posB.width * crossfade.toScale; diff --git a/test/ignores.json b/test/ignores.json index 60f94aea2f9..115a3de6e1f 100644 --- a/test/ignores.json +++ b/test/ignores.json @@ -1,7 +1,6 @@ { "query-tests/regressions/mapbox-gl-js#4494": "https://github.com/mapbox/mapbox-gl-js/issues/2716", "render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary", - "render-tests/line-dasharray/case/square": "https://github.com/mapbox/mapbox-gl-js/issues/9531", "render-tests/map-mode/static": "https://github.com/mapbox/mapbox-gl-js/issues/5649", "render-tests/map-mode/tile": "skip - mapbox-gl-js does not support tile-mode", "render-tests/map-mode/tile-avoid-edges": "skip - mapbox-gl-js does not support tile-mode", diff --git a/test/integration/render-tests/line-dasharray/case/square/expected.png b/test/integration/render-tests/line-dasharray/case/square/expected.png index 950a308bc81edef8c4a2812c8703f3782cd372d7..dfe993d8cc313675520417220786ee4b33b6cbb8 100644 GIT binary patch literal 3716 zcmd5xhQi-KvW#twrYFWAA3MT6Np$W{1KVZ&bIdJdibMNqPx)x>2$S67>4j(*$|7onzyP4kUxs%&&WR-$Z%eh?s`}%;4 zfGbzSl`*w=LN3gubTs>d#=j_6cWyaNP=1X}XLbE#Bll-SiwXNioUfa%{*IoDH`2=j zc)|D?JyUn?rxS5%p5(i(zJ>hO-M4uak+P7I?#QW@<<o0CsBZC&viSq~gKo^b zwATA)9^lIg6A}tFGZcCYee^*bg;nYTy$x{?F(eg$TogmB&=3gPR_F~Asl-sMb&@YM zPIrEG>S4>7f2X(YHt(<;{OpQ=<5eXkM^BU@SZ`jKS)8YAJ~@NbebnT8^4BZR4C4+S z10YWN0K^_%c}ZlY%gyG~XtC6D>y>Wd- zLxu6VwW(y~Je+;be)n*8%tjRzA>C42W9-uY`bo(9NO~=mteh*9cdDv|eY`%hM$}v1 zcFze(hGxnMuWb@U8c=LspeiEjART{8adQ^jBSbYg z)QveQf=!D&LRZYmE$;#m3WfZ;OM$C^eKFr=^|iTz_=3Y}x}{%K9dhZ)I*uQr3oS~H zNgvuwW}Mo&pQc6saYQ=OX zhzXZU2DwSj@RBOYxIxZvmo5P?C#6cz07l$*B%MYB7}iE3?riaN0I4ZJvIOj)+QKRh5vX8Y+9ByM-6lOpWSh z5}APpqR4R-?HGge@pPQ;x znbPu}3+;O-jLa)X2edt%8V3qDdqmjLC!#yg4YQI< zvlJE0NZGXc9kAudrepYRS{$pl!ppWEA$Ub`PErktt;ylT&D}^@S%IKEyf=tZy$3Xr zzIyG^eZ`SY#JX>cZJt#Tbj=mM;A%%a7|OAFB}y6Eq=N0=bV8Kv7}Z6hlumpJZv5|r!$b(JbHzCkwqQ|d|6>=;N< zg9YaD+VquY+9`RtNGD4nI}0J9)OxM~4Bgtu!&}ofGV{tyiFg-X2gsD|7OCzRP@F(uGzx zTiA%M`i!P^xw!C*spQUcpWIR%3u7#@`z8nC-iO9! ztvV9T6t*zNP;)@0iP|)t z-{W#%35vou911|06MK*qeTJithkp4YDiBS#X>M6DUVzBvUW{dBhkbh#!qCzdr*e(^ zy8}^U`f4PK_JRJKQhFxLAoJ97kZ^4j&go5CO)2}q-V4{6v>^}}|9MoGj@qbwqGVV! z_XcKt+enpjG&awBxsV$C_{rmNAUq*IYY_@0^Q*2uu#N}D@pG*Q25dNF`?(W8q*D8V zC#c1nA#g3iUy{hRO^5S~!`zV{K*E^@qK+nuLL#yK#q8`>mYT|(Dqpa)MN)_C0%iWK zb*z;+oKJ!>rIr$$zYJymco@JhcxBGecJWp$-W-ns4-h_5`;10S(NNkBTVVgf?3EmF z@Gf2RtL11DNM{fxD5yZ3&Kflu&yCC2CEb<5K7oOQWumq5m>kwMEIz0LV^Y-H)zia& z2y7?*DJyx*$e^f%_Znm*jF^;{n@A$uOJu(rarFOQ5F7)<+|%u!k;*1->T!_YZ$glFMH*y2G8rS-m|}0z6&HAZ(C_i{Pg& F{~z^#42}Q* literal 9458 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 D&Q-)q