diff --git a/src/symbol/shaping.js b/src/symbol/shaping.js index 0fe17ce2fb2..0ef63fc5867 100644 --- a/src/symbol/shaping.js +++ b/src/symbol/shaping.js @@ -441,7 +441,8 @@ function evaluateBreak(breakIndex: number, targetWidth: number, potentialBreaks: Array, penalty: number, - isLastBreak: boolean): Break { + isLastBreak: boolean, + tailWhiteSpace: number = 0): Break { // We could skip evaluating breaks where the line length (breakX - priorBreak.x) > maxWidth // ...but in fact we allow lines longer than maxWidth (if there's no break points) // ...and when targetWidth and maxWidth are close, strictly enforcing maxWidth can give @@ -462,7 +463,7 @@ function evaluateBreak(breakIndex: number, return { index: breakIndex, - x: breakX, + x: breakX + tailWhiteSpace, priorBreak: bestPriorBreak, badness: bestBreakBadness }; @@ -494,11 +495,23 @@ function determineLineBreaks(logicalInput: TaggedString, const hasServerSuggestedBreakpoints = logicalInput.text.indexOf("\u200b") >= 0; let currentX = 0; + let tailWhiteSpace = 0; for (let i = 0; i < logicalInput.length(); i++) { const section = logicalInput.getSection(i); + // Add glyph advance of previous invisible codePoint in case it is not zero, such as white space ' ' + currentX += tailWhiteSpace; + const codePoint = logicalInput.getCharCode(i); - if (!whitespace[codePoint]) currentX += getGlyphAdvance(codePoint, section, glyphMap, imagePositions, spacing, layoutTextSize); + const advance = getGlyphAdvance(codePoint, section, glyphMap, imagePositions, spacing, layoutTextSize); + // Do not add glyph advance for invisible codePoint in current iteration as we try to break line here, and invisible + // codePoint shouldn't affect the decision + if (!whitespace[codePoint]) { + currentX += advance; + tailWhiteSpace = 0; + } else { + tailWhiteSpace = advance; + } // Ideographic characters, spaces, and word-breaking punctuation that often appear without // surrounding spaces. @@ -513,7 +526,7 @@ function determineLineBreaks(logicalInput: TaggedString, targetWidth, potentialLineBreaks, calculatePenalty(codePoint, logicalInput.getCharCode(i + 1), ideographicBreak && hasServerSuggestedBreakpoints), - false)); + false, tailWhiteSpace)); } } } diff --git a/test/integration/glyphs/Overpass Mono Regular/0-255.pbf b/test/integration/glyphs/Overpass Mono Regular/0-255.pbf new file mode 100644 index 00000000000..aad1327e7f7 Binary files /dev/null and b/test/integration/glyphs/Overpass Mono Regular/0-255.pbf differ diff --git a/test/integration/glyphs/Overpass Mono Regular/8192-8447.pbf b/test/integration/glyphs/Overpass Mono Regular/8192-8447.pbf new file mode 100644 index 00000000000..a9e1c310446 Binary files /dev/null and b/test/integration/glyphs/Overpass Mono Regular/8192-8447.pbf differ diff --git a/test/integration/render-tests/text-letter-spacing/zoom-and-property-function/expected.png b/test/integration/render-tests/text-letter-spacing/zoom-and-property-function/expected.png index b6dad784bf4..dbc66711809 100644 Binary files a/test/integration/render-tests/text-letter-spacing/zoom-and-property-function/expected.png and b/test/integration/render-tests/text-letter-spacing/zoom-and-property-function/expected.png differ diff --git a/test/integration/render-tests/text-max-width/long-text/expected.png b/test/integration/render-tests/text-max-width/long-text/expected.png new file mode 100644 index 00000000000..619511ae96c Binary files /dev/null and b/test/integration/render-tests/text-max-width/long-text/expected.png differ diff --git a/test/integration/render-tests/text-max-width/long-text/style.json b/test/integration/render-tests/text-max-width/long-text/style.json new file mode 100644 index 00000000000..c4921a93413 --- /dev/null +++ b/test/integration/render-tests/text-max-width/long-text/style.json @@ -0,0 +1,52 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 500, + "width":350 + } + }, + "sources": { + "mapbox": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [0, 0] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "hsl(38, 48%, 86%)" + } + }, + { + "id": "literal", + "type": "symbol", + "source": "mapbox", + "layout": { + "text-justify": "left", + "text-anchor": "center", + "text-field": "Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people’s hats off—then, I account it high time to get to sea as soon as I can.", + "text-max-width": 30, + "text-size": 10, + "text-font": [ + "Overpass Mono Regular" + ], + "text-line-height": 1.2 + } + } + ] +} diff --git a/test/integration/render-tests/text-max-width/zoom-and-property-function/expected.png b/test/integration/render-tests/text-max-width/zoom-and-property-function/expected.png index 0ea29870aaa..943868d04a5 100644 Binary files a/test/integration/render-tests/text-max-width/zoom-and-property-function/expected.png and b/test/integration/render-tests/text-max-width/zoom-and-property-function/expected.png differ diff --git a/test/integration/render-tests/text-writing-mode/point_label/cjk-arabic-vertical-mode/expected.png b/test/integration/render-tests/text-writing-mode/point_label/cjk-arabic-vertical-mode/expected.png index 0983c750c82..a82a3bea1dc 100644 Binary files a/test/integration/render-tests/text-writing-mode/point_label/cjk-arabic-vertical-mode/expected.png and b/test/integration/render-tests/text-writing-mode/point_label/cjk-arabic-vertical-mode/expected.png differ