geometry.rs

  1use super::scene::{Path, PathVertex};
  2use crate::color::ColorU;
  3pub use pathfinder_geometry::*;
  4use rect::RectF;
  5use vector::{vec2f, Vector2F};
  6
  7pub struct PathBuilder {
  8    vertices: Vec<PathVertex>,
  9    start: Vector2F,
 10    current: Vector2F,
 11    contour_count: usize,
 12    bounds: RectF,
 13}
 14
 15enum PathVertexKind {
 16    Solid,
 17    Quadratic,
 18}
 19
 20impl PathBuilder {
 21    pub fn new() -> Self {
 22        Self {
 23            vertices: Vec::new(),
 24            start: vec2f(0., 0.),
 25            current: vec2f(0., 0.),
 26            contour_count: 0,
 27            bounds: RectF::default(),
 28        }
 29    }
 30
 31    pub fn reset(&mut self, point: Vector2F) {
 32        self.vertices.clear();
 33        self.start = point;
 34        self.current = point;
 35        self.contour_count = 0;
 36    }
 37
 38    pub fn line_to(&mut self, point: Vector2F) {
 39        self.contour_count += 1;
 40        if self.contour_count > 1 {
 41            self.push_triangle(self.start, self.current, point, PathVertexKind::Solid);
 42        }
 43
 44        self.current = point;
 45    }
 46
 47    pub fn curve_to(&mut self, point: Vector2F, ctrl: Vector2F) {
 48        self.contour_count += 1;
 49        if self.contour_count > 1 {
 50            self.push_triangle(self.start, self.current, point, PathVertexKind::Solid);
 51        }
 52
 53        self.push_triangle(self.current, ctrl, point, PathVertexKind::Quadratic);
 54        self.current = point;
 55    }
 56
 57    pub fn build(mut self, color: ColorU, clip_bounds: Option<RectF>) -> Path {
 58        if let Some(clip_bounds) = clip_bounds {
 59            self.bounds = self
 60                .bounds
 61                .intersection(clip_bounds)
 62                .unwrap_or(RectF::default());
 63        }
 64        Path {
 65            bounds: self.bounds,
 66            color,
 67            vertices: self.vertices,
 68        }
 69    }
 70
 71    fn push_triangle(&mut self, a: Vector2F, b: Vector2F, c: Vector2F, kind: PathVertexKind) {
 72        if self.vertices.is_empty() {
 73            self.bounds = RectF::new(a, Vector2F::zero());
 74        }
 75        self.bounds = self.bounds.union_point(a).union_point(b).union_point(c);
 76
 77        match kind {
 78            PathVertexKind::Solid => {
 79                self.vertices.push(PathVertex {
 80                    xy_position: a,
 81                    st_position: vec2f(0., 1.),
 82                });
 83                self.vertices.push(PathVertex {
 84                    xy_position: b,
 85                    st_position: vec2f(0., 1.),
 86                });
 87                self.vertices.push(PathVertex {
 88                    xy_position: c,
 89                    st_position: vec2f(0., 1.),
 90                });
 91            }
 92            PathVertexKind::Quadratic => {
 93                self.vertices.push(PathVertex {
 94                    xy_position: a,
 95                    st_position: vec2f(0., 0.),
 96                });
 97                self.vertices.push(PathVertex {
 98                    xy_position: b,
 99                    st_position: vec2f(0.5, 0.),
100                });
101                self.vertices.push(PathVertex {
102                    xy_position: c,
103                    st_position: vec2f(1., 1.),
104                });
105            }
106        }
107    }
108}