Align Container and debug borders to pixels.#669
Conversation
|
Awesome, this is 100% welcome and important. There are a few places where I've done this manually (mostly in runebender I guess?) and I haven't written it up anywhere. Would be good to have this be in the docs somewhere... |
|
and also 100% layouts should be on the grid. Maybe the simplest option would be to |
|
I think Solving this in some more generic way like |
|
Noted about ceil. That pr would be welcome in kurbo. |
a75fdf9 to
33dacdc
Compare
|
Okay so the kurbo changes have been merged and I'll try to tackle some of the future work (i.e. fix this issue more broadly and document it better) later this week. I'd prefer to do that in separate PRs. So I'd like to move forward with merging these changes here. Let me know if anything needs adjusting. |
|
looking now. |
cmyr
left a comment
There was a problem hiding this comment.
okay a couple notes but nothing blocking. I'm going to add you as a collaborator and you can merge this when you're satisfied.
druid/src/core.rs
Outdated
| let rect = Rect::from_origin_size( | ||
| (BORDER_MIDPOINT, BORDER_MIDPOINT), | ||
| (size.width - BORDER_WIDTH, size.height - BORDER_WIDTH), | ||
| ); |
There was a problem hiding this comment.
another way to think about this is in terms of insets:
const BORDER_WIDTH: f64 = 1.0;
let bounds = ctx.size().to_rect();
let stroke_inset = Insets::uniform(BORDER_WIDTH / 2.0);
let stroke_rect = rect.inset(stroke_inset);
// can also just write rect.inset(BORDER_WIDTH / 2.0) for uniform insetsThere was a problem hiding this comment.
The inset helper methods are definitely helpful and made the code more concise. In this case the insets do have to be negative though, to shrink the rect.
druid/src/widget/container.rs
Outdated
| self.corner_radius, | ||
| ); | ||
|
|
||
| if let Err(e) = paint_ctx.save() { |
There was a problem hiding this comment.
I really get annoyed by this api, will look into a helper method (this is unrelated to the current PR)
There was a problem hiding this comment.
Yeah the with_save method will reduce human failure chance.
druid/src/widget/container.rs
Outdated
| paint_ctx.clip(panel); | ||
|
|
||
| if let Some(background) = self.background.as_mut() { | ||
| let bg_rect = RoundedRect::from_origin_size( |
There was a problem hiding this comment.
my current preferred way to do this (until linebender/kurbo#92 merges) is paint_ctx.to_rect().to_rounded_rect(self.corner_radius); 😒
There was a problem hiding this comment.
Using the helper methods now!
|
I did some additional testing and found that |
How stroke works
The coordinates provided to stroke are fully respected and not rounded to an integer. Furthermore the stroke is positioned exactly on top of the provided coordinates. This means that if you draw a 1px wide line at pixel boundaries, 0.5px of the line width will be on one side pixel and the other 0.5px on the other side. Of course the pixel is usually the smallest unit a display has, so the 1px line ends up looking like a 2px line, although usually alpha blended. The solution is to specify the midpoint of a pixel instead, i.e. if you want the line to appear on the 2nd pixel row you specify 1.5 as the point.
Steps towards improving druid
This PR changes the way the
Containerwidget border and the debug borders are drawn. In both cases they are drawn inwards, i.e. within the widget size, with pixel accuracy.This PR also moves the
Containerborder drawing after the background drawing so that you can have both active at the same time.Real life example (400% zoom)
Future work
Labeland probably everything that usesLabel's layout in calculations of its own layout, e.g.Button.