Measuring text size

Is there any way of measuring the width and height of a Text widget? I haven’t found any APIs for doing this yet, but I was hoping there was some way of tapping into the inner workings of Iced to achieve this. Right now I have a solution where I measure the width and height of a glyph of the currently used font, but it seems to me that Iced is doing something more when rendering text, because I am not getting the exact same results as I should.

After living with an estimate for while while I was tackling other issues, I ended up giving this a new attempt. I think I finally found a way to calculate the size of a glyph that is consistently equal to the size Iced calculates. As a warning, this depends on the inner workings of Iced (which is hard to get around, I guess) so a new version might break this.

pub struct Font {
    pub name: &'static str,
    pub size: f32,
}

impl Font {
    pub fn new(name: &'static str, size: f32) -> Self {
        Self { name, size }
    }

    pub fn measure_glyph(&self, char: &str) -> Size {
        use cosmic_text::{Attrs, Buffer, Family, FontSystem, Metrics, Shaping};
        let line_height_scale = LineHeight::default();
        let line_height = line_height_scale.to_absolute(self.size.into()).0;

        let mut font_system = FontSystem::new();
        let metrics = Metrics {
            font_size: self.size,
            line_height,
        };
        let mut buffer = Buffer::new_empty(metrics);
        let attrs = Attrs::new().family(Family::Name(self.name));
        buffer.set_text(&mut font_system, char, attrs, Shaping::Advanced);

        let width = buffer.layout_runs().fold(0.0, |width, run| run.line_w.max(width));

        Size {
            width,
            height: buffer.metrics().line_height,
        }
    }
}

I’ve only used it to calculate the size of a single character, in a monospaced font. I guess the width will vary on a non-monospaced font, so I am unsure how well that will work.

1 Like

FWIW, I was working on creating a helper for ellipsizing text, but honestly have run out of time and don’t think I’ll be able to work on it for a while, so in case you want to take it and run with it, I’ve posted the code to

I think the next step in the code is to measure the cumulative size of the last line’s glyphs until you can fit the “…” and stopping there.

It’s littered with eprintln! calls that I added to make sense of the whole thing, so apologies in advance.

I appreciate the thought, but it is a bit beside what I am trying to do. It seems to contain some more advanced Iced code though, so I will definitely take a look! Thanks :smile:

1 Like