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