Skip to content

Conversation

@liunicholas6
Copy link
Contributor

Closes #3378
Didn't want to have to deal with working off of @iamthenoname repo so I made a new set of commits.
@0HyperCube Thanks for all the feedback!

@Keavon
Copy link
Member

Keavon commented Dec 14, 2025

!build


# Optional workspace dependencies
serde = { workspace = true, optional = true }
fixedbitset = "0.5.7"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the process is for adding dependencies -- I saw fixedbitset is a dependency of petgraph so I thought it would probably be OK to bring in; I can easily swap it out for a Vec:: or similar

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TrueDoctor can you give your thoughts on this please?

@github-actions
Copy link

📦 Build Complete for 8bdc906
https://b61a599b.graphite.pages.dev

@liunicholas6
Copy link
Contributor Author

Update -- looks like some fills still aren't working; probably going to take a lot of debug logging to figure out. Will take another look tomorrow

Comment on lines 279 to 280
let tangent = deriv.eval(t);
DVec2 { x: tangent.x, y: tangent.y }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the handle is placed on top of the anchor then this will be zero.

For reference, here is my impl of the tangent at start which attempts to avoid reporting zero length tangents:

/// Compute the tangent at t=0 for the path segment
pub fn tangent_at_start(segment: kurbo::PathSeg) -> kurbo::Vec2 {
let tangent = match segment {
kurbo::PathSeg::Line(line) => (line.p1 - line.p0).normalize(),
kurbo::PathSeg::Quad(quad_bez) => {
let first = (quad_bez.p1 - quad_bez.p0).normalize();
if first.is_finite() { first } else { (quad_bez.p2 - quad_bez.p0).normalize() }
}
kurbo::PathSeg::Cubic(cubic_bez) => {
let first = (cubic_bez.p1 - cubic_bez.p0).normalize();
if first.is_finite() {
first
} else {
let second = (cubic_bez.p2 - cubic_bez.p0).normalize();
if second.is_finite() { second } else { (cubic_bez.p3 - cubic_bez.p0).normalize() }
}
}
};
debug_assert!(tangent.is_finite(), "cannot round corner with NaN tangent {segment:?}");
tangent
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep -- I special-cased tangent_at_start and tangent_at_end for each type of segment but then didn't actually call into them on the match case.

I didn't think of the "find the first non-overlapping control point" strategy though; that's a good call that I addressed on revision.

@Keavon
Copy link
Member

Keavon commented Dec 21, 2025

!build

@github-actions
Copy link

📦 Build Complete for 1c733bb
https://45259c6a.graphite.pages.dev

@Keavon Keavon changed the title Branching mesh fill Implement proper fill rendering for vector meshes Dec 21, 2025
@Keavon Keavon enabled auto-merge (squash) December 21, 2025 02:39
@Keavon Keavon merged commit e73e524 into GraphiteEditor:master Dec 21, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Render vector mesh fills correctly as separate subpaths

3 participants