mirror of
https://github.com/penpot/penpot.git
synced 2026-10-09 20:26:17 +00:00
🐛 Fix inner and outer rect strokes ignoring corner radius (#11926)
This commit is contained in:
parent
98daf1592d
commit
4943285e63
@ -40,9 +40,12 @@ pub(super) fn draw_stroke_on_rect(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Radii as Skia fits them to the shape, so the stroke follows the fill.
|
||||||
|
let shape_radii = corners.map(|radii| *RRect::new_rect_radii(*rect, &radii).radii_ref());
|
||||||
|
|
||||||
// By default just draw the rect. Only dotted inner/outer strokes need
|
// By default just draw the rect. Only dotted inner/outer strokes need
|
||||||
// clipping to prevent the dotted pattern from appearing in wrong areas.
|
// clipping to prevent the dotted pattern from appearing in wrong areas.
|
||||||
let draw_stroke = || match corners {
|
let draw_stroke = || match &shape_radii {
|
||||||
Some(radii) => {
|
Some(radii) => {
|
||||||
let radii = stroke.outer_corners(radii);
|
let radii = stroke.outer_corners(radii);
|
||||||
let rrect = RRect::new_rect_radii(stroke_rect, &radii);
|
let rrect = RRect::new_rect_radii(stroke_rect, &radii);
|
||||||
@ -73,10 +76,13 @@ pub(super) fn draw_stroke_on_rect(
|
|||||||
draw_stroke();
|
draw_stroke();
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
} else if stroke.kind == StrokeKind::Inner
|
} else if stroke.kind == StrokeKind::Inner
|
||||||
&& (stroke.width >= rect.width() || stroke.width >= rect.height())
|
&& (stroke.width >= rect.width()
|
||||||
|
|| stroke.width >= rect.height()
|
||||||
|
|| inner_corners_collapse(stroke, rect, &shape_radii))
|
||||||
{
|
{
|
||||||
// When the inner stroke width exceeds a shape dimension, the inset
|
// When the inner stroke width exceeds a shape dimension, the inset
|
||||||
// rect goes negative and the stroke overflows outside the shape.
|
// rect goes negative and the stroke overflows outside the shape.
|
||||||
|
// Same when the inset radii can't follow the shape corners.
|
||||||
// Fall back to the same approach as the SVG renderer: draw with
|
// Fall back to the same approach as the SVG renderer: draw with
|
||||||
// doubled width centered on the original shape and clip to it.
|
// doubled width centered on the original shape and clip to it.
|
||||||
canvas.save();
|
canvas.save();
|
||||||
@ -106,6 +112,22 @@ pub(super) fn draw_stroke_on_rect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the inset radii clamp to zero or get rescaled by Skia to fit.
|
||||||
|
fn inner_corners_collapse(stroke: &Stroke, rect: &Rect, radii: &Option<Corners>) -> bool {
|
||||||
|
let Some(radii) = radii else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if matches!(stroke.style, StrokeStyle::Dotted | StrokeStyle::Dashed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let wanted = stroke.outer_corners(radii);
|
||||||
|
let inset = RRect::new_rect_radii(stroke.outer_rect(rect), &wanted);
|
||||||
|
radii
|
||||||
|
.iter()
|
||||||
|
.zip(wanted.iter().zip(inset.radii_ref()))
|
||||||
|
.any(|(shape, (want, got))| shape.x > 0.0 && (want.x <= 0.0 || want != got))
|
||||||
|
}
|
||||||
|
|
||||||
/// Draws a rect/frame stroke whose sides have different widths as the area
|
/// Draws a rect/frame stroke whose sides have different widths as the area
|
||||||
/// between an outer and an inner (rounded) rect, mitered like CSS borders.
|
/// between an outer and an inner (rounded) rect, mitered like CSS borders.
|
||||||
/// Dashed/dotted styles cut that band per side, each side fitting a whole
|
/// Dashed/dotted styles cut that band per side, each side fitting a whole
|
||||||
|
|||||||
@ -358,7 +358,9 @@ impl Stroke {
|
|||||||
|
|
||||||
let mut outer = *corners;
|
let mut outer = *corners;
|
||||||
for corner in outer.iter_mut() {
|
for corner in outer.iter_mut() {
|
||||||
corner.offset((offset, offset))
|
if corner.x > 0.0 {
|
||||||
|
corner.offset((offset, offset))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
outer
|
outer
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user