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
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2025 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Turning shapes into Bézier paths without approximation.
use ;
use ;
/// A generic trait for shapes that can be mapped exactly to Bézier path elements (i.e., without
/// approximation).
///
/// The methods on [`PaintScene`](crate::PaintScene) use this trait ensure that consistent behaviour
/// is maintained when Vello API is used to render content which might be rescaled.
///
/// This is implemented for [`Shape`]s from Kurbo that can be exactly mapped to Bézier path elements.
/// To convert a [`Shape`] which requires approximation (such as [`Circle`](kurbo::Circle) or
/// [`RoundedRect`](kurbo::RoundedRect)), you can use [`within`].
/// This however requires you to provide the tolerance.
/// See the docs of `within` for more details.
///
/// It is a requirement of this trait that [`Shape::path_elements`] returns the same iterator
/// as [`ExactPathElements::exact_path_elements`] for any provided tolerance value.
/// Use an approximated shape where an [`ExactPathElements`] is required, by approximating it to
/// within the given tolerance.
///
/// *WARNING*: Unlike [`ExactPathElements`], which will produce correct renderings for any scale, this
/// approximation is only valid for a fixed range of transforms.
///
/// As the user of this function, you are responsible for determining the correct tolerance for your use case.
/// A reasonable approach might be to select a tolerance which allows scaling up ("zooming in") by 4x (for example;
/// you should evaluate the correct value yourself) and remaining within your intended tolerance bound.
/// If the user zoomed past that limit, you would then recomputing the [`Scene`](crate::Scene) from your base data representation once that is exceeded.
/// If you know that the shape will not be scaled, you can use [`UNSCALED_TOLERANCE`].
/// The resulting path will be within 1/10th of a pixel of the actual shape, which is a negligible
/// difference for rendering.
///
/// This is useful for drawing shapes such as [`Circle`](kurbo::Circle)s and [`RoundedRect`](kurbo::RoundedRect)s.
// TODO: Provide as an extension trait?
/// The type used to implement [`within`].
/// The recommended tolerance for approximating shapes which won't be rescaled as Bezier paths.
///
/// This can be used as the tolerance parameter to [`within`], when you know that
/// a shape will be drawn at its natural size, without scaling or skew.
pub const UNSCALED_TOLERANCE: f64 = 0.1;
// TODO: Provide an `fn ideal_tolerance(transform: Affine) -> f64`
/// Implement `ExactPathElements` for an existing [`Shape`], which we know will not be approximated in Kurbo.
// In theory, the impl is the wrong way around; instead the `Shape` impl should be in terms of `ExactPathElements`.
passthrough!;
passthrough!;
passthrough!;
passthrough!;
passthrough!;
passthrough!;