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