From 2ea230c6fdb8902487b0127a9b4a24e005f115ea Mon Sep 17 00:00:00 2001 From: Tashcan Date: Sat, 21 Dec 2024 22:18:09 -0800 Subject: [PATCH] =?UTF-8?q?refactor(core):=20=F0=9F=92=A1=20skip=20paint?= =?UTF-8?q?=20for=20out=20of=20bounds=20widgets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + core/src/widget_tree/widget_id.rs | 35 ++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10ae73c6d..3aac7286c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he ### Changed - **core**: Optimize QueryId::is_same by not creating a String using format for every comparison (#678 @tashcan) +- **core**: Skip paint for out of bounds widgets (#677 @tashcan) ## [0.4.0-alpha.19] - 2024-12-18 diff --git a/core/src/widget_tree/widget_id.rs b/core/src/widget_tree/widget_id.rs index 4a4eb55de..1257dd6ea 100644 --- a/core/src/widget_tree/widget_id.rs +++ b/core/src/widget_tree/widget_id.rs @@ -1,5 +1,6 @@ use std::{convert::Infallible, rc::Rc}; +use ahash::HashSetExt; use indextree::{Node, NodeId}; use rxrust::ops::box_it::CloneableBoxOp; use smallvec::smallvec; @@ -289,21 +290,38 @@ impl WidgetId { pub(crate) fn paint_subtree(self, ctx: &mut PaintingCtx) { let mut w = Some(self); + + let wnd = ctx.window(); + let tree = wnd.tree(); + + let mut did_paint = HashSet::::new(); while let Some(id) = w { ctx.id = id; - ctx.painter.save(); - let wnd = ctx.window(); - let tree = wnd.tree(); let mut need_paint = false; if ctx.painter.alpha() != 0. { if let Some(layout_box) = ctx.box_rect() { - let render = id.assert_get(tree); + let transform = *ctx.painter.transform(); ctx .painter .translate(layout_box.min_x(), layout_box.min_y()); - render.paint(ctx); - need_paint = true; + if ctx + .painter() + .intersection_paint_bounds(&Rect::from_size(layout_box.size)) + .is_some() + { + let render = id.assert_get(tree); + ctx.painter.set_transform(transform); + ctx.painter.save(); + ctx + .painter + .translate(layout_box.min_x(), layout_box.min_y()); + render.paint(ctx); + did_paint.insert(id); + need_paint = true; + } else { + ctx.painter.set_transform(transform); + } } } @@ -314,7 +332,10 @@ impl WidgetId { let mut node = w; while let Some(p) = node { // self node sub-tree paint finished, goto sibling - ctx.painter.restore(); + if did_paint.contains(&p) { + did_paint.remove(&p); + ctx.painter.restore(); + } node = p.next_sibling(tree); if node.is_some() { break;