diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index 654908ceeb..abe050e16e 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -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 + '_> { + 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, @@ -1259,6 +1276,36 @@ impl Shape { } } + pub fn modified_children_ids_iter<'a>( + &'a self, + structure: Option<&'a Vec>, + include_hidden: bool, + ) -> Box> + 'a> { + if let Some(structure) = structure { + let mut result: Vec> = self + .children_ids_iter(include_hidden) + .map(Cow::Borrowed) + .collect(); + let mut to_remove = HashSet::>::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 { let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect(); diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index 6dafb1c202..c8411621e1 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -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::::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