Back to index

lightning-sunbird  0.9+nobinonly
nsCSSColorUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsCSSColorUtils.h"
00039 #include <math.h>
00040 
00041 // Weird color computing code stolen from winfe which was stolen
00042 // from the xfe which was written originally by Eric Bina. So there.
00043 
00044 #define RED_LUMINOSITY        299
00045 #define GREEN_LUMINOSITY      587
00046 #define BLUE_LUMINOSITY       114
00047 #define INTENSITY_FACTOR      25
00048 #define LIGHT_FACTOR          0
00049 #define LUMINOSITY_FACTOR     75
00050 
00051 #define MAX_COLOR             255
00052 #define COLOR_DARK_THRESHOLD  51
00053 #define COLOR_LIGHT_THRESHOLD 204
00054 
00055 #define COLOR_LITE_BS_FACTOR 45
00056 #define COLOR_LITE_TS_FACTOR 70
00057 
00058 #define COLOR_DARK_BS_FACTOR 30
00059 #define COLOR_DARK_TS_FACTOR 50
00060 
00061 #define LIGHT_GRAY NS_RGB(192, 192, 192)
00062 #define DARK_GRAY  NS_RGB(96, 96, 96)
00063 #define WHITE      NS_RGB(255, 255, 255)
00064 #define BLACK      NS_RGB(0, 0, 0)
00065 
00066 #define MAX_BRIGHTNESS  254
00067 #define MAX_DARKNESS     0
00068  
00069 void NS_Get3DColors(nscolor aResult[2], nscolor aBackgroundColor)
00070 {
00071   int rb = NS_GET_R(aBackgroundColor);
00072   int gb = NS_GET_G(aBackgroundColor);
00073   int bb = NS_GET_B(aBackgroundColor);
00074   
00075   int brightness = NS_GetBrightness(rb,gb,bb);
00076 
00077   int f0, f1;
00078   if (brightness < COLOR_DARK_THRESHOLD) {
00079     f0 = COLOR_DARK_BS_FACTOR;
00080     f1 = COLOR_DARK_TS_FACTOR;
00081   } else if (brightness > COLOR_LIGHT_THRESHOLD) {
00082     f0 = COLOR_LITE_BS_FACTOR;
00083     f1 = COLOR_LITE_TS_FACTOR;
00084   } else {
00085     f0 = COLOR_DARK_BS_FACTOR +
00086       (brightness *
00087        (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
00088     f1 = COLOR_DARK_TS_FACTOR +
00089       (brightness *
00090        (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
00091   }
00092 
00093   int r = rb - (f0 * rb / 100);
00094   int g = gb - (f0 * gb / 100);
00095   int b = bb - (f0 * bb / 100);
00096   aResult[0] = NS_RGB(r, g, b);
00097   if ((r == rb) && (g == gb) && (b == bb)) {
00098     aResult[0] = (aBackgroundColor == BLACK) ? DARK_GRAY : BLACK;
00099   }
00100 
00101   r = rb + (f1 * (MAX_COLOR - rb) / 100);
00102   if (r > 255) r = 255;
00103   g = gb + (f1 * (MAX_COLOR - gb) / 100);
00104   if (g > 255) g = 255;
00105   b = bb + (f1 * (MAX_COLOR - bb) / 100);
00106   if (b > 255) b = 255;
00107   aResult[1] = NS_RGB(r, g, b);
00108   if ((r == rb) && (g == gb) && (b == bb)) {
00109     aResult[1] = (aBackgroundColor == WHITE) ? LIGHT_GRAY : WHITE;
00110   }
00111 }
00112 
00113 void NS_GetSpecial3DColors(nscolor aResult[2],
00114                                                                                 nscolor aBackgroundColor,
00115                                                                                 nscolor aBorderColor)
00116 {
00117 
00118   PRUint8 f0, f1;
00119   PRUint8 r, g, b;
00120 
00121   PRUint8 rb = NS_GET_R(aBorderColor);
00122   PRUint8 gb = NS_GET_G(aBorderColor);
00123   PRUint8 bb = NS_GET_B(aBorderColor);
00124 
00125   // This needs to be optimized.
00126   // Calculating background brightness again and again is 
00127   // a waste of time!!!. Just calculate it only once.
00128   // .....somehow!!!
00129 
00130   PRUint8 red = NS_GET_R(aBackgroundColor);
00131   PRUint8 green = NS_GET_G(aBackgroundColor);
00132   PRUint8 blue = NS_GET_B(aBackgroundColor);
00133   
00134   PRUint8 elementBrightness = NS_GetBrightness(rb,gb,bb);
00135   PRUint8 backgroundBrightness = NS_GetBrightness(red, green, blue);
00136 
00137 
00138   if (backgroundBrightness < COLOR_DARK_THRESHOLD) {
00139     f0 = COLOR_DARK_BS_FACTOR;
00140     f1 = COLOR_DARK_TS_FACTOR;
00141        if(elementBrightness == MAX_DARKNESS)
00142        {
00143        rb = NS_GET_R(DARK_GRAY);
00144        gb = NS_GET_G(DARK_GRAY);
00145        bb = NS_GET_B(DARK_GRAY);
00146        }
00147   }else if (backgroundBrightness > COLOR_LIGHT_THRESHOLD) {
00148     f0 = COLOR_LITE_BS_FACTOR;
00149     f1 = COLOR_LITE_TS_FACTOR;
00150        if(elementBrightness == MAX_BRIGHTNESS)
00151        {
00152        rb = NS_GET_R(LIGHT_GRAY);
00153        gb = NS_GET_G(LIGHT_GRAY);
00154        bb = NS_GET_B(LIGHT_GRAY);
00155        }
00156   }else {
00157     f0 = COLOR_DARK_BS_FACTOR +
00158       (backgroundBrightness *
00159        (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
00160     f1 = COLOR_DARK_TS_FACTOR +
00161       (backgroundBrightness *
00162        (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
00163   }
00164   
00165   
00166   r = rb - (f0 * rb / 100);
00167   g = gb - (f0 * gb / 100);
00168   b = bb - (f0 * bb / 100);
00169   aResult[0] = NS_RGB(r, g, b);
00170 
00171   r = rb + (f1 * (MAX_COLOR - rb) / 100);
00172   g = gb + (f1 * (MAX_COLOR - gb) / 100);
00173   b = bb + (f1 * (MAX_COLOR - bb) / 100);
00174   aResult[1] = NS_RGB(r, g, b);
00175 }
00176 
00177 int NS_GetBrightness(PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue)
00178 {
00179 
00180   PRUint8 intensity = (aRed + aGreen + aBlue) / 3;
00181 
00182   PRUint8 luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000;
00183  
00184   return ((intensity * INTENSITY_FACTOR) +
00185           (luminosity * LUMINOSITY_FACTOR)) / 100;
00186 }
00187 
00188 PRInt32 NS_GetLuminosity(nscolor aColor)
00189 {
00190   return (NS_GET_R(aColor) * RED_LUMINOSITY +
00191           NS_GET_G(aColor) * GREEN_LUMINOSITY +
00192           NS_GET_B(aColor) * BLUE_LUMINOSITY);
00193 }
00194 
00195 // Function to convert RGB color space into the HSV colorspace
00196 // Hue is the primary color defined from 0 to 359 degrees
00197 // Saturation is defined from 0 to 255.  The higher the number.. the deeper the color
00198 // Value is the brightness of the color. 0 is black, 255 is white.  
00199 void
00200 NS_RGB2HSV(nscolor aColor,PRUint16 &aHue,PRUint16 &aSat,PRUint16 &aValue)
00201 {
00202 PRUint8  r,g,b;
00203 PRInt16  delta,min,max,r1,b1,g1;
00204 float    hue;
00205 
00206   r = NS_GET_R(aColor);
00207   g = NS_GET_G(aColor);
00208   b = NS_GET_B(aColor);
00209 
00210   if (r>g) {
00211     max = r;
00212     min = g;
00213   } else {
00214     max = g;
00215     min = r;
00216   }
00217 
00218   if (b>max) {
00219     max = b;
00220   }
00221   if (b<min) {
00222     min = b;
00223   }
00224 
00225   // value or brightness will always be the max of all the colors(RGB)
00226   aValue = max;   
00227   delta = max-min;
00228   aSat = (max!=0)?((delta*255)/max):0;
00229   r1 = r;
00230   b1 = b;
00231   g1 = g;
00232 
00233   if (aSat==0) {
00234     hue = 1000;
00235   } else {
00236     if(r==max){
00237       hue=(float)(g1-b1)/(float)delta;
00238     } else if (g1==max) {
00239       hue= 2.0f+(float)(b1-r1)/(float)delta;
00240     } else { 
00241       hue = 4.0f+(float)(r1-g1)/(float)delta;
00242     }
00243   }
00244 
00245   if(hue<999) {
00246     hue*=60;
00247     if(hue<0){
00248       hue+=360;
00249     }
00250   } else {
00251     hue=0;
00252   }
00253 
00254   aHue = (PRUint16)hue;
00255 }
00256 
00257 // Function to convert HSV color space into the RGB colorspace
00258 // Hue is the primary color defined from 0 to 359 degrees
00259 // Saturation is defined from 0 to 255.  The higher the number.. the deeper the color
00260 // Value is the brightness of the color. 0 is black, 255 is white.  
00261 void
00262 NS_HSV2RGB(nscolor &aColor,PRUint16 aHue,PRUint16 aSat,PRUint16 aValue)
00263 {
00264 PRUint16  r=0,g=0,b=0;
00265 PRUint16  i,p,q,t;
00266 double    h,f,percent;
00267 
00268   if ( aSat == 0 ){
00269     // achromatic color, no hue is defined
00270     r = aValue;
00271     g = aValue;
00272     b = aValue;
00273   } else {
00274     // hue in in degrees around the color wheel defined from
00275     // 0 to 360 degrees.  
00276     if (aHue >= 360) {
00277       aHue = 0;
00278     }
00279 
00280     // we break the color wheel into 6 areas.. these
00281     // areas define how the saturation and value define the color.
00282     // reds behave differently than the blues
00283     h = (double)aHue / 60.0;
00284     i = (PRUint16) floor(h);
00285     f = h-(double)i;
00286     percent = ((double)aValue/255.0);   // this needs to be a value from 0 to 1, so a percentage
00287                                         // can be calculated of the saturation.
00288     p = (PRUint16)(percent*(255-aSat));
00289     q = (PRUint16)(percent*(255-(aSat*f)));
00290     t = (PRUint16)(percent*(255-(aSat*(1.0-f))));
00291 
00292     // i is guarenteed to never be larger than 5.
00293     switch(i){
00294       case 0: r = aValue; g = t; b = p;break;
00295       case 1: r = q; g = aValue; b = p;break;
00296       case 2: r = p; g = aValue; b = t;break;
00297       case 3: r = p; g = q; b = aValue;break;
00298       case 4: r = t; g = p; b = aValue;break;
00299       case 5: r = aValue; g = p; b = q;break;
00300     }
00301   }
00302   aColor = NS_RGB(r,g,b);
00303 }