summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/core/SkMatrixInvert.cpp
blob: ea8d36702c1b11976f179b0165afb26c51b48ea7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/core/SkMatrixInvert.h"

#include "include/private/base/SkFloatingPoint.h"

SkScalar SkInvert2x2Matrix(const SkScalar inMatrix[4], SkScalar outMatrix[4]) {
    double a00 = inMatrix[0];
    double a01 = inMatrix[1];
    double a10 = inMatrix[2];
    double a11 = inMatrix[3];

    // Calculate the determinant
    double determinant = a00 * a11 - a01 * a10;
    if (outMatrix) {
        double invdet = sk_ieee_double_divide(1.0, determinant);
        outMatrix[0] =  a11 * invdet;
        outMatrix[1] = -a01 * invdet;
        outMatrix[2] = -a10 * invdet;
        outMatrix[3] =  a00 * invdet;
        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
        // values is non-finite, return zero to indicate a non-invertible matrix.
        if (!SkScalarsAreFinite(outMatrix, 4)) {
            determinant = 0.0f;
        }
    }
    return determinant;
}

SkScalar SkInvert3x3Matrix(const SkScalar inMatrix[9], SkScalar outMatrix[9]) {
    double a00 = inMatrix[0];
    double a01 = inMatrix[1];
    double a02 = inMatrix[2];
    double a10 = inMatrix[3];
    double a11 = inMatrix[4];
    double a12 = inMatrix[5];
    double a20 = inMatrix[6];
    double a21 = inMatrix[7];
    double a22 = inMatrix[8];

    double b01 =  a22 * a11 - a12 * a21;
    double b11 = -a22 * a10 + a12 * a20;
    double b21 =  a21 * a10 - a11 * a20;

    // Calculate the determinant
    double determinant = a00 * b01 + a01 * b11 + a02 * b21;
    if (outMatrix) {
        double invdet = sk_ieee_double_divide(1.0, determinant);
        outMatrix[0] = b01 * invdet;
        outMatrix[1] = (-a22 * a01 + a02 * a21) * invdet;
        outMatrix[2] = ( a12 * a01 - a02 * a11) * invdet;
        outMatrix[3] = b11 * invdet;
        outMatrix[4] = ( a22 * a00 - a02 * a20) * invdet;
        outMatrix[5] = (-a12 * a00 + a02 * a10) * invdet;
        outMatrix[6] = b21 * invdet;
        outMatrix[7] = (-a21 * a00 + a01 * a20) * invdet;
        outMatrix[8] = ( a11 * a00 - a01 * a10) * invdet;
        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
        // values is non-finite, return zero to indicate a non-invertible matrix.
        if (!SkScalarsAreFinite(outMatrix, 9)) {
            determinant = 0.0f;
        }
    }
    return determinant;
}

SkScalar SkInvert4x4Matrix(const SkScalar inMatrix[16], SkScalar outMatrix[16]) {
    double a00 = inMatrix[0];
    double a01 = inMatrix[1];
    double a02 = inMatrix[2];
    double a03 = inMatrix[3];
    double a10 = inMatrix[4];
    double a11 = inMatrix[5];
    double a12 = inMatrix[6];
    double a13 = inMatrix[7];
    double a20 = inMatrix[8];
    double a21 = inMatrix[9];
    double a22 = inMatrix[10];
    double a23 = inMatrix[11];
    double a30 = inMatrix[12];
    double a31 = inMatrix[13];
    double a32 = inMatrix[14];
    double a33 = inMatrix[15];

    double b00 = a00 * a11 - a01 * a10;
    double b01 = a00 * a12 - a02 * a10;
    double b02 = a00 * a13 - a03 * a10;
    double b03 = a01 * a12 - a02 * a11;
    double b04 = a01 * a13 - a03 * a11;
    double b05 = a02 * a13 - a03 * a12;
    double b06 = a20 * a31 - a21 * a30;
    double b07 = a20 * a32 - a22 * a30;
    double b08 = a20 * a33 - a23 * a30;
    double b09 = a21 * a32 - a22 * a31;
    double b10 = a21 * a33 - a23 * a31;
    double b11 = a22 * a33 - a23 * a32;

    // Calculate the determinant
    double determinant = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    if (outMatrix) {
        double invdet = sk_ieee_double_divide(1.0, determinant);
        b00 *= invdet;
        b01 *= invdet;
        b02 *= invdet;
        b03 *= invdet;
        b04 *= invdet;
        b05 *= invdet;
        b06 *= invdet;
        b07 *= invdet;
        b08 *= invdet;
        b09 *= invdet;
        b10 *= invdet;
        b11 *= invdet;

        outMatrix[0]  = a11 * b11 - a12 * b10 + a13 * b09;
        outMatrix[1]  = a02 * b10 - a01 * b11 - a03 * b09;
        outMatrix[2]  = a31 * b05 - a32 * b04 + a33 * b03;
        outMatrix[3]  = a22 * b04 - a21 * b05 - a23 * b03;
        outMatrix[4]  = a12 * b08 - a10 * b11 - a13 * b07;
        outMatrix[5]  = a00 * b11 - a02 * b08 + a03 * b07;
        outMatrix[6]  = a32 * b02 - a30 * b05 - a33 * b01;
        outMatrix[7]  = a20 * b05 - a22 * b02 + a23 * b01;
        outMatrix[8]  = a10 * b10 - a11 * b08 + a13 * b06;
        outMatrix[9]  = a01 * b08 - a00 * b10 - a03 * b06;
        outMatrix[10] = a30 * b04 - a31 * b02 + a33 * b00;
        outMatrix[11] = a21 * b02 - a20 * b04 - a23 * b00;
        outMatrix[12] = a11 * b07 - a10 * b09 - a12 * b06;
        outMatrix[13] = a00 * b09 - a01 * b07 + a02 * b06;
        outMatrix[14] = a31 * b01 - a30 * b03 - a32 * b00;
        outMatrix[15] = a20 * b03 - a21 * b01 + a22 * b00;

        // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix
        // values is non-finite, return zero to indicate a non-invertible matrix.
        if (!SkScalarsAreFinite(outMatrix, 16)) {
            determinant = 0.0f;
        }
    }
    return determinant;
}