summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmiao <miao.zhao@mapbox.com>2019-10-01 18:37:02 +0300
committerzmiao <miao.zhao@mapbox.com>2019-10-06 19:48:09 +0300
commit2bea4c50094dc236a34b082773a8f9424db0fc35 (patch)
tree4b66671d7f97cb1af94303c2aef9d3f4b6a0e61b
parenta8842884e27ff0567b5264ac3f96a5452d6bf69d (diff)
downloadqtlocation-mapboxgl-2bea4c50094dc236a34b082773a8f9424db0fc35.tar.gz
[core] Make text's baseline locating on the general virtual baseline.
-rw-r--r--src/mbgl/text/quads.cpp11
-rw-r--r--src/mbgl/text/shaping.cpp56
2 files changed, 38 insertions, 29 deletions
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index 3e3beb29a3..49b43c413a 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -117,7 +117,7 @@ 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.
- // If the glyph's baseline is applicable, we take the value of the baseline offset.
+ // If the glyph's baseline is applicable, we take the y value of the glyph.
// 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
@@ -125,14 +125,7 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
// necessary, but we also pull the glyph to the left along the x axis.
// The y coordinate includes baseline yOffset, therefore, needs to be accounted
// for when glyph is rotated and translated.
- if (shapedText.hasBaseline) {
- assert(fontPositions->second.ascender && fontPositions->second.descender);
- }
- const float yShift =
- (shapedText.hasBaseline
- ? ((-(fontPositions->second.ascender.value()) + fontPositions->second.descender.value()) / 2.0 *
- positionedGlyph.scale)
- : Shaping::yOffset);
+ const float yShift = (shapedText.hasBaseline ? positionedGlyph.y : Shaping::yOffset);
const Point<float> center{-halfAdvance, halfAdvance - yShift};
const float verticalRotation = -M_PI_2;
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index d4a30a3446..337dd613dd 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -134,11 +134,12 @@ void justifyLine(std::vector<PositionedGlyph>& positionedGlyphs,
const GlyphMap& glyphMap,
std::size_t start,
std::size_t end,
- float justify) {
- if (!justify) {
+ float justify,
+ float baselineOffset) {
+ if (!justify && !baselineOffset) {
return;
}
-
+
PositionedGlyph& glyph = positionedGlyphs[end];
auto glyphs = glyphMap.find(glyph.font);
if (glyphs == glyphMap.end()) {
@@ -151,6 +152,7 @@ void justifyLine(std::vector<PositionedGlyph>& positionedGlyphs,
for (std::size_t j = start; j <= end; j++) {
positionedGlyphs[j].x -= lineIndent;
+ positionedGlyphs[j].y += baselineOffset;
}
}
}
@@ -358,6 +360,7 @@ void shapeLines(Shaping& shaping,
continue;
}
+ float biggestHeight{0}, baselineOffset{0};
std::size_t lineStartIndex = shaping.positionedGlyphs.size();
for (std::size_t i = 0; i < line.length(); i++) {
const std::size_t sectionIndex = line.getSectionIndex(i);
@@ -374,21 +377,29 @@ void shapeLines(Shaping& shaping,
const Glyph& glyph = **it->second;
- // 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 share 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.
+ double ascender{0}, descender{0}, glyphOffset{0};
+ // In order to make different fonts aligned, they must share a general baseline that aligns with every
+ // font's real baseline. Glyph's position is counted from the top left corner, where is the ascender line
+ // starts. Since ascender is above the baseline, the glyphOffset is the negative shift. In order to make all
+ // the glyphs aligned with shaping box, for each line, we lock the heighest glyph (with scale) locating
+ // at the middle of the line, which will lead to a baseline shift. Then adjust the whole line with the
+ // baseline offset we calculated from the shift.
if (hasBaseline) {
assert(glyphs->second.ascender && glyphs->second.descender);
+ ascender = std::abs(glyphs->second.ascender.value());
+ descender = std::abs(glyphs->second.descender.value());
+ auto value = (ascender + descender) * section.scale;
+ if (biggestHeight < value) {
+ biggestHeight = value;
+ baselineOffset = (ascender - descender) / 2 * section.scale;
+ }
+ glyphOffset = -ascender * section.scale;
+ } else {
+ // 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.
+ glyphOffset = Shaping::yOffset + (lineMaxScale - section.scale) * util::ONE_EM;
}
- const float baselineOffset =
- (hasBaseline
- ? ((-(glyphs->second.ascender.value()) + glyphs->second.descender.value()) / 2.0 * 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.
@@ -398,10 +409,11 @@ void shapeLines(Shaping& shaping,
(allowVerticalPlacement &&
(util::i18n::isWhitespace(codePoint) || util::i18n::isCharInComplexShapingScript(codePoint)))) {
shaping.positionedGlyphs.emplace_back(
- codePoint, x, y + baselineOffset, false, section.fontStackHash, section.scale, sectionIndex);
+ codePoint, x, y + glyphOffset, false, section.fontStackHash, section.scale, sectionIndex);
x += glyph.metrics.advance * section.scale + spacing;
} else {
- shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, true, section.fontStackHash, section.scale, sectionIndex);
+ shaping.positionedGlyphs.emplace_back(
+ codePoint, x, y + glyphOffset, true, section.fontStackHash, section.scale, sectionIndex);
x += util::ONE_EM * section.scale + spacing;
}
}
@@ -410,9 +422,13 @@ void shapeLines(Shaping& shaping,
if (shaping.positionedGlyphs.size() != lineStartIndex) {
float lineLength = x - spacing; // Don't count trailing spacing
maxLineLength = util::max(lineLength, maxLineLength);
-
- justifyLine(shaping.positionedGlyphs, glyphMap, lineStartIndex,
- shaping.positionedGlyphs.size() - 1, justify);
+
+ justifyLine(shaping.positionedGlyphs,
+ glyphMap,
+ lineStartIndex,
+ shaping.positionedGlyphs.size() - 1,
+ justify,
+ baselineOffset);
}
x = 0;