Replace Bezier-rs use in the 'Offset Path' node with a Kurbo algorithm (#2596)

* minimally replace bezier-rs use in Offset Path node implementation with kurbo's API

* fix kurbo import

* refactor

* Code review

---------

Co-authored-by: indierusty <priyaayadav@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Priyanshu
2025-04-20 09:34:28 +05:30
committed by GitHub
parent a376832480
commit dd1feee734
5 changed files with 182 additions and 4 deletions

View File

@@ -437,7 +437,7 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
/// Alternatively, this can be interpreted as limiting the angle that the miter can form.
/// When the limit is exceeded, no manipulator group will be returned.
/// This value should be greater than 0. If not, the default of 4 will be used.
pub(crate) fn miter_line_join(&self, other: &Subpath<PointId>, miter_limit: Option<f64>) -> Option<ManipulatorGroup<PointId>> {
pub fn miter_line_join(&self, other: &Subpath<PointId>, miter_limit: Option<f64>) -> Option<ManipulatorGroup<PointId>> {
let miter_limit = match miter_limit {
Some(miter_limit) if miter_limit > f64::EPSILON => miter_limit,
_ => 4.,
@@ -491,7 +491,7 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
/// - The `out_handle` for the last manipulator group of `self`
/// - The new manipulator group to be added
/// - The `in_handle` for the first manipulator group of `other`
pub(crate) fn round_line_join(&self, other: &Subpath<PointId>, center: DVec2) -> (DVec2, ManipulatorGroup<PointId>, DVec2) {
pub fn round_line_join(&self, other: &Subpath<PointId>, center: DVec2) -> (DVec2, ManipulatorGroup<PointId>, DVec2) {
let left = self.manipulator_groups[self.len() - 1].anchor;
let right = other.manipulator_groups[0].anchor;

View File

@@ -1,4 +1,5 @@
use super::*;
use crate::BezierHandles;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils::{Cap, Join, SubpathTValue, TValue};
use glam::{DAffine2, DVec2};
@@ -307,7 +308,7 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
// at the incorrect location. This can be avoided by first trimming the two Subpaths at any extrema, effectively ignoring loopbacks.
/// Helper function to clip overlap of two intersecting open Subpaths. Returns an optional, as intersections may not exist for certain arrangements and distances.
/// Assumes that the Subpaths represents simple Bezier segments, and clips the Subpaths at the last intersection of the first Subpath, and first intersection of the last Subpath.
fn clip_simple_subpaths(subpath1: &Subpath<PointId>, subpath2: &Subpath<PointId>) -> Option<(Subpath<PointId>, Subpath<PointId>)> {
pub fn clip_simple_subpaths(subpath1: &Subpath<PointId>, subpath2: &Subpath<PointId>) -> Option<(Subpath<PointId>, Subpath<PointId>)> {
// Split the first subpath at its last intersection
let intersections1 = subpath1.subpath_intersections(subpath2, None, None);
if intersections1.is_empty() {
@@ -366,6 +367,7 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
.map(|bezier| bezier.offset(distance))
.filter(|subpath| subpath.len() >= 2) // In some cases the reduced and scaled bézier is marked by is_point (so the subpath is empty).
.collect::<Vec<Subpath<PointId>>>();
let mut drop_common_point = vec![true; self.len()];
// Clip or join consecutive Subpaths