@@ -69,10 +69,66 @@ TextBlobRef SpriteTextBlob::MakeWithShaper(const FontMgrRef& fontMgr,
69
69
70
70
const auto * spriteFont = static_cast <const SpriteSheetFont*>(font.get ());
71
71
72
- float baseline = 0 .0f ;
72
+ // TODO add configuration of the default falback font
73
+ auto getFallbackFont = [](const FontMgrRef& fontMgr, const FontRef& font) -> FontRef {
74
+ FontRef fallbackFont = font->fallback ();
75
+ if (!fallbackFont) {
76
+ fallbackFont = fontMgr->defaultFont ();
77
+ fallbackFont->setSize (font->size ());
78
+ fallbackFont->setAntialias (font->antialias ());
79
+ }
80
+ return fallbackFont;
81
+ };
82
+
83
+ // First iteration through the text/fonts/fallback fonts to
84
+ // calculate the total text height and baseline to be used.
85
+ FontMetrics metrics;
86
+ font->metrics (&metrics);
87
+ float baseline = -metrics.ascent ;
88
+ float textHeight = metrics.descent - metrics.ascent ;
89
+ {
90
+ // TODO this utf8 iteration between fonts/fallback is duplicated
91
+ // here and below, we could try to merge this code
92
+ base::utf8_decode decode (text);
93
+ while (true ) {
94
+ const codepoint_t chr = decode.next ();
95
+ if (chr == 0 )
96
+ break ;
97
+
98
+ const glyph_t glyph = spriteFont->codePointToGlyph (chr);
99
+ // Code point not found, use the fallback font or the FontMgr and
100
+ // create a run using another TextBlob.
101
+ if (glyph == 0 ) {
102
+ base::utf8_decode subDecode = decode;
103
+ while (true ) {
104
+ const base::utf8_decode prevSubDecode = subDecode;
105
+ const codepoint_t subChr = subDecode.next ();
106
+ if (subChr == 0 ) {
107
+ decode = subDecode;
108
+ break ;
109
+ }
110
+
111
+ // Continue the run until we find a glyph that can be
112
+ // represent with the original font.
113
+ if (spriteFont->codePointToGlyph (subChr) != 0 ) {
114
+ decode = prevSubDecode; // Go back to the previous decode point
115
+ break ;
116
+ }
117
+ }
118
+
119
+ // Calculate the max baseline/textHeight
120
+ FontRef fallbackFont = getFallbackFont (fontMgr, font);
121
+ FontMetrics fallbackMetrics;
122
+ fallbackFont->metrics (&fallbackMetrics);
123
+ baseline = std::max (baseline, -fallbackMetrics.ascent );
124
+ textHeight = std::max (textHeight, fallbackMetrics.descent - fallbackMetrics.ascent );
125
+ }
126
+ }
127
+ }
128
+
73
129
Runs runs;
74
130
Run run;
75
- auto addRun = [&runs, &run, &font, &baseline, handler]() {
131
+ auto addRun = [&runs, &run, &font, handler]() {
76
132
if (handler && !run.subBlob ) {
77
133
TextBlob::RunInfo info;
78
134
@@ -83,10 +139,6 @@ TextBlobRef SpriteTextBlob::MakeWithShaper(const FontMgrRef& fontMgr,
83
139
info.positions = run.positions .data ();
84
140
info.clusters = run.clusters .data ();
85
141
86
- FontMetrics metrics;
87
- font->metrics (&metrics);
88
- baseline = std::max (baseline, -metrics.ascent );
89
-
90
142
handler->commitRunBuffer (info);
91
143
}
92
144
runs.push_back (run);
@@ -134,25 +186,15 @@ TextBlobRef SpriteTextBlob::MakeWithShaper(const FontMgrRef& fontMgr,
134
186
run.utf8Range .begin = i;
135
187
run.utf8Range .end = j;
136
188
137
- // TODO add configuration of the default fallback font
138
- auto fallbackFont = fontMgr->defaultFont ();
139
- fallbackFont->setSize (font->size ());
140
- fallbackFont->setAntialias (font->antialias ());
141
-
142
189
// Align position between both fonts (font and fallbackFont)
143
190
// in the baseline pos of the original font.
144
- FontMetrics metrics ;
191
+ FontRef fallbackFont = getFallbackFont (fontMgr, font) ;
145
192
FontMetrics fallbackMetrics;
146
- font->metrics (&metrics);
147
193
fallbackFont->metrics (&fallbackMetrics);
148
194
149
195
gfx::PointF alignedPos;
150
196
alignedPos.x = pos.x ;
151
- const float baselineShift = -metrics.ascent + fallbackMetrics.ascent ;
152
- alignedPos.y = pos.y + baselineShift;
153
-
154
- // Adjust baseline for this composed TextBlob
155
- baseline = std::max (baseline, -fallbackMetrics.ascent + baselineShift);
197
+ alignedPos.y = pos.y + baseline + fallbackMetrics.ascent ;
156
198
157
199
OffsetHandler subHandler (handler, i, alignedPos);
158
200
run.subBlob = TextBlob::MakeWithShaper (fontMgr,
@@ -169,15 +211,18 @@ TextBlobRef SpriteTextBlob::MakeWithShaper(const FontMgrRef& fontMgr,
169
211
}
170
212
171
213
// Restore beginning of UTF8 range for the next run
172
- run.utf8Range .begin = decode. pos () - text. begin () ;
214
+ run.utf8Range .begin = j ;
173
215
continue ;
174
216
}
175
217
176
218
gfx::Rect glyphBounds = spriteFont->getGlyphBounds (glyph);
177
219
if (glyphBounds.isEmpty ())
178
220
continue ;
179
221
180
- run.add (glyph, pos, i - run.utf8Range .begin );
222
+ gfx::PointF alignedPos;
223
+ alignedPos.x = pos.x ;
224
+ alignedPos.y = pos.y + baseline + metrics.ascent ;
225
+ run.add (glyph, alignedPos, i - run.utf8Range .begin );
181
226
182
227
glyphBounds.offset (pos);
183
228
textBounds |= glyphBounds;
@@ -190,6 +235,7 @@ TextBlobRef SpriteTextBlob::MakeWithShaper(const FontMgrRef& fontMgr,
190
235
191
236
auto blob = base::make_ref<SpriteTextBlob>(textBounds, font, std::move (runs));
192
237
blob->setBaseline (baseline);
238
+ blob->setTextHeight (textHeight);
193
239
return blob;
194
240
}
195
241
0 commit comments