Delete the dead StrokeId and FillId attributes from the Vector segment and region domains (#4461)

This commit is contained in:
Keavon Chambers
2026-08-18 17:51:29 -07:00
committed by GitHub
parent 48e776c1af
commit 39425ca7ea
10 changed files with 49 additions and 119 deletions

View File

@@ -696,7 +696,7 @@ impl TableItemLayout for Vector {
}
VectorTableTab::Regions => {
table_rows.push(column_headings(&["", "segment_range"]));
table_rows.extend(self.region_domain.iter().map(|(id, segment_range, _)| {
table_rows.extend(self.region_domain.iter().map(|(id, segment_range)| {
vec![
TextLabel::new(format!("{}", id.inner())).narrow(true).widget_instance(),
TextLabel::new(format!("Segment {} Segment {}", segment_range.start().inner(), segment_range.end().inner()))

View File

@@ -2781,7 +2781,7 @@ impl Fsm for PathToolFsmState {
let find_index = |id: PointId| new_vector.point_domain.iter().enumerate().find(|(_, (point_id, _))| *point_id == id).map(|(index, _)| index);
// Add segments which have selected ends
for ((segment_id, segment, start, end), stroke) in old_vector.segment_iter().zip(old_vector.segment_domain.stroke().iter()) {
for (segment_id, segment, start, end) in old_vector.segment_iter() {
let both_ends_selected = layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(start)) && layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(end));
let segment_selected = layer_selection_state.is_segment_selected(segment_id);
@@ -2791,7 +2791,7 @@ impl Fsm for PathToolFsmState {
error!("Point does not exist in point domain");
return PathToolFsmState::Ready;
};
new_vector.segment_domain.push(segment_id, start_index, end_index, segment_to_handles(&segment), *stroke);
new_vector.segment_domain.push(segment_id, start_index, end_index, segment_to_handles(&segment));
}
}

View File

@@ -21,7 +21,7 @@ use graphene_std::Color;
use graphene_std::vector::misc::pathseg_points;
use graphene_std::vector::misc::{HandleId, ManipulatorPointId, dvec2_to_point};
use graphene_std::vector::style::FillChoice;
use graphene_std::vector::{NoHashBuilder, PointId, SegmentId, StrokeId, Vector, VectorModificationType};
use graphene_std::vector::{NoHashBuilder, PointId, SegmentId, Vector, VectorModificationType};
use kurbo::{BezPath, CubicBez, PathSeg};
#[derive(Default, ExtractField)]
@@ -1852,7 +1852,7 @@ impl Fsm for PenToolFsmState {
// We have the point. Join the 2 vertices and check if any path is closed.
if let Some(end) = closest_point {
let segment_id = SegmentId::generate();
vector.push(segment_id, start, end, (Some(handle_start), Some(handle_end)), StrokeId::ZERO);
vector.push(segment_id, start, end, (Some(handle_start), Some(handle_end)));
let grouped_segments = vector.auto_join_paths();
let closed_paths = grouped_segments.iter().filter(|path| path.is_closed() && path.contains(segment_id));

View File

@@ -197,7 +197,6 @@ impl MergeByDistanceExt for Vector {
let start = self.segment_domain.start_point()[segment_idx];
let end = self.segment_domain.end_point()[segment_idx];
let handles = self.segment_domain.handles()[segment_idx];
let stroke = self.segment_domain.stroke()[segment_idx];
// Get new indices for start and end points
let new_start = point_index_map[start].unwrap();
@@ -205,7 +204,7 @@ impl MergeByDistanceExt for Vector {
// Skip segments where start and end points were merged
if new_start != new_end {
new_segment_domain.push(id, new_start, new_end, handles, stroke);
new_segment_domain.push(id, new_start, new_end, handles);
}
}

View File

@@ -48,7 +48,7 @@ macro_rules! create_ids {
};
}
create_ids! { PointId, SegmentId, RegionId, StrokeId, FillId }
create_ids! { PointId, SegmentId, RegionId }
/// A no-op hasher that allows writing u64s (the id type).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
@@ -202,14 +202,13 @@ impl PointDomain {
#[derive(Clone, Debug, Default, PartialEq, graphene_hash::CacheHash, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Stores data which is per-segment. A segment is a bézier curve between two end points with a stroke. In future this will be extendable at runtime with custom attributes.
/// Stores data which is per-segment. A segment is a bézier curve between two end points. In future this will be extendable at runtime with custom attributes.
pub struct SegmentDomain {
#[cfg_attr(feature = "serde", serde(alias = "ids"))]
id: Vec<SegmentId>,
start_point: Vec<usize>,
end_point: Vec<usize>,
handles: Vec<BezierHandles>,
stroke: Vec<StrokeId>,
}
impl SegmentDomain {
@@ -219,7 +218,6 @@ impl SegmentDomain {
start_point: Vec::new(),
end_point: Vec::new(),
handles: Vec::new(),
stroke: Vec::new(),
}
}
@@ -229,7 +227,6 @@ impl SegmentDomain {
self.start_point.reserve(additional);
self.end_point.reserve(additional);
self.handles.reserve(additional);
self.stroke.reserve(additional);
}
pub(crate) fn retain(&mut self, f: impl Fn(&SegmentId) -> bool, points_length: usize) {
@@ -261,8 +258,6 @@ impl SegmentDomain {
self.end_point.retain(|_| keep.next().unwrap_or_default());
let mut keep = self.id.iter().map(can_delete());
self.handles.retain(|_| keep.next().unwrap_or_default());
let mut keep = self.id.iter().map(can_delete());
self.stroke.retain(|_| keep.next().unwrap_or_default());
let mut delete_iter = additional_delete_ids.iter().peekable();
self.id.retain(move |id| {
@@ -307,27 +302,22 @@ impl SegmentDomain {
&self.handles
}
pub fn stroke(&self) -> &[StrokeId] {
&self.stroke
}
pub fn push(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles, stroke: StrokeId) {
pub fn push(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles) {
#[cfg(debug_assertions)]
if self.id.contains(&id) {
warn!("Tried to push a duplicate segment to a segment domain");
return;
}
self.push_unchecked(id, start, end, handles, stroke);
self.push_unchecked(id, start, end, handles);
}
#[inline(always)]
pub fn push_unchecked(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles, stroke: StrokeId) {
pub fn push_unchecked(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles) {
self.id.push(id);
self.start_point.push(start);
self.end_point.push(end);
self.handles.push(handles);
self.stroke.push(stroke);
}
pub(crate) fn start_point_mut(&mut self) -> impl Iterator<Item = (SegmentId, &mut usize)> {
@@ -348,10 +338,6 @@ impl SegmentDomain {
nested.map(|((a, b), c)| (a, b, c))
}
pub(crate) fn stroke_mut(&mut self) -> impl Iterator<Item = (SegmentId, &mut StrokeId)> {
self.id.iter().copied().zip(self.stroke.iter_mut())
}
pub(crate) fn segment_start_from_id(&self, segment: SegmentId) -> Option<usize> {
self.id_to_index(segment).and_then(|index| self.start_point.get(index)).copied()
}
@@ -392,7 +378,6 @@ impl SegmentDomain {
self.start_point.extend(other.start_point.iter().map(|&index| id_map.point_offset + index));
self.end_point.extend(other.end_point.iter().map(|&index| id_map.point_offset + index));
self.handles.extend(other.handles.iter().map(|handles| handles.apply_transformation(|p| transform.transform_point2(p))));
self.stroke.extend(&other.stroke);
}
pub(crate) fn map_ids(&mut self, id_map: &IdMap) {
@@ -568,12 +553,11 @@ impl SegmentDomain {
#[derive(Clone, Debug, Default, PartialEq, Hash, graphene_hash::CacheHash, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Stores data which is per-region. A region is an enclosed area composed of a range of segments from the
/// [`SegmentDomain`] that can be given a fill. In future this will be extendable at runtime with custom attributes.
/// [`SegmentDomain`]. In future this will be extendable at runtime with custom attributes.
pub struct RegionDomain {
#[cfg_attr(feature = "serde", serde(alias = "ids"))]
id: Vec<RegionId>,
segment_range: Vec<std::ops::RangeInclusive<SegmentId>>,
fill: Vec<FillId>,
}
impl RegionDomain {
@@ -581,7 +565,6 @@ impl RegionDomain {
Self {
id: Vec::new(),
segment_range: Vec::new(),
fill: Vec::new(),
}
}
@@ -589,14 +572,11 @@ impl RegionDomain {
pub fn reserve(&mut self, additional: usize) {
self.id.reserve(additional);
self.segment_range.reserve(additional);
self.fill.reserve(additional);
}
pub(crate) fn retain(&mut self, f: impl Fn(&RegionId) -> bool) {
let mut keep = self.id.iter().map(&f);
self.segment_range.retain(|_| keep.next().unwrap_or_default());
let mut keep = self.id.iter().map(&f);
self.fill.retain(|_| keep.next().unwrap_or_default());
self.id.retain(&f);
}
@@ -608,26 +588,23 @@ impl RegionDomain {
let mut iter = keep.iter().copied();
self.segment_range.retain(|_| iter.next().unwrap());
let mut iter = keep.iter().copied();
self.fill.retain(|_| iter.next().unwrap());
let mut iter = keep.iter().copied();
self.id.retain(|_| iter.next().unwrap());
}
pub fn push(&mut self, id: RegionId, segment_range: std::ops::RangeInclusive<SegmentId>, fill: FillId) {
pub fn push(&mut self, id: RegionId, segment_range: std::ops::RangeInclusive<SegmentId>) {
#[cfg(debug_assertions)]
if self.id.contains(&id) {
warn!("Tried to push a duplicate region to a region domain");
return;
}
self.push_unchecked(id, segment_range, fill);
self.push_unchecked(id, segment_range);
}
#[inline(always)]
pub fn push_unchecked(&mut self, id: RegionId, segment_range: std::ops::RangeInclusive<SegmentId>, fill: FillId) {
pub fn push_unchecked(&mut self, id: RegionId, segment_range: std::ops::RangeInclusive<SegmentId>) {
self.id.push(id);
self.segment_range.push(segment_range);
self.fill.push(fill);
}
fn _resolve_id(&self, id: RegionId) -> Option<usize> {
@@ -642,10 +619,6 @@ impl RegionDomain {
self.id.iter().copied().zip(self.segment_range.iter_mut())
}
pub(crate) fn fill_mut(&mut self) -> impl Iterator<Item = (RegionId, &mut FillId)> {
self.id.iter().copied().zip(self.fill.iter_mut())
}
pub fn ids(&self) -> &[RegionId] {
&self.id
}
@@ -654,10 +627,6 @@ impl RegionDomain {
&self.segment_range
}
pub fn fill(&self) -> &[FillId] {
&self.fill
}
pub(crate) fn concat(&mut self, other: &Self, _transform: DAffine2, id_map: &IdMap) {
self.id.extend(other.id.iter().map(|id| *id_map.region_map.get(id).unwrap_or(id)));
self.segment_range.extend(
@@ -666,7 +635,6 @@ impl RegionDomain {
.iter()
.map(|range| *id_map.segment_map.get(range.start()).unwrap_or(range.start())..=*id_map.segment_map.get(range.end()).unwrap_or(range.end())),
);
self.fill.extend(&other.fill);
}
pub(crate) fn map_ids(&mut self, id_map: &IdMap) {
@@ -678,12 +646,11 @@ impl RegionDomain {
/// Iterates over regions in the domain.
///
/// Tuple is: (id, segment_range, fill)
pub fn iter(&self) -> impl Iterator<Item = (RegionId, std::ops::RangeInclusive<SegmentId>, FillId)> + '_ {
/// Tuple is: (id, segment_range)
pub fn iter(&self) -> impl Iterator<Item = (RegionId, std::ops::RangeInclusive<SegmentId>)> + '_ {
let ids = self.id.iter().copied();
let segment_range = self.segment_range.iter().cloned();
let fill = self.fill.iter().copied();
zip(ids, zip(segment_range, fill)).map(|(id, (segment_range, fill))| (id, segment_range, fill))
zip(ids, segment_range)
}
}

View File

@@ -95,8 +95,6 @@ pub(crate) struct SegmentModification {
handle_primary: HashMap<SegmentId, Option<DVec2>>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_hashmap", deserialize_with = "deserialize_hashmap"))]
handle_end: HashMap<SegmentId, Option<DVec2>>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_hashmap", deserialize_with = "deserialize_hashmap"))]
stroke: HashMap<SegmentId, StrokeId>,
}
impl SegmentModification {
@@ -167,17 +165,11 @@ impl SegmentModification {
};
}
for (id, stroke) in segment_domain.stroke_mut() {
let Some(&new) = self.stroke.get(&id) else { continue };
*stroke = new;
}
for &add_id in &self.add {
let Some(&start) = self.start_point.get(&add_id) else { continue };
let Some(&end) = self.end_point.get(&add_id) else { continue };
let Some(&handle_start) = self.handle_primary.get(&add_id) else { continue };
let Some(&handle_end) = self.handle_end.get(&add_id) else { continue };
let Some(&stroke) = self.stroke.get(&add_id) else { continue };
let Some(start_index) = point_domain.resolve_id(start) else {
warn!("invalid start id: {start:#?}");
@@ -204,7 +196,7 @@ impl SegmentModification {
continue;
}
segment_domain.push(add_id, start_index, end_index, handles, stroke);
segment_domain.push(add_id, start_index, end_index, handles);
}
assert!(
@@ -233,18 +225,16 @@ impl SegmentModification {
.segment_iter()
.map(|(id, segment, _, _)| (id, segment_to_handles(&segment).end().map(|handle| handle - point_to_dvec2(segment.end()))))
.collect(),
stroke: vector.segment_domain.ids().iter().copied().zip(vector.segment_domain.stroke().iter().cloned()).collect(),
}
}
fn push(&mut self, id: SegmentId, points: [PointId; 2], handles: [Option<DVec2>; 2], stroke: StrokeId) {
fn push(&mut self, id: SegmentId, points: [PointId; 2], handles: [Option<DVec2>; 2]) {
self.remove.remove(&id);
self.add.push(id);
self.start_point.insert(id, points[0]);
self.end_point.insert(id, points[1]);
self.handle_primary.insert(id, handles[0]);
self.handle_end.insert(id, handles[1]);
self.stroke.insert(id, stroke);
}
fn remove(&mut self, id: SegmentId) {
@@ -254,7 +244,6 @@ impl SegmentModification {
self.end_point.remove(&id);
self.handle_primary.remove(&id);
self.handle_end.remove(&id);
self.stroke.remove(&id);
}
}
@@ -267,8 +256,6 @@ pub(crate) struct RegionModification {
remove: HashSet<RegionId>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_hashmap", deserialize_with = "deserialize_hashmap"))]
segment_range: HashMap<RegionId, std::ops::RangeInclusive<SegmentId>>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_hashmap", deserialize_with = "deserialize_hashmap"))]
fill: HashMap<RegionId, FillId>,
}
impl RegionModification {
@@ -281,15 +268,9 @@ impl RegionModification {
*segment_range = new.clone(); // Range inclusive is not copy
}
for (id, fill) in region_domain.fill_mut() {
let Some(&new) = self.fill.get(&id) else { continue };
*fill = new;
}
for &add_id in &self.add {
let Some(segment_range) = self.segment_range.get(&add_id) else { continue };
let Some(&fill) = self.fill.get(&add_id) else { continue };
region_domain.push(add_id, segment_range.clone(), fill);
region_domain.push(add_id, segment_range.clone());
}
}
@@ -299,7 +280,6 @@ impl RegionModification {
add: vector.region_domain.ids().to_vec(),
remove: HashSet::new(),
segment_range: vector.region_domain.ids().iter().copied().zip(vector.region_domain.segment_range().iter().cloned()).collect(),
fill: vector.region_domain.ids().iter().copied().zip(vector.region_domain.fill().iter().cloned()).collect(),
}
}
}
@@ -382,13 +362,11 @@ impl VectorModification {
modified_segments.extend(self.segments.end_point.keys().filter(not_added_segment));
modified_segments.extend(self.segments.handle_primary.keys().filter(not_added_segment));
modified_segments.extend(self.segments.handle_end.keys().filter(not_added_segment));
modified_segments.extend(self.segments.stroke.keys().filter(not_added_segment));
// Count unique modified region IDs across all field maps
let mut modified_regions: HashSet<&RegionId> = HashSet::with_capacity(self.regions.segment_range.len());
let not_added_region = |id: &&RegionId| !add_regions.contains(id);
modified_regions.extend(self.regions.segment_range.keys().filter(not_added_region));
modified_regions.extend(self.regions.fill.keys().filter(not_added_region));
ModificationCategoryCounts {
points: [self.points.add.len(), self.points.remove.len(), point_modifications],
@@ -462,7 +440,7 @@ impl VectorModification {
/// Add a [`VectorModificationType`] to this modification.
pub fn modify(&mut self, vector_modification: &VectorModificationType) {
match vector_modification {
VectorModificationType::InsertSegment { id, points, handles } => self.segments.push(*id, *points, *handles, StrokeId::ZERO),
VectorModificationType::InsertSegment { id, points, handles } => self.segments.push(*id, *points, *handles),
VectorModificationType::InsertPoint { id, position } => self.points.push(*id, *position),
VectorModificationType::RemoveSegment { id } => self.segments.remove(*id),
@@ -685,14 +663,14 @@ impl<'a> AppendBezpath<'a> {
let next_segment_id = self.segment_id.next_id();
self.vector
.segment_domain
.push(next_segment_id, self.last_point_index.unwrap(), self.first_point_index.unwrap(), handle, StrokeId::ZERO);
.push(next_segment_id, self.last_point_index.unwrap(), self.first_point_index.unwrap(), handle);
// Create a new region.
let next_region_id = self.vector.region_domain.next_id();
let first_segment_id = self.first_segment_id.unwrap_or(next_segment_id);
let last_segment_id = next_segment_id;
self.vector.region_domain.push(next_region_id, first_segment_id..=last_segment_id, FillId::ZERO);
self.vector.region_domain.push(next_region_id, first_segment_id..=last_segment_id);
}
fn append_segment(&mut self, end_point: Point, handle: BezierHandles) {
@@ -704,9 +682,7 @@ impl<'a> AppendBezpath<'a> {
// Append the segment.
let next_segment_id = self.segment_id.next_id();
self.vector
.segment_domain
.push(next_segment_id, self.last_point_index.unwrap(), next_point_index, handle, StrokeId::ZERO);
self.vector.segment_domain.push(next_segment_id, self.last_point_index.unwrap(), next_point_index, handle);
// Update the states.
self.last_point = Some(end_point);

View File

@@ -75,7 +75,6 @@ impl core_types::transform::BakeTransform for Vector {
impl Vector {
/// Add a path of manipulator groups to this vector path.
pub fn append_manipulator_groups(&mut self, manipulator_groups: &[ManipulatorGroup], closed: bool, preserve_id: bool) {
let stroke_id = StrokeId::ZERO;
let mut point_id = self.point_domain.next_id();
let handles = |a: &ManipulatorGroup, b: &ManipulatorGroup| match (a.out_handle, b.in_handle) {
@@ -111,23 +110,21 @@ impl Vector {
let id = segment_id.next_id();
first_seg = Some(first_seg.unwrap_or(id));
last_seg = Some(id);
self.segment_domain.push(id, start, end_index, handles(&pair[0], &pair[1]), stroke_id);
self.segment_domain.push(id, start, end_index, handles(&pair[0], &pair[1]));
last_point = Some(end_index);
}
let fill_id = FillId::ZERO;
if closed {
if let (Some(last), Some(first), Some(first_id), Some(last_id)) = (manipulator_groups.last(), manipulator_groups.first(), first_point, last_point) {
let id = segment_id.next_id();
first_seg = Some(first_seg.unwrap_or(id));
last_seg = Some(id);
self.segment_domain.push(id, last_id, first_id, handles(last, first), stroke_id);
self.segment_domain.push(id, last_id, first_id, handles(last, first));
}
if let [Some(first_seg), Some(last_seg)] = [first_seg, last_seg] {
self.region_domain.push(self.region_domain.next_id(), first_seg..=last_seg, fill_id);
self.region_domain.push(self.region_domain.next_id(), first_seg..=last_seg);
}
}
}
@@ -157,7 +154,7 @@ impl Vector {
for (start, end) in segments_to_add {
let segment_id = self.segment_domain.next_id().next_id();
self.segment_domain.push(segment_id, start, end, BezierHandles::Linear, StrokeId::ZERO);
self.segment_domain.push(segment_id, start, end, BezierHandles::Linear);
}
}
@@ -280,7 +277,7 @@ impl Vector {
self.segment_domain.end_point().iter().map(|&index| self.point_domain.ids()[index])
}
pub fn push(&mut self, id: SegmentId, start: PointId, end: PointId, handles: (Option<DVec2>, Option<DVec2>), stroke: StrokeId) {
pub fn push(&mut self, id: SegmentId, start: PointId, end: PointId, handles: (Option<DVec2>, Option<DVec2>)) {
let [Some(start), Some(end)] = [start, end].map(|id| self.point_domain.resolve_id(id)) else {
return;
};
@@ -289,7 +286,7 @@ impl Vector {
(None, Some(handle)) | (Some(handle), None) => BezierHandles::Quadratic { handle },
(Some(handle_start), Some(handle_end)) => BezierHandles::Cubic { handle_start, handle_end },
};
self.segment_domain.push(id, start, end, handles, stroke)
self.segment_domain.push(id, start, end, handles)
}
pub fn handles_mut(&mut self) -> impl Iterator<Item = (SegmentId, &mut BezierHandles, PointId, PointId)> {

View File

@@ -32,7 +32,7 @@ pub mod vector {
pub use vector_types::vector::algorithms;
pub use vector_types::vector::click_target;
pub use vector_types::vector::misc::HandleId;
pub use vector_types::vector::{PointId, RegionId, SegmentId, StrokeId};
pub use vector_types::vector::{PointId, RegionId, SegmentId};
pub use vector_types::vector::{deserialize_hashmap, serialize_hashmap, serialize_hashmap_as_sorted_object};
// Re-export HandleExt trait and NoHashBuilder

View File

@@ -9,7 +9,7 @@ use vector_types::vector::algorithms::shapes;
use vector_types::vector::misc::BezierHandles;
use vector_types::vector::misc::{ArcType, AsU64, BoxCorners, GridType};
use vector_types::vector::misc::{HandleId, SpiralType};
use vector_types::vector::{PointId, SegmentId, StrokeId};
use vector_types::vector::{PointId, SegmentId};
/// Generates a circle shape with a chosen radius.
#[node_macro::node(category("Vector: Shape"))]
@@ -364,7 +364,7 @@ fn grid<T: GridSpacing>(
// Helper function to connect points with line segments.
let mut push_segment = |to_index: Option<usize>| {
if let Some(other_index) = to_index {
vector.segment_domain.push(segment_id.next_id(), other_index, current_index, BezierHandles::Linear, StrokeId::ZERO);
vector.segment_domain.push(segment_id.next_id(), other_index, current_index, BezierHandles::Linear);
}
};

View File

@@ -34,8 +34,7 @@ use vector_types::vector::misc::{
bezpath_from_manipulator_groups, bezpath_to_manipulator_groups, handles_to_segment, is_linear, point_to_dvec2, segment_to_handles,
};
use vector_types::vector::style::{DashPattern, Gradient, GradientSettings, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
use vector_types::vector::{FillId, PointId, RegionId, SegmentDomain, SegmentId, StrokeId, VectorExt};
use vector_types::vector::{PointDomain, RegionDomain};
use vector_types::vector::{PointDomain, PointId, RegionDomain, RegionId, SegmentDomain, SegmentId, VectorExt};
/// Implemented for `List` types that contain vector items reachable via mutable access.
/// Used by the whole-collection Assign Colors node so it can apply to either `List<Graphic>` or `List<Vector>`.
@@ -693,7 +692,6 @@ fn merge_by_distance<V: MapVectorItems + Send + Sync + 'static>(
pub mod extrude_algorithms {
use glam::DVec2;
use kurbo::{ParamCurve, ParamCurveDeriv};
use vector_types::vector::StrokeId;
use vector_types::vector::misc::BezierHandles;
use vector_types::vector::misc::ExtrudeJoiningAlgorithm;
@@ -740,7 +738,7 @@ pub mod extrude_algorithms {
let middle_point_index = vector.point_domain.len();
vector.point_domain.push(middle_point, DVec2::new(first.end().x, first.end().y));
vector.segment_domain.push(start_segment, start_index, middle_point_index, first_handles, StrokeId::ZERO);
vector.segment_domain.push(start_segment, start_index, middle_point_index, first_handles);
vector.segment_domain.set_start_point(segment_index, middle_point_index);
vector.segment_domain.set_handles(segment_index, second_handles);
@@ -766,7 +764,6 @@ pub mod extrude_algorithms {
vector.segment_domain.start_point()[index] + points_count,
vector.segment_domain.end_point()[index] + points_count,
vector.segment_domain.handles()[index].apply_transformation(|x| x + direction),
vector.segment_domain.stroke()[index],
);
}
}
@@ -817,9 +814,7 @@ pub mod extrude_algorithms {
continue;
}
vector
.segment_domain
.push(next_segment.next_id(), index, index + first_half_points, BezierHandles::Linear, StrokeId::ZERO);
vector.segment_domain.push(next_segment.next_id(), index, index + first_half_points, BezierHandles::Linear);
}
}
@@ -828,7 +823,7 @@ pub mod extrude_algorithms {
let mut next_segment = vector.segment_domain.next_id();
let first_half = vector.point_domain.len() / 2;
for index in 0..first_half {
vector.segment_domain.push(next_segment.next_id(), index, index + first_half, BezierHandles::Linear, StrokeId::ZERO);
vector.segment_domain.push(next_segment.next_id(), index, index + first_half, BezierHandles::Linear);
}
}
@@ -1298,15 +1293,13 @@ async fn points_to_polyline<V: MapVectorItems + 'n + Send>(_: impl Ctx, #[implem
if points_count >= 2 {
(0..points_count - 1).for_each(|i| {
segment_domain.push(next_id.next_id(), i, i + 1, BezierHandles::Linear, StrokeId::generate());
segment_domain.push(next_id.next_id(), i, i + 1, BezierHandles::Linear);
});
if closed && points_count != 2 {
segment_domain.push(next_id.next_id(), points_count - 1, 0, BezierHandles::Linear, StrokeId::generate());
segment_domain.push(next_id.next_id(), points_count - 1, 0, BezierHandles::Linear);
vector
.region_domain
.push(RegionId::generate(), segment_domain.ids()[0]..=*segment_domain.ids().last().unwrap(), FillId::generate());
vector.region_domain.push(RegionId::generate(), segment_domain.ids()[0]..=*segment_domain.ids().last().unwrap());
}
}
@@ -1417,11 +1410,11 @@ pub(crate) fn replace_with_polygons(vector: &mut Vector, polygons: Vec<Vec<DVec2
let id = next_segment.next_id();
first_segment.get_or_insert(id);
last_segment = Some(id);
segment_domain.push(id, start, end, BezierHandles::Linear, StrokeId::ZERO);
segment_domain.push(id, start, end, BezierHandles::Linear);
}
if let (Some(first), Some(last)) = (first_segment, last_segment) {
region_domain.push(next_region.next_id(), first..=last, FillId::ZERO);
region_domain.push(next_region.next_id(), first..=last);
}
}
} else {
@@ -1457,7 +1450,7 @@ pub(crate) fn replace_with_polygons(vector: &mut Vector, polygons: Vec<Vec<DVec2
}
let edge = if start < end { (start, end) } else { (end, start) };
if seen_edges.insert(edge) {
segment_domain.push(next_segment.next_id(), start, end, BezierHandles::Linear, StrokeId::ZERO);
segment_domain.push(next_segment.next_id(), start, end, BezierHandles::Linear);
}
}
}
@@ -2310,8 +2303,6 @@ async fn spline<V: MapVectorItems + 'n + Send>(_: impl Ctx, #[implementations(Gr
solve_spline_first_handle_open(&positions)
};
let stroke_id = StrokeId::ZERO;
// Create segments with computed Bezier handles and add them to the output vector element's segment domain.
for i in 0..(positions.len() - if closed { 0 } else { 1 }) {
let next_index = (i + 1) % positions.len();
@@ -2323,7 +2314,7 @@ async fn spline<V: MapVectorItems + 'n + Send>(_: impl Ctx, #[implementations(Gr
let handle_end = positions[next_index] * 2. - first_handles[next_index];
let handles = BezierHandles::Cubic { handle_start, handle_end };
segment_domain.push(next_id.next_id(), start_index, end_index, handles, stroke_id);
segment_domain.push(next_id.next_id(), start_index, end_index, handles);
}
}
@@ -2580,7 +2571,7 @@ async fn morph(
let handles = handles_from_manips(manip_window[0].out_handle, manip_window[1].in_handle);
let seg_id = segment_id.next_id();
first_segment_id.get_or_insert(seg_id);
vector.segment_domain.push_unchecked(seg_id, prev_point_index, point_index, handles, StrokeId::ZERO);
vector.segment_domain.push_unchecked(seg_id, prev_point_index, point_index, handles);
prev_point_index = point_index;
}
@@ -2589,10 +2580,10 @@ async fn morph(
let handles = handles_from_manips(manips.last().unwrap().out_handle, manips[0].in_handle);
let closing_seg_id = segment_id.next_id();
first_segment_id.get_or_insert(closing_seg_id);
vector.segment_domain.push_unchecked(closing_seg_id, prev_point_index, first_point_index, handles, StrokeId::ZERO);
vector.segment_domain.push_unchecked(closing_seg_id, prev_point_index, first_point_index, handles);
let region_id = vector.region_domain.next_id();
vector.region_domain.push_unchecked(region_id, first_segment_id.unwrap()..=closing_seg_id, FillId::ZERO);
vector.region_domain.push_unchecked(region_id, first_segment_id.unwrap()..=closing_seg_id);
}
}
@@ -3426,7 +3417,7 @@ fn bevel_algorithm(mut vector: Vector, transform: DAffine2, distance: f64) -> Ve
for &[start, end] in new_segments {
let handles = BezierHandles::Linear;
vector.segment_domain.push(next_id.next_id(), start, end, handles, StrokeId::ZERO);
vector.segment_domain.push(next_id.next_id(), start, end, handles);
}
}