1use tiny_skia::Transform;
5
6#[derive(Clone, Copy, Debug, PartialEq)]
8pub struct Mat {
9 pub a: f64,
10 pub b: f64,
11 pub c: f64,
12 pub d: f64,
13 pub e: f64,
14 pub f: f64,
15}
16
17impl Mat {
18 pub const IDENTITY: Mat = Mat {
19 a: 1.0,
20 b: 0.0,
21 c: 0.0,
22 d: 1.0,
23 e: 0.0,
24 f: 0.0,
25 };
26
27 pub fn new(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> Mat {
28 Mat { a, b, c, d, e, f }
29 }
30
31 pub fn scale(sx: f64, sy: f64) -> Mat {
32 Mat::new(sx, 0.0, 0.0, sy, 0.0, 0.0)
33 }
34
35 pub fn translate(tx: f64, ty: f64) -> Mat {
36 Mat::new(1.0, 0.0, 0.0, 1.0, tx, ty)
37 }
38
39 pub fn from_slice(v: &[f64]) -> Option<Mat> {
41 if v.len() != 6 || v.iter().any(|x| !x.is_finite()) {
42 return None;
43 }
44 Some(Mat::new(v[0], v[1], v[2], v[3], v[4], v[5]))
45 }
46
47 pub fn then(self, r: Mat) -> Mat {
50 Mat {
51 a: self.a * r.a + self.b * r.c,
52 b: self.a * r.b + self.b * r.d,
53 c: self.c * r.a + self.d * r.c,
54 d: self.c * r.b + self.d * r.d,
55 e: self.e * r.a + self.f * r.c + r.e,
56 f: self.e * r.b + self.f * r.d + r.f,
57 }
58 }
59
60 pub fn apply(self, x: f64, y: f64) -> (f64, f64) {
61 (
62 self.a * x + self.c * y + self.e,
63 self.b * x + self.d * y + self.f,
64 )
65 }
66
67 pub fn apply_vec(self, x: f64, y: f64) -> (f64, f64) {
69 (self.a * x + self.c * y, self.b * x + self.d * y)
70 }
71
72 pub fn det(self) -> f64 {
73 self.a * self.d - self.b * self.c
74 }
75
76 pub fn mean_scale(self) -> f64 {
79 self.det().abs().sqrt()
80 }
81
82 pub fn max_scale(self) -> f64 {
84 let sx = self.a.hypot(self.b);
85 let sy = self.c.hypot(self.d);
86 sx.max(sy)
87 }
88
89 pub fn invert(self) -> Option<Mat> {
90 let det = self.det();
91 if det.abs() < 1e-12 || !det.is_finite() {
92 return None;
93 }
94 let ia = self.d / det;
95 let ib = -self.b / det;
96 let ic = -self.c / det;
97 let id = self.a / det;
98 Some(Mat {
99 a: ia,
100 b: ib,
101 c: ic,
102 d: id,
103 e: -(self.e * ia + self.f * ic),
104 f: -(self.e * ib + self.f * id),
105 })
106 }
107
108 pub fn is_finite(self) -> bool {
109 [self.a, self.b, self.c, self.d, self.e, self.f]
110 .iter()
111 .all(|v| v.is_finite())
112 }
113
114 pub fn to_ts(self) -> Transform {
117 Transform::from_row(
118 self.a as f32,
119 self.b as f32,
120 self.c as f32,
121 self.d as f32,
122 self.e as f32,
123 self.f as f32,
124 )
125 }
126
127 pub fn unit_bbox(self) -> (f64, f64, f64, f64) {
130 let pts = [
131 self.apply(0.0, 0.0),
132 self.apply(1.0, 0.0),
133 self.apply(0.0, 1.0),
134 self.apply(1.0, 1.0),
135 ];
136 let mut b = (pts[0].0, pts[0].1, pts[0].0, pts[0].1);
137 for &(x, y) in &pts[1..] {
138 b.0 = b.0.min(x);
139 b.1 = b.1.min(y);
140 b.2 = b.2.max(x);
141 b.3 = b.3.max(y);
142 }
143 b
144 }
145}
146
147#[derive(Clone, Copy, Debug, PartialEq)]
149pub struct Box2 {
150 pub x0: f64,
151 pub y0: f64,
152 pub x1: f64,
153 pub y1: f64,
154}
155
156impl Box2 {
157 pub fn new(x0: f64, y0: f64, x1: f64, y1: f64) -> Box2 {
158 Box2 {
159 x0: x0.min(x1),
160 y0: y0.min(y1),
161 x1: x0.max(x1),
162 y1: y0.max(y1),
163 }
164 }
165
166 pub fn intersect(self, o: Box2) -> Box2 {
167 Box2 {
168 x0: self.x0.max(o.x0),
169 y0: self.y0.max(o.y0),
170 x1: self.x1.min(o.x1),
171 y1: self.y1.min(o.y1),
172 }
173 }
174
175 pub fn is_empty(self) -> bool {
176 !(self.x1 > self.x0 && self.y1 > self.y0)
177 }
178
179 pub fn width(self) -> f64 {
180 (self.x1 - self.x0).max(0.0)
181 }
182
183 pub fn height(self) -> f64 {
184 (self.y1 - self.y0).max(0.0)
185 }
186
187 pub fn transformed(self, m: Mat) -> Box2 {
189 let pts = [
190 m.apply(self.x0, self.y0),
191 m.apply(self.x1, self.y0),
192 m.apply(self.x0, self.y1),
193 m.apply(self.x1, self.y1),
194 ];
195 let mut b = Box2::new(pts[0].0, pts[0].1, pts[0].0, pts[0].1);
196 for &(x, y) in &pts[1..] {
197 b.x0 = b.x0.min(x);
198 b.y0 = b.y0.min(y);
199 b.x1 = b.x1.max(x);
200 b.y1 = b.y1.max(y);
201 }
202 b
203 }
204}