Skip to content

Commit 8fe4ff3

Browse files
committed
skia: Fix rendering of children outside a layer's intrinsic bounding rect
The layer clips (by being a texture), so we must make sure to size it beyond its intrinsic size and include the bounding rect of the children, in size **and** position. cc #9808
1 parent 95bc34e commit 8fe4ff3

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

internal/renderers/skia/itemrenderer.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub struct SkiaItemRenderer<'a> {
3939
state_stack: Vec<RenderState>,
4040
current_state: RenderState,
4141
image_cache: &'a ItemCache<Option<skia_safe::Image>>,
42+
layer_cache: &'a ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Image)>>,
4243
path_cache: &'a ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Path)>>,
4344
box_shadow_cache: &'a mut SkiaBoxShadowCache,
4445
}
@@ -49,6 +50,7 @@ impl<'a> SkiaItemRenderer<'a> {
4950
window: &'a i_slint_core::api::Window,
5051
surface: Option<&'a dyn crate::Surface>,
5152
image_cache: &'a ItemCache<Option<skia_safe::Image>>,
53+
layer_cache: &'a ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Image)>>,
5254
path_cache: &'a ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Path)>>,
5355
box_shadow_cache: &'a mut SkiaBoxShadowCache,
5456
) -> Self {
@@ -60,6 +62,7 @@ impl<'a> SkiaItemRenderer<'a> {
6062
state_stack: vec![],
6163
current_state: RenderState { alpha: 1.0, translation: Default::default() },
6264
image_cache,
65+
layer_cache,
6366
path_cache,
6467
box_shadow_cache,
6568
}
@@ -321,7 +324,7 @@ impl<'a> SkiaItemRenderer<'a> {
321324

322325
fn render_and_blend_layer(&mut self, item_rc: &ItemRc) -> RenderingResult {
323326
let current_clip = self.get_current_clip();
324-
if let Some(layer_image) = self.render_layer(item_rc, &|| {
327+
if let Some((layer_offset, layer_image)) = self.render_layer(item_rc, &|| {
325328
// We don't need to include the size of the "layer" item itself, since it has no content.
326329
let children_rect = i_slint_core::properties::evaluate_no_tracking(|| {
327330
item_rc.geometry().union(
@@ -332,9 +335,10 @@ impl<'a> SkiaItemRenderer<'a> {
332335
),
333336
)
334337
});
335-
children_rect.size_length()
338+
children_rect
336339
}) {
337340
let _saved_canvas = self.pixel_align_origin();
341+
self.canvas.translate(skia_safe::Vector::from((layer_offset.x, layer_offset.y)));
338342
self.canvas.draw_image_with_sampling_options(
339343
layer_image,
340344
skia_safe::Point::default(),
@@ -348,10 +352,12 @@ impl<'a> SkiaItemRenderer<'a> {
348352
fn render_layer(
349353
&mut self,
350354
item_rc: &ItemRc,
351-
layer_logical_size_fn: &dyn Fn() -> LogicalSize,
352-
) -> Option<skia_safe::Image> {
353-
self.image_cache.get_or_update_cache_entry(item_rc, || {
354-
let layer_size = layer_logical_size_fn() * self.scale_factor;
355+
layer_bounding_rect_fn: &dyn Fn() -> LogicalRect,
356+
) -> Option<(Vector2D<f32, PhysicalPx>, skia_safe::Image)> {
357+
self.layer_cache.get_or_update_cache_entry(item_rc, || {
358+
let bounding_rect = layer_bounding_rect_fn();
359+
let physical_origin = bounding_rect.origin * self.scale_factor;
360+
let layer_size = bounding_rect.size * self.scale_factor;
355361

356362
let image_info = skia_safe::ImageInfo::new(
357363
to_skia_size(&layer_size).to_ceil(),
@@ -368,9 +374,11 @@ impl<'a> SkiaItemRenderer<'a> {
368374
self.window,
369375
self.surface,
370376
self.image_cache,
377+
self.layer_cache,
371378
self.path_cache,
372379
self.box_shadow_cache,
373380
);
381+
sub_renderer.translate(-bounding_rect.origin.to_vector());
374382

375383
i_slint_core::item_rendering::render_item_children(
376384
&mut sub_renderer,
@@ -379,7 +387,7 @@ impl<'a> SkiaItemRenderer<'a> {
379387
&WindowInner::from_pub(self.window).window_adapter(),
380388
);
381389

382-
Some(surface.image_snapshot())
390+
Some((physical_origin.to_vector(), surface.image_snapshot()))
383391
})
384392
}
385393

internal/renderers/skia/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ pub struct SkiaRenderer {
161161
maybe_window_adapter: RefCell<Option<Weak<dyn WindowAdapter>>>,
162162
rendering_notifier: RefCell<Option<Box<dyn RenderingNotifier>>>,
163163
image_cache: ItemCache<Option<skia_safe::Image>>,
164+
layer_cache: ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Image)>>,
164165
path_cache: ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Path)>>,
165166
rendering_metrics_collector: RefCell<Option<Rc<RenderingMetricsCollector>>>,
166167
rendering_first_time: Cell<bool>,
@@ -186,6 +187,7 @@ impl SkiaRenderer {
186187
maybe_window_adapter: Default::default(),
187188
rendering_notifier: Default::default(),
188189
image_cache: Default::default(),
190+
layer_cache: Default::default(),
189191
path_cache: Default::default(),
190192
rendering_metrics_collector: Default::default(),
191193
rendering_first_time: Default::default(),
@@ -206,6 +208,7 @@ impl SkiaRenderer {
206208
maybe_window_adapter: Default::default(),
207209
rendering_notifier: Default::default(),
208210
image_cache: Default::default(),
211+
layer_cache: Default::default(),
209212
path_cache: Default::default(),
210213
rendering_metrics_collector: Default::default(),
211214
rendering_first_time: Default::default(),
@@ -239,6 +242,7 @@ impl SkiaRenderer {
239242
maybe_window_adapter: Default::default(),
240243
rendering_notifier: Default::default(),
241244
image_cache: Default::default(),
245+
layer_cache: Default::default(),
242246
path_cache: Default::default(),
243247
rendering_metrics_collector: Default::default(),
244248
rendering_first_time: Default::default(),
@@ -272,6 +276,7 @@ impl SkiaRenderer {
272276
maybe_window_adapter: Default::default(),
273277
rendering_notifier: Default::default(),
274278
image_cache: Default::default(),
279+
layer_cache: Default::default(),
275280
path_cache: Default::default(),
276281
rendering_metrics_collector: Default::default(),
277282
rendering_first_time: Default::default(),
@@ -404,6 +409,7 @@ impl SkiaRenderer {
404409
maybe_window_adapter: Default::default(),
405410
rendering_notifier: Default::default(),
406411
image_cache: Default::default(),
412+
layer_cache: Default::default(),
407413
path_cache: Default::default(),
408414
rendering_metrics_collector: Default::default(),
409415
rendering_first_time: Default::default(),
@@ -453,6 +459,7 @@ impl SkiaRenderer {
453459
maybe_window_adapter: Default::default(),
454460
rendering_notifier: Default::default(),
455461
image_cache: Default::default(),
462+
layer_cache: Default::default(),
456463
path_cache: Default::default(),
457464
rendering_metrics_collector: Default::default(),
458465
rendering_first_time: Cell::new(true),
@@ -648,6 +655,7 @@ impl SkiaRenderer {
648655
window,
649656
surface,
650657
&self.image_cache,
658+
&self.layer_cache,
651659
&self.path_cache,
652660
&mut box_shadow_cache,
653661
);

0 commit comments

Comments
 (0)