• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

Color.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  * 1. Redistributions of source code must retain the above copyright
00008  *    notice, this list of conditions and the following disclaimer.
00009  * 2. Redistributions in binary form must reproduce the above copyright
00010  *    notice, this list of conditions and the following disclaimer in the
00011  *    documentation and/or other materials provided with the distribution.
00012  *
00013  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
00014  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00016  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
00017  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00018  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00019  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00020  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00021  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00023  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00024  */
00025 
00026 #include "config.h"
00027 #include "wtf/Platform.h"
00028 #include "Color.h"
00029 
00030 #include "PlatformString.h"
00031 #include <math.h>
00032 #include <wtf/Assertions.h>
00033 #include <wtf/MathExtras.h>
00034 
00035 #ifdef Q_CC_MSVC
00036 #include <float.h>
00037 #define nextafter(x,y) ((long double)_nextafter((double)(x), (double)(y)))
00038 #define nextafterf(x,y) _nextafter(x,y)
00039 #endif
00040 
00041 //#include "ColorData.c"
00042 
00043 using namespace std;
00044 //using namespace WTF;
00045 
00046 #define min(a,b) (((a)<(b)?(a):(b)))
00047 #define max(a,b) (((a)>(b)?(a):(b)))
00048 
00049 namespace WebCore {
00050 
00051 const RGBA32 lightenedBlack = 0xFF545454;
00052 const RGBA32 darkenedWhite = 0xFFABABAB;
00053 
00054 RGBA32 makeRGB(int r, int g, int b)
00055 {
00056     return 0xFF000000 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
00057 }
00058 
00059 RGBA32 makeRGBA(int r, int g, int b, int a)
00060 {
00061     return max(0, min(a, 255)) << 24 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
00062 }
00063 
00064 static double calcHue(double temp1, double temp2, double hueVal)
00065 {
00066     if (hueVal < 0.0)
00067         hueVal++;
00068     else if (hueVal > 1.0)
00069         hueVal--;
00070     if (hueVal * 6.0 < 1.0)
00071         return temp1 + (temp2 - temp1) * hueVal * 6.0;
00072     if (hueVal * 2.0 < 1.0)
00073         return temp2;
00074     if (hueVal * 3.0 < 2.0)
00075         return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hueVal) * 6.0;
00076     return temp1;
00077 }
00078 
00079 // Explanation of this algorithm can be found in the CSS3 Color Module
00080 // specification at http://www.w3.org/TR/css3-color/#hsl-color with further
00081 // explanation available at http://en.wikipedia.org/wiki/HSL_color_space 
00082 
00083 // all values are in the range of 0 to 1.0
00084 RGBA32 makeRGBAFromHSLA(double hue, double saturation, double lightness, double alpha)
00085 {
00086     const double scaleFactor = nextafter(256.0, 0.0);
00087 
00088     if (!saturation) {
00089         int greyValue = static_cast<int>(lightness * scaleFactor);
00090         return makeRGBA(greyValue, greyValue, greyValue, static_cast<int>(alpha * scaleFactor));
00091     }
00092 
00093     double temp2 = lightness < 0.5 ? lightness * (1.0 + saturation) : lightness + saturation - lightness * saturation;
00094     double temp1 = 2.0 * lightness - temp2;
00095     
00096     return makeRGBA(static_cast<int>(calcHue(temp1, temp2, hue + 1.0 / 3.0) * scaleFactor), 
00097                     static_cast<int>(calcHue(temp1, temp2, hue) * scaleFactor),
00098                     static_cast<int>(calcHue(temp1, temp2, hue - 1.0 / 3.0) * scaleFactor),
00099                     static_cast<int>(alpha * scaleFactor));
00100 }
00101 
00102 // originally moved here from the CSS parser
00103 bool Color::parseHexColor(const String& name, RGBA32& rgb)
00104 {
00105     unsigned length = name.length();
00106     if (length != 3 && length != 6)
00107         return false;
00108     unsigned value = 0;
00109     /*for (unsigned i = 0; i < length; ++i) {
00110         if (!isASCIIHexDigit(name[i]))
00111             return false;
00112         value <<= 4;
00113         value |= toASCIIHexValue(name[i]);
00114     }
00115     if (length == 6) {
00116         rgb = 0xFF000000 | value;
00117         return true;
00118     }*/
00119     // #abc converts to #aabbcc
00120     rgb = 0xFF000000
00121         | (value & 0xF00) << 12 | (value & 0xF00) << 8
00122         | (value & 0xF0) << 8 | (value & 0xF0) << 4
00123         | (value & 0xF) << 4 | (value & 0xF);
00124     return true;
00125 }
00126 
00127 int differenceSquared(const Color& c1, const Color& c2)
00128 {
00129     int dR = c1.red() - c2.red();
00130     int dG = c1.green() - c2.green();
00131     int dB = c1.blue() - c2.blue();
00132     return dR * dR + dG * dG + dB * dB;
00133 }
00134 
00135 Color::Color(const String& name)
00136 {
00137     /*if (name.startsWith("#"))
00138         m_valid = parseHexColor(name.substring(1), m_color);
00139     else*/
00140         setNamedColor(name);
00141 }
00142 
00143 Color::Color(const char* name)
00144 {
00145     /*if (name[0] == '#')
00146         m_valid = parseHexColor(&name[1], m_color);
00147     else {
00148         const NamedColor* foundColor = findColor(name, strlen(name));
00149         m_color = foundColor ? foundColor->RGBValue : 0;
00150         m_color |= 0xFF000000;
00151         m_valid = foundColor;
00152     }*/
00153 }
00154 
00155 String Color::name() const
00156 {
00157     /*if (alpha() < 0xFF)
00158         return String::format("#%02X%02X%02X%02X", red(), green(), blue(), alpha());
00159     return String::format("#%02X%02X%02X", red(), green(), blue());*/
00160     return "";
00161 }
00162 
00163 /*static inline const NamedColor* findNamedColor(const String& name)
00164 {
00165     char buffer[64]; // easily big enough for the longest color name
00166     unsigned length = name.length();
00167     if (length > sizeof(buffer) - 1)
00168         return 0;
00169     for (unsigned i = 0; i < length; ++i) {
00170         UChar c = name[i];
00171         if (!c || c > 0x7F)
00172             return 0;
00173         buffer[i] = toASCIILower(static_cast<char>(c));
00174     }
00175     buffer[length] = '\0';
00176     return findColor(buffer, length);
00177 }*/
00178 
00179 void Color::setNamedColor(const String& name)
00180 {
00181     /*const NamedColor* foundColor = findNamedColor(name);
00182     m_color = foundColor ? foundColor->RGBValue : 0;
00183     m_color |= 0xFF000000;
00184     m_valid = foundColor;*/
00185 }
00186 
00187 Color Color::light() const
00188 {
00189     // Hardcode this common case for speed.
00190     if (m_color == black)
00191         return lightenedBlack;
00192     
00193     const float scaleFactor = nextafterf(256.0f, 0.0f);
00194 
00195     float r, g, b, a;
00196     getRGBA(r, g, b, a);
00197 
00198     float v = max(r, max(g, b));
00199 
00200     if (v == 0.0f)
00201         // Lightened black with alpha.
00202         return Color(0x54, 0x54, 0x54, alpha());
00203 
00204     float multiplier = min(1.0f, v + 0.33f) / v;
00205 
00206     return Color(static_cast<int>(multiplier * r * scaleFactor),
00207                  static_cast<int>(multiplier * g * scaleFactor),
00208                  static_cast<int>(multiplier * b * scaleFactor),
00209                  alpha());
00210 }
00211 
00212 Color Color::dark() const
00213 {
00214     // Hardcode this common case for speed.
00215     if (m_color == white)
00216         return darkenedWhite;
00217     
00218     const float scaleFactor = nextafterf(256.0f, 0.0f);
00219 
00220     float r, g, b, a;
00221     getRGBA(r, g, b, a);
00222 
00223     float v = max(r, max(g, b));
00224     float multiplier = max(0.0f, (v - 0.33f) / v);
00225 
00226     return Color(static_cast<int>(multiplier * r * scaleFactor),
00227                  static_cast<int>(multiplier * g * scaleFactor),
00228                  static_cast<int>(multiplier * b * scaleFactor),
00229                  alpha());
00230 }
00231 
00232 static int blendComponent(int c, int a)
00233 {
00234     // We use white.
00235     float alpha = a / 255.0f;
00236     int whiteBlend = 255 - a;
00237     c -= whiteBlend;
00238     return static_cast<int>(c / alpha);
00239 }
00240 
00241 const int cStartAlpha = 153; // 60%
00242 const int cEndAlpha = 204; // 80%;
00243 const int cAlphaIncrement = 17; // Increments in between.
00244 
00245 Color Color::blend(const Color& source) const
00246 {
00247     if (!alpha() || !source.hasAlpha())
00248         return source;
00249 
00250     if (!source.alpha())
00251         return *this;
00252 
00253     int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
00254     int a = d / 255;
00255     int r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d;
00256     int g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d;
00257     int b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d;
00258     return Color(r, g, b, a);
00259 }
00260 
00261 Color Color::blendWithWhite() const
00262 {
00263     // If the color contains alpha already, we leave it alone.
00264     if (hasAlpha())
00265         return *this;
00266 
00267     Color newColor;
00268     for (int alpha = cStartAlpha; alpha <= cEndAlpha; alpha += cAlphaIncrement) {
00269         // We have a solid color.  Convert to an equivalent color that looks the same when blended with white
00270         // at the current alpha.  Try using less transparency if the numbers end up being negative.
00271         int r = blendComponent(red(), alpha);
00272         int g = blendComponent(green(), alpha);
00273         int b = blendComponent(blue(), alpha);
00274         
00275         newColor = Color(r, g, b, alpha);
00276 
00277         if (r >= 0 && g >= 0 && b >= 0)
00278             break;
00279     }
00280     return newColor;
00281 }
00282 
00283 void Color::getRGBA(float& r, float& g, float& b, float& a) const
00284 {
00285     r = red() / 255.0f;
00286     g = green() / 255.0f;
00287     b = blue() / 255.0f;
00288     a = alpha() / 255.0f;
00289 }
00290 
00291 void Color::getRGBA(double& r, double& g, double& b, double& a) const
00292 {
00293     r = red() / 255.0;
00294     g = green() / 255.0;
00295     b = blue() / 255.0;
00296     a = alpha() / 255.0;
00297 }
00298 
00299 } // namespace WebCore

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal