6ebd53b22974e2e4735c845fc937be3de57241a2
[WebKit-https.git] / Source / WebCore / platform / graphics / ColorMatrix.cpp
1 /*
2  * Copyright (C) 2020 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ColorMatrix.h"
28
29 #include "ColorComponents.h"
30 #include <wtf/MathExtras.h>
31
32 namespace WebCore {
33
34 ColorMatrix::ColorMatrix()
35 {
36     makeIdentity();
37 }
38
39 ColorMatrix::ColorMatrix(const float values[20])
40 {
41     m_matrix[0][0] = values[0];
42     m_matrix[0][1] = values[1];
43     m_matrix[0][2] = values[2];
44     m_matrix[0][3] = values[3];
45     m_matrix[0][4] = values[4];
46
47     m_matrix[1][0] = values[5];
48     m_matrix[1][1] = values[6];
49     m_matrix[1][2] = values[7];
50     m_matrix[1][3] = values[8];
51     m_matrix[1][4] = values[9];
52
53     m_matrix[2][0] = values[10];
54     m_matrix[2][1] = values[11];
55     m_matrix[2][2] = values[12];
56     m_matrix[2][3] = values[13];
57     m_matrix[2][4] = values[14];
58
59     m_matrix[3][0] = values[15];
60     m_matrix[3][1] = values[16];
61     m_matrix[3][2] = values[17];
62     m_matrix[3][3] = values[18];
63     m_matrix[3][4] = values[19];
64 }
65
66 void ColorMatrix::makeIdentity()
67 {
68     memset(m_matrix, 0, sizeof(m_matrix));
69     m_matrix[0][0] = 1;
70     m_matrix[1][1] = 1;
71     m_matrix[2][2] = 1;
72     m_matrix[3][3] = 1;
73 }
74
75 ColorMatrix ColorMatrix::grayscaleMatrix(float amount)
76 {
77     ColorMatrix matrix;
78
79     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
80
81     // Values from https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
82     matrix.m_matrix[0][0] = 0.2126f + 0.7874f * oneMinusAmount;
83     matrix.m_matrix[0][1] = 0.7152f - 0.7152f * oneMinusAmount;
84     matrix.m_matrix[0][2] = 0.0722f - 0.0722f * oneMinusAmount;
85
86     matrix.m_matrix[1][0] = 0.2126f - 0.2126f * oneMinusAmount;
87     matrix.m_matrix[1][1] = 0.7152f + 0.2848f * oneMinusAmount;
88     matrix.m_matrix[1][2] = 0.0722f - 0.0722f * oneMinusAmount;
89
90     matrix.m_matrix[2][0] = 0.2126f - 0.2126f * oneMinusAmount;
91     matrix.m_matrix[2][1] = 0.7152f - 0.7152f * oneMinusAmount;
92     matrix.m_matrix[2][2] = 0.0722f + 0.9278f * oneMinusAmount;
93     
94     return matrix;
95 }
96
97 ColorMatrix ColorMatrix::saturationMatrix(float amount)
98 {
99     ColorMatrix matrix;
100
101     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
102     matrix.m_matrix[0][0] = 0.213f + 0.787f * amount;
103     matrix.m_matrix[0][1] = 0.715f - 0.715f * amount;
104     matrix.m_matrix[0][2] = 0.072f - 0.072f * amount;
105
106     matrix.m_matrix[1][0] = 0.213f - 0.213f * amount;
107     matrix.m_matrix[1][1] = 0.715f + 0.285f * amount;
108     matrix.m_matrix[1][2] = 0.072f - 0.072f * amount;
109
110     matrix.m_matrix[2][0] = 0.213f - 0.213f * amount;
111     matrix.m_matrix[2][1] = 0.715f - 0.715f * amount;
112     matrix.m_matrix[2][2] = 0.072f + 0.928f * amount;
113
114     return matrix;
115 }
116
117 ColorMatrix ColorMatrix::hueRotateMatrix(float angleInDegrees)
118 {
119     float cosHue = cos(deg2rad(angleInDegrees));
120     float sinHue = sin(deg2rad(angleInDegrees));
121
122     ColorMatrix matrix;
123
124     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
125     matrix.m_matrix[0][0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
126     matrix.m_matrix[0][1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
127     matrix.m_matrix[0][2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
128
129     matrix.m_matrix[1][0] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
130     matrix.m_matrix[1][1] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
131     matrix.m_matrix[1][2] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
132
133     matrix.m_matrix[2][0] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
134     matrix.m_matrix[2][1] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
135     matrix.m_matrix[2][2] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
136
137     return matrix;
138 }
139
140 ColorMatrix ColorMatrix::sepiaMatrix(float amount)
141 {
142     ColorMatrix matrix;
143
144     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
145
146     // Values from https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
147     matrix.m_matrix[0][0] = 0.393f + 0.607f * oneMinusAmount;
148     matrix.m_matrix[0][1] = 0.769f - 0.769f * oneMinusAmount;
149     matrix.m_matrix[0][2] = 0.189f - 0.189f * oneMinusAmount;
150
151     matrix.m_matrix[1][0] = 0.349f - 0.349f * oneMinusAmount;
152     matrix.m_matrix[1][1] = 0.686f + 0.314f * oneMinusAmount;
153     matrix.m_matrix[1][2] = 0.168f - 0.168f * oneMinusAmount;
154
155     matrix.m_matrix[2][0] = 0.272f - 0.272f * oneMinusAmount;
156     matrix.m_matrix[2][1] = 0.534f - 0.534f * oneMinusAmount;
157     matrix.m_matrix[2][2] = 0.131f + 0.869f * oneMinusAmount;
158
159     return matrix;
160 }
161
162 void ColorMatrix::transformColorComponents(ColorComponents<float>& colorComponents) const
163 {
164     auto [red, green, blue, alpha] = colorComponents;
165
166     colorComponents.components[0] = m_matrix[0][0] * red + m_matrix[0][1] * green + m_matrix[0][2] * blue + m_matrix[0][3] * alpha + m_matrix[0][4];
167     colorComponents.components[1] = m_matrix[1][0] * red + m_matrix[1][1] * green + m_matrix[1][2] * blue + m_matrix[1][3] * alpha + m_matrix[1][4];
168     colorComponents.components[2] = m_matrix[2][0] * red + m_matrix[2][1] * green + m_matrix[2][2] * blue + m_matrix[2][3] * alpha + m_matrix[2][4];
169     colorComponents.components[3] = m_matrix[3][0] * red + m_matrix[3][1] * green + m_matrix[3][2] * blue + m_matrix[3][3] * alpha + m_matrix[3][4];
170 }
171
172 ColorComponents<float> ColorMatrix::transformedColorComponents(const ColorComponents<float>& colorComponents) const
173 {
174     auto [red, green, blue, alpha] = colorComponents;
175
176     return {
177         m_matrix[0][0] * red + m_matrix[0][1] * green + m_matrix[0][2] * blue + m_matrix[0][3] * alpha + m_matrix[0][4],
178         m_matrix[1][0] * red + m_matrix[1][1] * green + m_matrix[1][2] * blue + m_matrix[1][3] * alpha + m_matrix[1][4],
179         m_matrix[2][0] * red + m_matrix[2][1] * green + m_matrix[2][2] * blue + m_matrix[2][3] * alpha + m_matrix[2][4],
180         m_matrix[3][0] * red + m_matrix[3][1] * green + m_matrix[3][2] * blue + m_matrix[3][3] * alpha + m_matrix[3][4]
181     };
182 }
183
184 } // namespace WebCore