xref: /aosp_15_r20/development/tools/winscope/src/common/geometry/transform_matrix.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright (C) 2024, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {Point} from './point';
18import {Point3D} from './point3d';
19import {Rect} from './rect';
20import {Region} from './region';
21
22// These values correspond to the values from the gui::Transform class in the platform, defined in:
23//     frameworks/native/libs/ui/include/ui/Transform.h
24// The values are listed in row-major order:
25//     [ dsdx, dtdx,  tx ]
26//     [ dtdy, dsdy,  ty ]
27//     [    0,    0,   1 ]
28export class TransformMatrix {
29  constructor(
30    readonly dsdx: number,
31    readonly dtdx: number,
32    readonly tx: number,
33    readonly dtdy: number,
34    readonly dsdy: number,
35    readonly ty: number,
36  ) {}
37
38  static from(
39    m: {
40      dsdx?: number;
41      dtdx?: number;
42      tx?: number;
43      dtdy?: number;
44      dsdy?: number;
45      ty?: number;
46    } = {},
47    fallback: TransformMatrix = IDENTITY_MATRIX,
48  ): TransformMatrix {
49    return new TransformMatrix(
50      m.dsdx ?? fallback.dsdx,
51      m.dtdx ?? fallback.dtdx,
52      m.tx ?? fallback.tx,
53      m.dtdy ?? fallback.dtdy,
54      m.dsdy ?? fallback.dsdy,
55      m.ty ?? fallback.ty,
56    );
57  }
58
59  isValid(): boolean {
60    return this.dsdx * this.dsdy !== this.dtdx * this.dtdy;
61  }
62
63  transformPoint(point: Point): Point {
64    return {
65      x: this.dsdx * point.x + this.dtdx * point.y + this.tx,
66      y: this.dtdy * point.x + this.dsdy * point.y + this.ty,
67    };
68  }
69
70  transformPoint3D(point: Point3D): Point3D {
71    const p = this.transformPoint(point);
72    return new Point3D(p.x, p.y, point.z);
73  }
74
75  transformRect(r: Rect): Rect {
76    const ltPrime = this.transformPoint({x: r.x, y: r.y});
77    const rbPrime = this.transformPoint({x: r.x + r.w, y: r.y + r.h});
78    const x = Math.min(ltPrime.x, rbPrime.x);
79    const y = Math.min(ltPrime.y, rbPrime.y);
80    return new Rect(
81      x,
82      y,
83      Math.max(ltPrime.x, rbPrime.x) - x,
84      Math.max(ltPrime.y, rbPrime.y) - y,
85    );
86  }
87
88  transformRegion(region: Region): Region {
89    return new Region(region.rects.map((rect) => this.transformRect(rect)));
90  }
91
92  inverse(): TransformMatrix {
93    const ident = 1.0 / this.det();
94    const result = {
95      dsdx: this.dsdy * ident,
96      dtdx: -this.dtdx * ident,
97      tx: 0,
98      dsdy: this.dsdx * ident,
99      dtdy: -this.dtdy * ident,
100      ty: 0,
101    };
102    const t = TransformMatrix.from(result).transformPoint({
103      x: -this.tx,
104      y: -this.ty,
105    });
106    result.tx = t.x;
107    result.ty = t.y;
108    return TransformMatrix.from(result);
109  }
110
111  addTy(ty: number): TransformMatrix {
112    return new TransformMatrix(
113      this.dsdx,
114      this.dtdx,
115      this.tx,
116      this.dtdy,
117      this.dsdy,
118      this.ty + ty,
119    );
120  }
121
122  isEqual(other: TransformMatrix): boolean {
123    return (
124      this.dsdx === other.dsdx &&
125      this.dtdx === other.dtdx &&
126      this.tx === other.tx &&
127      this.dtdy === other.dtdy &&
128      this.dsdy === other.dsdy &&
129      this.ty === other.ty
130    );
131  }
132
133  private det(): number {
134    return this.dsdx * this.dsdy - this.dtdx * this.dtdy;
135  }
136}
137
138export const IDENTITY_MATRIX = new TransformMatrix(1, 0, 0, 0, 1, 0);
139