mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
✨ Improved performance of children ancestors
This commit is contained in:
@@ -22,7 +22,8 @@ pub use surfaces::{SurfaceId, Surfaces};
|
||||
|
||||
use crate::performance;
|
||||
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::tiles::{self, PendingTiles, TileRect};
|
||||
@@ -1819,20 +1820,8 @@ impl RenderState {
|
||||
tree: &mut ShapesPool,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
) {
|
||||
let mut ancestors = IndexSet::new();
|
||||
for (uuid, matrix) in modifiers {
|
||||
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));
|
||||
}
|
||||
let ids: Vec<_> = modifiers.keys().collect();
|
||||
let ancestors = all_with_ancestors(&ids, tree, false);
|
||||
self.invalidate_and_update_tiles(&ancestors, tree, modifiers);
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,59 @@ pub struct Shape {
|
||||
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 {
|
||||
pub fn new(id: Uuid) -> Self {
|
||||
Self {
|
||||
|
||||
Reference in New Issue
Block a user