mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-08 00:05:00 +00:00
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>
This commit is contained in:
parent
2615d86934
commit
ebf351277d
2 changed files with 95 additions and 61 deletions
|
@ -7,7 +7,7 @@ use super::style::{PathStyle, Stroke};
|
|||
use crate::instances::Instances;
|
||||
use crate::{AlphaBlending, Color, GraphicGroupTable};
|
||||
pub use attributes::*;
|
||||
use bezier_rs::{BezierHandles, ManipulatorGroup};
|
||||
use bezier_rs::ManipulatorGroup;
|
||||
use core::borrow::Borrow;
|
||||
use dyn_any::DynAny;
|
||||
use glam::{DAffine2, DVec2};
|
||||
|
@ -179,66 +179,7 @@ impl VectorData {
|
|||
|
||||
/// Appends a Kurbo BezPath to the vector data.
|
||||
pub fn append_bezpath(&mut self, bezpath: kurbo::BezPath) {
|
||||
let mut first_point_index = None;
|
||||
let mut last_point_index = None;
|
||||
|
||||
let mut first_segment_id = None;
|
||||
let mut last_segment_id = None;
|
||||
|
||||
let mut point_id = self.point_domain.next_id();
|
||||
let mut segment_id = self.segment_domain.next_id();
|
||||
|
||||
let stroke_id = StrokeId::ZERO;
|
||||
let fill_id = FillId::ZERO;
|
||||
|
||||
for element in bezpath.elements() {
|
||||
match *element {
|
||||
kurbo::PathEl::MoveTo(point) => {
|
||||
let next_point_index = self.point_domain.ids().len();
|
||||
self.point_domain.push(point_id.next_id(), point_to_dvec2(point));
|
||||
first_point_index = Some(next_point_index);
|
||||
last_point_index = Some(next_point_index);
|
||||
}
|
||||
kurbo::PathEl::ClosePath => match (first_point_index, last_point_index) {
|
||||
(Some(first_point_index), Some(last_point_index)) => {
|
||||
let next_segment_id = segment_id.next_id();
|
||||
self.segment_domain.push(next_segment_id, first_point_index, last_point_index, BezierHandles::Linear, stroke_id);
|
||||
|
||||
let next_region_id = self.region_domain.next_id();
|
||||
self.region_domain.push(next_region_id, first_segment_id.unwrap()..=next_segment_id, fill_id);
|
||||
}
|
||||
_ => {
|
||||
error!("Empty bezpath cannot be closed.")
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut append_path_element = |handle: BezierHandles, point: kurbo::Point| {
|
||||
let next_point_index = self.point_domain.ids().len();
|
||||
self.point_domain.push(point_id.next_id(), point_to_dvec2(point));
|
||||
|
||||
let next_segment_id = segment_id.next_id();
|
||||
self.segment_domain.push(segment_id.next_id(), last_point_index.unwrap(), next_point_index, handle, stroke_id);
|
||||
|
||||
last_point_index = Some(next_point_index);
|
||||
first_segment_id = Some(first_segment_id.unwrap_or(next_segment_id));
|
||||
last_segment_id = Some(next_segment_id);
|
||||
};
|
||||
|
||||
match *element {
|
||||
kurbo::PathEl::LineTo(point) => append_path_element(BezierHandles::Linear, point),
|
||||
kurbo::PathEl::QuadTo(handle, point) => append_path_element(BezierHandles::Quadratic { handle: point_to_dvec2(handle) }, point),
|
||||
kurbo::PathEl::CurveTo(handle_start, handle_end, point) => append_path_element(
|
||||
BezierHandles::Cubic {
|
||||
handle_start: point_to_dvec2(handle_start),
|
||||
handle_end: point_to_dvec2(handle_end),
|
||||
},
|
||||
point,
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
AppendBezpath::append_bezpath(self, bezpath);
|
||||
}
|
||||
|
||||
/// Construct some new vector data from subpaths with an identity transform and black fill.
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::uuid::generate_uuid;
|
|||
use bezier_rs::BezierHandles;
|
||||
use core::hash::BuildHasher;
|
||||
use dyn_any::DynAny;
|
||||
use kurbo::{BezPath, PathEl};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
/// Represents a procedural change to the [`PointDomain`] in [`VectorData`].
|
||||
|
@ -552,3 +553,95 @@ where
|
|||
let visitor = HashMapVisitor { marker: std::marker::PhantomData };
|
||||
deserializer.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
pub struct AppendBezpath<'a> {
|
||||
first_point_index: Option<usize>,
|
||||
last_point_index: Option<usize>,
|
||||
first_segment_id: Option<SegmentId>,
|
||||
last_segment_id: Option<SegmentId>,
|
||||
next_handle: Option<BezierHandles>,
|
||||
point_id: PointId,
|
||||
segment_id: SegmentId,
|
||||
vector_data: &'a mut VectorData,
|
||||
}
|
||||
|
||||
impl<'a> AppendBezpath<'a> {
|
||||
fn new(vector_data: &'a mut VectorData) -> Self {
|
||||
Self {
|
||||
first_point_index: None,
|
||||
last_point_index: None,
|
||||
first_segment_id: None,
|
||||
last_segment_id: None,
|
||||
next_handle: None,
|
||||
point_id: vector_data.point_domain.next_id(),
|
||||
segment_id: vector_data.segment_domain.next_id(),
|
||||
vector_data,
|
||||
}
|
||||
}
|
||||
|
||||
fn append_path_element(&mut self, handle: BezierHandles, point: kurbo::Point, next_element: Option<&PathEl>) {
|
||||
if let Some(PathEl::ClosePath) = next_element {
|
||||
self.next_handle = Some(handle);
|
||||
} else {
|
||||
let next_point_index = self.vector_data.point_domain.ids().len();
|
||||
self.vector_data.point_domain.push(self.point_id.next_id(), point_to_dvec2(point));
|
||||
|
||||
let next_segment_id = self.segment_id.next_id();
|
||||
self.vector_data
|
||||
.segment_domain
|
||||
.push(self.segment_id.next_id(), self.last_point_index.unwrap(), next_point_index, handle, StrokeId::ZERO);
|
||||
|
||||
self.last_point_index = Some(next_point_index);
|
||||
self.first_segment_id = Some(self.first_segment_id.unwrap_or(next_segment_id));
|
||||
self.last_segment_id = Some(next_segment_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append_bezpath(vector_data: &'a mut VectorData, bezpath: BezPath) {
|
||||
let mut this = Self::new(vector_data);
|
||||
|
||||
let stroke_id = StrokeId::ZERO;
|
||||
let fill_id = FillId::ZERO;
|
||||
|
||||
for i in 0..bezpath.elements().len() {
|
||||
let current_element = bezpath.elements()[i];
|
||||
let next_element = bezpath.elements().get(i + 1);
|
||||
|
||||
match current_element {
|
||||
kurbo::PathEl::MoveTo(point) => {
|
||||
let next_point_index = this.vector_data.point_domain.ids().len();
|
||||
this.vector_data.point_domain.push(this.point_id.next_id(), point_to_dvec2(point));
|
||||
this.first_point_index = Some(next_point_index);
|
||||
this.last_point_index = Some(next_point_index);
|
||||
}
|
||||
kurbo::PathEl::ClosePath => match (this.first_point_index, this.last_point_index) {
|
||||
(Some(first_point_index), Some(last_point_index)) => {
|
||||
let next_segment_id = this.segment_id.next_id();
|
||||
this.vector_data
|
||||
.segment_domain
|
||||
.push(next_segment_id, last_point_index, first_point_index, this.next_handle.unwrap_or(BezierHandles::Linear), stroke_id);
|
||||
|
||||
let next_region_id = this.vector_data.region_domain.next_id();
|
||||
// In case there is only one anchor point.
|
||||
let first_segment_id = this.first_segment_id.unwrap_or(next_segment_id);
|
||||
|
||||
this.vector_data.region_domain.push(next_region_id, first_segment_id..=next_segment_id, fill_id);
|
||||
}
|
||||
_ => {
|
||||
error!("Empty bezpath cannot be closed.")
|
||||
}
|
||||
},
|
||||
kurbo::PathEl::LineTo(point) => this.append_path_element(BezierHandles::Linear, point, next_element),
|
||||
kurbo::PathEl::QuadTo(handle, point) => this.append_path_element(BezierHandles::Quadratic { handle: point_to_dvec2(handle) }, point, next_element),
|
||||
kurbo::PathEl::CurveTo(handle_start, handle_end, point) => this.append_path_element(
|
||||
BezierHandles::Cubic {
|
||||
handle_start: point_to_dvec2(handle_start),
|
||||
handle_end: point_to_dvec2(handle_end),
|
||||
},
|
||||
point,
|
||||
next_element,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue