1 /*
2  * Cogl
3  *
4  * A Low Level GPU Graphics and Utilities API
5  *
6  * Copyright (C) 2008,2009 Intel Corporation.
7  *
8  * Permission is hereby granted, free of charge, to any person
9  * obtaining a copy of this software and associated documentation
10  * files (the "Software"), to deal in the Software without
11  * restriction, including without limitation the rights to use, copy,
12  * modify, merge, publish, distribute, sublicense, and/or sell copies
13  * of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be
17  * included in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  * SOFTWARE.
27  *
28  *
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <string.h>
36 
37 #include "cogl-util.h"
38 #include "cogl-color.h"
39 #include "cogl-fixed.h"
40 #include "cogl-color-private.h"
41 #include "cogl-gtype-private.h"
42 
43 COGL_GTYPE_DEFINE_BOXED (Color, color, cogl_color_copy, cogl_color_free);
44 
45 CoglColor *
cogl_color_new(void)46 cogl_color_new (void)
47 {
48   return g_slice_new (CoglColor);
49 }
50 
51 CoglColor *
cogl_color_copy(const CoglColor * color)52 cogl_color_copy (const CoglColor *color)
53 {
54   if (G_LIKELY (color))
55     return g_slice_dup (CoglColor, color);
56 
57   return NULL;
58 }
59 
60 void
cogl_color_free(CoglColor * color)61 cogl_color_free (CoglColor *color)
62 {
63   if (G_LIKELY (color))
64     g_slice_free (CoglColor, color);
65 }
66 
67 void
cogl_color_init_from_4ub(CoglColor * color,uint8_t red,uint8_t green,uint8_t blue,uint8_t alpha)68 cogl_color_init_from_4ub (CoglColor *color,
69                           uint8_t red,
70                           uint8_t green,
71                           uint8_t blue,
72                           uint8_t alpha)
73 {
74   _COGL_RETURN_IF_FAIL (color != NULL);
75 
76   color->red   = red;
77   color->green = green;
78   color->blue  = blue;
79   color->alpha = alpha;
80 }
81 
82 /* XXX: deprecated, use cogl_color_init_from_4ub */
83 void
cogl_color_set_from_4ub(CoglColor * dest,uint8_t red,uint8_t green,uint8_t blue,uint8_t alpha)84 cogl_color_set_from_4ub (CoglColor *dest,
85                          uint8_t red,
86                          uint8_t green,
87                          uint8_t blue,
88                          uint8_t alpha)
89 {
90   cogl_color_init_from_4ub (dest, red, green, blue, alpha);
91 }
92 
93 void
cogl_color_init_from_4f(CoglColor * color,float red,float green,float blue,float alpha)94 cogl_color_init_from_4f (CoglColor *color,
95                          float red,
96                          float green,
97                          float blue,
98                          float alpha)
99 {
100   _COGL_RETURN_IF_FAIL (color != NULL);
101 
102   color->red   =  (red * 255);
103   color->green =  (green * 255);
104   color->blue  =  (blue * 255);
105   color->alpha =  (alpha * 255);
106 }
107 
108 /* XXX: deprecated, use cogl_color_init_from_4f */
109 void
cogl_color_set_from_4f(CoglColor * color,float red,float green,float blue,float alpha)110 cogl_color_set_from_4f (CoglColor *color,
111                         float red,
112                         float green,
113                         float blue,
114                         float alpha)
115 {
116   cogl_color_init_from_4f (color, red, green, blue, alpha);
117 }
118 
119 void
cogl_color_init_from_4fv(CoglColor * color,const float * color_array)120 cogl_color_init_from_4fv (CoglColor *color,
121                           const float *color_array)
122 {
123   _COGL_RETURN_IF_FAIL (color != NULL);
124 
125   color->red   =  (color_array[0] * 255);
126   color->green =  (color_array[1] * 255);
127   color->blue  =  (color_array[2] * 255);
128   color->alpha =  (color_array[3] * 255);
129 }
130 
131 unsigned char
cogl_color_get_red_byte(const CoglColor * color)132 cogl_color_get_red_byte (const CoglColor *color)
133 {
134   return color->red;
135 }
136 
137 float
cogl_color_get_red_float(const CoglColor * color)138 cogl_color_get_red_float (const CoglColor *color)
139 {
140   return (float) color->red / 255.0;
141 }
142 
143 float
cogl_color_get_red(const CoglColor * color)144 cogl_color_get_red (const CoglColor *color)
145 {
146   return  ((float) color->red / 255.0);
147 }
148 
149 unsigned char
cogl_color_get_green_byte(const CoglColor * color)150 cogl_color_get_green_byte (const CoglColor *color)
151 {
152   return color->green;
153 }
154 
155 float
cogl_color_get_green_float(const CoglColor * color)156 cogl_color_get_green_float (const CoglColor *color)
157 {
158   return (float) color->green / 255.0;
159 }
160 
161 float
cogl_color_get_green(const CoglColor * color)162 cogl_color_get_green (const CoglColor *color)
163 {
164   return  ((float) color->green / 255.0);
165 }
166 
167 unsigned char
cogl_color_get_blue_byte(const CoglColor * color)168 cogl_color_get_blue_byte (const CoglColor *color)
169 {
170   return color->blue;
171 }
172 
173 float
cogl_color_get_blue_float(const CoglColor * color)174 cogl_color_get_blue_float (const CoglColor *color)
175 {
176   return (float) color->blue / 255.0;
177 }
178 
179 float
cogl_color_get_blue(const CoglColor * color)180 cogl_color_get_blue (const CoglColor *color)
181 {
182   return  ((float) color->blue / 255.0);
183 }
184 
185 unsigned char
cogl_color_get_alpha_byte(const CoglColor * color)186 cogl_color_get_alpha_byte (const CoglColor *color)
187 {
188   return color->alpha;
189 }
190 
191 float
cogl_color_get_alpha_float(const CoglColor * color)192 cogl_color_get_alpha_float (const CoglColor *color)
193 {
194   return (float) color->alpha / 255.0;
195 }
196 
197 float
cogl_color_get_alpha(const CoglColor * color)198 cogl_color_get_alpha (const CoglColor *color)
199 {
200   return  ((float) color->alpha / 255.0);
201 }
202 
203 void
cogl_color_set_red_byte(CoglColor * color,unsigned char red)204 cogl_color_set_red_byte (CoglColor     *color,
205                          unsigned char  red)
206 {
207   color->red = red;
208 }
209 
210 void
cogl_color_set_red_float(CoglColor * color,float red)211 cogl_color_set_red_float (CoglColor *color,
212                           float      red)
213 {
214   color->red = red * 255.0;
215 }
216 
217 void
cogl_color_set_red(CoglColor * color,float red)218 cogl_color_set_red (CoglColor *color,
219                     float      red)
220 {
221   color->red = red * 255.0;
222 }
223 
224 void
cogl_color_set_green_byte(CoglColor * color,unsigned char green)225 cogl_color_set_green_byte (CoglColor     *color,
226                            unsigned char  green)
227 {
228   color->green = green;
229 }
230 
231 void
cogl_color_set_green_float(CoglColor * color,float green)232 cogl_color_set_green_float (CoglColor *color,
233                             float green)
234 {
235   color->green = green * 255.0;
236 }
237 
238 void
cogl_color_set_green(CoglColor * color,float green)239 cogl_color_set_green (CoglColor *color,
240                       float green)
241 {
242   color->green = green * 255.0;
243 }
244 
245 void
cogl_color_set_blue_byte(CoglColor * color,unsigned char blue)246 cogl_color_set_blue_byte (CoglColor *color,
247                           unsigned char blue)
248 {
249   color->blue = blue;
250 }
251 
252 void
cogl_color_set_blue_float(CoglColor * color,float blue)253 cogl_color_set_blue_float (CoglColor *color,
254                            float blue)
255 {
256   color->blue = blue * 255.0;
257 }
258 
259 void
cogl_color_set_blue(CoglColor * color,float blue)260 cogl_color_set_blue (CoglColor *color,
261                      float blue)
262 {
263   color->blue = blue * 255.0;
264 }
265 
266 void
cogl_color_set_alpha_byte(CoglColor * color,unsigned char alpha)267 cogl_color_set_alpha_byte (CoglColor *color,
268                            unsigned char  alpha)
269 {
270   color->alpha = alpha;
271 }
272 
273 void
cogl_color_set_alpha_float(CoglColor * color,float alpha)274 cogl_color_set_alpha_float (CoglColor *color,
275                             float alpha)
276 {
277   color->alpha = alpha * 255.0;
278 }
279 
280 void
cogl_color_set_alpha(CoglColor * color,float alpha)281 cogl_color_set_alpha (CoglColor *color,
282                       float alpha)
283 {
284   color->alpha = alpha * 255.0;
285 }
286 
287 void
cogl_color_premultiply(CoglColor * color)288 cogl_color_premultiply (CoglColor *color)
289 {
290   color->red = (color->red * color->alpha + 128) / 255;
291   color->green = (color->green * color->alpha + 128) / 255;
292   color->blue = (color->blue * color->alpha + 128) / 255;
293 }
294 
295 void
cogl_color_unpremultiply(CoglColor * color)296 cogl_color_unpremultiply (CoglColor *color)
297 {
298   if (color->alpha != 0)
299     {
300       color->red = (color->red * 255) / color->alpha;
301       color->green = (color->green * 255) / color->alpha;
302       color->blue = (color->blue * 255) / color->alpha;
303     }
304 }
305 
306 CoglBool
cogl_color_equal(const void * v1,const void * v2)307 cogl_color_equal (const void *v1, const void *v2)
308 {
309   const uint32_t *c1 = v1, *c2 = v2;
310 
311   _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE);
312   _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE);
313 
314   /* XXX: We don't compare the padding */
315   return *c1 == *c2 ? TRUE : FALSE;
316 }
317 
318 void
_cogl_color_get_rgba_4ubv(const CoglColor * color,uint8_t * dest)319 _cogl_color_get_rgba_4ubv (const CoglColor *color,
320                            uint8_t *dest)
321 {
322   memcpy (dest, color, 4);
323 }
324 
325 void
cogl_color_to_hsl(const CoglColor * color,float * hue,float * saturation,float * luminance)326 cogl_color_to_hsl (const CoglColor *color,
327                    float           *hue,
328                    float           *saturation,
329                    float           *luminance)
330 {
331   float red, green, blue;
332   float min, max, delta;
333   float h, l, s;
334 
335   red   = color->red / 255.0;
336   green = color->green / 255.0;
337   blue  = color->blue / 255.0;
338 
339   if (red > green)
340     {
341       if (red > blue)
342 	max = red;
343       else
344 	max = blue;
345 
346       if (green < blue)
347 	min = green;
348       else
349 	min = blue;
350     }
351   else
352     {
353       if (green > blue)
354 	max = green;
355       else
356 	max = blue;
357 
358       if (red < blue)
359 	min = red;
360       else
361 	min = blue;
362     }
363 
364   l = (max + min) / 2;
365   s = 0;
366   h = 0;
367 
368   if (max != min)
369     {
370       if (l <= 0.5)
371 	s = (max - min) / (max + min);
372       else
373 	s = (max - min) / (2.0 - max - min);
374 
375       delta = max - min;
376 
377       if (red == max)
378 	h = (green - blue) / delta;
379       else if (green == max)
380 	h = 2.0 + (blue - red) / delta;
381       else if (blue == max)
382 	h = 4.0 + (red - green) / delta;
383 
384       h *= 60;
385 
386       if (h < 0)
387 	h += 360.0;
388     }
389 
390   if (hue)
391     *hue = h;
392 
393   if (luminance)
394     *luminance = l;
395 
396   if (saturation)
397     *saturation = s;
398 }
399 
400 void
cogl_color_init_from_hsl(CoglColor * color,float hue,float saturation,float luminance)401 cogl_color_init_from_hsl (CoglColor *color,
402                           float      hue,
403                           float      saturation,
404                           float      luminance)
405 {
406   float tmp1, tmp2;
407   float tmp3[3];
408   float clr[3];
409   int   i;
410 
411   hue /= 360.0;
412 
413   if (saturation == 0)
414     {
415       cogl_color_init_from_4f (color, luminance, luminance, luminance, 1.0f);
416       return;
417     }
418 
419   if (luminance <= 0.5)
420     tmp2 = luminance * (1.0 + saturation);
421   else
422     tmp2 = luminance + saturation - (luminance * saturation);
423 
424   tmp1 = 2.0 * luminance - tmp2;
425 
426   tmp3[0] = hue + 1.0 / 3.0;
427   tmp3[1] = hue;
428   tmp3[2] = hue - 1.0 / 3.0;
429 
430   for (i = 0; i < 3; i++)
431     {
432       if (tmp3[i] < 0)
433         tmp3[i] += 1.0;
434 
435       if (tmp3[i] > 1)
436         tmp3[i] -= 1.0;
437 
438       if (6.0 * tmp3[i] < 1.0)
439         clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0;
440       else if (2.0 * tmp3[i] < 1.0)
441         clr[i] = tmp2;
442       else if (3.0 * tmp3[i] < 2.0)
443         clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0);
444       else
445         clr[i] = tmp1;
446     }
447 
448   cogl_color_init_from_4f (color, clr[0], clr[1], clr[2], 1.0f);
449 }
450