perf: Enable 512KB LVGL image cache on PSRAM and move modified lvgl to local components

This commit is contained in:
Adolfo Reyna
2026-07-09 22:27:55 -04:00
parent df93252281
commit c4ec7ead55
3999 changed files with 813776 additions and 0 deletions
@@ -0,0 +1,22 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_func_1(void)
{
TEST_FAIL();
}
#endif
@@ -0,0 +1,154 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static uint32_t MEM_SIZE = 0;
// Cache size in bytes
#define CACHE_SIZE_BYTES 1000
lv_cache_t * cache;
typedef struct _test_data {
lv_cache_slot_size_t slot;
int32_t key1;
int32_t key2;
void * data; // malloced data
} test_data;
static lv_cache_compare_res_t compare_cb(const test_data * lhs, const test_data * rhs)
{
if(lhs->key1 != rhs->key1) {
return lhs->key1 > rhs->key1 ? 1 : -1;
}
if(lhs->key2 != rhs->key2) {
return lhs->key2 > rhs->key2 ? 1 : -1;
}
return 0;
}
static void free_cb(test_data * node, void * user_data)
{
LV_UNUSED(user_data);
lv_free(node->data);
}
void setUp(void)
{
/* Function run before every test */
MEM_SIZE = lv_test_get_free_mem();
lv_cache_ops_t ops = {
.compare_cb = (lv_cache_compare_cb_t) compare_cb,
.create_cb = NULL,
.free_cb = (lv_cache_free_cb_t)free_cb,
};
cache = lv_cache_create(&lv_cache_class_lru_rb_size, sizeof(test_data), CACHE_SIZE_BYTES, ops);
}
void tearDown(void)
{
/* Function run after every test */
lv_cache_destroy(cache, NULL);
cache = NULL;
TEST_ASSERT_MEM_LEAK_LESS_THAN(MEM_SIZE, 32);
}
void test_cache_1(void)
{
void * record_data_ptr = NULL;
// create many node unless cache is full
uint32_t curr_mem_size = 8;
uint32_t curr_total_mem_size = 0;
while(curr_total_mem_size < CACHE_SIZE_BYTES) {
test_data search_key = {
.slot.size = curr_mem_size,
.key1 = (int32_t)curr_mem_size,
.key2 = (int32_t)curr_mem_size + 1
};
// acquire cache first
lv_cache_entry_t * entry = lv_cache_acquire(cache, &search_key, NULL);
if(entry != NULL) {
continue;
}
// if cache miss then add cache
entry = lv_cache_add(cache, &search_key, NULL);
TEST_ASSERT_NOT_NULL(entry);
test_data * data = lv_cache_entry_get_data(entry);
TEST_ASSERT_NOT_NULL(data);
data->data = lv_malloc(data->slot.size);
// record data ptr when {key1 = 32, key2 = 33}.
if(search_key.key1 == 32 && search_key.key2 == 33) {
record_data_ptr = data->data;
}
lv_cache_release(cache, entry, NULL);
curr_total_mem_size += curr_mem_size;
curr_mem_size *= 2;
TEST_PRINTF("cache free: %d, allocated: %d", lv_cache_get_free_size(cache, NULL), curr_mem_size);
}
/*
* allocated = 8 + 16 + 32 + 64 + 128 + 256 - 8 - 16 + 512 = 992
* free = 1000 - 992 = 8
* The last node size should be 1024, but the cache's max size is 1000. So new entry will be allocated failed and
* the loop will break.
* */
TEST_ASSERT_EQUAL(8, lv_cache_get_free_size(cache, NULL));
/*
* Search entry {key1 = 32, key2 = 33}
*/
test_data search_key32 = {
.key1 = 32,
.key2 = 33
};
lv_cache_entry_t * entry_key32 = lv_cache_acquire(cache, &search_key32, NULL);
test_data * cached_data_key32 = lv_cache_entry_get_data(entry_key32);
TEST_ASSERT_EQUAL(record_data_ptr, cached_data_key32->data);
/*
* Now drop the cache {key1 = 32, key2 = 33}. However, this entry is acquired once without release, so `drop`
* will not release the memory allocated by this entry.
*/
size_t mem_curr_free = lv_test_get_free_mem();
lv_cache_drop(cache, &search_key32, NULL);
/*
* Though it doesn't release the data, the entry and other structure has been freed.
* lv_rb_note_t (4 ptr + 1 int32 may align to 8 bit on 64 bit machine) + lv_ll (2 ptr + node_size).
* Also, the def heap has some other aligned attributes. It'll also affect the final result.
*/
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_curr_free,
sizeof(lv_rb_node_t)
+ sizeof(void *) + (sizeof(lv_ll_node_t *) + sizeof(lv_ll_node_t *))
+ 32); // the last 32 is an error in memory allocating
mem_curr_free = lv_test_get_free_mem();
lv_cache_release(cache, entry_key32, NULL);
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_curr_free,
lv_cache_entry_get_size(sizeof(test_data)) + sizeof(void *)
+ 32
+ 32);
// Now the freed cache size should be 8 + 32 = 40
TEST_ASSERT_EQUAL(40, lv_cache_get_free_size(cache, NULL));
}
#endif
@@ -0,0 +1,78 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_func_1(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
LV_IMAGE_DECLARE(test_RGB565_RLE_align64);
lv_obj_t * obj;
/*Larger bg image*/
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 60, 40);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 0, 0);
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 60, 40);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 20, 0);
/*Smaller bg image*/
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 0, 0);
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 20, 0);
/*Smaller bg image tiled*/
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 0, 0);
lv_obj_set_style_bg_image_tiled(obj, true, 0);
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 20, 0);
lv_obj_set_style_bg_image_tiled(obj, true, 0);
/*Smaller bg image tiled and opacity*/
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 0, 0);
lv_obj_set_style_bg_image_tiled(obj, true, 0);
lv_obj_set_style_bg_image_opa(obj, LV_OPA_50, 0);
obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_set_style_bg_image_src(obj, &test_RGB565_RLE_align64, 0);
lv_obj_set_style_radius(obj, 20, 0);
lv_obj_set_style_bg_image_tiled(obj, true, 0);
lv_obj_set_style_bg_image_opa(obj, LV_OPA_50, 0);
#if LV_BIN_DECODER_RAM_LOAD
TEST_ASSERT_EQUAL_SCREENSHOT("draw/bg_image_1.png");
#endif
}
#endif
@@ -0,0 +1,66 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static lv_obj_t * create_panel(int32_t radius, bool transform)
{
lv_obj_t * parent = lv_obj_create(lv_screen_active());
lv_obj_set_style_pad_all(parent, 3, 0);
lv_obj_set_style_radius(parent, radius, 0);
lv_obj_set_style_clip_corner(parent, true, 0);
lv_obj_set_style_shadow_color(parent, lv_color_hex(0x888888), 0);
lv_obj_set_style_shadow_width(parent, 30, 0);
lv_obj_set_style_shadow_spread(parent, 10, 0);
lv_obj_set_style_outline_color(parent, lv_color_hex(0xff0000), 0);
lv_obj_set_style_outline_width(parent, 2, 0);
lv_obj_set_style_outline_pad(parent, 5, 0);
if(transform) lv_obj_set_style_transform_rotation(parent, 300, 0);
lv_obj_t * label = lv_label_create(parent);
lv_obj_set_width(label, lv_pct(200));
lv_label_set_text(label,
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus dignissim quam id eros iaculis dapibus. Mauris nisl orci, vulputate sed eleifend a, consectetur et nulla.");
lv_obj_set_style_text_font(label, &lv_font_montserrat_24, 0);
lv_obj_set_style_bg_color(label, lv_palette_main(LV_PALETTE_RED), 0);
lv_obj_set_style_bg_opa(label, LV_OPA_20, 0);
lv_obj_update_layout(parent);
lv_obj_scroll_by(parent, -15, -15, LV_ANIM_OFF);
return parent;
}
void test_clip_corner_1(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_set_style_pad_column(lv_screen_active(), 40, 0);
create_panel(0, false);
create_panel(10, false);
create_panel(30, false);
create_panel(100, false);
lv_obj_t * cont = create_panel(0, true);
lv_obj_add_flag(cont, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
create_panel(10, true);
create_panel(30, true);
create_panel(100, true);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/clip_corner_1.png");
}
#endif
@@ -0,0 +1,170 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
}
void tearDown(void)
{
/* Function run after every test */
}
static void canvas_basic_render(uint8_t * canvas_buf, lv_color_format_t render_cf, const char * name_main,
const char * name_sub)
{
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas, canvas_buf, 180, 180, render_cf);
lv_canvas_fill_bg(canvas, lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 2), LV_OPA_COVER);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_area_t area;
char txt[64];
lv_snprintf(txt, sizeof(txt), "%s_to_%s", name_main, name_sub);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.text = txt;
area.x1 = 3;
area.x2 = 180;
area.y1 = 5;
area.y2 = 25;
lv_draw_label(&layer, &label_dsc, &area);
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.radius = 10;
rect_dsc.bg_color = lv_palette_main(LV_PALETTE_RED);
rect_dsc.bg_opa = LV_OPA_COVER;
rect_dsc.outline_color = lv_palette_main(LV_PALETTE_INDIGO);
rect_dsc.outline_width = 10;
rect_dsc.outline_pad = -5;
rect_dsc.outline_opa = LV_OPA_60;
rect_dsc.shadow_color = lv_palette_main(LV_PALETTE_ORANGE);
rect_dsc.shadow_width = 10;
rect_dsc.shadow_offset_x = 5;
rect_dsc.shadow_offset_y = 10;
area.x1 = 10;
area.x2 = 170;
area.y1 = 30;
area.y2 = 60;
lv_draw_rect(&layer, &rect_dsc, &area);
area.y1 = 80;
area.y2 = 110;
rect_dsc.bg_grad.dir = LV_GRAD_DIR_HOR;
rect_dsc.bg_grad.stops_count = 2;
rect_dsc.bg_grad.stops[0].color = lv_palette_main(LV_PALETTE_RED);
rect_dsc.bg_grad.stops[0].opa = LV_OPA_COVER;
rect_dsc.bg_grad.stops[0].frac = 0;
rect_dsc.bg_grad.stops[1].color = lv_palette_main(LV_PALETTE_GREEN);
rect_dsc.bg_grad.stops[1].opa = LV_OPA_COVER;
rect_dsc.bg_grad.stops[1].frac = 255;
lv_draw_rect(&layer, &rect_dsc, &area);
area.y1 = 130;
area.y2 = 160;
rect_dsc.bg_grad.stops[0].opa = LV_OPA_30;
lv_draw_rect(&layer, &rect_dsc, &area);
lv_canvas_finish_layer(canvas, &layer);
lv_obj_delete(canvas);
}
void canvas_blend_test(lv_obj_t * canvas_large, lv_draw_image_dsc_t * img_dsc, const char * name_main,
const char * name_sub, lv_color_format_t small_render_cf, uint32_t idx)
{
lv_draw_buf_t * img = (lv_draw_buf_t *)img_dsc->src;
img->header.cf = small_render_cf;
img->header.stride = lv_draw_buf_width_to_stride(180, small_render_cf);
canvas_basic_render((uint8_t *)img->data, small_render_cf, name_main, name_sub);
lv_area_t area;
area.x1 = (idx % 2) * 380 + 10;
area.x2 = area.x1 + 179;
area.y1 = (idx / 2) * 190 + 10;
area.y2 = area.y1 + 179;
lv_layer_t layer;
img_dsc->opa = LV_OPA_COVER;
lv_canvas_init_layer(canvas_large, &layer);
lv_draw_image(&layer, img_dsc, &area);
lv_canvas_finish_layer(canvas_large, &layer);
lv_area_move(&area, 190, 0);
img_dsc->opa = LV_OPA_50;
lv_canvas_init_layer(canvas_large, &layer);
lv_draw_image(&layer, img_dsc, &area);
lv_canvas_finish_layer(canvas_large, &layer);
lv_image_cache_drop(img);
}
static void canvas_draw(const char * name, lv_color_format_t large_render_cf)
{
lv_obj_clean(lv_screen_active());
static LV_ATTRIBUTE_MEM_ALIGN uint8_t canvas_buf[LV_TEST_WIDTH_TO_STRIDE(180, 4) * 180 + LV_DRAW_BUF_ALIGN];
static uint8_t canvas2_buf[LV_TEST_WIDTH_TO_STRIDE(768, 4) * 390 + LV_DRAW_BUF_ALIGN];
lv_obj_t * canvas2 = lv_canvas_create(lv_screen_active());
lv_canvas_set_buffer(canvas2, lv_draw_buf_align(canvas2_buf, large_render_cf), 768, 390, large_render_cf);
lv_canvas_fill_bg(canvas2, lv_palette_lighten(LV_PALETTE_BLUE_GREY, 2), LV_OPA_COVER);
lv_draw_buf_t img;
lv_draw_buf_init(&img, 180, 180, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO, canvas_buf, sizeof(canvas_buf));
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.src = &img;
canvas_blend_test(canvas2, &img_dsc, "rgb565", name, LV_COLOR_FORMAT_RGB565, 0);
canvas_blend_test(canvas2, &img_dsc, "rgb888", name, LV_COLOR_FORMAT_RGB888, 1);
canvas_blend_test(canvas2, &img_dsc, "xrgb8888", name, LV_COLOR_FORMAT_XRGB8888, 2);
canvas_blend_test(canvas2, &img_dsc, "argb8888", name, LV_COLOR_FORMAT_ARGB8888, 3);
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "draw/blend_to_%s.png", name);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
}
void test_xrgb8888(void)
{
canvas_draw("xrgb8888", LV_COLOR_FORMAT_XRGB8888);
}
void test_argb8888(void)
{
canvas_draw("argb8888", LV_COLOR_FORMAT_ARGB8888);
}
void test_rgb888(void)
{
canvas_draw("rgb888", LV_COLOR_FORMAT_RGB888);
}
void test_rgb565(void)
{
canvas_draw("rgb565", LV_COLOR_FORMAT_RGB565);
}
#endif
@@ -0,0 +1,61 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
}
void tearDown(void)
{
}
void test_register_custom_handlers(void)
{
lv_draw_sw_custom_blend_handler_t handler = {
.dest_cf = LV_COLOR_FORMAT_I2,
.handler = NULL,
};
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
}
void test_overwrite_custom_handler(void)
{
lv_draw_sw_custom_blend_handler_t handler = {
.dest_cf = LV_COLOR_FORMAT_I2,
.handler = (lv_draw_sw_blend_handler_t)0xDEADBEEF,
};
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
lv_draw_sw_custom_blend_handler_t handler2 = {
.dest_cf = LV_COLOR_FORMAT_I2,
.handler = (lv_draw_sw_blend_handler_t)0xCAFEBABE,
};
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler2));
lv_draw_sw_blend_handler_t handler3 = lv_draw_sw_get_blend_handler(LV_COLOR_FORMAT_I2);
TEST_ASSERT_NOT_NULL(handler3);
TEST_ASSERT_EQUAL_PTR(handler3, (lv_draw_sw_blend_handler_t)0xCAFEBABE);
}
void test_unregister_custom_handler(void)
{
lv_draw_sw_custom_blend_handler_t handler = {
.dest_cf = LV_COLOR_FORMAT_I2,
.handler = NULL,
};
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
TEST_ASSERT_TRUE(lv_draw_sw_unregister_blend_handler(LV_COLOR_FORMAT_I2));
lv_draw_sw_blend_handler_t handler2 = lv_draw_sw_get_blend_handler(LV_COLOR_FORMAT_I2);
TEST_ASSERT_NULL(handler2);
}
#endif
@@ -0,0 +1,148 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static lv_obj_t * label_create(const lv_font_t * font, lv_style_t * style, const char * text_base)
{
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text_fmt(label, "%s: the quick brown fox jumps over the lazy dog", text_base);
// lv_label_set_text_fmt(label, "l");
lv_obj_set_style_text_font(label, font, 0);
if(style) lv_obj_add_style(label, style, 0);
return label;
}
static void all_labels_create(const char * name, lv_style_t * style)
{
LV_FONT_DECLARE(test_font_montserrat_ascii_1bpp);
LV_FONT_DECLARE(test_font_montserrat_ascii_2bpp);
LV_FONT_DECLARE(test_font_montserrat_ascii_4bpp);
LV_FONT_DECLARE(test_font_montserrat_ascii_8bpp);
LV_FONT_DECLARE(test_font_montserrat_ascii_3bpp_compressed);
label_create(&test_font_montserrat_ascii_1bpp, style, "1bpp font");
label_create(&test_font_montserrat_ascii_2bpp, style, "2bpp font");
label_create(&test_font_montserrat_ascii_4bpp, style, "4bpp font");
label_create(&test_font_montserrat_ascii_8bpp, style, "8bpp font");
label_create(&test_font_montserrat_ascii_3bpp_compressed, style, "3bpp compressed font");
char buf[64];
lv_snprintf(buf, sizeof(buf), "draw/label_%s.png", name);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
void test_draw_label_normal(void)
{
all_labels_create("normal", NULL);
}
void test_draw_label_color(void)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_color(&style, lv_palette_main(LV_PALETTE_RED));
all_labels_create("color", &style);
}
void test_draw_label_opa(void)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_color(&style, lv_palette_main(LV_PALETTE_RED));
all_labels_create("opa", &style);
}
void test_draw_label_color_and_opa(void)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_color(&style, lv_palette_main(LV_PALETTE_RED));
lv_style_set_text_opa(&style, LV_OPA_50);
all_labels_create("color_and_opa", &style);
}
static lv_obj_t * decor_label_create(lv_text_decor_t decor, lv_text_align_t align, lv_opa_t opa)
{
lv_color_t color = lv_palette_main(LV_PALETTE_BLUE);
lv_color_t sel_bg_color = lv_palette_lighten(LV_PALETTE_RED, 4);
lv_color_t sel_color = lv_palette_darken(LV_PALETTE_RED, 4);
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Hi,\nTesting the\nlabels.");
lv_obj_set_style_text_decor(label, decor, 0);
lv_obj_set_style_text_color(label, color, 0);
lv_obj_set_style_text_opa(label, opa, 0);
lv_obj_set_style_text_align(label, align, 0);
lv_obj_set_style_bg_color(label, sel_bg_color, LV_PART_SELECTED);
lv_obj_set_style_text_color(label, sel_color, LV_PART_SELECTED);
lv_label_set_text_selection_start(label, 10);
lv_label_set_text_selection_end(label, 19);
return label;
}
static void all_decor_labels_create(lv_text_decor_t decor)
{
lv_obj_t * label;
label = decor_label_create(decor, LV_TEXT_ALIGN_LEFT, LV_OPA_COVER);
lv_obj_add_flag(label, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
label = decor_label_create(decor, LV_TEXT_ALIGN_CENTER, LV_OPA_COVER);
label = decor_label_create(decor, LV_TEXT_ALIGN_RIGHT, LV_OPA_COVER);
label = decor_label_create(decor, LV_TEXT_ALIGN_LEFT, LV_OPA_50);
label = decor_label_create(decor, LV_TEXT_ALIGN_CENTER, LV_OPA_50);
label = decor_label_create(decor, LV_TEXT_ALIGN_RIGHT, LV_OPA_50);
}
void test_label_decor(void)
{
all_decor_labels_create(LV_TEXT_DECOR_NONE);
all_decor_labels_create(LV_TEXT_DECOR_UNDERLINE);
all_decor_labels_create(LV_TEXT_DECOR_STRIKETHROUGH);
all_decor_labels_create(LV_TEXT_DECOR_UNDERLINE | LV_TEXT_DECOR_STRIKETHROUGH);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/label_decor.png");
}
void test_label_selection_and_recolor(void)
{
lv_text_decor_t decor = LV_TEXT_DECOR_NONE;
lv_color_t color = lv_palette_main(LV_PALETTE_BLUE);
lv_color_t sel_bg_color = lv_palette_lighten(LV_PALETTE_RED, 4);
lv_color_t sel_color = lv_palette_darken(LV_PALETTE_RED, 4);
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_recolor(label, true);
lv_label_set_text(label, "Hi, Testing the #00ff00 colored labels.#");
lv_obj_set_style_text_decor(label, decor, 0);
lv_obj_set_style_text_color(label, color, 0);
lv_obj_set_style_text_opa(label, LV_OPA_COVER, 0);
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_style_bg_color(label, sel_bg_color, LV_PART_SELECTED);
lv_obj_set_style_text_color(label, sel_color, LV_PART_SELECTED);
lv_label_set_text_selection_start(label, 10);
lv_label_set_text_selection_end(label, 25);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/label_selection_and_recolor.png");
}
#endif
@@ -0,0 +1,99 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
lv_obj_t * test_obj_create(const void * mask_src, int32_t scale, int32_t angle)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 200);
lv_obj_set_style_bg_color(obj, lv_color_hex3(0xf88), 0);
lv_obj_set_style_bitmap_mask_src(obj, mask_src, 0);
lv_obj_set_style_transform_scale(obj, scale, 0);
lv_obj_set_style_transform_rotation(obj, angle, 0);
lv_obj_center(obj);
lv_obj_t * label = lv_label_create(obj);
lv_obj_set_width(label, lv_pct(100));
lv_label_set_text(label,
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque suscipit risus nec pharetra pulvinar. In hac habitasse platea dictumst. Proin placerat congue massa eu luctus. Suspendisse risus nulla, consectetur eget odio ut, mollis sollicitudin magna. Suspendisse volutpat consequat laoreet. Aenean sodales suscipit leo, vitae pulvinar lorem pulvinar eu. Nullam molestie hendrerit est sit amet imperdiet.");
lv_obj_center(label);
return obj;
}
void test_draw_layer_bitmap_mask_from_variable(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
LV_IMAGE_DECLARE(test_image_cogwheel_a8);
test_obj_create(&test_image_cogwheel_a8, LV_SCALE_NONE, 0);
test_obj_create(&test_image_cogwheel_a8, 300, 0);
test_obj_create(&test_image_cogwheel_a8, LV_SCALE_NONE, 200);
test_obj_create(&test_image_cogwheel_a8, 80, 600);
#ifndef NON_AMD64_BUILD
TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask.png");
#endif
}
void test_draw_layer_bitmap_mask_from_image(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
const char * mask_src = "A:src/test_files/binimages/cogwheel.A8.bin";
test_obj_create(mask_src, LV_SCALE_NONE, 0);
test_obj_create(mask_src, 300, 0);
test_obj_create(mask_src, LV_SCALE_NONE, 200);
test_obj_create(mask_src, 80, 600);
#ifndef NON_AMD64_BUILD
TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask.png");
#endif
}
void test_draw_layer_bitmap_mask_from_image_not_found(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
const char * mask_src = "A:nonexistent/file";
test_obj_create(mask_src, LV_SCALE_NONE, 0);
test_obj_create(mask_src, 300, 0);
test_obj_create(mask_src, LV_SCALE_NONE, 200);
test_obj_create(mask_src, 80, 600);
#ifndef NON_AMD64_BUILD
TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask_not_masked.png");
#endif
}
void test_draw_layer_dispatch(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_style_opa_layered(obj, LV_OPA_50, 0);
lv_obj_set_style_opa(obj, LV_OPA_0, 0);
lv_obj_center(obj);
/*Verify whether this scenario will result in a busy loop.*/
TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_dispatch.png");
}
#endif
@@ -0,0 +1,107 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static lv_obj_t * canvas_create(void)
{
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_size(canvas, 500, 360);
lv_draw_buf_t * draw_buf = lv_draw_buf_create(500, 360, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO);
lv_draw_buf_clear(draw_buf, NULL);
lv_canvas_set_draw_buf(canvas, draw_buf);
return canvas;
}
static void canvas_destroy(lv_obj_t * canvas)
{
lv_draw_buf_destroy(lv_canvas_get_draw_buf(canvas));
lv_obj_delete(canvas);
}
void test_draw_sin_wave(void)
{
const char * string = "lol~ I'm wavvvvvvving~";
const uint32_t string_len = lv_strlen(string);
LV_FONT_DECLARE(test_font_montserrat_ascii_4bpp);
lv_obj_t * canvas = canvas_create();
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_letter_dsc_t letter_dsc;
lv_draw_letter_dsc_init(&letter_dsc);
letter_dsc.color = lv_color_hex(0xff0000);
letter_dsc.font = &test_font_montserrat_ascii_4bpp;
{
#define CURVE1_X(t) (t * 2 + 20)
#define CURVE1_Y(t) (lv_trigo_sin(t) * 40 / 32767 + 80)
int32_t pre_x = CURVE1_X(-1);
int32_t pre_y = CURVE1_Y(-1);
for(int16_t i = 0; i < 30; i++) {
const int32_t angle = i * 10;
const int32_t x = CURVE1_X(angle);
const int32_t y = CURVE1_Y(angle);
letter_dsc.unicode = (uint32_t)string[i % string_len];
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x);
letter_dsc.rotation = (letter_dsc.rotation > 180 ? letter_dsc.rotation - 360 : letter_dsc.rotation) * 5;
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
.x = x, .y = y
});
pre_x = x;
pre_y = y;
}
}
{
#define CURVE2_X(t) (t * 3 + 20)
#define CURVE2_Y(t) (lv_trigo_sin((t) * 4) * 40 / 32767 + 230)
int32_t pre_x = CURVE2_X(-1);
int32_t pre_y = CURVE2_Y(-1);
for(int16_t i = 0; i < 30; i++) {
const int32_t angle = i * 5;
const int32_t x = CURVE2_X(angle);
const int32_t y = CURVE2_Y(angle);
letter_dsc.unicode = (uint32_t)string[i % string_len];
letter_dsc.rotation = lv_atan2(y - pre_y, x - pre_x) * 10;
letter_dsc.color = lv_color_hsv_to_rgb(i * 10, 100, 100);
lv_draw_letter(&layer, &letter_dsc, &(lv_point_t) {
.x = x, .y = y
});
pre_x = x;
pre_y = y;
}
}
lv_canvas_finish_layer(canvas, &layer);
#ifndef NON_AMD64_BUILD
TEST_ASSERT_EQUAL_SCREENSHOT("draw/letter_0.png");
#endif
canvas_destroy(canvas);
}
#endif
@@ -0,0 +1,706 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include <string.h>
#include "unity/unity.h"
static lv_layer_t layer;
static lv_obj_t * canvas;
static lv_draw_buf_t * canvas_buf;
void setUp(void)
{
canvas = lv_canvas_create(lv_scr_act());
canvas_buf = lv_draw_buf_create(480, 480, LV_COLOR_FORMAT_ARGB8888, 0);
TEST_ASSERT_NOT_NULL(canvas_buf);
lv_canvas_set_draw_buf(canvas, canvas_buf);
lv_canvas_fill_bg(canvas, lv_color_make(0xff, 0xff, 0xff), 255);
lv_canvas_init_layer(canvas, &layer);
}
void tearDown(void)
{
lv_image_cache_drop(canvas_buf);
lv_draw_buf_destroy(canvas_buf);
lv_obj_del(canvas);
}
#if LV_USE_VECTOR_GRAPHIC && LV_USE_SVG
#define SNAPSHOT_NAME(n) (#n)
static void draw_snapshot(const char * name)
{
LV_UNUSED(name);
#ifndef NON_AMD64_BUILD
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "draw/svg_draw_%s.lp64.png", name);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
#else
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "draw/svg_draw_%s.lp32.png", name);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
#endif
}
static void draw_svg(lv_svg_node_t * svg)
{
lv_image_cache_drop(canvas_buf);
lv_canvas_set_draw_buf(canvas, canvas_buf);
lv_canvas_fill_bg(canvas, lv_color_make(0xff, 0xff, 0xff), 255);
lv_draw_svg(&layer, svg);
lv_canvas_finish_layer(canvas, &layer);
}
void test_draw_group(void)
{
const char * svg_group_1 = \
"<svg><g fill=\"#FF0000\">"
"<rect x=\"0\" y=\"0\" width=\"100\" height=\"100\"/>"
"<circle cx=\"100\" cy=\"100\" r=\"50\"/>"
"<ellipse fill=\"#00F\" cx=\"200\" cy=\"200\" rx=\"100\" ry=50/>"
"</g></svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_group_1, lv_strlen(svg_group_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_group_1));
lv_svg_node_delete(svg);
const char * svg_group_2 = \
"<svg><g fill=\"blue\"><g>"
"<rect width=\"100\" height=\"100\" fill=\"inherit\"/>"
"<circle cx=\"200\" cy=\"200\" r=\"50\" fill=\"green\"/>"
"</g></g></svg>";
svg = lv_svg_load_data(svg_group_2, lv_strlen(svg_group_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_group_2));
lv_svg_node_delete(svg);
const char * svg_group_3 = \
"<svg><use xlink:href=\"#g1\" x=50 y=50/>"
"<g fill=\"blue\" xml:id=\"g1\">"
"<rect width=20 height=20/>"
"<rect x=30 width=20 height=20 fill=green/>"
"</g></svg>";
svg = lv_svg_load_data(svg_group_3, lv_strlen(svg_group_3));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_group_3));
lv_svg_node_delete(svg);
const char * svg_group_4 = \
"<svg><defs><linearGradient id=\"s1\">"
"<stop offset=\"0.1\" stop-color=\"red\"/>"
"<stop offset=\"0.8\" stop-color=\"green\"/>"
"</linearGradient></defs>"
"<g fill=\"url(#s1)\" id=\"g1\">"
"<rect width=20 height=20/><g>"
"<rect x=30 width=20 height=20 fill=blue/>"
"<rect x=30 x=80 y= 30 width=20 height =20 fill=red/></g></g>"
"<use xlink:href=\"#g1\" x=150 y=100/>"
"<use xlink:href=\"#g1\" x=250 y=100/></svg>";
svg = lv_svg_load_data(svg_group_4, lv_strlen(svg_group_4));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_group_4));
lv_svg_node_delete(svg);
}
static void load_image(const char * image_url, lv_draw_image_dsc_t * img_dsc)
{
if(strcmp(image_url, "cogwheel.bin") == 0) {
LV_IMAGE_DECLARE(test_image_cogwheel_argb8888);
img_dsc->header = test_image_cogwheel_argb8888.header;
img_dsc->src = &test_image_cogwheel_argb8888;
}
}
static const char * get_font_path(const char * font_family)
{
LV_UNUSED(font_family);
#ifndef TEST_FONT_PATH
return "./src/test_files/fonts/noto/NotoSansSC-Regular.ttf";
#else
return TEST_FONT_PATH;
#endif
}
const lv_svg_render_hal_t hal = {
.load_image = load_image,
.get_font_path = get_font_path,
};
void test_draw_shapes(void)
{
lv_svg_render_init(&hal);
const char * svg_shapes_1 = \
"<svg><rect fill=\"red\" x=\"0\" y=\"0\" width=\"100\" height=\"100\"/>"
"<circle fill=\"red\" cx=\"100\" cy=\"100\" r=\"50\"/>"
"<ellipse stroke=\"red\" fill=\"none\" cx=\"200\" cy=\"200\" rx=\"100\" ry=50/>"
"</svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_shapes_1, lv_strlen(svg_shapes_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_1));
lv_svg_node_delete(svg);
const char * svg_shapes_2 = \
"<svg>"
"<rect fill=\"rgb(0, 0, 200)\" x=\"0\" y=\"0\" width=\"100\" height=\"100\""
" transform=\"translate(50, 50) rotate(45) translate(-50, -50)\"/>"
"</svg>";
svg = lv_svg_load_data(svg_shapes_2, lv_strlen(svg_shapes_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_2));
lv_svg_node_delete(svg);
const char * svg_shapes_3 = \
"<svg width=\"4cm\" height=\"2cm\" viewBox=\"0 0 400 200\">"
"<defs><linearGradient xml:id=\"MyGradient\">"
"<stop offset=\"0.05\" stop-color=\"#F60\"/>"
"<stop offset=\"0.95\" stop-color=\"#FF6\"/>"
"</linearGradient></defs>"
"<rect fill=\"url(#MyGradient)\" stroke=\"black\" stroke-width=\"5\""
" x=\"100\" y=\"100\" width=\"600\" height=\"200\"/>"
"</svg>";
svg = lv_svg_load_data(svg_shapes_3, lv_strlen(svg_shapes_3));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_3));
lv_svg_node_delete(svg);
const char * svg_shapes_4 = \
"<svg width=\"480\" height=\"360\" viewBox=\"0 0 480 360\">"
"<defs><solidColor xml:id=\"solidMaroon\" solid-color=\"maroon\" solid-opacity=\"0.7\"/>"
"</defs><g>"
"<circle transform=\"translate(100, 150)\" fill=\"url(#solidMaroon)\" r=\"30\"/>"
"<rect fill=\"url(#solidMaroon)\" transform=\"translate(190, 150)\" x=\"-30\" y=\"-30\" width=\"60\" height=\"60\"/>"
"<path fill=\"url(#solidMaroon)\" transform=\"translate(270, 150)\" d=\"M 0 -30 L 30 30 L -30 30 Z\" />"
"<text fill=\"url(#solidMaroon)\" transform=\"translate(340, 150)\" "
"y=\"21\" font-weight=\"bold\" font-size=\"60\">A</text>"
"</g></svg>";
svg = lv_svg_load_data(svg_shapes_4, lv_strlen(svg_shapes_4));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_4));
lv_svg_node_delete(svg);
const char * svg_shapes_5 = \
"<svg width=\"8cm\" height=\"4cm\" viewBox=\"0 0 800 400\">"
"<defs><radialGradient id=\"MyGradient\" gradientUnits=\"userSpaceOnUse\""
" cx=\"400\" cy=\"200\" r=\"300\">"
"<stop offset=\"0.2\" stop-color=\"black\"/>"
"<stop offset=\"0.75\" stop-color=\"white\"/>"
"</radialGradient></defs>"
"<rect fill=\"url(#MyGradient)\" stroke=\"black\" stroke-width=\"5\""
" x=\"100\" y=\"100\" width=\"600\" height=\"200\"/></svg>";
svg = lv_svg_load_data(svg_shapes_5, lv_strlen(svg_shapes_5));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_5));
lv_svg_node_delete(svg);
const char * svg_shapes_6 = \
"<svg width=\"8cm\" height=\"4cm\" viewBox=\"0 0 800 400\">"
"<defs><radialGradient id=\"MyGradient\">"
"<stop offset=\"0.2\" stop-color=\"white\"/>"
"<stop offset=\"0.75\" stop-color=\"black\"/>"
"</radialGradient></defs>"
"<rect fill=\"url(#MyGradient)\" stroke=\"black\" stroke-width=\"5\""
"x=\"100\" y=\"100\" width=\"300\" height=\"300\"/></svg>";
svg = lv_svg_load_data(svg_shapes_6, lv_strlen(svg_shapes_6));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_6));
lv_svg_node_delete(svg);
const char * svg_shapes_7 = \
"<svg width=\"8cm\" height=\"4cm\" viewBox=\"0 0 800 400\">"
"<defs><linearGradient xml:id=\"MyGradient\" x1=0 y1=0 x2=500 y2=350 gradientUnits=\"userSpaceOnUse\">"
"<stop offset=\"0.05\" stop-color=\"#F60\"/>"
"<stop offset=\"0.95\" stop-color=\"#FF6\"/>"
"</linearGradient></defs>"
"<rect fill=\"url(#MyGradient)\" stroke=\"black\" stroke-width=\"5\""
" x=\"100\" y=\"100\" width=\"600\" height=\"200\"/></svg>";
svg = lv_svg_load_data(svg_shapes_7, lv_strlen(svg_shapes_7));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_7));
lv_svg_node_delete(svg);
const char * svg_shapes_8 = \
"<svg width=\"7cm\" height=\"2cm\" viewBox=\"0 0 700 200\">"
"<g><defs><linearGradient id=\"MyGradient\" gradientUnits=\"objectBoundingBox\">"
"<stop offset=\"0\" stop-color=\"#F60\"/>"
"<stop offset=\"1\" stop-color=\"#FF6\"/>"
"</linearGradient></defs>"
"<rect x=\"1\" y=\"1\" width=\"698\" height=\"198\" fill=\"none\" stroke=\"blue\" stroke-width=\"2\"/>"
"<g fill=\"url(#MyGradient)\">"
"<rect x=\"100\" y=\"50\" width=\"200\" height=\"100\"/>"
"<rect x=\"400\" y=\"50\" width=\"200\" height=\"100\"/>"
"</g></g></svg>";
svg = lv_svg_load_data(svg_shapes_8, lv_strlen(svg_shapes_8));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_8));
lv_svg_node_delete(svg);
const char * svg_shapes_9 = \
"<svg width=\"8cm\" height=\"4cm\" viewBox=\"0 0 800 400\">"
"<g><defs><linearGradient id=\"MyGradient\" gradientUnits=\"userSpaceOnUse\""
" x1=0 y1=0 x2=350 y2=350>"
"<stop offset=\"0\" stop-color=\"red\"/>"
"<stop offset=\"0.5\" stop-color=\"blue\"/>"
"</linearGradient></defs>"
"<rect fill=\"url(#MyGradient)\" stroke=\"black\" stroke-width=\"5\""
" x=\"0\" y=\"0\" width=\"200\" height=\"600\"/></g></svg>";
svg = lv_svg_load_data(svg_shapes_9, lv_strlen(svg_shapes_9));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_9));
lv_svg_node_delete(svg);
const char * svg_shapes_10 = \
"<svg width='144' height='144' viewBox='0 0 144 144'><g>"
"<rect x='4' y='4' width='136' height='136' fill='url(#paint2_linear_13691_50994)' fill-opacity='1.0'/>"
"</g><defs><linearGradient id='paint2_linear_13691_50994' x1='4' y1='4' x2='280' y2='280'"
" gradientUnits='userSpaceOnUse'>"
"<stop stop-color='white'/><stop offset='1' stop-color='#000000'/></linearGradient>"
"</defs></svg>";
svg = lv_svg_load_data(svg_shapes_10, lv_strlen(svg_shapes_10));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_10));
lv_svg_node_delete(svg);
const char * svg_shapes_11 = \
"<svg width=\'800\' height=\'800\' viewBox=\'0 0 800 800\' fill=\'none\' xmlns=\'http://www.w3.org/2000/svg\'>"
"<rect x=\'10\' y=\'10\' width=\'200\' height=\'200\' fill=\'url(#paint0_linear_13691_50971)\'/>"
"<rect x=\'212\' y=\'10\' width=\'200\' height=\'200\' fill=\'url(#paint0_linear_13691_50971)\'/>"
"<rect x=\'10\' y=\'212\' width=\'200\' height=\'200\' fill=\'url(#paint0_linear_13691_50971)\'/>"
"<rect x=\'212\' y=\'212\' width=\'200\' height=\'200\' fill=\'url(#paint0_linear_13691_50971)\'/>"
"<defs><linearGradient id=\'paint0_linear_13691_50971\' x1=\'10\' y1=\'10\' "
"x2=\'400\' y2=\'400\' gradientUnits=\'userSpaceOnUse\' >"
"<stop offset=\'0\' stop-color=\'red\' stop-opacity=\'1\'/>"
"<stop offset=\'1\' stop-color=\'green\' stop-opacity=\'1\'/>"
"</linearGradient></defs></svg>";
svg = lv_svg_load_data(svg_shapes_11, lv_strlen(svg_shapes_11));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_shapes_11));
lv_svg_node_delete(svg);
}
void test_draw_image(void)
{
lv_svg_render_init(&hal);
const char * svg_image_0 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"none\""
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_image_0, lv_strlen(svg_image_0));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_0));
lv_svg_node_delete(svg);
const char * svg_image_1 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\""
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_1, lv_strlen(svg_image_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_1));
lv_svg_node_delete(svg);
const char * svg_image_2 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"540\" preserveAspectRatio=\"xMinYMin\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"540\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_2, lv_strlen(svg_image_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_2));
lv_svg_node_delete(svg);
const char * svg_image_3 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"540\" preserveAspectRatio=\" xMinYMid\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"540\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_3, lv_strlen(svg_image_3));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_3));
lv_svg_node_delete(svg);
const char * svg_image_4 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"540\" opacity=\"0.5\" preserveAspectRatio=\" xMinYMax\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"540\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_4, lv_strlen(svg_image_4));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_4));
lv_svg_node_delete(svg);
const char * svg_image_5 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"xMidYMin\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_5, lv_strlen(svg_image_5));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_5));
lv_svg_node_delete(svg);
const char * svg_image_6 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"xMidYMax\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_6, lv_strlen(svg_image_6));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_6));
lv_svg_node_delete(svg);
const char * svg_image_7 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"xMaxYMin\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_7, lv_strlen(svg_image_7));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_7));
lv_svg_node_delete(svg);
const char * svg_image_8 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"xMaxYMid\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_8, lv_strlen(svg_image_8));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_8));
lv_svg_node_delete(svg);
const char * svg_image_9 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"360\" height=\"240\" preserveAspectRatio=\"xMaxYMax\" "
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"360\" height=\"240\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_9, lv_strlen(svg_image_9));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_9));
lv_svg_node_delete(svg);
const char * svg_image_10 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"50\" height=\"30\" preserveAspectRatio=\"meet\""
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"50\" height=\"30\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_10, lv_strlen(svg_image_10));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_10));
lv_svg_node_delete(svg);
const char * svg_image_11 = \
"<svg width=\"400\" height=\"400\">"
"<image x=\"0\" y=\"0\" width=\"50\" height=\"30\" preserveAspectRatio=\"xMidYMid slice\""
"xlink:href=\"cogwheel.bin\" />"
"<rect x=\"0\" y=\"0\" width=\"50\" height=\"30\" fill=\"none\" stroke=\"blue\"/></svg>";
svg = lv_svg_load_data(svg_image_11, lv_strlen(svg_image_11));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_11));
lv_svg_node_delete(svg);
const char * svg_image_12 = \
"<svg width=\"200\" height=\"200\">"
"<image x=\"90\" y=\"-65\" width=\"80\" height=\"90\" transform=\"rotate(45)\""
" xlink:href=\"cogwheel.bin\"/>"
"</svg>";
svg = lv_svg_load_data(svg_image_12, lv_strlen(svg_image_12));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_image_12));
lv_svg_node_delete(svg);
}
void test_draw_text(void)
{
lv_svg_render_init(&hal);
const char * svg_text_1 = \
"<svg><text x=20 y=60 font-family=\"sans-serif\" font-size=\"24\">"
"hello <tspan fill=\"red\" font-size=\"36\">all</tspan> world"
"</text></svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_text_1, lv_strlen(svg_text_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_text_1));
lv_svg_node_delete(svg);
const char * svg_text_2 = \
"<svg><defs><linearGradient id=\"g1\">"
"<stop offset=\"0.1\" stop-color=\"blue\"/>"
"<stop offset =\"0.8\" stop-color=\"red\"/>"
"</linearGradient></defs>"
"<text fill=\"url(#g1)\" x=20 y=60 font-family=\"sans-serif\" font-size=\"48px\" font-weight=\"bold\">"
"hello <tspan fill=\"green\" font-size=\"24px\">all</tspan> world"
"</text></svg>";
svg = lv_svg_load_data(svg_text_2, lv_strlen(svg_text_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_text_2));
lv_svg_node_delete(svg);
}
void test_draw_complex(void)
{
lv_svg_render_init(&hal);
const char * svg_com_1 = \
"<?xml version=\"1.0\"?><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
"version=\"1.2\" baseProfile=\"tiny\" width=\"10cm\" height=\"3cm\" viewBox=\"0 0 100 30\">"
"<desc>'use' with a 'transform' attribute</desc>"
"<defs><rect xml:id=\"MyRect\" x=\"0\" y=\"0\" width=\"60\" height=\"10\"/></defs>"
"<rect x=\".1\" y=\".1\" width=\"99.8\" height=\"29.8\" fill=\"none\" stroke=\"blue\" stroke-width=\".2\"/>"
"<use xlink:href=\"#MyRect\" fill=\"red\" transform=\"translate(20,2.5) rotate(10)\"/>"
"<use xlink:href=\"#MyRect\" fill=\"green\" transform=\"translate(20,2.5) rotate(-10)\"/>"
"</svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_com_1, lv_strlen(svg_com_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_1));
lv_svg_node_delete(svg);
const char * svg_com_2 = \
"<svg width=\"10cm\" height=\"3cm\" viewBox=\"0 0 100 30\">"
"<g id=g1><rect id=\"MyRect1\" x=\"0\" y=\"0\" width=\"60\" height=\"10\"/>"
"<rect id=\"MyRect2\" x=\"0\" y=\"12\" width=\"60\" height=\"10\"/>"
"</g><rect x=\".1\" y=\".1\" width=\"99.8\" height=\"29.8\""
" fill=\"none\" stroke=\"blue\" stroke-width=\".2\"/>"
"<use xlink:href=\"#g1\" fill=\"green\" transform=\"translate(20,2.5) rotate(-10)\"/>"
"<use xlink:href=\"#MyRect1\" fill=\"red\" transform=\"translate(20,2.5) rotate(10)\"/>"
"</svg>";
svg = lv_svg_load_data(svg_com_2, lv_strlen(svg_com_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_2));
lv_svg_node_delete(svg);
const char * svg_com_3 = \
"<svg width=5cm height=4cm viewBox=\"0 0 500 400\">"
"<rect fill=none stroke=blue stroke-width=1 x=1 y=1 width=498 height=398 />"
"<polyline fill=none stroke=#888888 stroke-width=1 points=\"100,200 100,100\" />"
"<polyline fill=none stroke=#888888 stroke-width=1 points=\"250,100 250,200\" />"
"<polyline fill=none stroke=#888888 stroke-width=1 points=\"250,200 250,300\" />"
"<polyline fill=none stroke=#888888 stroke-width=1 points=\"400,300 400,200\" />"
"<path fill=none stroke=red stroke-width=5 d=\"M100,200 C100,100 250,100 250,200"
" S400,300 400,200\" />"
"<circle fill=#888888 stroke=none stroke-width=2 cx=100 cy=200 r=10 />"
"<circle fill=#888888 stroke=none stroke-width=2 cx=250 cy=200 r=10 />"
"<circle fill=#888888 stroke=none stroke-width=2 cx=400 cy=200 r=10 />"
"<circle fill=#888888 stroke=none cx=100 cy=100 r=10 />"
"<circle fill=#888888 stroke=none cx=250 cy=100 r=10 />"
"<circle fill=#888888 stroke=none cx=400 cy=300 r=10 />"
"<circle fill=none stroke=blue stroke-width=4 cx=250 cy=300 r=9 />"
"<text font-size=22 font-family=\"Verdana\" x=25 y=70>M100,200 C100,100 250,100 250,200</text>"
"<text font-size=22 font-family=\"Verdana\" x=325 y=350>S400,300 400,200</text>"
"</svg>";
svg = lv_svg_load_data(svg_com_3, lv_strlen(svg_com_3));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_3));
lv_svg_node_delete(svg);
const char * svg_com_4 = \
"<?xml version='1.0'?>"
"<svg width='12cm' height='4cm' viewBox='0 0 1200 400' "
"xmlns='http://www.w3.org/2000/svg' version='1.2' baseProfile='tiny'>"
"<desc>Example rect02 - rounded rectangles</desc>"
"<!-- Show outline of canvas using 'rect' element -->"
"<rect x='1' y='1' width='1198' height='398'"
" fill='none' stroke='blue' stroke-width='2'/>"
"<rect x='100' y='100' width='400' height='200' rx='50'"
" fill='green' />"
"<g transform='translate(700 210) rotate(-30)'>"
"<rect x='0' y='0' width='400' height='200' rx='50'"
" fill='none' stroke='purple' stroke-width='30' />"
"</g></svg>";
svg = lv_svg_load_data(svg_com_4, lv_strlen(svg_com_4));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_4));
lv_svg_node_delete(svg);
const char * svg_com_5 = \
"<svg width='12cm' height='4cm' viewBox='0 0 1200 400'>"
"<rect x='1' y='1' width='1198' height='398' "
" fill='none' stroke='blue' stroke-width='2' />"
"<g transform='translate(300 200)'>"
"<ellipse rx='250' ry='100' "
"fill='red' /></g>"
"<ellipse transform='translate(900 200) rotate(-30)' "
"rx='250' ry='100' fill='none' stroke='blue' stroke-width='20' />"
"</svg>";
svg = lv_svg_load_data(svg_com_5, lv_strlen(svg_com_5));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_5));
lv_svg_node_delete(svg);
const char * svg_com_6 = \
"<svg width='12cm' height='4cm' viewBox='0 0 1200 400'>"
"<rect x='1' y='1' width='1198' height='398'"
" fill='none' stroke='blue' stroke-width='2' />"
"<g stroke='green' >"
"<line x1='100' y1='300' x2='300' y2='100'"
" stroke-width='5' />"
"<line x1='300' y1='300' x2='500' y2='100'"
" stroke-width='10' />"
"<line x1='500' y1='300' x2='700' y2='100'"
" stroke-width='15' />"
"<line x1='700' y1='300' x2='900' y2='100'"
" stroke-width='20' />"
"<line x1='900' y1='300' x2='1100' y2='100'"
" stroke-width='25' />"
"</g></svg>";
svg = lv_svg_load_data(svg_com_6, lv_strlen(svg_com_6));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_6));
lv_svg_node_delete(svg);
const char * svg_com_7 = \
"<svg width='12cm' height='4cm' viewBox='0 0 1200 400'>"
"<rect x='1' y='1' width='1198' height='398'"
" fill='none' stroke='blue' stroke-width='2' />"
"<polyline fill='none' stroke='blue' stroke-width='10' "
" points='50,375"
" 150,375 150,325 250,325 250,375"
" 350,375 350,250 450,250 450,375"
" 550,375 550,175 650,175 650,375"
" 750,375 750,100 850,100 850,375"
" 950,375 950,25 1050,25 1050,375"
" 1150,375' />"
"</svg>";
svg = lv_svg_load_data(svg_com_7, lv_strlen(svg_com_7));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_7));
lv_svg_node_delete(svg);
const char * svg_com_8 = \
"<svg xmlns='http://www.w3.org/2000/svg' "
"width='100%' height='100%' viewBox='0 0 400 400' "
"direction='rtl' xml:lang='fa'>"
"<text x='200' y='200' font-size='20'>داستان SVG Tiny 1.2 طولا ني است.</text>"
"</svg>";
svg = lv_svg_load_data(svg_com_8, lv_strlen(svg_com_8));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_com_8));
lv_svg_node_delete(svg);
}
void test_draw_svg(void)
{
const char * svg_viewport_1 = \
"<svg width=\"300px\" height=\"300px\" viewport-fill-opacity=\"0.5\" viewport-fill=\"blue\"></svg>";
lv_svg_node_t * svg = lv_svg_load_data(svg_viewport_1, lv_strlen(svg_viewport_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_viewport_1));
lv_svg_node_delete(svg);
const char * svg_viewport_2 = \
"<svg width=\"100px\" height=\"100px\" viewport-fill=\"green\"></svg>";
svg = lv_svg_load_data(svg_viewport_2, lv_strlen(svg_viewport_2));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_viewport_2));
lv_svg_node_delete(svg);
const char * svg_viewport_3 = \
"<svg width=\"300\" height=\"200\" viewBox=\"100 0 1500 1000\""
"preserveAspectRatio=\"none\">"
"<rect x=\"0\" y=\"0\" width=\"1500\" height=\"1000\""
"fill=\"yellow\" stroke=\"blue\" stroke-width=\"12\"/>"
"<path fill=\"red\" d=\"M 750,100 L 250,900 L 1250,900 z\"/>"
"<text x=\"100\" y=\"600\" font-size=\"200\" font-family=\"Verdana\">"
"Stretch to fit</text>"
"</svg>";
svg = lv_svg_load_data(svg_viewport_3, lv_strlen(svg_viewport_3));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
draw_svg(svg);
draw_snapshot(SNAPSHOT_NAME(svg_viewport_3));
lv_svg_node_delete(svg);
}
#else
void test_draw_svg(void)
{
;
}
#endif
#endif
@@ -0,0 +1,447 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_rotate90_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[2 * 3] = {0};
uint16_t expectedArray[2 * 3] = {
0x3330, 0x6660,
0x2220, 0x5550,
0x1110, 0x4440,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
2 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[3 * 2] = {0};
uint16_t expectedArray[3 * 2] = {
0x6660, 0x5550, 0x4440,
0x3330, 0x2220, 0x1110,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
3 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[2 * 3] = {0};
uint16_t expectedArray[2 * 3] = {
0x4440, 0x1110,
0x5550, 0x2220,
0x6660, 0x3330
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
2 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate90_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[2 * 3 * 3] = {0};
uint8_t expectedArray[2 * 3 * 3] = {
0x33, 0x3A, 0x3B, 0x66, 0x6A, 0x6B,
0x22, 0x2A, 0x2B, 0x55, 0x5A, 0x5B,
0x11, 0x1A, 0x1B, 0x44, 0x4A, 0x4B,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * 3,
2 * 3,
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[3 * 2 * 3] = {0};
uint8_t expectedArray[3 * 2 * 3] = {
0x66, 0x6A, 0x6B, 0x55, 0x5A, 0x5B, 0x44, 0x4A, 0x4B,
0x33, 0x3A, 0x3B, 0x22, 0x2A, 0x2B, 0x11, 0x1A, 0x1B
};
lv_draw_sw_rotate(srcArray, dstArray,
2, 3,
2 * 3,
2 * 3,
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[2 * 3 * 3] = {0};
uint8_t expectedArray[2 * 3 * 3] = {
0x44, 0x4A, 0x4B, 0x11, 0x1A, 0x1B,
0x55, 0x5A, 0x5B, 0x22, 0x2A, 0x2B,
0x66, 0x6A, 0x6B, 0x33, 0x3A, 0x3B,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * 3,
2 * 3,
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate90_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0x111A1B1C, 0x222A2B2C, 0x333A3B3C,
0x444A4B4C, 0x555A5B5C, 0x666A6B6C
};
uint32_t dstArray[2 * 3] = {0};
uint32_t expectedArray[2 * 3] = {
0x333A3B3C, 0x666A6B6C,
0x222A2B2C, 0x555A5B5C,
0x111A1B1C, 0x444A4B4C,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0xFF0000FF, 0xFF00FF00, // Row 1: Red, Green
0xFFFF0000, 0xFFFFFFFF, // Row 2: Blue, White
0xFF00FFFF, 0xFFFFFF00 // Row 3: Cyan, Yellow
};
uint32_t dstArray[3 * 2] = {0};
uint32_t expectedArray[3 * 2] = {
0xFFFFFF00, 0xFF00FFFF, // Rotated Row 1
0xFFFFFFFF, 0xFFFF0000, // Rotated Row 2
0xFF00FF00, 0xFF0000FF // Rotated Row 3
};
lv_draw_sw_rotate(srcArray, dstArray,
2, 3,
2 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0x111A1B1C, 0x222A2B2C, 0x333A3B3C,
0x444A4B4C, 0x555A5B5C, 0x666A6B6C
};
uint32_t dstArray[2 * 3] = {0};
uint32_t expectedArray[2 * 3] = {
0x444A4B4C, 0x111A1B1C,
0x555A5B5C, 0x222A2B2C,
0x666A6B6C, 0x333A3B3C
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate90_L8(void)
{
uint8_t srcArray[3 * 2] = {
0x11, 0x22, 0x33,
0x44, 0x55, 0x66
};
uint8_t dstArray[2 * 3] = {0};
uint8_t expectedArray[2 * 3] = {
0x33, 0x66,
0x22, 0x55,
0x11, 0x44,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint8_t),
2 * sizeof(uint8_t),
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_L8);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_L8(void)
{
uint8_t srcArray[3 * 2] = {
0x11, 0x22, 0x33,
0x44, 0x55, 0x66
};
uint8_t dstArray[3 * 2] = {0};
uint8_t expectedArray[3 * 2] = {
0x66, 0x55, 0x44,
0x33, 0x22, 0x11,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint8_t),
3 * sizeof(uint8_t),
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_L8);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_L8(void)
{
uint8_t srcArray[3 * 2] = {
0x11, 0x22, 0x33,
0x44, 0x55, 0x66
};
uint8_t dstArray[2 * 3] = {0};
uint8_t expectedArray[2 * 3] = {
0x44, 0x11,
0x55, 0x22,
0x66, 0x33
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint8_t),
2 * sizeof(uint8_t),
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_L8);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_invert(void)
{
uint8_t expected_buf[10] = {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6};
/*Aligned start and aligned end*/
uint8_t buf1[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
lv_draw_sw_i1_invert(buf1, 8);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_buf, buf1, 8);
/*Unaligned start and unaligned end*/
uint8_t buf2[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
lv_draw_sw_i1_invert(&buf2[3], 6);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&expected_buf[3], &buf2[3], 6);
/*Small buffer*/
uint8_t buf3[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
lv_draw_sw_i1_invert(&buf3[3], 2);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&expected_buf[3], &buf3[3], 2);
}
void test_vtile_small(void)
{
uint8_t src_buf[8] = {0x3C, 0x42, 0x81, 0xA5, 0x81, 0x81, 0x42, 0x3C};
uint8_t dst_buf[8] = {0};
uint8_t expected_buf_msb[8] = {0x3C, 0x42, 0x91, 0x81, 0x81, 0x91, 0x42, 0x3C};
uint8_t expected_buf_lsb[8] = {0x3C, 0x42, 0x89, 0x81, 0x81, 0x89, 0x42, 0x3C};
lv_draw_sw_i1_convert_to_vtiled(src_buf, 8, 8, 8, dst_buf, 8, false);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_buf_msb, dst_buf, 8);
lv_draw_sw_i1_convert_to_vtiled(src_buf, 8, 8, 8, dst_buf, 8, true);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_buf_lsb, dst_buf, 8);
}
void test_vtile_rectangular(void)
{
uint8_t src_buf[80] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x80, 0x83, 0xE1, 0x00,
0x40, 0x80, 0x84, 0x01, 0x00,
0x40, 0x41, 0x08, 0x01, 0x00,
0x40, 0x41, 0x10, 0x01, 0x00,
0x40, 0x41, 0x20, 0x01, 0x00,
0x40, 0x41, 0x20, 0x01, 0x00,
0x40, 0x41, 0x20, 0x01, 0x00,
0x40, 0x41, 0x20, 0x01, 0x00,
0x40, 0x23, 0x20, 0x01, 0x00,
0x40, 0x22, 0x20, 0xF1, 0x00,
0x40, 0x14, 0x20, 0x11, 0x00,
0x40, 0x14, 0x10, 0x11, 0x00,
0x40, 0x08, 0x08, 0x11, 0x00,
0x7E, 0x08, 0x07, 0xF1, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t dst_buf[80] = {0};
uint8_t expected_buf_msb[80] = {
0x00, 0x00,
0x7F, 0xFE,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x00,
0x60, 0x00,
0x1F, 0x80,
0x00, 0x60,
0x00, 0x18,
0x00, 0x06,
0x00, 0x18,
0x00, 0x60,
0x3F, 0x80,
0xC0, 0x00,
0x00, 0x00,
0x07, 0xF0,
0x08, 0x08,
0x10, 0x04,
0x20, 0x02,
0x80, 0x02,
0x80, 0x02,
0x80, 0x22,
0x80, 0x22,
0x80, 0x22,
0x00, 0x3E,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0xFF, 0xFE,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x02,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};
uint8_t expected_buf_lsb[80] = {
0x00, 0x00,
0xFE, 0x7F,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x00,
0x06, 0x00,
0xF8, 0x01,
0x00, 0x06,
0x00, 0x18,
0x00, 0x60,
0x00, 0x18,
0x00, 0x06,
0xF8, 0x03,
0x06, 0x00,
0x00, 0x00,
0xE0, 0x0F,
0x10, 0x10,
0x08, 0x20,
0x04, 0x40,
0x02, 0x40,
0x02, 0x40,
0x02, 0x44,
0x02, 0x44,
0x02, 0x44,
0x00, 0x7C,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0xFE, 0x7F,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x40,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};
lv_draw_sw_i1_convert_to_vtiled(src_buf, 80, 40, 16, dst_buf, 80, false);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_buf_msb, dst_buf, 8);
lv_draw_sw_i1_convert_to_vtiled(src_buf, 80, 40, 16, dst_buf, 80, true);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected_buf_lsb, dst_buf, 8);
}
#endif
@@ -0,0 +1,405 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
/*Bypassing resolution check*/
#define TEST_DISPLAY_ROTATION_ASSERT_EQUAL_SCREENSHOT(path) TEST_ASSERT_MESSAGE(lv_test_screenshot_compare(path), path);
#ifndef NON_AMD64_BUILD
#define EXT_NAME ".lp64.png"
#else
#define EXT_NAME ".lp32.png"
#endif
typedef void (*draw_cb_t)(lv_layer_t *, const lv_matrix_t *);
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void draw_shapes(lv_layer_t * layer, const lv_matrix_t * transform)
{
lv_vector_dsc_t * ctx = lv_vector_dsc_create(layer);
lv_vector_dsc_set_transform(ctx, transform);
lv_area_t rect = {0, 0, 640, 480};
lv_vector_dsc_set_fill_color(ctx, lv_color_white());
rect = lv_matrix_transform_area(transform, &rect);
lv_vector_clear_area(ctx, &rect);
lv_vector_path_t * path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_MEDIUM);
lv_area_t rect1 = {50, 50, 150, 150};
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_path_clear(path);
lv_vector_path_append_rect(path, &rect1, 0, 0);
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0xff, 0x00, 0x00));
lv_vector_dsc_add_path(ctx, path);
lv_vector_path_clear(path);
lv_vector_path_append_rect(path, &rect1, 20, 20);
lv_vector_dsc_translate(ctx, 150, 0);
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0x00, 0x00, 0xff));
lv_vector_dsc_add_path(ctx, path);
lv_fpoint_t pc = {100, 100};
lv_vector_path_clear(path);
lv_vector_path_append_circle(path, &pc, 50, 50);
lv_vector_dsc_translate(ctx, 150, 0);
lv_vector_dsc_set_fill_color32(ctx, lv_color_to_32(lv_color_make(0x00, 0xff, 0x00), 0x80));
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_dsc_translate(ctx, 0, 150);
lv_grad_stop_t stops[2];
lv_memzero(stops, sizeof(stops));
stops[0].color = lv_color_hex(0xffffff);
stops[0].opa = LV_OPA_COVER;
stops[0].frac = 0;
stops[1].color = lv_color_hex(0x000000);
stops[1].opa = LV_OPA_COVER;
stops[1].frac = 255;
lv_matrix_t mt;
lv_matrix_identity(&mt);
lv_vector_dsc_set_fill_transform(ctx, &mt);
lv_vector_dsc_set_fill_radial_gradient(ctx, 100, 100, 50);
lv_vector_dsc_set_fill_gradient_color_stops(ctx, stops, 2);
lv_vector_dsc_set_fill_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_PAD);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_dsc_translate(ctx, 150, 150);
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
LV_IMAGE_DECLARE(test_image_cogwheel_argb8888);
img_dsc.header = test_image_cogwheel_argb8888.header;
img_dsc.src = &test_image_cogwheel_argb8888;
lv_vector_dsc_set_fill_image(ctx, &img_dsc);
lv_matrix_identity(&mt);
lv_matrix_translate(&mt, 50, 50);
//lv_matrix_rotate(&mt, 45);
//lv_matrix_scale(&mt, 1.5f, 1.5f);
lv_matrix_translate(&mt, -50, -50);
lv_vector_dsc_set_fill_transform(ctx, &mt);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_dsc_translate(ctx, 300, 150);
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0xff, 0x00, 0x00));
lv_vector_dsc_add_path(ctx, path);
lv_vector_path_clear(path);
lv_vector_path_append_rect(path, &rect1, 20, 20);
lv_area_t rect2 = {80, 80, 120, 120};
lv_vector_path_append_rect(path, &rect2, 15, 15);
lv_vector_dsc_translate(ctx, 50, 0);
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0x00, 0x80, 0xff));
lv_vector_dsc_set_blend_mode(ctx, LV_VECTOR_BLEND_MULTIPLY);
lv_vector_dsc_set_fill_rule(ctx, LV_VECTOR_FILL_EVENODD);
lv_vector_dsc_add_path(ctx, path);
lv_vector_path_clear(path);
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_dsc_set_blend_mode(ctx, LV_VECTOR_BLEND_SRC_OVER);
rect = (lv_area_t) {
500, 50, 550, 100
};
lv_vector_dsc_set_fill_color(ctx, lv_color_lighten(lv_color_black(), 50));
rect = lv_matrix_transform_area(transform, &rect);
lv_vector_clear_area(ctx, &rect); // clear screen
lv_fpoint_t p = {500, 100}; /* Center */
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0x00, 0xff, 0xff));
lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_COVER);
lv_vector_dsc_set_stroke_width(ctx, 2.0f);
lv_vector_dsc_set_stroke_dash(ctx, NULL, 0);
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_TRANSP);
lv_vector_path_move_to(path, &p);
lv_fpoint_t temp = {p.x + 50, p.y};
lv_vector_path_line_to(path, &temp);
lv_vector_path_append_arc(path, &p, 50, 0, -90, false);
lv_vector_path_line_to(path, &p);
lv_vector_path_close(path);
lv_vector_dsc_add_path(ctx, path);
/* Below code has same effect as above one but with solid fill */
lv_vector_dsc_set_fill_color(ctx, lv_color_make(0xFF, 0x00, 0x00));
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_COVER);
lv_vector_path_clear(path);
lv_vector_path_append_arc(path, &p, 50, 45, 45, true);
lv_vector_dsc_add_path(ctx, path); // draw a path
/* Test image filling with absolute coordinates */
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_dsc_set_fill_units(ctx, LV_VECTOR_FILL_UNITS_USER_SPACE_ON_USE);
lv_vector_dsc_set_fill_image(ctx, &img_dsc);
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_50);
lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_TRANSP);
lv_matrix_identity(&mt);
lv_matrix_translate(&mt, 50, 350);
lv_vector_dsc_set_fill_transform(ctx, &mt);
lv_vector_path_clear(path);
/* Aligned with translate. Image resolution is 100x100, cropped to 50% of width and height */
lv_area_t img_area = {50, 350, 50 + 50, 350 + 50};
lv_vector_path_append_rect(path, &img_area, 0, 0);
lv_vector_dsc_add_path(ctx, path);
lv_draw_vector(ctx);
lv_vector_path_delete(path);
lv_vector_dsc_delete(ctx);
}
static void draw_lines(lv_layer_t * layer, const lv_matrix_t * transform)
{
lv_vector_dsc_t * ctx = lv_vector_dsc_create(layer);
lv_vector_dsc_set_transform(ctx, transform);
lv_area_t rect = {0, 0, 640, 480};
lv_vector_dsc_set_fill_color(ctx, lv_color_white());
rect = lv_matrix_transform_area(transform, &rect);
lv_vector_clear_area(ctx, &rect);
lv_vector_path_t * path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_MEDIUM);
lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_COVER);
lv_vector_dsc_set_fill_opa(ctx, LV_OPA_0);
lv_fpoint_t pts1[] = {{50, 50}, {400, 50}};
lv_vector_path_clear(path);
lv_vector_path_move_to(path, &pts1[0]);
lv_vector_path_line_to(path, &pts1[1]);
lv_vector_dsc_add_path(ctx, path);
lv_fpoint_t pts2[] = {{50, 80}, {400, 80}};
lv_vector_path_clear(path);
lv_vector_path_move_to(path, &pts2[0]);
lv_vector_path_line_to(path, &pts2[1]);
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0xff, 0x00, 0x00));
lv_vector_dsc_set_stroke_width(ctx, 3.0f);
lv_vector_dsc_add_path(ctx, path);
lv_fpoint_t pts3[] = {{50, 120}, {400, 120}};
lv_vector_path_clear(path);
lv_vector_path_move_to(path, &pts3[0]);
lv_vector_path_line_to(path, &pts3[1]);
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0x00, 0xff, 0x00));
lv_vector_dsc_set_stroke_width(ctx, 5.0f);
float dashes[] = {10, 15, 20, 12};
lv_vector_dsc_set_stroke_dash(ctx, dashes, 4);
lv_vector_dsc_add_path(ctx, path);
lv_fpoint_t pts4[] = {{100, 150}, {50, 250}, {150, 250}};
lv_vector_path_clear(path);
lv_vector_path_move_to(path, &pts4[0]);
lv_vector_path_line_to(path, &pts4[1]);
lv_vector_path_line_to(path, &pts4[2]);
lv_vector_dsc_set_stroke_color(ctx, lv_color_make(0x00, 0x00, 0x00));
lv_vector_dsc_set_stroke_width(ctx, 10.0f);
lv_vector_dsc_set_stroke_dash(ctx, NULL, 0);
lv_vector_dsc_set_stroke_join(ctx, LV_VECTOR_STROKE_JOIN_MITER);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_translate(ctx, 150, 0);
lv_vector_dsc_set_stroke_join(ctx, LV_VECTOR_STROKE_JOIN_BEVEL);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_translate(ctx, 150, 0);
lv_vector_dsc_set_stroke_join(ctx, LV_VECTOR_STROKE_JOIN_ROUND);
lv_vector_dsc_add_path(ctx, path);
lv_fpoint_t pts5[] = {{50, 300}, {150, 300}};
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_path_clear(path);
lv_vector_path_move_to(path, &pts5[0]);
lv_vector_path_line_to(path, &pts5[1]);
lv_vector_dsc_set_stroke_cap(ctx, LV_VECTOR_STROKE_CAP_BUTT);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_translate(ctx, 0, 40);
lv_vector_dsc_set_stroke_cap(ctx, LV_VECTOR_STROKE_CAP_SQUARE);
lv_vector_dsc_add_path(ctx, path);
lv_vector_dsc_translate(ctx, 0, 40);
lv_vector_dsc_set_stroke_cap(ctx, LV_VECTOR_STROKE_CAP_ROUND);
lv_vector_dsc_add_path(ctx, path);
lv_area_t rect1 = {250, 300, 350, 400};
lv_vector_dsc_set_transform(ctx, transform);
lv_vector_path_clear(path);
lv_vector_path_append_rect(path, &rect1, 0, 0);
lv_grad_stop_t stops[2];
lv_memzero(stops, sizeof(stops));
stops[0].color = lv_color_hex(0xff0000);
stops[0].opa = LV_OPA_COVER;
stops[0].frac = 0;
stops[1].color = lv_color_hex(0x00ff00);
stops[1].opa = LV_OPA_COVER;
stops[1].frac = 255;
lv_matrix_t mt;
lv_matrix_identity(&mt);
lv_matrix_rotate(&mt, 5);
lv_matrix_translate(&mt, 20, 20);
lv_vector_dsc_set_stroke_transform(ctx, &mt);
lv_vector_dsc_set_stroke_join(ctx, LV_VECTOR_STROKE_JOIN_MITER);
lv_vector_dsc_set_stroke_linear_gradient(ctx, 250, 300, 350, 300);
lv_vector_dsc_set_stroke_gradient_color_stops(ctx, stops, 2);
lv_vector_dsc_set_stroke_gradient_spread(ctx, LV_VECTOR_GRADIENT_SPREAD_REFLECT);
lv_vector_dsc_add_path(ctx, path); // draw a path
lv_draw_vector(ctx);
lv_vector_path_delete(path);
lv_vector_dsc_delete(ctx);
}
static void canvas_draw(const char * name, draw_cb_t draw_cb)
{
LV_UNUSED(name);
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_draw_buf_t * draw_buf = lv_draw_buf_create(640, 480, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO);
TEST_ASSERT_NOT_NULL(draw_buf);
lv_draw_buf_clear(draw_buf, NULL);
lv_canvas_set_draw_buf(canvas, draw_buf);
lv_canvas_fill_bg(canvas, lv_color_make(0xff, 0xff, 0xff), 255);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_matrix_t matrix;
lv_matrix_identity(&matrix);
draw_cb(&layer, &matrix);
lv_canvas_finish_layer(canvas, &layer);
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "draw/vector_%s" EXT_NAME, name);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
lv_image_cache_drop(draw_buf);
lv_draw_buf_destroy(draw_buf);
lv_obj_delete(canvas);
}
void test_transform(void)
{
lv_matrix_t matrix;
lv_matrix_identity(&matrix);
lv_matrix_translate(&matrix, 100, 100);
lv_fpoint_t p = {10, 10};
lv_matrix_transform_point(&matrix, &p);
TEST_ASSERT_EQUAL_FLOAT(110.0f, p.x);
TEST_ASSERT_EQUAL_FLOAT(110.0f, p.y);
lv_vector_path_t * path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_MEDIUM);
lv_vector_path_move_to(path, &p);
lv_fpoint_t p2 = {20, 20};
lv_vector_path_line_to(path, &p2);
lv_matrix_transform_path(&matrix, path);
lv_fpoint_t * pt = lv_array_at(&path->points, 0);
TEST_ASSERT_EQUAL_FLOAT(210.0f, pt[0].x);
TEST_ASSERT_EQUAL_FLOAT(210.0f, pt[0].y);
TEST_ASSERT_EQUAL_FLOAT(120.0f, pt[1].x);
TEST_ASSERT_EQUAL_FLOAT(120.0f, pt[1].y);
lv_vector_path_delete(path);
}
void test_draw_lines(void)
{
canvas_draw("draw_lines", draw_lines);
}
void test_draw_shapes(void)
{
canvas_draw("draw_shapes", draw_shapes);
}
static void event_cb(lv_event_t * e)
{
lv_layer_t * layer = lv_event_get_layer(e);
lv_obj_t * obj = lv_event_get_current_target_obj(e);
draw_cb_t draw_cb = (draw_cb_t)(lv_uintptr_t)lv_event_get_user_data(e);
LV_ASSERT_NULL(draw_cb);
lv_matrix_t matrix;
lv_matrix_identity(&matrix);
lv_matrix_translate(&matrix, obj->coords.x1, obj->coords.y1);
draw_cb(layer, &matrix);
}
static void draw_during_rendering(const char * name, draw_cb_t draw_cb)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, lv_pct(90), lv_pct(90));
lv_obj_center(obj);
lv_obj_add_event_cb(obj, event_cb, LV_EVENT_DRAW_MAIN, (void *)(lv_uintptr_t)draw_cb);
char fn_buf[128];
lv_snprintf(fn_buf, sizeof(fn_buf), "draw/vector_draw_%s_during_rendering" EXT_NAME, name);
TEST_DISPLAY_ROTATION_ASSERT_EQUAL_SCREENSHOT(fn_buf);
lv_obj_delete(obj);
}
void test_draw_during_rendering(void)
{
draw_during_rendering("shapes", draw_shapes);
draw_during_rendering("lines", draw_lines);
}
void test_draw_display_matrix_rotation(void)
{
#if LV_DRAW_TRANSFORM_USE_MATRIX
lv_display_t * disp = lv_display_get_default();
lv_display_set_matrix_rotation(disp, true);
TEST_ASSERT_TRUE(lv_display_get_matrix_rotation(disp));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_0);
draw_during_rendering("shapes_disp_rotation_0", draw_shapes);
draw_during_rendering("lines_disp_rotation_0", draw_lines);
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90);
draw_during_rendering("shapes_disp_rotation_90", draw_shapes);
draw_during_rendering("lines_disp_rotation_90", draw_lines);
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_180);
draw_during_rendering("shapes_disp_rotation_180", draw_shapes);
draw_during_rendering("lines_disp_rotation_180", draw_lines);
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
draw_during_rendering("shapes_disp_rotation_270", draw_shapes);
draw_during_rendering("lines_disp_rotation_270", draw_lines);
lv_display_set_matrix_rotation(disp, false);
TEST_ASSERT_FALSE(lv_display_get_matrix_rotation(disp));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_0);
draw_during_rendering("shapes_disp_rotation_0", draw_shapes);
draw_during_rendering("lines_disp_rotation_0", draw_lines);
#else
TEST_PASS();
#endif
}
#endif
@@ -0,0 +1,309 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <stdio.h>
static const char * color_formats[] = {
"I1", /*7 I1*/
"I2", /*8 I2*/
"I4", /*9 I4*/
"I8", /*10 I8*/
"A1", /*11 A1*/
"A2", /*12 A2*/
"A4", /*13 A4*/
"A8", /*14 A8*/
"RGB565A8", /*20 RGB565A8*/
"RGB565", /*18 RGB565*/
"RGB888", /*15 RGB888*/
"XRGB8888", /*17 XRGB8888*/
"ARGB8888", /*16 ARGB8888*/
};
static const char * compressions[] = {
"UNCOMPRESSED",
#if LV_BIN_DECODER_RAM_LOAD == 1
"RLE",
"LZ4"
#endif
};
static const char * modes[] = {
"simple",
"recolor",
"rotate",
"rotate_recolor",
};
static const int stride_align[] = {
1,
64,
};
LV_IMAGE_DECLARE(test_I1_NONE_align1);
LV_IMAGE_DECLARE(test_I2_NONE_align1);
LV_IMAGE_DECLARE(test_I4_NONE_align1);
LV_IMAGE_DECLARE(test_I8_NONE_align1);
LV_IMAGE_DECLARE(test_A1_NONE_align1);
LV_IMAGE_DECLARE(test_A2_NONE_align1);
LV_IMAGE_DECLARE(test_A4_NONE_align1);
LV_IMAGE_DECLARE(test_A8_NONE_align1);
LV_IMAGE_DECLARE(test_RGB565A8_NONE_align1);
LV_IMAGE_DECLARE(test_RGB565_NONE_align1);
LV_IMAGE_DECLARE(test_RGB888_NONE_align1);
LV_IMAGE_DECLARE(test_XRGB8888_NONE_align1);
LV_IMAGE_DECLARE(test_ARGB8888_NONE_align1);
LV_IMAGE_DECLARE(test_I1_RLE_align1);
LV_IMAGE_DECLARE(test_I2_RLE_align1);
LV_IMAGE_DECLARE(test_I4_RLE_align1);
LV_IMAGE_DECLARE(test_I8_RLE_align1);
LV_IMAGE_DECLARE(test_A1_RLE_align1);
LV_IMAGE_DECLARE(test_A2_RLE_align1);
LV_IMAGE_DECLARE(test_A4_RLE_align1);
LV_IMAGE_DECLARE(test_A8_RLE_align1);
LV_IMAGE_DECLARE(test_RGB565A8_RLE_align1);
LV_IMAGE_DECLARE(test_RGB565_RLE_align1);
LV_IMAGE_DECLARE(test_RGB888_RLE_align1);
LV_IMAGE_DECLARE(test_XRGB8888_RLE_align1);
LV_IMAGE_DECLARE(test_ARGB8888_RLE_align1);
LV_IMAGE_DECLARE(test_I1_LZ4_align1);
LV_IMAGE_DECLARE(test_I2_LZ4_align1);
LV_IMAGE_DECLARE(test_I4_LZ4_align1);
LV_IMAGE_DECLARE(test_I8_LZ4_align1);
LV_IMAGE_DECLARE(test_A1_LZ4_align1);
LV_IMAGE_DECLARE(test_A2_LZ4_align1);
LV_IMAGE_DECLARE(test_A4_LZ4_align1);
LV_IMAGE_DECLARE(test_A8_LZ4_align1);
LV_IMAGE_DECLARE(test_RGB565A8_LZ4_align1);
LV_IMAGE_DECLARE(test_RGB565_LZ4_align1);
LV_IMAGE_DECLARE(test_RGB888_LZ4_align1);
LV_IMAGE_DECLARE(test_XRGB8888_LZ4_align1);
LV_IMAGE_DECLARE(test_ARGB8888_LZ4_align1);
LV_IMAGE_DECLARE(test_I1_NONE_align64);
LV_IMAGE_DECLARE(test_I2_NONE_align64);
LV_IMAGE_DECLARE(test_I4_NONE_align64);
LV_IMAGE_DECLARE(test_I8_NONE_align64);
LV_IMAGE_DECLARE(test_A1_NONE_align64);
LV_IMAGE_DECLARE(test_A2_NONE_align64);
LV_IMAGE_DECLARE(test_A4_NONE_align64);
LV_IMAGE_DECLARE(test_A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565_NONE_align64);
LV_IMAGE_DECLARE(test_RGB888_NONE_align64);
LV_IMAGE_DECLARE(test_XRGB8888_NONE_align64);
LV_IMAGE_DECLARE(test_ARGB8888_NONE_align64);
LV_IMAGE_DECLARE(test_I1_RLE_align64);
LV_IMAGE_DECLARE(test_I2_RLE_align64);
LV_IMAGE_DECLARE(test_I4_RLE_align64);
LV_IMAGE_DECLARE(test_I8_RLE_align64);
LV_IMAGE_DECLARE(test_A1_RLE_align64);
LV_IMAGE_DECLARE(test_A2_RLE_align64);
LV_IMAGE_DECLARE(test_A4_RLE_align64);
LV_IMAGE_DECLARE(test_A8_RLE_align64);
LV_IMAGE_DECLARE(test_RGB565A8_RLE_align64);
LV_IMAGE_DECLARE(test_RGB565_RLE_align64);
LV_IMAGE_DECLARE(test_RGB888_RLE_align64);
LV_IMAGE_DECLARE(test_XRGB8888_RLE_align64);
LV_IMAGE_DECLARE(test_ARGB8888_RLE_align64);
LV_IMAGE_DECLARE(test_I1_LZ4_align64);
LV_IMAGE_DECLARE(test_I2_LZ4_align64);
LV_IMAGE_DECLARE(test_I4_LZ4_align64);
LV_IMAGE_DECLARE(test_I8_LZ4_align64);
LV_IMAGE_DECLARE(test_A1_LZ4_align64);
LV_IMAGE_DECLARE(test_A2_LZ4_align64);
LV_IMAGE_DECLARE(test_A4_LZ4_align64);
LV_IMAGE_DECLARE(test_A8_LZ4_align64);
LV_IMAGE_DECLARE(test_RGB565A8_LZ4_align64);
LV_IMAGE_DECLARE(test_RGB565_LZ4_align64);
LV_IMAGE_DECLARE(test_RGB888_LZ4_align64);
LV_IMAGE_DECLARE(test_XRGB8888_LZ4_align64);
LV_IMAGE_DECLARE(test_ARGB8888_LZ4_align64);
static const void * c_array_images[sizeof(stride_align)][sizeof(compressions)][sizeof(color_formats)] = {
{
{
&test_I1_NONE_align1,
&test_I2_NONE_align1,
&test_I4_NONE_align1,
&test_I8_NONE_align1,
&test_A1_NONE_align1,
&test_A2_NONE_align1,
&test_A4_NONE_align1,
&test_A8_NONE_align1,
&test_RGB565A8_NONE_align1,
&test_RGB565_NONE_align1,
&test_RGB888_NONE_align1,
&test_XRGB8888_NONE_align1,
&test_ARGB8888_NONE_align1,
},
{
&test_I1_RLE_align1,
&test_I2_RLE_align1,
&test_I4_RLE_align1,
&test_I8_RLE_align1,
&test_A1_RLE_align1,
&test_A2_RLE_align1,
&test_A4_RLE_align1,
&test_A8_RLE_align1,
&test_RGB565A8_RLE_align1,
&test_RGB565_RLE_align1,
&test_RGB888_RLE_align1,
&test_XRGB8888_RLE_align1,
&test_ARGB8888_RLE_align1,
},
{
&test_I1_LZ4_align1,
&test_I2_LZ4_align1,
&test_I4_LZ4_align1,
&test_I8_LZ4_align1,
&test_A1_LZ4_align1,
&test_A2_LZ4_align1,
&test_A4_LZ4_align1,
&test_A8_LZ4_align1,
&test_RGB565A8_LZ4_align1,
&test_RGB565_LZ4_align1,
&test_RGB888_LZ4_align1,
&test_XRGB8888_LZ4_align1,
&test_ARGB8888_LZ4_align1,
}
},
{
{
&test_I1_NONE_align64,
&test_I2_NONE_align64,
&test_I4_NONE_align64,
&test_I8_NONE_align64,
&test_A1_NONE_align64,
&test_A2_NONE_align64,
&test_A4_NONE_align64,
&test_A8_NONE_align64,
&test_RGB565A8_NONE_align64,
&test_RGB565_NONE_align64,
&test_RGB888_NONE_align64,
&test_XRGB8888_NONE_align64,
&test_ARGB8888_NONE_align64,
},
{
&test_I1_RLE_align64,
&test_I2_RLE_align64,
&test_I4_RLE_align64,
&test_I8_RLE_align64,
&test_A1_RLE_align64,
&test_A2_RLE_align64,
&test_A4_RLE_align64,
&test_A8_RLE_align64,
&test_RGB565A8_RLE_align64,
&test_RGB565_RLE_align64,
&test_RGB888_RLE_align64,
&test_XRGB8888_RLE_align64,
&test_ARGB8888_RLE_align64,
},
{
&test_I1_LZ4_align64,
&test_I2_LZ4_align64,
&test_I4_LZ4_align64,
&test_I8_LZ4_align64,
&test_A1_LZ4_align64,
&test_A2_LZ4_align64,
&test_A4_LZ4_align64,
&test_A8_LZ4_align64,
&test_RGB565A8_LZ4_align64,
&test_RGB565_LZ4_align64,
&test_RGB888_LZ4_align64,
&test_XRGB8888_LZ4_align64,
&test_ARGB8888_LZ4_align64,
}
}
};
void setUp(void)
{
/* Function run before every test */
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_clean(lv_screen_active());
}
void tearDown(void)
{
/* Function run after every test */
}
static void img_create(const char * name, const void * img_src, bool rotate, bool recolor)
{
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 120, LV_SIZE_CONTENT);
lv_obj_set_style_bg_color(cont, lv_palette_main(LV_PALETTE_LIGHT_BLUE), 0);
lv_obj_set_style_pad_all(cont, 5, 0);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_t * img = lv_image_create(cont);
lv_image_set_src(img, img_src);
lv_obj_set_style_image_recolor(img, lv_palette_main(LV_PALETTE_RED), 0); /*For A8*/
if(recolor) lv_obj_set_style_image_recolor_opa(img, LV_OPA_70, 0);
if(rotate) lv_image_set_rotation(img, 450);
lv_obj_t * label = lv_label_create(cont);
lv_label_set_text(label, name);
}
static void bin_image_create(bool rotate, bool recolor, int align, int compress)
{
char name[32];
char path[256];
int stride = stride_align[align];
for(unsigned i = 0; i < sizeof(color_formats) / sizeof(color_formats[0]); i++) {
lv_snprintf(name, sizeof(name), "bin%s", color_formats[i]);
lv_snprintf(path, sizeof(path), "A:test_images/stride_align%d/%s/test_%s.bin", stride, compressions[compress],
color_formats[i]);
img_create(name, path, rotate, recolor);
}
}
static void c_array_image_create(bool rotate, bool recolor, int align, int compress)
{
char name[32];
for(unsigned i = 0; i < sizeof(color_formats) / sizeof(color_formats[0]); i++) {
lv_snprintf(name, sizeof(name), "%s%s", compressions[compress], color_formats[i]);
const void * src = c_array_images[align][compress][i];
img_create(name, src, rotate, recolor);
}
}
void test_image_formats(void)
{
for(unsigned align = 0; align <= 1; align++) {
int stride = stride_align[align];
for(unsigned mode = 0; mode <= 3; mode++) {
bool rotate = mode & 0x02;
bool recolor = mode & 0x01;
#if LV_BIN_DECODER_RAM_LOAD == 0
if(rotate) continue; /* Transform relies on LV_BIN_DECODER_RAM_LOAD to be enabled */
#endif
/*Loop compressions array and do test.*/
for(unsigned i = 0; i < sizeof(compressions) / sizeof(compressions[0]); i++) {
char reference[256];
bin_image_create(rotate, recolor, align, i);
lv_snprintf(reference, sizeof(reference), "draw/bin_image_stride%d_%s_%s.png", stride, compressions[i], modes[mode]);
TEST_ASSERT_EQUAL_SCREENSHOT(reference);
lv_obj_clean(lv_screen_active());
c_array_image_create(rotate, recolor, align, i);
lv_snprintf(reference, sizeof(reference), "draw/c_array_image_stride%d_%s_%s.png", stride, compressions[i],
modes[mode]);
TEST_ASSERT_EQUAL_SCREENSHOT(reference);
lv_obj_clean(lv_screen_active());
}
}
}
}
#endif
@@ -0,0 +1,62 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_no_residual_border_on_scale_down(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_center(obj);
lv_obj_set_style_border_color(obj, lv_color_hex3(0xf00), 0);
lv_obj_set_style_bg_color(obj, lv_color_hex3(0x0f0), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/layer_transform_1.png");
int32_t pivot_x[] = {lv_pct(50), lv_pct(8), lv_pct(0), lv_pct(106), lv_pct(-16)};
int32_t pivot_y[] = {lv_pct(50), lv_pct(12), lv_pct(0), lv_pct(113), lv_pct(-27)};
int32_t scale[] = {256 * 4, 412, 569, 288, 711};
uint32_t i;
for(i = 0; i < 5; i++) {
lv_obj_set_style_transform_pivot_x(obj, pivot_x[i], 0);
lv_obj_set_style_transform_pivot_y(obj, pivot_y[i], 0);
lv_obj_set_style_transform_scale(obj, scale[i], 0);
lv_refr_now(NULL);
/*Should be the same as the original without any artifacts*/
lv_obj_set_style_transform_scale(obj, 256, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/layer_transform_1.png");
}
}
void test_update_layer_type_on_state_change(void)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_transform_rotation(&style, 90);
lv_style_set_transform_scale_x(&style, 100);
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_center(obj);
lv_obj_add_style(obj, &style, LV_STATE_CHECKED);
lv_refr_now(NULL);
lv_obj_add_state(obj, LV_STATE_CHECKED);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/layer_transform_2.png");
}
#endif
@@ -0,0 +1,48 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_al88(void)
{
#if LV_USE_DRAW_VG_LITE
TEST_PASS();
#else
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_AL88);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/al88/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
#endif
}
#endif
@@ -0,0 +1,56 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_render_to_argb1555(void)
{
/**
* There is a slight color deviation between thorvg on 32-bit and 64-bit platforms.
* The deviation will be amplified when using lower precision color formats.
* Only 64-bit platforms are tested here.
*/
#if LV_USE_DRAW_VG_LITE && LV_USE_SNAPSHOT && !defined(NON_AMD64_BUILD)
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
lv_draw_buf_t * draw_buf = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_ARGB1555);
lv_obj_t * img = lv_image_create(lv_layer_top());
lv_image_set_src(img, draw_buf);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/argb1555/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
lv_obj_delete(img);
lv_draw_buf_destroy(draw_buf);
}
}
#else
TEST_PASS();
#endif
}
#endif
@@ -0,0 +1,56 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_render_to_argb2222(void)
{
/**
* There is a slight color deviation between thorvg on 32-bit and 64-bit platforms.
* The deviation will be amplified when using lower precision color formats.
* Only 64-bit platforms are tested here.
*/
#if LV_USE_DRAW_VG_LITE && LV_USE_SNAPSHOT && !defined(NON_AMD64_BUILD)
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
lv_draw_buf_t * draw_buf = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_ARGB2222);
lv_obj_t * img = lv_image_create(lv_layer_top());
lv_image_set_src(img, draw_buf);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/argb2222/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
lv_obj_delete(img);
lv_draw_buf_destroy(draw_buf);
}
}
#else
TEST_PASS();
#endif
}
#endif
@@ -0,0 +1,56 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_render_to_argb4444(void)
{
/**
* There is a slight color deviation between thorvg on 32-bit and 64-bit platforms.
* The deviation will be amplified when using lower precision color formats.
* Only 64-bit platforms are tested here.
*/
#if LV_USE_DRAW_VG_LITE && LV_USE_SNAPSHOT && !defined(NON_AMD64_BUILD)
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
lv_draw_buf_t * draw_buf = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_ARGB4444);
lv_obj_t * img = lv_image_create(lv_layer_top());
lv_image_set_src(img, draw_buf);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/argb4444/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
lv_obj_delete(img);
lv_draw_buf_destroy(draw_buf);
}
}
#else
TEST_PASS();
#endif
}
#endif
@@ -0,0 +1,44 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_argb8888(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_ARGB8888);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/argb8888/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,44 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_argb8888_premultiplied(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/argb8888_premultiplied/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,42 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_i1(void)
{
#if LV_BIN_DECODER_RAM_LOAD && LV_USE_DRAW_VG_LITE == 0
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_I1);
lv_opa_t opa_values[2] = {0xff, 0xc0};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/i1/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
#else
/*Without LV_BIN_DECODER_RAM_LOAD can't test rotated images*/
TEST_PASS();
#endif
}
#endif
@@ -0,0 +1,43 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_l8(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_L8);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
lv_demo_render(i, opa_values[opa]);
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/l8/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,45 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_rgb565(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_RGB565);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/rgb565/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,44 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_rgb565_swapped(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_RGB565_SWAPPED);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/rgb565_swapped/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,45 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_rgb888(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_RGB888);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/rgb888/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,45 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
}
void test_render_to_xrgb8888(void)
{
lv_display_set_color_format(NULL, LV_COLOR_FORMAT_XRGB8888);
lv_opa_t opa_values[2] = {0xff, 0x80};
uint32_t opa;
for(opa = 0; opa < 2; opa++) {
uint32_t i;
for(i = 0; i < LV_DEMO_RENDER_SCENE_NUM; i++) {
/*Skip test with transformed indexed images if they are not loaded to RAM*/
if(LV_BIN_DECODER_RAM_LOAD == 0 &&
(i == LV_DEMO_RENDER_SCENE_IMAGE_NORMAL_3 ||
i == LV_DEMO_RENDER_SCENE_IMAGE_RECOLOR_3)) continue;
lv_demo_render(i, opa_values[opa]);
char buf[128];
lv_snprintf(buf, sizeof(buf), "draw/render/xrgb8888/demo_render_%s_opa_%d.png",
lv_demo_render_get_scene_name(i), opa_values[opa]);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
}
}
#endif
@@ -0,0 +1,88 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#if LV_USE_BARCODE
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_barcode_normal(void)
{
lv_obj_t * barcode = lv_barcode_create(active_screen);
TEST_ASSERT_NOT_NULL(barcode);
lv_obj_center(barcode);
lv_color_t dark_color = lv_color_black();
lv_color_t light_color = lv_color_white();
uint16_t scale = 2;
lv_result_t res;
lv_barcode_set_dark_color(barcode, dark_color);
lv_barcode_set_light_color(barcode, light_color);
lv_barcode_set_scale(barcode, scale);
TEST_ASSERT_EQUAL_COLOR(lv_barcode_get_dark_color(barcode), dark_color);
TEST_ASSERT_EQUAL_COLOR(lv_barcode_get_light_color(barcode), light_color);
TEST_ASSERT_EQUAL(lv_barcode_get_scale(barcode), scale);
/* Test horizontal mode */
lv_barcode_set_direction(barcode, LV_DIR_HOR);
lv_obj_set_height(barcode, 50);
res = lv_barcode_update(barcode, "https://lvgl.io");
TEST_ASSERT_EQUAL(res, LV_RESULT_OK);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_1.png");
/* Test vertical mode */
lv_barcode_set_direction(barcode, LV_DIR_VER);
lv_obj_set_size(barcode, 50, LV_SIZE_CONTENT);
res = lv_barcode_update(barcode, "https://lvgl.io");
TEST_ASSERT_EQUAL(res, LV_RESULT_OK);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_2.png");
/* Test tiled + horizontal mode */
lv_barcode_set_tiled(barcode, true);
lv_barcode_set_direction(barcode, LV_DIR_HOR);
lv_obj_set_size(barcode, LV_SIZE_CONTENT, 50);
res = lv_barcode_update(barcode, "https://lvgl.io");
TEST_ASSERT_EQUAL(res, LV_RESULT_OK);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_tiled_1.png");
/* Test tiled + vertical mode */
lv_barcode_set_direction(barcode, LV_DIR_VER);
lv_obj_set_size(barcode, 50, LV_SIZE_CONTENT);
res = lv_barcode_update(barcode, "https://lvgl.io");
TEST_ASSERT_EQUAL(res, LV_RESULT_OK);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_tiled_2.png");
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_barcode_normal(void)
{
}
#endif
#endif
@@ -0,0 +1,212 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void create_image(const void * src)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, src);
lv_obj_center(img);
}
static void bin_decoder(const void * src, const char * screenshot)
{
lv_image_cache_drop(src);
create_image(src);
TEST_ASSERT_EQUAL_SCREENSHOT(screenshot);
lv_obj_clean(lv_screen_active());
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
lv_obj_clean(lv_screen_active());
create_image(src);
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT(screenshot);
lv_obj_clean(lv_screen_active());
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 0);
}
static void create_image_tile(const void * src)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, src);
lv_obj_center(img);
lv_obj_set_size(img, 275, 175);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
}
static lv_image_dsc_t * get_image_dsc(void)
{
#define IMAGE_WIDTH 32
#define IMAGE_HEIGHT 2
static LV_ATTRIBUTE_MEM_ALIGN uint8_t image_map[IMAGE_WIDTH * IMAGE_HEIGHT * sizeof(lv_color32_t)] = { 0 };
static lv_image_dsc_t image_dsc = { 0 };
image_dsc.header.magic = LV_IMAGE_HEADER_MAGIC,
image_dsc.header.cf = LV_COLOR_FORMAT_ARGB8888;
image_dsc.header.w = IMAGE_WIDTH;
image_dsc.header.h = IMAGE_HEIGHT;
image_dsc.header.stride = IMAGE_WIDTH * sizeof(lv_color32_t);
image_dsc.data_size = sizeof(image_map);
image_dsc.data = image_map;
return &image_dsc;
}
void bin_decoder_tile(const void * src, const char * screenshot)
{
create_image_tile(src);
TEST_ASSERT_EQUAL_SCREENSHOT(screenshot);
lv_obj_clean(lv_screen_active());
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
lv_obj_clean(lv_screen_active());
create_image_tile(src);
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT(screenshot);
lv_obj_clean(lv_screen_active());
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 0);
}
void test_bin_decoder_i4(void)
{
LV_IMAGE_DECLARE(test_image_cogwheel_i4);
bin_decoder(&test_image_cogwheel_i4, "libs/bin_decoder_1.png");
}
void test_bin_decoder_i4_tile(void)
{
LV_IMAGE_DECLARE(test_image_cogwheel_i4);
bin_decoder_tile(&test_image_cogwheel_i4, "libs/bin_decoder_2.png");
}
void test_bin_decoder_argb8888(void)
{
LV_IMAGE_DECLARE(test_image_cogwheel_argb8888);
bin_decoder(&test_image_cogwheel_argb8888, "libs/bin_decoder_3.png");
}
void test_bin_decoder_argb8888_tile(void)
{
LV_IMAGE_DECLARE(test_image_cogwheel_argb8888);
bin_decoder_tile(&test_image_cogwheel_argb8888, "libs/bin_decoder_4.png");
}
void test_bin_decoder_image_dsc_error_handling(void)
{
lv_image_dsc_t * image_dsc = get_image_dsc();
/* Valid image */
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid magic */
image_dsc = get_image_dsc();
image_dsc->header.magic = 0;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid NULL data */
image_dsc = get_image_dsc();
image_dsc->data = NULL;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid data_size */
image_dsc = get_image_dsc();
image_dsc->data_size = 0;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid stride */
image_dsc = get_image_dsc();
image_dsc->header.stride = 0;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid color format */
image_dsc = get_image_dsc();
image_dsc->header.cf = LV_COLOR_FORMAT_UNKNOWN;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid image size */
image_dsc = get_image_dsc();
image_dsc->header.w++;
image_dsc->header.h++;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid unaligned data */
image_dsc = get_image_dsc();
image_dsc->data = image_dsc->data + 1;
image_dsc->header.h = 1;
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test invalid flags */
image_dsc = get_image_dsc();
image_dsc->header.flags = (LV_IMAGE_FLAGS_ALLOCATED | LV_IMAGE_FLAGS_PREMULTIPLIED);
bin_decoder(image_dsc, "libs/bin_decoder_empty_image.png");
/* Test NULL image */
bin_decoder(NULL, "libs/bin_decoder_empty_image.png");
}
void test_bin_decoder_flush_cache(void)
{
#if LV_BIN_DECODER_RAM_LOAD == 1
LV_IMAGE_DECLARE(test_I1_NONE_align64);
LV_IMAGE_DECLARE(test_I2_NONE_align64);
LV_IMAGE_DECLARE(test_I4_NONE_align64);
LV_IMAGE_DECLARE(test_I8_NONE_align64);
LV_IMAGE_DECLARE(test_A1_NONE_align64);
LV_IMAGE_DECLARE(test_A2_NONE_align64);
LV_IMAGE_DECLARE(test_A4_NONE_align64);
LV_IMAGE_DECLARE(test_A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565_NONE_align64);
LV_IMAGE_DECLARE(test_RGB888_NONE_align64);
LV_IMAGE_DECLARE(test_XRGB8888_NONE_align64);
LV_IMAGE_DECLARE(test_ARGB8888_NONE_align64);
const lv_image_dsc_t * img_dscs[] = {
&test_I1_NONE_align64,
&test_I2_NONE_align64,
&test_I4_NONE_align64,
&test_I8_NONE_align64,
&test_A1_NONE_align64,
&test_A2_NONE_align64,
&test_A4_NONE_align64,
&test_A8_NONE_align64,
&test_RGB565A8_NONE_align64,
&test_RGB565_NONE_align64,
&test_RGB888_NONE_align64,
&test_XRGB8888_NONE_align64,
&test_ARGB8888_NONE_align64,
};
const lv_image_decoder_args_t args = {
.no_cache = true,
.premultiply = false,
.stride_align = false,
.use_indexed = true,
.flush_cache = true,
};
for(unsigned long i = 0; i < sizeof(img_dscs) / sizeof(img_dscs[0]); i++) {
lv_image_decoder_dsc_t decoder_dsc;
lv_result_t res = lv_image_decoder_open(&decoder_dsc, img_dscs[i], &args);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
lv_image_decoder_close(&decoder_dsc);
}
#endif
}
#endif
@@ -0,0 +1,72 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void create_image(void)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.bmp");
lv_obj_center(img);
}
void test_bmp(void)
{
create_image();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/bmp_1.png");
lv_obj_clean(lv_screen_active());
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
lv_obj_clean(lv_screen_active());
create_image();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/bmp_1.png");
lv_obj_clean(lv_screen_active());
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 0);
}
static void create_image_tile(void)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.bmp");
lv_obj_center(img);
lv_obj_set_size(img, 300, 200);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
}
void test_bmp_align_tile(void)
{
create_image_tile();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/bmp_2.png");
lv_obj_clean(lv_screen_active());
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
lv_obj_clean(lv_screen_active());
create_image_tile();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/bmp_2.png");
lv_obj_clean(lv_screen_active());
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 0);
}
#endif
@@ -0,0 +1,146 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#if LV_USE_FFMPEG
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void create_image_item(lv_obj_t * parent, const void * src, const char * text)
{
lv_obj_t * cont = lv_obj_create(parent);
lv_obj_remove_style_all(cont);
lv_obj_set_size(cont, 300, 200);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * img = lv_image_create(cont);
lv_image_set_src(img, src);
lv_obj_t * label = lv_label_create(cont);
lv_label_set_text(label, text);
}
static void create_images(void)
{
lv_obj_t * screen = lv_screen_active();
lv_obj_clean(screen);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo.png", "PNG File (32 bit)");
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_png_no_ext", "PNG File (32 bit) No Extension");
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_8bit_palette.png", "PNG File (8 bit palette)");
}
void test_ffmpeg_image_decoder_1(void)
{
/* Temporarily remove other decoder */
#if LV_USE_LODEPNG
lv_lodepng_deinit();
#endif
#if LV_USE_LIBPNG
lv_libpng_deinit();
#endif
create_images();
/* Should decode images consistently with other PNG decoders */
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_1.png");
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_1.png");
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 32);
/* Re-add other decoder */
#if LV_USE_LODEPNG
lv_lodepng_init();
#endif
#if LV_USE_LIBPNG
lv_libpng_init();
#endif
lv_obj_clean(lv_screen_active());
}
void test_ffmpeg_player_1(void)
{
lv_obj_t * player = lv_ffmpeg_player_create(lv_screen_active());
lv_ffmpeg_player_set_auto_restart(player, true);
lv_obj_center(player);
lv_ffmpeg_player_set_src(player, "A:ERROR_FILE.mp4");
lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_START);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_error_file.png");
/* Video: test_video_birds.mp4 Update frame rate 25FPS */
lv_ffmpeg_player_set_src(player, "A:src/test_assets/test_video_birds.mp4");
/* Not started, it should be in the black screen */
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_frame_0.png");
lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_START);
lv_test_wait(400);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_frame_1.png");
lv_test_wait(400);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_frame_2.png");
lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_PAUSE);
lv_test_wait(400);
/* Paused, it should be in the same frame */
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_frame_2.png");
lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_RESUME);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/ffmpeg_player_frame_3.png");
lv_obj_delete(player);
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_ffmpeg_image_decoder_1(void)
{
}
void test_ffmpeg_player_1(void)
{
}
#endif /* LV_USE_FFMPEG */
#endif /* LV_BUILD_TEST */
@@ -0,0 +1,316 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#if LV_USE_FREETYPE && LV_USE_FONT_MANAGER
#include "rnd_unicodes/lv_rnd_unicodes.h"
#ifndef NON_AMD64_BUILD
#define TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(INDEX) \
lv_snprintf(buf, sizeof(buf), "libs/font_stress/snapshot_%0d.lp64.png", (INDEX));\
TEST_ASSERT_EQUAL_SCREENSHOT(buf)
#else
#define TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(INDEX) \
lv_snprintf(buf, sizeof(buf), "libs/font_stress/snapshot_%0d.lp32.png", (INDEX));\
TEST_ASSERT_EQUAL_SCREENSHOT(buf)
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
const char ** font_name_arr;
int font_cnt;
int label_cnt;
int loop_cnt;
} font_stress_config_t;
struct _font_stress_ctx_t;
typedef lv_font_t * (*font_create_cb_t)(struct _font_stress_ctx_t * ctx,
const char * name,
lv_freetype_font_render_mode_t render_mode,
uint32_t size,
lv_freetype_font_style_t style);
typedef void (*font_delete_cb_t)(struct _font_stress_ctx_t * ctx, lv_font_t * font);
typedef struct _font_stress_ctx_t {
font_stress_config_t config;
lv_obj_t * par;
lv_obj_t ** label_arr;
lv_font_manager_t * font_manager;
font_create_cb_t font_create_cb;
font_delete_cb_t font_delete_cb;
} font_stress_ctx_t;
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static font_stress_ctx_t g_ctx = { 0 };
/**********************
* MACROS
**********************/
#define RND_START_SEED 0x114514
#define CAPTURE_SKIP_FRAMES 17
#define MAX_FONT_SIZE 128
#define MAX_LABEL_CNT 32
#define MAX_LOOP_CNT 200
#define MAX_LABEL_CONTENT_LEN 16
/**********************
* GLOBAL FUNCTIONS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
static lv_obj_t * font_stress_label_create(font_stress_ctx_t * ctx, const char * font_name, lv_obj_t * par, int size,
int x, int y)
{
static const uint16_t font_style[] = {
LV_FREETYPE_FONT_STYLE_NORMAL,
LV_FREETYPE_FONT_STYLE_ITALIC,
LV_FREETYPE_FONT_STYLE_BOLD,
};
uint32_t index = lv_rand(0, sizeof(font_style) / sizeof(uint16_t) - 1);
uint32_t r = lv_rand(0, 0xFF);
uint32_t g = lv_rand(0, 0xFF);
uint32_t b = lv_rand(0, 0xFF);
lv_opa_t opa = lv_rand(0, LV_OPA_COVER);
lv_color_t color = lv_color_make(r, g, b);
lv_font_t * font = ctx->font_create_cb(ctx, font_name, LV_FREETYPE_FONT_RENDER_MODE_BITMAP, size, font_style[index]);
if(!font) {
return NULL;
}
lv_obj_t * label = lv_label_create(par);
lv_obj_set_style_text_font(label, font, 0);
lv_obj_set_style_text_opa(label, opa, 0);
lv_obj_set_style_text_color(label, color, 0);
lv_obj_set_pos(label, x, y);
lv_obj_set_style_outline_color(label, color, 0);
lv_obj_set_style_outline_width(label, 1, 0);
uint8_t str[128];
lv_random_utf8_chars(str, sizeof(str), LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE, LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE_LEN,
MAX_LABEL_CONTENT_LEN);
lv_label_set_text(label, (char *)str);
return label;
}
static void font_stress_label_delete(font_stress_ctx_t * ctx, lv_obj_t * label)
{
const lv_font_t * font = lv_obj_get_style_text_font(label, 0);
TEST_ASSERT_NOT_NULL(font);
lv_obj_del(label);
ctx->font_delete_cb(ctx, (lv_font_t *)font);
}
static void font_stress_label_delete_all(font_stress_ctx_t * ctx)
{
for(int i = 0; i < ctx->config.label_cnt; i++) {
lv_obj_t * label = ctx->label_arr[i];
if(label) {
font_stress_label_delete(ctx, label);
ctx->label_arr[i] = NULL;
}
}
}
static void font_stress_update(font_stress_ctx_t * ctx)
{
uint32_t label_index = lv_rand(0, ctx->config.label_cnt - 1);
uint32_t font_index = lv_rand(0, ctx->config.font_cnt - 1);
uint32_t font_size = lv_rand(0, MAX_FONT_SIZE);
uint32_t label_x = lv_rand(0, LV_HOR_RES) - LV_HOR_RES / 2;
uint32_t label_y = lv_rand(0, LV_VER_RES);
lv_obj_t * label = ctx->label_arr[label_index];
if(label) {
font_stress_label_delete(ctx, label);
ctx->label_arr[label_index] = NULL;
}
else {
const char * pathname = ctx->config.font_name_arr[font_index];
TEST_ASSERT_NOT_NULL(pathname);
label = font_stress_label_create(
ctx,
pathname,
ctx->par,
(int)font_size,
(int)label_x,
(int)label_y);
ctx->label_arr[label_index] = label;
}
}
static lv_font_t * freetype_font_create_cb(font_stress_ctx_t * ctx,
const char * name,
lv_freetype_font_render_mode_t render_mode,
uint32_t size,
lv_freetype_font_style_t style)
{
LV_UNUSED(ctx);
return lv_freetype_font_create(name, render_mode, size, style);
}
static void freetype_font_delete_cb(font_stress_ctx_t * ctx, lv_font_t * font)
{
LV_UNUSED(ctx);
lv_freetype_font_delete(font);
}
static lv_font_t * font_manager_font_create_cb(font_stress_ctx_t * ctx,
const char * name,
lv_freetype_font_render_mode_t render_mode,
uint32_t size,
lv_freetype_font_style_t style)
{
TEST_ASSERT_NOT_NULL(ctx->font_manager);
return lv_font_manager_create_font(ctx->font_manager, name, render_mode, size, style, LV_FONT_KERNING_NONE);
}
static void font_manager_font_delete_cb(font_stress_ctx_t * ctx, lv_font_t * font)
{
TEST_ASSERT_NOT_NULL(ctx->font_manager);
lv_font_manager_delete_font(ctx->font_manager, font);
}
void setUp(void)
{
lv_freetype_init(LV_FREETYPE_CACHE_FT_GLYPH_CNT);
g_ctx.par = lv_screen_active();
g_ctx.config.label_cnt = MAX_LABEL_CNT;
g_ctx.label_arr = lv_malloc_zeroed(sizeof(lv_obj_t *) * g_ctx.config.label_cnt);
TEST_ASSERT_NOT_NULL(g_ctx.label_arr);
}
void tearDown(void)
{
font_stress_label_delete_all(&g_ctx);
lv_freetype_uninit();
lv_free(g_ctx.label_arr);
g_ctx.label_arr = NULL;
}
void test_font_stress(void)
{
lv_rand_set_seed(RND_START_SEED);
static const char * font_name_arr[] = {
"./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
"../src/libs/freetype/arial.ttf",
"./src/test_files/fonts/Montserrat-Bold.ttf",
"UNKNOWN_FONT_NAME"
};
g_ctx.config.loop_cnt = MAX_LOOP_CNT;
g_ctx.config.font_name_arr = font_name_arr;
g_ctx.config.font_cnt = sizeof(font_name_arr) / sizeof(font_name_arr[0]);
g_ctx.font_create_cb = freetype_font_create_cb;
g_ctx.font_delete_cb = freetype_font_delete_cb;
for(uint32_t i = 0; g_ctx.config.loop_cnt > 0; g_ctx.config.loop_cnt--) {
font_stress_update(&g_ctx);
lv_refr_now(NULL);
if(g_ctx.config.loop_cnt % CAPTURE_SKIP_FRAMES == 0) {
char buf[64];
TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(i);
i++;
}
}
font_stress_label_delete_all(&g_ctx);
}
void test_font_manager_stress(void)
{
lv_rand_set_seed(RND_START_SEED);
g_ctx.font_manager = lv_font_manager_create(2);
TEST_ASSERT_NOT_NULL(g_ctx.font_manager);
lv_font_manager_add_src_static(g_ctx.font_manager, "NotoSansSC-Regular",
"./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
&lv_freetype_font_class);
lv_font_manager_add_src_static(g_ctx.font_manager, "Arial", "../src/libs/freetype/arial.ttf", &lv_freetype_font_class);
lv_font_manager_add_src(g_ctx.font_manager, "Montserrat-Bold", "./src/test_files/fonts/Montserrat-Bold.ttf",
&lv_freetype_font_class);
lv_font_manager_add_src(g_ctx.font_manager, "UNKNOWN", "UNKNOWN_FONT_PATH", &lv_freetype_font_class);
static const char * font_name_arr[] = {
"NotoSansSC-Regular,Arial",
"Arial",
"Montserrat-Bold",
"UNKNOWN"
};
g_ctx.config.loop_cnt = MAX_LOOP_CNT;
g_ctx.config.font_name_arr = font_name_arr;
g_ctx.config.font_cnt = sizeof(font_name_arr) / sizeof(font_name_arr[0]);
g_ctx.font_create_cb = font_manager_font_create_cb;
g_ctx.font_delete_cb = font_manager_font_delete_cb;
for(uint32_t i = 0; g_ctx.config.loop_cnt > 0; g_ctx.config.loop_cnt--) {
font_stress_update(&g_ctx);
lv_refr_now(NULL);
if(g_ctx.config.loop_cnt % CAPTURE_SKIP_FRAMES == 0) {
char buf[64];
TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(i);
i++;
}
}
font_stress_label_delete_all(&g_ctx);
bool remove_ok = lv_font_manager_remove_src(g_ctx.font_manager, "Arial");
TEST_ASSERT_TRUE(remove_ok);
remove_ok = lv_font_manager_remove_src(g_ctx.font_manager, "UNKNOWN");
TEST_ASSERT_TRUE(remove_ok);
bool success = lv_font_manager_delete(g_ctx.font_manager);
TEST_ASSERT_TRUE(success);
g_ctx.font_manager = NULL;
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_font_stress(void)
{
}
void test_font_manager_stress(void)
{
}
#endif
#endif
@@ -0,0 +1,648 @@
#if LV_BUILD_TEST
#include "lvgl.h"
#include "src/libs/freetype/lv_freetype_private.h"
#include "unity/unity.h"
#if LV_USE_FREETYPE
#ifndef NON_AMD64_BUILD
#define EXT_NAME ".lp64.png"
#else
#define EXT_NAME ".lp32.png"
#endif
#define OPTION_GENERATE_OUTLINE_DATA 0
/*
* Generated vector ops string can use https://w-mai.github.io/vegravis/
* to visualize the outline data.
**/
#define OPTION_GENERATE_VECTOR_OPS_STRING 0
static const char * UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_CN =
"鉴于对人类家庭所有成员的固有尊严及其平等的和不移的权利的承认,乃是世界自由、正义与和平的基础...";
static const char * UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_EN =
"Whereas recognition of the inherent dignity and of the equal and inalienable rights of all members of the human family is the foundation of freedom, justice and peace in the world...";
static const char * UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_JP =
"人間の家族のすべての構成員の固有の尊厳と平等で譲渡不能な権利とを承認することは、自由と正義と平和の基礎である...";
// Outline data for unicode '龘' (U+9F98)
static const lv_freetype_outline_event_param_t outline_data_U9F98[] = {
{NULL, 1, {5888, 6889}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6445, 6889}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6238, 5915}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5681, 5915}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5888, 6889}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2069, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4576, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4508, 4825}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2525, 4825}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2178, 3195}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1654, 3195}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2069, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5714, 6070}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8573, 6070}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8401, 5259}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5542, 5259}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5606, 5562}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7916, 5562}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7962, 5775}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5652, 5775}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5714, 6070}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5580, 5439}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6137, 5439}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5786, 3785}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5832, 3600}, {5756, 3645}, {0, 0}, {0, 0}},
{NULL, 4, {6195, 3555}, {5909, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {6461, 3555}, {6261, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {6904, 3555}, {6662, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {7359, 3555}, {7146, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {7670, 3555}, {7572, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {7880, 3579}, {7801, 3555}, {0, 0}, {0, 0}},
{NULL, 4, {8010, 3690}, {7959, 3604}, {0, 0}, {0, 0}},
{NULL, 4, {8107, 3957}, {8061, 3777}, {0, 0}, {0, 0}},
{NULL, 4, {8305, 3887}, {8188, 3916}, {0, 0}, {0, 0}},
{NULL, 4, {8526, 3842}, {8422, 3858}, {0, 0}, {0, 0}},
{NULL, 4, {8238, 3359}, {8416, 3482}, {0, 0}, {0, 0}},
{NULL, 4, {7668, 3236}, {8061, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {7446, 3236}, {7610, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {7074, 3236}, {7283, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {6656, 3236}, {6865, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {6287, 3236}, {6447, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {6078, 3236}, {6127, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {5345, 3334}, {5538, 3236}, {0, 0}, {0, 0}},
{NULL, 4, {5230, 3793}, {5153, 3432}, {0, 0}, {0, 0}},
{NULL, 2, {5580, 5439}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4305, 6185}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4756, 6038}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {4494, 5726}, {4616, 5874}, {0, 0}, {0, 0}},
{NULL, 4, {4258, 5464}, {4373, 5579}, {0, 0}, {0, 0}},
{NULL, 2, {3901, 5595}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {4120, 5894}, {4002, 5726}, {0, 0}, {0, 0}},
{NULL, 4, {4305, 6185}, {4238, 6062}, {0, 0}, {0, 0}},
{NULL, 1, {2506, 6046}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2941, 6169}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {3051, 5894}, {3014, 6046}, {0, 0}, {0, 0}},
{NULL, 4, {3088, 5628}, {3089, 5743}, {0, 0}, {0, 0}},
{NULL, 2, {2610, 5497}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {2584, 5763}, {2616, 5603}, {0, 0}, {0, 0}},
{NULL, 4, {2506, 6046}, {2553, 5923}, {0, 0}, {0, 0}},
{NULL, 1, {4322, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4846, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4515, 3588}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {4421, 3362}, {4481, 3432}, {0, 0}, {0, 0}},
{NULL, 4, {4238, 3252}, {4362, 3293}, {0, 0}, {0, 0}},
{NULL, 4, {3912, 3203}, {4115, 3211}, {0, 0}, {0, 0}},
{NULL, 4, {3423, 3195}, {3710, 3195}, {0, 0}, {0, 0}},
{NULL, 4, {3409, 3359}, {3433, 3277}, {0, 0}, {0, 0}},
{NULL, 4, {3358, 3506}, {3385, 3441}, {0, 0}, {0, 0}},
{NULL, 4, {3677, 3506}, {3530, 3506}, {0, 0}, {0, 0}},
{NULL, 4, {3874, 3506}, {3825, 3506}, {0, 0}, {0, 0}},
{NULL, 4, {3956, 3522}, {3932, 3506}, {0, 0}, {0, 0}},
{NULL, 4, {3991, 3588}, {3980, 3539}, {0, 0}, {0, 0}},
{NULL, 2, {4322, 5145}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6071, 6595}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8988, 6595}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8923, 6291}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6006, 6291}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6071, 6595}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5732, 5038}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8190, 5038}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8132, 4768}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5674, 4768}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5732, 5038}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5646, 4555}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8046, 4555}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7987, 4276}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5587, 4276}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5646, 4555}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5523, 4055}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8046, 4055}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7989, 3785}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5466, 3785}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5523, 4055}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2081, 4047}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4350, 4047}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4288, 3752}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2019, 3752}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2081, 4047}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2196, 4588}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4465, 4588}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4402, 4293}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2133, 4293}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2196, 4588}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2066, 6447}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5351, 6447}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5284, 6128}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1999, 6128}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2066, 6447}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {1689, 5710}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5433, 5710}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5365, 5390}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1621, 5390}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1689, 5710}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {3383, 6824}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3903, 6914}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {4030, 6607}, {3973, 6783}, {0, 0}, {0, 0}},
{NULL, 4, {4110, 6308}, {4087, 6431}, {0, 0}, {0, 0}},
{NULL, 2, {3568, 6185}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {3507, 6500}, {3554, 6316}, {0, 0}, {0, 0}},
{NULL, 4, {3383, 6824}, {3461, 6685}, {0, 0}, {0, 0}},
{NULL, 1, {3008, 3129}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3377, 3129}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3168, 2146}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2799, 2146}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3008, 3129}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {860, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2163, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2095, 1106}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1136, 1106}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {776, -590}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {432, -590}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {860, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2834, 2310}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4317, 2310}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4143, 1491}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2660, 1491}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2723, 1786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3853, 1786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3901, 2015}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2771, 2015}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2834, 2310}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2703, 1696}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3063, 1696}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2698, -25}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {2705, -184}, {2672, -147}, {0, 0}, {0, 0}},
{NULL, 4, {2869, -221}, {2738, -221}, {0, 0}, {0, 0}},
{NULL, 4, {3045, -221}, {2919, -221}, {0, 0}, {0, 0}},
{NULL, 4, {3311, -221}, {3172, -221}, {0, 0}, {0, 0}},
{NULL, 4, {3500, -221}, {3451, -221}, {0, 0}, {0, 0}},
{NULL, 4, {3659, -147}, {3607, -221}, {0, 0}, {0, 0}},
{NULL, 4, {3776, 188}, {3711, -74}, {0, 0}, {0, 0}},
{NULL, 4, {3899, 114}, {3824, 147}, {0, 0}, {0, 0}},
{NULL, 4, {4044, 66}, {3974, 82}, {0, 0}, {0, 0}},
{NULL, 4, {3826, -418}, {3951, -295}, {0, 0}, {0, 0}},
{NULL, 4, {3473, -541}, {3702, -541}, {0, 0}, {0, 0}},
{NULL, 4, {3346, -541}, {3449, -541}, {0, 0}, {0, 0}},
{NULL, 4, {3121, -541}, {3244, -541}, {0, 0}, {0, 0}},
{NULL, 4, {2899, -541}, {2998, -541}, {0, 0}, {0, 0}},
{NULL, 4, {2769, -541}, {2801, -541}, {0, 0}, {0, 0}},
{NULL, 4, {2366, -446}, {2465, -541}, {0, 0}, {0, 0}},
{NULL, 4, {2338, -25}, {2268, -352}, {0, 0}, {0, 0}},
{NULL, 2, {2703, 1696}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2189, 2474}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2462, 2335}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {2225, 2031}, {2337, 2171}, {0, 0}, {0, 0}},
{NULL, 4, {2019, 1794}, {2114, 1892}, {0, 0}, {0, 0}},
{NULL, 2, {1800, 1917}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {2003, 2199}, {1892, 2040}, {0, 0}, {0, 0}},
{NULL, 4, {2189, 2474}, {2115, 2359}, {0, 0}, {0, 0}},
{NULL, 1, {1134, 2367}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1451, 2433}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {1517, 2166}, {1492, 2318}, {0, 0}, {0, 0}},
{NULL, 4, {1543, 1901}, {1542, 2015}, {0, 0}, {0, 0}},
{NULL, 2, {1204, 1810}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {1196, 2080}, {1212, 1925}, {0, 0}, {0, 0}},
{NULL, 4, {1134, 2367}, {1180, 2236}, {0, 0}, {0, 0}},
{NULL, 1, {2015, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2367, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2022, -197}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {1941, -426}, {1989, -352}, {0, 0}, {0, 0}},
{NULL, 4, {1794, -541}, {1893, -500}, {0, 0}, {0, 0}},
{NULL, 4, {1551, -586}, {1703, -582}, {0, 0}, {0, 0}},
{NULL, 4, {1169, -590}, {1399, -590}, {0, 0}, {0, 0}},
{NULL, 4, {1166, -430}, {1176, -516}, {0, 0}, {0, 0}},
{NULL, 4, {1139, -270}, {1156, -344}, {0, 0}, {0, 0}},
{NULL, 4, {1415, -279}, {1293, -279}, {0, 0}, {0, 0}},
{NULL, 4, {1579, -279}, {1538, -279}, {0, 0}, {0, 0}},
{NULL, 4, {1670, -197}, {1653, -279}, {0, 0}, {0, 0}},
{NULL, 2, {2015, 1425}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {3108, 2826}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4492, 2826}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4429, 2531}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3045, 2531}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3108, 2826}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2779, 1278}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4016, 1278}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3958, 1008}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2721, 1008}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2779, 1278}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2674, 786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3919, 786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3862, 516}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2617, 516}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2674, 786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {2570, 295}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3692, 295}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {3632, 16}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2510, 16}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2570, 295}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {791, 328}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1946, 328}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1883, 33}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {728, 33}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {791, 328}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {905, 868}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2060, 868}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1998, 573}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {843, 573}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {905, 868}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {1016, 2736}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2769, 2736}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2701, 2417}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {948, 2417}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {1016, 2736}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {739, 1974}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2640, 1974}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2570, 1647}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {669, 1647}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {739, 1974}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {1666, 3056}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {2019, 3138}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {2100, 2887}, {2069, 3031}, {0, 0}, {0, 0}},
{NULL, 4, {2142, 2638}, {2131, 2744}, {0, 0}, {0, 0}},
{NULL, 2, {1756, 2515}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {1729, 2777}, {1755, 2630}, {0, 0}, {0, 0}},
{NULL, 4, {1666, 3056}, {1703, 2925}, {0, 0}, {0, 0}},
{NULL, 1, {6779, 3105}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7156, 3105}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6949, 2130}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6572, 2130}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6779, 3105}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4558, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5901, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5833, 1081}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4842, 1081}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4481, -614}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4129, -614}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4558, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6605, 2286}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8146, 2286}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7974, 1475}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6433, 1475}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6495, 1769}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7667, 1769}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7716, 1999}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6544, 1999}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6605, 2286}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6474, 1671}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6851, 1671}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6482, -66}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {6491, -217}, {6456, -188}, {0, 0}, {0, 0}},
{NULL, 4, {6665, -246}, {6526, -246}, {0, 0}, {0, 0}},
{NULL, 4, {6837, -246}, {6706, -246}, {0, 0}, {0, 0}},
{NULL, 4, {7112, -246}, {6969, -246}, {0, 0}, {0, 0}},
{NULL, 4, {7313, -246}, {7255, -246}, {0, 0}, {0, 0}},
{NULL, 4, {7474, -176}, {7419, -246}, {0, 0}, {0, 0}},
{NULL, 4, {7594, 156}, {7530, -106}, {0, 0}, {0, 0}},
{NULL, 4, {7723, 86}, {7643, 115}, {0, 0}, {0, 0}},
{NULL, 4, {7873, 41}, {7803, 57}, {0, 0}, {0, 0}},
{NULL, 4, {7653, -450}, {7778, -328}, {0, 0}, {0, 0}},
{NULL, 4, {7292, -573}, {7529, -573}, {0, 0}, {0, 0}},
{NULL, 4, {7152, -573}, {7259, -573}, {0, 0}, {0, 0}},
{NULL, 4, {6919, -573}, {7046, -573}, {0, 0}, {0, 0}},
{NULL, 4, {6689, -573}, {6792, -573}, {0, 0}, {0, 0}},
{NULL, 4, {6554, -573}, {6587, -573}, {0, 0}, {0, 0}},
{NULL, 4, {6144, -479}, {6251, -573}, {0, 0}, {0, 0}},
{NULL, 4, {6107, -57}, {6037, -385}, {0, 0}, {0, 0}},
{NULL, 2, {6474, 1671}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5928, 2449}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6217, 2310}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5978, 2015}, {6094, 2154}, {0, 0}, {0, 0}},
{NULL, 4, {5758, 1769}, {5863, 1876}, {0, 0}, {0, 0}},
{NULL, 2, {5530, 1892}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5742, 2175}, {5622, 2015}, {0, 0}, {0, 0}},
{NULL, 4, {5928, 2449}, {5862, 2335}, {0, 0}, {0, 0}},
{NULL, 1, {4834, 2351}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5157, 2408}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5232, 2146}, {5208, 2302}, {0, 0}, {0, 0}},
{NULL, 4, {5258, 1884}, {5256, 1991}, {0, 0}, {0, 0}},
{NULL, 2, {4910, 1786}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {4894, 2060}, {4910, 1901}, {0, 0}, {0, 0}},
{NULL, 4, {4834, 2351}, {4879, 2220}, {0, 0}, {0, 0}},
{NULL, 1, {5746, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6106, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5763, -213}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5684, -446}, {5728, -377}, {0, 0}, {0, 0}},
{NULL, 4, {5541, -565}, {5641, -516}, {0, 0}, {0, 0}},
{NULL, 4, {5280, -610}, {5433, -606}, {0, 0}, {0, 0}},
{NULL, 4, {4891, -614}, {5128, -614}, {0, 0}, {0, 0}},
{NULL, 4, {4888, -455}, {4899, -541}, {0, 0}, {0, 0}},
{NULL, 4, {4852, -295}, {4878, -369}, {0, 0}, {0, 0}},
{NULL, 4, {5138, -303}, {5007, -303}, {0, 0}, {0, 0}},
{NULL, 4, {5311, -295}, {5269, -303}, {0, 0}, {0, 0}},
{NULL, 4, {5401, -221}, {5385, -295}, {0, 0}, {0, 0}},
{NULL, 2, {5746, 1401}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6887, 2802}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8313, 2802}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {8250, 2507}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6824, 2507}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6887, 2802}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6549, 1253}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7827, 1253}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7770, 983}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6492, 983}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6549, 1253}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6445, 762}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7731, 762}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7674, 492}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6388, 492}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6445, 762}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {6340, 270}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7512, 270}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {7455, 0}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6283, 0}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6340, 270}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4496, 303}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5692, 303}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5630, 8}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4434, 8}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4496, 303}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4611, 844}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5807, 844}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5746, 557}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4550, 557}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4611, 844}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4715, 2720}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6517, 2720}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6447, 2392}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4645, 2392}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4715, 2720}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {4428, 1950}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6394, 1950}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {6326, 1630}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4360, 1630}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {4428, 1950}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 1, {5370, 3023}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 2, {5739, 3105}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5825, 2855}, {5790, 2998}, {0, 0}, {0, 0}},
{NULL, 4, {5872, 2613}, {5860, 2712}, {0, 0}, {0, 0}},
{NULL, 2, {5479, 2499}, {0, 0}, {0, 0}, {0, 0}},
{NULL, 4, {5434, 2752}, {5469, 2605}, {0, 0}, {0, 0}},
{NULL, 4, {5370, 3023}, {5400, 2900}, {0, 0}, {0, 0}},
{NULL, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
};
static void freetype_outline_event_cb(lv_event_t * e);
#if OPTION_GENERATE_VECTOR_OPS_STRING
static void vegravis_generate_vector_ops_string(lv_freetype_outline_event_param_t * param, char * buf,
uint32_t buf_len);
#endif
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void test_freetype_with_render_mode(lv_freetype_font_render_mode_t render_mode, const char * screenshot_name)
{
/*Create a font*/
lv_font_t * font_italic = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
render_mode,
24,
LV_FREETYPE_FONT_STYLE_ITALIC);
TEST_ASSERT_NOT_NULL(font_italic);
lv_font_t * font_normal = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
render_mode,
24,
LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NOT_NULL(font_normal);
lv_font_t * font_normal_small = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
render_mode,
12,
LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NOT_NULL(font_normal_small);
/* Emoji is only supported in bitmap mode */
lv_font_t * font_emoji = lv_freetype_font_create("../examples/libs/freetype/NotoColorEmoji-32.subset.ttf",
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
12,
LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NOT_NULL(font_emoji);
lv_font_t * font_path_error = lv_freetype_font_create("ERROR_PATH", render_mode, 24,
LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NULL(font_path_error);
font_path_error = lv_freetype_font_create("", render_mode, 24, LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NULL(font_path_error);
font_path_error = lv_freetype_font_create(NULL, render_mode, 24, LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NULL(font_path_error);
lv_font_t * font_size_error = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
render_mode,
0,
LV_FREETYPE_FONT_STYLE_NORMAL);
TEST_ASSERT_NULL(font_size_error);
/*Create style with the new font*/
static lv_style_t style_italic;
lv_style_init(&style_italic);
lv_style_set_text_font(&style_italic, font_italic);
lv_style_set_text_align(&style_italic, LV_TEXT_ALIGN_CENTER);
static lv_style_t style_normal;
lv_style_init(&style_normal);
lv_style_set_text_font(&style_normal, font_normal);
lv_style_set_text_align(&style_normal, LV_TEXT_ALIGN_CENTER);
static lv_style_t style_normal_small;
lv_style_init(&style_normal_small);
lv_style_set_text_font(&style_normal_small, font_normal_small);
static lv_style_t style_normal_emoji;
lv_style_init(&style_normal_emoji);
lv_style_set_text_font(&style_normal_emoji, font_emoji);
lv_style_set_text_align(&style_normal_emoji, LV_TEXT_ALIGN_CENTER);
/*Create a label with the new style*/
lv_obj_t * label0 = lv_label_create(lv_screen_active());
lv_obj_add_style(label0, &style_italic, 0);
lv_obj_set_width(label0, lv_obj_get_width(lv_screen_active()) - 20);
lv_label_set_text(label0, UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_CN);
lv_obj_align(label0, LV_ALIGN_TOP_MID, 0, 10);
lv_obj_t * label1 = lv_label_create(lv_screen_active());
lv_obj_add_style(label1, &style_normal, 0);
lv_obj_set_width(label1, lv_obj_get_width(lv_screen_active()) - 20);
lv_label_set_text(label1, UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_EN);
lv_obj_align_to(label1, label0, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_obj_t * label2 = lv_label_create(lv_screen_active());
lv_obj_add_style(label2, &style_normal_small, 0);
lv_obj_set_width(label2, lv_obj_get_width(lv_screen_active()) - 20);
lv_label_set_text(label2, UNIVERSAL_DECLARATION_OF_HUMAN_RIGHTS_JP);
lv_obj_align_to(label2, label1, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
/* test emoji rendering
* emoji font does not contain normal characters, use fallback to render them */
font_emoji->fallback = font_normal;
lv_obj_t * label_emoji = lv_label_create(lv_screen_active());
lv_obj_add_style(label_emoji, &style_normal_emoji, 0);
lv_obj_set_width(label_emoji, lv_obj_get_width(lv_screen_active()) - 20);
lv_label_set_text(label_emoji, "FreeType Emoji test: 😀");
lv_obj_align_to(label_emoji, label2, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
TEST_ASSERT_EQUAL_SCREENSHOT(screenshot_name);
lv_obj_clean(lv_screen_active());
lv_style_reset(&style_italic);
lv_style_reset(&style_normal);
lv_style_reset(&style_normal_small);
lv_style_reset(&style_normal_emoji);
lv_freetype_font_delete(font_italic);
lv_freetype_font_delete(font_normal);
lv_freetype_font_delete(font_normal_small);
lv_freetype_font_delete(font_emoji);
}
void test_freetype_render_bitmap(void)
{
test_freetype_with_render_mode(LV_FREETYPE_FONT_RENDER_MODE_BITMAP, "libs/freetype_render_bitmap" EXT_NAME);
}
void test_freetype_render_outline(void)
{
#if LV_USE_DRAW_VG_LITE
/* VG-Lite support rendering outline */
test_freetype_with_render_mode(LV_FREETYPE_FONT_RENDER_MODE_OUTLINE, "libs/freetype_render_outline.png");
LV_UNUSED(outline_data_U9F98);
LV_UNUSED(freetype_outline_event_cb);
#else
/* Outline rendering not supported, compare outline data only */
/*Create a font*/
lv_font_t * font_italic = lv_freetype_font_create("./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
LV_FREETYPE_FONT_RENDER_MODE_OUTLINE,
24,
LV_FREETYPE_FONT_STYLE_ITALIC);
TEST_ASSERT_NOT_NULL(font_italic);
/*Setup outline event for generating outline drawing data*/
lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, NULL);
lv_font_glyph_dsc_t g;
lv_font_get_glyph_dsc(font_italic, &g, 0x9F98, '\0');
const lv_ll_t * outline_data;
outline_data = (lv_ll_t *) lv_font_get_glyph_bitmap(&g, NULL);
uint32_t i = 0;
lv_freetype_outline_event_param_t * param;
LV_LL_READ(outline_data, param) {
#if OPTION_GENERATE_OUTLINE_DATA
/*FOR Generate outline data*/
#if OPTION_GENERATE_VECTOR_OPS_STRING
char buf[1024];
vegravis_generate_vector_ops_string(param, buf, sizeof(buf));
TEST_PRINTF("%s", buf);
#else
TEST_PRINTF("{NULL, %d, {%d, %d}, {%d, %d}, {%d, %d}}, ", param->type, param->to.x, param->to.y, param->control1.x,
param->control1.y, param->control2.x, param->control2.y);
#endif
#endif
TEST_ASSERT_EQUAL(param->type, outline_data_U9F98[i].type);
TEST_ASSERT_EQUAL(param->to.x, outline_data_U9F98[i].to.x);
TEST_ASSERT_EQUAL(param->to.y, outline_data_U9F98[i].to.y);
TEST_ASSERT_EQUAL(param->control1.x, outline_data_U9F98[i].control1.x);
TEST_ASSERT_EQUAL(param->control1.y, outline_data_U9F98[i].control1.y);
TEST_ASSERT_EQUAL(param->control2.x, outline_data_U9F98[i].control2.x);
TEST_ASSERT_EQUAL(param->control2.y, outline_data_U9F98[i].control2.y);
i++;
}
font_italic->release_glyph(font_italic, &g);
lv_freetype_font_delete(font_italic);
#endif
}
static void freetype_outline_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_freetype_outline_event_param_t * param = lv_event_get_param(e);
switch(code) {
case LV_EVENT_CREATE:
param->outline = lv_malloc_zeroed(sizeof(lv_ll_t));
lv_ll_init(param->outline, sizeof(lv_freetype_outline_event_param_t));
break;
case LV_EVENT_DELETE:
lv_ll_clear(param->outline);
lv_free(param->outline);
break;
case LV_EVENT_INSERT: {
void * entry = lv_ll_ins_tail(param->outline);
lv_memcpy(entry, param, sizeof(lv_freetype_outline_event_param_t));
break;
}
default:
LV_LOG_WARN("unknown event code: %d", code);
break;
}
}
#if OPTION_GENERATE_VECTOR_OPS_STRING
static void vegravis_generate_vector_ops_string(lv_freetype_outline_event_param_t * param, char * buf, uint32_t buf_len)
{
float x, y, p1x, p1y, p2x, p2y;
x = LV_FREETYPE_F26DOT6_TO_FLOAT(param->to.x);
y = LV_FREETYPE_F26DOT6_TO_FLOAT(param->to.y);
p1x = LV_FREETYPE_F26DOT6_TO_FLOAT(param->control1.x);
p1y = LV_FREETYPE_F26DOT6_TO_FLOAT(param->control1.y);
p2x = LV_FREETYPE_F26DOT6_TO_FLOAT(param->control2.x);
p2y = LV_FREETYPE_F26DOT6_TO_FLOAT(param->control2.y);
switch(param->type) {
case LV_FREETYPE_OUTLINE_MOVE_TO:
lv_snprintf(buf, buf_len, "MOVE, %f, %f, ", x, x);
break;
case LV_FREETYPE_OUTLINE_LINE_TO:
lv_snprintf(buf, buf_len, "LINE, %f, %f, ", x, y);
break;
case LV_FREETYPE_OUTLINE_CONIC_TO:
lv_snprintf(buf, buf_len, "QUAD, %f, %f, %f, %f, ", p1x, p1y, x, y);
break;
case LV_FREETYPE_OUTLINE_CUBIC_TO:
lv_snprintf(buf, buf_len, "CUBI, %f, %f, %f, %f, %f, %f, ", p1x, p1y, p2x, p2y, x, y);
break;
case LV_FREETYPE_OUTLINE_END:
lv_snprintf(buf, buf_len, "END, ");
break;
default:
break;
}
}
#endif
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_freetype_render_bitmap(void)
{
}
void test_freetype_render_outline(void)
{
}
#endif /*LV_USE_FREETYPE*/
#endif
@@ -0,0 +1,83 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void create_images(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * img;
lv_obj_t * label;
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, -150, -150);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "jpeg with exif orientation 0");
lv_obj_align(label, LV_ALIGN_CENTER, -150, -100);
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo_with_exif_orientation_180.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, 150, -150);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "jpeg with exif orientation 180");
lv_obj_align(label, LV_ALIGN_CENTER, 150, -100);
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo_with_exif_orientation_90.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, -150, 40);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "jpeg with exif orientation 90");
lv_obj_align(label, LV_ALIGN_CENTER, -150, 150);
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo_with_exif_orientation_270.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, 150, 40);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "jpeg with exif orientation 270");
lv_obj_align(label, LV_ALIGN_CENTER, 150, 150);
}
void test_jpg_2(void)
{
/* Temporarily remove tjpgd decoder */
lv_tjpgd_deinit();
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_2.png");
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_2.png");
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 64);
/* Re-add tjpgd decoder */
lv_tjpgd_init();
}
#endif
@@ -0,0 +1,79 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void create_image_item(lv_obj_t * parent, const void * src, const char * text)
{
lv_obj_t * cont = lv_obj_create(parent);
lv_obj_remove_style_all(cont);
lv_obj_set_size(cont, 300, 200);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * img = lv_image_create(cont);
lv_image_set_src(img, src);
lv_obj_t * label = lv_label_create(cont);
lv_label_set_text(label, text);
}
static void create_images(void)
{
lv_obj_t * screen = lv_screen_active();
lv_obj_clean(screen);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
/* PNG array */
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
create_image_item(screen, &test_img_lvgl_logo_png, "Array");
/* 32 bit PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo.png", "File (32 bit)");
/* No extension PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_png_no_ext", "File (32 bit) No Extension");
/* 8 bit palette PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_8bit_palette.png", "File (8 bit palette)");
}
void test_libpng_1(void)
{
/* Temporarily remove lodepng decoder */
lv_lodepng_deinit();
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 32);
/* Re-add lodepng decoder */
lv_lodepng_init();
}
#endif
@@ -0,0 +1,79 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void create_image_item(lv_obj_t * parent, const void * src, const char * text)
{
lv_obj_t * cont = lv_obj_create(parent);
lv_obj_remove_style_all(cont);
lv_obj_set_size(cont, 300, 200);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * img = lv_image_create(cont);
lv_image_set_src(img, src);
lv_obj_t * label = lv_label_create(cont);
lv_label_set_text(label, text);
}
static void create_images(void)
{
lv_obj_t * screen = lv_screen_active();
lv_obj_clean(screen);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
/* PNG array */
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
create_image_item(screen, &test_img_lvgl_logo_png, "Array");
/* 32 bit PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo.png", "File (32 bit)");
/* No extension PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_png_no_ext", "File (32 bit) No Extension");
/* 8 bit palette PNG file */
create_image_item(screen, "A:src/test_assets/test_img_lvgl_logo_8bit_palette.png", "File (8 bit palette)");
}
void test_lodepng_1(void)
{
/* Temporarily remove libpng decoder */
lv_libpng_deinit();
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 40);
/* Re-add libpng decoder */
lv_libpng_init();
}
#endif
@@ -0,0 +1,54 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_memmove(void)
{
#if LV_USE_STDLIB_STRING == LV_STDLIB_BUILTIN
char buf[6] = {0, 1, 2, 3, 4, 5};
char * dst;
char * src;
dst = buf;
src = buf;
/*Case of dst == src*/
lv_memmove(dst, src, 4);
for(int i = 0; i < 4; i++) {
TEST_ASSERT_EQUAL_INT(i, buf[i]);
}
/* Case of dst < src */
dst = &buf[0];
src = &buf[1];
lv_memmove(dst, src, 4);
for(int i = 0; i < 4; i++) {
TEST_ASSERT_EQUAL_INT(i + 1, buf[i]);
}
/* Case of dst > src */
for(int i = 0; i < 5; i++) buf[i] = i;
dst = &buf[1];
src = &buf[0];
lv_memmove(dst, src, 4);
TEST_ASSERT_EQUAL_INT(0, buf[0]);
for(int i = 1; i < 5; i++) {
TEST_ASSERT_EQUAL_INT(i - 1, buf[i]);
}
#endif
}
#endif
@@ -0,0 +1,61 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#if LV_USE_QRCODE
#include <string.h>
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_barcode_normal(void)
{
lv_color_t bg_color = lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 5);
lv_color_t fg_color = lv_palette_darken(LV_PALETTE_BLUE, 4);
lv_obj_t * qr = lv_qrcode_create(active_screen);
TEST_ASSERT_NOT_NULL(qr);
lv_qrcode_set_size(qr, 150);
lv_qrcode_set_dark_color(qr, fg_color);
lv_qrcode_set_light_color(qr, bg_color);
/*Set data*/
const char * data = "https://lvgl.io";
lv_result_t res = lv_qrcode_update(qr, data, strlen(data));
TEST_ASSERT_EQUAL(res, LV_RESULT_OK);
lv_obj_center(qr);
/*Add a border with bg_color*/
lv_obj_set_style_border_color(qr, bg_color, 0);
lv_obj_set_style_border_width(qr, 5, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/qrcode_1.png");
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_barcode_normal(void)
{
}
#endif
#endif
@@ -0,0 +1,70 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void assert_screenshot(const char * path)
{
#ifndef NON_AMD64_BUILD
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "libs/%s.lp64.png", path);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
#else
char fn_buf[64];
lv_snprintf(fn_buf, sizeof(fn_buf), "libs/%s.lp32.png", path);
TEST_ASSERT_EQUAL_SCREENSHOT(fn_buf);
#endif
}
void test_svg_decoder(void)
{
LV_IMAGE_DECLARE(test_image_svg);
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_obj_set_size(img, lv_pct(100), lv_pct(50));
lv_obj_set_style_outline_width(img, 4, 0);
lv_image_set_src(img, &test_image_svg);
lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
assert_screenshot("svg_decoder_1");
}
void test_svg_decoder_file(void)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_obj_set_size(img, lv_pct(100), lv_pct(100));
lv_obj_set_style_outline_width(img, 4, 0);
lv_image_set_src(img, "A:src/test_assets/test_img_svg_tiger.svg");
lv_image_set_scale(img, 96);
lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
assert_screenshot("svg_decoder_2");
}
void test_svg_snapshot(void)
{
LV_IMAGE_DECLARE(test_image_svg);
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &test_image_svg);
lv_obj_center(img);
lv_draw_buf_t * draw_buf = lv_snapshot_take(img, LV_COLOR_FORMAT_ARGB8888);
lv_obj_add_flag(img, LV_OBJ_FLAG_HIDDEN);
lv_obj_t * img2 = lv_image_create(lv_screen_active());
lv_image_set_src(img2, draw_buf);
lv_obj_set_style_outline_width(img2, 2, 0);
lv_obj_set_style_outline_color(img2, lv_color_hex3(0xf00), 0);
lv_obj_center(img2);
assert_screenshot("svg_decoder_3");
lv_draw_buf_destroy(draw_buf);
}
#endif
@@ -0,0 +1,117 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_tiny_ttf_rendering_test(void)
{
#if LV_USE_TINY_TTF
/*Create a font*/
extern const uint8_t test_ubuntu_font[];
extern size_t test_ubuntu_font_size;
lv_font_t * font = lv_tiny_ttf_create_data(test_ubuntu_font, test_ubuntu_font_size, 30);
/*Create style with the new font*/
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, font);
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_bg_color(&style, lv_color_hex(0xffaaaa));
/*Create a label with the new style*/
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_add_style(label, &style, 0);
lv_label_set_text(label, "Hello world\n"
"I'm a font created with Tiny TTF\n"
"Accents: ÁÉÍÓÖŐÜŰ áéíóöőüű");
lv_obj_center(label);
#ifndef NON_AMD64_BUILD
TEST_ASSERT_EQUAL_SCREENSHOT("libs/tiny_ttf_1.png");
#endif
lv_obj_delete(label);
lv_tiny_ttf_destroy(font);
#else
TEST_PASS();
#endif
}
void test_tiny_ttf_kerning(void)
{
#if LV_USE_TINY_TTF
extern const uint8_t test_kern_one_otf[];
extern size_t test_kern_one_otf_size;
lv_font_t * font_normal = lv_tiny_ttf_create_data(test_kern_one_otf, test_kern_one_otf_size, 80);
lv_font_t * font_none = lv_tiny_ttf_create_data(test_kern_one_otf, test_kern_one_otf_size, 80);
lv_font_set_kerning(font_none, LV_FONT_KERNING_NONE);
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, lv_pct(90), lv_pct(90));
lv_obj_center(cont);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * label_normal = lv_label_create(cont);
lv_label_set_text(label_normal, "ıTuTuTı");
lv_obj_set_style_text_font(label_normal, font_normal, LV_PART_MAIN);
lv_obj_t * label_none = lv_label_create(cont);
lv_label_set_text(label_none, "ıTuTuTı");
lv_obj_set_style_text_font(label_none, font_none, LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/tiny_ttf_2.png");
lv_obj_delete(cont);
lv_tiny_ttf_destroy(font_normal);
lv_tiny_ttf_destroy(font_none);
#else
TEST_PASS();
#endif
}
void test_tiny_ttf_gpos(void)
{
#if LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT
lv_font_t * font_normal = lv_tiny_ttf_create_file("A:src/test_assets/test_gpos_one.ttf", 60);
lv_font_t * font_none = lv_tiny_ttf_create_file("A:src/test_assets/test_gpos_one.ttf", 60);
lv_font_set_kerning(font_none, LV_FONT_KERNING_NONE);
lv_obj_t * label_normal = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label_normal, LV_LABEL_LONG_WRAP);
lv_label_set_text(label_normal, "ĄJ Ąg Ąģ Ąj Ąȷ Qȷ ąj ąȷ gȷ ģȷ ıȷ ųȷ vȷ Va Vá Vą Vf Vfl V.");
lv_obj_set_style_text_font(label_normal, font_normal, LV_PART_MAIN);
lv_obj_set_width(label_normal, 700);
lv_obj_set_style_text_align(label_normal, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_align(label_normal, LV_ALIGN_CENTER, 0, -100);
lv_obj_t * label_none = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label_normal, LV_LABEL_LONG_WRAP);
lv_label_set_text(label_none, "ĄJ Ąg Ąģ Ąj Ąȷ Qȷ ąj ąȷ gȷ ģȷ ıȷ ųȷ vȷ Va Vá Vą Vf Vfl V.");
lv_obj_set_style_text_font(label_none, font_none, LV_PART_MAIN);
lv_obj_set_width(label_none, 700);
lv_obj_set_style_text_align(label_none, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_align(label_none, LV_ALIGN_CENTER, 0, 100);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/tiny_ttf_3.png");
lv_tiny_ttf_destroy(font_normal);
lv_tiny_ttf_destroy(font_none);
#else
TEST_IGNORE_MESSAGE("Ignoring test_tiny_ttf_gpos as it requires LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT");
#endif
}
#endif
@@ -0,0 +1,103 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void create_images(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * img;
lv_obj_t * label;
LV_IMAGE_DECLARE(test_img_lvgl_logo_jpg);
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &test_img_lvgl_logo_jpg);
lv_obj_align(img, LV_ALIGN_CENTER, -100, -20);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Array");
lv_obj_align(label, LV_ALIGN_CENTER, -100, 20);
img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, 100, -20);
label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "File");
lv_obj_align(label, LV_ALIGN_CENTER, 100, 20);
}
void test_tjpgd_1(void)
{
/* Temporarily remove libjpeg_turbo decoder */
lv_libjpeg_turbo_deinit();
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_1.png");
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_1.png");
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 32);
/* Re-add libjpeg_turbo decoder */
lv_libjpeg_turbo_init();
}
static void create_image_2(void)
{
LV_IMG_DECLARE(test_img_lvgl_logo_jpg);
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &test_img_lvgl_logo_jpg);
lv_obj_center(img);
lv_obj_set_size(img, 300, 200);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
}
void test_jdpgd_align_tile(void)
{
/* Temporarily remove libjpeg_turbo decoder */
lv_libjpeg_turbo_deinit();
create_image_2();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_3.png");
lv_obj_clean(lv_screen_active());
size_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
lv_obj_clean(lv_screen_active());
create_image_2();
lv_obj_invalidate(lv_screen_active());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_3.png");
lv_obj_clean(lv_screen_active());
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 0);
/* Re-add libjpeg_turbo decoder */
lv_libjpeg_turbo_init();
}
#endif
@@ -0,0 +1,174 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
static void simple_style(lv_obj_t * obj)
{
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN);
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_OFF);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN);
lv_obj_set_style_pad_all(obj, 0, LV_PART_MAIN);
lv_obj_set_style_margin_all(obj, 0, LV_PART_MAIN);
lv_obj_set_style_outline_pad(obj, 0, LV_PART_MAIN);
lv_obj_set_style_outline_width(obj, 0, LV_PART_MAIN);
}
static lv_obj_t * create_row(lv_flex_align_t main_place, int n_children)
{
lv_obj_t * row = lv_obj_create(lv_screen_active());
lv_obj_set_size(row, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, main_place, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
simple_style(row);
for(int i = 0; i < n_children; i++) {
lv_obj_t * child = lv_obj_create(row);
lv_obj_set_size(child, 40, 40);
lv_obj_set_style_bg_color(child, lv_palette_main(LV_PALETTE_BLUE), 0);
simple_style(child);
}
return row;
}
void test_align(void)
{
create_row(LV_FLEX_ALIGN_CENTER, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_center1.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_CENTER, 2);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_center2.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_EVENLY, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_evenly1.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_EVENLY, 2);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_evenly2.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_AROUND, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_around1.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_AROUND, 2);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_around2.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_BETWEEN, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_between1.png");
lv_obj_clean(active_screen);
create_row(LV_FLEX_ALIGN_SPACE_BETWEEN, 2);
TEST_ASSERT_EQUAL_SCREENSHOT("align_flex_space_between2.png");
lv_obj_clean(active_screen);
}
/*See https://github.com/lvgl/lvgl/issues/7035*/
void test_wrap_grow_min_width(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
for(int i = 0; i < 14; i++) {
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_style_min_width(obj, 100, 0);
lv_obj_set_style_pad_all(obj, 0, 0);
lv_obj_set_height(obj, 70 + (i % 3) * 20);
uint8_t grow = (i % 3);
lv_obj_set_flex_grow(obj, grow);
if(i == 9) {
lv_obj_add_flag(obj, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
}
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text_fmt(label, "grow:%d%s", grow, i == 9 ? "\nnew track" : "");
lv_obj_center(label);
}
TEST_ASSERT_EQUAL_SCREENSHOT("flex_wrap_grow_min_width.png");
}
static lv_obj_t * cont_row_5_create(void)
{
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_center(cont);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW);
for(int i = 0; i < 5; i++) {
lv_obj_t * btn = lv_button_create(cont);
lv_obj_set_size(btn, 40, 60);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text_fmt(label, "%d", i);
lv_obj_center(label);
}
return cont;
}
static void hide(lv_obj_t * cont, uint32_t idx)
{
lv_obj_add_flag(lv_obj_get_child(cont, idx), LV_OBJ_FLAG_HIDDEN);
}
void test_flex_hide_items(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_t * cont;
cont = cont_row_5_create();
cont = cont_row_5_create();
hide(cont, 0);
cont = cont_row_5_create();
hide(cont, 0);
hide(cont, 1);
cont = cont_row_5_create();
hide(cont, 4);
cont = cont_row_5_create();
hide(cont, 3);
hide(cont, 4);
cont = cont_row_5_create();
hide(cont, 0);
hide(cont, 1);
hide(cont, 3);
hide(cont, 4);
cont = cont_row_5_create();
hide(cont, 1);
hide(cont, 3);
cont = cont_row_5_create();
hide(cont, 0);
hide(cont, 4);
TEST_ASSERT_EQUAL_SCREENSHOT("flex_hide_items.png");
}
#endif
@@ -0,0 +1,196 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
lv_anim_delete_all();
}
static void exec_cb(void * var, int32_t v)
{
int32_t * var_i32 = var;
*var_i32 = v;
}
static void custom_exec_cb(lv_anim_t * a, int32_t v)
{
int32_t * var_i32 = a->var;
*var_i32 = v;
}
void test_anim_delete(void)
{
int32_t var;
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, &var);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_exec_cb(&a, exec_cb);
lv_anim_set_duration(&a, 100);
lv_anim_start(&a);
lv_test_wait(20);
TEST_ASSERT_EQUAL(19, var);
bool deleted;
/*Wrong variable, nothing should happen*/
deleted = lv_anim_delete(&a, exec_cb);
TEST_ASSERT_FALSE(deleted);
lv_test_wait(20);
TEST_ASSERT_EQUAL(39, var);
/*The value shouldn't change after delete*/
deleted = lv_anim_delete(&var, exec_cb);
TEST_ASSERT_TRUE(deleted);
lv_test_wait(20);
TEST_ASSERT_EQUAL(39, var);
}
void test_anim_delete_custom(void)
{
int32_t var;
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, &var);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_custom_exec_cb(&a, custom_exec_cb);
lv_anim_set_duration(&a, 100);
lv_anim_start(&a);
lv_test_wait(20);
TEST_ASSERT_EQUAL(19, var);
bool deleted;
/*Wrong callback, nothing should happen*/
deleted = lv_anim_delete(&var, exec_cb);
TEST_ASSERT_FALSE(deleted);
lv_test_wait(20);
TEST_ASSERT_EQUAL(39, var);
/*The value shouldn't change after delete*/
deleted = lv_anim_delete(&var, NULL);
TEST_ASSERT_TRUE(deleted);
lv_test_wait(20);
TEST_ASSERT_EQUAL(39, var);
}
void test_anim_pause(void)
{
int32_t var;
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, &var);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_exec_cb(&a, exec_cb);
lv_anim_set_duration(&a, 100);
lv_anim_t * animation = lv_anim_start(&a);
lv_test_wait(40);
TEST_ASSERT_EQUAL(39, var);
lv_anim_pause(animation);
lv_test_wait(40);
TEST_ASSERT_EQUAL(39, var);
lv_anim_resume(animation);
lv_test_wait(20);
TEST_ASSERT_EQUAL(59, var);
lv_test_wait(41);
TEST_ASSERT_EQUAL(100, var);
}
void test_anim_pause_for(void)
{
int32_t var;
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, &var);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_exec_cb(&a, exec_cb);
lv_anim_set_duration(&a, 100);
lv_anim_t * animation = lv_anim_start(&a);
lv_anim_pause_for(animation, 20);
lv_test_wait(40);
TEST_ASSERT_EQUAL(19, var);
lv_anim_pause_for(animation, 20);
lv_test_wait(40);
lv_test_wait(40);
TEST_ASSERT_EQUAL(79, var);
/*Delete the animation to avoid accessing it after return*/
lv_anim_delete(&var, exec_cb);
}
void test_anim_pause_for_resume(void)
{
int32_t var;
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, &var);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_exec_cb(&a, exec_cb);
lv_anim_set_duration(&a, 100);
lv_anim_t * animation = lv_anim_start(&a);
lv_anim_pause_for(animation, 40);
lv_test_wait(20);
lv_anim_resume(animation);
lv_test_wait(20);
TEST_ASSERT_EQUAL(19, var);
}
static void event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target_obj(e);
int * var = lv_event_get_user_data(e);
lv_anim_delete(obj, NULL);
*var += 1;
}
void test_scroll_anim_delete(void)
{
int var = 0;
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_add_event_cb(obj, event_cb, LV_EVENT_SCROLL_END, &var);
lv_obj_scroll_by(obj, 0, 100, LV_ANIM_ON);
lv_test_wait(20);
lv_obj_scroll_by(obj, 0, 100, LV_ANIM_ON);
TEST_ASSERT_EQUAL(1, var);
}
#endif
@@ -0,0 +1,610 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_anim_timeline_t * anim_timeline;
static uint32_t anim1_start_called;
static uint32_t anim2_start_called;
static uint32_t anim1_completed_called;
static uint32_t anim2_completed_called;
void setUp(void)
{
/* Function run before every test */
anim_timeline = NULL;
}
void tearDown(void)
{
/* Function run after every test */
if(anim_timeline) lv_anim_timeline_delete(anim_timeline);
lv_obj_clean(lv_screen_active());
}
void test_anim_timeline_progress_1(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_set_pos(obj, 30, 40);
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 0, 700);
lv_anim_set_duration(&a1, 1000);
anim_timeline = lv_anim_timeline_create();
TEST_ASSERT_NOT_NULL(anim_timeline);
lv_anim_timeline_add(anim_timeline, 0, &a1);
lv_anim_timeline_set_progress(anim_timeline, 0);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(0, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 65535);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 10000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(105, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 20000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(213, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 30000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(319, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 40000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(426, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 50000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(533, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 60000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(639, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 32768);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(350, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 65535);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
}
void test_anim_timeline_progress_2(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 0, 700);
lv_anim_set_duration(&a1, 1000);
lv_anim_t a2;
lv_anim_init(&a2);
lv_anim_set_exec_cb(&a2, (lv_anim_exec_xcb_t)lv_obj_set_y);
lv_anim_set_var(&a2, obj);
lv_anim_set_values(&a2, 0, 300);
lv_anim_set_duration(&a2, 1000);
/*
* |------X------|
* |------Y------|
* 0 500 1000 1500 ms
* 0 21845 43690 65535 progress
*/
anim_timeline = lv_anim_timeline_create();
lv_anim_timeline_add(anim_timeline, 0, &a1);
lv_anim_timeline_add(anim_timeline, 500, &a2);
lv_anim_timeline_set_progress(anim_timeline, 0);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(0, lv_obj_get_x(obj));
lv_anim_timeline_set_progress(anim_timeline, 65535);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(300, lv_obj_get_y(obj));
lv_anim_timeline_set_progress(anim_timeline, 10000);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(159, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(0, lv_obj_get_y(obj));
lv_anim_timeline_set_progress(anim_timeline, 21845);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(350, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(0, lv_obj_get_y(obj));
lv_anim_timeline_set_progress(anim_timeline, 32768);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(525, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(75, lv_obj_get_y(obj));
lv_anim_timeline_set_progress(anim_timeline, 43690);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(150, lv_obj_get_y(obj));
lv_anim_timeline_set_progress(anim_timeline, 65535);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
TEST_ASSERT_EQUAL(300, lv_obj_get_y(obj));
}
void test_anim_timeline_start(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_set_pos(obj, 70, 70);
/*
* |------1------|
* |-----Y-----|
* |--------Z--------|
* 0 200 1000 1500 2000 2500 3500 ms
* ? 50 100 200 400 700 value (px)
*/
anim_timeline = lv_anim_timeline_create();
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 50, 100);
lv_anim_set_duration(&a1, 800);
lv_anim_set_early_apply(&a1, false);
lv_anim_timeline_add(anim_timeline, 200, &a1);
lv_anim_set_values(&a1, 200, 300);
lv_anim_set_duration(&a1, 1000);
lv_anim_timeline_add(anim_timeline, 1500, &a1);
/*Overlap with the previous*/
lv_anim_set_values(&a1, 400, 700);
lv_anim_set_duration(&a1, 1500);
lv_anim_timeline_add(anim_timeline, 2000, &a1);
lv_anim_timeline_start(anim_timeline);
/*As doesn't start at the beginning keep the original value*/
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(70, lv_obj_get_x(obj));
lv_test_wait(199);
TEST_ASSERT_EQUAL(70, lv_obj_get_x(obj));
lv_test_wait(1); /*200*/
TEST_ASSERT_EQUAL(50, lv_obj_get_x(obj));
lv_test_wait(400); /*600*/
TEST_ASSERT_EQUAL(75, lv_obj_get_x(obj));
lv_test_wait(400); /*1000*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
/*There is a gap*/
lv_test_wait(100); /*1100*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
/*Should change it*/
lv_obj_set_x(obj, 10);
lv_test_wait(100); /*1200*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
lv_test_wait(300); /*1500*/
TEST_ASSERT_EQUAL(200, lv_obj_get_x(obj));
lv_test_wait(499); /*1999*/
TEST_ASSERT_EQUAL(249, lv_obj_get_x(obj));
lv_test_wait(1); /*2000*/
TEST_ASSERT_EQUAL(400, lv_obj_get_x(obj));
lv_test_wait(500); /*2500*/
TEST_ASSERT_EQUAL(499, lv_obj_get_x(obj));
lv_test_wait(500); /*3000*/
TEST_ASSERT_EQUAL(599, lv_obj_get_x(obj));
lv_test_wait(500); /*3500*/
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
lv_test_wait(500); /*3500*/
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
/*Nothing should change it*/
lv_obj_set_x(obj, 20);
lv_test_wait(100); /*3600*/
TEST_ASSERT_EQUAL(20, lv_obj_get_x(obj));
}
void test_anim_timeline_reverse(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_set_pos(obj, 70, 70);
/* Reverse this:
* |------1------|
* |-----Y-----|
* |--------Z--------|
* 0 200 1000 1500 2000 2500 3500 ms
* ? 50 100 200 300 700 value (px)
*/
anim_timeline = lv_anim_timeline_create();
lv_anim_timeline_set_reverse(anim_timeline, true);
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 50, 100);
lv_anim_set_duration(&a1, 800);
lv_anim_set_early_apply(&a1, false);
lv_anim_timeline_add(anim_timeline, 200, &a1);
lv_anim_set_values(&a1, 200, 300);
lv_anim_set_duration(&a1, 1000);
lv_anim_timeline_add(anim_timeline, 1500, &a1);
/*Overlap with the previous*/
lv_anim_set_values(&a1, 400, 700);
lv_anim_set_duration(&a1, 1500);
lv_anim_timeline_add(anim_timeline, 2000, &a1);
lv_anim_timeline_set_progress(anim_timeline, LV_ANIM_TIMELINE_PROGRESS_MAX);
lv_anim_timeline_start(anim_timeline); /*0 (3500)*/
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(700, lv_obj_get_x(obj));
lv_test_wait(999); /*999 (2501)*/
TEST_ASSERT_EQUAL(500, lv_obj_get_x(obj));
lv_test_wait(201); /*1200 (2300)*/
TEST_ASSERT_EQUAL(459, lv_obj_get_x(obj));
lv_test_wait(300); /*1500 (2000)*/
TEST_ASSERT_EQUAL(400, lv_obj_get_x(obj));
lv_test_wait(500); /*2000 (1500)*/
TEST_ASSERT_EQUAL(200, lv_obj_get_x(obj));
/*There is a gap*/
lv_test_wait(100); /*2100 (1400)*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
/*Should change it*/
lv_obj_set_x(obj, 10);
lv_test_wait(100); /*2200 (1300)*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
lv_test_wait(300); /*2500 (1000)*/
TEST_ASSERT_EQUAL(100, lv_obj_get_x(obj));
lv_test_wait(400); /*2900 (600)*/
TEST_ASSERT_EQUAL(75, lv_obj_get_x(obj));
lv_test_wait(400); /*3300 (200)*/
TEST_ASSERT_EQUAL(50, lv_obj_get_x(obj));
/*There is a gap*/
lv_test_wait(100); /*3400 (100)*/
TEST_ASSERT_EQUAL(50, lv_obj_get_x(obj));
/*Nothing should change it*/
lv_obj_set_x(obj, 20);
lv_test_wait(100);
TEST_ASSERT_EQUAL(20, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(20, lv_obj_get_x(obj));
}
void test_anim_timeline_repeat(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_set_pos(obj, 30, 40);
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 0, 1000);
lv_anim_set_duration(&a1, 1000);
anim_timeline = lv_anim_timeline_create();
TEST_ASSERT_NOT_NULL(anim_timeline);
lv_anim_timeline_add(anim_timeline, 0, &a1);
lv_anim_timeline_set_repeat_count(anim_timeline, 3);
lv_anim_timeline_set_repeat_delay(anim_timeline, 1);
lv_anim_timeline_start(anim_timeline);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(1, lv_anim_timeline_get_repeat_delay(anim_timeline));
TEST_ASSERT_EQUAL(1000, lv_anim_timeline_get_playtime(anim_timeline));
lv_test_wait(100);
TEST_ASSERT_EQUAL(99, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(599, lv_obj_get_x(obj));
lv_test_wait(400);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(1);
TEST_ASSERT_EQUAL(0, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(500, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(701);
TEST_ASSERT_EQUAL(699, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
}
void test_anim_timeline_delay(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_set_pos(obj, 30, 40);
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_var(&a1, obj);
lv_anim_set_values(&a1, 0, 1000);
lv_anim_set_duration(&a1, 1000);
anim_timeline = lv_anim_timeline_create();
TEST_ASSERT_NOT_NULL(anim_timeline);
lv_anim_timeline_add(anim_timeline, 0, &a1);
lv_anim_timeline_set_repeat_count(anim_timeline, 3);
lv_anim_timeline_set_repeat_delay(anim_timeline, 1000);
lv_anim_timeline_start(anim_timeline);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL(1000, lv_anim_timeline_get_repeat_delay(anim_timeline));
TEST_ASSERT_EQUAL(1000, lv_anim_timeline_get_playtime(anim_timeline));
lv_test_wait(100);
TEST_ASSERT_EQUAL(99, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(599, lv_obj_get_x(obj));
lv_test_wait(400);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(0, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(500, lv_obj_get_x(obj));
lv_test_wait(500);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(1700);
TEST_ASSERT_EQUAL(699, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
lv_test_wait(1000);
TEST_ASSERT_EQUAL(1000, lv_obj_get_x(obj));
}
void anim1_exec_cb(void * var, int32_t v)
{
LV_UNUSED(var);
LV_UNUSED(v);
}
void anim1_start(lv_anim_t * a)
{
LV_UNUSED(a);
anim1_start_called++;
}
void anim1_completed(lv_anim_t * a)
{
LV_UNUSED(a);
anim1_completed_called++;
}
void anim2_exec_cb(void * var, int32_t v)
{
LV_UNUSED(var);
LV_UNUSED(v);
}
void anim2_start(lv_anim_t * a)
{
LV_UNUSED(a);
anim2_start_called++;
}
void anim2_completed(lv_anim_t * a)
{
LV_UNUSED(a);
anim2_completed_called++;
}
void test_anim_timeline_with_anim_start_cb_and_completed_cb(void)
{
lv_anim_t anim1;
lv_anim_t anim2;
lv_anim_init(&anim1);
lv_anim_set_values(&anim1, 0, 1024);
lv_anim_set_duration(&anim1, 300);
lv_anim_set_exec_cb(&anim1, anim1_exec_cb);
lv_anim_set_start_cb(&anim1, anim1_start);
lv_anim_set_completed_cb(&anim1, anim1_completed);
anim1_start_called = 0;
anim1_completed_called = 0;
lv_memcpy(&anim2, &anim1, sizeof(anim1));
lv_anim_set_duration(&anim2, 300);
lv_anim_set_path_cb(&anim2, lv_anim_path_overshoot);
lv_anim_set_exec_cb(&anim2, anim2_exec_cb);
lv_anim_set_start_cb(&anim2, anim2_start);
lv_anim_set_completed_cb(&anim2, anim2_completed);
anim2_start_called = 0;
anim2_completed_called = 0;
anim_timeline = lv_anim_timeline_create();
lv_anim_timeline_add(anim_timeline, 0, &anim1);
lv_anim_timeline_add(anim_timeline, 200, &anim2);
lv_anim_timeline_set_progress(anim_timeline, 0);
lv_anim_timeline_start(anim_timeline);
lv_refr_now(NULL);
/* |----- Reverse ------|
* |-----anim1-----| |--anim1 rvs--|
* |----anim2----| |--anim2 rvs--|
*
* 0 200 300 500 600 800 900 1100
*/
lv_test_wait(20); /*Wait 20 ms*/
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
TEST_ASSERT_EQUAL(0, anim2_start_called);
TEST_ASSERT_EQUAL(0, anim2_completed_called);
lv_test_wait(200); /*Now we are at 220ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(0, anim2_completed_called);
lv_test_wait(100); /*Now we are at 320ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(1, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(0, anim2_completed_called);
lv_test_wait(200); /*Now we are at 520ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(1, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(1, anim2_completed_called);
lv_test_wait(80); /*Now we are at 600ms */
anim1_start_called = 0;
anim1_completed_called = 0;
anim2_start_called = 0;
anim2_completed_called = 0;
lv_anim_timeline_set_reverse(anim_timeline, true);
lv_anim_timeline_set_progress(anim_timeline, LV_ANIM_TIMELINE_PROGRESS_MAX);
lv_anim_timeline_start(anim_timeline);
lv_test_wait(20); /*Now we are at 620ms */
TEST_ASSERT_EQUAL(0, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(0, anim2_completed_called);
lv_test_wait(200); /*Now we are at 820ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(0, anim2_completed_called);
lv_test_wait(100); /*Now we are at 920ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(1, anim2_completed_called);
lv_test_wait(200); /*Now we are at 1120ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(1, anim1_completed_called);
TEST_ASSERT_EQUAL(1, anim2_start_called);
TEST_ASSERT_EQUAL(1, anim2_completed_called);
}
void test_anim_timeline_without_exec_cb_but_anim_start_cb_and_completed_cb(void)
{
lv_anim_t anim1;
lv_anim_init(&anim1);
lv_anim_set_values(&anim1, 0, 1024);
lv_anim_set_duration(&anim1, 300);
lv_anim_set_exec_cb(&anim1, anim1_exec_cb);
lv_anim_set_start_cb(&anim1, anim1_start);
lv_anim_set_completed_cb(&anim1, anim1_completed);
anim1_start_called = 0;
anim1_completed_called = 0;
anim_timeline = lv_anim_timeline_create();
lv_anim_timeline_add(anim_timeline, 200, &anim1);
lv_anim_timeline_set_progress(anim_timeline, 0);
lv_anim_timeline_start(anim_timeline);
lv_refr_now(NULL);
/*
* |----anim1----|
*
* 0 200 300 500
*/
lv_test_wait(20); /*Wait 20 ms*/
TEST_ASSERT_EQUAL(0, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
lv_test_wait(200); /*Now we are at 220ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(0, anim1_completed_called);
lv_test_wait(300); /*Now we are at 520ms */
TEST_ASSERT_EQUAL(1, anim1_start_called);
TEST_ASSERT_EQUAL(1, anim1_completed_called);
}
#endif
@@ -0,0 +1,278 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#define PCT_MAX_VALUE 268435455
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_pct(void)
{
int32_t pct_val;
int32_t pct_coord;
pct_val = 0;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = 1;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = 100;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = 111111111;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = PCT_MAX_VALUE;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = -1;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = -100;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = -111111111;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
pct_val = -PCT_MAX_VALUE;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(pct_val, LV_COORD_GET_PCT(pct_coord));
/**
* Out of bounds behavior.
* The pct value will be clamped to the max/min value if it's out of bounds.
*/
pct_val = PCT_MAX_VALUE + 1;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(PCT_MAX_VALUE, LV_COORD_GET_PCT(pct_coord));
pct_val = PCT_MAX_VALUE + 100;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(PCT_MAX_VALUE, LV_COORD_GET_PCT(pct_coord));
pct_val = -PCT_MAX_VALUE - 1;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(-PCT_MAX_VALUE, LV_COORD_GET_PCT(pct_coord));
pct_val = -PCT_MAX_VALUE - 100;
pct_coord = lv_pct(pct_val);
TEST_ASSERT_TRUE(LV_COORD_IS_PCT(pct_coord));
TEST_ASSERT_FALSE(LV_COORD_IS_PX(pct_coord));
TEST_ASSERT_TRUE(LV_COORD_IS_SPEC(pct_coord));
TEST_ASSERT_EQUAL_INT32(-PCT_MAX_VALUE, LV_COORD_GET_PCT(pct_coord));
}
void test_area_diff(void)
{
lv_area_t expected[4] = {
{0, 0, 100, 29}, /* wide top rectangle */
{0, 91, 100, 100}, /* wide bottom rectangle */
{0, 30, 39, 90}, /* left rectangle */
{81, 30, 100, 90} /* right rectangle */
};
lv_area_t outer = {0, 0, 100, 100};
lv_area_t remove = {40, 30, 80, 90};
lv_area_t actual[4];
lv_memset(actual, 0, sizeof(actual));
int8_t area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 4);
TEST_PRINTF("%d %d %d %d", actual[0].x1, actual[0].y1, actual[0].x2, actual[0].y2);
TEST_ASSERT_TRUE(lv_area_is_equal(&expected[0], &actual[0]));
TEST_PRINTF("%d %d %d %d", actual[1].x1, actual[1].y1, actual[1].x2, actual[1].y2);
TEST_ASSERT_TRUE(lv_area_is_equal(&expected[1], &actual[1]));
TEST_PRINTF("%d %d %d %d", actual[2].x1, actual[2].y1, actual[2].x2, actual[2].y2);
TEST_ASSERT_TRUE(lv_area_is_equal(&expected[2], &actual[2]));
TEST_PRINTF("%d %d %d %d", actual[3].x1, actual[3].y1, actual[3].x2, actual[3].y2);
TEST_ASSERT_TRUE(lv_area_is_equal(&expected[3], &actual[3]));
/* no left edge */
lv_area_set(&remove, 0, 10, 10, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 3);
lv_area_set(&remove, 1, 10, 10, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 4);
/* no right edge */
lv_area_set(&remove, 90, 10, 100, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 3);
lv_area_set(&remove, 90, 10, 99, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 4);
/* no top edge */
lv_area_set(&remove, 10, 0, 20, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 3);
lv_area_set(&remove, 10, 1, 20, 20);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 4);
/* no bottom edge */
lv_area_set(&remove, 10, 90, 20, 100);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 3);
lv_area_set(&remove, 10, 90, 20, 99);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 4);
/* top and left edges missing */
lv_area_set(&remove, -50, -50, 50, 50);
area_count = lv_area_diff(actual, &outer, &remove);
TEST_ASSERT_EQUAL_INT8(area_count, 2);
}
#define GRID_WIDTH 5
#define GRID_HEIGHT 5
static void grid_assert_equal(char grid1[GRID_HEIGHT][GRID_WIDTH], char grid2[GRID_HEIGHT][GRID_WIDTH])
{
for(int y = 0; y < GRID_HEIGHT; y++) {
for(int x = 0; x < GRID_WIDTH; x++) {
TEST_ASSERT_EQUAL_CHAR(grid1[y][x], grid2[y][x]);
}
}
}
static void grid_mark(char grid[GRID_HEIGHT][GRID_WIDTH], const lv_area_t * area, char c, bool assert_change)
{
for(int y = area->y1; y <= area->y2; y++) {
for(int x = area->x1; x <= area->x2; x++) {
if(assert_change) TEST_ASSERT_NOT_EQUAL_CHAR(grid[y][x], c);
grid[y][x] = c;
}
}
}
static void grid_mark_area_diff_simple(char grid[GRID_HEIGHT][GRID_WIDTH], const lv_area_t * outer,
const lv_area_t * remove)
{
grid_mark(grid, outer, 'x', true);
lv_area_t intersection;
if(lv_area_intersect(&intersection, outer, remove)) {
grid_mark(grid, &intersection, ' ', true);
}
}
static void grid_mark_area_diff(char grid[GRID_HEIGHT][GRID_WIDTH], const lv_area_t * outer, const lv_area_t * remove)
{
lv_area_t parts[4];
int8_t num_parts = lv_area_diff(parts, outer, remove);
if(num_parts < 0) {
grid_mark(grid, outer, 'x', true);
}
for(int i = 0; i < num_parts; i++) {
grid_mark(grid, &parts[i], 'x', true);
}
}
void test_area_diff_property()
{
lv_rand_set_seed(7875);
char grid_simple[GRID_HEIGHT][GRID_WIDTH];
char grid[GRID_HEIGHT][GRID_WIDTH];
lv_area_t everything;
everything.x1 = 0;
everything.y1 = 0;
everything.x2 = GRID_WIDTH - 1;
everything.y2 = GRID_HEIGHT - 1;
for(int test = 0; test < 200; test++) {
lv_area_t outer;
outer.x1 = lv_rand(0, GRID_WIDTH - 1);
outer.y1 = lv_rand(0, GRID_HEIGHT - 1);
outer.x2 = lv_rand(outer.x1, GRID_WIDTH - 1);
outer.y2 = lv_rand(outer.y1, GRID_HEIGHT - 1);
lv_area_t remove;
remove.x1 = lv_rand(0, GRID_WIDTH - 1);
remove.y1 = lv_rand(0, GRID_HEIGHT - 1);
remove.x2 = lv_rand(remove.x1, GRID_WIDTH - 1);
remove.y2 = lv_rand(remove.y1, GRID_HEIGHT - 1);
TEST_PRINTF("%d %d %d %d / %d %d %d %d", outer.x1, outer.y1, outer.x2, outer.y2, remove.x1, remove.y1, remove.x2,
remove.y2);
/*Mark remaining area using simple algorithm*/
grid_mark(grid_simple, &everything, ' ', false);
grid_mark_area_diff_simple(grid_simple, &outer, &remove);
/*Mark remaining area using more efficient lv_area_diff()*/
grid_mark(grid, &everything, ' ', false);
grid_mark_area_diff(grid, &outer, &remove);
grid_assert_equal(grid_simple, grid);
}
}
#endif
@@ -0,0 +1,103 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_array_t array;
void setUp(void)
{
lv_array_init(&array, LV_ARRAY_DEFAULT_CAPACITY, sizeof(int32_t));
}
void tearDown(void)
{
lv_array_deinit(&array);
}
void test_array_append_values(void)
{
const int32_t new_size = LV_ARRAY_DEFAULT_CAPACITY + 2;
TEST_ASSERT_EQUAL_UINT32(0, lv_array_size(&array));
for(int32_t i = 0; i < new_size; i++) {
lv_array_push_back(&array, &i);
}
/*push back will automatically extent the array size.*/
TEST_ASSERT_EQUAL_UINT32(new_size, lv_array_size(&array));
}
void test_array_set_get(void)
{
int32_t v = 100;
lv_array_push_back(&array, &v);
int32_t * r = lv_array_at(&array, 0);
TEST_ASSERT_EQUAL_UINT32(100, *r);
}
void test_array_size(void)
{
for(int32_t i = 0; i < 10; i++) {
lv_array_push_back(&array, &i);
}
TEST_ASSERT_EQUAL_UINT32(0, lv_array_is_full(&array) ? 1 : 0);
lv_array_clear(&array);
TEST_ASSERT_EQUAL_UINT32(1, lv_array_is_empty(&array) ? 1 : 0);
TEST_ASSERT_EQUAL_UINT32(0, lv_array_size(&array));
}
void test_array_resize(void)
{
for(int32_t i = 0; i < LV_ARRAY_DEFAULT_CAPACITY; i++) {
lv_array_push_back(&array, &i);
}
TEST_ASSERT_EQUAL_UINT32(LV_ARRAY_DEFAULT_CAPACITY, lv_array_size(&array));
lv_array_resize(&array, 12);
TEST_ASSERT_EQUAL_UINT32(LV_ARRAY_DEFAULT_CAPACITY, lv_array_size(&array));
TEST_ASSERT_EQUAL_UINT32(12, lv_array_capacity(&array));
lv_array_resize(&array, 6);
TEST_ASSERT_EQUAL_UINT32(LV_ARRAY_DEFAULT_CAPACITY, lv_array_size(&array));
TEST_ASSERT_EQUAL_UINT32(6, lv_array_capacity(&array));
}
void test_array_copy(void)
{
for(int32_t i = 0; i < LV_ARRAY_DEFAULT_CAPACITY; i++) {
lv_array_push_back(&array, &i);
}
uint32_t array_size = lv_array_size(&array);
lv_array_t array2 = { 0 };
lv_array_copy(&array2, &array);
TEST_ASSERT_EQUAL_UINT32(array_size, lv_array_size(&array2));
uint32_t * r = lv_array_at(&array2, 1);
TEST_ASSERT_EQUAL_UINT32(1, *r);
lv_array_deinit(&array2);
}
void test_array_concat(void)
{
lv_array_t a, b;
lv_array_init(&a, 4, sizeof(int32_t));
lv_array_init(&b, 4, sizeof(int32_t));
for(int32_t i = 0; i < 4; i++) {
lv_array_push_back(&a, &i);
lv_array_push_back(&b, &i);
}
TEST_ASSERT_TRUE(lv_array_concat(&a, &b) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_UINT32(8, lv_array_size(&a));
for(int32_t i = 0; i < 8; i++) {
int32_t * v = lv_array_at(&a, i);
TEST_ASSERT_EQUAL_INT32(i % 4, *v);
}
lv_array_deinit(&a);
lv_array_deinit(&b);
}
#endif
@@ -0,0 +1,270 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static void create_ui(void);
static void chart_type_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void buttonmatrix_event_cb(lv_event_t * e);
static lv_obj_t * list_button_create(lv_obj_t * parent);
static void opa_anim_cb(void * var, int32_t v);
static void draw_to_canvas(lv_obj_t * canvas);
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_binding(void)
{
create_ui();
/*Wait for the animation*/
lv_test_wait(500);
TEST_ASSERT_EQUAL_SCREENSHOT("binding.png");
}
static void create_ui(void)
{
/*Create a colors*/
lv_color_t c1 = lv_color_hex(0xff0000);
lv_color_t c2 = lv_palette_darken(LV_PALETTE_BLUE, 2);
lv_color_t c3 = lv_color_mix(c1, c2, LV_OPA_60);
/*Create a style*/
static lv_style_t style_big_font;
lv_style_init(&style_big_font);
/*Use a built-in font*/
lv_style_set_text_font(&style_big_font, &lv_font_montserrat_24);
/*Get the active screen*/
lv_obj_t * scr = lv_screen_active();
/*Declare static array of integers, and test grid setting options*/
static int32_t gird_cols[] = {300, LV_GRID_FR(3), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST};
static int32_t gird_rows[] = {100, LV_GRID_FR(1), LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
lv_obj_set_grid_dsc_array(scr, gird_cols, gird_rows);
static lv_subject_t chart_type_subject;
lv_subject_init_int(&chart_type_subject, 0);
/*Create a widget*/
lv_obj_t * dropdown = lv_dropdown_create(scr);
/*Pass a string as argument*/
lv_dropdown_set_options(dropdown, "Lines\nBars");
/*Use grid align options*/
lv_obj_set_grid_cell(dropdown, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
/*Bind to a subject*/
lv_dropdown_bind_value(dropdown, &chart_type_subject);
/*Create a chart with an external array of points*/
lv_obj_t * chart = lv_chart_create(lv_screen_active());
lv_obj_set_grid_cell(chart, LV_GRID_ALIGN_STRETCH, 0, 1, LV_GRID_ALIGN_CENTER, 1, 1);
lv_chart_series_t * series = lv_chart_add_series(chart, c3, LV_CHART_AXIS_PRIMARY_X);
static int32_t chart_y_array[10] = {10, 25, 50, 40, 30, 35, 60, 65, 70, 75};
lv_chart_set_series_ext_y_array(chart, series, chart_y_array);
/*Add custom observer callback*/
lv_subject_add_observer_obj(&chart_type_subject, chart_type_observer_cb, chart, NULL);
/*Manually set the subject's value*/
lv_subject_set_int(&chart_type_subject, 1);
lv_obj_t * label = lv_label_create(scr);
lv_obj_set_grid_cell(label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
/*Apply styles on main part and default state*/
lv_obj_set_style_bg_opa(label, LV_OPA_70, 0);
lv_obj_set_style_bg_color(label, c1, 0);
lv_obj_set_style_text_color(label, c2, 0);
lv_obj_add_style(label, &style_big_font, 0);
/*Declare an array of strings*/
static const char * btnmatrix_options[] = {
"First", "Second", "\n",
"Third", ""
};
static const lv_buttonmatrix_ctrl_t btnmatrix_ctrl[] = {
LV_BUTTONMATRIX_CTRL_DISABLED, 2 | LV_BUTTONMATRIX_CTRL_CHECKED,
1,
};
lv_obj_t * btnmatrix = lv_buttonmatrix_create(scr);
lv_obj_set_grid_cell(btnmatrix, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_STRETCH, 1, 1);
/*Pass string and enum arrays*/
lv_buttonmatrix_set_map(btnmatrix, btnmatrix_options);
lv_buttonmatrix_set_ctrl_map(btnmatrix, btnmatrix_ctrl);
/*Add style to non main part and non default state*/
lv_obj_add_style(btnmatrix, &style_big_font, LV_PART_ITEMS | LV_STATE_CHECKED);
lv_buttonmatrix_set_selected_button(btnmatrix, 1);
lv_obj_add_event_cb(btnmatrix, buttonmatrix_event_cb, LV_EVENT_VALUE_CHANGED, label);
lv_obj_send_event(btnmatrix, LV_EVENT_VALUE_CHANGED, NULL);
/*Create a base object*/
lv_obj_t * cont = lv_obj_create(scr);
/*Span 2 rows*/
lv_obj_set_grid_cell(cont, LV_GRID_ALIGN_STRETCH, 2, 1, LV_GRID_ALIGN_STRETCH, 0, 2);
/*Apply flex layout*/
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
/*For loop*/
uint32_t i;
for(i = 0; i < 10; i++) {
/*Call a function implemented in the binding which returns a widget*/
lv_obj_t * btn = list_button_create(cont);
if(i == 0) {
/*Start an animation*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, btn);
lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_50);
lv_anim_set_exec_cb(&a, opa_anim_cb); /*Pass a callback*/
lv_anim_set_duration(&a, 300);
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
lv_anim_start(&a);
}
if(i == 1) {
/*Use flags*/
lv_obj_add_flag(btn, LV_OBJ_FLAG_HIDDEN);
}
if(i == 2) {
lv_obj_t * btn_label = lv_obj_get_child(btn, 0);
lv_label_set_text(btn_label, "A multi-line text with a ° symbol");
lv_obj_set_width(btn_label, lv_pct(100));
}
if(i == 3) {
/*Start an infinite animation and delete this button later*/
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, btn);
lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_50);
lv_anim_set_exec_cb(&a, opa_anim_cb); /*Pass a callback*/
lv_anim_set_duration(&a, 300);
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
lv_anim_start(&a);
}
}
/*Wait and delete the button with the animation*/
lv_test_wait(300);
lv_obj_delete(lv_obj_get_child(cont, 3));
/*Large byte array*/
static uint8_t canvas_buf[LV_CANVAS_BUF_SIZE(400, 100, 16, LV_DRAW_BUF_STRIDE_ALIGN)];
lv_obj_t * canvas = lv_canvas_create(scr);
lv_obj_set_grid_cell(canvas, LV_GRID_ALIGN_START, 0, 2, LV_GRID_ALIGN_START, 2, 1);
/*Test RGB565 rendering*/
lv_canvas_set_buffer(canvas, lv_draw_buf_align(canvas_buf, LV_COLOR_FORMAT_RGB565), 400, 100, LV_COLOR_FORMAT_RGB565);
lv_canvas_fill_bg(canvas, c2, LV_OPA_COVER);
draw_to_canvas(canvas);
LV_IMAGE_DECLARE(test_img_lvgl_logo_jpg);
lv_obj_t * img;
img = lv_image_create(scr);
lv_image_set_src(img, &test_img_lvgl_logo_jpg);
lv_obj_align(img, LV_ALIGN_BOTTOM_RIGHT, -20, -20);
lv_obj_add_flag(img, LV_OBJ_FLAG_IGNORE_LAYOUT);
img = lv_image_create(scr);
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.png");
lv_obj_set_pos(img, 500, 420);
lv_obj_add_flag(img, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_image_set_rotation(img, 200);
lv_image_set_scale_x(img, 400);
}
static void chart_type_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
int32_t v = lv_subject_get_int(subject);
lv_obj_t * chart = lv_observer_get_target(observer);
lv_chart_set_type(chart, v == 0 ? LV_CHART_TYPE_LINE : LV_CHART_TYPE_BAR);
}
static void buttonmatrix_event_cb(lv_event_t * e)
{
lv_obj_t * label = lv_event_get_user_data(e);
lv_obj_t * buttonmatrix = lv_event_get_target(e);
uint32_t idx = lv_buttonmatrix_get_selected_button(buttonmatrix);
const char * text = lv_buttonmatrix_get_button_text(buttonmatrix, idx);
lv_label_set_text(label, text);
}
static lv_obj_t * list_button_create(lv_obj_t * parent)
{
lv_obj_t * btn = lv_button_create(parent);
lv_obj_set_size(btn, lv_pct(100), LV_SIZE_CONTENT);
/*Get an integer*/
uint32_t idx = lv_obj_get_index(btn);
/*Formatted string for label*/
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text_fmt(label, LV_SYMBOL_FILE " Item %d", idx);
return btn;
}
static void opa_anim_cb(void * var, int32_t v)
{
lv_obj_set_style_opa(var, v, 0);
}
static void draw_to_canvas(lv_obj_t * canvas)
{
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
/*Use draw descriptors*/
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
lv_draw_image_dsc_t image_draw_dsc;
lv_draw_image_dsc_init(&image_draw_dsc);
image_draw_dsc.src = &test_img_lvgl_logo_png;
lv_area_t coords = {10, 10, 10 + test_img_lvgl_logo_png.header.w - 1, 10 + test_img_lvgl_logo_png.header.h - 1};
lv_draw_image(&layer, &image_draw_dsc, &coords);
/*Reuse the draw descriptor*/
lv_area_move(&coords, 40, 40);
image_draw_dsc.opa = LV_OPA_50;
lv_draw_image(&layer, &image_draw_dsc, &coords);
lv_draw_line_dsc_t line_draw_dsc;
lv_draw_line_dsc_init(&line_draw_dsc);
line_draw_dsc.color = lv_color_hex3(0xCA8);
line_draw_dsc.width = 8;
line_draw_dsc.round_end = 1;
line_draw_dsc.round_start = 1;
lv_point_precise_set(&line_draw_dsc.p1, 150, 30);
lv_point_precise_set(&line_draw_dsc.p2, 350, 55);
lv_draw_line(&layer, &line_draw_dsc);
lv_canvas_finish_layer(canvas, &layer);
lv_color_t c = lv_color_hex(0xff0000);
uint32_t i;
for(i = 0; i < 50; i++) {
lv_canvas_set_px(canvas, 100 + i * 2, 10, c, LV_OPA_COVER);
}
}
#endif
@@ -0,0 +1,211 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_circle_buf_t * circle_buf;
#define circle_buf_CAPACITY 4
void setUp(void)
{
circle_buf = lv_circle_buf_create(circle_buf_CAPACITY, sizeof(int32_t));
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_capacity(circle_buf), circle_buf_CAPACITY);
TEST_ASSERT_EQUAL_UINT32(0, lv_circle_buf_size(circle_buf));
/**
* Write values to the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is full, the write operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 0; i < circle_buf_CAPACITY * 2; i++) {
const lv_result_t res = lv_circle_buf_write(circle_buf, &i);
if(i < circle_buf_CAPACITY) TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
else TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
/**
* After writing values to the buffer, the size of the buffer should be equal to the capacity.
*/
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_size(circle_buf), circle_buf_CAPACITY);
}
void tearDown(void)
{
lv_circle_buf_destroy(circle_buf);
circle_buf = NULL;
}
void test_circle_buf_read_write_peek_values(void)
{
/**
* Read 1 value from the buffer.
*/
{
int32_t value;
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(0, value);
}
/**
* Peek values will not advance the read and write cursors.
* If the peek index is greater than the size of the buffer, it will returns looply.
*/
for(int32_t i = 0, j = 1; i < circle_buf_CAPACITY * 10; i++, j++) {
int32_t value;
const lv_result_t res = lv_circle_buf_peek_at(circle_buf, i, &value);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(j, value);
if(j == 3) j = 0;
}
/**
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
int32_t value;
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
if(i < circle_buf_CAPACITY) {
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(i, value);
}
else {
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
}
/**
* After reading values from the buffer, the size of the buffer should be equal to 0.
*/
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
}
void test_circle_buf_skip_values(void)
{
/**
* Skip 1 value from the buffer.
*/
{
const lv_result_t res = lv_circle_buf_skip(circle_buf);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
}
/**
* Skip values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is empty, the skip operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
const lv_result_t res = lv_circle_buf_skip(circle_buf);
if(i < circle_buf_CAPACITY) {
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
}
else {
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
}
/**
* After skipping values from the buffer, the size of the buffer should be equal to 0.
*/
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
}
void test_circle_buf_read_after_read_and_write(void)
{
/**
* Read 1 value from the buffer.
*/
{
int32_t value;
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(0, value);
}
/**
* Write 1 value to the buffer.
*/
{
const int32_t value = 4;
const lv_result_t res = lv_circle_buf_write(circle_buf, &value);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
}
const int32_t expected[] = {4, 1, 2, 3};
TEST_ASSERT_EQUAL_INT32_ARRAY(expected, ((lv_array_t *)circle_buf)->data, 4);
/**
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
int32_t value;
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
if(i <= circle_buf_CAPACITY) {
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(i, value);
}
else {
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
}
}
void test_circle_buf_reset(void)
{
/**
* Reset the circle buffer, now the buffer should be empty just like lv_circle_buf_create.
*/
lv_circle_buf_reset(circle_buf);
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_capacity(circle_buf), circle_buf_CAPACITY);
TEST_ASSERT_EQUAL_UINT32(0, lv_circle_buf_size(circle_buf));
/**
* Write values to the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is full, the write operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 0; i < circle_buf_CAPACITY * 2; i++) {
const lv_result_t res = lv_circle_buf_write(circle_buf, &i);
if(i < circle_buf_CAPACITY) TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
else TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
/**
* After writing values to the buffer, the size of the buffer should be equal to the capacity.
*/
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_size(circle_buf), circle_buf_CAPACITY);
/**
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
*/
for(int32_t i = 0; i < circle_buf_CAPACITY * 2; i++) {
int32_t value;
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
if(i < circle_buf_CAPACITY) {
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
TEST_ASSERT_EQUAL_INT32(i, value);
}
else {
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
}
}
}
#endif
@@ -0,0 +1,163 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
struct click_counts {
uint32_t num_clicked;
uint32_t num_short_clicked;
uint32_t num_single_clicked;
uint32_t num_double_clicked;
uint32_t num_triple_clicked;
uint32_t num_long_pressed;
uint8_t short_click_streak;
};
static void click_event_cb(lv_event_t * e)
{
struct click_counts * counts = lv_event_get_user_data(e);
switch(lv_event_get_code(e)) {
case LV_EVENT_CLICKED:
counts->num_clicked++;
break;
case LV_EVENT_SHORT_CLICKED:
counts->num_short_clicked++;
break;
case LV_EVENT_SINGLE_CLICKED:
counts->num_single_clicked++;
break;
case LV_EVENT_DOUBLE_CLICKED:
counts->num_double_clicked++;
break;
case LV_EVENT_TRIPLE_CLICKED:
counts->num_triple_clicked++;
break;
case LV_EVENT_LONG_PRESSED:
counts->num_long_pressed++;
break;
default:
break;
}
lv_indev_t * indev = lv_event_get_param(e);
counts->short_click_streak = lv_indev_get_short_click_streak(indev);
}
void test_click(void)
{
/*Setup button that counts events.*/
struct click_counts counts;
lv_obj_t * btn = lv_button_create(lv_screen_active());
lv_obj_set_size(btn, 100, 100);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_CLICKED, &counts);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_SHORT_CLICKED, &counts);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_SINGLE_CLICKED, &counts);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_DOUBLE_CLICKED, &counts);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_TRIPLE_CLICKED, &counts);
lv_obj_add_event_cb(btn, click_event_cb, LV_EVENT_LONG_PRESSED, &counts);
/*Simple click.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(50, 50);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(1, counts.short_click_streak);
/*Second click nearby.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(47, 52);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(2, counts.short_click_streak);
/*Third click nearby.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(49, 55);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(3, counts.short_click_streak);
/*Fourth click nearby.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(50, 50);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(4, counts.short_click_streak);
/*Resetting the click streak due to distance.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(10, 10);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(1, counts.short_click_streak);
/*Second click nearby.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_click_at(12, 14);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(2, counts.short_click_streak);
/*Resetting the click streak due to time.*/
lv_memzero(&counts, sizeof(counts));
lv_test_wait(1000);
lv_test_mouse_click_at(12, 14);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(1, counts.short_click_streak);
/*Long press does not continue (or start) click streak.*/
lv_memzero(&counts, sizeof(counts));
lv_test_mouse_press();
lv_test_wait(1000);
lv_test_mouse_release();
lv_test_wait(50);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_short_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_single_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_double_clicked);
TEST_ASSERT_EQUAL_UINT32(0, counts.num_triple_clicked);
TEST_ASSERT_EQUAL_UINT32(1, counts.num_long_pressed);
TEST_ASSERT_EQUAL_UINT8(1, counts.short_click_streak);
}
#endif
@@ -0,0 +1,20 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void test_config(void);
void test_config(void)
{
TEST_ASSERT_EQUAL(130, LV_DPI_DEF);
TEST_ASSERT_EQUAL(130, lv_display_get_dpi(NULL));
TEST_ASSERT_EQUAL(800, LV_HOR_RES);
TEST_ASSERT_EQUAL(800, lv_display_get_horizontal_resolution(NULL));
TEST_ASSERT_EQUAL(480, LV_VER_RES);
TEST_ASSERT_EQUAL(480, lv_display_get_vertical_resolution(NULL));
TEST_ASSERT_EQUAL(32, LV_COLOR_DEPTH);
}
#endif
@@ -0,0 +1,35 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
static void loop_through_stress_test(void)
{
#if LV_USE_DEMO_STRESS
while(1) {
lv_timer_handler();
if(lv_demo_stress_finished()) {
break;
}
lv_tick_inc(1);
}
#endif
}
void test_demo_stress(void)
{
#if LV_USE_DEMO_STRESS
lv_demo_stress();
#endif
/* loop once to allow objects to be created */
loop_through_stress_test();
size_t mem_before = lv_test_get_free_mem();
/* loop 5 more times */
for(uint32_t i = 0; i < 5; i++) {
loop_through_stress_test();
}
TEST_ASSERT_EQUAL(mem_before, lv_test_get_free_mem());
}
#endif
@@ -0,0 +1,15 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
void test_demo_widgets(void)
{
#if LV_USE_DEMO_WIDGETS
lv_demo_widgets();
#endif
}
#endif
@@ -0,0 +1,208 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
/*Bypassing resolution check*/
#define TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT(path) TEST_ASSERT_MESSAGE(lv_test_screenshot_compare(path), path);
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
lv_display_set_matrix_rotation(NULL, false);
lv_obj_clean(lv_screen_active());
}
struct display_area_test_set {
/* Parameters for setting up the display */
uint32_t width;
uint32_t height;
lv_color_format_t color_format;
lv_display_render_mode_t render_mode;
/* Parameters for testing */
uint32_t invalidated_width;
uint32_t invalidated_height;
uint32_t expected_buf0_size;
};
void test_get_drawbuf_size_double_buffered(void)
{
static LV_ATTRIBUTE_MEM_ALIGN uint8_t buf0[200 + LV_DRAW_BUF_ALIGN];
static LV_ATTRIBUTE_MEM_ALIGN uint8_t buf1[200 + LV_DRAW_BUF_ALIGN];
lv_display_t * disp = lv_display_create(10, 20);
lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB888);
lv_display_set_buffers(disp, lv_draw_buf_align(buf0, LV_COLOR_FORMAT_RGB888), lv_draw_buf_align(buf1,
LV_COLOR_FORMAT_RGB888), 200, LV_DISPLAY_RENDER_MODE_PARTIAL);
TEST_ASSERT_EQUAL(200, lv_display_get_draw_buf_size(disp));
lv_display_delete(disp);
}
void test_get_drawbuf_size_single_buffered(void)
{
static LV_ATTRIBUTE_MEM_ALIGN uint8_t buf0[200 + LV_DRAW_BUF_ALIGN];
lv_display_t * disp = lv_display_create(10, 20);
lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB888);
lv_display_set_buffers(disp, lv_draw_buf_align(buf0, LV_COLOR_FORMAT_RGB888), NULL, 200,
LV_DISPLAY_RENDER_MODE_PARTIAL);
TEST_ASSERT_EQUAL(200, lv_display_get_draw_buf_size(disp));
lv_display_delete(disp);
}
static void exec_invalidated_drawbuf_size_test(const struct display_area_test_set * test_set)
{
uint32_t buffer_size = lv_draw_buf_width_to_stride(test_set->width, test_set->color_format) * test_set->height;
uint8_t * buf0 = lv_malloc(buffer_size + LV_DRAW_BUF_ALIGN);
lv_display_t * disp = lv_display_create(test_set->width, test_set->height);
lv_display_set_color_format(disp, test_set->color_format);
lv_display_set_buffers(disp, lv_draw_buf_align(buf0, test_set->color_format), NULL, buffer_size,
test_set->render_mode);
uint32_t invalidated_size = lv_display_get_invalidated_draw_buf_size(disp, test_set->invalidated_width,
test_set->invalidated_height);
TEST_ASSERT_EQUAL(test_set->expected_buf0_size, invalidated_size);
lv_free(buf0);
lv_display_delete(disp);
}
void test_get_invalidated_drawbuf_size_rgb888_partial()
{
struct display_area_test_set test_set = {
.width = 10,
.height = 20,
.color_format = LV_COLOR_FORMAT_RGB888,
.render_mode = LV_DISPLAY_RENDER_MODE_PARTIAL,
.invalidated_width = 5,
.invalidated_height = 5,
.expected_buf0_size = lv_draw_buf_width_to_stride(5, LV_COLOR_FORMAT_RGB888) * 5,
};
exec_invalidated_drawbuf_size_test(&test_set);
}
void test_get_invalidated_drawbuf_size_rgb888_full()
{
struct display_area_test_set test_set = {
.width = 10,
.height = 20,
.color_format = LV_COLOR_FORMAT_RGB888,
.render_mode = LV_DISPLAY_RENDER_MODE_FULL,
.invalidated_width = 10,
.invalidated_height = 20,
.expected_buf0_size = lv_draw_buf_width_to_stride(10, LV_COLOR_FORMAT_RGB888) * 20,
};
exec_invalidated_drawbuf_size_test(&test_set);
}
void test_get_invalidated_drawbuf_size_i1_full()
{
struct display_area_test_set test_set = {
.width = 180,
.height = 90,
.color_format = LV_COLOR_FORMAT_I1,
.render_mode = LV_DISPLAY_RENDER_MODE_FULL,
.invalidated_width = 180,
.invalidated_height = 90,
.expected_buf0_size = lv_draw_buf_width_to_stride(180, LV_COLOR_FORMAT_I1) * 90,
};
exec_invalidated_drawbuf_size_test(&test_set);
}
void test_get_invalidated_drawbuf_size_i1_partial()
{
struct display_area_test_set test_set = {
.width = 180,
.height = 90,
.color_format = LV_COLOR_FORMAT_I1,
.render_mode = LV_DISPLAY_RENDER_MODE_PARTIAL,
.invalidated_width = 180,
.invalidated_height = 10,
.expected_buf0_size = lv_draw_buf_width_to_stride(180, LV_COLOR_FORMAT_I1) * 10,
};
exec_invalidated_drawbuf_size_test(&test_set);
}
void test_display_matrix_rotation(void)
{
#if LV_DRAW_TRANSFORM_USE_MATRIX
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 300, 200);
lv_obj_set_pos(obj, 30, 20);
lv_obj_t * label = lv_label_create(obj);
lv_display_t * disp = lv_obj_get_display(obj);
lv_display_set_matrix_rotation(disp, true);
TEST_ASSERT_TRUE(lv_display_get_matrix_rotation(disp));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_0);
lv_label_set_text(label, "Rotation: 0 degrees");
TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT("display_matrix_rotation_0.png");
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90);
lv_label_set_text(label, "Rotation: 90 degrees");
TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT("display_matrix_rotation_90.png");
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_180);
lv_label_set_text(label, "Rotation: 180 degrees");
TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT("display_matrix_rotation_180.png");
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
lv_label_set_text(label, "Rotation: 270 degrees");
TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT("display_matrix_rotation_270.png");
lv_display_set_matrix_rotation(disp, false);
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_0);
lv_label_set_text(label, "Rotation: 0 degrees");
TEST_DISPLAY_ASSERT_EQUAL_SCREENSHOT("display_matrix_rotation_0.png");
#else
TEST_PASS();
#endif
}
static void dummy_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p)
{
LV_UNUSED(area);
LV_UNUSED(color_p);
lv_display_flush_ready(disp);
}
void test_display_triple_buffer(void)
{
lv_display_t * disp = lv_display_create(480, 320);
lv_display_set_flush_cb(disp, dummy_flush_cb);
lv_draw_buf_t * buf1 = lv_draw_buf_create(480, 320, LV_COLOR_FORMAT_NATIVE, 0);
lv_draw_buf_t * buf2 = lv_draw_buf_create(480, 320, LV_COLOR_FORMAT_NATIVE, 0);
lv_draw_buf_t * buf3 = lv_draw_buf_create(480, 320, LV_COLOR_FORMAT_NATIVE, 0);
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
lv_display_set_draw_buffers(disp, buf1, buf2);
lv_display_set_3rd_draw_buffer(disp, buf3);
lv_obj_invalidate(lv_display_get_screen_active(disp));
lv_display_refr_timer(lv_display_get_refr_timer(disp));
TEST_ASSERT_EQUAL(lv_display_get_buf_active(disp), buf2);
lv_obj_invalidate(lv_display_get_screen_active(disp));
lv_display_refr_timer(lv_display_get_refr_timer(disp));
TEST_ASSERT_EQUAL(lv_display_get_buf_active(disp), buf3);
lv_obj_invalidate(lv_display_get_screen_active(disp));
lv_display_refr_timer(lv_display_get_refr_timer(disp));
TEST_ASSERT_EQUAL(lv_display_get_buf_active(disp), buf1);
lv_display_delete(disp);
lv_draw_buf_destroy(buf1);
lv_draw_buf_destroy(buf2);
lv_draw_buf_destroy(buf3);
}
#endif
@@ -0,0 +1,117 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_draw_buf_stride_adjust(void)
{
#if LV_BIN_DECODER_RAM_LOAD == 1
const char * color_formats[] = {
"I1",
"I2",
"I4",
"I8",
#if 0 /* Decoder will convert them to A8 anyway.*/
"A1",
"A2",
"A4",
#endif
"A8",
"RGB565",
#if 0 /* RGB565 with alpha is not supported*/
"RGB565A8",
"ARGB8565",
#endif
"RGB888",
"ARGB8888",
"XRGB8888",
};
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_obj_center(img);
const lv_image_decoder_args_t args = {
.no_cache = true,
.premultiply = false,
.stride_align = false,
.use_indexed = true,
};
for(unsigned long i = 0; i < sizeof(color_formats) / sizeof(color_formats[0]); i++) {
char img_src[256];
char ref_image[256];
snprintf(img_src, sizeof(img_src), "A:test_images/stride_align1/UNCOMPRESSED/test_%s.bin", color_formats[i]);
snprintf(ref_image, sizeof(ref_image), "draw/temp_%s.o", color_formats[i]); /*Use .o file name so git ignores it.*/
lv_image_set_src(img, img_src);
TEST_ASSERT_EQUAL_SCREENSHOT(ref_image); /*Generate the reference image, use .o so git ignore it*/
lv_image_cache_drop(img_src); /* Image could be added to cache during lv_image_set_src*/
lv_image_decoder_dsc_t decoder_dsc;
lv_result_t res = lv_image_decoder_open(&decoder_dsc, img_src, &args);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
lv_draw_buf_t * decoded = lv_draw_buf_dup(decoder_dsc.decoded);
TEST_ASSERT_NOT_NULL(decoded);
const lv_image_header_t header = decoder_dsc.decoded->header;
uint32_t image_width = header.w;
uint32_t image_height = header.h;
uint32_t image_stride = header.stride;
uint32_t min_stride = (image_width * lv_color_format_get_bpp(header.cf) + 7) >> 3;
/*Close the decoder since we copied out the decoded draw buffer*/
lv_image_decoder_close(&decoder_dsc);
/* Shrink stride to below minimal stride(by -1 in code below) should fail */
res = lv_draw_buf_adjust_stride(decoded, min_stride - 1);
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
/*Expand the stride should fail if stride is too large that buffer size overflow*/
res = lv_draw_buf_adjust_stride(decoded, image_stride + 1);
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
/*Create a larger draw buffer*/
lv_draw_buf_t * larger = lv_draw_buf_create(image_width, image_height, header.cf, min_stride + 100);
/*Copy draw buffer, it should look same.*/
lv_draw_buf_copy(larger, NULL, decoded, NULL);
lv_image_cache_drop(larger);
lv_image_set_src(img, larger);
TEST_ASSERT_EQUAL_SCREENSHOT(ref_image); /*The image should still looks same*/
/* Shrink stride to minimal stride should succeed */
res = lv_draw_buf_adjust_stride(larger, min_stride);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
lv_image_cache_drop(larger);
lv_image_set_src(img, larger);
TEST_ASSERT_EQUAL_SCREENSHOT(ref_image); /*Test against with above reference image*/
/* Expand the stride should work, use a proper stride value should succeed*/
res = lv_draw_buf_adjust_stride(larger, min_stride + 20);
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
lv_image_cache_drop(larger);
lv_image_set_src(img, larger);
TEST_ASSERT_EQUAL_SCREENSHOT(ref_image); /*The image should still look same*/
lv_draw_buf_destroy(larger);
lv_draw_buf_destroy(decoded);
}
lv_obj_delete(img);
#endif
}
#endif
@@ -0,0 +1,145 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static void event_object_deletion_cb(const lv_obj_class_t * cls, lv_event_t * e)
{
LV_UNUSED(cls);
if(lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) {
lv_obj_delete(lv_event_get_target(e));
}
}
static const lv_obj_class_t event_object_deletion_class = {
.event_cb = event_object_deletion_cb,
.base_class = &lv_obj_class
};
/* Checks for memory leaks/invalid memory accesses on deleted objects */
void test_event_object_deletion(void)
{
lv_obj_t * obj = lv_obj_class_create_obj(&event_object_deletion_class, lv_screen_active());
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
}
/* Add and then remove event should not memory leak */
void test_event_should_not_memory_lean(void)
{
lv_mem_monitor_t monitor;
lv_mem_monitor(&monitor);
lv_obj_t * obj = lv_obj_create(lv_screen_active());
size_t initial_free_size = monitor.free_size;
for(int i = 0; i < 10; i++) {
lv_obj_add_event_cb(obj, NULL, LV_EVENT_ALL, NULL);
}
lv_obj_delete(obj);
lv_mem_monitor_t m2;
lv_mem_monitor(&m2);
TEST_ASSERT_LESS_OR_EQUAL_CHAR(initial_free_size, m2.free_size);
}
static uint32_t pre_cnt_1;
static uint32_t pre_cnt_2;
static uint32_t post_cnt_1;
static uint32_t post_cnt_2;
static bool pre_stop_1;
static bool post_stop_1;
static void event_pre_1_cb(lv_event_t * e)
{
pre_cnt_1++;
if(pre_stop_1) lv_event_stop_processing(e);
}
static void event_pre_2_cb(lv_event_t * e)
{
LV_UNUSED(e);
pre_cnt_2++;
}
static void event_post_1_cb(lv_event_t * e)
{
post_cnt_1++;
if(post_stop_1) lv_event_stop_processing(e);
}
static void event_post_2_cb(lv_event_t * e)
{
LV_UNUSED(e);
post_cnt_2++;
}
/* Add and then remove event should not memory leak */
void test_event_stop_processing(void)
{
lv_obj_t * btn = lv_button_create(lv_screen_active());
lv_obj_set_size(btn, 200, 100);
lv_obj_add_event_cb(btn, event_pre_1_cb, LV_EVENT_CLICKED | LV_EVENT_PREPROCESS, NULL);
lv_obj_add_event_cb(btn, event_pre_2_cb, LV_EVENT_CLICKED | LV_EVENT_PREPROCESS, NULL);
lv_obj_add_event_cb(btn, event_post_1_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(btn, event_post_2_cb, LV_EVENT_CLICKED, NULL);
pre_cnt_1 = 0;
pre_cnt_2 = 0;
post_cnt_1 = 0;
post_cnt_2 = 0;
pre_stop_1 = false;
post_stop_1 = false;
lv_test_mouse_click_at(30, 30);
TEST_ASSERT_EQUAL(pre_cnt_1, 1);
TEST_ASSERT_EQUAL(pre_cnt_2, 1);
TEST_ASSERT_EQUAL(post_cnt_1, 1);
TEST_ASSERT_EQUAL(post_cnt_2, 1);
pre_cnt_1 = 0;
pre_cnt_2 = 0;
post_cnt_1 = 0;
post_cnt_2 = 0;
pre_stop_1 = true;
post_stop_1 = false;
lv_test_mouse_click_at(30, 30);
TEST_ASSERT_EQUAL(pre_cnt_1, 1);
TEST_ASSERT_EQUAL(pre_cnt_2, 0);
TEST_ASSERT_EQUAL(post_cnt_1, 0);
TEST_ASSERT_EQUAL(post_cnt_2, 0);
pre_cnt_1 = 0;
pre_cnt_2 = 0;
post_cnt_1 = 0;
post_cnt_2 = 0;
pre_stop_1 = false;
post_stop_1 = true;
lv_test_mouse_click_at(30, 30);
TEST_ASSERT_EQUAL(pre_cnt_1, 1);
TEST_ASSERT_EQUAL(pre_cnt_2, 1);
TEST_ASSERT_EQUAL(post_cnt_1, 1);
TEST_ASSERT_EQUAL(post_cnt_2, 0);
}
static uint32_t click_count = 0;
static void event_click_to_delete_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
click_count++;
if(click_count == 10) lv_obj_remove_event(obj, 0);
else if(click_count == 15) lv_obj_delete(obj);
else lv_obj_send_event(obj, LV_EVENT_CLICKED, NULL);
}
void test_event_delete_obj_in_recursive_event_call(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_add_event_cb(obj, event_click_to_delete_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(obj, NULL, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(obj, event_click_to_delete_cb, LV_EVENT_CLICKED, NULL);
lv_test_mouse_click_at(30, 30);
}
#endif
@@ -0,0 +1,106 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <unistd.h>
#include <sys/stat.h>
static lv_obj_t * active_screen = NULL;
static lv_obj_t * file_explorer_obj;
static lv_file_explorer_t * file_explorer;
static lv_table_t * file_table;
void setUp(void)
{
active_screen = lv_screen_active();
file_explorer_obj = lv_file_explorer_create(active_screen);
file_explorer = (lv_file_explorer_t *)file_explorer_obj;
file_table = (lv_table_t *)file_explorer->file_table;
}
void tearDown(void)
{
/* Is there a way to destroy a chart without having to call remove_series for each of it series? */
lv_obj_clean(active_screen);
}
void test_file_explorer_read_dir(void)
{
uint8_t back_row = 0, dev_row = 0, shm_row = 0, home_row = 0, user_row = 0;
mkdir("src/test_files/test_file_explorer_folder", 0777);
mkdir("src/test_files/test_file_explorer_folder/dev", 0777);
mkdir("src/test_files/test_file_explorer_folder/dev/shm", 0777);
mkdir("src/test_files/test_file_explorer_folder/home", 0777);
mkdir("src/test_files/test_file_explorer_folder/home/web_user", 0777);
lv_file_explorer_open_dir(file_explorer_obj, "A:src/test_files/test_file_explorer_folder");
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/",
lv_file_explorer_get_current_path(file_explorer_obj));
for(uint8_t i = 0; i < file_table->row_cnt; i++) {
if(lv_strcmp(lv_table_get_cell_value(file_explorer->file_table, i, 0), LV_SYMBOL_LEFT " Back") == 0) {
back_row = i;
}
if(lv_strcmp(lv_table_get_cell_value(file_explorer->file_table, i, 0), LV_SYMBOL_DIRECTORY " dev") == 0) {
dev_row = i;
}
if(lv_strcmp(lv_table_get_cell_value(file_explorer->file_table, i, 0), LV_SYMBOL_DIRECTORY " home") == 0) {
home_row = i;
}
}
/* Since the default table->col_act = LV_TABLE_CELL_NONE, it is necessary to specify file_table->col_act = 0 */
file_table->col_act = 0;
file_table->row_act = dev_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/dev/",
lv_file_explorer_get_current_path(file_explorer_obj));
for(uint8_t i = 0; i < file_table->row_cnt; i++) {
if(lv_strcmp(lv_table_get_cell_value(file_explorer->file_table, i, 0), LV_SYMBOL_DIRECTORY " shm") == 0) {
shm_row = i;
}
}
file_table->row_act = shm_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/dev/shm/",
lv_file_explorer_get_current_path(file_explorer_obj));
file_table->row_act = back_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/dev/",
lv_file_explorer_get_current_path(file_explorer_obj));
file_table->row_act = back_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/",
lv_file_explorer_get_current_path(file_explorer_obj));
file_table->row_act = home_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/home/",
lv_file_explorer_get_current_path(file_explorer_obj));
for(uint8_t i = 0; i < file_table->row_cnt; i++) {
if(lv_strcmp(lv_table_get_cell_value(file_explorer->file_table, i, 0), LV_SYMBOL_DIRECTORY " web_user") == 0) {
user_row = i;
}
}
file_table->row_act = user_row;
lv_obj_send_event(file_explorer->file_table, LV_EVENT_CLICKED, NULL);
TEST_ASSERT_EQUAL_STRING("A:src/test_files/test_file_explorer_folder/home/web_user/",
lv_file_explorer_get_current_path(file_explorer_obj));
rmdir("src/test_files/test_file_explorer_folder/dev/shm");
rmdir("src/test_files/test_file_explorer_folder/dev");
rmdir("src/test_files/test_file_explorer_folder/home/web_user");
rmdir("src/test_files/test_file_explorer_folder/home");
rmdir("src/test_files/test_file_explorer_folder");
}
#endif
@@ -0,0 +1,325 @@
/**
* @file test_font_loader.c
*
*/
/*********************
* INCLUDES
*********************/
#if LV_BUILD_TEST
#include "../../lvgl.h"
#include "unity/unity.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static int compare_fonts(lv_font_t * f1, lv_font_t * f2);
void test_font_loader_with_cache(void);
void test_font_loader_no_cache(void);
void test_font_loader_from_buffer(void);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/* fonts converted to C structs using the LVGL Font Converter */
extern lv_font_t test_font_1;
extern lv_font_t test_font_2;
extern lv_font_t test_font_3;
/* font binaries converted to plain C arrays */
extern uint8_t const test_font_1_buf[6876];
extern uint8_t const test_font_2_buf[7252];
extern uint8_t const test_font_3_buf[4892];
static lv_font_t * font_1_bin = NULL;
static lv_font_t * font_2_bin = NULL;
static lv_font_t * font_3_bin = NULL;
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void common(void)
{
compare_fonts(&test_font_1, font_1_bin);
compare_fonts(&test_font_2, font_2_bin);
compare_fonts(&test_font_3, font_3_bin);
/* create labels for testing */
lv_obj_t * scr = lv_screen_active();
lv_obj_t * label1 = lv_label_create(scr);
lv_obj_t * label2 = lv_label_create(scr);
lv_obj_t * label3 = lv_label_create(scr);
lv_obj_set_flex_flow(scr, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(scr, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_label_set_text(label1, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label1, font_1_bin, 0);
lv_label_set_text(label2, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label2, font_2_bin, 0);
lv_label_set_text(label3, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label3, font_3_bin, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_1.png");
lv_obj_clean(lv_screen_active());
lv_binfont_destroy(font_1_bin);
lv_binfont_destroy(font_2_bin);
lv_binfont_destroy(font_3_bin);
}
void test_font_loader_with_cache(void)
{
/*Test with cache ('A' has cache)*/
font_1_bin = lv_binfont_create("A:src/test_assets/test_font_1.fnt");
TEST_ASSERT_NOT_NULL(font_1_bin);
font_2_bin = lv_binfont_create("A:src/test_assets/test_font_2.fnt");
TEST_ASSERT_NOT_NULL(font_2_bin);
font_3_bin = lv_binfont_create("A:src/test_assets/test_font_3.fnt");
TEST_ASSERT_NOT_NULL(font_3_bin);
common();
}
void test_font_loader_no_cache(void)
{
/*Test without cache ('B' has NO cache)*/
font_1_bin = lv_binfont_create("B:src/test_assets/test_font_1.fnt");
TEST_ASSERT_NOT_NULL(font_1_bin);
font_2_bin = lv_binfont_create("B:src/test_assets/test_font_2.fnt");
TEST_ASSERT_NOT_NULL(font_2_bin);
font_3_bin = lv_binfont_create("B:src/test_assets/test_font_3.fnt");
TEST_ASSERT_NOT_NULL(font_3_bin);
common();
}
void test_font_loader_from_buffer(void)
{
/*Test with memfs*/
font_1_bin = lv_binfont_create_from_buffer((void *)&test_font_1_buf, sizeof(test_font_1_buf));
TEST_ASSERT_NOT_NULL(font_1_bin);
font_2_bin = lv_binfont_create_from_buffer((void *)&test_font_2_buf, sizeof(test_font_2_buf));
TEST_ASSERT_NOT_NULL(font_2_bin);
font_3_bin = lv_binfont_create_from_buffer((void *)&test_font_3_buf, sizeof(test_font_3_buf));
TEST_ASSERT_NOT_NULL(font_3_bin);
common();
}
void test_font_loader_reload(void)
{
/*Reload a font which is being used by a label*/
lv_obj_t * scr = lv_screen_active();
lv_obj_t * label = lv_label_create(scr);
lv_obj_center(label);
lv_label_set_text(label, "The quick brown fox jumped over the lazy dog");
lv_font_t style_font;
lv_font_t * font;
font = lv_binfont_create("A:src/test_assets/test_font_2.fnt");
TEST_ASSERT_NOT_NULL(font);
lv_memcpy(&style_font, font, sizeof(lv_font_t));
lv_obj_set_style_text_font(label, &style_font, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_2.png");
lv_binfont_destroy(font);
font = lv_binfont_create("A:src/test_assets/test_font_3.fnt");
TEST_ASSERT_NOT_NULL(font);
lv_memcpy(&style_font, font, sizeof(lv_font_t));
lv_obj_report_style_change(NULL);
TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_3.png");
lv_obj_delete(label);
lv_binfont_destroy(font);
}
static int compare_fonts(lv_font_t * f1, lv_font_t * f2)
{
TEST_ASSERT_NOT_NULL_MESSAGE(f1, "font not null");
TEST_ASSERT_NOT_NULL_MESSAGE(f2, "font not null");
// Skip these test because -Wpedantic tells
// ISO C forbids passing argument 1 of ‘TEST_ASSERT_EQUAL_PTR_MESSAGE’ between function pointer and ‘void *’
// TEST_ASSERT_EQUAL_PTR_MESSAGE(f1->get_glyph_dsc, f2->get_glyph_dsc, "glyph_dsc");
// TEST_ASSERT_EQUAL_PTR_MESSAGE(f1->get_glyph_bitmap, f2->get_glyph_bitmap, "glyph_bitmap");
TEST_ASSERT_EQUAL_INT_MESSAGE(f1->line_height, f2->line_height, "line_height");
TEST_ASSERT_EQUAL_INT_MESSAGE(f1->base_line, f2->base_line, "base_line");
TEST_ASSERT_EQUAL_INT_MESSAGE(f1->subpx, f2->subpx, "subpx");
lv_font_fmt_txt_dsc_t * dsc1 = (lv_font_fmt_txt_dsc_t *)f1->dsc;
lv_font_fmt_txt_dsc_t * dsc2 = (lv_font_fmt_txt_dsc_t *)f2->dsc;
TEST_ASSERT_EQUAL_INT_MESSAGE(dsc1->kern_scale, dsc2->kern_scale, "kern_scale");
TEST_ASSERT_EQUAL_INT_MESSAGE(dsc1->cmap_num, dsc2->cmap_num, "cmap_num");
TEST_ASSERT_EQUAL_INT_MESSAGE(dsc1->bpp, dsc2->bpp, "bpp");
TEST_ASSERT_EQUAL_INT_MESSAGE(dsc1->kern_classes, dsc2->kern_classes, "kern_classes");
TEST_ASSERT_EQUAL_INT_MESSAGE(dsc1->bitmap_format, dsc2->bitmap_format, "bitmap_format");
// cmaps
int total_glyphs = 0;
for(int i = 0; i < dsc1->cmap_num; ++i) {
lv_font_fmt_txt_cmap_t * cmaps1 = (lv_font_fmt_txt_cmap_t *)&dsc1->cmaps[i];
lv_font_fmt_txt_cmap_t * cmaps2 = (lv_font_fmt_txt_cmap_t *)&dsc2->cmaps[i];
TEST_ASSERT_EQUAL_INT_MESSAGE(cmaps1->range_start, cmaps2->range_start, "range_start");
TEST_ASSERT_EQUAL_INT_MESSAGE(cmaps1->range_length, cmaps2->range_length, "range_length");
TEST_ASSERT_EQUAL_INT_MESSAGE(cmaps1->glyph_id_start, cmaps2->glyph_id_start, "glyph_id_start");
TEST_ASSERT_EQUAL_INT_MESSAGE(cmaps1->type, cmaps2->type, "type");
TEST_ASSERT_EQUAL_INT_MESSAGE(cmaps1->list_length, cmaps2->list_length, "list_length");
if(cmaps1->unicode_list != NULL && cmaps2->unicode_list != NULL) {
TEST_ASSERT_TRUE_MESSAGE(cmaps1->unicode_list && cmaps2->unicode_list, "unicode_list");
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
(uint8_t *)cmaps1->unicode_list,
(uint8_t *)cmaps2->unicode_list,
sizeof(uint16_t) * cmaps1->list_length,
"unicode_list");
total_glyphs += cmaps1->list_length;
}
else {
total_glyphs += cmaps1->range_length;
TEST_ASSERT_EQUAL_PTR_MESSAGE(cmaps1->unicode_list, cmaps2->unicode_list, "unicode_list");
}
if(cmaps1->glyph_id_ofs_list != NULL && cmaps2->glyph_id_ofs_list != NULL) {
uint8_t * ids1 = (uint8_t *)cmaps1->glyph_id_ofs_list;
uint8_t * ids2 = (uint8_t *)cmaps2->glyph_id_ofs_list;
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(ids1, ids2, cmaps1->list_length, "glyph_id_ofs_list");
}
else {
TEST_ASSERT_EQUAL_PTR_MESSAGE(cmaps1->glyph_id_ofs_list, cmaps2->glyph_id_ofs_list, "glyph_id_ofs_list");
}
}
// kern_dsc
if(dsc1->kern_classes == 1 && dsc2->kern_classes == 1) {
lv_font_fmt_txt_kern_classes_t * kern1 = (lv_font_fmt_txt_kern_classes_t *)dsc1->kern_dsc;
lv_font_fmt_txt_kern_classes_t * kern2 = (lv_font_fmt_txt_kern_classes_t *)dsc2->kern_dsc;
if(kern1 != NULL && kern2 != NULL) {
TEST_ASSERT_EQUAL_INT_MESSAGE(kern1->right_class_cnt, kern2->right_class_cnt, "right_class_cnt");
TEST_ASSERT_EQUAL_INT_MESSAGE(kern1->left_class_cnt, kern2->left_class_cnt, "left_class_cnt");
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
(uint8_t *)kern1->left_class_mapping,
(uint8_t *)kern2->left_class_mapping,
kern1->left_class_cnt,
"left_class_mapping");
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
(uint8_t *)kern1->right_class_mapping,
(uint8_t *)kern2->right_class_mapping,
kern1->right_class_cnt,
"right_class_mapping");
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
(uint8_t *)kern1->class_pair_values,
(uint8_t *)kern2->class_pair_values,
kern1->right_class_cnt * kern1->left_class_cnt,
"class_pair_values");
}
else {
TEST_ASSERT_EQUAL_PTR_MESSAGE(kern1, kern2, "kern");
}
}
else if(dsc1->kern_classes == 0 && dsc2->kern_classes == 0) {
lv_font_fmt_txt_kern_pair_t * kern1 = (lv_font_fmt_txt_kern_pair_t *)dsc1->kern_dsc;
lv_font_fmt_txt_kern_pair_t * kern2 = (lv_font_fmt_txt_kern_pair_t *)dsc2->kern_dsc;
if(kern1 != NULL && kern2 != NULL) {
TEST_ASSERT_EQUAL_INT_MESSAGE(kern1->glyph_ids_size, kern2->glyph_ids_size, "glyph_ids_size");
TEST_ASSERT_EQUAL_INT_MESSAGE(kern1->pair_cnt, kern2->pair_cnt, "pair_cnt");
int ids_size;
if(kern1->glyph_ids_size == 0) {
ids_size = sizeof(int8_t) * 2 * kern1->pair_cnt;
}
else {
ids_size = sizeof(int16_t) * 2 * kern1->pair_cnt;
}
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(kern1->glyph_ids, kern2->glyph_ids, ids_size, "glyph_ids");
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
(uint8_t *) kern1->values,
(uint8_t *) kern2->values,
kern1->pair_cnt,
"glyph_values");
}
}
lv_font_fmt_txt_glyph_dsc_t * glyph_dsc1 = (lv_font_fmt_txt_glyph_dsc_t *)dsc1->glyph_dsc;
lv_font_fmt_txt_glyph_dsc_t * glyph_dsc2 = (lv_font_fmt_txt_glyph_dsc_t *)dsc2->glyph_dsc;
for(int i = 0; i < total_glyphs; ++i) {
if(i < total_glyphs - 1) {
int size1 = glyph_dsc1[i + 1].bitmap_index - glyph_dsc1[i].bitmap_index;
if(size1 > 0) {
TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(
dsc1->glyph_bitmap + glyph_dsc1[i].bitmap_index,
dsc2->glyph_bitmap + glyph_dsc2[i].bitmap_index,
size1 - 1, "glyph_bitmap");
}
}
TEST_ASSERT_EQUAL_INT_MESSAGE(glyph_dsc1[i].adv_w, glyph_dsc2[i].adv_w, "adv_w");
TEST_ASSERT_EQUAL_INT_MESSAGE(glyph_dsc1[i].box_w, glyph_dsc2[i].box_w, "box_w");
TEST_ASSERT_EQUAL_INT_MESSAGE(glyph_dsc1[i].box_h, glyph_dsc2[i].box_h, "box_h");
TEST_ASSERT_EQUAL_INT_MESSAGE(glyph_dsc1[i].ofs_x, glyph_dsc2[i].ofs_x, "ofs_x");
TEST_ASSERT_EQUAL_INT_MESSAGE(glyph_dsc1[i].ofs_y, glyph_dsc2[i].ofs_y, "ofs_y");
}
LV_LOG_INFO("No differences found!");
return 0;
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif // LV_BUILD_TEST
@@ -0,0 +1,247 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#if LV_USE_FONT_MANAGER \
&& LV_FONT_MONTSERRAT_14 && LV_FONT_MONTSERRAT_32 \
&& LV_USE_FREETYPE \
&& LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT
/**
* There are some differences between the rendering of FreeType in 64-bit and 32-bit,
* so we compare them separately here.
*/
#ifndef NON_AMD64_BUILD
#define EXT_NAME ".lp64.png"
#else
#define EXT_NAME ".lp32.png"
#endif
static lv_font_manager_t * g_font_manager = NULL;
typedef bool (*add_src_cb_t)(lv_font_manager_t * manager,
const char * name,
const void * src,
const lv_font_class_t * class_p);
void setUp(void)
{
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
static void test_font_manager_src(add_src_cb_t add_src_cb)
{
g_font_manager = lv_font_manager_create(2);
TEST_ASSERT_NOT_NULL(g_font_manager);
/* Register built-in font sources */
static lv_builtin_font_src_t builtin_font_src[3] = { 0 };
builtin_font_src[0].font_p = &lv_font_montserrat_14;
builtin_font_src[0].size = 14;
builtin_font_src[1].font_p = &lv_font_montserrat_32;
builtin_font_src[1].size = 32;
/* IMPORTANT! Marking the end of the array */
builtin_font_src[2].font_p = NULL;
builtin_font_src[2].size = 0;
bool add_src_result = add_src_cb(g_font_manager,
"Montserrat",
builtin_font_src,
&lv_builtin_font_class);
TEST_ASSERT_TRUE(add_src_result);
/* Try to add the same source again, should fail */
add_src_result = add_src_cb(g_font_manager,
"Montserrat",
builtin_font_src,
&lv_builtin_font_class);
TEST_ASSERT_FALSE(add_src_result);
/* Register FreeType font source */
add_src_result = add_src_cb(g_font_manager,
"NotoSansSC-Regular",
"./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
&lv_freetype_font_class);
TEST_ASSERT_TRUE(add_src_result);
/* Register TinyTTF font source */
extern const uint8_t test_ubuntu_font[];
extern size_t test_ubuntu_font_size;
static lv_tiny_ttf_font_src_t tiny_ttf_font_data_src = { 0 };
tiny_ttf_font_data_src.data = test_ubuntu_font;
tiny_ttf_font_data_src.data_size = test_ubuntu_font_size;
add_src_result = add_src_cb(g_font_manager,
"Ubuntu-Medium",
&tiny_ttf_font_data_src,
&lv_tiny_ttf_font_class);
TEST_ASSERT_TRUE(add_src_result);
static lv_tiny_ttf_font_src_t tiny_ttf_font_file_src = { 0 };
tiny_ttf_font_file_src.path = "A:src/test_files/fonts/noto/NotoSansSC-Regular.ttf";
add_src_result = add_src_cb(g_font_manager,
"NotoSansSC-Regular-2",
&tiny_ttf_font_file_src,
&lv_tiny_ttf_font_class);
TEST_ASSERT_TRUE(add_src_result);
/* Register binary font source */
static const lv_binfont_font_src_t binfont_font_file_src = {
.font_size = 20,
.path = "A:src/test_assets/test_font_3.fnt",
.buffer = NULL,
.buffer_size = 0,
};
add_src_result = add_src_cb(g_font_manager,
"RobotoMono-Regular-file",
&binfont_font_file_src,
&lv_binfont_font_class);
TEST_ASSERT_TRUE(add_src_result);
extern uint8_t const test_font_3_buf[4892];
static lv_binfont_font_src_t binfont_font_buffer_src = { 0 };
binfont_font_buffer_src.font_size = 20;
binfont_font_buffer_src.buffer = test_font_3_buf;
binfont_font_buffer_src.buffer_size = sizeof(test_font_3_buf);
add_src_result = add_src_cb(g_font_manager,
"RobotoMono-Regular-buffer",
&binfont_font_buffer_src,
&lv_binfont_font_class);
TEST_ASSERT_TRUE(add_src_result);
/* Create font from font manager */
/* Try to create font with unknown name, should fail */
lv_font_t * font_unknown = lv_font_manager_create_font(g_font_manager,
"UNKNOWN_FONT_NAME",
0,
10,
0,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NULL(font_unknown);
lv_font_t * font_14 = lv_font_manager_create_font(g_font_manager,
"NotoSansSC-Regular,Ubuntu-Medium,Montserrat,UNKNOWN_FONT_NAME",
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
14,
LV_FREETYPE_FONT_STYLE_NORMAL,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NOT_NULL(font_14);
lv_font_t * font_32 = lv_font_manager_create_font(g_font_manager,
"Ubuntu-Medium,NotoSansSC-Regular,Montserrat",
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
32,
LV_FREETYPE_FONT_STYLE_NORMAL,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NOT_NULL(font_32);
lv_font_t * font_40 = lv_font_manager_create_font(g_font_manager,
"Ubuntu-Medium,NotoSansSC-Regular-2,Montserrat",
0,
40,
0,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NOT_NULL(font_40);
lv_font_t * font_file_20 = lv_font_manager_create_font(g_font_manager,
"RobotoMono-Regular-file,NotoSansSC-Regular-2",
0,
20,
0,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NOT_NULL(font_file_20);
lv_font_t * font_buffer_20 = lv_font_manager_create_font(g_font_manager,
"RobotoMono-Regular-buffer,NotoSansSC-Regular-2",
0,
20,
0,
LV_FONT_KERNING_NONE);
TEST_ASSERT_NOT_NULL(font_file_20);
/* Create label with the font */
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label,
"这是一段中文。\n"
"This is a English text.\n"
"Symbols: " LV_SYMBOL_OK LV_SYMBOL_CLOSE);
lv_obj_center(label);
lv_obj_set_style_text_font(label, font_14, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_1" EXT_NAME);
lv_obj_set_style_text_font(label, font_32, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_2" EXT_NAME);
lv_obj_set_style_text_font(label, font_40, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_3" EXT_NAME);
/* Freetype fonts have not been tested, so there is no need to distinguish and process images */
lv_obj_set_style_text_font(label, font_file_20, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_4.png");
/* Rendered images should be the same */
lv_obj_set_style_text_font(label, font_buffer_20, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_4.png");
/* Should not be deleted successfully, because it is used by the label */
bool delete_result = lv_font_manager_delete(g_font_manager);
TEST_ASSERT_FALSE(delete_result);
lv_obj_delete(label);
lv_font_manager_delete_font(g_font_manager, font_14);
lv_font_manager_delete_font(g_font_manager, font_32);
lv_font_manager_delete_font(g_font_manager, font_40);
lv_font_manager_delete_font(g_font_manager, font_file_20);
lv_font_manager_delete_font(g_font_manager, font_buffer_20);
/* Trying to delete a font that was not created by the font manager, it needs to handle this situation */
lv_font_manager_delete_font(g_font_manager, (lv_font_t *)LV_FONT_DEFAULT);
lv_font_manager_delete_font(g_font_manager, (lv_font_t *)&lv_font_montserrat_32);
delete_result = lv_font_manager_delete(g_font_manager);
TEST_ASSERT_TRUE(delete_result);
g_font_manager = NULL;
}
void test_font_manager_src_normal(void)
{
test_font_manager_src(lv_font_manager_add_src);
}
void test_font_manager_src_static(void)
{
test_font_manager_src(lv_font_manager_add_src_static);
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_font_manager_src_normal(void)
{
}
void test_font_manager_src_static(void)
{
}
#endif
#endif /* LV_BUILD_TEST */
@@ -0,0 +1,278 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <string.h>
const char * read_exp =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sed maximus orci. Morbi massa nisi, varius eu convallis ac, venenatis at metus. In in nibh id urna pretium feugiat vitae eu libero. Ut eget fringilla eros. Nunc ullamcorper lectus mauris, vel rhoncus velit volutpat et. Phasellus sed molestie massa. Maecenas quis dui sollicitudin, vulputate nunc ut, dictum quam. Nam a congue lorem. Nulla non facilisis sapien. Ut luctus nulla nibh, sed finibus urna porta non. Duis aliquet augue id urna euismod auctor. Integer pellentesque vulputate enim non mattis. Donec finibus mattis dolor, et feugiat nisi pharetra porta. Mauris ullamcorper cursus magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.";
static void read_range(lv_fs_file_t * f, uint32_t from, uint32_t to);
static void read_random_drv(char drv_letter, uint32_t cache_size);
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
void test_read(void)
{
lv_fs_res_t res;
char cur[512];
if(getcwd(cur, 512) != NULL) {
errno = 0;
void * a = fopen("src/test_files/readtest.txt", "r");
printf("%s, %d, %p\n", cur, errno, a);
fclose(a);
/*'A' has cache*/
lv_fs_file_t fa;
res = lv_fs_open(&fa, "A:src/test_files/readtest.txt", LV_FS_MODE_RD);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
/*'B' has no cache*/
lv_fs_file_t fb;
res = lv_fs_open(&fb, "B:src/test_files/readtest.txt", LV_FS_MODE_RD);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
/*Use an odd size to make sure it's not aligned with the driver's cache size*/
uint8_t buf[79];
uint32_t cnt = 0;
uint32_t br = 1;
while(br) {
res = lv_fs_read(&fa, buf, sizeof(buf), &br);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
TEST_ASSERT_TRUE(memcmp(buf, read_exp + cnt, br) == 0);
res = lv_fs_read(&fb, buf, sizeof(buf), &br);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
TEST_ASSERT_TRUE(memcmp(buf, read_exp + cnt, br) == 0);
cnt += br;
}
lv_fs_close(&fa);
lv_fs_close(&fb);
}
}
void test_read_random(void)
{
read_random_drv('A', 8);
read_random_drv('B', 8);
read_random_drv('A', 32);
read_random_drv('B', 32);
read_random_drv('A', 128);
read_random_drv('B', 128);
read_random_drv('A', 1024);
read_random_drv('B', 1024);
}
/**
* Read bytes from the `from` index to the `to index`
* Assume that file `f` has 256 byte of content 0..255
*/
static void read_range(lv_fs_file_t * f, uint32_t from, uint32_t to)
{
lv_fs_seek(f, from, LV_FS_SEEK_SET);
uint32_t len = to - from + 1;
uint8_t buf_rd[256];
uint32_t br;
lv_fs_read(f, buf_rd, len, &br);
TEST_ASSERT_EQUAL(br, len);
uint32_t i;
for(i = 0; i < len; i++) {
TEST_ASSERT_EQUAL(buf_rd[i], from + i);
}
}
static void read_next(lv_fs_file_t * f, uint32_t from, uint32_t len)
{
uint8_t buf_rd[256];
uint32_t br;
lv_fs_read(f, buf_rd, len, &br);
TEST_ASSERT_EQUAL(br, len);
uint32_t i;
for(i = 0; i < br; i++) {
TEST_ASSERT_EQUAL(buf_rd[i], from + i);
}
}
static void read_random_drv(char drv_letter, uint32_t cache_size)
{
/*Hack to force a small cache size*/
lv_fs_drv_t * drv = lv_fs_get_drv(drv_letter);
uint32_t original_cache_size = drv->cache_size;
drv->cache_size = cache_size;
char fn[64];
lv_snprintf(fn, sizeof(fn), "%c:fs_read_random.bin", drv_letter);
lv_fs_res_t res;
lv_fs_file_t f;
res = lv_fs_open(&f, fn, LV_FS_MODE_WR);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
uint8_t buf256[256];
uint32_t i;
for(i = 0; i < 256; i++) buf256[i] = i;
res = lv_fs_write(&f, buf256, 256, NULL);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
res = lv_fs_close(&f);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
// *INDENT-OFF*
static const uint8_t ranges[1000][4] = {
/*{from, to, next_read_cnt, next_read_cnt}*/
{34, 36, 31, 13}, {40, 55, 40, 19}, {75, 92, 31, 1}, {80, 91, 19, 31}, {121, 141, 5, 22}, {8, 23, 21, 39}, {33, 37, 5, 34}, {71, 90, 22, 37}, {111, 124, 14, 38}, {2, 15, 6, 16}, {109, 129, 14, 13}, {85, 97, 10, 24}, {79, 90, 31, 32}, {8, 23, 4, 1}, {13, 21, 9, 15}, {90, 95, 2, 21}, {77, 95, 17, 28}, {60, 75, 26, 13}, {115, 117, 19, 24}, {31, 46, 9, 17}, {81, 98, 8, 32}, {115, 121, 33, 2}, {25, 31, 34, 23}, {26, 42, 16, 26}, {105, 121, 30, 16}, {82, 99, 26, 3}, {83, 87, 37, 6}, {33, 43, 34, 36}, {35, 51, 18, 30}, {29, 34, 20, 31}, {25, 36, 21, 23}, {123, 125, 40, 16}, {12, 30, 35, 14}, {80, 94, 19, 19}, {94, 112, 19, 13}, {113, 117, 15, 20}, {39, 53, 19, 14}, {38, 49, 29, 16}, {56, 63, 3, 7}, {128, 140, 8, 7}, {112, 115, 5, 16}, {68, 87, 24, 34}, {88, 95, 18, 12}, {4, 20, 18, 29}, {4, 8, 10, 32}, {33, 43, 28, 3}, {67, 80, 10, 13}, {74, 86, 14, 8}, {78, 98, 12, 26}, {86, 92, 24, 34}, {63, 66, 12, 30}, {117, 119, 40, 37}, {90, 97, 23, 11}, {95, 107, 39, 40}, {67, 74, 6, 34}, {128, 133, 11, 22}, {98, 99, 12, 25}, {91, 110, 5, 15}, {33, 37, 13, 32}, {12, 32, 3, 34}, {100, 102, 5, 25}, {52, 63, 37, 31}, {108, 125, 39, 7}, {77, 81, 28, 27}, {36, 54, 9, 29}, {109, 126, 12, 29}, {61, 70, 28, 19}, {47, 66, 9, 25}, {66, 69, 3, 17}, {75, 89, 26, 5}, {89, 103, 22, 15}, {113, 133, 34, 28}, {113, 114, 32, 33}, {124, 141, 9, 33}, {79, 85, 30, 28}, {60, 61, 30, 9}, {39, 54, 9, 18}, {93, 104, 35, 17}, {112, 122, 15, 6}, {104, 116, 1, 3}, {60, 62, 29, 9}, {119, 132, 40, 22}, {54, 70, 15, 14}, {8, 20, 24, 30}, {18, 29, 24, 1}, {104, 120, 15, 23}, {15, 25, 16, 32}, {45, 54, 14, 16}, {75, 79, 1, 38}, {52, 59, 15, 19}, {109, 128, 35, 38}, {85, 89, 7, 33}, {5, 6, 26, 32}, {12, 16, 32, 39}, {85, 105, 30, 4}, {88, 103, 37, 31}, {88, 104, 21, 23}, {18, 31, 5, 32}, {35, 50, 7, 5}, {3, 4, 3, 3}, {105, 120, 7, 3},
{21, 37, 21, 23}, {75, 93, 4, 39}, {3, 10, 6, 40}, {90, 107, 1, 23}, {100, 115, 37, 11}, {99, 107, 18, 14}, {127, 135, 11, 33}, {63, 74, 27, 14}, {96, 108, 3, 14}, {64, 76, 19, 3}, {67, 84, 15, 34}, {82, 91, 15, 22}, {34, 44, 14, 36}, {107, 114, 15, 31}, {120, 130, 31, 33}, {126, 134, 25, 31}, {58, 78, 11, 14}, {124, 127, 19, 13}, {114, 129, 13, 12}, {111, 128, 9, 40}, {127, 134, 9, 23}, {128, 131, 39, 7}, {62, 65, 28, 29}, {87, 104, 38, 17}, {13, 29, 24, 37}, {124, 133, 20, 24}, {63, 64, 28, 32}, {59, 69, 17, 8}, {12, 13, 1, 25}, {64, 78, 14, 25}, {49, 69, 20, 36}, {96, 105, 10, 8}, {29, 31, 27, 11}, {67, 83, 37, 2}, {89, 96, 2, 6}, {23, 27, 7, 1}, {87, 93, 13, 9}, {25, 43, 1, 26}, {81, 93, 12, 39}, {62, 68, 13, 32}, {114, 133, 6, 19}, {10, 21, 2, 25}, {94, 102, 24, 12}, {13, 29, 2, 26}, {110, 111, 14, 10}, {120, 123, 17, 1}, {121, 135, 31, 16}, {120, 127, 3, 34}, {74, 79, 32, 24}, {120, 138, 16, 13}, {121, 133, 25, 20}, {87, 101, 33, 31}, {79, 89, 27, 39}, {48, 60, 20, 35}, {43, 63, 9, 30}, {8, 27, 39, 13}, {77, 83, 30, 29}, {109, 116, 24, 5}, {122, 139, 4, 34}, {74, 82, 1, 22}, {98, 118, 20, 4}, {30, 34, 9, 25}, {98, 99, 37, 35}, {105, 108, 17, 4}, {84, 103, 19, 8}, {116, 133, 28, 40}, {53, 70, 27, 23}, {91, 93, 40, 8}, {116, 124, 21, 30}, {66, 68, 11, 32}, {91, 109, 27, 27}, {74, 83, 3, 17}, {57, 60, 22, 12}, {7, 15, 37, 16}, {93, 106, 6, 22}, {104, 106, 30, 20}, {56, 73, 9, 38}, {105, 110, 5, 19}, {122, 134, 30, 37}, {71, 83, 25, 26}, {68, 85, 21, 28}, {126, 140, 10, 29}, {87, 93, 38, 14}, {68, 82, 31, 20}, {26, 41, 8, 32}, {52, 55, 17, 13}, {51, 60, 31, 14}, {122, 126, 30, 26}, {32, 43, 3, 22}, {76, 93, 28, 24}, {97, 117, 12, 21}, {9, 17, 36, 21}, {52, 71, 24, 5}, {123, 138, 14, 21}, {82, 84, 9, 17}, {32, 34, 40, 24}, {89, 99, 21, 15}, {16, 32, 19, 9}, {39, 48, 38, 6}, {125, 129, 18, 31},
{28, 37, 21, 15}, {70, 77, 35, 31}, {107, 127, 18, 31}, {118, 125, 3, 23}, {89, 97, 28, 25}, {78, 96, 21, 40}, {19, 20, 9, 21}, {25, 38, 19, 35}, {63, 83, 2, 34}, {39, 58, 37, 1}, {52, 63, 1, 33}, {110, 120, 10, 16}, {84, 87, 31, 22}, {10, 22, 32, 22}, {84, 87, 39, 21}, {61, 70, 12, 22}, {118, 132, 4, 30}, {41, 50, 19, 36}, {3, 5, 40, 2}, {122, 123, 4, 28}, {121, 139, 25, 38}, {49, 69, 32, 13}, {60, 78, 32, 24}, {26, 32, 36, 19}, {54, 71, 15, 7}, {70, 76, 17, 37}, {15, 32, 15, 40}, {37, 52, 22, 22}, {46, 47, 20, 27}, {90, 91, 37, 23}, {104, 123, 4, 31}, {111, 129, 1, 33}, {25, 45, 21, 36}, {1, 21, 29, 25}, {104, 123, 33, 26}, {1, 3, 17, 20}, {63, 77, 14, 5}, {48, 55, 29, 19}, {126, 137, 29, 32}, {83, 91, 1, 36}, {120, 123, 22, 18}, {42, 57, 27, 9}, {106, 114, 8, 20}, {101, 107, 14, 36}, {52, 58, 11, 26}, {16, 22, 39, 27}, {107, 120, 35, 31}, {21, 37, 9, 11}, {110, 128, 35, 5}, {65, 83, 39, 39}, {13, 18, 10, 9}, {95, 96, 37, 8}, {94, 96, 14, 2}, {85, 87, 25, 7}, {27, 38, 1, 34}, {15, 25, 21, 27}, {87, 92, 18, 24}, {34, 44, 10, 19}, {123, 140, 31, 35}, {40, 48, 14, 2}, {63, 80, 14, 22}, {104, 109, 9, 39}, {109, 121, 36, 22}, {43, 53, 26, 36}, {117, 127, 15, 15}, {27, 31, 34, 32}, {30, 41, 2, 11}, {89, 102, 40, 16}, {107, 124, 22, 19}, {104, 117, 33, 22}, {10, 26, 21, 32}, {51, 58, 11, 34}, {87, 98, 27, 25}, {99, 116, 36, 35}, {103, 114, 4, 34}, {109, 121, 25, 8}, {114, 126, 6, 6}, {47, 66, 31, 14}, {115, 125, 39, 34}, {27, 29, 15, 7}, {103, 109, 12, 5}, {109, 111, 21, 39}, {83, 84, 7, 2}, {63, 67, 2, 37}, {14, 15, 35, 10}, {43, 56, 25, 27}, {74, 93, 2, 22}, {59, 79, 2, 18}, {56, 70, 39, 16}, {116, 128, 40, 38}, {14, 24, 6, 26}, {103, 106, 18, 29}, {128, 146, 7, 21}, {63, 83, 32, 33}, {109, 116, 26, 16}, {85, 89, 10, 5}, {116, 129, 17, 37}, {97, 116, 26, 7}, {98, 100, 40, 13}, {94, 109, 24, 32},
{105, 118, 7, 40}, {37, 45, 18, 18}, {65, 77, 34, 18}, {47, 59, 30, 21}, {4, 6, 35, 16}, {34, 47, 17, 38}, {81, 97, 17, 9}, {80, 88, 38, 8}, {118, 123, 34, 19}, {82, 93, 24, 18}, {82, 101, 21, 17}, {67, 72, 18, 27}, {117, 121, 20, 21}, {107, 119, 16, 11}, {19, 36, 13, 29}, {39, 56, 40, 20}, {14, 22, 24, 6}, {31, 32, 24, 39}, {46, 52, 36, 3}, {70, 80, 1, 27}, {108, 112, 2, 35}, {81, 89, 26, 35}, {66, 72, 15, 23}, {46, 63, 23, 22}, {96, 104, 4, 4}, {23, 27, 17, 12}, {84, 88, 11, 21}, {79, 98, 26, 8}, {38, 52, 1, 5}, {125, 141, 39, 27}, {112, 121, 33, 3}, {103, 109, 8, 16}, {96, 106, 31, 16}, {74, 87, 14, 31}, {96, 113, 2, 28}, {107, 113, 23, 30}, {64, 83, 33, 13}, {79, 92, 6, 29}, {80, 82, 35, 10}, {28, 34, 11, 4}, {123, 137, 40, 30}, {107, 119, 36, 34}, {114, 132, 9, 28}, {100, 114, 35, 22}, {123, 131, 33, 10}, {83, 92, 22, 19}, {29, 34, 15, 14}, {104, 110, 40, 26}, {7, 27, 34, 38}, {29, 39, 35, 1}, {87, 102, 10, 25}, {117, 126, 31, 40}, {62, 71, 4, 25}, {4, 18, 11, 28}, {41, 54, 25, 13}, {41, 60, 40, 31}, {122, 138, 19, 26}, {117, 123, 35, 34}, {10, 21, 33, 1}, {60, 64, 27, 38}, {55, 58, 34, 39}, {51, 56, 36, 12}, {101, 119, 13, 14}, {90, 91, 18, 12}, {74, 87, 3, 24}, {45, 59, 8, 19}, {60, 74, 24, 33}, {84, 87, 11, 38}, {107, 116, 16, 20}, {58, 70, 12, 34}, {99, 103, 26, 26}, {62, 73, 32, 33}, {68, 81, 7, 12}, {106, 122, 37, 27}, {109, 110, 11, 32}, {89, 94, 21, 17}, {98, 108, 3, 40}, {77, 94, 24, 34}, {17, 36, 34, 30}, {65, 70, 8, 7}, {31, 38, 1, 36}, {28, 43, 15, 5}, {107, 111, 13, 8}, {31, 49, 18, 35}, {50, 55, 3, 24}, {4, 16, 24, 19}, {35, 40, 40, 30}, {117, 130, 35, 20}, {33, 38, 9, 37}, {3, 5, 40, 38}, {18, 35, 30, 15}, {65, 70, 40, 16}, {121, 136, 13, 6}, {3, 21, 3, 20}, {41, 54, 14, 37}, {51, 67, 4, 1}, {80, 82, 8, 28}, {12, 21, 35, 30}, {75, 91, 19, 14}, {96, 99, 31, 13},
{45, 46, 35, 30}, {39, 57, 11, 17}, {104, 109, 7, 39}, {126, 135, 18, 25}, {55, 74, 16, 39}, {21, 37, 29, 24}, {22, 29, 36, 3}, {38, 41, 14, 34}, {52, 59, 35, 27}, {110, 125, 20, 28}, {33, 48, 38, 1}, {23, 34, 13, 38}, {55, 60, 33, 23}, {71, 76, 16, 1}, {22, 28, 16, 22}, {43, 50, 35, 16}, {91, 96, 40, 21}, {100, 119, 39, 22}, {64, 66, 29, 32}, {95, 98, 21, 30}, {61, 77, 12, 7}, {46, 52, 3, 13}, {108, 121, 35, 14}, {9, 15, 25, 9}, {41, 60, 24, 20}, {4, 23, 5, 29}, {29, 31, 2, 10}, {58, 62, 38, 6}, {40, 60, 8, 29}, {41, 54, 5, 25}, {99, 108, 5, 33}, {56, 57, 11, 18}, {94, 95, 9, 28}, {34, 37, 13, 40}, {128, 140, 39, 35}, {101, 110, 5, 4}, {41, 45, 31, 11}, {58, 72, 9, 24}, {48, 54, 24, 35}, {10, 21, 6, 12}, {38, 58, 11, 4}, {2, 22, 18, 9}, {6, 15, 22, 7}, {74, 94, 18, 14}, {75, 84, 29, 29}, {20, 40, 32, 39}, {8, 22, 20, 12}, {116, 136, 32, 40}, {20, 26, 8, 24}, {96, 99, 15, 33}, {26, 34, 35, 27}, {25, 42, 36, 8}, {89, 109, 38, 20}, {43, 54, 30, 21}, {48, 57, 36, 31}, {83, 86, 1, 35}, {65, 74, 4, 21}, {17, 27, 4, 38}, {1, 13, 25, 18}, {75, 93, 28, 32}, {40, 41, 40, 40}, {6, 11, 6, 34}, {2, 8, 4, 23}, {82, 98, 34, 18}, {81, 94, 30, 8}, {33, 38, 39, 31}, {89, 101, 5, 16}, {22, 32, 22, 27}, {124, 139, 20, 7}, {75, 84, 8, 18}, {26, 37, 8, 4}, {90, 92, 32, 25}, {69, 71, 31, 34}, {90, 105, 30, 38}, {8, 28, 35, 26}, {112, 115, 29, 21}, {103, 121, 29, 28}, {52, 60, 15, 31}, {86, 92, 8, 2}, {79, 88, 39, 3}, {124, 127, 39, 16}, {5, 20, 25, 13}, {38, 57, 25, 39}, {56, 71, 8, 10}, {49, 60, 6, 1}, {49, 52, 35, 16}, {64, 75, 36, 39}, {4, 16, 34, 13}, {125, 129, 8, 19}, {99, 119, 29, 28}, {91, 92, 13, 3}, {127, 135, 13, 19}, {49, 62, 12, 19}, {10, 26, 25, 2}, {119, 120, 35, 12}, {111, 122, 22, 11}, {51, 67, 23, 15}, {66, 69, 9, 21}, {63, 71, 11, 38}, {28, 33, 31, 2},
{66, 84, 12, 11}, {29, 44, 12, 13}, {67, 87, 17, 1}, {82, 98, 7, 12}, {15, 16, 5, 31}, {10, 19, 29, 8}, {121, 123, 9, 15}, {42, 58, 4, 30}, {59, 66, 8, 33}, {75, 88, 39, 32}, {39, 51, 40, 27}, {19, 21, 25, 2}, {18, 30, 3, 38}, {0, 4, 27, 29}, {76, 77, 30, 9}, {42, 46, 1, 19}, {116, 133, 1, 18}, {119, 125, 16, 2}, {78, 93, 33, 2}, {111, 114, 9, 14}, {3, 21, 6, 22}, {26, 37, 21, 16}, {10, 23, 34, 6}, {52, 71, 24, 21}, {122, 140, 25, 38}, {107, 127, 1, 32}, {118, 129, 28, 8}, {52, 61, 7, 16}, {61, 65, 30, 5}, {57, 68, 39, 15}, {56, 75, 35, 18}, {25, 35, 1, 12}, {114, 116, 39, 15}, {117, 120, 24, 36}, {106, 121, 24, 16}, {113, 117, 27, 8}, {122, 133, 20, 1}, {53, 70, 18, 19}, {93, 98, 2, 6}, {71, 77, 37, 21}, {17, 35, 38, 14}, {84, 104, 38, 39}, {78, 84, 9, 36}, {36, 44, 7, 12}, {5, 9, 23, 27}, {29, 42, 37, 24}, {70, 84, 1, 22}, {81, 86, 8, 35}, {90, 92, 4, 9}, {62, 81, 12, 33}, {119, 132, 27, 11}, {113, 118, 32, 37}, {33, 37, 10, 29}, {117, 133, 5, 8}, {70, 88, 37, 40}, {48, 59, 32, 27}, {34, 37, 2, 38}, {116, 117, 19, 19}, {58, 62, 13, 21}, {34, 36, 34, 20}, {116, 118, 39, 10}, {38, 58, 17, 17}, {55, 69, 22, 37}, {119, 137, 29, 21}, {8, 22, 39, 16}, {85, 88, 4, 29}, {94, 95, 14, 36}, {119, 136, 16, 27}, {93, 103, 23, 16}, {44, 64, 22, 19}, {110, 112, 21, 29}, {15, 19, 4, 19}, {6, 20, 29, 10}, {3, 6, 9, 20}, {50, 68, 34, 35}, {13, 20, 28, 24}, {125, 132, 18, 20}, {112, 127, 2, 39}, {61, 74, 36, 29}, {123, 133, 39, 26}, {70, 87, 31, 30}, {80, 85, 40, 6}, {22, 35, 5, 23}, {92, 107, 14, 27}, {86, 104, 26, 24}, {79, 90, 4, 20}, {87, 88, 1, 27}, {19, 36, 8, 32}, {19, 26, 11, 1}, {95, 104, 14, 35}, {63, 66, 8, 5}, {122, 131, 7, 21}, {8, 19, 26, 7}, {1, 21, 18, 2}, {21, 38, 23, 26}, {81, 88, 7, 31}, {21, 32, 20, 25}, {114, 123, 11, 27}, {93, 112, 12, 31}, {37, 51, 11, 1},
{117, 134, 21, 36}, {3, 10, 39, 40}, {104, 122, 9, 40}, {86, 104, 9, 37}, {20, 27, 20, 9}, {47, 62, 25, 22}, {95, 102, 28, 20}, {42, 47, 21, 28}, {12, 18, 24, 27}, {65, 74, 2, 8}, {18, 26, 28, 18}, {65, 85, 21, 14}, {34, 50, 35, 35}, {92, 107, 26, 14}, {19, 27, 34, 24}, {82, 89, 2, 38}, {93, 95, 4, 6}, {124, 138, 6, 1}, {102, 104, 2, 24}, {58, 68, 33, 2}, {86, 94, 24, 17}, {46, 54, 18, 19}, {74, 91, 33, 28}, {105, 112, 1, 33}, {56, 62, 23, 12}, {57, 70, 38, 36}, {120, 132, 4, 36}, {30, 47, 10, 24}, {32, 51, 28, 29}, {117, 137, 25, 27}, {21, 41, 18, 13}, {45, 54, 22, 39}, {91, 106, 37, 10}, {44, 55, 5, 35}, {77, 94, 20, 6}, {104, 114, 8, 5}, {55, 75, 27, 20}, {4, 9, 11, 23}, {12, 16, 8, 35}, {124, 137, 30, 27}, {74, 94, 16, 32}, {70, 72, 32, 33}, {4, 5, 22, 31}, {8, 23, 12, 33}, {56, 71, 37, 25}, {69, 88, 37, 1}, {82, 101, 37, 14}, {36, 47, 2, 4}, {101, 104, 3, 18}, {4, 8, 13, 35}, {37, 51, 20, 2}, {69, 84, 29, 28}, {9, 17, 9, 26}, {127, 143, 20, 16}, {81, 95, 22, 40}, {77, 84, 4, 15}, {32, 37, 9, 20}, {19, 35, 28, 39}, {89, 94, 15, 40}, {111, 114, 3, 16}, {112, 116, 12, 29}, {77, 95, 16, 17}, {122, 135, 31, 8}, {37, 48, 34, 19}, {35, 40, 18, 4}, {86, 99, 23, 24}, {63, 69, 25, 22}, {41, 61, 31, 4}, {114, 120, 11, 37}, {33, 47, 11, 35}, {51, 52, 30, 5}, {124, 125, 18, 27}, {32, 51, 3, 4}, {120, 129, 25, 29}, {107, 121, 2, 32}, {58, 76, 1, 33}, {128, 134, 8, 24}, {85, 105, 21, 36}, {91, 101, 36, 15}, {34, 50, 1, 15}, {128, 145, 28, 35}, {14, 24, 3, 39}, {102, 115, 37, 19}, {37, 55, 5, 9}, {126, 134, 12, 12}, {13, 22, 37, 39}, {65, 68, 30, 30}, {115, 125, 31, 29}, {58, 61, 7, 11}, {123, 129, 33, 30}, {15, 16, 12, 37}, {57, 68, 21, 34}, {62, 74, 7, 12}, {19, 25, 22, 23}, {60, 61, 32, 38}, {24, 37, 5, 28}, {128, 142, 11, 11}, {3, 18, 40, 13}, {118, 133, 12, 31}, {51, 69, 6, 27},
{19, 30, 7, 27}, {49, 57, 17, 22}, {39, 53, 3, 39}, {36, 40, 1, 34}, {87, 88, 29, 40}, {97, 110, 8, 36}, {108, 120, 21, 33}, {82, 84, 1, 22}, {9, 23, 12, 25}, {25, 38, 35, 27}, {81, 99, 19, 6}, {98, 109, 38, 26}, {90, 94, 27, 4}, {74, 81, 28, 19}, {128, 130, 27, 30}, {52, 57, 15, 36}, {8, 21, 11, 28}, {115, 120, 18, 10}, {108, 126, 7, 11}, {70, 75, 16, 3}, {20, 22, 7, 1}, {110, 121, 5, 13}, {16, 20, 10, 28}, {14, 15, 27, 26}, {46, 57, 30, 3}, {2, 5, 14, 16}, {18, 21, 33, 3}, {117, 136, 8, 11}, {94, 111, 21, 30}, {41, 61, 30, 2}, {113, 121, 11, 37}, {58, 78, 21, 13}, {25, 32, 31, 20}, {10, 17, 21, 3}, {27, 30, 2, 26}, {1, 17, 12, 40}, {8, 20, 12, 20}, {82, 90, 35, 25}, {15, 27, 40, 9}, {11, 18, 40, 20}, {100, 107, 9, 6}, {6, 10, 2, 1}, {39, 40, 16, 8}, {16, 35, 7, 11}, {76, 80, 31, 14}, {16, 34, 12, 21}, {121, 127, 20, 20}, {66, 73, 36, 5}, {101, 120, 32, 17}, {25, 31, 14, 17}, {91, 99, 21, 5}, {6, 12, 11, 7}, {91, 102, 27, 12}, {82, 102, 24, 8}, {65, 67, 40, 35}, {7, 9, 19, 7}, {17, 31, 7, 20}, {16, 31, 17, 36}, {26, 36, 16, 16}, {104, 112, 13, 27}, {48, 67, 24, 3}, {46, 56, 32, 27}, {69, 89, 21, 20}, {114, 132, 33, 32}, {90, 106, 7, 27}, {78, 85, 5, 39}, {118, 136, 24, 25}, {110, 116, 28, 14}, {53, 70, 30, 34}, {106, 108, 36, 40}, {76, 96, 17, 23}, {21, 30, 10, 6}, {35, 45, 1, 5}, {92, 105, 30, 36}, {99, 110, 21, 32}, {123, 140, 5, 28}, {101, 109, 8, 18}, {91, 110, 29, 9}, {60, 62, 14, 25}, {98, 106, 35, 2}, {9, 26, 3, 9}, {74, 92, 5, 34}, {37, 45, 17, 2}, {37, 51, 2, 33}, {113, 131, 2, 9}, {106, 117, 26, 2}, {114, 131, 27, 32}, {123, 133, 19, 22}, {75, 80, 10, 20}, {84, 90, 33, 33}, {102, 116, 24, 29}, {39, 44, 3, 2}, {11, 13, 7, 2}, {90, 91, 23, 19}, {67, 86, 39, 40}, {122, 135, 37, 5}, {105, 116, 2, 8}, {71, 82, 19, 19}, {58, 65, 13, 22}, {76, 91, 37, 16},
{27, 28, 13, 16}, {24, 38, 21, 2}, {7, 13, 20, 21}, {2, 12, 15, 29}, {26, 32, 13, 34}, {81, 93, 16, 13}, {42, 56, 15, 14}, {66, 72, 6, 10}, {49, 59, 29, 17}, {51, 70, 23, 29}, {119, 128, 34, 6}, {36, 56, 38, 15}, {10, 23, 17, 11}, {3, 7, 24, 12}, {15, 24, 26, 8}, {74, 76, 17, 10}, {70, 86, 19, 25}, {27, 45, 38, 16}, {107, 119, 31, 18}, {101, 114, 23, 37}, {108, 125, 39, 19}, {1, 14, 27, 26}, {110, 121, 35, 8}, {37, 46, 28, 25}, {89, 94, 17, 8}, {119, 123, 19, 6}, {13, 27, 22, 18}, {32, 44, 40, 19}, {52, 56, 17, 39}, {96, 98, 32, 32}, {46, 60, 14, 24}, {120, 131, 9, 24}, {54, 71, 29, 10}, {19, 31, 37, 22}, {39, 55, 23, 30}, {47, 59, 15, 8}, {40, 49, 20, 23}, {69, 82, 22, 32}, {2, 8, 10, 21}, {79, 81, 33, 28}, {6, 20, 7, 9}, {46, 48, 12, 15}, {54, 57, 11, 1}, {93, 95, 24, 40}, {101, 110, 37, 35}, {14, 29, 8, 14}, {4, 16, 36, 38}, {95, 98, 4, 8}, {104, 107, 6, 5}, {21, 29, 25, 40}, {1, 10, 25, 2}, {57, 59, 24, 2}, {118, 119, 30, 1}, {107, 127, 28, 37}, {127, 141, 5, 38}, {87, 99, 33, 15}, {62, 73, 22, 29}, {41, 50, 16, 18}, {100, 113, 15, 20}, {37, 52, 40, 15}, {17, 35, 13, 16}, {33, 48, 39, 18}, {98, 111, 29, 2}, {59, 78, 33, 12}, {7, 16, 40, 19}, {47, 55, 30, 29}, {35, 46, 40, 8}, {101, 112, 15, 39}, {73, 88, 21, 2}, {56, 76, 4, 10}, {71, 75, 20, 4}, {98, 105, 35, 29}, {5, 24, 30, 20}, {32, 36, 19, 33}, {61, 70, 28, 35}, {101, 109, 11, 29}, {47, 50, 31, 24}, {106, 125, 31, 4}, {36, 55, 24, 34}, {7, 8, 17, 18}, {47, 67, 34, 32}, {11, 12, 29, 2}, {32, 34, 9, 37}, {48, 64, 14, 17}, {108, 114, 26, 31}, {124, 142, 32, 3}, {17, 37, 36, 17}, {22, 40, 18, 6}, {103, 104, 39, 29}, {47, 57, 18, 18}, {85, 92, 6, 21}, {100, 118, 26, 27}, {105, 114, 22, 27}, {104, 107, 14, 30}, {99, 117, 27, 20}, {91, 95, 15, 8}, {21, 26, 39, 25}, {51, 71, 30, 37}, {63, 73, 21, 32}, {128, 145, 5, 18},
{50, 51, 39, 31}, {35, 53, 27, 23}, {107, 114, 2, 24}, {12, 28, 24, 4}, {5, 20, 34, 39}, {98, 106, 28, 23}, {23, 28, 30, 34}, {69, 87, 10, 38}, {23, 42, 16, 27}, {27, 43, 16, 13}, {59, 77, 27, 33}, {28, 45, 28, 30}, {88, 89, 15, 9}, {103, 106, 14, 23}, {89, 105, 3, 28}, {29, 32, 36, 11}, {29, 43, 32, 20}, {104, 106, 8, 18}, {19, 22, 14, 11}, {99, 114, 25, 40}, {18, 27, 17, 28}, {69, 81, 36, 15}, {15, 30, 6, 12}, {46, 64, 12, 21}, {38, 44, 35, 33}, {36, 44, 31, 5}, {20, 29, 35, 19}, {83, 96, 14, 32}, {127, 135, 18, 2}, {114, 134, 23, 35}, {34, 45, 18, 40}, {122, 131, 19, 21}, {86, 103, 37, 36}, {94, 110, 15, 26}, {35, 54, 33, 24}, {91, 102, 12, 31}, {26, 42, 27, 1}, {9, 29, 35, 30}, {115, 130, 36, 4}, {44, 55, 32, 38}, {62, 67, 27, 38}, {65, 83, 18, 2}, {6, 13, 33, 32}, {46, 55, 33, 11}, {30, 46, 1, 19}, {76, 87, 30, 27}, {41, 59, 14, 25}, {49, 51, 39, 19}, {122, 140, 3, 3}, {105, 108, 33, 40}, {106, 121, 32, 19}, {76, 96, 16, 11}, {41, 51, 27, 6}, {81, 101, 10, 30}, {121, 126, 19, 24}, {113, 125, 28, 25}, {47, 50, 38, 13}, {105, 123, 10, 27}, {85, 100, 1, 36}, {56, 72, 37, 25}, {69, 83, 24, 4}, {106, 124, 33, 27}, {99, 117, 30, 30}, {41, 57, 27, 31}, {80, 87, 7, 13}, {43, 44, 13, 37}, {33, 37, 6, 25}, {16, 24, 27, 20}, {126, 140, 4, 34}, {19, 38, 8, 19}, {96, 100, 14, 15}, {48, 54, 13, 26}, {56, 73, 21, 14}, {92, 108, 25, 3}, {14, 17, 22, 4}, {76, 77, 30, 16}, {30, 49, 32, 8}, {37, 54, 4, 24}, {6, 21, 37, 10}, {22, 26, 2, 23}, {81, 91, 10, 9}, {92, 95, 34, 17}, {25, 37, 12, 26}, {2, 4, 34, 23}, {7, 25, 8, 6}, {69, 86, 10, 10}, {112, 122, 4, 28}, {103, 110, 21, 23}, {120, 123, 2, 37}, {51, 54, 7, 14}, {29, 41, 37, 20}, {125, 143, 31, 28}, {31, 36, 28, 38}, {90, 105, 12, 2}, {14, 16, 30, 37}, {124, 128, 36, 22}, {45, 60, 12, 21}, {67, 83, 27, 17}, {100, 112, 37, 30},
};
// *INDENT-ON*
for(i = 0; i < 1000; i++) {
uint8_t from = ranges[i][0];
uint8_t to = ranges[i][1];
read_range(&f, from, to);
from = to + 1;
uint8_t next = ranges[i][2];
read_next(&f, from, next);
from += next;
next = ranges[i][3];
read_next(&f, from, next);
}
res = lv_fs_close(&f);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
drv->cache_size = original_cache_size;
}
void test_write_read_random(void)
{
lv_fs_drv_t * drv = lv_fs_get_drv('A');
uint32_t original_cache_size = drv->cache_size;
drv->cache_size = 7;
/* create the file and reopen for read+write. stdio "rb+" mode requires the file to exist */
lv_fs_res_t res;
lv_fs_file_t f;
res = lv_fs_open(&f, "A:fs_write_read_random.bin", LV_FS_MODE_WR);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
res = lv_fs_close(&f);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
res = lv_fs_open(&f, "A:fs_write_read_random.bin", LV_FS_MODE_WR | LV_FS_MODE_RD);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
uint8_t buf1000[1000];
for(uint32_t i = 0; i < 1000; i++) buf1000[i] = i;
res = lv_fs_write(&f, buf1000, 1000, NULL);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
/**
* {{{action, amount}, ... x20 actions per combo}, ... x100 combos}
* actions are read (0), write (1), seek (2)
* read and write amount ranges from 1 to 20. seek amount ranges from -20 to 20.
* seeks occur as frequently as reads+writes combined.
*/
// *INDENT-OFF*
static const int8_t actions[100][20][2] = {
{{2, -20}, {2, 17}, {0, 20}, {2, 19}, {1, 18}, {1, 4}, {1, 13}, {2, -7}, {1, 6}, {1, 19}, {2, 3}, {1, 12}, {2, 12}, {2, -2}, {2, -20}, {2, -17}, {1, 15}, {2, -17}, {0, 18}, {2, 14}}, {{2, 19}, {2, 17}, {2, -12}, {2, -5}, {2, -1}, {2, -17}, {1, 4}, {2, 19}, {2, 3}, {2, 1}, {2, 10}, {2, 18}, {0, 10}, {2, 8}, {2, 17}, {2, 20}, {0, 5}, {0, 14}, {0, 6}, {1, 8}}, {{0, 1}, {2, -20}, {2, -12}, {1, 9}, {0, 9}, {2, 19}, {1, 8}, {0, 13}, {0, 5}, {2, -7}, {2, -14}, {0, 8}, {2, 13}, {1, 5}, {0, 3}, {0, 16}, {2, 19}, {0, 4}, {1, 6}, {2, -4}}, {{0, 1}, {2, 12}, {1, 7}, {1, 17}, {1, 19}, {0, 8}, {1, 1}, {2, 9}, {2, -14}, {2, 14}, {2, -17}, {2, 11}, {1, 4}, {2, 19}, {2, -18}, {1, 12}, {2, -14}, {0, 9}, {1, 7}, {2, 17}}, {{2, -6}, {0, 13}, {1, 15}, {1, 8}, {2, -1}, {2, 15}, {2, 3}, {2, -16}, {2, -11}, {2, 14}, {2, -19}, {2, 6}, {1, 10}, {1, 6}, {1, 12}, {2, 12}, {0, 10}, {2, 10}, {2, -4}, {2, 5}}, {{2, -6}, {1, 2}, {1, 11}, {1, 19}, {2, 2}, {2, 20}, {2, -19}, {2, -7}, {0, 13}, {2, 4}, {1, 6}, {0, 9}, {0, 6}, {2, -1}, {2, -5}, {2, 14}, {2, 15}, {0, 4}, {0, 6}, {0, 10}}, {{1, 17}, {1, 17}, {0, 15}, {0, 3}, {1, 8}, {2, -9}, {1, 13}, {0, 20}, {0, 3}, {1, 17}, {2, -8}, {2, -1}, {1, 13}, {0, 13}, {0, 8}, {1, 1}, {2, -4}, {2, 13}, {2, 17}, {2, -14}}, {{1, 17}, {1, 13}, {1, 17}, {1, 5}, {1, 3}, {0, 20}, {2, 12}, {0, 13}, {2, 5}, {2, -10}, {2, 10}, {0, 6}, {2, 18}, {0, 17}, {2, 2}, {1, 5}, {2, 16}, {2, -10}, {0, 2}, {2, -9}}, {{2, 7}, {2, -2}, {1, 14}, {0, 15}, {1, 2}, {2, 6}, {2, 11}, {1, 2}, {0, 12}, {2, 9}, {0, 17}, {0, 15}, {2, -19}, {0, 11}, {2, 3}, {2, 15}, {2, 19}, {2, -16}, {1, 6}, {1, 15}}, {{2, 12}, {1, 2}, {2, -4}, {2, -20}, {0, 18}, {2, -16}, {1, 15}, {2, -9}, {2, -7}, {1, 1}, {0, 7}, {0, 18}, {1, 18}, {0, 2}, {2, 17}, {1, 2}, {1, 8}, {1, 18}, {2, -7}, {0, 2}},
{{2, 19}, {2, 17}, {2, -7}, {0, 17}, {0, 18}, {1, 4}, {1, 1}, {0, 3}, {2, 4}, {2, -4}, {1, 20}, {0, 1}, {2, 20}, {0, 6}, {2, 10}, {0, 19}, {2, -1}, {0, 7}, {0, 16}, {1, 13}}, {{2, 10}, {2, 13}, {2, 15}, {2, 3}, {2, 12}, {0, 14}, {2, 6}, {2, 14}, {2, -13}, {2, 18}, {0, 19}, {2, -8}, {2, -9}, {0, 12}, {2, -20}, {2, -6}, {2, 15}, {2, 18}, {1, 18}, {1, 10}}, {{0, 15}, {2, -6}, {2, 17}, {1, 7}, {0, 9}, {0, 11}, {0, 12}, {0, 20}, {2, -1}, {2, -8}, {0, 13}, {2, 19}, {1, 3}, {0, 18}, {1, 13}, {2, 12}, {2, 13}, {1, 5}, {2, -14}, {2, 18}}, {{0, 6}, {1, 4}, {1, 6}, {0, 2}, {2, 8}, {1, 9}, {2, 20}, {0, 9}, {2, -1}, {2, 5}, {0, 18}, {2, 8}, {2, 12}, {2, -14}, {0, 18}, {1, 1}, {2, -15}, {2, 14}, {2, -11}, {2, -2}}, {{1, 4}, {2, 6}, {2, 18}, {1, 19}, {0, 18}, {0, 19}, {0, 14}, {0, 12}, {2, 3}, {0, 19}, {2, -20}, {0, 8}, {2, -15}, {2, -15}, {0, 8}, {1, 17}, {2, 2}, {1, 14}, {0, 11}, {0, 13}}, {{2, -10}, {2, -8}, {1, 18}, {1, 11}, {1, 5}, {0, 2}, {2, -19}, {2, -9}, {1, 5}, {2, -1}, {2, 2}, {1, 5}, {0, 9}, {0, 17}, {2, 2}, {0, 10}, {1, 12}, {1, 10}, {0, 8}, {2, -13}}, {{0, 13}, {1, 5}, {2, -1}, {2, -16}, {2, 2}, {0, 6}, {2, -11}, {0, 5}, {2, 5}, {2, -6}, {2, -6}, {1, 19}, {0, 8}, {2, -16}, {2, 14}, {0, 11}, {0, 14}, {0, 18}, {0, 14}, {2, 1}}, {{2, 3}, {2, -2}, {0, 10}, {1, 1}, {0, 10}, {2, -15}, {2, 19}, {2, 2}, {1, 15}, {1, 10}, {2, -18}, {0, 20}, {0, 10}, {2, 3}, {1, 13}, {0, 8}, {0, 16}, {0, 14}, {2, 13}, {2, -7}}, {{0, 4}, {1, 7}, {0, 2}, {0, 15}, {0, 20}, {1, 9}, {0, 14}, {2, 18}, {0, 1}, {0, 4}, {2, -17}, {1, 10}, {1, 15}, {0, 2}, {2, -6}, {2, 4}, {2, 4}, {2, 17}, {2, -13}, {1, 20}}, {{1, 8}, {0, 20}, {2, 4}, {1, 6}, {2, -19}, {1, 4}, {0, 5}, {1, 8}, {1, 17}, {2, -4}, {2, 14}, {1, 10}, {2, 7}, {1, 18}, {2, 17}, {1, 6}, {0, 20}, {2, 1}, {2, -12}, {2, 18}},
{{2, -7}, {1, 12}, {2, 4}, {2, 14}, {0, 13}, {1, 17}, {2, -2}, {2, -9}, {2, -13}, {1, 4}, {2, 4}, {1, 5}, {0, 15}, {2, -11}, {2, 3}, {2, 1}, {2, -11}, {2, 11}, {2, -11}, {0, 4}}, {{1, 7}, {2, 20}, {0, 6}, {0, 9}, {1, 2}, {0, 11}, {2, 4}, {2, -19}, {0, 17}, {2, -7}, {0, 20}, {0, 10}, {1, 11}, {1, 20}, {1, 6}, {2, 14}, {0, 11}, {0, 19}, {2, 4}, {1, 8}}, {{0, 9}, {2, -3}, {1, 17}, {2, 14}, {2, 3}, {1, 19}, {2, 17}, {0, 18}, {2, 16}, {0, 9}, {2, -15}, {1, 14}, {2, 11}, {2, -7}, {0, 17}, {2, 12}, {2, 6}, {2, 9}, {0, 7}, {1, 3}}, {{0, 1}, {2, 13}, {1, 19}, {0, 19}, {2, 6}, {2, -14}, {2, 8}, {2, -18}, {2, 4}, {2, -7}, {0, 12}, {2, 15}, {1, 3}, {2, -19}, {2, 15}, {2, -2}, {1, 19}, {1, 18}, {1, 19}, {0, 16}}, {{2, 7}, {2, 14}, {2, 14}, {2, -19}, {0, 1}, {2, -5}, {0, 17}, {2, 2}, {2, 15}, {1, 13}, {0, 20}, {0, 12}, {2, 20}, {0, 9}, {2, -8}, {0, 14}, {1, 19}, {2, -15}, {2, 17}, {2, -12}}, {{0, 16}, {2, -7}, {2, -4}, {1, 11}, {1, 17}, {2, -14}, {0, 16}, {2, 6}, {1, 19}, {2, 17}, {2, 10}, {2, -12}, {2, -17}, {1, 4}, {2, -14}, {2, -7}, {2, -17}, {2, -1}, {2, -16}, {1, 8}}, {{0, 5}, {0, 15}, {2, 4}, {2, 20}, {2, 7}, {2, 3}, {2, 17}, {0, 8}, {0, 18}, {2, -18}, {1, 1}, {0, 15}, {2, -4}, {0, 13}, {1, 11}, {0, 4}, {2, 11}, {1, 11}, {1, 10}, {2, -9}}, {{2, -5}, {2, -16}, {1, 2}, {1, 17}, {2, 9}, {2, -2}, {0, 7}, {0, 14}, {2, -10}, {0, 6}, {1, 14}, {1, 15}, {2, 12}, {2, 11}, {2, -9}, {2, -10}, {2, -14}, {2, 9}, {0, 13}, {2, 5}}, {{2, 8}, {2, -16}, {2, 20}, {1, 8}, {1, 2}, {2, -5}, {2, -20}, {1, 2}, {1, 4}, {1, 9}, {0, 19}, {2, -18}, {0, 6}, {0, 13}, {1, 5}, {2, 2}, {0, 4}, {1, 19}, {2, 15}, {1, 12}}, {{2, -8}, {0, 16}, {1, 10}, {2, 5}, {2, -16}, {0, 3}, {2, 5}, {0, 6}, {1, 17}, {2, 1}, {2, 13}, {0, 3}, {0, 6}, {0, 6}, {0, 19}, {1, 13}, {2, 19}, {2, 5}, {1, 16}, {2, 5}},
{{2, -19}, {2, -1}, {0, 19}, {2, -3}, {2, 13}, {2, -12}, {0, 2}, {2, -20}, {2, 15}, {2, -9}, {2, -2}, {2, 13}, {2, -6}, {0, 2}, {1, 6}, {2, -1}, {0, 12}, {0, 20}, {2, -14}, {1, 2}}, {{1, 9}, {2, -14}, {2, -2}, {2, -13}, {0, 3}, {1, 6}, {2, 20}, {2, 11}, {2, 17}, {2, 5}, {0, 5}, {1, 1}, {2, -9}, {1, 8}, {2, -2}, {0, 18}, {2, -8}, {1, 11}, {2, 6}, {1, 7}}, {{2, 17}, {2, 14}, {2, 16}, {1, 20}, {2, -1}, {2, -7}, {1, 3}, {1, 14}, {0, 1}, {0, 18}, {2, -14}, {0, 10}, {0, 18}, {2, 19}, {1, 13}, {2, -16}, {1, 17}, {1, 1}, {2, -13}, {0, 13}}, {{2, -2}, {0, 14}, {0, 12}, {2, -8}, {1, 16}, {0, 18}, {2, 5}, {2, 13}, {1, 14}, {2, -4}, {2, 16}, {2, -16}, {2, 16}, {1, 18}, {2, 15}, {2, 4}, {2, -5}, {1, 7}, {2, -20}, {2, -9}}, {{2, 18}, {2, 2}, {2, 5}, {0, 4}, {2, 17}, {2, -15}, {2, 8}, {2, -11}, {1, 8}, {2, -6}, {2, -13}, {0, 5}, {0, 18}, {0, 15}, {2, -8}, {2, -15}, {1, 1}, {2, 4}, {2, -9}, {2, 14}}, {{2, -1}, {2, 1}, {1, 12}, {0, 9}, {2, -11}, {1, 4}, {1, 11}, {1, 5}, {0, 12}, {2, -7}, {1, 1}, {0, 6}, {0, 15}, {2, -10}, {2, -18}, {2, -12}, {0, 3}, {2, 2}, {2, -17}, {2, 1}}, {{2, -5}, {2, 18}, {1, 2}, {2, 14}, {2, 20}, {0, 13}, {0, 11}, {0, 6}, {2, -7}, {2, 13}, {1, 13}, {2, -1}, {1, 12}, {2, -9}, {2, 3}, {1, 6}, {2, -16}, {0, 6}, {0, 9}, {2, -14}}, {{1, 6}, {2, 7}, {2, -13}, {0, 5}, {1, 4}, {0, 15}, {2, 18}, {2, -4}, {2, 16}, {1, 1}, {2, 17}, {0, 2}, {1, 12}, {0, 17}, {1, 18}, {1, 5}, {1, 8}, {1, 4}, {2, -9}, {1, 9}}, {{0, 20}, {1, 10}, {2, 20}, {2, 13}, {0, 18}, {0, 10}, {1, 3}, {0, 8}, {2, -16}, {2, -16}, {2, -2}, {0, 20}, {2, -19}, {2, -11}, {1, 17}, {1, 18}, {1, 5}, {0, 6}, {2, -9}, {1, 8}}, {{0, 18}, {0, 19}, {2, 16}, {2, -14}, {1, 7}, {1, 9}, {0, 16}, {0, 16}, {1, 17}, {0, 14}, {2, -16}, {1, 6}, {1, 11}, {2, 7}, {1, 19}, {1, 11}, {2, -14}, {0, 7}, {1, 12}, {0, 2}},
{{2, 3}, {2, -15}, {0, 13}, {2, -3}, {0, 16}, {1, 18}, {0, 11}, {0, 16}, {1, 13}, {2, -18}, {1, 14}, {2, 11}, {0, 11}, {2, -14}, {2, -19}, {0, 2}, {2, -7}, {0, 5}, {0, 20}, {2, -7}}, {{2, 9}, {2, 5}, {2, 7}, {0, 15}, {2, 4}, {0, 5}, {2, -17}, {2, 16}, {2, 8}, {0, 11}, {0, 1}, {1, 8}, {2, -5}, {1, 1}, {2, 4}, {2, -4}, {2, -17}, {0, 5}, {1, 10}, {0, 5}}, {{0, 11}, {1, 16}, {1, 18}, {0, 5}, {2, -13}, {0, 5}, {1, 13}, {1, 10}, {1, 11}, {0, 5}, {1, 9}, {1, 4}, {1, 19}, {2, 1}, {1, 19}, {1, 18}, {1, 8}, {2, 2}, {2, -5}, {1, 4}}, {{0, 12}, {1, 16}, {2, -1}, {1, 10}, {1, 10}, {2, -19}, {2, -20}, {1, 17}, {1, 19}, {1, 4}, {2, 12}, {0, 1}, {2, -15}, {2, -1}, {2, -10}, {2, -19}, {0, 18}, {0, 6}, {2, 18}, {0, 18}}, {{1, 10}, {0, 13}, {2, 3}, {0, 20}, {0, 19}, {0, 5}, {0, 9}, {0, 5}, {0, 20}, {0, 9}, {2, 16}, {1, 11}, {0, 12}, {2, -17}, {0, 20}, {0, 14}, {1, 17}, {2, 15}, {1, 7}, {2, -1}}, {{2, -10}, {2, 1}, {0, 2}, {2, -11}, {2, -17}, {2, -10}, {1, 9}, {2, -6}, {2, -19}, {1, 14}, {0, 4}, {1, 6}, {2, -9}, {2, 3}, {1, 2}, {2, 19}, {1, 15}, {0, 7}, {0, 4}, {2, 2}}, {{1, 12}, {2, -8}, {2, 13}, {2, -19}, {0, 17}, {0, 20}, {1, 3}, {1, 15}, {1, 20}, {2, 17}, {0, 12}, {2, -2}, {1, 8}, {2, -12}, {0, 11}, {2, 17}, {1, 14}, {1, 13}, {2, 2}, {2, 3}}, {{0, 13}, {1, 13}, {2, -4}, {1, 17}, {1, 1}, {1, 5}, {0, 10}, {1, 12}, {0, 9}, {2, -16}, {0, 13}, {2, 19}, {2, 9}, {1, 18}, {2, -1}, {2, -14}, {0, 5}, {1, 2}, {0, 20}, {2, -19}}, {{1, 7}, {2, 19}, {2, 11}, {2, -16}, {1, 19}, {2, -14}, {0, 7}, {1, 10}, {2, 8}, {0, 12}, {1, 12}, {2, -11}, {2, 6}, {2, -16}, {2, 15}, {1, 20}, {2, -12}, {1, 7}, {2, -16}, {2, 7}}, {{0, 8}, {2, 19}, {1, 12}, {2, -12}, {2, 4}, {1, 10}, {1, 13}, {2, 2}, {2, -14}, {2, -10}, {2, 18}, {1, 16}, {0, 10}, {2, 19}, {2, -1}, {1, 17}, {2, -1}, {0, 14}, {1, 11}, {0, 18}},
{{2, 2}, {2, -2}, {2, 12}, {0, 7}, {0, 14}, {2, -15}, {2, 13}, {2, -3}, {0, 1}, {2, -2}, {1, 2}, {2, 4}, {2, 4}, {2, 16}, {1, 4}, {2, 1}, {1, 9}, {1, 6}, {1, 12}, {1, 11}}, {{2, -10}, {1, 16}, {1, 12}, {0, 18}, {2, -13}, {0, 19}, {2, 15}, {0, 11}, {0, 2}, {0, 4}, {0, 7}, {0, 10}, {2, -10}, {2, 11}, {0, 13}, {0, 10}, {2, -14}, {2, -18}, {0, 7}, {2, 16}}, {{2, -19}, {2, -5}, {1, 9}, {0, 15}, {2, 4}, {2, -14}, {1, 13}, {2, 10}, {2, -7}, {2, 14}, {2, 8}, {2, 9}, {0, 14}, {2, -4}, {1, 2}, {1, 19}, {0, 18}, {2, 18}, {1, 6}, {2, -6}}, {{2, -15}, {2, 1}, {0, 8}, {1, 5}, {2, -11}, {2, -3}, {0, 19}, {0, 4}, {1, 19}, {1, 2}, {1, 2}, {0, 3}, {0, 16}, {2, -3}, {2, 18}, {1, 20}, {2, -16}, {2, -2}, {2, -17}, {1, 15}}, {{1, 19}, {2, -11}, {1, 13}, {0, 14}, {1, 18}, {2, 11}, {2, 13}, {2, -14}, {1, 5}, {2, -6}, {0, 4}, {2, 19}, {0, 12}, {1, 4}, {2, -6}, {2, 8}, {2, 9}, {2, -10}, {2, -3}, {2, -19}}, {{2, 7}, {2, -9}, {2, 5}, {2, 12}, {2, -20}, {2, -3}, {2, -12}, {2, 5}, {0, 6}, {2, 15}, {1, 8}, {1, 9}, {2, 18}, {2, -14}, {2, 10}, {1, 5}, {1, 2}, {0, 14}, {2, 14}, {0, 19}}, {{2, 12}, {0, 9}, {0, 14}, {1, 4}, {2, 4}, {2, -8}, {2, 4}, {0, 13}, {1, 10}, {2, 18}, {2, 13}, {2, 15}, {1, 18}, {2, 7}, {2, -18}, {2, 18}, {1, 9}, {2, -9}, {0, 16}, {2, -14}}, {{0, 16}, {2, 9}, {2, 7}, {1, 6}, {0, 14}, {2, -18}, {1, 14}, {1, 2}, {0, 10}, {1, 6}, {0, 10}, {2, 2}, {1, 1}, {0, 19}, {1, 6}, {2, -3}, {2, 3}, {2, 12}, {2, 5}, {1, 18}}, {{2, -17}, {0, 17}, {0, 5}, {2, 18}, {2, 8}, {0, 14}, {0, 10}, {1, 20}, {2, 7}, {1, 10}, {1, 14}, {1, 10}, {0, 11}, {1, 15}, {0, 16}, {1, 14}, {0, 3}, {2, 16}, {2, -5}, {2, -4}}, {{1, 15}, {2, -9}, {0, 11}, {0, 16}, {2, 1}, {0, 12}, {0, 7}, {0, 16}, {2, 14}, {0, 3}, {1, 11}, {2, 4}, {1, 6}, {2, -1}, {1, 20}, {1, 13}, {0, 2}, {2, -12}, {0, 9}, {2, 8}},
{{0, 1}, {2, -4}, {0, 19}, {2, -15}, {2, -16}, {2, -10}, {2, 7}, {0, 10}, {2, -6}, {2, -8}, {2, -3}, {2, 18}, {1, 20}, {2, 10}, {1, 18}, {2, -3}, {0, 7}, {2, 3}, {2, 14}, {2, 15}}, {{1, 17}, {0, 7}, {1, 17}, {2, -8}, {2, -12}, {2, -9}, {2, 15}, {0, 10}, {1, 10}, {2, -6}, {2, -20}, {1, 17}, {2, -9}, {1, 15}, {1, 3}, {1, 8}, {0, 1}, {1, 13}, {2, -5}, {0, 14}}, {{2, 8}, {0, 11}, {0, 12}, {2, 5}, {2, -4}, {2, -5}, {2, -2}, {0, 20}, {2, -4}, {1, 1}, {1, 2}, {0, 4}, {2, 14}, {1, 17}, {2, -13}, {1, 13}, {2, 12}, {2, 20}, {2, 14}, {2, -9}}, {{2, -20}, {2, 13}, {1, 20}, {2, 20}, {2, 9}, {0, 16}, {2, 1}, {0, 13}, {2, 17}, {2, 8}, {2, 13}, {2, -3}, {2, -1}, {2, -19}, {2, 1}, {1, 16}, {2, -16}, {0, 6}, {2, 2}, {1, 8}}, {{1, 4}, {1, 9}, {1, 8}, {2, -12}, {0, 4}, {1, 8}, {0, 9}, {2, -2}, {2, -19}, {2, 2}, {2, -1}, {0, 14}, {2, 4}, {2, -17}, {0, 1}, {2, 4}, {2, -20}, {2, 3}, {0, 7}, {1, 4}}, {{0, 6}, {2, -5}, {1, 13}, {2, 15}, {2, 11}, {0, 7}, {1, 17}, {2, 9}, {1, 14}, {2, -7}, {2, 12}, {2, -18}, {0, 19}, {2, -1}, {2, 14}, {2, 5}, {2, -16}, {1, 2}, {2, -2}, {0, 17}}, {{1, 11}, {2, 4}, {2, 7}, {1, 16}, {2, 14}, {0, 14}, {2, 16}, {1, 11}, {1, 10}, {2, -3}, {2, -10}, {1, 7}, {2, 9}, {0, 19}, {2, 1}, {0, 7}, {1, 11}, {0, 9}, {2, -16}, {1, 8}}, {{0, 10}, {0, 4}, {2, -8}, {2, 20}, {2, 16}, {2, 5}, {0, 16}, {1, 6}, {2, 2}, {2, 14}, {2, 11}, {1, 15}, {2, -10}, {2, -5}, {0, 4}, {0, 4}, {2, -13}, {2, 11}, {0, 13}, {0, 11}}, {{0, 6}, {1, 4}, {2, 15}, {2, 17}, {1, 1}, {2, -20}, {1, 18}, {0, 19}, {2, -12}, {2, 1}, {2, -15}, {2, -11}, {1, 19}, {0, 13}, {1, 2}, {0, 17}, {2, 14}, {0, 14}, {2, 12}, {0, 19}}, {{2, -16}, {1, 20}, {2, -14}, {1, 7}, {2, -13}, {2, 19}, {2, 20}, {2, -14}, {1, 17}, {2, 20}, {1, 2}, {2, -19}, {2, -17}, {2, 18}, {2, 6}, {1, 17}, {2, 7}, {0, 8}, {1, 20}, {2, 9}},
{{2, 20}, {2, 17}, {2, 15}, {1, 13}, {0, 7}, {2, -6}, {0, 8}, {2, -17}, {1, 15}, {2, -20}, {0, 17}, {2, -17}, {0, 12}, {1, 14}, {2, -8}, {2, -17}, {0, 12}, {2, -3}, {2, -13}, {0, 7}}, {{0, 3}, {2, 12}, {2, 4}, {0, 13}, {0, 15}, {1, 4}, {2, 7}, {2, -20}, {0, 4}, {0, 6}, {0, 12}, {2, 10}, {2, -13}, {0, 20}, {2, -11}, {0, 16}, {2, -13}, {2, -5}, {1, 14}, {0, 7}}, {{2, 16}, {1, 11}, {2, -1}, {0, 9}, {0, 19}, {2, 9}, {2, 6}, {1, 15}, {2, 2}, {2, 8}, {1, 3}, {2, 20}, {2, -18}, {2, -15}, {2, -20}, {0, 10}, {1, 9}, {2, 5}, {2, -17}, {2, 14}}, {{2, -15}, {2, -10}, {2, -18}, {1, 20}, {1, 4}, {0, 18}, {1, 10}, {2, 19}, {2, -9}, {2, 20}, {0, 1}, {0, 11}, {2, -18}, {2, 5}, {1, 15}, {0, 10}, {2, -14}, {2, 6}, {0, 17}, {0, 3}}, {{1, 18}, {1, 5}, {0, 11}, {2, 11}, {0, 13}, {1, 5}, {0, 19}, {2, 20}, {1, 10}, {2, 19}, {0, 13}, {0, 7}, {2, 1}, {2, 14}, {1, 19}, {0, 9}, {1, 17}, {2, 18}, {0, 11}, {1, 9}}, {{2, -17}, {2, 10}, {2, -19}, {2, -18}, {2, 6}, {0, 9}, {0, 20}, {1, 7}, {2, -14}, {2, -11}, {0, 14}, {1, 1}, {0, 13}, {0, 2}, {2, 3}, {0, 2}, {2, 11}, {2, 10}, {2, 12}, {2, -4}}, {{2, 13}, {1, 14}, {2, 7}, {1, 12}, {2, -9}, {2, -4}, {2, -8}, {2, 13}, {0, 3}, {1, 20}, {2, 2}, {2, 5}, {0, 19}, {0, 10}, {2, 14}, {2, -15}, {1, 5}, {2, 18}, {2, -8}, {2, 6}}, {{1, 5}, {1, 9}, {1, 19}, {2, 19}, {0, 13}, {2, 2}, {2, 12}, {2, 17}, {2, -16}, {0, 12}, {0, 9}, {1, 17}, {0, 13}, {2, 7}, {1, 7}, {2, 14}, {0, 12}, {0, 7}, {2, -16}, {1, 7}}, {{2, 15}, {0, 9}, {1, 3}, {0, 4}, {2, -3}, {0, 12}, {2, 9}, {0, 6}, {1, 16}, {0, 10}, {2, -6}, {1, 20}, {2, 11}, {2, -3}, {2, -6}, {0, 15}, {0, 14}, {0, 11}, {2, -19}, {2, -14}}, {{0, 12}, {2, 8}, {1, 20}, {2, 18}, {2, 3}, {2, 2}, {2, 4}, {2, 7}, {2, -19}, {2, -9}, {2, 2}, {0, 19}, {0, 11}, {2, -9}, {0, 9}, {2, -14}, {1, 13}, {0, 2}, {0, 1}, {2, -19}},
{{2, -4}, {1, 6}, {0, 18}, {2, 4}, {1, 12}, {0, 17}, {2, 10}, {2, 13}, {2, 10}, {1, 10}, {2, -1}, {2, -11}, {2, -15}, {2, -5}, {2, -16}, {2, -12}, {0, 2}, {2, -10}, {2, 15}, {1, 2}}, {{2, -9}, {2, -14}, {1, 4}, {0, 5}, {2, -9}, {0, 7}, {0, 9}, {1, 16}, {1, 10}, {2, -14}, {0, 7}, {2, -18}, {0, 19}, {1, 3}, {1, 7}, {2, -19}, {2, 14}, {0, 9}, {1, 7}, {2, -5}}, {{2, 16}, {0, 13}, {2, 20}, {2, -9}, {0, 20}, {2, 20}, {0, 5}, {0, 6}, {1, 4}, {2, -11}, {0, 14}, {0, 9}, {2, 18}, {0, 14}, {0, 12}, {2, 16}, {2, 8}, {2, -13}, {1, 9}, {1, 3}}, {{2, 1}, {2, 13}, {2, -8}, {0, 9}, {2, -16}, {0, 12}, {0, 12}, {2, 19}, {2, -10}, {2, 1}, {2, -20}, {1, 10}, {0, 18}, {2, -15}, {2, -15}, {1, 15}, {0, 15}, {0, 1}, {2, -5}, {0, 19}}, {{2, 6}, {2, 15}, {2, -20}, {1, 20}, {2, 3}, {2, 7}, {1, 1}, {0, 5}, {0, 4}, {2, 8}, {1, 19}, {2, -3}, {2, 18}, {1, 10}, {0, 11}, {2, -19}, {0, 3}, {2, 5}, {1, 4}, {0, 6}}, {{0, 5}, {2, -17}, {1, 1}, {0, 1}, {2, -9}, {0, 8}, {2, -10}, {2, -4}, {0, 13}, {2, 19}, {0, 6}, {2, 9}, {2, 14}, {2, 11}, {0, 16}, {2, 13}, {1, 1}, {2, 9}, {2, 14}, {0, 18}}, {{0, 10}, {1, 12}, {1, 4}, {2, -12}, {2, 7}, {0, 5}, {1, 15}, {2, 7}, {2, 17}, {1, 18}, {2, 3}, {0, 12}, {1, 8}, {1, 13}, {2, -17}, {1, 20}, {0, 18}, {1, 12}, {1, 16}, {0, 16}}, {{2, -10}, {2, -1}, {2, 10}, {1, 4}, {2, -12}, {1, 19}, {2, 18}, {2, -15}, {2, -5}, {1, 11}, {2, -7}, {0, 20}, {2, -12}, {2, -12}, {1, 11}, {2, 8}, {2, 2}, {2, -2}, {2, -4}, {2, 19}}, {{2, 5}, {1, 15}, {1, 18}, {2, 20}, {1, 4}, {0, 7}, {2, -8}, {2, 1}, {2, -6}, {2, 8}, {1, 1}, {2, 12}, {1, 15}, {0, 16}, {1, 13}, {0, 1}, {0, 19}, {0, 20}, {2, -3}, {0, 12}}, {{1, 18}, {2, -4}, {1, 8}, {2, 19}, {1, 11}, {0, 12}, {0, 20}, {2, 4}, {1, 12}, {0, 17}, {2, 8}, {1, 5}, {2, -13}, {1, 3}, {1, 14}, {1, 4}, {0, 20}, {1, 18}, {0, 7}, {0, 17}},
{{2, 14}, {2, 10}, {2, -12}, {2, -15}, {1, 3}, {2, -17}, {1, 12}, {2, 9}, {2, -9}, {0, 11}, {2, 12}, {0, 16}, {0, 13}, {2, -17}, {2, 13}, {2, 11}, {1, 13}, {2, 16}, {0, 14}, {2, -8}}, {{0, 16}, {2, -10}, {1, 12}, {1, 12}, {2, 19}, {1, 5}, {2, 1}, {2, 19}, {0, 17}, {2, -19}, {2, 20}, {0, 7}, {1, 11}, {2, -3}, {2, -19}, {2, -20}, {2, 15}, {2, -18}, {2, 11}, {2, -19}}, {{2, -11}, {2, 10}, {0, 10}, {1, 15}, {1, 1}, {2, 7}, {2, -9}, {2, -3}, {0, 2}, {0, 20}, {0, 1}, {2, 14}, {2, -16}, {1, 14}, {0, 19}, {0, 11}, {2, 4}, {2, -9}, {2, -4}, {2, -10}}, {{2, 2}, {2, 17}, {1, 7}, {0, 18}, {0, 12}, {2, -15}, {2, 18}, {1, 7}, {1, 3}, {2, 14}, {1, 19}, {1, 6}, {2, -19}, {2, 9}, {0, 11}, {1, 13}, {2, -13}, {0, 19}, {1, 15}, {0, 14}}, {{2, 14}, {1, 3}, {2, 4}, {0, 14}, {1, 8}, {2, 7}, {0, 16}, {1, 11}, {2, 11}, {1, 13}, {1, 6}, {2, -10}, {0, 17}, {1, 18}, {1, 1}, {2, -11}, {1, 9}, {0, 16}, {2, 5}, {2, -6}}, {{0, 11}, {2, -2}, {1, 7}, {2, 8}, {2, 20}, {0, 7}, {0, 14}, {2, -17}, {2, 14}, {2, -14}, {2, -16}, {2, -12}, {2, -19}, {2, 10}, {2, -8}, {1, 1}, {1, 14}, {0, 5}, {0, 14}, {2, 14}}, {{2, 10}, {2, 18}, {1, 15}, {1, 15}, {2, 10}, {2, 14}, {1, 15}, {2, -16}, {2, -4}, {2, -1}, {2, -20}, {2, 2}, {1, 6}, {0, 2}, {2, -17}, {0, 13}, {2, -8}, {2, 18}, {2, 9}, {2, -12}}, {{2, -7}, {1, 16}, {2, 15}, {1, 14}, {1, 15}, {0, 8}, {1, 19}, {2, -13}, {2, 17}, {2, 4}, {2, -17}, {2, -2}, {0, 8}, {1, 11}, {2, 14}, {0, 13}, {2, -12}, {2, -1}, {2, -5}, {0, 6}}, {{0, 2}, {2, -1}, {2, -15}, {1, 9}, {0, 17}, {0, 8}, {2, 19}, {0, 5}, {1, 16}, {2, 3}, {1, 17}, {2, -8}, {2, -1}, {2, -4}, {2, -16}, {0, 4}, {2, -8}, {2, 14}, {2, -20}, {2, -15}}, {{0, 5}, {0, 20}, {1, 13}, {0, 13}, {2, 18}, {1, 19}, {0, 7}, {0, 13}, {2, -7}, {2, 11}, {0, 16}, {1, 6}, {2, -19}, {2, 6}, {1, 18}, {2, 4}, {2, -7}, {2, -8}, {2, 20}, {0, 19}}
};
// *INDENT-ON*
uint8_t buf[20];
uint8_t n = 0;
uint32_t bres = 0;
for(uint32_t i = 0; i < 100; i++) {
/* bring the pos back to the middle of the file */
int32_t pos = 500;
res = lv_fs_seek(&f, pos, LV_FS_SEEK_SET);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
for(uint32_t j = 0; j < 20; j++) {
int8_t action = actions[i][j][0];
int8_t amount = actions[i][j][1];
switch(action) {
case 0: /* read */
res = lv_fs_read(&f, buf, amount, &bres);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
TEST_ASSERT_EQUAL(amount, bres);
TEST_ASSERT(0 == memcmp(buf, buf1000 + pos, amount));
pos += amount;
break;
case 1: /* write */
for(int32_t k = 0; k < amount; k++) {
buf[k] = n;
buf1000[pos + k] = n;
n++;
}
res = lv_fs_write(&f, buf, amount, &bres);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
TEST_ASSERT_EQUAL(amount, bres);
pos += amount;
break;
case 2: /* seek */
pos += amount; /* amount may be negative */
res = lv_fs_seek(&f, pos, LV_FS_SEEK_SET);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
break;
}
}
}
/* test SEEK_END */
uint32_t tell_pos;
res = lv_fs_seek(&f, 0, LV_FS_SEEK_END);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
res = lv_fs_tell(&f, &tell_pos);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
TEST_ASSERT_EQUAL(tell_pos, 1000);
res = lv_fs_close(&f);
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
drv->cache_size = original_cache_size;
}
#endif
@@ -0,0 +1,50 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
typedef struct {
uint32_t num_gesture;
float scale;
} click_counts_t;
static void gesture_event_cb(lv_event_t * e)
{
click_counts_t * counts = lv_event_get_user_data(e);
counts->scale = lv_event_get_pinch_scale(e);
++counts->num_gesture;
}
void test_gesture_pinch(void)
{
/*Setup button that counts events.*/
click_counts_t counts;
lv_memzero(&counts, sizeof(counts));
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_add_flag(label, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(label, 320, 320);
lv_obj_add_event_cb(label, gesture_event_cb, LV_EVENT_GESTURE, &counts);
/*Simple multi-touch.*/
lv_point_t point_begin_0 = {120, 200};
lv_point_t point_begin_1 = {200, 120};
lv_point_t point_end_0 = {80, 250};
lv_point_t point_end_1 = {250, 80};
lv_test_gesture_pinch(point_begin_0, point_begin_1, point_end_0, point_end_1);
TEST_ASSERT_GREATER_THAN(0, counts.num_gesture);
}
#endif
@@ -0,0 +1,89 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
lv_obj_clean(lv_screen_active());
}
void tearDown(void)
{
/* Function run after every test */
}
static void button_create(lv_obj_t * parent, const char * text, int32_t x, int32_t y)
{
lv_obj_t * btn = lv_button_create(parent);
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_STRETCH, x, 1, LV_GRID_ALIGN_STRETCH, y, 1);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, text);
lv_obj_center(label);
}
void test_subgrid_row(void)
{
const int32_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
const int32_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_t * cont_main = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont_main, 700, 300);
lv_obj_center(cont_main);
lv_obj_set_grid_dsc_array(cont_main, col_dsc, row_dsc);
const int32_t col_dsc2[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_t * cont_sub = lv_obj_create(cont_main);
lv_obj_set_grid_cell(cont_sub, LV_GRID_ALIGN_STRETCH, 1, 2, LV_GRID_ALIGN_STRETCH, 1, 2);
lv_obj_set_grid_dsc_array(cont_sub, col_dsc2, NULL);
lv_obj_set_style_pad_all(cont_sub, 0, 0);
button_create(cont_main, "Main 0,0", 0, 0);
button_create(cont_main, "Main 3,3", 3, 3);
button_create(cont_main, "Main 2,2", 2, 2);
button_create(cont_sub, "Sub 0,0", 0, 0);
button_create(cont_sub, "Sub 1,0", 1, 0);
button_create(cont_sub, "Sub 2,0", 2, 0);
button_create(cont_sub, "Sub 3,0", 3, 0);
button_create(cont_sub, "Sub 1,1", 1, 1);
button_create(cont_sub, "Sub 0,1", 0, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("subgrid_row.png");
}
void test_subgrid_col(void)
{
const int32_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
const int32_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_t * cont_main = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont_main, 700, 300);
lv_obj_center(cont_main);
lv_obj_set_grid_dsc_array(cont_main, col_dsc, row_dsc);
const int32_t row_dsc2[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_t * cont_sub = lv_obj_create(cont_main);
lv_obj_set_grid_cell(cont_sub, LV_GRID_ALIGN_STRETCH, 1, 2, LV_GRID_ALIGN_STRETCH, 1, 2);
lv_obj_set_grid_dsc_array(cont_sub, NULL, row_dsc2);
lv_obj_set_style_pad_all(cont_sub, 0, 0);
button_create(cont_main, "Main 0,0", 0, 0);
button_create(cont_main, "Main 3,3", 3, 3);
button_create(cont_main, "Main 2,2", 2, 2);
button_create(cont_sub, "Sub 0,0", 0, 0);
button_create(cont_sub, "Sub 0,1", 0, 1);
button_create(cont_sub, "Sub 0,2", 0, 2);
button_create(cont_sub, "Sub 0,3", 0, 3);
button_create(cont_sub, "Sub 1,0", 1, 0);
button_create(cont_sub, "Sub 1,1", 1, 1);
TEST_ASSERT_EQUAL_SCREENSHOT("subgrid_col.png");
}
#endif
@@ -0,0 +1,47 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
/**
* Tests that green/blue checker pattern of various row and column sizes
* completely covers underyling screen, no red background visible.
*/
void test_grid_fr(void)
{
static int32_t col_dsc[] = {3 * 9, LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_FR(3), LV_GRID_FR(4), LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {3 * 3, LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_set_style_bg_color(active_screen, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN);
lv_obj_set_layout(active_screen, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(active_screen, col_dsc, row_dsc);
lv_obj_set_style_pad_row(active_screen, 0, LV_PART_MAIN);
lv_obj_set_style_pad_column(active_screen, 0, LV_PART_MAIN);
for(int col = 0; col < 5; col++) {
for(int row = 0; row < 5; row++) {
lv_obj_t * child = lv_obj_create(active_screen);
lv_obj_set_size(child, 1, 1);
lv_obj_set_grid_cell(child, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1);
lv_obj_set_style_bg_color(child, lv_palette_main((row + col) % 2 ? LV_PALETTE_GREEN : LV_PALETTE_BLUE), LV_PART_MAIN);
lv_obj_set_style_radius(child, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(child, 0, LV_PART_MAIN);
}
}
TEST_ASSERT_EQUAL_SCREENSHOT("grid_fr.png");
}
#endif
@@ -0,0 +1,113 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
static lv_obj_t * g_screen;
static lv_group_t * g_group;
static struct {
bool press_happened;
uint32_t key;
lv_obj_t * obj;
} g_key_data;
void setUp(void)
{
g_screen = lv_screen_active();
g_group = lv_group_create();
g_key_data.press_happened = false;
}
void tearDown(void)
{
lv_obj_clean(g_screen);
lv_group_delete(g_group); /* also removes all indevs set to the group */
}
static void key_event_cb(lv_event_t * e)
{
TEST_ASSERT_FALSE(g_key_data.press_happened);
g_key_data.press_happened = true;
g_key_data.key = *(uint32_t *)lv_event_get_param(e);
g_key_data.obj = lv_event_get_target_obj(e);
}
static void gridnav_one_axis_move_only(uint32_t key_grid_axis_next,
uint32_t key_grid_axis_prev,
uint32_t key_obj_axis_next,
uint32_t key_obj_axis_prev,
lv_gridnav_ctrl_t gridnav_ctrl,
lv_flex_flow_t flex_flow)
{
lv_indev_set_group(lv_test_indev_get_indev(LV_INDEV_TYPE_KEYPAD), g_group);
lv_obj_t * cont = lv_obj_create(g_screen);
lv_obj_set_flex_flow(cont, flex_flow);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_size(cont, lv_pct(100), lv_pct(100));
lv_obj_center(cont);
lv_gridnav_add(cont, gridnav_ctrl);
lv_group_add_obj(g_group, cont);
lv_obj_t * objs[3];
for(uint32_t i = 0; i < 3; i++) {
lv_obj_t * obj = lv_obj_create(cont);
lv_obj_create(obj); /* the obj needs a child to be focusable by gridnav */
lv_group_remove_obj(obj);
lv_obj_add_event_cb(obj, key_event_cb, LV_EVENT_KEY, NULL);
objs[i] = obj;
}
TEST_ASSERT(lv_obj_get_state(objs[0]) & LV_STATE_FOCUSED);
/* gridnav direction key moves the focus */
lv_test_key_hit(key_grid_axis_next);
TEST_ASSERT(lv_obj_get_state(objs[1]) & LV_STATE_FOCUSED);
TEST_ASSERT_FALSE(g_key_data.press_happened);
/* non gridnav direction key does not move the focus. */
/* the key is sent to the object instead */
lv_test_key_hit(key_obj_axis_next);
TEST_ASSERT(lv_obj_get_state(objs[1]) & LV_STATE_FOCUSED);
TEST_ASSERT_TRUE(g_key_data.press_happened);
TEST_ASSERT(g_key_data.key == key_obj_axis_next);
TEST_ASSERT(g_key_data.obj == objs[1]);
g_key_data.press_happened = false;
lv_test_key_hit(key_obj_axis_prev);
TEST_ASSERT(lv_obj_get_state(objs[1]) & LV_STATE_FOCUSED);
TEST_ASSERT_TRUE(g_key_data.press_happened);
TEST_ASSERT(g_key_data.key == key_obj_axis_prev);
TEST_ASSERT(g_key_data.obj == objs[1]);
g_key_data.press_happened = false;
/* go back */
lv_test_key_hit(key_grid_axis_prev);
TEST_ASSERT(lv_obj_get_state(objs[0]) & LV_STATE_FOCUSED);
TEST_ASSERT_FALSE(g_key_data.press_happened);
/* at the beginning, can't move further back */
lv_test_key_hit(key_grid_axis_prev);
TEST_ASSERT(lv_obj_get_state(objs[0]) & LV_STATE_FOCUSED);
TEST_ASSERT_FALSE(g_key_data.press_happened);
}
void test_gridnav_vertical_move_only(void)
{
gridnav_one_axis_move_only(LV_KEY_DOWN,
LV_KEY_UP,
LV_KEY_RIGHT,
LV_KEY_LEFT,
LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY,
LV_FLEX_FLOW_COLUMN);
}
void test_gridnav_horizontal_move_only(void)
{
gridnav_one_axis_move_only(LV_KEY_RIGHT,
LV_KEY_LEFT,
LV_KEY_DOWN,
LV_KEY_UP,
LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY,
LV_FLEX_FLOW_ROW);
}
#endif
@@ -0,0 +1,61 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
}
void tearDown(void)
{
}
void test_group_count(void)
{
lv_group_t * group_1 = lv_group_create();
lv_group_t * group_2 = lv_group_create();
TEST_ASSERT_EQUAL_UINT32(lv_group_get_count(), 2U);
lv_group_delete(group_2);
TEST_ASSERT_EQUAL_UINT32(lv_group_get_count(), 1U);
lv_group_delete(group_1);
TEST_ASSERT_EQUAL_UINT32(lv_group_get_count(), 0U);
}
void test_group_by_index(void)
{
lv_group_t * group_1 = lv_group_create();
lv_group_t * group_2 = lv_group_create();
TEST_ASSERT_EQUAL_PTR(lv_group_by_index(2), NULL);
TEST_ASSERT_EQUAL_PTR(lv_group_by_index(0), group_1);
TEST_ASSERT_EQUAL_PTR(lv_group_by_index(1), group_2);
lv_group_delete(group_1);
lv_group_delete(group_2);
}
void test_group_obj_by_index(void)
{
lv_group_t * group = lv_group_create();
TEST_ASSERT_EQUAL_PTR(lv_group_get_obj_by_index(group, 0), NULL);
lv_obj_t * obj_0 = lv_obj_create(NULL);
lv_obj_t * obj_1 = lv_obj_create(NULL);
lv_group_add_obj(group, obj_0);
lv_group_add_obj(group, obj_1);
TEST_ASSERT_EQUAL_PTR(lv_group_get_obj_by_index(group, 0), obj_0);
TEST_ASSERT_EQUAL_PTR(lv_group_get_obj_by_index(group, 1), obj_1);
lv_group_remove_obj(obj_0);
TEST_ASSERT_EQUAL_PTR(lv_group_get_obj_by_index(group, 0), obj_1);
TEST_ASSERT_EQUAL_PTR(lv_group_get_obj_by_index(group, 1), NULL);
}
#endif
@@ -0,0 +1,96 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#define TEST_HOVER_COUNTS 20
typedef struct _test_hover_t {
/* data */
char id[32];
uint32_t counts;
} test_hover_t;
static test_hover_t label_hovered;
static test_hover_t btn_hovered;
static const lv_point_t pointer1[] = {
{0, 0}, {110, 20}, {150, 26}, {120, 19}, {0, 0},
};
static const lv_point_t pointer2[] = {
{0, 0}, {60, 100}, {80, 100}, {120, 120}, {0, 0},
};
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static void hovered_event_cb(lv_event_t * e)
{
test_hover_t * hover = lv_event_get_user_data(e);
lv_log("Object(ID:%s) hovered %u/%d times.\n", hover->id, hover->counts, TEST_HOVER_COUNTS);
}
static void test_move_mouse(lv_point_t * point, uint8_t size)
{
lv_point_t * p = point;
for(uint8_t j = 0; j < TEST_HOVER_COUNTS; j++) {
for(uint8_t i = 0; i < size; i++) {
lv_test_mouse_move_to(p[i].x, p[i].y);
lv_test_wait(50);
}
}
}
void test_hover_basic(void)
{
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_set_size(label, 200, 20);
lv_label_set_text(label, "Clickable text can be hovered!");
lv_obj_set_pos(label, 100, 20);
lv_obj_add_flag(label, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_style_text_color(label, lv_color_hex(0x5be1b6), LV_PART_MAIN | LV_STATE_HOVERED);
/*Set hover callback*/
lv_obj_stringify_id(label, label_hovered.id, sizeof(label_hovered.id));
label_hovered.counts = 0;
lv_obj_add_event_cb(label, hovered_event_cb, LV_EVENT_HOVER_OVER, &label_hovered);
lv_obj_t * btn = lv_button_create(lv_screen_active());
lv_obj_set_pos(btn, 64, 100);
lv_obj_set_size(btn, 128, 48);
lv_obj_set_style_bg_opa(btn, 128, LV_PART_MAIN | LV_STATE_HOVERED);
/*Set hover callback*/
lv_obj_stringify_id(btn, btn_hovered.id, sizeof(btn_hovered.id));
btn_hovered.counts = 0;
lv_obj_add_event_cb(btn, hovered_event_cb, LV_EVENT_HOVER_OVER, &btn_hovered);
test_move_mouse((lv_point_t *)pointer1, 5);
test_move_mouse((lv_point_t *)pointer2, 5);
}
void test_hover_delete(void)
{
for(int i = 0; i < 4; i++) {
lv_obj_t * btn = lv_button_create(lv_screen_active());
lv_obj_set_size(btn, 200, 100);
lv_test_mouse_move_to(i * 10, 50);
lv_test_wait(50);
lv_obj_delete(btn); /*No crash while deleting the hovered button*/
lv_test_wait(50);
}
}
#endif
@@ -0,0 +1,60 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
static uint32_t indev_reset_count = 0;
void setUp(void)
{
/* Function run before every test */
indev_reset_count = 0;
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static void event_cb(lv_event_t * e)
{
lv_obj_t * scroll_obj = lv_event_get_target(e);
lv_obj_t * act_obj = lv_obj_get_child(scroll_obj, 0);
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_SCROLL && act_obj) {
lv_obj_delete(act_obj);
}
else if(code == LV_EVENT_INDEV_RESET) {
indev_reset_count += 1;
}
}
void test_indev_wait_release(void)
{
lv_obj_t * scroll_obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(scroll_obj, 300, 300);
lv_obj_align(scroll_obj, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_add_event_cb(scroll_obj, event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * act_obj = lv_obj_create(scroll_obj);
lv_obj_set_size(act_obj, 400, 200);
lv_obj_align(act_obj, LV_ALIGN_LEFT_MID, 0, 0);
lv_test_mouse_move_to(200, 200);
lv_test_mouse_press();
lv_test_wait(50);
lv_test_mouse_move_by(-20, 0);
lv_test_mouse_press();
lv_test_wait(50);
lv_test_mouse_move_by(-20, 0);
lv_test_mouse_press();
lv_test_wait(50);
lv_test_mouse_release();
TEST_ASSERT_EQUAL_UINT32(1, indev_reset_count);
}
#endif
@@ -0,0 +1,58 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static void event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
uint32_t * pressed_count = lv_event_get_user_data(e);
switch(lv_event_get_code(e)) {
case LV_EVENT_PRESSED:
(*pressed_count)++;
lv_indev_wait_release(lv_indev_active());
break;
case LV_EVENT_PRESS_LOST:
lv_indev_reset(lv_indev_active(), obj);
break;
default:
break;
}
}
void test_indev_wait_release(void)
{
uint32_t pressed_count = 0;
lv_obj_t * btn = lv_button_create(lv_screen_active());
lv_obj_set_size(btn, 100, 100);
lv_obj_add_event_cb(btn, event_cb, LV_EVENT_ALL, &pressed_count);
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_move_to(50, 50);
lv_test_mouse_press();
lv_test_wait(50);
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_press();
lv_test_wait(50);
lv_test_mouse_release();
lv_test_wait(50);
TEST_ASSERT_EQUAL_UINT32(2, pressed_count);
}
#endif
@@ -0,0 +1,80 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color)
{
lv_obj_t * obj = lv_obj_create(parent);
lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN);
lv_obj_set_width(obj, 150);
lv_obj_set_height(obj, 150);
return obj;
}
void obj_set_margin(lv_obj_t * obj, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN);
lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN);
lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN);
lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN);
}
// takes no effect on position but size.
void test_align(void)
{
lv_obj_t * obj0 = active_screen;
lv_obj_set_width(obj0, 800);
lv_obj_set_height(obj0, 400);
lv_obj_center(obj0);
lv_obj_set_style_pad_all(obj0, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(obj0, 0, LV_PART_MAIN);
lv_obj_t * obj0s[] = {
obj_create(obj0, lv_palette_main(LV_PALETTE_BLUE)),
obj_create(obj0, lv_palette_main(LV_PALETTE_RED)),
obj_create(obj0, lv_palette_main(LV_PALETTE_DEEP_PURPLE)),
obj_create(obj0, lv_palette_main(LV_PALETTE_GREEN)),
obj_create(obj0, lv_palette_main(LV_PALETTE_PINK))
};
lv_obj_align(obj0s[0], LV_ALIGN_TOP_MID, 0, 0);
lv_obj_align_to(obj0s[1], obj0s[0], LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
lv_obj_align_to(obj0s[2], obj0s[1], LV_ALIGN_OUT_RIGHT_MID, 0, 0);
lv_obj_align_to(obj0s[3], obj0s[2], LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
lv_obj_update_layout(obj0);
obj_set_margin(obj0s[0], 20, 50, 60, 50);
lv_obj_set_style_width(obj0s[0], LV_PCT(60), LV_PART_MAIN);
obj_set_margin(obj0s[1], 15, 12, 50, 20);
obj_set_margin(obj0s[2], 25, 25, 100, 20);
obj_set_margin(obj0s[3], 12, 50, 100, 100);
lv_obj_set_style_width(obj0s[3], LV_PCT(100), LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_align_0.png");
obj_set_margin(obj0s[4], 6, 100, 100, 100);
lv_obj_set_style_radius(obj0s[0], 0, LV_PART_MAIN);
lv_obj_align(obj0s[4], LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_update_layout(obj0);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_align_1.png");
}
#endif
@@ -0,0 +1,94 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color)
{
lv_obj_t * obj = lv_obj_create(parent);
lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN);
lv_obj_set_width(obj, 150);
lv_obj_set_height(obj, 150);
return obj;
}
void obj_set_margin(lv_obj_t * obj, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN);
lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN);
lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN);
lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN);
}
void test_flex(void)
{
#define N 5
lv_obj_t * obj0 = active_screen;
lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_all(obj0, 0, LV_PART_MAIN);
lv_obj_set_style_pad_gap(obj0, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(obj0, 0, LV_PART_MAIN);
lv_obj_t * obj0s[N] = {
obj_create(obj0, lv_palette_main(LV_PALETTE_BLUE)),
obj_create(obj0, lv_palette_main(LV_PALETTE_RED)),
obj_create(obj0, lv_palette_main(LV_PALETTE_PURPLE)),
obj_create(obj0, lv_palette_main(LV_PALETTE_GREEN)),
obj_create(obj0, lv_palette_main(LV_PALETTE_PINK))
};
lv_obj_t * o;
for(int i = 0; i < N; i++) {
o = obj0s[i];
lv_obj_set_style_radius(o, 0, LV_PART_MAIN);
lv_obj_set_scrollbar_mode(o, LV_SCROLLBAR_MODE_OFF);
lv_obj_set_style_border_width(o, 0, LV_PART_MAIN);
}
lv_obj_set_width(obj0s[0], LV_PCT(50));
lv_obj_set_height(obj0s[0], LV_PCT(50));
obj_set_margin(obj0s[0], 50, 3, 10, 50);
obj_set_margin(obj0s[1], 25, 6, 20, 50);
obj_set_margin(obj0s[2], 12, 12, 30, 50);
obj_set_margin(obj0s[3], 12, 25, 30, 50);
obj_set_margin(obj0s[4], 24, 50, 50, 50);
lv_obj_update_layout(obj0);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_0.png");
lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_ROW_WRAP);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_1.png");
lv_obj_set_style_flex_main_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_2.png");
lv_obj_set_style_flex_cross_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_3.png");
lv_obj_set_style_flex_track_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_4.png");
lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_COLUMN_WRAP);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_5.png");
#undef N
}
#endif
@@ -0,0 +1,107 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color)
{
lv_obj_t * obj = lv_obj_create(parent);
lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN);
lv_obj_set_width(obj, 150);
lv_obj_set_height(obj, 150);
return obj;
}
void obj_set_margin(lv_obj_t * obj, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN);
lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN);
lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN);
lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN);
}
void test_grid(void)
{
#define M 5
#define N 8
lv_obj_t * obj0 = active_screen;
static int32_t row_dsc[M + 1];
static int32_t col_dsc[N + 1];
row_dsc[M] = LV_GRID_TEMPLATE_LAST;
col_dsc[N] = LV_GRID_TEMPLATE_LAST;
for(int i = 0; i < M; ++i) {
row_dsc[i] = 80;
}
for(int i = 0; i < N; ++i) {
col_dsc[i] = 80;
}
static lv_palette_t colors[] = {
LV_PALETTE_BLUE,
LV_PALETTE_PURPLE,
LV_PALETTE_GREEN,
LV_PALETTE_PINK,
LV_PALETTE_AMBER,
LV_PALETTE_BLUE_GREY,
LV_PALETTE_INDIGO
};
lv_obj_set_layout(obj0, LV_LAYOUT_GRID);
lv_obj_set_grid_align(obj0, LV_GRID_ALIGN_CENTER, LV_GRID_ALIGN_CENTER);
lv_obj_set_grid_dsc_array(obj0, col_dsc, row_dsc);
lv_obj_set_style_pad_gap(obj0, 0, LV_PART_MAIN);
lv_obj_set_style_pad_row(obj0, 0, LV_PART_MAIN);
lv_obj_set_style_pad_column(obj0, 0, LV_PART_MAIN);
lv_obj_t * obj0s[M][N];
for(int i = 0; i < M; ++i) {
for(int j = 0; j < N; ++j) {
obj0s[i][j] = obj_create(obj0,
lv_palette_main(colors[(i * M + j) % ((sizeof colors) / (sizeof(lv_palette_t)))]));
}
}
lv_obj_t * o;
for(int i = 0; i < M; i++) {
for(int j = 0; j < N; ++j) {
o = obj0s[i][j];
lv_obj_set_style_radius(o, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(o, 0, LV_PART_MAIN);
lv_obj_set_scrollbar_mode(o, LV_SCROLLBAR_MODE_OFF);
lv_obj_set_width(o, 30);
lv_obj_set_grid_cell(o, LV_GRID_ALIGN_CENTER, j, 1, LV_GRID_ALIGN_STRETCH, i, 1);
lv_obj_set_style_margin_top(o, i * 5, LV_PART_MAIN);
lv_obj_set_style_margin_left(o, i * 5 + j * 5, LV_PART_MAIN);
lv_obj_set_style_margin_right(o, i * 5, LV_PART_MAIN);
lv_obj_set_style_margin_bottom(o, i * 5 + j * 5, LV_PART_MAIN);
}
}
lv_obj_update_layout(obj0);
TEST_ASSERT_EQUAL_SCREENSHOT("margin_grid_0.png");
#undef M
#undef N
}
#endif
@@ -0,0 +1,139 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#define ERROR_THRESHOLD 5 /*5 in 1024, 0.5% max error allowed*/
#define NEWTON_ITERATIONS 8
static float do_cubic_bezier_f(float t, float a, float b, float c)
{
/*a*t^3 + b*t^2 + c*t*/
return ((a * t + b) * t + c) * t;
}
/**
* Calculate the y value of cubic-bezier(x1, y1, x2, y2) function as specified x.
* @param x time in range of [0..1]
* @param x1 x of control point 1 in range of [0..1]
* @param y1 y of control point 1 in range of [0..1]
* @param x2 x of control point 2 in range of [0..1]
* @param y2 y of control point 2 in range of [0..1]
* @return the value calculated
*/
static float lv_cubic_bezier_f(float x, float x1, float y1, float x2, float y2)
{
float ax, bx, cx, ay, by, cy;
float tl, tr, t; /*t in cubic-bezier function, used for bisection */
float xs; /*x sampled on curve */
float d; /*slope value at specified t*/
if(x == 0 || x == 1) return x;
cx = 3.f * x1;
bx = 3.f * (x2 - x1) - cx;
ax = 1.f - cx - bx;
cy = 3.f * y1;
by = 3.f * (y2 - y1) - cy;
ay = 1.f - cy - by;
/*Try Newton's method firstly */
t = x; /*Make a guess*/
for(int i = 0; i < NEWTON_ITERATIONS; i++) {
xs = do_cubic_bezier_f(t, ax, bx, cx);
xs -= x;
if(LV_ABS(xs) < 1e-6f) goto found;
d = (3.f * ax * t + 2.f * bx) * t + cx;
if(LV_ABS(d) < 1e-6f) break;
t -= xs / d;
}
/*Fallback to bisection method for reliability*/
tl = 0.f, tr = 1.f, t = x;
if(t < tl) {
t = tl;
goto found;
}
if(t > tr) {
t = tr;
goto found;
}
while(tl < tr) {
xs = do_cubic_bezier_f(t, ax, bx, cx);
if(LV_ABS(xs - x) < 1e-6f) goto found;
x > xs ? (tl = t) : (tr = t);
t = (tr - tl) * .5f + tl;
}
found:
return do_cubic_bezier_f(t, ay, by, cy);
}
static int test_cubic_bezier_ease_functions(float fx1, float fy1, float fx2, float fy2)
{
int x1, y1, x2, y2, y;
float t, t_step, fy;
t_step = .001f;
x1 = LV_BEZIER_VAL_FLOAT(fx1);
y1 = LV_BEZIER_VAL_FLOAT(fy1);
x2 = LV_BEZIER_VAL_FLOAT(fx2);
y2 = LV_BEZIER_VAL_FLOAT(fy2);
for(t = 0; t <= 1; t += t_step) {
fy = lv_cubic_bezier_f(t, fx1, fy1, fx2, fy2);
y = lv_cubic_bezier(LV_BEZIER_VAL_FLOAT(t), x1, y1, x2, y2);
if(LV_ABS(LV_BEZIER_VAL_FLOAT(fy) - y) >= ERROR_THRESHOLD) {
return 0;
}
}
return 1;
}
static uint32_t lv_bezier3_legacy(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
{
uint32_t t_rem = 1024 - t;
uint32_t t_rem2 = (t_rem * t_rem) >> 10;
uint32_t t_rem3 = (t_rem2 * t_rem) >> 10;
uint32_t t2 = (t * t) >> 10;
uint32_t t3 = (t2 * t) >> 10;
uint32_t v1 = (t_rem3 * u0) >> 10;
uint32_t v2 = (3 * t_rem2 * t * u1) >> 20;
uint32_t v3 = (3 * t_rem * t2 * u2) >> 20;
uint32_t v4 = (t3 * u3) >> 10;
return v1 + v2 + v3 + v4;
}
void test_math_cubic_bezier_result_should_be_precise(void)
{
/*ease-in-out function*/
TEST_ASSERT_TRUE(test_cubic_bezier_ease_functions(.42f, 0, .58f, 1));
/*ease-out function*/
TEST_ASSERT_TRUE(test_cubic_bezier_ease_functions(0, 0, .58f, 1));
/*ease-in function*/
TEST_ASSERT_TRUE(test_cubic_bezier_ease_functions(.42f, 0, 1, 1));
/*ease function*/
TEST_ASSERT_TRUE(test_cubic_bezier_ease_functions(.25f, .1f, .25f, 1));
int32_t u0 = 0, u1 = 50, u2 = 952, u3 = LV_BEZIER_VAL_MAX;
for(int32_t i = 0; i <= 1024; i++) {
int32_t legacy = lv_bezier3_legacy(i, u0, u1, u2, u3);
int32_t cubic_bezier = lv_bezier3(i, u0, u1, u2, u3);
TEST_ASSERT_TRUE(LV_ABS(legacy - cubic_bezier) <= 5);
}
}
#endif
@@ -0,0 +1,53 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
/* #3324 */
void test_mem_buf_realloc(void)
{
#ifdef LVGL_CI_USING_DEF_HEAP
void * buf1 = lv_malloc(20);
void * buf2 = lv_realloc(buf1, LV_MEM_SIZE + 16384);
TEST_ASSERT_NULL(buf2);
#endif
}
/* #7573: Test memcpy with unaligned addresses */
void test_memcpy_unaligned(void)
{
union {
uint8_t u8[20];
uint32_t dummy_u32;
} source, destination;
/* Initialize source with some values */
for(int i = 0; i < 20; i++) {
source.u8[i] = (uint8_t)(i + 1);
}
/* Ensure unaligned addresses */
uint8_t * unaligned_source = source.u8 + 1;
uint8_t * unaligned_destination = destination.u8 + 1;
/* Perform lv_memcpy */
lv_memcpy(unaligned_destination, unaligned_source, 19);
/* Verify that the copied values match the source */
for(int i = 0; i < 19; i++) {
TEST_ASSERT_EQUAL_UINT8(unaligned_source[i], unaligned_destination[i]);
}
}
#endif
@@ -0,0 +1,964 @@
#if LV_BUILD_TEST == 1
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static uint32_t observer_called = 0;
void setUp(void)
{
observer_called = 0;
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static int32_t prev_v;
static int32_t current_v;
static void observer_basic(lv_observer_t * observer, lv_subject_t * subject)
{
LV_UNUSED(observer);
LV_UNUSED(subject);
observer_called++;
}
static void observer_int(lv_observer_t * observer, lv_subject_t * subject)
{
LV_UNUSED(observer);
prev_v = lv_subject_get_previous_int(subject);
current_v = lv_subject_get_int(subject);
}
void test_observer_add_remove(void)
{
static lv_subject_t subject;
lv_subject_init_int(&subject, 5);
lv_observer_t * observer =
lv_subject_add_observer(&subject, observer_int, NULL);
current_v = 0;
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL(10, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(10, current_v);
lv_observer_remove(observer);
lv_subject_set_int(&subject, 15);
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(10, current_v); /*The observer cb is not called*/
static lv_subject_t uninitialized_subject;
observer = lv_subject_add_observer(&uninitialized_subject, observer_int,
NULL);
TEST_ASSERT_EQUAL_PTR(NULL, observer); /*The observer must be NULL*/
}
void test_object_observer_add_remove(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_observer_t * observer = lv_obj_bind_flag_if_eq(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_observer_remove(observer);
lv_subject_set_int(&subject, 1);
/* This shouldn't get updated */
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_obj_delete(obj);
/* We shouldn't crash here */
}
static lv_event_dsc_t * get_event_delete_from_obj(lv_obj_t * obj)
{
/* The remove event is a event callback using the observer as the user data */
uint32_t event_cnt = lv_event_get_count(&obj->spec_attr->event_list);
for(uint32_t i = 0; i < event_cnt; i++) {
lv_event_dsc_t * event = lv_obj_get_event_dsc(obj, i);
TEST_ASSERT_NOT_NULL(event);
if(event->filter == LV_EVENT_DELETE) {
return event;
}
}
return NULL;
}
void test_obj_remove_from_subject_removes_delete_event(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
(void)lv_subject_add_observer_obj(&subject, observer_basic, obj, NULL);
{
/*
* We expect the event delete to be added to the object allowing the observer
* to be deleted when the object is deleted
*/
TEST_ASSERT_NOT_NULL(obj->spec_attr);
TEST_ASSERT_EQUAL(lv_event_get_count(&obj->spec_attr->event_list), 1);
lv_event_dsc_t * delete_event = get_event_delete_from_obj(obj);
TEST_ASSERT_NOT_NULL(delete_event);
}
{
/* Removing the object from the subject should remove the delete event entry */
lv_obj_remove_from_subject(obj, &subject);
lv_event_dsc_t * delete_event = get_event_delete_from_obj(obj);
TEST_ASSERT_NULL(delete_event);
}
}
void test_observer_remove_removes_obj_callback(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_observer_t * observer = lv_subject_add_observer_obj(&subject, observer_basic, obj, NULL);
{
/*
* We expect the event delete to be added to the object allowing the observer
* to be deleted when the object is deleted
*/
TEST_ASSERT_NOT_NULL(obj->spec_attr);
TEST_ASSERT_EQUAL(lv_event_get_count(&obj->spec_attr->event_list), 1);
lv_event_dsc_t * delete_event = get_event_delete_from_obj(obj);
TEST_ASSERT_NOT_NULL(delete_event);
}
{
/* Removing the observer associated with the object should remove the delete event entry */
lv_observer_remove(observer);
lv_event_dsc_t * delete_event = get_event_delete_from_obj(obj);
TEST_ASSERT_NULL(delete_event);
}
}
void test_observer_int(void)
{
static lv_subject_t subject;
lv_subject_init_int(&subject, 5);
lv_observer_t * basic_observer =
lv_subject_add_observer(&subject, observer_basic, NULL);
TEST_ASSERT_EQUAL(5, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(5, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(1, observer_called);
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL(10, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(5, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(2, observer_called);
lv_subject_set_int(&subject, 15);
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(10, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/* Observer shouldn't be called if value is the same */
lv_subject_set_int(&subject, 15);
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(15, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/*Ignore incorrect types*/
lv_subject_set_pointer(&subject, NULL);
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(15, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_subject_set_color(&subject, lv_color_black());
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(15, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_subject_copy_string(&subject, "hello");
TEST_ASSERT_EQUAL(15, lv_subject_get_int(&subject));
TEST_ASSERT_EQUAL(15, lv_subject_get_previous_int(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_observer_remove(basic_observer);
}
void test_observer_string(void)
{
char buf_current[32];
char buf_previous[32];
lv_subject_t subject;
lv_subject_init_string(&subject, buf_current, buf_previous,
sizeof(buf_current), "hello");
lv_observer_t * basic_observer =
lv_subject_add_observer(&subject, observer_basic, NULL);
TEST_ASSERT_EQUAL_STRING("hello", lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("hello",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(1, observer_called);
lv_subject_copy_string(&subject, "my name is John");
TEST_ASSERT_EQUAL_STRING("my name is John",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("hello",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(2, observer_called);
lv_subject_copy_string(&subject, "how are you?");
TEST_ASSERT_EQUAL_STRING("how are you?",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("my name is John",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/* Observer shouldn't be called with same value */
lv_subject_copy_string(&subject, "how are you?");
TEST_ASSERT_EQUAL_STRING("how are you?",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("how are you?",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_subject_snprintf(&subject, "I ate %d pizzas", 10);
TEST_ASSERT_EQUAL_STRING("I ate 10 pizzas",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("how are you?",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(4, observer_called);
lv_subject_snprintf(&subject, "%d: %s", 1, "Coding is fun !");
TEST_ASSERT_EQUAL_STRING("1: Coding is fun !",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("I ate 10 pizzas",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(5, observer_called);
/* Observer shouldn't be called with same value */
lv_subject_snprintf(&subject, "%d: %s", 1, "Coding is fun !");
TEST_ASSERT_EQUAL_STRING("1: Coding is fun !",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("1: Coding is fun !",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(5, observer_called);
/*Clip long text*/
lv_subject_copy_string(
&subject,
"text to be clipped to 32 chars.this should be clipped");
TEST_ASSERT_EQUAL_STRING("text to be clipped to 32 chars.",
lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("1: Coding is fun !",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(6, observer_called);
/*Check if the previous string is clipped correctly*/
lv_subject_copy_string(&subject, "a");
TEST_ASSERT_EQUAL_STRING("a", lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("text to be clipped to 32 chars.",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(7, observer_called);
/*Ignore incorrect types*/
lv_subject_set_pointer(&subject, NULL);
TEST_ASSERT_EQUAL_STRING("a", lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("text to be clipped to 32 chars.",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(7, observer_called);
lv_subject_set_color(&subject, lv_color_black());
TEST_ASSERT_EQUAL_STRING("a", lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("text to be clipped to 32 chars.",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(7, observer_called);
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL_STRING("a", lv_subject_get_string(&subject));
TEST_ASSERT_EQUAL_STRING("text to be clipped to 32 chars.",
lv_subject_get_previous_string(&subject));
TEST_ASSERT_EQUAL(7, observer_called);
lv_observer_remove(basic_observer);
}
void test_observer_pointer(void)
{
static int32_t a[3] = { 0 };
static lv_subject_t subject;
lv_subject_init_pointer(&subject, &a[0]);
lv_observer_t * basic_observer =
lv_subject_add_observer(&subject, observer_basic, NULL);
TEST_ASSERT_EQUAL(1, observer_called);
TEST_ASSERT_EQUAL_PTR(&a[0], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[0], lv_subject_get_previous_pointer(&subject));
lv_subject_set_pointer(&subject, &a[1]);
TEST_ASSERT_EQUAL_PTR(&a[1], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[0], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(2, observer_called);
lv_subject_set_pointer(&subject, &a[2]);
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[1], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/*
* Even if pointer is the same, the observer should still get called as we shouldn't assume
* what the pointer is indicating
*/
lv_subject_set_pointer(&subject, &a[2]);
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(4, observer_called);
/*Ignore incorrect types*/
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(4, observer_called);
lv_subject_set_color(&subject, lv_color_black());
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(4, observer_called);
lv_subject_copy_string(&subject, "hello");
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_pointer(&subject));
TEST_ASSERT_EQUAL_PTR(&a[2], lv_subject_get_previous_pointer(&subject));
TEST_ASSERT_EQUAL(4, observer_called);
lv_observer_remove(basic_observer);
}
void test_observer_color(void)
{
static lv_subject_t subject;
lv_subject_init_color(&subject, lv_color_hex3(0x123));
lv_observer_t * basic_observer =
lv_subject_add_observer(&subject, observer_basic, NULL);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0x123),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0x123),
lv_subject_get_previous_color(&subject));
TEST_ASSERT_EQUAL(1, observer_called);
lv_subject_set_color(&subject, lv_color_hex3(0x456));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0x456),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0x123),
lv_subject_get_previous_color(&subject));
TEST_ASSERT_EQUAL(2, observer_called);
lv_subject_set_color(&subject, lv_color_hex3(0xabc));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0x456),
lv_subject_get_previous_color(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/* Observer shouldn't be called if value is the same */
lv_subject_set_color(&subject, lv_color_hex3(0xabc));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_previous_color(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/*Ignore incorrect types*/
lv_subject_set_pointer(&subject, NULL);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_previous_color(&subject));
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_previous_color(&subject));
lv_subject_copy_string(&subject, "hello");
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_color(&subject));
TEST_ASSERT_EQUAL_COLOR(lv_color_hex3(0xabc),
lv_subject_get_previous_color(&subject));
lv_observer_remove(basic_observer);
}
static int32_t group_observer_called;
static void group_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
LV_UNUSED(observer);
LV_UNUSED(subject);
group_observer_called++;
}
void test_observer_group(void)
{
static lv_subject_t subject_main;
static lv_subject_t subject_sub1;
static lv_subject_t subject_sub2;
static lv_subject_t * subject_list[2] = { &subject_sub1, &subject_sub2 };
lv_subject_init_int(&subject_sub1, 1);
lv_subject_init_int(&subject_sub2, 2);
lv_subject_init_group(&subject_main, subject_list, 2);
TEST_ASSERT_EQUAL_PTR(&subject_sub1,
lv_subject_get_group_element(&subject_main, 0));
TEST_ASSERT_EQUAL_PTR(&subject_sub2,
lv_subject_get_group_element(&subject_main, 1));
TEST_ASSERT_EQUAL_PTR(NULL,
lv_subject_get_group_element(&subject_main, 2));
TEST_ASSERT_EQUAL_PTR(NULL, lv_subject_get_group_element(&subject_main,
1000));
group_observer_called = 0;
lv_subject_add_observer(&subject_main, group_observer_cb, NULL);
TEST_ASSERT_EQUAL(1, group_observer_called);
lv_subject_set_int(&subject_sub1, 10);
TEST_ASSERT_EQUAL(2, group_observer_called);
lv_subject_set_int(&subject_sub2, 20);
TEST_ASSERT_EQUAL(3, group_observer_called);
}
void test_observer_obj_flag_invalid_subject(void)
{
typedef lv_observer_t * (*lv_obj_bind_flag_fn)(
lv_obj_t *, lv_subject_t *, lv_obj_flag_t, int32_t);
static const lv_obj_bind_flag_fn fns[] = {
lv_obj_bind_flag_if_eq, lv_obj_bind_flag_if_not_eq,
lv_obj_bind_flag_if_ge, lv_obj_bind_flag_if_gt,
lv_obj_bind_flag_if_lt, lv_obj_bind_flag_if_le,
};
static lv_subject_t invalid_subjects[4];
static char buf1[30];
static char buf2[30];
lv_obj_t * obj = lv_obj_create(lv_screen_active());
const size_t fns_size = sizeof(fns) / sizeof(fns[0]);
const size_t subjects_size =
sizeof(invalid_subjects) / sizeof(invalid_subjects[0]);
/* Can only bind to int */
lv_subject_init_pointer(&invalid_subjects[0], NULL);
lv_subject_init_string(&invalid_subjects[1], buf1, buf2, 30, "test");
lv_subject_init_color(&invalid_subjects[2], (lv_color_t) {
0, 0, 0
});
lv_subject_init_group(&invalid_subjects[3], NULL, 0);
for(size_t i = 0; i < fns_size; ++i) {
for(size_t j = 0; j < subjects_size; ++j) {
TEST_ASSERT_EQUAL_PTR(NULL,
fns[i](obj, &invalid_subjects[j],
LV_OBJ_FLAG_HIDDEN, 5));
}
}
}
void test_observer_obj_flag_eq(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_flag_if_eq(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_obj_bind_flag_if_not_eq(obj, &subject, LV_OBJ_FLAG_CHECKABLE, 10);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE));
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE));
}
void test_observer_obj_flag_ge(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_flag_if_ge(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
}
void test_observer_obj_flag_gt(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_flag_if_gt(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
}
void test_observer_obj_flag_le(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 7);
lv_obj_bind_flag_if_le(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
}
void test_observer_obj_flag_lt(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 7);
lv_obj_bind_flag_if_lt(obj, &subject, LV_OBJ_FLAG_HIDDEN, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(false, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
lv_subject_set_int(&subject, 3);
TEST_ASSERT_EQUAL(true, lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN));
}
void test_observer_obj_state_invalid_subject(void)
{
typedef lv_observer_t * (*lv_obj_bind_state_fn)(
lv_obj_t *, lv_subject_t *, lv_state_t, int32_t);
static const lv_obj_bind_state_fn fns[] = {
lv_obj_bind_state_if_eq, lv_obj_bind_state_if_not_eq,
lv_obj_bind_state_if_ge, lv_obj_bind_state_if_gt,
lv_obj_bind_state_if_lt, lv_obj_bind_state_if_le,
};
static lv_subject_t invalid_subjects[4];
static char buf1[30];
static char buf2[30];
lv_obj_t * obj = lv_obj_create(lv_screen_active());
const size_t fns_size = sizeof(fns) / sizeof(fns[0]);
const size_t subjects_size =
sizeof(invalid_subjects) / sizeof(invalid_subjects[0]);
/* Can only bind to int */
lv_subject_init_pointer(&invalid_subjects[0], NULL);
lv_subject_init_string(&invalid_subjects[1], buf1, buf2, 30, "test");
lv_subject_init_color(&invalid_subjects[2], (lv_color_t) {
0, 0, 0
});
lv_subject_init_group(&invalid_subjects[3],
NULL, 0);
for(size_t i = 0; i < fns_size; ++i) {
for(size_t j = 0; j < subjects_size; ++j) {
TEST_ASSERT_EQUAL_PTR(
NULL, fns[i](obj, &invalid_subjects[j], 0, 5));
}
}
}
void test_observer_obj_state_eq(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_state_if_eq(obj, &subject, LV_STATE_CHECKED, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_obj_bind_state_if_not_eq(obj, &subject, LV_STATE_DISABLED, 10);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_DISABLED));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_DISABLED));
lv_subject_set_int(&subject, 10);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_DISABLED));
}
void test_observer_obj_state_gt(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_state_if_gt(obj, &subject, LV_STATE_CHECKED, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 7);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
}
void test_observer_obj_state_ge(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_state_if_ge(obj, &subject, LV_STATE_CHECKED, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
}
void test_observer_obj_state_le(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_state_if_le(obj, &subject, LV_STATE_CHECKED, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 6);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
}
void test_observer_obj_state_lt(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_state_if_lt(obj, &subject, LV_STATE_CHECKED, 5);
/*Should be applied immediately*/
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 5);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 4);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
}
void test_observer_button_checked(void)
{
lv_obj_t * obj = lv_button_create(lv_screen_active());
lv_obj_set_size(obj, 100, 100);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
lv_obj_update_layout(obj);
/*Can bind only to int*/
static lv_subject_t subject_wrong;
lv_subject_init_pointer(&subject_wrong, NULL);
lv_observer_t * observer = lv_obj_bind_checked(obj, &subject_wrong);
TEST_ASSERT_EQUAL_PTR(NULL, observer);
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_obj_bind_checked(obj, &subject);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_subject_set_int(&subject, 0);
TEST_ASSERT_EQUAL(false, lv_obj_has_state(obj, LV_STATE_CHECKED));
lv_test_mouse_click_at(10, 10);
TEST_ASSERT_EQUAL(true, lv_obj_has_state(obj, LV_STATE_CHECKED));
TEST_ASSERT_EQUAL(1, lv_subject_get_int(&subject));
}
void test_observer_label_text_normal(void)
{
lv_obj_t * obj = lv_label_create(lv_screen_active());
lv_observer_t * observer;
/*Cannot bind color*/
static lv_subject_t subject_color;
lv_subject_init_color(&subject_color, lv_color_black());
observer = lv_label_bind_text(obj, &subject_color, NULL);
TEST_ASSERT_EQUAL_PTR(NULL, observer);
/*Bind it with "%d" if NULL is passed*/
static lv_subject_t subject_int;
lv_subject_init_int(&subject_int, 10);
observer = lv_label_bind_text(obj, &subject_int, NULL);
TEST_ASSERT_EQUAL_STRING("10", lv_label_get_text(obj));
/*Bind to string*/
static char buf[32];
static lv_subject_t subject_string;
lv_subject_init_string(&subject_string, buf, NULL, 32, "hello");
lv_label_bind_text(obj, &subject_string, NULL);
TEST_ASSERT_EQUAL_STRING("hello", lv_label_get_text(obj));
lv_subject_copy_string(&subject_string, "world");
TEST_ASSERT_EQUAL_STRING("world", lv_label_get_text(obj));
/*Remove the label from the subject*/
lv_obj_remove_from_subject(obj, &subject_string);
lv_subject_copy_string(&subject_string, "nothing");
TEST_ASSERT_EQUAL_STRING("world", lv_label_get_text(obj));
/*Bind to pointer*/
static lv_subject_t subject_pointer;
lv_subject_init_pointer(&subject_pointer, "HELLO");
lv_label_bind_text(obj, &subject_pointer, NULL);
TEST_ASSERT_EQUAL_STRING("HELLO", lv_label_get_text(obj));
lv_subject_set_pointer(&subject_pointer, "WORLD");
TEST_ASSERT_EQUAL_STRING("WORLD", lv_label_get_text(obj));
/*Remove the label from the subject*/
lv_obj_remove_from_subject(obj, &subject_pointer);
lv_subject_copy_string(&subject_pointer, "NOTHING");
TEST_ASSERT_EQUAL_STRING("WORLD", lv_label_get_text(obj));
}
void test_observer_label_text_formatted(void)
{
lv_obj_t * obj = lv_label_create(lv_screen_active());
lv_observer_t * observer;
/*Cannot bind color*/
static lv_subject_t subject_color;
lv_subject_init_color(&subject_color, lv_color_black());
observer = lv_label_bind_text(obj, &subject_color, NULL);
TEST_ASSERT_EQUAL_PTR(NULL, observer);
/*Bind to int*/
static lv_subject_t subject_int;
lv_subject_init_int(&subject_int, 10);
lv_label_bind_text(obj, &subject_int, "value: %d");
TEST_ASSERT_EQUAL_STRING("value: 10", lv_label_get_text(obj));
lv_subject_set_int(&subject_int, -20);
TEST_ASSERT_EQUAL_STRING("value: -20", lv_label_get_text(obj));
/*Remove the label from the subject*/
lv_obj_remove_from_subject(obj, &subject_int);
lv_subject_set_int(&subject_int, 100);
TEST_ASSERT_EQUAL_STRING("value: -20", lv_label_get_text(obj));
/*Bind to string*/
static char buf[32];
static lv_subject_t subject_string;
lv_subject_init_string(&subject_string, buf, NULL, 32, "hello");
lv_label_bind_text(obj, &subject_string, "text: %s");
TEST_ASSERT_EQUAL_STRING("text: hello", lv_label_get_text(obj));
lv_subject_copy_string(&subject_string, "world");
TEST_ASSERT_EQUAL_STRING("text: world", lv_label_get_text(obj));
/*Remove the label from the subject*/
lv_obj_remove_from_subject(obj, &subject_string);
lv_subject_copy_string(&subject_string, "nothing");
TEST_ASSERT_EQUAL_STRING("text: world", lv_label_get_text(obj));
/*Bind to pointer*/
static lv_subject_t subject_pointer;
lv_subject_init_pointer(&subject_pointer, "HELLO");
lv_label_bind_text(obj, &subject_pointer, "pointer: %s");
TEST_ASSERT_EQUAL_STRING("pointer: HELLO", lv_label_get_text(obj));
lv_subject_set_pointer(&subject_pointer, "WORLD");
TEST_ASSERT_EQUAL_STRING("pointer: WORLD", lv_label_get_text(obj));
/*Remove the label from the subject*/
lv_obj_remove_from_subject(obj, &subject_pointer);
lv_subject_copy_string(&subject_pointer, "NOTHING");
TEST_ASSERT_EQUAL_STRING("pointer: WORLD", lv_label_get_text(obj));
}
void test_observer_arc_value(void)
{
lv_obj_t * obj = lv_arc_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 30);
lv_arc_bind_value(obj, &subject);
TEST_ASSERT_EQUAL(30, lv_arc_get_value(obj));
lv_subject_set_int(&subject, 40);
TEST_ASSERT_EQUAL(40, lv_arc_get_value(obj));
lv_obj_update_layout(obj);
lv_test_mouse_release();
lv_test_wait(100);
lv_test_mouse_move_to(65, 10);
lv_test_mouse_press();
lv_test_wait(100);
lv_test_mouse_release();
TEST_ASSERT_EQUAL(50, lv_arc_get_value(obj));
TEST_ASSERT_EQUAL(50, lv_subject_get_int(&subject));
}
void test_observer_slider_value(void)
{
lv_obj_t * obj = lv_slider_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 30);
lv_slider_bind_value(obj, &subject);
TEST_ASSERT_EQUAL(30, lv_slider_get_value(obj));
lv_subject_set_int(&subject, 40);
TEST_ASSERT_EQUAL(40, lv_slider_get_value(obj));
lv_obj_update_layout(obj);
lv_test_mouse_release();
lv_test_wait(100);
lv_test_mouse_move_to(65, 10);
lv_test_mouse_press();
lv_test_wait(100);
lv_test_mouse_move_to(75, 10);
lv_test_mouse_press();
lv_test_wait(100);
lv_test_mouse_release();
TEST_ASSERT_EQUAL(29, lv_slider_get_value(obj));
TEST_ASSERT_EQUAL(29, lv_subject_get_int(&subject));
}
void test_observer_roller_value(void)
{
lv_obj_t * obj = lv_roller_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_roller_bind_value(obj, &subject);
TEST_ASSERT_EQUAL(1, lv_roller_get_selected(obj));
lv_subject_set_int(&subject, 2);
TEST_ASSERT_EQUAL(2, lv_roller_get_selected(obj));
lv_obj_update_layout(obj);
lv_test_mouse_click_at(30, 10);
TEST_ASSERT_EQUAL(1, lv_roller_get_selected(obj));
TEST_ASSERT_EQUAL(1, lv_subject_get_int(&subject));
}
void test_observer_dropdown_value(void)
{
lv_obj_t * obj = lv_dropdown_create(lv_screen_active());
static lv_subject_t subject;
lv_subject_init_int(&subject, 1);
lv_dropdown_bind_value(obj, &subject);
TEST_ASSERT_EQUAL(1, lv_dropdown_get_selected(obj));
lv_subject_set_int(&subject, 2);
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(obj));
lv_obj_update_layout(obj);
lv_test_mouse_click_at(30, 10);
lv_test_mouse_click_at(30, 60);
TEST_ASSERT_EQUAL(0, lv_dropdown_get_selected(obj));
TEST_ASSERT_EQUAL(0, lv_subject_get_int(&subject));
}
void test_observer_deinit(void)
{
static lv_subject_t subject;
uint32_t mem = lv_test_get_free_mem();
uint32_t i;
for(i = 0; i < 64; i++) {
lv_obj_t * obj1 = lv_slider_create(lv_screen_active());
lv_obj_t * obj2 = lv_slider_create(lv_screen_active());
lv_subject_init_int(&subject, 30);
lv_slider_bind_value(obj1, &subject);
lv_slider_bind_value(obj2, &subject);
lv_subject_add_observer(&subject, observer_int, NULL);
lv_obj_delete(obj1);
lv_subject_deinit(&subject);
lv_obj_delete(obj2);
}
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem, 32);
}
#endif
@@ -0,0 +1,101 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <string.h>
#define OUTPUT_LINE_MAX 8
#define OUTPUT_BUF_MAX 128
static uint32_t profiler_tick = 0;
static int output_line = 0;
static char output_buf[OUTPUT_LINE_MAX][OUTPUT_BUF_MAX];
static uint64_t get_tick_cb(void)
{
return profiler_tick++;
}
static void flush_cb(const char * buf)
{
TEST_ASSERT_LESS_THAN(OUTPUT_LINE_MAX, output_line);
TEST_ASSERT_LESS_THAN(OUTPUT_BUF_MAX, strlen(buf));
lv_strcpy(output_buf[output_line], buf);
output_line++;
}
void setUp(void)
{
lv_profiler_builtin_config_t config;
lv_profiler_builtin_config_init(&config);
config.buf_size = 1024;
config.tick_per_sec = 1; /* One second is equal to 1000000 microseconds */
config.tick_get_cb = get_tick_cb;
config.flush_cb = flush_cb;
lv_profiler_builtin_init(&config);
}
void tearDown(void)
{
lv_profiler_builtin_uninit();
}
void test_profiler_normal(void)
{
/* enable profiler */
lv_profiler_builtin_set_enable(true);
/* reset */
profiler_tick = 0;
output_line = 0;
lv_memzero(output_buf, sizeof(output_buf));
/* test profiler */
LV_PROFILER_BEGIN;
LV_PROFILER_END;
LV_PROFILER_BEGIN_TAG("custom_tag");
LV_PROFILER_END_TAG("custom_tag");
/* flush output */
lv_profiler_builtin_flush();
/* check output */
TEST_ASSERT_EQUAL_INT(output_line, 4);
TEST_ASSERT_EQUAL_INT(profiler_tick, 4);
TEST_ASSERT_EQUAL_STRING(output_buf[0], " LVGL-1 [0] 0.000000000: tracing_mark_write: B|1|test_profiler_normal\n");
TEST_ASSERT_EQUAL_STRING(output_buf[1], " LVGL-1 [0] 1.000000000: tracing_mark_write: E|1|test_profiler_normal\n");
TEST_ASSERT_EQUAL_STRING(output_buf[2], " LVGL-1 [0] 2.000000000: tracing_mark_write: B|1|custom_tag\n");
TEST_ASSERT_EQUAL_STRING(output_buf[3], " LVGL-1 [0] 3.000000000: tracing_mark_write: E|1|custom_tag\n");
}
void test_profiler_disable(void)
{
/* disable profiler */
lv_profiler_builtin_set_enable(false);
/* reset */
profiler_tick = 0;
output_line = 0;
lv_memzero(output_buf, sizeof(output_buf));
/* test profiler */
LV_PROFILER_BEGIN;
LV_PROFILER_END;
LV_PROFILER_BEGIN_TAG("custom_tag");
LV_PROFILER_END_TAG("custom_tag");
/* flush output */
lv_profiler_builtin_flush();
/* check output */
TEST_ASSERT_EQUAL_INT(output_line, 0);
TEST_ASSERT_EQUAL_INT(profiler_tick, 0);
TEST_ASSERT_EQUAL_CHAR(output_buf[1][0], '\0');
TEST_ASSERT_EQUAL_CHAR(output_buf[2][0], '\0');
TEST_ASSERT_EQUAL_CHAR(output_buf[3][0], '\0');
TEST_ASSERT_EQUAL_CHAR(output_buf[4][0], '\0');
}
#endif
@@ -0,0 +1,113 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "../demos/lv_demos.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_recolor_1(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 150, 150);
lv_obj_set_style_border_width(obj, 0, 0);
lv_obj_set_style_recolor(obj, lv_color_black(), 0);
lv_obj_set_style_recolor_opa(obj, LV_OPA_0, 0);
lv_obj_t * obj1 = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj1, 150, 150);
lv_obj_set_style_border_width(obj1, 0, 0);
lv_obj_set_style_bg_color(obj1, lv_color_hex(0xff0000), 0);
lv_obj_set_style_bg_opa(obj1, LV_OPA_50, 0);
lv_obj_t * obj2 = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj2, 150, 150);
lv_obj_set_style_border_width(obj2, 0, 0);
lv_obj_set_style_recolor(obj2, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(obj2, LV_OPA_50, 0);
lv_obj_t * obj3 = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj3, 150, 150);
lv_obj_set_style_border_width(obj3, 0, 0);
lv_obj_set_style_bg_color(obj3, lv_color_hex(0x00ff00), 0);
lv_obj_set_style_bg_opa(obj3, LV_OPA_50, 0);
lv_obj_set_style_recolor(obj3, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(obj3, LV_OPA_50, 0);
lv_obj_t * obj4 = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj4, 150, 150);
lv_obj_set_style_border_width(obj4, 0, 0);
lv_obj_set_style_recolor(obj4, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(obj4, LV_OPA_50, 0);
lv_obj_t * obj5 = lv_obj_create(obj4);
lv_obj_set_size(obj5, 50, 50);
lv_obj_set_style_border_width(obj5, 0, 0);
lv_obj_set_style_bg_color(obj5, lv_color_hex(0xff00), 0);
lv_obj_set_style_bg_opa(obj5, LV_OPA_100, 0);
lv_obj_align(obj5, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_t * obj6 = lv_obj_create(obj4);
lv_obj_set_size(obj6, 50, 50);
lv_obj_set_style_border_width(obj6, 0, 0);
lv_obj_set_style_bg_color(obj6, lv_color_hex(0xff00), 0);
lv_obj_set_style_bg_opa(obj6, LV_OPA_50, 0);
lv_obj_align(obj6, LV_ALIGN_RIGHT_MID, 0, 0);
LV_IMAGE_DECLARE(img_demo_widgets_avatar);
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &img_demo_widgets_avatar);
lv_obj_t * img1 = lv_image_create(lv_screen_active());
lv_image_set_src(img1, &img_demo_widgets_avatar);
lv_obj_set_style_image_recolor(img1, lv_color_hex(0xff0000), 0);
lv_obj_set_style_image_recolor_opa(img1, LV_OPA_50, 0);
lv_obj_t * img2 = lv_image_create(lv_screen_active());
lv_image_set_src(img2, &img_demo_widgets_avatar);
lv_obj_set_style_recolor(img2, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(img2, LV_OPA_50, 0);
lv_obj_t * img3 = lv_image_create(lv_screen_active());
lv_image_set_src(img3, &img_demo_widgets_avatar);
lv_obj_set_style_image_recolor(img3, lv_color_hex(0xff00), 0);
lv_obj_set_style_image_recolor_opa(img3, LV_OPA_50, 0);
lv_obj_set_style_recolor(img3, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(img3, LV_OPA_50, 0);
lv_obj_t * lable = lv_label_create(lv_screen_active());
lv_label_set_text(lable, "Hello World Hello World");
lv_obj_t * lable1 = lv_label_create(lv_screen_active());
lv_label_set_text(lable1, "Hello World Hello World");
lv_obj_set_style_text_color(lable1, lv_color_hex(0xff0000), 0);
lv_obj_set_style_text_opa(lable1, LV_OPA_50, 0);
lv_obj_t * lable2 = lv_label_create(lv_screen_active());
lv_label_set_text(lable2, "Hello World Hello World");
lv_obj_set_style_recolor(lable2, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(lable2, LV_OPA_50, 0);
lv_obj_t * lable3 = lv_label_create(lv_screen_active());
lv_label_set_text(lable3, "Hello World Hello World");
lv_obj_set_style_recolor(lable3, lv_color_hex(0xff0000), 0);
lv_obj_set_style_recolor_opa(lable3, LV_OPA_50, 0);
lv_obj_set_style_text_color(lable3, lv_color_hex(0xff00), 0);
lv_obj_set_style_text_opa(lable3, LV_OPA_50, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("recolor_1.png");
}
#endif
@@ -0,0 +1,135 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void test_screen_load_no_crash(void)
{
/*Delete active screen and load new screen should not crash*/
lv_obj_t * screen = lv_screen_active();
lv_obj_delete(screen);
screen = lv_obj_create(NULL);
lv_screen_load(screen);
/*Consecutively loading multiple screens with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_screen_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 2000, 0, false);
lv_screen_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 500, false);
}
void test_screen_load_with_delete_no_crash(void)
{
/*Delete active screen and load new screen should not crash*/
lv_obj_t * screen = lv_screen_active();
lv_obj_del(screen);
screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_wait(100);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_2);
lv_test_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), true);
}
void test_screen_load_with_delete_no_crash2(void)
{
/*Delete active screen and load new screen should not crash*/
lv_obj_t * screen = lv_screen_active();
lv_obj_del(screen);
screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_wait(100);
lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_3);
lv_test_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
}
static bool screen_1_unloaded_called = false;
static void screen_with_anim_1_unloaded_cb(lv_event_t * e)
{
LV_UNUSED(e);
screen_1_unloaded_called = true;
}
void test_screen_load_with_delete_event(void)
{
/*Delete active screen and load new screen should not crash*/
lv_obj_t * screen = lv_screen_active();
lv_obj_del(screen);
screen = lv_obj_create(NULL);
lv_scr_load(screen);
/*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/
lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL);
lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL);
lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false);
lv_obj_add_event_cb(screen_with_anim_1, screen_with_anim_1_unloaded_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true);
lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true);
/*Wait to trigger the animation start callbacks*/
lv_test_wait(100);
TEST_ASSERT_EQUAL(screen_1_unloaded_called, true);
lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true);
/*The active screen should be immediately replaced*/
TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_3);
lv_test_wait(400);
/*Check for the screens status after the transition*/
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false);
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
}
#endif
@@ -0,0 +1,139 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#if LV_USE_SNAPSHOT
#include "unity/unity.h"
#define NUM_SNAPSHOTS 10
void test_snapshot_should_not_leak_memory(void)
{
uint32_t idx = 0;
size_t initial_available_memory = 0;
size_t final_available_memory = 0;
lv_mem_monitor_t monitor;
lv_draw_buf_t * snapshots[NUM_SNAPSHOTS] = {NULL};
lv_mem_monitor(&monitor);
initial_available_memory = monitor.free_size;
for(idx = 0; idx < NUM_SNAPSHOTS; idx++) {
snapshots[idx] = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_NATIVE_WITH_ALPHA);
TEST_ASSERT_NOT_NULL(snapshots[idx]);
}
for(idx = 0; idx < NUM_SNAPSHOTS; idx++) {
lv_draw_buf_destroy(snapshots[idx]);
}
lv_mem_monitor(&monitor);
final_available_memory = monitor.free_size;
TEST_ASSERT_EQUAL(initial_available_memory, final_available_memory);
}
void test_snapshot_with_transform_should_not_leak_memory(void)
{
uint32_t idx = 0;
size_t initial_available_memory = 0;
size_t final_available_memory = 0;
lv_mem_monitor_t monitor;
lv_draw_buf_t * snapshots[NUM_SNAPSHOTS] = {NULL};
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_center(label);
lv_obj_set_style_text_font(label, &lv_font_montserrat_28, 0);
lv_label_set_text(label, "Wubba lubba dub dub!");
lv_obj_set_style_transform_rotation(label, 450, 0);
lv_mem_monitor(&monitor);
initial_available_memory = monitor.free_size;
for(idx = 0; idx < NUM_SNAPSHOTS; idx++) {
snapshots[idx] = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_NATIVE_WITH_ALPHA);
TEST_ASSERT_NOT_NULL(snapshots[idx]);
}
for(idx = 0; idx < NUM_SNAPSHOTS; idx++) {
lv_draw_buf_destroy(snapshots[idx]);
}
lv_mem_monitor(&monitor);
final_available_memory = monitor.free_size;
lv_obj_delete(label);
TEST_ASSERT_EQUAL(initial_available_memory, final_available_memory);
}
void test_snapshot_take_snapshot_immediately_after_obj_create(void)
{
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_set_style_text_font(label, &lv_font_montserrat_28, 0);
lv_label_set_text(label, "Wubba lubba dub dub!");
lv_draw_buf_t * draw_dsc = lv_snapshot_take(label, LV_COLOR_FORMAT_ARGB8888);
lv_obj_t * img_obj = lv_image_create(lv_screen_active());
lv_image_set_src(img_obj, draw_dsc);
lv_obj_delete(label);
TEST_ASSERT_EQUAL_SCREENSHOT("snapshot_0.png");
lv_obj_center(img_obj);
lv_image_set_inner_align(img_obj, LV_IMAGE_ALIGN_CENTER);
lv_image_set_rotation(img_obj, 450);
TEST_ASSERT_EQUAL_SCREENSHOT("snapshot_1.png");
lv_obj_delete(img_obj);
lv_draw_buf_destroy(draw_dsc);
}
void test_snapshot_take_snapshot_with_transform(void)
{
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_set_style_text_font(label, &lv_font_montserrat_28, 0);
lv_label_set_text(label, "Wubba lubba dub dub!");
lv_obj_set_style_transform_rotation(label, 450, 0);
lv_draw_buf_t * draw_dsc = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_ARGB8888);
lv_obj_delete(label);
lv_obj_t * img_obj = lv_image_create(lv_screen_active());
lv_image_set_src(img_obj, draw_dsc);
TEST_ASSERT_EQUAL_SCREENSHOT("snapshot_2.png");
lv_obj_delete(img_obj);
lv_draw_buf_destroy(draw_dsc);
}
#else /*LV_USE_SNAPSHOT*/
void test_snapshot_should_not_leak_memory(void)
{
}
void test_snapshot_with_transform_should_not_leak_memory(void)
{
}
void test_snapshot_take_snapshot_immediately_after_obj_create(void)
{
}
void test_snapshot_take_snapshot_with_transform(void)
{
}
#endif
#endif
@@ -0,0 +1,144 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <unistd.h>
static void obj_set_height_helper(void * obj, int32_t height)
{
lv_obj_set_height((lv_obj_t *)obj, (int32_t)height);
}
void test_gradient_vertical_misalignment(void)
{
/* Tests gradient caching as the height of widget changes.*/
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_style_bg_grad_dir(obj, LV_GRAD_DIR_VER, 0);
lv_obj_set_style_bg_grad_color(obj, lv_color_hex(0xff0000), 0);
lv_obj_set_style_bg_color(obj, lv_color_hex(0x00ff00), 0);
lv_obj_set_size(obj, 300, 100);
lv_refr_now(NULL);
lv_obj_set_style_bg_grad_color(obj, lv_color_hex(0xffff00), 0);
lv_obj_set_style_bg_color(obj, lv_color_hex(0x00ffff), 0);
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
lv_anim_set_exec_cb(&a, obj_set_height_helper);
lv_anim_set_duration(&a, 1000);
lv_anim_set_reverse_duration(&a, 1000);
lv_anim_set_repeat_count(&a, 100);
lv_anim_set_values(&a, 0, 300);
lv_anim_start(&a);
uint32_t i;
for(i = 0; i < 100; i++) {
lv_timer_handler();
lv_tick_inc(73); /*Use a not round number to cover more anim states */
usleep(1000);
}
}
void test_custom_prop_ids(void)
{
uint8_t fake_flag = 0;
uint32_t initial_custom_props = lv_style_get_num_custom_props();
uint32_t max_props_to_register = 64;
for(uint32_t i = 0; i < max_props_to_register; i++) {
lv_style_prop_t prop = lv_style_register_prop(fake_flag);
/* Should have a higher index than the last built-in prop */
TEST_ASSERT_GREATER_THAN(LV_STYLE_LAST_BUILT_IN_PROP, prop);
if(i == 0) {
/* Should be equal to the first expected index of a custom prop */
TEST_ASSERT_EQUAL(LV_STYLE_NUM_BUILT_IN_PROPS + initial_custom_props, prop);
}
/*We should find our flags*/
TEST_ASSERT_EQUAL(fake_flag, lv_style_prop_lookup_flags(prop));
if(fake_flag == 0xff)
fake_flag = 0;
else
fake_flag++;
}
TEST_ASSERT_EQUAL(initial_custom_props + max_props_to_register, lv_style_get_num_custom_props());
/*
* Check that the resizing algorithm works correctly, given that 64 props
* were registered + whatever's built-in. A failure here may just indicate
* that LVGL registers more built-in properties now and this needs adjustment.
*/
TEST_ASSERT_EQUAL(LV_GLOBAL_DEFAULT()->style_custom_table_size, 64);
}
const lv_style_const_prop_t const_style_props[] = {
LV_STYLE_CONST_WIDTH(51),
LV_STYLE_CONST_HEIGHT(50),
LV_STYLE_CONST_PROPS_END
};
LV_STYLE_CONST_INIT(const_style, const_style_props);
void test_const_style(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_add_style(obj, &const_style, LV_PART_MAIN);
TEST_ASSERT_EQUAL(51, lv_obj_get_style_width(obj, LV_PART_MAIN));
TEST_ASSERT_EQUAL(50, lv_obj_get_style_height(obj, LV_PART_MAIN));
}
void test_style_replacement(void)
{
/*Define styles*/
lv_style_t style_red;
lv_style_t style_blue;
lv_style_init(&style_red);
lv_style_set_bg_color(&style_red, lv_color_hex(0xff0000));
lv_style_init(&style_blue);
lv_style_set_bg_color(&style_blue, lv_color_hex(0x0000ff));
/*Create object with style*/
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_add_style(obj, &style_red, LV_PART_MAIN);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex(0xff0000), lv_obj_get_style_bg_color(obj, LV_PART_MAIN));
/*Replace style successfully*/
bool replaced = lv_obj_replace_style(obj, &style_red, &style_blue, LV_PART_MAIN);
TEST_ASSERT_EQUAL(true, replaced);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex(0x0000ff), lv_obj_get_style_bg_color(obj, LV_PART_MAIN));
/*Failed replacement (already replaced)*/
replaced = lv_obj_replace_style(obj, &style_red, &style_blue, LV_PART_MAIN);
TEST_ASSERT_EQUAL(false, replaced);
TEST_ASSERT_EQUAL_COLOR(lv_color_hex(0x0000ff), lv_obj_get_style_bg_color(obj, LV_PART_MAIN));
lv_style_reset(&style_red);
lv_style_reset(&style_blue);
}
void test_style_has_prop(void)
{
lv_style_t style;
lv_style_init(&style);
lv_style_set_outline_color(&style, lv_color_white());
/*Create object with style*/
lv_obj_t * obj = lv_obj_create(lv_screen_active());
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_COLOR));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_WIDTH));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_INDICATOR, LV_STYLE_OUTLINE_COLOR));
lv_obj_add_style(obj, &style, LV_PART_MAIN);
lv_obj_set_style_outline_width(obj, 2, LV_PART_MAIN);
TEST_ASSERT_EQUAL(true, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_COLOR));
TEST_ASSERT_EQUAL(true, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_WIDTH));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_INDICATOR, LV_STYLE_OUTLINE_COLOR));
lv_style_reset(&style);
}
#endif
@@ -0,0 +1,880 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#define LV_ARRAY_GET(array, index, type) ((type*)lv_array_at((array), (index)))
static const char * svg_str_1 = \
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
"<!-- some comment content <tag> <desc> ... -->"
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" baseProfile=\"tiny\""
"width=\"300px\" height=\"600px\" viewBox =\"0 0 10 10\">"
"<rect xml:id=rect1 fill=\"white\" x=\"10\" y=\"10\" width=\"100\" height=\"100\"/>"
"<desc> SVG Test </desc>"
"</svg>";
void setUp(void)
{
}
void tearDown(void)
{
}
void testSvgParser(void)
{
lv_svg_node_t * svg = lv_svg_load_data(svg_str_1, lv_strlen(svg_str_1));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
}
void testNode(void)
{
lv_svg_node_t * svg = lv_svg_node_create(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
}
void testNodeTree(void)
{
lv_svg_node_t * root = lv_svg_node_create(NULL);
lv_svg_node_t * node1 = lv_svg_node_create(root);
lv_svg_node_t * node2 = lv_svg_node_create(node1);
lv_svg_node_t * node3 = lv_svg_node_create(root);
lv_svg_attr_t attr1;
attr1.id = LV_SVG_ATTR_X;
attr1.val_type = LV_SVG_ATTR_VALUE_DATA;
attr1.value.fval = 10.0f;
lv_array_push_back(&node3->attrs, &attr1);
TEST_ASSERT_EQUAL(lv_array_size(&node3->attrs), 1);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&node3->attrs, 0, lv_svg_attr_t))->value.fval, 10.0f);
lv_svg_node_delete(node2);
lv_svg_node_delete(root);
}
void testSvgElement(void)
{
const char * svg_1 = \
"<svg version=\"1.2\" baseProfile=\"tiny\"></svg>";
lv_svg_node_t * svg_node1 = lv_svg_load_data(svg_1, lv_strlen(svg_1));
TEST_ASSERT_EQUAL(lv_array_size(&svg_node1->attrs), 2);
TEST_ASSERT_EQUAL_STRING((LV_ARRAY_GET(&svg_node1->attrs, 0, lv_svg_attr_t))->value.sval, "1.2");
TEST_ASSERT_EQUAL_STRING((LV_ARRAY_GET(&svg_node1->attrs, 1, lv_svg_attr_t))->value.sval, "tiny");
lv_svg_node_delete(svg_node1);
/* test viewBox */
const char * svg_viewbox0 = \
"<svg viewBox=\"none\"></svg>";
lv_svg_node_t * svg_node_viewbox = lv_svg_load_data(svg_viewbox0, lv_strlen(svg_viewbox0));
TEST_ASSERT_EQUAL(0, LV_ARRAY_GET(&svg_node_viewbox->attrs, 0, lv_svg_attr_t)->class_type);
lv_svg_node_delete(svg_node_viewbox);
const char * svg_viewbox1 = \
"<svg viewBox=\"0 0 10 10\"></svg>";
lv_svg_node_t * svg_node_viewbox1 = lv_svg_load_data(svg_viewbox1, lv_strlen(svg_viewbox1));
float ret1[4] = {0.0f, 0.0f, 10.0f, 10.0f};
TEST_ASSERT_EQUAL_FLOAT_ARRAY(ret1, (float *)(LV_ARRAY_GET(&svg_node_viewbox1->attrs, 0, lv_svg_attr_t))->value.val, 4);
lv_svg_node_delete(svg_node_viewbox1);
const char * svg_viewbox2 = \
"<svg viewBox=\"-5,10 +10,-10\"></svg>";
lv_svg_node_t * svg_node_viewbox2 = lv_svg_load_data(svg_viewbox2, lv_strlen(svg_viewbox2));
float ret2[4] = {-5.0f, 10.0f, 10.0f, -10.0f};
TEST_ASSERT_EQUAL_FLOAT_ARRAY(ret2, (float *)(LV_ARRAY_GET(&svg_node_viewbox2->attrs, 0, lv_svg_attr_t))->value.val, 4);
lv_svg_node_delete(svg_node_viewbox2);
const char * svg_viewbox3 = \
"<svg viewBox=\"-5,-5\"></svg>";
lv_svg_node_t * svg_node_viewbox3 = lv_svg_load_data(svg_viewbox3, lv_strlen(svg_viewbox3));
TEST_ASSERT_EQUAL(0, LV_ARRAY_GET(&svg_node_viewbox3->attrs, 0, lv_svg_attr_t)->class_type);
lv_svg_node_delete(svg_node_viewbox3);
const char * svg_viewbox4 = \
"<svg viewBox=\"-5,-5 .2 1.5E+1\"></svg>";
lv_svg_node_t * svg_node_viewbox4 = lv_svg_load_data(svg_viewbox4, lv_strlen(svg_viewbox4));
float ret4[4] = {-5.0f, -5.0f, 0.2f, 15.0f};
TEST_ASSERT_EQUAL_FLOAT_ARRAY(ret4, (float *)(LV_ARRAY_GET(&svg_node_viewbox4->attrs, 0, lv_svg_attr_t))->value.val, 4);
lv_svg_node_delete(svg_node_viewbox4);
/* width and height */
const char * svg_wh = \
"<svg width=\"100\" height=\"100px\"></svg>";
lv_svg_node_t * svg_node_wh = lv_svg_load_data(svg_wh, lv_strlen(svg_wh));
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh->attrs, 0, lv_svg_attr_t))->value.fval, 100.0f);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh->attrs, 1, lv_svg_attr_t))->value.fval, 100.0f);
lv_svg_node_delete(svg_node_wh);
const char * svg_wh2 = \
"<svg width=\"10cm\" height=\"100mm\"></svg>";
lv_svg_node_t * svg_node_wh2 = lv_svg_load_data(svg_wh2, lv_strlen(svg_wh2));
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh2->attrs, 0, lv_svg_attr_t))->value.fval, 377.9528f);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh2->attrs, 1, lv_svg_attr_t))->value.fval, 377.9528f);
lv_svg_node_delete(svg_node_wh2);
const char * svg_wh3 = \
"<svg width=\"10in\" height=\"10pc\"></svg>";
lv_svg_node_t * svg_node_wh3 = lv_svg_load_data(svg_wh3, lv_strlen(svg_wh3));
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh3->attrs, 0, lv_svg_attr_t))->value.fval, 960.0f);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh3->attrs, 1, lv_svg_attr_t))->value.fval, 160.0f);
lv_svg_node_delete(svg_node_wh3);
const char * svg_wh4 = \
"<svg width=\"10em\" height=\"10ex\"></svg>";
lv_svg_node_t * svg_node_wh4 = lv_svg_load_data(svg_wh4, lv_strlen(svg_wh4));
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh4->attrs, 0, lv_svg_attr_t))->value.fval, 160.0f);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh4->attrs, 1, lv_svg_attr_t))->value.fval, 83.2f);
lv_svg_node_delete(svg_node_wh4);
const char * svg_wh5 = \
"<svg width=\"10pt\" height=\"100%\"></svg>";
lv_svg_node_t * svg_node_wh5 = lv_svg_load_data(svg_wh5, lv_strlen(svg_wh5));
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh5->attrs, 0, lv_svg_attr_t))->value.fval, 13.3333f);
TEST_ASSERT_EQUAL_FLOAT((LV_ARRAY_GET(&svg_node_wh5->attrs, 1, lv_svg_attr_t))->value.fval, 1.0f);
lv_svg_node_delete(svg_node_wh5);
const char * svg_wh6 = \
"<svg width=\"2048\" height=\"1023.549\"></svg>";
lv_svg_node_t * svg_node_wh6 = lv_svg_load_data(svg_wh6, lv_strlen(svg_wh6));
lv_svg_render_obj_t * draw_list = lv_svg_render_create(svg_node_wh6);
float svg_wh6_w, svg_wh6_h;
lv_svg_render_get_viewport_size(draw_list, &svg_wh6_w, &svg_wh6_h);
TEST_ASSERT_EQUAL_FLOAT(svg_wh6_w, 2048.0f);
TEST_ASSERT_EQUAL_FLOAT(svg_wh6_h, 1023.549f);
lv_svg_render_delete(draw_list);
lv_svg_node_delete(svg_node_wh6);
/* preserveAspectRatio */
const char * svg_ar0 = \
"<svg preserveAspectRatio=\"none meet\"></svg>";
lv_svg_node_t * svg_node_ar = lv_svg_load_data(svg_ar0, lv_strlen(svg_ar0));
TEST_ASSERT_EQUAL(lv_array_size(&svg_node_ar->attrs), 1);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar1 = \
"<svg preserveAspectRatio=\"xMinYMin meet\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar1, lv_strlen(svg_ar1));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 2);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar2 = \
"<svg preserveAspectRatio=\" xMidYMin slice\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar2, lv_strlen(svg_ar2));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 5);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar3 = \
"<svg preserveAspectRatio=\"xMaxYMin unknow\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar3, lv_strlen(svg_ar3));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 6);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar4 = \
"<svg preserveAspectRatio=\"xMinYMid meet\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar4, lv_strlen(svg_ar4));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 8);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar5 = \
"<svg preserveAspectRatio=\"xMidYMid\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar5, lv_strlen(svg_ar5));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 10);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar6 = \
"<svg preserveAspectRatio=\"xMaxYMid slice\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar6, lv_strlen(svg_ar6));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 13);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar7 = \
"<svg preserveAspectRatio=\"xMinYMax slice\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar7, lv_strlen(svg_ar7));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 15);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar8 = \
"<svg preserveAspectRatio=\"xMidYMax meet\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar8, lv_strlen(svg_ar8));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 16);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar9 = \
"<svg preserveAspectRatio=\"xMaxYMax meet\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar9, lv_strlen(svg_ar9));
TEST_ASSERT_EQUAL((LV_ARRAY_GET(&svg_node_ar->attrs, 0, lv_svg_attr_t))->value.uval, 18);
lv_svg_node_delete(svg_node_ar);
const char * svg_ar10 = \
"<svg preserveAspectRatio=\"unknown\"></svg>";
svg_node_ar = lv_svg_load_data(svg_ar10, lv_strlen(svg_ar10));
TEST_ASSERT_EQUAL(lv_array_size(&svg_node_ar->attrs), 1);
lv_svg_node_delete(svg_node_ar);
}
void testPolylineElement(void)
{
const char * svg_poly1 = \
"<svg><polyline points=\"100.0,50 200,150.0 180,110 200,200 210,340\"/></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_poly1, lv_strlen(svg_poly1));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
5);
lv_svg_node_delete(svg_node_root);
const char * svg_poly2 = \
"<svg><polyline points=\"\n100.0,50\t200,150.0\n180,110\r \"/></svg>";
svg_node_root = lv_svg_load_data(svg_poly2, lv_strlen(svg_poly2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
3);
lv_svg_node_delete(svg_node_root);
const char * svg_poly3 = \
"<svg><polyline points=\"100.0 200,150.0 edf,err\"/></svg>";
svg_node_root = lv_svg_load_data(svg_poly3, lv_strlen(svg_poly3));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
1);
lv_svg_node_delete(svg_node_root);
const char * svg_poly4 = \
"<svg><polyline points=\"100.0\"/></svg>";
svg_node_root = lv_svg_load_data(svg_poly4, lv_strlen(svg_poly4));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
0);
lv_svg_node_delete(svg_node_root);
const char * svg_poly5 = \
"<svg><polyline points=\" \"/></svg>";
svg_node_root = lv_svg_load_data(svg_poly5, lv_strlen(svg_poly5));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
lv_svg_node_delete(svg_node_root);
}
void testPathElement(void)
{
const char * svg_path1 = \
"<svg><path d=\" \"/></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_path1, lv_strlen(svg_path1));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
lv_svg_node_delete(svg_node_root);
const char * svg_path2 = \
"<svg><path d=\"REt321\"/></svg>";
svg_node_root = lv_svg_load_data(svg_path2, lv_strlen(svg_path2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
0);
lv_svg_node_delete(svg_node_root);
const char * svg_path3 = \
"<svg><path d=\"1223\"/></svg>";
svg_node_root = lv_svg_load_data(svg_path3, lv_strlen(svg_path3));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
0);
lv_svg_node_delete(svg_node_root);
const char * svg_path4 = \
"<svg><path d=\"m 100 200 150 180 L300 500 C 400 450 320.0 280.5 400 400 Z\"/></svg>";
svg_node_root = lv_svg_load_data(svg_path4, lv_strlen(svg_path4));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
5);
lv_svg_node_delete(svg_node_root);
const char * svg_path5 = \
"<svg><path d=\"M 100 200 300 500 L400 450 l 150 100 H 500 h 100 H 600 v 100 s 100 200 300 400\"/></svg>";
svg_node_root = lv_svg_load_data(svg_path5, lv_strlen(svg_path5));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
9);
uint32_t seg_size = sizeof(uint32_t) + sizeof(lv_svg_point_t);
lv_svg_attr_values_list_t * list = (lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0,
lv_svg_attr_t))->value.val;
lv_svg_attr_path_value_t * path = (lv_svg_attr_path_value_t *)(&list->data);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_MOVE_TO);
path = (lv_svg_attr_path_value_t *)((uint8_t *)&list->data + seg_size);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_LINE_TO);
path = (lv_svg_attr_path_value_t *)((uint8_t *)&list->data + seg_size * 2);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_LINE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, 400.0f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 450.0f);
path = (lv_svg_attr_path_value_t *)((uint8_t *)&list->data + seg_size * 7);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_LINE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, 600.0f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 650.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_path6 = \
"<svg><path d=\"M 100 200 C300 500 400 450 320.0 280.5 c320 340 230 220 200 200"
" S400 400 450 450 s 500 450 550 550 q200 200 300 300 T400 400 l 450 450 480 520 t 500 500\"/></svg>";
svg_node_root = lv_svg_load_data(svg_path6, lv_strlen(svg_path6));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
10);
lv_svg_node_delete(svg_node_root);
}
void testTransform(void)
{
const char * svg_tr1 = \
"<svg><g transform=\" \"/></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_tr1, lv_strlen(svg_tr1));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
lv_svg_node_delete(svg_node_root);
const char * svg_tr2 = \
"<svg><g transform=\"none\"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr2, lv_strlen(svg_tr2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 1);
lv_svg_node_delete(svg_node_root);
const char * svg_tr3 = \
"<svg><g transform=\"matrix()\"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr3, lv_strlen(svg_tr3));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
lv_svg_matrix_t * matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 1.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 1.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[2][2], 1.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr4 = \
"<svg><g transform=\"matrix(1.5, 0, 2.0, 2, 10, 20)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr4, lv_strlen(svg_tr4));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 1.5f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][0], 0.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][1], 2.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 2.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 10.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 20.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr5 = \
"<svg><g transform=\"translate(1, 2) translate(2.0, 2)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr5, lv_strlen(svg_tr5));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 3.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 4.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr6 = \
"<svg><g transform=\" scale(0.5) scale(0.5 0.5)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr6, lv_strlen(svg_tr6));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 0.25f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 0.25f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr7 = \
"<svg><g transform=\" translate(10 ) scale( 0.5 0.5) scale(0.5 ) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr7, lv_strlen(svg_tr7));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 10.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 0.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 0.25f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 0.25f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr8 = \
"<svg><g transform=\" rotate(90 10 10) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr8, lv_strlen(svg_tr8));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 20.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 0.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr9 = \
"<svg><g transform=\" rotate(90 ) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr9, lv_strlen(svg_tr9));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 0.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 0.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_tr10 = \
"<svg><g transform=\" skewX(10) skewY(10) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_tr10, lv_strlen(svg_tr10));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][1], 0.176327f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][0], 0.176327f);
lv_svg_node_delete(svg_node_root);
}
void testStrokeFill(void)
{
const char * svg_sf1 = \
"<svg><g fill=\" \"/></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_sf1, lv_strlen(svg_sf1));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
lv_svg_node_delete(svg_node_root);
const char * svg_sf2 = \
"<svg><g fill=\"none\" stroke=\"inherit\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf2, lv_strlen(svg_sf2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 2);
lv_svg_node_delete(svg_node_root);
const char * svg_sf3 = \
"<svg><g fill=\" url(#grad1) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf3, lv_strlen(svg_sf3));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
const char * str = (const char *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(str, "grad1");
lv_svg_node_delete(svg_node_root);
const char * svg_sf4 = \
"<svg><g fill=\" url( # grad2 ) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf4, lv_strlen(svg_sf4));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
str = (const char *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(str, "");
lv_svg_node_delete(svg_node_root);
const char * svg_sf5 = \
"<svg><g fill=\" url( #grad2 ) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf5, lv_strlen(svg_sf5));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
str = (const char *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(str, "grad2");
lv_svg_node_delete(svg_node_root);
const char * svg_sf6 = \
"<svg><g fill=\" url (#grad2) \"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf6, lv_strlen(svg_sf6));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
uint32_t c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0);
lv_svg_node_delete(svg_node_root);
const char * svg_sf7 = \
"<svg><g fill=\"rgb(255, 255, 255)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf7, lv_strlen(svg_sf7));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xffffff);
lv_svg_node_delete(svg_node_root);
const char * svg_sf8 = \
"<svg><g fill=\"rgb(50%, 50%, 50%)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf8, lv_strlen(svg_sf8));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0x808080);
lv_svg_node_delete(svg_node_root);
const char * svg_sf9 = \
"<svg><g fill=\"#F00\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf9, lv_strlen(svg_sf9));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xff0000);
lv_svg_node_delete(svg_node_root);
const char * svg_sf10 = \
"<svg><g fill=\"#FF8000\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf10, lv_strlen(svg_sf10));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xff8000);
lv_svg_node_delete(svg_node_root);
const char * svg_sf11 = \
"<svg><g fill=\"red\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf11, lv_strlen(svg_sf11));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xff0000);
lv_svg_node_delete(svg_node_root);
const char * svg_sf12 = \
"<svg><g fill=\"rgba(255, 255, 255, 1.0)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf12, lv_strlen(svg_sf12));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xffffffff);
lv_svg_node_delete(svg_node_root);
const char * svg_sf13 = \
"<svg><g fill=\"rgba(255, 255, 255, 128)\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf13, lv_strlen(svg_sf13));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
c = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0x80ffffff);
lv_svg_node_delete(svg_node_root);
}
void testStrokeFillAttrs(void)
{
const char * svg_sf0 = \
"<svg><g fill-rule=\'\'/></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_sf0, lv_strlen(svg_sf0));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
lv_svg_node_delete(svg_node_root);
const char * svg_sf1 = \
"<svg><g stroke-width=1 stroke-miterlimit=3 fill-rule=\'inherit\' /></svg>";
svg_node_root = lv_svg_load_data(svg_sf1, lv_strlen(svg_sf1));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
float f1 = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(f1, 1.0f);
uint32_t f2 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(f2, 3);
lv_svg_node_delete(svg_node_root);
const char * svg_sf2 = \
"<svg><g fill-rule=\"evenodd\" stroke-width=\'-1\' stroke-miterlimit=\'-5.0\'/></svg>";
svg_node_root = lv_svg_load_data(svg_sf2, lv_strlen(svg_sf2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
uint32_t r1 = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(r1, LV_SVG_FILL_EVENODD);
float w1 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(w1, 0.0f);
uint32_t l1 = (LV_ARRAY_GET(&svg_node->attrs, 2, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(l1, 1);
lv_svg_node_delete(svg_node_root);
const char * svg_sf3 = \
"<svg><g stroke-linecap=\"round\" stroke-linejoin=\' bevel\' fill-rule=nonzero/></svg>";
svg_node_root = lv_svg_load_data(svg_sf3, lv_strlen(svg_sf3));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
uint32_t c1 = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c1, LV_SVG_LINE_CAP_ROUND);
uint32_t c2 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c2, LV_SVG_LINE_JOIN_BEVEL);
uint32_t r2 = (LV_ARRAY_GET(&svg_node->attrs, 2, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(r2, LV_SVG_FILL_NONZERO);
lv_svg_node_delete(svg_node_root);
const char * svg_sf4 = \
"<svg><g stroke-linecap=\" square \" stroke-linejoin=round/></svg>";
svg_node_root = lv_svg_load_data(svg_sf4, lv_strlen(svg_sf4));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
uint32_t c3 = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c3, LV_SVG_LINE_CAP_SQUARE);
uint32_t c4 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c4, LV_SVG_LINE_JOIN_ROUND);
lv_svg_node_delete(svg_node_root);
const char * svg_sf5 = \
"<svg><g stroke-linecap=\"a\" stroke-linejoin=\'b\' stroke-dasharray=\"none\" stroke-opacity=\"inherit\"/></svg>";
svg_node_root = lv_svg_load_data(svg_sf5, lv_strlen(svg_sf5));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
uint32_t c5 = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c5, LV_SVG_LINE_CAP_BUTT);
uint32_t c6 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(c6, LV_SVG_LINE_JOIN_MITER);
lv_svg_node_delete(svg_node_root);
const char * svg_sf6 = \
"<svg><g stroke-dasharray=\"1,2,3, 2.5, 3 \" stroke-dashoffset=1.2"
" fill-opacity=\"2.0\" stroke-dasharray=\"inherit\" /></svg>";
svg_node_root = lv_svg_load_data(svg_sf6, lv_strlen(svg_sf6));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
lv_svg_attr_values_list_t * list = (lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0,
lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(list->length, 5);
float * arr = (float *)(&list->data);
float ret[5] = {1.0f, 2.0f, 3.0f, 2.5f, 3.0f};
TEST_ASSERT_EQUAL_FLOAT_ARRAY(ret, arr, 5);
float c8 = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(c8, 1.2f);
float c9 = (LV_ARRAY_GET(&svg_node->attrs, 2, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(c9, 1.0f);
lv_svg_node_delete(svg_node_root);
}
void testTextAttrs(void)
{
const char * svg_sf0 = \
"<svg><text font-size=\'16\' font-family=\"arial\" font-variant=inherit>hello world!</text></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_sf0, lv_strlen(svg_sf0));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
float font_size = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(font_size, 16.0f);
const char * font_family = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(font_family, "arial");
lv_svg_node_t * svg_node1 = LV_SVG_NODE_CHILD(svg_node, 0);
const char * content = svg_node1->xml_id;
TEST_ASSERT_EQUAL_STRING(content, "hello world!");
lv_svg_node_delete(svg_node_root);
const char * svg_sf1 = \
"<svg><text font-size=\'16em\' font=\'user\' font-style=\" italic \" >hello<tspan>my\n</tspan>world!</text></svg>";
svg_node_root = lv_svg_load_data(svg_sf1, lv_strlen(svg_sf1));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
font_size = (LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(font_size, 256.0f);
const char * font_style = (LV_ARRAY_GET(&svg_node->attrs, 1, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(font_style, "italic ");
svg_node1 = LV_SVG_NODE_CHILD(svg_node, 0);
const char * content1 = svg_node1->xml_id;
TEST_ASSERT_EQUAL_STRING(content1, "hello");
svg_node1 = LV_SVG_NODE_CHILD(svg_node, 2);
const char * content2 = svg_node1->xml_id;
TEST_ASSERT_EQUAL_STRING(content2, "world!");
svg_node1 = LV_SVG_NODE_CHILD(svg_node, 1);
lv_svg_node_t * svg_node2 = LV_SVG_NODE_CHILD(svg_node1, 0);
const char * content3 = svg_node2->xml_id;
TEST_ASSERT_EQUAL_STRING(content3, "my");
lv_svg_node_delete(svg_node_root);
}
void testGradient(void)
{
const char * svg_gt1 = \
"<svg><linearGradient id=\"gt1\" gradientUnits= objectBoundingBox>"
"<stop stop-color='red' offset=0.1/>"
"<stop stop-color=\'black\' stop-opacity=\"0.5\" offset=1.0/>"
"</linearGradient></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_gt1, lv_strlen(svg_gt1));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_EQUAL_STRING(svg_node->xml_id, "gt1");
lv_svg_node_t * svg_node1 = LV_SVG_NODE_CHILD(svg_node, 1);
uint32_t c1 = (LV_ARRAY_GET(&svg_node1->attrs, 0, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c1, 0);
float o1 = (LV_ARRAY_GET(&svg_node1->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(o1, 0.5f);
float o2 = (LV_ARRAY_GET(&svg_node1->attrs, 2, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(o2, 1.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_gt2 = \
"<svg><defs><radialGradient xml:id=\"gt2\" gradientUnits=\"userSpaceOnUse\""
"cx=\"400\" cy=\"200\" r=\"300\">"
"<stop offset=\"0\" stop-color=\"red\"/>"
"<stop offset=\"0.5\" stop-color=\"blue\"/>"
"<stop offset=\"1\" stop-color=\"red\"/>"
"</radialGradient></defs></svg>";
svg_node_root = lv_svg_load_data(svg_gt2, lv_strlen(svg_gt2));
svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0); //defs
svg_node1 = LV_SVG_NODE_CHILD(svg_node, 0);
TEST_ASSERT_EQUAL_STRING(svg_node1->xml_id, "gt2");
uint32_t g = (LV_ARRAY_GET(&svg_node1->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(g, LV_SVG_GRADIENT_UNITS_USER_SPACE);
float cx = (LV_ARRAY_GET(&svg_node1->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(cx, 400.0f);
float cy = (LV_ARRAY_GET(&svg_node1->attrs, 2, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(cy, 200.0f);
lv_svg_node_delete(svg_node_root);
}
void testBadCase(void)
{
const char * svg_b1 = \
"<rect x=10 y=10 width=100 height=100/>";
lv_svg_node_t * svg = lv_svg_load_data(svg_b1, lv_strlen(svg_b1));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b2 = \
"<svg><text><rect x=10 y=10 width=200 height=200/></svg>";
svg = lv_svg_load_data(svg_b2, lv_strlen(svg_b2));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b3 = \
"<svg><rect x=10 y=10 width=200 height/></svg>";
svg = lv_svg_load_data(svg_b3, lv_strlen(svg_b3));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b4 = \
"<svg><g fill=\"url( \"/></svg>";
svg = lv_svg_load_data(svg_b4, lv_strlen(svg_b4));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(0, LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t)->class_type);
lv_svg_node_delete(svg);
const char * svg_b5 = \
"<svg><g transform=matrix/></svg>";
svg = lv_svg_load_data(svg_b5, lv_strlen(svg_b5));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
lv_svg_matrix_t * matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 1.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 1.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[2][2], 1.0f);
lv_svg_node_delete(svg);
const char * svg_b6 = \
"<svg><123><123></svg>";
svg = lv_svg_load_data(svg_b6, lv_strlen(svg_b6));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b7 = \
"<svg><my> bad case <you></svg>";
svg = lv_svg_load_data(svg_b7, lv_strlen(svg_b7));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b8 = \
"<svg><path d=\"M 100 L150 180 L 150 Z\"/></svg>";
svg = lv_svg_load_data(svg_b8, lv_strlen(svg_b8));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
3);
uint32_t seg_size = sizeof(uint32_t) + sizeof(lv_svg_point_t);
lv_svg_attr_values_list_t * list = (lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0,
lv_svg_attr_t))->value.val;
lv_svg_attr_path_value_t * path = (lv_svg_attr_path_value_t *)(&list->data);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_MOVE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, 100.0f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 150.0f);
path = (lv_svg_attr_path_value_t *)((uint8_t *)&list->data + seg_size);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_LINE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, 180.0f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 150.0f);
lv_svg_node_delete(svg);
const char * svg_b9 = \
"<svg><path d=\"M 100 200 L150 Z\"/></svg>";
svg = lv_svg_load_data(svg_b9, lv_strlen(svg_b9));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
1);
seg_size = sizeof(uint32_t) + sizeof(lv_svg_point_t);
list = (lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
path = (lv_svg_attr_path_value_t *)(&list->data);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_MOVE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, 100.0f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 200.0f);
lv_svg_node_delete(svg);
const char * svg_b10 = \
"<svg></text>bad case</text></svg>";
svg = lv_svg_load_data(svg_b10, lv_strlen(svg_b10));
TEST_ASSERT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b11 = \
"<svg><text font-size></text></svg>";
svg = lv_svg_load_data(svg_b11, lv_strlen(svg_b11));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
TEST_ASSERT_EQUAL(LV_TREE_NODE(svg_node)->child_cnt, 0);
lv_svg_node_delete(svg);
const char * svg_b12 = \
"<svg><text font-size=></text></svg>";
svg = lv_svg_load_data(svg_b12, lv_strlen(svg_b12));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(lv_array_size(&svg_node->attrs), 0);
TEST_ASSERT_EQUAL(LV_TREE_NODE(svg_node)->child_cnt, 0);
lv_svg_node_delete(svg);
const char * svg_b13 = \
"<svg><!-aaaa /></svg>";
svg = lv_svg_load_data(svg_b13, lv_strlen(svg_b13));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b14 = \
"<svg><rect"
"x=1 y=1 width=10 height=10"
"x=1 y=1 width=10 height=10"
"x=1 y=1 width=10 height=10"
" /></svg>";
svg = lv_svg_load_data(svg_b14, lv_strlen(svg_b14));
TEST_ASSERT_NOT_EQUAL(NULL, svg);
lv_svg_node_delete(svg);
const char * svg_b15 = \
"<svg>"
"<path d=\'m-122.3,84.285s0.1,1.894-0.73,1.875c-0.82-0.019-17.27-48.094-37.8-45.851,0,0,17.78-7.353,38.53,43.976z\'/>"
"</svg>";
svg = lv_svg_load_data(svg_b15, lv_strlen(svg_b15));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
TEST_ASSERT_EQUAL(((lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val)->length,
5);
seg_size = sizeof(uint32_t) + sizeof(lv_svg_point_t);
list = (lv_svg_attr_values_list_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
path = (lv_svg_attr_path_value_t *)(&list->data);
TEST_ASSERT_EQUAL(path->cmd, LV_SVG_PATH_CMD_MOVE_TO);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->x, -122.3f);
TEST_ASSERT_EQUAL_FLOAT(((lv_svg_point_t *)(&path->data))->y, 84.285f);
lv_svg_node_delete(svg);
const char * svg_b16 = \
"<svg>"
"<g transform=\'matrix(1.7656463,0,0,1.7656463,324.90716,255.00942)\'>"
"</g>"
"</svg>";
svg = lv_svg_load_data(svg_b16, lv_strlen(svg_b16));
svg_node = LV_SVG_NODE_CHILD(svg, 0);
matrix = (lv_svg_matrix_t *)(LV_ARRAY_GET(&svg_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][0], 1.7656463f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][0], 0.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][1], 0.0f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][1], 1.7656463f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[0][2], 324.90716f);
TEST_ASSERT_EQUAL_FLOAT(matrix->m[1][2], 255.00942f);
lv_svg_node_delete(svg);
}
#endif
@@ -0,0 +1,267 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#define LV_ARRAY_GET(array, index, type) ((type*)lv_array_at((array), (index)))
void setUp(void)
{
}
void tearDown(void)
{
}
void testAnimate(void)
{
const char * svg_anim0 = \
"<svg><rect xml:id=\"RectElement\" x=\"300\" y=\"100\" width=\"300\" height=\"100\">"
"<animate attributeName=\"x\" dur=\"9s\" fill=\"freeze\" from=\"300\" to=\"0\"/>"
"</rect></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_anim0, lv_strlen(svg_anim0));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
lv_svg_node_t * anim_node = LV_SVG_NODE_CHILD(svg_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE, anim_node->type);
lv_svg_attr_type_t at = (LV_ARRAY_GET(&anim_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(LV_SVG_ATTR_X, at);
float dur = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(dur, 9000.0f);
int ft = (LV_ARRAY_GET(&anim_node->attrs, 2, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(ft, LV_SVG_ANIM_FREEZE);
float fr = (LV_ARRAY_GET(&anim_node->attrs, 3, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(fr, 300.0f);
float to = (LV_ARRAY_GET(&anim_node->attrs, 4, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(to, 0.0f);
lv_svg_node_delete(svg_node_root);
}
void testSet(void)
{
const char * svg_anim0 = \
"<svg><rect xml:id=\"RectElement\" x=\"300\" y=\"100\" width=\"300\" height=\"100\">"
"<set attributeName=\"x\" to=\"500\" values=\"0\"/>"
"</rect></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_anim0, lv_strlen(svg_anim0));
lv_svg_node_t * svg_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
lv_svg_node_t * anim_node = LV_SVG_NODE_CHILD(svg_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_SET, anim_node->type);
lv_svg_attr_type_t at = (LV_ARRAY_GET(&anim_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(LV_SVG_ATTR_X, at);
float to = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(to, 500.0f);
lv_svg_node_delete(svg_node_root);
}
void testAnimateMotion(void)
{
const char * svg_anim0 = \
"<svg><path xml:id=\"path1\" d=\"M100,250 C 100,50 400,50 400,250\" "
"fill=\"none\" stroke=\"blue\" stroke-width=\"7.06\"/>"
"<animateMotion dur=\"6s\" repeatCount=\"indefinite\" rotate=\"auto\">"
"<mpath xlink:href=\"#path1\"/>"
"</animateMotion>"
"</svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_anim0, lv_strlen(svg_anim0));
lv_svg_node_t * path_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_NOT_EQUAL(NULL, path_node);
lv_svg_node_t * anim_node = LV_SVG_NODE_CHILD(svg_node_root, 1);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_MOTION, anim_node->type);
lv_svg_node_t * mpath_node = LV_SVG_NODE_CHILD(anim_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, mpath_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_MPATH, mpath_node->type);
const char * xlink = (LV_ARRAY_GET(&mpath_node->attrs, 0, lv_svg_attr_t))->value.sval;
TEST_ASSERT_EQUAL_STRING(xlink, path_node->xml_id);
uint32_t rp = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(rp, 0);
float rt = (LV_ARRAY_GET(&anim_node->attrs, 2, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL_FLOAT(rt, 0.0f);
lv_svg_node_delete(svg_node_root);
const char * svg_anim1 = \
"<svg><circle r=\"5\" fill=\"blue\">"
"<animateMotion begin=\"500ms\" dur=\"3.1s\" calcMode=\"linear\" keyPoints=\"0.5; 0.8; 1.0\" path=\"M15,43 C15,43 36,20 65,33\"/>"
"</circle>"
"</svg>";
svg_node_root = lv_svg_load_data(svg_anim1, lv_strlen(svg_anim1));
path_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
anim_node = LV_SVG_NODE_CHILD(path_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_MOTION, anim_node->type);
lv_svg_attr_values_list_t * lb = (LV_ARRAY_GET(&anim_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lb->length, 1);
float * fb = (float *)(&lb->data);
TEST_ASSERT_EQUAL_FLOAT(*fb, 500.0f);
float dr = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.fval;
TEST_ASSERT_EQUAL(dr, 3100.0f);
int cm = (LV_ARRAY_GET(&anim_node->attrs, 2, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(cm, LV_SVG_ANIM_CALC_MODE_LINEAR);
lv_svg_attr_values_list_t * l = (LV_ARRAY_GET(&anim_node->attrs, 3, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(l->length, 3);
float * pt = (float *)(&l->data);
TEST_ASSERT_EQUAL_FLOAT(pt[0], 0.5f);
TEST_ASSERT_EQUAL_FLOAT(pt[1], 0.8f);
TEST_ASSERT_EQUAL_FLOAT(pt[2], 1.0f);
lv_svg_attr_values_list_t * lp = (LV_ARRAY_GET(&anim_node->attrs, 4, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lp->length, 2);
lv_svg_node_delete(svg_node_root);
const char * svg_anim2 = \
"<svg><circle r=\"5\" fill=\"blue\">"
"<animateMotion begin=\"5s;2s\" end=\"8s;10s\" values=\"100, 50;200 200\" keyTimes=\"100ms;200ms\""
" keySplines=\"0 0 1.5 1.0; 0.5 0.5, 2.0,1.5\" additive=\"sum\" accumulate=\"none\"/>"
"</circle>"
"</svg>";
svg_node_root = lv_svg_load_data(svg_anim2, lv_strlen(svg_anim2));
path_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
anim_node = LV_SVG_NODE_CHILD(path_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_MOTION, anim_node->type);
lb = (LV_ARRAY_GET(&anim_node->attrs, 0, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lb->length, 2);
fb = (float *)(&lb->data);
TEST_ASSERT_EQUAL_FLOAT(fb[0], 5000.0f);
TEST_ASSERT_EQUAL_FLOAT(fb[1], 2000.0f);
lb = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lb->length, 2);
fb = (float *)(&lb->data);
TEST_ASSERT_EQUAL_FLOAT(fb[0], 8000.0f);
TEST_ASSERT_EQUAL_FLOAT(fb[1], 10000.0f);
lb = (LV_ARRAY_GET(&anim_node->attrs, 2, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lb->length, 2);
lv_svg_point_t * ps = (lv_svg_point_t *)(&lb->data);
TEST_ASSERT_EQUAL_FLOAT(ps[0].x, 100.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[0].y, 50.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[1].x, 200.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[1].y, 200.0f);
lb = (LV_ARRAY_GET(&anim_node->attrs, 3, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(lb->length, 2);
fb = (float *)(&lb->data);
TEST_ASSERT_EQUAL_FLOAT(fb[0], 100.0f);
TEST_ASSERT_EQUAL_FLOAT(fb[1], 200.0f);
l = (LV_ARRAY_GET(&anim_node->attrs, 4, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(l->length, 4);
ps = (lv_svg_point_t *)(&l->data);
TEST_ASSERT_EQUAL_FLOAT(ps[0].x, 0.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[0].y, 0.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[1].x, 1.5f);
TEST_ASSERT_EQUAL_FLOAT(ps[1].y, 1.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[2].x, 0.5f);
TEST_ASSERT_EQUAL_FLOAT(ps[2].y, 0.5f);
TEST_ASSERT_EQUAL_FLOAT(ps[3].x, 2.0f);
TEST_ASSERT_EQUAL_FLOAT(ps[3].y, 1.5f);
lv_svg_node_delete(svg_node_root);
}
void testAnimateTransform(void)
{
const char * svg_anim0 = \
"<svg><rect transform=\"skewX(30)\" x=0 y=0 width=100 height=100>"
"<animateTransform attributeName=\"transform\" attributeType=\"XML\""
"type=\"rotate\" from=\"0\" to=\"90\" dur=\"5s\""
"additive=\"sum\" fill=\"freeze\"/>"
"<animateTransform attributeName=\"transform\" attributeType=\"XML\""
"type=\"scale\" from=\"1\" to=\"2\" dur=\"5s\" values=\"0.5; 0.2, 0.2\""
"additive=\"sum\" fill=\"freeze\"/>"
"</rect></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_anim0, lv_strlen(svg_anim0));
lv_svg_node_t * path_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_NOT_EQUAL(NULL, path_node);
lv_svg_node_t * anim_node1 = LV_SVG_NODE_CHILD(path_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node1);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_TRANSFORM, anim_node1->type);
lv_svg_node_t * anim_node2 = LV_SVG_NODE_CHILD(path_node, 1);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node2);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_TRANSFORM, anim_node2->type);
lv_svg_attr_type_t at = (LV_ARRAY_GET(&anim_node1->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(LV_SVG_ATTR_TRANSFORM, at);
lv_svg_transform_type_t tt = (LV_ARRAY_GET(&anim_node1->attrs, 1, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(LV_SVG_TRANSFORM_TYPE_ROTATE, tt);
lv_svg_attr_values_list_t * l = (LV_ARRAY_GET(&anim_node1->attrs, 2, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(l->length, 1);
float * pt = (float *)(&l->data);
TEST_ASSERT_EQUAL_FLOAT(pt[0], 0.0f);
l = (LV_ARRAY_GET(&anim_node2->attrs, 5, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(l->length, 2);
lv_svg_attr_values_list_t * ll = (lv_svg_attr_values_list_t *)(&l->data);
TEST_ASSERT_EQUAL(ll->length, 1);
pt = (float *)(&ll->data);
TEST_ASSERT_EQUAL_FLOAT(pt[0], 0.5f);
ll = (lv_svg_attr_values_list_t *)((uint8_t *)(&l->data) + sizeof(uint32_t) + sizeof(float) * 4);
TEST_ASSERT_EQUAL(ll->length, 2);
pt = (float *)(&ll->data);
TEST_ASSERT_EQUAL_FLOAT(pt[0], 0.2f);
TEST_ASSERT_EQUAL_FLOAT(pt[1], 0.2f);
lv_svg_node_delete(svg_node_root);
}
void testAnimateColor(void)
{
const char * svg_anim0 = \
"<svg><rect color=\"yellow\" fill=\"black\">"
"<animateColor attributeName=\"fill\" from=\"red\" to=\"#DDF\" "
"begin=\"1s\" dur=\"5s\" fill=\"freeze\" additive=\"sum\" repeatCount=5 restart=\"whenNotActive\" values=\"rgb(0,255,0);black\" />"
"</rect></svg>";
lv_svg_node_t * svg_node_root = lv_svg_load_data(svg_anim0, lv_strlen(svg_anim0));
lv_svg_node_t * path_node = LV_SVG_NODE_CHILD(svg_node_root, 0);
TEST_ASSERT_NOT_EQUAL(NULL, path_node);
lv_svg_node_t * anim_node = LV_SVG_NODE_CHILD(path_node, 0);
TEST_ASSERT_NOT_EQUAL(NULL, anim_node);
TEST_ASSERT_EQUAL(LV_SVG_TAG_ANIMATE_COLOR, anim_node->type);
lv_svg_attr_type_t at = (LV_ARRAY_GET(&anim_node->attrs, 0, lv_svg_attr_t))->value.ival;
TEST_ASSERT_EQUAL(LV_SVG_ATTR_FILL, at);
uint32_t c = (LV_ARRAY_GET(&anim_node->attrs, 1, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xFF0000);
c = (LV_ARRAY_GET(&anim_node->attrs, 2, lv_svg_attr_t))->value.uval;
TEST_ASSERT_EQUAL(c, 0xDDDDFF);
lv_svg_attr_values_list_t * l = (LV_ARRAY_GET(&anim_node->attrs, 9, lv_svg_attr_t))->value.val;
TEST_ASSERT_EQUAL(l->length, 2);
uint32_t * pc = (uint32_t *)(&l->data);
TEST_ASSERT_EQUAL(pc[0], 0x00FF00);
TEST_ASSERT_EQUAL(pc[1], 0x000000);
lv_svg_node_delete(svg_node_root);
}
#endif
@@ -0,0 +1,213 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#define MY_CLASS &lv_test_tree_class
typedef struct {
lv_tree_node_t base;
int data1;
float data2;
} lv_test_node_t;
static void lv_test_constructor(const lv_tree_class_t * class_p, lv_tree_node_t * node)
{
LV_UNUSED(class_p);
lv_test_node_t * t = (lv_test_node_t *)node;
t->data1 = 100;
t->data2 = 100.0f;
}
static void lv_test_destructor(const lv_tree_class_t * class_p, lv_tree_node_t * node)
{
LV_UNUSED(class_p);
lv_test_node_t * t = (lv_test_node_t *)node;
t->data1 = 0;
t->data2 = 0.0f;
}
const lv_tree_class_t lv_test_tree_class = {
.base_class = &lv_tree_node_class,
.instance_size = sizeof(lv_test_node_t),
.constructor_cb = lv_test_constructor,
.destructor_cb = lv_test_destructor,
};
static lv_test_node_t * lv_test_create(lv_test_node_t * parent)
{
lv_tree_node_t * node = lv_tree_node_create(MY_CLASS, (lv_tree_node_t *)parent);
return (lv_test_node_t *)node;
}
static void lv_test_delete(lv_test_node_t * node)
{
lv_tree_node_delete((lv_tree_node_t *)node);
}
static lv_test_node_t * test;
void setUp(void)
{
test = lv_test_create(NULL);
}
void tearDown(void)
{
lv_test_delete(test);
}
void testCreateAndDelete(void)
{
lv_test_node_t * node = lv_test_create(test);
TEST_ASSERT_EQUAL_UINT32(1, test->base.child_cnt);
TEST_ASSERT_EQUAL_UINT32(0, node->base.child_cnt);
TEST_ASSERT_EQUAL(test, node->base.parent);
TEST_ASSERT_EQUAL(NULL, test->base.parent);
TEST_ASSERT_EQUAL_INT32(100, node->data1);
TEST_ASSERT_EQUAL_FLOAT(100.0f, node->data2);
lv_test_delete(node);
TEST_ASSERT_EQUAL(NULL, test->base.children[0]);
}
struct _result {
int32_t result[8];
int32_t num;
};
static bool test_walk_cb(const lv_tree_node_t * node, void * data)
{
lv_test_node_t * n = (lv_test_node_t *)node;
struct _result * ret = (struct _result *)data;
ret->result[ret->num++] = n->data1;
return true;
}
void testBuildTree(void)
{
lv_test_node_t * node = lv_test_create(test);
node->data1 = 0;
for(int i = 0; i < 16; i++) {
lv_test_node_t * snode = lv_test_create(node);
snode->data1 = i;
TEST_ASSERT_NOT_EQUAL(NULL, snode);
}
TEST_ASSERT_EQUAL(16, node->base.child_cnt);
lv_test_delete(node);
}
void testWalkTree(void)
{
lv_test_node_t * node = lv_test_create(test);
node->data1 = 1;
lv_test_node_t * node1 = lv_test_create(node);
node1->data1 = 2;
lv_test_node_t * node2 = lv_test_create(node);
node2->data1 = 3;
lv_test_node_t * node11 = lv_test_create(node1);
node11->data1 = 4;
lv_test_node_t * node12 = lv_test_create(node1);
node12->data1 = 5;
lv_test_node_t * node21 = lv_test_create(node2);
node21->data1 = 6;
lv_test_node_t * node111 = lv_test_create(node11);
node111->data1 = 7;
struct _result result = {.num = 0};
lv_tree_walk((lv_tree_node_t *)node, LV_TREE_WALK_POST_ORDER, test_walk_cb, NULL, NULL, &result);
int32_t ret[8] = {7, 4, 5, 2, 6, 3, 1};
TEST_ASSERT_EQUAL_INT32_ARRAY(ret, result.result, 8);
result.num = 0;
lv_memset(&result, 0, sizeof(struct _result));
lv_tree_walk((lv_tree_node_t *)node, LV_TREE_WALK_PRE_ORDER, test_walk_cb, NULL, NULL, &result);
int32_t ret2[8] = {1, 2, 4, 7, 5, 3, 6};
TEST_ASSERT_EQUAL_INT32_ARRAY(ret2, result.result, 8);
lv_test_delete(node111);
result.num = 0;
lv_memset(&result, 0, sizeof(struct _result));
lv_tree_walk((lv_tree_node_t *)node, LV_TREE_WALK_PRE_ORDER, test_walk_cb, NULL, NULL, &result);
int32_t ret3[8] = {1, 2, 4, 5, 3, 6};
TEST_ASSERT_EQUAL_INT32_ARRAY(ret3, result.result, 8);
lv_test_delete(node);
}
static bool test_search_cb(const lv_tree_node_t * node, void * data)
{
lv_test_node_t * n = (lv_test_node_t *)node;
struct _result * ret = (struct _result *)data;
if(n->data1 == 3) {
return false;
}
ret->result[ret->num++] = n->data1;
return true;
}
static bool test_before_search_cb(const lv_tree_node_t * node, void * data)
{
LV_UNUSED(node);
LV_UNUSED(data);
return true;
}
static void test_after_search_cb(const lv_tree_node_t * node, void * data)
{
LV_UNUSED(node);
LV_UNUSED(data);
}
void testTreeSearch(void)
{
lv_test_node_t * node = lv_test_create(test);
node->data1 = 1;
lv_test_node_t * node1 = lv_test_create(node);
node1->data1 = 2;
lv_test_node_t * node2 = lv_test_create(node);
node2->data1 = 3;
lv_test_node_t * node11 = lv_test_create(node1);
node11->data1 = 4;
struct _result result = {.num = 0};
lv_tree_walk((lv_tree_node_t *)node, LV_TREE_WALK_PRE_ORDER, test_search_cb, test_before_search_cb,
test_after_search_cb, &result);
int32_t ret2[4] = {1, 2};
TEST_ASSERT_EQUAL_INT32_ARRAY(ret2, result.result, 2);
result.num = 0;
lv_memset(&result, 0, sizeof(struct _result));
lv_tree_walk((lv_tree_node_t *)node, LV_TREE_WALK_POST_ORDER, test_search_cb, test_before_search_cb,
test_after_search_cb, &result);
int32_t ret3[4] = {4, 2};
TEST_ASSERT_EQUAL_INT32_ARRAY(ret3, result.result, 2);
lv_test_delete(node);
}
#endif
@@ -0,0 +1,207 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include "../../../src/misc/lv_text_private.h"
#include <string.h>
void test_txt_should_insert_string_into_another(void)
{
const char * msg = "Hello ";
const char * suffix = "World";
char target[20] = {0};
size_t msg_len = strlen(msg);
strcpy(target, msg);
lv_text_ins(target, msg_len, suffix);
TEST_ASSERT_EQUAL_STRING("Hello World", target);
}
void test_txt_should_handle_null_pointers_when_inserting(void)
{
const char * msg = "Hello ";
char target[20] = {0};
size_t msg_len = strlen(msg);
strcpy(target, msg);
lv_text_ins(target, msg_len, NULL);
TEST_ASSERT_EQUAL_STRING("Hello ", target);
}
void test_txt_cut_should_handle_null_pointer_to_txt(void)
{
lv_text_cut(NULL, 0, 6);
}
void test_txt_cut_happy_path(void)
{
char msg[] = "Hello World";
lv_text_cut(msg, 0, 6);
TEST_ASSERT_EQUAL_STRING("World", msg);
}
void test_txt_cut_should_handle_len_longer_than_string_length(void)
{
char msg[] = "Hello World";
lv_text_cut(msg, 0, 30);
TEST_ASSERT_EQUAL_UINT8(msg[0], 0x00);
}
void test_txt_get_encoded_next_should_decode_valid_ascii(void)
{
char msg[] = "Hello World!";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32((uint32_t) 'H', result);
}
void test_txt_get_encoded_next_detect_valid_2_byte_input(void)
{
char msg[] = "\xc3\xb1";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(241, result);
}
void test_txt_get_encoded_next_detect_invalid_2_byte_input(void)
{
char msg[] = "\xc3\x28";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(0, result);
}
void test_txt_get_encoded_next_detect_valid_3_byte_input(void)
{
char msg[] = "\xe2\x82\xa1";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(8353, result);
}
void test_txt_get_encoded_next_detect_invalid_3_byte_input(void)
{
char msg[] = "\xe2\x28\xa1";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(0, result);
}
void test_txt_get_encoded_next_detect_valid_4_byte_input(void)
{
char msg[] = "\xf0\x90\x8c\xbc";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(66364, result);
}
void test_txt_get_encoded_next_detect_invalid_4_byte_input(void)
{
char msg[] = "\xf0\x28\x8c\x28";
uint32_t result = 0;
result = lv_text_encoded_next(msg, NULL);
TEST_ASSERT_EQUAL_UINT32(0, result);
}
/* See #2615 for more information */
void test_txt_next_line_should_handle_empty_string(void)
{
const lv_font_t * font_ptr = NULL;
int32_t letter_space = 0;
int32_t max_width = 0;
lv_text_flag_t flag = LV_TEXT_FLAG_NONE;
uint32_t next_line = lv_text_get_next_line("", 0, font_ptr, letter_space, max_width, NULL, flag);
TEST_ASSERT_EQUAL_UINT32(0, next_line);
}
void test_lv_text_encoded_letter_next_2_should_handle_null_pointer(void)
{
const char * txt = NULL;
uint32_t letter = 100, letter_next = 101, ofs = 0;
lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &ofs);
/* Expect both letter and letter_next to be 0 because the input string is NULL */
TEST_ASSERT_EQUAL_UINT32(0, letter);
TEST_ASSERT_EQUAL_UINT32(0, letter_next);
TEST_ASSERT_EQUAL_UINT32(0, ofs);
}
void test_lv_text_encoded_letter_next_2_should_handle_empty_string(void)
{
const char * txt = "";
uint32_t letter = 100, letter_next = 101, ofs = 0;
lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &ofs);
/* Expect both letter and letter_next to be 0 because the input string is empty */
TEST_ASSERT_EQUAL_UINT32(0, letter);
TEST_ASSERT_EQUAL_UINT32(0, letter_next);
TEST_ASSERT_EQUAL_UINT32(0, ofs);
}
void test_lv_text_encoded_letter_next_2_should_handle_single_ascii_character(void)
{
const char * txt = "A";
uint32_t letter = 0, letter_next = 0, ofs = 0;
lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &ofs);
/* Expect letter to be 'A' (ASCII 65), letter_next to be 0 (no next character), and ofs to point to end of string */
TEST_ASSERT_EQUAL_UINT32('A', letter);
TEST_ASSERT_EQUAL_UINT32(0, letter_next);
TEST_ASSERT_EQUAL_UINT32(1, ofs);
}
void test_lv_text_encoded_letter_next_2_should_handle_utf8_multibyte_character(void)
{
const char * txt = "é"; /* UTF-8 encoding: 0xC3 0xA9 */
uint32_t letter = 0, letter_next = 0, ofs = 0;
lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &ofs);
/* Expect letter to decode 'é', letter_next to be 0 (no next character), and ofs to point to end of string */
TEST_ASSERT_EQUAL_UINT32(0xE9, letter); /* Unicode code point for 'é' */
TEST_ASSERT_EQUAL_UINT32(0, letter_next);
TEST_ASSERT_EQUAL_UINT32(2, ofs); /* 'é' is 2 bytes long in UTF-8 */
}
void test_lv_text_encoded_letter_next_2_should_handle_two_utf8_characters(void)
{
const char * txt = "éA"; /* UTF-8 encoding: 0xC3 0xA9 0x41 */
uint32_t letter = 0, letter_next = 0, ofs = 0;
lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &ofs);
/* Expect letter to decode 'é', letter_next to be 'A', and ofs to point after 'é' */
TEST_ASSERT_EQUAL_UINT32(0xE9, letter); /* Unicode code point for 'é' */
TEST_ASSERT_EQUAL_UINT32('A', letter_next); /* ASCII value for 'A' */
TEST_ASSERT_EQUAL_UINT32(2, ofs); /* Offset after 'é' */
}
#endif
@@ -0,0 +1,143 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
LV_IMAGE_DECLARE(test_animimg001);
LV_IMAGE_DECLARE(test_animimg002);
LV_IMAGE_DECLARE(test_animimg003);
static const lv_image_dsc_t * anim_imgs[3] = {
&test_animimg001,
&test_animimg002,
&test_animimg003,
};
static lv_obj_t * active_screen = NULL;
static lv_obj_t * animimg = NULL;
void setUp(void);
void tearDown(void);
void test_animimg_successful_create(void);
void test_animimg_set_src(void);
void test_animimg_set_src_reverse(void);
void test_animimg_get_src_count(void);
void test_animimg_set_duration(void);
void test_animimg_set_repeat_count_infinite(void);
void test_animimg_start(void);
void setUp(void)
{
active_screen = lv_screen_active();
animimg = lv_animimg_create(active_screen);
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_animimg_successful_create(void)
{
TEST_ASSERT_NOT_NULL(animimg);
}
void test_animimg_set_src(void)
{
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
TEST_ASSERT_NOT_NULL(animimg);
}
void test_animimg_set_src_reverse(void)
{
lv_animimg_set_src_reverse(animimg, (const void **) anim_imgs, 3);
TEST_ASSERT_NOT_NULL(animimg);
}
void test_animimg_get_src(void)
{
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
const void ** actual_dsc = lv_animimg_get_src(animimg);
TEST_ASSERT_NOT_NULL(actual_dsc);
TEST_ASSERT_EQUAL_PTR(actual_dsc, anim_imgs);
}
void test_animimg_get_src_count(void)
{
uint8_t expected_count = 3;
lv_animimg_set_src(animimg, (const void **) anim_imgs, expected_count);
uint8_t actual_count = lv_animimg_get_src_count(animimg);
TEST_ASSERT_EQUAL_UINT8(actual_count, expected_count);
}
void test_animimg_set_duration(void)
{
uint16_t expected_duration = 1000;
lv_animimg_set_duration(animimg, expected_duration);
uint16_t actual_duration = lv_animimg_get_duration(animimg);
TEST_ASSERT_EQUAL_UINT16(actual_duration, expected_duration);
}
void test_animimg_set_repeat_count_infinite(void)
{
lv_animimg_set_repeat_count(animimg, LV_ANIM_REPEAT_INFINITE);
uint32_t actual_count = lv_animimg_get_repeat_count(animimg);
TEST_ASSERT_EQUAL_UINT32(actual_count, LV_ANIM_REPEAT_INFINITE);
}
void test_animimg_start(void)
{
// for lv_animimg_start() to actually work,
// we need to properly setup the widget beforehand
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
lv_animimg_set_duration(animimg, 1000);
lv_animimg_set_repeat_count(animimg, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animimg);
TEST_ASSERT_NOT_NULL(animimg);
}
void test_animimg_property(void)
{
#if LV_USE_OBJ_PROPERTY
lv_property_t prop;
lv_obj_t * obj = lv_animimg_create(lv_screen_active());
prop.id = LV_PROPERTY_ANIMIMAGE_SRC;
prop.arg1.ptr = anim_imgs;
prop.arg2.num = 3;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_PTR(lv_obj_get_property(obj, LV_PROPERTY_ANIMIMAGE_SRC).ptr, anim_imgs);
TEST_ASSERT_EQUAL_PTR(lv_animimg_get_src(obj), anim_imgs);
TEST_ASSERT_EQUAL_INT(lv_animimg_get_src_count(obj), 3);
TEST_ASSERT_EQUAL_INT(3, lv_obj_get_property(obj, LV_PROPERTY_ANIMIMAGE_SRC_COUNT).num);
prop.id = LV_PROPERTY_ANIMIMAGE_DURATION;
prop.num = 1000;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(1000, lv_animimg_get_duration(obj));
TEST_ASSERT_EQUAL_INT(1000, lv_obj_get_property(obj, LV_PROPERTY_ANIMIMAGE_DURATION).num);
prop.id = LV_PROPERTY_ANIMIMAGE_REPEAT_COUNT;
prop.num = LV_ANIM_REPEAT_INFINITE;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(LV_ANIM_REPEAT_INFINITE, lv_animimg_get_repeat_count(obj));
TEST_ASSERT_EQUAL_INT(LV_ANIM_REPEAT_INFINITE, lv_obj_get_property(obj, LV_PROPERTY_ANIMIMAGE_REPEAT_COUNT).num_u);
#endif
}
#endif
@@ -0,0 +1,312 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
/* This function runs before each test */
void setUp(void);
void test_arc_creation_successful(void);
void test_arc_should_truncate_to_max_range_when_new_value_exceeds_it(void);
void test_arc_should_truncate_to_min_range_when_new_value_is_inferior(void);
void test_arc_should_update_value_after_updating_range(void);
void test_arc_should_update_angles_when_changing_to_symmetrical_mode(void);
void test_arc_should_update_angles_when_changing_to_symmetrical_mode_value_more_than_middle_range(void);
void test_arc_angles_when_reversed(void);
static lv_obj_t * active_screen = NULL;
static lv_obj_t * arc = NULL;
static lv_obj_t * arc2 = NULL;
static uint32_t event_cnt;
static uint32_t event_cnt2;
static void dummy_event_cb(lv_event_t * e);
static void dummy_event_cb2(lv_event_t * e);
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
lv_obj_set_style_layout(active_screen, LV_LAYOUT_NONE, 0);
}
void test_arc_creation_successful(void)
{
arc = lv_arc_create(active_screen);
TEST_ASSERT_NOT_NULL(arc);
}
void test_arc_basic_render(void)
{
arc = lv_arc_create(active_screen);
lv_obj_set_size(arc, 100, 100);
lv_obj_center(arc);
lv_arc_set_value(arc, 70);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_1.png");
}
void test_arc_rgb565a8_image(void)
{
#if LV_BIN_DECODER_RAM_LOAD
/*RGB565A8 image rendering requires special handling*/
arc = lv_arc_create(active_screen);
lv_obj_set_size(arc, 100, 100);
lv_obj_center(arc);
lv_arc_set_value(arc, 70);
lv_obj_set_style_arc_width(arc, 30, 0);
lv_obj_set_style_arc_width(arc, 30, LV_PART_INDICATOR);
lv_obj_set_style_arc_image_src(arc, "A:src/test_files/binimages/cogwheel.RGB565A8.bin", LV_PART_INDICATOR);
lv_obj_set_style_arc_opa(arc, 150, LV_PART_INDICATOR);
lv_obj_set_style_bg_opa(arc, 0, LV_PART_KNOB);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_2.png");
#endif
}
void test_arc_should_truncate_to_max_range_when_new_value_exceeds_it(void)
{
/* Default max range is 100 */
int16_t value_after_truncation = 100;
arc = lv_arc_create(active_screen);
lv_arc_set_value(arc, 200);
TEST_ASSERT_EQUAL_INT16(value_after_truncation, lv_arc_get_value(arc));
}
void test_arc_should_truncate_to_min_range_when_new_value_is_inferior(void)
{
/* Default min range is 100 */
int16_t value_after_truncation = 0;
arc = lv_arc_create(active_screen);
lv_arc_set_value(arc, 0);
TEST_ASSERT_EQUAL_INT16(value_after_truncation, lv_arc_get_value(arc));
}
void test_arc_should_update_value_after_updating_range(void)
{
int16_t value_after_updating_max_range = 50;
int16_t value_after_updating_min_range = 30;
arc = lv_arc_create(active_screen);
lv_arc_set_value(arc, 80);
lv_arc_set_range(arc, 1, 50);
TEST_ASSERT_EQUAL_INT16(value_after_updating_max_range, lv_arc_get_value(arc));
lv_arc_set_value(arc, 10);
lv_arc_set_range(arc, 30, 50);
TEST_ASSERT_EQUAL_INT16(value_after_updating_min_range, lv_arc_get_value(arc));
}
void test_arc_should_update_angles_when_changing_to_symmetrical_mode(void)
{
int16_t expected_angle_start = 135;
int16_t expected_angle_end = 270;
/* start angle is 135, end angle is 45 at creation */
arc = lv_arc_create(active_screen);
lv_arc_set_mode(arc, LV_ARC_MODE_SYMMETRICAL);
TEST_ASSERT_EQUAL_INT16(expected_angle_start, lv_arc_get_angle_start(arc));
TEST_ASSERT_EQUAL_INT16(expected_angle_end, lv_arc_get_angle_end(arc));
}
void test_arc_should_update_angles_when_changing_to_symmetrical_mode_value_more_than_middle_range(void)
{
int16_t expected_angle_start = 270;
int16_t expected_angle_end = 45;
/* start angle is 135, end angle is 45 at creation */
arc = lv_arc_create(active_screen);
lv_arc_set_value(arc, 100);
lv_arc_set_mode(arc, LV_ARC_MODE_SYMMETRICAL);
TEST_ASSERT_EQUAL_INT16(expected_angle_start, lv_arc_get_angle_start(arc));
TEST_ASSERT_EQUAL_INT16(expected_angle_end, lv_arc_get_angle_end(arc));
}
/* See #2522 for more information */
void test_arc_angles_when_reversed(void)
{
uint16_t expected_start_angle = 54;
uint16_t expected_end_angle = 90;
int16_t expected_value = 40;
lv_obj_t * arcBlack;
arcBlack = lv_arc_create(lv_screen_active());
lv_arc_set_mode(arcBlack, LV_ARC_MODE_REVERSE);
lv_arc_set_bg_angles(arcBlack, 0, 90);
lv_arc_set_value(arcBlack, expected_value);
TEST_ASSERT_EQUAL_UINT16(expected_start_angle, lv_arc_get_angle_start(arcBlack));
TEST_ASSERT_EQUAL_UINT16(expected_end_angle, lv_arc_get_angle_end(arcBlack));
TEST_ASSERT_EQUAL_INT16(expected_value, lv_arc_get_value(arcBlack));
}
void test_arc_click_area_with_adv_hittest(void)
{
arc = lv_arc_create(lv_screen_active());
lv_obj_set_size(arc, 100, 100);
lv_obj_set_style_arc_width(arc, 10, 0);
lv_obj_add_flag(arc, LV_OBJ_FLAG_ADV_HITTEST);
lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
lv_obj_set_ext_click_area(arc, 5);
/*No click detected at the middle*/
event_cnt = 0;
lv_test_mouse_click_at(50, 50);
TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
/*No click close to the radius - bg_arc - ext_click_area*/
event_cnt = 0;
lv_test_mouse_click_at(83, 50);
TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
/*Click on the radius - bg_arc - ext_click_area*/
event_cnt = 0;
lv_test_mouse_click_at(86, 50);
TEST_ASSERT_GREATER_THAN(0, event_cnt);
/*Click on the radius + ext_click_area*/
event_cnt = 0;
lv_test_mouse_click_at(104, 50);
TEST_ASSERT_GREATER_THAN(0, event_cnt);
/*No click beyond to the radius + ext_click_area*/
event_cnt = 0;
lv_test_mouse_click_at(106, 50);
TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
}
/* Check value doesn't go to max when clicking on the other side of the arc */
void test_arc_click_sustained_from_start_to_end_does_not_set_value_to_max(void)
{
arc = lv_arc_create(lv_screen_active());
lv_arc_set_value(arc, 0);
lv_obj_set_size(arc, 100, 100);
lv_obj_center(arc);
lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
event_cnt = 0;
/* Click close to start angle */
event_cnt = 0;
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_move_to(376, 285);
lv_test_mouse_press();
lv_test_wait(500);
lv_test_mouse_release();
lv_test_wait(50);
TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
TEST_ASSERT_EQUAL_INT32(lv_arc_get_min_value(arc), lv_arc_get_value(arc));
/* Click close to end angle */
event_cnt = 0;
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_move_to(376, 285);
lv_test_mouse_press();
lv_test_wait(500);
lv_test_mouse_move_to(415, 281);
lv_test_wait(500);
lv_test_mouse_release();
lv_test_wait(50);
TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
TEST_ASSERT_EQUAL_INT32(lv_arc_get_min_value(arc), lv_arc_get_value(arc));
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_3.png");
}
void test_two_overlapping_arcs_can_be_interacted_independently(void)
{
arc = lv_arc_create(lv_screen_active());
arc2 = lv_arc_create(lv_screen_active());
lv_arc_set_value(arc, 0);
lv_arc_set_value(arc2, 0);
lv_obj_set_size(arc, 100, 100);
lv_obj_set_size(arc2, 100, 100);
lv_arc_set_bg_angles(arc, 20, 160);
lv_arc_set_bg_angles(arc2, 200, 340);
lv_obj_add_flag(arc, LV_OBJ_FLAG_ADV_HITTEST);
lv_obj_add_flag(arc2, LV_OBJ_FLAG_ADV_HITTEST);
lv_arc_set_value(arc, 10);
lv_arc_set_value(arc2, 10);
lv_arc_set_rotation(arc, 355);
lv_arc_set_rotation(arc2, 355);
lv_obj_center(arc);
lv_obj_center(arc2);
// Add event callback to both arcs
lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(arc2, dummy_event_cb2, LV_EVENT_PRESSED, NULL);
// Reset event counters
event_cnt = 0;
event_cnt2 = 0;
// Click on the position of the first arc (center)
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_move_to(400, 195);
lv_test_mouse_press();
lv_test_wait(500);
lv_test_mouse_release();
lv_test_wait(50);
// Verify that the event callback was called for the first arc
TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
TEST_ASSERT_EQUAL_UINT32(1, event_cnt2);
// click on the position of the second arc (center)
lv_test_mouse_release();
lv_test_wait(50);
lv_test_mouse_move_to(400, 285);
lv_test_mouse_press();
lv_test_wait(500);
lv_test_mouse_release();
lv_test_wait(50);
// Verify that the event callback was called for the second arc
TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
TEST_ASSERT_EQUAL_UINT32(1, event_cnt2);
// Verify that the screen remains as expected after the interactions
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/overlapping_arcs_test.png");
}
static void dummy_event_cb(lv_event_t * e)
{
LV_UNUSED(e);
event_cnt++;
}
static void dummy_event_cb2(lv_event_t * e)
{
LV_UNUSED(e);
event_cnt2++;
}
#endif
@@ -0,0 +1,573 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * g_active_screen = NULL;
static lv_obj_t * g_bar = NULL;
void setUp(void)
{
g_active_screen = lv_screen_active();
g_bar = lv_bar_create(g_active_screen);
}
void tearDown(void)
{
lv_obj_clean(g_active_screen);
}
void test_bar_should_have_valid_default_attributes(void)
{
TEST_ASSERT_EQUAL(0, lv_bar_get_min_value(g_bar));
TEST_ASSERT_EQUAL(100, lv_bar_get_max_value(g_bar));
TEST_ASSERT_EQUAL(LV_BAR_MODE_NORMAL, lv_bar_get_mode(g_bar));
}
/*
* Bar has two parts, main and indicator, coordinates of the latter are
* calculated based on:
* - Bar size
* - Bar (main part) padding
* - Bar value
* - Bar coordinates
* - Bar base direction
* See Boxing model in docs for reference.
*
* Bar properties assumed:
* - mode: LV_BAR_MODE_NORMAL
* - min value: 0
* - max value: 100
* - base direction: LTR
*/
void test_bar_should_update_indicator_right_coordinate_based_on_bar_value(void)
{
lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
static lv_style_t bar_style;
const int32_t style_padding = 5u;
const int32_t bar_width = 200u;
const int32_t bar_height = 20u;
int32_t bar_value = 10u;
lv_style_init(&bar_style);
lv_style_set_pad_all(&bar_style, style_padding);
/* Setup new style */
lv_obj_remove_style_all(g_bar);
lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
/* Set properties */
lv_obj_set_size(g_bar, bar_width, bar_height);
lv_bar_set_value(g_bar, bar_value, LV_ANIM_OFF);
/* FIXME: Remove wait */
lv_test_wait(50);
int32_t actual_coord = lv_area_get_width(&bar_ptr->indic_area);
/* Calculate bar indicator right coordinate, using rule of 3 */
int32_t bar_max_value = lv_bar_get_max_value(g_bar);
int32_t indicator_part_width = lv_obj_get_content_width(g_bar);
int32_t expected_coord = (bar_value * indicator_part_width) / bar_max_value;
TEST_ASSERT_EQUAL_INT32(expected_coord, actual_coord);
}
/*
* Bar has two parts, main and indicator, coordinates of the latter are
* calculated based on:
* - Bar size
* - Bar (main part) padding
* - Bar value
* - Bar coordinates
* - Bar base direction
* See Boxing model in docs for reference.
*
* Bar properties assumed:
* - mode: LV_BAR_MODE_NORMAL
* - min value: 0
* - max value: 100
*/
void test_bar_rtl_should_update_indicator_left_coordinate_based_on_bar_value(void)
{
lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
static lv_style_t bar_style;
const int32_t style_padding = 5u;
const int32_t bar_width = 200u;
const int32_t bar_height = 20u;
int32_t bar_value = 10u;
lv_style_init(&bar_style);
lv_style_set_pad_all(&bar_style, style_padding);
/* Setup new style */
lv_obj_remove_style_all(g_bar);
lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
/* Set properties */
lv_obj_set_size(g_bar, bar_width, bar_height);
lv_bar_set_value(g_bar, bar_value, LV_ANIM_OFF);
lv_obj_set_style_base_dir(g_bar, LV_BASE_DIR_RTL, 0);
/* FIXME: Remove wait */
lv_test_wait(50);
int32_t actual_coord = bar_ptr->indic_area.x1;
/* Calculate current indicator width */
int32_t bar_max_value = lv_bar_get_max_value(g_bar);
int32_t indicator_part_width = lv_obj_get_content_width(g_bar);
int32_t right_padding = lv_obj_get_style_pad_right(g_bar, LV_PART_MAIN);
int32_t indicator_width = (bar_value * indicator_part_width) / bar_max_value;
int32_t expected_coord = (bar_width - right_padding) - indicator_width;
TEST_ASSERT_EQUAL_INT32(expected_coord, actual_coord);
}
void test_bar_normal(void)
{
int32_t w = 300;
int32_t h = 40;
int32_t h_gap = 20;
int32_t w_gap = 20;
int32_t y = h_gap;
int32_t x = w_gap;
lv_color_t bg_color = lv_color_black();
lv_color_t indic_color = lv_color_hex(0x0000FF);
lv_obj_t * screen = lv_obj_create(lv_screen_active());
lv_obj_remove_style_all(screen);
lv_obj_set_size(screen, 800, 480);
lv_obj_center(screen);
lv_obj_set_style_bg_color(screen, lv_color_white(), 0);
lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
lv_obj_set_style_pad_all(screen, 0, 0);
lv_obj_t * test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
y += h + h_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
lv_obj_set_style_base_dir(test_bar, LV_BASE_DIR_RTL, 0);
y += h + h_gap;
x = 150;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
x += h + w_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 100, 0);
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/bar_1.png");
}
/**
* Same as test_bar_normal, but with min and max values set.
*/
void test_bar_normal_empty_and_full(void)
{
int32_t w = 300;
int32_t h = 40;
int32_t h_gap = 20;
int32_t w_gap = 20;
int32_t y = h_gap;
int32_t x = w_gap;
lv_color_t bg_color = lv_color_black();
lv_color_t indic_color = lv_color_hex(0x0000FF);
lv_obj_t * screen = lv_obj_create(lv_screen_active());
lv_obj_remove_style_all(screen);
lv_obj_set_size(screen, 800, 480);
lv_obj_center(screen);
lv_obj_set_style_bg_color(screen, lv_color_white(), 0);
lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
lv_obj_set_style_pad_all(screen, 0, 0);
lv_obj_t * test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 0, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
y += h + h_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 0, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
lv_obj_set_style_base_dir(test_bar, LV_BASE_DIR_RTL, 0);
y += h + h_gap;
x = 150;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 0, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
x += h + w_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 100, 0);
lv_bar_set_value(test_bar, 0, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
y = h_gap;
x = w_gap + 400;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 100, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
y += h + h_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 100, LV_ANIM_OFF);
lv_obj_set_size(test_bar, w, h);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
lv_obj_set_style_base_dir(test_bar, LV_BASE_DIR_RTL, 0);
y += h + h_gap;
x += 150;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 0, 100);
lv_bar_set_value(test_bar, 100, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
x += h + w_gap;
test_bar = lv_bar_create(screen);
lv_obj_set_style_radius(test_bar, 100, 0);
lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
lv_bar_set_range(test_bar, 100, 0);
lv_bar_set_value(test_bar, 100, LV_ANIM_OFF);
lv_obj_set_size(test_bar, h, w);
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/bar_3.png");
}
void test_bar_indicator_area_should_get_smaller_when_padding_is_increased(void)
{
lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
const int32_t style_padding = 10u;
static lv_style_t bar_style;
int32_t new_height = 0u;
int32_t new_width = 0u;
int32_t original_height = 0u;
int32_t original_width = 0u;
lv_bar_set_value(g_bar, 50, LV_ANIM_OFF);
lv_test_wait(50);
original_width = lv_area_get_width(&bar_ptr->indic_area);
original_height = lv_area_get_height(&bar_ptr->indic_area);
/* Setup new padding */
lv_style_init(&bar_style);
lv_style_set_pad_all(&bar_style, style_padding);
lv_obj_set_size(g_bar, 100, 50);
/* Apply new style */
lv_obj_remove_style_all(g_bar);
lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
/* Notify LVGL of style change */
lv_obj_report_style_change(&bar_style);
lv_test_wait(50);
new_height = lv_area_get_height(&bar_ptr->indic_area);
new_width = lv_area_get_width(&bar_ptr->indic_area);
TEST_ASSERT_LESS_THAN_INT32(original_height, new_height);
TEST_ASSERT_LESS_THAN_INT32(original_width, new_width);
}
void test_bar_start_value_should_only_change_when_in_range_mode(void)
{
int32_t new_start_value = 20u;
lv_bar_set_value(g_bar, 90, LV_ANIM_OFF);
lv_bar_set_start_value(g_bar, new_start_value, LV_ANIM_OFF);
/* Start value shouldn't be updated when not in RANGE mode */
TEST_ASSERT_EQUAL_INT32(0u, lv_bar_get_start_value(g_bar));
/* Set bar in RANGE mode so we can edit the start value */
lv_bar_set_mode(g_bar, LV_BAR_MODE_RANGE);
lv_bar_set_start_value(g_bar, new_start_value, LV_ANIM_OFF);
TEST_ASSERT_EQUAL_INT32(new_start_value, lv_bar_get_start_value(g_bar));
}
void test_bar_start_value_should_be_smaller_than_current_value_in_range_mode(void)
{
/* Set bar in RANGE mode so we can edit the start value */
lv_bar_set_mode(g_bar, LV_BAR_MODE_RANGE);
lv_bar_set_value(g_bar, 50, LV_ANIM_OFF);
lv_bar_set_start_value(g_bar, 100u, LV_ANIM_OFF);
TEST_ASSERT_EQUAL_INT32(lv_bar_get_value(g_bar), lv_bar_get_start_value(g_bar));
}
void test_bar_current_value_should_be_truncated_to_max_value_when_exceeds_it(void)
{
int32_t max_value = lv_bar_get_max_value(g_bar);
int32_t new_value = max_value + 1u;
lv_bar_set_value(g_bar, new_value, LV_ANIM_OFF);
TEST_ASSERT_EQUAL_INT32(max_value, lv_bar_get_value(g_bar));
}
void test_bar_current_value_should_be_truncated_to_min_value_when_it_is_below_it(void)
{
int32_t min_value = lv_bar_get_min_value(g_bar);
int32_t new_value = min_value - 1u;
lv_bar_set_value(g_bar, new_value, LV_ANIM_OFF);
TEST_ASSERT_EQUAL_INT32(min_value, lv_bar_get_value(g_bar));
}
/** When in symmetrical mode, the bar indicator has to be drawn towards the min
* range value. Requires a negative min range value and a positive max range
* value.
*
* Bar properties assumed:
* - base direction: LTR
*/
void test_bar_indicator_should_be_drawn_towards_the_min_range_side_after_setting_a_more_negative_value(void)
{
lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
/* Setup bar properties */
lv_obj_set_size(g_bar, 100, 50);
lv_bar_set_mode(g_bar, LV_BAR_MODE_SYMMETRICAL);
lv_bar_set_range(g_bar, -100, 100);
/* Set bar value to 1, so it gets drawn at the middle of the bar */
lv_bar_set_value(g_bar, 1, LV_ANIM_OFF);
lv_test_wait(50);
int32_t original_pos = bar_ptr->indic_area.x1;
/* Set bar to a more negative value */
lv_bar_set_value(g_bar, -50, LV_ANIM_OFF);
lv_test_wait(50);
int32_t final_pos = bar_ptr->indic_area.x1;
TEST_ASSERT_LESS_THAN(original_pos, final_pos);
}
static lv_obj_t * styled_bar_create(bool ver, int32_t start_value, int32_t end_value, lv_grad_dir_t grad_dir,
int32_t bg_radius, int32_t indic_radius, int32_t bg_pad)
{
lv_obj_t * bar = lv_bar_create(lv_screen_active());
if(ver) lv_obj_set_size(bar, 20, 100);
else lv_obj_set_size(bar, 100, 20);
lv_bar_set_range(bar, 0, 100);
lv_bar_set_mode(bar, LV_BAR_MODE_RANGE);
lv_bar_set_value(bar, end_value, LV_ANIM_OFF);
lv_bar_set_start_value(bar, start_value, LV_ANIM_OFF);
lv_obj_set_style_bg_opa(bar, 255, LV_PART_MAIN);
lv_obj_set_style_bg_color(bar, lv_color_hex3(0x0ff), LV_PART_MAIN);
lv_obj_set_style_radius(bar, bg_radius, LV_PART_MAIN);
lv_obj_set_style_pad_all(bar, bg_pad, LV_PART_MAIN);
lv_obj_set_style_bg_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
lv_obj_set_style_bg_color(bar, lv_color_hex3(0xf0f), LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_color(bar, lv_color_hex3(0x8f8), LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_dir(bar, grad_dir, LV_PART_INDICATOR);
lv_obj_set_style_border_width(bar, 2, LV_PART_INDICATOR);
lv_obj_set_style_border_color(bar, lv_color_hex3(0x0f0), LV_PART_INDICATOR);
lv_obj_set_style_border_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
lv_obj_set_style_outline_width(bar, 2, LV_PART_INDICATOR);
lv_obj_set_style_outline_pad(bar, 4, LV_PART_INDICATOR);
lv_obj_set_style_outline_color(bar, lv_color_hex3(0xff0), LV_PART_INDICATOR);
lv_obj_set_style_outline_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
lv_obj_set_style_shadow_width(bar, 20, LV_PART_INDICATOR);
lv_obj_set_style_shadow_spread(bar, 5, LV_PART_INDICATOR);
lv_obj_set_style_shadow_color(bar, lv_color_hex3(0xf00), LV_PART_INDICATOR);
lv_obj_set_style_shadow_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
lv_obj_set_style_radius(bar, indic_radius, LV_PART_INDICATOR);
return bar;
}
static void render_test_screen_create(bool ver, lv_grad_dir_t grad_dir, const char * ref_img_path)
{
lv_obj_t * active_screen = lv_screen_active();
lv_obj_clean(active_screen);
lv_obj_set_flex_flow(active_screen, ver ? LV_FLEX_FLOW_ROW_WRAP : LV_FLEX_FLOW_COLUMN_WRAP);
lv_obj_set_flex_align(active_screen, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_set_style_pad_row(active_screen, 17, 0);
lv_obj_set_style_pad_column(active_screen, 12, 0);
lv_obj_set_style_pad_all(active_screen, 15, 0);
int32_t bar_values[6][2] = {{0, 5}, {0, 50}, {0, 95}, {5, 100}, {95, 100}, {20, 90}};
int32_t bg_radius[2] = {0, 15};
int32_t indic_radius[2] = {0, 15};
int32_t bg_pad[3] = {-5, 0, 5};
uint32_t pad;
for(pad = 0; pad < 3; pad++) {
uint32_t indic_r;
for(indic_r = 0; indic_r < 2; indic_r++) {
uint32_t bg_r;
for(bg_r = 0; bg_r < 2; bg_r++) {
uint32_t v;
for(v = 0; v < 6; v++) {
styled_bar_create(ver, bar_values[v][0], bar_values[v][1], grad_dir, bg_radius[bg_r], indic_radius[indic_r],
bg_pad[pad]);
}
}
}
}
TEST_ASSERT_EQUAL_SCREENSHOT(ref_img_path);
}
void test_bar_render_corner(void)
{
render_test_screen_create(false, LV_GRAD_DIR_NONE, "widgets/bar_corner_1.png");
render_test_screen_create(false, LV_GRAD_DIR_HOR, "widgets/bar_corner_2.png");
render_test_screen_create(false, LV_GRAD_DIR_VER, "widgets/bar_corner_3.png");
render_test_screen_create(true, LV_GRAD_DIR_NONE, "widgets/bar_corner_4.png");
render_test_screen_create(true, LV_GRAD_DIR_HOR, "widgets/bar_corner_5.png");
render_test_screen_create(true, LV_GRAD_DIR_VER, "widgets/bar_corner_6.png");
}
static lv_obj_t * bar_create_orientation(lv_bar_orientation_t orientation, int32_t w, int32_t h)
{
lv_obj_t * bar = lv_bar_create(g_active_screen);
lv_bar_set_orientation(bar, orientation);
lv_obj_set_size(bar, w, h);
lv_bar_set_value(bar, 30, LV_ANIM_OFF);
return bar;
}
void test_bar_orientation(void)
{
lv_obj_clean(g_active_screen);
lv_obj_set_flex_flow(g_active_screen, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_t * label;
label = lv_label_create(g_active_screen);
lv_label_set_text(label, "Auto");
lv_obj_set_width(label, lv_pct(100));
bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 100, 20);
bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 20, 100);
bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 100, 100);
label = lv_label_create(g_active_screen);
lv_label_set_text(label, "Vertical");
lv_obj_set_width(label, lv_pct(100));
bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 100, 20);
bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 20, 100);
bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 100, 100);
label = lv_label_create(g_active_screen);
lv_label_set_text(label, "Horizontal");
lv_obj_set_width(label, lv_pct(100));
bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 100, 20);
bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 20, 100);
bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 100, 100);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/bar_2.png");
}
#endif
@@ -0,0 +1,29 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_button_creation(void)
{
lv_obj_t * btn;
btn = lv_button_create(active_screen);
TEST_ASSERT_NOT_NULL(btn);
/* These flags are set in the object's constructor. */
TEST_ASSERT_TRUE(lv_obj_has_flag(btn, LV_OBJ_FLAG_SCROLL_ON_FOCUS));
TEST_ASSERT_FALSE(lv_obj_has_flag(btn, LV_OBJ_FLAG_SCROLLABLE));
}
#endif
@@ -0,0 +1,459 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
static lv_obj_t * btnm;
static bool event_triggered = false;
lv_event_code_t exp_evt_code;
void setUp(void)
{
active_screen = lv_screen_active();
btnm = lv_buttonmatrix_create(active_screen);
TEST_ASSERT_NOT_NULL(btnm);
event_triggered = false;
exp_evt_code = 0;
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_button_matrix_creation(void)
{
const char * const * map;
/* Verify the default map. */
map = lv_buttonmatrix_get_map(btnm);
TEST_ASSERT_EQUAL_STRING(map[0], "Btn1");
TEST_ASSERT_EQUAL_STRING(map[1], "Btn2");
TEST_ASSERT_EQUAL_STRING(map[2], "Btn3");
TEST_ASSERT_EQUAL_STRING(map[3], "\n");
TEST_ASSERT_EQUAL_STRING(map[4], "Btn4");
TEST_ASSERT_EQUAL_STRING(map[5], "Btn5");
}
void test_button_matrix_set_map_works(void)
{
const char * const * ret_map;
static const char * exp_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, exp_map);
/* Verify if the map was set correctly. */
ret_map = lv_buttonmatrix_get_map(btnm);
TEST_ASSERT_EQUAL_STRING(exp_map[0], ret_map[0]);
TEST_ASSERT_EQUAL_STRING(exp_map[1], ret_map[1]);
TEST_ASSERT_EQUAL_STRING(exp_map[2], ret_map[2]);
TEST_ASSERT_EQUAL_STRING(exp_map[3], ret_map[3]);
TEST_ASSERT_EQUAL_STRING(exp_map[4], ret_map[4]);
TEST_ASSERT_EQUAL_STRING(exp_map[5], ret_map[5]);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/btnm_1.png");
}
void test_button_matrix_render_2(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_set_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_obj_set_pos(btnm, 10, 10);
static const char * btn_map2[] = {"A", "\n", "B", "\n", "C", "\n", "D", ""};
btnm = lv_buttonmatrix_create(active_screen);
TEST_ASSERT_NOT_NULL(btnm);
lv_obj_set_width(btnm, 150);
lv_obj_set_height(btnm, 250);
lv_buttonmatrix_set_map(btnm, btn_map2);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_set_one_checked(btnm, true);
lv_buttonmatrix_set_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_obj_set_pos(btnm, 10, 160);
static const char * btn_map3[] = {"A", "B", "C", "\n", "D", "E", "F", ""};
btnm = lv_buttonmatrix_create(active_screen);
TEST_ASSERT_NOT_NULL(btnm);
lv_buttonmatrix_set_map(btnm, btn_map3);
lv_obj_set_width(btnm, 400);
lv_buttonmatrix_set_button_width(btnm, 0, 3);
lv_buttonmatrix_set_button_width(btnm, 1, 2);
lv_buttonmatrix_set_button_width(btnm, 2, 1);
lv_buttonmatrix_set_button_width(btnm, 3, 1);
lv_buttonmatrix_set_button_width(btnm, 4, 2);
lv_buttonmatrix_set_button_width(btnm, 5, 3);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_set_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 4, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_obj_set_pos(btnm, 300, 10);
static const char * btn_map4[] = {"A", "B", "C", "D", "E", "F", "G", "\n",
"G", "F", "E", "D", "C", "B", "A", ""
};
btnm = lv_buttonmatrix_create(active_screen);
lv_buttonmatrix_set_map(btnm, btn_map4);
lv_obj_set_width(btnm, 600);
lv_obj_set_height(btnm, 150);
lv_buttonmatrix_set_button_width(btnm, 0, 1);
lv_buttonmatrix_set_button_width(btnm, 1, 2);
lv_buttonmatrix_set_button_width(btnm, 2, 3);
lv_buttonmatrix_set_button_width(btnm, 3, 4);
lv_buttonmatrix_set_button_width(btnm, 4, 5);
lv_buttonmatrix_set_button_width(btnm, 5, 6);
lv_buttonmatrix_set_button_width(btnm, 6, 7);
lv_buttonmatrix_set_button_width(btnm, 7, 7);
lv_buttonmatrix_set_button_width(btnm, 8, 6);
lv_buttonmatrix_set_button_width(btnm, 9, 5);
lv_buttonmatrix_set_button_width(btnm, 10, 4);
lv_buttonmatrix_set_button_width(btnm, 11, 3);
lv_buttonmatrix_set_button_width(btnm, 12, 2);
lv_buttonmatrix_set_button_width(btnm, 13, 1);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_set_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 5, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 7, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 9, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 11, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_obj_set_pos(btnm, 180, 160);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/btnm_2.png");
}
void test_button_matrix_set_ctrl_map_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_ctrl_t ctrl_map[4];
ctrl_map[0] = 1 | LV_BUTTONMATRIX_CTRL_DISABLED;
ctrl_map[1] = 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE | LV_BUTTONMATRIX_CTRL_CHECKED;
ctrl_map[2] = 1 | LV_BUTTONMATRIX_CTRL_HIDDEN;
ctrl_map[3] = 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE;
lv_buttonmatrix_set_ctrl_map(btnm, ctrl_map);
/* Verify if the ctrl map was set correctly. */
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_DISABLED));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 1,
LV_BUTTONMATRIX_CTRL_CHECKABLE | LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKABLE));
/* Also checking randomly that no other flags are set. */
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_CHECKABLE));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_DISABLED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 4, LV_BUTTONMATRIX_CTRL_HIDDEN));
}
void test_button_matrix_set_button_ctrl_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
/* Set btn control map using individual APIs. */
lv_buttonmatrix_set_button_ctrl(btnm, 0, 1 | LV_BUTTONMATRIX_CTRL_DISABLED);
lv_buttonmatrix_set_button_ctrl(btnm, 1, 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE | LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 2, 1 | LV_BUTTONMATRIX_CTRL_HIDDEN);
lv_buttonmatrix_set_button_ctrl(btnm, 3, 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE);
/* Verify if the ctrl map was set correctly. */
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_DISABLED));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 1,
LV_BUTTONMATRIX_CTRL_CHECKABLE | LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKABLE));
/* Also checking randomly that no other flags are set. */
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_CHECKABLE));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_DISABLED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 4, LV_BUTTONMATRIX_CTRL_HIDDEN));
}
void test_button_matrix_clear_button_ctrl_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
/* Set btn control map using individual APIs. */
lv_buttonmatrix_set_button_ctrl(btnm, 0, 1 | LV_BUTTONMATRIX_CTRL_DISABLED);
lv_buttonmatrix_set_button_ctrl(btnm, 1, 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE | LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 2, 1 | LV_BUTTONMATRIX_CTRL_HIDDEN);
lv_buttonmatrix_set_button_ctrl(btnm, 3, 1 | LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_clear_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_DISABLED);
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_DISABLED));
lv_buttonmatrix_clear_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED);
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED));
lv_buttonmatrix_clear_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN);
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN));
lv_buttonmatrix_clear_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKABLE);
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKABLE));
}
void test_button_matrix_set_selected_button_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_selected_button(btnm, 2);
TEST_ASSERT_EQUAL_UINT16(2, lv_buttonmatrix_get_selected_button(btnm));
lv_buttonmatrix_set_selected_button(btnm, 0);
TEST_ASSERT_EQUAL_UINT16(0, lv_buttonmatrix_get_selected_button(btnm));
lv_buttonmatrix_set_selected_button(btnm, 3);
TEST_ASSERT_EQUAL_UINT16(3, lv_buttonmatrix_get_selected_button(btnm));
lv_buttonmatrix_set_selected_button(btnm, 1);
TEST_ASSERT_EQUAL_UINT16(1, lv_buttonmatrix_get_selected_button(btnm));
}
void test_button_matrix_set_button_ctrl_all_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_HIDDEN);
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_HIDDEN));
}
void test_button_matrix_clear_button_ctrl_all_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_HIDDEN);
lv_buttonmatrix_clear_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_HIDDEN);
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_HIDDEN));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_HIDDEN));
}
void test_button_matrix_set_button_width_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_width(btnm, 1, 3);
lv_buttonmatrix_set_button_width(btnm, 2, 2);
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 1, 3));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 2, 2));
}
void test_button_matrix_set_one_checked_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_buttonmatrix_set_one_checked(btnm, true);
lv_buttonmatrix_set_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_CHECKED);
lv_buttonmatrix_set_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED);
TEST_ASSERT_TRUE(lv_buttonmatrix_get_one_checked(btnm));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 1, LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_FALSE(lv_buttonmatrix_has_button_ctrl(btnm, 2, LV_BUTTONMATRIX_CTRL_CHECKED));
TEST_ASSERT_TRUE(lv_buttonmatrix_has_button_ctrl(btnm, 3, LV_BUTTONMATRIX_CTRL_CHECKED));
}
void test_button_matrix_get_button_text_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
TEST_ASSERT_EQUAL_STRING("A", lv_buttonmatrix_get_button_text(btnm, 0));
TEST_ASSERT_EQUAL_STRING("B", lv_buttonmatrix_get_button_text(btnm, 1));
TEST_ASSERT_EQUAL_STRING("C", lv_buttonmatrix_get_button_text(btnm, 2));
TEST_ASSERT_EQUAL_STRING("D", lv_buttonmatrix_get_button_text(btnm, 3));
}
/* Common event handler for all the consecutive test cases. */
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
if(code == exp_evt_code) {
event_triggered = true;
}
}
void test_button_matrix_pressed_event_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_PRESSED, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_PRESSED;
/* Click button index 0. */
lv_test_mouse_click_at(10, 10);
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_release_event_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_RELEASED, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_RELEASED;
/* Click button index 0. */
lv_test_mouse_click_at(65, 35);
TEST_ASSERT_TRUE(event_triggered);
event_triggered = false;
/* This will increase test coverage by unchecking the
same button. */
lv_buttonmatrix_set_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_POPOVER);
/* Click button index 0. */
lv_test_mouse_click_at(65, 35);
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_key_event_works(void)
{
uint32_t keyCode;
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_update_layout(btnm); /*The force calculating the button areas*/
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_KEY, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_KEY;
lv_buttonmatrix_t * btnmObj = (lv_buttonmatrix_t *)btnm;
/* Select the first button. */
lv_buttonmatrix_set_selected_button(btnm, 0);
keyCode = LV_KEY_RIGHT;
lv_obj_send_event(btnm, LV_EVENT_KEY, &keyCode);
TEST_ASSERT_TRUE(event_triggered);
uint16_t btnId = lv_buttonmatrix_get_selected_button(btnm);
TEST_ASSERT_EQUAL_INT(1, btnId);
event_triggered = false;
keyCode = LV_KEY_LEFT;
lv_obj_send_event(btnm, LV_EVENT_KEY, &keyCode);
TEST_ASSERT_TRUE(event_triggered);
btnId = lv_buttonmatrix_get_selected_button(btnm);
TEST_ASSERT_EQUAL_INT(0, btnId);
event_triggered = false;
keyCode = LV_KEY_DOWN;
lv_obj_send_event(btnm, LV_EVENT_KEY, &keyCode);
TEST_ASSERT_TRUE(event_triggered);
btnId = lv_buttonmatrix_get_selected_button(btnm);
TEST_ASSERT_EQUAL_INT(2, btnId);
event_triggered = false;
keyCode = LV_KEY_UP;
lv_obj_send_event(btnm, LV_EVENT_KEY, &keyCode);
TEST_ASSERT_TRUE(event_triggered);
btnId = lv_buttonmatrix_get_selected_button(btnm);
TEST_ASSERT_EQUAL_INT(0, btnId);
/* Added this code to increase code coverage. */
btnmObj->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE;
lv_buttonmatrix_set_button_ctrl(btnm, 0, LV_BUTTONMATRIX_CTRL_HIDDEN);
keyCode = LV_KEY_DOWN;
lv_obj_send_event(btnm, LV_EVENT_KEY, &keyCode);
TEST_ASSERT_TRUE(event_triggered);
event_triggered = false;
}
void test_button_matrix_pressing_event_works(void)
{
lv_buttonmatrix_t * btnmObj = (lv_buttonmatrix_t *)btnm;
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_PRESSING, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_PRESSING;
/* Select a button before raising a simulated event.
* This is done to increase code coverage. */
btnmObj->btn_id_sel = 3;
/* Send a dummy lv_indev_t object as param to avoid crashing during build. */
lv_obj_send_event(btnm, LV_EVENT_PRESSING, lv_test_indev_get_indev(LV_INDEV_TYPE_POINTER));
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_long_press_repeat_event_works(void)
{
lv_buttonmatrix_t * btnmObj = (lv_buttonmatrix_t *)btnm;
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_LONG_PRESSED_REPEAT;
/* Select a button before raising a simulated event.
* This is done to increase code coverage. */
btnmObj->btn_id_sel = 0;
lv_obj_send_event(btnm, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_press_lost_event_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_PRESS_LOST, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_PRESS_LOST;
lv_obj_send_event(btnm, LV_EVENT_PRESS_LOST, NULL);
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_defocused_event_works(void)
{
lv_buttonmatrix_t * btnmObj = (lv_buttonmatrix_t *)btnm;
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_DEFOCUSED, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_DEFOCUSED;
/* Select a button before raising a simulated event.
* This is done to increase code coverage. */
btnmObj->btn_id_sel = 0;
lv_obj_send_event(btnm, LV_EVENT_DEFOCUSED, NULL);
TEST_ASSERT_TRUE(event_triggered);
}
void test_button_matrix_focused_event_works(void)
{
static const char * btn_map[] = {"A", "B", "\n", "C", "D", ""};
lv_buttonmatrix_set_map(btnm, btn_map);
lv_buttonmatrix_set_button_ctrl_all(btnm, LV_BUTTONMATRIX_CTRL_CHECKABLE);
lv_obj_add_event_cb(btnm, event_handler, LV_EVENT_FOCUSED, NULL);
/* Set expected event code before the event is raised. */
exp_evt_code = LV_EVENT_FOCUSED;
lv_obj_send_event(btnm, LV_EVENT_FOCUSED, NULL);
TEST_ASSERT_TRUE(event_triggered);
}
#endif
@@ -0,0 +1,258 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
/* This function runs before each test */
void setUp(void);
/* This function runs after every test */
void tearDown(void);
void test_calendar_creation_successful(void);
void test_calendar_set_today_date(void);
void test_calendar_set_today_date_gui(void);
void test_calendar_set_showed_date_gui(void);
void test_calendar_set_highlighted_dates(void);
void test_calendar_set_highlighted_dates_gui(void);
void test_calendar_set_day_names_gui(void);
void test_calendar_get_highlighted_dates_num(void);
void test_calendar_header_dropdown_create_gui(void);
void test_calendar_header_arrow_create_gui(void);
void test_calendar_event_key_down_gui(void);
void test_calendar_get_pressed_date_null(void);
void test_calendar_get_btnmatrix(void);
static lv_obj_t * g_active_screen = NULL;
static lv_obj_t * g_calendar = NULL;
void setUp(void)
{
g_active_screen = lv_screen_active();
g_calendar = lv_calendar_create(g_active_screen);
}
void tearDown(void)
{
lv_obj_clean(g_active_screen);
}
void test_calendar_creation_successful(void)
{
TEST_ASSERT_NOT_NULL(g_calendar);
}
void test_calendar_set_today_date(void)
{
/* Work with 2022-09-21 as today (start of spring in Southern hemisphere) */
lv_calendar_date_t today;
today.year = 2022;
today.month = 9;
today.day = 21;
lv_calendar_set_today_date(g_calendar, today.year, today.month, today.day);
const lv_calendar_date_t * date_after_test = lv_calendar_get_today_date(g_calendar);
TEST_ASSERT_EQUAL_INT16(today.year, date_after_test->year);
TEST_ASSERT_EQUAL_INT16(today.month, date_after_test->month);
TEST_ASSERT_EQUAL_INT16(today.day, date_after_test->day);
}
void test_calendar_set_today_date_gui(void)
{
/* Work with 2022-09-21 as today (start of spring in Southern hemisphere) */
lv_calendar_date_t today;
today.year = 2022;
today.month = 9;
today.day = 21;
lv_calendar_set_today_date(g_calendar, today.year, today.month, today.day);
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_01.png");
}
void test_calendar_set_showed_date_gui(void)
{
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_02.png");
}
void test_calendar_set_highlighted_dates(void)
{
/*Highlight a few days*/
static lv_calendar_date_t highlighted_days[3]; /*Only its pointer will be saved so should be static*/
highlighted_days[0].year = 2022;
highlighted_days[0].month = 2;
highlighted_days[0].day = 6;
highlighted_days[1].year = 2022;
highlighted_days[1].month = 2;
highlighted_days[1].day = 11;
highlighted_days[2].year = 2022;
highlighted_days[2].month = 2;
highlighted_days[2].day = 22;
lv_calendar_set_highlighted_dates(g_calendar, highlighted_days, 3);
const lv_calendar_date_t * highlighted_days_after_test = lv_calendar_get_highlighted_dates(g_calendar);
for(int i = 0; i < 3; i++) {
TEST_ASSERT_EQUAL_INT16(highlighted_days[i].year, highlighted_days_after_test[i].year);
TEST_ASSERT_EQUAL_INT16(highlighted_days[i].month, highlighted_days_after_test[i].month);
TEST_ASSERT_EQUAL_INT16(highlighted_days[i].day, highlighted_days_after_test[i].day);
}
}
void test_calendar_set_highlighted_dates_gui(void)
{
/*Highlight a few days*/
static lv_calendar_date_t highlighted_days[3]; /*Only its pointer will be saved so should be static*/
highlighted_days[0].year = 2022;
highlighted_days[0].month = 2;
highlighted_days[0].day = 6;
highlighted_days[1].year = 2022;
highlighted_days[1].month = 2;
highlighted_days[1].day = 11;
highlighted_days[2].year = 2022;
highlighted_days[2].month = 2;
highlighted_days[2].day = 22;
lv_calendar_set_highlighted_dates(g_calendar, highlighted_days, 3);
lv_calendar_set_month_shown(g_calendar, 2022, 2);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_03.png");
}
void test_calendar_set_day_names_gui(void)
{
static const char * day_names[7] = {"Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"};
lv_calendar_set_day_names(g_calendar, day_names);
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_04.png");
}
void test_calendar_get_highlighted_dates_num(void)
{
/*Highlight a few days*/
static lv_calendar_date_t highlighted_days[3]; /*Only its pointer will be saved so should be static*/
highlighted_days[0].year = 2022;
highlighted_days[0].month = 2;
highlighted_days[0].day = 6;
highlighted_days[1].year = 2022;
highlighted_days[1].month = 2;
highlighted_days[1].day = 11;
highlighted_days[2].year = 2022;
highlighted_days[2].month = 2;
highlighted_days[2].day = 22;
lv_calendar_set_highlighted_dates(g_calendar, highlighted_days, 3);
TEST_ASSERT_EQUAL_INT16(3, lv_calendar_get_highlighted_dates_num(g_calendar));
}
void test_calendar_header_dropdown_create_gui(void)
{
lv_calendar_add_header_dropdown(g_calendar);
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_05.png");
}
void test_calendar_header_dropdown_ascending_year_order(void)
{
const char * years = "2020\n2021\n2022\n2023\n2024\n";
lv_calendar_header_dropdown_create(g_calendar);
lv_calendar_header_dropdown_set_year_list(g_calendar, years);
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_05.png");
}
void test_calendar_header_dropdown_descending_year_order(void)
{
const char * years = "2024\n2023\n2022\n2021\n2020\n";
lv_calendar_header_dropdown_create(g_calendar);
lv_calendar_header_dropdown_set_year_list(g_calendar, years);
lv_calendar_set_month_shown(g_calendar, 2022, 9);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_05.png");
}
void test_calendar_header_arrow_create_gui(void)
{
lv_calendar_add_header_arrow(g_calendar);
lv_calendar_set_month_shown(g_calendar, 2022, 10); // Use October to avoid month name sliding
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_06.png");
}
void test_calendar_event_key_down_gui(void)
{
uint32_t key = LV_KEY_DOWN;
lv_calendar_set_month_shown(g_calendar, 2022, 9);
lv_obj_send_event(g_calendar, LV_EVENT_KEY, (void *) &key);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_07.png");
}
void test_calendar_get_pressed_date_null(void)
{
lv_calendar_set_month_shown(g_calendar, 2022, 9);
lv_calendar_date_t pressed_date;
lv_result_t result = lv_calendar_get_pressed_date(g_calendar, &pressed_date);
TEST_ASSERT_EQUAL(result, LV_RESULT_INVALID);
}
void test_calendar_get_btnmatrix(void)
{
lv_obj_t * btnm = lv_calendar_get_btnmatrix(g_calendar);
TEST_ASSERT_NOT_NULL(btnm);
}
void test_calendar_custom_year_list(void)
{
lv_obj_t * calendar = lv_calendar_create(lv_screen_active());
lv_calendar_add_header_dropdown(calendar);
const char * years = "2024\n2023\n2022\n2021\n2020\n2019";
lv_calendar_header_dropdown_set_year_list(calendar, years);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_08.png");
}
void test_calendar_chinese_calendar(void)
{
lv_obj_set_size(g_calendar, 400, 350);
lv_obj_center(g_calendar);
lv_calendar_set_today_date(g_calendar, 2024, 03, 22);
lv_calendar_set_month_shown(g_calendar, 2024, 03);
lv_obj_set_style_text_font(g_calendar, &lv_font_source_han_sans_sc_14_cjk, LV_PART_MAIN);
lv_calendar_set_chinese_mode(g_calendar, true);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/calendar_09.png");
}
#endif /* LV_BUILD_TEST */
@@ -0,0 +1,160 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * g_screen_active;
void setUp(void)
{
g_screen_active = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(g_screen_active);
}
static void draw_event_cb(lv_event_t * e)
{
int * draw_counter = lv_event_get_user_data(e);
(*draw_counter)++;
}
static void canvas_draw_buf_reshape(lv_draw_buf_t * draw_buf)
{
#if LV_USE_DRAW_VG_LITE
/* VG-Lite requires automatic stride calculation */
lv_draw_buf_t * buf = lv_draw_buf_reshape(draw_buf,
draw_buf->header.cf,
draw_buf->header.w,
draw_buf->header.h,
LV_STRIDE_AUTO);
TEST_ASSERT(buf == draw_buf);
#else
LV_UNUSED(draw_buf);
#endif
}
void test_canvas_functions_invalidate(void)
{
lv_obj_t * canvas = lv_canvas_create(g_screen_active);
int draw_counter = 0;
lv_obj_add_event_cb(canvas, draw_event_cb, LV_EVENT_DRAW_MAIN, &draw_counter);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 0);
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, 100, 100, LV_COLOR_FORMAT_NATIVE);
LV_DRAW_BUF_INIT_STATIC(draw_buf);
canvas_draw_buf_reshape(&draw_buf);
lv_canvas_set_draw_buf(canvas, &draw_buf);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 1);
lv_canvas_set_px(canvas, 0, 0, lv_color_black(), LV_OPA_COVER);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 2);
lv_canvas_fill_bg(canvas, lv_color_black(), LV_OPA_COVER);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 3);
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_line_dsc_t line_dsc;
lv_draw_line_dsc_init(&line_dsc);
line_dsc.p1.x = 10;
line_dsc.p1.y = 10;
line_dsc.p2.x = 20;
line_dsc.p2.y = 20;
line_dsc.width = 5;
lv_draw_line(&layer, &line_dsc);
lv_canvas_finish_layer(canvas, &layer);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 4);
lv_refr_now(NULL);
TEST_ASSERT(draw_counter == 4);
}
void test_canvas_fill_and_set_px(void)
{
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_obj_center(canvas);
LV_DRAW_BUF_DEFINE_STATIC(buf_i1, 10, 10, LV_COLOR_FORMAT_I1);
LV_DRAW_BUF_INIT_STATIC(buf_i1);
canvas_draw_buf_reshape(&buf_i1);
lv_canvas_set_draw_buf(canvas, &buf_i1);
lv_canvas_set_palette(canvas, 0, lv_color32_make(0x00, 0xff, 0x00, 0xff));
lv_canvas_set_palette(canvas, 1, lv_color32_make(0x00, 0x00, 0xff, 0xff));
lv_canvas_fill_bg(canvas, lv_color_hex(0), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(1), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_i2, 10, 10, LV_COLOR_FORMAT_I2);
LV_DRAW_BUF_INIT_STATIC(buf_i2);
canvas_draw_buf_reshape(&buf_i2);
lv_canvas_set_draw_buf(canvas, &buf_i2);
lv_canvas_set_palette(canvas, 0, lv_color32_make(0x00, 0xff, 0x00, 0xff));
lv_canvas_set_palette(canvas, 3, lv_color32_make(0x00, 0x00, 0xff, 0xff));
lv_canvas_fill_bg(canvas, lv_color_hex(0), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(3), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_i4, 10, 10, LV_COLOR_FORMAT_I4);
LV_DRAW_BUF_INIT_STATIC(buf_i4);
canvas_draw_buf_reshape(&buf_i4);
lv_canvas_set_draw_buf(canvas, &buf_i4);
lv_canvas_set_palette(canvas, 0, lv_color32_make(0x00, 0xff, 0x00, 0xff));
lv_canvas_set_palette(canvas, 15, lv_color32_make(0x00, 0x00, 0xff, 0xff));
lv_canvas_fill_bg(canvas, lv_color_hex(0), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(15), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_i8, 10, 10, LV_COLOR_FORMAT_I8);
LV_DRAW_BUF_INIT_STATIC(buf_i8);
canvas_draw_buf_reshape(&buf_i8);
lv_canvas_set_draw_buf(canvas, &buf_i8);
lv_canvas_set_palette(canvas, 0, lv_color32_make(0x00, 0xff, 0x00, 0xff));
lv_canvas_set_palette(canvas, 255, lv_color32_make(0x00, 0x00, 0xff, 0xff));
lv_canvas_fill_bg(canvas, lv_color_hex(0), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(255), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_rgb888, 10, 10, LV_COLOR_FORMAT_RGB888);
LV_DRAW_BUF_INIT_STATIC(buf_rgb888);
canvas_draw_buf_reshape(&buf_rgb888);
lv_canvas_set_draw_buf(canvas, &buf_rgb888);
lv_canvas_fill_bg(canvas, lv_color_hex(0x00ff00), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(0x0000ff), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_rgb565, 10, 10, LV_COLOR_FORMAT_RGB565);
LV_DRAW_BUF_INIT_STATIC(buf_rgb565);
canvas_draw_buf_reshape(&buf_rgb565);
lv_canvas_set_draw_buf(canvas, &buf_rgb565);
lv_canvas_fill_bg(canvas, lv_color_hex(0x00ff00), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(0x0000ff), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_xrgb8888, 10, 10, LV_COLOR_FORMAT_XRGB8888);
LV_DRAW_BUF_INIT_STATIC(buf_xrgb8888);
canvas_draw_buf_reshape(&buf_xrgb8888);
lv_canvas_set_draw_buf(canvas, &buf_xrgb8888);
lv_canvas_fill_bg(canvas, lv_color_hex(0x00ff00), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(0x0000ff), 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
LV_DRAW_BUF_DEFINE_STATIC(buf_argb8888, 10, 10, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(buf_argb8888);
canvas_draw_buf_reshape(&buf_argb8888);
lv_canvas_set_draw_buf(canvas, &buf_argb8888);
lv_canvas_fill_bg(canvas, lv_color_hex(0x00ff00), LV_OPA_COVER);
lv_canvas_set_px(canvas, 1, 7, lv_color_hex(0x0000ff), LV_OPA_COVER);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/canvas_1.png");
}
#endif
@@ -0,0 +1,215 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
static lv_obj_t * chart = NULL;
static lv_color_t red_color;
void setUp(void)
{
active_screen = lv_screen_active();
chart = lv_chart_create(active_screen);
red_color = lv_palette_main(LV_PALETTE_RED);
}
void tearDown(void)
{
/* Is there a way to destroy a chart without having to call remove_series for each of it series? */
lv_obj_clean(active_screen);
}
/* NOTE: Default chart type is LV_CHART_TYPE_LINE */
void test_chart_add_series(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
TEST_ASSERT_NOT_NULL_MESSAGE(red_series, "Red series not added to chart");
TEST_ASSERT_NULL_MESSAGE(red_series->x_points, "X points in non scatter chart should not point to anything");
lv_chart_remove_series(chart, red_series);
}
void test_chart_set_point_count_increments(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
uint16_t points_in_series = lv_chart_get_point_count(chart);
uint16_t new_point_count = points_in_series * 2;
lv_chart_set_point_count(chart, new_point_count);
TEST_ASSERT_EQUAL_MESSAGE(new_point_count, lv_chart_get_point_count(chart),
"Actual points in chart are less than expected");
lv_chart_remove_series(chart, red_series);
}
void test_chart_set_point_count_decrements(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
uint16_t points_in_series = lv_chart_get_point_count(chart);
uint16_t new_point_count = points_in_series / 2;
lv_chart_set_point_count(chart, new_point_count);
TEST_ASSERT_EQUAL_MESSAGE(new_point_count, lv_chart_get_point_count(chart),
"Actual points in chart are more than expected");
lv_chart_remove_series(chart, red_series);
}
void test_chart_set_point_count_as_same(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
uint16_t points_in_series = lv_chart_get_point_count(chart);
uint16_t new_point_count = points_in_series;
lv_chart_set_point_count(chart, new_point_count);
TEST_ASSERT_EQUAL_MESSAGE(new_point_count, lv_chart_get_point_count(chart),
"Actual points is not equal to original point count");
lv_chart_remove_series(chart, red_series);
}
void test_chart_set_new_point_count_as_zero(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
lv_chart_set_point_count(chart, 0u);
TEST_ASSERT_EQUAL_MESSAGE(1u, lv_chart_get_point_count(chart), "Actual points in chart are more than 1");
lv_chart_remove_series(chart, red_series);
}
void test_chart_point_is_added_at_the_end_of_a_series(void)
{
lv_chart_series_t * red_series;
red_series = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_SECONDARY_Y);
TEST_ASSERT_NOT_NULL_MESSAGE(red_series, "Red series not added to chart");
TEST_ASSERT_NULL_MESSAGE(red_series->x_points, "X points in non scatter chart should not point to anything");
lv_chart_remove_series(chart, red_series);
}
void test_chart_one_point_when_setting_point_count_to_zero(void)
{
lv_chart_set_point_count(chart, 0u);
TEST_ASSERT_EQUAL(1u, lv_chart_get_point_count(chart));
}
static void chart_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_DRAW_TASK_ADDED) {
lv_draw_task_t * draw_task = lv_event_get_param(e);
lv_draw_dsc_base_t * base_dsc = draw_task->draw_dsc;
lv_chart_type_t chart_type = lv_chart_get_type(obj);
if(chart_type == LV_CHART_TYPE_LINE && base_dsc->part != LV_PART_INDICATOR) return;
if(chart_type == LV_CHART_TYPE_BAR && base_dsc->part != LV_PART_ITEMS) return;
const lv_chart_series_t * ser = NULL;
for(uint32_t i = 0; i < base_dsc->id1 + 1; i++) {
ser = lv_chart_get_series_next(obj, ser);
}
char buf[8];
lv_snprintf(buf, sizeof(buf), "%"LV_PRIu32, ser->y_points[base_dsc->id2]);
lv_point_t text_size;
lv_text_get_size(&text_size, buf, LV_FONT_DEFAULT, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_task->area.x1 + lv_area_get_width(&draw_task->area) / 2 - text_size.x / 2;
txt_area.x2 = txt_area.x1 + text_size.x;
txt_area.y2 = draw_task->area.y1 - LV_DPX(15);
txt_area.y1 = txt_area.y2 - text_size.y;
lv_area_t bg_area;
bg_area.x1 = txt_area.x1 - LV_DPX(8);
bg_area.x2 = txt_area.x2 + LV_DPX(8);
bg_area.y1 = txt_area.y1 - LV_DPX(8);
bg_area.y2 = txt_area.y2 + LV_DPX(8);
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = ser->color;
rect_dsc.radius = LV_DPX(5);
lv_draw_rect(base_dsc->layer, &rect_dsc, &bg_area);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_white();
label_dsc.font = LV_FONT_DEFAULT;
label_dsc.text = buf;
label_dsc.text_local = true;
lv_draw_label(base_dsc->layer, &label_dsc, &txt_area);
}
}
void test_draw_task_hooking(void)
{
lv_obj_t * chart_wrapper = lv_obj_create(lv_screen_active());
lv_obj_set_size(chart_wrapper, 600, 300);
lv_obj_center(chart_wrapper);
lv_obj_set_parent(chart, chart_wrapper);
lv_obj_set_size(chart, lv_pct(200), lv_pct(100));
lv_obj_add_flag(chart, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
lv_chart_set_div_line_count(chart, 0, 21);
lv_chart_set_point_count(chart, 21);
lv_obj_add_event_cb(chart, chart_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
lv_chart_series_t * chart_set1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_YELLOW), 0);
lv_chart_series_t * chart_set2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), 0);
lv_chart_series_t * chart_set3 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), 0);
lv_chart_set_axis_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 700);
int32_t points[21] = {0, 31, 59, 81, 95, 100, 95, 81, 59, 31, 0, -31, -59, -81, -95, -100, -95, -81, -59, -31, 0};
for(uint32_t i = 0; i < 21; i++) {
lv_chart_set_next_value(chart, chart_set1, points[i] + 100);
lv_chart_set_next_value(chart, chart_set2, points[i] + 300);
lv_chart_set_next_value(chart, chart_set3, points[i] + 500);
}
lv_obj_scroll_to_x(chart_wrapper, 300, LV_ANIM_OFF);
lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/chart_line_draw_hook.png");
lv_chart_set_type(chart, LV_CHART_TYPE_BAR);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/chart_bar_draw_hook.png");
}
void test_chart_scatter(void)
{
lv_obj_center(chart);
lv_obj_set_size(chart, LV_PCT(100), LV_PCT(100));
lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 50, 100);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 20);
lv_chart_set_point_count(chart, 3);
lv_chart_series_t * ser = lv_chart_add_series(chart, red_color, LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_next_value2(chart, ser, 50, 10);
lv_chart_set_next_value2(chart, ser, 75, 12);
lv_chart_set_next_value2(chart, ser, 100, 20);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/chart_scatter.png");
}
#endif
@@ -0,0 +1,138 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
void test_checkbox_creation_successful(void);
void test_checkbox_should_call_event_handler_on_click_when_enabled(void);
void test_checkbox_should_have_default_text_when_created(void);
void test_checkbox_should_return_dynamically_allocated_text(void);
void test_checkbox_should_allocate_memory_for_static_text(void);
static lv_obj_t * active_screen = NULL;
static lv_obj_t * checkbox = NULL;
static volatile bool event_called = false;
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
if(LV_EVENT_VALUE_CHANGED == code) {
event_called = true;
}
}
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_checkbox_creation_successful(void)
{
active_screen = lv_screen_active();
checkbox = lv_checkbox_create(active_screen);
TEST_ASSERT_NOT_NULL(checkbox);
}
void test_checkbox_should_call_event_handler_on_click_when_enabled(void)
{
active_screen = lv_screen_active();
checkbox = lv_checkbox_create(active_screen);
lv_obj_add_state(checkbox, LV_STATE_CHECKED);
lv_obj_add_event_cb(checkbox, event_handler, LV_EVENT_ALL, NULL);
lv_test_mouse_click_at(checkbox->coords.x1, checkbox->coords.y1);
TEST_ASSERT_TRUE(event_called);
event_called = false;
}
void test_checkbox_should_have_default_text_when_created(void)
{
const char * default_text = "Check box";
active_screen = lv_screen_active();
checkbox = lv_checkbox_create(active_screen);
TEST_ASSERT_EQUAL_STRING(default_text, lv_checkbox_get_text(checkbox));
TEST_ASSERT_NOT_NULL(lv_checkbox_get_text(checkbox));
}
void test_checkbox_should_return_dynamically_allocated_text(void)
{
const char * message = "Hello World!";
active_screen = lv_screen_active();
checkbox = lv_checkbox_create(active_screen);
lv_checkbox_set_text(checkbox, message);
TEST_ASSERT_EQUAL_STRING(message, lv_checkbox_get_text(checkbox));
TEST_ASSERT_NOT_NULL(lv_checkbox_get_text(checkbox));
}
void test_checkbox_should_allocate_memory_for_static_text(void)
{
size_t initial_available_memory = 0;
const char * static_text = "Keep me while you exist";
lv_mem_monitor_t m1;
lv_mem_monitor(&m1);
active_screen = lv_screen_active();
checkbox = lv_checkbox_create(active_screen);
initial_available_memory = m1.free_size;
lv_checkbox_set_text_static(checkbox, static_text);
lv_mem_monitor(&m1);
LV_UNUSED(initial_available_memory);
LV_HEAP_CHECK(TEST_ASSERT_LESS_THAN(initial_available_memory, m1.free_size));
}
void test_checkbox_rtl(void)
{
const char * message =
"מעבד, או בשמו המלא יחידת עיבוד מרכזית (באנגלית: CPU - Central Processing Unit).";
lv_obj_t * screen = lv_obj_create(lv_screen_active());
lv_obj_remove_style_all(screen);
lv_obj_set_size(screen, 800, 480);
lv_obj_center(screen);
lv_obj_set_style_bg_color(screen, lv_color_white(), 0);
lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
lv_obj_set_style_pad_all(screen, 0, 0);
lv_obj_t * test_checkbox = lv_checkbox_create(active_screen);
lv_checkbox_set_text(test_checkbox, message);
lv_obj_set_style_text_font(test_checkbox, &lv_font_dejavu_16_persian_hebrew, 0);
lv_obj_center(test_checkbox);
lv_obj_set_style_base_dir(test_checkbox, LV_BASE_DIR_RTL, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/checkbox_rtl_1.png");
}
void test_checkbox_style_opa(void)
{
lv_obj_t * obj = lv_checkbox_create(lv_screen_active());
lv_obj_set_style_opa(obj, LV_OPA_0, LV_PART_INDICATOR);
lv_obj_center(obj);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/checkbox_1.png");
}
#endif
@@ -0,0 +1,510 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <string.h>
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_dropdown_create_delete(void)
{
lv_dropdown_create(lv_screen_active());
TEST_ASSERT_EQUAL(2, lv_obj_get_child_count(lv_screen_active()));
lv_obj_t * dd2 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd2, 200, 0);
TEST_ASSERT_EQUAL(4, lv_obj_get_child_count(lv_screen_active()));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_dropdown_open(dd2);
TEST_ASSERT_EQUAL(4, lv_obj_get_child_count(lv_screen_active()));
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd2));
lv_dropdown_open(dd2); /*Try to open again*/
TEST_ASSERT_EQUAL(4, lv_obj_get_child_count(lv_screen_active()));
lv_obj_t * dd3 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd3, 400, 0);
TEST_ASSERT_EQUAL(6, lv_obj_get_child_count(lv_screen_active()));
lv_dropdown_open(dd3);
TEST_ASSERT_EQUAL(6, lv_obj_get_child_count(lv_screen_active()));
lv_dropdown_close(dd3);
TEST_ASSERT_EQUAL(6, lv_obj_get_child_count(lv_screen_active()));
lv_dropdown_close(dd3); /*Try to close again*/
TEST_ASSERT_EQUAL(6, lv_obj_get_child_count(lv_screen_active()));
lv_obj_delete(dd2);
TEST_ASSERT_EQUAL(4, lv_obj_get_child_count(lv_screen_active()));
lv_obj_clean(lv_screen_active());
TEST_ASSERT_EQUAL(0, lv_obj_get_child_count(lv_screen_active()));
}
void test_dropdown_set_options(void)
{
lv_mem_monitor_t m1;
lv_mem_monitor(&m1);
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
TEST_ASSERT_EQUAL_STRING("Option 1\nOption 2\nOption 3", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(3, lv_dropdown_get_option_count(dd1));
lv_dropdown_set_options(dd1, "a1\nb2\nc3\nd4\ne5\nf6");
TEST_ASSERT_EQUAL_STRING("a1\nb2\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(6, lv_dropdown_get_option_count(dd1));
lv_obj_set_width(dd1, 200);
lv_dropdown_open(dd1);
lv_obj_update_layout(dd1);
TEST_ASSERT_EQUAL(200, lv_obj_get_width(lv_dropdown_get_list(dd1)));
lv_dropdown_close(dd1);
lv_dropdown_add_option(dd1, "x0", 0);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(7, lv_dropdown_get_option_count(dd1));
lv_dropdown_add_option(dd1, "y0", 3);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\ny0\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(8, lv_dropdown_get_option_count(dd1));
lv_dropdown_add_option(dd1, "z0", LV_DROPDOWN_POS_LAST);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\ny0\nc3\nd4\ne5\nf6\nz0", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(9, lv_dropdown_get_option_count(dd1));
lv_dropdown_clear_options(dd1);
TEST_ASSERT_EQUAL_STRING("", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(0, lv_dropdown_get_option_count(dd1));
lv_dropdown_set_options(dd1, "o1\no2"); /*Just to add some content before lv_dropdown_set_options_static*/
lv_dropdown_set_options_static(dd1, "a1\nb2\nc3\nd4\ne5\nf6");
TEST_ASSERT_EQUAL_STRING("a1\nb2\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(6, lv_dropdown_get_option_count(dd1));
lv_dropdown_add_option(dd1, "x0", 0);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(7, lv_dropdown_get_option_count(dd1));
lv_dropdown_add_option(dd1, "y0", 3);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\ny0\nc3\nd4\ne5\nf6", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(8, lv_dropdown_get_option_count(dd1));
lv_dropdown_add_option(dd1, "z0", LV_DROPDOWN_POS_LAST);
TEST_ASSERT_EQUAL_STRING("x0\na1\nb2\ny0\nc3\nd4\ne5\nf6\nz0", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(9, lv_dropdown_get_option_count(dd1));
lv_dropdown_clear_options(dd1);
TEST_ASSERT_EQUAL_STRING("", lv_dropdown_get_options(dd1));
TEST_ASSERT_EQUAL(0, lv_dropdown_get_option_count(dd1));
lv_obj_delete(dd1);
lv_mem_monitor_t m2;
lv_mem_monitor(&m2);
TEST_ASSERT_UINT_WITHIN(48, m1.free_size, m2.free_size);
}
void test_dropdown_select(void)
{
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_selected(dd1, 2);
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(dd1));
char buf[32];
memset(buf, 0x00, sizeof(buf));
lv_dropdown_get_selected_str(dd1, buf, sizeof(buf));
TEST_ASSERT_EQUAL_STRING("Option 3", buf);
memset(buf, 0x00, sizeof(buf));
lv_dropdown_get_selected_str(dd1, buf, 4);
TEST_ASSERT_EQUAL_STRING("Opt", buf);
/*Out of range*/
lv_dropdown_set_selected(dd1, 3);
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(dd1));
}
void test_dropdown_click(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_obj_update_layout(dd1);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
lv_test_mouse_click_at(dd1->coords.x1 + 5, dd1->coords.y1 + 5);
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd1));
lv_obj_t * list = lv_dropdown_get_list(dd1);
TEST_ASSERT_EQUAL(0, lv_dropdown_get_selected(dd1));
lv_test_mouse_click_at(list->coords.x1 + 5, list->coords.y2 - 25);
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
}
static uint32_t event_cnt;
static void dd_event(lv_event_t * e)
{
LV_UNUSED(e);
event_cnt++;
}
void test_dropdown_keypad(void)
{
lv_obj_clean(lv_screen_active());
lv_group_t * g = lv_group_create();
lv_indev_set_group(lv_test_indev_get_indev(LV_INDEV_TYPE_KEYPAD), g);
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd1, 20, 20);
lv_dropdown_set_options(dd1, "1\n2\n3\n4\n5\n6\n7\n8");
lv_group_add_obj(g, dd1);
lv_obj_add_event_cb(dd1, dd_event, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_t * dd2 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd2, 300, 20);
lv_group_add_obj(g, dd2);
event_cnt = 0;
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_RIGHT); /*Same as down*/
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(1, event_cnt);
lv_test_key_hit(LV_KEY_DOWN); /*Open the list too*/
TEST_ASSERT_NOT_NULL(lv_dropdown_get_list(dd1));
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(3, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(2, event_cnt);
lv_test_key_hit(LV_KEY_RIGHT); /*Open the list too*/
TEST_ASSERT_NOT_NULL(lv_dropdown_get_list(dd1));
lv_test_key_hit(LV_KEY_RIGHT);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(4, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(3, event_cnt);
lv_test_key_hit(LV_KEY_LEFT); /*Open the list too*/
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd1));
lv_test_key_hit(LV_KEY_LEFT);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(3, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(4, event_cnt);
lv_test_key_hit(LV_KEY_UP); /*Open the list too*/
TEST_ASSERT_NOT_NULL(lv_dropdown_get_list(dd1));
lv_test_key_hit(LV_KEY_UP);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(2, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(5, event_cnt);
lv_test_key_hit(LV_KEY_UP);
lv_test_key_hit(LV_KEY_UP);
lv_test_key_hit(LV_KEY_UP);
lv_test_key_hit(LV_KEY_UP);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(0, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(6, event_cnt);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_DOWN);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(7, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(7, event_cnt);
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd1));
lv_test_key_hit(LV_KEY_NEXT);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_test_key_hit(LV_KEY_ENTER);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_NOT_NULL(lv_dropdown_get_list(dd2));
lv_indev_set_group(lv_test_indev_get_indev(LV_INDEV_TYPE_KEYPAD), NULL);
lv_group_delete(g);
}
void test_dropdown_encoder(void)
{
lv_obj_clean(lv_screen_active());
lv_group_t * g = lv_group_create();
lv_indev_set_group(lv_test_indev_get_indev(LV_INDEV_TYPE_ENCODER), g);
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd1, 20, 20);
lv_dropdown_set_options(dd1, "1\n2\n3\n4\n5\n6\n7\n8");
lv_group_add_obj(g, dd1);
lv_obj_add_event_cb(dd1, dd_event, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_t * dd2 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd2, 300, 20);
lv_group_add_obj(g, dd2);
event_cnt = 0;
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_test_encoder_click();
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd1));
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd2));
lv_test_encoder_turn(5);
lv_test_encoder_click();
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(5, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(1, event_cnt);
lv_test_encoder_click();
lv_test_encoder_turn(-1);
lv_test_encoder_click();
TEST_ASSERT_EQUAL(4, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(2, event_cnt);
lv_test_encoder_click();
lv_test_encoder_turn(2);
lv_test_encoder_press();
lv_test_wait(1000); //Long press
lv_test_encoder_release();
lv_test_wait(50);
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_EQUAL(4, lv_dropdown_get_selected(dd1));
TEST_ASSERT_EQUAL(2, event_cnt);
lv_test_encoder_turn(1);
lv_test_encoder_click();
TEST_ASSERT_FALSE(lv_dropdown_is_open(dd1));
TEST_ASSERT_TRUE(lv_dropdown_is_open(dd2));
lv_indev_set_group(lv_test_indev_get_indev(LV_INDEV_TYPE_ENCODER), NULL);
lv_group_delete(g);
}
void test_dropdown_render_1(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd1, 10, 10);
lv_dropdown_set_selected(dd1, 1);
lv_obj_t * dd2 = lv_dropdown_create(lv_screen_active());
lv_obj_set_pos(dd2, 200, 10);
lv_obj_set_width(dd2, 200);
lv_dropdown_set_selected(dd2, 2);
lv_dropdown_open(dd2);
TEST_ASSERT_TRUE(lv_dropdown_get_selected_highlight(dd2));
lv_dropdown_set_selected_highlight(dd2, false);
TEST_ASSERT_FALSE(lv_dropdown_get_selected_highlight(dd2));
lv_obj_t * dd3 = lv_dropdown_create(lv_screen_active());
lv_obj_set_style_pad_hor(dd3, 5, 0);
lv_obj_set_style_pad_ver(dd3, 20, 0);
lv_obj_set_pos(dd3, 500, 150);
TEST_ASSERT_EQUAL_PTR(NULL, lv_dropdown_get_text(dd3));
lv_dropdown_set_text(dd3, "A text");
TEST_ASSERT_EQUAL_STRING("A text", lv_dropdown_get_text(dd3));
lv_dropdown_set_selected(dd3, 2);
TEST_ASSERT_EQUAL(LV_DIR_BOTTOM, lv_dropdown_get_dir(dd3));
lv_dropdown_set_dir(dd3, LV_DIR_LEFT);
TEST_ASSERT_EQUAL(LV_DIR_LEFT, lv_dropdown_get_dir(dd3));
TEST_ASSERT_EQUAL_STRING(LV_SYMBOL_DOWN, lv_dropdown_get_symbol(dd3));
lv_dropdown_set_symbol(dd3, LV_SYMBOL_LEFT);
TEST_ASSERT_EQUAL_STRING(LV_SYMBOL_LEFT, lv_dropdown_get_symbol(dd3));
lv_dropdown_set_options(dd3, "a0\na1\na2\na3\na4\na5\na6\na7\na8\na9\na10\na11\na12\na13\na14\na15\na16");
lv_dropdown_open(dd3);
lv_obj_t * list = lv_dropdown_get_list(dd3);
lv_obj_set_style_text_line_space(list, 5, 0);
lv_obj_set_style_bg_color(list, lv_color_hex3(0xf00), LV_PART_SELECTED | LV_STATE_CHECKED);
lv_dropdown_set_selected(dd3, 3);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/dropdown_1.png");
}
void test_dropdown_render_2(void)
{
lv_obj_clean(lv_screen_active());
LV_IMAGE_DECLARE(test_image_caret_down);
lv_obj_t * dd1 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd1, "Short");
lv_dropdown_set_options(dd1, "1\n2");
lv_dropdown_set_symbol(dd1, &test_image_caret_down);
lv_dropdown_open(dd1);
lv_obj_t * dd2 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd2, "Go Up");
lv_dropdown_set_options(dd2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15");
lv_dropdown_set_symbol(dd2, NULL);
lv_obj_align(dd2, LV_ALIGN_LEFT_MID, 150, 50);
lv_dropdown_open(dd2);
lv_obj_t * dd3 = lv_dropdown_create(lv_screen_active());
lv_obj_set_height(dd3, 70);
lv_dropdown_set_text(dd3, "Limit Down");
lv_dropdown_set_options(dd3, "1aaaaaaaaaaaaaaaa\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15");
lv_obj_align(dd3, LV_ALIGN_LEFT_MID, 300, -10);
lv_dropdown_open(dd3);
lv_obj_t * dd4 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd4, "Limit Top");
lv_dropdown_set_options(dd4, "1aaaaaaaaaaaaaaaa\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15");
lv_obj_align(dd4, LV_ALIGN_LEFT_MID, 450, 10);
lv_dropdown_set_dir(dd4, LV_DIR_TOP);
lv_dropdown_set_symbol(dd4, LV_SYMBOL_UP);
lv_dropdown_open(dd4);
lv_obj_t * dd5 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd5, "Go Down");
lv_dropdown_set_options(dd5, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15");
lv_dropdown_set_dir(dd5, LV_DIR_TOP);
lv_dropdown_set_symbol(dd5, LV_SYMBOL_UP);
lv_obj_align(dd5, LV_ALIGN_LEFT_MID, 650, -200);
lv_dropdown_open(dd5);
lv_obj_t * dd6 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd6, "Right");
lv_dropdown_set_options(dd6, "1aaa\n2aa\n3aa");
lv_dropdown_set_dir(dd6, LV_DIR_RIGHT);
lv_dropdown_set_symbol(dd6, LV_SYMBOL_RIGHT);
lv_obj_align(dd6, LV_ALIGN_BOTTOM_LEFT, 20, -20);
lv_dropdown_open(dd6);
lv_obj_set_style_text_align(lv_dropdown_get_list(dd6), LV_TEXT_ALIGN_RIGHT, 0);
lv_obj_t * dd7 = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_text(dd7, "Left");
lv_dropdown_set_options(dd7, "1aaa\n2\n3");
lv_dropdown_set_dir(dd7, LV_DIR_LEFT);
lv_dropdown_set_symbol(dd7, LV_SYMBOL_LEFT);
lv_obj_align(dd7, LV_ALIGN_BOTTOM_RIGHT, -20, -20);
lv_dropdown_open(dd7);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/dropdown_2.png");
}
/* See #2893 */
void test_dropdown_should_list_on_top(void)
{
lv_obj_t * cont1 = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont1, 200, 100);
lv_obj_t * dd = lv_dropdown_create(cont1);
lv_obj_t * cont2 = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont2, 200, 100);
lv_obj_set_pos(cont2, 0, 100);
lv_dropdown_open(dd);
lv_obj_t * list = lv_dropdown_get_list(dd);
TEST_ASSERT_EQUAL_PTR(lv_screen_active(), lv_obj_get_parent(list));
TEST_ASSERT_EQUAL_INT(2, lv_obj_get_index(list));
}
/* See #4191 */
void test_dropdown_get_options_should_check_lengths(void)
{
lv_obj_t * dd = lv_dropdown_create(lv_screen_active());
lv_dropdown_set_options(dd, "abc\nab");
TEST_ASSERT_EQUAL_INT(1, lv_dropdown_get_option_index(dd, "ab"));
lv_dropdown_set_options(dd, "Option 1\nOption 2\nOption 3\nOption");
TEST_ASSERT_EQUAL_INT(3, lv_dropdown_get_option_index(dd, "Option"));
TEST_ASSERT_EQUAL_INT(-1, lv_dropdown_get_option_index(dd, "Option "));
}
void test_dropdown_properties(void)
{
#if LV_USE_OBJ_PROPERTY
lv_obj_t * obj = lv_dropdown_create(lv_screen_active());
lv_property_t prop = { };
prop.id = LV_PROPERTY_DROPDOWN_TEXT;
prop.ptr = "Hello";
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_STRING("Hello", lv_dropdown_get_text(obj));
TEST_ASSERT_EQUAL_STRING("Hello", lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_TEXT).ptr);
prop.id = LV_PROPERTY_DROPDOWN_OPTIONS;
prop.ptr = "Option 1\nOption 2";
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_STRING("Option 1\nOption 2", lv_dropdown_get_options(obj));
TEST_ASSERT_EQUAL_STRING("Option 1\nOption 2", lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_OPTIONS).ptr);
TEST_ASSERT_EQUAL(2, lv_dropdown_get_option_count(obj));
TEST_ASSERT_EQUAL(2, lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_OPTION_COUNT).num);
prop.id = LV_PROPERTY_DROPDOWN_SELECTED;
prop.num = 1;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(1, lv_dropdown_get_selected(obj));
TEST_ASSERT_EQUAL_INT(1, lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_SELECTED).num);
prop.id = LV_PROPERTY_DROPDOWN_DIR;
prop.num = LV_DIR_LEFT;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(LV_DIR_LEFT, lv_dropdown_get_dir(obj));
TEST_ASSERT_EQUAL_INT(LV_DIR_LEFT, lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_DIR).num);
prop.id = LV_PROPERTY_DROPDOWN_SYMBOL;
prop.ptr = LV_SYMBOL_DOWN;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_STRING(LV_SYMBOL_DOWN, lv_dropdown_get_symbol(obj));
TEST_ASSERT_EQUAL_STRING(LV_SYMBOL_DOWN, lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_SYMBOL).ptr);
prop.id = LV_PROPERTY_DROPDOWN_SELECTED_HIGHLIGHT;
prop.num = true;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_TRUE(lv_dropdown_get_selected_highlight(obj));
TEST_ASSERT_TRUE(lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_SELECTED_HIGHLIGHT).num);
lv_dropdown_open(obj);
TEST_ASSERT_TRUE(lv_dropdown_is_open(obj));
TEST_ASSERT_TRUE(lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_IS_OPEN).enable);
lv_dropdown_close(obj);
TEST_ASSERT_FALSE(lv_dropdown_is_open(obj));
TEST_ASSERT_FALSE(lv_obj_get_property(obj, LV_PROPERTY_DROPDOWN_IS_OPEN).enable);
#endif
}
#endif
@@ -0,0 +1,708 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
LV_IMAGE_DECLARE(test_arc_bg);
void setUp(void)
{
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
static lv_obj_t * img_create(void)
{
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &test_img_lvgl_logo_png);
lv_obj_set_style_bg_opa(img, LV_OPA_20, 0);
lv_obj_set_style_bg_color(img, lv_color_hex(0x000000), 0);
lv_obj_set_style_shadow_width(img, 10, 0);
lv_obj_set_style_shadow_color(img, lv_color_hex(0xff0000), 0);
return img;
}
void test_image_rotated_pivot_center(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 100 + (i % 4) * 160, 150 + (i / 4) * 150);
lv_image_set_rotation(img, i * 450);
/*The default pivot should be the center*/
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_rotate_pivot_center.png");
}
void test_image_rotated_pivot_top_left(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 120 + (i % 4) * 180, 100 + (i / 4) * 300);
lv_image_set_rotation(img, i * 450);
lv_image_set_pivot(img, 0, 0);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_rotate_pivot_top_left.png");
}
void test_image_scale_pivot_center(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
lv_image_set_scale(img, 64 + i * 64);
/*The default pivot should be the center*/
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_pivot_center.png");
}
void test_image_scale_pivot_top_left(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
lv_image_set_scale(img, 64 + i * 64);
lv_image_set_pivot(img, 0, 0);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_pivot_top_left.png");
}
void test_image_scale_x_pivot_center(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
lv_image_set_scale_x(img, 64 + i * 64);
/*The default pivot should be the center*/
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_x_pivot_center.png");
}
void test_image_scale_x_pivot_top_left(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
lv_image_set_scale_x(img, 64 + i * 64);
lv_image_set_pivot(img, 0, 0);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_x_pivot_top_left.png");
}
void test_image_scale_y_pivot_center(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
lv_image_set_scale_y(img, 64 + i * 64);
/*The default pivot should be the center*/
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_y_pivot_center.png");
}
void test_image_scale_y_pivot_top_left(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 10 + (i % 4) * 190, 150 + (i / 4) * 150);
lv_image_set_scale_y(img, 64 + i * 64);
lv_image_set_pivot(img, 0, 0);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_scale_y_pivot_top_left.png");
}
void test_image_rotate_and_scale_pivot_center(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 40 + (i % 4) * 200, 150 + (i / 4) * 150);
lv_image_set_scale_x(img, 64 + i * 64);
lv_image_set_scale_y(img, 32 + i * 96);
lv_image_set_rotation(img, 200 + i * 333);
/*The default pivot should be the center*/
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_rotate_and_scale_pivot_center.png");
}
void test_image_rotate_and_scale_pivot_top_left(void)
{
lv_obj_t * img;
uint32_t i;
for(i = 0; i < 8; i++) {
img = img_create();
lv_obj_set_pos(img, 120 + (i % 4) * 180, 120 + (i / 4) * 220);
lv_image_set_scale_x(img, 64 + i * 64);
lv_image_set_scale_y(img, 32 + i * 96);
lv_image_set_rotation(img, 200 + i * 333);
lv_image_set_pivot(img, 0, 0);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_rotate_and_scale_pivot_top_left.png");
}
void test_image_normal_align(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, aligns[i]);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_normal_align.png");
}
void test_image_normal_align_offset(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, aligns[i]);
lv_image_set_offset_x(img, 15);
lv_image_set_offset_y(img, 20);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_normal_align_offset.png");
}
void test_image_transform_align(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_scale_x(img, 300);
lv_image_set_scale_y(img, 200);
lv_image_set_rotation(img, 200);
lv_image_set_inner_align(img, aligns[i]);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_transform_align.png");
}
void test_image_transform_align_offset(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, aligns[i]);
lv_image_set_offset_x(img, 15);
lv_image_set_offset_y(img, 20);
lv_image_set_scale_x(img, 300);
lv_image_set_scale_y(img, 200);
lv_image_set_rotation(img, 200);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_transform_align_offset.png");
}
void test_image_stretch(void)
{
lv_obj_t * img;
uint32_t i;
int32_t img_w = test_img_lvgl_logo_png.header.w;
int32_t img_h = test_img_lvgl_logo_png.header.h;
int32_t w_array[] = {img_w / 2, img_w, img_w * 2};
int32_t h_array[] = {img_h / 2, img_h, img_h * 2};
for(i = 0; i < 9; i++) {
img = img_create();
const int32_t w = w_array[i / 3];
const int32_t h = h_array[i % 3];
lv_obj_set_size(img, w, h);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_STRETCH);
// Because of the integer scaling, it is possible the actual image width is 1 less than the object width
TEST_ASSERT_INT_WITHIN(1, w, lv_image_get_transformed_width(img));
TEST_ASSERT_INT_WITHIN(1, h, lv_image_get_transformed_height(img));
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_stretch.png");
}
void test_image_contain(void)
{
lv_obj_t * img;
uint32_t i;
int32_t img_w = test_img_lvgl_logo_png.header.w;
int32_t img_h = test_img_lvgl_logo_png.header.h;
int32_t aspect_ratio = img_w / img_h;
int32_t w_array[] = {img_w / 2, img_w, img_w * 2};
int32_t h_array[] = {img_h / 2, img_h, img_h * 2};
for(i = 0; i < 9; i++) {
img = img_create();
const int32_t w = w_array[i / 3];
const int32_t h = h_array[i % 3];
lv_obj_set_size(img, w, h);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_CONTAIN);
const int32_t scale = lv_image_get_scale(img);
TEST_ASSERT_EQUAL_INT(aspect_ratio, lv_image_get_transformed_width(img) / lv_image_get_transformed_height(img));
TEST_ASSERT_EQUAL_INT((img_w * scale) >> 8, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT((img_h * scale) >> 8, lv_image_get_transformed_height(img));
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_contain.png");
}
void test_image_cover(void)
{
lv_obj_t * img;
uint32_t i;
int32_t img_w = test_img_lvgl_logo_png.header.w;
int32_t img_h = test_img_lvgl_logo_png.header.h;
int32_t aspect_ratio = img_w / img_h;
int32_t w_array[] = {img_w / 2, img_w, img_w * 2};
int32_t h_array[] = {img_h / 2, img_h, img_h * 2};
for(i = 0; i < 9; i++) {
img = img_create();
const int32_t w = w_array[i / 3];
const int32_t h = h_array[i % 3];
lv_obj_set_size(img, w, h);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_COVER);
const int32_t scale = lv_image_get_scale(img);
TEST_ASSERT_EQUAL_INT(aspect_ratio, lv_image_get_transformed_width(img) / lv_image_get_transformed_height(img));
TEST_ASSERT_EQUAL_INT((img_w * scale) >> 8, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT((img_h * scale) >> 8, lv_image_get_transformed_height(img));
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_cover.png");
}
void test_image_tile(void)
{
lv_obj_t * img;
img = img_create();
lv_obj_set_size(img, 350, LV_SIZE_CONTENT);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_obj_set_pos(img, 20, 20);
img = img_create();
lv_obj_set_size(img, LV_SIZE_CONTENT, 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_obj_set_pos(img, 420, 20);
img = img_create();
lv_obj_set_size(img, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_obj_set_pos(img, 20, 220);
lv_image_set_offset_x(img, -20);
lv_image_set_offset_y(img, 20);
img = img_create();
lv_obj_set_size(img, 150, 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_obj_set_pos(img, 220, 220);
img = img_create();
lv_obj_set_size(img, 150, 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_obj_set_pos(img, 420, 220);
lv_image_set_offset_x(img, -2000);
lv_image_set_offset_y(img, 2000);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_tile.png");
}
void test_image_ignore_transformation_settings_when_stretched(void)
{
lv_obj_t * img = img_create();
lv_obj_set_size(img, 200, 300);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_STRETCH);
lv_image_set_rotation(img, 100);
lv_image_set_pivot(img, 200, 300);
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
lv_point_t pivot;
lv_image_get_pivot(img, &pivot);
TEST_ASSERT_EQUAL_INT(0, pivot.x);
TEST_ASSERT_EQUAL_INT(0, pivot.y);
int32_t scale_x_original = lv_image_get_scale_x(img);
int32_t scale_y_original = lv_image_get_scale_y(img);
lv_image_set_scale_x(img, 400);
lv_image_set_scale_y(img, 500);
TEST_ASSERT_EQUAL_INT(scale_x_original, lv_image_get_scale_x(img));
TEST_ASSERT_EQUAL_INT(scale_y_original, lv_image_get_scale_y(img));
}
void test_image_ignore_transformation_settings_when_contained(void)
{
lv_obj_t * img = img_create();
lv_obj_set_size(img, 200, 300);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_CONTAIN);
lv_image_set_rotation(img, 100);
lv_image_set_pivot(img, 200, 300);
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
lv_point_t pivot;
lv_image_get_pivot(img, &pivot);
TEST_ASSERT_EQUAL_INT(0, pivot.x);
TEST_ASSERT_EQUAL_INT(0, pivot.y);
int32_t scale_x_original = lv_image_get_scale_x(img);
int32_t scale_y_original = lv_image_get_scale_y(img);
lv_image_set_scale_x(img, 400);
lv_image_set_scale_y(img, 500);
TEST_ASSERT_EQUAL_INT(scale_x_original, lv_image_get_scale_x(img));
TEST_ASSERT_EQUAL_INT(scale_y_original, lv_image_get_scale_y(img));
}
void test_image_ignore_transformation_settings_when_covered(void)
{
lv_obj_t * img = img_create();
lv_obj_set_size(img, 200, 300);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_COVER);
lv_image_set_rotation(img, 100);
lv_image_set_pivot(img, 200, 300);
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
lv_point_t pivot;
lv_image_get_pivot(img, &pivot);
TEST_ASSERT_EQUAL_INT(0, pivot.x);
TEST_ASSERT_EQUAL_INT(0, pivot.y);
int32_t scale_x_original = lv_image_get_scale_x(img);
int32_t scale_y_original = lv_image_get_scale_y(img);
lv_image_set_scale_x(img, 400);
lv_image_set_scale_y(img, 500);
TEST_ASSERT_EQUAL_INT(scale_x_original, lv_image_get_scale_x(img));
TEST_ASSERT_EQUAL_INT(scale_y_original, lv_image_get_scale_y(img));
}
void test_image_ignore_transformation_settings_when_tiled(void)
{
lv_obj_t * img = img_create();
lv_obj_set_size(img, 200, 300);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_TILE);
lv_image_set_rotation(img, 100);
lv_image_set_pivot(img, 200, 300);
lv_image_set_scale_x(img, 400);
lv_image_set_scale_y(img, 500);
lv_point_t pivot;
lv_image_get_pivot(img, &pivot);
TEST_ASSERT_EQUAL_INT(0, pivot.x);
TEST_ASSERT_EQUAL_INT(0, pivot.y);
TEST_ASSERT_EQUAL_INT(0, lv_image_get_rotation(img));
TEST_ASSERT_EQUAL_INT(LV_SCALE_NONE, lv_image_get_scale_x(img));
TEST_ASSERT_EQUAL_INT(LV_SCALE_NONE, lv_image_get_scale_y(img));
}
void test_image_get_scaled_size(void)
{
lv_obj_t * img = img_create();
lv_obj_set_size(img, 200, 300);
int32_t img_w = test_img_lvgl_logo_png.header.w;
int32_t img_h = test_img_lvgl_logo_png.header.h;
TEST_ASSERT_EQUAL_INT(img_w, lv_image_get_src_width(img));
TEST_ASSERT_EQUAL_INT(img_h, lv_image_get_src_height(img));
TEST_ASSERT_EQUAL_INT(img_w, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT(img_h, lv_image_get_transformed_height(img));
lv_image_set_rotation(img, 900);
TEST_ASSERT_EQUAL_INT(img_h, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT(img_w, lv_image_get_transformed_height(img));
lv_image_set_rotation(img, 1800);
TEST_ASSERT_EQUAL_INT(img_w, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT(img_h, lv_image_get_transformed_height(img));
}
static void create_test_images(int32_t radius, int32_t scale, int32_t angle)
{
LV_IMAGE_DECLARE(test_I1_NONE_align64);
LV_IMAGE_DECLARE(test_I2_NONE_align64);
LV_IMAGE_DECLARE(test_I4_NONE_align64);
LV_IMAGE_DECLARE(test_I8_NONE_align64);
LV_IMAGE_DECLARE(test_A1_NONE_align64);
LV_IMAGE_DECLARE(test_A2_NONE_align64);
LV_IMAGE_DECLARE(test_A4_NONE_align64);
LV_IMAGE_DECLARE(test_A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565A8_NONE_align64);
LV_IMAGE_DECLARE(test_RGB565_NONE_align64);
LV_IMAGE_DECLARE(test_RGB888_NONE_align64);
LV_IMAGE_DECLARE(test_XRGB8888_NONE_align64);
LV_IMAGE_DECLARE(test_ARGB8888_NONE_align64);
const lv_image_dsc_t * img_dscs[] = {
&test_I1_NONE_align64,
&test_I2_NONE_align64,
&test_I4_NONE_align64,
&test_I8_NONE_align64,
&test_A1_NONE_align64,
&test_A2_NONE_align64,
&test_A4_NONE_align64,
&test_A8_NONE_align64,
&test_RGB565A8_NONE_align64,
&test_RGB565_NONE_align64,
&test_RGB888_NONE_align64,
&test_XRGB8888_NONE_align64,
&test_ARGB8888_NONE_align64,
};
const char * names[] = {
"I1",
"I2",
"I4",
"I8",
"A1",
"A2",
"A4",
"A8",
"RGB565A8",
"RGB565",
"RGB888",
"XRGB8888",
"ARGB8888",
};
lv_obj_clean(lv_screen_active());
for(size_t i = 0; i < sizeof(img_dscs) / sizeof(img_dscs[0]); i++) {
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_t * img = lv_image_create(cont);
lv_image_set_src(img, img_dscs[i]);
lv_obj_set_style_radius(img, radius, 0);
lv_obj_set_style_image_recolor(img, lv_color_hex3(0xf00), 0);
lv_image_set_scale(img, scale);
lv_image_set_rotation(img, angle);
lv_obj_t * label = lv_label_create(cont);
lv_label_set_text(label, names[i]);
}
}
void test_image_clip_radius(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
create_test_images(20, LV_SCALE_NONE, 0);
#if LV_BIN_DECODER_RAM_LOAD
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_clip_radius_20.png");
#endif
create_test_images(LV_RADIUS_CIRCLE, LV_SCALE_NONE, 0);
#if LV_BIN_DECODER_RAM_LOAD
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_clip_radius_circle.png");
#endif
create_test_images(20, 300, 200);
#if LV_BIN_DECODER_RAM_LOAD
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_clip_radius_circle_scaled_rotated.png");
#endif
}
void test_image_properties(void)
{
#if LV_USE_OBJ_PROPERTY
lv_obj_t * obj = lv_image_create(lv_screen_active());
lv_property_t prop = { };
prop.id = LV_PROPERTY_IMAGE_SRC;
prop.ptr = &test_arc_bg;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_PTR(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_SRC).ptr, &test_arc_bg);
TEST_ASSERT_EQUAL_PTR(lv_image_get_src(obj), &test_arc_bg);
prop.id = LV_PROPERTY_IMAGE_OFFSET_X;
prop.num = 10;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_OFFSET_X).num, 10);
TEST_ASSERT_EQUAL_INT(lv_image_get_offset_x(obj), 10);
prop.id = LV_PROPERTY_IMAGE_OFFSET_Y;
prop.num = 20;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_OFFSET_Y).num, 20);
TEST_ASSERT_EQUAL_INT(lv_image_get_offset_y(obj), 20);
prop.id = LV_PROPERTY_IMAGE_ROTATION;
prop.num = 30;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_ROTATION).num, 30);
TEST_ASSERT_EQUAL_INT(lv_image_get_rotation(obj), 30);
prop.id = LV_PROPERTY_IMAGE_PIVOT;
prop.point.x = 40;
prop.point.y = 50;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_PIVOT).point.x, 40);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_PIVOT).point.y, 50);
lv_point_t pivot;
lv_image_get_pivot(obj, &pivot);
TEST_ASSERT_EQUAL_INT(pivot.x, 40);
TEST_ASSERT_EQUAL_INT(pivot.y, 50);
prop.id = LV_PROPERTY_IMAGE_SCALE;
prop.num = 60;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_SCALE).num, 60);
TEST_ASSERT_EQUAL_INT(lv_image_get_scale(obj), 60);
prop.id = LV_PROPERTY_IMAGE_SCALE_X;
prop.num = 70;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_SCALE_X).num, 70);
TEST_ASSERT_EQUAL_INT(lv_image_get_scale_x(obj), 70);
prop.id = LV_PROPERTY_IMAGE_SCALE_Y;
prop.num = 80;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_SCALE_Y).num, 80);
TEST_ASSERT_EQUAL_INT(lv_image_get_scale_y(obj), 80);
prop.id = LV_PROPERTY_IMAGE_BLEND_MODE;
prop.num = LV_BLEND_MODE_ADDITIVE;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_BLEND_MODE).num, LV_BLEND_MODE_ADDITIVE);
TEST_ASSERT_EQUAL_INT(lv_image_get_blend_mode(obj), LV_BLEND_MODE_ADDITIVE);
prop.id = LV_PROPERTY_IMAGE_ANTIALIAS;
prop.num = 0;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_ANTIALIAS).num, 0);
TEST_ASSERT_EQUAL_INT(lv_image_get_antialias(obj), 0);
prop.id = LV_PROPERTY_IMAGE_INNER_ALIGN;
prop.num = LV_IMAGE_ALIGN_TOP_MID;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(lv_obj_get_property(obj, LV_PROPERTY_IMAGE_INNER_ALIGN).num, LV_IMAGE_ALIGN_TOP_MID);
TEST_ASSERT_EQUAL_INT(lv_image_get_inner_align(obj), LV_IMAGE_ALIGN_TOP_MID);
#endif
}
void test_image_symbol_normal_align(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_image_set_src(img, LV_SYMBOL_IMAGE);
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, aligns[i]);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_symbol_normal_align.png");
}
void test_image_symbol_normal_align_offset(void)
{
lv_obj_t * img;
uint32_t i;
lv_image_align_t aligns[] = {
LV_IMAGE_ALIGN_TOP_LEFT, LV_IMAGE_ALIGN_TOP_MID, LV_IMAGE_ALIGN_TOP_RIGHT,
LV_IMAGE_ALIGN_LEFT_MID, LV_IMAGE_ALIGN_CENTER, LV_IMAGE_ALIGN_RIGHT_MID,
LV_IMAGE_ALIGN_BOTTOM_LEFT, LV_IMAGE_ALIGN_BOTTOM_MID, LV_IMAGE_ALIGN_BOTTOM_RIGHT,
};
for(i = 0; i < 9; i++) {
img = img_create();
lv_image_set_src(img, LV_SYMBOL_IMAGE);
lv_obj_set_size(img, 200, 120);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, aligns[i]);
lv_image_set_offset_x(img, 10);
lv_image_set_offset_y(img, 15);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_symbol_normal_align_offset.png");
}
#endif
@@ -0,0 +1,58 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
lv_obj_clean(lv_screen_active());
}
void test_imagebutton_basic_appearance(void)
{
/**
* from lv_example_imagebutton_1
*/
LV_IMAGE_DECLARE(imagebutton_left);
LV_IMAGE_DECLARE(imagebutton_right);
LV_IMAGE_DECLARE(imagebutton_mid);
/*Create an image button*/
lv_obj_t * imagebutton1 = lv_imagebutton_create(lv_screen_active());
lv_imagebutton_set_src(imagebutton1, LV_IMAGEBUTTON_STATE_RELEASED, &imagebutton_left, &imagebutton_mid,
&imagebutton_right);
lv_obj_set_style_text_color(imagebutton1, lv_color_white(), 0);
lv_obj_set_width(imagebutton1, 100);
lv_obj_align(imagebutton1, LV_ALIGN_CENTER, -150, 0);
/*Create a label on the image button*/
lv_obj_t * label = lv_label_create(imagebutton1);
lv_label_set_text(label, "Button");
lv_obj_align(label, LV_ALIGN_CENTER, 0, -4);
/**
* from lv_demo_music
*/
LV_IMAGE_DECLARE(music_button_play);
lv_obj_t * play_button = lv_imagebutton_create(lv_screen_active());
lv_imagebutton_set_src(play_button, LV_IMAGEBUTTON_STATE_RELEASED, NULL, &music_button_play, NULL);
lv_obj_align(play_button, LV_ALIGN_CENTER, 100, 0);
/**
* compare screenshot
*/
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/imagebutton_1.png");
}
#endif
@@ -0,0 +1,58 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
static const void * get_imgfont_path(const lv_font_t * font, uint32_t unicode, uint32_t unicode_next,
int32_t * offset_y, void * user_data)
{
LV_UNUSED(font);
LV_UNUSED(unicode_next);
LV_UNUSED(offset_y);
LV_UNUSED(user_data);
LV_IMAGE_DECLARE(emoji_F617);
if(unicode == 0xF617) {
return &emoji_F617;
}
else if(unicode == 0xF600) {
return "A:src/test_assets/test_img_emoji_F600.png";
}
return NULL;
}
void test_imgfont_creation(void)
{
lv_font_t * imgfont = lv_imgfont_create(80, get_imgfont_path, NULL);
TEST_ASSERT_NOT_NULL(imgfont);
imgfont->fallback = LV_FONT_DEFAULT;
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "12\uF600\uF617\uF000AB");
lv_obj_set_style_text_font(label, imgfont, LV_PART_MAIN);
lv_obj_center(label);
lv_refr_now(NULL);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/imgfont_1.png");
lv_imgfont_destroy(imgfont);
}
#endif
@@ -0,0 +1,76 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_keyboard_mode(void)
{
lv_obj_t * keyboard = lv_keyboard_create(active_screen);
lv_obj_set_size(keyboard, LV_PCT(100), LV_PCT(50));
lv_obj_align(keyboard, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_obj_set_style_text_font(keyboard, &lv_font_dejavu_16_persian_hebrew, LV_PART_MAIN);
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/keyboard_1.png");
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_TEXT_UPPER);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/keyboard_2.png");
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_SPECIAL);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/keyboard_3.png");
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_NUMBER);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/keyboard_4.png");
}
void test_keyboard_properties(void)
{
#if LV_USE_OBJ_PROPERTY
lv_obj_t * obj = lv_keyboard_create(lv_screen_active());
lv_property_t prop = { };
lv_obj_t * test_area = lv_textarea_create(lv_screen_active());
prop.id = LV_PROPERTY_KEYBOARD_TEXTAREA;
prop.ptr = test_area;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_PTR(test_area, lv_keyboard_get_textarea(obj));
TEST_ASSERT_EQUAL_PTR(test_area, lv_obj_get_property(obj, LV_PROPERTY_KEYBOARD_TEXTAREA).ptr);
prop.id = LV_PROPERTY_KEYBOARD_MODE;
prop.num = LV_KEYBOARD_MODE_TEXT_UPPER;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(LV_KEYBOARD_MODE_TEXT_UPPER, lv_keyboard_get_mode(obj));
TEST_ASSERT_EQUAL_INT(LV_KEYBOARD_MODE_TEXT_UPPER, lv_obj_get_property(obj, LV_PROPERTY_KEYBOARD_MODE).num);
prop.id = LV_PROPERTY_KEYBOARD_POPOVERS;
prop.num = 1;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(1, lv_keyboard_get_popovers(obj));
TEST_ASSERT_EQUAL_INT(1, lv_obj_get_property(obj, LV_PROPERTY_KEYBOARD_POPOVERS).num);
prop.id = LV_PROPERTY_KEYBOARD_SELECTED_BUTTON;
prop.num = 1;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_INT(1, lv_keyboard_get_selected_button(obj));
TEST_ASSERT_EQUAL_INT(1, lv_obj_get_property(obj, LV_PROPERTY_KEYBOARD_SELECTED_BUTTON).num);
#endif
}
#endif
@@ -0,0 +1,694 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
#include <string.h>
static const char * long_text =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras malesuada ultrices magna in rutrum.";
static const char * long_text_multiline =
"Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit.\nCras malesuada ultrices magna in rutrum.\n";
static const char * empty_text = "";
static lv_obj_t * active_screen = NULL;
static lv_obj_t * label;
static lv_obj_t * long_label;
static lv_obj_t * long_label_multiline;
static lv_obj_t * empty_label;
void setUp(void)
{
active_screen = lv_screen_active();
label = lv_label_create(active_screen);
long_label = lv_label_create(active_screen);
long_label_multiline = lv_label_create(active_screen);
empty_label = lv_label_create(active_screen);
lv_label_set_text(long_label, long_text);
lv_label_set_text(long_label_multiline, long_text_multiline);
lv_label_set_text(empty_label, empty_text);
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
void test_label_creation(void)
{
TEST_ASSERT_EQUAL_STRING(lv_label_get_text(label), LV_LABEL_DEFAULT_TEXT);
TEST_ASSERT_EQUAL(lv_label_get_long_mode(label), LV_LABEL_LONG_MODE_WRAP);
}
void test_label_set_text(void)
{
const char * new_text = "Hello world";
/* Refresh with the current text. */
lv_label_set_text(label, NULL);
TEST_ASSERT_EQUAL_STRING(lv_label_get_text(label), LV_LABEL_DEFAULT_TEXT);
/* '\0' terminated character string to set new text. */
lv_label_set_text(label, new_text);
TEST_ASSERT_EQUAL_STRING(lv_label_get_text(label), new_text);
}
void test_label_get_letter_pos_align_left(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_LEFT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 29,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_get_letter_pos_align_left_on_empty_text(void)
{
lv_obj_set_style_text_align(empty_label, LV_TEXT_ALIGN_LEFT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(empty_label)) - 1;
lv_label_get_letter_pos(empty_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(empty_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_long_text_multiline_get_letter_pos_align_left(void)
{
lv_obj_set_style_text_align(long_label_multiline, LV_TEXT_ALIGN_LEFT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
lv_point_t last_letter_after_new_line_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 305,
.y = 32
};
const lv_point_t expected_last_letter_after_new_line_point = {
.x = 0,
.y = 48
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
const uint32_t last_letter_after_new_line = strlen(lv_label_get_text(long_label_multiline));
lv_label_get_letter_pos(long_label_multiline, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_after_new_line, &last_letter_after_new_line_point);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.x, last_letter_after_new_line_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.y, last_letter_after_new_line_point.y);
}
void test_label_long_text_get_letter_pos_align_left(void)
{
lv_label_set_long_mode(long_label, LV_LABEL_LONG_MODE_WRAP);
lv_obj_set_width(long_label, 150);
lv_obj_set_height(long_label, 500);
lv_obj_set_style_text_align(long_label, LV_TEXT_ALIGN_LEFT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 1536
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(long_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_get_letter_pos_align_right(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_RIGHT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = -29,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_get_letter_pos_align_right_on_empty_text(void)
{
lv_obj_set_style_text_align(empty_label, LV_TEXT_ALIGN_RIGHT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(empty_label)) - 1;
lv_label_get_letter_pos(empty_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(empty_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_long_text_multiline_get_letter_pos_align_right(void)
{
lv_obj_set_style_text_align(long_label_multiline, LV_TEXT_ALIGN_RIGHT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
lv_point_t last_letter_after_new_line_point;
const lv_point_t expected_first_letter_point = {
.x = -205,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 32
};
const lv_point_t expected_last_letter_after_new_line_point = {
.x = 0,
.y = 48
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
const uint32_t last_letter_after_new_line = strlen(lv_label_get_text(long_label_multiline));
lv_label_get_letter_pos(long_label_multiline, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_after_new_line, &last_letter_after_new_line_point);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.x, last_letter_after_new_line_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.y, last_letter_after_new_line_point.y);
}
void test_label_long_text_get_letter_pos_align_right(void)
{
lv_label_set_long_mode(long_label, LV_LABEL_LONG_MODE_WRAP);
lv_obj_set_width(long_label, 150);
lv_obj_set_height(long_label, 500);
lv_obj_set_style_text_align(long_label, LV_TEXT_ALIGN_RIGHT, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = -8,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = -3,
.y = 1536
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(long_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_get_letter_pos_align_center(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = -14,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 15,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_get_letter_pos_align_center_on_empty_text(void)
{
lv_obj_set_style_text_align(empty_label, LV_TEXT_ALIGN_CENTER, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = 0,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 0,
.y = 0
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(empty_label)) - 1;
lv_label_get_letter_pos(empty_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(empty_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_long_text_multiline_get_letter_pos_align_center(void)
{
lv_obj_set_style_text_align(long_label_multiline, LV_TEXT_ALIGN_CENTER, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
lv_point_t last_letter_after_new_line_point;
const lv_point_t expected_first_letter_point = {
.x = -102,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = 153,
.y = 32
};
const lv_point_t expected_last_letter_after_new_line_point = {
.x = 0,
.y = 48
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label_multiline)) - 1; /* char index starts at 0 */
const uint32_t last_letter_after_new_line = strlen(lv_label_get_text(long_label_multiline));
lv_label_get_letter_pos(long_label_multiline, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
lv_label_get_letter_pos(long_label_multiline, last_letter_after_new_line, &last_letter_after_new_line_point);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.x, last_letter_after_new_line_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_after_new_line_point.y, last_letter_after_new_line_point.y);
}
void test_label_long_text_get_letter_pos_align_center(void)
{
lv_label_set_long_mode(long_label, LV_LABEL_LONG_MODE_WRAP);
lv_obj_set_width(long_label, 150);
lv_obj_set_height(long_label, 500);
lv_obj_set_style_text_align(long_label, LV_TEXT_ALIGN_CENTER, 0);
lv_point_t first_letter_point;
lv_point_t last_letter_point;
const lv_point_t expected_first_letter_point = {
.x = -4,
.y = 0
};
const lv_point_t expected_last_letter_point = {
.x = -1,
.y = 1536
};
const uint32_t first_letter_idx = 0;
const uint32_t last_letter_idx = strlen(lv_label_get_text(long_label)) - 1; /* char index starts at 0 */
lv_label_get_letter_pos(long_label, first_letter_idx, &first_letter_point);
TEST_ASSERT_EQUAL(expected_first_letter_point.x, first_letter_point.x);
TEST_ASSERT_EQUAL(expected_first_letter_point.y, first_letter_point.y);
lv_label_get_letter_pos(long_label, last_letter_idx, &last_letter_point);
TEST_ASSERT_EQUAL(expected_last_letter_point.x, last_letter_point.x);
TEST_ASSERT_EQUAL(expected_last_letter_point.y, last_letter_point.y);
}
void test_label_is_char_under_pos_align_left(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_LEFT, 0);
bool expected_result = true;
bool result = false;
lv_point_t last_letter_point;
/* Getting the last letter point */
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
/* We should get true, since we know the last letter is in this coordinate */
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
/* If we test a move away from the last letter then we should get false */
expected_result = false;
last_letter_point.x += 50;
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
}
void test_label_is_char_under_pos_align_right(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_RIGHT, 0);
bool expected_result = true;
bool result = false;
lv_point_t last_letter_point;
/* Getting the last letter point */
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
/* We should get true, since we know the last letter is in this coordinate */
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
/* If we test a move away from the last letter then we should get false */
expected_result = false;
last_letter_point.x -= 50;
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
}
void test_label_is_char_under_pos_align_center(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
bool expected_result = true;
bool result = false;
lv_point_t last_letter_point;
/* Getting the last letter point */
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
/* We should get true, since we know the last letter is in this coordinate */
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
/* If we test a move away from the last letter then we should get false */
expected_result = false;
last_letter_point.x -= 50;
result = lv_label_is_char_under_pos(label, &last_letter_point);
TEST_ASSERT_EQUAL(expected_result, result);
}
void test_label_cut_text(void)
{
const char * expected_text = "Te";
/* label has the default text which is "Text", let's remove "xt" from it */
lv_label_cut_text(label, 2, 2);
TEST_ASSERT_EQUAL_STRING(expected_text, lv_label_get_text(label));
}
void test_label_get_letter_on_left(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_LEFT, 0);
lv_point_t last_letter_point;
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
uint32_t letter_idx_result = lv_label_get_letter_on(label, &last_letter_point, true);
TEST_ASSERT_EQUAL(last_letter_idx, letter_idx_result);
}
void test_label_get_letter_on_center(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
lv_point_t last_letter_point;
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
uint32_t letter_idx_result = lv_label_get_letter_on(label, &last_letter_point, true);
TEST_ASSERT_EQUAL(last_letter_idx, letter_idx_result);
}
void test_label_get_letter_on_right(void)
{
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_RIGHT, 0);
lv_point_t last_letter_point;
const uint32_t last_letter_idx = strlen(lv_label_get_text(label)) - 1;
lv_label_get_letter_pos(label, last_letter_idx, &last_letter_point);
uint32_t letter_idx_result = lv_label_get_letter_on(label, &last_letter_point, true);
TEST_ASSERT_EQUAL(last_letter_idx, letter_idx_result);
}
void test_label_text_selection(void)
{
const uint32_t selection_start = 0;
const uint32_t selection_end = strlen(lv_label_get_text(label)) - 1;
lv_label_set_text_selection_start(label, selection_start);
lv_label_set_text_selection_end(label, selection_end);
uint32_t start = lv_label_get_text_selection_start(label);
uint32_t end = lv_label_get_text_selection_end(label);
TEST_ASSERT_EQUAL(selection_start, start);
TEST_ASSERT_EQUAL(selection_end, end);
}
void test_label_rtl_dot_long_mode(void)
{
const char * message =
"מעבד, או בשמו המלא יחידת עיבוד מרכזית (באנגלית: CPU - Central Processing Unit).";
lv_obj_t * screen = lv_obj_create(lv_screen_active());
lv_obj_remove_style_all(screen);
lv_obj_set_size(screen, 800, 480);
lv_obj_center(screen);
lv_obj_set_style_bg_color(screen, lv_color_white(), 0);
lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
lv_obj_set_style_pad_all(screen, 0, 0);
lv_obj_t * test_label = lv_label_create(screen);
lv_obj_set_style_text_font(test_label, &lv_font_dejavu_16_persian_hebrew, 0);
lv_label_set_long_mode(test_label, LV_LABEL_LONG_MODE_DOTS);
lv_obj_set_style_base_dir(test_label, LV_BASE_DIR_RTL, 0);
lv_obj_set_size(test_label, 300, lv_font_dejavu_16_persian_hebrew.line_height);
lv_label_set_text(test_label, message);
lv_obj_center(test_label);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_rtl_dot_long_mode.png");
}
void test_label_max_width(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * test_label1 = lv_label_create(lv_screen_active());
lv_label_set_text(test_label1, long_text);
lv_obj_set_width(test_label1, 600);
lv_obj_set_style_max_width(test_label1, 200, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_label1, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_label1, LV_OPA_100, LV_PART_MAIN);
lv_obj_t * test_label2 = lv_label_create(lv_screen_active());
lv_label_set_text(test_label2, long_text);
lv_obj_set_width(test_label2, 600);
lv_obj_set_height(test_label2, 50);
lv_obj_set_x(test_label2, 300);
lv_obj_set_style_max_width(test_label2, 200, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_label2, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_label2, LV_OPA_100, LV_PART_MAIN);
lv_label_set_long_mode(test_label2, LV_LABEL_LONG_MODE_DOTS);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_max_width.png");
}
void test_label_with_recolor_cmd(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * label_recolor = lv_label_create(lv_screen_active());
lv_label_set_text(label_recolor, "Write a #ff0000 red# word");
lv_label_set_recolor(label_recolor, true);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_recolor.png");
}
static void scroll_next_step(lv_obj_t * label1, lv_obj_t * label2, const char * text1, const char * text2, uint32_t idx)
{
lv_label_set_text(label1, (idx % 2) == 0 ? text1 : text2);
lv_label_set_text(label2, (idx % 2) == 0 ? text1 : text2);
char buf[128];
lv_snprintf(buf, sizeof(buf), "widgets/label_scroll_%d.png", idx);
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
lv_test_wait(783); /*Use an odd delay*/
}
void test_label_scroll_mid_update(void)
{
lv_obj_clean(lv_screen_active());
const char * text1 = "This is a long text that we will update while scrolling";
const char * text2 = "THIS IS A LONG TEXT THAT WE WILL UPDATE WHILE SCROLLING";
lv_obj_t * label1 = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label1, LV_LABEL_LONG_MODE_SCROLL);
lv_label_set_text(label1, text1);
lv_obj_set_width(label1, 150);
lv_obj_set_pos(label1, 10, 10);
lv_obj_t * label2 = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label2, LV_LABEL_LONG_MODE_SCROLL_CIRCULAR);
lv_label_set_text(label2, text1);
lv_obj_set_width(label2, 150);
lv_obj_set_pos(label2, 10, 80);
uint32_t i;
for(i = 0; i < 20; i++) {
scroll_next_step(label1, label2, text1, text2, i);
}
}
/*
* For the LONG_MODE_CLIP mode, just re-use the screenshot from the initial
* screen of the long mode scroll
*/
void test_label_long_mode_clip(void)
{
lv_obj_clean(lv_screen_active());
const char * text1 = "This is a long text that we will update while scrolling";
lv_obj_t * label1 = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label1, LV_LABEL_LONG_MODE_CLIP);
lv_label_set_text(label1, text1);
lv_obj_set_width(label1, 150);
lv_obj_set_pos(label1, 10, 10);
lv_obj_t * label2 = lv_label_create(lv_screen_active());
lv_label_set_long_mode(label2, LV_LABEL_LONG_MODE_CLIP);
lv_label_set_text(label2, text1);
lv_obj_set_width(label2, 150);
lv_obj_set_pos(label2, 10, 80);
char buf[128];
lv_snprintf(buf, sizeof(buf), "widgets/label_scroll_0.png");
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
#endif
@@ -0,0 +1,107 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
void setUp(void)
{
active_screen = lv_screen_active();
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_led_render_1(void)
{
lv_obj_t * led = lv_led_create(active_screen);
lv_obj_align(led, LV_ALIGN_CENTER, -80, 0);
lv_led_off(led);
led = lv_led_create(active_screen);
lv_obj_align(led, LV_ALIGN_CENTER, 0, 0);
lv_led_set_brightness(led, 150);
lv_led_set_color(led, lv_palette_main(LV_PALETTE_RED));
led = lv_led_create(active_screen);
lv_obj_align(led, LV_ALIGN_CENTER, 80, 0);
lv_led_on(led);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/led_1.png");
}
void test_led_set_color_works(void)
{
lv_obj_t * led = lv_led_create(active_screen);
lv_led_t * ledObj = (lv_led_t *)led;
/* Test by changing colors randomly. */
lv_led_set_color(led, lv_palette_main(LV_PALETTE_AMBER));
TEST_ASSERT_EQUAL_COLOR(lv_palette_main(LV_PALETTE_AMBER), ledObj->color);
lv_led_set_color(led, lv_palette_main(LV_PALETTE_GREY));
TEST_ASSERT_EQUAL_COLOR(lv_palette_main(LV_PALETTE_GREY), ledObj->color);
lv_led_set_color(led, lv_palette_main(LV_PALETTE_RED));
TEST_ASSERT_EQUAL_COLOR(lv_palette_main(LV_PALETTE_RED), ledObj->color);
}
void test_led_set_brightness_works(void)
{
lv_obj_t * led = lv_led_create(active_screen);
/* Test by changing brightness randomly. */
lv_led_set_brightness(led, 150);
TEST_ASSERT_EQUAL(150, lv_led_get_brightness(led));
lv_led_set_brightness(led, 10);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MIN, lv_led_get_brightness(led));
lv_led_set_brightness(led, 255);
TEST_ASSERT_EQUAL(255, lv_led_get_brightness(led));
}
void test_led_on_off_works(void)
{
lv_obj_t * led = lv_led_create(active_screen);
lv_led_on(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MAX, lv_led_get_brightness(led));
lv_led_off(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MIN, lv_led_get_brightness(led));
lv_led_on(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MAX, lv_led_get_brightness(led));
}
void test_led_toggle_works(void)
{
lv_obj_t * led = lv_led_create(active_screen);
lv_led_on(led);
lv_led_toggle(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MIN, lv_led_get_brightness(led));
lv_led_toggle(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MAX, lv_led_get_brightness(led));
lv_led_toggle(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MIN, lv_led_get_brightness(led));
}
void test_led_get_brightness_works(void)
{
lv_obj_t * led = lv_led_create(active_screen);
lv_led_on(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MAX, lv_led_get_brightness(led));
lv_led_off(led);
TEST_ASSERT_EQUAL(LV_LED_BRIGHT_MIN, lv_led_get_brightness(led));
lv_led_set_brightness(led, 150);
TEST_ASSERT_EQUAL(150, lv_led_get_brightness(led));
}
#endif
@@ -0,0 +1,165 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * active_screen = NULL;
static lv_obj_t * line = NULL;
static const uint16_t default_point_num = 0U;
static const int32_t initial_extra_draw_size = 5U;
static const int32_t final_extra_draw_size = 10U;
void setUp(void)
{
active_screen = lv_screen_active();
line = lv_line_create(active_screen);
}
void tearDown(void)
{
lv_obj_clean(active_screen);
}
void test_line_should_have_valid_documented_default_values(void)
{
TEST_ASSERT_EQUAL_UINT16(default_point_num, lv_line_get_point_count(line));
TEST_ASSERT_NULL(lv_line_get_points(line));
TEST_ASSERT_FALSE(lv_line_get_y_invert(line));
TEST_ASSERT_FALSE(lv_obj_has_flag(line, LV_OBJ_FLAG_CLICKABLE));
/* line doesn't have any points, so it's 0,0 in size */
TEST_ASSERT_EQUAL_UINT16(0U, lv_obj_get_self_width(line));
TEST_ASSERT_EQUAL_UINT16(0U, lv_obj_get_self_height(line));
}
void test_line_should_return_valid_y_invert(void)
{
lv_line_set_y_invert(line, true);
TEST_ASSERT_TRUE(lv_line_get_y_invert(line));
}
void test_line_size_should_be_updated_after_adding_points(void)
{
static lv_point_precise_t points[] = { {5, 5} };
uint16_t point_cnt = (uint16_t) sizeof(points) / sizeof(lv_point_precise_t);
lv_line_set_points(line, points, point_cnt);
int32_t calculated_width = 0;
int32_t calculated_height = 0;
/* Get the biggest coordinate on both axis */
uint16_t point_idx = 0;
for(point_idx = 0; point_idx < point_cnt; point_idx++) {
calculated_width = (int32_t)LV_MAX(points[point_idx].x, calculated_width);
calculated_height = (int32_t)LV_MAX(points[point_idx].y, calculated_height);
}
TEST_ASSERT_EQUAL_UINT16(calculated_width, lv_obj_get_self_width(line));
TEST_ASSERT_EQUAL_UINT16(calculated_height, lv_obj_get_self_height(line));
}
static void line_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
/* Set the new line extra draw size */
lv_event_set_ext_draw_size(e, initial_extra_draw_size);
}
}
void test_line_should_update_extra_draw_size_based_on_style(void)
{
/* Setup an event handler for line extra draw size event */
lv_obj_add_event_cb(line, line_event_cb, LV_EVENT_ALL, NULL);
/* Trigger the extra draw size event */
lv_obj_refresh_ext_draw_size(line);
TEST_ASSERT_EQUAL(initial_extra_draw_size, lv_obj_get_ext_draw_size(line));
/* Update line width style, the event handler should set the extra draw size
* to the line width */
lv_obj_set_style_line_width(line, final_extra_draw_size, LV_PART_MAIN);
/* Trigger the extra draw size event */
lv_obj_refresh_ext_draw_size(line);
TEST_ASSERT_EQUAL(final_extra_draw_size, lv_obj_get_ext_draw_size(line));
}
void test_line_basic_render(void)
{
static lv_point_precise_t points[] = { {5, 5},
{100, 5}, /*Horizontal*/
{100, 100}, /*Vertical*/
{120, 5}, /*Steep*/
{200, 20}, /*Flat*/
};
uint16_t point_cnt = (uint16_t) sizeof(points) / sizeof(lv_point_precise_t);
lv_line_set_points(line, points, point_cnt);
lv_obj_set_pos(line, 10, 10);
line = lv_line_create(active_screen);
lv_line_set_points(line, points, point_cnt);
lv_obj_set_pos(line, 400, 0);
lv_obj_set_style_line_width(line, 5, LV_PART_MAIN);
lv_obj_set_style_line_dash_gap(line, 3, LV_PART_MAIN);
lv_obj_set_style_line_dash_width(line, 10, LV_PART_MAIN);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/line_1.png");
}
void test_line_dash_gap(void)
{
static lv_point_precise_t line_points1[3] = { {50, 50}, {250, 50}, {250, 250} };
static lv_point_precise_t line_points2[3] = { {50, 250}, {50, 50}, {250, 50} };
lv_obj_t * line1;
line1 = lv_line_create(lv_screen_active());
lv_line_set_points(line1, line_points1, 3);
lv_obj_set_style_line_width(line1, 1, LV_PART_MAIN);
lv_obj_set_style_line_dash_width(line1, 1, LV_PART_MAIN);
lv_obj_set_style_line_dash_gap(line1, 1, LV_PART_MAIN);
lv_obj_align(line1, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_t * line2;
line2 = lv_line_create(lv_screen_active());
lv_line_set_points(line2, line_points2, 3);
lv_obj_set_style_line_width(line2, 2, LV_PART_MAIN);
lv_obj_set_style_line_dash_width(line2, 2, LV_PART_MAIN);
lv_obj_set_style_line_dash_gap(line2, 2, LV_PART_MAIN);
lv_obj_center(line2);
lv_obj_t * line3;
line3 = lv_line_create(lv_screen_active());
lv_line_set_points(line3, line_points2, 3);
lv_obj_set_style_line_width(line3, 5, LV_PART_MAIN);
lv_obj_set_style_line_dash_width(line3, 3, LV_PART_MAIN);
lv_obj_set_style_line_dash_gap(line3, 1, LV_PART_MAIN);
lv_obj_align(line3, LV_ALIGN_RIGHT_MID, 0, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/line_2.png");
}
void test_line_point_array_getters_and_setters(void)
{
const lv_point_precise_t points[3] = {{10, 20}, {30, 40}, {50, 60}};
lv_line_set_points(line, points, 3);
TEST_ASSERT_EQUAL_UINT32(3, lv_line_get_point_count(line));
TEST_ASSERT_FALSE(lv_line_is_point_array_mutable(line));
TEST_ASSERT_EQUAL_PTR(points, lv_line_get_points(line));
TEST_ASSERT_NULL(lv_line_get_points_mutable(line));
lv_point_precise_t points_mutable[2] = {{10, 20}, {30, 40}};
lv_line_set_points_mutable(line, points_mutable, 2);
TEST_ASSERT_EQUAL_UINT32(2, lv_line_get_point_count(line));
TEST_ASSERT_TRUE(lv_line_is_point_array_mutable(line));
TEST_ASSERT_EQUAL_PTR(points_mutable, lv_line_get_points(line));
TEST_ASSERT_EQUAL_PTR(points_mutable, lv_line_get_points_mutable(line));
}
#endif
@@ -0,0 +1,65 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "../../lvgl_private.h"
#include "unity/unity.h"
static lv_obj_t * list;
void setUp(void)
{
list = lv_list_create(lv_screen_active());
}
void tearDown(void)
{
}
void test_list_get_text_from_added_button(void)
{
const char * message = "LVGL Rocks!";
lv_obj_t * button_ok = lv_list_add_button(list, LV_SYMBOL_OK, message);
TEST_ASSERT_EQUAL_STRING(message, lv_list_get_button_text(list, button_ok));
}
void test_list_get_text_from_button_without_symbol(void)
{
const char * message = "LVGL Rocks!";
lv_obj_t * button_ok = lv_list_add_button(list, NULL, message);
TEST_ASSERT_EQUAL_STRING(message, lv_list_get_button_text(list, button_ok));
}
void test_list_gets_empty_text_from_button_without_text(void)
{
const char * empty_text = "";
lv_obj_t * button_ok = lv_list_add_button(list, NULL, NULL);
TEST_ASSERT_EQUAL_STRING(empty_text, lv_list_get_button_text(list, button_ok));
}
void test_list_get_text_from_label(void)
{
const char * message = "LVGL Rocks!";
lv_obj_t * label = lv_list_add_text(list, message);
TEST_ASSERT_EQUAL_STRING(message, lv_label_get_text(label));
}
void test_list_snapshot(void)
{
lv_obj_t * snapshot_list = lv_list_create(lv_screen_active());
lv_list_add_text(snapshot_list, "File");
lv_list_add_button(snapshot_list, LV_SYMBOL_FILE, "New");
lv_list_add_button(snapshot_list, LV_SYMBOL_DIRECTORY, "Open");
lv_list_add_button(snapshot_list, LV_SYMBOL_SAVE, "Save");
lv_obj_center(snapshot_list);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/list_1.png");
}
#endif
@@ -0,0 +1,174 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
static uint32_t buf[LV_TEST_WIDTH_TO_STRIDE(100, 4) * 100 + LV_DRAW_BUF_ALIGN];
extern const uint8_t test_lottie_approve[];
extern const size_t test_lottie_approve_size;
/*Due to different floating point precision
*the rendered images are slightly different on different architectures
*So compare the screenshots only on AMD64*/
#ifdef NON_AMD64_BUILD
#undef TEST_ASSERT_EQUAL_SCREENSHOT
#define TEST_ASSERT_EQUAL_SCREENSHOT(path) (void) path
#endif
void setUp(void)
{
}
void tearDown(void)
{
lv_obj_clean(lv_screen_active());
}
void test_lottie_simple(void)
{
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
lv_obj_center(lottie);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_1.png");
/*Wait a little*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
/*Should be the last frame*/
lv_test_fast_forward(750);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_3.png");
/*Setting a source should reset the animation*/
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
/*Should reset automatically*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
}
void test_lottie_load_from_file(void)
{
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_file(lottie, "src/test_assets/test_lottie_approve.json");
lv_obj_center(lottie);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_1.png");
/*Wait a little*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
/*Should be the last frame*/
lv_test_fast_forward(750);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_3.png");
/*Setting a source should reset the animation*/
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
/*Should reset automatically*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
}
void test_lottie_missing_settings(void)
{
uint32_t tmp_buf[LV_TEST_WIDTH_TO_STRIDE(100, 4) * 100 + LV_DRAW_BUF_ALIGN];
lv_obj_t * lottie1 = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie1, 100, 100, lv_draw_buf_align(tmp_buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
/*Shouldn't crash without source*/
lv_timer_handler();
lv_obj_t * lottie2 = lv_lottie_create(lv_screen_active());
/*Set the source first*/
lv_lottie_set_src_data(lottie2, test_lottie_approve, test_lottie_approve_size);
/*Shouldn't crash without buffer*/
lv_timer_handler();
lv_lottie_set_buffer(lottie2, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_obj_center(lottie2);
lv_test_fast_forward(950);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_3.png");
}
void test_lottie_rescale(void)
{
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
lv_obj_center(lottie);
/*Wait a little*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
lv_lottie_set_buffer(lottie, 50, 50, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2_small.png");
/*Should be the last frame*/
lv_test_fast_forward(750);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_3_small.png");
}
void test_lottie_non_uniform_shape(void)
{
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 50, 200, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
lv_obj_center(lottie);
lv_test_fast_forward(950);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_4.png");
}
void test_lottie_memory_leak(void)
{
size_t mem_before = lv_test_get_free_mem();
uint32_t i;
for(i = 0; i < 32; i++) {
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
lv_obj_center(lottie);
lv_test_fast_forward(753 * i); /*Render a random frame*/
lv_timer_handler();
lv_obj_delete(lottie);
}
TEST_ASSERT_MEM_LEAK_LESS_THAN(mem_before, 16);
}
void test_lottie_no_jump_when_visible_again(void)
{
lv_obj_t * lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_buffer(lottie, 100, 100, lv_draw_buf_align(buf, LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED));
lv_lottie_set_src_data(lottie, test_lottie_approve, test_lottie_approve_size);
lv_obj_center(lottie);
/*Wait a little*/
lv_test_fast_forward(200);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
lv_obj_add_flag(lottie, LV_OBJ_FLAG_HIDDEN);
lv_test_fast_forward(300);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_1.png"); /*Empty screen*/
/*Should be on the same frame*/
lv_obj_clear_flag(lottie, LV_OBJ_FLAG_HIDDEN);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_2.png");
lv_test_fast_forward(750);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/lottie_3.png");
}
#endif

Some files were not shown because too many files have changed in this diff Show More