Flutter Impeller
impeller::Matrix Struct Reference

A 4x4 matrix using column-major storage. More...

#include <matrix.h>

Public Member Functions

constexpr Matrix ()
 
constexpr Matrix (Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
 
 Matrix (const MatrixDecomposition &decomposition)
 
constexpr Matrix Basis () const
 The Matrix without its w components (without translation). More...
 
constexpr Matrix To3x3 () const
 
constexpr Matrix Translate (const Vector3 &t) const
 
constexpr Matrix Scale (const Vector3 &s) const
 
constexpr Matrix Multiply (const Matrix &o) const
 
constexpr Matrix Transpose () const
 
Matrix Invert () const
 
Scalar GetDeterminant () const
 
bool IsInvertible () const
 
Scalar GetMaxBasisLengthXY () const
 Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases). The matrix might lengthen a non-axis-aligned vector by more than this value. More...
 
std::optional< ScalarGetMinScale2D () const
 Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matrix. If the matrix has perspective components, the method will return a nullopt. More...
 
std::optional< ScalarGetMaxScale2D () const
 Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matrix. If the matrix has perspective components, the method will return a nullopt. More...
 
constexpr Vector3 GetBasisX () const
 
constexpr Vector3 GetBasisY () const
 
constexpr Vector3 GetBasisZ () const
 
Vector3 GetScale () const
 
Scalar GetDirectionScale (Vector3 direction) const
 
bool IsFinite () const
 
constexpr bool IsAffine () const
 
constexpr bool HasPerspective2D () const
 
constexpr bool HasPerspective () const
 
constexpr bool HasTranslation () const
 
constexpr bool IsAligned2D (Scalar tolerance=0) const
 
constexpr bool IsAligned (Scalar tolerance=0) const
 
constexpr bool IsIdentity () const
 
constexpr bool IsTranslationOnly () const
 Returns true if the matrix has no entries other than translation components. Note that an identity matrix meets this criteria. More...
 
constexpr bool IsTranslationScaleOnly () const
 Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix meets this criteria. More...
 
std::optional< MatrixDecompositionDecompose () const
 
std::optional< std::pair< Scalar, Scalar > > GetScales2D () const
 Compute the two non-negative scales applied by this matrix to 2D coordinates and return them as an optional pair of Scalar values in any order. If the matrix has perspective elements, this method will return a nullopt. More...
 
bool Equals (const Matrix &matrix, Scalar epsilon=1e-5f) const
 
constexpr bool operator== (const Matrix &m) const
 
constexpr bool operator!= (const Matrix &m) const
 
Matrix operator+ (const Vector3 &t) const
 
Matrix operator- (const Vector3 &t) const
 
Matrix operator* (const Matrix &m) const
 
Matrix operator+ (const Matrix &m) const
 
constexpr Vector4 operator* (const Vector4 &v) const
 
constexpr Vector3 operator* (const Vector3 &v) const
 
constexpr Point operator* (const Point &v) const
 
constexpr Vector3 TransformHomogenous (const Point &v) const
 
constexpr Vector4 TransformDirection (const Vector4 &v) const
 
constexpr Vector3 TransformDirection (const Vector3 &v) const
 
constexpr Vector2 TransformDirection (const Vector2 &v) const
 
constexpr Quad Transform (const Quad &quad) const
 

Static Public Member Functions

