diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2017-02-10 16:57:48 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-02-10 18:57:48 -0600 |
commit | e6c15d0f6f285bc604c0d93381b9b1d3957cb5c9 (patch) | |
tree | fefef07141b72a96d12f6ff788c8727b20420bab /src/mbgl/text | |
parent | 0bbc6b814cbec44be7026a0bac83d56e4d71a287 (diff) | |
download | qtlocation-mapboxgl-e6c15d0f6f285bc604c0d93381b9b1d3957cb5c9.tar.gz |
Upright CJK characters in vertically-oriented labels (#7114)
CJK characters and adjacent punctuation now remain upright in vertically oriented labels that have line placement.
Fixes #1682.
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/glyph.hpp | 39 | ||||
-rw-r--r-- | src/mbgl/text/glyph_set.cpp | 28 | ||||
-rw-r--r-- | src/mbgl/text/glyph_set.hpp | 9 | ||||
-rw-r--r-- | src/mbgl/text/quads.cpp | 21 | ||||
-rw-r--r-- | src/mbgl/text/quads.hpp | 6 |
5 files changed, 80 insertions, 23 deletions
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp index 2bf1448492..c89d045dfc 100644 --- a/src/mbgl/text/glyph.hpp +++ b/src/mbgl/text/glyph.hpp @@ -2,6 +2,7 @@ #include <mbgl/text/glyph_range.hpp> #include <mbgl/util/rect.hpp> +#include <mbgl/util/traits.hpp> #include <cstdint> #include <vector> @@ -52,25 +53,29 @@ typedef std::map<uint32_t, Glyph> GlyphPositions; class PositionedGlyph { public: - explicit PositionedGlyph(uint32_t glyph_, float x_, float y_) - : glyph(glyph_), x(x_), y(y_) {} + explicit PositionedGlyph(uint32_t glyph_, float x_, float y_, float angle_) + : glyph(glyph_), x(x_), y(y_), angle(angle_) {} uint32_t glyph = 0; float x = 0; float y = 0; + float angle = 0; }; +enum class WritingModeType : uint8_t; + class Shaping { public: explicit Shaping() : top(0), bottom(0), left(0), right(0) {} - explicit Shaping(float x, float y, std::u16string text_) - : text(std::move(text_)), top(y), bottom(y), left(x), right(x) {} + explicit Shaping(float x, float y, std::u16string text_, WritingModeType writingMode_) + : text(std::move(text_)), top(y), bottom(y), left(x), right(x), writingMode(writingMode_) {} std::vector<PositionedGlyph> positionedGlyphs; std::u16string text; int32_t top; int32_t bottom; int32_t left; int32_t right; + WritingModeType writingMode; explicit operator bool() const { return !positionedGlyphs.empty(); } }; @@ -90,4 +95,30 @@ public: GlyphMetrics metrics; }; +enum class WritingModeType : uint8_t { + None = 0, + Horizontal = 1 << 0, + Vertical = 1 << 1, +}; + +constexpr WritingModeType operator|(WritingModeType a, WritingModeType b) { + return WritingModeType(mbgl::underlying_type(a) | mbgl::underlying_type(b)); +} + +constexpr WritingModeType& operator|=(WritingModeType& a, WritingModeType b) { + return (a = a | b); +} + +constexpr bool operator&(WritingModeType lhs, WritingModeType rhs) { + return mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs); +} + +constexpr WritingModeType& operator&=(WritingModeType& lhs, WritingModeType rhs) { + return (lhs = WritingModeType(mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs))); +} + +constexpr WritingModeType operator~(WritingModeType value) { + return WritingModeType(~mbgl::underlying_type(value)); +} + } // end namespace mbgl diff --git a/src/mbgl/text/glyph_set.cpp b/src/mbgl/text/glyph_set.cpp index b4b3195486..61d5cac926 100644 --- a/src/mbgl/text/glyph_set.cpp +++ b/src/mbgl/text/glyph_set.cpp @@ -42,18 +42,19 @@ const Shaping GlyphSet::getShaping(const std::u16string& logicalInput, const float justify, const float spacing, const Point<float>& translate, + const float verticalHeight, + const WritingModeType writingMode, BiDi& bidi) const { - // The string stored in shaping.text is used for finding duplicates, but may end up quite // different from the glyphs that get shown - Shaping shaping(translate.x * 24, translate.y * 24, logicalInput); + Shaping shaping(translate.x * 24, translate.y * 24, logicalInput, writingMode); std::vector<std::u16string> reorderedLines = bidi.processText(logicalInput, - determineLineBreaks(logicalInput, spacing, maxWidth)); + determineLineBreaks(logicalInput, spacing, maxWidth, writingMode)); shapeLines(shaping, reorderedLines, spacing, lineHeight, horizontalAlign, verticalAlign, - justify, translate); + justify, translate, verticalHeight, writingMode); return shaping; } @@ -198,8 +199,9 @@ std::set<std::size_t> leastBadBreaks(const PotentialBreak& lastLineBreak) { // more intuitive, but we can't do that because the visual order may be changed by line breaks! std::set<std::size_t> GlyphSet::determineLineBreaks(const std::u16string& logicalInput, const float spacing, - float maxWidth) const { - if (!maxWidth) { + float maxWidth, + const WritingModeType writingMode) const { + if (!maxWidth || writingMode != WritingModeType::Horizontal) { return {}; } @@ -239,7 +241,9 @@ void GlyphSet::shapeLines(Shaping& shaping, const float horizontalAlign, const float verticalAlign, const float justify, - const Point<float>& translate) const { + const Point<float>& translate, + const float verticalHeight, + const WritingModeType writingMode) const { // the y offset *should* be part of the font metadata const int32_t yOffset = -17; @@ -266,8 +270,14 @@ void GlyphSet::shapeLines(Shaping& shaping, } const SDFGlyph& glyph = it->second; - shaping.positionedGlyphs.emplace_back(chr, x, y); - x += glyph.metrics.advance + spacing; + + if (writingMode == WritingModeType::Horizontal || !util::i18n::hasUprightVerticalOrientation(chr)) { + shaping.positionedGlyphs.emplace_back(chr, x, y, 0); + x += glyph.metrics.advance + spacing; + } else { + shaping.positionedGlyphs.emplace_back(chr, x, 0, -M_PI_2); + x += verticalHeight + spacing; + } } // Only justify if we placed at least one glyph diff --git a/src/mbgl/text/glyph_set.hpp b/src/mbgl/text/glyph_set.hpp index 3037cefca0..0342c82eb5 100644 --- a/src/mbgl/text/glyph_set.hpp +++ b/src/mbgl/text/glyph_set.hpp @@ -18,6 +18,8 @@ public: float justify, float spacing, const Point<float>& translate, + float verticalHeight, + const WritingModeType, BiDi& bidi) const; private: @@ -26,7 +28,8 @@ private: float maxWidth) const; std::set<std::size_t> determineLineBreaks(const std::u16string& logicalInput, const float spacing, - float maxWidth) const; + float maxWidth, + const WritingModeType) const; void shapeLines(Shaping& shaping, const std::vector<std::u16string>& lines, @@ -35,7 +38,9 @@ private: float horizontalAlign, float verticalAlign, float justify, - const Point<float>& translate) const; + const Point<float>& translate, + float verticalHeight, + const WritingModeType) const; std::map<uint32_t, SDFGlyph> sdfs; }; diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 10c4dfea90..b4a3ea09a4 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -89,7 +89,7 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon, } SymbolQuads quads; - quads.emplace_back(tl, tr, bl, br, image.pos, 0, 0, anchor.point, globalMinScale, std::numeric_limits<float>::infinity()); + quads.emplace_back(tl, tr, bl, br, image.pos, 0, 0, anchor.point, globalMinScale, std::numeric_limits<float>::infinity(), shapedText.writingMode); return quads; } @@ -207,10 +207,19 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, const float x2 = x1 + rect.w; const float y2 = y1 + rect.h; - const Point<float> otl{x1, y1}; - const Point<float> otr{x2, y1}; - const Point<float> obl{x1, y2}; - const Point<float> obr{x2, y2}; + const Point<float> center{positionedGlyph.x, static_cast<float>(static_cast<float>(glyph.metrics.advance) / 2.0)}; + + Point<float> otl{x1, y1}; + Point<float> otr{x2, y1}; + Point<float> obl{x1, y2}; + Point<float> obr{x2, y2}; + + if (positionedGlyph.angle != 0) { + otl = util::rotate(otl - center, positionedGlyph.angle) + center; + otr = util::rotate(otr - center, positionedGlyph.angle) + center; + obl = util::rotate(obl - center, positionedGlyph.angle) + center; + obr = util::rotate(obr - center, positionedGlyph.angle) + center; + } for (const GlyphInstance &instance : glyphInstances) { @@ -236,7 +245,7 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, const float anchorAngle = std::fmod((anchor.angle + instance.offset + 2 * M_PI), (2 * M_PI)); const float glyphAngle = std::fmod((instance.angle + instance.offset + 2 * M_PI), (2 * M_PI)); - quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale); + quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale, shapedText.writingMode); } diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp index 75fb53aade..760015340e 100644 --- a/src/mbgl/text/quads.hpp +++ b/src/mbgl/text/quads.hpp @@ -15,7 +15,7 @@ class PositionedIcon; struct SymbolQuad { explicit SymbolQuad(Point<float> tl_, Point<float> tr_, Point<float> bl_, Point<float> br_, Rect<uint16_t> tex_, float anchorAngle_, float glyphAngle_, Point<float> anchorPoint_, - float minScale_, float maxScale_) + float minScale_, float maxScale_, WritingModeType writingMode_) : tl(std::move(tl_)), tr(std::move(tr_)), bl(std::move(bl_)), @@ -25,13 +25,15 @@ struct SymbolQuad { glyphAngle(glyphAngle_), anchorPoint(std::move(anchorPoint_)), minScale(minScale_), - maxScale(maxScale_) {} + maxScale(maxScale_), + writingMode(writingMode_) {} Point<float> tl, tr, bl, br; Rect<uint16_t> tex; float anchorAngle, glyphAngle; Point<float> anchorPoint; float minScale, maxScale; + WritingModeType writingMode; }; typedef std::vector<SymbolQuad> SymbolQuads; |