🎉 Use Vec instead of Indexset
Some checks failed
_STAGING / build-bundle (push) Has been cancelled
_STAGING / build-docker (push) Has been cancelled
_DEVELOP / build-bundle (push) Has been cancelled
_DEVELOP / build-docker (push) Has been cancelled
Commit Message Check / Check Commit Message (push) Has been cancelled

This commit is contained in:
Alejandro Alonso
2025-11-06 11:42:34 +01:00
committed by Alonso Torres
parent 61202e1cab
commit ba092f03e1
7 changed files with 63 additions and 61 deletions

View File

@@ -14,7 +14,6 @@ mod view;
mod wapi;
mod wasm;
use indexmap::IndexSet;
use math::{Bounds, Matrix};
use mem::SerializableResult;
use shapes::{StructureEntry, StructureEntryType, TransformEntry};
@@ -303,8 +302,8 @@ pub extern "C" fn add_shape_child(a: u32, b: u32, c: u32, d: u32) {
});
}
fn set_children_set(entries: IndexSet<Uuid>) {
let mut deleted = IndexSet::new();
fn set_children_set(entries: Vec<Uuid>) {
let mut deleted = Vec::new();
let mut parent_id = None;
with_current_shape_mut!(state, |shape: &mut Shape| {
@@ -326,13 +325,13 @@ fn set_children_set(entries: IndexSet<Uuid>) {
#[no_mangle]
pub extern "C" fn set_children_0() {
let entries = IndexSet::from_iter(vec![]);
let entries = vec![];
set_children_set(entries);
}
#[no_mangle]
pub extern "C" fn set_children_1(a1: u32, b1: u32, c1: u32, d1: u32) {
let entries = IndexSet::from_iter(vec![uuid_from_u32_quartet(a1, b1, c1, d1)]);
let entries = vec![uuid_from_u32_quartet(a1, b1, c1, d1)];
set_children_set(entries);
}
@@ -347,10 +346,10 @@ pub extern "C" fn set_children_2(
c2: u32,
d2: u32,
) {
let entries = IndexSet::from_iter(vec![
let entries = vec![
uuid_from_u32_quartet(a1, b1, c1, d1),
uuid_from_u32_quartet(a2, b2, c2, d2),
]);
];
set_children_set(entries);
}
@@ -369,11 +368,11 @@ pub extern "C" fn set_children_3(
c3: u32,
d3: u32,
) {
let entries = IndexSet::from_iter(vec![
let entries = vec![
uuid_from_u32_quartet(a1, b1, c1, d1),
uuid_from_u32_quartet(a2, b2, c2, d2),
uuid_from_u32_quartet(a3, b3, c3, d3),
]);
];
set_children_set(entries);
}
@@ -396,12 +395,12 @@ pub extern "C" fn set_children_4(
c4: u32,
d4: u32,
) {
let entries = IndexSet::from_iter(vec![
let entries = vec![
uuid_from_u32_quartet(a1, b1, c1, d1),
uuid_from_u32_quartet(a2, b2, c2, d2),
uuid_from_u32_quartet(a3, b3, c3, d3),
uuid_from_u32_quartet(a4, b4, c4, d4),
]);
];
set_children_set(entries);
}
@@ -428,13 +427,13 @@ pub extern "C" fn set_children_5(
c5: u32,
d5: u32,
) {
let entries = IndexSet::from_iter(vec![
let entries = vec![
uuid_from_u32_quartet(a1, b1, c1, d1),
uuid_from_u32_quartet(a2, b2, c2, d2),
uuid_from_u32_quartet(a3, b3, c3, d3),
uuid_from_u32_quartet(a4, b4, c4, d4),
uuid_from_u32_quartet(a5, b5, c5, d5),
]);
];
set_children_set(entries);
}
@@ -442,7 +441,7 @@ pub extern "C" fn set_children_5(
pub extern "C" fn set_children() {
let bytes = mem::bytes_or_empty();
let entries: IndexSet<Uuid> = bytes
let entries: Vec<Uuid> = bytes
.chunks(size_of::<<Uuid as SerializableResult>::BytesType>())
.map(|data| Uuid::from_bytes(data.try_into().unwrap()))
.collect();

View File

@@ -5,7 +5,6 @@ use crate::state::ShapesPoolRef;
use crate::uuid::Uuid;
use bezier_rs::{Bezier, BezierHandles, ProjectionOptions, TValue};
use glam::DVec2;
use indexmap::IndexSet;
use skia_safe as skia;
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap};
@@ -384,11 +383,7 @@ fn beziers_to_segments(beziers: &[(BezierSource, Bezier)]) -> Vec<Segment> {
result
}
pub fn bool_from_shapes(
bool_type: BoolType,
children_ids: &IndexSet<Uuid>,
shapes: ShapesPoolRef,
) -> Path {
pub fn bool_from_shapes(bool_type: BoolType, children_ids: &[Uuid], shapes: ShapesPoolRef) -> Path {
if children_ids.is_empty() {
return Path::default();
}

View File

@@ -30,8 +30,6 @@ use crate::uuid::Uuid;
use crate::view::Viewbox;
use crate::wapi;
use indexmap::IndexSet;
pub use fonts::*;
pub use images::*;
@@ -1492,11 +1490,14 @@ impl RenderState {
// We only need first level shapes
let mut valid_ids: Vec<Uuid> = ids
.iter()
.filter_map(|id| root_ids.get(id).map(|_| *id))
.filter(|id| root_ids.contains(id))
.copied()
.collect();
// These shapes for the tile should be ordered as they are in the parent node
valid_ids.sort_by_key(|id| root_ids.get_index_of(id));
valid_ids.sort_by_key(|id| {
root_ids.iter().position(|x| x == id).unwrap_or(usize::MAX)
});
self.pending_nodes.extend(valid_ids.into_iter().map(|id| {
NodeRenderState {
@@ -1687,7 +1688,7 @@ impl RenderState {
///
/// This is useful when you have a pre-computed set of shape IDs that need to be refreshed,
/// regardless of their relationship to other shapes (e.g., ancestors, descendants, or any other collection).
pub fn update_tiles_shapes(&mut self, shape_ids: &IndexSet<Uuid>, tree: ShapesPoolMutRef<'_>) {
pub fn update_tiles_shapes(&mut self, shape_ids: &[Uuid], tree: ShapesPoolMutRef<'_>) {
performance::begin_measure!("invalidate_and_update_tiles");
let mut all_tiles = HashSet::<tiles::Tile>::new();
for shape_id in shape_ids {

View File

@@ -48,7 +48,6 @@ pub use text::*;
pub use transform::*;
use crate::math::{self, Bounds, Matrix, Point};
use indexmap::IndexSet;
use crate::state::ShapesPoolRef;
@@ -161,7 +160,7 @@ pub struct Shape {
pub id: Uuid,
pub parent_id: Option<Uuid>,
pub shape_type: Type,
pub children: IndexSet<Uuid>,
pub children: Vec<Uuid>,
pub selrect: math::Rect,
pub transform: Matrix,
pub rotation: f32,
@@ -201,16 +200,21 @@ pub fn all_with_ancestors(
shapes: &[Uuid],
shapes_pool: ShapesPoolRef,
include_hidden: bool,
) -> IndexSet<Uuid> {
) -> Vec<Uuid> {
let mut pending = Vec::from_iter(shapes.iter());
let mut result = IndexSet::new();
let mut result = Vec::new();
let mut seen = HashSet::new();
while !pending.is_empty() {
let Some(current_id) = pending.pop() else {
break;
};
result.insert(*current_id);
if !seen.insert(*current_id) {
continue;
}
result.push(*current_id);
let Some(parent_id) = shapes_pool.get(current_id).and_then(|s| s.parent_id) else {
continue;
@@ -220,7 +224,7 @@ pub fn all_with_ancestors(
continue;
}
if result.contains(&parent_id) {
if seen.contains(&parent_id) {
continue;
}
@@ -244,7 +248,7 @@ impl Shape {
id,
parent_id: None,
shape_type: Type::Rect(Rect::default()),
children: IndexSet::<Uuid>::new(),
children: Vec::new(),
selrect: math::Rect::new_empty(),
transform: Matrix::default(),
rotation: 0.,
@@ -560,15 +564,15 @@ impl Shape {
}
pub fn add_child(&mut self, id: Uuid) {
self.children.insert(id);
self.children.push(id);
}
pub fn compute_children_differences(
&mut self,
children: &IndexSet<Uuid>,
) -> (IndexSet<Uuid>, IndexSet<Uuid>) {
let added = children.difference(&self.children).cloned().collect();
let removed = self.children.difference(children).cloned().collect();
pub fn compute_children_differences(&mut self, children: &[Uuid]) -> (Vec<Uuid>, Vec<Uuid>) {
let current_set: HashSet<Uuid> = self.children.iter().copied().collect();
let new_set: HashSet<Uuid> = children.iter().copied().collect();
let added: Vec<Uuid> = new_set.difference(&current_set).copied().collect();
let removed: Vec<Uuid> = current_set.difference(&new_set).copied().collect();
(added, removed)
}
@@ -946,26 +950,26 @@ impl Shape {
self.children.first()
}
pub fn children_ids(&self, include_hidden: bool) -> IndexSet<Uuid> {
pub fn children_ids(&self, include_hidden: bool) -> Vec<Uuid> {
if include_hidden {
return self.children.clone().into_iter().rev().collect();
return self.children.iter().rev().copied().collect();
}
if let Type::Bool(_) = self.shape_type {
IndexSet::<Uuid>::new()
Vec::new()
} else if let Type::Group(group) = self.shape_type {
if group.masked {
self.children
.iter()
.rev()
.take(self.children.len() - 1)
.cloned()
.copied()
.collect()
} else {
self.children.clone().into_iter().rev().collect()
self.children.iter().rev().copied().collect()
}
} else {
self.children.clone().into_iter().rev().collect()
self.children.iter().rev().copied().collect()
}
}
@@ -992,7 +996,7 @@ impl Shape {
shapes: ShapesPoolRef,
include_hidden: bool,
include_self: bool,
) -> IndexSet<Uuid> {
) -> Vec<Uuid> {
let all_children = self.children_ids_iter(include_hidden).flat_map(|id| {
shapes
.get(id)

View File

@@ -6,7 +6,6 @@ use crate::shapes::{
};
use crate::state::ShapesPoolRef;
use crate::uuid::Uuid;
use indexmap::IndexSet;
use std::collections::{HashMap, VecDeque};
use super::common::GetBounds;
@@ -538,7 +537,7 @@ fn cell_bounds(
pub fn create_cell_data<'a>(
layout_bounds: &Bounds,
children: &IndexSet<Uuid>,
children: &[Uuid],
shapes: ShapesPoolRef<'a>,
cells: &Vec<GridCell>,
column_tracks: &[TrackData],

View File

@@ -136,19 +136,24 @@ impl<'a> State<'a> {
/// invalidated and recalculated to include the new child. This ensures that frames
/// and groups properly encompass their children.
pub fn set_parent_for_current_shape(&mut self, id: Uuid) {
let shape = {
let Some(shape) = self.current_shape_mut() else {
panic!("Invalid current shape")
};
// If the shape already has the same parent, do nothing
if shape.parent_id == Some(id) {
return;
}
shape.set_parent(id);
// TODO this clone doesn't seem necessary
shape.clone()
};
// Note: We don't call parent.add_child() here because we are
// asuming the parent is updating its children list via set_children() calls.
// Calling add_child here would create duplicates.
if let Some(parent) = shape.parent_id.and_then(|id| self.shapes.get_mut(&id)) {
// Invalidate parent's extrect so it gets recalculated to include the new child
if let Some(parent) = self.shapes.get_mut(&id) {
parent.invalidate_extrect();
parent.add_child(shape.id);
}
}

View File

@@ -1,13 +1,12 @@
use macros::ToJs;
use indexmap::IndexSet;
use super::RawSegmentData;
use crate::math;
use crate::shapes::BoolType;
use crate::uuid::Uuid;
use crate::{mem, SerializableResult};
use crate::{with_current_shape_mut, with_state, STATE};
use std::mem::size_of;
#[derive(Debug, Clone, Copy, PartialEq, ToJs)]
#[repr(u8)]
@@ -47,7 +46,7 @@ pub extern "C" fn set_shape_bool_type(raw_bool_type: u8) {
pub extern "C" fn calculate_bool(raw_bool_type: u8) -> *mut u8 {
let bytes = mem::bytes_or_empty();
let entries: IndexSet<Uuid> = bytes
let entries: Vec<Uuid> = bytes
.chunks(size_of::<<Uuid as SerializableResult>::BytesType>())
.map(|data| Uuid::from_bytes(data.try_into().unwrap()))
.collect();