feat(draw): add initial SDL renderer

It caches SW rendered bitmaps in textures.
The cache is also updated to support data and source separately.
E.g. source is a path to an image, and if that image changes all
related cache entries needs to found and invalidated.

Limitations of SDL rederer:
- not all draw task types are supported
- image transformation is not supported
- some textures (e.g. button matrix texts) are not detected as cached
- images are not cached
- images are supported only from path
This commit is contained in:
Gabor Kiss-Vamosi
2023-11-18 15:33:58 +01:00
parent cd6b4db6e8
commit 2f3e8d4066
58 changed files with 1049 additions and 282 deletions

View File

@@ -225,7 +225,7 @@ static void draw_vector(lv_layer_t * layer)
void lv_demo_vector_graphic(void) void lv_demo_vector_graphic(void)
{ {
static uint8_t canvas_buf[WIDTH * HEIGHT * 4]; static uint8_t canvas_buf[LV_CANVAS_BUF_SIZE(WIDTH, HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
lv_obj_t * canvas = lv_canvas_create(lv_scr_act()); lv_obj_t * canvas = lv_canvas_create(lv_scr_act());
lv_canvas_set_buffer(canvas, canvas_buf, WIDTH, HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_set_buffer(canvas, canvas_buf, WIDTH, HEIGHT, LV_COLOR_FORMAT_ARGB8888);

View File

@@ -249,6 +249,7 @@ static void profile_create(lv_obj_t * parent)
LV_IMAGE_DECLARE(img_demo_widgets_avatar); LV_IMAGE_DECLARE(img_demo_widgets_avatar);
lv_obj_t * avatar = lv_image_create(panel1); lv_obj_t * avatar = lv_image_create(panel1);
lv_image_set_src(avatar, &img_demo_widgets_avatar); lv_image_set_src(avatar, &img_demo_widgets_avatar);
// lv_image_set_src(avatar, "A:lvgl/demos/widgets/assets/avatar.png")
lv_obj_t * name = lv_label_create(panel1); lv_obj_t * name = lv_label_create(panel1);
lv_label_set_text(name, "Elena Smith"); lv_label_set_text(name, "Elena Smith");

View File

@@ -26,11 +26,11 @@ void lv_example_canvas_1(void)
lv_draw_label_dsc_init(&label_dsc); lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_palette_main(LV_PALETTE_ORANGE); label_dsc.color = lv_palette_main(LV_PALETTE_ORANGE);
label_dsc.text = "Some text on text canvas"; label_dsc.text = "Some text on text canvas";
/*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 16, LV_DRAW_BUF_STRIDE_ALIGN)];
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_RGB565);
lv_obj_center(canvas); lv_obj_center(canvas);
lv_canvas_fill_bg(canvas, lv_palette_lighten(LV_PALETTE_GREY, 3), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_palette_lighten(LV_PALETTE_GREY, 3), LV_OPA_COVER);
@@ -47,11 +47,18 @@ void lv_example_canvas_1(void)
/*Test the rotation. It requires another buffer where the original image is stored. /*Test the rotation. It requires another buffer where the original image is stored.
*So copy the current image to buffer and rotate it to the canvas*/ *So copy the current image to buffer and rotate it to the canvas*/
static uint8_t cbuf_tmp[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf_tmp[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/
canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas);
lv_memcpy(cbuf_tmp, cbuf, sizeof(cbuf_tmp)); lv_memcpy(cbuf_tmp, cbuf, sizeof(cbuf_tmp));
lv_image_dsc_t img; lv_image_dsc_t img;
img.data = (void *)cbuf_tmp; img.data = (void *)cbuf_tmp;
img.header.cf = LV_COLOR_FORMAT_NATIVE; img.header.cf = LV_COLOR_FORMAT_ARGB8888;
img.header.w = CANVAS_WIDTH; img.header.w = CANVAS_WIDTH;
img.header.h = CANVAS_HEIGHT; img.header.h = CANVAS_HEIGHT;

View File

@@ -10,11 +10,11 @@
void lv_example_canvas_3(void) void lv_example_canvas_3(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -10,11 +10,11 @@
void lv_example_canvas_4(void) void lv_example_canvas_4(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -10,11 +10,11 @@
void lv_example_canvas_5(void) void lv_example_canvas_5(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -10,11 +10,11 @@
void lv_example_canvas_6(void) void lv_example_canvas_6(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -10,11 +10,11 @@
void lv_example_canvas_7(void) void lv_example_canvas_7(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -12,11 +12,11 @@
void lv_example_canvas_8(void) void lv_example_canvas_8(void)
{ {
/*Create a buffer for the canvas*/ /*Create a buffer for the canvas*/
static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
/*Create a canvas and initialize its palette*/ /*Create a canvas and initialize its palette*/
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
lv_obj_center(canvas); lv_obj_center(canvas);

View File

@@ -5,13 +5,17 @@ void lv_example_image_1(void)
{ {
LV_IMAGE_DECLARE(img_cogwheel_argb); LV_IMAGE_DECLARE(img_cogwheel_argb);
lv_obj_t * img1 = lv_image_create(lv_screen_active()); lv_obj_t * img1 = lv_image_create(lv_screen_active());
lv_image_set_src(img1, &img_cogwheel_argb); lv_image_set_src(img1, "A:lvgl/demos/widgets/assets/avatar.png");
lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20); lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_size(img1, 200, 200); lv_image_set_scale_x(img1, 512);
lv_image_set_scale_y(img1, 128);
lv_image_set_rotation(img1, 10);
lv_obj_t * img2 = lv_image_create(lv_screen_active()); lv_obj_t * img2 = lv_image_create(lv_screen_active());
lv_image_set_src(img2, LV_SYMBOL_OK "Accept"); lv_image_set_src(img2, LV_SYMBOL_OK "Accept");
lv_obj_align_to(img2, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); lv_obj_align_to(img2, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
lv_obj_set_style_bg_opa(img1, 100, 0);
} }
#endif #endif

View File

@@ -127,6 +127,9 @@
/* Use NXP's PXP on iMX RTxxx platforms. */ /* Use NXP's PXP on iMX RTxxx platforms. */
#define LV_USE_DRAW_PXP 0 #define LV_USE_DRAW_PXP 0
/* Draw using cached SDL textures*/
#define LV_USE_DRAW_SDL 0
/*================= /*=================
* OPERATING SYSTEM * OPERATING SYSTEM
*=================*/ *=================*/

View File

@@ -93,7 +93,7 @@ void lv_refr_now(lv_display_t * disp)
void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
{ {
lv_area_t clip_area_ori = layer->clip_area; lv_area_t clip_area_ori = layer->_clip_area;
lv_area_t clip_coords_for_obj; lv_area_t clip_coords_for_obj;
/*Truncate the clip area to `obj size + ext size` area*/ /*Truncate the clip area to `obj size + ext size` area*/
@@ -104,7 +104,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
if(!_lv_area_intersect(&clip_coords_for_obj, &clip_area_ori, &obj_coords_ext)) return; if(!_lv_area_intersect(&clip_coords_for_obj, &clip_area_ori, &obj_coords_ext)) return;
/*If the object is visible on the current clip area*/ /*If the object is visible on the current clip area*/
layer->clip_area = clip_coords_for_obj; layer->_clip_area = clip_coords_for_obj;
lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN_BEGIN, layer);
lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN, layer);
@@ -139,14 +139,14 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
uint32_t child_cnt = lv_obj_get_child_count(obj); uint32_t child_cnt = lv_obj_get_child_count(obj);
if(child_cnt == 0) { if(child_cnt == 0) {
/*If the object was visible on the clip area call the post draw events too*/ /*If the object was visible on the clip area call the post draw events too*/
layer->clip_area = clip_coords_for_obj; layer->_clip_area = clip_coords_for_obj;
/*If all the children are redrawn make 'post draw' draw*/ /*If all the children are redrawn make 'post draw' draw*/
lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer);
lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer);
lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer);
} }
else { else {
layer->clip_area = clip_coords_for_children; layer->_clip_area = clip_coords_for_children;
bool clip_corner = lv_obj_get_style_clip_corner(obj, LV_PART_MAIN); bool clip_corner = lv_obj_get_style_clip_corner(obj, LV_PART_MAIN);
int32_t radius = 0; int32_t radius = 0;
@@ -162,7 +162,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
} }
/*If the object was visible on the clip area call the post draw events too*/ /*If the object was visible on the clip area call the post draw events too*/
layer->clip_area = clip_coords_for_obj; layer->_clip_area = clip_coords_for_obj;
/*If all the children are redrawn make 'post draw' draw*/ /*If all the children are redrawn make 'post draw' draw*/
lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer);
lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer);
@@ -228,7 +228,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
mid.y1 += rout; mid.y1 += rout;
mid.y2 -= rout; mid.y2 -= rout;
if(_lv_area_intersect(&mid, &mid, &clip_area_ori)) { if(_lv_area_intersect(&mid, &mid, &clip_area_ori)) {
layer->clip_area = mid; layer->_clip_area = mid;
for(i = 0; i < child_cnt; i++) { for(i = 0; i < child_cnt; i++) {
lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_t * child = obj->spec_attr->children[i];
refr_obj(layer, child); refr_obj(layer, child);
@@ -245,7 +245,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
/** /**
@@ -606,12 +606,12 @@ static void refr_area(const lv_area_t * area_p)
if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) {
disp_refr->last_part = 1; disp_refr->last_part = 1;
layer->clip_area = disp_area; layer->_clip_area = disp_area;
refr_area_part(layer); refr_area_part(layer);
} }
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) { else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
disp_refr->last_part = disp_refr->last_area; disp_refr->last_part = disp_refr->last_area;
layer->clip_area = *area_p; layer->_clip_area = *area_p;
refr_area_part(layer); refr_area_part(layer);
} }
return; return;
@@ -638,7 +638,7 @@ static void refr_area(const lv_area_t * area_p)
layer->buf = disp_refr->buf_act; layer->buf = disp_refr->buf_act;
layer->buf_area = sub_area; layer->buf_area = sub_area;
layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format);
layer->clip_area = sub_area; layer->_clip_area = sub_area;
if(sub_area.y2 > y2) sub_area.y2 = y2; if(sub_area.y2 > y2) sub_area.y2 = y2;
row_last = sub_area.y2; row_last = sub_area.y2;
if(y2 == row_last) disp_refr->last_part = 1; if(y2 == row_last) disp_refr->last_part = 1;
@@ -654,7 +654,7 @@ static void refr_area(const lv_area_t * area_p)
sub_area.y2 = y2; sub_area.y2 = y2;
layer->buf = disp_refr->buf_act; layer->buf = disp_refr->buf_act;
layer->buf_area = sub_area; layer->buf_area = sub_area;
layer->clip_area = sub_area; layer->_clip_area = sub_area;
disp_refr->last_part = 1; disp_refr->last_part = 1;
refr_area_part(layer); refr_area_part(layer);
} }
@@ -662,7 +662,7 @@ static void refr_area(const lv_area_t * area_p)
static void refr_area_part(lv_layer_t * layer) static void refr_area_part(lv_layer_t * layer)
{ {
disp_refr->refreshed_area = layer->clip_area; disp_refr->refreshed_area = layer->_clip_area;
/* In single buffered mode wait here until the buffer is freed. /* In single buffered mode wait here until the buffer is freed.
* Else we would draw into the buffer while it's still being transferred to the display*/ * Else we would draw into the buffer while it's still being transferred to the display*/
@@ -680,9 +680,9 @@ static void refr_area_part(lv_layer_t * layer)
lv_obj_t * top_prev_scr = NULL; lv_obj_t * top_prev_scr = NULL;
/*Get the most top object which is not covered by others*/ /*Get the most top object which is not covered by others*/
top_act_scr = lv_refr_get_top_obj(&layer->clip_area, lv_display_get_screen_active(disp_refr)); top_act_scr = lv_refr_get_top_obj(&layer->_clip_area, lv_display_get_screen_active(disp_refr));
if(disp_refr->prev_scr) { if(disp_refr->prev_scr) {
top_prev_scr = lv_refr_get_top_obj(&layer->clip_area, disp_refr->prev_scr); top_prev_scr = lv_refr_get_top_obj(&layer->_clip_area, disp_refr->prev_scr);
} }
/*Draw a bottom layer background if there is no top object*/ /*Draw a bottom layer background if there is no top object*/
@@ -824,7 +824,7 @@ static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_t
lv_area_t clip_coords_for_obj; lv_area_t clip_coords_for_obj;
lv_area_t tranf_coords = obj_coords_ext; lv_area_t tranf_coords = obj_coords_ext;
lv_obj_get_transformed_area(obj, &tranf_coords, false, false); lv_obj_get_transformed_area(obj, &tranf_coords, false, false);
if(!_lv_area_intersect(&clip_coords_for_obj, &layer->clip_area, &tranf_coords)) { if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &tranf_coords)) {
return LV_RESULT_INVALID; return LV_RESULT_INVALID;
} }
@@ -842,7 +842,7 @@ static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_t
} }
else if(layer_type == LV_LAYER_TYPE_SIMPLE) { else if(layer_type == LV_LAYER_TYPE_SIMPLE) {
lv_area_t clip_coords_for_obj; lv_area_t clip_coords_for_obj;
if(!_lv_area_intersect(&clip_coords_for_obj, &layer->clip_area, &obj_coords_ext)) { if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &obj_coords_ext)) {
return LV_RESULT_INVALID; return LV_RESULT_INVALID;
} }
*layer_area_out = clip_coords_for_obj; *layer_area_out = clip_coords_for_obj;

View File

@@ -15,6 +15,8 @@
#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/ #define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/
#include LV_SDL_INCLUDE_PATH #include LV_SDL_INCLUDE_PATH
#include <SDL2/SDL_image.h>
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
@@ -74,6 +76,12 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
SDL_StartTextInput(); SDL_StartTextInput();
event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL); event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL);
lv_tick_set_cb(SDL_GetTicks); lv_tick_set_cb(SDL_GetTicks);
if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) {
fprintf(stderr, "could not initialize sdl2_image: %s\n", IMG_GetError());
return NULL;
}
inited = true; inited = true;
} }
@@ -147,6 +155,12 @@ void lv_sdl_window_set_title(lv_display_t * disp, const char * title)
SDL_SetWindowTitle(dsc->window, title); SDL_SetWindowTitle(dsc->window, title);
} }
SDL_Renderer * lv_sdl_window_get_renderer(lv_display_t * disp)
{
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
return dsc->renderer;
}
void lv_sdl_quit() void lv_sdl_quit()
{ {
if(inited) { if(inited) {
@@ -260,6 +274,7 @@ static void window_create(lv_display_t * disp)
dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE); dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE);
texture_resize(disp); texture_resize(disp);
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp));
lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size); lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size);
#if LV_SDL_DIRECT_MODE_2_BUF #if LV_SDL_DIRECT_MODE_2_BUF
@@ -273,6 +288,7 @@ static void window_create(lv_display_t * disp)
static void window_update(lv_display_t * disp) static void window_update(lv_display_t * disp)
{ {
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
#if LV_USE_DRAW_SDL == 0
int32_t hor_res = lv_display_get_horizontal_resolution(disp); int32_t hor_res = lv_display_get_horizontal_resolution(disp);
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp)); uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp));
SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride); SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride);
@@ -281,6 +297,7 @@ static void window_update(lv_display_t * disp)
/*Update the renderer with the texture containing the rendered image*/ /*Update the renderer with the texture containing the rendered image*/
SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL); SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL);
#endif
SDL_RenderPresent(dsc->renderer); SDL_RenderPresent(dsc->renderer);
} }

