-
Notifications
You must be signed in to change notification settings - Fork 149
Description
I try to utilize cosmic-text to draw text to a bitmap and to obtain a tight bounding box around the result. Right now, I am confused by the calculation of the vertical offset of the text. To elaborate further, let us assume that we draw a single glyph, i.e. the letter "g", using a Buffer. For the sake of simplicity, we set line_height == font_size == 72.0 (i.e. we do not apply leading aka additional distance between the lines). When we call Buffer::draw(), the code first creates a LayoutRunIter whose line_y property is initialized as follows:
Line 215 in bfb5eef
| line_y: buffer.metrics.y_offset(), |
In our case, y_offset() evaluates to 0.0 (no leading, see above) and therefore, our run starts at a vertical offset of 0.0. Now, we call next() on the iterator to draw the first run and observe that line_y is incremented by the line height which is equal to the font size (aka 72.0):
Line 241 in bfb5eef
| self.line_y += self.buffer.metrics.line_height; |
Finally, we obtain the glyph image from `swash' and draw it to the given offset:
Lines 718 to 720 in bfb5eef
| cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| { | |
| f(x_int + x, run.line_y as i32 + y_int + y, 1, 1, color); | |
| }); |
run.line_y still evaluates to 72.0 in our example. However, if I understand correctly, the swash image is positioned relatively to the baseline of the glyph. I did not find explicit confirmation for this assumption in the swash documentation, but the swash_demo repo provides an extensive sample for this. When drawing its layout, it incorporates the baseline into the vertical offset as seen here:
https://github.com/dfrg/swash_demo/blob/55aedbc8604201f1b4925e2b986db59b838dc062/src/main.rs#L493
In opposition, cosmic-text effectively places the baseline at the bottom of the line. When I try to draw my "g" glyph to the top-left corner of a bitmap and set my bounding box height to 72 pix, I end up with the following result:
How to fix this? I am not adept in typography, but for my understanding, the vertical offset must be corrected by the descent of the font as displayed here:
Indeed, to draw my glyphs to the bitmap, I tried to calculate the baseline of the font by myself to apply this correction. This approach works, but cosmic-text makes it pretty hard to implement it. Basically, I have to layout my line, obtain the FontID from the glyphs, query the Font from the FontSystem and do something like this:
let metrics = font.as_swash().metrics(&[]);
let total_height = metrics.ascent + metrics.descent;
let baseline = font_size * metrics.ascent / total_height;In fact, this is about the same calculation that is done in the swash demo, see here:
By using baseline instead of font_size (resp. the total line height) as vertical offset, I finally get the correct result. I can live with this approach, but it would be nice if cosmic-text made it easier for me to access the baseline offsets of the layout lines.
Sorry for the long explanation. I hope the issue has been made clear - and thanks for your awesome work on this crate!