static constexpr Matrix MakeColumn (Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
 
static constexpr Matrix MakeRow (Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
 
static constexpr Matrix MakeTranslation (const Vector3 &t)
 
static constexpr Matrix MakeScale (const Vector3 &s)
 
static constexpr Matrix MakeTranslateScale (const Vector3 &s, const Vector3 &t)
 
static constexpr Matrix MakeScale (const Vector2 &s)
 
static constexpr Matrix MakeSkew (Scalar sx, Scalar sy)
 
static Matrix MakeRotation (Quaternion q)
 
static Matrix MakeRotation (Radians radians, const Vector4 &r)
 
static Matrix MakeRotationX (Radians r)
 
static Matrix MakeRotationY (Radians r)
 
static Matrix MakeRotationZ (Radians r)
 
template<class T >
static constexpr Matrix MakeOrthographic (TSize< T > size)
 
static Matrix MakePerspective (Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
 
template<class T >
static constexpr Matrix MakePerspective (Radians fov_y, TSize< T > size, Scalar z_near, Scalar z_far)
 
static Matrix MakeLookAt (Vector3 position, Vector3 target, Vector3 up)
 
static Vector2 CosSin (Radians radians)
 

Public Attributes

union {
   Scalar   m [16]
 
   Scalar   e [4][4]
 
   Vector4   vec [4]
 
}; 
 

Detailed Description

A 4x4 matrix using column-major storage.

        Utility methods that need to make assumptions about normalized
        device coordinates must use the following convention:
          * Left-handed coordinate system. Positive rotation is
            clockwise about axis of rotation.
          * Lower left corner is -1.0f, -1.0.
          * Upper right corner is  1.0f,  1.0.
          * Visible z-space is from 0.0 to 1.0.
            * This is NOT the same as OpenGL! Be careful.
          * NDC origin is at (0.0f, 0.0f, 0.5f). 

Definition at line 37 of file matrix.h.

Constructor & Destructor Documentation

◆ Matrix() [1/3]

constexpr impeller::Matrix::Matrix ( )
inlineconstexpr

Constructs a default identity matrix.

Definition at line 47 of file matrix.h.

49  : vec{ Vector4(1.0f, 0.0f, 0.0f, 0.0f),
50  Vector4(0.0f, 1.0f, 0.0f, 0.0f),
51  Vector4(0.0f, 0.0f, 1.0f, 0.0f),
52  Vector4(0.0f, 0.0f, 0.0f, 1.0f)} {}
Vector4 vec[4]
Definition: matrix.h:41

Referenced by Basis(), MakeColumn(), MakeRotation(), MakeRotationX(), MakeRotationY(), MakeRotationZ(), MakeRow(), MakeScale(), MakeSkew(), MakeTranslateScale(), MakeTranslation(), Multiply(), operator+(), Scale(), To3x3(), and Translate().

◆ Matrix() [2/3]

constexpr impeller::Matrix::Matrix ( Scalar  m0,
Scalar  m1,
Scalar  m2,
Scalar  m3,
Scalar  m4,
Scalar  m5,
Scalar  m6,
Scalar  m7,
Scalar  m8,
Scalar  m9,
Scalar  m10,
Scalar  m11,
Scalar  m12,
Scalar  m13,
Scalar  m14,
Scalar  m15 
)
inlineconstexpr

Definition at line 56 of file matrix.h.

60  : vec{Vector4(m0, m1, m2, m3),
61  Vector4(m4, m5, m6, m7),
62  Vector4(m8, m9, m10, m11),
63  Vector4(m12, m13, m14, m15)} {}

◆ Matrix() [3/3]

impeller::Matrix::Matrix ( const MatrixDecomposition decomposition)
explicit

Definition at line 14 of file matrix.cc.

14  : Matrix() {
15  /*
16  * Apply perspective.
17  */
18  for (int i = 0; i < 4; i++) {
19  e[i][3] = d.perspective.e[i];
20  }
21 
22  /*
23  * Apply translation.
24  */
25  for (int i = 0; i < 3; i++) {
26  for (int j = 0; j < 3; j++) {
27  e[3][i] += d.translation.e[j] * e[j][i];
28  }
29  }
30 
31  /*
32  * Apply rotation.
33  */
34 
35  Matrix rotation;
36 
37  const auto x = -d.rotation.x;
38  const auto y = -d.rotation.y;
39  const auto z = -d.rotation.z;
40  const auto w = d.rotation.w;
41 
42  /*
43  * Construct a composite rotation matrix from the quaternion values.
44  */
45 
46  rotation.e[0][0] = 1.0 - 2.0 * (y * y + z * z);
47  rotation.e[0][1] = 2.0 * (x * y - z * w);
48  rotation.e[0][2] = 2.0 * (x * z + y * w);
49  rotation.e[1][0] = 2.0 * (x * y + z * w);
50  rotation.e[1][1] = 1.0 - 2.0 * (x * x + z * z);
51  rotation.e[1][2] = 2.0 * (y * z - x * w);
52  rotation.e[2][0] = 2.0 * (x * z - y * w);
53  rotation.e[2][1] = 2.0 * (y * z + x * w);
54  rotation.e[2][2] = 1.0 - 2.0 * (x * x + y * y);
55 
56  *this = *this * rotation;
57 
58  /*
59  * Apply shear.
60  */
61  Matrix shear;
62 
63  if (d.shear.e[2] != 0) {
64  shear.e[2][1] = d.shear.e[2];
65  *this = *this * shear;
66  }
67 
68  if (d.shear.e[1] != 0) {
69  shear.e[2][1] = 0.0;
70  shear.e[2][0] = d.shear.e[1];
71  *this = *this * shear;
72  }
73 
74  if (d.shear.e[0] != 0) {
75  shear.e[2][0] = 0.0;
76  shear.e[1][0] = d.shear.e[0];
77  *this = *this * shear;
78  }
79 
80  /*
81  * Apply scale.
82  */
83  for (int i = 0; i < 3; i++) {
84  for (int j = 0; j < 3; j++) {
85  e[i][j] *= d.scale.e[i];
86  }
87  }
88 }
int32_t x
constexpr Matrix()
Definition: matrix.h:47
Scalar e[4][4]
Definition: matrix.h:40

References impeller::Shear::e, impeller::Vector3::e, impeller::Vector4::e, e, impeller::MatrixDecomposition::perspective, impeller::MatrixDecomposition::rotation, impeller::MatrixDecomposition::scale, impeller::MatrixDecomposition::shear, impeller::MatrixDecomposition::translation, impeller::Quaternion::w, x, impeller::Quaternion::x, impeller::Quaternion::y, and impeller::Quaternion::z.

Member Function Documentation

◆ Basis()

constexpr Matrix impeller::Matrix::Basis ( ) const
inlineconstexpr

The Matrix without its w components (without translation).

Definition at line 239 of file matrix.h.

239  {
240  // clang-format off
241  return Matrix(
242  m[0], m[1], m[2], 0.0f,
243  m[4], m[5], m[6], 0.0f,
244  m[8], m[9], m[10], 0.0f,
245  0.0f, 0.0f, 0.0f, 1.0
246  );
247  // clang-format on
248  }
Scalar m[16]
Definition: matrix.h:39

References m, and Matrix().

Referenced by impeller::TextContents::ComputeVertexData(), GetDirectionScale(), impeller::DirectionalMorphologyFilterContents::GetFilterCoverage(), impeller::GaussianBlurFilterContents::GetFilterSourceCoverage(), impeller::LocalMatrixFilterContents::GetFilterSourceCoverage(), impeller::SolidRRectLikeBlurContents::Render(), and impeller::testing::TEST().

◆ CosSin()

static Vector2 impeller::Matrix::CosSin ( Radians  radians)
inlinestatic

Definition at line 685 of file matrix.h.

685  {
686  // The precision of a float around 1.0 is much lower than it is
687  // around 0.0, so we end up with cases on quadrant rotations where
688  // we get a +/-1.0 for one of the values and a non-zero value for
689  // the other. This happens around quadrant rotations which makes it
690  // especially common and results in unclean quadrant rotation
691  // matrices which do not return true from |IsAligned[2D]| even
692  // though that is exactly where you need them to exhibit that property.
693  // It also injects small floating point mantissa errors into the
694  // matrices whenever you concatenate them with a quadrant rotation.
695  //
696  // This issue is also exacerbated by the fact that, in radians, the
697  // angles for quadrant rotations are irrational numbers. The measuring
698  // error for representing 90 degree multiples is small enough that
699  // either sin or cos will return a value near +/-1.0, but not small
700  // enough that the other value will be a clean 0.0.
701  //
702  // Some geometry packages simply discard very small numbers from
703  // sin/cos, but the following approach specifically targets just the
704  // area around a quadrant rotation (where either the sin or cos are
705  // measuring as +/-1.0) for symmetry of precision.
706 
707  Scalar sin = std::sin(radians.radians);
708  if (std::abs(sin) == 1.0f) {
709  // 90 or 270 degrees (mod 360)
710  return {0.0f, sin};
711  } else {
712  Scalar cos = std::cos(radians.radians);
713  if (std::abs(cos) == 1.0f) {
714  // 0 or 180 degrees (mod 360)
715  return {cos, 0.0f};
716  }
717  return {cos, sin};
718  }
719  }
float Scalar
Definition: scalar.h:19

References impeller::Radians::radians.

Referenced by impeller::Arc::ComputeIterations(), impeller::Arc::GetTightArcBounds(), impeller::RSTransform::Make(), MakeRotation(), MakeRotationX(), MakeRotationY(), and MakeRotationZ().

◆ Decompose()

std::optional< MatrixDecomposition > impeller::Matrix::Decompose ( ) const

Definition at line 202 of file matrix.cc.

202  {
203  /*
204  * Normalize the matrix.
205  */
206  Matrix self = *this;
207 
208  if (self.e[3][3] == 0) {
209  return std::nullopt;
210  }
211 
212  for (int i = 0; i < 4; i++) {
213  for (int j = 0; j < 4; j++) {
214  self.e[i][j] /= self.e[3][3];
215  }
216  }
217 
218  /*
219  * `perspectiveMatrix` is used to solve for perspective, but it also provides
220  * an easy way to test for singularity of the upper 3x3 component.
221  */
222  Matrix perpectiveMatrix = self;
223  for (int i = 0; i < 3; i++) {
224  perpectiveMatrix.e[i][3] = 0;
225  }
226 
227  perpectiveMatrix.e[3][3] = 1;
228 
229  if (!perpectiveMatrix.IsInvertible()) {
230  return std::nullopt;
231  }
232 
233  MatrixDecomposition result;
234 
235  /*
236  * ==========================================================================
237  * First, isolate perspective.
238  * ==========================================================================
239  */
240  if (self.e[0][3] != 0.0 || self.e[1][3] != 0.0 || self.e[2][3] != 0.0) {
241  /*
242  * prhs is the right hand side of the equation.
243  */
244  const Vector4 rightHandSide(self.e[0][3], //
245  self.e[1][3], //
246  self.e[2][3], //
247  self.e[3][3]);
248 
249  /*
250  * Solve the equation by inverting `perspectiveMatrix` and multiplying
251  * prhs by the inverse.
252  */
253 
254  result.perspective = perpectiveMatrix.Invert().Transpose() * rightHandSide;
255 
256  /*
257  * Clear the perspective partition.
258  */
259  self.e[0][3] = self.e[1][3] = self.e[2][3] = 0;
260  self.e[3][3] = 1;
261  }
262 
263  /*
264  * ==========================================================================
265  * Next, the translation.
266  * ==========================================================================
267  */
268  result.translation = {self.e[3][0], self.e[3][1], self.e[3][2]};
269  self.e[3][0] = self.e[3][1] = self.e[3][2] = 0.0;
270 
271  /*
272  * ==========================================================================
273  * Next, the scale and shear.
274  * ==========================================================================
275  */
276  Vector3 row[3];
277  for (int i = 0; i < 3; i++) {
278  row[i].x = self.e[i][0];
279  row[i].y = self.e[i][1];
280  row[i].z = self.e[i][2];
281  }
282 
283  /*
284  * Compute X scale factor and normalize first row.
285  */
286  result.scale.x = row[0].GetLength();
287  row[0] = row[0].Normalize();
288 
289  /*
290  * Compute XY shear factor and make 2nd row orthogonal to 1st.
291  */
292  result.shear.xy = row[0].Dot(row[1]);
293  row[1] = Vector3::Combine(row[1], 1.0, row[0], -result.shear.xy);
294 
295  /*
296  * Compute Y scale and normalize 2nd row.
297  */
298  result.scale.y = row[1].GetLength();
299  row[1] = row[1].Normalize();
300  result.shear.xy /= result.scale.y;
301 
302  /*
303  * Compute XZ and YZ shears, orthogonalize 3rd row.
304  */
305  result.shear.xz = row[0].Dot(row[2]);
306  row[2] = Vector3::Combine(row[2], 1.0, row[0], -result.shear.xz);
307  result.shear.yz = row[1].Dot(row[2]);
308  row[2] = Vector3::Combine(row[2], 1.0, row[1], -result.shear.yz);
309 
310  /*
311  * Next, get Z scale and normalize 3rd row.
312  */
313  result.scale.z = row[2].GetLength();
314  row[2] = row[2].Normalize();
315 
316  result.shear.xz /= result.scale.z;
317  result.shear.yz /= result.scale.z;
318 
319  /*
320  * At this point, the matrix (in rows[]) is orthonormal.
321  * Check for a coordinate system flip. If the determinant
322  * is -1, then negate the matrix and the scaling factors.
323  */
324  if (row[0].Dot(row[1].Cross(row[2])) < 0) {
325  result.scale.x *= -1;
326  result.scale.y *= -1;
327  result.scale.z *= -1;
328 
329  for (int i = 0; i < 3; i++) {
330  row[i].x *= -1;
331  row[i].y *= -1;
332  row[i].z *= -1;
333  }
334  }
335 
336  /*
337  * ==========================================================================
338  * Finally, get the rotations out.
339  * ==========================================================================
340  */
341  result.rotation.x =
342  0.5 * sqrt(fmax(1.0 + row[0].x - row[1].y - row[2].z, 0.0));
343  result.rotation.y =
344  0.5 * sqrt(fmax(1.0 - row[0].x + row[1].y - row[2].z, 0.0));
345  result.rotation.z =
346  0.5 * sqrt(fmax(1.0 - row[0].x - row[1].y + row[2].z, 0.0));
347  result.rotation.w =
348  0.5 * sqrt(fmax(1.0 + row[0].x + row[1].y + row[2].z, 0.0));
349 
350  if (row[2].y > row[1].z) {
351  result.rotation.x = -result.rotation.x;
352  }
353  if (row[0].z > row[2].x) {
354  result.rotation.y = -result.rotation.y;
355  }
356  if (row[1].x > row[0].y) {
357  result.rotation.z = -result.rotation.z;
358  }
359 
360  return result;
361 }
static constexpr Vector3 Combine(const Vector3 &a, Scalar aScale, const Vector3 &b, Scalar bScale)
Definition: vector.h:192

References impeller::Vector3::Combine(), impeller::Vector3::Dot(), impeller::Vector3::e, impeller::Vector4::e, e, impeller::Vector3::GetLength(), Invert(), IsInvertible(), impeller::Vector3::Normalize(), impeller::MatrixDecomposition::perspective, impeller::MatrixDecomposition::rotation, impeller::MatrixDecomposition::scale, impeller::MatrixDecomposition::shear, impeller::MatrixDecomposition::translation, Transpose(), impeller::Quaternion::w, x, impeller::Quaternion::x, impeller::Vector3::x, impeller::Shear::xy, impeller::Shear::xz, impeller::Quaternion::y, impeller::Vector3::y, impeller::Shear::yz, impeller::Quaternion::z, and impeller::Vector3::z.

Referenced by impeller::testing::TEST().

◆ Equals()

bool impeller::Matrix::Equals ( const Matrix matrix,
Scalar  epsilon = 1e-5f 
) const
inline

Definition at line 520 of file matrix.h.

520  {
521  const Scalar* a = m;
522  const Scalar* b = matrix.m;
523  return ScalarNearlyEqual(a[0], b[0], epsilon) &&
524  ScalarNearlyEqual(a[1], b[1], epsilon) &&
525  ScalarNearlyEqual(a[2], b[2], epsilon) &&
526  ScalarNearlyEqual(a[3], b[3], epsilon) &&
527  ScalarNearlyEqual(a[4], b[4], epsilon) &&
528  ScalarNearlyEqual(a[5], b[5], epsilon) &&
529  ScalarNearlyEqual(a[6], b[6], epsilon) &&
530  ScalarNearlyEqual(a[7], b[7], epsilon) &&
531  ScalarNearlyEqual(a[8], b[8], epsilon) &&
532  ScalarNearlyEqual(a[9], b[9], epsilon) &&
533  ScalarNearlyEqual(a[10], b[10], epsilon) &&
534  ScalarNearlyEqual(a[11], b[11], epsilon) &&
535  ScalarNearlyEqual(a[12], b[12], epsilon) &&
536  ScalarNearlyEqual(a[13], b[13], epsilon) &&
537  ScalarNearlyEqual(a[14], b[14], epsilon) &&
538  ScalarNearlyEqual(a[15], b[15], epsilon);
539  }
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:36

References impeller::saturated::b, m, and impeller::ScalarNearlyEqual().

◆ GetBasisX()

constexpr Vector3 impeller::Matrix::GetBasisX ( ) const
inlineconstexpr

Definition at line 388 of file matrix.h.

388 { return Vector3(m[0], m[1], m[2]); }

References m.

Referenced by impeller::Paint::MaskBlurDescriptor::CreateMaskBlur(), and GetScale().

◆ GetBasisY()

constexpr Vector3 impeller::Matrix::GetBasisY ( ) const
inlineconstexpr

Definition at line 390 of file matrix.h.

390 { return Vector3(m[4], m[5], m[6]); }

References m.

Referenced by impeller::Paint::MaskBlurDescriptor::CreateMaskBlur(), and GetScale().

◆ GetBasisZ()

constexpr Vector3 impeller::Matrix::GetBasisZ ( ) const
inlineconstexpr

Definition at line 392 of file matrix.h.

392 { return Vector3(m[8], m[9], m[10]); }

References m.

Referenced by GetScale().

◆ GetDeterminant()

Scalar impeller::Matrix::GetDeterminant ( ) const

Definition at line 164 of file matrix.cc.

164  {
165  auto a00 = e[0][0];
166  auto a01 = e[0][1];
167  auto a02 = e[0][2];
168  auto a03 = e[0][3];
169  auto a10 = e[1][0];
170  auto a11 = e[1][1];
171  auto a12 = e[1][2];
172  auto a13 = e[1][3];
173  auto a20 = e[2][0];
174  auto a21 = e[2][1];
175  auto a22 = e[2][2];
176  auto a23 = e[2][3];
177  auto a30 = e[3][0];
178  auto a31 = e[3][1];
179  auto a32 = e[3][2];
180  auto a33 = e[3][3];
181 
182  auto b00 = a00 * a11 - a01 * a10;
183  auto b01 = a00 * a12 - a02 * a10;
184  auto b02 = a00 * a13 - a03 * a10;
185  auto b03 = a01 * a12 - a02 * a11;
186  auto b04 = a01 * a13 - a03 * a11;
187  auto b05 = a02 * a13 - a03 * a12;
188  auto b06 = a20 * a31 - a21 * a30;
189  auto b07 = a20 * a32 - a22 * a30;
190  auto b08 = a20 * a33 - a23 * a30;
191  auto b09 = a21 * a32 - a22 * a31;
192  auto b10 = a21 * a33 - a23 * a31;
193  auto b11 = a22 * a33 - a23 * a32;
194 
195  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
196 }

References e.

Referenced by IsInvertible().

◆ GetDirectionScale()

Scalar impeller::Matrix::GetDirectionScale ( Vector3  direction) const
inline

Definition at line 399 of file matrix.h.

399  {
400  return 1.0f / (this->Basis().Invert() * direction.Normalize()).GetLength() *
401  direction.GetLength();
402  }
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
Definition: matrix.h:239
Matrix Invert() const
Definition: matrix.cc:99

References Basis(), impeller::Vector3::GetLength(), Invert(), and impeller::Vector3::Normalize().

Referenced by impeller::testing::TEST().

◆ GetMaxBasisLengthXY()

Scalar impeller::Matrix::GetMaxBasisLengthXY ( ) const
inline

Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases). The matrix might lengthen a non-axis-aligned vector by more than this value.

See also
|GetMaxScale2D|

Definition at line 328 of file matrix.h.

328  {
329  // The full basis computation requires computing the squared scaling factor
330  // for translate/scale only matrices. This substantially limits the range of
331  // precision for small and large scales. Instead, check for the common cases
332  // and directly return the max scaling factor.
333  if (e[0][1] == 0 && e[1][0] == 0) {
334  return std::max(std::abs(e[0][0]), std::abs(e[1][1]));
335  }
336  return std::sqrt(std::max(e[0][0] * e[0][0] + e[0][1] * e[0][1],
337  e[1][0] * e[1][0] + e[1][1] * e[1][1]));
338  }

References e.

Referenced by impeller::LineContents::CalculatePerVertex(), impeller::Canvas::DrawTextFrame(), impeller::Tessellator::FilledArc(), impeller::Tessellator::FilledCircle(), impeller::Tessellator::FilledEllipse(), impeller::Tessellator::FilledRoundRect(), impeller::StrokeRectGeometry::GetPositionBuffer(), impeller::LineContents::Render(), impeller::Tessellator::RoundCapLine(), impeller::Tessellator::StrokedArc(), impeller::Tessellator::StrokedCircle(), and impeller::testing::TEST().

◆ GetMaxScale2D()

std::optional<Scalar> impeller::Matrix::GetMaxScale2D ( ) const
inline

Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matrix. If the matrix has perspective components, the method will return a nullopt.

Note that negative scale factors really represent a positive scale factor with a flip, so the absolute value (the positive scale factor) is returned instead so that the results can be directly applied to rendering calculations to compute the potential size of an operation.

This method differs from the "basis length" methods in that those methods answer the question "how much does this transform stretch perfectly horizontal or vertical source vectors, whereas this method can answer "what's the largest scale applied to any vector regardless of direction".

See also
|GetScales2D|

Definition at line 380 of file matrix.h.

380  {
381  auto scales = GetScales2D();
382  if (!scales.has_value()) {
383  return std::nullopt;
384  }
385  return std::max(scales->first, scales->second);
386  }
std::optional< std::pair< Scalar, Scalar > > GetScales2D() const
Compute the two non-negative scales applied by this matrix to 2D coordinates and return them as an op...
Definition: matrix.cc:363

References GetScales2D().

Referenced by impeller::testing::TEST().

◆ GetMinScale2D()

std::optional<Scalar> impeller::Matrix::GetMinScale2D ( ) const
inline

Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matrix. If the matrix has perspective components, the method will return a nullopt.

Note that negative scale factors really represent a positive scale factor with a flip, so the absolute value (the positive scale factor) is returned instead so that the results can be directly applied to rendering calculations to compute the potential size of an operation.

This method differs from the "basis length" methods in that those methods answer the question "how much does this transform stretch perfectly horizontal or vertical source vectors, whereas this method can answer "what's the smallest scale applied to any vector regardless of direction".

See also
|GetScales2D|

Definition at line 356 of file matrix.h.

356  {
357  auto scales = GetScales2D();
358  if (!scales.has_value()) {
359  return std::nullopt;
360  }
361  return std::min(scales->first, scales->second);
362  }

References GetScales2D().

Referenced by impeller::testing::TEST().

◆ GetScale()

Vector3 impeller::Matrix::GetScale ( ) const
inline

Definition at line 394 of file matrix.h.

394  {
395  return Vector3(GetBasisX().GetLength(), GetBasisY().GetLength(),
396  GetBasisZ().GetLength());
397  }
constexpr Vector3 GetBasisY() const
Definition: matrix.h:390
constexpr Vector3 GetBasisZ() const
Definition: matrix.h:392
constexpr Vector3 GetBasisX() const
Definition: matrix.h:388

References GetBasisX(), GetBasisY(), and GetBasisZ().

Referenced by impeller::DlDispatcherBase::drawShadow().

◆ GetScales2D()

std::optional< std::pair< Scalar, Scalar > > impeller::Matrix::GetScales2D ( ) const

Compute the two non-negative scales applied by this matrix to 2D coordinates and return them as an optional pair of Scalar values in any order. If the matrix has perspective elements, this method will return a nullopt.

Note that negative scale factors really represent a positive scale factor with a flip, so the absolute value (the positive scale factor) is returned instead so that the results can be directly applied to rendering calculations to compute the potential size of an operation.

See also
|GetMinScale2D|
|GetMaxScale2D|

Definition at line 363 of file matrix.cc.

363  {
364  if (HasPerspective2D()) {
365  return std::nullopt;
366  }
367 
368  // We only operate on the uppermost 2x2 matrix since those are the only
369  // values that can induce a scale on 2D coordinates.
370  // [ a b ]
371  // [ c d ]
372  double a = m[0];
373  double b = m[1];
374  double c = m[4];
375  double d = m[5];
376 
377  if (b == 0.0f && c == 0.0f) {
378  return {{std::abs(a), std::abs(d)}};
379  }
380 
381  if (a == 0.0f && d == 0.0f) {
382  return {{std::abs(b), std::abs(c)}};
383  }
384 
385  // Compute eigenvalues for the matrix (transpose(A) * A):
386  // [ a2 b2 ] == [ a b ] [ a c ] == [ aa + bb ac + bd ]
387  // [ c2 d2 ] [ c d ] [ b d ] [ ac + bd cc + dd ]
388  // (note the reverse diagonal entries in the answer are identical)
389  double a2 = a * a + b * b;
390  double b2 = a * c + b * d;
391  double c2 = b2;
392  double d2 = c * c + d * d;
393 
394  //
395  // If L is an eigenvalue, then
396  // det(this - L*Identity) == 0
397  // det([ a - L b ]
398  // [ c d - L ]) == 0
399  // (a - L) * (d - L) - bc == 0
400  // ad - aL - dL + L^2 - bc == 0
401  // L^2 + (-a + -d)L + ad - bc == 0
402  //
403  // Using quadratic equation for (Ax^2 + Bx + C):
404  // A == 1
405  // B == -(a2 + d2)
406  // C == a2d2 - b2c2
407  //
408  // (We use -B for calculations because the square is the same as B and we
409  // need -B for the final quadratic equation computations anyway.)
410  double minus_B = a2 + d2;
411  double C = a2 * d2 - b2 * c2;
412  double B_squared_minus_4AC = minus_B * minus_B - 4 * 1.0f * C;
413 
414  double quadratic_sqrt;
415  if (B_squared_minus_4AC <= 0.0f) {
416  // This test should never fail, but we might be slightly negative
417  FML_DCHECK(B_squared_minus_4AC + kEhCloseEnough >= 0.0f);
418  // Uniform scales (possibly rotated) would tend to end up here
419  // in which case both eigenvalues are identical
420  quadratic_sqrt = 0.0f;
421  } else {
422  quadratic_sqrt = std::sqrt(B_squared_minus_4AC);
423  }
424 
425  // Since this is returning the sqrt of the values, we can guarantee that
426  // the returned scales are non-negative.
427  FML_DCHECK(minus_B - quadratic_sqrt >= 0.0f);
428  FML_DCHECK(minus_B + quadratic_sqrt >= 0.0f);
429  return {{std::sqrt((minus_B - quadratic_sqrt) / 2.0f),
430  std::sqrt((minus_B + quadratic_sqrt) / 2.0f)}};
431 }
constexpr float kEhCloseEnough
Definition: constants.h:57
constexpr bool HasPerspective2D() const
Definition: matrix.h:414

References impeller::saturated::b, HasPerspective2D(), impeller::kEhCloseEnough, and m.

Referenced by GetMaxScale2D(), GetMinScale2D(), and impeller::testing::TEST().

◆ HasPerspective()

constexpr bool impeller::Matrix::HasPerspective ( ) const
inlineconstexpr

Definition at line 418 of file matrix.h.

418  {
419  return m[3] != 0 || m[7] != 0 || m[11] != 0 || m[15] != 1;
420  }

References m.

Referenced by impeller::DlDispatcherBase::drawDisplayList(), impeller::FirstPassDispatcher::drawDisplayList(), IsAligned(), and impeller::testing::TEST().

◆ HasPerspective2D()

constexpr bool impeller::Matrix::HasPerspective2D ( ) const
inlineconstexpr

Definition at line 414 of file matrix.h.

414  {
415  return m[3] != 0 || m[7] != 0 || m[15] != 1;
416  }

References m.

Referenced by GetScales2D(), IsAligned2D(), and impeller::testing::TEST().

◆ HasTranslation()

constexpr bool impeller::Matrix::HasTranslation ( ) const
inlineconstexpr

Definition at line 422 of file matrix.h.

422 { return m[12] != 0 || m[13] != 0; }

References m.

◆ Invert()

Matrix impeller::Matrix::Invert ( ) const

Definition at line 99 of file matrix.cc.

99  {
100  Matrix tmp{
101  m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] +
102  m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10],
103 
104  -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] -
105  m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10],
106 
107  m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] +
108  m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6],
109 
110  -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] -
111  m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6],
112 
113  -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] -
114  m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10],
115 
116  m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] +
117  m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10],
118 
119  -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] -
120  m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6],
121 
122  m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] +
123  m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6],
124 
125  m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] +
126  m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9],
127 
128  -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] -
129  m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9],
130 
131  m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] +
132  m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5],
133 
134  -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] -
135  m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5],
136 
137  -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] -
138  m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9],
139 
140  m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] +
141  m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9],
142 
143  -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] -
144  m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5],
145 
146  m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] +
147  m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]};
148 
149  Scalar det =
150  m[0] * tmp.m[0] + m[1] * tmp.m[4] + m[2] * tmp.m[8] + m[3] * tmp.m[12];
151 
152  if (det == 0) {
153  return {};
154  }
155 
156  det = 1.0 / det;
157 
158  return {tmp.m[0] * det, tmp.m[1] * det, tmp.m[2] * det, tmp.m[3] * det,
159  tmp.m[4] * det, tmp.m[5] * det, tmp.m[6] * det, tmp.m[7] * det,
160  tmp.m[8] * det, tmp.m[9] * det, tmp.m[10] * det, tmp.m[11] * det,
161  tmp.m[12] * det, tmp.m[13] * det, tmp.m[14] * det, tmp.m[15] * det};
162 }