View File

@@ -18,6 +18,7 @@ extern "C" {
#include "../../indev/lv_indev.h" #include "../../indev/lv_indev.h"
#if LV_USE_SDL #if LV_USE_SDL
#include LV_SDL_INCLUDE_PATH
/********************* /*********************
* DEFINES * DEFINES
@@ -41,6 +42,8 @@ lv_display_t * _lv_sdl_get_disp_from_win_id(uint32_t win_id);
void lv_sdl_window_set_title(lv_display_t * disp, const char * title); void lv_sdl_window_set_title(lv_display_t * disp, const char * title);
SDL_Renderer * lv_sdl_window_get_renderer(lv_display_t * disp);
void lv_sdl_quit(); void lv_sdl_quit();
/********************** /**********************

View File

@@ -83,7 +83,7 @@ lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords)
lv_draw_task_t * new_task = lv_malloc_zeroed(sizeof(lv_draw_task_t)); lv_draw_task_t * new_task = lv_malloc_zeroed(sizeof(lv_draw_task_t));
new_task->area = *coords; new_task->area = *coords;
new_task->clip_area = layer->clip_area; new_task->clip_area = layer->_clip_area;
new_task->state = LV_DRAW_TASK_STATE_QUEUED; new_task->state = LV_DRAW_TASK_STATE_QUEUED;
/*Find the tail*/ /*Find the tail*/
@@ -110,13 +110,14 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
/*Send LV_EVENT_DRAW_TASK_ADDED and dispatch only on the "main" draw_task /*Send LV_EVENT_DRAW_TASK_ADDED and dispatch only on the "main" draw_task
*and not on the draw tasks added in the event. *and not on the draw tasks added in the event.
*Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends *Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends and besides
*Dispatching might remove the "main" draw task while it's still being used in the event*/ *dispatching might remove the "main" draw task while it's still being used in the event*/
if(info->task_running == false) { if(info->task_running == false) {
info->task_running = true;
if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) { if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) {
info->task_running = true;
lv_obj_send_event(base_dsc->obj, LV_EVENT_DRAW_TASK_ADDED, t); lv_obj_send_event(base_dsc->obj, LV_EVENT_DRAW_TASK_ADDED, t);
info->task_running = false;
} }
/*Let the draw units set their preference score*/ /*Let the draw units set their preference score*/
@@ -129,7 +130,6 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
} }
lv_draw_dispatch(); lv_draw_dispatch();
info->task_running = false;
} }
else { else {
/*Let the draw units set their preference score*/ /*Let the draw units set their preference score*/
@@ -292,17 +292,17 @@ lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_tas
{ {
LV_PROFILER_BEGIN; LV_PROFILER_BEGIN;
/*If the first task is screen sized, there cannot be independent areas*/ /*If the first task is screen sized, there cannot be independent areas*/
if(layer->draw_task_head) { // if(layer->draw_task_head) {
int32_t hor_res = lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()); // int32_t hor_res = lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing());
int32_t ver_res = lv_display_get_vertical_resolution(_lv_refr_get_disp_refreshing()); // int32_t ver_res = lv_display_get_vertical_resolution(_lv_refr_get_disp_refreshing());
lv_draw_task_t * t = layer->draw_task_head; // lv_draw_task_t * t = layer->draw_task_head;
if(t->state != LV_DRAW_TASK_STATE_QUEUED && // if(t->state != LV_DRAW_TASK_STATE_QUEUED &&
t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 && // t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 &&
t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) { // t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) {
LV_PROFILER_END; // LV_PROFILER_END;
return NULL; // return NULL;
} // }
} // }
lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head; lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head;
while(t) { while(t) {
@@ -328,7 +328,7 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c
if(new_layer == NULL) return NULL; if(new_layer == NULL) return NULL;
new_layer->parent = parent_layer; new_layer->parent = parent_layer;
new_layer->clip_area = *area; new_layer->_clip_area = *area;
new_layer->buf_area = *area; new_layer->buf_area = *area;
new_layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), color_format); new_layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), color_format);
new_layer->color_format = color_format; new_layer->color_format = color_format;

View File

@@ -152,21 +152,24 @@ typedef struct _lv_layer_t {
void * buf; void * buf;
uint32_t buf_stride; uint32_t buf_stride;
/** The absolute coordinates of the buffer */
lv_area_t buf_area; lv_area_t buf_area;
/** The color format of the layer. LV_COLOR_FORMAT_... */
lv_color_format_t color_format; lv_color_format_t color_format;
/** /**
* NEVER USE IT DRAW UNITS. USED INTERNALLY DURING DRAW TASK CREATION.
* The current clip area with absolute coordinates, always the same or smaller than `buf_area` * The current clip area with absolute coordinates, always the same or smaller than `buf_area`
* Can be set before new draw tasks are added to indicate the clip area of the draw tasks. * Can be set before new draw tasks are added to indicate the clip area of the draw tasks.
* Therefore `lv_draw_add_task()` always saves it in the new draw task to know the clip area when the draw task was added. * Therefore `lv_draw_add_task()` always saves it in the new draw task to know the clip area when the draw task was added.
* During drawing the draw units also sees the saved clip_area and should use it during drawing. * During drawing the draw units also sees the saved clip_area and should use it during drawing.
* During drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks. * During drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks.
*/ */
lv_area_t clip_area; lv_area_t _clip_area;
/** /** Linked list of draw tasks */
* Linked list of draw tasks
*/
lv_draw_task_t * draw_task_head; lv_draw_task_t * draw_task_head;
struct _lv_layer_t * parent; struct _lv_layer_t * parent;
@@ -181,6 +184,8 @@ typedef struct {
uint32_t id1; uint32_t id1;
uint32_t id2; uint32_t id2;
lv_layer_t * layer; lv_layer_t * layer;
size_t dsc_size;
void * user_data;
} lv_draw_dsc_base_t; } lv_draw_dsc_base_t;
typedef struct { typedef struct {

View File

@@ -46,6 +46,7 @@ void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc)
dsc->scale_x = LV_SCALE_NONE; dsc->scale_x = LV_SCALE_NONE;
dsc->scale_y = LV_SCALE_NONE; dsc->scale_y = LV_SCALE_NONE;
dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t);
} }
void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords)

View File

@@ -58,6 +58,7 @@ void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
dsc->sel_color = lv_color_black(); dsc->sel_color = lv_color_black();
dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE); dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE);
dsc->bidi_dir = LV_BASE_DIR_LTR; dsc->bidi_dir = LV_BASE_DIR_LTR;
dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t);
} }
void lv_draw_letter_dsc_init(lv_draw_glyph_dsc_t * dsc) void lv_draw_letter_dsc_init(lv_draw_glyph_dsc_t * dsc)

View File

@@ -59,6 +59,7 @@ void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc)
{ {
lv_memzero(dsc, sizeof(*dsc)); lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER; dsc->opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t);
} }
void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc) void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc)
@@ -66,18 +67,21 @@ void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc)
lv_memzero(dsc, sizeof(*dsc)); lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER; dsc->opa = LV_OPA_COVER;
dsc->side = LV_BORDER_SIDE_FULL; dsc->side = LV_BORDER_SIDE_FULL;
dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
} }
void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc) void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc)
{ {
lv_memzero(dsc, sizeof(*dsc)); lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER; dsc->opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t);
} }
void lv_draw_bg_image_dsc_init(lv_draw_bg_image_dsc_t * dsc) void lv_draw_bg_image_dsc_init(lv_draw_bg_image_dsc_t * dsc)
{ {
lv_memzero(dsc, sizeof(*dsc)); lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER; dsc->opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_bg_image_dsc_t);
} }
void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
@@ -133,6 +137,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a
lv_draw_box_shadow_dsc_t * shadow_dsc = lv_malloc(sizeof(lv_draw_box_shadow_dsc_t)); lv_draw_box_shadow_dsc_t * shadow_dsc = lv_malloc(sizeof(lv_draw_box_shadow_dsc_t));
t->draw_dsc = shadow_dsc; t->draw_dsc = shadow_dsc;
shadow_dsc->base = dsc->base; shadow_dsc->base = dsc->base;
shadow_dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t);
shadow_dsc->radius = dsc->radius; shadow_dsc->radius = dsc->radius;
shadow_dsc->color = dsc->shadow_color; shadow_dsc->color = dsc->shadow_color;
shadow_dsc->width = dsc->shadow_width; shadow_dsc->width = dsc->shadow_width;
@@ -158,13 +163,16 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a
t = lv_draw_add_task(layer, &bg_coords); t = lv_draw_add_task(layer, &bg_coords);
lv_draw_fill_dsc_t * bg_dsc = lv_malloc(sizeof(lv_draw_fill_dsc_t)); lv_draw_fill_dsc_t * bg_dsc = lv_malloc(sizeof(lv_draw_fill_dsc_t));
lv_draw_fill_dsc_init(bg_dsc);
t->draw_dsc = bg_dsc; t->draw_dsc = bg_dsc;
bg_dsc->base = dsc->base; bg_dsc->base = dsc->base;
bg_dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t);
bg_dsc->radius = dsc->radius; bg_dsc->radius = dsc->radius;
bg_dsc->color = dsc->bg_color; bg_dsc->color = dsc->bg_color;
bg_dsc->grad = dsc->bg_grad; bg_dsc->grad = dsc->bg_grad;
bg_dsc->opa = dsc->bg_opa; bg_dsc->opa = dsc->bg_opa;
t->type = LV_DRAW_TASK_TYPE_FILL; t->type = LV_DRAW_TASK_TYPE_FILL;
lv_draw_finalize_task_creation(layer, t); lv_draw_finalize_task_creation(layer, t);
} }
@@ -190,6 +198,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a
lv_draw_bg_image_dsc_t * bg_image_dsc = lv_malloc(sizeof(lv_draw_bg_image_dsc_t)); lv_draw_bg_image_dsc_t * bg_image_dsc = lv_malloc(sizeof(lv_draw_bg_image_dsc_t));
t->draw_dsc = bg_image_dsc; t->draw_dsc = bg_image_dsc;
bg_image_dsc->base = dsc->base; bg_image_dsc->base = dsc->base;
bg_image_dsc->base.dsc_size = sizeof(lv_draw_bg_image_dsc_t);
bg_image_dsc->radius = dsc->radius; bg_image_dsc->radius = dsc->radius;
bg_image_dsc->src = dsc->bg_image_src; bg_image_dsc->src = dsc->bg_image_src;
bg_image_dsc->font = dsc->bg_image_symbol_font; bg_image_dsc->font = dsc->bg_image_symbol_font;
@@ -209,6 +218,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a
lv_draw_border_dsc_t * border_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); lv_draw_border_dsc_t * border_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t));
t->draw_dsc = border_dsc; t->draw_dsc = border_dsc;
border_dsc->base = dsc->base; border_dsc->base = dsc->base;
border_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
border_dsc->radius = dsc->radius; border_dsc->radius = dsc->radius;
border_dsc->color = dsc->border_color; border_dsc->color = dsc->border_color;
border_dsc->opa = dsc->border_opa; border_dsc->opa = dsc->border_opa;
@@ -226,6 +236,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a
lv_draw_border_dsc_t * outline_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); lv_draw_border_dsc_t * outline_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t));
t->draw_dsc = outline_dsc; t->draw_dsc = outline_dsc;
outline_dsc->base = dsc->base; outline_dsc->base = dsc->base;
outline_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
outline_dsc->radius = dsc->radius == LV_RADIUS_CIRCLE ? LV_RADIUS_CIRCLE : dsc->radius + dsc->outline_width + outline_dsc->radius = dsc->radius == LV_RADIUS_CIRCLE ? LV_RADIUS_CIRCLE : dsc->radius + dsc->outline_width +
dsc->outline_pad; dsc->outline_pad;
outline_dsc->color = dsc->outline_color; outline_dsc->color = dsc->outline_color;

