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