iced-rs / iced

A cross-platform GUI library for Rust, inspired by Elm
https://iced.rs
MIT License
23.49k stars 1.08k forks source link

Rounding bug from text::Renderer::measure() #1666

Open latidoremi opened 1 year ago

latidoremi commented 1 year ago

Is there an existing issue for this?

Is this issue related to iced?

What happened?

This might seem a bit trivial but it's way more noticeable in my actual project

text_bounds_bug

Notice the thin black line under the pick lists, the black background is a widget::Container with height set to Length::Shrink, which means the buttons are a little bit higher than the pick lists, but they're actually using the same text size and padding, and the weird thing is, this happens when text size is set to exactly 15 or a multiple of 15 like 30, 60, etc.

I checked out the source code and noticed that widget::PickList is using the text_size variable as the height of the intrinsic size, while the text on a button which is widget::Text is using the height calculated from text::Renderer::measure()

pick_list_layout button_layout text_layout text_pipeline_measure

I added some println!s so that I can log the size and stuff, here's the result with all text size set to 15

PickList | intrinsic:Size { width: 19.0, height: 15.0 }, Size { width: 100.0, height: 23.0 }
PickList | intrinsic:Size { width: 19.0, height: 15.0 }, Size { width: 100.0, height: 23.0 }
Pipeline | content:aaa, bounds: Rect { min: point(0.0, 0.0), max: point(19.0125, 15.000001) }
Text | content:aaa, Size { width: 20.0, height: 16.0 }
Button | content_size: Size { width: 20.0, height: 16.0 }, Size { width: 28.0, height: 24.0 }
Pipeline | content:Afg, bounds: Rect { min: point(0.0, 0.0), max: point(19.1, 15.000001) }
Text | content:Afg, Size { width: 20.0, height: 16.0 }
Button | content_size: Size { width: 20.0, height: 16.0 }, Size { width: 28.0, height: 24.0 }
PickList | intrinsic:Size { width: 19.0, height: 15.0 }, Size { width: 100.0, height: 23.0 }
PickList | intrinsic:Size { width: 19.0, height: 15.0 }, Size { width: 100.0, height: 23.0 }
Pipeline | content:aaa, bounds: Rect { min: point(0.0, 0.0), max: point(19.0125, 15.000001) }
Text | content:aaa, Size { width: 20.0, height: 16.0 }
Button | content_size: Size { width: 20.0, height: 16.0 }, Size { width: 28.0, height: 24.0 }
Pipeline | content:Afg, bounds: Rect { min: point(0.0, 0.0), max: point(19.1, 15.000001) }
Text | content:Afg, Size { width: 20.0, height: 16.0 }
Button | content_size: Size { width: 20.0, height: 16.0 }, Size { width: 28.0, height: 24.0 }

So it ceils 15.000001 to 16.0, that's what makes the buttons bigger

A simple solution is using the size variable as the height and the black line is gone

I'd like to know what you guys think

Test file: text_bounds_bug.rs.txt

What is the expected behavior?

text_bounds_fixed

Version

master

Operative System

macOS

Do you have any log output?

No response

manokara commented 1 year ago

I've had a similar problem while trying to implement a hex viewer widget (https://github.com/manokara/iced_widgets/issues/1). Looking back, I was overengineering the rendering of the rows by splitting each row into batches of highlighted and non highlighted text primitives (code), which was causing misaligned pairs as you can see in the GIF there. It could be easily solved by using two text primitives overlayed on top of each other with the appropriate blank space for highlighted and non-highlighted pairs. But on the other hand, if I were to give the option for the user to choose a font and they chose a non-monospace one, it would probably look weird again.

I remember bringing this up on Zulip around that time to and I think we agreed on it it as a "wontfix, for now at least". Could we bring that discussion up again now that iced is a little bit more mature, @hecrj?