Line data Source code
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 0 : 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 0 : uint8_t rb = NS_GET_R(aBorderColor);
46 0 : uint8_t gb = NS_GET_G(aBorderColor);
47 0 : uint8_t bb = NS_GET_B(aBorderColor);
48 :
49 0 : 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 0 : uint8_t red = NS_GET_R(aBackgroundColor);
57 0 : uint8_t green = NS_GET_G(aBackgroundColor);
58 0 : uint8_t blue = NS_GET_B(aBackgroundColor);
59 :
60 0 : uint8_t elementBrightness = NS_GetBrightness(rb,gb,bb);
61 0 : uint8_t backgroundBrightness = NS_GetBrightness(red, green, blue);
62 :
63 :
64 0 : if (backgroundBrightness < COLOR_DARK_THRESHOLD) {
65 0 : f0 = COLOR_DARK_BS_FACTOR;
66 0 : f1 = COLOR_DARK_TS_FACTOR;
67 0 : if(elementBrightness == MAX_DARKNESS)
68 : {
69 0 : rb = NS_GET_R(DARK_GRAY);
70 0 : gb = NS_GET_G(DARK_GRAY);
71 0 : bb = NS_GET_B(DARK_GRAY);
72 : }
73 0 : }else if (backgroundBrightness > COLOR_LIGHT_THRESHOLD) {
74 0 : f0 = COLOR_LITE_BS_FACTOR;
75 0 : f1 = COLOR_LITE_TS_FACTOR;
76 0 : if(elementBrightness == MAX_BRIGHTNESS)
77 : {
78 0 : rb = NS_GET_R(LIGHT_GRAY);
79 0 : gb = NS_GET_G(LIGHT_GRAY);
80 0 : bb = NS_GET_B(LIGHT_GRAY);
81 : }
82 : }else {
83 0 : f0 = COLOR_DARK_BS_FACTOR +
84 0 : (backgroundBrightness *
85 0 : (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
86 0 : f1 = COLOR_DARK_TS_FACTOR +
87 0 : (backgroundBrightness *
88 0 : (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
89 : }
90 :
91 :
92 0 : r = rb - (f0 * rb / 100);
93 0 : g = gb - (f0 * gb / 100);
94 0 : b = bb - (f0 * bb / 100);
95 0 : aResult[0] = NS_RGBA(r, g, b, a);
96 :
97 0 : r = rb + (f1 * (MAX_COLOR - rb) / 100);
98 0 : g = gb + (f1 * (MAX_COLOR - gb) / 100);
99 0 : b = bb + (f1 * (MAX_COLOR - bb) / 100);
100 0 : aResult[1] = NS_RGBA(r, g, b, a);
101 0 : }
102 :
103 0 : int NS_GetBrightness(uint8_t aRed, uint8_t aGreen, uint8_t aBlue)
104 : {
105 :
106 0 : uint8_t intensity = (aRed + aGreen + aBlue) / 3;
107 :
108 0 : uint8_t luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000;
109 :
110 0 : return ((intensity * INTENSITY_FACTOR) +
111 0 : (luminosity * LUMINOSITY_FACTOR)) / 100;
112 : }
113 :
114 4 : 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 4 : NS_ASSERTION(NS_GET_A(aColor) == 255,
120 : "impossible to compute luminosity of a non-opaque color");
121 :
122 8 : return (NS_GET_R(aColor) * RED_LUMINOSITY +
123 4 : NS_GET_G(aColor) * GREEN_LUMINOSITY +
124 4 : 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 0 : 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 0 : r = NS_GET_R(aColor);
139 0 : g = NS_GET_G(aColor);
140 0 : b = NS_GET_B(aColor);
141 :
142 0 : if (r>g) {
143 0 : max = r;
144 0 : min = g;
145 : } else {
146 0 : max = g;
147 0 : min = r;
148 : }
149 :
150 0 : if (b>max) {
151 0 : max = b;
152 : }
153 0 : if (b<min) {
154 0 : min = b;
155 : }
156 :
157 : // value or brightness will always be the max of all the colors(RGB)
158 0 : aValue = max;
159 0 : delta = max-min;
160 0 : aSat = (max!=0)?((delta*255)/max):0;
161 0 : r1 = r;
162 0 : b1 = b;
163 0 : g1 = g;
164 :
165 0 : if (aSat==0) {
166 0 : hue = 1000;
167 : } else {
168 0 : if(r==max){
169 0 : hue=(float)(g1-b1)/(float)delta;
170 0 : } else if (g1==max) {
171 0 : hue= 2.0f+(float)(b1-r1)/(float)delta;
172 : } else {
173 0 : hue = 4.0f+(float)(r1-g1)/(float)delta;
174 : }
175 : }
176 :
177 0 : if(hue<999) {
178 0 : hue*=60;
179 0 : if(hue<0){
180 0 : hue+=360;
181 : }
182 : } else {
183 0 : hue=0;
184 : }
185 :
186 0 : aHue = (uint16_t)hue;
187 :
188 0 : aAlpha = NS_GET_A(aColor);
189 0 : }
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 0 : void NS_HSV2RGB(nscolor &aColor, uint16_t aHue, uint16_t aSat, uint16_t aValue,
196 : uint8_t aAlpha)
197 : {
198 0 : uint16_t r = 0, g = 0, b = 0;
199 : uint16_t i, p, q, t;
200 : double h, f, percent;
201 :
202 0 : if ( aSat == 0 ){
203 : // achromatic color, no hue is defined
204 0 : r = aValue;
205 0 : g = aValue;
206 0 : b = aValue;
207 : } else {
208 : // hue in in degrees around the color wheel defined from
209 : // 0 to 360 degrees.
210 0 : if (aHue >= 360) {
211 0 : 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 0 : h = (double)aHue / 60.0;
218 0 : i = (uint16_t) floor(h);
219 0 : f = h-(double)i;
220 0 : 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 0 : p = (uint16_t)(percent*(255-aSat));
223 0 : q = (uint16_t)(percent*(255-(aSat*f)));
224 0 : t = (uint16_t)(percent*(255-(aSat*(1.0-f))));
225 :
226 : // i is guaranteed to never be larger than 5.
227 0 : switch(i){
228 0 : case 0: r = aValue; g = t; b = p;break;
229 0 : case 1: r = q; g = aValue; b = p;break;
230 0 : case 2: r = p; g = aValue; b = t;break;
231 0 : case 3: r = p; g = q; b = aValue;break;
232 0 : case 4: r = t; g = p; b = aValue;break;
233 0 : case 5: r = aValue; g = p; b = q;break;
234 : }
235 : }
236 0 : aColor = NS_RGBA(r, g, b, aAlpha);
237 0 : }
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
|