View File

@@ -476,7 +476,7 @@ lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer)
lv_matrix_identity(&(stroke_dsc->matrix)); // identity matrix lv_matrix_identity(&(stroke_dsc->matrix)); // identity matrix
dsc->current_dsc.blend_mode = LV_VECTOR_BLEND_SRC_OVER; dsc->current_dsc.blend_mode = LV_VECTOR_BLEND_SRC_OVER;
dsc->current_dsc.scissor_area = layer->clip_area; dsc->current_dsc.scissor_area = layer->_clip_area;
lv_matrix_identity(&(dsc->current_dsc.matrix)); // identity matrix lv_matrix_identity(&(dsc->current_dsc.matrix)); // identity matrix
dsc->tasks.task_list = NULL; dsc->tasks.task_list = NULL;
return dsc; return dsc;
@@ -638,7 +638,7 @@ void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_gr
void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path) void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path)
{ {
lv_area_t rect; lv_area_t rect;
if(!_lv_area_intersect(&rect, &(dsc->layer->clip_area), &(dsc->current_dsc.scissor_area))) { if(!_lv_area_intersect(&rect, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) {
return; return;
} }
@@ -666,7 +666,7 @@ void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path
void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect) void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect)
{ {
lv_area_t r; lv_area_t r;
if(!_lv_area_intersect(&r, &(dsc->layer->clip_area), &(dsc->current_dsc.scissor_area))) { if(!_lv_area_intersect(&r, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) {
return; return;
} }
@@ -691,7 +691,7 @@ void lv_draw_vector(lv_vector_dsc_t * dsc)
lv_layer_t * layer = dsc->layer; lv_layer_t * layer = dsc->layer;
lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->clip_area)); lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->_clip_area));
t->type = LV_DRAW_TASK_TYPE_VECTOR; t->type = LV_DRAW_TASK_TYPE_VECTOR;
t->draw_dsc = lv_malloc(sizeof(lv_draw_vector_task_dsc_t)); t->draw_dsc = lv_malloc(sizeof(lv_draw_vector_task_dsc_t));
lv_memcpy(t->draw_dsc, &(dsc->tasks), sizeof(lv_draw_vector_task_dsc_t)); lv_memcpy(t->draw_dsc, &(dsc->tasks), sizeof(lv_draw_vector_task_dsc_t));

View File

@@ -94,6 +94,7 @@ typedef struct _lv_image_decoder_t {
lv_image_decoder_open_f_t open_cb; lv_image_decoder_open_f_t open_cb;
lv_image_decoder_get_area_cb_t get_area_cb; lv_image_decoder_get_area_cb_t get_area_cb;
lv_image_decoder_close_f_t close_cb; lv_image_decoder_close_f_t close_cb;
uint32_t cache_data_type;
void * user_data; void * user_data;
} lv_image_decoder_t; } lv_image_decoder_t;

400
src/draw/sdl/lv_draw_sdl.c Normal file
View File

@@ -0,0 +1,400 @@
/**
* @file lv_draw_sdl.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../lv_draw.h"
#if LV_USE_DRAW_SDL
#include LV_SDL_INCLUDE_PATH
#include <SDL2/SDL_image.h>
#include "lv_draw_sdl.h"
#include "../../core/lv_refr.h"
#include "../../display/lv_display_private.h"
#include "../../stdlib/lv_string.h"
#include "../../dev/sdl/lv_sdl_window.h"
/*********************
* DEFINES
*********************/
#define DRAW_UNIT_ID_SDL 100
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t * draw_dsc;
int32_t w;
int32_t h;
SDL_Texture * texture;
} cache_data_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void execute_drawing(lv_draw_sdl_unit_t * u);
static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/**********************
* GLOBAL PROTOTYPES
**********************/
static uint8_t sdl_render_buf[2048 * 1024 * 4];
/**********************
* STATIC VARIABLES
**********************/
static SDL_Texture * layer_get_texture(lv_layer_t * layer);
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sdl_init(void)
{
lv_draw_sdl_unit_t * draw_sdl_unit = lv_draw_create_unit(sizeof(lv_draw_sdl_unit_t));
draw_sdl_unit->base_unit.dispatch_cb = dispatch;
draw_sdl_unit->base_unit.evaluate_cb = evaluate;
draw_sdl_unit->texture_cache_data_type = lv_cache_register_data_type();
}
/**********************
* STATIC FUNCTIONS
**********************/
static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{
lv_draw_sdl_unit_t * draw_sdl_unit = (lv_draw_sdl_unit_t *) draw_unit;
/*Return immediately if it's busy with a draw task*/
if(draw_sdl_unit->task_act) return 0;
lv_draw_task_t * t = NULL;
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_SDL);
if(t == NULL) return -1;
lv_display_t * disp = _lv_refr_get_disp_refreshing();
SDL_Texture * texture = layer_get_texture(layer);
if(layer != disp->layer_head && texture == NULL) {
void * buf = lv_draw_layer_alloc_buf(layer);
if(buf == NULL) return -1;
SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp);
int32_t w = lv_area_get_width(&layer->buf_area);
int32_t h = lv_area_get_height(&layer->buf_area);
layer->user_data = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_TARGET, w, h);
}
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
draw_sdl_unit->base_unit.target_layer = layer;
draw_sdl_unit->base_unit.clip_area = &t->clip_area;
draw_sdl_unit->task_act = t;
execute_drawing(draw_sdl_unit);
draw_sdl_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
draw_sdl_unit->task_act = NULL;
/*The draw unit is free now. Request a new dispatching as it can get a new task*/
lv_draw_dispatch_request();
return 1;
}
static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
{
LV_UNUSED(draw_unit);
if(((lv_draw_dsc_base_t *)task->draw_dsc)->user_data == NULL) {
task->preference_score = 0;
task->preferred_draw_unit_id = DRAW_UNIT_ID_SDL;
}
return 0;
}
bool compare_cb(const void * data1, const void * data2, size_t data_size)
{
LV_UNUSED(data_size);
const cache_data_t * d1 = data1;
const cache_data_t * d2 = data2;
if(d1->w != d2->w) return false;
if(d1->h != d2->h) return false;
if(d1->draw_dsc->dsc_size != d2->draw_dsc->dsc_size) return false;
if(memcmp(d1->draw_dsc, d2->draw_dsc, d1->draw_dsc->dsc_size)) return false;
return true;
}
void invalidate_cb(lv_cache_entry_t * e)
{
const cache_data_t * d = e->data;
lv_free((void *)d->draw_dsc);
SDL_DestroyTexture(d->texture);
lv_free((void *)d);
e->data = NULL;
e->data_size = 0;
}
static lv_cache_entry_t * draw_to_texture(lv_draw_sdl_unit_t * u)
{
lv_draw_task_t * task = u->task_act;
lv_layer_t dest_layer;
lv_memzero(&dest_layer, sizeof(dest_layer));
dest_layer.buf = lv_draw_buf_align(sdl_render_buf, LV_COLOR_FORMAT_ARGB8888);
dest_layer.color_format = LV_COLOR_FORMAT_ARGB8888;
lv_area_t a;
_lv_area_intersect(&a, u->base_unit.clip_area, &task->area);
dest_layer.buf_area = task->area;
dest_layer._clip_area = task->area;
lv_memzero(sdl_render_buf, lv_area_get_size(&dest_layer.buf_area) * 4 + 100);
lv_display_t * disp = _lv_refr_get_disp_refreshing();
uint32_t tick = lv_tick_get();
SDL_Texture * texture = NULL;
switch(task->type) {
case LV_DRAW_TASK_TYPE_FILL: {
lv_draw_fill_dsc_t * fill_dsc = task->draw_dsc;
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp);
rect_dsc.bg_color = fill_dsc->color;
rect_dsc.bg_grad = fill_dsc->grad;
rect_dsc.radius = fill_dsc->radius;
rect_dsc.bg_opa = fill_dsc->opa;
lv_draw_rect(&dest_layer, &rect_dsc, &task->area);
}
break;
case LV_DRAW_TASK_TYPE_BORDER: {
lv_draw_border_dsc_t * border_dsc = task->draw_dsc;;
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp);
rect_dsc.bg_opa = LV_OPA_TRANSP;
rect_dsc.radius = border_dsc->radius;
rect_dsc.border_color = border_dsc->color;
rect_dsc.border_opa = border_dsc->opa;
rect_dsc.border_side = border_dsc->side;
rect_dsc.border_width = border_dsc->width;
lv_draw_rect(&dest_layer, &rect_dsc, &task->area);
break;
}
case LV_DRAW_TASK_TYPE_LABEL: {
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
lv_memcpy(&label_dsc, task->draw_dsc, sizeof(label_dsc));
label_dsc.base.user_data = lv_sdl_window_get_renderer(disp);
lv_draw_label(&dest_layer, &label_dsc, &task->area);
}
break;
case LV_DRAW_TASK_TYPE_IMAGE: {
lv_draw_image_dsc_t * image_dsc = task->draw_dsc;
// SDL_Surface* loadImage(std::string path) {
const char * path = image_dsc->src;
SDL_Surface * surface = IMG_Load(&path[2]);
if(surface == NULL) {
fprintf(stderr, "could not load image: %s\n", IMG_GetError());
return NULL;
}
lv_display_t * disp = _lv_refr_get_disp_refreshing();
SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp);
texture = SDL_CreateTextureFromSurface(renderer, surface);
break;
}
default:
return NULL;
break;
}
while(dest_layer.draw_task_head) {
lv_draw_dispatch_layer(disp, &dest_layer);
if(dest_layer.draw_task_head) {
lv_draw_dispatch_wait_for_request();
}
}
SDL_Rect rect;
rect.x = dest_layer.buf_area.x1;
rect.y = dest_layer.buf_area.y1;
rect.w = lv_area_get_width(&dest_layer.buf_area);
rect.h = lv_area_get_height(&dest_layer.buf_area);
if(texture == NULL) {
texture = SDL_CreateTexture(lv_sdl_window_get_renderer(disp), SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC, rect.w, rect.h);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_UpdateTexture(texture, NULL, sdl_render_buf, rect.w * 4);
}
else {
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
}
cache_data_t * data = lv_malloc(sizeof(cache_data_t));
lv_draw_dsc_base_t * base_dsc = task->draw_dsc;
data->draw_dsc = lv_malloc(base_dsc->dsc_size);
lv_memcpy((void *)data->draw_dsc, base_dsc, base_dsc->dsc_size);
data->w = lv_area_get_width(&task->area);
data->h = lv_area_get_height(&task->area);
data->texture = texture;
lv_cache_entry_t * e = lv_cache_add(data, sizeof(cache_data_t), u->texture_cache_data_type,
lv_area_get_size(&task->area) * 4);
e->compare_cb = compare_cb;
e->invalidate_cb = invalidate_cb;
e->weight = lv_tick_elaps(tick);
e->weight += lv_area_get_size(&task->area) / 10000;
if(e->weight == 0) e->weight++;
return e;
}
static void blend_texture_layer(lv_draw_sdl_unit_t * u)
{
lv_display_t * disp = _lv_refr_get_disp_refreshing();
SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp);
SDL_Rect clip_rect;
clip_rect.x = u->base_unit.clip_area->x1;
clip_rect.y = u->base_unit.clip_area->y1;
clip_rect.w = lv_area_get_width(u->base_unit.clip_area);
clip_rect.h = lv_area_get_height(u->base_unit.clip_area);
lv_draw_task_t * t = u->task_act;
SDL_Rect rect;
rect.x = t->area.x1;
rect.y = t->area.y1;
rect.w = lv_area_get_width(&t->area);
rect.h = lv_area_get_height(&t->area);
lv_draw_image_dsc_t * draw_dsc = t->draw_dsc;
lv_layer_t * src_layer = (lv_layer_t *)draw_dsc->src;
SDL_Texture * src_texture = layer_get_texture(src_layer);
SDL_SetTextureAlphaMod(src_texture, draw_dsc->opa);
SDL_SetTextureBlendMode(src_texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(renderer, layer_get_texture(u->base_unit.target_layer));
SDL_RenderSetClipRect(renderer, &clip_rect);
SDL_RenderCopy(renderer, src_texture, NULL, &rect);
SDL_DestroyTexture(src_texture);
SDL_RenderSetClipRect(renderer, NULL);
}
static void draw_from_cached_texture(lv_draw_sdl_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
cache_data_t data_to_find;
data_to_find.draw_dsc = (lv_draw_dsc_base_t *)t->draw_dsc;
lv_draw_dsc_base_t * base_dsc = t->draw_dsc;
data_to_find.w = lv_area_get_width(&t->area);
data_to_find.h = lv_area_get_height(&t->area);
data_to_find.texture = NULL;
/*user_data stores the renderer to differentiate it from SW rendered tasks.
*However the cached texture is independent from the renderer so use NULL user_data*/
void * user_data_saved = data_to_find.draw_dsc->user_data;
data_to_find.draw_dsc->user_data = NULL;
lv_cache_lock();
lv_cache_entry_t * e = lv_cache_find_by_data(&data_to_find, sizeof(data_to_find), u->texture_cache_data_type);
data_to_find.draw_dsc->user_data = user_data_saved;
if(e == NULL) {
printf("cache_miss %d\n", t->type);
e = draw_to_texture(u);
}
if(e == NULL) {
lv_cache_unlock();
return;
}
const cache_data_t * data_cached = lv_cache_get_data(e);
SDL_Texture * texture = data_cached->texture;
lv_display_t * disp = _lv_refr_get_disp_refreshing();
SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp);
lv_layer_t * dest_layer = u->base_unit.target_layer;
SDL_Rect clip_rect;
clip_rect.x = u->base_unit.clip_area->x1 - dest_layer->buf_area.x1;
clip_rect.y = u->base_unit.clip_area->y1 - dest_layer->buf_area.y1;
clip_rect.w = lv_area_get_width(u->base_unit.clip_area);
clip_rect.h = lv_area_get_height(u->base_unit.clip_area);
SDL_Rect rect;
SDL_SetRenderTarget(renderer, layer_get_texture(dest_layer));
if(t->type == LV_DRAW_TASK_TYPE_IMAGE) {
lv_draw_image_dsc_t * draw_dsc = t->draw_dsc;
lv_area_t image_area;
image_area.x1 = 0;
image_area.y1 = 0;
image_area.x2 = draw_dsc->header.w - 1;
image_area.y2 = draw_dsc->header.h - 1;
lv_area_move(&image_area, t->area.x1 - dest_layer->buf_area.x1, t->area.y1 - dest_layer->buf_area.y1);
rect.x = image_area.x1;
rect.y = image_area.y1;
rect.w = lv_area_get_width(&image_area);
rect.h = lv_area_get_height(&image_area);
SDL_RenderSetClipRect(renderer, &clip_rect);
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
else {
rect.x = t->area.x1 - dest_layer->buf_area.x1;
rect.y = t->area.y1 - dest_layer->buf_area.y1;
rect.w = lv_area_get_width(&t->area);
rect.h = lv_area_get_height(&t->area);
SDL_RenderSetClipRect(renderer, &clip_rect);
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
SDL_RenderSetClipRect(renderer, NULL);
lv_cache_release(e);
lv_cache_unlock();
}
static void execute_drawing(lv_draw_sdl_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
if(t->type == LV_DRAW_TASK_TYPE_BOX_SHADOW) return;
if(t->type == LV_DRAW_TASK_TYPE_LINE) return;
if(t->type == LV_DRAW_TASK_TYPE_TRIANGLE) return;
if(t->type == LV_DRAW_TASK_TYPE_BG_IMG) return;
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
blend_texture_layer(u);
}
else {
draw_from_cached_texture(u);
}
}
static SDL_Texture * layer_get_texture(lv_layer_t * layer)
{
return layer->user_data;
}
#endif /*LV_USE_DRAW_SDL*/

