Improved performance of children ancestors

This commit is contained in:
alonso.torres
2025-10-20 15:41:17 +02:00
parent 17fefcf0bc
commit 9d7cac5e73
2 changed files with 57 additions and 15 deletions

View File

@@ -22,7 +22,8 @@ pub use surfaces::{SurfaceId, Surfaces};
use crate::performance; use crate::performance;
use crate::shapes::{ use crate::shapes::{
Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor, Stroke, StructureEntry, Type, all_with_ancestors, Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor, Stroke,
StructureEntry, Type,
}; };
use crate::state::ShapesPool; use crate::state::ShapesPool;
use crate::tiles::{self, PendingTiles, TileRect}; use crate::tiles::{self, PendingTiles, TileRect};
@@ -1819,20 +1820,8 @@ impl RenderState {
tree: &mut ShapesPool, tree: &mut ShapesPool,
modifiers: &HashMap<Uuid, Matrix>, modifiers: &HashMap<Uuid, Matrix>,
) { ) {
let mut ancestors = IndexSet::new(); let ids: Vec<_> = modifiers.keys().collect();
for (uuid, matrix) in modifiers { let ancestors = all_with_ancestors(&ids, tree, false);
let mut shape = {
let Some(shape) = tree.get(uuid) else {
panic!("Invalid current shape")
};
let shape: Cow<Shape> = Cow::Borrowed(shape);
shape
};
shape.to_mut().apply_transform(matrix);
ancestors.insert(*uuid);
ancestors.extend(shape.all_ancestors(tree, false));
}
self.invalidate_and_update_tiles(&ancestors, tree, modifiers); self.invalidate_and_update_tiles(&ancestors, tree, modifiers);
} }

View File

@@ -182,6 +182,59 @@ pub struct Shape {
pub extrect: OnceCell<math::Rect>, pub extrect: OnceCell<math::Rect>,
} }
// Returns all ancestor shapes of this shape, traversing up the parent hierarchy
//
// This function walks up the parent chain starting from this shape's parent,
// collecting all ancestor IDs. It stops when it reaches a nil UUID or when
// an ancestor is hidden (unless include_hidden is true).
//
// # Arguments
// * `shapes` - The shapes pool containing all shapes
// * `include_hidden` - Whether to include hidden ancestors in the result
//
// # Returns
// A set of ancestor UUIDs in traversal order (closest ancestor first)
pub fn all_with_ancestors(
shapes: &[&Uuid],
shapes_pool: &ShapesPool,
include_hidden: bool,
) -> IndexSet<Uuid> {
let mut pending = Vec::from(shapes);
let mut result = IndexSet::new();
while !pending.is_empty() {
let Some(current_id) = pending.pop() else {
break;
};
result.insert(*current_id);
let Some(parent_id) = shapes_pool.get(current_id).and_then(|s| s.parent_id) else {
continue;
};
if parent_id == Uuid::nil() {
continue;
}
if result.contains(&parent_id) {
continue;
}
// Check if the ancestor is hidden
let Some(parent) = shapes_pool.get(&parent_id) else {
continue;
};
if !include_hidden && parent.hidden() {
continue;
}
pending.push(&parent.id);
}
result
}
impl Shape { impl Shape {
pub fn new(id: Uuid) -> Self { pub fn new(id: Uuid) -> Self {
Self { Self {