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}