vello_common/
transforms.rs1use crate::kurbo::Affine;
7use smallvec::{SmallVec, smallvec};
8
9#[derive(Debug, Clone)]
11pub struct Transforms {
12 transform: Affine,
13 paint_transform: Affine,
14}
15
16impl Default for Transforms {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl Transforms {
23 pub fn new() -> Self {
25 Self {
26 transform: Affine::IDENTITY,
27 paint_transform: Affine::IDENTITY,
28 }
29 }
30
31 pub fn transform(&self) -> &Affine {
33 &self.transform
34 }
35
36 pub fn scene_transform(&self) -> Affine {
38 self.transform
39 }
40
41 pub fn set_transform(&mut self, transform: Affine) {
43 self.transform = transform;
44 }
45
46 pub fn reset_transform(&mut self) {
48 self.transform = Affine::IDENTITY;
49 }
50
51 pub fn paint_transform(&self) -> &Affine {
53 &self.paint_transform
54 }
55
56 pub fn scene_paint_transform(&self) -> Affine {
58 self.scene_transform() * self.paint_transform
59 }
60
61 pub fn set_paint_transform(&mut self, paint_transform: Affine) {
63 self.paint_transform = paint_transform;
64 }
65
66 pub fn reset_paint_transform(&mut self) {
68 self.paint_transform = Affine::IDENTITY;
69 }
70
71 pub fn clip_path_transform(&self) -> Affine {
75 self.transform
76 }
77}
78
79#[derive(Debug)]
81pub struct RootTransforms {
82 transforms: SmallVec<[Affine; 3]>,
83}
84
85impl Default for RootTransforms {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl RootTransforms {
92 pub fn new() -> Self {
94 Self {
95 transforms: smallvec![Affine::IDENTITY],
96 }
97 }
98
99 pub fn root_transform(&self) -> Affine {
102 *self
103 .transforms
104 .last()
105 .expect("root transform stack should never be empty")
106 }
107
108 pub fn effective_path_transform(&self, transforms: &Transforms) -> Affine {
110 self.root_transform() * transforms.transform
111 }
112
113 pub fn effective_paint_transform(&self, transforms: &Transforms) -> Affine {
115 self.effective_path_transform(transforms) * transforms.paint_transform
116 }
117
118 pub fn push_root(&mut self, relative_transform: Affine) {
120 self.transforms
121 .push(relative_transform * self.root_transform());
122 }
123
124 pub fn pop_root(&mut self) {
126 self.transforms.pop();
127 }
128
129 pub fn reset(&mut self) {
131 self.transforms.clear();
132 self.transforms.push(Affine::IDENTITY);
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn root_transforms_accumulate_relative_transforms() {
142 let mut roots = RootTransforms::new();
143 let parent = Affine::translate((10.0, 20.0));
144 let child = Affine::scale(2.0);
145
146 roots.push_root(parent);
147 roots.push_root(child);
148
149 assert_eq!(roots.root_transform(), child * parent);
150 }
151
152 #[test]
153 fn pop_root_restores_parent_transform() {
154 let mut roots = RootTransforms::new();
155 let parent = Affine::translate((10.0, 20.0));
156
157 roots.push_root(parent);
158 roots.push_root(Affine::scale(2.0));
159 roots.pop_root();
160
161 assert_eq!(roots.root_transform(), parent);
162 }
163
164 #[test]
165 fn effective_transforms_include_root_scene_and_paint_transforms() {
166 let mut roots = RootTransforms::new();
167 let root = Affine::translate((10.0, 20.0));
168 let scene = Affine::scale(2.0);
169 let paint = Affine::translate((3.0, 4.0));
170 let mut transforms = Transforms::new();
171 transforms.set_transform(scene);
172 transforms.set_paint_transform(paint);
173 roots.push_root(root);
174
175 assert_eq!(roots.effective_path_transform(&transforms), root * scene);
176 assert_eq!(
177 roots.effective_paint_transform(&transforms),
178 root * scene * paint
179 );
180 }
181}