Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text-pitch-alignment #2668

Merged
merged 4 commits into from
Jun 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions js/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ var programAttributes = [{
type: 'Uint8'
}];

function addVertex(array, x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom) {
function addVertex(array, x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom, labelangle) {
return array.emplaceBack(
// pos
x,
Expand All @@ -81,7 +81,7 @@ function addVertex(array, x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom)
tx / 4, // tex
ty / 4, // tex
(labelminzoom || 0) * 10, // labelminzoom
0,
labelangle, // labelangle
// data2
(minzoom || 0) * 10, // minzoom
Math.min(maxzoom || 25, 25) * 10); // minzoom
Expand Down Expand Up @@ -462,11 +462,10 @@ SymbolBucket.prototype.addSymbols = function(programName, quadsStart, quadsEnd,

for (var k = quadsStart; k < quadsEnd; k++) {

var symbol = this.symbolQuadsArray.get(k).SymbolQuad,
angle = symbol.angle;
var symbol = this.symbolQuadsArray.get(k).SymbolQuad;

// drop upside down versions of glyphs
var a = (angle + placementAngle + Math.PI) % (Math.PI * 2);
var a = (symbol.anchorAngle + placementAngle + Math.PI) % (Math.PI * 2);
if (keepUpright && alongLine && (a <= Math.PI / 2 || a > Math.PI * 3 / 2)) continue;

var tl = symbol.tl,
Expand All @@ -484,10 +483,13 @@ SymbolBucket.prototype.addSymbols = function(programName, quadsStart, quadsEnd,
// Lower min zoom so that while fading out the label it can be shown outside of collision-free zoom levels
if (minZoom === placementZoom) minZoom = 0;

var index = addVertex(vertexArray, anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom, maxZoom, placementZoom);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y, minZoom, maxZoom, placementZoom);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h, minZoom, maxZoom, placementZoom);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, minZoom, maxZoom, placementZoom);
// Encode angle of glyph
var glyphAngle = Math.round((symbol.glyphAngle / (Math.PI * 2)) * 256);

var index = addVertex(vertexArray, anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom, maxZoom, placementZoom, glyphAngle);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y, minZoom, maxZoom, placementZoom, glyphAngle);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h, minZoom, maxZoom, placementZoom, glyphAngle);
addVertex(vertexArray, anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, minZoom, maxZoom, placementZoom, glyphAngle);

