Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 9aedf6d

Browse files
committed
[core] Add descender, ascender in glyphMetrics. Fix mixed fonts dis-allignment
1 parent 3888af2 commit 9aedf6d

3 files changed

Lines changed: 55 additions & 22 deletions

File tree

src/mbgl/text/glyph.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ struct GlyphMetrics {
3030
int32_t left = 0;
3131
int32_t top = 0;
3232
uint32_t advance = 0;
33+
double ascender = 0.0;
34+
double descender = 0.0;
3335
};
3436

3537
inline bool operator==(const GlyphMetrics& lhs, const GlyphMetrics& rhs) {

src/mbgl/text/glyph_pbf.cpp

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ std::vector<Glyph> parseGlyphPBF(const GlyphRange& glyphRange, const std::string
1111
protozero::pbf_reader glyphs_pbf(data);
1212

1313
while (glyphs_pbf.next(1)) {
14-
auto fontstack_pbf = glyphs_pbf.get_message();
15-
while (fontstack_pbf.next(3)) {
14+
auto readGlyphMetrics = [glyphRange, &result](protozero::pbf_reader& fontstack_pbf) {
1615
auto glyph_pbf = fontstack_pbf.get_message();
17-
1816
Glyph glyph;
1917
protozero::data_view glyphData;
2018

@@ -64,27 +62,58 @@ std::vector<Glyph> parseGlyphPBF(const GlyphRange& glyphRange, const std::string
6462
glyph.metrics.width >= 256 || glyph.metrics.height >= 256 ||
6563
glyph.metrics.left < -128 || glyph.metrics.left >= 128 ||
6664
glyph.metrics.top < -128 || glyph.metrics.top >= 128 ||
67-
glyph.metrics.advance >= 256 ||
68-
glyph.id < glyphRange.first || glyph.id > glyphRange.second) {
69-
continue;
65+
glyph.metrics.advance >= 256 || glyph.id < glyphRange.first ||
66+
glyph.id > glyphRange.second) {
67+
return;
7068
}
7169

7270
// If the area of width/height is non-zero, we need to adjust the expected size
7371
// with the implicit border size, otherwise we expect there to be no bitmap at all.
7472
if (glyph.metrics.width && glyph.metrics.height) {
75-
const Size size {
76-
glyph.metrics.width + 2 * Glyph::borderSize,
77-
glyph.metrics.height + 2 * Glyph::borderSize
78-
};
73+
const Size size{ glyph.metrics.width + 2 * Glyph::borderSize,
74+
glyph.metrics.height + 2 * Glyph::borderSize };
7975

8076
if (size.area() != glyphData.size()) {
81-
continue;
77+
return;
8278
}
8379

84-
glyph.bitmap = AlphaImage(size, reinterpret_cast<const uint8_t*>(glyphData.data()), glyphData.size());
80+
glyph.bitmap = AlphaImage(size, reinterpret_cast<const uint8_t*>(glyphData.data()),
81+
glyphData.size());
8582
}
8683

8784
result.push_back(std::move(glyph));
85+
};
86+
87+
double ascender{ 0.0 }, descender{ 0.0 };
88+
uint16_t count{ 0 };
89+
auto fontstack_pbf = glyphs_pbf.get_message();
90+
while (fontstack_pbf.next()) {
91+
switch (fontstack_pbf.tag()) {
92+
case 3: {
93+
readGlyphMetrics(fontstack_pbf);
94+
++count;
95+
break;
96+
}
97+
case 4: {
98+
ascender = fontstack_pbf.get_double();
99+
break;
100+
}
101+
case 5: {
102+
descender = fontstack_pbf.get_double();
103+
break;
104+
}
105+
default: {
106+
fontstack_pbf.skip();
107+
break;
108+
}
109+
}
110+
}
111+
if (ascender != 0.0 || descender != 0.0) {
112+
assert(count <= result.size());
113+
for (uint16_t i = result.size() - count; i <= result.size() - 1; ++i) {
114+
result[i].metrics.ascender = ascender;
115+
result[i].metrics.descender = descender;
116+
}
88117
}
89118
}
90119

src/mbgl/text/shaping.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@ void shapeLines(Shaping& shaping,
326326
const GlyphMap& glyphMap,
327327
bool allowVerticalPlacement) {
328328
float x = 0;
329-
float y = Shaping::yOffset;
330-
329+
float y = 0;
331330
float maxLineLength = 0;
332331

333332

@@ -359,21 +358,25 @@ void shapeLines(Shaping& shaping,
359358
if (it == glyphs->second.end() || !it->second) {
360359
continue;
361360
}
362-
363-
// We don't know the baseline, but since we're laying out
364-
// at 24 points, we can calculate how much it will move when
365-
// we scale up or down.
366-
const double baselineOffset = (lineMaxScale - section.scale) * util::ONE_EM;
367-
361+
368362
const Glyph& glyph = **it->second;
369363

364+
// Each glyph's baseline is starting from its acsender, which is the vertical distance
365+
// from the horizontal baseline to the highest ‘character’ coordinate in a font face.
366+
// Since we're laying out at 24 points, we need also calculate how much it will move
367+
// when we scale up or down.
368+
const double baselineOffset = -glyph.metrics.ascender * section.scale +
369+
(lineMaxScale - section.scale) * util::ONE_EM;
370+
370371
if (writingMode == WritingModeType::Horizontal ||
371372
// Don't verticalize glyphs that have no upright orientation if vertical placement is disabled.
372373
(!allowVerticalPlacement && !util::i18n::hasUprightVerticalOrientation(codePoint)) ||
373374
// If vertical placement is ebabled, don't verticalize glyphs that
374375
// are from complex text layout script, or whitespaces.
375376
(allowVerticalPlacement && (util::i18n::isWhitespace(codePoint) || util::i18n::isCharInComplexShapingScript(codePoint)))) {
376-
shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, false, section.fontStackHash, section.scale, sectionIndex);
377+
shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, false,
378+
section.fontStackHash, section.scale,
379+
sectionIndex);
377380
x += glyph.metrics.advance * section.scale + spacing;
378381
} else {
379382
shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, true, section.fontStackHash, section.scale, sectionIndex);
@@ -399,7 +402,6 @@ void shapeLines(Shaping& shaping,
399402
align(shaping, justify, anchorAlign.horizontalAlign, anchorAlign.verticalAlign, maxLineLength,
400403
lineHeight, lines.size());
401404
const float height = y - Shaping::yOffset;
402-
403405
// Calculate the bounding box
404406
shaping.top += -anchorAlign.verticalAlign * height;
405407
shaping.bottom = shaping.top + height;

0 commit comments

Comments
 (0)