1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef SkM44_DEFINED
9cb93a386Sopenharmony_ci#define SkM44_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
12cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
13cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cistruct SK_API SkV2 {
16cb93a386Sopenharmony_ci    float x, y;
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci    bool operator==(const SkV2 v) const { return x == v.x && y == v.y; }
19cb93a386Sopenharmony_ci    bool operator!=(const SkV2 v) const { return !(*this == v); }
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci    static SkScalar   Dot(SkV2 a, SkV2 b) { return a.x * b.x + a.y * b.y; }
22cb93a386Sopenharmony_ci    static SkScalar Cross(SkV2 a, SkV2 b) { return a.x * b.y - a.y * b.x; }
23cb93a386Sopenharmony_ci    static SkV2 Normalize(SkV2 v) { return v * (1.0f / v.length()); }
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci    SkV2 operator-() const { return {-x, -y}; }
26cb93a386Sopenharmony_ci    SkV2 operator+(SkV2 v) const { return {x+v.x, y+v.y}; }
27cb93a386Sopenharmony_ci    SkV2 operator-(SkV2 v) const { return {x-v.x, y-v.y}; }
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    SkV2 operator*(SkV2 v) const { return {x*v.x, y*v.y}; }
30cb93a386Sopenharmony_ci    friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; }
31cb93a386Sopenharmony_ci    friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; }
32cb93a386Sopenharmony_ci    friend SkV2 operator/(SkV2 v, SkScalar s) { return {v.x/s, v.y/s}; }
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci    void operator+=(SkV2 v) { *this = *this + v; }
35cb93a386Sopenharmony_ci    void operator-=(SkV2 v) { *this = *this - v; }
36cb93a386Sopenharmony_ci    void operator*=(SkV2 v) { *this = *this * v; }
37cb93a386Sopenharmony_ci    void operator*=(SkScalar s) { *this = *this * s; }
38cb93a386Sopenharmony_ci    void operator/=(SkScalar s) { *this = *this / s; }
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci    SkScalar lengthSquared() const { return Dot(*this, *this); }
41cb93a386Sopenharmony_ci    SkScalar length() const { return SkScalarSqrt(this->lengthSquared()); }
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci    SkScalar   dot(SkV2 v) const { return Dot(*this, v); }
44cb93a386Sopenharmony_ci    SkScalar cross(SkV2 v) const { return Cross(*this, v); }
45cb93a386Sopenharmony_ci    SkV2 normalize()       const { return Normalize(*this); }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    const float* ptr() const { return &x; }
48cb93a386Sopenharmony_ci    float* ptr() { return &x; }
49cb93a386Sopenharmony_ci};
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_cistruct SK_API SkV3 {
52cb93a386Sopenharmony_ci    float x, y, z;
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    bool operator==(const SkV3& v) const {
55cb93a386Sopenharmony_ci        return x == v.x && y == v.y && z == v.z;
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci    bool operator!=(const SkV3& v) const { return !(*this == v); }
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    static SkScalar Dot(const SkV3& a, const SkV3& b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
60cb93a386Sopenharmony_ci    static SkV3   Cross(const SkV3& a, const SkV3& b) {
61cb93a386Sopenharmony_ci        return { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x };
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci    static SkV3 Normalize(const SkV3& v) { return v * (1.0f / v.length()); }
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    SkV3 operator-() const { return {-x, -y, -z}; }
66cb93a386Sopenharmony_ci    SkV3 operator+(const SkV3& v) const { return { x + v.x, y + v.y, z + v.z }; }
67cb93a386Sopenharmony_ci    SkV3 operator-(const SkV3& v) const { return { x - v.x, y - v.y, z - v.z }; }
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    SkV3 operator*(const SkV3& v) const {
70cb93a386Sopenharmony_ci        return { x*v.x, y*v.y, z*v.z };
71cb93a386Sopenharmony_ci    }
72cb93a386Sopenharmony_ci    friend SkV3 operator*(const SkV3& v, SkScalar s) {
73cb93a386Sopenharmony_ci        return { v.x*s, v.y*s, v.z*s };
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci    friend SkV3 operator*(SkScalar s, const SkV3& v) { return v*s; }
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    void operator+=(SkV3 v) { *this = *this + v; }
78cb93a386Sopenharmony_ci    void operator-=(SkV3 v) { *this = *this - v; }
79cb93a386Sopenharmony_ci    void operator*=(SkV3 v) { *this = *this * v; }
80cb93a386Sopenharmony_ci    void operator*=(SkScalar s) { *this = *this * s; }
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci    SkScalar lengthSquared() const { return Dot(*this, *this); }
83cb93a386Sopenharmony_ci    SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); }
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    SkScalar dot(const SkV3& v) const { return Dot(*this, v); }
86cb93a386Sopenharmony_ci    SkV3   cross(const SkV3& v) const { return Cross(*this, v); }
87cb93a386Sopenharmony_ci    SkV3 normalize()            const { return Normalize(*this); }
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    const float* ptr() const { return &x; }
90cb93a386Sopenharmony_ci    float* ptr() { return &x; }
91cb93a386Sopenharmony_ci};
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_cistruct SK_API SkV4 {
94cb93a386Sopenharmony_ci    float x, y, z, w;
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    bool operator==(const SkV4& v) const {
97cb93a386Sopenharmony_ci        return x == v.x && y == v.y && z == v.z && w == v.w;
98cb93a386Sopenharmony_ci    }
99cb93a386Sopenharmony_ci    bool operator!=(const SkV4& v) const { return !(*this == v); }
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    SkV4 operator-() const { return {-x, -y, -z, -w}; }
102cb93a386Sopenharmony_ci    SkV4 operator+(const SkV4& v) const { return { x + v.x, y + v.y, z + v.z, w + v.w }; }
103cb93a386Sopenharmony_ci    SkV4 operator-(const SkV4& v) const { return { x - v.x, y - v.y, z - v.z, w - v.w }; }
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci    SkV4 operator*(const SkV4& v) const {
106cb93a386Sopenharmony_ci        return { x*v.x, y*v.y, z*v.z, w*v.w };
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci    friend SkV4 operator*(const SkV4& v, SkScalar s) {
109cb93a386Sopenharmony_ci        return { v.x*s, v.y*s, v.z*s, v.w*s };
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci    friend SkV4 operator*(SkScalar s, const SkV4& v) { return v*s; }
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    const float* ptr() const { return &x; }
114cb93a386Sopenharmony_ci    float* ptr() { return &x; }
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci    float operator[](int i) const {
117cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i < 4);
118cb93a386Sopenharmony_ci        return this->ptr()[i];
119cb93a386Sopenharmony_ci    }
120cb93a386Sopenharmony_ci    float& operator[](int i) {
121cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i < 4);
122cb93a386Sopenharmony_ci        return this->ptr()[i];
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci};
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci/**
127cb93a386Sopenharmony_ci *  4x4 matrix used by SkCanvas and other parts of Skia.
128cb93a386Sopenharmony_ci *
129cb93a386Sopenharmony_ci *  Skia assumes a right-handed coordinate system:
130cb93a386Sopenharmony_ci *      +X goes to the right
131cb93a386Sopenharmony_ci *      +Y goes down
132cb93a386Sopenharmony_ci *      +Z goes into the screen (away from the viewer)
133cb93a386Sopenharmony_ci */
134cb93a386Sopenharmony_ciclass SK_API SkM44 {
135cb93a386Sopenharmony_cipublic:
136cb93a386Sopenharmony_ci    SkM44(const SkM44& src) = default;
137cb93a386Sopenharmony_ci    SkM44& operator=(const SkM44& src) = default;
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci    constexpr SkM44()
140cb93a386Sopenharmony_ci        : fMat{1, 0, 0, 0,
141cb93a386Sopenharmony_ci               0, 1, 0, 0,
142cb93a386Sopenharmony_ci               0, 0, 1, 0,
143cb93a386Sopenharmony_ci               0, 0, 0, 1}
144cb93a386Sopenharmony_ci        {}
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    SkM44(const SkM44& a, const SkM44& b) {
147cb93a386Sopenharmony_ci        this->setConcat(a, b);
148cb93a386Sopenharmony_ci    }
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci    enum Uninitialized_Constructor {
151cb93a386Sopenharmony_ci        kUninitialized_Constructor
152cb93a386Sopenharmony_ci    };
153cb93a386Sopenharmony_ci    SkM44(Uninitialized_Constructor) {}
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    enum NaN_Constructor {
156cb93a386Sopenharmony_ci        kNaN_Constructor
157cb93a386Sopenharmony_ci    };
158cb93a386Sopenharmony_ci    constexpr SkM44(NaN_Constructor)
159cb93a386Sopenharmony_ci        : fMat{SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
160cb93a386Sopenharmony_ci               SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
161cb93a386Sopenharmony_ci               SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
162cb93a386Sopenharmony_ci               SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN}
163cb93a386Sopenharmony_ci    {}
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci    /**
166cb93a386Sopenharmony_ci     *  The constructor parameters are in row-major order.
167cb93a386Sopenharmony_ci     */
168cb93a386Sopenharmony_ci    constexpr SkM44(SkScalar m0, SkScalar m4, SkScalar m8,  SkScalar m12,
169cb93a386Sopenharmony_ci                    SkScalar m1, SkScalar m5, SkScalar m9,  SkScalar m13,
170cb93a386Sopenharmony_ci                    SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
171cb93a386Sopenharmony_ci                    SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15)
172cb93a386Sopenharmony_ci        // fMat is column-major order in memory.
173cb93a386Sopenharmony_ci        : fMat{m0,  m1,  m2,  m3,
174cb93a386Sopenharmony_ci               m4,  m5,  m6,  m7,
175cb93a386Sopenharmony_ci               m8,  m9,  m10, m11,
176cb93a386Sopenharmony_ci               m12, m13, m14, m15}
177cb93a386Sopenharmony_ci    {}
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    static SkM44 Rows(const SkV4& r0, const SkV4& r1, const SkV4& r2, const SkV4& r3) {
180cb93a386Sopenharmony_ci        SkM44 m(kUninitialized_Constructor);
181cb93a386Sopenharmony_ci        m.setRow(0, r0);
182cb93a386Sopenharmony_ci        m.setRow(1, r1);
183cb93a386Sopenharmony_ci        m.setRow(2, r2);
184cb93a386Sopenharmony_ci        m.setRow(3, r3);
185cb93a386Sopenharmony_ci        return m;
186cb93a386Sopenharmony_ci    }
187cb93a386Sopenharmony_ci    static SkM44 Cols(const SkV4& c0, const SkV4& c1, const SkV4& c2, const SkV4& c3) {
188cb93a386Sopenharmony_ci        SkM44 m(kUninitialized_Constructor);
189cb93a386Sopenharmony_ci        m.setCol(0, c0);
190cb93a386Sopenharmony_ci        m.setCol(1, c1);
191cb93a386Sopenharmony_ci        m.setCol(2, c2);
192cb93a386Sopenharmony_ci        m.setCol(3, c3);
193cb93a386Sopenharmony_ci        return m;
194cb93a386Sopenharmony_ci    }
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    static SkM44 RowMajor(const SkScalar r[16]) {
197cb93a386Sopenharmony_ci        return SkM44(r[ 0], r[ 1], r[ 2], r[ 3],
198cb93a386Sopenharmony_ci                     r[ 4], r[ 5], r[ 6], r[ 7],
199cb93a386Sopenharmony_ci                     r[ 8], r[ 9], r[10], r[11],
200cb93a386Sopenharmony_ci                     r[12], r[13], r[14], r[15]);
201cb93a386Sopenharmony_ci    }
202cb93a386Sopenharmony_ci    static SkM44 ColMajor(const SkScalar c[16]) {
203cb93a386Sopenharmony_ci        return SkM44(c[0], c[4], c[ 8], c[12],
204cb93a386Sopenharmony_ci                     c[1], c[5], c[ 9], c[13],
205cb93a386Sopenharmony_ci                     c[2], c[6], c[10], c[14],
206cb93a386Sopenharmony_ci                     c[3], c[7], c[11], c[15]);
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci    static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) {
210cb93a386Sopenharmony_ci        return SkM44(1, 0, 0, x,
211cb93a386Sopenharmony_ci                     0, 1, 0, y,
212cb93a386Sopenharmony_ci                     0, 0, 1, z,
213cb93a386Sopenharmony_ci                     0, 0, 0, 1);
214cb93a386Sopenharmony_ci    }
215cb93a386Sopenharmony_ci
216cb93a386Sopenharmony_ci    static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) {
217cb93a386Sopenharmony_ci        return SkM44(x, 0, 0, 0,
218cb93a386Sopenharmony_ci                     0, y, 0, 0,
219cb93a386Sopenharmony_ci                     0, 0, z, 0,
220cb93a386Sopenharmony_ci                     0, 0, 0, 1);
221cb93a386Sopenharmony_ci    }
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci    static SkM44 Rotate(SkV3 axis, SkScalar radians) {
224cb93a386Sopenharmony_ci        SkM44 m(kUninitialized_Constructor);
225cb93a386Sopenharmony_ci        m.setRotate(axis, radians);
226cb93a386Sopenharmony_ci        return m;
227cb93a386Sopenharmony_ci    }
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci    // Scales and translates 'src' to fill 'dst' exactly.
230cb93a386Sopenharmony_ci    static SkM44 RectToRect(const SkRect& src, const SkRect& dst);
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci    static SkM44 LookAt(const SkV3& eye, const SkV3& center, const SkV3& up);
233cb93a386Sopenharmony_ci    static SkM44 Perspective(float near, float far, float angle);
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    bool operator==(const SkM44& other) const;
236cb93a386Sopenharmony_ci    bool operator!=(const SkM44& other) const {
237cb93a386Sopenharmony_ci        return !(other == *this);
238cb93a386Sopenharmony_ci    }
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ci    void getColMajor(SkScalar v[]) const {
241cb93a386Sopenharmony_ci        memcpy(v, fMat, sizeof(fMat));
242cb93a386Sopenharmony_ci    }
243cb93a386Sopenharmony_ci    void getRowMajor(SkScalar v[]) const;
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ci    SkScalar rc(int r, int c) const {
246cb93a386Sopenharmony_ci        SkASSERT(r >= 0 && r <= 3);
247cb93a386Sopenharmony_ci        SkASSERT(c >= 0 && c <= 3);
248cb93a386Sopenharmony_ci        return fMat[c*4 + r];
249cb93a386Sopenharmony_ci    }
250cb93a386Sopenharmony_ci    void setRC(int r, int c, SkScalar value) {
251cb93a386Sopenharmony_ci        SkASSERT(r >= 0 && r <= 3);
252cb93a386Sopenharmony_ci        SkASSERT(c >= 0 && c <= 3);
253cb93a386Sopenharmony_ci        fMat[c*4 + r] = value;
254cb93a386Sopenharmony_ci    }
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci    SkV4 row(int i) const {
257cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i <= 3);
258cb93a386Sopenharmony_ci        return {fMat[i + 0], fMat[i + 4], fMat[i + 8], fMat[i + 12]};
259cb93a386Sopenharmony_ci    }
260cb93a386Sopenharmony_ci    SkV4 col(int i) const {
261cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i <= 3);
262cb93a386Sopenharmony_ci        return {fMat[i*4 + 0], fMat[i*4 + 1], fMat[i*4 + 2], fMat[i*4 + 3]};
263cb93a386Sopenharmony_ci    }
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    void setRow(int i, const SkV4& v) {
266cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i <= 3);
267cb93a386Sopenharmony_ci        fMat[i + 0]  = v.x;
268cb93a386Sopenharmony_ci        fMat[i + 4]  = v.y;
269cb93a386Sopenharmony_ci        fMat[i + 8]  = v.z;
270cb93a386Sopenharmony_ci        fMat[i + 12] = v.w;
271cb93a386Sopenharmony_ci    }
272cb93a386Sopenharmony_ci    void setCol(int i, const SkV4& v) {
273cb93a386Sopenharmony_ci        SkASSERT(i >= 0 && i <= 3);
274cb93a386Sopenharmony_ci        memcpy(&fMat[i*4], v.ptr(), sizeof(v));
275cb93a386Sopenharmony_ci    }
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci    SkM44& setIdentity() {
278cb93a386Sopenharmony_ci        *this = { 1, 0, 0, 0,
279cb93a386Sopenharmony_ci                  0, 1, 0, 0,
280cb93a386Sopenharmony_ci                  0, 0, 1, 0,
281cb93a386Sopenharmony_ci                  0, 0, 0, 1 };
282cb93a386Sopenharmony_ci        return *this;
283cb93a386Sopenharmony_ci    }
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) {
286cb93a386Sopenharmony_ci        *this = { 1, 0, 0, x,
287cb93a386Sopenharmony_ci                  0, 1, 0, y,
288cb93a386Sopenharmony_ci                  0, 0, 1, z,
289cb93a386Sopenharmony_ci                  0, 0, 0, 1 };
290cb93a386Sopenharmony_ci        return *this;
291cb93a386Sopenharmony_ci    }
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) {
294cb93a386Sopenharmony_ci        *this = { x, 0, 0, 0,
295cb93a386Sopenharmony_ci                  0, y, 0, 0,
296cb93a386Sopenharmony_ci                  0, 0, z, 0,
297cb93a386Sopenharmony_ci                  0, 0, 0, 1 };
298cb93a386Sopenharmony_ci        return *this;
299cb93a386Sopenharmony_ci    }
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ci    /**
302cb93a386Sopenharmony_ci     *  Set this matrix to rotate about the specified unit-length axis vector,
303cb93a386Sopenharmony_ci     *  by an angle specified by its sin() and cos().
304cb93a386Sopenharmony_ci     *
305cb93a386Sopenharmony_ci     *  This does not attempt to verify that axis.length() == 1 or that the sin,cos values
306cb93a386Sopenharmony_ci     *  are correct.
307cb93a386Sopenharmony_ci     */
308cb93a386Sopenharmony_ci    SkM44& setRotateUnitSinCos(SkV3 axis, SkScalar sinAngle, SkScalar cosAngle);
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_ci    /**
311cb93a386Sopenharmony_ci     *  Set this matrix to rotate about the specified unit-length axis vector,
312cb93a386Sopenharmony_ci     *  by an angle specified in radians.
313cb93a386Sopenharmony_ci     *
314cb93a386Sopenharmony_ci     *  This does not attempt to verify that axis.length() == 1.
315cb93a386Sopenharmony_ci     */
316cb93a386Sopenharmony_ci    SkM44& setRotateUnit(SkV3 axis, SkScalar radians) {
317cb93a386Sopenharmony_ci        return this->setRotateUnitSinCos(axis, SkScalarSin(radians), SkScalarCos(radians));
318cb93a386Sopenharmony_ci    }
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_ci    /**
321cb93a386Sopenharmony_ci     *  Set this matrix to rotate about the specified axis vector,
322cb93a386Sopenharmony_ci     *  by an angle specified in radians.
323cb93a386Sopenharmony_ci     *
324cb93a386Sopenharmony_ci     *  Note: axis is not assumed to be unit-length, so it will be normalized internally.
325cb93a386Sopenharmony_ci     *        If axis is already unit-length, call setRotateAboutUnitRadians() instead.
326cb93a386Sopenharmony_ci     */
327cb93a386Sopenharmony_ci    SkM44& setRotate(SkV3 axis, SkScalar radians);
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    SkM44& setConcat(const SkM44& a, const SkM44& b);
330cb93a386Sopenharmony_ci
331cb93a386Sopenharmony_ci    friend SkM44 operator*(const SkM44& a, const SkM44& b) {
332cb93a386Sopenharmony_ci        return SkM44(a, b);
333cb93a386Sopenharmony_ci    }
334cb93a386Sopenharmony_ci
335cb93a386Sopenharmony_ci    SkM44& preConcat(const SkM44& m) {
336cb93a386Sopenharmony_ci        return this->setConcat(*this, m);
337cb93a386Sopenharmony_ci    }
338cb93a386Sopenharmony_ci
339cb93a386Sopenharmony_ci    SkM44& postConcat(const SkM44& m) {
340cb93a386Sopenharmony_ci        return this->setConcat(m, *this);
341cb93a386Sopenharmony_ci    }
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci    /**
344cb93a386Sopenharmony_ci     *  A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 0, 1].
345cb93a386Sopenharmony_ci     *  For most uses, a bottom row of [0, 0, 0, X] behaves like a non-perspective matrix, though
346cb93a386Sopenharmony_ci     *  it will be categorized as perspective. Calling normalizePerspective() will change the
347cb93a386Sopenharmony_ci     *  matrix such that, if its bottom row was [0, 0, 0, X], it will be changed to [0, 0, 0, 1]
348cb93a386Sopenharmony_ci     *  by scaling the rest of the matrix by 1/X.
349cb93a386Sopenharmony_ci     *
350cb93a386Sopenharmony_ci     *  | A B C D |    | A/X B/X C/X D/X |
351cb93a386Sopenharmony_ci     *  | E F G H | -> | E/X F/X G/X H/X |   for X != 0
352cb93a386Sopenharmony_ci     *  | I J K L |    | I/X J/X K/X L/X |
353cb93a386Sopenharmony_ci     *  | 0 0 0 X |    |  0   0   0   1  |
354cb93a386Sopenharmony_ci     */
355cb93a386Sopenharmony_ci    void normalizePerspective();
356cb93a386Sopenharmony_ci
357cb93a386Sopenharmony_ci    /** Returns true if all elements of the matrix are finite. Returns false if any
358cb93a386Sopenharmony_ci        element is infinity, or NaN.
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci        @return  true if matrix has only finite elements
361cb93a386Sopenharmony_ci    */
362cb93a386Sopenharmony_ci    bool isFinite() const { return SkScalarsAreFinite(fMat, 16); }
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci    /** If this is invertible, return that in inverse and return true. If it is
365cb93a386Sopenharmony_ci     *  not invertible, return false and leave the inverse parameter unchanged.
366cb93a386Sopenharmony_ci     */
367cb93a386Sopenharmony_ci    bool SK_WARN_UNUSED_RESULT invert(SkM44* inverse) const;
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci    SkM44 SK_WARN_UNUSED_RESULT transpose() const;
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci    void dump() const;
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ci    /** Writes text representation of SkM44 to string.
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci        @param desc     the string storing a description of parameters.
376cb93a386Sopenharmony_ci        @param depth    the number of tabs preceding each line.
377cb93a386Sopenharmony_ci    */
378cb93a386Sopenharmony_ci    void dump(std::string& desc, int depth) const;
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_ci    ////////////
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci    SkV4 map(float x, float y, float z, float w) const;
383cb93a386Sopenharmony_ci    SkV4 operator*(const SkV4& v) const {
384cb93a386Sopenharmony_ci        return this->map(v.x, v.y, v.z, v.w);
385cb93a386Sopenharmony_ci    }
386cb93a386Sopenharmony_ci    SkV3 operator*(SkV3 v) const {
387cb93a386Sopenharmony_ci        auto v4 = this->map(v.x, v.y, v.z, 0);
388cb93a386Sopenharmony_ci        return {v4.x, v4.y, v4.z};
389cb93a386Sopenharmony_ci    }
390cb93a386Sopenharmony_ci    ////////////////////// Converting to/from SkMatrix
391cb93a386Sopenharmony_ci
392cb93a386Sopenharmony_ci    /* When converting from SkM44 to SkMatrix, the third row and
393cb93a386Sopenharmony_ci     * column is dropped.  When converting from SkMatrix to SkM44
394cb93a386Sopenharmony_ci     * the third row and column remain as identity:
395cb93a386Sopenharmony_ci     * [ a b c ]      [ a b 0 c ]
396cb93a386Sopenharmony_ci     * [ d e f ]  ->  [ d e 0 f ]
397cb93a386Sopenharmony_ci     * [ g h i ]      [ 0 0 1 0 ]
398cb93a386Sopenharmony_ci     *                [ g h 0 i ]
399cb93a386Sopenharmony_ci     */
400cb93a386Sopenharmony_ci    SkMatrix asM33() const {
401cb93a386Sopenharmony_ci        return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12],
402cb93a386Sopenharmony_ci                                 fMat[1], fMat[5], fMat[13],
403cb93a386Sopenharmony_ci                                 fMat[3], fMat[7], fMat[15]);
404cb93a386Sopenharmony_ci    }
405cb93a386Sopenharmony_ci
406cb93a386Sopenharmony_ci    explicit SkM44(const SkMatrix& src)
407cb93a386Sopenharmony_ci    : SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX],  0, src[SkMatrix::kMTransX],
408cb93a386Sopenharmony_ci            src[SkMatrix::kMSkewY],  src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY],
409cb93a386Sopenharmony_ci            0,                       0,                       1, 0,
410cb93a386Sopenharmony_ci            src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2])
411cb93a386Sopenharmony_ci    {}
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci    SkM44& preTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
414cb93a386Sopenharmony_ci    SkM44& postTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_ci    SkM44& preScale(SkScalar x, SkScalar y);
417cb93a386Sopenharmony_ci    SkM44& preScale(SkScalar x, SkScalar y, SkScalar z);
418cb93a386Sopenharmony_ci    SkM44& preConcat(const SkMatrix&);
419cb93a386Sopenharmony_ci
420cb93a386Sopenharmony_ciprivate:
421cb93a386Sopenharmony_ci    /* Stored in column-major.
422cb93a386Sopenharmony_ci     *  Indices
423cb93a386Sopenharmony_ci     *  0  4  8  12        1 0 0 trans_x
424cb93a386Sopenharmony_ci     *  1  5  9  13  e.g.  0 1 0 trans_y
425cb93a386Sopenharmony_ci     *  2  6 10  14        0 0 1 trans_z
426cb93a386Sopenharmony_ci     *  3  7 11  15        0 0 0 1
427cb93a386Sopenharmony_ci     */
428cb93a386Sopenharmony_ci    SkScalar fMat[16];
429cb93a386Sopenharmony_ci
430cb93a386Sopenharmony_ci    friend class SkMatrixPriv;
431cb93a386Sopenharmony_ci};
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci#endif
434