2

我正在尝试使用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,我会收到以下文本:

这个单词

如您所见,角色无处不在。

我需要考虑字体ascentdescent大小。但是,这是我遇到问题的地方。

ascent我可以使用以下计算来补偿:

let bounds = glyph.pixel_bounding_box()?;
let offset_y = bounds.height() as f32 - v_metrics.ascent;

然后将四边形网格向下移动offset_y.

当文本中没有像“g”这样的下降器时,这会改善输出:

在此处输入图像描述

但在涉及降序字符时无济于事:

在此处输入图像描述

我无法弄清楚这些rusttype例子是如何处理这个问题的。他们使用Font::layoutmethod,但这没有任何特殊的垂直对齐代码。

我肯定做错了什么。请帮忙!

4

1 回答 1

0

尝试补偿下降:

let offset_y = bounds.height() as f32 - v_metrics.ascent + v_metrics.descent;
于 2021-08-23T11:43:38.300 回答