agg_rust/
conv_transform.rs1use crate::basics::{is_vertex, VertexSource};
9use crate::span_interpolator_linear::Transformer;
10use crate::trans_affine::TransAffine;
11
12pub struct ConvTransform<VS: VertexSource, T: Transformer = TransAffine> {
22 source: VS,
23 trans: T,
24}
25
26impl<VS: VertexSource, T: Transformer> ConvTransform<VS, T> {
27 pub fn new(source: VS, trans: T) -> Self {
28 Self { source, trans }
29 }
30
31 pub fn set_transform(&mut self, trans: T) {
32 self.trans = trans;
33 }
34
35 pub fn transform(&self) -> &T {
36 &self.trans
37 }
38
39 pub fn source(&self) -> &VS {
40 &self.source
41 }
42
43 pub fn source_mut(&mut self) -> &mut VS {
44 &mut self.source
45 }
46}
47
48impl<VS: VertexSource, T: Transformer> VertexSource for ConvTransform<VS, T> {
49 fn rewind(&mut self, path_id: u32) {
50 self.source.rewind(path_id);
51 }
52
53 fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
54 let cmd = self.source.vertex(x, y);
55 if is_vertex(cmd) {
56 self.trans.transform(x, y);
57 }
58 cmd
59 }
60}
61
62#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::basics::{PATH_CMD_LINE_TO, PATH_CMD_MOVE_TO, PATH_CMD_STOP};
70 use crate::path_storage::PathStorage;
71
72 #[test]
73 fn test_identity_transform() {
74 let mut path = PathStorage::new();
75 path.move_to(10.0, 20.0);
76 path.line_to(30.0, 40.0);
77
78 let mut ct = ConvTransform::new(path, TransAffine::default());
79 ct.rewind(0);
80
81 let (mut x, mut y) = (0.0, 0.0);
82 let cmd = ct.vertex(&mut x, &mut y);
83 assert_eq!(cmd, PATH_CMD_MOVE_TO);
84 assert!((x - 10.0).abs() < 1e-10);
85 assert!((y - 20.0).abs() < 1e-10);
86
87 let cmd = ct.vertex(&mut x, &mut y);
88 assert_eq!(cmd, PATH_CMD_LINE_TO);
89 assert!((x - 30.0).abs() < 1e-10);
90 assert!((y - 40.0).abs() < 1e-10);
91 }
92
93 #[test]
94 fn test_translation() {
95 let mut path = PathStorage::new();
96 path.move_to(10.0, 20.0);
97
98 let trans = TransAffine::new_translation(100.0, 200.0);
99 let mut ct = ConvTransform::new(path, trans);
100 ct.rewind(0);
101
102 let (mut x, mut y) = (0.0, 0.0);
103 ct.vertex(&mut x, &mut y);
104 assert!((x - 110.0).abs() < 1e-10);
105 assert!((y - 220.0).abs() < 1e-10);
106 }
107
108 #[test]
109 fn test_scaling() {
110 let mut path = PathStorage::new();
111 path.move_to(10.0, 20.0);
112 path.line_to(30.0, 40.0);
113
114 let trans = TransAffine::new_scaling(2.0, 3.0);
115 let mut ct = ConvTransform::new(path, trans);
116 ct.rewind(0);
117
118 let (mut x, mut y) = (0.0, 0.0);
119 ct.vertex(&mut x, &mut y);
120 assert!((x - 20.0).abs() < 1e-10);
121 assert!((y - 60.0).abs() < 1e-10);
122
123 ct.vertex(&mut x, &mut y);
124 assert!((x - 60.0).abs() < 1e-10);
125 assert!((y - 120.0).abs() < 1e-10);
126 }
127
128 #[test]
129 fn test_stop_not_transformed() {
130 let path = PathStorage::new();
131 let mut ct = ConvTransform::new(path, TransAffine::new_scaling(2.0, 2.0));
133 ct.rewind(0);
134
135 let (mut x, mut y) = (0.0, 0.0);
136 let cmd = ct.vertex(&mut x, &mut y);
137 assert_eq!(cmd, PATH_CMD_STOP);
138 }
139
140 #[test]
141 fn test_set_transform() {
142 let mut path = PathStorage::new();
143 path.move_to(10.0, 10.0);
144
145 let mut ct = ConvTransform::new(path, TransAffine::default());
146 ct.set_transform(TransAffine::new_translation(5.0, 5.0));
147 ct.rewind(0);
148
149 let (mut x, mut y) = (0.0, 0.0);
150 ct.vertex(&mut x, &mut y);
151 assert!((x - 15.0).abs() < 1e-10);
152 assert!((y - 15.0).abs() < 1e-10);
153 }
154
155 #[test]
156 fn test_generic_transformer_via_reference() {
157 use crate::trans_polar::TransPolar;
159
160 let mut path = PathStorage::new();
161 path.move_to(0.0, 100.0);
162
163 let polar = TransPolar::new();
164 let mut ct = ConvTransform::new(path, &polar);
166 ct.rewind(0);
167
168 let (mut x, mut y) = (0.0, 0.0);
169 let cmd = ct.vertex(&mut x, &mut y);
170 assert_eq!(cmd, PATH_CMD_MOVE_TO);
171 assert!((x - 100.0).abs() < 1e-10);
174 assert!((y - 0.0).abs() < 1e-10);
175 }
176}