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*/