mirror of
https://github.com/penpot/penpot.git
synced 2025-07-12 22:27:58 +02:00
♻️ Refactor modifiers methods
This commit is contained in:
parent
afec3b9bc1
commit
36b6f6323a
1 changed files with 215 additions and 180 deletions
|
@ -150,44 +150,21 @@ fn set_pixel_precision(transform: &mut Matrix, bounds: &mut Bounds) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn propagate_modifiers(
|
||||
state: &State,
|
||||
modifiers: &[TransformEntry],
|
||||
fn propagate_transform(
|
||||
entry: TransformEntry,
|
||||
pixel_precision: bool,
|
||||
) -> Vec<TransformEntry> {
|
||||
let shapes = &state.shapes;
|
||||
|
||||
let font_col = state.render_state.fonts.font_collection();
|
||||
let mut entries: VecDeque<_> = modifiers
|
||||
.iter()
|
||||
.map(|entry| Modifier::Transform(entry.clone()))
|
||||
.collect();
|
||||
|
||||
for id in state.structure.keys() {
|
||||
if id != &Uuid::nil() {
|
||||
entries.push_back(Modifier::Reflow(*id));
|
||||
}
|
||||
}
|
||||
|
||||
let mut modifiers = HashMap::<Uuid, Matrix>::new();
|
||||
let mut bounds = HashMap::<Uuid, Bounds>::new();
|
||||
|
||||
let mut reflown = HashSet::<Uuid>::new();
|
||||
let mut layout_reflows = Vec::<Uuid>::new();
|
||||
|
||||
// We first propagate the transforms to the children and then after
|
||||
// recalculate the layouts. The layout can create further transforms that
|
||||
// we need to re-propagate.
|
||||
// In order for loop to eventualy finish, we limit the flex reflow to just
|
||||
// one (the reflown set).
|
||||
while !entries.is_empty() {
|
||||
while let Some(modifier) = entries.pop_front() {
|
||||
match modifier {
|
||||
Modifier::Transform(entry) => {
|
||||
state: &State,
|
||||
entries: &mut VecDeque<Modifier>,
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
modifiers: &mut HashMap<Uuid, Matrix>,
|
||||
) {
|
||||
let Some(shape) = state.shapes.get(&entry.id) else {
|
||||
continue;
|
||||
return;
|
||||
};
|
||||
|
||||
let shapes = &state.shapes;
|
||||
let font_col = state.render_state.fonts.font_collection();
|
||||
|
||||
let shape_bounds_before = bounds.find(shape);
|
||||
let mut shape_bounds_after = shape_bounds_before.transform(&entry.transform);
|
||||
|
||||
|
@ -220,7 +197,7 @@ pub fn propagate_modifiers(
|
|||
&shape_bounds_before,
|
||||
&shape_bounds_after,
|
||||
transform,
|
||||
&bounds,
|
||||
bounds,
|
||||
&state.structure,
|
||||
&state.scale_content,
|
||||
);
|
||||
|
@ -244,22 +221,28 @@ pub fn propagate_modifiers(
|
|||
}
|
||||
}
|
||||
|
||||
Modifier::Reflow(id) => {
|
||||
let Some(shape) = state.shapes.get(&id) else {
|
||||
continue;
|
||||
fn propagate_reflow(
|
||||
id: &Uuid,
|
||||
state: &State,
|
||||
entries: &mut VecDeque<Modifier>,
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
layout_reflows: &mut Vec<Uuid>,
|
||||
reflown: &mut HashSet<Uuid>,
|
||||
) {
|
||||
let Some(shape) = state.shapes.get(id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let shapes = &state.shapes;
|
||||
let mut reflow_parent = false;
|
||||
|
||||
match &shape.shape_type {
|
||||
Type::Frame(Frame {
|
||||
layout: Some(_), ..
|
||||
}) => {
|
||||
if !reflown.contains(&id) {
|
||||
if !reflown.contains(id) {
|
||||
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 !reflown.contains(&parent_id) {
|
||||
// If this is a fill layout but the parent has not been reflown yet
|
||||
|
@ -270,20 +253,17 @@ pub fn propagate_modifiers(
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if !skip_reflow {
|
||||
layout_reflows.push(id);
|
||||
layout_reflows.push(*id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Type::Group(Group { masked: true }) => {
|
||||
let children_ids =
|
||||
modified_children_ids(shape, state.structure.get(&shape.id), true);
|
||||
let children_ids = modified_children_ids(shape, state.structure.get(&shape.id), true);
|
||||
if let Some(child) = shapes.get(&children_ids[0]) {
|
||||
let child_bounds = bounds.find(child);
|
||||
bounds.insert(shape.id, child_bounds);
|
||||
|
@ -292,7 +272,7 @@ pub fn propagate_modifiers(
|
|||
}
|
||||
Type::Group(_) => {
|
||||
if let Some(shape_bounds) =
|
||||
calculate_group_bounds(shape, shapes, &bounds, &state.structure)
|
||||
calculate_group_bounds(shape, shapes, bounds, &state.structure)
|
||||
{
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
|
@ -303,7 +283,7 @@ pub fn propagate_modifiers(
|
|||
// new path... impossible right now. I'm going to use for the moment the group
|
||||
// calculation
|
||||
if let Some(shape_bounds) =
|
||||
calculate_group_bounds(shape, shapes, &bounds, &state.structure)
|
||||
calculate_group_bounds(shape, shapes, bounds, &state.structure)
|
||||
{
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
|
@ -320,18 +300,20 @@ pub fn propagate_modifiers(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for id in layout_reflows.iter() {
|
||||
if reflown.contains(id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fn reflow_shape(
|
||||
id: &Uuid,
|
||||
state: &State,
|
||||
reflown: &mut HashSet<Uuid>,
|
||||
entries: &mut VecDeque<Modifier>,
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
) {
|
||||
let Some(shape) = state.shapes.get(id) else {
|
||||
continue;
|
||||
return;
|
||||
};
|
||||
|
||||
let shapes = &state.shapes;
|
||||
|
||||
let shape = if let Some(scale_content) = state.scale_content.get(id) {
|
||||
&shape.scale_content(*scale_content)
|
||||
} else {
|
||||
|
@ -339,7 +321,7 @@ pub fn propagate_modifiers(
|
|||
};
|
||||
|
||||
let Type::Frame(frame_data) = &shape.shape_type else {
|
||||
continue;
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(Layout::FlexLayout(layout_data, flex_data)) = &frame_data.layout {
|
||||
|
@ -348,25 +330,78 @@ pub fn propagate_modifiers(
|
|||
layout_data,
|
||||
flex_data,
|
||||
shapes,
|
||||
&mut bounds,
|
||||
bounds,
|
||||
&state.structure,
|
||||
);
|
||||
entries.append(&mut children);
|
||||
}
|
||||
|
||||
if let Some(Layout::GridLayout(layout_data, grid_data)) = &frame_data.layout {
|
||||
} else if let Some(Layout::GridLayout(layout_data, grid_data)) = &frame_data.layout {
|
||||
let mut children = grid_layout::reflow_grid_layout(
|
||||
shape,
|
||||
layout_data,
|
||||
grid_data,
|
||||
shapes,
|
||||
&mut bounds,
|
||||
bounds,
|
||||
&state.structure,
|
||||
);
|
||||
entries.append(&mut children);
|
||||
}
|
||||
reflown.insert(*id);
|
||||
}
|
||||
|
||||
pub fn propagate_modifiers(
|
||||
state: &State,
|
||||
modifiers: &[TransformEntry],
|
||||
pixel_precision: bool,
|
||||
) -> Vec<TransformEntry> {
|
||||
let mut entries: VecDeque<_> = modifiers
|
||||
.iter()
|
||||
.map(|entry| Modifier::Transform(entry.clone()))
|
||||
.collect();
|
||||
|
||||
for id in state.structure.keys() {
|
||||
if id != &Uuid::nil() {
|
||||
entries.push_back(Modifier::Reflow(*id));
|
||||
}
|
||||
}
|
||||
|
||||
let mut modifiers = HashMap::<Uuid, Matrix>::new();
|
||||
let mut bounds = HashMap::<Uuid, Bounds>::new();
|
||||
let mut reflown = HashSet::<Uuid>::new();
|
||||
let mut layout_reflows = Vec::<Uuid>::new();
|
||||
|
||||
// We first propagate the transforms to the children and then after
|
||||
// recalculate the layouts. The layout can create further transforms that
|
||||
// we need to re-propagate.
|
||||
// In order for loop to eventualy finish, we limit the flex reflow to just
|
||||
// one (the reflown set).
|
||||
while !entries.is_empty() {
|
||||
while let Some(modifier) = entries.pop_front() {
|
||||
match modifier {
|
||||
Modifier::Transform(entry) => propagate_transform(
|
||||
entry,
|
||||
pixel_precision,
|
||||
state,
|
||||
&mut entries,
|
||||
&mut bounds,
|
||||
&mut modifiers,
|
||||
),
|
||||
Modifier::Reflow(id) => propagate_reflow(
|
||||
&id,
|
||||
state,
|
||||
&mut entries,
|
||||
&mut bounds,
|
||||
&mut layout_reflows,
|
||||
&mut reflown,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
for id in layout_reflows.iter() {
|
||||
if reflown.contains(id) {
|
||||
continue;
|
||||
}
|
||||
reflow_shape(id, state, &mut reflown, &mut entries, &mut bounds);
|
||||
}
|
||||
layout_reflows = Vec::new();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue