Add stroke_rectangle

This method should be able to leverage performance improvements in lyon's
`tessellate_rectangle` over `tessellate_path`.
This commit is contained in:
Vlad-Stefan Harbuz 2024-06-21 10:41:17 +01:00 committed by Héctor Ramón Jiménez
parent abd323181d
commit ec39390c23
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
4 changed files with 100 additions and 0 deletions

View file

@ -65,6 +65,17 @@ where
self.raw.stroke(path, stroke); 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 /// Draws the characters of the given [`Text`] on the [`Frame`], filling
/// them with the given color. /// them with the given color.
/// ///
@ -200,6 +211,12 @@ pub trait Backend: Sized {
fn paste(&mut self, frame: Self); fn paste(&mut self, frame: Self);
fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>); 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(&mut self, path: &Path, fill: impl Into<Fill>);
fn fill_text(&mut self, text: impl Into<Text>); fn fill_text(&mut self, text: impl Into<Text>);
@ -248,6 +265,13 @@ impl Backend for () {
fn paste(&mut self, _frame: Self) {} fn paste(&mut self, _frame: Self) {}
fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {} 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(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
fn fill_text(&mut self, _text: impl Into<Text>) {} fn fill_text(&mut self, _text: impl Into<Text>) {}

View file

@ -540,6 +540,19 @@ mod geometry {
delegate!(self, frame, frame.stroke(path, stroke)); 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>) { fn fill_text(&mut self, text: impl Into<Text>) {
delegate!(self, frame, frame.fill_text(text)); delegate!(self, frame, frame.fill_text(text));
} }

View file

@ -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>) { fn fill_text(&mut self, text: impl Into<geometry::Text>) {
let text = text.into(); let text = text.into();

View file

@ -253,6 +253,44 @@ impl geometry::frame::Backend for Frame {
.expect("Stroke path"); .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>) { fn fill_text(&mut self, text: impl Into<geometry::Text>) {
let text = text.into(); let text = text.into();