diff options
Diffstat (limited to 'library/src/visualize')
| -rw-r--r-- | library/src/visualize/mod.rs | 2 | ||||
| -rw-r--r-- | library/src/visualize/polygon.rs | 71 |
2 files changed, 73 insertions, 0 deletions
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<Paint>, + + /// How to stroke the polygon. See the [lines's + /// documentation]($func/line.stroke) for more details. + #[resolve] + #[fold] + pub stroke: Option<PartialStroke>, + + /// The vertices of the polygon. The polygon automatically closes itself. + #[variadic] + pub vertices: Vec<Axes<Rel<Length>>>, +} + +impl Layout for PolygonElem { + fn layout( + &self, + _: &mut Vt, + styles: StyleChain, + regions: Regions, + ) -> SourceResult<Fragment> { + let points: Vec<Point> = 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)) + } +} |
