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