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::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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user