View File

@@ -0,0 +1,89 @@
/**
* @file lv_draw_sw.h
*
*/
#ifndef LV_DRAW_SW_H
#define LV_DRAW_SW_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_draw.h"
#if LV_USE_DRAW_SDL
#include "../../misc/lv_area.h"
#include "../../misc/lv_color.h"
#include "../../display/lv_display.h"
#include "../../osal/lv_os.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_unit_t base_unit;
struct _lv_draw_task_t * task_act;
uint32_t texture_cache_data_type;
} lv_draw_sdl_unit_t;
#if LV_DRAW_SW_SHADOW_CACHE_SIZE
typedef struct {
uint8_t cache[LV_DRAW_SW_SHADOW_CACHE_SIZE * LV_DRAW_SW_SHADOW_CACHE_SIZE];
int32_t cache_size;
int32_t cache_r;
} lv_draw_sw_shadow_cache_t;
#endif
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_sdl_init(void);
LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords);
void lv_draw_sdl_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sdl_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sdl_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sdl_bg_image(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sdl_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_sdl_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords);
LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
void lv_draw_sdl_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords);
void lv_draw_sdl_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc);
void lv_draw_sdl_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords);
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_SDL*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SDL_H*/

View File

@@ -40,7 +40,9 @@
static void execute_drawing(lv_draw_sw_unit_t * u); static void execute_drawing(lv_draw_sw_unit_t * u);
static int32_t lv_draw_sw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit); static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit);
/********************** /**********************
@@ -66,7 +68,8 @@ void lv_draw_sw_init(void)
uint32_t i; uint32_t i;
for(i = 0; i < LV_DRAW_SW_DRAW_UNIT_CNT; i++) { for(i = 0; i < LV_DRAW_SW_DRAW_UNIT_CNT; i++) {
lv_draw_sw_unit_t * draw_sw_unit = lv_draw_create_unit(sizeof(lv_draw_sw_unit_t)); lv_draw_sw_unit_t * draw_sw_unit = lv_draw_create_unit(sizeof(lv_draw_sw_unit_t));
draw_sw_unit->base_unit.dispatch_cb = lv_draw_sw_dispatch; draw_sw_unit->base_unit.dispatch_cb = dispatch;
draw_sw_unit->base_unit.evaluate_cb = evaluate;
draw_sw_unit->idx = i; draw_sw_unit->idx = i;
draw_sw_unit->base_unit.delete_cb = LV_USE_OS ? lv_draw_sw_delete : NULL; draw_sw_unit->base_unit.delete_cb = LV_USE_OS ? lv_draw_sw_delete : NULL;
@@ -114,7 +117,18 @@ static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static int32_t lv_draw_sw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
{
LV_UNUSED(draw_unit);
if(task->preference_score >= 100) {
task->preference_score = 100;
task->preferred_draw_unit_id = DRAW_UNIT_ID_SW;
}
return 0;
}
static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{ {
lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit;

View File

@@ -197,7 +197,7 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj
lv_image_dsc_t * img = lv_canvas_get_image(obj); lv_image_dsc_t * img = lv_canvas_get_image(obj);
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(img, LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(img, LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
if(!img->data) { if(!img->data) {
@@ -205,9 +205,9 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj
return; return;
} }
LV_LOG_INFO("free canvas buffer: %p", img->data); LV_LOG_INFO("free canvas buffer: %p", lv_canvas_get_buf(obj));
lv_draw_buf_free((void *)img->data); lv_draw_buf_free((void *)lv_canvas_get_buf(obj));
img->data = NULL; img->data = NULL;
} }
@@ -216,12 +216,13 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h)
LV_ASSERT_NULL(obj); LV_ASSERT_NULL(obj);
LV_ASSERT(w > 0); LV_ASSERT(w > 0);
lv_image_dsc_t * img = lv_canvas_get_image(obj); void * buf = (void *)lv_canvas_get_buf(obj);
void * buf = (void *)img->data; lv_draw_buf_free((void *)buf);
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_I1); uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_I1);
uint32_t buf_size = stride * h; uint32_t buf_size = stride * h;
buf = lv_draw_buf_malloc(buf_size, LV_COLOR_FORMAT_I1); /*+8 for the 2x4 byte pallette*/
buf = lv_draw_buf_malloc(buf_size + 8, LV_COLOR_FORMAT_I1);
LV_ASSERT_MALLOC(buf); LV_ASSERT_MALLOC(buf);
if(!buf) { if(!buf) {
@@ -229,7 +230,6 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h)
return false; return false;
} }
lv_draw_buf_free((void *)img->data);
lv_canvas_set_buffer(obj, buf, w, h, LV_COLOR_FORMAT_I1); lv_canvas_set_buffer(obj, buf, w, h, LV_COLOR_FORMAT_I1);
LV_LOG_INFO("set canvas buffer: %p, width = %d", buf, (int)w); LV_LOG_INFO("set canvas buffer: %p, width = %d", buf, (int)w);
return true; return true;

View File

@@ -63,7 +63,7 @@ void lv_gif_set_src(lv_obj_t * obj, const void * src)
/*Close previous gif if any*/ /*Close previous gif if any*/
if(gifobj->gif) { if(gifobj->gif) {
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
gd_close_gif(gifobj->gif); gd_close_gif(gifobj->gif);
@@ -127,7 +127,7 @@ static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
lv_gif_t * gifobj = (lv_gif_t *) obj; lv_gif_t * gifobj = (lv_gif_t *) obj;
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
if(gifobj->gif) if(gifobj->gif)
@@ -155,7 +155,7 @@ static void next_frame_task_cb(lv_timer_t * t)
gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data); gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data);
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
lv_obj_invalidate(obj); lv_obj_invalidate(obj);
} }

View File

@@ -39,6 +39,7 @@ static const void * decode_jpeg_file(const char * filename);
static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height);
static void error_exit(j_common_ptr cinfo); static void error_exit(j_common_ptr cinfo);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
static void cache_invalidate_cb(lv_cache_entry_t * entry);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -61,6 +62,7 @@ void lv_libjpeg_turbo_init(void)
lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close); lv_image_decoder_set_close_cb(dec, decoder_close);
dec->cache_data_type = lv_cache_register_data_type();
} }
void lv_libjpeg_turbo_deinit(void) void lv_libjpeg_turbo_deinit(void)
@@ -155,26 +157,26 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src; const char * fn = dsc->src;
uint32_t t = lv_tick_get();
const void * decoded_img = decode_jpeg_file(fn);
t = lv_tick_elaps(t);
lv_cache_lock(); lv_cache_lock();
lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * JPEG_PIXEL_SIZE); lv_cache_entry_t * cache = lv_cache_add(decoded_img, 0, dsc->header.w * dsc->header.h * JPEG_PIXEL_SIZE,
decoder->cache_data_type);
if(cache == NULL) { if(cache == NULL) {
lv_cache_unlock(); lv_cache_unlock();
return LV_RESULT_INVALID; return LV_RESULT_INVALID;
} }
uint32_t t = lv_tick_get();
const void * decoded_img = decode_jpeg_file(fn);
t = lv_tick_elaps(t);
cache->weight = t; cache->weight = t;
cache->data = decoded_img; cache->invalidate_cb = cache_invalidate_cb;
cache->free_data = 1;
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src); cache->src = lv_strdup(dsc->src);
cache->src_type = LV_CACHE_SRC_TYPE_STR; cache->src_type = LV_CACHE_SRC_TYPE_PATH;
cache->free_src = 1;
} }
else { else {
cache->src_type = LV_CACHE_SRC_TYPE_PTR; cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
cache->src = dsc->src; cache->src = dsc->src;
} }
@@ -205,7 +207,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src; const char * fn = dsc->src;
lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
if(cache) { if(cache) {
dsc->img_data = lv_cache_get_data(cache); dsc->img_data = lv_cache_get_data(cache);
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
@@ -473,4 +475,12 @@ static void error_exit(j_common_ptr cinfo)
longjmp(myerr->jb, 1); longjmp(myerr->jb, 1);
} }
static void cache_invalidate_cb(lv_cache_entry_t * entry)
{
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
lv_free((void *)entry->data);
}
#endif /*LV_USE_LIBJPEG_TURBO*/ #endif /*LV_USE_LIBJPEG_TURBO*/

View File

@@ -28,6 +28,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static const void * decode_png_file(const char * filename); static const void * decode_png_file(const char * filename);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
static void cache_invalidate_cb(lv_cache_entry_t * entry);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -50,6 +51,7 @@ void lv_libpng_init(void)
lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close); lv_image_decoder_set_close_cb(dec, decoder_close);
dec->cache_data_type = lv_cache_register_data_type();
} }
void lv_libpng_deinit(void) void lv_libpng_deinit(void)
@@ -129,26 +131,26 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
/*If it's a PNG file...*/ /*If it's a PNG file...*/
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src; const char * fn = dsc->src;
uint32_t t = lv_tick_get();
const void * decoded_img = decode_png_file(fn);
t = lv_tick_elaps(t);
lv_cache_lock(); lv_cache_lock();
lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * sizeof(uint32_t)); lv_cache_entry_t * cache = lv_cache_add(decoded_img, 0, decoder->cache_data_type,
dsc->header.w * dsc->header.h * sizeof(uint32_t));
if(cache == NULL) { if(cache == NULL) {
lv_cache_unlock(); lv_cache_unlock();
return LV_RESULT_INVALID; return LV_RESULT_INVALID;
} }
uint32_t t = lv_tick_get();
const void * decoded_img = decode_png_file(fn);
t = lv_tick_elaps(t);
cache->weight = t; cache->weight = t;
cache->data = decoded_img; cache->invalidate_cb = cache_invalidate_cb;
cache->free_data = 1;
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src); cache->src = lv_strdup(dsc->src);
cache->src_type = LV_CACHE_SRC_TYPE_STR; cache->src_type = LV_CACHE_SRC_TYPE_PATH;
cache->free_src = 1;
} }
else { else {
cache->src_type = LV_CACHE_SRC_TYPE_PTR; cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
cache->src = dsc->src; cache->src = dsc->src;
} }
@@ -180,7 +182,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src; const char * fn = dsc->src;
lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
if(cache) { if(cache) {
dsc->img_data = lv_cache_get_data(cache); dsc->img_data = lv_cache_get_data(cache);
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
@@ -299,4 +301,11 @@ static const void * decode_png_file(const char * filename)
return image_data; return image_data;
} }
static void cache_invalidate_cb(lv_cache_entry_t * entry)
{
lv_free((void *)entry->src);
lv_free((void *)entry->data);
}
#endif /*LV_USE_LIBPNG*/ #endif /*LV_USE_LIBPNG*/

