• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/**
23 * These values correspond to the values from the gui::Transform class in the
24 * platform, defined in:
25 * frameworks/native/libs/ui/include/ui/Transform.h
26 * The values are listed in row-major order:
27 *     [ dsdx, dtdx,  tx ]
28 *     [ dtdy, dsdy,  ty ]
29 *     [    0,    0,   1 ]
30 */
31export class TransformMatrix {
32  constructor(
33    readonly dsdx: number,
34    readonly dtdx: number,
35    readonly tx: number,
36    readonly dtdy: number,
37    readonly dsdy: number,
38    readonly ty: number,
39  ) {}
40
41  static from(
42    m: {
43      dsdx?: number;
44      dtdx?: number;
45      tx?: number;
46      dtdy?: number;
47      dsdy?: number;
48      ty?: number;
49    } = {},
50    fallback: TransformMatrix = IDENTITY_MATRIX,
51  ): TransformMatrix {
52    return new TransformMatrix(
53      m.dsdx ?? fallback.dsdx,
54      m.dtdx ?? fallback.dtdx,
55      m.tx ?? fallback.tx,
56      m.dtdy ?? fallback.dtdy,
57      m.dsdy ?? fallback.dsdy,
58      m.ty ?? fallback.ty,
59    );
60  }
61
62  isValid(): boolean {
63    return this.dsdx * this.dsdy !== this.dtdx * this.dtdy;
64  }
65
66  transformPoint(point: Point): Point {
67    return {
68      x: this.dsdx * point.x + this.dtdx * point.y + this.tx,
69      y: this.dtdy * point.x + this.dsdy * point.y + this.ty,
70    };
71  }
72
73  transformPoint3D(point: Point3D): Point3D {
74    const p = this.transformPoint(point);
75    return new Point3D(p.x, p.y, point.z);
76  }
77
78  transformRect(r: Rect): Rect {
79    const ltPrime = this.transformPoint({x: r.x, y: r.y});
80    const rbPrime = this.transformPoint({x: r.x + r.w, y: r.y + r.h});
81    const x = Math.min(ltPrime.x, rbPrime.x);
82    const y = Math.min(ltPrime.y, rbPrime.y);
83    return new Rect(
84      x,
85      y,
86      Math.max(ltPrime.x, rbPrime.x) - x,
87      Math.max(ltPrime.y, rbPrime.y) - y,
88    );
89  }
90
91  transformRegion(region: Region): Region {
92    return new Region(region.rects.map((rect) => this.transformRect(rect)));
93  }
94
95  inverse(): TransformMatrix {
96    const ident = 1.0 / this.det();
97    const result = {
98      dsdx: this.dsdy * ident,
99      dtdx: -this.dtdx * ident,
100      tx: 0,
101      dsdy: this.dsdx * ident,
102      dtdy: -this.dtdy * ident,
103      ty: 0,
104    };
105    const t = TransformMatrix.from(result).transformPoint({
106      x: -this.tx,
107      y: -this.ty,
108    });
109    result.tx = t.x;
110    result.ty = t.y;
111    return TransformMatrix.from(result);
112  }
113
114  addTy(ty: number): TransformMatrix {
115    return new TransformMatrix(
116      this.dsdx,
117      this.dtdx,
118      this.tx,
119      this.dtdy,
120      this.dsdy,
121      this.ty + ty,
122    );
123  }
124
125  isEqual(other: TransformMatrix): boolean {
126    return (
127      this.dsdx === other.dsdx &&
128      this.dtdx === other.dtdx &&
129      this.tx === other.tx &&
130      this.dtdy === other.dtdy &&
131      this.dsdy === other.dsdy &&
132      this.ty === other.ty
133    );
134  }
135
136  private det(): number {
137    return this.dsdx * this.dsdy - this.dtdx * this.dtdy;
138  }
139}
140
141/**
142 * The identity matrix, which has no effect on any point or rect.
143 */
144export const IDENTITY_MATRIX = new TransformMatrix(1, 0, 0, 0, 1, 0);
145