mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00:00
Prototype integration of linesweeper crate into graphite
This commit is contained in:
parent
63cce26755
commit
dd45af48f4
4 changed files with 62 additions and 3 deletions
|
@ -25,6 +25,8 @@ default = ["parsing"]
|
|||
|
||||
[dependencies]
|
||||
glam = "0.29.0"
|
||||
kurbo.version = "=0.11"
|
||||
linesweeper = "0.0.4"
|
||||
regex = "1.10.6"
|
||||
slotmap = "1.0.7"
|
||||
|
||||
|
|
|
@ -16,6 +16,62 @@ mod path;
|
|||
#[cfg(test)]
|
||||
mod visual_tests;
|
||||
|
||||
pub fn linesweeper_bool(a: &Path, a_fill_rule: FillRule, b: &Path, b_fill_rule: FillRule, op: PathBooleanOperation) -> Result<Vec<Path>, BooleanError> {
|
||||
let a = to_kurbo_path(a);
|
||||
let b = to_kurbo_path(b);
|
||||
let op = match op {
|
||||
PathBooleanOperation::Union => linesweeper::BinaryOp::Union,
|
||||
PathBooleanOperation::Difference => linesweeper::BinaryOp::Difference,
|
||||
PathBooleanOperation::Intersection => linesweeper::BinaryOp::Intersection,
|
||||
_ => panic!(),
|
||||
};
|
||||
let output = linesweeper::binary_op(&a, &b, linesweeper::FillRule::NonZero, op).unwrap();
|
||||
Ok(from_kurbo_path(&output))
|
||||
}
|
||||
|
||||
fn to_kurbo_path(a: &Vec<PathSegment>) -> kurbo::BezPath {
|
||||
let mut a_new = kurbo::BezPath::new();
|
||||
for segment in a {
|
||||
let PathSegment::Cubic(p1, p2, p3, p4) = segment else { panic!("{:?}", segment) };
|
||||
let k = |x: &glam::DVec2| kurbo::Point::new(x.x, x.y);
|
||||
if a_new.is_empty() {
|
||||
a_new.push(kurbo::PathEl::MoveTo(k(p1)));
|
||||
}
|
||||
a_new.push(kurbo::PathEl::CurveTo(k(p2), k(p3), k(p4)))
|
||||
}
|
||||
a_new
|
||||
}
|
||||
fn from_kurbo_path(a: &linesweeper::topology::Contours) -> Vec<Path> {
|
||||
let mut output = vec![];
|
||||
for contour in a.contours() {
|
||||
let mut a_new = vec![];
|
||||
let mut start = glam::DVec2::ZERO;
|
||||
let mut last = glam::DVec2::ZERO;
|
||||
for segment in &contour.path {
|
||||
let k = |x: kurbo::Point| glam::DVec2::new(x.x, x.y);
|
||||
match segment {
|
||||
kurbo::PathEl::MoveTo(p1) => {
|
||||
last = k(p1);
|
||||
start = k(p1)
|
||||
}
|
||||
kurbo::PathEl::CurveTo(p2, p3, p4) => {
|
||||
a_new.push(PathSegment::Cubic(last, k(p2), k(p3), k(p4)));
|
||||
last = k(p4)
|
||||
}
|
||||
kurbo::PathEl::QuadTo(p2, p3) => {
|
||||
a_new.push(PathSegment::Quadratic(last, k(p2), k(p3)));
|
||||
last = k(p3)
|
||||
}
|
||||
kurbo::PathEl::LineTo(p) => a_new.push(PathSegment::Cubic(last, last, k(p), k(p))),
|
||||
kurbo::PathEl::ClosePath => a_new.push(PathSegment::Cubic(last, last, start, start)),
|
||||
_ => panic!("{:?}", segment),
|
||||
};
|
||||
}
|
||||
output.push(a_new);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub(crate) use parsing::*;
|
||||
pub(crate) use path::*;
|
||||
|
|
|
@ -89,6 +89,7 @@ web-sys = { workspace = true, optional = true, features = [
|
|||
# Optional dependencies
|
||||
image-compare = { version = "0.4.1", optional = true }
|
||||
ndarray = "0.16.1"
|
||||
linesweeper = "0.0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
|
|
|
@ -233,14 +233,14 @@ fn to_path_segments(path: &mut Vec<path_bool::PathSegment>, subpath: &bezier_rs:
|
|||
}
|
||||
global_end = end;
|
||||
let segment = match transformed.handles {
|
||||
bezier_rs::BezierHandles::Linear => PathSegment::Line(start, end),
|
||||
bezier_rs::BezierHandles::Linear => PathSegment::Cubic(start, start, end, end),
|
||||
bezier_rs::BezierHandles::Quadratic { handle } => PathSegment::Quadratic(start, handle, end),
|
||||
bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => PathSegment::Cubic(start, handle_start, handle_end, end),
|
||||
};
|
||||
path.push(segment);
|
||||
}
|
||||
if let Some(start) = global_start {
|
||||
path.push(PathSegment::Line(global_end, start));
|
||||
path.push(PathSegment::Cubic(global_end, global_end, start, start));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ fn boolean_union(a: Path, b: Path) -> Vec<Path> {
|
|||
}
|
||||
|
||||
fn path_bool(a: Path, b: Path, op: PathBooleanOperation) -> Vec<Path> {
|
||||
match path_bool::path_boolean(&a, FillRule::NonZero, &b, FillRule::NonZero, op) {
|
||||
match path_bool::linesweeper_bool(&a, FillRule::NonZero, &b, FillRule::NonZero, op) {
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
let a_path = path_bool::path_to_path_data(&a, 0.001);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue