Skip to content

fix: glyph overflow in text layout, affecting text_size and draw_text_mut #767

Open
var4yn wants to merge 3 commits intoimage-rs:mainfrom
var4yn:master
Open

fix: glyph overflow in text layout, affecting text_size and draw_text_mut #767
var4yn wants to merge 3 commits intoimage-rs:mainfrom
var4yn:master

Conversation

@var4yn
Copy link
Copy Markdown
Contributor

@var4yn var4yn commented Mar 26, 2026

ISSUE: #710

Problem

When rendering glyphs that extend beyond the font's ascent line (e.g. Ä, Ö, Ü),
the returned text_size did not account for the overshoot, causing the rendered text
to be clipped.

Solution

Added an second cycle in layout_glyphs to compute above_ascent and below_ascent
values.

  • above_y: the minimum value among glyphs that extend above the ascent line (less than zero).
  • below_y: the minimum value among glyphs that extend below the ascent line (greater than zero).

These values are used to calculate the correct height and correct offset_y in layout_glyphs.

Before / After

Upd: The font from the issue is used. The changes are clearly visible.

Before After
overflow_glyph_before_out overflow_glyph_after_out
overflow_glyph_before_symbols overflow_glyph_after_symbols
overflow_glyph_before_symbols_little overflow_glyph_after_symbols_little
overflow_glyph_before_symbol2 overflow_glyph_after_symbol2

@var4yn
Copy link
Copy Markdown
Contributor Author

var4yn commented Mar 26, 2026

For old tests - test_draw_text, test_draw_text_with_alpha, truth images need to be replaced.

I'm ready to do this if this PR is of interest

@var4yn
Copy link
Copy Markdown
Contributor Author

var4yn commented Mar 26, 2026

I just noticed that the fix isn't very visible on the DejaVu font.
Perhaps I should update the font in the tests to the font from the example in the issue.

@var4yn
Copy link
Copy Markdown
Contributor Author

var4yn commented Mar 26, 2026

Code to generate Before/After images:

use image::RgbaImage;

macro_rules! txt_img {
    ($func_name:ident, $imageproc: ident) => {
        pub fn $func_name(word: &str) -> RgbaImage {
            let mplantin = include_bytes!("../fonts/mplantin.ttf");
            let mplantin = ab_glyph::FontArc::try_from_slice(mplantin).unwrap();

            let font_size = 128.0;

            let (w, h) = $imageproc::drawing::text_size(font_size, &mplantin, word);
            let mut image = RgbaImage::from_pixel(w, h, image::Rgba([0, 0, 0, 255]));

            $imageproc::drawing::draw_text_mut(
                &mut image,
                image::Rgba([100u8, 100u8, 100u8, 255u8]),
                0,
                0,
                font_size,
                &mplantin,
                word,
            );

            image
        }
    };
}

txt_img!(txt_img_before_fix, imageproc);
txt_img!(txt_img_after_fix,  imageproc_2);

fn main() {
    
    let words = [
        ("ÁÄaaa", "out"),
        ("Á", "symbol2"),
        ("Äabcpghky", "symbols"),
        ("abcpghky", "symbols_little"),
        ("1.", "number"),
    ];

    for (word, filename) in words {

        let img_before = txt_img_before_fix(word);
        let img_after = txt_img_after_fix(word);

        img_before.save(format!("{}.png", filename)).ok();
        img_after.save(format!("{}_after_fix.png", filename)).ok();

    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant