summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2017-02-10 16:57:48 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-02-10 18:57:48 -0600
commite6c15d0f6f285bc604c0d93381b9b1d3957cb5c9 (patch)
treefefef07141b72a96d12f6ff788c8727b20420bab /src/mbgl/text
parent0bbc6b814cbec44be7026a0bac83d56e4d71a287 (diff)
downloadqtlocation-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.hpp39
-rw-r--r--src/mbgl/text/glyph_set.cpp28
-rw-r--r--src/mbgl/text/glyph_set.hpp9
-rw-r--r--src/mbgl/text/quads.cpp21
-rw-r--r--src/mbgl/text/quads.hpp6
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;