summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorTobias Schmitz <tobiasschmitz2001@gmail.com>2025-07-09 15:53:25 +0200
committerTobias Schmitz <tobiasschmitz2001@gmail.com>2025-07-09 17:34:17 +0200
commit25ef7119e6b9b30b7dfa12da1c9f2002f4de1f6d (patch)
tree9b384f5538c07cfa93f86703d3eafe7a2ba84949 /crates
parentc85240a8fe090a3ccb660b9cb73de14d523ca3db (diff)
feat: use old cap behavior for corners with radius < stroke-width
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-layout/src/shapes.rs36
1 files changed, 24 insertions, 12 deletions
diff --git a/crates/typst-layout/src/shapes.rs b/crates/typst-layout/src/shapes.rs
index 0d19c346..461ef8f2 100644
--- a/crates/typst-layout/src/shapes.rs
+++ b/crates/typst-layout/src/shapes.rs
@@ -1162,19 +1162,31 @@ impl ControlPoints {
}
}
- /// If no stroke is specified before and there is a radius, use the same
- /// width as on the side after. Otherwise default to zero.
+ /// Whether to use the [`Self::stroke_after`] if [`Self::stroke_before`] is
+ /// missing to compute the control points. If the radius is too small, caps
+ /// other than the [`LineCap::Butt`] might be misshaped.
+ fn reuse_stroke_after_for_cap(&self) -> Option<Abs> {
+ self.stroke_after.filter(|s| 2.0 * *s < self.radius)
+ }
+
+ /// Either fall back to [`Self::reuse_stroke_after_for_cap`] or zero.
fn stroke_width_before(&self) -> Abs {
self.stroke_before
- .or(self.stroke_after.filter(|_| self.radius != Abs::zero()))
+ .or(self.reuse_stroke_after_for_cap())
.unwrap_or(Abs::zero())
}
- /// If no stroke is specified after and there is a radius, use the same
- /// width as on the side before. Otherwise default to zero.
+ /// Whether to use the [`Self::stroke_before`] if [`Self::stroke_after`] is
+ /// missing to compute the control points. If the radius is too small, caps
+ /// other than the [`LineCap::Butt`] might be misshaped.
+ fn reuse_stroke_before_for_cap(&self) -> Option<Abs> {
+ self.stroke_before.filter(|s| 2.0 * *s < self.radius)
+ }
+
+ /// Either fall back to [`Self::reuse_stroke_before_for_cap`] or zero.
fn stroke_width_after(&self) -> Abs {
self.stroke_after
- .or(self.stroke_before.filter(|_| self.radius != Abs::zero()))
+ .or(self.reuse_stroke_before_for_cap())
.unwrap_or(Abs::zero())
}
@@ -1324,9 +1336,9 @@ impl ControlPoints {
/// a default "butt" cap is used.
pub fn start_cap(&self, curve: &mut Curve, cap_type: LineCap) {
// Avoid misshaped caps on small radii.
- let small_radius = self.radius < 2.0 * self.stroke_width_after();
- if self.stroke_before.is_some()
- || cap_type == LineCap::Butt
+ let small_radius = self.reuse_stroke_after_for_cap().is_none();
+ if cap_type == LineCap::Butt
+ || self.stroke_before.is_some()
|| self.radius != Abs::zero() && small_radius
{
// Just the default cap.
@@ -1359,9 +1371,9 @@ impl ControlPoints {
/// a default "butt" cap is used.
pub fn end_cap(&self, curve: &mut Curve, cap_type: LineCap) {
// Avoid misshaped caps on small radii.
- let small_radius = self.radius < 2.0 * self.stroke_width_before();
- if self.stroke_after.is_some()
- || cap_type == LineCap::Butt
+ let small_radius = self.reuse_stroke_before_for_cap().is_none();
+ if cap_type == LineCap::Butt
+ || self.stroke_after.is_some()
|| self.radius != Abs::zero() && small_radius
{
// Just the default cap.