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