References m.

Referenced by Decompose(), GetDirectionScale(), impeller::MatrixFilterContents::GetFilterCoverage(), impeller::LocalMatrixFilterContents::GetFilterSourceCoverage(), impeller::Snapshot::GetUVTransform(), impeller::TextShadowCache::Lookup(), impeller::SolidRRectLikeBlurContents::Render(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::ColorSourceContents::SetEffectTransform(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ IsAffine()

constexpr bool impeller::Matrix::IsAffine ( ) const
inlineconstexpr

Definition at line 409 of file matrix.h.

409  {
410  return (m[2] == 0 && m[3] == 0 && m[6] == 0 && m[7] == 0 && m[8] == 0 &&
411  m[9] == 0 && m[10] == 1 && m[11] == 0 && m[14] == 0 && m[15] == 1);
412  }

References m.

◆ IsAligned()

constexpr bool impeller::Matrix::IsAligned ( Scalar  tolerance = 0) const
inlineconstexpr

Definition at line 439 of file matrix.h.

439  {
440  if (HasPerspective()) {
441  return false;
442  }
443  int v[] = {!ScalarNearlyZero(m[0], tolerance), //
444  !ScalarNearlyZero(m[1], tolerance), //
445  !ScalarNearlyZero(m[2], tolerance), //
446  !ScalarNearlyZero(m[4], tolerance), //
447  !ScalarNearlyZero(m[5], tolerance), //
448  !ScalarNearlyZero(m[6], tolerance), //
449  !ScalarNearlyZero(m[8], tolerance), //
450  !ScalarNearlyZero(m[9], tolerance), //
451  !ScalarNearlyZero(m[10], tolerance)};
452  // Check if all three basis vectors are aligned to an axis.
453  if (v[0] + v[1] + v[2] != 1 || //
454  v[3] + v[4] + v[5] != 1 || //
455  v[6] + v[7] + v[8] != 1) {
456  return false;
457  }
458  // Ensure that none of the basis vectors overlap.
459  if (v[0] + v[3] + v[6] != 1 || //
460  v[1] + v[4] + v[7] != 1 || //
461  v[2] + v[5] + v[8] != 1) {
462  return false;
463  }
464  return true;
465  }
constexpr bool ScalarNearlyZero(Scalar x, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:31
constexpr bool HasPerspective() const
Definition: matrix.h:418

References HasPerspective(), m, and impeller::ScalarNearlyZero().

Referenced by impeller::testing::TEST().

◆ IsAligned2D()

constexpr bool impeller::Matrix::IsAligned2D ( Scalar  tolerance = 0) const
inlineconstexpr

Definition at line 424 of file matrix.h.

424  {
425  if (HasPerspective2D()) {
426  return false;
427  }
428  if (ScalarNearlyZero(m[1], tolerance) &&
429  ScalarNearlyZero(m[4], tolerance)) {
430  return true;
431  }
432  if (ScalarNearlyZero(m[0], tolerance) &&
433  ScalarNearlyZero(m[5], tolerance)) {
434  return true;
435  }
436  return false;
437  }

References HasPerspective2D(), m, and impeller::ScalarNearlyZero().

Referenced by impeller::testing::TEST().

◆ IsFinite()

bool impeller::Matrix::IsFinite ( ) const
inline

Definition at line 404 of file matrix.h.

404  {
405  return vec[0].IsFinite() && vec[1].IsFinite() && vec[2].IsFinite() &&
406  vec[3].IsFinite();
407  }
bool IsFinite() const
Definition: vector.h:258

References impeller::Vector4::IsFinite(), and vec.

Referenced by impeller::testing::TEST().

◆ IsIdentity()

constexpr bool impeller::Matrix::IsIdentity ( ) const
inlineconstexpr

Definition at line 467 of file matrix.h.

467  {
468  return (
469  // clang-format off
470  m[0] == 1.0f && m[1] == 0.0f && m[2] == 0.0f && m[3] == 0.0f &&
471  m[4] == 0.0f && m[5] == 1.0f && m[6] == 0.0f && m[7] == 0.0f &&
472  m[8] == 0.0f && m[9] == 0.0f && m[10] == 1.0f && m[11] == 0.0f &&
473  m[12] == 0.0f && m[13] == 0.0f && m[14] == 0.0f && m[15] == 1.0f
474  // clang-format on
475  );
476  }

References m.

Referenced by impeller::testing::TEST_P(), and impeller::interop::testing::TEST_P().

◆ IsInvertible()

bool impeller::Matrix::IsInvertible ( ) const
inline

Definition at line 321 of file matrix.h.

321 { return GetDeterminant() != 0; }
Scalar GetDeterminant() const
Definition: matrix.cc:164

References GetDeterminant().

Referenced by Decompose(), and impeller::testing::TEST_P().

◆ IsTranslationOnly()

constexpr bool impeller::Matrix::IsTranslationOnly ( ) const
inlineconstexpr

Returns true if the matrix has no entries other than translation components. Note that an identity matrix meets this criteria.

Definition at line 480 of file matrix.h.

480  {
481  return (
482  // clang-format off
483  m[0] == 1.0 && m[1] == 0.0 && m[2] == 0.0 && m[3] == 0.0 &&
484  m[4] == 0.0 && m[5] == 1.0 && m[6] == 0.0 && m[7] == 0.0 &&
485  m[8] == 0.0 && m[9] == 0.0 && m[10] == 1.0 && m[11] == 0.0 &&
486  m[15] == 1.0
487  // clang-format on
488  );
489  }

References m.

◆ IsTranslationScaleOnly()

constexpr bool impeller::Matrix::IsTranslationScaleOnly ( ) const
inlineconstexpr

Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix meets this criteria.

Definition at line 493 of file matrix.h.

493  {
494  return (
495  // clang-format off
496  m[0] != 0.0 && m[1] == 0.0 && m[2] == 0.0 && m[3] == 0.0 &&
497  m[4] == 0.0 && m[5] != 0.0 && m[6] == 0.0 && m[7] == 0.0 &&
498  m[8] == 0.0 && m[9] == 0.0 && m[10] != 0.0 && m[11] == 0.0 &&
499  m[15] == 1.0
500  // clang-format on
501  );
502  }

References m.

Referenced by impeller::TextContents::ComputeVertexData(), and impeller::TextContents::Render().

◆ MakeColumn()

static constexpr Matrix impeller::Matrix::MakeColumn ( Scalar  m0,
Scalar  m1,
Scalar  m2,
Scalar  m3,
Scalar  m4,
Scalar  m5,
Scalar  m6,
Scalar  m7,
Scalar  m8,
Scalar  m9,
Scalar  m10,
Scalar  m11,
Scalar  m12,
Scalar  m13,
Scalar  m14,
Scalar  m15 
)
inlinestaticconstexpr

Definition at line 69 of file matrix.h.

73  {
74  return Matrix(m0, m1, m2, m3,
75  m4, m5, m6, m7,
76  m8, m9, m10, m11,
77  m12, m13, m14, m15);
78 
79  }

References Matrix().

Referenced by impeller::testing::TEST(), impeller::FirstPassDispatcher::transform2DAffine(), and impeller::FirstPassDispatcher::transformFullPerspective().

◆ MakeLookAt()

static Matrix impeller::Matrix::MakeLookAt ( Vector3  position,
Vector3  target,
Vector3  up 
)
inlinestatic

Definition at line 668 of file matrix.h.

670  {
671  Vector3 forward = (target - position).Normalize();
672  Vector3 right = up.Cross(forward);
673  up = forward.Cross(right);
674 
675  // clang-format off
676  return {
677  right.x, up.x, forward.x, 0.0f,
678  right.y, up.y, forward.y, 0.0f,
679  right.z, up.z, forward.z, 0.0f,
680  -right.Dot(position), -up.Dot(position), -forward.Dot(position), 1.0f
681  };
682  // clang-format on
683  }

References impeller::Vector3::Cross(), impeller::Vector3::Dot(), impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by impeller::testing::TEST().

◆ MakeOrthographic()

template<class T >
static constexpr Matrix impeller::Matrix::MakeOrthographic ( TSize< T >  size)
inlinestaticconstexpr

Definition at line 633 of file matrix.h.

633  {
634  // Per assumptions about NDC documented above.
635  const auto scale =
636  MakeScale({2.0f / static_cast<Scalar>(size.width),
637  -2.0f / static_cast<Scalar>(size.height), 0.0f});
638  const auto translate = MakeTranslation({-1.0f, 1.0f, 0.5f});
639  return translate * scale;
640  }
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104

References impeller::TSize< T >::height, MakeScale(), MakeTranslation(), and impeller::TSize< T >::width.

Referenced by ImGui_ImplImpeller_RenderDrawData(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakePerspective() [1/2]

static Matrix impeller::Matrix::MakePerspective ( Radians  fov_y,
Scalar  aspect_ratio,
Scalar  z_near,
Scalar  z_far 
)
inlinestatic

Definition at line 642 of file matrix.h.

645  {
646  Scalar height = std::tan(fov_y.radians * 0.5f);
647  Scalar width = height * aspect_ratio;
648 
649  // clang-format off
650  return {
651  1.0f / width, 0.0f, 0.0f, 0.0f,
652  0.0f, 1.0f / height, 0.0f, 0.0f,
653  0.0f, 0.0f, z_far / (z_far - z_near), 1.0f,
654  0.0f, 0.0f, -(z_far * z_near) / (z_far - z_near), 0.0f,
655  };
656  // clang-format on
657  }

References impeller::Radians::radians.

Referenced by MakePerspective(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakePerspective() [2/2]

template<class T >
static constexpr Matrix impeller::Matrix::MakePerspective ( Radians  fov_y,
TSize< T >  size,
Scalar  z_near,
Scalar  z_far 
)
inlinestaticconstexpr

Definition at line 660 of file matrix.h.

663  {
664  return MakePerspective(fov_y, static_cast<Scalar>(size.width) / size.height,
665  z_near, z_far);
666  }
static Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
Definition: matrix.h:642

References impeller::TSize< T >::height, MakePerspective(), and impeller::TSize< T >::width.

◆ MakeRotation() [1/2]

static Matrix impeller::Matrix::MakeRotation ( Quaternion  q)
inlinestatic

Definition at line 136 of file matrix.h.

136  {
137  // clang-format off
138  return Matrix(
139  1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z,
140  2.0f * q.x * q.y + 2.0f * q.z * q.w,
141  2.0f * q.x * q.z - 2.0f * q.y * q.w,
142  0.0f,
143 
144  2.0f * q.x * q.y - 2.0f * q.z * q.w,
145  1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z,
146  2.0f * q.y * q.z + 2.0f * q.x * q.w,
147  0.0f,
148 
149  2.0f * q.x * q.z + 2.0f * q.y * q.w,
150  2.0f * q.y * q.z - 2.0f * q.x * q.w,
151  1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y,
152  0.0f,
153 
154  0.0f,
155  0.0f,
156  0.0f,
157  1.0f);
158  // clang-format on
159  }

References Matrix(), impeller::Quaternion::w, impeller::Quaternion::x, impeller::Quaternion::y, and impeller::Quaternion::z.

Referenced by impeller::testing::TEST().

◆ MakeRotation() [2/2]

static Matrix impeller::Matrix::MakeRotation ( Radians  radians,
const Vector4 r 
)
inlinestatic

Definition at line 161 of file matrix.h.

161  {
162  const Vector4 v = r.Normalize();
163 
164  const Vector2 cos_sin = CosSin(radians);
165  const Scalar cosine = cos_sin.x;
166  const Scalar cosp = 1.0f - cosine;
167  const Scalar sine = cos_sin.y;
168 
169  // clang-format off
170  return Matrix(
171  cosine + cosp * v.x * v.x,
172  cosp * v.x * v.y + v.z * sine,
173  cosp * v.x * v.z - v.y * sine,
174  0.0f,
175 
176  cosp * v.x * v.y - v.z * sine,
177  cosine + cosp * v.y * v.y,
178  cosp * v.y * v.z + v.x * sine,
179  0.0f,
180 
181  cosp * v.x * v.z + v.y * sine,
182  cosp * v.y * v.z - v.x * sine,
183  cosine + cosp * v.z * v.z,
184  0.0f,
185 
186  0.0f,
187  0.0f,
188  0.0f,
189  1.0f);
190  // clang-format on
191  }
Point Vector2
Definition: point.h:331
static Vector2 CosSin(Radians radians)
Definition: matrix.h:685

References CosSin(), Matrix(), impeller::Vector4::Normalize(), impeller::TPoint< T >::x, impeller::Vector4::x, impeller::TPoint< T >::y, impeller::Vector4::y, and impeller::Vector4::z.

◆ MakeRotationX()

static Matrix impeller::Matrix::MakeRotationX ( Radians  r)
inlinestatic

Definition at line 193 of file matrix.h.

193  {
194  const Vector2 cos_sin = CosSin(r);
195  const Scalar cosine = cos_sin.x;
196  const Scalar sine = cos_sin.y;
197 
198  // clang-format off
199  return Matrix(
200  1.0f, 0.0f, 0.0f, 0.0f,
201  0.0f, cosine, sine, 0.0f,
202  0.0f, -sine, cosine, 0.0f,
203  0.0f, 0.0f, 0.0f, 1.0f
204  );
205  // clang-format on
206  }

References CosSin(), Matrix(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakeRotationY()

static Matrix impeller::Matrix::MakeRotationY ( Radians  r)
inlinestatic

Definition at line 208 of file matrix.h.

208  {
209  const Vector2 cos_sin = CosSin(r);
210  const Scalar cosine = cos_sin.x;
211  const Scalar sine = cos_sin.y;
212 
213  // clang-format off
214  return Matrix(
215  cosine, 0.0f, -sine, 0.0f,
216  0.0f, 1.0f, 0.0f, 0.0f,
217  sine, 0.0f, cosine, 0.0f,
218  0.0f, 0.0f, 0.0f, 1.0f
219  );
220  // clang-format on
221  }

References CosSin(), Matrix(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakeRotationZ()

static Matrix impeller::Matrix::MakeRotationZ ( Radians  r)
inlinestatic

Definition at line 223 of file matrix.h.

223  {
224  const Vector2 cos_sin = CosSin(r);
225  const Scalar cosine = cos_sin.x;
226  const Scalar sine = cos_sin.y;
227 
228  // clang-format off
229  return Matrix (
230  cosine, sine, 0.0f, 0.0f,
231  -sine, cosine, 0.0f, 0.0f,
232  0.0f, 0.0f, 1.0f, 0.0f,
233  0.0f, 0.0f, 0.0f, 1.0
234  );
235  // clang-format on
236  }

References CosSin(), Matrix(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::FirstPassDispatcher::rotate(), impeller::Canvas::Rotate(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakeRow()

static constexpr Matrix impeller::Matrix::MakeRow ( Scalar  m0,
Scalar  m1,
Scalar  m2,
Scalar  m3,
Scalar  m4,
Scalar  m5,
Scalar  m6,
Scalar  m7,
Scalar  m8,
Scalar  m9,
Scalar  m10,
Scalar  m11,
Scalar  m12,
Scalar  m13,
Scalar  m14,
Scalar  m15 
)
inlinestaticconstexpr

Definition at line 83 of file matrix.h.

87  {
88  return Matrix(m0, m4, m8, m12,
89  m1, m5, m9, m13,
90  m2, m6, m10, m14,
91  m3, m7, m11, m15);
92  }

References Matrix().

Referenced by impeller::RSTransform::GetMatrix(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakeScale() [1/2]

static constexpr Matrix impeller::Matrix::MakeScale ( const Vector2 s)
inlinestaticconstexpr

Definition at line 123 of file matrix.h.

123  {
124  return MakeScale(Vector3(s.x, s.y, 1.0f));
125  }

References MakeScale(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

◆ MakeScale() [2/2]

static constexpr Matrix impeller::Matrix::MakeScale ( const Vector3 s)
inlinestaticconstexpr

◆ MakeSkew()

static constexpr Matrix impeller::Matrix::MakeSkew ( Scalar  sx,
Scalar  sy 
)
inlinestaticconstexpr

Definition at line 127 of file matrix.h.

127  {
128  // clang-format off
129  return Matrix(1.0f, sy , 0.0f, 0.0f,
130  sx , 1.0f, 0.0f, 0.0f,
131  0.0f, 0.0f, 1.0f, 0.0f,
132  0.0f, 0.0f, 0.0f, 1.0f);
133  // clang-format on
134  }

References Matrix().

Referenced by impeller::FirstPassDispatcher::skew(), impeller::Canvas::Skew(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ MakeTranslateScale()

static constexpr Matrix impeller::Matrix::MakeTranslateScale ( const Vector3 s,
const Vector3 t 
)
inlinestaticconstexpr

Definition at line 113 of file matrix.h.

114  {
115  // clang-format off
116  return Matrix(s.x, 0.0f, 0.0f, 0.0f,
117  0.0f, s.y, 0.0f, 0.0f,
118  0.0f, 0.0f, s.z, 0.0f,
119  t.x , t.y, t.z, 1.0f);
120  // clang-format on
121  }

References Matrix(), impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by impeller::Canvas::DrawImageRect(), impeller::Entity::GetShaderTransform(), and impeller::testing::TEST().

◆ MakeTranslation()

◆ Multiply()

constexpr Matrix impeller::Matrix::Multiply ( const Matrix o) const
inlineconstexpr

Definition at line 284 of file matrix.h.

284  {
285  // clang-format off
286  return Matrix(
287  m[0] * o.m[0] + m[4] * o.m[1] + m[8] * o.m[2] + m[12] * o.m[3],
288  m[1] * o.m[0] + m[5] * o.m[1] + m[9] * o.m[2] + m[13] * o.m[3],
289  m[2] * o.m[0] + m[6] * o.m[1] + m[10] * o.m[2] + m[14] * o.m[3],
290  m[3] * o.m[0] + m[7] * o.m[1] + m[11] * o.m[2] + m[15] * o.m[3],
291  m[0] * o.m[4] + m[4] * o.m[5] + m[8] * o.m[6] + m[12] * o.m[7],
292  m[1] * o.m[4] + m[5] * o.m[5] + m[9] * o.m[6] + m[13] * o.m[7],
293  m[2] * o.m[4] + m[6] * o.m[5] + m[10] * o.m[6] + m[14] * o.m[7],
294  m[3] * o.m[4] + m[7] * o.m[5] + m[11] * o.m[6] + m[15] * o.m[7],
295  m[0] * o.m[8] + m[4] * o.m[9] + m[8] * o.m[10] + m[12] * o.m[11],
296  m[1] * o.m[8] + m[5] * o.m[9] + m[9] * o.m[10] + m[13] * o.m[11],
297  m[2] * o.m[8] + m[6] * o.m[9] + m[10] * o.m[10] + m[14] * o.m[11],
298  m[3] * o.m[8] + m[7] * o.m[9] + m[11] * o.m[10] + m[15] * o.m[11],
299  m[0] * o.m[12] + m[4] * o.m[13] + m[8] * o.m[14] + m[12] * o.m[15],
300  m[1] * o.m[12] + m[5] * o.m[13] + m[9] * o.m[14] + m[13] * o.m[15],
301  m[2] * o.m[12] + m[6] * o.m[13] + m[10] * o.m[14] + m[14] * o.m[15],
302  m[3] * o.m[12] + m[7] * o.m[13] + m[11] * o.m[14] + m[15] * o.m[15]);
303  // clang-format on
304  }

References m, and Matrix().

Referenced by operator*().

◆ operator!=()

constexpr bool impeller::Matrix::operator!= ( const Matrix m) const
inlineconstexpr

Definition at line 550 of file matrix.h.

550  {
551  // clang-format off
552  return vec[0] != m.vec[0]
553  || vec[1] != m.vec[1]
554  || vec[2] != m.vec[2]
555  || vec[3] != m.vec[3];
556  // clang-format on
557  }

References m, and vec.

◆ operator*() [1/4]

Matrix impeller::Matrix::operator* ( const Matrix m) const
inline

Definition at line 563 of file matrix.h.

563 { return Multiply(m); }
constexpr Matrix Multiply(const Matrix &o) const
Definition: matrix.h:284

References m, and Multiply().

◆ operator*() [2/4]

constexpr Point impeller::Matrix::operator* ( const Point v) const
inlineconstexpr

Definition at line 588 of file matrix.h.

588  {
589  Scalar w = v.x * m[3] + v.y * m[7] + m[15];
590  Point result(v.x * m[0] + v.y * m[4] + m[12],
591  v.x * m[1] + v.y * m[5] + m[13]);
592 
593  // This is Skia's behavior, but it may be reasonable to allow UB for the w=0
594  // case.
595  if (w) {
596  w = 1 / w;
597  }
598  return result * w;
599  }
TPoint< Scalar > Point
Definition: point.h:327

References m, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

◆ operator*() [3/4]

constexpr Vector3 impeller::Matrix::operator* ( const Vector3 v) const
inlineconstexpr

Definition at line 574 of file matrix.h.

574  {
575  Scalar w = v.x * m[3] + v.y * m[7] + v.z * m[11] + m[15];
576  Vector3 result(v.x * m[0] + v.y * m[4] + v.z * m[8] + m[12],
577  v.x * m[1] + v.y * m[5] + v.z * m[9] + m[13],
578  v.x * m[2] + v.y * m[6] + v.z * m[10] + m[14]);
579 
580  // This is Skia's behavior, but it may be reasonable to allow UB for the w=0
581  // case.
582  if (w) {
583  w = 1 / w;
584  }
585  return result * w;
586  }

References m, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

◆ operator*() [4/4]

constexpr Vector4 impeller::Matrix::operator* ( const Vector4 v) const
inlineconstexpr

Definition at line 567 of file matrix.h.

567  {
568  return Vector4(v.x * m[0] + v.y * m[4] + v.z * m[8] + v.w * m[12],
569  v.x * m[1] + v.y * m[5] + v.z * m[9] + v.w * m[13],
570  v.x * m[2] + v.y * m[6] + v.z * m[10] + v.w * m[14],
571  v.x * m[3] + v.y * m[7] + v.z * m[11] + v.w * m[15]);
572  }

References m, impeller::Vector4::w, impeller::Vector4::x, impeller::Vector4::y, and impeller::Vector4::z.

◆ operator+() [1/2]

Matrix impeller::Matrix::operator+ ( const Matrix m) const

Definition at line 90 of file matrix.cc.

90  {
91  return Matrix(
92  m[0] + o.m[0], m[1] + o.m[1], m[2] + o.m[2], m[3] + o.m[3], //
93  m[4] + o.m[4], m[5] + o.m[5], m[6] + o.m[6], m[7] + o.m[7], //
94  m[8] + o.m[8], m[9] + o.m[9], m[10] + o.m[10], m[11] + o.m[11], //
95  m[12] + o.m[12], m[13] + o.m[13], m[14] + o.m[14], m[15] + o.m[15] //
96  );
97 }

References m, and Matrix().

◆ operator+() [2/2]

Matrix impeller::Matrix::operator+ ( const Vector3 t) const
inline

Definition at line 559 of file matrix.h.

559 { return Translate(t); }
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263

References Translate().

◆ operator-()

Matrix impeller::Matrix::operator- ( const Vector3 t) const
inline

Definition at line 561 of file matrix.h.

561 { return Translate(-t); }

References Translate().

◆ operator==()

constexpr bool impeller::Matrix::operator== ( const Matrix m) const
inlineconstexpr

Definition at line 541 of file matrix.h.

541  {
542  // clang-format off
543  return vec[0] == m.vec[0]
544  && vec[1] == m.vec[1]
545  && vec[2] == m.vec[2]
546  && vec[3] == m.vec[3];
547  // clang-format on
548  }

References m, and vec.

◆ Scale()

constexpr Matrix impeller::Matrix::Scale ( const Vector3 s) const
inlineconstexpr

Definition at line 275 of file matrix.h.

275  {
276  // clang-format off
277  return Matrix(m[0] * s.x, m[1] * s.x, m[2] * s.x, m[3] * s.x,
278  m[4] * s.y, m[5] * s.y, m[6] * s.y, m[7] * s.y,
279  m[8] * s.z, m[9] * s.z, m[10] * s.z, m[11] * s.z,
280  m[12] , m[13] , m[14] , m[15] );
281  // clang-format on
282  }

References m, Matrix(), impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by impeller::FirstPassDispatcher::scale(), and impeller::testing::TEST_P().

◆ To3x3()

constexpr Matrix impeller::Matrix::To3x3 ( ) const
inlineconstexpr

Definition at line 252 of file matrix.h.

252  {
253  // clang-format off
254  return Matrix(
255  m[0], m[1], 0, m[3],
256  m[4], m[5], 0, m[7],
257  0, 0, 1, 0,
258  m[12], m[13], 0, m[15]
259  );
260  // clang-format on
261  }

References m, and Matrix().

◆ Transform()

constexpr Quad impeller::Matrix::Transform ( const Quad quad) const
inlineconstexpr

Definition at line 623 of file matrix.h.

623  {
624  return {
625  *this * quad[0],
626  *this * quad[1],
627  *this * quad[2],
628  *this * quad[3],
629  };
630  }

Referenced by impeller::GaussianBlurFilterContents::CalculateUVs(), and impeller::testing::TEST_P().

◆ TransformDirection() [1/3]

constexpr Vector2 impeller::Matrix::TransformDirection ( const Vector2 v) const
inlineconstexpr

Definition at line 619 of file matrix.h.

619  {
620  return Vector2(v.x * m[0] + v.y * m[4], v.x * m[1] + v.y * m[5]);
621  }

References m, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

◆ TransformDirection() [2/3]

constexpr Vector3 impeller::Matrix::TransformDirection ( const Vector3 v) const
inlineconstexpr

Definition at line 613 of file matrix.h.

613  {
614  return Vector3(v.x * m[0] + v.y * m[4] + v.z * m[8],
615  v.x * m[1] + v.y * m[5] + v.z * m[9],
616  v.x * m[2] + v.y * m[6] + v.z * m[10]);
617  }

References m, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

◆ TransformDirection() [3/3]

constexpr Vector4 impeller::Matrix::TransformDirection ( const Vector4 v) const
inlineconstexpr

Definition at line 607 of file matrix.h.

607  {
608  return Vector4(v.x * m[0] + v.y * m[4] + v.z * m[8],
609  v.x * m[1] + v.y * m[5] + v.z * m[9],
610  v.x * m[2] + v.y * m[6] + v.z * m[10], v.w);
611  }

References m, impeller::Vector4::w, impeller::Vector4::x, impeller::Vector4::y, and impeller::Vector4::z.

Referenced by impeller::BorderMaskBlurFilterContents::GetFilterSourceCoverage(), and impeller::DirectionalMorphologyFilterContents::GetFilterSourceCoverage().

◆ TransformHomogenous()

constexpr Vector3 impeller::Matrix::TransformHomogenous ( const Point v) const
inlineconstexpr

Definition at line 601 of file matrix.h.

601  {
602  return Vector3(v.x * m[0] + v.y * m[4] + m[12],
603  v.x * m[1] + v.y * m[5] + m[13],
604  v.x * m[3] + v.y * m[7] + m[15]);
605  }

References m, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST().

◆ Translate()

constexpr Matrix impeller::Matrix::Translate ( const Vector3 t) const
inlineconstexpr

Definition at line 263 of file matrix.h.

263  {
264  // clang-format off
265  return Matrix(m[0], m[1], m[2], m[3],
266  m[4], m[5], m[6], m[7],
267  m[8], m[9], m[10], m[11],
268  m[0] * t.x + m[4] * t.y + m[8] * t.z + m[12],
269  m[1] * t.x + m[5] * t.y + m[9] * t.z + m[13],
270  m[2] * t.x + m[6] * t.y + m[10] * t.z + m[14],
271  m[3] * t.x + m[7] * t.y + m[11] * t.z + m[15]);
272  // clang-format on
273  }

References m, Matrix(), impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by ImGui_ImplImpeller_RenderDrawData(), operator+(), operator-(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::FirstPassDispatcher::translate().

◆ Transpose()

constexpr Matrix impeller::Matrix::Transpose ( ) const
inlineconstexpr

Definition at line 306 of file matrix.h.

306  {
307  // clang-format off
308  return {
309  m[0], m[4], m[8], m[12],
310  m[1], m[5], m[9], m[13],
311  m[2], m[6], m[10], m[14],
312  m[3], m[7], m[11], m[15],
313  };
314  // clang-format on
315  }

References m.

Referenced by Decompose().

Member Data Documentation

◆ 

union { ... }

◆ e

Scalar impeller::Matrix::e[4][4]

◆ m

◆ vec

Vector4 impeller::Matrix::vec[4]

Definition at line 41 of file matrix.h.

Referenced by IsFinite(), operator!=(), operator==(), and impeller::testing::TEST_P().


The documentation for this struct was generated from the following files: