surpass/
affine_transform.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::hash;
6
7use crate::{CanonBits, Point};
8
9/// 2D transformation that preserves parallel lines.
10///
11/// Such a transformation can combine translation, scale, flip, rotate and shears.
12/// It is represented by a 3 by 3 matrix where the last row is [0, 0, 1].
13///
14/// ```text
15/// [ x' ]   [ u.x v.x t.x ] [ x ]
16/// [ y' ] = [ u.y v.y t.y ] [ y ]
17/// [ 1  ]   [   0   0   1 ] [ 1 ]
18/// ```
19#[derive(Copy, Clone, Debug)]
20pub struct AffineTransform {
21    pub ux: f32,
22    pub uy: f32,
23    pub vx: f32,
24    pub vy: f32,
25    pub tx: f32,
26    pub ty: f32,
27}
28
29impl AffineTransform {
30    pub(crate) fn transform(&self, point: Point) -> Point {
31        Point {
32            x: self.ux.mul_add(point.x, self.vx.mul_add(point.y, self.tx)),
33            y: self.uy.mul_add(point.x, self.vy.mul_add(point.y, self.ty)),
34        }
35    }
36
37    pub(crate) fn is_identity(&self) -> bool {
38        *self == Self::default()
39    }
40
41    pub fn to_array(&self) -> [f32; 6] {
42        [self.ux, self.uy, self.vx, self.vy, self.tx, self.ty]
43    }
44}
45
46impl Eq for AffineTransform {}
47
48impl PartialEq for AffineTransform {
49    fn eq(&self, other: &Self) -> bool {
50        self.ux == other.ux
51            && self.uy == other.uy
52            && self.vx == other.vx
53            && self.vy == other.vy
54            && self.tx == other.tx
55            && self.ty == other.ty
56    }
57}
58
59impl hash::Hash for AffineTransform {
60    fn hash<H: hash::Hasher>(&self, state: &mut H) {
61        self.ux.to_canon_bits().hash(state);
62        self.uy.to_canon_bits().hash(state);
63        self.vx.to_canon_bits().hash(state);
64        self.vy.to_canon_bits().hash(state);
65        self.tx.to_canon_bits().hash(state);
66        self.ty.to_canon_bits().hash(state);
67    }
68}
69
70impl Default for AffineTransform {
71    fn default() -> Self {
72        Self { ux: 1.0, vx: 0.0, tx: 0.0, uy: 0.0, vy: 1.0, ty: 0.0 }
73    }
74}
75
76impl From<[f32; 6]> for AffineTransform {
77    fn from(transform: [f32; 6]) -> Self {
78        Self {
79            ux: transform[0],
80            uy: transform[2],
81            vx: transform[1],
82            vy: transform[3],
83            tx: transform[4],
84            ty: transform[5],
85        }
86    }
87}