@@ -27,10 +27,15 @@ impl PaintingViewer {
// draw a lightening bolt ⚡
let mut builder = PathBuilder::fill();
- builder.move_to(point(px(150.), px(200.)));
- builder.line_to(point(px(200.), px(125.)));
- builder.line_to(point(px(200.), px(175.)));
- builder.line_to(point(px(250.), px(100.)));
+ builder.add_polygon(
+ &[
+ point(px(150.), px(200.)),
+ point(px(200.), px(125.)),
+ point(px(200.), px(175.)),
+ point(px(250.), px(100.)),
+ ],
+ false,
+ );
let path = builder.build().unwrap();
lines.push((path, rgb(0x1d4ed8).into()));
@@ -58,6 +63,7 @@ impl PaintingViewer {
.color_space(ColorSpace::Oklab),
));
+ // draw linear gradient
let square_bounds = Bounds {
origin: point(px(450.), px(100.)),
size: size(px(200.), px(80.)),
@@ -87,6 +93,47 @@ impl PaintingViewer {
),
));
+ // draw a pie chart
+ let center = point(px(96.), px(96.));
+ let pie_center = point(px(775.), px(155.));
+ let segments = [
+ (
+ point(px(871.), px(155.)),
+ point(px(747.), px(63.)),
+ rgb(0x1374e9),
+ ),
+ (
+ point(px(747.), px(63.)),
+ point(px(679.), px(163.)),
+ rgb(0xe13527),
+ ),
+ (
+ point(px(679.), px(163.)),
+ point(px(754.), px(249.)),
+ rgb(0x0751ce),
+ ),
+ (
+ point(px(754.), px(249.)),
+ point(px(854.), px(210.)),
+ rgb(0x209742),
+ ),
+ (
+ point(px(854.), px(210.)),
+ point(px(871.), px(155.)),
+ rgb(0xfbc10a),
+ ),
+ ];
+
+ for (start, end, color) in segments {
+ let mut builder = PathBuilder::fill();
+ builder.move_to(start);
+ builder.arc_to(center, px(0.), false, false, end);
+ builder.line_to(pie_center);
+ builder.close();
+ let path = builder.build().unwrap();
+ lines.push((path, color.into()));
+ }
+
// draw a wave
let options = StrokeOptions::default()
.with_line_width(1.)
@@ -1,6 +1,9 @@
use anyhow::Error;
-use etagere::euclid::Vector2D;
+use etagere::euclid::{Point2D, Vector2D};
use lyon::geom::Angle;
+use lyon::math::{Vector, vector};
+use lyon::path::traits::SvgPathBuilder;
+use lyon::path::{ArcFlags, Polygon};
use lyon::tessellation::{
BuffersBuilder, FillTessellator, FillVertex, StrokeTessellator, StrokeVertex, VertexBuffers,
};
@@ -56,6 +59,18 @@ impl From<Point<Pixels>> for lyon::math::Point {
}
}
+impl From<Point<Pixels>> for Vector {
+ fn from(p: Point<Pixels>) -> Self {
+ vector(p.x.0, p.y.0)
+ }
+}
+
+impl From<Point<Pixels>> for Point2D<f32, Pixels> {
+ fn from(p: Point<Pixels>) -> Self {
+ Point2D::new(p.x.0, p.y.0)
+ }
+}
+
impl Default for PathBuilder {
fn default() -> Self {
Self {
@@ -116,6 +131,49 @@ impl PathBuilder {
.cubic_bezier_to(control_a.into(), control_b.into(), to.into());
}
+ /// Adds an elliptical arc.
+ pub fn arc_to(
+ &mut self,
+ radii: Point<Pixels>,
+ x_rotation: Pixels,
+ large_arc: bool,
+ sweep: bool,
+ to: Point<Pixels>,
+ ) {
+ self.raw.arc_to(
+ radii.into(),
+ Angle::degrees(x_rotation.into()),
+ ArcFlags { large_arc, sweep },
+ to.into(),
+ );
+ }
+
+ /// Equivalent to `arc_to` in relative coordinates.
+ pub fn relative_arc_to(
+ &mut self,
+ radii: Point<Pixels>,
+ x_rotation: Pixels,
+ large_arc: bool,
+ sweep: bool,
+ to: Point<Pixels>,
+ ) {
+ self.raw.relative_arc_to(
+ radii.into(),
+ Angle::degrees(x_rotation.into()),
+ ArcFlags { large_arc, sweep },
+ to.into(),
+ );
+ }
+
+ /// Adds a polygon.
+ pub fn add_polygon(&mut self, points: &[Point<Pixels>], closed: bool) {
+ let points = points.iter().copied().map(|p| p.into()).collect::<Vec<_>>();
+ self.raw.add_polygon(Polygon {
+ points: points.as_ref(),
+ closed,
+ });
+ }
+
/// Close the current sub-path.
#[inline]
pub fn close(&mut self) {