View File

@@ -20,6 +20,9 @@
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct {
} cache_data_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
@@ -30,6 +33,7 @@ static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc
static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt); static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt);
static const void * decode_png_data(const void * png_data, size_t png_data_size); static const void * decode_png_data(const void * png_data, size_t png_data_size);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
static void cache_invalidate_cb(lv_cache_entry_t * entry);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -52,6 +56,7 @@ void lv_lodepng_init(void)
lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close); lv_image_decoder_set_close_cb(dec, decoder_close);
dec->cache_data_type = lv_cache_register_data_type();
} }
void lv_lodepng_deinit(void) void lv_lodepng_deinit(void)
@@ -182,7 +187,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
} }
lv_cache_lock(); lv_cache_lock();
lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * 4); lv_cache_entry_t * cache = lv_cache_add(NULL, 0, decoder->cache_data_type, dsc->header.w * dsc->header.h * 4);
if(cache == NULL) { if(cache == NULL) {
lv_cache_unlock(); lv_cache_unlock();
return LV_RESULT_INVALID; return LV_RESULT_INVALID;
@@ -193,15 +198,14 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
t = lv_tick_elaps(t); t = lv_tick_elaps(t);
cache->weight = t; cache->weight = t;
cache->data = decoded_img; cache->data = decoded_img;
cache->free_data = 1; cache->invalidate_cb = cache_invalidate_cb;
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src); cache->src = lv_strdup(dsc->src);
cache->src_type = LV_CACHE_SRC_TYPE_STR; cache->src_type = LV_CACHE_SRC_TYPE_PATH;
cache->free_src = 1;
lv_free((void *)png_data); lv_free((void *)png_data);
} }
else { else {
cache->src_type = LV_CACHE_SRC_TYPE_PTR; cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
cache->src = dsc->src; cache->src = dsc->src;
} }
@@ -233,7 +237,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
if(dsc->src_type == LV_IMAGE_SRC_FILE) { if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src; const char * fn = dsc->src;
lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
if(cache) { if(cache) {
dsc->img_data = lv_cache_get_data(cache); dsc->img_data = lv_cache_get_data(cache);
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
@@ -245,7 +249,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = dsc->src; const lv_image_dsc_t * img_dsc = dsc->src;
lv_cache_entry_t * cache = lv_cache_find(img_dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0); lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
if(cache) { if(cache) {
dsc->img_data = lv_cache_get_data(cache); dsc->img_data = lv_cache_get_data(cache);
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
@@ -294,4 +298,10 @@ static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt)
} }
} }
static void cache_invalidate_cb(lv_cache_entry_t * entry)
{
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
lv_free((void *)entry->data);
}
#endif /*LV_USE_LODEPNG*/ #endif /*LV_USE_LODEPNG*/

View File

@@ -66,7 +66,7 @@ void lv_qrcode_set_size(lv_obj_t * obj, int32_t size)
lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj); lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj);
void * buf = (void *)img_dsc->data; void * buf = (void *)img_dsc->data;
uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size, size); uint32_t buf_size = LV_CANVAS_BUF_SIZE(size, size, 1, LV_DRAW_BUF_STRIDE_ALIGN);
buf = lv_realloc(buf, buf_size); buf = lv_realloc(buf, buf_size);
LV_ASSERT_MALLOC(buf); LV_ASSERT_MALLOC(buf);
if(buf == NULL) { if(buf == NULL) {
@@ -226,14 +226,14 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj); lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj);
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(img_dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(img_dsc, LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
if(!img_dsc->data) { if(!img_dsc->data) {
return; return;
} }
lv_free((void *)img_dsc->data); lv_free((void *)lv_canvas_get_image(obj));
img_dsc->data = NULL; img_dsc->data = NULL;
} }

View File

@@ -121,6 +121,12 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d
return true; /*true: glyph found; false: glyph was not found*/ return true; /*true: glyph found; false: glyph was not found*/
} }
static void cache_invalidate_cb(lv_cache_entry_t * entry)
{
lv_draw_buf_free((void *)entry->data);
}
static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter, uint8_t * bitmap_buf) static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter, uint8_t * bitmap_buf)
{ {
LV_UNUSED(bitmap_buf); LV_UNUSED(bitmap_buf);
@@ -139,37 +145,50 @@ static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8); uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8);
lv_cache_lock(); lv_cache_lock();
uint32_t cp = unicode_letter; uint32_t cp = unicode_letter;
lv_cache_entry_t * cache = lv_cache_find(font, LV_CACHE_SRC_TYPE_PTR, font->line_height, cp); lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, font, LV_CACHE_SRC_TYPE_POINTER);
while(cache) {
if(cache->param1 == (int32_t)font->line_height && cache->param2 == (int32_t)cp) break;
cache = lv_cache_find_by_src(cache, font, LV_CACHE_SRC_TYPE_POINTER);
}
if(cache) { if(cache) {
uint8_t * buffer = (uint8_t *)lv_cache_get_data(cache); uint8_t * buffer = (uint8_t *)lv_cache_get_data(cache);
lv_cache_release(cache);
lv_cache_unlock(); lv_cache_unlock();
return buffer; return buffer;
} }
size_t szb = h * stride; size_t szb = h * stride;
lv_cache_entry_t * entry = lv_cache_add(szb);
uint8_t * buffer = lv_draw_buf_malloc(szb, LV_COLOR_FORMAT_A8);
if(NULL == buffer) {
LV_LOG_ERROR("tiny_ttf: out of memory\n");
lv_cache_unlock();
return NULL;
}
lv_cache_entry_t * entry = lv_cache_add(buffer, 0, LV_CACHE_DATA_TYPE_NOT_SET, szb);
if(entry == NULL) { if(entry == NULL) {
lv_cache_unlock(); lv_cache_unlock();
lv_draw_buf_free(buffer);
LV_LOG_ERROR("tiny_ttf: cache not allocated\n"); LV_LOG_ERROR("tiny_ttf: cache not allocated\n");
return NULL; return NULL;
} }
/* This smells. We add the codepoint to the base pointer to get a key. */ /* This smells. We add the codepoint to the base pointer to get a key. */
entry->src = font; entry->src = font;
entry->src_type = LV_CACHE_SRC_TYPE_PTR; entry->src_type = LV_CACHE_SRC_TYPE_POINTER;
entry->param1 = font->line_height; entry->param1 = font->line_height;
entry->param2 = cp; entry->param2 = cp;
uint8_t * buffer = lv_draw_buf_malloc(szb, LV_COLOR_FORMAT_A8); entry->invalidate_cb = cache_invalidate_cb;
if(NULL == buffer) {
LV_LOG_ERROR("tiny_ttf: out of memory\n"); /*Just to increment life*/
lv_cache_invalidate(entry); lv_cache_get_data(entry);
lv_cache_unlock();
return NULL;
}
entry->data = buffer;
entry->free_data = 1;
memset(buffer, 0, szb); memset(buffer, 0, szb);
stbtt_MakeGlyphBitmap(info, buffer, w, h, stride, dsc->scale, dsc->scale, g1); stbtt_MakeGlyphBitmap(info, bitmap_buf, w, h, stride, dsc->scale, dsc->scale, g1);
lv_memcpy(buffer, bitmap_buf, stride * h);
lv_cache_release(entry);
lv_cache_unlock(); lv_cache_unlock();
return buffer; /*Or NULL if not found*/ return bitmap_buf; /*Or NULL if not found*/
} }
static lv_result_t lv_tiny_ttf_create(lv_font_t * out_font, const char * path, const void * data, size_t data_size, static lv_result_t lv_tiny_ttf_create(lv_font_t * out_font, const char * path, const void * data, size_t data_size,
@@ -268,4 +287,6 @@ void lv_tiny_ttf_destroy(lv_font_t * font)
} }
} }
} }
#endif #endif

View File

@@ -28,6 +28,7 @@ extern "C" {
/********************** /**********************
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
#if LV_TINY_TTF_FILE_SUPPORT !=0 #if LV_TINY_TTF_FILE_SUPPORT !=0
/* create a font from the specified file or path with the specified line height.*/ /* create a font from the specified file or path with the specified line height.*/
lv_result_t lv_tiny_ttf_create_file(lv_font_t * font, const char * path, int32_t font_size); lv_result_t lv_tiny_ttf_create_file(lv_font_t * font, const char * path, int32_t font_size);

View File

@@ -325,6 +325,15 @@
#endif #endif
#endif #endif
/* Draw using cached SDL textures*/
#ifndef LV_USE_DRAW_SDL
#ifdef CONFIG_LV_USE_DRAW_SDL
#define LV_USE_DRAW_SDL CONFIG_LV_USE_DRAW_SDL
#else
#define LV_USE_DRAW_SDL 0
#endif
#endif
/*================= /*=================
* OPERATING SYSTEM * OPERATING SYSTEM
*=================*/ *=================*/

View File

@@ -164,6 +164,10 @@ void lv_init(void)
lv_draw_pxp_init(); lv_draw_pxp_init();
#endif #endif
#if LV_USE_DRAW_SDL
lv_draw_sdl_init();
#endif
_lv_obj_style_init(); _lv_obj_style_init();
/*Initialize the screen refresh system*/ /*Initialize the screen refresh system*/

View File

@@ -56,7 +56,7 @@ void lv_cache_set_manager(lv_cache_manager_t * manager)
else if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(0); else if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(0);
_cache_manager.add_cb = manager->add_cb; _cache_manager.add_cb = manager->add_cb;
_cache_manager.find_cb = manager->find_cb; _cache_manager.find_by_data_cb = manager->find_by_data_cb;
_cache_manager.invalidate_cb = manager->invalidate_cb; _cache_manager.invalidate_cb = manager->invalidate_cb;
_cache_manager.get_data_cb = manager->get_data_cb; _cache_manager.get_data_cb = manager->get_data_cb;
_cache_manager.release_cb = manager->release_cb; _cache_manager.release_cb = manager->release_cb;
@@ -66,20 +66,28 @@ void lv_cache_set_manager(lv_cache_manager_t * manager)
if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(_cache_manager.max_size); if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(_cache_manager.max_size);
} }
lv_cache_entry_t * lv_cache_add(size_t size) lv_cache_entry_t * lv_cache_add(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage)
{ {
LV_ASSERT(_cache_manager.locked); LV_ASSERT(_cache_manager.locked);
if(_cache_manager.add_cb == NULL) return NULL; if(_cache_manager.add_cb == NULL) return NULL;
return _cache_manager.add_cb(size); return _cache_manager.add_cb(data, data_size, data_type, memory_usage);
} }
lv_cache_entry_t * lv_cache_find(const void * src_ptr, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2) lv_cache_entry_t * lv_cache_find_by_data(const void * data, size_t data_size, uint32_t data_type)
{ {
LV_ASSERT(_cache_manager.locked); LV_ASSERT(_cache_manager.locked);
if(_cache_manager.find_cb == NULL) return NULL; if(_cache_manager.find_by_data_cb == NULL) return NULL;
return _cache_manager.find_cb(src_ptr, src_type, param1, param2); return _cache_manager.find_by_data_cb(data, data_size, data_type);
}
lv_cache_entry_t * lv_cache_find_by_src(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type)
{
LV_ASSERT(_cache_manager.locked);
if(_cache_manager.find_by_src_cb == NULL) return NULL;
return _cache_manager.find_by_src_cb(entry, src, src_type);
} }
void lv_cache_invalidate(lv_cache_entry_t * entry) void lv_cache_invalidate(lv_cache_entry_t * entry)
@@ -90,6 +98,16 @@ void lv_cache_invalidate(lv_cache_entry_t * entry)
_cache_manager.invalidate_cb(entry); _cache_manager.invalidate_cb(entry);
} }
void lv_cache_invalidate_by_src(const void * src, lv_cache_src_type_t src_type)
{
LV_ASSERT(_cache_manager.locked);
lv_cache_entry_t * entry = lv_cache_find_by_src(NULL, src, src_type);
while(entry) {
lv_cache_invalidate(entry);
entry = lv_cache_find_by_src(entry, src, src_type);
}
}
const void * lv_cache_get_data(lv_cache_entry_t * entry) const void * lv_cache_get_data(lv_cache_entry_t * entry)
{ {
LV_ASSERT(_cache_manager.locked); LV_ASSERT(_cache_manager.locked);
@@ -133,6 +151,12 @@ void lv_cache_unlock(void)
lv_mutex_unlock(&_cache_manager.mutex); lv_mutex_unlock(&_cache_manager.mutex);
} }
uint32_t lv_cache_register_data_type(void)
{
_cache_manager.last_data_type++;
return _cache_manager.last_data_type;
}
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/

View File

@@ -15,41 +15,77 @@ extern "C" {
*********************/ *********************/
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h>
#include "../osal/lv_os.h" #include "../osal/lv_os.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define LV_CACHE_DATA_TYPE_NOT_SET 0xFFFFFFFF
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef enum { typedef enum {
LV_CACHE_SRC_TYPE_PTR, LV_CACHE_SRC_TYPE_PATH,
LV_CACHE_SRC_TYPE_STR, LV_CACHE_SRC_TYPE_POINTER,
_LV_CACHE_SRC_TYPE_LAST,
} lv_cache_src_type_t; } lv_cache_src_type_t;
typedef struct _lv_cache_entry_t { typedef struct _lv_cache_entry_t {
/**The image source or other source related to the cache content.*/
/**
* The data to cache.
* Can be just a pointer to a byte array, or pointer to a complex structure, or anything else*/
const void * data;
/**
* Size of data in bytes.
* It's not the size of the cached data, just the size of the structure pointed by `data`
* E.g. `data` can point to descriptor struct and the size of that struct needs to be stored here.
* It can be used in the `compary_cb` to compare `data` fields of the entries with a requested one*/
uint32_t data_size;
/**An integer ID to tell the type of the cached data.
* If set to `LV_CACHE_DATA_TYPE_NOT_SET` `lv_cache_find_by_data` cannot be used*/
uint32_t data_type;
/**
* The source from which the cache is created.
* It's can or cannot be the same as data, or different, or NULL.
* It's used to find the cache entries which are relted to same source.
* E.g. the same image, font, etc. */
const void * src; const void * src;
lv_cache_src_type_t src_type; lv_cache_src_type_t src_type;
/** Some extra parameters to describe the source. E.g. the current frame of an animation*/ /**Arbitrary parameters to better identify the source*/
uint32_t param1; int32_t param1;
uint32_t param2; int32_t param2;
/** Memory in bytes used by data. */
uint32_t memory_usage;
/**
* Called to compare the data of cache entries.
* Before calling this function LVGL checks that `data_size` of both entries are the same.
* This callback look into `data` and check all the pointers and their content on any level.
* @param data1 first data to compare
* @param data2 second data to compare
* @param data_size size of data
* @return true: `data1` and `data2` are the same
*/
bool (*compare_cb)(const void * data1, const void * data2, size_t data_size);
/**
* Called when the entry is invalidated to free its data
* @param e the cache entry to free
*/
void (*invalidate_cb)(struct _lv_cache_entry_t * e);
/** User processing tag*/ /** User processing tag*/
uint32_t process_state; uint32_t process_state;
/** The data to cache*/
const void * data;
/** Size of data in bytes*/
uint32_t data_size;
/** On access to any cache entry, `life` of each cache entry will be incremented by their own `weight` to keep the entry alive longer*/ /** On access to any cache entry, `life` of each cache entry will be incremented by their own `weight` to keep the entry alive longer*/
uint32_t weight; uint32_t weight;
@@ -61,12 +97,6 @@ typedef struct _lv_cache_entry_t {
* A data will dropped from the cache only if its usage_count is zero */ * A data will dropped from the cache only if its usage_count is zero */
uint32_t usage_count; uint32_t usage_count;
/** Call `lv_free` on `src` when the entry is removed from the cache */
uint32_t free_src : 1;
/** Call `lv_draw_buf_free` on `data` when the entry is removed from the cache */
uint32_t free_data : 1;
/** The cache entry was larger then the max cache size so only a temporary entry was allocated /** The cache entry was larger then the max cache size so only a temporary entry was allocated
* The entry will be closed and freed in `lv_cache_release` automatically*/ * The entry will be closed and freed in `lv_cache_release` automatically*/
uint32_t temporary : 1; uint32_t temporary : 1;
@@ -79,21 +109,33 @@ typedef struct _lv_cache_entry_t {
* Add a new entry to the cache with the given size. * Add a new entry to the cache with the given size.
* It won't allocate any buffers just free enough space to be a new entry * It won't allocate any buffers just free enough space to be a new entry
* with `size` bytes fits. * with `size` bytes fits.
* @param size the size of the new entry in bytes * @param data data the cache, can be a complex structure too
* @return a handler for the new cache entry * @param data_size the size of data (if it's a struct then the size of the struct)
* @param data_type type of data to identify the kind of this cache entry
* @param memory_usage the size of memory used by this entry (`data` might contain pointers so it's size of all buffers related to entry)
* @return a handler for the new cache entry
*/ */
typedef lv_cache_entry_t * (*lv_cache_add_cb)(size_t size); typedef lv_cache_entry_t * (*lv_cache_add_cb)(const void * data, size_t data_size, uint32_t data_type,
size_t memory_usage);
/** /**
* Find a cache entry * Find a cache entry based on its data
* @param src_ptr pointer to the source data * @param data the data to find
* @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`) * @param data_size size of data
* @param param1 param1, which was set when the cache was added * @param data_type ID for the data type
* @param param2 param2, which was set when the cache was added * @return the cache entry with given `data` or NULL if not found
* @return the cache entry with given source and parameters or NULL if not found
*/ */
typedef lv_cache_entry_t * (*lv_cache_find_cb)(const void * src_ptr, lv_cache_src_type_t src_type, uint32_t param1, typedef lv_cache_entry_t * (*lv_cache_find_by_data_cb)(const void * data, size_t data_size, uint32_t data_type);
uint32_t param2);
/**
* Get the next entry which has the given source and parameters
* @param prev_entry pointer to the previous entry from which the nest should be found. NULL means to start from the beginning.
* @param src a pointer or a string
* @param src_type element of lv_cache_src_type_t
* @return the cache entry with given source or NULL if not found
*/
typedef lv_cache_entry_t * (*lv_cache_find_by_src_cb)(lv_cache_entry_t * entry, const void * src,
lv_cache_src_type_t src_type);
/** /**
* Invalidate (drop) a cache entry * Invalidate (drop) a cache entry
@@ -130,7 +172,8 @@ typedef void (*lv_cache_empty_cb)(void);
typedef struct { typedef struct {
lv_cache_add_cb add_cb; lv_cache_add_cb add_cb;
lv_cache_find_cb find_cb; lv_cache_find_by_data_cb find_by_data_cb;
lv_cache_find_by_src_cb find_by_src_cb;
lv_cache_invalidate_cb invalidate_cb; lv_cache_invalidate_cb invalidate_cb;
lv_cache_get_data_cb get_data_cb; lv_cache_get_data_cb get_data_cb;
lv_cache_release_cb release_cb; lv_cache_release_cb release_cb;
@@ -140,6 +183,7 @@ typedef struct {
lv_mutex_t mutex; lv_mutex_t mutex;
size_t max_size; size_t max_size;
uint32_t locked : 1; /**< Show the mutex state, used to log unlocked cache access*/ uint32_t locked : 1; /**< Show the mutex state, used to log unlocked cache access*/
uint32_t last_data_type;
} lv_cache_manager_t; } lv_cache_manager_t;
/********************** /**********************
@@ -166,27 +210,45 @@ void lv_cache_set_manager(lv_cache_manager_t * manager);
* Add a new entry to the cache with the given size. * Add a new entry to the cache with the given size.
* It won't allocate any buffers just free enough space to be a new entry * It won't allocate any buffers just free enough space to be a new entry
* with `size` bytes fits. * with `size` bytes fits.
* @param size the size of the new entry in bytes * @param data data the cache, can be a complex structure too
* @return a handler for the new cache entry * @param data_size the size of data (if it's a struct then the size of the struct)
* @param data_type type of data to identify the kind of this cache entry
* @param memory_usage the size of memory used by this entry (`data` might contain pointers so it's size of all buffers related to entry)
* @return a handler for the new cache entry
*/ */
lv_cache_entry_t * lv_cache_add(size_t size); lv_cache_entry_t * lv_cache_add(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage);
/** /**
* Find a cache entry with pointer source type * Find a cache entry based on its data
* @param src_ptr pointer to the source data * @param data the data to find
* @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`) * @param data_size size of data
* @param param1 param1, which was set when the cache was added * @param data_type ID of data type
* @param param2 param2, which was set when the cache was added * @return the cache entry with given `data` or NULL if not found
* @return the cache entry with given source and parameters or NULL if not found
*/ */
lv_cache_entry_t * lv_cache_find(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2); lv_cache_entry_t * lv_cache_find_by_data(const void * data, size_t data_size, uint32_t data_type);
/** /**
* Invalidate (drop) a cache entry * Get the next entry which has the given source and parameters
* @param prev_entry pointer to the previous entry from which the nest should be found. NULL means to start from the beginning.
* @param src a pointer or a string
* @param src_type element of lv_cache_src_type_t
* @return the cache entry with given source or NULL if not found
*/
lv_cache_entry_t * lv_cache_find_by_src(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type);
/**
* Invalidate (drop) a cache entry. It will call the entry's `invalidate_cb` to free the resources
* @param entry the entry to invalidate. (can be retrieved by `lv_cache_find()`) * @param entry the entry to invalidate. (can be retrieved by `lv_cache_find()`)
*/ */
void lv_cache_invalidate(lv_cache_entry_t * entry); void lv_cache_invalidate(lv_cache_entry_t * entry);
/**
* Invalidate all cache entries with a given source
* @param src a pointer or a string
* @param src_type element of lv_cache_src_type_t
*/
void lv_cache_invalidate_by_src(const void * src, lv_cache_src_type_t src_type);
/** /**
* Get the data of a cache entry. * Get the data of a cache entry.
* It is considered a cached data access so the cache manager can count that * It is considered a cached data access so the cache manager can count that
@@ -227,6 +289,12 @@ void lv_cache_lock(void);
*/ */
void lv_cache_unlock(void); void lv_cache_unlock(void);
/**
* Register a data type which can be used as `entry->data_type`.
* @return the registered unique data type ID.
*/
uint32_t lv_cache_register_data_type(void);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

View File

@@ -25,8 +25,9 @@
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static lv_cache_entry_t * add_cb(size_t size); static lv_cache_entry_t * add_cb(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage);
static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2); static lv_cache_entry_t * find_by_data_cb(const void * data, size_t data_size, uint32_t data_type);
static lv_cache_entry_t * find_by_src_cb(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type);
static void invalidate_cb(lv_cache_entry_t * entry); static void invalidate_cb(lv_cache_entry_t * entry);
static const void * get_data_cb(lv_cache_entry_t * entry); static const void * get_data_cb(lv_cache_entry_t * entry);
static void release_cb(lv_cache_entry_t * entry); static void release_cb(lv_cache_entry_t * entry);
@@ -57,7 +58,8 @@ void _lv_cache_builtin_init(void)
_lv_ll_init(&dsc.entry_ll, sizeof(lv_cache_entry_t)); _lv_ll_init(&dsc.entry_ll, sizeof(lv_cache_entry_t));
_cache_manager.add_cb = add_cb; _cache_manager.add_cb = add_cb;
_cache_manager.find_cb = find_cb; _cache_manager.find_by_data_cb = find_by_data_cb;
_cache_manager.find_by_src_cb = find_by_src_cb;
_cache_manager.invalidate_cb = invalidate_cb; _cache_manager.invalidate_cb = invalidate_cb;
_cache_manager.get_data_cb = get_data_cb; _cache_manager.get_data_cb = get_data_cb;
_cache_manager.release_cb = release_cb; _cache_manager.release_cb = release_cb;
@@ -74,15 +76,15 @@ void _lv_cache_builtin_deinit(void)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static lv_cache_entry_t * add_cb(size_t size) static lv_cache_entry_t * add_cb(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage)
{ {
size_t max_size = lv_cache_get_max_size(); size_t max_size = lv_cache_get_max_size();
/*Can't cache data larger than max size*/ /*Can't cache data larger than max size*/
bool temporary = size > max_size ? true : false; bool temporary = memory_usage > max_size ? true : false;
if(!temporary) { if(!temporary) {
/*Keep dropping items until there is enough space*/ /*Keep dropping items until there is enough space*/
while(dsc.cur_size + size > _cache_manager.max_size) { while(dsc.cur_size + memory_usage > _cache_manager.max_size) {
bool ret = drop_youngest(); bool ret = drop_youngest();
/*No item could be dropped. /*No item could be dropped.
@@ -96,29 +98,32 @@ static lv_cache_entry_t * add_cb(size_t size)
lv_cache_entry_t * entry = _lv_ll_ins_head(&dsc.entry_ll); lv_cache_entry_t * entry = _lv_ll_ins_head(&dsc.entry_ll);
lv_memzero(entry, sizeof(lv_cache_entry_t)); lv_memzero(entry, sizeof(lv_cache_entry_t));
entry->data_size = size; entry->memory_usage = memory_usage;
entry->weight = 1; entry->weight = 1;
entry->temporary = temporary; entry->temporary = temporary;
entry->data = data;
entry->data_size = data_size;
entry->data_type = data_type;
if(temporary) { if(temporary) {
LV_TRACE_CACHE("Add temporary cache: %lu bytes", (unsigned long)size); LV_TRACE_CACHE("Add temporary cache: %lu bytes", (unsigned long)memory_usage);
} }
else { else {
LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)size); LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)memory_usage);
dsc.cur_size += size; dsc.cur_size += memory_usage;
} }
return entry; return entry;
} }
static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2) static lv_cache_entry_t * find_by_data_cb(const void * data, size_t data_size, uint32_t data_type)
{ {
lv_cache_entry_t * entry = _lv_ll_get_head(&dsc.entry_ll); lv_cache_entry_t * entry = _lv_ll_get_head(&dsc.entry_ll);
while(entry) { while(entry) {
if(param1 == entry->param1 && param2 == entry->param2 && src_type == entry->src_type && if(entry->data_type == data_type && entry->data_size == data_size) {
((src_type == LV_CACHE_SRC_TYPE_PTR && src == entry->src) || if(entry->compare_cb(entry->data, data, data_size)) {
(src_type == LV_CACHE_SRC_TYPE_STR && strcmp(src, entry->src) == 0))) { return entry;
return entry; }
} }
entry = _lv_ll_get_next(&dsc.entry_ll, entry); entry = _lv_ll_get_next(&dsc.entry_ll, entry);
@@ -127,15 +132,28 @@ static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type
return NULL; return NULL;
} }
static lv_cache_entry_t * find_by_src_cb(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type)
{
if(entry == NULL) entry = _lv_ll_get_head(&dsc.entry_ll);
else entry = _lv_ll_get_next(&dsc.entry_ll, entry);
while(entry) {
if(src_type == LV_CACHE_SRC_TYPE_POINTER && entry->src == src) return entry;
if(src_type == LV_CACHE_SRC_TYPE_PATH && lv_strcmp(entry->src, src) == 0) return entry;
entry = _lv_ll_get_next(&dsc.entry_ll, entry);
}
return NULL;
}
static void invalidate_cb(lv_cache_entry_t * entry) static void invalidate_cb(lv_cache_entry_t * entry)
{ {
if(entry == NULL) return; if(entry == NULL) return;
dsc.cur_size -= entry->data_size; dsc.cur_size -= entry->memory_usage;
LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->data_size); LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->memory_usage);
if(entry->free_src) lv_free((void *)entry->src); if(entry->invalidate_cb) entry->invalidate_cb(entry);
if(entry->free_data) lv_draw_buf_free((void *)entry->data);
_lv_ll_remove(&dsc.entry_ll, entry); _lv_ll_remove(&dsc.entry_ll, entry);
lv_free(entry); lv_free(entry);

View File

@@ -129,7 +129,7 @@ lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_ima
layer.buf_area.x2 = snapshot_area.x1 + w - 1; layer.buf_area.x2 = snapshot_area.x1 + w - 1;
layer.buf_area.y2 = snapshot_area.y1 + h - 1; layer.buf_area.y2 = snapshot_area.y1 + h - 1;
layer.color_format = cf; layer.color_format = cf;
layer.clip_area = snapshot_area; layer._clip_area = snapshot_area;
lv_display_t * disp_old = _lv_refr_get_disp_refreshing(); lv_display_t * disp_old = _lv_refr_get_disp_refreshing();
lv_display_t * disp_new = lv_obj_get_disp(obj); lv_display_t * disp_new = lv_obj_get_disp(obj);

View File

@@ -171,6 +171,15 @@ char * lv_strcpy(char * dst, const char * src)
return tmp; return tmp;
} }
int32_t lv_strcmp(const char * s1, const char * s2)
{
while(*s1 && (*s1 == *s2)) {
s1++;
s2++;
}
return *(const unsigned char *)s1 - *(const unsigned char *)s2;
}
char * lv_strdup(const char * src) char * lv_strdup(const char * src)
{ {
size_t len = lv_strlen(src) + 1; size_t len = lv_strlen(src) + 1;

View File

@@ -68,6 +68,11 @@ char * lv_strcpy(char * dst, const char * src)
return strcpy(dst, src); return strcpy(dst, src);
} }
int32_t lv_strcmp(const char * s1, const char * s2)
{
return strcmp(s1, s2);
}
char * lv_strdup(const char * src) char * lv_strdup(const char * src)
{ {
/*strdup uses malloc, so use the built in malloc if it's enabled */ /*strdup uses malloc, so use the built in malloc if it's enabled */

View File

@@ -83,6 +83,21 @@ char * lv_strncpy(char * dst, const char * src, size_t dest_size);
*/ */
char * lv_strcpy(char * dst, const char * src); char * lv_strcpy(char * dst, const char * src);
/**
* Compare 2 strings
* @param s1 pointer to the first string
* @param s2 pointer to the first string
* @return the difference between the value of the first unmatching character.
*/
int32_t lv_strcmp(const char * s1, const char * s2);
/**
* @brief Duplicate a string by allocating a new one and copying the content.
* @param src Pointer to the source of data to be copied.
* @return A pointer to the new allocated string. NULL if failed.
*/
char * lv_strdup(const char * src);
/** /**
* @brief Duplicate a string by allocating a new one and copying the content. * @brief Duplicate a string by allocating a new one and copying the content.
* @param src Pointer to the source of data to be copied. * @param src Pointer to the source of data to be copied.

View File

@@ -453,7 +453,7 @@ static void draw_indic(lv_event_t * e)
draw_rect_dsc.shadow_width = 0; draw_rect_dsc.shadow_width = 0;
lv_area_t indic_clip_area; lv_area_t indic_clip_area;
if(_lv_area_intersect(&indic_clip_area, &indic_area, &layer->clip_area)) { if(_lv_area_intersect(&indic_clip_area, &indic_area, &layer->_clip_area)) {
lv_layer_t * layer_indic = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &indic_area); lv_layer_t * layer_indic = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &indic_area);
lv_draw_rect(layer_indic, &draw_rect_dsc, &indic_area); lv_draw_rect(layer_indic, &draw_rect_dsc, &indic_area);

View File

@@ -70,16 +70,17 @@ void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_c
lv_canvas_t * canvas = (lv_canvas_t *)obj; lv_canvas_t * canvas = (lv_canvas_t *)obj;
canvas->buf_unaligned = buf;
canvas->dsc.header.cf = cf; canvas->dsc.header.cf = cf;
canvas->dsc.header.w = w; canvas->dsc.header.w = w;
canvas->dsc.header.h = h; canvas->dsc.header.h = h;
canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf); /*Let LVGL calculate it automatically*/ canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf);
canvas->dsc.data = buf; canvas->dsc.data = lv_draw_buf_align(buf, cf);
canvas->dsc.data_size = w * h * lv_color_format_get_size(cf); canvas->dsc.data_size = w * h * lv_color_format_get_size(cf);
lv_image_set_src(obj, &canvas->dsc); lv_image_set_src(obj, &canvas->dsc);
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(&canvas->dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(&canvas->dsc, LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
} }
@@ -205,6 +206,15 @@ lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * obj)
return &canvas->dsc; return &canvas->dsc;
} }
const void * lv_canvas_get_buf(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_canvas_t * canvas = (lv_canvas_t *)obj;
return canvas->buf_unaligned;
}
/*===================== /*=====================
* Other functions * Other functions
*====================*/ *====================*/
@@ -298,7 +308,7 @@ void lv_canvas_init_layer(lv_obj_t * canvas, lv_layer_t * layer)
layer->buf = lv_draw_buf_align((uint8_t *)dsc->data, dsc->header.cf); layer->buf = lv_draw_buf_align((uint8_t *)dsc->data, dsc->header.cf);
layer->color_format = dsc->header.cf; layer->color_format = dsc->header.cf;
layer->buf_area = canvas_area; layer->buf_area = canvas_area;
layer->clip_area = canvas_area; layer->_clip_area = canvas_area;
layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format);
} }
@@ -340,7 +350,7 @@ static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
lv_canvas_t * canvas = (lv_canvas_t *)obj; lv_canvas_t * canvas = (lv_canvas_t *)obj;
lv_cache_lock(); lv_cache_lock();
lv_cache_invalidate(lv_cache_find(&canvas->dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); lv_cache_invalidate_by_src(&canvas->dsc, LV_CACHE_SRC_TYPE_POINTER);
lv_cache_unlock(); lv_cache_unlock();
} }

View File

@@ -33,6 +33,7 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_canvas_class;
typedef struct { typedef struct {
lv_image_t img; lv_image_t img;
lv_image_dsc_t dsc; lv_image_dsc_t dsc;
const void * buf_unaligned;
} lv_canvas_t; } lv_canvas_t;
/********************** /**********************
@@ -91,6 +92,15 @@ lv_color32_t lv_canvas_get_px(lv_obj_t * obj, int32_t x, int32_t y);
*/ */
lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * canvas); lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * canvas);
/**
* Return the pointer for the buffer.
* It's recommended to use this function instead of the buffer form the
* return value of lv_canvas_get_image() as is can be aligned
* @param canvas pointer to a canvas object
* @return pointer to the buffer
*/
const void * lv_canvas_get_buf(lv_obj_t * canvas);
/*===================== /*=====================
* Other functions * Other functions
*====================*/ *====================*/
@@ -122,21 +132,8 @@ void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR(w, h)
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h)
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR_ALPHA(w, h)
/*+ 1: to be sure no fractional row*/ #define LV_CANVAS_BUF_SIZE(w, h, bpp, stride) (((((w * bpp + 7) >> 3) + stride - 1) & ~(stride - 1)) * h + LV_DRAW_BUF_ALIGN)
#define LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_1BIT(w, h)
#define LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_2BIT(w, h)
#define LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_4BIT(w, h)
#define LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_8BIT(w, h)
/*4 * X: for palette*/
#define LV_CANVAS_BUF_SIZE_INDEXED_1BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_1BIT(w, h)
#define LV_CANVAS_BUF_SIZE_INDEXED_2BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_2BIT(w, h)
#define LV_CANVAS_BUF_SIZE_INDEXED_4BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_4BIT(w, h)
#define LV_CANVAS_BUF_SIZE_INDEXED_8BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_8BIT(w, h)
#endif /*LV_USE_CANVAS*/ #endif /*LV_USE_CANVAS*/

View File

@@ -719,11 +719,11 @@ static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer)
lv_chart_t * chart = (lv_chart_t *)obj; lv_chart_t * chart = (lv_chart_t *)obj;
lv_area_t series_clip_area; lv_area_t series_clip_area;
bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->clip_area); bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area);
if(mask_ret == false) return; if(mask_ret == false) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = series_clip_area; layer->_clip_area = series_clip_area;
int16_t i; int16_t i;
int16_t i_start; int16_t i_start;
@@ -787,16 +787,16 @@ static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer)
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer) static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer)
{ {
lv_area_t clip_area; lv_area_t clip_area;
if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
lv_chart_t * chart = (lv_chart_t *)obj; lv_chart_t * chart = (lv_chart_t *)obj;
if(chart->point_cnt < 2) return; if(chart->point_cnt < 2) return;
@@ -812,7 +812,7 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer)
lv_chart_series_t * ser; lv_chart_series_t * ser;
lv_area_t series_clip_area; lv_area_t series_clip_area;
bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->clip_area); bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area);
if(mask_ret == false) return; if(mask_ret == false) return;
lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_t line_dsc;
@@ -934,17 +934,17 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer)
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer) static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer)
{ {
lv_area_t clip_area; lv_area_t clip_area;
if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
lv_chart_t * chart = (lv_chart_t *)obj; lv_chart_t * chart = (lv_chart_t *)obj;
@@ -1054,17 +1054,17 @@ static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer)
} }
line_dsc.base.id1++; line_dsc.base.id1++;
point_dsc_default.base.id1++; point_dsc_default.base.id1++;
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
} }
static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer) static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer)
{ {
lv_area_t clip_area; lv_area_t clip_area;
if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
lv_chart_t * chart = (lv_chart_t *)obj; lv_chart_t * chart = (lv_chart_t *)obj;
@@ -1128,7 +1128,7 @@ static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer)
col_dsc.base.id1++; col_dsc.base.id1++;
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer) static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer)
@@ -1139,10 +1139,10 @@ static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer)
if(_lv_ll_is_empty(&chart->cursor_ll)) return; if(_lv_ll_is_empty(&chart->cursor_ll)) return;
lv_area_t clip_area; lv_area_t clip_area;
if(!_lv_area_intersect(&clip_area, &layer->clip_area, &obj->coords)) return; if(!_lv_area_intersect(&clip_area, &layer->_clip_area, &obj->coords)) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
lv_chart_cursor_t * cursor; lv_chart_cursor_t * cursor;
@@ -1226,7 +1226,7 @@ static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer)
point_dsc_ori.base.id1++; point_dsc_ori.base.id1++;
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
/** /**

View File

@@ -908,10 +908,10 @@ static void draw_list(lv_event_t * e)
* the selected option can be drawn on only the background*/ * the selected option can be drawn on only the background*/
lv_area_t clip_area_core; lv_area_t clip_area_core;
bool has_common; bool has_common;
has_common = _lv_area_intersect(&clip_area_core, &layer->clip_area, &dropdown->list->coords); has_common = _lv_area_intersect(&clip_area_core, &layer->_clip_area, &dropdown->list->coords);
if(has_common) { if(has_common) {
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area_core; layer->_clip_area = clip_area_core;
if(dropdown->selected_highlight) { if(dropdown->selected_highlight) {
if(dropdown->pr_opt_id == dropdown->sel_opt_id) { if(dropdown->pr_opt_id == dropdown->sel_opt_id) {
draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED);
@@ -928,7 +928,7 @@ static void draw_list(lv_event_t * e)
draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED);
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
} }
@@ -1005,13 +1005,13 @@ static void draw_box_label(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t
area_sel.x2 = list_obj->coords.x2; area_sel.x2 = list_obj->coords.x2;
lv_area_t mask_sel; lv_area_t mask_sel;
bool area_ok; bool area_ok;
area_ok = _lv_area_intersect(&mask_sel, &layer->clip_area, &area_sel); area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &area_sel);
if(area_ok) { if(area_ok) {
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = mask_sel; layer->_clip_area = mask_sel;
label_dsc.text = lv_label_get_text(label); label_dsc.text = lv_label_get_text(label);
lv_draw_label(layer, &label_dsc, &label->coords); lv_draw_label(layer, &label_dsc, &label->coords);
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
list_obj->state = state_orig; list_obj->state = state_orig;
list_obj->skip_trans = 0; list_obj->skip_trans = 0;

View File

@@ -360,7 +360,7 @@ void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom)
if(zoom == 0) zoom = 1; if(zoom == 0) zoom = 1;
scale_update(obj, img->scale_y, zoom); scale_update(obj, img->scale_x, zoom);
} }
void lv_image_set_antialias(lv_obj_t * obj, bool antialias) void lv_image_set_antialias(lv_obj_t * obj, bool antialias)
@@ -664,7 +664,7 @@ static void draw_image(lv_event_t * e)
lv_draw_image_dsc_init(&draw_dsc); lv_draw_image_dsc_init(&draw_dsc);
lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &draw_dsc); lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &draw_dsc);
lv_area_t clip_area_ori = layer->clip_area; lv_area_t clip_area_ori = layer->_clip_area;
lv_image_get_pivot(obj, &draw_dsc.pivot); lv_image_get_pivot(obj, &draw_dsc.pivot);
draw_dsc.scale_x = img->scale_x; draw_dsc.scale_x = img->scale_x;
@@ -680,17 +680,17 @@ static void draw_image(lv_event_t * e)
lv_area_align(&obj->coords, &img_area, img->align, img->offset.x, img->offset.y); lv_area_align(&obj->coords, &img_area, img->align, img->offset.x, img->offset.y);
} }
else if(img->align == LV_IMAGE_ALIGN_TILE) { else if(img->align == LV_IMAGE_ALIGN_TILE) {
_lv_area_intersect(&layer->clip_area, &layer->clip_area, &obj->coords); _lv_area_intersect(&layer->_clip_area, &layer->_clip_area, &obj->coords);
lv_area_move(&img_area, img->offset.x, img->offset.y); lv_area_move(&img_area, img->offset.x, img->offset.y);
lv_area_move(&img_area, lv_area_move(&img_area,
((layer->clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w, ((layer->_clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w,
((layer->clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h); ((layer->_clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h);
draw_dsc.tile = 1; draw_dsc.tile = 1;
} }
lv_draw_image(layer, &draw_dsc, &img_area); lv_draw_image(layer, &draw_dsc, &img_area);
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
else if(img->src_type == LV_IMAGE_SRC_SYMBOL) { else if(img->src_type == LV_IMAGE_SRC_SYMBOL) {

View File

@@ -262,12 +262,12 @@ static void draw_main(lv_event_t * e)
clip_area_center.y2 = coords.y2; clip_area_center.y2 = coords.y2;
bool comm_res; bool comm_res;
comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, &layer->clip_area); comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, &layer->_clip_area);
if(comm_res) { if(comm_res) {
int32_t i; int32_t i;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area_center; layer->_clip_area = clip_area_center;
coords_part.x1 = coords.x1 + left_w; coords_part.x1 = coords.x1 + left_w;
coords_part.y1 = coords.y1; coords_part.y1 = coords.y1;
@@ -280,7 +280,7 @@ static void draw_main(lv_event_t * e)
coords_part.x1 = coords_part.x2 + 1; coords_part.x1 = coords_part.x2 + 1;
coords_part.x2 += src_info->header.w; coords_part.x2 += src_info->header.w;
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
} }
} }

View File

@@ -754,7 +754,7 @@ static void draw_main(lv_event_t * e)
} }
lv_area_t txt_clip; lv_area_t txt_clip;
bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, &layer->clip_area); bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, &layer->_clip_area);
if(!is_common) { if(!is_common) {
return; return;
} }
@@ -765,17 +765,17 @@ static void draw_main(lv_event_t * e)
txt_coords.y2 = obj->coords.y2; txt_coords.y2 = obj->coords.y2;
} }
if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) {
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = txt_clip; layer->_clip_area = txt_clip;
lv_draw_label(layer, &label_draw_dsc, &txt_coords); lv_draw_label(layer, &label_draw_dsc, &txt_coords);
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
else { else {
lv_draw_label(layer, &label_draw_dsc, &txt_coords); lv_draw_label(layer, &label_draw_dsc, &txt_coords);
} }
lv_area_t clip_area_ori = layer->clip_area; lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = txt_clip; layer->_clip_area = txt_clip;
if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) {
lv_point_t size; lv_point_t size;
@@ -800,7 +800,7 @@ static void draw_main(lv_event_t * e)
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void overwrite_anim_property(lv_anim_t * dest, const lv_anim_t * src, lv_label_long_mode_t mode) static void overwrite_anim_property(lv_anim_t * dest, const lv_anim_t * src, lv_label_long_mode_t mode)

View File

@@ -485,7 +485,7 @@ static void draw_main(lv_event_t * e)
get_sel_area(obj, &sel_area); get_sel_area(obj, &sel_area);
lv_area_t mask_sel; lv_area_t mask_sel;
bool area_ok; bool area_ok;
area_ok = _lv_area_intersect(&mask_sel, &layer->clip_area, &sel_area); area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &sel_area);
if(area_ok) { if(area_ok) {
lv_obj_t * label = get_label(obj); lv_obj_t * label = get_label(obj);
@@ -523,11 +523,11 @@ static void draw_main(lv_event_t * e)
label_sel_area.y2 = label_sel_area.y1 + res_p.y; label_sel_area.y2 = label_sel_area.y1 + res_p.y;
label_dsc.flag |= LV_TEXT_FLAG_EXPAND; label_dsc.flag |= LV_TEXT_FLAG_EXPAND;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = mask_sel; layer->_clip_area = mask_sel;
label_dsc.text = lv_label_get_text(label); label_dsc.text = lv_label_get_text(label);
lv_draw_label(layer, &label_dsc, &label_sel_area); lv_draw_label(layer, &label_dsc, &label_sel_area);
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
} }
} }
@@ -547,10 +547,10 @@ static void draw_label(lv_event_t * e)
/*If the roller has shadow or outline it has some ext. draw size /*If the roller has shadow or outline it has some ext. draw size
*therefore the label can overflow the roller's boundaries. *therefore the label can overflow the roller's boundaries.
*To solve this limit the clip area to the "plain" roller.*/ *To solve this limit the clip area to the "plain" roller.*/
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
lv_area_t roller_clip_area; lv_area_t roller_clip_area;
if(!_lv_area_intersect(&roller_clip_area, &layer->clip_area, &roller->coords)) return; if(!_lv_area_intersect(&roller_clip_area, &layer->_clip_area, &roller->coords)) return;
layer->clip_area = roller_clip_area; layer->_clip_area = roller_clip_area;
lv_area_t sel_area; lv_area_t sel_area;
get_sel_area(roller, &sel_area); get_sel_area(roller, &sel_area);
@@ -560,27 +560,27 @@ static void draw_label(lv_event_t * e)
clip2.y1 = label_obj->coords.y1; clip2.y1 = label_obj->coords.y1;
clip2.x2 = label_obj->coords.x2; clip2.x2 = label_obj->coords.x2;
clip2.y2 = sel_area.y1; clip2.y2 = sel_area.y1;
if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) { if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) {
const lv_area_t clip_area_ori2 = layer->clip_area; const lv_area_t clip_area_ori2 = layer->_clip_area;
layer->clip_area = clip2; layer->_clip_area = clip2;
label_draw_dsc.text = lv_label_get_text(label_obj); label_draw_dsc.text = lv_label_get_text(label_obj);
lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); lv_draw_label(layer, &label_draw_dsc, &label_obj->coords);
layer->clip_area = clip_area_ori2; layer->_clip_area = clip_area_ori2;
} }
clip2.x1 = label_obj->coords.x1; clip2.x1 = label_obj->coords.x1;
clip2.y1 = sel_area.y2; clip2.y1 = sel_area.y2;
clip2.x2 = label_obj->coords.x2; clip2.x2 = label_obj->coords.x2;
clip2.y2 = label_obj->coords.y2; clip2.y2 = label_obj->coords.y2;
if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) { if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) {
const lv_area_t clip_area_ori2 = layer->clip_area; const lv_area_t clip_area_ori2 = layer->_clip_area;
layer->clip_area = clip2; layer->_clip_area = clip2;
label_draw_dsc.text = lv_label_get_text(label_obj); label_draw_dsc.text = lv_label_get_text(label_obj);
lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); lv_draw_label(layer, &label_draw_dsc, &label_obj->coords);
layer->clip_area = clip_area_ori2; layer->_clip_area = clip_area_ori2;
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area) static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area)

