servo / font-kit

A cross-platform font loading library written in Rust
Apache License 2.0
660 stars 98 forks source link

How to render text into one line with a given font? #204

Open oovm opened 1 year ago

oovm commented 1 year ago

How can I render a whole line of text into a colored bitmap?

I made some attempts, but encountered the following problems:

  1. The width of the space is 0
  2. Emoji rendering without color.

My render function is as follows

fn render_text(text: &str, font: &Font, font_size: f32) -> anyhow::Result<Canvas> {
    let mut chars = vec![];
    for char in text.chars() {
        let glyph_id = match font.glyph_for_char(char) {
            Some(s) => s,
            None => Err(format!("No such char `{char}` in font `{}`", font.family_name()))?,
        };
        let size = font.raster_bounds(
            glyph_id,
            font_size,
            Transform2F::from_translation(Vector2F::new(0.0, font_size)),
            HintingOptions::None,
            RasterizationOptions::SubpixelAa,
        )?;
        chars.push((glyph_id, size));
    }
    let mut x = 0.0;
    let mut canvas = Canvas::new(Vector2I::new(font_size as i32), Format::A8);
    for (glyph_id, rect) in chars {
        font.rasterize_glyph(
            &mut canvas,
            glyph_id,
            font_size,
            Transform2F::from_translation(Vector2F::new(x, font_size)),
            HintingOptions::None,
            RasterizationOptions::SubpixelAa,
        )?;
        x += rect.size().x() as f32;
    }
    Ok(canvas)
}
jdm commented 1 year ago

https://github.com/servo/servo/blob/309c4f9b51a4a0c951da1b96a91fdef040b52e82/components/canvas/raqote_backend.rs#L521-L560 is the routine we use in servo.