linebender / skribo

A Rust library for low-level text layout.
Apache License 2.0
327 stars 35 forks source link

How to use Skribo for text layout #26

Open tiffany352 opened 4 years ago

tiffany352 commented 4 years ago

I'm trying to use LayoutSession and do text line breaking using it. However, the public API only exposes the offset values which isn't based on the advance and there is no evident way of getting the width of a run when calling LayoutSession::iter_substr.

Is there something I'm missing? I may create a PR that adds what I need if not.

cormacrelf commented 4 years ago

Can you add the offset of the last glyph and its advance width to get the total width?

Hopefully that would be correct even in RTL runs.

tiffany352 commented 4 years ago

That technically works but it's a pretty messy solution...

let mut session = LayoutSession::create(text, &TextStyle { size: 32.0 }, collection);

let mut width = 0.0;
for run in session.iter_substr(0..text.len()) {
    let font = run.font();
    let metrics = font.font.metrics();
    let units_per_px = metrics.units_per_em / 32;
    for glyph in run.glyphs() {
        width = glyph.offset.x
            + font.font.advance(glyph.glyph_id).unwrap().x / units_per_px as f32;
    }
}
cormacrelf commented 4 years ago

LayoutRangeIter is where you’d put a nice API for it. I’ve just discovered fragments have a precomputed whole-fragment advance width, so you can just sum those. It can be a &self method, as it’s got a slice to work with.

cormacrelf commented 4 years ago

(For now, your code would be faster if it skipped to the last of each iterator — runs and glyphs all have summing built in, so you can, and that avoids iterating all glyphs I’m every run. Not sure about what units they’re in, looks like you would need to maybe have braces around (offset+advance)? I don’t know.)