1 /**
2  * @file lv_color.h
3  *
4  */
5 
6 #ifndef LV_COLOR_H
7 #define LV_COLOR_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #include "../lv_conf_internal.h"
17 #include "lv_math.h"
18 
19 /*Error checking*/
20 #if LV_COLOR_DEPTH == 24
21 #error "LV_COLOR_DEPTH  24 is deprecated. Use LV_COLOR_DEPTH  32 instead (lv_conf.h)"
22 #endif
23 
24 #if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0
25 #error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h"
26 #endif
27 
28 #if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0
29 #error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h"
30 #endif
31 
32 #include <stdint.h>
33 
34 /*********************
35  *      DEFINES
36  *********************/
37 #define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF)
38 #define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
39 #define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80)
40 #define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00)
41 #define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00)
42 #define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00)
43 #define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00)
44 #define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00)
45 #define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00)
46 #define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00)
47 #define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF)
48 #define LV_COLOR_AQUA LV_COLOR_CYAN
49 #define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80)
50 #define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF)
51 #define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80)
52 #define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF, 0x00, 0xFF)
53 #define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80)
54 #define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00)
55 
56 /**
57  * Opacity percentages.
58  */
59 enum {
60     LV_OPA_TRANSP = 0,
61     LV_OPA_0      = 0,
62     LV_OPA_10     = 25,
63     LV_OPA_20     = 51,
64     LV_OPA_30     = 76,
65     LV_OPA_40     = 102,
66     LV_OPA_50     = 127,
67     LV_OPA_60     = 153,
68     LV_OPA_70     = 178,
69     LV_OPA_80     = 204,
70     LV_OPA_90     = 229,
71     LV_OPA_100    = 255,
72     LV_OPA_COVER  = 255,
73 };
74 
75 #define LV_OPA_MIN 2    /*Opacities below this will be transparent*/
76 #define LV_OPA_MAX 253  /*Opacities above this will fully cover*/
77 
78 #if LV_COLOR_DEPTH == 1
79 #define LV_COLOR_SIZE 8
80 #elif LV_COLOR_DEPTH == 8
81 #define LV_COLOR_SIZE 8
82 #elif LV_COLOR_DEPTH == 16
83 #define LV_COLOR_SIZE 16
84 #elif LV_COLOR_DEPTH == 32
85 #define LV_COLOR_SIZE 32
86 #else
87 #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
88 #endif
89 
90 
91 /* Adjust color mix functions rounding.
92  * GPUs might calculate color mix (blending) differently.
93  * Should be in range of 0..254
94  * 0: no adjustment, get the integer part of the result (round down)
95  * 64: round up from x.75
96  * 128: round up from half
97  * 192: round up from x.25
98  * 254: round up */
99 #ifndef LV_COLOR_MIX_ROUND_OFS
100 #if LV_COLOR_DEPTH == 32
101 #define LV_COLOR_MIX_ROUND_OFS 0
102 #else
103 #define LV_COLOR_MIX_ROUND_OFS 128
104 #endif
105 #endif
106 
107 /*---------------------------------------
108  * Macros for all existing  color depths
109  * to set/get values of the color channels
110  *------------------------------------------*/
111 # define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1);
112 # define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1);
113 # define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1);
114 # define LV_COLOR_SET_A1(c, v)
115 
116 # define LV_COLOR_GET_R1(c) (c).ch.red
117 # define LV_COLOR_GET_G1(c) (c).ch.green
118 # define LV_COLOR_GET_B1(c) (c).ch.blue
119 # define LV_COLOR_GET_A1(c) 1
120 
121 # define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)(v) & 0x7U;
122 # define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)(v) & 0x7U;
123 # define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)(v) & 0x3U;
124 # define LV_COLOR_SET_A8(c, v) do {} while(0)
125 
126 # define LV_COLOR_GET_R8(c) (c).ch.red
127 # define LV_COLOR_GET_G8(c) (c).ch.green
128 # define LV_COLOR_GET_B8(c) (c).ch.blue
129 # define LV_COLOR_GET_A8(c) 0xFF
130 
131 # define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint8_t)(v) & 0x1FU;
132 # define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)(v) & 0x3FU;
133 # define LV_COLOR_SET_G16_SWAP(c, v) {(c).ch.green_h = (uint8_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint8_t)((v) & 0x7);}
134 # define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint8_t)(v) & 0x1FU;
135 # define LV_COLOR_SET_A16(c, v) do {} while(0)
136 
137 # define LV_COLOR_GET_R16(c) (c).ch.red
138 # define LV_COLOR_GET_G16(c) (c).ch.green
139 # define LV_COLOR_GET_G16_SWAP(c) (((c).ch.green_h << 3) + (c).ch.green_l)
140 # define LV_COLOR_GET_B16(c) (c).ch.blue
141 # define LV_COLOR_GET_A16(c) 0xFF
142 
143 # define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint32_t)((v) & 0xFF);
144 # define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint32_t)((v) & 0xFF);
145 # define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint32_t)((v) & 0xFF);
146 # define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint32_t)((v) & 0xFF);
147 
148 # define LV_COLOR_GET_R32(c) (c).ch.red
149 # define LV_COLOR_GET_G32(c) (c).ch.green
150 # define LV_COLOR_GET_B32(c) (c).ch.blue
151 # define LV_COLOR_GET_A32(c) (c).ch.alpha
152 
153 
154 /*---------------------------------------
155  * Macros for the current color depth
156  * to set/get values of the color channels
157  *------------------------------------------*/
158 #if LV_COLOR_DEPTH == 1
159 # define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R1(c,v)
160 # define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G1(c,v)
161 # define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B1(c,v)
162 # define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A1(c,v)
163 
164 # define LV_COLOR_GET_R(c) LV_COLOR_GET_R1(c)
165 # define LV_COLOR_GET_G(c) LV_COLOR_GET_G1(c)
166 # define LV_COLOR_GET_B(c) LV_COLOR_GET_B1(c)
167 # define LV_COLOR_GET_A(c) LV_COLOR_GET_A1(c)
168 
169 #elif LV_COLOR_DEPTH == 8
170 # define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R8(c,v)
171 # define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G8(c,v)
172 # define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B8(c,v)
173 # define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A8(c,v)
174 
175 # define LV_COLOR_GET_R(c) LV_COLOR_GET_R8(c)
176 # define LV_COLOR_GET_G(c) LV_COLOR_GET_G8(c)
177 # define LV_COLOR_GET_B(c) LV_COLOR_GET_B8(c)
178 # define LV_COLOR_GET_A(c) LV_COLOR_GET_A8(c)
179 
180 #elif LV_COLOR_DEPTH == 16
181 # define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R16(c,v)
182 # if LV_COLOR_16_SWAP == 0
183 #   define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16(c,v)
184 # else
185 #   define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16_SWAP(c,v)
186 # endif
187 # define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B16(c,v)
188 # define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A16(c,v)
189 
190 # define LV_COLOR_GET_R(c) LV_COLOR_GET_R16(c)
191 # if LV_COLOR_16_SWAP == 0
192 #   define LV_COLOR_GET_G(c) LV_COLOR_GET_G16(c)
193 # else
194 #   define LV_COLOR_GET_G(c) LV_COLOR_GET_G16_SWAP(c)
195 # endif
196 # define LV_COLOR_GET_B(c)   LV_COLOR_GET_B16(c)
197 # define LV_COLOR_GET_A(c)   LV_COLOR_GET_A16(c)
198 
199 #elif LV_COLOR_DEPTH == 32
200 # define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R32(c,v)
201 # define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G32(c,v)
202 # define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B32(c,v)
203 # define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A32(c,v)
204 
205 # define LV_COLOR_GET_R(c) LV_COLOR_GET_R32(c)
206 # define LV_COLOR_GET_G(c) LV_COLOR_GET_G32(c)
207 # define LV_COLOR_GET_B(c) LV_COLOR_GET_B32(c)
208 # define LV_COLOR_GET_A(c) LV_COLOR_GET_A32(c)
209 #endif
210 
211 /**********************
212  *      TYPEDEFS
213  **********************/
214 
215 typedef union {
216     union {
217         uint8_t blue : 1;
218         uint8_t green : 1;
219         uint8_t red : 1;
220     } ch;
221     uint8_t full;
222 } lv_color1_t;
223 
224 typedef union {
225     struct {
226         uint8_t blue : 2;
227         uint8_t green : 3;
228         uint8_t red : 3;
229     } ch;
230     uint8_t full;
231 } lv_color8_t;
232 
233 typedef union {
234     struct {
235 #if LV_COLOR_16_SWAP == 0
236         uint16_t blue : 5;
237         uint16_t green : 6;
238         uint16_t red : 5;
239 #else
240         uint16_t green_h : 3;
241         uint16_t red : 5;
242         uint16_t blue : 5;
243         uint16_t green_l : 3;
244 #endif
245     } ch;
246     uint16_t full;
247 } lv_color16_t;
248 
249 typedef union {
250     struct {
251         uint8_t blue;
252         uint8_t green;
253         uint8_t red;
254         uint8_t alpha;
255     } ch;
256     uint32_t full;
257 } lv_color32_t;
258 
259 #if LV_COLOR_DEPTH == 1
260 typedef uint8_t lv_color_int_t;
261 typedef lv_color1_t lv_color_t;
262 #elif LV_COLOR_DEPTH == 8
263 typedef uint8_t lv_color_int_t;
264 typedef lv_color8_t lv_color_t;
265 #elif LV_COLOR_DEPTH == 16
266 typedef uint16_t lv_color_int_t;
267 typedef lv_color16_t lv_color_t;
268 #elif LV_COLOR_DEPTH == 32
269 typedef uint32_t lv_color_int_t;
270 typedef lv_color32_t lv_color_t;
271 #else
272 #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
273 #endif
274 
275 
276 typedef struct {
277     uint16_t h;
278     uint8_t s;
279     uint8_t v;
280 } lv_color_hsv_t;
281 
282 //! @cond Doxygen_Suppress
283 /*No idea where the guard is required but else throws warnings in the docs*/
284 typedef uint8_t lv_opa_t;
285 //! @endcond
286 
287 /**********************
288  * GLOBAL PROTOTYPES
289  **********************/
290 
291 /*In color conversations:
292  * - When converting to bigger color type the LSB weight of 1 LSB is calculated
293  *   E.g. 16 bit Red has 5 bits
294  *         8 bit Red has 2 bits
295  *        ----------------------
296  *        8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10
297  *
298  * - When calculating to smaller color type simply shift out the LSBs
299  *   E.g.  8 bit Red has 2 bits
300  *        16 bit Red has 5 bits
301  *        ----------------------
302  *         Shift right with 5 - 3 = 2
303  */
lv_color_to1(lv_color_t color)304 static inline uint8_t lv_color_to1(lv_color_t color)
305 {
306 #if LV_COLOR_DEPTH == 1
307     return color.full;
308 #elif LV_COLOR_DEPTH == 8
309     if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) {
310         return 1;
311     }
312     else {
313         return 0;
314     }
315 #elif LV_COLOR_DEPTH == 16
316     if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) {
317         return 1;
318     }
319     else {
320         return 0;
321     }
322 #elif LV_COLOR_DEPTH == 32
323     if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) {
324         return 1;
325     }
326     else {
327         return 0;
328     }
329 #endif
330 }
331 
lv_color_to8(lv_color_t color)332 static inline uint8_t lv_color_to8(lv_color_t color)
333 {
334 #if LV_COLOR_DEPTH == 1
335     if(color.full == 0)
336         return 0;
337     else
338         return 0xFF;
339 #elif LV_COLOR_DEPTH == 8
340     return color.full;
341 #elif LV_COLOR_DEPTH == 16
342     lv_color8_t ret;
343     LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2);   /* 5 - 3  = 2*/
344     LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 3); /* 6 - 3  = 3*/
345     LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3);  /* 5 - 2  = 3*/
346     return ret.full;
347 #elif LV_COLOR_DEPTH == 32
348     lv_color8_t ret;
349     LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5);   /* 8 - 3  = 5*/
350     LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 5); /* 8 - 3  = 5*/
351     LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6);  /* 8 - 2  = 6*/
352     return ret.full;
353 #endif
354 }
355 
lv_color_to16(lv_color_t color)356 static inline uint16_t lv_color_to16(lv_color_t color)
357 {
358 #if LV_COLOR_DEPTH == 1
359     if(color.full == 0)
360         return 0;
361     else
362         return 0xFFFF;
363 #elif LV_COLOR_DEPTH == 8
364     lv_color16_t ret;
365     LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4);     /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
366 #if LV_COLOR_16_SWAP == 0
367     LV_COLOR_SET_G16(ret,  LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
368 #else
369     LV_COLOR_SET_G16_SWAP(ret, (LV_COLOR_GET_G(color) * 9)); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
370 #endif
371     LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10);  /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
372     return ret.full;
373 #elif LV_COLOR_DEPTH == 16
374     return color.full;
375 #elif LV_COLOR_DEPTH == 32
376     lv_color16_t ret;
377     LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3);   /* 8 - 5  = 3*/
378 
379 #if LV_COLOR_16_SWAP == 0
380     LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /* 8 - 6  = 2*/
381 #else
382     LV_COLOR_SET_G16_SWAP(ret, ret.ch.green_h = (LV_COLOR_GET_G(color) >> 2); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
383 #endif
384     LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3);  /* 8 - 5  = 3*/
385     return ret.full;
386 #endif
387 }
388 
lv_color_to32(lv_color_t color)389 static inline uint32_t lv_color_to32(lv_color_t color)
390 {
391 #if LV_COLOR_DEPTH == 1
392     if(color.full == 0)
393         return 0xFF000000;
394     else
395         return 0xFFFFFFFF;
396 #elif LV_COLOR_DEPTH == 8
397     lv_color32_t ret;
398     LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36);     /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
399     LV_COLOR_SET_G32(ret, LV_COLOR_GET_G(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
400     LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85);   /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
401     LV_COLOR_SET_A32(ret, 0xFF);
402     return ret.full;
403 #elif LV_COLOR_DEPTH == 16
404     /**
405      * The floating point math for conversion is:
406      *  valueto = valuefrom * ( (2^bitsto - 1) / (float)(2^bitsfrom - 1) )
407      * The faster integer math for conversion is:
408      *  valueto = ( valuefrom * multiplier + adder ) >> divisor
409      *   multiplier = FLOOR( ( (2^bitsto - 1) << divisor ) / (float)(2^bitsfrom - 1) )
410      *
411      * Find the first divisor where ( adder >> divisor ) <= 0
412      *
413      * 5-bit to 8-bit: ( 31 * multiplier + adder ) >> divisor = 255
414      * divisor  multiplier  adder  min (0)  max (31)
415      *       0           8      7        7       255
416      *       1          16     14        7       255
417      *       2          32     28        7       255
418      *       3          65     25        3       255
419      *       4         131     19        1       255
420      *       5         263      7        0       255
421      *
422      * 6-bit to 8-bit: 255 = ( 63 * multiplier + adder ) >> divisor
423      * divisor  multiplier  adder  min (0)  max (63)
424      *       0           4      3        3       255
425      *       1           8      6        3       255
426      *       2          16     12        3       255
427      *       3          32     24        3       255
428      *       4          64     48        3       255
429      *       5         129     33        1       255
430      *       6         259      3        0       255
431      */
432 
433     lv_color32_t ret;
434     LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7) >> 5);
435     LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3) >> 6);
436     LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7) >> 5);
437     LV_COLOR_SET_A32(ret, 0xFF);
438     return ret.full;
439 #elif LV_COLOR_DEPTH == 32
440     return color.full;
441 #endif
442 }
443 
444 
445 //! @cond Doxygen_Suppress
446 
447 /**
448  * Mix two colors with a given ratio.
449  * @param c1 the first color to mix (usually the foreground)
450  * @param c2 the second color to mix (usually the background)
451  * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half`c2`
452  * @return the mixed color
453  */
lv_color_mix(lv_color_t c1,lv_color_t c2,uint8_t mix)454 LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
455 {
456     lv_color_t ret;
457 #if LV_COLOR_DEPTH != 1
458     /*LV_COLOR_DEPTH == 8, 16 or 32*/
459     LV_COLOR_SET_R(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) *
460                                         (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
461     LV_COLOR_SET_G(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) *
462                                         (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
463     LV_COLOR_SET_B(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) *
464                                         (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
465     LV_COLOR_SET_A(ret, 0xFF);
466 #else
467     /*LV_COLOR_DEPTH == 1*/
468     ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
469 #endif
470 
471     return ret;
472 }
473 
lv_color_premult(lv_color_t c,uint8_t mix,uint16_t * out)474 LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out)
475 {
476 #if LV_COLOR_DEPTH != 1
477     out[0] = (uint16_t) LV_COLOR_GET_R(c) * mix;
478     out[1] = (uint16_t) LV_COLOR_GET_G(c) * mix;
479     out[2] = (uint16_t) LV_COLOR_GET_B(c) * mix;
480 #else
481     (void) mix;
482     /*Pre-multiplication can't be used with 1 bpp*/
483     out[0] = LV_COLOR_GET_R(c);
484     out[1] = LV_COLOR_GET_G(c);
485     out[2] = LV_COLOR_GET_B(c);
486 #endif
487 
488 }
489 
490 
491 /**
492  * Mix two colors with a given ratio. It runs faster then `lv_color_mix` but requires some pre computation.
493  * @param c1 The first color. Should be preprocessed with `lv_color_premult(c1)`
494  * @param c2 The second color. As it is no pre computation required on it
495  * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half `c2`.
496  *            Should be modified like mix = `255 - mix`
497  * @return the mixed color
498  * @note 255 won't give clearly `c1`.
499  */
lv_color_mix_premult(uint16_t * premult_c1,lv_color_t c2,uint8_t mix)500 LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix)
501 {
502     lv_color_t ret;
503 #if LV_COLOR_DEPTH != 1
504     /*LV_COLOR_DEPTH == 8, 16 or 32*/
505     LV_COLOR_SET_R(ret, LV_MATH_UDIV255((uint16_t) premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
506     LV_COLOR_SET_G(ret, LV_MATH_UDIV255((uint16_t) premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
507     LV_COLOR_SET_B(ret, LV_MATH_UDIV255((uint16_t) premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
508     LV_COLOR_SET_A(ret, 0xFF);
509 #else
510     /*LV_COLOR_DEPTH == 1*/
511     /*Restore color1*/
512     lv_color_t c1;
513     LV_COLOR_SET_R(c1, premult_c1[0]);
514     LV_COLOR_SET_G(c1, premult_c1[1]);
515     LV_COLOR_SET_B(c1, premult_c1[2]);
516     ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
517 #endif
518 
519     return ret;
520 }
521 
522 
523 /**
524  * Mix two colors. Both color can have alpha value. It requires ARGB888 colors.
525  * @param bg_color background color
526  * @param bg_opa alpha of the background color
527  * @param fg_color foreground color
528  * @param fg_opa alpha of the foreground color
529  * @param res_color the result color
530  * @param res_opa the result opacity
531  */
lv_color_mix_with_alpha(lv_color_t bg_color,lv_opa_t bg_opa,lv_color_t fg_color,lv_opa_t fg_opa,lv_color_t * res_color,lv_opa_t * res_opa)532 LV_ATTRIBUTE_FAST_MEM static inline void lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa,
533                                                                  lv_color_t fg_color, lv_opa_t fg_opa,
534                                                                  lv_color_t * res_color, lv_opa_t * res_opa)
535 {
536     /* Pick the foreground if it's fully opaque or the Background is fully transparent*/
537     if(fg_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
538         res_color->full = fg_color.full;
539         *res_opa = fg_opa;
540     }
541     /*Transparent foreground: use the Background*/
542     else if(fg_opa <= LV_OPA_MIN) {
543         res_color->full = bg_color.full;
544         *res_opa = bg_opa;
545     }
546     /*Opaque background: use simple mix*/
547     else if(bg_opa >= LV_OPA_MAX) {
548         *res_color = lv_color_mix(fg_color, bg_color, fg_opa);
549         *res_opa = LV_OPA_COVER;
550     }
551     /*Both colors have alpha. Expensive calculation need to be applied*/
552     else {
553         /*Save the parameters and the result. If they will be asked again don't compute again*/
554         static lv_opa_t fg_opa_save     = 0;
555         static lv_opa_t bg_opa_save     = 0;
556         static lv_color_t fg_color_save = {.full = 0};
557         static lv_color_t bg_color_save = {.full = 0};
558         static lv_color_t res_color_saved = {.full = 0};
559         static lv_opa_t res_opa_saved = 0;
560 
561         if(fg_opa != fg_opa_save || bg_opa != bg_opa_save || fg_color.full != fg_color_save.full ||
562            bg_color.full != bg_color_save.full) {
563             fg_opa_save        = fg_opa;
564             bg_opa_save        = bg_opa;
565             fg_color_save.full = fg_color.full;
566             bg_color_save.full = bg_color.full;
567             /*Info:
568              * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/
569             res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8);
570             if(res_opa_saved == 0) {
571                 while(1)
572                     ;
573             }
574             lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved;
575             res_color_saved  = lv_color_mix(fg_color, bg_color, ratio);
576 
577         }
578 
579         res_color->full = res_color_saved.full;
580         *res_opa = res_opa_saved;
581     }
582 }
583 
584 //! @endcond
585 
586 /**
587  * Get the brightness of a color
588  * @param color a color
589  * @return the brightness [0..255]
590  */
lv_color_brightness(lv_color_t color)591 static inline uint8_t lv_color_brightness(lv_color_t color)
592 {
593     lv_color32_t c32;
594     c32.full        = lv_color_to32(color);
595     uint16_t bright = (uint16_t)(3u * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4u * LV_COLOR_GET_G32(c32));
596     return (uint8_t)(bright >> 3);
597 }
598 
599 #if defined(__cplusplus) && !defined(_LV_COLOR_HAS_MODERN_CPP)
600 /**
601 * MSVC compiler's definition of the __cplusplus indicating 199711L regardless to C++ standard version
602 * see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-cplusplus
603 * so we use _MSC_VER macro unstead of __cplusplus
604 */
605 #ifdef _MSC_VER
606 #if _MSC_VER >= 1900 /* Visual Studio 2015 */
607 #define _LV_COLOR_HAS_MODERN_CPP 1
608 #endif
609 #else
610 #if __cplusplus >= 201103L
611 #define _LV_COLOR_HAS_MODERN_CPP 1
612 #endif
613 #endif
614 #endif /* __cplusplus */
615 
616 #ifndef _LV_COLOR_HAS_MODERN_CPP
617 #define _LV_COLOR_HAS_MODERN_CPP 0
618 #endif
619 
620 #if _LV_COLOR_HAS_MODERN_CPP
621 /* Fix msvc compiler error C4576 inside C++ code */
622 #define _LV_COLOR_MAKE_TYPE_HELPER lv_color_t
623 #else
624 #define _LV_COLOR_MAKE_TYPE_HELPER (lv_color_t)
625 #endif
626 
627 /* The most simple macro to create a color from R,G and B values */
628 #if LV_COLOR_DEPTH == 1
629 #define LV_COLOR_MAKE(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{.full = (uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))})
630 #elif LV_COLOR_DEPTH == 8
631 #define LV_COLOR_MAKE(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}})
632 #elif LV_COLOR_DEPTH == 16
633 #if LV_COLOR_16_SWAP == 0
634 #define LV_COLOR_MAKE(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x3FU), (uint16_t)((r8 >> 3) & 0x1FU)}})
635 #else
636 #define LV_COLOR_MAKE(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint16_t)((g8 >> 5) & 0x7U), (uint16_t)((r8 >> 3) & 0x1FU), (uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x7U)}})
637 #endif
638 #elif LV_COLOR_DEPTH == 32
639 #define LV_COLOR_MAKE(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
640 #endif
641 
lv_color_make(uint8_t r,uint8_t g,uint8_t b)642 static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b)
643 {
644     return LV_COLOR_MAKE(r, g, b);
645 }
646 
lv_color_hex(uint32_t c)647 static inline lv_color_t lv_color_hex(uint32_t c)
648 {
649     return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF));
650 }
651 
lv_color_hex3(uint32_t c)652 static inline lv_color_t lv_color_hex3(uint32_t c)
653 {
654     return lv_color_make((uint8_t)(((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), (uint8_t)((c & 0xF0) | ((c & 0xF0) >> 4)),
655                          (uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
656 }
657 
658 
659 //! @cond Doxygen_Suppress
660 //!
661 LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num);
662 
663 //! @endcond
664 lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl);
665 
666 lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl);
667 
668 /**
669  * Convert a HSV color to RGB
670  * @param h hue [0..359]
671  * @param s saturation [0..100]
672  * @param v value [0..100]
673  * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
674  */
675 lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
676 
677 /**
678  * Convert a 32-bit RGB color to HSV
679  * @param r8 8-bit red
680  * @param g8 8-bit green
681  * @param b8 8-bit blue
682  * @return the given RGB color in HSV
683  */
684 lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8);
685 
686 /**
687  * Convert a color to HSV
688  * @param color color
689  * @return the given color in HSV
690  */
691 lv_color_hsv_t lv_color_to_hsv(lv_color_t color);
692 
693 
694 /**********************
695  *      MACROS
696  **********************/
697 
698 #ifdef __cplusplus
699 } /* extern "C" */
700 #endif
701 
702 #endif /*USE_COLOR*/
703