Flutter Impeller
matrix_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gtest/gtest.h"
6 
8 
11 
12 namespace impeller {
13 namespace testing {
14 
15 TEST(MatrixTest, Multiply) {
16  Matrix x(0.0, 0.0, 0.0, 1.0, //
17  1.0, 0.0, 0.0, 1.0, //
18  0.0, 1.0, 0.0, 1.0, //
19  1.0, 1.0, 0.0, 1.0);
20  Matrix translate = Matrix::MakeTranslation({10, 20, 0});
21  Matrix result = translate * x;
22  EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
23  11.0, 20.0, 0.0, 1.0, //
24  10.0, 21.0, 0.0, 1.0, //
25  11.0, 21.0, 0.0, 1.0)));
26 }
27 
28 TEST(MatrixTest, Equals) {
29  Matrix x;
30  Matrix y = x;
31  EXPECT_TRUE(x.Equals(y));
32 }
33 
34 TEST(MatrixTest, NotEquals) {
35  Matrix x;
36  Matrix y = x.Translate({1, 0, 0});
37  EXPECT_FALSE(x.Equals(y));
38 }
39 
40 TEST(MatrixTest, HasPerspective2D) {
41  EXPECT_FALSE(Matrix().HasPerspective2D());
42 
43  auto test = [](int index, bool expect) {
44  Matrix matrix;
45  EXPECT_FALSE(matrix.HasPerspective2D());
46  matrix.m[index] = 0.5f;
47  EXPECT_EQ(matrix.HasPerspective2D(), expect) << "index: " << index;
48  };
49 
50  // clang-format off
51  test( 0, false); test( 1, false); test( 2, false); test( 3, true);
52  test( 4, false); test( 5, false); test( 6, false); test( 7, true);
53  test( 8, false); test( 9, false); test(10, false); test(11, false);
54  test(12, false); test(13, false); test(14, false); test(15, true);
55  // clang-format on
56 }
57 
58 TEST(MatrixTest, HasPerspective) {
59  EXPECT_FALSE(Matrix().HasPerspective());
60 
61  auto test = [](int index, bool expect) {
62  Matrix matrix;
63  EXPECT_FALSE(matrix.HasPerspective());
64  matrix.m[index] = 0.5f;
65  EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
66  };
67 
68  // clang-format off
69  test( 0, false); test( 1, false); test( 2, false); test( 3, true);
70  test( 4, false); test( 5, false); test( 6, false); test( 7, true);
71  test( 8, false); test( 9, false); test(10, false); test(11, true);
72  test(12, false); test(13, false); test(14, false); test(15, true);
73  // clang-format on
74 }
75 
76 TEST(MatrixTest, HasTranslation) {
77  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).HasTranslation());
78  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).HasTranslation());
79  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).HasTranslation());
80  EXPECT_FALSE(Matrix().HasTranslation());
81 }
82 
83 TEST(MatrixTest, IsTranslationOnly) {
84  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationOnly());
85  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationScaleOnly());
86  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationOnly());
87  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationScaleOnly());
88  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationOnly());
89  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationScaleOnly());
90  EXPECT_TRUE(Matrix().IsTranslationOnly());
91  EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
92 }
93 
94 TEST(MatrixTest, IsTranslationScaleOnly) {
95  EXPECT_FALSE(Matrix::MakeScale({100, 100, 1}).IsTranslationOnly());
96  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsTranslationScaleOnly());
97  EXPECT_FALSE(Matrix::MakeScale({1, 100, 1}).IsTranslationOnly());
98  EXPECT_TRUE(Matrix::MakeScale({1, 100, 1}).IsTranslationScaleOnly());
99  EXPECT_FALSE(Matrix::MakeScale({100, 1, 1}).IsTranslationOnly());
100  EXPECT_TRUE(Matrix::MakeScale({100, 1, 1}).IsTranslationScaleOnly());
101  EXPECT_TRUE(Matrix().IsTranslationOnly());
102  EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
103 }
104 
105 TEST(MatrixTest, IsInvertibleGetDeterminant) {
106  EXPECT_TRUE(Matrix().IsInvertible());
107  EXPECT_NE(Matrix().GetDeterminant(), 0.0f);
108 
109  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsInvertible());
110  EXPECT_NE(Matrix::MakeTranslation({100, 100, 0}).GetDeterminant(), 0.0f);
111 
112  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsInvertible());
113  EXPECT_NE(Matrix::MakeScale({100, 100, 1}).GetDeterminant(), 0.0f);
114 
115  EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsInvertible());
116  EXPECT_NE(Matrix::MakeRotationX(Degrees(30)).GetDeterminant(), 0.0f);
117 
118  EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsInvertible());
119  EXPECT_NE(Matrix::MakeRotationY(Degrees(30)).GetDeterminant(), 0.0f);
120 
121  EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsInvertible());
122  EXPECT_NE(Matrix::MakeRotationZ(Degrees(30)).GetDeterminant(), 0.0f);
123 
124  EXPECT_FALSE(Matrix::MakeScale({0, 1, 1}).IsInvertible());
125  EXPECT_EQ(Matrix::MakeScale({0, 1, 1}).GetDeterminant(), 0.0f);
126  EXPECT_FALSE(Matrix::MakeScale({1, 0, 1}).IsInvertible());
127  EXPECT_EQ(Matrix::MakeScale({1, 0, 1}).GetDeterminant(), 0.0f);
128  EXPECT_FALSE(Matrix::MakeScale({1, 1, 0}).IsInvertible());
129  EXPECT_EQ(Matrix::MakeScale({1, 1, 0}).GetDeterminant(), 0.0f);
130 }
131 
132 TEST(MatrixTest, IsFinite) {
133  EXPECT_TRUE(Matrix().IsFinite());
134 
135  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsFinite());
136  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsFinite());
137 
138  EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsFinite());
139  EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsFinite());
140  EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsFinite());
141 
142  EXPECT_TRUE(Matrix::MakeScale({0, 1, 1}).IsFinite());
143  EXPECT_TRUE(Matrix::MakeScale({1, 0, 1}).IsFinite());
144  EXPECT_TRUE(Matrix::MakeScale({1, 1, 0}).IsFinite());
145 
146  for (int i = 0; i < 16; i++) {
147  {
148  Matrix matrix;
149  ASSERT_TRUE(matrix.IsFinite());
150  matrix.m[i] = std::numeric_limits<Scalar>::infinity();
151  ASSERT_FALSE(matrix.IsFinite());
152  }
153 
154  {
155  Matrix matrix;
156  ASSERT_TRUE(matrix.IsFinite());
157  matrix.m[i] = -std::numeric_limits<Scalar>::infinity();
158  ASSERT_FALSE(matrix.IsFinite());
159  }
160 
161  {
162  Matrix matrix;
163  ASSERT_TRUE(matrix.IsFinite());
164  matrix.m[i] = -std::numeric_limits<Scalar>::quiet_NaN();
165  ASSERT_FALSE(matrix.IsFinite());
166  }
167  }
168 }
169 
170 TEST(MatrixTest, IsAligned2D) {
171  EXPECT_TRUE(Matrix().IsAligned2D());
172  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
173 
174  auto test = [](int index, bool expect) {
175  Matrix matrix;
176  EXPECT_TRUE(matrix.IsAligned2D());
177  matrix.m[index] = 0.5f;
178  EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
179  };
180 
181  // clang-format off
182  test( 0, true); test( 1, false); test( 2, true); test( 3, false);
183  test( 4, false); test( 5, true); test( 6, true); test( 7, false);
184  test( 8, true); test( 9, true); test(10, true); test(11, true);
185  test(12, true); test(13, true); test(14, true); test(15, false);
186  // clang-format on
187 
188  // True for quadrant rotations from -250 to +250 full circles
189  for (int i = -1000; i < 1000; i++) {
190  Degrees d = Degrees(i * 90);
191  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
192  EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
193  }
194 
195  // False for half degree rotations from -999.5 to +1000.5 degrees
196  for (int i = -1000; i < 1000; i++) {
197  Degrees d = Degrees(i + 0.5f);
198  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
199  EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
200  }
201 }
202 
203 TEST(MatrixTest, IsAligned) {
204  EXPECT_TRUE(Matrix().IsAligned());
205  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
206 
207  // Begin Legacy tests transferred over from geometry_unittests.cc
208  {
209  auto m = Matrix::MakeTranslation({1, 2, 3});
210  bool result = m.IsAligned();
211  ASSERT_TRUE(result);
212  }
213 
214  {
215  auto m = Matrix::MakeRotationZ(Degrees{123});
216  bool result = m.IsAligned();
217  ASSERT_FALSE(result);
218  }
219  // End Legacy tests transferred over from geometry_unittests.cc
220 
221  auto test = [](int index, bool expect) {
222  Matrix matrix;
223  EXPECT_TRUE(matrix.IsAligned());
224  matrix.m[index] = 0.5f;
225  EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
226  };
227 
228  // clang-format off
229  test( 0, true); test( 1, false); test( 2, false); test( 3, false);
230  test( 4, false); test( 5, true); test( 6, false); test( 7, false);
231  test( 8, false); test( 9, false); test(10, true); test(11, false);
232  test(12, true); test(13, true); test(14, true); test(15, false);
233  // clang-format on
234 
235  // True for quadrant rotations from -250 to +250 full circles
236  for (int i = -1000; i < 1000; i++) {
237  Degrees d = Degrees(i * 90);
238  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
239  EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
240  }
241 
242  // False for half degree rotations from -999.5 to +1000.5 degrees
243  for (int i = -1000; i < 1000; i++) {
244  Degrees d = Degrees(i + 0.5f);
245  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
246  EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
247  }
248 }
249 
250 TEST(MatrixTest, TransformHomogenous) {
251  Matrix matrix = Matrix::MakeColumn(
252  // clang-format off
253  2.0f, 3.0f, 5.0f, 7.0f,
254  11.0f, 13.0f, 17.0f, 19.0f,
255  23.0f, 29.0f, 31.0f, 37.0f,
256  41.0f, 43.0f, 47.0f, 53.0f
257  // clang-format on
258  );
259  EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
260  Vector3(32.0f, 33.0f, 41.0f));
261 }
262 
263 TEST(MatrixTest, GetMaxBasisXYNegativeScale) {
264  Matrix m = Matrix::MakeScale({-2, 1, 1});
265 
266  EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
267 
268  m = Matrix::MakeScale({1, -3, 1});
269 
270  EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
271 }
272 
273 // Verifies a translate scale matrix doesn't need to compute sqrt(pow(scale, 2))
274 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor) {
275  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
276  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
277 
278  m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
279  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
280 }
281 
282 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate) {
283  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
284  m.e[0][1] = 2;
285 
286  EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
287 }
288 
289 TEST(MatrixTest, GetBasisXYScale2D) {
290  Matrix m = Matrix::MakeScale({5.0f, 3.0f, 1.0f});
291  EXPECT_POINT_NEAR(m.GetBasisX2D(), Vector2(5.0f, 0.0f));
292  EXPECT_POINT_NEAR(m.GetBasisY2D(), Vector2(0.0f, 3.0f));
293  EXPECT_POINT_NEAR(m.GetBasisScaleXY(), Vector2(5.0f, 3.0f));
294 
296  // clang-format off
297  2.0f, 3.0f, 0.0f, 0.0f,
298  5.0f, 7.0f, 0.0f, 0.0f,
299  0.0f, 0.0f, 1.0f, 0.0f,
300  0.0f, 0.0f, 0.0f, 1.0f
301  // clang-format on
302  );
303  EXPECT_POINT_NEAR(m2.GetBasisX2D(), Vector2(2.0f, 3.0f));
304  EXPECT_POINT_NEAR(m2.GetBasisY2D(), Vector2(5.0f, 7.0f));
305  EXPECT_POINT_NEAR(m2.GetBasisScaleXY(), Vector2(sqrt(13.0f), sqrt(74.0f)));
306 
308  // clang-format off
309  2.0f, 3.0f, 4.0f, 11.0f,
310  5.0f, 7.0f, 6.0f, 13.0f,
311  1.0f, 8.0f, 9.0f, 15.0f,
312  1.0f, 1.0f, 1.0f, 17.0f
313  // clang-format on
314  );
315  EXPECT_POINT_NEAR(m3.GetBasisX2D(), Vector2(2.0f, 3.0f));
316  EXPECT_POINT_NEAR(m3.GetBasisY2D(), Vector2(5.0f, 7.0f));
317  EXPECT_POINT_NEAR(m2.GetBasisScaleXY(), Vector2(sqrt(13.0f), sqrt(74.0f)));
318 }
319 
320 TEST(MatrixTest, TranslateWithPerspective) {
321  Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
322  0.0, 1.0, 0.0, 20.0, //
323  0.0, 0.0, 1.0, 0.0, //
324  0.0, 2.0, 0.0, 30.0);
325  Matrix result = m.Translate({100, 200});
326  EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
327  0.0, 1.0, 0.0, 220.0, //
328  0.0, 0.0, 1.0, 0.0, //
329  0.0, 2.0, 0.0, 430.0)));
330 }
331 
332 TEST(MatrixTest, MakeScaleTranslate) {
333  EXPECT_TRUE(MatrixNear(
334  Matrix::MakeTranslateScale({1, 1, 1.0 / 1024}, {10, 10, 1.0 / 1024}),
335  Matrix::MakeTranslation({10, 10, 1.0 / 1024}) *
336  Matrix::MakeScale({1, 1, 1.0 / 1024})));
337 
338  EXPECT_TRUE(MatrixNear(
339  Matrix::MakeTranslateScale({2, 2, 2}, {10, 10, 0}),
340  Matrix::MakeTranslation({10, 10, 0}) * Matrix::MakeScale({2, 2, 2})));
341 
342  EXPECT_TRUE(MatrixNear(
343  Matrix::MakeTranslateScale({0, 0, 0}, {0, 0, 0}),
344  Matrix::MakeTranslation({0, 0, 0}) * Matrix::MakeScale({0, 0, 0})));
345 }
346 
347 TEST(MatrixTest, To3x3) {
348  Matrix x(1.0, 0.0, 4.0, 0.0, //
349  0.0, 1.0, 4.0, 0.0, //
350  6.0, 5.0, 111.0, 7.0, //
351  0.0, 0.0, 9.0, 1.0);
352 
353  EXPECT_TRUE(MatrixNear(x.To3x3(), Matrix()));
354 }
355 
356 TEST(MatrixTest, MinMaxScales2D) {
357  // The GetScales2D() method is allowed to return the scales in any
358  // order so we need to take special care in verifying the return
359  // value to test them in either order.
360  auto check_pair = [](const Matrix& matrix, Scalar scale1, Scalar scale2) {
361  auto pair = matrix.GetScales2D();
362  EXPECT_TRUE(pair.has_value())
363  << "Scales: " << scale1 << ", " << scale2 << ", " << matrix;
364  if (ScalarNearlyEqual(pair->first, scale1)) {
365  EXPECT_FLOAT_EQ(pair->first, scale1) << matrix;
366  EXPECT_FLOAT_EQ(pair->second, scale2) << matrix;
367  } else {
368  EXPECT_FLOAT_EQ(pair->first, scale2) << matrix;
369  EXPECT_FLOAT_EQ(pair->second, scale1) << matrix;
370  }
371  };
372 
373  for (int i = 1; i < 10; i++) {
374  Scalar xScale = static_cast<Scalar>(i);
375  for (int j = 1; j < 10; j++) {
376  Scalar yScale = static_cast<Scalar>(j);
377  Scalar minScale = std::min(xScale, yScale);
378  Scalar maxScale = std::max(xScale, yScale);
379 
380  {
381  // Simple scale
382  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
383  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
384  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
385  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
386  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
387  check_pair(matrix, xScale, yScale);
388  }
389 
390  {
391  // Simple scale with Z scale
392  Matrix matrix = Matrix::MakeScale({xScale, yScale, 5.0f});
393  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
394  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
395  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
396  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
397  check_pair(matrix, xScale, yScale);
398  }
399 
400  {
401  // Simple scale + translate
402  Matrix matrix = Matrix::MakeTranslateScale({xScale, yScale, 1.0f},
403  {10.0f, 15.0f, 2.0f});
404  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
405  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
406  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
407  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
408  check_pair(matrix, xScale, yScale);
409  }
410 
411  for (int d = 45; d < 360; d += 45) {
412  {
413  // Rotation * Scale
414  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f}) *
416  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
417  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
418  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
419  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
420  check_pair(matrix, xScale, yScale);
421  }
422 
423  {
424  // Scale * Rotation
425  Matrix matrix = Matrix::MakeRotationZ(Degrees(d)) *
426  Matrix::MakeScale({xScale, yScale, 1.0f});
427  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
428  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
429  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
430  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
431  check_pair(matrix, xScale, yScale);
432  }
433  }
434 
435  {
436  // Scale + PerspectiveX (returns invalid values)
437  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
438  matrix.m[3] = 0.1;
439  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
440  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
441  EXPECT_FALSE(matrix.GetScales2D().has_value());
442  }
443 
444  {
445  // Scale + PerspectiveY (returns invalid values)
446  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
447  matrix.m[7] = 0.1;
448  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
449  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
450  EXPECT_FALSE(matrix.GetScales2D().has_value());
451  }
452 
453  {
454  // Scale + PerspectiveZ (Z ignored; returns actual scales)
455  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
456  matrix.m[11] = 0.1;
457  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
458  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
459  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
460  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
461  check_pair(matrix, xScale, yScale);
462  }
463 
464  {
465  // Scale + PerspectiveW (returns invalid values)
466  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
467  matrix.m[15] = 0.1;
468  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
469  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
470  EXPECT_FALSE(matrix.GetScales2D().has_value());
471  }
472  }
473  }
474 }
475 
476 } // namespace testing
477 } // namespace impeller
int32_t x
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
#define EXPECT_POINT_NEAR(a, b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
float Scalar
Definition: scalar.h:19
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:36
Scalar degrees
Definition: scalar.h:67
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
Vector2 GetBasisScaleXY() const
Definition: matrix.h:403
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
Scalar m[16]
Definition: matrix.h:39
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263
std::optional< Scalar > GetMinScale2D() const
Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matr...
Definition: matrix.h:356
constexpr bool IsAligned(Scalar tolerance=0) const
Definition: matrix.h:447
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)
Definition: matrix.h:69
static Matrix MakeRotationY(Radians r)
Definition: matrix.h:208
constexpr bool HasPerspective2D() const
Definition: matrix.h:422
bool IsFinite() const
Definition: matrix.h:412
constexpr Vector2 GetBasisX2D() const
Definition: matrix.h:399
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)
Definition: matrix.h:83
constexpr Vector3 TransformHomogenous(const Point &v) const
Definition: matrix.h:609
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition: matrix.h:113
Scalar e[4][4]
Definition: matrix.h:40
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:223
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
std::optional< Scalar > GetMaxScale2D() const
Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matr...
Definition: matrix.h:380
constexpr Vector2 GetBasisY2D() const
Definition: matrix.h:401
constexpr bool HasPerspective() const
Definition: matrix.h:426
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr bool IsAligned2D(Scalar tolerance=0) const
Definition: matrix.h:432
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
Definition: matrix.h:328
static Matrix MakeRotationX(Radians r)
Definition: matrix.h:193