summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmiao <zmiao.jamie@gmail.com>2019-09-24 18:56:48 +0300
committerzmiao <miao.zhao@mapbox.com>2019-10-06 19:48:08 +0300
commit97c6ed20ee00df22dd737498107d656ec3ef7a67 (patch)
treef8cf6e70115587e727171a1b2c457fc5c4be92fa
parent54c310f95dec0ed2d972a62a65ef283fce7683a1 (diff)
downloadqtlocation-mapboxgl-97c6ed20ee00df22dd737498107d656ec3ef7a67.tar.gz
[core] Change font's baseline value to the midline of the font fase.
-rw-r--r--src/mbgl/text/glyph.hpp1
-rw-r--r--src/mbgl/text/quads.cpp15
-rw-r--r--src/mbgl/text/shaping.cpp44
3 files changed, 46 insertions, 14 deletions
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp
index 8977f4992a..c56247f205 100644
--- a/src/mbgl/text/glyph.hpp
+++ b/src/mbgl/text/glyph.hpp
@@ -94,6 +94,7 @@ class Shaping {
explicit operator bool() const { return !positionedGlyphs.empty(); }
// The y offset *should* be part of the font metadata.
static constexpr int32_t yOffset = -17;
+ bool hasBaseline{false};
};
enum class WritingModeType : uint8_t {
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index 281c5d99de..c703f331bc 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -80,7 +80,7 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
const GlyphPosition& glyph = positionsIt->second;
const Rect<uint16_t>& rect = glyph.rect;
- // The rects have an addditional buffer that is not included in their size;
+ // The rects have an additional buffer that is not included in their size;
const float glyphPadding = 1.0f;
const float rectBuffer = 3.0f + glyphPadding;
@@ -115,8 +115,9 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
if (rotateVerticalGlyph) {
// Vertical-supporting glyphs are laid out in 24x24 point boxes (1 square em)
- // In horizontal orientation, the y values for glyphs are below the midline
- // and we use a "yOffset" of -17 to pull them up to the middle.
+ // In horizontal orientation, the y values for glyphs are below the midline.
+ // If the glyph's baseline is applicable, we take the value of the baseline offset.
+ // Otherwise, we use a "yOffset" of -17 to pull them up to the middle.
// By rotating counter-clockwise around the point at the center of the left
// edge of a 24x24 layout box centered below the midline, we align the center
// of the glyphs with the horizontal midline, so the yOffset is no longer
@@ -124,14 +125,16 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
// The y coordinate includes baseline yOffset, therefore, needs to be accounted
// for when glyph is rotated and translated.
- const Point<float> center{ -halfAdvance, halfAdvance - Shaping::yOffset };
+ float yShift =
+ shapedText.hasBaseline ? (-glyph.metrics.ascender + glyph.metrics.descender) / 2 : Shaping::yOffset;
+ const Point<float> center{-halfAdvance, halfAdvance - yShift};
const float verticalRotation = -M_PI_2;
// xHalfWidhtOffsetcorrection is a difference between full-width and half-width
// advance, should be 0 for full-width glyphs and will pull up half-width glyphs.
const float xHalfWidhtOffsetcorrection = util::ONE_EM / 2 - halfAdvance;
- const Point<float> xOffsetCorrection{ 5.0f - Shaping::yOffset - xHalfWidhtOffsetcorrection, 0.0f };
-
+ const Point<float> xOffsetCorrection{5.0f - yShift - xHalfWidhtOffsetcorrection, 0.0f};
+
tl = util::rotate(tl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
tr = util::rotate(tr - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
bl = util::rotate(bl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index d1f70e5173..efcf17873e 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -328,11 +328,34 @@ void shapeLines(Shaping& shaping,
float x = 0;
float y = 0;
float maxLineLength = 0;
+ bool hasBaseline{false};
+
+ for (std::size_t i = 0; i < lines.size(); ++i) {
+ TaggedString& line = lines[i];
+ line.trim();
+ for (std::size_t j = 0; j < line.length(); ++j) {
+ const std::size_t sectionIndex = line.getSectionIndex(j);
+ const SectionOptions& section = line.sectionAt(sectionIndex);
+ char16_t codePoint = line.getCharCodeAt(i);
+ auto glyphs = glyphMap.find(section.fontStackHash);
+ if (glyphs == glyphMap.end()) {
+ continue;
+ }
+ auto it = glyphs->second.find(codePoint);
+ if (it == glyphs->second.end() || !it->second) {
+ continue;
+ }
+ const Glyph& glyph = **it->second;
+ hasBaseline = glyph.metrics.ascender != 0 && glyph.metrics.descender != 0;
+ if (!hasBaseline) break;
+ }
+ if (!hasBaseline) break;
+ }
const float justify = textJustify == style::TextJustifyType::Right ? 1 :
textJustify == style::TextJustifyType::Left ? 0 :
0.5;
-
+
for (TaggedString& line : lines) {
// Collapse whitespace so it doesn't throw off justification
line.trim();
@@ -360,13 +383,17 @@ void shapeLines(Shaping& shaping,
const Glyph& glyph = **it->second;
- // Each glyph's baseline is starting from its acsender, which is the vertical distance
- // from the horizontal baseline to the highest ‘character’ coordinate in a font face.
- // Since we're laying out at 24 points, we need also calculate how much it will move
- // when we scale up or down.
- const bool hasBaseline = glyph.metrics.ascender != 0 && glyph.metrics.descender != 0;
- const double baselineOffset = (hasBaseline ? (-glyph.metrics.ascender * section.scale) : shaping.yOffset) +
- (lineMaxScale - section.scale) * util::ONE_EM;
+ // In order to make different fonts aligned, they must share a general baseline that starts from the midline
+ // of each font face. Baseline offset is the vertical distance from font face's baseline to its top most
+ // position, which is the half size of the sum (ascender + descender). Since glyph's position is counted
+ // from the top left corner, the negative shift is needed. So different fonts shares the same baseline but
+ // with different offset shift. If font's baseline is not applicable, fall back to use a default baseline
+ // offset, see shaping.yOffset. Since we're laying out at 24 points, we need also calculate how much it will
+ // move when we scale up or down.
+ const double baselineOffset =
+ (hasBaseline ? ((-glyph.metrics.ascender + glyph.metrics.descender) / 2 * section.scale)
+ : shaping.yOffset) +
+ (lineMaxScale - section.scale) * util::ONE_EM;
if (writingMode == WritingModeType::Horizontal ||
// Don't verticalize glyphs that have no upright orientation if vertical placement is disabled.
@@ -407,6 +434,7 @@ void shapeLines(Shaping& shaping,
shaping.bottom = shaping.top + height;
shaping.left += -anchorAlign.horizontalAlign * maxLineLength;
shaping.right = shaping.left + maxLineLength;
+ shaping.hasBaseline = hasBaseline;
}
const Shaping getShaping(const TaggedString& formattedString,