1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* functions that manipulate colors */
39 :
40 : #include "nsCSSColorUtils.h"
41 : #include "nsDebug.h"
42 : #include <math.h>
43 :
44 : // Weird color computing code stolen from winfe which was stolen
45 : // from the xfe which was written originally by Eric Bina. So there.
46 :
47 : #define RED_LUMINOSITY 299
48 : #define GREEN_LUMINOSITY 587
49 : #define BLUE_LUMINOSITY 114
50 : #define INTENSITY_FACTOR 25
51 : #define LIGHT_FACTOR 0
52 : #define LUMINOSITY_FACTOR 75
53 :
54 : #define MAX_COLOR 255
55 : #define COLOR_DARK_THRESHOLD 51
56 : #define COLOR_LIGHT_THRESHOLD 204
57 :
58 : #define COLOR_LITE_BS_FACTOR 45
59 : #define COLOR_LITE_TS_FACTOR 70
60 :
61 : #define COLOR_DARK_BS_FACTOR 30
62 : #define COLOR_DARK_TS_FACTOR 50
63 :
64 : #define LIGHT_GRAY NS_RGB(192, 192, 192)
65 : #define DARK_GRAY NS_RGB(96, 96, 96)
66 : #define WHITE NS_RGB(255, 255, 255)
67 : #define BLACK NS_RGB(0, 0, 0)
68 :
69 : #define MAX_BRIGHTNESS 254
70 : #define MAX_DARKNESS 0
71 :
72 0 : void NS_GetSpecial3DColors(nscolor aResult[2],
73 : nscolor aBackgroundColor,
74 : nscolor aBorderColor)
75 : {
76 :
77 : PRUint8 f0, f1;
78 : PRUint8 r, g, b;
79 :
80 0 : PRUint8 rb = NS_GET_R(aBorderColor);
81 0 : PRUint8 gb = NS_GET_G(aBorderColor);
82 0 : PRUint8 bb = NS_GET_B(aBorderColor);
83 :
84 0 : PRUint8 a = NS_GET_A(aBorderColor);
85 :
86 : // This needs to be optimized.
87 : // Calculating background brightness again and again is
88 : // a waste of time!!!. Just calculate it only once.
89 : // .....somehow!!!
90 :
91 0 : PRUint8 red = NS_GET_R(aBackgroundColor);
92 0 : PRUint8 green = NS_GET_G(aBackgroundColor);
93 0 : PRUint8 blue = NS_GET_B(aBackgroundColor);
94 :
95 0 : PRUint8 elementBrightness = NS_GetBrightness(rb,gb,bb);
96 0 : PRUint8 backgroundBrightness = NS_GetBrightness(red, green, blue);
97 :
98 :
99 0 : if (backgroundBrightness < COLOR_DARK_THRESHOLD) {
100 0 : f0 = COLOR_DARK_BS_FACTOR;
101 0 : f1 = COLOR_DARK_TS_FACTOR;
102 0 : if(elementBrightness == MAX_DARKNESS)
103 : {
104 0 : rb = NS_GET_R(DARK_GRAY);
105 0 : gb = NS_GET_G(DARK_GRAY);
106 0 : bb = NS_GET_B(DARK_GRAY);
107 : }
108 0 : }else if (backgroundBrightness > COLOR_LIGHT_THRESHOLD) {
109 0 : f0 = COLOR_LITE_BS_FACTOR;
110 0 : f1 = COLOR_LITE_TS_FACTOR;
111 0 : if(elementBrightness == MAX_BRIGHTNESS)
112 : {
113 0 : rb = NS_GET_R(LIGHT_GRAY);
114 0 : gb = NS_GET_G(LIGHT_GRAY);
115 0 : bb = NS_GET_B(LIGHT_GRAY);
116 : }
117 : }else {
118 : f0 = COLOR_DARK_BS_FACTOR +
119 : (backgroundBrightness *
120 0 : (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
121 : f1 = COLOR_DARK_TS_FACTOR +
122 : (backgroundBrightness *
123 0 : (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
124 : }
125 :
126 :
127 0 : r = rb - (f0 * rb / 100);
128 0 : g = gb - (f0 * gb / 100);
129 0 : b = bb - (f0 * bb / 100);
130 0 : aResult[0] = NS_RGBA(r, g, b, a);
131 :
132 0 : r = rb + (f1 * (MAX_COLOR - rb) / 100);
133 0 : g = gb + (f1 * (MAX_COLOR - gb) / 100);
134 0 : b = bb + (f1 * (MAX_COLOR - bb) / 100);
135 0 : aResult[1] = NS_RGBA(r, g, b, a);
136 0 : }
137 :
138 0 : int NS_GetBrightness(PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue)
139 : {
140 :
141 0 : PRUint8 intensity = (aRed + aGreen + aBlue) / 3;
142 :
143 0 : PRUint8 luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000;
144 :
145 : return ((intensity * INTENSITY_FACTOR) +
146 0 : (luminosity * LUMINOSITY_FACTOR)) / 100;
147 : }
148 :
149 0 : PRInt32 NS_GetLuminosity(nscolor aColor)
150 : {
151 : // When aColor is not opaque, the perceived luminosity will depend
152 : // on what color(s) aColor is ultimately drawn on top of, which we
153 : // do not know.
154 0 : NS_ASSERTION(NS_GET_A(aColor) == 255,
155 : "impossible to compute luminosity of a non-opaque color");
156 :
157 : return (NS_GET_R(aColor) * RED_LUMINOSITY +
158 : NS_GET_G(aColor) * GREEN_LUMINOSITY +
159 0 : NS_GET_B(aColor) * BLUE_LUMINOSITY);
160 : }
161 :
162 : // Function to convert RGB color space into the HSV colorspace
163 : // Hue is the primary color defined from 0 to 359 degrees
164 : // Saturation is defined from 0 to 255. The higher the number.. the deeper
165 : // the color Value is the brightness of the color. 0 is black, 255 is white.
166 0 : void NS_RGB2HSV(nscolor aColor, PRUint16 &aHue, PRUint16 &aSat,
167 : PRUint16 &aValue, PRUint8 &aAlpha)
168 : {
169 : PRUint8 r, g, b;
170 : PRInt16 delta, min, max, r1, b1, g1;
171 : float hue;
172 :
173 0 : r = NS_GET_R(aColor);
174 0 : g = NS_GET_G(aColor);
175 0 : b = NS_GET_B(aColor);
176 :
177 0 : if (r>g) {
178 0 : max = r;
179 0 : min = g;
180 : } else {
181 0 : max = g;
182 0 : min = r;
183 : }
184 :
185 0 : if (b>max) {
186 0 : max = b;
187 : }
188 0 : if (b<min) {
189 0 : min = b;
190 : }
191 :
192 : // value or brightness will always be the max of all the colors(RGB)
193 0 : aValue = max;
194 0 : delta = max-min;
195 0 : aSat = (max!=0)?((delta*255)/max):0;
196 0 : r1 = r;
197 0 : b1 = b;
198 0 : g1 = g;
199 :
200 0 : if (aSat==0) {
201 0 : hue = 1000;
202 : } else {
203 0 : if(r==max){
204 0 : hue=(float)(g1-b1)/(float)delta;
205 0 : } else if (g1==max) {
206 0 : hue= 2.0f+(float)(b1-r1)/(float)delta;
207 : } else {
208 0 : hue = 4.0f+(float)(r1-g1)/(float)delta;
209 : }
210 : }
211 :
212 0 : if(hue<999) {
213 0 : hue*=60;
214 0 : if(hue<0){
215 0 : hue+=360;
216 : }
217 : } else {
218 0 : hue=0;
219 : }
220 :
221 0 : aHue = (PRUint16)hue;
222 :
223 0 : aAlpha = NS_GET_A(aColor);
224 0 : }
225 :
226 : // Function to convert HSV color space into the RGB colorspace
227 : // Hue is the primary color defined from 0 to 359 degrees
228 : // Saturation is defined from 0 to 255. The higher the number.. the deeper
229 : // the color Value is the brightness of the color. 0 is black, 255 is white.
230 0 : void NS_HSV2RGB(nscolor &aColor, PRUint16 aHue, PRUint16 aSat, PRUint16 aValue,
231 : PRUint8 aAlpha)
232 : {
233 0 : PRUint16 r = 0, g = 0, b = 0;
234 : PRUint16 i, p, q, t;
235 : double h, f, percent;
236 :
237 0 : if ( aSat == 0 ){
238 : // achromatic color, no hue is defined
239 0 : r = aValue;
240 0 : g = aValue;
241 0 : b = aValue;
242 : } else {
243 : // hue in in degrees around the color wheel defined from
244 : // 0 to 360 degrees.
245 0 : if (aHue >= 360) {
246 0 : aHue = 0;
247 : }
248 :
249 : // we break the color wheel into 6 areas.. these
250 : // areas define how the saturation and value define the color.
251 : // reds behave differently than the blues
252 0 : h = (double)aHue / 60.0;
253 0 : i = (PRUint16) floor(h);
254 0 : f = h-(double)i;
255 0 : percent = ((double)aValue/255.0); // this needs to be a value from 0 to 1, so a percentage
256 : // can be calculated of the saturation.
257 0 : p = (PRUint16)(percent*(255-aSat));
258 0 : q = (PRUint16)(percent*(255-(aSat*f)));
259 0 : t = (PRUint16)(percent*(255-(aSat*(1.0-f))));
260 :
261 : // i is guaranteed to never be larger than 5.
262 0 : switch(i){
263 0 : case 0: r = aValue; g = t; b = p;break;
264 0 : case 1: r = q; g = aValue; b = p;break;
265 0 : case 2: r = p; g = aValue; b = t;break;
266 0 : case 3: r = p; g = q; b = aValue;break;
267 0 : case 4: r = t; g = p; b = aValue;break;
268 0 : case 5: r = aValue; g = p; b = q;break;
269 : }
270 : }
271 0 : aColor = NS_RGBA(r, g, b, aAlpha);
272 0 : }
|