Skip to content

Commit ebf3512

Browse files
indierustyKeavon
andauthored
Refactor and fix append_bezpath() method on vector data (#2649)
* refactor 'append_bezpath' method. * fix a bug. --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent 2615d86 commit ebf3512

File tree

2 files changed

+95
-61
lines changed

2 files changed

+95
-61
lines changed

node-graph/gcore/src/vector/vector_data.rs

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::style::{PathStyle, Stroke};
77
use crate::instances::Instances;
88
use crate::{AlphaBlending, Color, GraphicGroupTable};
99
pub use attributes::*;
10-
use bezier_rs::{BezierHandles, ManipulatorGroup};
10+
use bezier_rs::ManipulatorGroup;
1111
use core::borrow::Borrow;
1212
use dyn_any::DynAny;
1313
use glam::{DAffine2, DVec2};
@@ -179,66 +179,7 @@ impl VectorData {
179179

180180
/// Appends a Kurbo BezPath to the vector data.
181181
pub fn append_bezpath(&mut self, bezpath: kurbo::BezPath) {
182-
let mut first_point_index = None;
183-
let mut last_point_index = None;
184-
185-
let mut first_segment_id = None;
186-
let mut last_segment_id = None;
187-
188-
let mut point_id = self.point_domain.next_id();
189-
let mut segment_id = self.segment_domain.next_id();
190-
191-
let stroke_id = StrokeId::ZERO;
192-
let fill_id = FillId::ZERO;
193-
194-
for element in bezpath.elements() {
195-
match *element {
196-
kurbo::PathEl::MoveTo(point) => {
197-
let next_point_index = self.point_domain.ids().len();
198-
self.point_domain.push(point_id.next_id(), point_to_dvec2(point));
199-
first_point_index = Some(next_point_index);
200-
last_point_index = Some(next_point_index);
201-
}
202-
kurbo::PathEl::ClosePath => match (first_point_index, last_point_index) {
203-
(Some(first_point_index), Some(last_point_index)) => {
204-
let next_segment_id = segment_id.next_id();
205-
self.segment_domain.push(next_segment_id, first_point_index, last_point_index, BezierHandles::Linear, stroke_id);
206-
207-
let next_region_id = self.region_domain.next_id();
208-
self.region_domain.push(next_region_id, first_segment_id.unwrap()..=next_segment_id, fill_id);
209-
}
210-
_ => {
211-
error!("Empty bezpath cannot be closed.")
212-
}
213-
},
214-
_ => {}
215-
}
216-
217-
let mut append_path_element = |handle: BezierHandles, point: kurbo::Point| {
218-
let next_point_index = self.point_domain.ids().len();
219-
self.point_domain.push(point_id.next_id(), point_to_dvec2(point));
220-
221-
let next_segment_id = segment_id.next_id();
222-
self.segment_domain.push(segment_id.next_id(), last_point_index.unwrap(), next_point_index, handle, stroke_id);
223-
224-
last_point_index = Some(next_point_index);
225-
first_segment_id = Some(first_segment_id.unwrap_or(next_segment_id));
226-
last_segment_id = Some(next_segment_id);
227-
};
228-
229-
match *element {
230-
kurbo::PathEl::LineTo(point) => append_path_element(BezierHandles::Linear, point),
231-
kurbo::PathEl::QuadTo(handle, point) => append_path_element(BezierHandles::Quadratic { handle: point_to_dvec2(handle) }, point),
232-
kurbo::PathEl::CurveTo(handle_start, handle_end, point) => append_path_element(
233-
BezierHandles::Cubic {
234-
handle_start: point_to_dvec2(handle_start),
235-
handle_end: point_to_dvec2(handle_end),
236-
},
237-
point,
238-
),
239-
_ => {}
240-
}
241-
}
182+
AppendBezpath::append_bezpath(self, bezpath);
242183
}
243184

244185
/// Construct some new vector data from subpaths with an identity transform and black fill.

node-graph/gcore/src/vector/vector_data/modification.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::uuid::generate_uuid;
55
use bezier_rs::BezierHandles;
66
use core::hash::BuildHasher;
77
use dyn_any::DynAny;
8+
use kurbo::{BezPath, PathEl};
89
use std::collections::{HashMap, HashSet};
910

1011
/// Represents a procedural change to the [`PointDomain`] in [`VectorData`].
@@ -552,3 +553,95 @@ where
552553
let visitor = HashMapVisitor { marker: std::marker::PhantomData };
553554
deserializer.deserialize_seq(visitor)
554555
}
556+
557+
pub struct AppendBezpath<'a> {
558+
first_point_index: Option<usize>,
559+
last_point_index: Option<usize>,
560+
first_segment_id: Option<SegmentId>,
561+
last_segment_id: Option<SegmentId>,
562+
next_handle: Option<BezierHandles>,
563+
point_id: PointId,
564+
segment_id: SegmentId,
565+
vector_data: &'a mut VectorData,
566+
}
567+
568+
impl<'a> AppendBezpath<'a> {
569+
fn new(vector_data: &'a mut VectorData) -> Self {
570+
Self {
571+
first_point_index: None,
572+
last_point_index: None,
573+
first_segment_id: None,
574+
last_segment_id: None,
575+
next_handle: None,
576+
point_id: vector_data.point_domain.next_id(),
577+
segment_id: vector_data.segment_domain.next_id(),
578+
vector_data,
579+
}
580+
}
581+
582+
fn append_path_element(&mut self, handle: BezierHandles, point: kurbo::Point, next_element: Option<&PathEl>) {
583+
if let Some(PathEl::ClosePath) = next_element {
584+
self.next_handle = Some(handle);
585+
} else {
586+
let next_point_index = self.vector_data.point_domain.ids().len();
587+
self.vector_data.point_domain.push(self.point_id.next_id(), point_to_dvec2(point));
588+
589+
let next_segment_id = self.segment_id.next_id();
590+
self.vector_data
591+
.segment_domain
592+
.push(self.segment_id.next_id(), self.last_point_index.unwrap(), next_point_index, handle, StrokeId::ZERO);
593+
594+
self.last_point_index = Some(next_point_index);
595+
self.first_segment_id = Some(self.first_segment_id.unwrap_or(next_segment_id));
596+
self.last_segment_id = Some(next_segment_id);
597+
}
598+
}
599+
600+
pub fn append_bezpath(vector_data: &'a mut VectorData, bezpath: BezPath) {
601+
let mut this = Self::new(vector_data);
602+
603+
let stroke_id = StrokeId::ZERO;
604+
let fill_id = FillId::ZERO;
605+
606+
for i in 0..bezpath.elements().len() {
607+
let current_element = bezpath.elements()[i];
608+
let next_element = bezpath.elements().get(i + 1);
609+
610+
match current_element {
611+
kurbo::PathEl::MoveTo(point) => {
612+
let next_point_index = this.vector_data.point_domain.ids().len();
613+
this.vector_data.point_domain.push(this.point_id.next_id(), point_to_dvec2(point));
614+
this.first_point_index = Some(next_point_index);
615+
this.last_point_index = Some(next_point_index);
616+
}
617+
kurbo::PathEl::ClosePath => match (this.first_point_index, this.last_point_index) {
618+
(Some(first_point_index), Some(last_point_index)) => {
619+
let next_segment_id = this.segment_id.next_id();
620+
this.vector_data
621+
.segment_domain
622+
.push(next_segment_id, last_point_index, first_point_index, this.next_handle.unwrap_or(BezierHandles::Linear), stroke_id);
623+
624+
let next_region_id = this.vector_data.region_domain.next_id();
625+
// In case there is only one anchor point.
626+
let first_segment_id = this.first_segment_id.unwrap_or(next_segment_id);
627+
628+
this.vector_data.region_domain.push(next_region_id, first_segment_id..=next_segment_id, fill_id);
629+
}
630+
_ => {
631+
error!("Empty bezpath cannot be closed.")
632+
}
633+
},
634+
kurbo::PathEl::LineTo(point) => this.append_path_element(BezierHandles::Linear, point, next_element),
635+
kurbo::PathEl::QuadTo(handle, point) => this.append_path_element(BezierHandles::Quadratic { handle: point_to_dvec2(handle) }, point, next_element),
636+
kurbo::PathEl::CurveTo(handle_start, handle_end, point) => this.append_path_element(
637+
BezierHandles::Cubic {
638+
handle_start: point_to_dvec2(handle_start),
639+
handle_end: point_to_dvec2(handle_end),
640+
},
641+
point,
642+
next_element,
643+
),
644+
}
645+
}
646+
}
647+
}

0 commit comments

Comments
 (0)