Skip to content

Commit

Permalink
support icon-text-fit with vertical text (#8835)
Browse files Browse the repository at this point in the history
  • Loading branch information
ansis authored Oct 15, 2019
1 parent 4a4bc6a commit 79c3534
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 116 deletions.
116 changes: 66 additions & 50 deletions src/data/array_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,14 +477,14 @@ register('StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48', StructArrayLayout2i2ui3ul3u

/**
* Implementation of the StructArray layout:
* [0]: Int16[7]
* [14]: Uint16[11]
* [36]: Uint32[1]
* [40]: Float32[3]
* [0]: Int16[8]
* [16]: Uint16[14]
* [44]: Uint32[1]
* [48]: Float32[3]
*
* @private
*/
class StructArrayLayout7i11ui1ul3f52 extends StructArray {
class StructArrayLayout8i14ui1ul3f60 extends StructArray {
uint8: Uint8Array;
int16: Int16Array;
uint16: Uint16Array;
Expand All @@ -499,23 +499,23 @@ class StructArrayLayout7i11ui1ul3f52 extends StructArray {
this.float32 = new Float32Array(this.arrayBuffer);
}

emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number, v18: number, v19: number, v20: number, v21: number) {
emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number, v18: number, v19: number, v20: number, v21: number, v22: number, v23: number, v24: number, v25: number) {
const i = this.length;
this.resize(i + 1);
return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25);
}

emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number, v18: number, v19: number, v20: number, v21: number) {
const o2 = i * 26;
const o4 = i * 13;
emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number, v18: number, v19: number, v20: number, v21: number, v22: number, v23: number, v24: number, v25: number) {
const o2 = i * 30;
const o4 = i * 15;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
this.int16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
this.int16[o2 + 7] = v7;
this.uint16[o2 + 8] = v8;
this.uint16[o2 + 9] = v9;
this.uint16[o2 + 10] = v10;
Expand All @@ -526,16 +526,20 @@ class StructArrayLayout7i11ui1ul3f52 extends StructArray {
this.uint16[o2 + 15] = v15;
this.uint16[o2 + 16] = v16;
this.uint16[o2 + 17] = v17;
this.uint32[o4 + 9] = v18;
this.float32[o4 + 10] = v19;
this.float32[o4 + 11] = v20;
this.float32[o4 + 12] = v21;
this.uint16[o2 + 18] = v18;
this.uint16[o2 + 19] = v19;
this.uint16[o2 + 20] = v20;
this.uint16[o2 + 21] = v21;
this.uint32[o4 + 11] = v22;
this.float32[o4 + 12] = v23;
this.float32[o4 + 13] = v24;
this.float32[o4 + 14] = v25;
return i;
}
}

StructArrayLayout7i11ui1ul3f52.prototype.bytesPerElement = 52;
register('StructArrayLayout7i11ui1ul3f52', StructArrayLayout7i11ui1ul3f52);
StructArrayLayout8i14ui1ul3f60.prototype.bytesPerElement = 60;
register('StructArrayLayout8i14ui1ul3f60', StructArrayLayout8i14ui1ul3f60);

/**
* Implementation of the StructArray layout:
Expand Down Expand Up @@ -943,17 +947,21 @@ class SymbolInstanceStruct extends Struct {
leftJustifiedTextSymbolIndex: number;
verticalPlacedTextSymbolIndex: number;
placedIconSymbolIndex: number;
verticalPlacedIconSymbolIndex: number;
key: number;
textBoxStartIndex: number;
textBoxEndIndex: number;
verticalTextBoxStartIndex: number;
verticalTextBoxEndIndex: number;
iconBoxStartIndex: number;
iconBoxEndIndex: number;
verticalIconBoxStartIndex: number;
verticalIconBoxEndIndex: number;
featureIndex: number;
numHorizontalGlyphVertices: number;
numVerticalGlyphVertices: number;
numIconVertices: number;
numVerticalIconVertices: number;
crossTileID: number;
textBoxScale: number;
textOffset0: number;
Expand All @@ -972,46 +980,54 @@ class SymbolInstanceStruct extends Struct {
set verticalPlacedTextSymbolIndex(x: number) { this._structArray.int16[this._pos2 + 5] = x; }
get placedIconSymbolIndex() { return this._structArray.int16[this._pos2 + 6]; }
set placedIconSymbolIndex(x: number) { this._structArray.int16[this._pos2 + 6] = x; }
get key() { return this._structArray.uint16[this._pos2 + 7]; }
set key(x: number) { this._structArray.uint16[this._pos2 + 7] = x; }
get textBoxStartIndex() { return this._structArray.uint16[this._pos2 + 8]; }
set textBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 8] = x; }
get textBoxEndIndex() { return this._structArray.uint16[this._pos2 + 9]; }
set textBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 9] = x; }
get verticalTextBoxStartIndex() { return this._structArray.uint16[this._pos2 + 10]; }
set verticalTextBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 10] = x; }
get verticalTextBoxEndIndex() { return this._structArray.uint16[this._pos2 + 11]; }
set verticalTextBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 11] = x; }
get iconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 12]; }
set iconBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 12] = x; }
get iconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 13]; }
set iconBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 13] = x; }
get featureIndex() { return this._structArray.uint16[this._pos2 + 14]; }
set featureIndex(x: number) { this._structArray.uint16[this._pos2 + 14] = x; }
get numHorizontalGlyphVertices() { return this._structArray.uint16[this._pos2 + 15]; }
set numHorizontalGlyphVertices(x: number) { this._structArray.uint16[this._pos2 + 15] = x; }
get numVerticalGlyphVertices() { return this._structArray.uint16[this._pos2 + 16]; }
set numVerticalGlyphVertices(x: number) { this._structArray.uint16[this._pos2 + 16] = x; }
get numIconVertices() { return this._structArray.uint16[this._pos2 + 17]; }
set numIconVertices(x: number) { this._structArray.uint16[this._pos2 + 17] = x; }
get crossTileID() { return this._structArray.uint32[this._pos4 + 9]; }
set crossTileID(x: number) { this._structArray.uint32[this._pos4 + 9] = x; }
get textBoxScale() { return this._structArray.float32[this._pos4 + 10]; }
set textBoxScale(x: number) { this._structArray.float32[this._pos4 + 10] = x; }
get textOffset0() { return this._structArray.float32[this._pos4 + 11]; }
set textOffset0(x: number) { this._structArray.float32[this._pos4 + 11] = x; }
get textOffset1() { return this._structArray.float32[this._pos4 + 12]; }
set textOffset1(x: number) { this._structArray.float32[this._pos4 + 12] = x; }
get verticalPlacedIconSymbolIndex() { return this._structArray.int16[this._pos2 + 7]; }
set verticalPlacedIconSymbolIndex(x: number) { this._structArray.int16[this._pos2 + 7] = x; }
get key() { return this._structArray.uint16[this._pos2 + 8]; }
set key(x: number) { this._structArray.uint16[this._pos2 + 8] = x; }
get textBoxStartIndex() { return this._structArray.uint16[this._pos2 + 9]; }
set textBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 9] = x; }
get textBoxEndIndex() { return this._structArray.uint16[this._pos2 + 10]; }
set textBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 10] = x; }
get verticalTextBoxStartIndex() { return this._structArray.uint16[this._pos2 + 11]; }
set verticalTextBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 11] = x; }
get verticalTextBoxEndIndex() { return this._structArray.uint16[this._pos2 + 12]; }
set verticalTextBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 12] = x; }
get iconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 13]; }
set iconBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 13] = x; }
get iconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 14]; }
set iconBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 14] = x; }
get verticalIconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 15]; }
set verticalIconBoxStartIndex(x: number) { this._structArray.uint16[this._pos2 + 15] = x; }
get verticalIconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 16]; }
set verticalIconBoxEndIndex(x: number) { this._structArray.uint16[this._pos2 + 16] = x; }
get featureIndex() { return this._structArray.uint16[this._pos2 + 17]; }
set featureIndex(x: number) { this._structArray.uint16[this._pos2 + 17] = x; }
get numHorizontalGlyphVertices() { return this._structArray.uint16[this._pos2 + 18]; }
set numHorizontalGlyphVertices(x: number) { this._structArray.uint16[this._pos2 + 18] = x; }
get numVerticalGlyphVertices() { return this._structArray.uint16[this._pos2 + 19]; }
set numVerticalGlyphVertices(x: number) { this._structArray.uint16[this._pos2 + 19] = x; }
get numIconVertices() { return this._structArray.uint16[this._pos2 + 20]; }
set numIconVertices(x: number) { this._structArray.uint16[this._pos2 + 20] = x; }
get numVerticalIconVertices() { return this._structArray.uint16[this._pos2 + 21]; }
set numVerticalIconVertices(x: number) { this._structArray.uint16[this._pos2 + 21] = x; }
get crossTileID() { return this._structArray.uint32[this._pos4 + 11]; }
set crossTileID(x: number) { this._structArray.uint32[this._pos4 + 11] = x; }
get textBoxScale() { return this._structArray.float32[this._pos4 + 12]; }
set textBoxScale(x: number) { this._structArray.float32[this._pos4 + 12] = x; }
get textOffset0() { return this._structArray.float32[this._pos4 + 13]; }
set textOffset0(x: number) { this._structArray.float32[this._pos4 + 13] = x; }
get textOffset1() { return this._structArray.float32[this._pos4 + 14]; }
set textOffset1(x: number) { this._structArray.float32[this._pos4 + 14] = x; }
}

SymbolInstanceStruct.prototype.size = 52;
SymbolInstanceStruct.prototype.size = 60;

export type SymbolInstance = SymbolInstanceStruct;

/**
* @private
*/
export class SymbolInstanceArray extends StructArrayLayout7i11ui1ul3f52 {
export class SymbolInstanceArray extends StructArrayLayout8i14ui1ul3f60 {
/**
* Return the SymbolInstanceStruct at the given location in the array.
* @param {number} index The index of the element.
Expand Down Expand Up @@ -1134,7 +1150,7 @@ export {
StructArrayLayout2i2i2i12,
StructArrayLayout2ub2f12,
StructArrayLayout2i2ui3ul3ui2f3ub1ul1i48,
StructArrayLayout7i11ui1ul3f52,
StructArrayLayout8i14ui1ul3f60,
StructArrayLayout1f4,
StructArrayLayout3i6,
StructArrayLayout1ul2ui8,
Expand Down
4 changes: 4 additions & 0 deletions src/data/bucket/symbol_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,21 @@ export const symbolInstance = createLayout([
{type: 'Int16', name: 'leftJustifiedTextSymbolIndex'},
{type: 'Int16', name: 'verticalPlacedTextSymbolIndex'},
{type: 'Int16', name: 'placedIconSymbolIndex'},
{type: 'Int16', name: 'verticalPlacedIconSymbolIndex'},
{type: 'Uint16', name: 'key'},
{type: 'Uint16', name: 'textBoxStartIndex'},
{type: 'Uint16', name: 'textBoxEndIndex'},
{type: 'Uint16', name: 'verticalTextBoxStartIndex'},
{type: 'Uint16', name: 'verticalTextBoxEndIndex'},
{type: 'Uint16', name: 'iconBoxStartIndex'},
{type: 'Uint16', name: 'iconBoxEndIndex'},
{type: 'Uint16', name: 'verticalIconBoxStartIndex'},
{type: 'Uint16', name: 'verticalIconBoxEndIndex'},
{type: 'Uint16', name: 'featureIndex'},
{type: 'Uint16', name: 'numHorizontalGlyphVertices'},
{type: 'Uint16', name: 'numVerticalGlyphVertices'},
{type: 'Uint16', name: 'numIconVertices'},
{type: 'Uint16', name: 'numVerticalIconVertices'},
{type: 'Uint32', name: 'crossTileID'},
{type: 'Float32', name: 'textBoxScale'},
{type: 'Float32', components: 2, name: 'textOffset'}
Expand Down
43 changes: 36 additions & 7 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ export type CollisionArrays = {
textBox?: SingleCollisionBox;
verticalTextBox?: SingleCollisionBox;
iconBox?: SingleCollisionBox;
verticalIconBox?: SingleCollisionBox;
textCircles?: Array<number>;
textFeatureIndex?: number;
verticalTextFeatureIndex?: number;
iconFeatureIndex?: number;
verticalIconFeatureIndex?: number;
};

export type SymbolFeature = {|
Expand Down Expand Up @@ -711,12 +713,18 @@ class SymbolBucket implements Bucket {
this.addDebugCollisionBoxes(symbolInstance.textBoxStartIndex, symbolInstance.textBoxEndIndex, symbolInstance, true);
this.addDebugCollisionBoxes(symbolInstance.verticalTextBoxStartIndex, symbolInstance.verticalTextBoxEndIndex, symbolInstance, true);
this.addDebugCollisionBoxes(symbolInstance.iconBoxStartIndex, symbolInstance.iconBoxEndIndex, symbolInstance, false);
this.addDebugCollisionBoxes(symbolInstance.verticalIconBoxStartIndex, symbolInstance.verticalIconBoxEndIndex, symbolInstance, false);
}
}

// These flat arrays are meant to be quicker to iterate over than the source
// CollisionBoxArray
_deserializeCollisionBoxesForSymbol(collisionBoxArray: CollisionBoxArray, textStartIndex: number, textEndIndex: number, verticalTextStartIndex: number, verticalTextEndIndex: number, iconStartIndex: number, iconEndIndex: number): CollisionArrays {
_deserializeCollisionBoxesForSymbol(collisionBoxArray: CollisionBoxArray,
textStartIndex: number, textEndIndex: number,
verticalTextStartIndex: number, verticalTextEndIndex: number,
iconStartIndex: number, iconEndIndex: number,
verticalIconStartIndex: number, verticalIconEndIndex: number): CollisionArrays {

const collisionArrays = {};
for (let k = textStartIndex; k < textEndIndex; k++) {
const box: CollisionBox = (collisionBoxArray.get(k): any);
Expand Down Expand Up @@ -750,6 +758,15 @@ class SymbolBucket implements Bucket {
break; // Only one box allowed per instance
}
}
for (let k = verticalIconStartIndex; k < verticalIconEndIndex; k++) {
// An icon can only have one box now, so this indexing is a bit vestigial...
const box: CollisionBox = (collisionBoxArray.get(k): any);
if (box.radius === 0) {
collisionArrays.verticalIconBox = {x1: box.x1, y1: box.y1, x2: box.x2, y2: box.y2, anchorPointX: box.anchorPointX, anchorPointY: box.anchorPointY};
collisionArrays.verticalIconFeatureIndex = box.featureIndex;
break; // Only one box allowed per instance
}
}
return collisionArrays;
}

Expand All @@ -764,7 +781,9 @@ class SymbolBucket implements Bucket {
symbolInstance.verticalTextBoxStartIndex,
symbolInstance.verticalTextBoxEndIndex,
symbolInstance.iconBoxStartIndex,
symbolInstance.iconBoxEndIndex
symbolInstance.iconBoxEndIndex,
symbolInstance.verticalIconBoxStartIndex,
symbolInstance.verticalIconBoxEndIndex
));
}
}
Expand Down Expand Up @@ -803,6 +822,15 @@ class SymbolBucket implements Bucket {
}
}

addIndicesForPlacedIconSymbol(placedIconSymbolIndex: number) {
const placedIcon = this.icon.placedSymbolArray.get(placedIconSymbolIndex);
if (placedIcon.numGlyphs) {
const vertexIndex = placedIcon.vertexStartIndex;
this.icon.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2);
this.icon.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
}
}

getSortedSymbolIndexes(angle: number) {
if (this.sortedAngle === angle && this.symbolInstanceIndexes !== undefined) {
return this.symbolInstanceIndexes;
Expand Down Expand Up @@ -870,11 +898,12 @@ class SymbolBucket implements Bucket {
this.addIndicesForPlacedTextSymbol(symbolInstance.verticalPlacedTextSymbolIndex);
}

const placedIcon = this.icon.placedSymbolArray.get(i);
if (placedIcon.numGlyphs) {
const vertexIndex = placedIcon.vertexStartIndex;
this.icon.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2);
this.icon.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
if (symbolInstance.placedIconSymbolIndex >= 0) {
this.addIndicesForPlacedIconSymbol(symbolInstance.placedIconSymbolIndex);
}

if (symbolInstance.verticalPlacedIconSymbolIndex >= 0) {
this.addIndicesForPlacedIconSymbol(symbolInstance.verticalPlacedIconSymbolIndex);
}
}

Expand Down
25 changes: 0 additions & 25 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,29 +208,6 @@ function updateVariableAnchorsForBucket(bucket, rotateWithMap, pitchWithMap, var
bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicTextLayoutVertexArray);
}

function updateVerticalLabels(bucket) {
const placedSymbols = bucket.text.placedSymbolArray;
const dynamicLayoutVertexArray = bucket.text.dynamicLayoutVertexArray;
dynamicLayoutVertexArray.clear();
for (let s = 0; s < placedSymbols.length; s++) {
const symbol: any = placedSymbols.get(s);
const shouldHide = symbol.hidden || !symbol.placedOrientation;
if (shouldHide) {
// These symbols are from an orientation that is not being used, or a label that wasn't placed
// so we don't need to do the extra math to figure out what incremental shift to apply.
symbolProjection.hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
} else {
const tileAnchor = new Point(symbol.anchorX, symbol.anchorY);
const angle = (bucket.allowVerticalPlacement && symbol.placedOrientation === WritingMode.vertical) ? Math.PI / 2 : 0;

for (let g = 0; g < symbol.numGlyphs; g++) {
addDynamicAttributes(dynamicLayoutVertexArray, tileAnchor, angle);
}
}
}
bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray);
}

function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate, translateAnchor,
rotationAlignment, pitchAlignment, keepUpright, stencilMode, colorMode) {

Expand Down Expand Up @@ -305,8 +282,6 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate

if (alongLine) {
symbolProjection.updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright);
} else if (isText && size && bucket.allowVerticalPlacement && !variablePlacement) {
updateVerticalLabels(bucket);
}

const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor),
Expand Down
Loading

0 comments on commit 79c3534

Please sign in to comment.