Flutter Engine
matrix_decomposition.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 namespace flutter {
8 
9 static inline SkV3 SkV3Combine(const SkV3& a,
10  float a_scale,
11  const SkV3& b,
12  float b_scale) {
13  return (a * a_scale) + (b * b_scale);
14 }
15 
17  : MatrixDecomposition(SkM44{matrix}) {}
18 
19 // Use custom normalize to avoid skia precision loss/normalize() privatization.
20 static inline void SkV3Normalize(SkV3* v) {
21  double mag = sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
22  double scale = 1.0 / mag;
23  v->x *= scale;
24  v->y *= scale;
25  v->z *= scale;
26 }
27 
28 MatrixDecomposition::MatrixDecomposition(SkM44 matrix) : valid_(false) {
29  if (matrix.rc(3, 3) == 0) {
30  return;
31  }
32 
33  for (int i = 0; i < 4; i++) {
34  for (int j = 0; j < 4; j++) {
35  matrix.setRC(j, i, matrix.rc(j, i) / matrix.rc(3, 3));
36  }
37  }
38 
39  SkM44 perpective_matrix = matrix;
40  for (int i = 0; i < 3; i++) {
41  perpective_matrix.setRC(3, i, 0.0);
42  }
43 
44  perpective_matrix.setRC(3, 3, 1.0);
45 
46  SkM44 inverted(SkM44::Uninitialized_Constructor::kUninitialized_Constructor);
47  if (!perpective_matrix.invert(&inverted)) {
48  return;
49  }
50 
51  if (matrix.rc(3, 0) != 0.0 || matrix.rc(3, 1) != 0.0 ||
52  matrix.rc(3, 2) != 0.0) {
53  const SkV4 right_hand_side = matrix.row(3);
54 
55  perspective_ = inverted.transpose() * right_hand_side;
56 
57  matrix.setRow(3, {0, 0, 0, 1});
58  }
59 
60  translation_ = {matrix.rc(0, 3), matrix.rc(1, 3), matrix.rc(2, 3)};
61 
62  matrix.setRC(0, 3, 0.0);
63  matrix.setRC(1, 3, 0.0);
64  matrix.setRC(2, 3, 0.0);
65 
66  SkV3 row[3];
67  for (int i = 0; i < 3; i++) {
68  row[i] = {matrix.rc(0, i), matrix.rc(1, i), matrix.rc(2, i)};
69  }
70 
71  scale_.x = row[0].length();
72 
73  SkV3Normalize(&row[0]);
74 
75  shear_.x = row[0].dot(row[1]);
76  row[1] = SkV3Combine(row[1], 1.0, row[0], -shear_.x);
77 
78  scale_.y = row[1].length();
79 
80  SkV3Normalize(&row[1]);
81 
82  shear_.x /= scale_.y;
83 
84  shear_.y = row[0].dot(row[2]);
85  row[2] = SkV3Combine(row[2], 1.0, row[0], -shear_.y);
86  shear_.z = row[1].dot(row[2]);
87  row[2] = SkV3Combine(row[2], 1.0, row[1], -shear_.z);
88 
89  scale_.z = row[2].length();
90 
91  SkV3Normalize(&row[2]);
92 
93  shear_.y /= scale_.z;
94  shear_.z /= scale_.z;
95 
96  if (row[0].dot(row[1].cross(row[2])) < 0) {
97  scale_ *= -1;
98 
99  for (int i = 0; i < 3; i++) {
100  row[i] *= -1;
101  }
102  }
103 
104  rotation_.x = 0.5 * sqrt(fmax(1.0 + row[0].x - row[1].y - row[2].z, 0.0));
105  rotation_.y = 0.5 * sqrt(fmax(1.0 - row[0].x + row[1].y - row[2].z, 0.0));
106  rotation_.z = 0.5 * sqrt(fmax(1.0 - row[0].x - row[1].y + row[2].z, 0.0));
107  rotation_.w = 0.5 * sqrt(fmax(1.0 + row[0].x + row[1].y + row[2].z, 0.0));
108 
109  if (row[2].y > row[1].z) {
110  rotation_.x = -rotation_.x;
111  }
112  if (row[0].z > row[2].x) {
113  rotation_.y = -rotation_.y;
114  }
115  if (row[1].x > row[0].y) {
116  rotation_.z = -rotation_.z;
117  }
118 
119  valid_ = true;
120 }
121 
123 
125  return valid_;
126 }
127 
128 } // namespace flutter
static SkV3 SkV3Combine(const SkV3 &a, float a_scale, const SkV3 &b, float b_scale)
MatrixDecomposition(const SkMatrix &matrix)
static void SkV3Normalize(SkV3 *v)