4d1eeb05c2ba7a350463e68f07e74e7b0efd2b12
[WebKit-https.git] / Source / WebCore / platform / graphics / ColorUtilities.h
1 /*
2  * Copyright (C) 2017, 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 #pragma once
27
28 #include <algorithm>
29 #include <array>
30 #include <math.h>
31
32 namespace WebCore {
33
34 struct FloatComponents {
35     FloatComponents(float a = 0, float b = 0, float c = 0, float d = 0)
36     {
37         components[0] = a;
38         components[1] = b;
39         components[2] = c;
40         components[3] = d;
41     }
42
43     FloatComponents(const std::array<float, 4>& values)
44     {
45         components[0] = values[0];
46         components[1] = values[1];
47         components[2] = values[2];
48         components[3] = values[3];
49     }
50
51     FloatComponents& operator+=(const FloatComponents& rhs)
52     {
53         components[0] += rhs.components[0];
54         components[1] += rhs.components[1];
55         components[2] += rhs.components[2];
56         components[3] += rhs.components[3];
57         return *this;
58     }
59
60     FloatComponents operator+(float rhs) const
61     {
62         FloatComponents result;
63         result.components[0] = components[0] + rhs;
64         result.components[1] = components[1] + rhs;
65         result.components[2] = components[2] + rhs;
66         result.components[3] = components[3] + rhs;
67         return result;
68     }
69
70     FloatComponents operator/(float denominator) const
71     {
72         FloatComponents result;
73         result.components[0] = components[0] / denominator;
74         result.components[1] = components[1] / denominator;
75         result.components[2] = components[2] / denominator;
76         result.components[3] = components[3] / denominator;
77         return result;
78     }
79
80     FloatComponents operator*(float factor) const
81     {
82         FloatComponents result;
83         result.components[0] = components[0] * factor;
84         result.components[1] = components[1] * factor;
85         result.components[2] = components[2] * factor;
86         result.components[3] = components[3] * factor;
87         return result;
88     }
89
90     FloatComponents abs() const
91     {
92         FloatComponents result;
93         result.components[0] = fabs(components[0]);
94         result.components[1] = fabs(components[1]);
95         result.components[2] = fabs(components[2]);
96         result.components[3] = fabs(components[3]);
97         return result;
98     }
99
100     template<std::size_t N>
101     float get() const
102     {
103         return components[N];
104     }
105
106     std::array<float, 4> components;
107 };
108
109 bool areEssentiallyEqual(const FloatComponents&, const FloatComponents&);
110
111 struct ColorComponents {
112     ColorComponents(const FloatComponents&);
113     
114     static ColorComponents fromRGBA(unsigned pixel)
115     {
116         return ColorComponents((pixel >> 24) & 0xFF, (pixel >> 16) & 0xFF, (pixel >> 8) & 0xFF, pixel & 0xFF);
117     }
118     
119     ColorComponents(uint8_t a = 0, uint8_t b = 0, uint8_t c = 0, uint8_t d = 0)
120     {
121         components[0] = a;
122         components[1] = b;
123         components[2] = c;
124         components[3] = d;
125     }
126     
127     unsigned toRGBA() const
128     {
129         return components[0] << 24 | components[1] << 16 | components[2] << 8 | components[3];
130     }
131
132     std::array<uint8_t, 4> components;
133 };
134
135 inline ColorComponents perComponentMax(const ColorComponents& a, const ColorComponents& b)
136 {
137     return {
138         std::max(a.components[0], b.components[0]),
139         std::max(a.components[1], b.components[1]),
140         std::max(a.components[2], b.components[2]),
141         std::max(a.components[3], b.components[3])
142     };
143 }
144
145 inline ColorComponents perComponentMin(const ColorComponents& a, const ColorComponents& b)
146 {
147     return {
148         std::min(a.components[0], b.components[0]),
149         std::min(a.components[1], b.components[1]),
150         std::min(a.components[2], b.components[2]),
151         std::min(a.components[3], b.components[3])
152     };
153 }
154
155 inline bool operator==(const ColorComponents& a, const ColorComponents& b)
156 {
157     return a.components == b.components;
158 }
159
160 inline bool operator!=(const ColorComponents& a, const ColorComponents& b)
161 {
162     return !(a == b);
163 }
164
165 inline uint8_t clampedColorComponent(float f)
166 {
167     // See also colorFloatToRGBAByte().
168     return std::clamp(static_cast<int>(lroundf(255.0f * f)), 0, 255);
169 }
170
171 inline unsigned byteOffsetOfPixel(unsigned x, unsigned y, unsigned rowBytes)
172 {
173     const unsigned bytesPerPixel = 4;
174     return x * bytesPerPixel + y * rowBytes;
175 }
176
177 // 0-1 components, result is clamped.
178 float linearToRGBColorComponent(float);
179 float rgbToLinearColorComponent(float);
180
181 FloatComponents rgbToLinearComponents(const FloatComponents&);
182 FloatComponents linearToRGBComponents(const FloatComponents&);
183
184 FloatComponents p3ToSRGB(const FloatComponents&);
185 FloatComponents sRGBToP3(const FloatComponents&);
186
187 WEBCORE_EXPORT FloatComponents sRGBToHSL(const FloatComponents&);
188 WEBCORE_EXPORT FloatComponents hslToSRGB(const FloatComponents&);
189
190 float lightness(const FloatComponents& sRGBCompontents);
191 float luminance(const FloatComponents& sRGBCompontents);
192 float contrastRatio(const FloatComponents&, const FloatComponents&);
193
194 FloatComponents premultiplied(const FloatComponents& sRGBCompontents);
195
196 } // namespace WebCore
197
198 namespace std {
199
200 template<>
201 class tuple_size<WebCore::FloatComponents> : public std::integral_constant<std::size_t, 4> {
202 };
203
204 template<std::size_t N>
205 class tuple_element<N, WebCore::FloatComponents> {
206 public:
207     using type = float;
208 };
209
210 }