mirror of
https://github.com/CTCaer/hekate
synced 2024-09-07 00:29:00 +00:00
![CTCaer](/assets/img/avatar_default.png)
BDK will allow developers to use the full collection of drivers, with limited editing, if any, for making payloads for Nintendo Switch. Using a single source for everything will also help decoupling Switch specific code and easily port it to other Tegra X1/X1+ platforms. And maybe even to lower targets. Everything is now centrilized into bdk folder. Every module or project can utilize it by simply including it. This is just the start and it will continue to improve.
456 lines
13 KiB
C
456 lines
13 KiB
C
/*
|
|
* Copyright (c) 2019 CTCaer
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @file lv_color.h
|
|
*
|
|
*/
|
|
|
|
#ifndef LV_COLOR_H
|
|
#define LV_COLOR_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#ifdef LV_CONF_INCLUDE_SIMPLE
|
|
#include "lv_conf.h"
|
|
#else
|
|
#include "../../lv_conf.h"
|
|
#endif
|
|
|
|
/*Error checking*/
|
|
#if LV_COLOR_DEPTH == 24
|
|
#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)"
|
|
#endif
|
|
|
|
#if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0
|
|
#error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h"
|
|
#endif
|
|
|
|
#if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0
|
|
#error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h"
|
|
#endif
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
#define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF,0xFF,0xFF)
|
|
#define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0,0xC0,0xC0)
|
|
#define LV_COLOR_GRAY LV_COLOR_MAKE(0x80,0x80,0x80)
|
|
#define LV_COLOR_BLACK LV_COLOR_MAKE(0x00,0x00,0x00)
|
|
#define LV_COLOR_RED LV_COLOR_MAKE(0xFF,0x00,0x00)
|
|
#define LV_COLOR_MAROON LV_COLOR_MAKE(0x80,0x00,0x00)
|
|
#define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF,0xFF,0x00)
|
|
#define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80,0x80,0x00)
|
|
#define LV_COLOR_LIME LV_COLOR_MAKE(0x00,0xFF,0x00)
|
|
#define LV_COLOR_GREEN LV_COLOR_MAKE(0x00,0x80,0x00)
|
|
#define LV_COLOR_CYAN LV_COLOR_MAKE(0x00,0xFF,0xFF)
|
|
#define LV_COLOR_AQUA LV_COLOR_CYAN
|
|
#define LV_COLOR_TEAL LV_COLOR_MAKE(0x00,0x80,0x80)
|
|
#define LV_COLOR_BLUE LV_COLOR_MAKE(0x00,0x00,0xFF)
|
|
#define LV_COLOR_NAVY LV_COLOR_MAKE(0x00,0x00,0x80)
|
|
#define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF,0x00,0xFF)
|
|
#define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80,0x00,0x80)
|
|
#define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF,0xA5,0x00)
|
|
|
|
enum {
|
|
LV_OPA_TRANSP = 0,
|
|
LV_OPA_0 = 0,
|
|
LV_OPA_10 = 25,
|
|
LV_OPA_20 = 51,
|
|
LV_OPA_30 = 76,
|
|
LV_OPA_40 = 102,
|
|
LV_OPA_50 = 127,
|
|
LV_OPA_60 = 153,
|
|
LV_OPA_70 = 178,
|
|
LV_OPA_80 = 204,
|
|
LV_OPA_90 = 229,
|
|
LV_OPA_100 = 255,
|
|
LV_OPA_COVER = 255,
|
|
};
|
|
|
|
#define LV_OPA_MIN 16 /*Opacities below this will be transparent*/
|
|
#define LV_OPA_MAX 251 /*Opacities above this will fully cover*/
|
|
|
|
#if LV_COLOR_DEPTH == 1
|
|
#define LV_COLOR_SIZE 8
|
|
#elif LV_COLOR_DEPTH == 8
|
|
#define LV_COLOR_SIZE 8
|
|
#elif LV_COLOR_DEPTH == 16
|
|
#define LV_COLOR_SIZE 16
|
|
#elif LV_COLOR_DEPTH == 32
|
|
#define LV_COLOR_SIZE 32
|
|
#else
|
|
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
|
#endif
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
typedef union
|
|
{
|
|
uint8_t blue :1;
|
|
uint8_t green :1;
|
|
uint8_t red :1;
|
|
uint8_t full :1;
|
|
} lv_color1_t;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t blue :2;
|
|
uint8_t green :3;
|
|
uint8_t red :3;
|
|
};
|
|
uint8_t full;
|
|
} lv_color8_t;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
#if LV_COLOR_16_SWAP == 0
|
|
uint16_t blue :5;
|
|
uint16_t green :6;
|
|
uint16_t red :5;
|
|
#else
|
|
uint16_t green_h :3;
|
|
uint16_t red :5;
|
|
uint16_t blue :5;
|
|
uint16_t green_l :3;
|
|
#endif
|
|
};
|
|
uint16_t full;
|
|
} lv_color16_t;
|
|
|
|
typedef union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t blue;
|
|
uint8_t green;
|
|
uint8_t red;
|
|
uint8_t alpha;
|
|
};
|
|
uint32_t full;
|
|
} lv_color32_t;
|
|
|
|
#if LV_COLOR_DEPTH == 1
|
|
typedef uint8_t lv_color_int_t;
|
|
typedef lv_color1_t lv_color_t;
|
|
#elif LV_COLOR_DEPTH == 8
|
|
typedef uint8_t lv_color_int_t;
|
|
typedef lv_color8_t lv_color_t;
|
|
#elif LV_COLOR_DEPTH == 16
|
|
typedef uint16_t lv_color_int_t;
|
|
typedef lv_color16_t lv_color_t;
|
|
#elif LV_COLOR_DEPTH == 32
|
|
typedef uint32_t lv_color_int_t;
|
|
typedef lv_color32_t lv_color_t;
|
|
#else
|
|
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
|
#endif
|
|
|
|
typedef uint8_t lv_opa_t;
|
|
|
|
typedef struct
|
|
{
|
|
uint16_t h;
|
|
uint8_t s;
|
|
uint8_t v;
|
|
} lv_color_hsv_t;
|
|
|
|
/**********************
|
|
* GLOBAL PROTOTYPES
|
|
**********************/
|
|
|
|
/*In color conversations:
|
|
* - When converting to bigger color type the LSB weight of 1 LSB is calculated
|
|
* E.g. 16 bit Red has 5 bits
|
|
* 8 bit Red has 2 bits
|
|
* ----------------------
|
|
* 8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10
|
|
*
|
|
* - When calculating to smaller color type simply shift out the LSBs
|
|
* E.g. 8 bit Red has 2 bits
|
|
* 16 bit Red has 5 bits
|
|
* ----------------------
|
|
* Shift right with 5 - 3 = 2
|
|
*/
|
|
|
|
static inline uint8_t lv_color_to1(lv_color_t color)
|
|
{
|
|
#if LV_COLOR_DEPTH == 1
|
|
return color.full;
|
|
#elif LV_COLOR_DEPTH == 8
|
|
if((color.red & 0x4) ||
|
|
(color.green & 0x4) ||
|
|
(color.blue & 0x2)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
#elif LV_COLOR_DEPTH == 16
|
|
# if LV_COLOR_16_SWAP == 0
|
|
if((color.red & 0x10) ||
|
|
(color.green & 0x20) ||
|
|
(color.blue & 0x10)) {
|
|
return 1;
|
|
# else
|
|
if((color.red & 0x10) ||
|
|
(color.green_h & 0x20) ||
|
|
(color.blue & 0x10)) {
|
|
return 1;
|
|
# endif
|
|
} else {
|
|
return 0;
|
|
}
|
|
#elif LV_COLOR_DEPTH == 32
|
|
if((color.red & 0x80) ||
|
|
(color.green & 0x80) ||
|
|
(color.blue & 0x80)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static inline uint8_t lv_color_to8(lv_color_t color)
|
|
{
|
|
#if LV_COLOR_DEPTH == 1
|
|
if(color.full == 0) return 0;
|
|
else return 0xFF;
|
|
#elif LV_COLOR_DEPTH == 8
|
|
return color.full;
|
|
#elif LV_COLOR_DEPTH == 16
|
|
|
|
# if LV_COLOR_16_SWAP == 0
|
|
lv_color8_t ret;
|
|
ret.red = color.red >> 2; /* 5 - 3 = 2*/
|
|
ret.green = color.green >> 3; /* 6 - 3 = 3*/
|
|
ret.blue = color.blue >> 3; /* 5 - 2 = 3*/
|
|
return ret.full;
|
|
# else
|
|
lv_color8_t ret;
|
|
ret.red = color.red >> 2; /* 5 - 3 = 2*/
|
|
ret.green = color.green_h; /* 6 - 3 = 3*/
|
|
ret.blue = color.blue >> 3; /* 5 - 2 = 3*/
|
|
return ret.full;
|
|
# endif
|
|
#elif LV_COLOR_DEPTH == 32
|
|
lv_color8_t ret;
|
|
ret.red = color.red >> 5; /* 8 - 3 = 5*/
|
|
ret.green = color.green >> 5; /* 8 - 3 = 5*/
|
|
ret.blue = color.blue >> 6; /* 8 - 2 = 6*/
|
|
return ret.full;
|
|
#endif
|
|
}
|
|
|
|
static inline uint16_t lv_color_to16(lv_color_t color)
|
|
{
|
|
#if LV_COLOR_DEPTH == 1
|
|
if(color.full == 0) return 0;
|
|
else return 0xFFFF;
|
|
#elif LV_COLOR_DEPTH == 8
|
|
lv_color16_t ret;
|
|
# if LV_COLOR_16_SWAP == 0
|
|
ret.red = color.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
|
|
ret.green = color.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
|
|
ret.blue = color.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
|
|
# else
|
|
ret.red = color.red * 4;
|
|
uint8_t g_tmp = color.green * 9;
|
|
ret.green_h = (g_tmp & 0x1F) >> 3;
|
|
ret.green_l = g_tmp & 0x07;
|
|
ret.blue = color.blue * 10;
|
|
# endif
|
|
return ret.full;
|
|
#elif LV_COLOR_DEPTH == 16
|
|
return color.full;
|
|
#elif LV_COLOR_DEPTH == 32
|
|
lv_color16_t ret;
|
|
# if LV_COLOR_16_SWAP == 0
|
|
ret.red = color.red >> 3; /* 8 - 5 = 3*/
|
|
ret.green = color.green >> 2; /* 8 - 6 = 2*/
|
|
ret.blue = color.blue >> 3; /* 8 - 5 = 3*/
|
|
# else
|
|
ret.red = color.red >> 3;
|
|
ret.green_h = (color.green & 0xE0) >> 5;
|
|
ret.green_l = (color.green & 0x1C) >> 2;
|
|
ret.blue = color.blue >> 3;
|
|
# endif
|
|
return ret.full;
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t lv_color_to32(lv_color_t color)
|
|
{
|
|
#if LV_COLOR_DEPTH == 1
|
|
if(color.full == 0) return 0;
|
|
else return 0xFFFFFFFF;
|
|
#elif LV_COLOR_DEPTH == 8
|
|
lv_color32_t ret;
|
|
ret.red = color.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
|
ret.green = color.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
|
ret.blue = color.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
|
|
ret.alpha = 0xFF;
|
|
return ret.full;
|
|
#elif LV_COLOR_DEPTH == 16
|
|
# if LV_COLOR_16_SWAP == 0
|
|
lv_color32_t ret;
|
|
ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
|
ret.green = color.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
|
ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
|
ret.alpha = 0xFF;
|
|
return ret.full;
|
|
# else
|
|
lv_color32_t ret;
|
|
ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
|
ret.green = ((color.green_h << 3) + color.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
|
ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
|
ret.alpha = 0xFF;
|
|
return ret.full;
|
|
# endif
|
|
#elif LV_COLOR_DEPTH == 32
|
|
return color.full;
|
|
#endif
|
|
}
|
|
|
|
static inline lv_color_t lv_color_mix(const lv_color_t c1, const lv_color_t c2, uint8_t mix)
|
|
{
|
|
lv_color_t ret;
|
|
#if LV_COLOR_DEPTH != 1 && LV_COLOR_DEPTH != 32
|
|
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
|
ret.red = (uint16_t)((uint16_t) c1.red * mix + (c2.red * (255 - mix))) >> 8;
|
|
# if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
|
/*If swapped Green is in 2 parts*/
|
|
uint16_t g_1 = (c1.green_h << 3) + c1.green_l;
|
|
uint16_t g_2 = (c2.green_h << 3) + c2.green_l;
|
|
uint16_t g_out = (uint16_t)((uint16_t) g_1 * mix + (g_2 * (255 - mix))) >> 8;
|
|
ret.green_h = g_out >> 3;
|
|
ret.green_l = g_out & 0x7;
|
|
# else
|
|
ret.green = (uint16_t)((uint16_t) c1.green * mix + (c2.green * (255 - mix))) >> 8;
|
|
# endif
|
|
ret.blue = (uint16_t)((uint16_t) c1.blue * mix + (c2.blue * (255 - mix))) >> 8;
|
|
#else
|
|
# if LV_COLOR_DEPTH == 32
|
|
uint32_t rb = (((c1.full & 0x00FF00FF) * mix) + ((c2.full & 0x00FF00FF) * (255 - mix))) >> 8;
|
|
uint32_t g = (((((c1.full & 0x0000FF00) >> 8) * mix) + (((c2.full & 0x0000FF00) >> 8) * (255 - mix))) >> 8) << 8;
|
|
ret.full = 0xFF000000 | (0x00FF00FF & rb) | (0x0000FF00 & g);
|
|
# else
|
|
/*LV_COLOR_DEPTH == 1*/
|
|
ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
|
|
# endif
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Get the brightness of a color
|
|
* @param color a color
|
|
* @return the brightness [0..255]
|
|
*/
|
|
static inline uint8_t lv_color_brightness(lv_color_t color)
|
|
{
|
|
lv_color32_t c32;
|
|
c32.full = lv_color_to32(color);
|
|
uint16_t bright = 3 * c32.red + c32.blue + 4 * c32.green;
|
|
return (uint16_t) bright >> 3;
|
|
}
|
|
|
|
/* The most simple macro to create a color from R,G and B values
|
|
* The order of bit field is different on Big-endian and Little-endian machines*/
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
#if LV_COLOR_DEPTH == 1
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
|
#elif LV_COLOR_DEPTH == 8
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}})
|
|
#elif LV_COLOR_DEPTH == 16
|
|
# if LV_COLOR_16_SWAP == 0
|
|
# define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}})
|
|
# else
|
|
# define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}})
|
|
# endif
|
|
#elif LV_COLOR_DEPTH == 32
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
|
|
#endif
|
|
#else
|
|
#if LV_COLOR_DEPTH == 1
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(r8 >> 7 | g8 >> 7 | b8 >> 7)})
|
|
#elif LV_COLOR_DEPTH == 8
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{r8 >> 6, g8 >> 5, b8 >> 5}})
|
|
#elif LV_COLOR_DEPTH == 16
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{r8 >> 3, g8 >> 2, b8 >> 3}})
|
|
#elif LV_COLOR_DEPTH == 32
|
|
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{0xff, r8, g8, b8}}) /*Fix 0xff alpha*/
|
|
#endif
|
|
#endif
|
|
|
|
#if LV_COLOR_DEPTH == 32 // Concatenate into one 32-bit set.
|
|
#define LV_COLOR_HEX(c) ((lv_color_t){.full = (c | 0xFF000000)})
|
|
#else
|
|
#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)c >> 16) & 0xFF), \
|
|
((uint32_t)((uint32_t)c >> 8) & 0xFF), \
|
|
((uint32_t) c & 0xFF))
|
|
#endif
|
|
|
|
/*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/
|
|
#define LV_COLOR_HEX3(c) LV_COLOR_MAKE((((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), \
|
|
((uint32_t)(c & 0xF0) | ((c & 0xF0) >> 4)), \
|
|
((uint32_t)(c & 0xF) | ((c & 0xF) << 4)))
|
|
|
|
|
|
/**
|
|
* Convert a HSV color to RGB
|
|
* @param h hue [0..359]
|
|
* @param s saturation [0..100]
|
|
* @param v value [0..100]
|
|
* @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
|
|
*/
|
|
lv_color_t lv_color_hsv_to_rgb(uint16_t hue, uint8_t sat, uint8_t val);
|
|
|
|
/**
|
|
* Convert an RGB color to HSV
|
|
* @param r red
|
|
* @param g green
|
|
* @param b blue
|
|
* @return the given RGB color n HSV
|
|
*/
|
|
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b);
|
|
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#endif /*USE_COLOR*/
|