From 44165d09a9e6c09d4c5a9dbeab1af7f23e3d887a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olle=20L=C3=B6gdahl?= Date: Tue, 28 Mar 2023 16:43:16 +0200 Subject: Add polygon drawing primitive (#314) --- library/src/lib.rs | 1 + library/src/visualize/mod.rs | 2 ++ library/src/visualize/polygon.rs | 71 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 library/src/visualize/polygon.rs (limited to 'library/src') diff --git a/library/src/lib.rs b/library/src/lib.rs index 1a998700..178db8a2 100644 --- a/library/src/lib.rs +++ b/library/src/lib.rs @@ -83,6 +83,7 @@ fn global(math: Module, calc: Module) -> Module { global.define("square", visualize::SquareElem::func()); global.define("ellipse", visualize::EllipseElem::func()); global.define("circle", visualize::CircleElem::func()); + global.define("polygon", visualize::PolygonElem::func()); // Meta. global.define("document", meta::DocumentElem::func()); diff --git a/library/src/visualize/mod.rs b/library/src/visualize/mod.rs index 1c87eeb3..198c707d 100644 --- a/library/src/visualize/mod.rs +++ b/library/src/visualize/mod.rs @@ -3,7 +3,9 @@ mod image; mod line; mod shape; +mod polygon; pub use self::image::*; pub use self::line::*; pub use self::shape::*; +pub use self::polygon::*; \ No newline at end of file diff --git a/library/src/visualize/polygon.rs b/library/src/visualize/polygon.rs new file mode 100644 index 00000000..40058834 --- /dev/null +++ b/library/src/visualize/polygon.rs @@ -0,0 +1,71 @@ +use crate::prelude::*; + +/// A closed-path polygon. +/// +/// ## Example +/// ```example +/// #polygon(fill: blue, (0pt, 0pt), (10pt, 0pt), (10pt, 10pt)) +/// ``` +/// +/// Display: Polygon +/// Category: visualize +#[element(Layout)] +pub struct PolygonElem { + /// How to fill the polygon. See the + /// [rectangle's documentation]($func/rect.fill) for more details. + pub fill: Option, + + /// How to stroke the polygon. See the [lines's + /// documentation]($func/line.stroke) for more details. + #[resolve] + #[fold] + pub stroke: Option, + + /// The vertices of the polygon. The polygon automatically closes itself. + #[variadic] + pub vertices: Vec>>, +} + +impl Layout for PolygonElem { + fn layout( + &self, + _: &mut Vt, + styles: StyleChain, + regions: Regions, + ) -> SourceResult { + let points: Vec = self + .vertices() + .iter() + .map(|c| { + c.resolve(styles) + .zip(regions.base()) + .map(|(l, b)| l.relative_to(b)) + .to_point() + }) + .collect(); + + let size = points.iter().fold(Point::zero(), |max, c| c.max(max)).to_size(); + + let target = regions.expand.select(regions.size, size); + let mut frame = Frame::new(target); + + // only create a path if there is more than zero points. + if points.len() > 0 { + let stroke = self.stroke(styles).map(|e| e.unwrap_or_default()); + let fill = self.fill(styles); + + // construct a closed path given all points. + let mut path = Path::new(); + path.move_to(points[0]); + for point in &points[1..] { + path.line_to(*point); + } + path.close_path(); + + let shape = Shape { geometry: Geometry::Path(path), stroke, fill }; + frame.push(Point::zero(), FrameItem::Shape(shape, self.span())); + } + + Ok(Fragment::frame(frame)) + } +} -- cgit v1.2.3