1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2008 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/platform/graphics/color.h"
27 
28 #include "build/build_config.h"
29 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
30 #include "third_party/blink/renderer/platform/wtf/assertions.h"
31 #include "third_party/blink/renderer/platform/wtf/decimal.h"
32 #include "third_party/blink/renderer/platform/wtf/dtoa.h"
33 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
34 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
35 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
36 #include "third_party/skia/include/core/SkColor.h"
37 
38 namespace blink {
39 
40 // VS 2015 and above allow these definitions and in this case require them
41 #if !defined(COMPILER_MSVC) || _MSC_VER >= 1900
42 // FIXME: Use C++11 enum classes to avoid static data member initializer
43 // definition problems.
44 const RGBA32 Color::kBlack;
45 const RGBA32 Color::kWhite;
46 const RGBA32 Color::kDarkGray;
47 const RGBA32 Color::kGray;
48 const RGBA32 Color::kLightGray;
49 const RGBA32 Color::kTransparent;
50 #endif
51 
52 namespace {
53 
54 const RGBA32 kLightenedBlack = 0xFF545454;
55 const RGBA32 kDarkenedWhite = 0xFFABABAB;
56 
57 const int kCStartAlpha = 153;     // 60%
58 const int kCEndAlpha = 204;       // 80%;
59 const int kCAlphaIncrement = 17;  // Increments in between.
60 
BlendComponent(int c,int a)61 int BlendComponent(int c, int a) {
62   // We use white.
63   float alpha = a / 255.0f;
64   int white_blend = 255 - a;
65   c -= white_blend;
66   return static_cast<int>(c / alpha);
67 }
68 
CalcHue(double temp1,double temp2,double hue_val)69 double CalcHue(double temp1, double temp2, double hue_val) {
70   if (hue_val < 0.0)
71     hue_val += 6.0;
72   else if (hue_val >= 6.0)
73     hue_val -= 6.0;
74   if (hue_val < 1.0)
75     return temp1 + (temp2 - temp1) * hue_val;
76   if (hue_val < 3.0)
77     return temp2;
78   if (hue_val < 4.0)
79     return temp1 + (temp2 - temp1) * (4.0 - hue_val);
80   return temp1;
81 }
82 
ColorFloatToRGBAByte(float f)83 int ColorFloatToRGBAByte(float f) {
84   return clampTo(static_cast<int>(lroundf(255.0f * f)), 0, 255);
85 }
86 
87 // originally moved here from the CSS parser
88 template <typename CharacterType>
ParseHexColorInternal(const CharacterType * name,unsigned length,RGBA32 & rgb)89 inline bool ParseHexColorInternal(const CharacterType* name,
90                                   unsigned length,
91                                   RGBA32& rgb) {
92   if (length != 3 && length != 4 && length != 6 && length != 8)
93     return false;
94   if ((length == 8 || length == 4) &&
95       !RuntimeEnabledFeatures::CSSHexAlphaColorEnabled())
96     return false;
97   unsigned value = 0;
98   for (unsigned i = 0; i < length; ++i) {
99     if (!IsASCIIHexDigit(name[i]))
100       return false;
101     value <<= 4;
102     value |= ToASCIIHexValue(name[i]);
103   }
104   if (length == 6) {
105     rgb = 0xFF000000 | value;
106     return true;
107   }
108   if (length == 8) {
109     // We parsed the values into RGBA order, but the RGBA32 type
110     // expects them to be in ARGB order, so we right rotate eight bits.
111     rgb = value << 24 | value >> 8;
112     return true;
113   }
114   if (length == 4) {
115     // #abcd converts to ddaabbcc in RGBA32.
116     rgb = (value & 0xF) << 28 | (value & 0xF) << 24 | (value & 0xF000) << 8 |
117           (value & 0xF000) << 4 | (value & 0xF00) << 4 | (value & 0xF00) |
118           (value & 0xF0) | (value & 0xF0) >> 4;
119     return true;
120   }
121   // #abc converts to #aabbcc
122   rgb = 0xFF000000 | (value & 0xF00) << 12 | (value & 0xF00) << 8 |
123         (value & 0xF0) << 8 | (value & 0xF0) << 4 | (value & 0xF) << 4 |
124         (value & 0xF);
125   return true;
126 }
127 
FindNamedColor(const String & name)128 inline const NamedColor* FindNamedColor(const String& name) {
129   char buffer[64];  // easily big enough for the longest color name
130   unsigned length = name.length();
131   if (length > sizeof(buffer) - 1)
132     return nullptr;
133   for (unsigned i = 0; i < length; ++i) {
134     UChar c = name[i];
135     if (!c || c > 0x7F)
136       return nullptr;
137     buffer[i] = ToASCIILower(static_cast<char>(c));
138   }
139   buffer[length] = '\0';
140   return FindColor(buffer, length);
141 }
142 
143 }  // namespace
144 
MakeRGB(int r,int g,int b)145 RGBA32 MakeRGB(int r, int g, int b) {
146   return 0xFF000000 | clampTo(r, 0, 255) << 16 | clampTo(g, 0, 255) << 8 |
147          clampTo(b, 0, 255);
148 }
149 
MakeRGBA(int r,int g,int b,int a)150 RGBA32 MakeRGBA(int r, int g, int b, int a) {
151   return clampTo(a, 0, 255) << 24 | clampTo(r, 0, 255) << 16 |
152          clampTo(g, 0, 255) << 8 | clampTo(b, 0, 255);
153 }
154 
MakeRGBA32FromFloats(float r,float g,float b,float a)155 RGBA32 MakeRGBA32FromFloats(float r, float g, float b, float a) {
156   return ColorFloatToRGBAByte(a) << 24 | ColorFloatToRGBAByte(r) << 16 |
157          ColorFloatToRGBAByte(g) << 8 | ColorFloatToRGBAByte(b);
158 }
159 
160 // Explanation of this algorithm can be found in the CSS Color 4 Module
161 // specification at https://drafts.csswg.org/css-color-4/#hsl-to-rgb with
162 // further explanation available at http://en.wikipedia.org/wiki/HSL_color_space
163 
164 // Hue is in the range of 0 to 6.0, the remainder are in the range 0 to 1.0
MakeRGBAFromHSLA(double hue,double saturation,double lightness,double alpha)165 RGBA32 MakeRGBAFromHSLA(double hue,
166                         double saturation,
167                         double lightness,
168                         double alpha) {
169   const double scale_factor = 255.0;
170 
171   if (!saturation) {
172     int grey_value = static_cast<int>(round(lightness * scale_factor));
173     return MakeRGBA(grey_value, grey_value, grey_value,
174                     static_cast<int>(round(alpha * scale_factor)));
175   }
176 
177   double temp2 = lightness <= 0.5
178                      ? lightness * (1.0 + saturation)
179                      : lightness + saturation - lightness * saturation;
180   double temp1 = 2.0 * lightness - temp2;
181 
182   return MakeRGBA(
183       static_cast<int>(round(CalcHue(temp1, temp2, hue + 2.0) * scale_factor)),
184       static_cast<int>(round(CalcHue(temp1, temp2, hue) * scale_factor)),
185       static_cast<int>(round(CalcHue(temp1, temp2, hue - 2.0) * scale_factor)),
186       static_cast<int>(round(alpha * scale_factor)));
187 }
188 
MakeRGBAFromCMYKA(float c,float m,float y,float k,float a)189 RGBA32 MakeRGBAFromCMYKA(float c, float m, float y, float k, float a) {
190   double colors = 1 - k;
191   int r = static_cast<int>(nextafter(256, 0) * (colors * (1 - c)));
192   int g = static_cast<int>(nextafter(256, 0) * (colors * (1 - m)));
193   int b = static_cast<int>(nextafter(256, 0) * (colors * (1 - y)));
194   return MakeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a));
195 }
196 
ParseHexColor(const LChar * name,unsigned length,RGBA32 & rgb)197 bool Color::ParseHexColor(const LChar* name, unsigned length, RGBA32& rgb) {
198   return ParseHexColorInternal(name, length, rgb);
199 }
200 
ParseHexColor(const UChar * name,unsigned length,RGBA32 & rgb)201 bool Color::ParseHexColor(const UChar* name, unsigned length, RGBA32& rgb) {
202   return ParseHexColorInternal(name, length, rgb);
203 }
204 
ParseHexColor(const StringView & name,RGBA32 & rgb)205 bool Color::ParseHexColor(const StringView& name, RGBA32& rgb) {
206   if (name.IsEmpty())
207     return false;
208   if (name.Is8Bit())
209     return ParseHexColor(name.Characters8(), name.length(), rgb);
210   return ParseHexColor(name.Characters16(), name.length(), rgb);
211 }
212 
DifferenceSquared(const Color & c1,const Color & c2)213 int DifferenceSquared(const Color& c1, const Color& c2) {
214   int d_r = c1.Red() - c2.Red();
215   int d_g = c1.Green() - c2.Green();
216   int d_b = c1.Blue() - c2.Blue();
217   return d_r * d_r + d_g * d_g + d_b * d_b;
218 }
219 
SetFromString(const String & name)220 bool Color::SetFromString(const String& name) {
221   if (name[0] != '#')
222     return SetNamedColor(name);
223   if (name.Is8Bit())
224     return ParseHexColor(name.Characters8() + 1, name.length() - 1, color_);
225   return ParseHexColor(name.Characters16() + 1, name.length() - 1, color_);
226 }
227 
Serialized() const228 String Color::Serialized() const {
229   if (!HasAlpha())
230     return String::Format("#%02x%02x%02x", Red(), Green(), Blue());
231 
232   StringBuilder result;
233   result.ReserveCapacity(28);
234 
235   result.Append("rgba(");
236   result.AppendNumber(Red());
237   result.Append(", ");
238   result.AppendNumber(Green());
239   result.Append(", ");
240   result.AppendNumber(Blue());
241   result.Append(", ");
242 
243   if (!Alpha())
244     result.Append('0');
245   else {
246     result.Append(Decimal::FromDouble(Alpha() / 255.0).ToString());
247   }
248 
249   result.Append(')');
250   return result.ToString();
251 }
252 
NameForLayoutTreeAsText() const253 String Color::NameForLayoutTreeAsText() const {
254   if (Alpha() < 0xFF)
255     return String::Format("#%02X%02X%02X%02X", Red(), Green(), Blue(), Alpha());
256   return String::Format("#%02X%02X%02X", Red(), Green(), Blue());
257 }
258 
SetNamedColor(const String & name)259 bool Color::SetNamedColor(const String& name) {
260   const NamedColor* found_color = FindNamedColor(name);
261   color_ = found_color ? found_color->argb_value : 0;
262   return found_color;
263 }
264 
operator SkColor() const265 Color::operator SkColor() const {
266   return SkColorSetARGB(Alpha(), Red(), Green(), Blue());
267 }
268 
Light() const269 Color Color::Light() const {
270   // Hardcode this common case for speed.
271   if (color_ == kBlack)
272     return kLightenedBlack;
273 
274   const float scale_factor = nextafterf(256.0f, 0.0f);
275 
276   float r, g, b, a;
277   GetRGBA(r, g, b, a);
278 
279   float v = std::max(r, std::max(g, b));
280 
281   if (v == 0.0f)
282     // Lightened black with alpha.
283     return Color(0x54, 0x54, 0x54, Alpha());
284 
285   float multiplier = std::min(1.0f, v + 0.33f) / v;
286 
287   return Color(static_cast<int>(multiplier * r * scale_factor),
288                static_cast<int>(multiplier * g * scale_factor),
289                static_cast<int>(multiplier * b * scale_factor), Alpha());
290 }
291 
Dark() const292 Color Color::Dark() const {
293   // Hardcode this common case for speed.
294   if (color_ == kWhite)
295     return kDarkenedWhite;
296 
297   const float scale_factor = nextafterf(256.0f, 0.0f);
298 
299   float r, g, b, a;
300   GetRGBA(r, g, b, a);
301 
302   float v = std::max(r, std::max(g, b));
303   float multiplier = (v == 0.0f) ? 0.0f : std::max(0.0f, (v - 0.33f) / v);
304 
305   return Color(static_cast<int>(multiplier * r * scale_factor),
306                static_cast<int>(multiplier * g * scale_factor),
307                static_cast<int>(multiplier * b * scale_factor), Alpha());
308 }
309 
CombineWithAlpha(float other_alpha) const310 Color Color::CombineWithAlpha(float other_alpha) const {
311   RGBA32 rgb_only = Rgb() & 0x00FFFFFF;
312   float override_alpha = (Alpha() / 255.f) * other_alpha;
313   return rgb_only | ColorFloatToRGBAByte(override_alpha) << 24;
314 }
315 
Blend(const Color & source) const316 Color Color::Blend(const Color& source) const {
317   if (!Alpha() || !source.HasAlpha())
318     return source;
319 
320   if (!source.Alpha())
321     return *this;
322 
323   int d = 255 * (Alpha() + source.Alpha()) - Alpha() * source.Alpha();
324   int a = d / 255;
325   int r = (Red() * Alpha() * (255 - source.Alpha()) +
326            255 * source.Alpha() * source.Red()) /
327           d;
328   int g = (Green() * Alpha() * (255 - source.Alpha()) +
329            255 * source.Alpha() * source.Green()) /
330           d;
331   int b = (Blue() * Alpha() * (255 - source.Alpha()) +
332            255 * source.Alpha() * source.Blue()) /
333           d;
334   return Color(r, g, b, a);
335 }
336 
BlendWithWhite() const337 Color Color::BlendWithWhite() const {
338   // If the color contains alpha already, we leave it alone.
339   if (HasAlpha())
340     return *this;
341 
342   Color new_color;
343   for (int alpha = kCStartAlpha; alpha <= kCEndAlpha;
344        alpha += kCAlphaIncrement) {
345     // We have a solid color.  Convert to an equivalent color that looks the
346     // same when blended with white at the current alpha.  Try using less
347     // transparency if the numbers end up being negative.
348     int r = BlendComponent(Red(), alpha);
349     int g = BlendComponent(Green(), alpha);
350     int b = BlendComponent(Blue(), alpha);
351 
352     new_color = Color(r, g, b, alpha);
353 
354     if (r >= 0 && g >= 0 && b >= 0)
355       break;
356   }
357   return new_color;
358 }
359 
GetRGBA(float & r,float & g,float & b,float & a) const360 void Color::GetRGBA(float& r, float& g, float& b, float& a) const {
361   r = Red() / 255.0f;
362   g = Green() / 255.0f;
363   b = Blue() / 255.0f;
364   a = Alpha() / 255.0f;
365 }
366 
GetRGBA(double & r,double & g,double & b,double & a) const367 void Color::GetRGBA(double& r, double& g, double& b, double& a) const {
368   r = Red() / 255.0;
369   g = Green() / 255.0;
370   b = Blue() / 255.0;
371   a = Alpha() / 255.0;
372 }
373 
GetHSL(double & hue,double & saturation,double & lightness) const374 void Color::GetHSL(double& hue, double& saturation, double& lightness) const {
375   // http://en.wikipedia.org/wiki/HSL_color_space. This is a direct copy of
376   // the algorithm therein, although it's 360^o based and we end up wanting
377   // [0...1) based. It's clearer if we stick to 360^o until the end.
378   double r = static_cast<double>(Red()) / 255.0;
379   double g = static_cast<double>(Green()) / 255.0;
380   double b = static_cast<double>(Blue()) / 255.0;
381   double max = std::max(std::max(r, g), b);
382   double min = std::min(std::min(r, g), b);
383 
384   if (max == min)
385     hue = 0.0;
386   else if (max == r)
387     hue = (60.0 * ((g - b) / (max - min))) + 360.0;
388   else if (max == g)
389     hue = (60.0 * ((b - r) / (max - min))) + 120.0;
390   else
391     hue = (60.0 * ((r - g) / (max - min))) + 240.0;
392 
393   if (hue >= 360.0)
394     hue -= 360.0;
395 
396   // makeRGBAFromHSLA assumes that hue is in [0...1).
397   hue /= 360.0;
398 
399   lightness = 0.5 * (max + min);
400   if (max == min)
401     saturation = 0.0;
402   else if (lightness <= 0.5)
403     saturation = ((max - min) / (max + min));
404   else
405     saturation = ((max - min) / (2.0 - (max + min)));
406 }
407 
ColorFromPremultipliedARGB(RGBA32 pixel_color)408 Color ColorFromPremultipliedARGB(RGBA32 pixel_color) {
409   int alpha = AlphaChannel(pixel_color);
410   if (alpha && alpha < 255) {
411     return Color::CreateUnchecked(RedChannel(pixel_color) * 255 / alpha,
412                                   GreenChannel(pixel_color) * 255 / alpha,
413                                   BlueChannel(pixel_color) * 255 / alpha,
414                                   alpha);
415   } else
416     return Color(pixel_color);
417 }
418 
PremultipliedARGBFromColor(const Color & color)419 RGBA32 PremultipliedARGBFromColor(const Color& color) {
420   unsigned pixel_color;
421 
422   unsigned alpha = color.Alpha();
423   if (alpha < 255) {
424     pixel_color =
425         Color::CreateUnchecked((color.Red() * alpha + 254) / 255,
426                                (color.Green() * alpha + 254) / 255,
427                                (color.Blue() * alpha + 254) / 255, alpha)
428             .Rgb();
429   } else
430     pixel_color = color.Rgb();
431 
432   return pixel_color;
433 }
434 
435 }  // namespace blink
436