xref: /aosp_15_r20/frameworks/base/libs/hwui/Matrix.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #pragma once
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include "Rect.h"
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker #include <SkMatrix.h>
22*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h>
23*d57664e9SAndroid Build Coastguard Worker #include <iomanip>
24*d57664e9SAndroid Build Coastguard Worker #include <ostream>
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker namespace android {
27*d57664e9SAndroid Build Coastguard Worker namespace uirenderer {
28*d57664e9SAndroid Build Coastguard Worker 
29*d57664e9SAndroid Build Coastguard Worker #define SK_MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
30*d57664e9SAndroid Build Coastguard Worker #define SK_MATRIX_STRING_V "[%.9f %.9f %.9f] [%.9f %.9f %.9f] [%.9f %.9f %.9f]"
31*d57664e9SAndroid Build Coastguard Worker #define SK_MATRIX_ARGS(m)                                                                      \
32*d57664e9SAndroid Build Coastguard Worker     (m)->get(0), (m)->get(1), (m)->get(2), (m)->get(3), (m)->get(4), (m)->get(5), (m)->get(6), \
33*d57664e9SAndroid Build Coastguard Worker             (m)->get(7), (m)->get(8)
34*d57664e9SAndroid Build Coastguard Worker 
35*d57664e9SAndroid Build Coastguard Worker #define MATRIX_4_STRING                           \
36*d57664e9SAndroid Build Coastguard Worker     "[%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]" \
37*d57664e9SAndroid Build Coastguard Worker     " [%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]"
38*d57664e9SAndroid Build Coastguard Worker #define MATRIX_4_ARGS(m)                                                                           \
39*d57664e9SAndroid Build Coastguard Worker     (m)->data[0], (m)->data[4], (m)->data[8], (m)->data[12], (m)->data[1], (m)->data[5],           \
40*d57664e9SAndroid Build Coastguard Worker             (m)->data[9], (m)->data[13], (m)->data[2], (m)->data[6], (m)->data[10], (m)->data[14], \
41*d57664e9SAndroid Build Coastguard Worker             (m)->data[3], (m)->data[7], (m)->data[11], (m)->data[15]
42*d57664e9SAndroid Build Coastguard Worker 
43*d57664e9SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
44*d57664e9SAndroid Build Coastguard Worker // Classes
45*d57664e9SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
46*d57664e9SAndroid Build Coastguard Worker 
47*d57664e9SAndroid Build Coastguard Worker class Matrix4 {
48*d57664e9SAndroid Build Coastguard Worker public:
49*d57664e9SAndroid Build Coastguard Worker     float data[16];
50*d57664e9SAndroid Build Coastguard Worker 
51*d57664e9SAndroid Build Coastguard Worker     enum Entry {
52*d57664e9SAndroid Build Coastguard Worker         kScaleX = 0,
53*d57664e9SAndroid Build Coastguard Worker         kSkewY = 1,
54*d57664e9SAndroid Build Coastguard Worker         kPerspective0 = 3,
55*d57664e9SAndroid Build Coastguard Worker         kSkewX = 4,
56*d57664e9SAndroid Build Coastguard Worker         kScaleY = 5,
57*d57664e9SAndroid Build Coastguard Worker         kPerspective1 = 7,
58*d57664e9SAndroid Build Coastguard Worker         kScaleZ = 10,
59*d57664e9SAndroid Build Coastguard Worker         kTranslateX = 12,
60*d57664e9SAndroid Build Coastguard Worker         kTranslateY = 13,
61*d57664e9SAndroid Build Coastguard Worker         kTranslateZ = 14,
62*d57664e9SAndroid Build Coastguard Worker         kPerspective2 = 15
63*d57664e9SAndroid Build Coastguard Worker     };
64*d57664e9SAndroid Build Coastguard Worker 
65*d57664e9SAndroid Build Coastguard Worker     // NOTE: The flags from kTypeIdentity to kTypePerspective
66*d57664e9SAndroid Build Coastguard Worker     //       must be kept in sync with the type flags found
67*d57664e9SAndroid Build Coastguard Worker     //       in SkMatrix
68*d57664e9SAndroid Build Coastguard Worker     enum Type {
69*d57664e9SAndroid Build Coastguard Worker         kTypeIdentity = 0,
70*d57664e9SAndroid Build Coastguard Worker         kTypeTranslate = 0x1,
71*d57664e9SAndroid Build Coastguard Worker         kTypeScale = 0x2,
72*d57664e9SAndroid Build Coastguard Worker         kTypeAffine = 0x4,
73*d57664e9SAndroid Build Coastguard Worker         kTypePerspective = 0x8,
74*d57664e9SAndroid Build Coastguard Worker         kTypeRectToRect = 0x10,
75*d57664e9SAndroid Build Coastguard Worker         kTypeUnknown = 0x20,
76*d57664e9SAndroid Build Coastguard Worker     };
77*d57664e9SAndroid Build Coastguard Worker 
78*d57664e9SAndroid Build Coastguard Worker     static const int sGeometryMask = 0xf;
79*d57664e9SAndroid Build Coastguard Worker 
Matrix4()80*d57664e9SAndroid Build Coastguard Worker     Matrix4() { loadIdentity(); }
81*d57664e9SAndroid Build Coastguard Worker 
Matrix4(const float * v)82*d57664e9SAndroid Build Coastguard Worker     explicit Matrix4(const float* v) { load(v); }
83*d57664e9SAndroid Build Coastguard Worker 
Matrix4(const SkMatrix & v)84*d57664e9SAndroid Build Coastguard Worker     Matrix4(const SkMatrix& v) {  // NOLINT(google-explicit-constructor)
85*d57664e9SAndroid Build Coastguard Worker         load(v);
86*d57664e9SAndroid Build Coastguard Worker     }
87*d57664e9SAndroid Build Coastguard Worker 
88*d57664e9SAndroid Build Coastguard Worker     float operator[](int index) const { return data[index]; }
89*d57664e9SAndroid Build Coastguard Worker 
90*d57664e9SAndroid Build Coastguard Worker     float& operator[](int index) {
91*d57664e9SAndroid Build Coastguard Worker         mType = kTypeUnknown;
92*d57664e9SAndroid Build Coastguard Worker         return data[index];
93*d57664e9SAndroid Build Coastguard Worker     }
94*d57664e9SAndroid Build Coastguard Worker 
95*d57664e9SAndroid Build Coastguard Worker     Matrix4& operator=(const SkMatrix& v) {
96*d57664e9SAndroid Build Coastguard Worker         load(v);
97*d57664e9SAndroid Build Coastguard Worker         return *this;
98*d57664e9SAndroid Build Coastguard Worker     }
99*d57664e9SAndroid Build Coastguard Worker 
100*d57664e9SAndroid Build Coastguard Worker     friend bool operator==(const Matrix4& a, const Matrix4& b) {
101*d57664e9SAndroid Build Coastguard Worker         return !memcmp(&a.data[0], &b.data[0], 16 * sizeof(float));
102*d57664e9SAndroid Build Coastguard Worker     }
103*d57664e9SAndroid Build Coastguard Worker 
104*d57664e9SAndroid Build Coastguard Worker     friend bool operator!=(const Matrix4& a, const Matrix4& b) { return !(a == b); }
105*d57664e9SAndroid Build Coastguard Worker 
106*d57664e9SAndroid Build Coastguard Worker     void loadIdentity();
107*d57664e9SAndroid Build Coastguard Worker 
108*d57664e9SAndroid Build Coastguard Worker     void load(const float* v);
109*d57664e9SAndroid Build Coastguard Worker     void load(const SkMatrix& v);
110*d57664e9SAndroid Build Coastguard Worker 
111*d57664e9SAndroid Build Coastguard Worker     void loadInverse(const Matrix4& v);
112*d57664e9SAndroid Build Coastguard Worker 
113*d57664e9SAndroid Build Coastguard Worker     void loadTranslate(float x, float y, float z);
114*d57664e9SAndroid Build Coastguard Worker     void loadScale(float sx, float sy, float sz);
115*d57664e9SAndroid Build Coastguard Worker     void loadSkew(float sx, float sy);
116*d57664e9SAndroid Build Coastguard Worker     void loadRotate(float angle);
117*d57664e9SAndroid Build Coastguard Worker     void loadRotate(float angle, float x, float y, float z);
118*d57664e9SAndroid Build Coastguard Worker     void loadMultiply(const Matrix4& u, const Matrix4& v);
119*d57664e9SAndroid Build Coastguard Worker 
120*d57664e9SAndroid Build Coastguard Worker     void loadOrtho(float left, float right, float bottom, float top, float near, float far);
loadOrtho(int width,int height)121*d57664e9SAndroid Build Coastguard Worker     void loadOrtho(int width, int height) { loadOrtho(0, width, height, 0, -1, 1); }
122*d57664e9SAndroid Build Coastguard Worker 
123*d57664e9SAndroid Build Coastguard Worker     uint8_t getType() const;
124*d57664e9SAndroid Build Coastguard Worker 
multiplyInverse(const Matrix4 & v)125*d57664e9SAndroid Build Coastguard Worker     void multiplyInverse(const Matrix4& v) {
126*d57664e9SAndroid Build Coastguard Worker         Matrix4 inv;
127*d57664e9SAndroid Build Coastguard Worker         inv.loadInverse(v);
128*d57664e9SAndroid Build Coastguard Worker         multiply(inv);
129*d57664e9SAndroid Build Coastguard Worker     }
130*d57664e9SAndroid Build Coastguard Worker 
multiply(const Matrix4 & v)131*d57664e9SAndroid Build Coastguard Worker     void multiply(const Matrix4& v) {
132*d57664e9SAndroid Build Coastguard Worker         if (!v.isIdentity()) {
133*d57664e9SAndroid Build Coastguard Worker             Matrix4 u;
134*d57664e9SAndroid Build Coastguard Worker             u.loadMultiply(*this, v);
135*d57664e9SAndroid Build Coastguard Worker             *this = u;
136*d57664e9SAndroid Build Coastguard Worker         }
137*d57664e9SAndroid Build Coastguard Worker     }
138*d57664e9SAndroid Build Coastguard Worker 
139*d57664e9SAndroid Build Coastguard Worker     void multiply(float v);
140*d57664e9SAndroid Build Coastguard Worker 
141*d57664e9SAndroid Build Coastguard Worker     void translate(float x, float y, float z = 0) {
142*d57664e9SAndroid Build Coastguard Worker         if ((getType() & sGeometryMask) <= kTypeTranslate) {
143*d57664e9SAndroid Build Coastguard Worker             data[kTranslateX] += x;
144*d57664e9SAndroid Build Coastguard Worker             data[kTranslateY] += y;
145*d57664e9SAndroid Build Coastguard Worker             data[kTranslateZ] += z;
146*d57664e9SAndroid Build Coastguard Worker             mType |= kTypeUnknown;
147*d57664e9SAndroid Build Coastguard Worker         } else {
148*d57664e9SAndroid Build Coastguard Worker             // Doing a translation will only affect the translate bit of the type
149*d57664e9SAndroid Build Coastguard Worker             // Save the type
150*d57664e9SAndroid Build Coastguard Worker             uint8_t type = mType;
151*d57664e9SAndroid Build Coastguard Worker 
152*d57664e9SAndroid Build Coastguard Worker             Matrix4 u;
153*d57664e9SAndroid Build Coastguard Worker             u.loadTranslate(x, y, z);
154*d57664e9SAndroid Build Coastguard Worker             multiply(u);
155*d57664e9SAndroid Build Coastguard Worker 
156*d57664e9SAndroid Build Coastguard Worker             // Restore the type and fix the translate bit
157*d57664e9SAndroid Build Coastguard Worker             mType = type;
158*d57664e9SAndroid Build Coastguard Worker             if (data[kTranslateX] != 0.0f || data[kTranslateY] != 0.0f) {
159*d57664e9SAndroid Build Coastguard Worker                 mType |= kTypeTranslate;
160*d57664e9SAndroid Build Coastguard Worker             } else {
161*d57664e9SAndroid Build Coastguard Worker                 mType &= ~kTypeTranslate;
162*d57664e9SAndroid Build Coastguard Worker             }
163*d57664e9SAndroid Build Coastguard Worker         }
164*d57664e9SAndroid Build Coastguard Worker     }
165*d57664e9SAndroid Build Coastguard Worker 
scale(float sx,float sy,float sz)166*d57664e9SAndroid Build Coastguard Worker     void scale(float sx, float sy, float sz) {
167*d57664e9SAndroid Build Coastguard Worker         Matrix4 u;
168*d57664e9SAndroid Build Coastguard Worker         u.loadScale(sx, sy, sz);
169*d57664e9SAndroid Build Coastguard Worker         multiply(u);
170*d57664e9SAndroid Build Coastguard Worker     }
171*d57664e9SAndroid Build Coastguard Worker 
skew(float sx,float sy)172*d57664e9SAndroid Build Coastguard Worker     void skew(float sx, float sy) {
173*d57664e9SAndroid Build Coastguard Worker         Matrix4 u;
174*d57664e9SAndroid Build Coastguard Worker         u.loadSkew(sx, sy);
175*d57664e9SAndroid Build Coastguard Worker         multiply(u);
176*d57664e9SAndroid Build Coastguard Worker     }
177*d57664e9SAndroid Build Coastguard Worker 
rotate(float angle,float x,float y,float z)178*d57664e9SAndroid Build Coastguard Worker     void rotate(float angle, float x, float y, float z) {
179*d57664e9SAndroid Build Coastguard Worker         Matrix4 u;
180*d57664e9SAndroid Build Coastguard Worker         u.loadRotate(angle, x, y, z);
181*d57664e9SAndroid Build Coastguard Worker         multiply(u);
182*d57664e9SAndroid Build Coastguard Worker     }
183*d57664e9SAndroid Build Coastguard Worker 
184*d57664e9SAndroid Build Coastguard Worker     /**
185*d57664e9SAndroid Build Coastguard Worker      * If the matrix is identity or translate and/or scale.
186*d57664e9SAndroid Build Coastguard Worker      */
187*d57664e9SAndroid Build Coastguard Worker     bool isSimple() const;
188*d57664e9SAndroid Build Coastguard Worker     bool isPureTranslate() const;
189*d57664e9SAndroid Build Coastguard Worker     bool isIdentity() const;
190*d57664e9SAndroid Build Coastguard Worker     bool isPerspective() const;
191*d57664e9SAndroid Build Coastguard Worker     bool rectToRect() const;
192*d57664e9SAndroid Build Coastguard Worker     bool positiveScale() const;
193*d57664e9SAndroid Build Coastguard Worker 
194*d57664e9SAndroid Build Coastguard Worker     bool changesBounds() const;
195*d57664e9SAndroid Build Coastguard Worker 
196*d57664e9SAndroid Build Coastguard Worker     void copyTo(float* v) const;
197*d57664e9SAndroid Build Coastguard Worker     void copyTo(SkMatrix& v) const;
198*d57664e9SAndroid Build Coastguard Worker 
199*d57664e9SAndroid Build Coastguard Worker     float mapZ(const Vector3& orig) const;
200*d57664e9SAndroid Build Coastguard Worker     void mapPoint3d(Vector3& vec) const;
201*d57664e9SAndroid Build Coastguard Worker     void mapPoint(float& x, float& y) const;  // 2d only
202*d57664e9SAndroid Build Coastguard Worker     void mapRect(Rect& r) const;              // 2d only
203*d57664e9SAndroid Build Coastguard Worker 
204*d57664e9SAndroid Build Coastguard Worker     float getTranslateX() const;
205*d57664e9SAndroid Build Coastguard Worker     float getTranslateY() const;
206*d57664e9SAndroid Build Coastguard Worker 
207*d57664e9SAndroid Build Coastguard Worker     void decomposeScale(float& sx, float& sy) const;
208*d57664e9SAndroid Build Coastguard Worker 
209*d57664e9SAndroid Build Coastguard Worker     void dump(const char* label = nullptr) const;
210*d57664e9SAndroid Build Coastguard Worker 
211*d57664e9SAndroid Build Coastguard Worker     friend std::ostream& operator<<(std::ostream& os, const Matrix4& matrix) {
212*d57664e9SAndroid Build Coastguard Worker         if (matrix.isSimple()) {
213*d57664e9SAndroid Build Coastguard Worker             os << "offset " << matrix.getTranslateX() << "x" << matrix.getTranslateY();
214*d57664e9SAndroid Build Coastguard Worker             if (!matrix.isPureTranslate()) {
215*d57664e9SAndroid Build Coastguard Worker                 os << ", scale " << matrix[kScaleX] << "x" << matrix[kScaleY];
216*d57664e9SAndroid Build Coastguard Worker             }
217*d57664e9SAndroid Build Coastguard Worker         } else {
218*d57664e9SAndroid Build Coastguard Worker             os << "[" << matrix[0];
219*d57664e9SAndroid Build Coastguard Worker             for (int i = 1; i < 16; i++) {
220*d57664e9SAndroid Build Coastguard Worker                 os << ", " << matrix[i];
221*d57664e9SAndroid Build Coastguard Worker             }
222*d57664e9SAndroid Build Coastguard Worker             os << "]";
223*d57664e9SAndroid Build Coastguard Worker         }
224*d57664e9SAndroid Build Coastguard Worker         return os;
225*d57664e9SAndroid Build Coastguard Worker     }
226*d57664e9SAndroid Build Coastguard Worker 
227*d57664e9SAndroid Build Coastguard Worker     static const Matrix4& identity();
228*d57664e9SAndroid Build Coastguard Worker 
invalidateType()229*d57664e9SAndroid Build Coastguard Worker     void invalidateType() { mType = kTypeUnknown; }
230*d57664e9SAndroid Build Coastguard Worker 
231*d57664e9SAndroid Build Coastguard Worker private:
232*d57664e9SAndroid Build Coastguard Worker     mutable uint8_t mType;
233*d57664e9SAndroid Build Coastguard Worker 
get(int i,int j)234*d57664e9SAndroid Build Coastguard Worker     inline float get(int i, int j) const { return data[i * 4 + j]; }
235*d57664e9SAndroid Build Coastguard Worker 
set(int i,int j,float v)236*d57664e9SAndroid Build Coastguard Worker     inline void set(int i, int j, float v) { data[i * 4 + j] = v; }
237*d57664e9SAndroid Build Coastguard Worker 
238*d57664e9SAndroid Build Coastguard Worker     uint8_t getGeometryType() const;
239*d57664e9SAndroid Build Coastguard Worker 
240*d57664e9SAndroid Build Coastguard Worker };  // class Matrix4
241*d57664e9SAndroid Build Coastguard Worker 
242*d57664e9SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
243*d57664e9SAndroid Build Coastguard Worker // Types
244*d57664e9SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
245*d57664e9SAndroid Build Coastguard Worker 
246*d57664e9SAndroid Build Coastguard Worker typedef Matrix4 mat4;
247*d57664e9SAndroid Build Coastguard Worker 
248*d57664e9SAndroid Build Coastguard Worker }  // namespace uirenderer
249*d57664e9SAndroid Build Coastguard Worker }  // namespace android
250