mirror of
https://github.com/penpot/penpot.git
synced 2025-01-20 13:42:59 -05:00
🐛 Open paths should always be rendered with center alignment
This commit is contained in:
parent
de0eee13af
commit
98806defbf
3 changed files with 37 additions and 15 deletions
|
@ -73,6 +73,7 @@ impl TryFrom<RawPathData> for Segment {
|
|||
pub struct Path {
|
||||
segments: Vec<Segment>,
|
||||
skia_path: skia::Path,
|
||||
open: bool,
|
||||
}
|
||||
|
||||
fn starts_and_ends_at_same_point(path: &skia::Path) -> bool {
|
||||
|
@ -91,6 +92,7 @@ impl TryFrom<Vec<RawPathData>> for Path {
|
|||
type Error = String;
|
||||
|
||||
fn try_from(value: Vec<RawPathData>) -> Result<Self, Self::Error> {
|
||||
let mut open = true;
|
||||
let segments = value
|
||||
.into_iter()
|
||||
.map(|raw| Segment::try_from(raw))
|
||||
|
@ -110,17 +112,20 @@ impl TryFrom<Vec<RawPathData>> for Path {
|
|||
}
|
||||
Segment::Close => {
|
||||
skia_path.close();
|
||||
open = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !skia_path.is_last_contour_closed() && starts_and_ends_at_same_point(&skia_path) {
|
||||
skia_path.close();
|
||||
open = false;
|
||||
}
|
||||
|
||||
Ok(Path {
|
||||
segments,
|
||||
skia_path,
|
||||
open,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -129,4 +134,8 @@ impl Path {
|
|||
pub fn to_skia_path(&self) -> skia::Path {
|
||||
self.skia_path.snapshot()
|
||||
}
|
||||
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.open
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ fn render_stroke(
|
|||
Kind::Rect(rect) => draw_stroke_on_rect(surface.canvas(), stroke, rect, &selrect),
|
||||
Kind::Circle(rect) => draw_stroke_on_circle(surface.canvas(), stroke, rect, &selrect),
|
||||
Kind::Path(path) => {
|
||||
draw_stroke_on_path(surface.canvas(), stroke, path, &selrect, path_transform)
|
||||
draw_stroke_on_path(surface.canvas(), stroke, path, &selrect, path_transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,9 +165,10 @@ fn draw_stroke_on_path(
|
|||
let mut skia_path = path.to_skia_path();
|
||||
skia_path.transform(path_transform.unwrap());
|
||||
|
||||
let paint_stroke = stroke.to_stroked_paint(selrect);
|
||||
let kind = stroke.render_kind(path.is_open());
|
||||
let paint_stroke = stroke.to_stroked_paint(kind.clone(), selrect);
|
||||
// Draw the different kind of strokes for a path requires different strategies:
|
||||
match stroke.kind {
|
||||
match kind {
|
||||
// For inner stroke we draw a center stroke (with double width) and clip to the original path (that way the extra outer stroke is removed)
|
||||
StrokeKind::InnerStroke => {
|
||||
canvas.clip_path(&skia_path, skia::ClipOp::Intersect, true);
|
||||
|
@ -288,10 +289,11 @@ pub fn draw_image_stroke_in_container(
|
|||
Kind::Path(p) => {
|
||||
let mut path = p.to_skia_path();
|
||||
path.transform(path_transform.unwrap());
|
||||
if stroke.kind == StrokeKind::InnerStroke {
|
||||
let stroke_kind = stroke.render_kind(p.is_open());
|
||||
if stroke_kind == StrokeKind::InnerStroke {
|
||||
canvas.clip_path(&path, skia::ClipOp::Intersect, true);
|
||||
}
|
||||
let paint = stroke.to_stroked_paint(&outer_rect);
|
||||
let paint = stroke.to_stroked_paint(stroke_kind, &outer_rect);
|
||||
canvas.draw_path(&path, &paint);
|
||||
}
|
||||
}
|
||||
|
@ -317,13 +319,15 @@ pub fn draw_image_stroke_in_container(
|
|||
canvas.draw_image_rect(image, None, dest_rect, &image_paint);
|
||||
|
||||
// Clear outer stroke for paths if necessary. When adding an outer stroke we need to empty the stroke added too in the inner area.
|
||||
if let (Kind::Path(p), StrokeKind::OuterStroke) = (kind, &stroke.kind) {
|
||||
let mut path = p.to_skia_path();
|
||||
path.transform(path_transform.unwrap());
|
||||
let mut clear_paint = skia::Paint::default();
|
||||
clear_paint.set_blend_mode(skia::BlendMode::Clear);
|
||||
clear_paint.set_anti_alias(true);
|
||||
canvas.draw_path(&path, &clear_paint);
|
||||
if let Kind::Path(p) = kind {
|
||||
if stroke.render_kind(p.is_open()) == StrokeKind::OuterStroke {
|
||||
let mut path = p.to_skia_path();
|
||||
path.transform(path_transform.unwrap());
|
||||
let mut clear_paint = skia::Paint::default();
|
||||
clear_paint.set_blend_mode(skia::BlendMode::Clear);
|
||||
clear_paint.set_anti_alias(true);
|
||||
canvas.draw_path(&path, &clear_paint);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore canvas state
|
||||
|
|
|
@ -46,10 +46,19 @@ pub struct Stroke {
|
|||
pub style: StrokeStyle,
|
||||
pub cap_end: StrokeCap,
|
||||
pub cap_start: StrokeCap,
|
||||
pub kind: StrokeKind,
|
||||
kind: StrokeKind,
|
||||
}
|
||||
|
||||
impl Stroke {
|
||||
// Strokes for open shapes should be rendered as if they were centered.
|
||||
pub fn render_kind(&self, is_open: bool) -> StrokeKind {
|
||||
if is_open {
|
||||
StrokeKind::CenterStroke
|
||||
} else {
|
||||
self.kind.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_center_stroke(width: f32, style: i32) -> Self {
|
||||
let transparent = skia::Color::from_argb(0, 0, 0, 0);
|
||||
Stroke {
|
||||
|
@ -153,9 +162,9 @@ impl Stroke {
|
|||
paint
|
||||
}
|
||||
|
||||
pub fn to_stroked_paint(&self, rect: &math::Rect) -> skia::Paint {
|
||||
pub fn to_stroked_paint(&self, kind: StrokeKind, rect: &math::Rect) -> skia::Paint {
|
||||
let mut paint = self.to_paint(rect);
|
||||
match self.kind {
|
||||
match kind {
|
||||
StrokeKind::InnerStroke => {
|
||||
paint.set_stroke_width(2. * self.width);
|
||||
paint
|
||||
|
|
Loading…
Add table
Reference in a new issue