summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Vlad-Stefan Harbuz <vlad@vladh.net>2024-06-21 10:41:17 +0100
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-09-10 23:44:04 +0200
commitec39390c23cd46a115bb0528abdb2c5527f1272a (patch)
tree104c7209bc2c37cdd332b31d8308237461a22a63
parentabd323181d613f1dc69b6cbe885dce556f427de2 (diff)
downloadiced-ec39390c23cd46a115bb0528abdb2c5527f1272a.tar.gz
iced-ec39390c23cd46a115bb0528abdb2c5527f1272a.tar.bz2
iced-ec39390c23cd46a115bb0528abdb2c5527f1272a.zip
Add stroke_rectangle
This method should be able to leverage performance improvements in lyon's `tessellate_rectangle` over `tessellate_path`.
-rw-r--r--graphics/src/geometry/frame.rs24
-rw-r--r--renderer/src/fallback.rs13
-rw-r--r--tiny_skia/src/geometry.rs25
-rw-r--r--wgpu/src/geometry.rs38
4 files changed, 100 insertions, 0 deletions
diff --git a/graphics/src/geometry/frame.rs b/graphics/src/geometry/frame.rs
index b5f2f139..3dee7e75 100644
--- a/graphics/src/geometry/frame.rs
+++ b/graphics/src/geometry/frame.rs
@@ -65,6 +65,17 @@ where
self.raw.stroke(path, stroke);
}
+ /// Draws the stroke of an axis-aligned rectangle with the provided style
+ /// given its top-left corner coordinate and its `Size` on the [`Frame`] .
+ pub fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ ) {
+ self.raw.stroke_rectangle(top_left, size, stroke);
+ }
+
/// Draws the characters of the given [`Text`] on the [`Frame`], filling
/// them with the given color.
///
@@ -200,6 +211,12 @@ pub trait Backend: Sized {
fn paste(&mut self, frame: Self);
fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>);
+ fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ );
fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
fn fill_text(&mut self, text: impl Into<Text>);
@@ -248,6 +265,13 @@ impl Backend for () {
fn paste(&mut self, _frame: Self) {}
fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
+ fn stroke_rectangle<'a>(
+ &mut self,
+ _top_left: Point,
+ _size: Size,
+ _stroke: impl Into<Stroke<'a>>,
+ ) {
+ }
fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
fn fill_text(&mut self, _text: impl Into<Text>) {}
diff --git a/renderer/src/fallback.rs b/renderer/src/fallback.rs
index fbd285db..8cb18bde 100644
--- a/renderer/src/fallback.rs
+++ b/renderer/src/fallback.rs
@@ -540,6 +540,19 @@ mod geometry {
delegate!(self, frame, frame.stroke(path, stroke));
}
+ fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ ) {
+ delegate!(
+ self,
+ frame,
+ frame.stroke_rectangle(top_left, size, stroke)
+ );
+ }
+
fn fill_text(&mut self, text: impl Into<Text>) {
delegate!(self, frame, frame.fill_text(text));
}
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index 659612d1..532a53cd 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -168,6 +168,31 @@ impl geometry::frame::Backend for Frame {
});
}
+ fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ ) {
+ let Some(path) = convert_path(&Path::rectangle(top_left, size))
+ .and_then(|path| path.transform(self.transform))
+ else {
+ return;
+ };
+
+ let stroke = stroke.into();
+ let skia_stroke = into_stroke(&stroke);
+
+ let mut paint = into_paint(stroke.style);
+ paint.shader.transform(self.transform);
+
+ self.primitives.push(Primitive::Stroke {
+ path,
+ paint,
+ stroke: skia_stroke,
+ });
+ }
+
fn fill_text(&mut self, text: impl Into<geometry::Text>) {
let text = text.into();
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs
index be65ba36..8e6f77d7 100644
--- a/wgpu/src/geometry.rs
+++ b/wgpu/src/geometry.rs
@@ -253,6 +253,44 @@ impl geometry::frame::Backend for Frame {
.expect("Stroke path");
}
+ fn stroke_rectangle<'a>(
+ &mut self,
+ top_left: Point,
+ size: Size,
+ stroke: impl Into<Stroke<'a>>,
+ ) {
+ let stroke = stroke.into();
+
+ let mut buffer = self
+ .buffers
+ .get_stroke(&self.transforms.current.transform_style(stroke.style));
+
+ let top_left = self
+ .transforms
+ .current
+ .0
+ .transform_point(lyon::math::Point::new(top_left.x, top_left.y));
+
+ let size =
+ self.transforms.current.0.transform_vector(
+ lyon::math::Vector::new(size.width, size.height),
+ );
+
+ let mut options = tessellation::StrokeOptions::default();
+ options.line_width = stroke.width;
+ options.start_cap = into_line_cap(stroke.line_cap);
+ options.end_cap = into_line_cap(stroke.line_cap);
+ options.line_join = into_line_join(stroke.line_join);
+
+ self.stroke_tessellator
+ .tessellate_rectangle(
+ &lyon::math::Box2D::new(top_left, top_left + size),
+ &options,
+ buffer.as_mut(),
+ )
+ .expect("Stroke rectangle");
+ }
+
fn fill_text(&mut self, text: impl Into<geometry::Text>) {
let text = text.into();