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 {
|
pub fn bounds(&self) -> Bounds {
|
||||||
*self.bounds
|
*self.bounds.get_or_init(|| self.calculate_bounds())
|
||||||
.get_or_init(|| self.calculate_bounds())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selrect(&self) -> math::Rect {
|
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(
|
pub fn all_children(
|
||||||
&self,
|
&self,
|
||||||
shapes: &ShapesPool,
|
shapes: &ShapesPool,
|
||||||
@@ -1259,6 +1276,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> {
|
pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> {
|
||||||
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();
|
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ fn propagate_children(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: PERFORMANCE
|
|
||||||
fn calculate_group_bounds(
|
fn calculate_group_bounds(
|
||||||
shape: &Shape,
|
shape: &Shape,
|
||||||
shapes: &ShapesPool,
|
shapes: &ShapesPool,
|
||||||
@@ -98,16 +97,14 @@ fn calculate_group_bounds(
|
|||||||
let shape_bounds = bounds.find(shape);
|
let shape_bounds = bounds.find(shape);
|
||||||
let mut result = Vec::<Point>::new();
|
let mut result = Vec::<Point>::new();
|
||||||
|
|
||||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
for child_id in shape.modified_children_ids_iter(structure.get(&shape.id), true) {
|
||||||
for child_id in children_ids.iter() {
|
let Some(child) = shapes.get(&child_id) else {
|
||||||
let Some(child) = shapes.get(child_id) else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let child_bounds = bounds.find(child);
|
let child_bounds = bounds.find(child);
|
||||||
result.append(&mut child_bounds.points());
|
result.append(&mut child_bounds.points());
|
||||||
}
|
}
|
||||||
|
|
||||||
shape_bounds.with_points(result)
|
shape_bounds.with_points(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,30 +274,32 @@ fn propagate_reflow(
|
|||||||
let shapes = &state.shapes;
|
let shapes = &state.shapes;
|
||||||
let mut reflow_parent = false;
|
let mut reflow_parent = false;
|
||||||
|
|
||||||
|
if reflown.contains(&id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match &shape.shape_type {
|
match &shape.shape_type {
|
||||||
Type::Frame(Frame {
|
Type::Frame(Frame {
|
||||||
layout: Some(_), ..
|
layout: Some(_), ..
|
||||||
}) => {
|
}) => {
|
||||||
if !reflown.contains(id) {
|
let mut skip_reflow = false;
|
||||||
let mut skip_reflow = false;
|
if shape.is_layout_horizontal_fill() || shape.is_layout_vertical_fill() {
|
||||||
if shape.is_layout_horizontal_fill() || shape.is_layout_vertical_fill() {
|
if let Some(parent_id) = shape.parent_id {
|
||||||
if let Some(parent_id) = shape.parent_id {
|
if !reflown.contains(&parent_id) {
|
||||||
if !reflown.contains(&parent_id) {
|
// If this is a fill layout but the parent has not been reflown yet
|
||||||
// If this is a fill layout but the parent has not been reflown yet
|
// we wait for the next iteration for reflow
|
||||||
// we wait for the next iteration for reflow
|
skip_reflow = true;
|
||||||
skip_reflow = true;
|
reflow_parent = true;
|
||||||
reflow_parent = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if shape.is_layout_vertical_auto() || shape.is_layout_horizontal_auto() {
|
if shape.is_layout_vertical_auto() || shape.is_layout_horizontal_auto() {
|
||||||
reflow_parent = true;
|
reflow_parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !skip_reflow {
|
if !skip_reflow {
|
||||||
layout_reflows.push(*id);
|
layout_reflows.push(*id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Group(Group { masked: true }) => {
|
Type::Group(Group { masked: true }) => {
|
||||||
@@ -310,6 +309,7 @@ fn propagate_reflow(
|
|||||||
bounds.insert(shape.id, child_bounds);
|
bounds.insert(shape.id, child_bounds);
|
||||||
reflow_parent = true;
|
reflow_parent = true;
|
||||||
}
|
}
|
||||||
|
reflown.insert(*id);
|
||||||
}
|
}
|
||||||
Type::Group(_) => {
|
Type::Group(_) => {
|
||||||
if let Some(shape_bounds) =
|
if let Some(shape_bounds) =
|
||||||
@@ -318,6 +318,7 @@ fn propagate_reflow(
|
|||||||
bounds.insert(shape.id, shape_bounds);
|
bounds.insert(shape.id, shape_bounds);
|
||||||
reflow_parent = true;
|
reflow_parent = true;
|
||||||
}
|
}
|
||||||
|
reflown.insert(*id);
|
||||||
}
|
}
|
||||||
Type::Bool(_) => {
|
Type::Bool(_) => {
|
||||||
if let Some(shape_bounds) =
|
if let Some(shape_bounds) =
|
||||||
@@ -326,6 +327,7 @@ fn propagate_reflow(
|
|||||||
bounds.insert(shape.id, shape_bounds);
|
bounds.insert(shape.id, shape_bounds);
|
||||||
reflow_parent = true;
|
reflow_parent = true;
|
||||||
}
|
}
|
||||||
|
reflown.insert(*id);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Other shapes don't have to be reflown
|
// Other shapes don't have to be reflown
|
||||||
|
|||||||
Reference in New Issue
Block a user