Home | History | Annotate | Download | only in graphics
      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 "config.h"
     27 #include "Color.h"
     28 
     29 #include "PlatformString.h"
     30 #include <math.h>
     31 #include <wtf/Assertions.h>
     32 #include <wtf/MathExtras.h>
     33 
     34 #include "ColorData.c"
     35 
     36 using namespace std;
     37 using namespace WTF;
     38 
     39 namespace WebCore {
     40 
     41 #if !COMPILER(MSVC)
     42 const RGBA32 Color::black;
     43 const RGBA32 Color::white;
     44 const RGBA32 Color::darkGray;
     45 const RGBA32 Color::gray;
     46 const RGBA32 Color::lightGray;
     47 const RGBA32 Color::transparent;
     48 #endif
     49 
     50 static const RGBA32 lightenedBlack = 0xFF545454;
     51 static const RGBA32 darkenedWhite = 0xFFABABAB;
     52 
     53 RGBA32 makeRGB(int r, int g, int b)
     54 {
     55     return 0xFF000000 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
     56 }
     57 
     58 RGBA32 makeRGBA(int r, int g, int b, int a)
     59 {
     60     return max(0, min(a, 255)) << 24 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
     61 }
     62 
     63 static int colorFloatToRGBAByte(float f)
     64 {
     65     // We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
     66     return max(0, min(static_cast<int>(lroundf(255.0f * f)), 255));
     67 }
     68 
     69 RGBA32 makeRGBA32FromFloats(float r, float g, float b, float a)
     70 {
     71     return colorFloatToRGBAByte(a) << 24 | colorFloatToRGBAByte(r) << 16 | colorFloatToRGBAByte(g) << 8 | colorFloatToRGBAByte(b);
     72 }
     73 
     74 RGBA32 colorWithOverrideAlpha(RGBA32 color, float overrideAlpha)
     75 {
     76     RGBA32 rgbOnly = color & 0x00FFFFFF;
     77     RGBA32 rgba = rgbOnly | colorFloatToRGBAByte(overrideAlpha) << 24;
     78     return rgba;
     79 }
     80 
     81 static double calcHue(double temp1, double temp2, double hueVal)
     82 {
     83     if (hueVal < 0.0)
     84         hueVal++;
     85     else if (hueVal > 1.0)
     86         hueVal--;
     87     if (hueVal * 6.0 < 1.0)
     88         return temp1 + (temp2 - temp1) * hueVal * 6.0;
     89     if (hueVal * 2.0 < 1.0)
     90         return temp2;
     91     if (hueVal * 3.0 < 2.0)
     92         return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hueVal) * 6.0;
     93     return temp1;
     94 }
     95 
     96 // Explanation of this algorithm can be found in the CSS3 Color Module
     97 // specification at http://www.w3.org/TR/css3-color/#hsl-color with further
     98 // explanation available at http://en.wikipedia.org/wiki/HSL_color_space
     99 
    100 // all values are in the range of 0 to 1.0
    101 RGBA32 makeRGBAFromHSLA(double hue, double saturation, double lightness, double alpha)
    102 {
    103     const double scaleFactor = nextafter(256.0, 0.0);
    104 
    105     if (!saturation) {
    106         int greyValue = static_cast<int>(lightness * scaleFactor);
    107         return makeRGBA(greyValue, greyValue, greyValue, static_cast<int>(alpha * scaleFactor));
    108     }
    109 
    110     double temp2 = lightness < 0.5 ? lightness * (1.0 + saturation) : lightness + saturation - lightness * saturation;
    111     double temp1 = 2.0 * lightness - temp2;
    112 
    113     return makeRGBA(static_cast<int>(calcHue(temp1, temp2, hue + 1.0 / 3.0) * scaleFactor),
    114                     static_cast<int>(calcHue(temp1, temp2, hue) * scaleFactor),
    115                     static_cast<int>(calcHue(temp1, temp2, hue - 1.0 / 3.0) * scaleFactor),
    116                     static_cast<int>(alpha * scaleFactor));
    117 }
    118 
    119 RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a)
    120 {
    121     double colors = 1 - k;
    122     int r = static_cast<int>(nextafter(256, 0) * (colors * (1 - c)));
    123     int g = static_cast<int>(nextafter(256, 0) * (colors * (1 - m)));
    124     int b = static_cast<int>(nextafter(256, 0) * (colors * (1 - y)));
    125     return makeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a));
    126 }
    127 
    128 // originally moved here from the CSS parser
    129 bool Color::parseHexColor(const String& name, RGBA32& rgb)
    130 {
    131     unsigned length = name.length();
    132     if (length != 3 && length != 6)
    133         return false;
    134     unsigned value = 0;
    135     for (unsigned i = 0; i < length; ++i) {
    136         if (!isASCIIHexDigit(name[i]))
    137             return false;
    138         value <<= 4;
    139         value |= toASCIIHexValue(name[i]);
    140     }
    141     if (length == 6) {
    142         rgb = 0xFF000000 | value;
    143         return true;
    144     }
    145     // #abc converts to #aabbcc
    146     rgb = 0xFF000000
    147         | (value & 0xF00) << 12 | (value & 0xF00) << 8
    148         | (value & 0xF0) << 8 | (value & 0xF0) << 4
    149         | (value & 0xF) << 4 | (value & 0xF);
    150     return true;
    151 }
    152 
    153 int differenceSquared(const Color& c1, const Color& c2)
    154 {
    155     int dR = c1.red() - c2.red();
    156     int dG = c1.green() - c2.green();
    157     int dB = c1.blue() - c2.blue();
    158     return dR * dR + dG * dG + dB * dB;
    159 }
    160 
    161 Color::Color(const String& name)
    162 {
    163     if (name.startsWith("#"))
    164         m_valid = parseHexColor(name.substring(1), m_color);
    165     else
    166         setNamedColor(name);
    167 }
    168 
    169 Color::Color(const char* name)
    170 {
    171     if (name[0] == '#')
    172         m_valid = parseHexColor(&name[1], m_color);
    173     else {
    174         const NamedColor* foundColor = findColor(name, strlen(name));
    175         m_color = foundColor ? foundColor->RGBValue : 0;
    176         m_color |= 0xFF000000;
    177         m_valid = foundColor;
    178     }
    179 }
    180 
    181 String Color::name() const
    182 {
    183     if (alpha() < 0xFF)
    184         return String::format("#%02X%02X%02X%02X", red(), green(), blue(), alpha());
    185     return String::format("#%02X%02X%02X", red(), green(), blue());
    186 }
    187 
    188 static inline const NamedColor* findNamedColor(const String& name)
    189 {
    190     char buffer[64]; // easily big enough for the longest color name
    191     unsigned length = name.length();
    192     if (length > sizeof(buffer) - 1)
    193         return 0;
    194     for (unsigned i = 0; i < length; ++i) {
    195         UChar c = name[i];
    196         if (!c || c > 0x7F)
    197             return 0;
    198         buffer[i] = toASCIILower(static_cast<char>(c));
    199     }
    200     buffer[length] = '\0';
    201     return findColor(buffer, length);
    202 }
    203 
    204 void Color::setNamedColor(const String& name)
    205 {
    206     const NamedColor* foundColor = findNamedColor(name);
    207     m_color = foundColor ? foundColor->RGBValue : 0;
    208     m_color |= 0xFF000000;
    209     m_valid = foundColor;
    210 }
    211 
    212 Color Color::light() const
    213 {
    214     // Hardcode this common case for speed.
    215     if (m_color == black)
    216         return lightenedBlack;
    217 
    218     const float scaleFactor = nextafterf(256.0f, 0.0f);
    219 
    220     float r, g, b, a;
    221     getRGBA(r, g, b, a);
    222 
    223     float v = max(r, max(g, b));
    224 
    225     if (v == 0.0f)
    226         // Lightened black with alpha.
    227         return Color(0x54, 0x54, 0x54, alpha());
    228 
    229     float multiplier = min(1.0f, v + 0.33f) / v;
    230 
    231     return Color(static_cast<int>(multiplier * r * scaleFactor),
    232                  static_cast<int>(multiplier * g * scaleFactor),
    233                  static_cast<int>(multiplier * b * scaleFactor),
    234                  alpha());
    235 }
    236 
    237 Color Color::dark() const
    238 {
    239     // Hardcode this common case for speed.
    240     if (m_color == white)
    241         return darkenedWhite;
    242 
    243     const float scaleFactor = nextafterf(256.0f, 0.0f);
    244 
    245     float r, g, b, a;
    246     getRGBA(r, g, b, a);
    247 
    248     float v = max(r, max(g, b));
    249     float multiplier = max(0.0f, (v - 0.33f) / v);
    250 
    251     return Color(static_cast<int>(multiplier * r * scaleFactor),
    252                  static_cast<int>(multiplier * g * scaleFactor),
    253                  static_cast<int>(multiplier * b * scaleFactor),
    254                  alpha());
    255 }
    256 
    257 static int blendComponent(int c, int a)
    258 {
    259     // We use white.
    260     float alpha = a / 255.0f;
    261     int whiteBlend = 255 - a;
    262     c -= whiteBlend;
    263     return static_cast<int>(c / alpha);
    264 }
    265 
    266 const int cStartAlpha = 153; // 60%
    267 const int cEndAlpha = 204; // 80%;
    268 const int cAlphaIncrement = 17; // Increments in between.
    269 
    270 Color Color::blend(const Color& source) const
    271 {
    272     if (!alpha() || !source.hasAlpha())
    273         return source;
    274 
    275     if (!source.alpha())
    276         return *this;
    277 
    278     int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
    279     int a = d / 255;
    280     int r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d;
    281     int g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d;
    282     int b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d;
    283     return Color(r, g, b, a);
    284 }
    285 
    286 Color Color::blendWithWhite() const
    287 {
    288     // If the color contains alpha already, we leave it alone.
    289     if (hasAlpha())
    290         return *this;
    291 
    292     Color newColor;
    293     for (int alpha = cStartAlpha; alpha <= cEndAlpha; alpha += cAlphaIncrement) {
    294         // We have a solid color.  Convert to an equivalent color that looks the same when blended with white
    295         // at the current alpha.  Try using less transparency if the numbers end up being negative.
    296         int r = blendComponent(red(), alpha);
    297         int g = blendComponent(green(), alpha);
    298         int b = blendComponent(blue(), alpha);
    299 
    300         newColor = Color(r, g, b, alpha);
    301 
    302         if (r >= 0 && g >= 0 && b >= 0)
    303             break;
    304     }
    305     return newColor;
    306 }
    307 
    308 void Color::getRGBA(float& r, float& g, float& b, float& a) const
    309 {
    310     r = red() / 255.0f;
    311     g = green() / 255.0f;
    312     b = blue() / 255.0f;
    313     a = alpha() / 255.0f;
    314 }
    315 
    316 void Color::getRGBA(double& r, double& g, double& b, double& a) const
    317 {
    318     r = red() / 255.0;
    319     g = green() / 255.0;
    320     b = blue() / 255.0;
    321     a = alpha() / 255.0;
    322 }
    323 
    324 void Color::getHSL(double& hue, double& saturation, double& lightness) const
    325 {
    326     // http://en.wikipedia.org/wiki/HSL_color_space. This is a direct copy of
    327     // the algorithm therein, although it's 360^o based and we end up wanting
    328     // [0...1) based. It's clearer if we stick to 360^o until the end.
    329     double r = static_cast<double>(red()) / 255.0;
    330     double g = static_cast<double>(green()) / 255.0;
    331     double b = static_cast<double>(blue()) / 255.0;
    332     double max = std::max(std::max(r, g), b);
    333     double min = std::min(std::min(r, g), b);
    334 
    335     if (max == min)
    336         hue = 0.0;
    337     else if (max == r)
    338         hue = (60.0 * ((g - b) / (max - min))) + 360.0;
    339     else if (max == g)
    340         hue = (60.0 * ((b - r) / (max - min))) + 120.0;
    341     else
    342         hue = (60.0 * ((r - g) / (max - min))) + 240.0;
    343 
    344     if (hue >= 360.0)
    345         hue -= 360.0;
    346 
    347     // makeRGBAFromHSLA assumes that hue is in [0...1).
    348     hue /= 360.0;
    349 
    350     lightness = 0.5 * (max + min);
    351     if (max == min)
    352         saturation = 0.0;
    353     else if (lightness <= 0.5)
    354         saturation = ((max - min) / (max + min));
    355     else
    356         saturation = ((max - min) / (2.0 - (max + min)));
    357 }
    358 
    359 Color colorFromPremultipliedARGB(unsigned pixelColor)
    360 {
    361     RGBA32 rgba;
    362 
    363     if (unsigned alpha = (pixelColor & 0xFF000000) >> 24) {
    364         rgba = makeRGBA(((pixelColor & 0x00FF0000) >> 16) * 255 / alpha,
    365                         ((pixelColor & 0x0000FF00) >> 8) * 255 / alpha,
    366                          (pixelColor & 0x000000FF) * 255 / alpha,
    367                           alpha);
    368     } else
    369         rgba = pixelColor;
    370 
    371     return Color(rgba);
    372 }
    373 
    374 unsigned premultipliedARGBFromColor(const Color& color)
    375 {
    376     unsigned pixelColor;
    377 
    378     if (unsigned alpha = color.alpha()) {
    379         pixelColor = alpha << 24 |
    380              ((color.red() * alpha  + 254) / 255) << 16 |
    381              ((color.green() * alpha  + 254) / 255) << 8 |
    382              ((color.blue() * alpha  + 254) / 255);
    383     } else
    384          pixelColor = color.rgb();
    385 
    386     return pixelColor;
    387 }
    388 
    389 } // namespace WebCore
    390