From f968792286f548dc3ad9f61c94f17578143d2a86 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sat, 4 Aug 2018 01:46:00 +0200 Subject: [PATCH] add the optional VDB write interface to the display driver (vdb_wr) --- lv_conf_templ.h | 5 +- lv_core/lv_refr.c | 26 ++++++ lv_core/lv_style.c | 4 +- lv_core/lv_vdb.c | 22 ++--- lv_core/lv_vdb.h | 4 +- lv_draw/lv_draw_vbasic.c | 194 ++++++++++++++++++++++++--------------- lv_hal/lv_hal_disp.c | 5 + lv_hal/lv_hal_disp.h | 6 ++ lv_misc/lv_color.h | 11 +++ lv_objx/lv_img.c | 12 +++ lv_objx/lv_img.h | 6 ++ lv_objx/lv_list.c | 17 ++-- 12 files changed, 213 insertions(+), 99 deletions(-) diff --git a/lv_conf_templ.h b/lv_conf_templ.h index 1aaddf257..c3c3d3dbb 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -38,8 +38,9 @@ * Required for buffered drawing, opacity and anti-aliasing * VDB makes the double buffering, you don't need to deal with it! * Typical size: ~1/10 screen */ -#define LV_VDB_SIZE (20 * LV_HOR_RES) /*Size of VDB in pixel count (1/10 screen size is good for first)*/ -#define LV_VDB_ADR 0 /*Place VDB to a specific address (e.g. in external RAM) (0: allocate automatically into RAM)*/ +#define LV_VDB_SIZE (8 * LV_HOR_RES) /*Size of VDB in pixel count (1/10 screen size is good for first)*/ +#define LV_VDB_PX_BPP LV_COLOR_SIZE /*Bit-per-pixel of VDB. Useful for monochrome or non-standard color format displays. (Set `disp_drv->vdb_wr` and `disp_drv->vdb_rd` too)*/ +#define LV_VDB_ADR 0 /*Place VDB to a specific address (e.g. in external RAM) (0: allocate automatically into RAM)*/ /* Use two Virtual Display buffers (VDB) parallelize rendering and flushing (optional) * The flushing should use DMA to write the frame buffer in the background*/ diff --git a/lv_core/lv_refr.c b/lv_core/lv_refr.c index 4f43e4251..d6bf90299 100644 --- a/lv_core/lv_refr.c +++ b/lv_core/lv_refr.c @@ -286,8 +286,34 @@ static void lv_refr_area_with_vdb(const lv_area_t * area_p) lv_coord_t y2 = area_p->y2 >= LV_VER_RES ? y2 = LV_VER_RES - 1 : area_p->y2; uint32_t max_row = (uint32_t) LV_VDB_SIZE / w; + if(max_row > h) max_row = h; + + /*Round down the lines of VDB if rounding is added*/ + if(round_cb) { + /**/ + lv_area_t tmp; + tmp.x1 = 0; + tmp.x2 = 0; + tmp.y1 = 0; + tmp.y2 = max_row; + + lv_coord_t y_tmp = max_row; + do { + tmp.y2 = y_tmp; + round_cb(&tmp); + y_tmp --; /*Decrement the number of line until it is rounded to a smaller value the original. */ + } while(tmp.y2 > max_row && y_tmp != 0); + + if(y_tmp == 0) { + LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to small VDB)"); + return; + } else { + max_row = tmp.y2; + } + } + /*Always use the full row*/ uint32_t row; lv_coord_t row_last = 0; diff --git a/lv_core/lv_style.c b/lv_core/lv_style.c index aedd4ce10..4de607e4b 100644 --- a/lv_core/lv_style.c +++ b/lv_core/lv_style.c @@ -94,7 +94,7 @@ void lv_style_init(void) lv_style_scr.body.shadow.width = 0; lv_style_scr.text.opa = LV_OPA_COVER; - lv_style_scr.text.color = LV_COLOR_MAKE(0x30, 0x30, 0x30); + lv_style_scr.text.color = LV_COLOR_BLACK;//MAKE(0x30, 0x30, 0x30); lv_style_scr.text.font = LV_FONT_DEFAULT; lv_style_scr.text.letter_space = 2; lv_style_scr.text.line_space = 2; @@ -115,7 +115,7 @@ void lv_style_init(void) lv_style_plain_color.text.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0); lv_style_plain_color.image.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0); lv_style_plain_color.line.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0); - lv_style_plain_color.body.main_color = LV_COLOR_MAKE(0x55, 0x96, 0xd8); + lv_style_plain_color.body.main_color = LV_COLOR_BLACK;//LV_COLOR_MAKE(0x55, 0x96, 0xd8); lv_style_plain_color.body.grad_color = lv_style_plain_color.body.main_color; /*Pretty style */ diff --git a/lv_core/lv_vdb.c b/lv_core/lv_vdb.c index 7894fcea8..6dc2eb37c 100644 --- a/lv_core/lv_vdb.c +++ b/lv_core/lv_vdb.c @@ -21,9 +21,9 @@ * TYPEDEFS **********************/ typedef enum { - LV_VDB_STATE_FREE = 0, - LV_VDB_STATE_ACTIVE, - LV_VDB_STATE_FLUSH, + LV_VDB_STATE_FREE = 0, /*Not used*/ + LV_VDB_STATE_ACTIVE, /*Being used to render*/ + LV_VDB_STATE_FLUSH, /*Flushing pixels from it*/ } lv_vdb_state_t; /********************** @@ -40,21 +40,21 @@ typedef enum { static volatile lv_vdb_state_t vdb_state = LV_VDB_STATE_ACTIVE; # if LV_VDB_ADR == 0 /*If the buffer address is not specified simply allocate it*/ -static lv_color_t vdb_buf[LV_VDB_SIZE]; -static lv_vdb_t vdb = {.buf = vdb_buf}; -# else +static uint8_t vdb_buf[(LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3]; +static lv_vdb_t vdb = {.buf = (lv_color_t*)vdb_buf}; +# else /*LV_VDB_ADR != 0*/ /*If the buffer address is specified use that address*/ static lv_vdb_t vdb = {.buf = (lv_color_t *)LV_VDB_ADR}; # endif -#else +#else /*LV_VDB_DOUBLE != 0*/ /*Double VDB*/ static volatile lv_vdb_state_t vdb_state[2] = {LV_VDB_STATE_FREE, LV_VDB_STATE_FREE}; # if LV_VDB_ADR == 0 /*If the buffer address is not specified simply allocate it*/ -static lv_color_t vdb_buf1[LV_VDB_SIZE]; -static lv_color_t vdb_buf2[LV_VDB_SIZE]; -static lv_vdb_t vdb[2] = {{.buf = vdb_buf1}, {.buf = vdb_buf2}}; -# else +static uint8_t vdb_buf1[(LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3]; +static uint8_t vdb_buf2[(LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3]; +static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *) vdb_buf1}, {.buf = (lv_color_t *) vdb_buf2}}; +# else /*LV_VDB_ADR != 0*/ /*If the buffer address is specified use that address*/ static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *)LV_VDB_ADR}, {.buf = (lv_color_t *)LV_VDB2_ADR}}; # endif diff --git a/lv_core/lv_vdb.h b/lv_core/lv_vdb.h index 5ca1ccf12..37bee2edb 100644 --- a/lv_core/lv_vdb.h +++ b/lv_core/lv_vdb.h @@ -53,10 +53,8 @@ lv_vdb_t * lv_vdb_get(void); */ void lv_vdb_flush(void); - /** - * In 'LV_VDB_DOUBLE' mode has to be called when 'disp_map()' - * is ready with copying the map to a frame buffer. + * Call in the display driver's 'disp_flush' function when the flushing is finished */ void lv_flush_ready(void); diff --git a/lv_draw/lv_draw_vbasic.c b/lv_draw/lv_draw_vbasic.c index fa6390cac..2ba1d90e3 100644 --- a/lv_draw/lv_draw_vbasic.c +++ b/lv_draw/lv_draw_vbasic.c @@ -75,13 +75,18 @@ void lv_vpx(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t col /*Make the coordinates relative to VDB*/ x -= vdb_p->area.x1; y -= vdb_p->area.y1; - lv_color_t * vdb_px_p = vdb_p->buf + y * vdb_width + x; - if(opa == LV_OPA_COVER) { - *vdb_px_p = color; - } else { - *vdb_px_p = lv_color_mix(color, *vdb_px_p, opa); - } + lv_disp_t * disp = lv_disp_get_active(); + if(disp->driver.vdb_wr) { + disp->driver.vdb_wr((uint8_t*)vdb_p->buf, vdb_width, x, y, color, opa); + } else { + lv_color_t * vdb_px_p = vdb_p->buf + y * vdb_width + x; + if(opa == LV_OPA_COVER) { + *vdb_px_p = color; + } else { + *vdb_px_p = lv_color_mix(color, *vdb_px_p, opa); + } + } } @@ -126,7 +131,7 @@ void lv_vfill(const lv_area_t * cords_p, const lv_area_t * mask_p, lv_coord_t w = lv_area_get_width(&vdb_rel_a); /*Don't use hw. acc. for every small fill (because of the init overhead)*/ if(w < VFILL_HW_ACC_SIZE_LIMIT) { - sw_color_fill(&vdb_p->area, vdb_buf_tmp, &vdb_rel_a, color, opa); + sw_color_fill(&vdb_p->area, vdb_p->buf, &vdb_rel_a, color, opa); } /*Not opaque fill*/ else if(opa == LV_OPA_COVER) { @@ -160,7 +165,7 @@ void lv_vfill(const lv_area_t * cords_p, const lv_area_t * mask_p, } /*Else use sw fill if no better option*/ else { - sw_color_fill(&vdb_p->area, vdb_buf_tmp, &vdb_rel_a, color, opa); + sw_color_fill(&vdb_p->area, vdb_p->buf, &vdb_rel_a, color, opa); } } @@ -185,12 +190,12 @@ void lv_vfill(const lv_area_t * cords_p, const lv_area_t * mask_p, } /*Use sw fill with opa if no better option*/ else { - sw_color_fill(&vdb_p->area, vdb_buf_tmp, &vdb_rel_a, color, opa); + sw_color_fill(&vdb_p->area, vdb_p->buf, &vdb_rel_a, color, opa); } } #else - sw_color_fill(&vdb_p->area, vdb_buf_tmp, &vdb_rel_a, color, opa); + sw_color_fill(&vdb_p->area, vdb_p->buf, &vdb_rel_a, color, opa); #endif } @@ -207,7 +212,6 @@ void lv_vletter(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) { - 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*/ @@ -291,7 +295,10 @@ void lv_vletter(const lv_point_t * pos_p, const lv_area_t * mask_p, /*Move on the map too*/ map_p += (row_start * width_byte_bpp) + ((col_start * bpp) >> 3); + lv_disp_t * disp = lv_disp_get_active(); + uint8_t letter_px; + lv_opa_t px_opa; for(row = row_start; row < row_end; row ++) { col_byte_cnt = 0; col_bit = (col_start * bpp) % 8; @@ -299,13 +306,21 @@ void lv_vletter(const lv_point_t * pos_p, const lv_area_t * mask_p, for(col = col_start; col < col_end; col ++) { letter_px = (*map_p & mask) >> (8 - col_bit - bpp); if(letter_px != 0) { - if(opa == LV_OPA_COVER) { - *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, bpp == 8 ? letter_px : bpp_opa_table[letter_px]); - } else { - *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, bpp == 8 ? - (uint16_t)((uint16_t)letter_px * opa) >> 8 : - (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8); - } + if(opa == LV_OPA_COVER) { + px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px]; + } else { + px_opa = bpp == 8 ? + (uint16_t)((uint16_t)letter_px * opa) >> 8 : + (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8; + } + + if(disp->driver.vdb_wr) { + disp->driver.vdb_wr((uint8_t*)vdb_p->buf, vdb_width, + (col + pos_x) - vdb_p->area.x1, (row + pos_y) - vdb_p->area.y1, + color, px_opa); + } else { + *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa); + } } vdb_buf_tmp++; @@ -341,6 +356,7 @@ void lv_vmap(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) { + lv_area_t masked_a; bool union_ok; lv_vdb_t * vdb_p = lv_vdb_get(); @@ -379,22 +395,38 @@ void lv_vmap(const lv_area_t * cords_p, const lv_area_t * mask_p, lv_coord_t row; lv_coord_t map_useful_w = lv_area_get_width(&masked_a); + lv_disp_t * disp = lv_disp_get_active(); + /*The simplest case just copy the pixels into the VDB*/ if(chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && recolor_opa == LV_OPA_TRANSP) { - for(row = masked_a.y1; row <= masked_a.y2; row++) { + /*Use the custom VDB write function is exists*/ + if(disp->driver.vdb_wr) { + lv_coord_t col; + for(row = masked_a.y1; row <= masked_a.y2; row++) { + for(col = 0; col < map_useful_w; col++) { + lv_color_t px_color = (lv_color_t) *((lv_color_t *)&map_p[(uint32_t)col * px_size_byte]); + disp->driver.vdb_wr((uint8_t*)vdb_p->buf, vdb_width, col + masked_a.x1, row, px_color, opa); + } + map_p += map_width * px_size_byte; /*Next row on the map*/ + } + } + /*Normal native VDB*/ + else { + for(row = masked_a.y1; row <= masked_a.y2; row++) { #if USE_LV_GPU - if(lv_disp_is_mem_blend_supported() == false) { - sw_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); - } else { - lv_disp_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); - } + if(lv_disp_is_mem_blend_supported() == false) { + sw_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); + } else { + lv_disp_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); + } #else - sw_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); + sw_mem_blend(vdb_buf_tmp, (lv_color_t *)map_p, map_useful_w, opa); #endif - map_p += map_width * px_size_byte; /*Next row on the map*/ - vdb_buf_tmp += vdb_width; /*Next row on the VDB*/ - } + map_p += map_width * px_size_byte; /*Next row on the map*/ + vdb_buf_tmp += vdb_width; /*Next row on the VDB*/ + } + } } /*In the other cases every pixel need to be checked one-by-one*/ @@ -431,29 +463,36 @@ void lv_vmap(const lv_area_t * cords_p, const lv_area_t * mask_p, /*Re-color the pixel if required*/ if(recolor_opa != LV_OPA_TRANSP) { - if(last_img_px.full != px_color.full) { /*Minor acceleration: calculate only for new colors (save the last)*/ last_img_px = px_color; recolored_px = lv_color_mix(recolor, last_img_px, recolor_opa); } - - if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col].full = recolored_px.full; - else vdb_buf_tmp[col] = lv_color_mix(recolored_px, vdb_buf_tmp[col], opa_result); + /*Handle custom VDB write is present*/ + if(disp->driver.vdb_wr) { + disp->driver.vdb_wr((uint8_t*)vdb_p->buf, vdb_width, col + masked_a.x1, row, recolored_px, opa_result); + } + /*Normal native VDB write*/ + else { + if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col].full = recolored_px.full; + else vdb_buf_tmp[col] = lv_color_mix(recolored_px, vdb_buf_tmp[col], opa_result); + } } else { - if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col] = px_color; - else vdb_buf_tmp[col] = lv_color_mix(px_color, vdb_buf_tmp[col], opa_result); + /*Handle custom VDB write is present*/ + if(disp->driver.vdb_wr) { + disp->driver.vdb_wr((uint8_t*)vdb_p->buf, vdb_width, col + masked_a.x1, row, px_color, opa_result); + } + /*Normal native VDB write*/ + else { + if(opa_result == LV_OPA_COVER) vdb_buf_tmp[col] = px_color; + else vdb_buf_tmp[col] = lv_color_mix(px_color, vdb_buf_tmp[col], opa_result); + } } - - } - /*Next row on the map*/ - map_p += map_width * px_size_byte; - vdb_buf_tmp += vdb_width; /*Next row on the VDB*/ + map_p += map_width * px_size_byte; /*Next row on the map*/ + vdb_buf_tmp += vdb_width; /*Next row on the VDB*/ } - } - } /********************** @@ -489,44 +528,55 @@ static void sw_mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t len */ static void sw_color_fill(lv_area_t * mem_area, lv_color_t * mem, const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa) { - /*Set all row in vdb to the given color*/ lv_coord_t row; lv_coord_t col; lv_coord_t mem_width = lv_area_get_width(mem_area); - /*Run simpler function without opacity*/ - if(opa == LV_OPA_COVER) { - /*Fill the first row with 'color'*/ - for(col = fill_area->x1; col <= fill_area->x2; col++) { - mem[col] = color; - } + lv_disp_t * disp = lv_disp_get_active(); + if(disp->driver.vdb_wr) { + for(col = fill_area->x1; col <= fill_area->x2; col++) { + for(row = fill_area->y1; row <= fill_area->y2; row++) { + disp->driver.vdb_wr((uint8_t*)mem, mem_width, col, row, color, opa); + } + } + } else { + mem += fill_area->y1 * mem_width; /*Go to the first row*/ - /*Copy the first row to all other rows*/ - lv_color_t * mem_first = &mem[fill_area->x1]; - lv_coord_t copy_size = (fill_area->x2 - fill_area->x1 + 1) * sizeof(lv_color_t); - mem += mem_width; + /*Run simpler function without opacity*/ + if(opa == LV_OPA_COVER) { - for(row = fill_area->y1 + 1; row <= fill_area->y2; row++) { - memcpy(&mem[fill_area->x1], mem_first, copy_size); - mem += mem_width; - } - } - /*Calculate with alpha too*/ - else { - lv_color_t bg_tmp = LV_COLOR_BLACK; - lv_color_t opa_tmp = lv_color_mix(color, bg_tmp, opa); - for(row = fill_area->y1; row <= fill_area->y2; row++) { - for(col = fill_area->x1; col <= fill_area->x2; col++) { - /*If the bg color changed recalculate the result color*/ - if(mem[col].full != bg_tmp.full) { - bg_tmp = mem[col]; - opa_tmp = lv_color_mix(color, bg_tmp, opa); - } - mem[col] = opa_tmp; - } - mem += mem_width; - } + /*Fill the first row with 'color'*/ + for(col = fill_area->x1; col <= fill_area->x2; col++) { + mem[col] = color; + } + + /*Copy the first row to all other rows*/ + lv_color_t * mem_first = &mem[fill_area->x1]; + lv_coord_t copy_size = (fill_area->x2 - fill_area->x1 + 1) * sizeof(lv_color_t); + mem += mem_width; + + for(row = fill_area->y1 + 1; row <= fill_area->y2; row++) { + memcpy(&mem[fill_area->x1], mem_first, copy_size); + mem += mem_width; + } + } + /*Calculate with alpha too*/ + else { + lv_color_t bg_tmp = LV_COLOR_BLACK; + lv_color_t opa_tmp = lv_color_mix(color, bg_tmp, opa); + for(row = fill_area->y1; row <= fill_area->y2; row++) { + for(col = fill_area->x1; col <= fill_area->x2; col++) { + /*If the bg color changed recalculate the result color*/ + if(mem[col].full != bg_tmp.full) { + bg_tmp = mem[col]; + opa_tmp = lv_color_mix(color, bg_tmp, opa); + } + mem[col] = opa_tmp; + } + mem += mem_width; + } + } } } diff --git a/lv_hal/lv_hal_disp.c b/lv_hal/lv_hal_disp.c index cf4c55c17..da601fa58 100644 --- a/lv_hal/lv_hal_disp.c +++ b/lv_hal/lv_hal_disp.c @@ -57,6 +57,10 @@ void lv_disp_drv_init(lv_disp_drv_t * driver) driver->mem_blend = NULL; driver->mem_fill = NULL; #endif + +#if LV_VDB_SIZE + driver->vdb_wr = NULL; +#endif } /** @@ -224,6 +228,7 @@ bool lv_disp_is_mem_fill_supported(void) if(active->driver.mem_fill) return true; else return false; } + #endif /********************** diff --git a/lv_hal/lv_hal_disp.h b/lv_hal/lv_hal_disp.h index ae225f140..131b948cc 100644 --- a/lv_hal/lv_hal_disp.h +++ b/lv_hal/lv_hal_disp.h @@ -19,6 +19,7 @@ extern "C" { #include #include "lv_hal.h" #include "../lv_misc/lv_color.h" +#include "../lv_misc/lv_area.h" /********************* * DEFINES @@ -41,6 +42,7 @@ typedef struct _disp_drv_t { /*Write pixel map (e.g. image) to the display*/ void (*disp_map)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p); + /*Optional interface functions to use GPU*/ #if USE_LV_GPU /*Blend two memories using opacity (GPU only)*/ void (*mem_blend)(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); @@ -49,6 +51,10 @@ typedef struct _disp_drv_t { void (*mem_fill)(lv_color_t * dest, uint32_t length, lv_color_t color); #endif +#if LV_VDB_SIZE + /*Optional: Set a pixel in a buffer according to the requirements of the display*/ + void (*vdb_wr)(uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa); +#endif } lv_disp_drv_t; typedef struct _disp_t { diff --git a/lv_misc/lv_color.h b/lv_misc/lv_color.h index a2611c595..5d1bd51cc 100644 --- a/lv_misc/lv_color.h +++ b/lv_misc/lv_color.h @@ -57,6 +57,17 @@ extern "C" { #define LV_OPA_100 255 #define LV_OPA_COVER 255 +#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 == 24 +#define LV_COLOR_SIZE 32 +#else +#error "Invalid color depth (LV_COLOR_DEPTH in lv_conf.h)" +#endif /********************** * TYPEDEFS diff --git a/lv_objx/lv_img.c b/lv_objx/lv_img.c index 81b357270..4fe5fb56a 100644 --- a/lv_objx/lv_img.c +++ b/lv_objx/lv_img.c @@ -249,6 +249,18 @@ lv_img_src_t lv_img_get_src_type(const void * src) else return LV_IMG_SRC_UNKNOWN; } +/** + * Get the source of the image + * @param img pointer to an image object + * @return the image source (symbol, file name or C array) + */ +const void * lv_img_get_src(lv_obj_t * img) +{ + lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + + return ext->src; +} + /** * Get the name of the file set for an image * @param img pointer to an image diff --git a/lv_objx/lv_img.h b/lv_objx/lv_img.h index 861ff56dc..35acf4daf 100644 --- a/lv_objx/lv_img.h +++ b/lv_objx/lv_img.h @@ -125,6 +125,12 @@ static inline void lv_img_set_upscale(lv_obj_t * img, bool upcale) */ lv_img_src_t lv_img_get_src_type(const void * src); +/** + * Get the source of the image + * @param img pointer to an image object + * @return the image source (symbol, file name or C array) + */ +const void * lv_img_get_src(lv_obj_t * img); /** * Get the name of the file set for an image diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index 49123ed7c..ed16d51a1 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -119,16 +119,16 @@ lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy) } else { lv_list_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - lv_obj_t * copy_btn = lv_obj_get_child_back(lv_page_get_scrl(copy), NULL); - lv_obj_t * new_btn; + lv_obj_t * copy_btn = get_prev_btn(copy, NULL); while(copy_btn) { - new_btn = lv_btn_create(new_list, copy_btn); + const void * img_src = NULL; #if USE_LV_IMG lv_obj_t * copy_img = lv_list_get_btn_img(copy_btn); - if(copy_img) lv_img_create(new_btn, copy_img); + if(copy_img) img_src = lv_img_get_src(copy_img); #endif - lv_label_create(new_btn, lv_list_get_btn_label(copy_btn)); - copy_btn = lv_obj_get_child_back(lv_page_get_scrl(copy), copy_btn); + lv_list_add(new_list, img_src, lv_list_get_btn_text(copy_btn), lv_btn_get_action(copy_btn, LV_BTN_ACTION_CLICK)); + // new_btn = lv_btn_create(new_list, copy_btn); + copy_btn = get_prev_btn(copy, copy_btn); } lv_list_set_style(new_list, LV_LIST_STYLE_BTN_REL, copy_ext->styles_btn[LV_BTN_STATE_REL]); @@ -684,10 +684,9 @@ static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * para btn_i = get_next_btn(list, btn_i); } - + /*Make the released button "selected"*/ + lv_list_set_btn_selected(list, btn); } - /*Make the released button "selected"*/ - lv_list_set_btn_selected(list, btn); /* If `click_focus == 1` then LV_SIGNAL_FOCUS need to know which button triggered the focus * to mark it as selected (pressed state)*/