1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::{
options::{Options, StrokeOptions},
tess, PolyBuilder,
};
use gee::{LineSegment, Point, Rect};
#[derive(Clone, Debug, Default)]
pub struct FreePolyBuilder {
points: Vec<tess::geom::Point<f32>>,
open: bool,
bounding_rect: Option<Rect>,
options: Options,
}
impl FreePolyBuilder {
pub fn new() -> Self {
Self::default()
}
pub(crate) fn from_parts(
points: impl IntoIterator<Item = Point>,
open: bool,
bounding_rect: Option<Rect>,
options: Options,
) -> Self {
Self {
open,
bounding_rect,
options,
..Self::from_points(points)
}
}
pub fn from_points(points: impl IntoIterator<Item = Point>) -> Self {
Self::default().with_points(points.into_iter().map(Into::into))
}
pub fn from_line_segments(lines: impl IntoIterator<Item = LineSegment>) -> Self {
Self::default().with_line_segments(lines)
}
pub fn with_point(mut self, point: Point) -> Self {
self.points.push(point.into());
self.bounding_rect = self
.bounding_rect
.map(|bounding_rect| bounding_rect.grow_to(point))
.or_else(|| {
if self.points.len() == 2 {
Some(Rect::from_points(
self.points[0].into(),
self.points[1].into(),
))
} else {
None
}
});
self
}
pub fn with_points(self, points: impl IntoIterator<Item = Point>) -> Self {
points
.into_iter()
.fold(self, |this, point| this.with_point(point))
}
pub fn with_line_segment(self, line: LineSegment) -> Self {
self.with_points(line.points())
}
pub fn with_line_segments(self, lines: impl IntoIterator<Item = LineSegment>) -> Self {
self.with_points(lines.into_iter().flat_map(|line| line.points()))
}
pub fn with_stroke(mut self, stroke_width: f32, open: bool) -> Self {
self.open = open;
self._with_stroke(stroke_width)
}
pub fn with_stroke_open(self, stroke_width: f32) -> Self {
self.with_stroke(stroke_width, true)
}
pub fn with_stroke_closed(self, stroke_width: f32) -> Self {
self.with_stroke(stroke_width, false)
}
pub fn with_stroke_opts(mut self, stroke_options: StrokeOptions, open: bool) -> Self {
self.open = open;
self._with_stroke_opts(stroke_options)
}
pub fn with_stroke_opts_open(self, stroke_options: StrokeOptions) -> Self {
self.with_stroke_opts(stroke_options, true)
}
pub fn with_stroke_opts_closed(self, stroke_options: StrokeOptions) -> Self {
self.with_stroke_opts(stroke_options, false)
}
stroke!(private);
fill!();
build!();
}
impl PolyBuilder for FreePolyBuilder {
fn options(&self) -> &Options {
&self.options
}
fn bounding_rect(&self) -> Rect {
self.bounding_rect.unwrap_or_default()
}
fn build<B: tess::path::traits::PathBuilder>(self, builder: &mut B) {
builder.add_polygon(tess::path::Polygon {
points: &self.points,
closed: !self.open,
});
}
}