lyon_path/
private.rs

1#![allow(clippy::too_many_arguments)]
2
3// This module contains a few helpers that should not be considered as part of the public API,
4// but are exposed for use by other lyon crates.
5// Changing them doesn't necessarily imply semver breaking bumps.
6
7pub use crate::geom::{CubicBezierSegment, QuadraticBezierSegment};
8pub use crate::math::Point;
9pub use crate::traits::PathBuilder;
10pub use crate::{Attributes, EndpointId};
11
12#[derive(Default, Copy, Clone, Debug, PartialEq)]
13pub struct DebugValidator {
14    #[cfg(debug_assertions)]
15    in_subpath: bool,
16}
17
18impl DebugValidator {
19    #[inline(always)]
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    #[inline(always)]
25    pub fn begin(&mut self) {
26        #[cfg(debug_assertions)]
27        {
28            assert!(!self.in_subpath, "multiple begin() calls without end()");
29            self.in_subpath = true;
30        }
31    }
32
33    #[inline(always)]
34    pub fn end(&mut self) {
35        #[cfg(debug_assertions)]
36        {
37            assert!(self.in_subpath, "end() called without begin()");
38            self.in_subpath = false;
39        }
40    }
41
42    #[inline(always)]
43    pub fn edge(&self) {
44        #[cfg(debug_assertions)]
45        assert!(self.in_subpath, "edge operation is made before begin()");
46    }
47
48    /// TODO: this should consume `self` to ensure it is dropped after this call
49    /// TODO: also, DebugValidator probably should not be exposed in the public API.
50    #[inline(always)]
51    pub fn build(&self) {
52        #[cfg(debug_assertions)]
53        assert!(!self.in_subpath, "build() called before end()");
54    }
55}
56
57pub fn flatten_quadratic_bezier(
58    tolerance: f32,
59    from: Point,
60    ctrl: Point,
61    to: Point,
62    attributes: Attributes,
63    prev_attributes: Attributes,
64    builder: &mut impl PathBuilder,
65    buffer: &mut [f32],
66) -> EndpointId {
67    let curve = QuadraticBezierSegment { from, ctrl, to };
68    let n = attributes.len();
69    let mut id = EndpointId::INVALID;
70    curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
71        let attr = if t.end == 1.0 {
72            attributes
73        } else {
74            for i in 0..n {
75                buffer[i] = prev_attributes[i] * (1.0 - t.end) + attributes[i] * t.end;
76            }
77            // BUG: https://github.com/rust-lang/rust-clippy/issues/10608
78            #[allow(clippy::redundant_slicing)]
79            &buffer[..]
80        };
81        id = builder.line_to(line.to, attr);
82    });
83
84    id
85}
86
87pub fn flatten_cubic_bezier(
88    tolerance: f32,
89    from: Point,
90    ctrl1: Point,
91    ctrl2: Point,
92    to: Point,
93    attributes: Attributes,
94    prev_attributes: Attributes,
95    builder: &mut impl PathBuilder,
96    buffer: &mut [f32],
97) -> EndpointId {
98    let curve = CubicBezierSegment {
99        from,
100        ctrl1,
101        ctrl2,
102        to,
103    };
104    let n = attributes.len();
105    let mut id = EndpointId::INVALID;
106    curve.for_each_flattened_with_t(tolerance, &mut |line, t| {
107        let attr = if t.end == 1.0 {
108            attributes
109        } else {
110            for i in 0..n {
111                buffer[i] = prev_attributes[i] * (1.0 - t.end) + attributes[i] * t.end;
112            }
113            // BUG: https://github.com/rust-lang/rust-clippy/issues/10608
114            #[allow(clippy::redundant_slicing)]
115            &buffer[..]
116        };
117        id = builder.line_to(line.to, attr);
118    });
119
120    id
121}