Extended Color: Move ColorMatrix to its own files
[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 <wtf/MathExtras.h>
30
31 namespace WebCore {
32
33 ColorMatrix::ColorMatrix()
34 {
35     makeIdentity();
36 }
37
38 ColorMatrix::ColorMatrix(const float values[20])
39 {
40     m_matrix[0][0] = values[0];
41     m_matrix[0][1] = values[1];
42     m_matrix[0][2] = values[2];
43     m_matrix[0][3] = values[3];
44     m_matrix[0][4] = values[4];
45
46     m_matrix[1][0] = values[5];
47     m_matrix[1][1] = values[6];
48     m_matrix[1][2] = values[7];
49     m_matrix[1][3] = values[8];
50     m_matrix[1][4] = values[9];
51
52     m_matrix[2][0] = values[10];
53     m_matrix[2][1] = values[11];
54     m_matrix[2][2] = values[12];
55     m_matrix[2][3] = values[13];
56     m_matrix[2][4] = values[14];
57
58     m_matrix[3][0] = values[15];
59     m_matrix[3][1] = values[16];
60     m_matrix[3][2] = values[17];
61     m_matrix[3][3] = values[18];
62     m_matrix[3][4] = values[19];
63 }
64
65 void ColorMatrix::makeIdentity()
66 {
67     memset(m_matrix, 0, sizeof(m_matrix));
68     m_matrix[0][0] = 1;
69     m_matrix[1][1] = 1;
70     m_matrix[2][2] = 1;
71     m_matrix[3][3] = 1;
72 }
73
74 ColorMatrix ColorMatrix::grayscaleMatrix(float amount)
75 {
76     ColorMatrix matrix;
77
78     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
79
80     // Values from https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
81     matrix.m_matrix[0][0] = 0.2126f + 0.7874f * oneMinusAmount;
82     matrix.m_matrix[0][1] = 0.7152f - 0.7152f * oneMinusAmount;
83     matrix.m_matrix[0][2] = 0.0722f - 0.0722f * oneMinusAmount;
84
85     matrix.m_matrix[1][0] = 0.2126f - 0.2126f * oneMinusAmount;
86     matrix.m_matrix[1][1] = 0.7152f + 0.2848f * oneMinusAmount;
87     matrix.m_matrix[1][2] = 0.0722f - 0.0722f * oneMinusAmount;
88
89     matrix.m_matrix[2][0] = 0.2126f - 0.2126f * oneMinusAmount;
90     matrix.m_matrix[2][1] = 0.7152f - 0.7152f * oneMinusAmount;
91     matrix.m_matrix[2][2] = 0.0722f + 0.9278f * oneMinusAmount;
92     
93     return matrix;
94 }
95
96 ColorMatrix ColorMatrix::saturationMatrix(float amount)
97 {
98     ColorMatrix matrix;
99
100     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
101     matrix.m_matrix[0][0] = 0.213f + 0.787f * amount;
102     matrix.m_matrix[0][1] = 0.715f - 0.715f * amount;
103     matrix.m_matrix[0][2] = 0.072f - 0.072f * amount;
104
105     matrix.m_matrix[1][0] = 0.213f - 0.213f * amount;
106     matrix.m_matrix[1][1] = 0.715f + 0.285f * amount;
107     matrix.m_matrix[1][2] = 0.072f - 0.072f * amount;
108
109     matrix.m_matrix[2][0] = 0.213f - 0.213f * amount;
110     matrix.m_matrix[2][1] = 0.715f - 0.715f * amount;
111     matrix.m_matrix[2][2] = 0.072f + 0.928f * amount;
112
113     return matrix;
114 }
115
116 ColorMatrix ColorMatrix::hueRotateMatrix(float angleInDegrees)
117 {
118     float cosHue = cos(deg2rad(angleInDegrees));
119     float sinHue = sin(deg2rad(angleInDegrees));
120
121     ColorMatrix matrix;
122
123     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
124     matrix.m_matrix[0][0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
125     matrix.m_matrix[0][1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
126     matrix.m_matrix[0][2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
127
128     matrix.m_matrix[1][0] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
129     matrix.m_matrix[1][1] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
130     matrix.m_matrix[1][2] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
131
132     matrix.m_matrix[2][0] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
133     matrix.m_matrix[2][1] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
134     matrix.m_matrix[2][2] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
135
136     return matrix;
137 }
138
139 ColorMatrix ColorMatrix::sepiaMatrix(float amount)
140 {
141     ColorMatrix matrix;
142
143     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
144
145     // Values from https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
146     matrix.m_matrix[0][0] = 0.393f + 0.607f * oneMinusAmount;
147     matrix.m_matrix[0][1] = 0.769f - 0.769f * oneMinusAmount;
148     matrix.m_matrix[0][2] = 0.189f - 0.189f * oneMinusAmount;
149
150     matrix.m_matrix[1][0] = 0.349f - 0.349f * oneMinusAmount;
151     matrix.m_matrix[1][1] = 0.686f + 0.314f * oneMinusAmount;
152     matrix.m_matrix[1][2] = 0.168f - 0.168f * oneMinusAmount;
153
154     matrix.m_matrix[2][0] = 0.272f - 0.272f * oneMinusAmount;
155     matrix.m_matrix[2][1] = 0.534f - 0.534f * oneMinusAmount;
156     matrix.m_matrix[2][2] = 0.131f + 0.869f * oneMinusAmount;
157
158     return matrix;
159 }
160
161 void ColorMatrix::transformColorComponents(FloatComponents& colorComponents) const
162 {
163     auto [red, green, blue, alpha] = colorComponents;
164
165     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];
166     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];
167     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];
168     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];
169 }
170
171 FloatComponents ColorMatrix::transformedColorComponents(const FloatComponents& colorComponents) const
172 {
173     auto [red, green, blue, alpha] = colorComponents;
174
175     return {
176         m_matrix[0][0] * red + m_matrix[0][1] * green + m_matrix[0][2] * blue + m_matrix[0][3] * alpha + m_matrix[0][4],
177         m_matrix[1][0] * red + m_matrix[1][1] * green + m_matrix[1][2] * blue + m_matrix[1][3] * alpha + m_matrix[1][4],
178         m_matrix[2][0] * red + m_matrix[2][1] * green + m_matrix[2][2] * blue + m_matrix[2][3] * alpha + m_matrix[2][4],
179         m_matrix[3][0] * red + m_matrix[3][1] * green + m_matrix[3][2] * blue + m_matrix[3][3] * alpha + m_matrix[3][4]
180     };
181 }
182
183 } // namespace WebCore