1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

feat(demos): High Resolution Demo Improvements (#7566)

This commit is contained in:
Liam 2025-01-09 11:24:47 -05:00 committed by GitHub
parent 137a2a647c
commit f47879b67e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 81 additions and 41 deletions

View File

@ -88,12 +88,15 @@ typedef void (*lv_demo_high_res_exit_cb_t)(lv_demo_high_res_api_t * api);
* `LV_FS_DEFAULT_DRIVE_LETTER` set. The display size should be
* 800x480, 1280x720, or 1920x1080.
* @param assets_path Folder where the image assets are.
* If `NULL`, "lvgl/demos/high_res/assets/" will be used.
* If `NULL`, "lvgl/demos/high_res/assets" will be used.
* @param logo_path A path to a logo to display in the bottom-left
* of the home screen. If `NULL`, an LVGL logo is used.
* @param slides_path Folder where the "About" app slideshow slides are.
* If `NULL`, "about_app_slides/" will be used.
* The images should be named like 1.png, 2.png, etc.
* If `NULL`, "about_app_slides" will be used.
* The images should be named like Slide1.png, Slide2.png, etc.
* They will be scaled to nine sixteenths the height of the
* display. I.e., a slide will not be scaled if it is
* 405 px high and the display is 720 px high.
* @param exit_cb A callback function which will be called when the
* "logout" button is clicked, or `NULL` to do nothing.
* @return A struct with subjects to control the UI
@ -112,12 +115,15 @@ lv_demo_high_res_api_t * lv_demo_high_res(const char * assets_path,
* `LV_FS_DEFAULT_DRIVE_LETTER` set. The display size should be
* 800x480, 1280x720, or 1920x1080.
* @param assets_path Folder where the image assets are.
* If `NULL`, "lvgl/demos/high_res/assets/" will be used.
* If `NULL`, "lvgl/demos/high_res/assets" will be used.
* @param logo_path A path to a logo to display in the bottom-left
* of the home screen. If `NULL`, an LVGL logo is used.
* @param slides_path Folder where the "About" app slideshow slides are.
* If `NULL`, "about_app_slides/" will be used.
* The images should be named like 1.png, 2.png, etc.
* If `NULL`, "about_app_slides" will be used.
* The images should be named like Slide1.png, Slide2.png, etc.
* They will be scaled to nine sixteenths the height of the
* display. I.e., a slide will not be scaled if it is
* 405 px high and the display is 720 px high.
*/
void lv_demo_high_res_api_example(const char * assets_path, const char * logo_path, const char * slides_path);

View File

@ -34,7 +34,6 @@ static bool advance_slides(lv_obj_t * slide_deck);
static void right_clicked_cb(lv_event_t * e);
static void play_pause_timer_cb(lv_timer_t * t);
static void play_pause_clicked_cb(lv_event_t * e);
static void slide_free_draw_buf_cb(lv_event_t * e);
/**********************
* STATIC VARIABLES
@ -99,18 +98,19 @@ void lv_demo_high_res_app_about(lv_obj_t * base_obj)
/* slides */
lv_fs_res_t res;
lv_fs_dir_t dir;
res = lv_fs_dir_open(&dir, c->slides_path);
if(res != LV_FS_RES_OK) {
if(lv_array_is_empty(&c->about_slides_array)) {
lv_obj_t * label = lv_label_create(bg_cont);
lv_label_set_text_fmt(label, "Couldn't open the '%s' folder to load the images", c->slides_path);
if(c->about_slides_dir_exists) {
lv_label_set_text_fmt(label, "Couldn't find images named Slide1.png, Slide2.png, etc. in the '%s' folder",
c->slides_path);
}
else {
lv_label_set_text_fmt(label, "Couldn't open the '%s' folder to load the images", c->slides_path);
}
lv_obj_center(label);
lv_obj_add_style(label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
return;
}
res = lv_fs_dir_close(&dir);
LV_ASSERT(res == LV_FS_RES_OK);
lv_obj_t * slides_cont = lv_obj_create(bg_cont);
lv_obj_remove_style_all(slides_cont);
@ -148,21 +148,11 @@ void lv_demo_high_res_app_about(lv_obj_t * base_obj)
lv_obj_t * slide;
char buf[256];
for(int32_t i = 1; ; i++) {
lv_snprintf(buf, sizeof(buf), "%s/Slide%"PRId32".png", c->slides_path, i);
lv_fs_file_t file;
res = lv_fs_open(&file, buf, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
break;
}
res = lv_fs_close(&file);
LV_ASSERT(res == LV_FS_RES_OK);
uint32_t about_slides_count = lv_array_size(&c->about_slides_array);
for(uint32_t i = 0; i < about_slides_count; i++) {
lv_image_dsc_t ** slide_src = lv_array_at(&c->about_slides_array, i);
slide = lv_image_create(slide_deck);
lv_image_dsc_t * loaded_draw_buf = lv_demo_high_res_image_preload(buf, LV_COLOR_FORMAT_NATIVE);
lv_image_set_src(slide, loaded_draw_buf);
lv_obj_add_event_cb(slide, slide_free_draw_buf_cb, LV_EVENT_DELETE, loaded_draw_buf);
lv_image_set_src(slide, *slide_src);
}
slide = lv_obj_get_child(slide_deck, 0);
@ -292,10 +282,4 @@ static void play_pause_clicked_cb(lv_event_t * e)
}
}
static void slide_free_draw_buf_cb(lv_event_t * e)
{
lv_image_dsc_t * loaded_draw_buf = lv_event_get_user_data(e);
lv_draw_buf_destroy((lv_draw_buf_t *)loaded_draw_buf);
}
#endif /*LV_USE_DEMO_HIGH_RES*/

View File

@ -201,6 +201,8 @@ typedef struct {
lv_subject_t top_margin_setting_subject;
lv_demo_high_res_api_t api;
lv_demo_high_res_subject_groups_t subject_groups;
lv_array_t about_slides_array;
bool about_slides_dir_exists;
} lv_demo_high_res_ctx_t;
LV_ATTRIBUTE_EXTERN_DATA extern const lv_demo_high_res_theme_t lv_demo_high_res_theme_light;
@ -231,7 +233,7 @@ lv_obj_t * lv_demo_high_res_simple_container_create(lv_obj_t * parent, bool vert
void lv_demo_high_res_label_bind_temperature(lv_obj_t * label, lv_subject_t * subject, lv_demo_high_res_ctx_t * c);
void lv_demo_high_res_theme_observer_image_src_cb(lv_observer_t * observer, lv_subject_t * subject);
void lv_demo_high_res_theme_observer_obj_bg_image_src_cb(lv_observer_t * observer, lv_subject_t * subject);
lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_format_t cf);
lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_format_t cf, int32_t scale);
/**********************
* MACROS

View File

@ -260,7 +260,7 @@ lv_obj_t * lv_demo_high_res_base_obj_create(const char * assets_path,
int chars = lv_snprintf(path_buf, sizeof(path_buf), "%s/img_lv_demo_high_res_%s_%s.png",
assets_path, image_details[i].name, size_prefix);
LV_ASSERT(chars < (int)sizeof(path_buf));
c->imgs[i] = lv_demo_high_res_image_preload(path_buf, image_details[i].cf);
c->imgs[i] = lv_demo_high_res_image_preload(path_buf, image_details[i].cf, LV_SCALE_NONE);
}
for(uint32_t i = 0; i < STYLE_COLOR_COUNT; i++) {
@ -274,7 +274,7 @@ lv_obj_t * lv_demo_high_res_base_obj_create(const char * assets_path,
}
c->sz->init_fonts_cb(c->fonts);
lv_subject_init_pointer(&c->th, (void *)&lv_demo_high_res_theme_light);
lv_subject_init_pointer(&c->th, (void *)&lv_demo_high_res_theme_dark);
c->th.user_data = c;
lv_subject_add_observer(&c->th, theme_observer_cb, c);
@ -333,6 +333,43 @@ lv_obj_t * lv_demo_high_res_base_obj_create(const char * assets_path,
lv_subject_init_group(&c->subject_groups.wifi.group, c->subject_groups.wifi.members,
ARRAY_LEN(c->subject_groups.wifi.members));
lv_array_init(&c->about_slides_array, 1, sizeof(lv_image_dsc_t *));
lv_fs_dir_t dir;
lv_fs_res_t fs_res = lv_fs_dir_open(&dir, slides_path);
if(fs_res == LV_FS_RES_OK) {
fs_res = lv_fs_dir_close(&dir);
LV_ASSERT(fs_res == LV_FS_RES_OK);
c->about_slides_dir_exists = true;
for(int32_t i = 1; ; i++) {
char buf[256];
lv_snprintf(buf, sizeof(buf), "%s/Slide%"LV_PRId32".png", slides_path, i);
lv_fs_file_t file;
fs_res = lv_fs_open(&file, buf, LV_FS_MODE_RD);
if(fs_res != LV_FS_RES_OK) {
break;
}
fs_res = lv_fs_close(&file);
LV_ASSERT(fs_res == LV_FS_RES_OK);
lv_image_header_t header;
lv_result_t res = lv_image_decoder_get_info(buf, &header);
if(res == LV_RESULT_INVALID) {
LV_LOG_WARN("Couldn't read the header info of slide image");
continue;
}
/* the ratio of a slide's height to the display's height will be 9:16 */
int32_t scale = (9 * 256 * vres) / (16 * header.h);
lv_image_dsc_t * loaded_draw_buf = lv_demo_high_res_image_preload(buf, LV_COLOR_FORMAT_NATIVE, scale);
if(loaded_draw_buf == NULL) continue;
lv_array_push_back(&c->about_slides_array, &loaded_draw_buf);
if(scale != LV_SCALE_NONE) LV_LOG_INFO("A slide was scaled by %"LV_PRId32" (256 means 1:1)", scale);
}
}
return base_obj;
}
@ -391,7 +428,7 @@ void lv_demo_high_res_theme_observer_obj_bg_image_src_cb(lv_observer_t * observe
}
}
lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_format_t cf)
lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_format_t cf, int32_t scale)
{
lv_image_header_t header;
lv_result_t res = lv_image_decoder_get_info(src, &header);
@ -401,7 +438,9 @@ lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_forma
}
lv_draw_buf_t * dest;
dest = lv_draw_buf_create(header.w, header.h, cf, LV_STRIDE_AUTO);
int32_t dest_w = header.w * scale / 256;
int32_t dest_h = header.h * scale / 256;
dest = lv_draw_buf_create(dest_w, dest_h, cf, LV_STRIDE_AUTO);
lv_obj_t * canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_draw_buf(canvas, dest);
@ -413,8 +452,10 @@ lv_image_dsc_t * lv_demo_high_res_image_preload(const void * src, lv_color_forma
lv_draw_image_dsc_t dsc;
lv_draw_image_dsc_init(&dsc);
dsc.src = src;
dsc.scale_x = scale;
dsc.scale_y = scale;
lv_area_t coords = {0, 0, LV_MIN(header.w, dest->header.w) - 1, LV_MIN(header.h, dest->header.h) - 1};
lv_area_t coords = {0, 0, header.w - 1, header.h - 1};
lv_draw_image(&layer, &dsc, &coords);
lv_canvas_finish_layer(canvas, &layer);
@ -545,6 +586,13 @@ static void free_ctx_event_cb(lv_event_t * e)
lv_subject_deinit(&subjects[i]);
}
uint32_t about_slides_count = lv_array_size(&c->about_slides_array);
for(uint32_t i = 0; i < about_slides_count; i++) {
lv_image_dsc_t ** slide = lv_array_at(&c->about_slides_array, i);
lv_draw_buf_destroy((lv_draw_buf_t *) *slide);
}
lv_array_deinit(&c->about_slides_array);
lv_free(c);
lv_obj_set_user_data(base_obj, NULL);