Implement rendering support for the color-filter CSS property
[WebKit-https.git] / Source / WebCore / platform / graphics / ColorUtilities.cpp
1 /*
2  * Copyright (C) 2017 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 "ColorUtilities.h"
28
29 #include "Color.h"
30 #include <wtf/MathExtras.h>
31
32 namespace WebCore {
33
34 ColorComponents::ColorComponents(const FloatComponents& floatComponents)
35 {
36     components[0] = clampedColorComponent(floatComponents.components[0]);
37     components[1] = clampedColorComponent(floatComponents.components[1]);
38     components[2] = clampedColorComponent(floatComponents.components[2]);
39     components[3] = clampedColorComponent(floatComponents.components[3]);
40 }
41
42 // These are the standard sRGB <-> linearRGB conversion functions (https://en.wikipedia.org/wiki/SRGB).
43 float linearToSRGBColorComponent(float c)
44 {
45     if (c < 0.0031308)
46         return 12.92 * c;
47
48     return clampTo<float>(1.055 * powf(c, 1.0 / 2.4) - 0.055, 0, 1);
49 }
50
51 float sRGBToLinearColorComponent(float c)
52 {
53     if (c <= 0.04045)
54         return c / 12.92;
55
56     return clampTo<float>(powf((c + 0.055) / 1.055, 2.4), 0, 1);
57 }
58
59 Color linearToSRGBColor(const Color& color)
60 {
61     float r, g, b, a;
62     color.getRGBA(r, g, b, a);
63     r = linearToSRGBColorComponent(r);
64     g = linearToSRGBColorComponent(g);
65     b = linearToSRGBColorComponent(b);
66
67     return Color(r, g, b, a);
68 }
69
70 Color sRGBToLinearColor(const Color& color)
71 {
72     float r, g, b, a;
73     color.getRGBA(r, g, b, a);
74     r = sRGBToLinearColorComponent(r);
75     g = sRGBToLinearColorComponent(g);
76     b = sRGBToLinearColorComponent(b);
77
78     return Color(r, g, b, a);
79 }
80
81
82 ColorMatrix::ColorMatrix()
83 {
84     makeIdentity();
85 }
86
87 void ColorMatrix::makeIdentity()
88 {
89     memset(m_matrix, 0, sizeof(m_matrix));
90     m_matrix[0][0] = 1;
91     m_matrix[1][1] = 1;
92     m_matrix[2][2] = 1;
93     m_matrix[3][3] = 1;
94 }
95
96 ColorMatrix ColorMatrix::grayscaleMatrix(float amount)
97 {
98     ColorMatrix matrix;
99
100     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
101
102     // Values from https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
103     matrix.m_matrix[0][0] = 0.2126f + 0.7874f * oneMinusAmount;
104     matrix.m_matrix[0][1] = 0.7152f - 0.7152f * oneMinusAmount;
105     matrix.m_matrix[0][2] = 0.0722f - 0.0722f * oneMinusAmount;
106
107     matrix.m_matrix[1][0] = 0.2126f - 0.2126f * oneMinusAmount;
108     matrix.m_matrix[1][1] = 0.7152f + 0.2848f * oneMinusAmount;
109     matrix.m_matrix[1][2] = 0.0722f - 0.0722f * oneMinusAmount;
110
111     matrix.m_matrix[2][0] = 0.2126f - 0.2126f * oneMinusAmount;
112     matrix.m_matrix[2][1] = 0.7152f - 0.7152f * oneMinusAmount;
113     matrix.m_matrix[2][2] = 0.0722f + 0.9278f * oneMinusAmount;
114     
115     return matrix;
116 }
117
118 ColorMatrix ColorMatrix::saturationMatrix(float amount)
119 {
120     ColorMatrix matrix;
121
122     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
123     matrix.m_matrix[0][0] = 0.213f + 0.787f * amount;
124     matrix.m_matrix[0][1] = 0.715f - 0.715f * amount;
125     matrix.m_matrix[0][2] = 0.072f - 0.072f * amount;
126
127     matrix.m_matrix[1][0] = 0.213f - 0.213f * amount;
128     matrix.m_matrix[1][1] = 0.715f + 0.285f * amount;
129     matrix.m_matrix[1][2] = 0.072f - 0.072f * amount;
130
131     matrix.m_matrix[2][0] = 0.213f - 0.213f * amount;
132     matrix.m_matrix[2][1] = 0.715f - 0.715f * amount;
133     matrix.m_matrix[2][2] = 0.072f + 0.928f * amount;
134
135     return matrix;
136 }
137
138 ColorMatrix ColorMatrix::hueRotateMatrix(float angleInDegrees)
139 {
140     float cosHue = cos(deg2rad(angleInDegrees));
141     float sinHue = sin(deg2rad(angleInDegrees));
142
143     ColorMatrix matrix;
144
145     // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
146     matrix.m_matrix[0][0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
147     matrix.m_matrix[0][1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
148     matrix.m_matrix[0][2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
149
150     matrix.m_matrix[1][0] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
151     matrix.m_matrix[1][1] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
152     matrix.m_matrix[1][2] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
153
154     matrix.m_matrix[2][0] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
155     matrix.m_matrix[2][1] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
156     matrix.m_matrix[2][2] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
157
158     return matrix;
159 }
160
161 ColorMatrix ColorMatrix::sepiaMatrix(float amount)
162 {
163     ColorMatrix matrix;
164
165     float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
166
167     // Values from https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
168     matrix.m_matrix[0][0] = 0.393f + 0.607f * oneMinusAmount;
169     matrix.m_matrix[0][1] = 0.769f - 0.769f * oneMinusAmount;
170     matrix.m_matrix[0][2] = 0.189f - 0.189f * oneMinusAmount;
171
172     matrix.m_matrix[1][0] = 0.349f - 0.349f * oneMinusAmount;
173     matrix.m_matrix[1][1] = 0.686f + 0.314f * oneMinusAmount;
174     matrix.m_matrix[1][2] = 0.168f - 0.168f * oneMinusAmount;
175
176     matrix.m_matrix[2][0] = 0.272f - 0.272f * oneMinusAmount;
177     matrix.m_matrix[2][1] = 0.534f - 0.534f * oneMinusAmount;
178     matrix.m_matrix[2][2] = 0.131f + 0.869f * oneMinusAmount;
179
180     return matrix;
181 }
182
183 void ColorMatrix::transformColorComponents(FloatComponents& colorComonents) const
184 {
185     float red = colorComonents.components[0];
186     float green = colorComonents.components[1];
187     float blue = colorComonents.components[2];
188     float alpha = colorComonents.components[3];
189
190     colorComonents.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];
191     colorComonents.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];
192     colorComonents.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];
193     colorComonents.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];
194 }
195
196 } // namespace WebCore