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