我正在尝试使用rusttype crate 来呈现文本。到目前为止,这太棒了,但是当我试图正确定位单个字形时,我遇到了障碍。
我通过将每个字形渲染为RgbaImage
(从图像箱,如rusttype
图像示例中)并将其渲染为四边形网格来渲染文本。
pub struct Glyph {
pub image: image::RgbaImage,
pub glyph: rusttype::PositionedGlyph<'static>,
pub vertical_offset: f32,
}
// &self.font is a rusttype::Font type
pub fn draw_glyph(&self, ch: char, font_size: f32) -> Option<Glyph> {
// Set size
let scale = rusttype::Scale::uniform(font_size);
let v_metrics = self.font.v_metrics(scale);
// Position and scale glyph
let offset = rusttype::point(0.0, 0.0 + v_metrics.ascent);
let glyph = self.font.glyph(ch).scaled(scale).positioned(offset);
// Get glyph dimensions
let bounds = glyph.pixel_bounding_box()?;
let glyph_height = (v_metrics.ascent - v_metrics.descent).ceil() as u32;
let glyph_width = (bounds.max.x - bounds.min.x) as u32;
// Try to align glyphs on a baseline
let offset_y = bounds.height() as f32 - v_metrics.ascent;
// Generate image
let mut image =
image::ImageBuffer::from_pixel(glyph_width, glyph_height, image::Rgba([200; 4]));
glyph.draw(|x, y, v| {
image.put_pixel(x, y, image::Rgba([0 + (v * 255.0) as u8; 4]));
});
Some(Glyph {
glyph: glyph,
image: image,
vertical_offset: offset_y,
})
}
但是,如果没有计算vertical_offset
,我会收到以下文本:
如您所见,角色无处不在。
我需要考虑字体ascent
的descent
大小。但是,这是我遇到问题的地方。
ascent
我可以使用以下计算来补偿:
let bounds = glyph.pixel_bounding_box()?;
let offset_y = bounds.height() as f32 - v_metrics.ascent;
然后将四边形网格向下移动offset_y
.
当文本中没有像“g”这样的下降器时,这会改善输出:
但在涉及降序字符时无济于事:
我无法弄清楚这些rusttype
例子是如何处理这个问题的。他们使用Font::layout
method,但这没有任何特殊的垂直对齐代码。
我肯定做错了什么。请帮忙!