🐛 Fix round/square linecaps not being applied correctly in open paths

This commit is contained in:
Belén Albeza 2026-05-07 17:40:30 +02:00 committed by Alonso Torres
parent c3743930c2
commit a52c4e099a
2 changed files with 23 additions and 0 deletions

View File

@ -302,6 +302,12 @@ fn handle_stroke_caps(
return;
}
// When both ends share the same simple line cap, Skia already drew it
// natively via `PaintCap` on the stroke paint, so skip the manual overlay.
if stroke.to_skia_linecap().is_some() {
return;
}
// Curves can have duplicated points, so let's remove consecutive duplicated points
let mut points = path.points().to_vec();
points.dedup();

View File

@ -293,6 +293,10 @@ impl Stroke {
}
}
if let Some(cap) = self.to_skia_linecap() {
paint.set_stroke_cap(cap);
}
paint
}
@ -330,6 +334,19 @@ impl Stroke {
cap_margin_for_cap(self.cap_start, self.width)
.max(cap_margin_for_cap(self.cap_end, self.width))
}
/// Returns a Skia `PaintCap` to apply natively on the stroke paint when
/// both ends share the same simple line cap (`Round/Round` or
/// `Square/Square`). Skia only emits cap geometry at sub-path endpoints,
/// so this is a no-op on closed paths and avoids the extra fill draw the
/// manual caps would otherwise require on open paths.
pub fn to_skia_linecap(&self) -> Option<skia::paint::Cap> {
match (self.cap_start, self.cap_end) {
(Some(StrokeCap::Round), Some(StrokeCap::Round)) => Some(skia::paint::Cap::Round),
(Some(StrokeCap::Square), Some(StrokeCap::Square)) => Some(skia::paint::Cap::Square),
_ => None,
}
}
}
fn align_rect_to_half_pixel(rect: &Rect, stroke_width: f32, scale: f32) -> Rect {