1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

fix(draw): rendering issues for vertical gradient with and without dithering (#3034)

This commit is contained in:
X-Ryl669 2022-01-22 15:43:37 +01:00 committed by GitHub
parent e143788903
commit 1f9d3892a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 21 deletions

View File

@ -54,7 +54,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_hor(lv_gradient_cache_t * grad, lv_
/*The apply the algorithm for this patch*/
for(lv_coord_t j = 0; j < w; j++) {
int8_t factor = dither_ordered_threshold_matrix[(y & 7) * 8 + ((j) & 7)] - 32;
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, j - 4, grad->hmap_size)];
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, j - 4, grad->size)];
lv_color32_t t;
t.ch.red = LV_CLAMP(0, tmp.ch.red + factor, 255);
t.ch.green = LV_CLAMP(0, tmp.ch.green + factor, 255);
@ -74,7 +74,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_ver(lv_gradient_cache_t * grad, lv_
Then we compute a complete row of ordered dither and store it in out. */
/*Extract patch for working with, selected pseudo randomly*/
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, y - 4, grad->hmap_size)];
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, y - 4, grad->size)];
/*The apply the algorithm for this patch*/
for(lv_coord_t j = 0; j < 8; j++) {
@ -116,10 +116,10 @@ LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(lv_gradient_cache_t * grad, lv
#define FS_COMPUTE_ERROR(e) { coef[0] = (e<<3) - e; coef[1] = (e<<2) - e; coef[2] = (e<<2) + e; coef[3] = e; }
#define FS_COMPONENTS(A, OP, B, C) A.ch.red = LV_CLAMP(0, A.ch.red OP B.r OP C.r, 255); A.ch.green = LV_CLAMP(0, A.ch.green OP B.g OP C.g, 255); A.ch.blue = LV_CLAMP(0, A.ch.blue OP B.b OP C.b, 255);
#define FS_QUANT_ERROR(e, t, q) { lv_color32_t u; u.full = lv_color_to32(q); e.r = (int8_t)(t.ch.red - u.ch.red); e.g = (int8_t)(t.ch.green - u.ch.green); e.b = (int8_t)(t.ch.blue - u.ch.blue); }
lv_scolor24_t next_px_err = {0}, next_l = grad->error_acc[1], error;
lv_scolor24_t next_px_err = {0}, next_l = {0}, error;
/*First last pixel are not dithered */
grad->map[0] = lv_color_hex(grad->hmap[0].full);
for(lv_coord_t x = 1; x < grad->hmap_size - 1; x++) {
for(lv_coord_t x = 1; x < grad->size - 1; x++) {
lv_color32_t t = grad->hmap[x];
lv_color_t q;
/*Add error term*/
@ -150,7 +150,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(lv_gradient_cache_t * grad, lv
grad->map[x] = q;
}
grad->map[grad->hmap_size - 1] = lv_color_hex(grad->hmap[grad->hmap_size - 1].full);
grad->map[grad->size - 1] = lv_color_hex(grad->hmap[grad->size - 1].full);
}
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_ver(lv_gradient_cache_t * grad, lv_coord_t xs, lv_coord_t y, lv_coord_t w)

View File

@ -72,11 +72,11 @@ static uint32_t compute_key(const lv_gradient_t * g, lv_coord_t size, lv_coord_t
static size_t get_cache_item_size(lv_gradient_cache_t * c)
{
size_t s = sizeof(*c) + c->size * sizeof(lv_color_t)
size_t s = sizeof(*c) + c->alloc_size * sizeof(lv_color_t)
#if _DITHER_GRADIENT
+ c->hmap_size * sizeof(lv_color32_t)
+ c->size * sizeof(lv_color32_t)
#if LV_DITHER_ERROR_DIFFUSION == 1
+ c->size * sizeof(lv_scolor24_t)
+ c->w * sizeof(lv_scolor24_t)
#endif
#endif
;
@ -159,7 +159,9 @@ static lv_res_t find_item(lv_gradient_cache_t * c, void * ctx)
static lv_gradient_cache_t * allocate_item(const lv_gradient_t * g, lv_coord_t w, lv_coord_t h)
{
lv_coord_t size = g->dir == LV_GRAD_DIR_HOR ? w : h;
size_t req_size = sizeof(lv_gradient_cache_t) + w * sizeof(lv_color_t)
lv_coord_t map_size = LV_MAX(w, h); /* The map is being used horizontally (width) unless
no dithering is selected where it's used vertically */
size_t req_size = sizeof(lv_gradient_cache_t) + map_size * sizeof(lv_color_t)
#if _DITHER_GRADIENT
+ size * sizeof(lv_color32_t)
#if LV_DITHER_ERROR_DIFFUSION == 1
@ -186,14 +188,15 @@ static lv_gradient_cache_t * allocate_item(const lv_gradient_t * g, lv_coord_t w
item->key = compute_key(g, size, w);
item->life = 1;
item->filled = 0;
item->size = w;
item->alloc_size = map_size;
item->size = size;
item->map = (lv_color_t *)(grad_cache_end + sizeof(*item));
#if _DITHER_GRADIENT
item->hmap = (lv_color32_t *)(grad_cache_end + sizeof(*item) + w * sizeof(lv_color_t));
item->hmap_size = size;
item->hmap = (lv_color32_t *)(grad_cache_end + sizeof(*item) + map_size * sizeof(lv_color_t));
#if LV_DITHER_ERROR_DIFFUSION == 1
item->error_acc = (lv_scolor24_t *)(grad_cache_end + sizeof(*item) + size * sizeof(lv_grad_color_t) + w * sizeof(
lv_color_t));
item->error_acc = (lv_scolor24_t *)(grad_cache_end + sizeof(*item) + size * sizeof(lv_grad_color_t) +
map_size * sizeof(lv_color_t));
item->w = w;
#endif
#endif
grad_cache_end += req_size;
@ -244,8 +247,8 @@ lv_gradient_cache_t * lv_grad_get_from_cache(const lv_gradient_t * g, lv_coord_t
/* Step 3: Fill it with the gradient, as expected */
#if _DITHER_GRADIENT
for(lv_coord_t i = 0; i < item->hmap_size; i++) {
item->hmap[i] = lv_grad_get(g, item->hmap_size, i);
for(lv_coord_t i = 0; i < item->size; i++) {
item->hmap[i] = lv_grad_get(g, item->size, i);
}
#if LV_DITHER_ERROR_DIFFUSION == 1
lv_memset_00(item->error_acc, w * sizeof(lv_scolor24_t));

View File

@ -45,14 +45,15 @@ typedef struct _lv_gradient_cache_t {
uint32_t filled : 1; /**< Used to skip dithering in it if already done */
lv_color_t * map; /**< The computed gradient low bitdepth color map, points into the
* cache's buffer, no free needed */
lv_coord_t alloc_size; /**< The map allocated size in colors */
lv_coord_t size; /**< The computed gradient color map size, in colors */
#if _DITHER_GRADIENT
lv_color32_t * hmap; /**< If dithering, we need to store the current, high bitdepth gradient
* map too, points to the cache's buffer, no free needed */
lv_coord_t hmap_size; /**< The array size in pixels */
#if LV_DITHER_ERROR_DIFFUSION == 1
lv_scolor24_t * error_acc; /**< Error diffusion dithering algorithm requires storing the last error
* drawn, points to the cache's buffer, no free needed */
lv_coord_t w; /**< The error array width in pixels */
#endif
#endif
} lv_gradient_cache_t;

View File

@ -177,6 +177,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
#if _DITHER_GRADIENT
lv_dither_mode_t dither_mode = dsc->bg_grad.dither;
lv_dither_func_t dither_func = &lv_dither_none;
lv_coord_t grad_size = coords_bg_w;
if(grad_dir == LV_GRAD_DIR_VER && dither_mode != LV_DITHER_NONE) {
/* When dithering, we are still using a map that's changing from line to line*/
blend_dsc.src_buf = grad->map;
@ -184,6 +185,8 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
if(grad && dither_mode == LV_DITHER_NONE) {
grad->filled = 0; /*Should we force refilling it each draw call ?*/
if(grad_dir == LV_GRAD_DIR_VER)
grad_size = coords_bg_h;
}
else
#if LV_DITHER_ERROR_DIFFUSION
@ -209,7 +212,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
#if _DITHER_GRADIENT
dither_func(grad, blend_area.x1, h - bg_coords.y1, coords_bg_w);
dither_func(grad, blend_area.x1, h - bg_coords.y1, grad_size);
#endif
if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[h - bg_coords.y1];
lv_draw_sw_blend(draw_ctx, &blend_dsc);
@ -235,7 +238,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
blend_area.y2 = top_y;
#if _DITHER_GRADIENT
dither_func(grad, blend_area.x1, top_y - bg_coords.y1, coords_bg_w);
dither_func(grad, blend_area.x1, top_y - bg_coords.y1, grad_size);
#endif
if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[top_y - bg_coords.y1];
lv_draw_sw_blend(draw_ctx, &blend_dsc);
@ -246,7 +249,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
blend_area.y2 = bottom_y;
#if _DITHER_GRADIENT
dither_func(grad, blend_area.x1, bottom_y - bg_coords.y1, coords_bg_w);
dither_func(grad, blend_area.x1, bottom_y - bg_coords.y1, grad_size);
#endif
if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[bottom_y - bg_coords.y1];
lv_draw_sw_blend(draw_ctx, &blend_dsc);
@ -285,7 +288,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co
blend_area.y2 = h;
#if _DITHER_GRADIENT
dither_func(grad, blend_area.x1, h - bg_coords.y1, coords_bg_w);
dither_func(grad, blend_area.x1, h - bg_coords.y1, grad_size);
#endif
if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[h - bg_coords.y1];
lv_draw_sw_blend(draw_ctx, &blend_dsc);