mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
✨ Improve performance of group bounds
This commit is contained in:
@@ -719,8 +719,7 @@ impl Shape {
|
||||
}
|
||||
|
||||
pub fn bounds(&self) -> Bounds {
|
||||
*self.bounds
|
||||
.get_or_init(|| self.calculate_bounds())
|
||||
*self.bounds.get_or_init(|| self.calculate_bounds())
|
||||
}
|
||||
|
||||
pub fn selrect(&self) -> math::Rect {
|
||||
@@ -947,6 +946,24 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn children_ids_iter(&self, include_hidden: bool) -> Box<dyn Iterator<Item = &Uuid> + '_> {
|
||||
if include_hidden {
|
||||
return Box::new(self.children.iter().rev());
|
||||
}
|
||||
|
||||
if let Type::Bool(_) = self.shape_type {
|
||||
Box::new([].iter())
|
||||
} else if let Type::Group(group) = self.shape_type {
|
||||
if group.masked {
|
||||
Box::new(self.children.iter().rev().take(self.children.len() - 1))
|
||||
} else {
|
||||
Box::new(self.children.iter().rev())
|
||||
}
|
||||
} else {
|
||||
Box::new(self.children.iter().rev())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_children(
|
||||
&self,
|
||||
shapes: &ShapesPool,
|
||||
@@ -1257,6 +1274,36 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modified_children_ids_iter<'a>(
|
||||
&'a self,
|
||||
structure: Option<&'a Vec<StructureEntry>>,
|
||||
include_hidden: bool,
|
||||
) -> Box<dyn Iterator<Item = Cow<'a, Uuid>> + 'a> {
|
||||
if let Some(structure) = structure {
|
||||
let mut result: Vec<Cow<'a, Uuid>> = self
|
||||
.children_ids_iter(include_hidden)
|
||||
.map(Cow::Borrowed)
|
||||
.collect();
|
||||
let mut to_remove = HashSet::<Cow<'a, Uuid>>::new();
|
||||
|
||||
for st in structure {
|
||||
match st.entry_type {
|
||||
StructureEntryType::AddChild => {
|
||||
result.insert(result.len() - st.index as usize, Cow::Owned(st.id));
|
||||
}
|
||||
StructureEntryType::RemoveChild => {
|
||||
to_remove.insert(Cow::Owned(st.id));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(result.into_iter().filter(move |id| !to_remove.contains(id)))
|
||||
} else {
|
||||
Box::new(self.children_ids_iter(include_hidden).map(Cow::Borrowed))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> {
|
||||
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ fn propagate_children(
|
||||
result
|
||||
}
|
||||
|
||||
// FIXME: PERFORMANCE
|
||||
fn calculate_group_bounds(
|
||||
shape: &Shape,
|
||||
shapes: &ShapesPool,
|
||||
@@ -98,16 +97,14 @@ fn calculate_group_bounds(
|
||||
let shape_bounds = bounds.find(shape);
|
||||
let mut result = Vec::<Point>::new();
|
||||
|
||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
for child_id in children_ids.iter() {
|
||||
let Some(child) = shapes.get(child_id) else {
|
||||
for child_id in shape.modified_children_ids_iter(structure.get(&shape.id), true) {
|
||||
let Some(child) = shapes.get(&child_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let child_bounds = bounds.find(child);
|
||||
result.append(&mut child_bounds.points());
|
||||
}
|
||||
|
||||
shape_bounds.with_points(result)
|
||||
}
|
||||
|
||||
@@ -277,30 +274,32 @@ fn propagate_reflow(
|
||||
let shapes = &state.shapes;
|
||||
let mut reflow_parent = false;
|
||||
|
||||
if reflown.contains(&id) {
|
||||
return;
|
||||
}
|
||||
|
||||
match &shape.shape_type {
|
||||
Type::Frame(Frame {
|
||||
layout: Some(_), ..
|
||||
}) => {
|
||||
if !reflown.contains(id) {
|
||||
let mut skip_reflow = false;
|
||||
if shape.is_layout_horizontal_fill() || shape.is_layout_vertical_fill() {
|
||||
if let Some(parent_id) = shape.parent_id {
|
||||
if !reflown.contains(&parent_id) {
|
||||
// If this is a fill layout but the parent has not been reflown yet
|
||||
// we wait for the next iteration for reflow
|
||||
skip_reflow = true;
|
||||
reflow_parent = true;
|
||||
}
|
||||
let mut skip_reflow = false;
|
||||
if shape.is_layout_horizontal_fill() || shape.is_layout_vertical_fill() {
|
||||
if let Some(parent_id) = shape.parent_id {
|
||||
if !reflown.contains(&parent_id) {
|
||||
// If this is a fill layout but the parent has not been reflown yet
|
||||
// we wait for the next iteration for reflow
|
||||
skip_reflow = true;
|
||||
reflow_parent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if shape.is_layout_vertical_auto() || shape.is_layout_horizontal_auto() {
|
||||
reflow_parent = true;
|
||||
}
|
||||
if shape.is_layout_vertical_auto() || shape.is_layout_horizontal_auto() {
|
||||
reflow_parent = true;
|
||||
}
|
||||
|
||||
if !skip_reflow {
|
||||
layout_reflows.push(*id);
|
||||
}
|
||||
if !skip_reflow {
|
||||
layout_reflows.push(*id);
|
||||
}
|
||||
}
|
||||
Type::Group(Group { masked: true }) => {
|
||||
@@ -310,6 +309,7 @@ fn propagate_reflow(
|
||||
bounds.insert(shape.id, child_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
reflown.insert(*id);
|
||||
}
|
||||
Type::Group(_) => {
|
||||
if let Some(shape_bounds) =
|
||||
@@ -318,6 +318,7 @@ fn propagate_reflow(
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
reflown.insert(*id);
|
||||
}
|
||||
Type::Bool(_) => {
|
||||
if let Some(shape_bounds) =
|
||||
@@ -326,6 +327,7 @@ fn propagate_reflow(
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
reflown.insert(*id);
|
||||
}
|
||||
_ => {
|
||||
// Other shapes don't have to be reflown
|
||||
|
||||
Reference in New Issue
Block a user