Reintroduce improved logic for mesh interior region fill determination (#4464)

* Decide branching mesh fill insideness by winding, normalizing drawn direction at the Path node

* Fix dead connector click targets by explicitly closing the kurbo ellipse port paths

* Fix hole subtraction when a hole vertex is snapped exactly onto its covering contour

* Classify embedded negative space by its single surrounding face so fully enclosed mesh cells still fill
This commit is contained in:
Keavon Chambers
2026-08-19 00:59:40 -07:00
committed by GitHub
parent daa8b6a5a4
commit 2fa6b743fe
6 changed files with 652 additions and 61 deletions

View File

@@ -1522,7 +1522,7 @@ fn render_vector_shape_svg(item: ItemRef<'_, Vector>, vector: &Vector, render: &
});
if use_face_fill {
for mut face_path in vector.construct_faces().filter(|face| face.area() >= 0.) {
for mut face_path in vector.construct_faces() {
face_path.apply_affine(Affine::new(applied_stroke_transform.to_cols_array()));
let face_d = face_path.to_svg();
@@ -1612,10 +1612,6 @@ fn render_vector_shape_svg(item: ItemRef<'_, Vector>, vector: &Vector, render: &
attributes.push_val(stroke_shape_attribute);
attributes.push_val(stroke_attribute);
if vector.is_branching() && !use_face_fill {
attributes.push("fill-rule", "evenodd");
}
let opacity = (opacity_attr * if render_params.for_mask { 1. } else { opacity_fill_attr }) as f32;
if opacity < 1. {
attributes.push("opacity", opacity.to_string());
@@ -1851,7 +1847,7 @@ fn render_vector_item_to_vello(
let use_face_fill = element.use_face_fill();
let do_fill = |scene: &mut Scene, context: &mut RenderContext| {
if use_face_fill {
for mut face_path in element.construct_faces().filter(|face| face.area() >= 0.) {
for mut face_path in element.construct_faces() {
face_path.apply_affine(Affine::new(applied_stroke_transform.to_cols_array()));
let mut kurbo_path = kurbo::BezPath::new();
for element in face_path {
@@ -1859,8 +1855,6 @@ fn render_vector_item_to_vello(
}
do_fill_path(scene, context, &kurbo_path, peniko::Fill::NonZero);
}
} else if element.is_branching() {
do_fill_path(scene, context, &path, peniko::Fill::EvenOdd);
} else {
do_fill_path(scene, context, &path, peniko::Fill::NonZero);
}