hekate/bdk/libs/lvgl/lv_draw/lv_draw_rbasic.c
CTCaer 185526d134 Introducing Bootloader Development Kit (BDK)
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.
2020-06-14 15:25:21 +03:00

270 lines
9 KiB
C

/**
* @file lv_draw_rbasic.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_rbasic.h"
#if USE_LV_REAL_DRAW != 0
#include "../lv_hal/lv_hal_disp.h"
#include "../lv_misc/lv_font.h"
#include "lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static lv_color_t letter_bg_color;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Put a pixel to the display
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
* @param mask_p the pixel will be drawn on this area
* @param color color of the pixel
* @param opa opacity (ignored, only for compatibility with lv_vpx)
*/
void lv_rpx(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t color, lv_opa_t opa)
{
(void)opa; /*Opa is used only for compatibility with lv_vpx*/
lv_area_t area;
area.x1 = x;
area.y1 = y;
area.x2 = x;
area.y2 = y;
lv_rfill(&area, mask_p, color, LV_OPA_COVER);
}
/**
* Fill an area on the display
* @param cords_p coordinates of the area to fill
* @param mask_p fill only o this mask
* @param color fill color
* @param opa opacity (ignored, only for compatibility with lv_vfill)
*/
void lv_rfill(const lv_area_t * cords_p, const lv_area_t * mask_p,
lv_color_t color, lv_opa_t opa)
{
(void)opa; /*Opa is used only for compatibility with lv_vfill*/
lv_area_t masked_area;
bool union_ok = true;
if(mask_p != NULL) {
union_ok = lv_area_intersect(&masked_area, cords_p, mask_p);
} else {
lv_area_t scr_area;
lv_area_set(&scr_area, 0, 0, LV_HOR_RES - 1, LV_VER_RES - 1);
union_ok = lv_area_intersect(&masked_area, cords_p, &scr_area);
}
if(union_ok != false) {
lv_disp_fill(masked_area.x1, masked_area.y1, masked_area.x2, masked_area.y2, color);
}
}
/**
* Draw a letter to the display
* @param pos_p left-top coordinate of the latter
* @param mask_p the letter will be drawn only on this area
* @param font_p pointer to font
* @param letter a letter to draw
* @param color color of letter
* @param opa opacity of letter (ignored, only for compatibility with lv_vletter)
*/
void lv_rletter(const lv_point_t * pos_p, const lv_area_t * mask_p,
const lv_font_t * font_p, uint32_t letter,
lv_color_t color, lv_opa_t opa)
{
(void)opa; /*Opa is used only for compatibility with lv_vletter*/
static uint8_t bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
static uint8_t bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
static uint8_t bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
68, 85, 102, 119,
136, 153, 170, 187,
204, 221, 238, 255
};
if(font_p == NULL) return;
uint8_t letter_w = lv_font_get_width(font_p, letter);
uint8_t letter_h = lv_font_get_height(font_p);
uint8_t bpp = lv_font_get_bpp(font_p, letter); /*Bit per pixel (1,2, 4 or 8)*/
uint8_t * bpp_opa_table;
uint8_t mask_init;
uint8_t mask;
switch(bpp) {
case 1:
bpp_opa_table = bpp1_opa_table;
mask_init = 0x80;
break;
case 2:
bpp_opa_table = bpp2_opa_table;
mask_init = 0xC0;
break;
case 4:
bpp_opa_table = bpp4_opa_table;
mask_init = 0xF0;
break;
case 8:
bpp_opa_table = NULL;
mask_init = 0xFF;
break; /*No opa table, pixel value will be used directly*/
default:
return; /*Invalid bpp. Can't render the letter*/
}
const uint8_t * map_p = lv_font_get_bitmap(font_p, letter);
if(map_p == NULL) return;
/*If the letter is completely out of mask don't draw it */
if(pos_p->x + letter_w < mask_p->x1 || pos_p->x > mask_p->x2 ||
pos_p->y + letter_h < mask_p->y1 || pos_p->y > mask_p->y2) return;
lv_coord_t col, row;
uint8_t col_bit;
uint8_t col_byte_cnt;
uint8_t width_byte_scr = letter_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/
if(letter_w & 0x7) width_byte_scr++;
uint8_t width_byte_bpp = (letter_w * bpp) >> 3; /*Letter width in byte. Real width in the font*/
if((letter_w * bpp) & 0x7) width_byte_bpp++;
/* Calculate the col/row start/end on the map*/
lv_coord_t col_start = pos_p->x >= mask_p->x1 ? 0 : mask_p->x1 - pos_p->x;
lv_coord_t col_end = pos_p->x + letter_w <= mask_p->x2 ? letter_w : mask_p->x2 - pos_p->x + 1;
lv_coord_t row_start = pos_p->y >= mask_p->y1 ? 0 : mask_p->y1 - pos_p->y;
lv_coord_t row_end = pos_p->y + letter_h <= mask_p->y2 ? letter_h : mask_p->y2 - pos_p->y + 1;
/*Move on the map too*/
map_p += (row_start * width_byte_bpp) + ((col_start * bpp) >> 3);
uint8_t letter_px;
for(row = row_start; row < row_end; row ++) {
col_byte_cnt = 0;
col_bit = (col_start * bpp) % 8;
mask = mask_init >> col_bit;
for(col = col_start; col < col_end; col ++) {
letter_px = (*map_p & mask) >> (8 - col_bit - bpp);
if(letter_px != 0) {
lv_rpx(pos_p->x + col, pos_p->y + row, mask_p, lv_color_mix(color, letter_bg_color, bpp == 8 ? letter_px : bpp_opa_table[letter_px]), LV_OPA_COVER);
}
if(col_bit < 8 - bpp) {
col_bit += bpp;
mask = mask >> bpp;
} else {
col_bit = 0;
col_byte_cnt ++;
mask = mask_init;
map_p ++;
}
}
map_p += (width_byte_bpp) - col_byte_cnt;
}
}
/**
* When the letter is ant-aliased it needs to know the background color
* @param bg_color the background color of the currently drawn letter
*/
void lv_rletter_set_background(lv_color_t color)
{
letter_bg_color = color;
}
/**
* Draw a color map to the display (image)
* @param cords_p coordinates the color map
* @param mask_p the map will drawn only on this area
* @param map_p pointer to a lv_color_t array
* @param opa opacity of the map (ignored, only for compatibility with 'lv_vmap')
* @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels
* @param alpha_byte true: extra alpha byte is inserted for every pixel (not supported, only l'v_vmap' can draw it)
* @param recolor mix the pixels with this color
* @param recolor_opa the intense of recoloring
*/
void lv_rmap(const lv_area_t * cords_p, const lv_area_t * mask_p,
const uint8_t * map_p, lv_opa_t opa, bool chroma_key, bool alpha_byte,
lv_color_t recolor, lv_opa_t recolor_opa)
{
if(alpha_byte) return; /*Pixel level opacity i not supported in real map drawing*/
(void)opa; /*opa is used only for compatibility with lv_vmap*/
lv_area_t masked_a;
bool union_ok;
union_ok = lv_area_intersect(&masked_a, cords_p, mask_p);
/*If there are common part of the mask and map then draw the map*/
if(union_ok == false) return;
/*Go to the first pixel*/
lv_coord_t map_width = lv_area_get_width(cords_p);
map_p += (masked_a.y1 - cords_p->y1) * map_width * sizeof(lv_color_t);
map_p += (masked_a.x1 - cords_p->x1) * sizeof(lv_color_t);
lv_coord_t row;
if(recolor_opa == LV_OPA_TRANSP && chroma_key == false) {
lv_coord_t mask_w = lv_area_get_width(&masked_a) - 1;
for(row = masked_a.y1; row <= masked_a.y2; row++) {
lv_disp_map(masked_a.x1, row, masked_a.x1 + mask_w, row, (lv_color_t *)map_p);
map_p += map_width * sizeof(lv_color_t); /*Next row on the map*/
}
} else {
lv_color_t chroma_key_color = LV_COLOR_TRANSP;
lv_coord_t col;
for(row = masked_a.y1; row <= masked_a.y2; row++) {
for(col = masked_a.x1; col <= masked_a.x2; col++) {
lv_color_t * px_color = (lv_color_t *) &map_p[(uint32_t)(col - masked_a.x1) * sizeof(lv_color_t)];
if(chroma_key && chroma_key_color.full == px_color->full) continue;
if(recolor_opa != LV_OPA_TRANSP) {
lv_color_t recolored_px = lv_color_mix(recolor, *px_color, recolor_opa);
lv_rpx(col, row, mask_p, recolored_px, LV_OPA_COVER);
} else {
lv_rpx(col, row, mask_p, *px_color, LV_OPA_COVER);
}
}
map_p += map_width * sizeof(lv_color_t); /*Next row on the map*/
}
}
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*USE_LV_REAL_DRAW*/