aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabor Kiss-Vamosi <kisvegabor@gmail.com>2023-11-18 15:33:58 +0100
committerGabor Kiss-Vamosi <kisvegabor@gmail.com>2023-11-18 15:35:45 +0100
commit2f3e8d40667d27bb9bb56778439787426cae3d9f (patch)
tree1634609361eb686a75432d844b73f6d6b5b2e8c0
parentcd6b4db6e8239ef2711e8c43a954650dc13a9a20 (diff)
downloadlvgl-2f3e8d40667d27bb9bb56778439787426cae3d9f.tar.gz
lvgl-2f3e8d40667d27bb9bb56778439787426cae3d9f.zip
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
-rw-r--r--demos/vector_graphic/lv_demo_vector_graphic.c2
-rw-r--r--demos/widgets/lv_demo_widgets.c1
-rw-r--r--examples/widgets/canvas/lv_example_canvas_1.c17
-rw-r--r--examples/widgets/canvas/lv_example_canvas_3.c4
-rw-r--r--examples/widgets/canvas/lv_example_canvas_4.c4
-rw-r--r--examples/widgets/canvas/lv_example_canvas_5.c4
-rw-r--r--examples/widgets/canvas/lv_example_canvas_6.c4
-rw-r--r--examples/widgets/canvas/lv_example_canvas_7.c4
-rw-r--r--examples/widgets/canvas/lv_example_canvas_8.c4
-rw-r--r--examples/widgets/img/lv_example_img_1.c10
-rw-r--r--lv_conf_template.h3
-rw-r--r--src/core/lv_refr.c32
-rw-r--r--src/dev/sdl/lv_sdl_window.c17
-rw-r--r--src/dev/sdl/lv_sdl_window.h3
-rw-r--r--src/draw/lv_draw.c34
-rw-r--r--src/draw/lv_draw.h13
-rw-r--r--src/draw/lv_draw_image.c1
-rw-r--r--src/draw/lv_draw_label.c1
-rw-r--r--src/draw/lv_draw_rect.c11
-rw-r--r--src/draw/lv_draw_vector.c8
-rw-r--r--src/draw/lv_image_decoder.h1
-rw-r--r--src/draw/sdl/lv_draw_sdl.c400
-rw-r--r--src/draw/sdl/lv_draw_sdl.h89
-rw-r--r--src/draw/sw/lv_draw_sw.c20
-rw-r--r--src/libs/barcode/lv_barcode.c14
-rw-r--r--src/libs/gif/lv_gif.c6
-rw-r--r--src/libs/libjpeg_turbo/lv_libjpeg_turbo.c30
-rw-r--r--src/libs/libpng/lv_libpng.c29
-rw-r--r--src/libs/lodepng/lv_lodepng.c24
-rw-r--r--src/libs/qrcode/lv_qrcode.c6
-rw-r--r--src/libs/tiny_ttf/lv_tiny_ttf.c49
-rw-r--r--src/libs/tiny_ttf/lv_tiny_ttf.h1
-rw-r--r--src/lv_conf_internal.h9
-rw-r--r--src/lv_init.c4
-rw-r--r--src/misc/lv_cache.c36
-rw-r--r--src/misc/lv_cache.h152
-rw-r--r--src/misc/lv_cache_builtin.c56
-rw-r--r--src/others/snapshot/lv_snapshot.c2
-rw-r--r--src/stdlib/builtin/lv_string_builtin.c9
-rw-r--r--src/stdlib/clib/lv_string_clib.c5
-rw-r--r--src/stdlib/lv_string.h15
-rw-r--r--src/widgets/bar/lv_bar.c2
-rw-r--r--src/widgets/canvas/lv_canvas.c20
-rw-r--r--src/widgets/canvas/lv_canvas.h27
-rw-r--r--src/widgets/chart/lv_chart.c42
-rw-r--r--src/widgets/dropdown/lv_dropdown.c16
-rw-r--r--src/widgets/image/lv_image.c12
-rw-r--r--src/widgets/imgbtn/lv_imgbtn.c8
-rw-r--r--src/widgets/label/lv_label.c14
-rw-r--r--src/widgets/roller/lv_roller.c32
-rw-r--r--src/widgets/span/lv_span.c10
-rw-r--r--src/widgets/table/lv_table.c12
-rw-r--r--tests/ref_imgs/libs/tiny_ttf_1.pngbin16326 -> 16331 bytes
-rw-r--r--tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.pngbin48338 -> 60052 bytes
-rw-r--r--tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.pngbin48423 -> 60091 bytes
-rw-r--r--tests/ref_imgs/widgets/image_transform_align.pngbin16771 -> 19482 bytes
-rw-r--r--tests/ref_imgs/widgets/image_transform_align_offset.pngbin17173 -> 18896 bytes
-rw-r--r--tests/src/test_cases/draw/test_draw_vector.c4
58 files changed, 1050 insertions, 283 deletions
diff --git a/demos/vector_graphic/lv_demo_vector_graphic.c b/demos/vector_graphic/lv_demo_vector_graphic.c
index 9aa870185..f5171c408 100644
--- a/demos/vector_graphic/lv_demo_vector_graphic.c
+++ b/demos/vector_graphic/lv_demo_vector_graphic.c
@@ -225,7 +225,7 @@ static void draw_vector(lv_layer_t * layer)
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_canvas_set_buffer(canvas, canvas_buf, WIDTH, HEIGHT, LV_COLOR_FORMAT_ARGB8888);
diff --git a/demos/widgets/lv_demo_widgets.c b/demos/widgets/lv_demo_widgets.c
index a6806a300..33e11ce93 100644
--- a/demos/widgets/lv_demo_widgets.c
+++ b/demos/widgets/lv_demo_widgets.c
@@ -249,6 +249,7 @@ static void profile_create(lv_obj_t * parent)
LV_IMAGE_DECLARE(img_demo_widgets_avatar);
lv_obj_t * avatar = lv_image_create(panel1);
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_label_set_text(name, "Elena Smith");
diff --git a/examples/widgets/canvas/lv_example_canvas_1.c b/examples/widgets/canvas/lv_example_canvas_1.c
index 92c820953..ceada1b65 100644
--- a/examples/widgets/canvas/lv_example_canvas_1.c
+++ b/examples/widgets/canvas/lv_example_canvas_1.c
@@ -26,11 +26,11 @@ void lv_example_canvas_1(void)
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_palette_main(LV_PALETTE_ORANGE);
label_dsc.text = "Some text on text canvas";
-
- static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)];
+ /*Create a buffer for the canvas*/
+ 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_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_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.
*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_image_dsc_t img;
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.h = CANVAS_HEIGHT;
diff --git a/examples/widgets/canvas/lv_example_canvas_3.c b/examples/widgets/canvas/lv_example_canvas_3.c
index 85049e423..65ff564d6 100644
--- a/examples/widgets/canvas/lv_example_canvas_3.c
+++ b/examples/widgets/canvas/lv_example_canvas_3.c
@@ -10,11 +10,11 @@
void lv_example_canvas_3(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/canvas/lv_example_canvas_4.c b/examples/widgets/canvas/lv_example_canvas_4.c
index a51b45b6a..7b9403ffc 100644
--- a/examples/widgets/canvas/lv_example_canvas_4.c
+++ b/examples/widgets/canvas/lv_example_canvas_4.c
@@ -10,11 +10,11 @@
void lv_example_canvas_4(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/canvas/lv_example_canvas_5.c b/examples/widgets/canvas/lv_example_canvas_5.c
index 5a32d8c02..34a52e0f8 100644
--- a/examples/widgets/canvas/lv_example_canvas_5.c
+++ b/examples/widgets/canvas/lv_example_canvas_5.c
@@ -10,11 +10,11 @@
void lv_example_canvas_5(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/canvas/lv_example_canvas_6.c b/examples/widgets/canvas/lv_example_canvas_6.c
index 34e9ecf48..c3edf7858 100644
--- a/examples/widgets/canvas/lv_example_canvas_6.c
+++ b/examples/widgets/canvas/lv_example_canvas_6.c
@@ -10,11 +10,11 @@
void lv_example_canvas_6(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/canvas/lv_example_canvas_7.c b/examples/widgets/canvas/lv_example_canvas_7.c
index da655b7fc..7bf29c40f 100644
--- a/examples/widgets/canvas/lv_example_canvas_7.c
+++ b/examples/widgets/canvas/lv_example_canvas_7.c
@@ -10,11 +10,11 @@
void lv_example_canvas_7(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/canvas/lv_example_canvas_8.c b/examples/widgets/canvas/lv_example_canvas_8.c
index 1022d4729..3bebdf69d 100644
--- a/examples/widgets/canvas/lv_example_canvas_8.c
+++ b/examples/widgets/canvas/lv_example_canvas_8.c
@@ -12,11 +12,11 @@
void lv_example_canvas_8(void)
{
/*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*/
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_obj_center(canvas);
diff --git a/examples/widgets/img/lv_example_img_1.c b/examples/widgets/img/lv_example_img_1.c
index e516f4df6..96e8da6fa 100644
--- a/examples/widgets/img/lv_example_img_1.c
+++ b/examples/widgets/img/lv_example_img_1.c
@@ -5,13 +5,17 @@ void lv_example_image_1(void)
{
LV_IMAGE_DECLARE(img_cogwheel_argb);
lv_obj_t * img1 = lv_image_create(lv_screen_active());
- lv_image_set_src(img1, &img_cogwheel_argb);
- lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20);
- lv_obj_set_size(img1, 200, 200);
+ lv_image_set_src(img1, "A:lvgl/demos/widgets/assets/avatar.png");
+ lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
+ 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_image_set_src(img2, LV_SYMBOL_OK "Accept");
lv_obj_align_to(img2, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
+
+ lv_obj_set_style_bg_opa(img1, 100, 0);
}
#endif
diff --git a/lv_conf_template.h b/lv_conf_template.h
index f488fd12b..c8dd84802 100644
--- a/lv_conf_template.h
+++ b/lv_conf_template.h
@@ -127,6 +127,9 @@
/* Use NXP's PXP on iMX RTxxx platforms. */
#define LV_USE_DRAW_PXP 0
+/* Draw using cached SDL textures*/
+#define LV_USE_DRAW_SDL 0
+
/*=================
* OPERATING SYSTEM
*=================*/
diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c
index 950b2190e..d1bcf5880 100644
--- a/src/core/lv_refr.c
+++ b/src/core/lv_refr.c
@@ -93,7 +93,7 @@ void lv_refr_now(lv_display_t * disp)
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;
/*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 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, 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);
if(child_cnt == 0) {
/*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*/
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_END, layer);
}
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);
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*/
- layer->clip_area = clip_coords_for_obj;
+ layer->_clip_area = clip_coords_for_obj;
/*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, layer);
@@ -228,7 +228,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
mid.y1 += rout;
mid.y2 -= rout;
if(_lv_area_intersect(&mid, &mid, &clip_area_ori)) {
- layer->clip_area = mid;
+ layer->_clip_area = mid;
for(i = 0; i < child_cnt; i++) {
lv_obj_t * child = obj->spec_attr->children[i];
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) {
disp_refr->last_part = 1;
- layer->clip_area = disp_area;
+ layer->_clip_area = disp_area;
refr_area_part(layer);
}
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
disp_refr->last_part = disp_refr->last_area;
- layer->clip_area = *area_p;
+ layer->_clip_area = *area_p;
refr_area_part(layer);
}
return;
@@ -638,7 +638,7 @@ static void refr_area(const lv_area_t * area_p)
layer->buf = disp_refr->buf_act;
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->clip_area = sub_area;
+ layer->_clip_area = sub_area;
if(sub_area.y2 > y2) sub_area.y2 = y2;
row_last = sub_area.y2;
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;
layer->buf = disp_refr->buf_act;
layer->buf_area = sub_area;
- layer->clip_area = sub_area;
+ layer->_clip_area = sub_area;
disp_refr->last_part = 1;
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)
{
- 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.
* 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;
/*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) {
- 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*/
@@ -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 tranf_coords = obj_coords_ext;
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;
}
@@ -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) {
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;
}
*layer_area_out = clip_coords_for_obj;
diff --git a/src/dev/sdl/lv_sdl_window.c b/src/dev/sdl/lv_sdl_window.c
index f9fbd71d9..f0465efec 100644
--- a/src/dev/sdl/lv_sdl_window.c
+++ b/src/dev/sdl/lv_sdl_window.c
@@ -15,6 +15,8 @@
#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/
#include LV_SDL_INCLUDE_PATH
+#include <SDL2/SDL_image.h>
+
/*********************
* DEFINES
*********************/
@@ -74,6 +76,12 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
SDL_StartTextInput();
event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL);
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;
}
@@ -147,6 +155,12 @@ void lv_sdl_window_set_title(lv_display_t * disp, const char * 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()
{
if(inited) {
@@ -260,6 +274,7 @@ static void window_create(lv_display_t * disp)
dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE);
texture_resize(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);
#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)
{
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);
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);
@@ -281,6 +297,7 @@ static void window_update(lv_display_t * disp)
/*Update the renderer with the texture containing the rendered image*/
SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL);
+#endif
SDL_RenderPresent(dsc->renderer);
}
diff --git a/src/dev/sdl/lv_sdl_window.h b/src/dev/sdl/lv_sdl_window.h
index 765685896..7f97ab22e 100644
--- a/src/dev/sdl/lv_sdl_window.h
+++ b/src/dev/sdl/lv_sdl_window.h
@@ -18,6 +18,7 @@ extern "C" {
#include "../../indev/lv_indev.h"
#if LV_USE_SDL
+#include LV_SDL_INCLUDE_PATH
/*********************
* 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);
+SDL_Renderer * lv_sdl_window_get_renderer(lv_display_t * disp);
+
void lv_sdl_quit();
/**********************
diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c
index 63ca87030..dc9b40d2c 100644
--- a/src/draw/lv_draw.c
+++ b/src/draw/lv_draw.c
@@ -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));
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;
/*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
*and not on the draw tasks added in the event.
- *Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends
- *Dispatching might remove the "main" draw task while it's still being used in the event*/
+ *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*/
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)) {
+ info->task_running = true;
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*/
@@ -129,7 +130,6 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
}
lv_draw_dispatch();
- info->task_running = false;
}
else {
/*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;
/*If the first task is screen sized, there cannot be independent areas*/
- if(layer->draw_task_head) {
- 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());
- lv_draw_task_t * t = layer->draw_task_head;
- if(t->state != LV_DRAW_TASK_STATE_QUEUED &&
- t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 &&
- t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) {
- LV_PROFILER_END;
- return NULL;
- }
- }
+ // if(layer->draw_task_head) {
+ // 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());
+ // lv_draw_task_t * t = layer->draw_task_head;
+ // if(t->state != LV_DRAW_TASK_STATE_QUEUED &&
+ // t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 &&
+ // t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) {
+ // LV_PROFILER_END;
+ // return NULL;
+ // }
+ // }
lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head;
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;
new_layer->parent = parent_layer;
- new_layer->clip_area = *area;
+ new_layer->_clip_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->color_format = color_format;
diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h
index 6ee9a36d1..c729f1c2e 100644
--- a/src/draw/lv_draw.h
+++ b/src/draw/lv_draw.h
@@ -152,21 +152,24 @@ typedef struct _lv_layer_t {
void * buf;
uint32_t buf_stride;
+
+ /** The absolute coordinates of the buffer */
lv_area_t buf_area;
+
+ /** The color format of the layer. LV_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`
* 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.
* 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.
*/
- 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;
struct _lv_layer_t * parent;
@@ -181,6 +184,8 @@ typedef struct {
uint32_t id1;
uint32_t id2;
lv_layer_t * layer;
+ size_t dsc_size;
+ void * user_data;
} lv_draw_dsc_base_t;
typedef struct {
diff --git a/src/draw/lv_draw_image.c b/src/draw/lv_draw_image.c
index 9f94a1517..527825c99 100644
--- a/src/draw/lv_draw_image.c
+++ b/src/draw/lv_draw_image.c
@@ -46,6 +46,7 @@ void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc)
dsc->scale_x = LV_SCALE_NONE;
dsc->scale_y = LV_SCALE_NONE;
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)
diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c
index 7ad6ed65c..cc215ae2a 100644
--- a/src/draw/lv_draw_label.c
+++ b/src/draw/lv_draw_label.c
@@ -58,6 +58,7 @@ void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
dsc->sel_color = lv_color_black();
dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE);
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)
diff --git a/src/draw/lv_draw_rect.c b/src/draw/lv_draw_rect.c
index 682f4eca5..f5cafb880 100644
--- a/src/draw/lv_draw_rect.c
+++ b/src/draw/lv_draw_rect.c
@@ -59,6 +59,7 @@ void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(*dsc));
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)
@@ -66,18 +67,21 @@ void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc)
lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER;
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)
{
lv_memzero(dsc, sizeof(*dsc));
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)
{
lv_memzero(dsc, sizeof(*dsc));
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)
@@ -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));
t->draw_dsc = shadow_dsc;
shadow_dsc->base = dsc->base;
+ shadow_dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t);
shadow_dsc->radius = dsc->radius;
shadow_dsc->color = dsc->shadow_color;
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);
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;
bg_dsc->base = dsc->base;
+ bg_dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t);
bg_dsc->radius = dsc->radius;
bg_dsc->color = dsc->bg_color;
bg_dsc->grad = dsc->bg_grad;
bg_dsc->opa = dsc->bg_opa;
t->type = LV_DRAW_TASK_TYPE_FILL;
+
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));
t->draw_dsc = bg_image_dsc;
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->src = dsc->bg_image_src;
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));
t->draw_dsc = border_dsc;
border_dsc->base = dsc->base;
+ border_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
border_dsc->radius = dsc->radius;
border_dsc->color = dsc->border_color;
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));
t->draw_dsc = outline_dsc;
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 +
dsc->outline_pad;
outline_dsc->color = dsc->outline_color;
diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c
index 34d221eaf..b43a41b1b 100644
--- a/src/draw/lv_draw_vector.c
+++ b/src/draw/lv_draw_vector.c
@@ -476,7 +476,7 @@ lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer)
lv_matrix_identity(&(stroke_dsc->matrix)); // identity matrix
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
dsc->tasks.task_list = NULL;
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)
{
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;
}
@@ -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)
{
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;
}
@@ -691,7 +691,7 @@ void lv_draw_vector(lv_vector_dsc_t * dsc)
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->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));
diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h
index 4d966099c..1a5bb40b1 100644
--- a/src/draw/lv_image_decoder.h
+++ b/src/draw/lv_image_decoder.h
@@ -94,6 +94,7 @@ typedef struct _lv_image_decoder_t {
lv_image_decoder_open_f_t open_cb;
lv_image_decoder_get_area_cb_t get_area_cb;
lv_image_decoder_close_f_t close_cb;
+ uint32_t cache_data_type;
void * user_data;
} lv_image_decoder_t;
diff --git a/src/draw/sdl/lv_draw_sdl.c b/src/draw/sdl/lv_draw_sdl.c
new file mode 100644
index 000000000..f39248694
--- /dev/null
+++ b/src/draw/sdl/lv_draw_sdl.c
@@ -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*/
diff --git a/src/draw/sdl/lv_draw_sdl.h b/src/draw/sdl/lv_draw_sdl.h
new file mode 100644
index 000000000..b834e5d9c
--- /dev/null
+++ b/src/draw/sdl/lv_draw_sdl.h
@@ -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*/
diff --git a/src/draw/sw/lv_draw_sw.c b/src/draw/sw/lv_draw_sw.c
index dbbf8111d..8381fe340 100644
--- a/src/draw/sw/lv_draw_sw.c
+++ b/src/draw/sw/lv_draw_sw.c
@@ -40,7 +40,9 @@
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);
/**********************
@@ -66,7 +68,8 @@ void lv_draw_sw_init(void)
uint32_t 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));
- 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->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 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;
diff --git a/src/libs/barcode/lv_barcode.c b/src/libs/barcode/lv_barcode.c
index e3f3d11c7..4f04afbe4 100644
--- a/src/libs/barcode/lv_barcode.c
+++ b/src/libs/barcode/lv_barcode.c
@@ -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_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();
if(!img->data) {
@@ -205,9 +205,9 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj
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;
}
@@ -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(w > 0);
- lv_image_dsc_t * img = lv_canvas_get_image(obj);
- void * buf = (void *)img->data;
+ void * buf = (void *)lv_canvas_get_buf(obj);
+ lv_draw_buf_free((void *)buf);
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_I1);
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);
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;
}
- lv_draw_buf_free((void *)img->data);
lv_canvas_set_buffer(obj, buf, w, h, LV_COLOR_FORMAT_I1);
LV_LOG_INFO("set canvas buffer: %p, width = %d", buf, (int)w);
return true;
diff --git a/src/libs/gif/lv_gif.c b/src/libs/gif/lv_gif.c
index 5d2b32973..b21b5909b 100644
--- a/src/libs/gif/lv_gif.c
+++ b/src/libs/gif/lv_gif.c
@@ -63,7 +63,7 @@ void lv_gif_set_src(lv_obj_t * obj, const void * src)
/*Close previous gif if any*/
if(gifobj->gif) {
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();
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_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();
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);
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_obj_invalidate(obj);
}
diff --git a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c
index df5d2ba24..0d2b0fe2d 100644
--- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c
+++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c
@@ -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 void error_exit(j_common_ptr cinfo);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
+static void cache_invalidate_cb(lv_cache_entry_t * entry);
/**********************
* 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_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close);
+ dec->cache_data_type = lv_cache_register_data_type();
}
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) {
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_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) {
lv_cache_unlock();
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->data = decoded_img;
- cache->free_data = 1;
+ cache->invalidate_cb = cache_invalidate_cb;
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src);
- cache->src_type = LV_CACHE_SRC_TYPE_STR;
- cache->free_src = 1;
+ cache->src_type = LV_CACHE_SRC_TYPE_PATH;
}
else {
- cache->src_type = LV_CACHE_SRC_TYPE_PTR;
+ cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
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) {
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) {
dsc->img_data = lv_cache_get_data(cache);
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);
}
+
+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*/
diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c
index ca0ab2927..59be1f007 100644
--- a/src/libs/libpng/lv_libpng.c
+++ b/src/libs/libpng/lv_libpng.c
@@ -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 const void * decode_png_file(const char * filename);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
+static void cache_invalidate_cb(lv_cache_entry_t * entry);
/**********************
* STATIC VARIABLES
@@ -50,6 +51,7 @@ void lv_libpng_init(void)
lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close);
+ dec->cache_data_type = lv_cache_register_data_type();
}
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(dsc->src_type == LV_IMAGE_SRC_FILE) {
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_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) {
lv_cache_unlock();
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->data = decoded_img;
- cache->free_data = 1;
+ cache->invalidate_cb = cache_invalidate_cb;
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src);
- cache->src_type = LV_CACHE_SRC_TYPE_STR;
- cache->free_src = 1;
+ cache->src_type = LV_CACHE_SRC_TYPE_PATH;
}
else {
- cache->src_type = LV_CACHE_SRC_TYPE_PTR;
+ cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
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) {
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) {
dsc->img_data = lv_cache_get_data(cache);
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;
}
+
+static void cache_invalidate_cb(lv_cache_entry_t * entry)
+{
+ lv_free((void *)entry->src);
+ lv_free((void *)entry->data);
+}
+
#endif /*LV_USE_LIBPNG*/
diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c
index 9400b177f..db753ba06 100644
--- a/src/libs/lodepng/lv_lodepng.c
+++ b/src/libs/lodepng/lv_lodepng.c
@@ -20,6 +20,9 @@
/**********************
* TYPEDEFS
**********************/
+typedef struct {
+
+} cache_data_t;
/**********************
* 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 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 void cache_invalidate_cb(lv_cache_entry_t * entry);
/**********************
* STATIC VARIABLES
@@ -52,6 +56,7 @@ void lv_lodepng_init(void)
lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close);
+ dec->cache_data_type = lv_cache_register_data_type();
}
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_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) {
lv_cache_unlock();
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);
cache->weight = t;
cache->data = decoded_img;
- cache->free_data = 1;
+ cache->invalidate_cb = cache_invalidate_cb;
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src);
- cache->src_type = LV_CACHE_SRC_TYPE_STR;
- cache->free_src = 1;
+ cache->src_type = LV_CACHE_SRC_TYPE_PATH;
lv_free((void *)png_data);
}
else {
- cache->src_type = LV_CACHE_SRC_TYPE_PTR;
+ cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
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) {
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) {
dsc->img_data = lv_cache_get_data(cache);
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) {
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) {
dsc->img_data = lv_cache_get_data(cache);
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*/
diff --git a/src/libs/qrcode/lv_qrcode.c b/src/libs/qrcode/lv_qrcode.c
index ebea012ba..6db4c9df2 100644
--- a/src/libs/qrcode/lv_qrcode.c
+++ b/src/libs/qrcode/lv_qrcode.c
@@ -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);
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);
LV_ASSERT_MALLOC(buf);
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_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();
if(!img_dsc->data) {
return;
}
- lv_free((void *)img_dsc->data);
+ lv_free((void *)lv_canvas_get_image(obj));
img_dsc->data = NULL;
}
diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.c b/src/libs/tiny_ttf/lv_tiny_ttf.c
index 750375c59..2592038dc 100644
--- a/src/libs/tiny_ttf/lv_tiny_ttf.c
+++ b/src/libs/tiny_ttf/lv_tiny_ttf.c
@@ -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*/
}
+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)
{
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);
lv_cache_lock();
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) {
uint8_t * buffer = (uint8_t *)lv_cache_get_data(cache);
+ lv_cache_release(cache);
lv_cache_unlock();
return buffer;
}
+
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) {
lv_cache_unlock();
+ lv_draw_buf_free(buffer);
LV_LOG_ERROR("tiny_ttf: cache not allocated\n");
return NULL;
}
/* This smells. We add the codepoint to the base pointer to get a key. */
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->param2 = cp;
- 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_invalidate(entry);
- lv_cache_unlock();
- return NULL;
- }
- entry->data = buffer;
- entry->free_data = 1;
+ entry->invalidate_cb = cache_invalidate_cb;
+
+ /*Just to increment life*/
+ lv_cache_get_data(entry);
+
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();
- 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,
@@ -268,4 +287,6 @@ void lv_tiny_ttf_destroy(lv_font_t * font)
}
}
}
+
+
#endif
diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.h b/src/libs/tiny_ttf/lv_tiny_ttf.h
index 23d9ea743..d9ee80d5c 100644
--- a/src/libs/tiny_ttf/lv_tiny_ttf.h
+++ b/src/libs/tiny_ttf/lv_tiny_ttf.h
@@ -28,6 +28,7 @@ extern "C" {
/**********************
* GLOBAL PROTOTYPES
**********************/
+
#if LV_TINY_TTF_FILE_SUPPORT !=0
/* 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);
diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h
index 7b735ec58..fa74c0133 100644
--- a/src/lv_conf_internal.h
+++ b/src/lv_conf_internal.h
@@ -325,6 +325,15 @@
#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
*=================*/
diff --git a/src/lv_init.c b/src/lv_init.c
index 9c8b7726b..1e458c826 100644
--- a/src/lv_init.c
+++ b/src/lv_init.c
@@ -164,6 +164,10 @@ void lv_init(void)
lv_draw_pxp_init();
#endif
+#if LV_USE_DRAW_SDL
+ lv_draw_sdl_init();
+#endif
+
_lv_obj_style_init();
/*Initialize the screen refresh system*/
diff --git a/src/misc/lv_cache.c b/src/misc/lv_cache.c
index 203944ca8..1ebf1e918 100644
--- a/src/misc/lv_cache.c
+++ b/src/misc/lv_cache.c
@@ -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);
_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.get_data_cb = manager->get_data_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);
}
-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);
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);
- 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)
@@ -90,6 +98,16 @@ void lv_cache_invalidate(lv_cache_entry_t * 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)
{
LV_ASSERT(_cache_manager.locked);
@@ -133,6 +151,12 @@ void lv_cache_unlock(void)
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
**********************/
diff --git a/src/misc/lv_cache.h b/src/misc/lv_cache.h
index 5a60ea900..f22bc6875 100644
--- a/src/misc/lv_cache.h
+++ b/src/misc/lv_cache.h
@@ -15,41 +15,77 @@ extern "C" {
*********************/
#include <stdint.h>
#include <stddef.h>
+#include <stdbool.h>
#include "../osal/lv_os.h"
/*********************
* DEFINES
*********************/
+#define LV_CACHE_DATA_TYPE_NOT_SET 0xFFFFFFFF
/**********************
* TYPEDEFS
**********************/
typedef enum {
- LV_CACHE_SRC_TYPE_PTR,
- LV_CACHE_SRC_TYPE_STR,
- _LV_CACHE_SRC_TYPE_LAST,
+ LV_CACHE_SRC_TYPE_PATH,
+ LV_CACHE_SRC_TYPE_POINTER,
} lv_cache_src_type_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;
lv_cache_src_type_t src_type;
- /** Some extra parameters to describe the source. E.g. the current frame of an animation*/
- uint32_t param1;
- uint32_t param2;
+ /**Arbitrary parameters to better identify the source*/
+ int32_t param1;
+ 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*/
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*/
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 */
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 entry will be closed and freed in `lv_cache_release` automatically*/
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.
* It won't allocate any buffers just free enough space to be a new entry
* with `size` bytes fits.
- * @param size the size of the new entry in bytes
- * @return a handler for the new cache entry
+ * @param data data the cache, can be a complex structure too
+ * @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
- * @param src_ptr pointer to the source data
- * @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`)
- * @param param1 param1, which was set when the cache was added
- * @param param2 param2, which was set when the cache was added
- * @return the cache entry with given source and parameters or NULL if not found
+ * Find a cache entry based on its data
+ * @param data the data to find
+ * @param data_size size of data
+ * @param data_type ID for the data type
+ * @return the cache entry with given `data` 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,
- uint32_t param2);
+typedef lv_cache_entry_t * (*lv_cache_find_by_data_cb)(const void * data, size_t data_size, uint32_t data_type);
+
+/**
+ * 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
@@ -130,7 +172,8 @@ typedef void (*lv_cache_empty_cb)(void);
typedef struct {
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_get_data_cb get_data_cb;
lv_cache_release_cb release_cb;
@@ -140,6 +183,7 @@ typedef struct {
lv_mutex_t mutex;
size_t max_size;
uint32_t locked : 1; /**< Show the mutex state, used to log unlocked cache access*/
+ uint32_t last_data_type;
} lv_cache_manager_t;
/**********************
@@ -166,28 +210,46 @@ void lv_cache_set_manager(lv_cache_manager_t * manager);
* 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
* with `size` bytes fits.
- * @param size the size of the new entry in bytes
- * @return a handler for the new cache entry
+ * @param data data the cache, can be a complex structure too
+ * @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
- * @param src_ptr pointer to the source data
- * @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`)
- * @param param1 param1, which was set when the cache was added
- * @param param2 param2, which was set when the cache was added
- * @return the cache entry with given source and parameters or NULL if not found
+ * Find a cache entry based on its data
+ * @param data the data to find
+ * @param data_size size of data
+ * @param data_type ID of data type
+ * @return the cache entry with given `data` 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()`)
*/
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.
* It is considered a cached data access so the cache manager can count that
* this entry was used on more times, and therefore it's more relevant.
@@ -227,6 +289,12 @@ void lv_cache_lock(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
**********************/
diff --git a/src/misc/lv_cache_builtin.c b/src/misc/lv_cache_builtin.c
index 223da5b35..8b98eb3b6 100644
--- a/src/misc/lv_cache_builtin.c
+++ b/src/misc/lv_cache_builtin.c
@@ -25,8 +25,9 @@
/**********************
* STATIC PROTOTYPES
**********************/
-static lv_cache_entry_t * add_cb(size_t size);
-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 * add_cb(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage);
+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 const void * get_data_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));
_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.get_data_cb = get_data_cb;
_cache_manager.release_cb = release_cb;
@@ -74,15 +76,15 @@ void _lv_cache_builtin_deinit(void)
* 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();
/*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) {
/*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();
/*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_memzero(entry, sizeof(lv_cache_entry_t));
- entry->data_size = size;
+ entry->memory_usage = memory_usage;
entry->weight = 1;
entry->temporary = temporary;
+ entry->data = data;
+ entry->data_size = data_size;
+ entry->data_type = data_type;
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 {
- LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)size);
- dsc.cur_size += size;
+ LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)memory_usage);
+ dsc.cur_size += memory_usage;
}
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);
while(entry) {
- if(param1 == entry->param1 && param2 == entry->param2 && src_type == entry->src_type &&
- ((src_type == LV_CACHE_SRC_TYPE_PTR && src == entry->src) ||
- (src_type == LV_CACHE_SRC_TYPE_STR && strcmp(src, entry->src) == 0))) {
- return entry;
+ if(entry->data_type == data_type && entry->data_size == data_size) {
+ if(entry->compare_cb(entry->data, data, data_size)) {
+ return 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;
}
+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)
{
if(entry == NULL) return;
- dsc.cur_size -= entry->data_size;
- LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->data_size);
+ dsc.cur_size -= entry->memory_usage;
+ LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->memory_usage);
- if(entry->free_src) lv_free((void *)entry->src);
- if(entry->free_data) lv_draw_buf_free((void *)entry->data);
+ if(entry->invalidate_cb) entry->invalidate_cb(entry);
_lv_ll_remove(&dsc.entry_ll, entry);
lv_free(entry);
diff --git a/src/others/snapshot/lv_snapshot.c b/src/others/snapshot/lv_snapshot.c
index 68c31ce68..c35af26a6 100644
--- a/src/others/snapshot/lv_snapshot.c
+++ b/src/others/snapshot/lv_snapshot.c
@@ -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.y2 = snapshot_area.y1 + h - 1;
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_new = lv_obj_get_disp(obj);
diff --git a/src/stdlib/builtin/lv_string_builtin.c b/src/stdlib/builtin/lv_string_builtin.c
index 3e0d5a8b6..aa20626b5 100644
--- a/src/stdlib/builtin/lv_string_builtin.c
+++ b/src/stdlib/builtin/lv_string_builtin.c
@@ -171,6 +171,15 @@ char * lv_strcpy(char * dst, const char * src)
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)
{
size_t len = lv_strlen(src) + 1;
diff --git a/src/stdlib/clib/lv_string_clib.c b/src/stdlib/clib/lv_string_clib.c
index 93aacbe60..76a3c159a 100644
--- a/src/stdlib/clib/lv_string_clib.c
+++ b/src/stdlib/clib/lv_string_clib.c
@@ -68,6 +68,11 @@ char * lv_strcpy(char * dst, const char * 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)
{
/*strdup uses malloc, so use the built in malloc if it's enabled */
diff --git a/src/stdlib/lv_string.h b/src/stdlib/lv_string.h
index 126aca9fb..01798a4de 100644
--- a/src/stdlib/lv_string.h
+++ b/src/stdlib/lv_string.h
@@ -84,6 +84,21 @@ char * lv_strncpy(char * dst, const char * src, size_t dest_size);
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.
* @param src Pointer to the source of data to be copied.
* @return A pointer to the new allocated string. NULL if failed.
diff --git a/src/widgets/bar/lv_bar.c b/src/widgets/bar/lv_bar.c
index 88d034a25..09e5b0b04 100644
--- a/src/widgets/bar/lv_bar.c
+++ b/src/widgets/bar/lv_bar.c
@@ -453,7 +453,7 @@ static void draw_indic(lv_event_t * e)
draw_rect_dsc.shadow_width = 0;
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_draw_rect(layer_indic, &draw_rect_dsc, &indic_area);
diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c
index 212e4e2a6..3eadc69a4 100644
--- a/src/widgets/canvas/lv_canvas.c
+++ b/src/widgets/canvas/lv_canvas.c
@@ -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;
+ canvas->buf_unaligned = buf;
canvas->dsc.header.cf = cf;
canvas->dsc.header.w = w;
canvas->dsc.header.h = h;
- canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf); /*Let LVGL calculate it automatically*/
- canvas->dsc.data = buf;
+ canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf);
+ canvas->dsc.data = lv_draw_buf_align(buf, cf);
canvas->dsc.data_size = w * h * lv_color_format_get_size(cf);
lv_image_set_src(obj, &canvas->dsc);
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();
}
@@ -205,6 +206,15 @@ lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * obj)
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
*====================*/
@@ -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->color_format = dsc->header.cf;
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);
}
@@ -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_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();
}
diff --git a/src/widgets/canvas/lv_canvas.h b/src/widgets/canvas/lv_canvas.h
index fa7b16fbc..e2aac005e 100644
--- a/src/widgets/canvas/lv_canvas.h
+++ b/src/widgets/canvas/lv_canvas.h
@@ -33,6 +33,7 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_canvas_class;
typedef struct {
lv_image_t img;
lv_image_dsc_t dsc;
+ const void * buf_unaligned;
} 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);
+/**
+ * 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
*====================*/
@@ -122,21 +132,8 @@ void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer);
/**********************
* 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_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)
+
+#define LV_CANVAS_BUF_SIZE(w, h, bpp, stride) (((((w * bpp + 7) >> 3) + stride - 1) & ~(stride - 1)) * h + LV_DRAW_BUF_ALIGN)
#endif /*LV_USE_CANVAS*/
diff --git a/src/widgets/chart/lv_chart.c b/src/widgets/chart/lv_chart.c
index acb4368c3..e16e4ecd8 100644
--- a/src/widgets/chart/lv_chart.c
+++ b/src/widgets/chart/lv_chart.c
@@ -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_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;
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = series_clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = series_clip_area;
int16_t i;
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)
{
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;
- layer->clip_area = clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
lv_chart_t * chart = (lv_chart_t *)obj;
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_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;
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)
{
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;
- layer->clip_area = clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
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++;
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)
{
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;
- layer->clip_area = clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
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++;
}
}
- layer->clip_area = clip_area_ori;
+ layer->_clip_area = clip_area_ori;
}
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;
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;
- layer->clip_area = clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
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++;
}
- layer->clip_area = clip_area_ori;
+ layer->_clip_area = clip_area_ori;
}
/**
diff --git a/src/widgets/dropdown/lv_dropdown.c b/src/widgets/dropdown/lv_dropdown.c
index 3bdfd3a7d..db4bb84af 100644
--- a/src/widgets/dropdown/lv_dropdown.c
+++ b/src/widgets/dropdown/lv_dropdown.c
@@ -908,10 +908,10 @@ static void draw_list(lv_event_t * e)
* the selected option can be drawn on only the background*/
lv_area_t clip_area_core;
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) {
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = clip_area_core;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area_core;
if(dropdown->selected_highlight) {
if(dropdown->pr_opt_id == dropdown->sel_opt_id) {
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_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;
lv_area_t mask_sel;
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) {
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = mask_sel;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = mask_sel;
label_dsc.text = lv_label_get_text(label);
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->skip_trans = 0;
diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c
index b0f951452..74da95960 100644
--- a/src/widgets/image/lv_image.c
+++ b/src/widgets/image/lv_image.c
@@ -360,7 +360,7 @@ void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom)
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)
@@ -664,7 +664,7 @@ static void draw_image(lv_event_t * e)
lv_draw_image_dsc_init(&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);
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);
}
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,
- ((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.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);
draw_dsc.tile = 1;
}
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) {
diff --git a/src/widgets/imgbtn/lv_imgbtn.c b/src/widgets/imgbtn/lv_imgbtn.c
index c8c2f7b42..9c402c4f2 100644
--- a/src/widgets/imgbtn/lv_imgbtn.c
+++ b/src/widgets/imgbtn/lv_imgbtn.c
@@ -262,12 +262,12 @@ static void draw_main(lv_event_t * e)
clip_area_center.y2 = coords.y2;
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) {
int32_t i;
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = clip_area_center;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area_center;
coords_part.x1 = coords.x1 + left_w;
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.x2 += src_info->header.w;
}
- layer->clip_area = clip_area_ori;
+ layer->_clip_area = clip_area_ori;
}
}
}
diff --git a/src/widgets/label/lv_label.c b/src/widgets/label/lv_label.c
index 8d44d4b09..83a66da2f 100644
--- a/src/widgets/label/lv_label.c
+++ b/src/widgets/label/lv_label.c
@@ -754,7 +754,7 @@ static void draw_main(lv_event_t * e)
}
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) {
return;
}
@@ -765,17 +765,17 @@ static void draw_main(lv_event_t * e)
txt_coords.y2 = obj->coords.y2;
}
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;
- layer->clip_area = txt_clip;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = txt_clip;
lv_draw_label(layer, &label_draw_dsc, &txt_coords);
- layer->clip_area = clip_area_ori;
+ layer->_clip_area = clip_area_ori;
}
else {
lv_draw_label(layer, &label_draw_dsc, &txt_coords);
}
- lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = txt_clip;
+ lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = txt_clip;
if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) {
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)
diff --git a/src/widgets/roller/lv_roller.c b/src/widgets/roller/lv_roller.c
index 36eb871b2..b48ae3d78 100644
--- a/src/widgets/roller/lv_roller.c
+++ b/src/widgets/roller/lv_roller.c
@@ -485,7 +485,7 @@ static void draw_main(lv_event_t * e)
get_sel_area(obj, &sel_area);
lv_area_t mask_sel;
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) {
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_dsc.flag |= LV_TEXT_FLAG_EXPAND;
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = mask_sel;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = mask_sel;
label_dsc.text = lv_label_get_text(label);
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
*therefore the label can overflow the roller's boundaries.
*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;
- if(!_lv_area_intersect(&roller_clip_area, &layer->clip_area, &roller->coords)) return;
- layer->clip_area = roller_clip_area;
+ if(!_lv_area_intersect(&roller_clip_area, &layer->_clip_area, &roller->coords)) return;
+ layer->_clip_area = roller_clip_area;
lv_area_t 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.x2 = label_obj->coords.x2;
clip2.y2 = sel_area.y1;
- if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) {
- const lv_area_t clip_area_ori2 = layer->clip_area;
- layer->clip_area = clip2;
+ if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) {
+ const lv_area_t clip_area_ori2 = layer->_clip_area;
+ layer->_clip_area = clip2;
label_draw_dsc.text = lv_label_get_text(label_obj);
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.y1 = sel_area.y2;
clip2.x2 = label_obj->coords.x2;
clip2.y2 = label_obj->coords.y2;
- if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) {
- const lv_area_t clip_area_ori2 = layer->clip_area;
- layer->clip_area = clip2;
+ if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) {
+ const lv_area_t clip_area_ori2 = layer->_clip_area;
+ layer->_clip_area = clip2;
label_draw_dsc.text = lv_label_get_text(label_obj);
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)
diff --git a/src/widgets/span/lv_span.c b/src/widgets/span/lv_span.c
index 33f317ea5..4e40a30e8 100644
--- a/src/widgets/span/lv_span.c
+++ b/src/widgets/span/lv_span.c
@@ -806,9 +806,9 @@ static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer)
/* return if no draw area */
lv_area_t clip_area;
- if(!_lv_area_intersect(&clip_area, &coords, &layer->clip_area)) return;
- const lv_area_t clip_area_ori = layer->clip_area;
- layer->clip_area = clip_area;
+ if(!_lv_area_intersect(&clip_area, &coords, &layer->_clip_area)) return;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
/* init draw variable */
lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE;
@@ -1056,12 +1056,12 @@ Next_line_init:
txt_pos.x = coords.x1;
txt_pos.y += max_line_h;
if(is_end_line || txt_pos.y > clip_area.y2 + 1) {
- layer->clip_area = clip_area_ori;
+ layer->_clip_area = clip_area_ori;
return;
}
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)
diff --git a/src/widgets/table/lv_table.c b/src/widgets/table/lv_table.c
index 5d53c6962..6f54d39d4 100644
--- a/src/widgets/table/lv_table.c
+++ b/src/widgets/table/lv_table.c
@@ -651,10 +651,10 @@ static void draw_main(lv_event_t * e)
lv_table_t * table = (lv_table_t *)obj;
lv_layer_t * layer = lv_event_get_layer(e);
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;
- layer->clip_area = clip_area;
+ const lv_area_t clip_area_ori = layer->_clip_area;
+ layer->_clip_area = clip_area;
lv_point_t txt_size;
lv_area_t cell_area;
@@ -819,10 +819,10 @@ static void draw_main(lv_event_t * e)
bool label_mask_ok;
label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area);
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;
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 */
diff --git a/tests/ref_imgs/libs/tiny_ttf_1.png b/tests/ref_imgs/libs/tiny_ttf_1.png
index c4ec1a0d2..9cccd3818 100644
--- a/tests/ref_imgs/libs/tiny_ttf_1.png
+++ b/tests/ref_imgs/libs/tiny_ttf_1.png
Binary files differ
diff --git a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png
index 07e50c81a..d679dfd92 100644
--- a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png
+++ b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png
Binary files differ
diff --git a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png
index 220c4a530..2fa4ba1a7 100644
--- a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png
+++ b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png
Binary files differ
diff --git a/tests/ref_imgs/widgets/image_transform_align.png b/tests/ref_imgs/widgets/image_transform_align.png
index c99818ec5..2cce9a4c5 100644
--- a/tests/ref_imgs/widgets/image_transform_align.png
+++ b/tests/ref_imgs/widgets/image_transform_align.png
Binary files differ
diff --git a/tests/ref_imgs/widgets/image_transform_align_offset.png b/tests/ref_imgs/widgets/image_transform_align_offset.png
index a8b1543e5..100ba9b1b 100644
--- a/tests/ref_imgs/widgets/image_transform_align_offset.png
+++ b/tests/ref_imgs/widgets/image_transform_align_offset.png
Binary files differ
diff --git a/tests/src/test_cases/draw/test_draw_vector.c b/tests/src/test_cases/draw/test_draw_vector.c
index f3f5398ca..f533ccb83 100644
--- a/tests/src/test_cases/draw/test_draw_vector.c
+++ b/tests/src/test_cases/draw/test_draw_vector.c
@@ -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 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_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_layer_t layer;