Home | History | Annotate | Download | only in hwui
      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