From c343ced77b3e8f6696fa51bf2df387ffd9b43a45 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 11 Aug 2015 16:01:32 +0300 Subject: [PATCH] get rid of text-max-size, icon-max-size and make text-size, icon-size layout properties fixes https://github.com/mapbox/mapbox-gl-style-spec/issues/255 --- js/data/create_bucket.js | 15 +++++++++++++++ js/data/symbol_bucket.js | 10 +++++++--- js/render/draw_symbol.js | 6 +++--- js/style/style_layer.js | 14 ++++++++++++-- package.json | 4 ++-- test/fixtures/style-basic.json | 13 +++++-------- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/js/data/create_bucket.js b/js/data/create_bucket.js index c0b81a137a0..3eec255308c 100644 --- a/js/data/create_bucket.js +++ b/js/data/create_bucket.js @@ -19,6 +19,21 @@ function createBucket(layer, buffers, z, overscaling, collisionDebug) { layout[k] = values[k].calculate(z, fakeZoomHistory); } + if (layer.type === 'symbol') { + // To reduce the number of labels that jump around when zooming we need + // to use a text-size value that is the same for all zoom levels. + // This calculates text-size at a high zoom level so that all tiles can + // use the same value when calculating anchor positions. + if (values['text-size']) { + layout['text-max-size'] = values['text-size'].calculate(18, fakeZoomHistory); + layout['text-size'] = values['text-size'].calculate(z + 1, fakeZoomHistory); + } + if (values['icon-size']) { + layout['icon-max-size'] = values['icon-size'].calculate(18, fakeZoomHistory); + layout['icon-size'] = values['icon-size'].calculate(z + 1, fakeZoomHistory); + } + } + var BucketClass = layer.type === 'line' ? LineBucket : layer.type === 'fill' ? FillBucket : diff --git a/js/data/symbol_bucket.js b/js/data/symbol_bucket.js index 0fc6c0b3890..e46a75e0988 100644 --- a/js/data/symbol_bucket.js +++ b/js/data/symbol_bucket.js @@ -138,9 +138,10 @@ SymbolBucket.prototype.addFeature = function(lines, shapedText, shapedIcon) { var glyphSize = 24; - var fontScale = layout['text-max-size'] / glyphSize, + var fontScale = layout['text-size'] / glyphSize, textBoxScale = this.tilePixelRatio * fontScale, - iconBoxScale = this.tilePixelRatio * layout['icon-max-size'], + textMaxBoxScale = this.tilePixelRatio * layout['text-max-size'] / glyphSize, + iconBoxScale = this.tilePixelRatio * layout['icon-size'], symbolMinDistance = this.tilePixelRatio * layout['symbol-spacing'], avoidEdges = layout['symbol-avoid-edges'], textPadding = layout['text-padding'] * this.tilePixelRatio, @@ -160,7 +161,7 @@ SymbolBucket.prototype.addFeature = function(lines, shapedText, shapedIcon) { // Calculate the anchor points around which you want to place labels var anchors = layout['symbol-placement'] === 'line' ? - getAnchors(line, symbolMinDistance, textMaxAngle, shapedText, glyphSize, textBoxScale, this.overscaling) : + getAnchors(line, symbolMinDistance, textMaxAngle, shapedText, glyphSize, textMaxBoxScale, this.overscaling) : [ new Anchor(line[0].x, line[0].y, 0) ]; // For each potential label, create the placement features used to check for collisions, and the quads use for rendering. @@ -205,6 +206,9 @@ SymbolBucket.prototype.placeFeatures = function(collisionTile, buffers, collisio var layout = this.layoutProperties; var maxScale = collisionTile.maxScale; + elementGroups.text['text-size'] = layout['text-size']; + elementGroups.icon['icon-size'] = layout['icon-size']; + var textAlongLine = layout['text-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line'; var iconAlongLine = layout['icon-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line'; diff --git a/js/render/draw_symbol.js b/js/render/draw_symbol.js index b0e6b6126f9..52a4df48540 100644 --- a/js/render/draw_symbol.js +++ b/js/render/draw_symbol.js @@ -67,7 +67,6 @@ function drawSymbol(painter, layer, posMatrix, tile, elementGroups, prefix, sdf) } mat4.scale(exMatrix, exMatrix, [s, s, 1]); - // If layer.paint.size > layer.layout[prefix + '-max-size'] then labels may collide var fontSize = layer.paint[prefix + '-size']; var fontScale = fontSize / defaultSizes[prefix]; mat4.scale(exMatrix, exMatrix, [ fontScale, fontScale, 1 ]); @@ -111,8 +110,9 @@ function drawSymbol(painter, layer, posMatrix, tile, elementGroups, prefix, sdf) gl.uniform1i(shader.u_skewed, skewed); gl.uniform1f(shader.u_extra, extra); - // adjust min/max zooms for variable font sies - var zoomAdjust = Math.log(fontSize / layer.layout[prefix + '-max-size']) / Math.LN2 || 0; + // adjust min/max zooms for variable font sizes + var zoomAdjust = Math.log(fontSize / elementGroups[prefix + '-size']) / Math.LN2 || 0; + gl.uniform1f(shader.u_zoom, (painter.transform.zoom - zoomAdjust) * 10); // current zoom level diff --git a/js/style/style_layer.js b/js/style/style_layer.js index d52bd8a2230..15a3436915f 100644 --- a/js/style/style_layer.js +++ b/js/style/style_layer.js @@ -35,6 +35,8 @@ StyleLayer.prototype = { } this.layout['symbol-avoid-edges'] = true; } + + this._resolvedLayout = new StyleDeclarationSet('layout', this.type, this.layout, this._constants || {}); } }, @@ -107,7 +109,15 @@ StyleLayer.prototype = { } } } - }, + + // the -size properties are used both as layout and paint. + // In the spec they are layout properties. This adds them + // as internal paint properties. + if (this.type === 'symbol') { + this._cascaded['text-size'] = new StyleTransition(this._resolvedLayout.values()['text-size'], undefined, globalTrans); + this._cascaded['icon-size'] = new StyleTransition(this._resolvedLayout.values()['icon-size'], undefined, globalTrans); + } +}, recalculate: function(z, zoomHistory) { var type = this.type, @@ -156,7 +166,7 @@ StyleLayer.prototype = { util.extend(this, util.pick(layer, ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', - 'layout'])); + 'layout', '_resolvedLayout'])); }, json: function() { diff --git a/package.json b/package.json index c53e65d3719..a2de9feb5ed 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "gl-matrix": "https://github.com/toji/gl-matrix/archive/v2.2.1.tar.gz", "glify": "0.5.0", "mapbox-gl-function": "^1.0.0", - "mapbox-gl-style-spec": "git+https://github.com/mapbox/mapbox-gl-style-spec.git#30c3f6fcd6d125563ae170cef14f645531e6fe84", + "mapbox-gl-style-spec": "git+https://github.com/mapbox/mapbox-gl-style-spec.git#104677886a9c1fb03d0d6abc69d78496db8b3a42", "minifyify": "^6.1.0", "pbf": "^1.2.0", "pngjs": "^0.4.0", @@ -39,7 +39,7 @@ "documentation": "git+https://github.com/documentationjs/documentation#d341019b32a8a257a93bd55586e7f09f42e29341", "eslint": "^0.14.1", "istanbul": "^0.3.0", - "mapbox-gl-test-suite": "git+https://github.com/mapbox/mapbox-gl-test-suite.git#3fbb91f077faa19a4fd352a9d1b48f85604deabc", + "mapbox-gl-test-suite": "git+https://github.com/mapbox/mapbox-gl-test-suite.git#af7481f223acec41421bcf9ec944651216c1358c", "marked": "0.3.x", "mkdirp": "^0.5.0", "prova": "^2.1.2", diff --git a/test/fixtures/style-basic.json b/test/fixtures/style-basic.json index 7e84df8fa11..fa3b22021bb 100644 --- a/test/fixtures/style-basic.json +++ b/test/fixtures/style-basic.json @@ -66,7 +66,6 @@ "source": "mapbox.mapbox-streets-v5", "source-layer": "poi_label", "layout": { - "icon-max-size": 12, "icon-rotation-alignment": "viewport" } }, { @@ -78,7 +77,6 @@ "layout": { "text-field": "{name}", "text-font": ["Open Sans Regular", "Arial Unicode MS Regular"], - "text-max-size": 16, "text-padding": 10 }, "paint": { @@ -95,17 +93,16 @@ "layout": { "text-field": "{name}", "text-font": ["Open Sans Regular", "Arial Unicode MS Regular"], - "text-max-size": 12, "text-max-angle": 59.59, - "symbol-spacing": 250 + "symbol-spacing": 250, + "text-size": { + "stops": [[4.770835839035499, 8.01], [15.477225251693334, 12]] + } }, "paint": { "text-color": "#000000", "text-halo-color": "rgba(255,255,255,0.7)", - "text-halo-width": 0.25, - "text-size": { - "stops": [[4.770835839035499, 8.01], [15.477225251693334, 12]] - } + "text-halo-width": 0.25 } }] }