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
123
124
125
126
127
128
#![allow(clippy::too_many_arguments)]
pub use crate::geom::{CubicBezierSegment, QuadraticBezierSegment};
pub use crate::math::Point;
pub use crate::traits::PathBuilder;
pub use crate::{Attributes, EndpointId};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DebugValidator {
#[cfg(debug_assertions)]
in_subpath: bool,
}
impl Default for DebugValidator {
fn default() -> Self {
Self::new()
}
}
impl DebugValidator {
#[inline(always)]
pub fn new() -> Self {
DebugValidator {
#[cfg(debug_assertions)]
in_subpath: false,
}
}
#[inline(always)]
pub fn begin(&mut self) {
#[cfg(debug_assertions)]
{
assert!(!self.in_subpath);
self.in_subpath = true;
}
}
#[inline(always)]
pub fn end(&mut self) {
#[cfg(debug_assertions)]
{
assert!(self.in_subpath);
self.in_subpath = false;
}
}
#[inline(always)]
pub fn edge(&self) {
#[cfg(debug_assertions)]
{
assert!(self.in_subpath);
}
}
#[inline(always)]
pub fn build(&self) {
#[cfg(debug_assertions)]
{
assert!(!self.in_subpath);
}
}
}
pub fn flatten_quadratic_bezier(
tolerance: f32,
from: Point,
ctrl: Point,
to: Point,
attributes: Attributes,
prev_attributes: Attributes,
builder: &mut impl PathBuilder,
buffer: &mut [f32],
) -> EndpointId {
let curve = QuadraticBezierSegment { from, ctrl, to };
let n = attributes.len();
let mut id = EndpointId::INVALID;
curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
let attr = if t.end == 1.0 {
attributes
} else {
for i in 0..n {
buffer[i] = prev_attributes[i] * (1.0 - t.end) + attributes[i] * t.end;
}
&buffer[..]
};
id = builder.line_to(line.to, attr);
});
id
}
pub fn flatten_cubic_bezier(
tolerance: f32,
from: Point,
ctrl1: Point,
ctrl2: Point,
to: Point,
attributes: Attributes,
prev_attributes: Attributes,
builder: &mut impl PathBuilder,
buffer: &mut [f32],
) -> EndpointId {
let curve = CubicBezierSegment {
from,
ctrl1,
ctrl2,
to,
};
let n = attributes.len();
let mut id = EndpointId::INVALID;
curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
let attr = if t.end == 1.0 {
attributes
} else {
for i in 0..n {
buffer[i] = prev_attributes[i] * (1.0 - t.end) + attributes[i] * t.end;
}
&buffer[..]
};
id = builder.line_to(line.to, attr);
});
id
}