summaryrefslogtreecommitdiff
path: root/library/src/visualize
diff options
context:
space:
mode:
Diffstat (limited to 'library/src/visualize')
-rw-r--r--library/src/visualize/mod.rs2
-rw-r--r--library/src/visualize/polygon.rs71
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))
+ }
+}