• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/core/SkMatrixInvert.h"
9 
10 #include "include/private/SkFloatingPoint.h"
11 
SkInvert2x2Matrix(const SkScalar inMatrix[4],SkScalar outMatrix[4])12 SkScalar SkInvert2x2Matrix(const SkScalar inMatrix[4], SkScalar outMatrix[4]) {
13     double a00 = inMatrix[0];
14     double a01 = inMatrix[1];
15     double a10 = inMatrix[2];
16     double a11 = inMatrix[3];
17 
18     // Calculate the determinant
19     double determinant = a00 * a11 - a01 * a10;
20     if (outMatrix) {
21         double invdet = sk_ieee_double_divide(1.0, determinant);
22         outMatrix[0] =  a11 * invdet;
23         outMatrix[1] = -a01 * invdet;
24         outMatrix[2] = -a10 * invdet;
25         outMatrix[3] =  a00 * invdet;
26         // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
27         // values is non-finite, return zero to indicate a non-invertible matrix.
28         if (!SkScalarsAreFinite(outMatrix, 4)) {
29             determinant = 0.0f;
30         }
31     }
32     return determinant;
33 }
34 
SkInvert3x3Matrix(const SkScalar inMatrix[9],SkScalar outMatrix[9])35 SkScalar SkInvert3x3Matrix(const SkScalar inMatrix[9], SkScalar outMatrix[9]) {
36     double a00 = inMatrix[0];
37     double a01 = inMatrix[1];
38     double a02 = inMatrix[2];
39     double a10 = inMatrix[3];
40     double a11 = inMatrix[4];
41     double a12 = inMatrix[5];
42     double a20 = inMatrix[6];
43     double a21 = inMatrix[7];
44     double a22 = inMatrix[8];
45 
46     double b01 =  a22 * a11 - a12 * a21;
47     double b11 = -a22 * a10 + a12 * a20;
48     double b21 =  a21 * a10 - a11 * a20;
49 
50     // Calculate the determinant
51     double determinant = a00 * b01 + a01 * b11 + a02 * b21;
52     if (outMatrix) {
53         double invdet = sk_ieee_double_divide(1.0, determinant);
54         outMatrix[0] = b01 * invdet;
55         outMatrix[1] = (-a22 * a01 + a02 * a21) * invdet;
56         outMatrix[2] = ( a12 * a01 - a02 * a11) * invdet;
57         outMatrix[3] = b11 * invdet;
58         outMatrix[4] = ( a22 * a00 - a02 * a20) * invdet;
59         outMatrix[5] = (-a12 * a00 + a02 * a10) * invdet;
60         outMatrix[6] = b21 * invdet;
61         outMatrix[7] = (-a21 * a00 + a01 * a20) * invdet;
62         outMatrix[8] = ( a11 * a00 - a01 * a10) * invdet;
63         // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
64         // values is non-finite, return zero to indicate a non-invertible matrix.
65         if (!SkScalarsAreFinite(outMatrix, 9)) {
66             determinant = 0.0f;
67         }
68     }
69     return determinant;
70 }
71 
SkInvert4x4Matrix(const SkScalar inMatrix[16],SkScalar outMatrix[16])72 SkScalar SkInvert4x4Matrix(const SkScalar inMatrix[16], SkScalar outMatrix[16]) {
73     double a00 = inMatrix[0];
74     double a01 = inMatrix[1];
75     double a02 = inMatrix[2];
76     double a03 = inMatrix[3];
77     double a10 = inMatrix[4];
78     double a11 = inMatrix[5];
79     double a12 = inMatrix[6];
80     double a13 = inMatrix[7];
81     double a20 = inMatrix[8];
82     double a21 = inMatrix[9];
83     double a22 = inMatrix[10];
84     double a23 = inMatrix[11];
85     double a30 = inMatrix[12];
86     double a31 = inMatrix[13];
87     double a32 = inMatrix[14];
88     double a33 = inMatrix[15];
89 
90     double b00 = a00 * a11 - a01 * a10;
91     double b01 = a00 * a12 - a02 * a10;
92     double b02 = a00 * a13 - a03 * a10;
93     double b03 = a01 * a12 - a02 * a11;
94     double b04 = a01 * a13 - a03 * a11;
95     double b05 = a02 * a13 - a03 * a12;
96     double b06 = a20 * a31 - a21 * a30;
97     double b07 = a20 * a32 - a22 * a30;
98     double b08 = a20 * a33 - a23 * a30;
99     double b09 = a21 * a32 - a22 * a31;
100     double b10 = a21 * a33 - a23 * a31;
101     double b11 = a22 * a33 - a23 * a32;
102 
103     // Calculate the determinant
104     double determinant = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
105     if (outMatrix) {
106         double invdet = sk_ieee_double_divide(1.0, determinant);
107         b00 *= invdet;
108         b01 *= invdet;
109         b02 *= invdet;
110         b03 *= invdet;
111         b04 *= invdet;
112         b05 *= invdet;
113         b06 *= invdet;
114         b07 *= invdet;
115         b08 *= invdet;
116         b09 *= invdet;
117         b10 *= invdet;
118         b11 *= invdet;
119 
120         outMatrix[0]  = a11 * b11 - a12 * b10 + a13 * b09;
121         outMatrix[1]  = a02 * b10 - a01 * b11 - a03 * b09;
122         outMatrix[2]  = a31 * b05 - a32 * b04 + a33 * b03;
123         outMatrix[3]  = a22 * b04 - a21 * b05 - a23 * b03;
124         outMatrix[4]  = a12 * b08 - a10 * b11 - a13 * b07;
125         outMatrix[5]  = a00 * b11 - a02 * b08 + a03 * b07;
126         outMatrix[6]  = a32 * b02 - a30 * b05 - a33 * b01;
127         outMatrix[7]  = a20 * b05 - a22 * b02 + a23 * b01;
128         outMatrix[8]  = a10 * b10 - a11 * b08 + a13 * b06;
129         outMatrix[9]  = a01 * b08 - a00 * b10 - a03 * b06;
130         outMatrix[10] = a30 * b04 - a31 * b02 + a33 * b00;
131         outMatrix[11] = a21 * b02 - a20 * b04 - a23 * b00;
132         outMatrix[12] = a11 * b07 - a10 * b09 - a12 * b06;
133         outMatrix[13] = a00 * b09 - a01 * b07 + a02 * b06;
134         outMatrix[14] = a31 * b01 - a30 * b03 - a32 * b00;
135         outMatrix[15] = a20 * b03 - a21 * b01 + a22 * b00;
136 
137         // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
138         // values is non-finite, return zero to indicate a non-invertible matrix.
139         if (!SkScalarsAreFinite(outMatrix, 16)) {
140             determinant = 0.0f;
141         }
142     }
143     return determinant;
144 }
145