mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 17:53:45 +08:00
shadow fixes
This commit is contained in:
parent
88c31521e0
commit
ef7a8f3543
@ -144,6 +144,13 @@ typedef void * lv_anim_user_data_t;
|
||||
|
||||
/* 1: Enable shadow drawing*/
|
||||
#define LV_USE_SHADOW 1
|
||||
#if LV_USE_SHADOW
|
||||
/* Allow buffering some shadow calculation
|
||||
* LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer,
|
||||
* where shadow size is `shadow_width + radius`
|
||||
* Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
#endif
|
||||
|
||||
/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/
|
||||
#define LV_USE_BLEND_MODES 1
|
||||
|
@ -215,6 +215,15 @@
|
||||
#ifndef LV_USE_SHADOW
|
||||
#define LV_USE_SHADOW 1
|
||||
#endif
|
||||
#if LV_USE_SHADOW
|
||||
/* Allow buffering some shadow calculation
|
||||
* LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer,
|
||||
* where shadow size is `shadow_width + radius`
|
||||
* Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#ifndef LV_SHADOW_CACHE_SIZE
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/
|
||||
#ifndef LV_USE_BLEND_MODES
|
||||
@ -295,6 +304,11 @@
|
||||
#define LV_ATTRIBUTE_TASK_HANDLER
|
||||
#endif
|
||||
|
||||
/* Define a custom attribute to `lv_disp_flush_ready` function */
|
||||
#ifndef LV_ATTRIBUTE_FLUSH_READY
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
#endif
|
||||
|
||||
/* With size optimization (-Os) the compiler might not align data to
|
||||
* 4 or 8 byte boundary. This alignment will be explicitly applied where needed.
|
||||
* E.g. __attribute__((aligned(4))) */
|
||||
@ -394,10 +408,8 @@
|
||||
|
||||
/*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#ifndef LV_USE_ASSERT_MEM_INTEGRITY
|
||||
#ifndef LV_USE_ASSERT_MEM_INTEGRITY
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Check the strings.
|
||||
* Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow)
|
||||
@ -414,7 +426,7 @@
|
||||
|
||||
/*Check if the styles are properly initialized. (Fast)*/
|
||||
#ifndef LV_USE_ASSERT_STYLE
|
||||
#define LV_USE_ASSERT_STYLE 1
|
||||
#define LV_USE_ASSERT_STYLE 0
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DEBUG*/
|
||||
@ -768,7 +780,7 @@
|
||||
#endif
|
||||
#if LV_USE_LED
|
||||
#ifndef LV_LED_BRIGHT_MIN
|
||||
# define LV_LED_BRIGHT_MIN 100 /*Minimal brightness*/
|
||||
# define LV_LED_BRIGHT_MIN 60 /*Minimal brightness*/
|
||||
#endif
|
||||
#ifndef LV_LED_BRIGHT_MAX
|
||||
# define LV_LED_BRIGHT_MAX 255 /*Maximal brightness*/
|
||||
|
@ -19,7 +19,6 @@
|
||||
*********************/
|
||||
#define SHADOW_UPSACALE_SHIFT 6
|
||||
#define SHADOW_ENHANCE 1
|
||||
#define SHADOW_CACHE_SIZE 100
|
||||
#define SPLIT_LIMIT 50
|
||||
|
||||
/**********************
|
||||
@ -31,20 +30,24 @@
|
||||
**********************/
|
||||
static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static void draw_border(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static inline lv_color_t grad_get(lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i);
|
||||
#if LV_USE_SHADOW
|
||||
static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t s, lv_coord_t r);
|
||||
static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf);
|
||||
#endif
|
||||
static void draw_pattern(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
static void draw_value(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static uint8_t sh_cache[SHADOW_CACHE_SIZE * SHADOW_CACHE_SIZE];
|
||||
#if LV_USE_SHADOW && LV_SHADOW_CACHE_SIZE
|
||||
static uint8_t sh_cache[LV_SHADOW_CACHE_SIZE * LV_SHADOW_CACHE_SIZE];
|
||||
static int32_t sh_cache_size = -1;
|
||||
static int32_t sh_cache_r = -1;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -85,8 +88,10 @@ void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc)
|
||||
void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return;
|
||||
|
||||
#if LV_USE_SHADOW
|
||||
draw_shadow(coords, clip, dsc);
|
||||
#endif
|
||||
|
||||
draw_outline(coords, clip, dsc);
|
||||
draw_bg(coords, clip, dsc);
|
||||
draw_pattern(coords, clip, dsc);
|
||||
@ -558,7 +563,7 @@ static inline lv_color_t grad_get(lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coo
|
||||
lv_opa_t mix = (i * 255) / d;
|
||||
return lv_color_mix(dsc->bg_grad_color, dsc->bg_color, mix);
|
||||
}
|
||||
|
||||
#if LV_USE_SHADOW
|
||||
static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
/*Check whether the shadow is visible*/
|
||||
@ -629,19 +634,30 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
|
||||
lv_opa_t * sh_buf;
|
||||
|
||||
#if LV_SHADOW_CACHE_SIZE
|
||||
if(sh_cache_size == corner_size && sh_cache_r == r_sh) {
|
||||
/*Use the cache if available*/
|
||||
sh_buf = lv_mem_buf_get(corner_size * corner_size);
|
||||
lv_memcpy(sh_buf, sh_cache, corner_size * corner_size);
|
||||
} else {
|
||||
/*A larger buffer is required for calculation */
|
||||
sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t));
|
||||
shadow_draw_corner_buf(&sh_rect_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh);
|
||||
|
||||
/*Cache the corner if it fits into the cache size*/
|
||||
if(corner_size * corner_size < sizeof(sh_cache)) {
|
||||
lv_memcpy(sh_cache, sh_buf, corner_size * corner_size);
|
||||
sh_cache_size = corner_size;
|
||||
sh_cache_r = r_sh;
|
||||
}
|
||||
}
|
||||
#else
|
||||
sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t));
|
||||
shadow_draw_corner_buf(&sh_rect_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh);
|
||||
#endif
|
||||
|
||||
lv_coord_t h_half = sh_area.y1 + lv_area_get_height(&sh_area) / 2;
|
||||
lv_coord_t w_half = sh_area.x1 + lv_area_get_width(&sh_area) / 2;
|
||||
|
||||
bool simple_mode = true;
|
||||
if(lv_draw_mask_get_cnt() > 0) simple_mode = false;
|
||||
@ -670,29 +686,34 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
lv_area_t ca;
|
||||
bool has_com = lv_area_intersect(&ca, &a, clip);
|
||||
if(has_com) {
|
||||
/*Avoid overlap in the middle with large radius*/
|
||||
if(ca.y2 > h_half) ca.y2 = h_half;
|
||||
if(ca.x1 <= w_half) ca.x1 = w_half + 1;
|
||||
|
||||
lv_coord_t h = lv_area_get_height(&ca);
|
||||
lv_coord_t w = lv_area_get_width(&ca);
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (ca.y1 - a.y1);
|
||||
if(w > 0) {
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (ca.y1 - a.y1);
|
||||
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y2 = fa.y1;
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y2 = fa.y1;
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1++;
|
||||
fa.y2++;
|
||||
sh_buf_tmp += corner_size;
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1++;
|
||||
fa.y2++;
|
||||
sh_buf_tmp += corner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Draw the bottom right corner*/
|
||||
a.x2 = sh_area.x2;
|
||||
a.x1 = a.x2 - corner_size + 1;
|
||||
@ -701,25 +722,32 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
|
||||
has_com = lv_area_intersect(&ca, &a, clip);
|
||||
if(has_com) {
|
||||
/*Avoid overlap in the middle with large radius*/
|
||||
if(ca.y1 <= h_half) ca.y1 = h_half + 1;
|
||||
if(ca.x1 <= w_half) ca.x1 = w_half + 1;
|
||||
|
||||
lv_coord_t h = lv_area_get_height(&ca);
|
||||
lv_coord_t w = lv_area_get_width(&ca);
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (a.y2 - ca.y2);
|
||||
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y1 = fa.y2; /*Fill from bottom to top*/
|
||||
if(w > 0) {
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (a.y2 - ca.y2);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y1 = fa.y2; /*Fill from bottom to top*/
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1--;
|
||||
fa.y2--;
|
||||
sh_buf_tmp += corner_size;
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1--;
|
||||
fa.y2--;
|
||||
sh_buf_tmp += corner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -783,25 +811,31 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
|
||||
has_com = lv_area_intersect(&ca, &a, clip);
|
||||
if(has_com) {
|
||||
/*Avoid overlap in the middle with large radius*/
|
||||
if(ca.y2 > h_half) ca.y2 = h_half;
|
||||
if(ca.x2 > w_half) ca.x2 = w_half;
|
||||
|
||||
lv_coord_t h = lv_area_get_height(&ca);
|
||||
lv_coord_t w = lv_area_get_width(&ca);
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (ca.y1 - a.y1);
|
||||
if(w > 0) {
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (ca.y1 - a.y1);
|
||||
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y2 = fa.y1;
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y2 = fa.y1;
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1++;
|
||||
fa.y2++;
|
||||
sh_buf_tmp += corner_size;
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1++;
|
||||
fa.y2++;
|
||||
sh_buf_tmp += corner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,29 +847,34 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
|
||||
has_com = lv_area_intersect(&ca, &a, clip);
|
||||
if(has_com) {
|
||||
/*Avoid overlap in the middle with large radius*/
|
||||
if(ca.y1 <= h_half) ca.y1 = h_half + 1;
|
||||
if(ca.x2 > w_half) ca.x2 = w_half;
|
||||
lv_coord_t h = lv_area_get_height(&ca);
|
||||
lv_coord_t w = lv_area_get_width(&ca);
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (a.y2 - ca.y2);
|
||||
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y1 = fa.y2; /*Fill from bottom to top*/
|
||||
if(w > 0) {
|
||||
sh_buf_tmp = sh_buf + (ca.x1 - a.x1);
|
||||
sh_buf_tmp += corner_size * (a.y2 - ca.y2);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
lv_area_t fa;
|
||||
lv_area_copy(&fa, &ca);
|
||||
fa.y1 = fa.y2; /*Fill from bottom to top*/
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(mask_buf, sh_buf_tmp, w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, fa.x1, fa.y1, w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
|
||||
lv_blend_fill(clip, &fa, dsc->shadow_color, mask_buf,
|
||||
mask_res, opa, dsc->shadow_blend_mode);
|
||||
fa.y1--;
|
||||
fa.y2--;
|
||||
sh_buf_tmp += corner_size;
|
||||
}
|
||||
fa.y1--;
|
||||
fa.y2--;
|
||||
sh_buf_tmp += corner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Fill the left side*/
|
||||
a.x1 = sh_area.x1;
|
||||
a.x2 = a.x1 + corner_size - 1;
|
||||
@ -953,7 +992,6 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Draw the middle area*/
|
||||
a.x1 = sh_area.x1 + corner_size;
|
||||
a.x2 = sh_area.x2 - corner_size;
|
||||
@ -986,6 +1024,13 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
|
||||
lv_mem_buf_release(sh_buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a blurred corner
|
||||
* @param coords Coordinates of the shadow
|
||||
* @param sh_buf a buffer to store the result. It's size should be `(sw + r)^2 * 2`
|
||||
* @param sw shadow width
|
||||
* @param r radius
|
||||
*/
|
||||
static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, lv_coord_t sw, lv_coord_t r)
|
||||
{
|
||||
int32_t sw_ori = sw;
|
||||
@ -1140,7 +1185,7 @@ static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups
|
||||
lv_mem_buf_release(sh_ups_blur_buf);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static void draw_outline(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user