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