elementArray.emplaceBack(index, index + 1, index + 2);
elementArray.emplaceBack(index + 1, index + 2, index + 3);
Expand Down Expand Up @@ -624,7 +626,8 @@ SymbolBucket.prototype.addSymbolQuad = function(symbolQuad) {
symbolQuad.tex.x,
symbolQuad.tex.y,
//angle
symbolQuad.angle,
symbolQuad.anchorAngle,
symbolQuad.glyphAngle,
// scales
symbolQuad.maxScale,
symbolQuad.minScale);
Expand Down
21 changes: 17 additions & 4 deletions js/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ function drawSymbols(painter, source, layer, coords) {
layer.paint['icon-translate'],
layer.paint['icon-translate-anchor'],
layer.layout['icon-rotation-alignment'],
// icon-pitch-alignment is not yet implemented
// and we simply inherit the rotation alignment
layer.layout['icon-rotation-alignment'],
layer.layout['icon-size'],
layer.paint['icon-halo-width'],
layer.paint['icon-halo-color'],
Expand All @@ -45,6 +48,7 @@ function drawSymbols(painter, source, layer, coords) {
layer.paint['text-translate'],
layer.paint['text-translate-anchor'],
layer.layout['text-rotation-alignment'],
layer.layout['text-pitch-alignment'],
layer.layout['text-size'],
layer.paint['text-halo-width'],
layer.paint['text-halo-color'],
Expand All @@ -61,6 +65,7 @@ function drawLayerSymbols(painter, source, layer, coords, isText,
translate,
translateAnchor,
rotationAlignment,
pitchAlignment,
size,
haloWidth,
haloColor,
Expand All @@ -83,6 +88,7 @@ function drawLayerSymbols(painter, source, layer, coords, isText,
translate,
translateAnchor,
rotationAlignment,
pitchAlignment,
size,
haloWidth,
haloColor,
Expand All @@ -96,21 +102,24 @@ function drawSymbol(painter, layer, posMatrix, tile, bucket, bufferGroups, isTex
translate,
translateAnchor,
rotationAlignment,
pitchAlignment,
size,
haloWidth,
haloColor,
haloBlur,
opacity,
color) {

var gl = painter.gl;
var tr = painter.transform;
var alignedWithMap = rotationAlignment === 'map';
var rotateWithMap = rotationAlignment === 'map';
var pitchWithMap = pitchAlignment === 'map';

var defaultSize = isText ? 24 : 1;
var fontScale = size / defaultSize;

var extrudeScale, s, gammaScale;
if (alignedWithMap) {
if (pitchWithMap) {
s = pixelsToTileUnits(tile, 1, painter.transform.zoom) * fontScale;
gammaScale = 1 / Math.cos(tr._pitch);
extrudeScale = [s, s];
Expand All @@ -125,7 +134,8 @@ function drawSymbol(painter, layer, posMatrix, tile, bucket, bufferGroups, isTex

var program = painter.useProgram(sdf ? 'sdf' : 'icon');
gl.uniformMatrix4fv(program.u_matrix, false, painter.translatePosMatrix(posMatrix, tile, translate, translateAnchor));
gl.uniform1i(program.u_skewed, alignedWithMap);
gl.uniform1i(program.u_rotate_with_map, rotateWithMap);
gl.uniform1i(program.u_pitch_with_map, pitchWithMap);
gl.uniform2fv(program.u_extrude_scale, extrudeScale);

gl.activeTexture(gl.TEXTURE0);
Expand All @@ -142,7 +152,7 @@ function drawSymbol(painter, layer, posMatrix, tile, bucket, bufferGroups, isTex
} else {
var mapMoving = painter.options.rotating || painter.options.zooming;
var iconScaled = fontScale !== 1 || browser.devicePixelRatio !== painter.spriteAtlas.pixelRatio || iconsNeedLinear;
var iconTransformed = alignedWithMap || painter.transform.pitch;
var iconTransformed = pitchWithMap || painter.transform.pitch;
painter.spriteAtlas.bind(gl, sdf || mapMoving || iconScaled || iconTransformed);
gl.uniform2f(program.u_texsize, painter.spriteAtlas.width / 4, painter.spriteAtlas.height / 4);
}
Expand Down Expand Up @@ -181,6 +191,9 @@ function drawSymbol(painter, layer, posMatrix, tile, bucket, bufferGroups, isTex
gl.uniform4fv(program.u_color, color);
gl.uniform1f(program.u_opacity, opacity);
gl.uniform1f(program.u_buffer, (256 - 64) / 256);
gl.uniform1f(program.u_pitch, tr.pitch / 360 * 2 * Math.PI);
gl.uniform1f(program.u_bearing, tr.bearing / 360 * 2 * Math.PI);
gl.uniform1f(program.u_aspect_ratio, tr.width / tr.height);

for (var i = 0; i < bufferGroups.length; i++) {
group = bufferGroups[i];
Expand Down
3 changes: 3 additions & 0 deletions js/style/style_layer/symbol_style_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ SymbolStyleLayer.prototype = util.inherit(StyleLayer, {
this.getLayoutValue('symbol-placement', globalProperties, featureProperties) === 'line' &&
!this.getLayoutProperty('icon-rotation-alignment')) {
return 'map';
// If unspecified `text-pitch-alignment` inherits `text-rotation-alignment`
} else if (name === 'text-pitch-alignment' && !this.getLayoutProperty('text-pitch-alignment')) {
return this.getLayoutValue('text-rotation-alignment');
} else {
return StyleLayer.prototype.getLayoutValue.apply(this, arguments);
}
Expand Down
26 changes: 13 additions & 13 deletions js/symbol/quads.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,23 @@ var minScale = 0.5; // underscale by 1 zoom level
* @param {Point} bl The offset of the bottom left corner from the anchor.
* @param {Point} br The offset of the bottom right corner from the anchor.
* @param {Object} tex The texture coordinates.
* @param {number} angle The angle of the label at it's center, not the angle of this quad.
* @param {number} anchorAngle The angle of the label at it's center, not the angle of this quad.
* @param {number} glyphAngle The angle of the glyph to be positioned in the quad.
* @param {number} minScale The minimum scale, relative to the tile's intended scale, that the glyph can be shown at.
* @param {number} maxScale The maximum scale, relative to the tile's intended scale, that the glyph can be shown at.
*
* @class SymbolQuad
* @private
*/
function SymbolQuad(anchorPoint, tl, tr, bl, br, tex, angle, minScale, maxScale) {
function SymbolQuad(anchorPoint, tl, tr, bl, br, tex, anchorAngle, glyphAngle, minScale, maxScale) {
this.anchorPoint = anchorPoint;
this.tl = tl;
this.tr = tr;
this.bl = bl;
this.br = br;
this.tex = tex;
this.angle = angle;
this.anchorAngle = anchorAngle;
this.glyphAngle = glyphAngle;
this.minScale = minScale;
this.maxScale = maxScale;
}
Expand Down Expand Up @@ -88,7 +90,7 @@ function getIconQuads(anchor, shapedIcon, boxScale, line, layout, alongLine) {
br = br.matMult(matrix);
}

return [new SymbolQuad(new Point(anchor.x, anchor.y), tl, tr, bl, br, shapedIcon.image.rect, 0, minScale, Infinity)];
return [new SymbolQuad(new Point(anchor.x, anchor.y), tl, tr, bl, br, shapedIcon.image.rect, 0, 0, minScale, Infinity)];
}

/**
Expand Down Expand Up @@ -155,12 +157,11 @@ function getGlyphQuads(anchor, shaping, boxScale, line, layout, alongLine) {
tl = otl,
tr = otr,
bl = obl,
br = obr,
angle = instance.angle + textRotate;
br = obr;

if (angle) {
var sin = Math.sin(angle),
cos = Math.cos(angle),
if (textRotate) {
var sin = Math.sin(textRotate),
cos = Math.cos(textRotate),
matrix = [cos, -sin, sin, cos];

tl = tl.matMult(matrix);
Expand All @@ -172,9 +173,9 @@ function getGlyphQuads(anchor, shaping, boxScale, line, layout, alongLine) {
// Prevent label from extending past the end of the line
var glyphMinScale = Math.max(instance.minScale, labelMinScale);

var glyphAngle = (anchor.angle + textRotate + instance.offset + 2 * Math.PI) % (2 * Math.PI);
quads.push(new SymbolQuad(instance.anchorPoint, tl, tr, bl, br, rect, glyphAngle, glyphMinScale, instance.maxScale));

var anchorAngle = (anchor.angle + textRotate + instance.offset + 2 * Math.PI) % (2 * Math.PI);
var glyphAngle = (instance.angle + textRotate + instance.offset + 2 * Math.PI) % (2 * Math.PI);
quads.push(new SymbolQuad(instance.anchorPoint, tl, tr, bl, br, rect, anchorAngle, glyphAngle, glyphMinScale, instance.maxScale));
}
}

Expand Down Expand Up @@ -219,7 +220,6 @@ function getSegmentGlyphs(glyphs, anchor, offset, line, segment, forward) {
// Get the angle of the line segment
var angle = Math.atan2(end.y - newAnchorPoint.y, end.x - newAnchorPoint.x);
if (!forward) angle += Math.PI;
if (upsideDown) angle += Math.PI;

glyphs.push({
anchorPoint: newAnchorPoint,
Expand Down
9 changes: 6 additions & 3 deletions js/symbol/symbol_quads.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ var SymbolQuadsArray = module.exports = new StructArrayType({
{ type: 'Int16', name: 'texX' },
{ type: 'Int16', name: 'texY' },

//the angle of the label at it's center, not the angle of this quad.
{ type: 'Float32', name: 'angle' },
// the angle of the label at it's center, not the angle of this quad.
{ type: 'Float32', name: 'anchorAngle' },
// the angle of this quad.
{ type: 'Float32', name: 'glyphAngle' },

// quad is only valid for scales < maxScale && scale > minScale.
{ type: 'Float32', name: 'maxScale' },
Expand All @@ -61,7 +63,8 @@ util.extendAll(SymbolQuadsArray.prototype.StructType.prototype, {
new Point(this.blX, this.blY),
new Point(this.brX, this.brY),
{ x: this.texX, y: this.texY, h: this.texH, w: this.texW, height: this.texH, width: this.texW },
this.angle,
this.anchorAngle,
this.glyphAngle,
this.minScale,
this.maxScale);
}
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"grid-index": "^0.1.0",
"mapbox-gl-function": "^1.2.1",
"mapbox-gl-js-supported": "^1.1.0",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#f0b94dcc5f782958e9aade61d592a207d8a46e0f",
"mapbox-gl-style-spec": "^8.7.0",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#30caf388dbddd02cfc4f967ffc94c1338c30fbf8",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#2461efc3d883f2f2e56a6c6b2bfd7d54bbfe9f86",
"minifyify": "^7.0.1",
"pbf": "^1.3.2",
"pngjs": "^2.2.0",
Expand Down Expand Up @@ -57,7 +57,7 @@
"highlight.js": "9.3.0",
"istanbul": "^0.4.2",
"lodash": "^4.13.1",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#6d3bcff5d51f6acea41230ffabad6bebdea49fa3",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#5587d796c99145991ea2a7b749a8782b7a0cb483",
"nyc": "^6.1.1",
"remark": "4.2.2",
"remark-html": "3.0.0",
Expand Down
60 changes: 60 additions & 0 deletions test/js/style/style_layer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,66 @@ test('StyleLayer#serialize', function(t) {
t.end();
});

test('StyleLayer#getLayoutValue (default exceptions)', function(assert) {
assert.test('symbol-placement:point => *-rotation-alignment:viewport', function(assert) {
var layer = StyleLayer.create({
"type": "symbol",
"layout": {
"symbol-placement": "point"
}
});
assert.equal(layer.getLayoutValue('text-rotation-alignment'), 'viewport');
assert.equal(layer.getLayoutValue('icon-rotation-alignment'), 'viewport');
assert.end();
});
assert.test('symbol-placement:line => *-rotation-alignment:map', function(assert) {
var layer = StyleLayer.create({
"type": "symbol",
"layout": {
"symbol-placement": "line"
}
});
assert.equal(layer.getLayoutValue('text-rotation-alignment'), 'map');
assert.equal(layer.getLayoutValue('icon-rotation-alignment'), 'map');
assert.end();
});
assert.test('text-rotation-alignment:map => text-pitch-alignment:map', function(assert) {
var layer = StyleLayer.create({
"type": "symbol",
"layout": {
"text-rotation-alignment": "map"
}
});
assert.equal(layer.getLayoutValue('text-rotation-alignment'), 'map');
assert.equal(layer.getLayoutValue('text-pitch-alignment'), 'map');
assert.end();
});
assert.test('text-rotation-alignment:viewport => text-pitch-alignment:viewport', function(assert) {
var layer = StyleLayer.create({
"type": "symbol",
"layout": {
"text-rotation-alignment": "viewport"
}
});
assert.equal(layer.getLayoutValue('text-rotation-alignment'), 'viewport');
assert.equal(layer.getLayoutValue('text-pitch-alignment'), 'viewport');
assert.end();
});
assert.test('text-pitch-alignment respected when set', function(assert) {
var layer = StyleLayer.create({
"type": "symbol",
"layout": {
"text-rotation-alignment": "viewport",
"text-pitch-alignment": "map"
}
});
assert.equal(layer.getLayoutValue('text-rotation-alignment'), 'viewport');
assert.equal(layer.getLayoutValue('text-pitch-alignment'), 'map');
assert.end();
});
assert.end();
});

function createAnimationLoop() {
return {
set: function() {},
Expand Down
6 changes: 4 additions & 2 deletions test/js/symbol/quads.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ test('getIconQuads', function(t) {
bl: { x: -8, y: 5 },
br: { x: 7, y: 5 },
tex: { w: 15, h: 11 },
angle: 0,
anchorAngle: 0,
glyphAngle: 0,
minScale: 0.5,
maxScale: Infinity } ]);
t.end();
Expand All @@ -45,7 +46,8 @@ test('getIconQuads', function(t) {
bl: { x: -8, y: 5 },
br: { x: 7, y: 5 },
tex: { w: 15, h: 11 },
angle: 0,
anchorAngle: 0,
glyphAngle: 0,
minScale: 0.5,
maxScale: Infinity }]);
t.end();
Expand Down