diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-11-14 14:53:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-14 14:53:21 -0800 |
commit | dbd22357441ec66c46cc7e46a01ed114a18f685c (patch) | |
tree | 7f4af9a1276139863b6828b6f7ea152fd5b954a9 /src/mbgl/text | |
parent | 1c79147a84fe9f852fa21bcf5629f490e8e2a8bf (diff) | |
download | qtlocation-mapboxgl-dbd22357441ec66c46cc7e46a01ed114a18f685c.tar.gz |
[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
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/glyph_set.cpp | 35 | ||||
-rw-r--r-- | src/mbgl/text/glyph_set.hpp | 3 |
2 files changed, 20 insertions, 18 deletions
diff --git a/src/mbgl/text/glyph_set.cpp b/src/mbgl/text/glyph_set.cpp index 0875a83850..c778de207b 100644 --- a/src/mbgl/text/glyph_set.cpp +++ b/src/mbgl/text/glyph_set.cpp @@ -1,6 +1,7 @@ #include <mbgl/text/glyph_set.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/math/minmax.hpp> +#include <mbgl/util/i18n.hpp> #include <cassert> @@ -54,7 +55,8 @@ const Shaping GlyphSet::getShaping(const std::u32string &string, const float max if (shaping.positionedGlyphs.empty()) return shaping; - lineWrap(shaping, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify, translate); + lineWrap(shaping, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify, translate, + util::i18n::allowsIdeographicBreaking(string)); return shaping; } @@ -85,9 +87,10 @@ void justifyLine(std::vector<PositionedGlyph> &positionedGlyphs, const std::map< } } -void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float maxWidth, - const float horizontalAlign, const float verticalAlign, - const float justify, const Point<float> &translate) const { +void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, float maxWidth, + const float horizontalAlign, const float verticalAlign, + const float justify, const Point<float> &translate, + bool useBalancedIdeographicBreaking) const { uint32_t lastSafeBreak = 0; uint32_t lengthBeforeCurrentLine = 0; @@ -99,6 +102,12 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma std::vector<PositionedGlyph> &positionedGlyphs = shaping.positionedGlyphs; if (maxWidth) { + if (useBalancedIdeographicBreaking) { + auto lastPositionedGlyph = positionedGlyphs[positionedGlyphs.size() - 1]; + uint32_t estimatedLineCount = std::fmax(1, std::ceil(lastPositionedGlyph.x / maxWidth)); + maxWidth = lastPositionedGlyph.x / estimatedLineCount; + } + for (uint32_t i = 0; i < positionedGlyphs.size(); i++) { PositionedGlyph &shape = positionedGlyphs[i]; @@ -119,8 +128,7 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma // Collapse invisible characters. uint32_t breakGlyph = positionedGlyphs[lastSafeBreak].glyph; uint32_t lineEnd = lastSafeBreak; - if (breakGlyph == 0x20 /* space */ - || breakGlyph == 0x200b /* zero-width space */) { + if (util::i18n::isVisible(breakGlyph)) { lineEnd--; } @@ -133,17 +141,10 @@ void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float ma line++; } - // Spaces, plus word-breaking punctuation that often appears without surrounding spaces. - if (shape.glyph == 0x20 /* space */ - || shape.glyph == 0x26 /* ampersand */ - || shape.glyph == 0x2b /* plus sign */ - || shape.glyph == 0x2d /* hyphen-minus */ - || shape.glyph == 0x2f /* solidus */ - || shape.glyph == 0xad /* soft hyphen */ - || shape.glyph == 0xb7 /* middle dot */ - || shape.glyph == 0x200b /* zero-width space */ - || shape.glyph == 0x2010 /* hyphen */ - || shape.glyph == 0x2013 /* en dash */) { + // Ideographic characters, spaces, and word-breaking punctuation that often appear without surrounding spaces. + if (useBalancedIdeographicBreaking + || util::i18n::allowsWordBreaking(shape.glyph) + || util::i18n::allowsIdeographicBreaking(shape.glyph)) { lastSafeBreak = i; } } diff --git a/src/mbgl/text/glyph_set.hpp b/src/mbgl/text/glyph_set.hpp index 37ffdb070a..fed7960a5f 100644 --- a/src/mbgl/text/glyph_set.hpp +++ b/src/mbgl/text/glyph_set.hpp @@ -13,7 +13,8 @@ public: float horizontalAlign, float verticalAlign, float justify, float spacing, const Point<float> &translate) const; void lineWrap(Shaping &shaping, float lineHeight, float maxWidth, float horizontalAlign, - float verticalAlign, float justify, const Point<float> &translate) const; + float verticalAlign, float justify, const Point<float> &translate, + bool useBalancedIdeographicBreaking) const; private: std::map<uint32_t, SDFGlyph> sdfs; |