Flutter Engine
matrix_decomposition_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 "flutter/flow/matrix_decomposition.h"
6 
7 #include <cmath>
8 
9 #include "gtest/gtest.h"
10 
11 namespace flutter {
12 namespace testing {
13 
15  SkM44 matrix;
16 
17  const auto angle = M_PI_4;
18  matrix.setRotate({0.0, 0.0, 1.0}, angle);
19 
20  flutter::MatrixDecomposition decomposition(matrix);
21  ASSERT_TRUE(decomposition.IsValid());
22 
23  const auto sine = sin(angle * 0.5);
24 
25  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
26  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
27  ASSERT_FLOAT_EQ(sine, decomposition.rotation().z);
28  ASSERT_FLOAT_EQ(cos(angle * 0.5), decomposition.rotation().w);
29 }
30 
32  SkM44 matrix;
33 
34  const auto scale = 5.0;
35  matrix.setScale(scale + 0, scale + 1, scale + 2);
36 
37  flutter::MatrixDecomposition decomposition(matrix);
38  ASSERT_TRUE(decomposition.IsValid());
39 
40  ASSERT_FLOAT_EQ(scale + 0, decomposition.scale().x);
41  ASSERT_FLOAT_EQ(scale + 1, decomposition.scale().y);
42  ASSERT_FLOAT_EQ(scale + 2, decomposition.scale().z);
43 }
44 
46  SkM44 matrix;
47 
48  const auto translate = 125.0;
49  matrix.setTranslate(translate + 0, translate + 1, translate + 2);
50 
51  flutter::MatrixDecomposition decomposition(matrix);
52  ASSERT_TRUE(decomposition.IsValid());
53 
54  ASSERT_FLOAT_EQ(translate + 0, decomposition.translation().x);
55  ASSERT_FLOAT_EQ(translate + 1, decomposition.translation().y);
56  ASSERT_FLOAT_EQ(translate + 2, decomposition.translation().z);
57 }
58 
59 TEST(MatrixDecomposition, Combination) {
60  const auto rotation = M_PI_4;
61  const auto scale = 5;
62  const auto translate = 125.0;
63 
64  SkM44 m1;
65  m1.setRotate({0, 0, 1}, rotation);
66 
67  SkM44 m2;
68  m2.setScale(scale, scale, scale);
69 
70  SkM44 m3;
71  m3.setTranslate(translate, translate, translate);
72 
73  SkM44 combined = m3 * m2 * m1;
74 
75  flutter::MatrixDecomposition decomposition(combined);
76  ASSERT_TRUE(decomposition.IsValid());
77 
78  ASSERT_FLOAT_EQ(translate, decomposition.translation().x);
79  ASSERT_FLOAT_EQ(translate, decomposition.translation().y);
80  ASSERT_FLOAT_EQ(translate, decomposition.translation().z);
81 
82  ASSERT_FLOAT_EQ(scale, decomposition.scale().x);
83  ASSERT_FLOAT_EQ(scale, decomposition.scale().y);
84  ASSERT_FLOAT_EQ(scale, decomposition.scale().z);
85 
86  const auto sine = sin(rotation * 0.5);
87 
88  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
89  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
90  ASSERT_FLOAT_EQ(sine, decomposition.rotation().z);
91  ASSERT_FLOAT_EQ(cos(rotation * 0.5), decomposition.rotation().w);
92 }
93 
94 TEST(MatrixDecomposition, ScaleFloatError) {
95  constexpr float scale_increment = 0.00001f;
96  float scale = 0.0001f;
97  while (scale < 2.0f) {
98  SkM44 matrix;
99  matrix.setScale(scale, scale, 1.0f);
100 
101  flutter::MatrixDecomposition decomposition3(matrix);
102  ASSERT_TRUE(decomposition3.IsValid());
103 
104  ASSERT_FLOAT_EQ(scale, decomposition3.scale().x);
105  ASSERT_FLOAT_EQ(scale, decomposition3.scale().y);
106  ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z);
107  ASSERT_FLOAT_EQ(0, decomposition3.rotation().x);
108  ASSERT_FLOAT_EQ(0, decomposition3.rotation().y);
109  ASSERT_FLOAT_EQ(0, decomposition3.rotation().z);
110  scale += scale_increment;
111  }
112 
113  SkM44 matrix;
114  const auto scale1 = 1.7734375f;
115  matrix.setScale(scale1, scale1, 1.f);
116 
117  // Bug upper bound (empirical)
118  const auto scale2 = 1.773437559603f;
119  SkM44 matrix2;
120  matrix2.setScale(scale2, scale2, 1.f);
121 
122  // Bug lower bound (empirical)
123  const auto scale3 = 1.7734374403954f;
124  SkM44 matrix3;
125  matrix3.setScale(scale3, scale3, 1.f);
126 
127  flutter::MatrixDecomposition decomposition(matrix);
128  ASSERT_TRUE(decomposition.IsValid());
129 
130  flutter::MatrixDecomposition decomposition2(matrix2);
131  ASSERT_TRUE(decomposition2.IsValid());
132 
133  flutter::MatrixDecomposition decomposition3(matrix3);
134  ASSERT_TRUE(decomposition3.IsValid());
135 
136  ASSERT_FLOAT_EQ(scale1, decomposition.scale().x);
137  ASSERT_FLOAT_EQ(scale1, decomposition.scale().y);
138  ASSERT_FLOAT_EQ(1.f, decomposition.scale().z);
139  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
140  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
141  ASSERT_FLOAT_EQ(0, decomposition.rotation().z);
142 
143  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().x);
144  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().y);
145  ASSERT_FLOAT_EQ(1.f, decomposition2.scale().z);
146  ASSERT_FLOAT_EQ(0, decomposition2.rotation().x);
147  ASSERT_FLOAT_EQ(0, decomposition2.rotation().y);
148  ASSERT_FLOAT_EQ(0, decomposition2.rotation().z);
149 
150  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().x);
151  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().y);
152  ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z);
153  ASSERT_FLOAT_EQ(0, decomposition3.rotation().x);
154  ASSERT_FLOAT_EQ(0, decomposition3.rotation().y);
155  ASSERT_FLOAT_EQ(0, decomposition3.rotation().z);
156 }
157 
158 } // namespace testing
159 } // namespace flutter
const SkV3 & translation() const
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations)