diff --git a/Cargo.lock b/Cargo.lock index 070a039ebb0123..2c12a1abbbd8ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5379,6 +5379,8 @@ dependencies = [ "sum_tree", "taffy", "thiserror 1.0.69", + "tiny-skia", + "tiny-skia-path", "unicode-segmentation", "usvg", "util", diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 952fed02fe88b9..49689dc2824419 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -117,6 +117,8 @@ rand.workspace = true util = { workspace = true, features = ["test-support"] } http_client = { workspace = true, features = ["test-support"] } unicode-segmentation.workspace = true +tiny-skia = "0.11.4" +tiny-skia-path = "0.11.4" [build-dependencies] embed-resource = "3.0" diff --git a/crates/gpui/examples/painting.rs b/crates/gpui/examples/painting.rs index 6b9f4952c6a2a7..56fbdf48b08780 100644 --- a/crates/gpui/examples/painting.rs +++ b/crates/gpui/examples/painting.rs @@ -115,27 +115,48 @@ impl Render for PaintingViewer { canvas( move |_, _| {}, move |_, _, cx| { - const STROKE_WIDTH: Pixels = px(2.0); + for path in default_lines { cx.paint_path(path, gpui::black()); } + + let stroke =tiny_skia::Stroke { + width: 1.0, + ..Default::default() + }; + for points in lines { - let mut path = Path::new(points[0]); + if points.len() < 2 { + continue; + } + + let mut builder = tiny_skia::PathBuilder::new(); + let first_p = points.first().unwrap(); + builder.move_to(first_p.x.0, first_p.y.0); for p in points.iter().skip(1) { - path.line_to(*p); + builder.line_to(p.x.0, p.y.0); } - let mut last = points.last().unwrap(); - for p in points.iter().rev() { - let mut offset_x = px(0.); - if last.x == p.x { - offset_x = STROKE_WIDTH; + let path = builder.finish().unwrap(); + let stroke_path = tiny_skia::PathStroker::new().stroke(&path, &stroke, cx.scale_factor()); + if let Some(stroke_path) = stroke_path { + let Some(first_p) = stroke_path.points().first() else { + break; + }; + + let mut path = Path::new(point(px(first_p.x), px(first_p.y))); + for i in 1..stroke_path.len() - 1 { + let p = stroke_path.points()[i]; + let verb = stroke_path.verbs()[i]; + match verb { + tiny_skia_path::PathVerb::Move => path.move_to(point(px(p.x), px(p.y))), + tiny_skia_path::PathVerb::Line => path.line_to(point(px(p.x), px(p.y))), + _ => {} + } } - path.line_to(point(p.x + offset_x, p.y + STROKE_WIDTH)); - last = p; + cx.paint_path(path, gpui::black()); } - cx.paint_path(path, gpui::black()); } }, ) diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index e947aee4fae1b7..cbcdf57c245e2a 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -722,15 +722,6 @@ impl Path { self.current = to; } - /// Close the current contour. - pub fn close(&mut self) { - self.contour_count += 1; - self.push_triangle( - (self.current, self.start, self.start), - (point(0., 1.), point(0., 1.), point(0., 1.)), - ); - } - /// Draw a straight line from the current point to the given point. pub fn line_to(&mut self, to: Point) { self.contour_count += 1;