View File

@@ -806,9 +806,9 @@ static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer)
/* return if no draw area */ /* return if no draw area */
lv_area_t clip_area; lv_area_t clip_area;
if(!_lv_area_intersect(&clip_area, &coords, &layer->clip_area)) return; if(!_lv_area_intersect(&clip_area, &coords, &layer->_clip_area)) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
/* init draw variable */ /* init draw variable */
lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE;
@@ -1056,12 +1056,12 @@ Next_line_init:
txt_pos.x = coords.x1; txt_pos.x = coords.x1;
txt_pos.y += max_line_h; txt_pos.y += max_line_h;
if(is_end_line || txt_pos.y > clip_area.y2 + 1) { if(is_end_line || txt_pos.y > clip_area.y2 + 1) {
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
return; return;
} }
max_w = max_width; max_w = max_width;
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
static void refresh_self_size(lv_obj_t * obj) static void refresh_self_size(lv_obj_t * obj)

View File

@@ -651,10 +651,10 @@ static void draw_main(lv_event_t * e)
lv_table_t * table = (lv_table_t *)obj; lv_table_t * table = (lv_table_t *)obj;
lv_layer_t * layer = lv_event_get_layer(e); lv_layer_t * layer = lv_event_get_layer(e);
lv_area_t clip_area; lv_area_t clip_area;
if(!_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area)) return; if(!_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area)) return;
const lv_area_t clip_area_ori = layer->clip_area; const lv_area_t clip_area_ori = layer->_clip_area;
layer->clip_area = clip_area; layer->_clip_area = clip_area;
lv_point_t txt_size; lv_point_t txt_size;
lv_area_t cell_area; lv_area_t cell_area;
@@ -819,10 +819,10 @@ static void draw_main(lv_event_t * e)
bool label_mask_ok; bool label_mask_ok;
label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area); label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area);
if(label_mask_ok) { if(label_mask_ok) {
layer->clip_area = label_clip_area; layer->_clip_area = label_clip_area;
label_dsc_act.text = table->cell_data[cell]->txt; label_dsc_act.text = table->cell_data[cell]->txt;
lv_draw_label(layer, &label_dsc_act, &txt_area); lv_draw_label(layer, &label_dsc_act, &txt_area);
layer->clip_area = clip_area; layer->_clip_area = clip_area;
} }
} }
@@ -831,7 +831,7 @@ static void draw_main(lv_event_t * e)
} }
} }
layer->clip_area = clip_area_ori; layer->_clip_area = clip_area_ori;
} }
/* Refreshes size of the table starting from @start_row row */ /* Refreshes size of the table starting from @start_row row */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -202,9 +202,9 @@ static void draw_lines(lv_layer_t * layer)
static void canvas_draw(const char * name, void (*draw_cb)(lv_layer_t *)) static void canvas_draw(const char * name, void (*draw_cb)(lv_layer_t *))
{ {
static uint8_t canvas_buf[CANVAS_WIDTH_TO_STRIDE(640, 4) * 480 + LV_DRAW_BUF_ALIGN]; static uint8_t canvas_buf[LV_CANVAS_BUF_SIZE(640, 480, 32, LV_DRAW_BUF_STRIDE_ALIGN)];
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, lv_draw_buf_align(canvas_buf, LV_COLOR_FORMAT_ARGB8888), 640, 480, lv_canvas_set_buffer(canvas, canvas_buf, 640, 480,
LV_COLOR_FORMAT_ARGB8888); LV_COLOR_FORMAT_ARGB8888);
lv_layer_t layer; lv_layer_t layer;