diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-05-21 22:46:18 +0300 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-05-24 05:59:07 -0700 |
commit | 0333f3fe448e18511060db81f430ef11f0e710df (patch) | |
tree | 851c7e41327996e45600aa6b837d3d1529285788 /src | |
parent | 5e00a2a764efcab85db63f20d1d97a87f79a6ece (diff) | |
download | qtlocation-mapboxgl-0333f3fe448e18511060db81f430ef11f0e710df.tar.gz |
[core] Prefer breaking lines at zero width space (ZWSP)
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/text/glyph.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/text/shaping.cpp | 35 |
2 files changed, 26 insertions, 11 deletions
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp index 7d6415c057..5105528512 100644 --- a/src/mbgl/text/glyph.hpp +++ b/src/mbgl/text/glyph.hpp @@ -88,8 +88,6 @@ class Shaping { float right = 0; WritingModeType writingMode; std::size_t lineCount = 0u; - std::string text = {}; - explicit operator bool() const { return !positionedGlyphs.empty(); } }; diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index ba21b97389..1d95376b04 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -9,8 +9,12 @@ #include <list> #include <cmath> -namespace mbgl { +namespace { + // Zero width space that is used to suggest break points for Japanese labels. + char16_t ZWSP = u'\u200b'; +} // namespace +namespace mbgl { // static AnchorAlignment AnchorAlignment::getAnchorAlignment(style::SymbolAnchorType anchor) { @@ -159,12 +163,13 @@ float calculateBadness(const float lineWidth, const float targetWidth, const flo return raggedness + std::pow(penalty, 2); } -float calculatePenalty(char16_t codePoint, char16_t nextCodePoint) { +float calculatePenalty(char16_t codePoint, char16_t nextCodePoint, bool penalizableIdeographicBreak) { float penalty = 0; // Force break on newline if (codePoint == 0x0a) { penalty -= 10000; } + // Penalize open parenthesis at end of line if (codePoint == 0x28 || codePoint == 0xff08) { penalty += 50; @@ -174,7 +179,13 @@ float calculatePenalty(char16_t codePoint, char16_t nextCodePoint) { if (nextCodePoint == 0x29 || nextCodePoint == 0xff09) { penalty += 50; } - + + // Penalize breaks between characters that allow ideographic breaking because + // they are less preferable than breaks at spaces (or zero width spaces) + if (penalizableIdeographicBreak) { + penalty += 150; + } + return penalty; } @@ -241,7 +252,9 @@ std::set<std::size_t> determineLineBreaks(const TaggedString& logicalInput, std::list<PotentialBreak> potentialBreaks; float currentX = 0; - + // Find first occurance of zero width space (ZWSP) character. + const bool hasServerSuggestedBreaks = logicalInput.rawText().find_first_of(ZWSP) != std::string::npos; + for (std::size_t i = 0; i < logicalInput.length(); i++) { const SectionOptions& section = logicalInput.getSection(i); char16_t codePoint = logicalInput.getCharCodeAt(i); @@ -256,11 +269,15 @@ std::set<std::size_t> determineLineBreaks(const TaggedString& logicalInput, // Ideographic characters, spaces, and word-breaking punctuation that often appear without // surrounding spaces. - if ((i < logicalInput.length() - 1) && - (util::i18n::allowsWordBreaking(codePoint) || util::i18n::allowsIdeographicBreaking(codePoint))) { - potentialBreaks.push_back(evaluateBreak(i+1, currentX, targetWidth, potentialBreaks, - calculatePenalty(codePoint, logicalInput.getCharCodeAt(i+1)), - false)); + if (i < logicalInput.length() - 1) { + const bool allowsIdeographicBreak = util::i18n::allowsIdeographicBreaking(codePoint); + if (allowsIdeographicBreak || util::i18n::allowsWordBreaking(codePoint)) { + const bool penalizableIdeographicBreak = allowsIdeographicBreak && hasServerSuggestedBreaks; + const std::size_t nextIndex = i + 1; + potentialBreaks.push_back(evaluateBreak(nextIndex, currentX, targetWidth, potentialBreaks, + calculatePenalty(codePoint, logicalInput.getCharCodeAt(nextIndex), penalizableIdeographicBreak), + false)); + } } } |