Fix use of bounding_rect to calculate the bounds of an item#11252
Conversation
7c182bc to
9118d77
Compare
24d0087 to
d9cd5af
Compare
This comment was marked as outdated.
This comment was marked as outdated.
bounding_rect to calculate the bounds of an item
|
Ok so with the latest fixes this now appears to be correct without regressions. There seems to be an issue that this PR partially mitigates but does not solve, where FemtoVG appears to incorrectly render when there are multiple sibling layers. From testing, though, this does not seem to be a regression and we should open a new ticket for it (if one does not already exist). BeforeSkia2026-04-08.11-42-17.mp4FemtoVG2026-04-08.11-42-57.mp4AfterSkia2026-04-08.11-43-54.mp4FemtoVG2026-04-08.12-15-13.mp4 |
…n_bounding_rect_inner`
…e inner geometry rather than iteratively
…ot the bounding rectangle
a88b6eb to
c224554
Compare
| let window_adapter = self.window().window_adapter(); | ||
| let current_clip = self.get_current_clip(); | ||
| if let Some((layer_offset, layer_image)) = self.render_layer(item_rc, &|| { | ||
| // We don't need to include the size of the "layer" item itself, since it has no content. |
There was a problem hiding this comment.
imho this comment was correct and calling the function item_children_bounding_rect without the with should be done.
| item_rc, | ||
| &window_adapter, | ||
| ) | ||
| .intersection(¤t_clip) |
There was a problem hiding this comment.
This will regress the original #10277 , the bug there is that if you close the door when the window is resized to be small, then resize the window to be bigger, then open the door, you have glishes.
ogoffart
left a comment
There was a problem hiding this comment.
So I see the folowing changes in this patch:
- we no longer do the union with item_rc.geometry() in the intersection call
- The
if item.as_ref().clips_children()section is greatly simplified by returning the full geometry instead of trying to recurse in some cases only. - We translate the item by the geometry's origin instead of the bounding_rect's origin
The change 3 shouldn't have much impact because most item return the same origin as their geometry right now.
The change 2. might have had a bug before?
The change 1, as i said, i don't understand why it fixes the problem. Could you elaborate?
| i_slint_core::properties::evaluate_no_tracking(|| { | ||
| i_slint_core::item_rendering::item_children_bounding_rect(item_rc, &window_adapter) | ||
| .intersection(¤t_clip.union(&item_rc.geometry())) | ||
| .intersection(¤t_clip) |
There was a problem hiding this comment.
Why did you remove the .union(&item_rc.geometry()) . Is that fixing a problem, which one?
There was a problem hiding this comment.
I thought this was what actually ended up fixing the issue but I was wrong, re-adding this didn't actually break it again. I'll revert this change since it's not necessary for the fix.
There was a problem hiding this comment.
So yes, it looks like using item_geom.origin as the child transform instead of bounding.origin is the core fix. I definitely tried switching back and forth on that earlier and it didn't change, though, which I'm quite confused by. I think that the item_with_children_bounding_rect vs item_children_bounding_rect change was somehow covering up that fix when I was testing it earlier.
There was a problem hiding this comment.
Then you can also revert all the changes in this file.
| if let Some((layer_origin, layer_image)) = self.render_layer(item_rc, &|| { | ||
| // We don't need to include the size of the "layer" item itself, since it has no content. | ||
| // But intersect with the union of the clip with the geometry to make sure we don't | ||
| // render insanely large surface. |
There was a problem hiding this comment.
I think you can put back this comment then.
There was a problem hiding this comment.
Already done, sorry I hadn't pushed yet because I've been setting up my linux laptop
| i_slint_core::properties::evaluate_no_tracking(|| { | ||
| i_slint_core::item_rendering::item_children_bounding_rect(item_rc, &window_adapter) | ||
| .intersection(¤t_clip.union(&item_rc.geometry())) | ||
| .intersection(¤t_clip) |
There was a problem hiding this comment.
Then you can also revert all the changes in this file.
|
Is it possible to make a screenshot test like the one i added in tests/screenshots/cases/layer/cache-rendering-hint-large.slint ? It is probably possible to reproduce the bug with the right elements. |
I'll have a go, I haven't made a screenshot test yet but I think this should be easy to reproduce |
| renderer.restore_state(); | ||
| } | ||
|
|
||
| fn item_with_children_bounding_rect_transformed( |
There was a problem hiding this comment.
nitpick:
The order of these function is a bit strange:
fn foo_helper1
pub fn foo
fn foo_helper2
I'm thinking the item_with_children_bounding_rect_transformed could be moved after.
There was a problem hiding this comment.
Yeah that makes sense to me. I usually put helper functions before the function they help, and I guess whoever wrote the other helper prefers to put helpers after. Will change now.
There was a problem hiding this comment.
My preference is actually, if a function is only used as a helper in one other function, to put the definition inside the function (although I'll only nest that a maximum of once). In my opinion that's the best way to make the intentions of the function clear.
There was a problem hiding this comment.
I used to prefer putting them before, But rust analyzer prefers putting them later when refactoring code into function, or generating helper function, and that's why i changed my habits, but i don't have strong opinions.
| // Software renderer uses i16 physical coordinates and has no layer cache. | ||
| //ignore: software |
There was a problem hiding this comment.
There is nothing which can't be in a i16 in this testcase.
so i think you can keep the test active for the software renderer.
| Text { | ||
| text: "foo"; | ||
| } | ||
| } |
There was a problem hiding this comment.
Unfortunately, the skia screenshots with Text don't work as the text rendering is not consistant accross platforms. Can you use a simple image (can use data: url now) or a rectangle?
There was a problem hiding this comment.
I've had trouble recreating this bug with any element other than Text.
EDIT: Ok, with the other changes I made to the test-case, switching it back to Rectangle instead of Text will now still reproduce the bug
| background: white; | ||
|
|
||
| Rectangle { | ||
| cache-rendering-hint: false; |
|
merged so it can be in the nightly |
Closes #10277.
This fixes the issue reported in the issue above, and (to my understanding) should implement the correct behaviour. I believe that the issue is that by doing the
bounding_rectcalculations (which zero out width and height in some cases) as we go along, we were ignoring some rectangles that we should not be and therefore potentially ignoring some translations that are semantically important. By only zeroing them out at the end, we ensure that we take the origins of all item bounds into account.