Skip to content

Fix use of bounding_rect to calculate the bounds of an item#11252

Merged
ogoffart merged 23 commits into
slint-ui:masterfrom
eira-fransham:10277-text-image-buffer-overwrite
Apr 13, 2026
Merged

Fix use of bounding_rect to calculate the bounds of an item#11252
ogoffart merged 23 commits into
slint-ui:masterfrom
eira-fransham:10277-text-image-buffer-overwrite

Conversation

@eira-fransham
Copy link
Copy Markdown
Contributor

@eira-fransham eira-fransham commented Apr 2, 2026

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_rect calculations (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.

@eira-fransham eira-fransham force-pushed the 10277-text-image-buffer-overwrite branch from 7c182bc to 9118d77 Compare April 7, 2026 09:23
@eira-fransham eira-fransham changed the title WIP: Hack Skia and FemtoVG backends to force usage of the partial renderer Partial revert of #10601 to fix incorrect rendering when not using partial renderer Apr 7, 2026
@eira-fransham eira-fransham marked this pull request as ready for review April 7, 2026 09:26
@eira-fransham eira-fransham requested a review from ogoffart April 7, 2026 09:26
@eira-fransham eira-fransham force-pushed the 10277-text-image-buffer-overwrite branch from 24d0087 to d9cd5af Compare April 7, 2026 10:58
@ogoffart

This comment was marked as outdated.

@eira-fransham eira-fransham changed the title Partial revert of #10601 to fix incorrect rendering when not using partial renderer Fix use of bounding_rect to calculate the bounds of an item Apr 7, 2026
Comment thread internal/core/item_rendering.rs Outdated
Comment thread internal/core/item_rendering.rs Outdated
Comment thread internal/core/item_rendering.rs Outdated
@eira-fransham eira-fransham requested a review from ogoffart April 8, 2026 07:39
Comment thread internal/core/item_rendering.rs Outdated
Comment thread internal/core/item_rendering.rs Outdated
@eira-fransham eira-fransham requested a review from ogoffart April 8, 2026 10:09
@eira-fransham
Copy link
Copy Markdown
Contributor Author

eira-fransham commented Apr 8, 2026

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).

Before

Skia

2026-04-08.11-42-17.mp4

FemtoVG

2026-04-08.11-42-57.mp4

After

Skia

2026-04-08.11-43-54.mp4

FemtoVG

2026-04-08.12-15-13.mp4

Comment thread internal/renderers/skia/itemrenderer.rs
Comment thread internal/core/item_rendering.rs Outdated
Comment thread internal/renderers/femtovg/itemrenderer.rs Outdated
Comment thread internal/renderers/skia/itemrenderer.rs
@eira-fransham eira-fransham requested a review from ogoffart April 8, 2026 12:36
@eira-fransham eira-fransham force-pushed the 10277-text-image-buffer-overwrite branch from a88b6eb to c224554 Compare April 8, 2026 14:13
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho this comment was correct and calling the function item_children_bounding_rect without the with should be done.

Comment thread internal/renderers/skia/itemrenderer.rs Outdated
item_rc,
&window_adapter,
)
.intersection(&current_clip)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@eira-fransham eira-fransham requested a review from ogoffart April 9, 2026 09:57
Copy link
Copy Markdown
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I see the folowing changes in this patch:

  1. we no longer do the union with item_rc.geometry() in the intersection call
  2. 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.
  3. 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?

Comment thread internal/renderers/skia/itemrenderer.rs Outdated
i_slint_core::properties::evaluate_no_tracking(|| {
i_slint_core::item_rendering::item_children_bounding_rect(item_rc, &window_adapter)
.intersection(&current_clip.union(&item_rc.geometry()))
.intersection(&current_clip)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove the .union(&item_rc.geometry()) . Is that fixing a problem, which one?

Copy link
Copy Markdown
Contributor Author

@eira-fransham eira-fransham Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

@eira-fransham eira-fransham Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can put back this comment then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already done, sorry I hadn't pushed yet because I've been setting up my linux laptop

Comment thread internal/renderers/skia/itemrenderer.rs Outdated
i_slint_core::properties::evaluate_no_tracking(|| {
i_slint_core::item_rendering::item_children_bounding_rect(item_rc, &window_adapter)
.intersection(&current_clip.union(&item_rc.geometry()))
.intersection(&current_clip)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you can also revert all the changes in this file.

@ogoffart
Copy link
Copy Markdown
Member

ogoffart commented Apr 9, 2026

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.

@eira-fransham
Copy link
Copy Markdown
Contributor Author

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

@ogoffart ogoffart modified the milestone: 1.16 Apr 9, 2026
Comment thread internal/core/item_rendering.rs Outdated
renderer.restore_state();
}

fn item_with_children_bounding_rect_transformed(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@eira-fransham eira-fransham requested a review from ogoffart April 13, 2026 09:31
Comment on lines +7 to +8
// Software renderer uses i16 physical coordinates and has no layer cache.
//ignore: software
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +28 to +31
Text {
text: "foo";
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

@eira-fransham eira-fransham Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should that not be true?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Copy Markdown
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash and merge

@ogoffart ogoffart merged commit d5d450c into slint-ui:master Apr 13, 2026
89 of 91 checks passed
@ogoffart
Copy link
Copy Markdown
Member

merged so it can be in the nightly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The first time you open the doors of the home-automation demo half the UI has not rendered

2 participants