Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit dbd2235

Browse files
authored
[core] Line-break ideographic text by character (#6828)
* [core] Line-break ideographic text by character Allow a line break to be inserted after any supported Chinese, Japanese, or Yi character in a point-placed label. Balance the lines unless non-ideographic text such as Latin letters are present. Fixes #1223. * [core] Moved more character classing into util::i18n * [core] Detect character properties by Unicode block * [test] Reenabled ideographic breaking tests
1 parent 1c79147 commit dbd2235

File tree

8 files changed

+409
-19
lines changed

8 files changed

+409
-19
lines changed

cmake/core-files.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ set(MBGL_CORE_FILES
439439
src/mbgl/util/http_header.hpp
440440
src/mbgl/util/http_timeout.cpp
441441
src/mbgl/util/http_timeout.hpp
442+
src/mbgl/util/i18n.cpp
443+
src/mbgl/util/i18n.hpp
442444
src/mbgl/util/interpolate.hpp
443445
src/mbgl/util/intersection_tests.cpp
444446
src/mbgl/util/intersection_tests.hpp

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"lodash": "^4.16.4",
2424
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#ec891ce5360e488d81f60991f95d2038b83c4e3c",
2525
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#7f62a4fc9f21e619824d68abbc4b03cbc1685572",
26-
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#af9ee275f19e81f839a2733e6906c3fac272620e",
26+
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#2f6453e17cd3d17ab2ff677056f65b9cab70f2e8",
2727
"mkdirp": "^0.5.1",
2828
"node-cmake": "^1.2.1",
2929
"request": "^2.72.0",

platform/ios/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
2121
* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270))
2222
* Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742))
2323
* Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908))
24+
* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
2425
* `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127))
2526
* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773))
2627
* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728))

platform/macos/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270))
1818
* Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742))
1919
* Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908))
20+
* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
2021
* Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811))
2122
* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773))
2223
* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728))

src/mbgl/text/glyph_set.cpp

+18-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <mbgl/text/glyph_set.hpp>
22
#include <mbgl/platform/log.hpp>
33
#include <mbgl/math/minmax.hpp>
4+
#include <mbgl/util/i18n.hpp>
45

56
#include <cassert>
67

@@ -54,7 +55,8 @@ const Shaping GlyphSet::getShaping(const std::u32string &string, const float max
5455
if (shaping.positionedGlyphs.empty())
5556
return shaping;
5657

57-
lineWrap(shaping, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify, translate);
58+
lineWrap(shaping, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify, translate,
59+
util::i18n::allowsIdeographicBreaking(string));
5860

5961
return shaping;
6062
}
@@ -85,9 +87,10 @@ void justifyLine(std::vector<PositionedGlyph> &positionedGlyphs, const std::map<
8587
}
8688
}
8789

88-
void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float maxWidth,
89-
const float horizontalAlign, const float verticalAlign,
90-
const float justify, const Point<float> &translate) const {
90+
void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, float maxWidth,
91+
const float horizontalAlign, const float verticalAlign,
92+
const float justify, const Point<float> &translate,
93+
bool useBalancedIdeographicBreaking) const {
9194
uint32_t lastSafeBreak = 0;
9295

9396
uint32_t lengthBeforeCurrentLine = 0;
@@ -99,6 +102,12 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma
99102
std::vector<PositionedGlyph> &positionedGlyphs = shaping.positionedGlyphs;
100103

101104
if (maxWidth) {
105+
if (useBalancedIdeographicBreaking) {
106+
auto lastPositionedGlyph = positionedGlyphs[positionedGlyphs.size() - 1];
107+
uint32_t estimatedLineCount = std::fmax(1, std::ceil(lastPositionedGlyph.x / maxWidth));
108+
maxWidth = lastPositionedGlyph.x / estimatedLineCount;
109+
}
110+
102111
for (uint32_t i = 0; i < positionedGlyphs.size(); i++) {
103112
PositionedGlyph &shape = positionedGlyphs[i];
104113

@@ -119,8 +128,7 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma
119128
// Collapse invisible characters.
120129
uint32_t breakGlyph = positionedGlyphs[lastSafeBreak].glyph;
121130
uint32_t lineEnd = lastSafeBreak;
122-
if (breakGlyph == 0x20 /* space */
123-
|| breakGlyph == 0x200b /* zero-width space */) {
131+
if (util::i18n::isVisible(breakGlyph)) {
124132
lineEnd--;
125133
}
126134

@@ -133,17 +141,10 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma
133141
line++;
134142
}
135143

136-
// Spaces, plus word-breaking punctuation that often appears without surrounding spaces.
137-
if (shape.glyph == 0x20 /* space */
138-
|| shape.glyph == 0x26 /* ampersand */
139-
|| shape.glyph == 0x2b /* plus sign */
140-
|| shape.glyph == 0x2d /* hyphen-minus */
141-
|| shape.glyph == 0x2f /* solidus */
142-
|| shape.glyph == 0xad /* soft hyphen */
143-
|| shape.glyph == 0xb7 /* middle dot */
144-
|| shape.glyph == 0x200b /* zero-width space */
145-
|| shape.glyph == 0x2010 /* hyphen */
146-
|| shape.glyph == 0x2013 /* en dash */) {
144+
// Ideographic characters, spaces, and word-breaking punctuation that often appear without surrounding spaces.
145+
if (useBalancedIdeographicBreaking
146+
|| util::i18n::allowsWordBreaking(shape.glyph)
147+
|| util::i18n::allowsIdeographicBreaking(shape.glyph)) {
147148
lastSafeBreak = i;
148149
}
149150
}

src/mbgl/text/glyph_set.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ class GlyphSet {
1313
float horizontalAlign, float verticalAlign, float justify,
1414
float spacing, const Point<float> &translate) const;
1515
void lineWrap(Shaping &shaping, float lineHeight, float maxWidth, float horizontalAlign,
16-
float verticalAlign, float justify, const Point<float> &translate) const;
16+
float verticalAlign, float justify, const Point<float> &translate,
17+
bool useBalancedIdeographicBreaking) const;
1718

1819
private:
1920
std::map<uint32_t, SDFGlyph> sdfs;

0 commit comments

Comments
 (0)