From 8c55a7e97798a47d1f7a5e4ab45f349eda740a0c Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Fri, 2 Jun 2017 17:36:52 -0400 Subject: [PATCH] Quick/dirty fix: apply rotation after text-offset --- src/symbol/quads.js | 57 ++++++++++------- src/symbol/shaping.js | 5 +- .../line-placement-true-offset/expected.png | Bin 0 -> 3050 bytes .../line-placement-true-offset/style.json | 58 ++++++++++++++++++ 4 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 test/integration/render-tests/text-keep-upright/line-placement-true-offset/expected.png create mode 100644 test/integration/render-tests/text-keep-upright/line-placement-true-offset/style.json diff --git a/src/symbol/quads.js b/src/symbol/quads.js index 62e244bd56c..de61e8df504 100644 --- a/src/symbol/quads.js +++ b/src/symbol/quads.js @@ -153,8 +153,10 @@ function getIconQuads(anchor, shapedIcon, boxScale, line, layer, alongLine, shap */ function getGlyphQuads(anchor, shaping, boxScale, line, layer, alongLine, globalProperties, featureProperties) { + const oneEm = 24; const textRotate = layer.getLayoutValue('text-rotate', globalProperties, featureProperties) * Math.PI / 180; const keepUpright = layer.layout['text-keep-upright']; + const textOffset = layer.getLayoutValue('text-offset', globalProperties, featureProperties).map((t)=> t * oneEm); const positionedGlyphs = shaping.positionedGlyphs; const quads = []; @@ -189,32 +191,19 @@ function getGlyphQuads(anchor, shaping, boxScale, line, layer, alongLine, global }]; } - const x1 = positionedGlyph.x + glyph.left; - const y1 = positionedGlyph.y - glyph.top; - const x2 = x1 + rect.w; - const y2 = y1 + rect.h; - - const center = new Point(positionedGlyph.x, glyph.advance / 2); - - const otl = new Point(x1, y1); - const otr = new Point(x2, y1); - const obl = new Point(x1, y2); - const obr = new Point(x2, y2); - - if (positionedGlyph.angle !== 0) { - otl._sub(center)._rotate(positionedGlyph.angle)._add(center); - otr._sub(center)._rotate(positionedGlyph.angle)._add(center); - obl._sub(center)._rotate(positionedGlyph.angle)._add(center); - obr._sub(center)._rotate(positionedGlyph.angle)._add(center); - } + const baseQuad = { + upright: calculateBaseQuad(positionedGlyph, glyph, rect, textOffset), + upsideDown: calculateBaseQuad(positionedGlyph, glyph, rect, [textOffset[0], -textOffset[1]]) + }; for (let i = 0; i < glyphInstances.length; i++) { const instance = glyphInstances[i]; - let tl = otl, - tr = otr, - bl = obl, - br = obr; + const base = baseQuad[instance.upsideDown ? 'upsideDown' : 'upright']; + let tl = base.tl, + tr = base.tr, + bl = base.bl, + br = base.br; if (textRotate) { const sin = Math.sin(textRotate), @@ -240,6 +229,30 @@ function getGlyphQuads(anchor, shaping, boxScale, line, layer, alongLine, global return quads; } +function calculateBaseQuad(positionedGlyph, glyph, rect, offset) { + const x1 = positionedGlyph.x + glyph.left + offset[0]; + const y1 = positionedGlyph.y - glyph.top + offset[1]; + const x2 = x1 + rect.w; + const y2 = y1 + rect.h; + + const center = new Point(positionedGlyph.x, glyph.advance / 2); + + const tl = new Point(x1, y1); + const tr = new Point(x2, y1); + const bl = new Point(x1, y2); + const br = new Point(x2, y2); + + if (positionedGlyph.angle !== 0) { + tl._sub(center)._rotate(positionedGlyph.angle)._add(center); + tr._sub(center)._rotate(positionedGlyph.angle)._add(center); + bl._sub(center)._rotate(positionedGlyph.angle)._add(center); + br._sub(center)._rotate(positionedGlyph.angle)._add(center); + } + + return { tl, tr, bl, br }; +} + + /** * We can only render glyph quads that slide along a straight line. To draw * curved lines we need an instance of a glyph for each segment it appears on. diff --git a/src/symbol/shaping.js b/src/symbol/shaping.js index 20076ea44bc..65336394f91 100644 --- a/src/symbol/shaping.js +++ b/src/symbol/shaping.js @@ -300,8 +300,9 @@ function justifyLine(positionedGlyphs, glyphs, start, end, justify) { } function align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, lineCount, translate) { - const shiftX = (justify - horizontalAlign) * maxLineLength + translate[0]; - const shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight + translate[1]; + // TODO: moving translate part to quads.js + const shiftX = (justify - horizontalAlign) * maxLineLength;// + translate[0]; + const shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight;// + translate[1]; for (let j = 0; j < positionedGlyphs.length; j++) { positionedGlyphs[j].x += shiftX; diff --git a/test/integration/render-tests/text-keep-upright/line-placement-true-offset/expected.png b/test/integration/render-tests/text-keep-upright/line-placement-true-offset/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6dfef6d7d611ea1f152740203fefa4924118a9 GIT binary patch literal 3050 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 literal 0 HcmV?d00001 diff --git a/test/integration/render-tests/text-keep-upright/line-placement-true-offset/style.json b/test/integration/render-tests/text-keep-upright/line-placement-true-offset/style.json new file mode 100644 index 00000000000..b587263ccf1 --- /dev/null +++ b/test/integration/render-tests/text-keep-upright/line-placement-true-offset/style.json @@ -0,0 +1,58 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "operations": [ + [ "setBearing", 20 ], + [ "wait" ] + ] + } + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [-20, -20], + [20, -20], + [20, 20], + [-20, 20] + ] + } + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "guid", + "type": "line", + "source": "geojson" + }, + { + "id": "text", + "type": "symbol", + "source": "geojson", + "layout": { + "symbol-placement": "line", + "symbol-spacing": 3, + "text-allow-overlap": true, + "text-ignore-placement": true, + "text-field": "A", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-keep-upright": true, + "text-offset": [0, -1] + } + } + ] +}