acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_color.h (23466B)

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